#pragma rtl #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "session.h" #include "mounturl.h" #include "seturl.h" #include "http.h" #include "readtcp.h" #include "tcpconnection.h" static char menuTitle[] = "\pArchive.org Disk Browser\xC9"; static char windowTitle[] = "\p Archive.org Disk Browser "; char diskbrowserRequestName[] = "\pSTH~DiskBrowser~"; char finderRequestName[] = "\pApple~Finder~"; #define winDiskBrowser 1001 #define searchLine 1002 #define searchButton 1003 #define findDisksForText 1004 #define forIIGSRadio 1005 #define forAnyAppleIIRadio 1006 #define disksList 1007 #define previousPageButton 1008 #define pageText 1009 #define pageNumberLine 1010 #define ofPagesText 1011 #define nextPageButton 1012 #define mountDiskButton 1013 Word resourceFileID; /* ID of our menu item in the Finder (or 0 if we're not active) */ Word menuItemID = 0; Word myUserID; GrafPortPtr window; Boolean resourceFileOpened, windowOpened; /* User preference */ boolean gsDisksOnly = true; #define DISK_LIST_LENGTH 10 struct diskListEntry { char *memPtr; Byte memFlag; }; struct diskListEntry diskList[DISK_LIST_LENGTH]; static struct MountURLRec mountURLRec = {sizeof(struct MountURLRec)}; Session sess = {0}; /* Record about our system window, to support processing by Desk Manager. */ /* See Prog. Ref. for System 6.0, page 20. */ static NDASysWindRecord sysWindRecord; void InstallMenuItem(void) { static MenuItemTemplate menuItem = { /* .version = */ 0x8000, /* show dividing line */ /* .itemID = */ 0, /* .itemChar = */ 0, /* .itemAltChar = */ 0, /* .itemCheck = */ 0, /* .itemFlag = */ refIsPointer, /* .itemTitleRef = */ (Long)&menuTitle }; tellFinderAddToExtrasOut dataOutRec; SendRequest(tellFinderAddToExtras, sendToName|stopAfterOne, (Long)&finderRequestName, (Long)&menuItem, (Ptr)&dataOutRec); if (dataOutRec.finderResult == 0) { menuItemID = dataOutRec.menuItemID; } else { menuItemID = 0; } } #pragma databank 1 void DrawContents(void) { Word origResourceApp = GetCurResourceApp(); SetCurResourceApp(myUserID); PenNormal(); /* use a "normal" pen */ DrawControls(GetPort()); /* draw controls in window */ SetCurResourceApp(origResourceApp); } #pragma databank 0 #pragma databank 1 void CloseBrowserWindow(void) { if (windowOpened) { CloseWindow(window); windowOpened = false; window = NULL; /* reset state */ gsDisksOnly = true; } if (resourceFileOpened && !windowOpened) { CloseResourceFile(resourceFileID); resourceFileOpened = false; } } #pragma databank 0 boolean DoLEEdit (int editAction) { CtlRecHndl ctl; /* target control handle */ unsigned long id; /* control ID */ GrafPortPtr port; /* caller's GrafPort */ port = GetPort(); SetPort(window); ctl = FindTargetCtl(); id = GetCtlID(ctl); if ((id == searchLine) || (id == pageNumberLine)) { LEFromScrap(); switch (editAction) { case cutAction: LECut((LERecHndl) GetCtlTitle(ctl)); LEToScrap(); break; case copyAction: LECopy((LERecHndl) GetCtlTitle(ctl)); LEToScrap(); break; case pasteAction: LEPaste((LERecHndl) GetCtlTitle(ctl)); break; case clearAction: LEDelete((LERecHndl) GetCtlTitle(ctl)); break; }; }; SetPort(port); return ((id == searchLine) || (id == pageNumberLine)); } /* Do a search */ void DoSearch(void) { static char searchURL[] = "http://archive.org/advancedsearch.php?q=emulator%3Aapple3&fl%5B%5D=identifier&fl%5B%5D=title&rows=3&page=1&output=json"; enum NetDiskError result; result = SetURL(&sess, searchURL, FALSE, FALSE); //TODO enable this once we have real code to build the URL //if (result != OPERATION_SUCCESSFUL) // goto errorReturn; result = DoHTTPRequest(&sess); if (result != OPERATION_SUCCESSFUL) goto errorReturn; /* Limit content to <64k, to avoid any problems with 16-bit computations */ if (sess.contentLength == 0 || sess.contentLength > 0xffff) sess.contentLength = 0xffff; char *buf = malloc(sess.contentLength + 1); if (buf == NULL) goto errorReturn; InitReadTCP(&sess, sess.contentLength, buf); while (TryReadTCP(&sess) == rsWaiting) /* keep reading */ ; *(buf + (sess.contentLength - sess.readCount)) = 0; //TODO for (int i = 0; i < DISK_LIST_LENGTH; i++) { diskList[i].memPtr = buf; diskList[i].memFlag = 0; } /* Update state of controls once disk list is available */ CtlRecHndl disksListHandle = GetCtlHandleFromID(window, disksList); HiliteControl(noHilite, disksListHandle); NewList2(NULL, 1, (Ref) diskList, refIsPointer, DISK_LIST_LENGTH, (Handle)disksListHandle); SetCtlMoreFlags( GetCtlMoreFlags(disksListHandle) | fCtlCanBeTarget | fCtlWantEvents, disksListHandle); HiliteControl(noHilite, GetCtlHandleFromID(window, mountDiskButton)); ShowControl(GetCtlHandleFromID(window, previousPageButton)); ShowControl(GetCtlHandleFromID(window, pageText)); ShowControl(GetCtlHandleFromID(window, pageNumberLine)); ShowControl(GetCtlHandleFromID(window, ofPagesText)); ShowControl(GetCtlHandleFromID(window, nextPageButton)); EndTCPConnection(&sess); return; errorReturn: EndTCPConnection(&sess); // TODO show error message //SysBeep(); } /* Handle an event after TaskMasterDA processing */ void HandleEvent(int eventCode, WmTaskRec *taskRec) { switch (eventCode) { case wInControl: switch (taskRec->wmTaskData4) { case searchButton: DoSearch(); break; case forIIGSRadio: gsDisksOnly = true; break; case forAnyAppleIIRadio: gsDisksOnly = false; break; case previousPageButton: //TODO break; case nextPageButton: //TODO break; case mountDiskButton: // TODO break; } break; case keyDownEvt: case autoKeyEvt: /* Handle keyboard shortcuts for cut/copy/paste */ if (taskRec->modifiers & appleKey) { switch (taskRec->message & 0x000000FF) { case 'x': case 'X': DoLEEdit(cutAction); break; case 'c': case 'C': DoLEEdit(copyAction); break; case 'v': case 'V': DoLEEdit(pasteAction); break; } } break; } } /* NDA-style action routine for our window */ #pragma databank 1 int ActionProc(EventRecord *eventRec, int actionCode) { static WmTaskRec taskRec; int handledAction = 0; switch (actionCode) { case eventAction: /* Copy basic event rec & use our own wmTaskMask, as per IIgs TN 84 */ memset(&taskRec, sizeof(taskRec), 0); memmove(&taskRec, eventRec, 16); taskRec.wmTaskMask = 0x1F7FFF; /* everything except tmInfo */ HandleEvent(TaskMasterDA(0, &taskRec), &taskRec); break; case cursorAction: break; case cutAction: case copyAction: case pasteAction: case clearAction: if (windowOpened) { handledAction = DoLEEdit(actionCode); } break; } return handledAction; } #pragma databank 0 asm void actionProcWrapper(void) { pha phy phx jsl ActionProc rtl } void ShowBrowserWindow(void) { if (windowOpened) { BringToFront(window); return; } Word origResourceApp = GetCurResourceApp(); SetCurResourceApp(myUserID); resourceFileID = OpenResourceFile(readEnable, NULL, LGetPathname2(myUserID, 1)); if (toolerror()) { resourceFileID = 0; resourceFileOpened = false; goto cleanup; } resourceFileOpened = true; window = NewWindow2(windowTitle, 0, DrawContents, NULL, refIsResource, winDiskBrowser, rWindParam1); if (toolerror()) { window = NULL; windowOpened = false; goto cleanup; } windowOpened = true; SetSysWindow(window); AuxWindInfoRecord *auxWindInfo = GetAuxWindInfo(window); if (toolerror()) { CloseWindow(window); windowOpened = false; window = NULL; goto cleanup; } memset(&sysWindRecord, sizeof(sysWindRecord), 0); sysWindRecord.closeProc = (ProcPtr)CloseBrowserWindow; sysWindRecord.actionProc = (ProcPtr)actionProcWrapper; sysWindRecord.eventMask = 0xFFFF; //0x03FF; sysWindRecord.memoryID = myUserID; auxWindInfo->NDASysWindPtr = (Ptr)&sysWindRecord; HiliteControl(inactiveHilite, GetCtlHandleFromID(window, disksList)); HiliteControl(inactiveHilite, GetCtlHandleFromID(window, mountDiskButton)); HideControl(GetCtlHandleFromID(window, previousPageButton)); HideControl(GetCtlHandleFromID(window, pageText)); HideControl(GetCtlHandleFromID(window, pageNumberLine)); HideControl(GetCtlHandleFromID(window, ofPagesText)); HideControl(GetCtlHandleFromID(window, nextPageButton)); cleanup: if (resourceFileOpened && !windowOpened) { CloseResourceFile(resourceFileID); resourceFileOpened = false; } SetCurResourceApp(origResourceApp); } void DoGoAway(void) { ResourceShutDown(); /* TODO remove menu item, other cleanup? */ } /* * Request procedure which may be called by the Finder. */ #pragma databank 1 #pragma toolparms 1 static pascal Word requestProc(Word reqCode, Long dataIn, void *dataOut) { switch (reqCode) { case finderSaysHello: InstallMenuItem(); break; case finderSaysExtrasChosen: if ((dataIn & 0x0000FFFF) == menuItemID) { ShowBrowserWindow(); return 0x8000; } break; case srqGoAway: DoGoAway(); ((srqGoAwayOut*)dataOut)->resultID = myUserID; ((srqGoAwayOut*)dataOut)->resultFlags = 0; return 0x8000; break; } return 0; } #pragma toolparms 0 #pragma databank 0 boolean NetDiskPresent(void) { mountURLRec.result = NETDISK_NOT_PRESENT; mountURLRec.url = ""; mountURLRec.flags = flgUseCache; SendRequest(MountURL, sendToName|stopAfterOne, (Long)NETDISK_REQUEST_NAME, (Long)&mountURLRec, NULL); if (mountURLRec.result == NETDISK_NOT_PRESENT) { return false; } return true; } int main(void) { myUserID = MMStartUp(); //userid() & 0xF0FF; Word origResourceApp = GetCurResourceApp(); ResourceStartUp(myUserID); SetCurResourceApp(origResourceApp); /* Bail out if NetDisk or Marinetti is not present */ if (!NetDiskPresent() || !TCPIPStatus() || toolerror()) { return 1; } AcceptRequests(diskbrowserRequestName, myUserID, &requestProc); }