// frame.c - faithful port of ORCA-C's Frame.cc sample. // // Mike Westerfield, Byte Works 1989. Original at // tools/orca-c/C.Samples/Desktop.Samples/Frame.cc. // // The simplest possible Apple IIgs desktop app: Apple/File/Edit menu // bar + TaskMaster event loop + About dialog. File>Quit (or cmd-Q) // exits. The "About Frame" item in the Apple menu shows the original // 4-line copyright dialog. // // Phase 4.1 migration: previously hand-rolled menu mini-format strings // + AlertTemplate boilerplate. Now uses iigs/uiBuilder.h for both, // shrinking the file by ~80 lines. #include "iigs/toolbox.h" #include "iigs/desktop.h" #include "iigs/eventLoop.h" #include "iigs/uiBuilder.h" #define apple_About 257 #define file_Quit 256 static void onAbout(uint16_t cmdId); static void onClose(uint32_t windowPtr); static void onMenuDispatch(uint16_t menuId, uint16_t itemId); static void onQuit(uint16_t cmdId); static const UiCmdHandlerT gCmdTable[] = { { apple_About, onAbout }, { file_Quit, onQuit }, }; static const UiMenuItemT gEditItems[] = { { 250, "Undo", 'Z', MI_CHECKED }, { 251, "Cut", 'X', 0 }, { 252, "Copy", 'C', 0 }, { 253, "Paste", 'V', 0 }, { 254, "Clear", 0, 0 }, }; static const UiMenuItemT gFileItems[] = { { 255, "Close", 0, MI_CHECKED }, { 256, "Quit", 'Q', 0 }, }; static const UiMenuItemT gAppleItems[] = { { 257, "About Frame", 0, MI_CHECKED }, }; static const UiMenuT gMenus[] = { { 1, "Apple", MN_APPLE, 1, gAppleItems }, { 2, " File ", 0, 2, gFileItems }, { 3, " Edit ", 0, 5, gEditItems }, }; static void onAbout(uint16_t cmdId) { (void)cmdId; uiBuilderAlert(UA_NOTE, "Frame 1.0\r" "Copyright 1989\r" "Byte Works, Inc.\r\r" "By Mike Westerfield"); } static void onClose(uint32_t windowPtr) { (void)windowPtr; // No app windows; close click is a no-op. } static void onMenuDispatch(uint16_t menuId, uint16_t itemId) { (void)menuId; uiBuilderDispatch(itemId, gCmdTable, (uint16_t)(sizeof gCmdTable / sizeof gCmdTable[0])); } static void onQuit(uint16_t cmdId) { (void)cmdId; iigsEventLoopQuit(); } static volatile uint16_t gIdleTicks; static void onIdle(void) { // Headless watchdog: exit cleanly if no menu pick fires within // ~4000 idle ticks. Interactive runs effectively never trip this. if (++gIdleTicks > 4000) { iigsEventLoopQuit(); } } int main(void) { unsigned short userId = startdesk(640); (void)userId; paintDesktopBackdrop(); uiBuilderInstallMenuBar(gMenus, (uint16_t)(sizeof gMenus / sizeof gMenus[0])); ShowCursor(); IigsEventCallbacksT cb; { unsigned char *p = (unsigned char *)&cb; for (uint16_t i = 0; i < sizeof cb; i++) { p[i] = 0; } } cb.onMenu = onMenuDispatch; cb.onClose = onClose; cb.onIdle = onIdle; iigsEventLoop(&cb); *(volatile unsigned char *)0x70 = 0x99; return 0; }