65816-llvm-mos/demos/frame.c
Scott Duensing da095402ec Updated
2026-06-02 23:17:57 -05:00

123 lines
3 KiB
C

// 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;
}