91 lines
3.4 KiB
C
91 lines
3.4 KiB
C
// iigs/cursor.h - convenience wrappers for the QuickDraw Cursor Mgr.
|
|
//
|
|
// What's here today: a small push/pop stack of CursorRecord COPIES so
|
|
// transient cursor state (e.g. "show busy while loading", "show I-beam
|
|
// in text fields") can be installed and restored without the caller
|
|
// owning a heap-resident cursor pointer. Toolset-owned cursor records
|
|
// can move under us when Memory Mgr compacts; the push routines copy
|
|
// 256 bytes from the toolset's live cursor into our save stack so the
|
|
// pop path always restores a valid record.
|
|
//
|
|
// Pair with InitCursor() (called by startdesk()). The push/pop calls
|
|
// hard-error before InitCursor has run - the Cursor Mgr's save buffer
|
|
// is NULL until then and any SetCursor would walk through 0.
|
|
//
|
|
// Phase 2.5 (2026-06-01) scope: thin wrappers + Wait / IBeam ROM
|
|
// shapes via GetCursorAdr(). Embedded cursor blobs are NOT in scope -
|
|
// callers who want a custom cursor should construct their own Cursor
|
|
// record (per ORCA quickdraw.h:112) and pass its pointer to SetCursor()
|
|
// directly.
|
|
|
|
#ifndef IIGS_CURSOR_H
|
|
#define IIGS_CURSOR_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "iigs/toolbox.h" // brings in IigsCursorT (opaque)
|
|
|
|
|
|
// Maximum nesting depth of iigsCursorPushArrow / iigsCursorPushBusy.
|
|
// 8 is generous for the desktop demos we ship; exceeding it triggers
|
|
// the assert-no-op behavior documented on the push routines.
|
|
#ifndef IIGS_CURSOR_STACK_DEPTH
|
|
#define IIGS_CURSOR_STACK_DEPTH 8
|
|
#endif
|
|
|
|
|
|
// Save a COPY of the currently-installed cursor on the internal stack
|
|
// and install the ROM arrow cursor. The "arrow" here is whatever
|
|
// shape InitCursor() set up - on IIgs that's the standard mouse arrow.
|
|
// We re-arm it by calling InitCursor again; the Cursor Mgr re-points
|
|
// its working cursor to the ROM arrow shape without re-allocating the
|
|
// save buffer (idempotent post-init).
|
|
//
|
|
// Precondition: InitCursor() must have been called (startdesk() does
|
|
// this). If not, the call is a no-op and returns nonzero.
|
|
// Stack overflow: if the push stack is already at IIGS_CURSOR_STACK_DEPTH,
|
|
// returns nonzero and does NOT change the active cursor.
|
|
//
|
|
// Returns 0 on success.
|
|
uint16_t iigsCursorPushArrow(void);
|
|
|
|
|
|
// Save a COPY of the currently-installed cursor on the internal stack
|
|
// and install the ROM "busy" (wristwatch) cursor via WaitCursor().
|
|
// Same preconditions and error path as iigsCursorPushArrow().
|
|
//
|
|
// Returns 0 on success.
|
|
uint16_t iigsCursorPushBusy(void);
|
|
|
|
|
|
// Pop the topmost saved CursorRecord and re-install it via SetCursor().
|
|
// The save stack stores full RECORD COPIES (not pointers), so this is
|
|
// safe even if Memory Mgr moved the toolset's live cursor since the
|
|
// matching push.
|
|
//
|
|
// Returns 0 on success. Returns nonzero if the stack is empty (under-
|
|
// flow) or if iigsCursorRegister has not yet been called.
|
|
uint16_t iigsCursorPop(void);
|
|
|
|
|
|
// Install `cursor` as the active cursor; the IigsCursorT layout MUST
|
|
// match QD's CursorRecord (cursorHeight, cursorWidth, cursorData[],
|
|
// cursorMask[], cursorHotSpot). Pass NULL to no-op. This is a thin
|
|
// wrapper around SetCursor() that also captures the new cursor as the
|
|
// "registered" cursor (used by iigsCursorPop() when the save stack is
|
|
// empty - that's how we get back to the application's default cursor
|
|
// after a Push/Pop mismatch).
|
|
//
|
|
// Returns 0 on success.
|
|
uint16_t iigsCursorRegister(const IigsCursorT *cursor);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // IIGS_CURSOR_H
|