AmendHub

Download:

cyberslak

/

lightsout

/

amendments

/

2

Preference support

Adds support for (autosaved) preferences, containing the server configuration and currently registered entities.

cyberslak made amendment 2 about 1 month ago
--- preferences.c Sun Mar 9 22:43:30 2025 +++ preferences.c Sun Mar 9 22:43:30 2025 @@ -0,0 +1,199 @@ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#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); +} + +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); +} + +Handle preferences_get_entities() +{ + Handle hnd = GetResource('ENTR', kEntsId); + return hnd; +} --- preferences.h Sun Mar 9 22:59:40 2025 +++ preferences.h Sun Mar 9 22:59:40 2025 @@ -0,0 +1,23 @@ +#pragma once + +#include "list.h" + +typedef struct lo_preferences +{ + char server_name[256]; + short port; + char token[256]; +} **PrefHandle; + +#define kPreferencesDialogId 129 +#define kPreferencesFile ((const char*)"Lights Out Preferences") +#define kPrefsId 1000 +#define kEntsId 1000 + +PrefHandle preferences_load(); +short preferences_save(PrefHandle prefs); + +short preferences_dialog(); + +short preferences_save_entities(list_t *entities); +Handle preferences_get_entities();