65816-llvm-mos/demos/frame.c
Scott Duensing d95c30e819 Update.
2026-05-20 20:14:20 -05:00

188 lines
5.2 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.
//
// Differences from the original:
// - The watchdog at the bottom of the loop forces a clean exit so
// the headless test (`demos/test.sh frame`) can verify $70 = $99.
// In interactive use the watchdog is benign.
#include "iigs/toolbox.h"
#include "iigs/desktop.h"
#define apple_About 257
#define file_Quit 256
#define wInSpecial 25
#define wInMenuBar 3
#define norml 0
#define stop 1
#define note 2
#define caution 3
#define buttonItem 10
#define statText 136
#define itemDisable 0x8000
typedef struct {
unsigned short wmWhat;
unsigned long wmMessage;
unsigned long wmWhen;
short wmWhereV, wmWhereH;
unsigned short wmModifiers;
unsigned long wmTaskData;
unsigned long wmTaskMask;
unsigned long wmLastClickTick;
unsigned long wmClickCount;
unsigned long wmTaskData2;
unsigned long wmTaskData3;
unsigned long wmTaskData4;
} WmTaskRec;
typedef struct {
short itemID;
short itemRectV1, itemRectH1, itemRectV2, itemRectH2;
unsigned short itemType;
void *itemDescr;
short itemValue;
short itemFlag;
void *itemColor;
} ItemTemplate;
typedef struct {
short atRectV1, atRectH1, atRectV2, atRectH2;
short atBtnHorz;
short atBeep0, atBeep1, atBeep2, atBeep3;
void *atSound;
void *atResv1;
void *atResv2;
void *atItemList[8];
} AlertTemplate;
static unsigned char editMenuStr[] = ">> Edit \\N3\r"
"--Undo\\N250V*Zz\r"
"--Cut\\N251*Xx\r"
"--Copy\\N252*Cc\r"
"--Paste\\N253*Vv\r"
"--Clear\\N254\r"
".\r";
static unsigned char fileMenuStr[] = ">> File \\N2\r"
"--Close\\N255V\r"
"--Quit\\N256*Qq\r"
".\r";
static unsigned char appleMenuStr[] = ">>@\\XN1\r"
"--About Frame\\N257V\r"
".\r";
static unsigned char gAboutMsg[] =
"\x3a" "Frame 1.0\r"
"Copyright 1989\r"
"Byte Works, Inc.\r\r"
"By Mike Westerfield";
static WmTaskRec gEvent;
static volatile unsigned short gDone;
static void doAlert(unsigned short kind, void *msg) {
static unsigned char okStr[] = "\x02OK";
static ItemTemplate button = {
1, 36, 15, 0, 0, buttonItem, okStr, 0, 0, (void *)0
};
static ItemTemplate message = {
100, 5, 100, 90, 280, itemDisable | statText, (void *)0, 0, 0, (void *)0
};
static AlertTemplate alertRec = {
50, 180, 107, 460,
2,
0x80, 0x80, 0x80, 0x80,
(void *)0, (void *)0, (void *)0,
{ (void *)0, (void *)0, (void *)0, (void *)0,
(void *)0, (void *)0, (void *)0, (void *)0 }
};
SetForeColor(0);
SetBackColor(15);
message.itemDescr = msg;
alertRec.atItemList[0] = (void *)&button;
alertRec.atItemList[1] = (void *)&message;
alertRec.atItemList[2] = (void *)0;
switch (kind) {
case norml: (void)Alert(&alertRec, (void *)0); break;
case stop: (void)StopAlert(&alertRec, (void *)0); break;
case note: (void)NoteAlert(&alertRec, (void *)0); break;
case caution: (void)CautionAlert(&alertRec, (void *)0); break;
default: break;
}
}
static void menuAbout(void) {
doAlert(note, gAboutMsg);
}
static void handleMenu(unsigned short menuNum) {
switch (menuNum) {
case apple_About: menuAbout(); break;
case file_Quit: gDone = 1; break;
default: break;
}
HiliteMenu(0, (unsigned short)(gEvent.wmTaskData >> 16));
}
static void initMenus(void) {
InsertMenu(NewMenu(editMenuStr), 0);
InsertMenu(NewMenu(fileMenuStr), 0);
InsertMenu(NewMenu(appleMenuStr), 0);
FixAppleMenu(1);
FixMenuBar();
DrawMenuBar();
}
int main(void) {
unsigned short userId = startdesk(640);
(void)userId;
paintDesktopBackdrop(); // white desktop (WM dither -> noise in
// our 640 B/W palette; paint directly)
initMenus();
gEvent.wmTaskMask = 0x1FFFL;
ShowCursor();
gDone = 0;
unsigned short watchdog = 0;
do {
unsigned short event = TaskMaster(0x076E, &gEvent);
switch (event) {
case wInSpecial:
case wInMenuBar:
handleMenu((unsigned short)gEvent.wmTaskData);
break;
default:
break;
}
watchdog++;
} while (!gDone && watchdog < 4000);
*(volatile unsigned char *)0x70 = 0x99;
return 0;
}