// 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 #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