/*
 * mouse.h — Sprinter mouse driver (RST 30h).
 *
 * The driver is installed in the system shell.  After a successful
 * mouse_init(), the driver tracks the hardware and you can query state
 * or move/show/hide the cursor on demand.
 *
 *   coordinate units:
 *     READ_STATE / GOTO take pixel coordinates.  In text mode 03h
 *     (80x32) divide x by 8 and y by 8 (NOT 16) to get char-cell
 *     position.
 *
 *   buttons bitmask:
 *     bit 0 = left, bit 1 = right
 */

#ifndef MOUSE_H
#define MOUSE_H

#include <stdint.h>

typedef struct {
    uint16_t x;        /* pixel coordinate */
    uint16_t y;        /* pixel coordinate */
    uint8_t  buttons;  /* bit 0 = left, bit 1 = right */
} mouse_state_t;

int  mouse_init   (void);                       /* 0 OK, -1 if no driver */
void mouse_show   (void);
void mouse_hide   (void);
void mouse_refresh(void);
void mouse_read   (mouse_state_t *st);
void mouse_goto   (int x, int y);
void mouse_bounds_x(int xmin, int xmax);
void mouse_bounds_y(int ymin, int ymax);

/* Text-mode cursor shape (function $0A).
 *   sym_and / sym_xor — character glyph mask
 *   attr_and / attr_xor — attribute byte mask
 * Default cursor is XOR'd inverse video at the cell. */
void mouse_text_cursor(uint8_t sym_and, uint8_t sym_xor,
                       uint8_t attr_and, uint8_t attr_xor);

/* ---- Graphics-mode cursor image (functions $09 / $0B) ----------- *
 * The driver accepts an opaque bitmap for the cursor in graphics modes.
 * Doc does not specify the byte layout — empirically size = width*height
 * bytes (1 byte per pixel for 256-colour mode, presumably packed nibbles
 * for 16-colour mode).  hot_x / hot_y mark the "click point" within the
 * cursor image (0,0 = top-left).
 */
typedef struct {
    const void *image;   /* bitmap data */
    uint8_t     width;
    uint8_t     height;
    uint8_t     hot_x;
    uint8_t     hot_y;
} mouse_cursor_t;

void mouse_load_cursor(const mouse_cursor_t *c);

/* Read back the current cursor.
 *   c->image must point to a buffer large enough to hold width*height bytes.
 *   width, height, hot_x, hot_y are written by the driver. */
void mouse_get_cursor(mouse_cursor_t *c);

/* ---- Sensitivity (functions $0E / $0F) ------------------------- *
 * Verified empirically (2026-05-31): the value is a DIVIDER — the
 * driver counts that many raw hardware steps from the mouse before
 * advancing the cursor by one screen pixel.  So **smaller value = more
 * sensitive** (cursor moves faster), and larger value = slower cursor.
 * (The doc statement "higher = less movement needed" appears to be
 * inverted.)  Useful starting point: 2 on both axes. */
uint8_t mouse_get_sensitivity_x(void);
uint8_t mouse_get_sensitivity_y(void);
void    mouse_set_sensitivity(uint8_t horz, uint8_t vert);

/* ---- Solid-C compatibility ------------------------------------- *
 * Solid-C uses shorter `ms_*` names + typed state structs.  The semantics
 * are identical to our `mouse_*` API. */

#define LEFT_BUTTON   1
#define RIGHT_BUTTON  2

/* MSGSTAT mirrors mouse_state_t — same field order and types. */
typedef mouse_state_t MSGSTAT;

#define ms_init       mouse_init
#define ms_show       mouse_show
#define ms_hide       mouse_hide
#define ms_ref        mouse_refresh
#define ms_xbnd       mouse_bounds_x
#define ms_ybnd       mouse_bounds_y
#define ms_spos       mouse_goto
#define mssgpos       mouse_goto
#define ms_tcur       mouse_text_cursor
#define ms_scur       mouse_load_cursor
#define ms_gcur       mouse_get_cursor
#define ms_vmod       mouse_video_mode_changed
#define ms_ssen       mouse_set_sensitivity
#define msgstat(st)   mouse_read((st))

/* ---- $81 CHANGE VIDEO MODE ------------------------------------- *
 * Call after changing the video mode (set_videotextmode or gfx_init) so
 * the driver re-syncs its internal coordinate ranges and cursor image.
 *
 * `mode` is the byte you switched to — TEXT_MODE_* (from <conio.h>) or
 * GFX_MODE_* (from <gfx.h>), e.g. 0x03 for 80×32 text or 0x81 for
 * 320×256×256.  The driver REQUIRES the new mode in register A —
 * passing garbage leaves the cursor mis-configured (text-mode XOR
 * pattern applied in graphics, etc.). */
void mouse_video_mode_changed(uint8_t mode);

#endif
