// SPDX-License-Identifier: MIT #include #include #include #include #include "preferences.h" #include "util.h" #include "dbuf.h" #include "entity.h" extern PrefHandle gPreferences; static short preferences_get_fsspec(FSSpec* out) { short ret = 0; char pathBuf[256]; short len; OSErr err; getcwd(pathBuf, 256); c2pstr(pathBuf); len = pathBuf[0]; len += strlcpy(pathBuf + len + 1, kPreferencesFile, 255 - len); if (len > 255) die("preferences path too long!"); pathBuf[0] = len; err = FSMakeFSSpec(0, 0, (const u8*)pathBuf, out); if (!(err == noErr || err == -43 /* file not found */)) die("Error during FSMakeFSSpec: %hd", err); return 0; } /* Generate a new, empty preferences resource. */ static Handle preferences_new() { PrefHandle hnd = (PrefHandle)NewHandle(sizeof(**hnd)); if (!hnd) die("out of memory"); HLock((Handle)hnd); (**gPreferences).server_name[0] = 0; (**gPreferences).token[0] = 0; (**gPreferences).port = 0; HUnlock((Handle)hnd); return (Handle)hnd; } PrefHandle preferences_load() { Handle prefHandle; FSSpec spec; OSErr err; short refNum; if (preferences_get_fsspec(&spec) < 0) return NULL; open: refNum = FSpOpenResFile(&spec, fsRdWrPerm); if (refNum < 0) { // attempt to create a new resource file FSpCreateResFile(&spec, 'LitO', 'pref', smRoman); err = ResError(); if (err != 0) die("error while creating resource file: %d", err); goto open; } prefHandle = Get1Resource('PREF', kPrefsId); if (!prefHandle) { prefHandle = preferences_new(); AddResource(prefHandle, 'PREF', kPrefsId, "\pPreferences"); UpdateResFile(refNum); // todo error handling here } return (PrefHandle)prefHandle; } short preferences_save(PrefHandle prefs) { short refNum = CurResFile(); ChangedResource((Handle)prefs); UpdateResFile(refNum); return ResError(); } short preferences_dialog() { DialogPtr dlog; GrafPtr oldPort; bool dialogDone = false; short itemHit; Handle addrHnd, portHnd, tokHnd, save, cancel; short addrType, portType, tokType, saveType, cancelType; short ret = 0; unsigned char portBuf[256]; dlog = GetNewDialog(kPreferencesDialogId, nil, (WindowPtr)-1); GetDialogItem(dlog, 1, &saveType, &save, nil); GetDialogItem(dlog, 2, &cancelType, &cancel, nil); GetDialogItem(dlog, 5, &addrType, &addrHnd, nil); GetDialogItem(dlog, 7, &portType, &portHnd, nil); GetDialogItem(dlog, 9, &tokType, &tokHnd, nil); SetDialogDefaultItem(dlog, 1); SetDialogCancelItem(dlog, 2); SetDialogTracksCursor(dlog, true); ShowWindow(dlog); GetPort(&oldPort); SetPort(dlog); while (!dialogDone) { ModalDialog(nil, &itemHit); switch (itemHit) { case 1: dialogDone = true; break; case 2: // cancel ret = -1; goto fail; break; } } HLock((Handle)gPreferences); GetDialogItemText(addrHnd, (u8*)(**gPreferences).server_name); GetDialogItemText(tokHnd, (u8*)(**gPreferences).token); GetDialogItemText(portHnd, portBuf); p2cstr((u8*)(**gPreferences).server_name); p2cstr((u8*)(**gPreferences).token); if (sscanf(p2cstr(portBuf), "%hu", &(**gPreferences).port) != 1) { ret = -1; } HUnlock((Handle)gPreferences); fail: DisposeDialog(dlog); SetPort(oldPort); return ret; } short preferences_save_entities(list_t *entities) { DB_INIT(entBuf, 1024); list_t *node; struct entity *ent; Handle entHandle, curHandle; short refNum = CurResFile(); list_foreach(entities, node) { ent = container_of(node, struct entity, node); db_printf(&entBuf, "%s", ent->id); entBuf.len += 1; // skip null terminator } entHandle = NewHandle(entBuf.len); if (!entHandle) die("Unable to save currently active entities"); HLock(entHandle); memcpy(*entHandle, entBuf.buf, entBuf.len); HUnlock(entHandle); db_destroy(&entBuf); SetResLoad(false); if ((curHandle = GetResource('ENTR', kEntsId)) != nil) RemoveResource(curHandle); SetResLoad(true); AddResource(entHandle, 'ENTR', kEntsId, "\pSaved entries"); UpdateResFile(refNum); return ResError(); } Handle preferences_get_entities() { Handle hnd = GetResource('ENTR', kEntsId); return hnd; }