| 1 |
// SPDX-License-Identifier: MIT |
| 2 |
|
| 3 |
#include <stdlib.h> |
| 4 |
#include <unistd.h> |
| 5 |
#include <string.h> |
| 6 |
#include <stdio.h> |
| 7 |
#include "preferences.h" |
| 8 |
#include "util.h" |
| 9 |
#include "dbuf.h" |
| 10 |
#include "entity.h" |
| 11 |
|
| 12 |
extern PrefHandle gPreferences; |
| 13 |
|
| 14 |
static short preferences_get_fsspec(FSSpec* out) |
| 15 |
{ |
| 16 |
short ret = 0; |
| 17 |
char pathBuf[256]; |
| 18 |
short len; |
| 19 |
OSErr err; |
| 20 |
|
| 21 |
getcwd(pathBuf, 256); |
| 22 |
c2pstr(pathBuf); |
| 23 |
|
| 24 |
len = pathBuf[0]; |
| 25 |
len += strlcpy(pathBuf + len + 1, kPreferencesFile, 255 - len); |
| 26 |
if (len > 255) |
| 27 |
die("preferences path too long!"); |
| 28 |
|
| 29 |
pathBuf[0] = len; |
| 30 |
err = FSMakeFSSpec(0, 0, (const u8*)pathBuf, out); |
| 31 |
|
| 32 |
if (!(err == noErr || err == -43 /* file not found */)) |
| 33 |
die("Error during FSMakeFSSpec: %hd", err); |
| 34 |
|
| 35 |
return 0; |
| 36 |
} |
| 37 |
|
| 38 |
/* Generate a new, empty preferences resource. */ |
| 39 |
static Handle preferences_new() |
| 40 |
{ |
| 41 |
PrefHandle hnd = (PrefHandle)NewHandle(sizeof(**hnd)); |
| 42 |
if (!hnd) die("out of memory"); |
| 43 |
HLock((Handle)hnd); |
| 44 |
|
| 45 |
(**gPreferences).server_name[0] = 0; |
| 46 |
(**gPreferences).token[0] = 0; |
| 47 |
(**gPreferences).port = 0; |
| 48 |
|
| 49 |
HUnlock((Handle)hnd); |
| 50 |
return (Handle)hnd; |
| 51 |
} |
| 52 |
|
| 53 |
PrefHandle preferences_load() |
| 54 |
{ |
| 55 |
Handle prefHandle; |
| 56 |
FSSpec spec; |
| 57 |
OSErr err; |
| 58 |
short refNum; |
| 59 |
|
| 60 |
if (preferences_get_fsspec(&spec) < 0) |
| 61 |
return NULL; |
| 62 |
|
| 63 |
open: |
| 64 |
refNum = FSpOpenResFile(&spec, fsRdWrPerm); |
| 65 |
|
| 66 |
if (refNum < 0) |
| 67 |
{ |
| 68 |
// attempt to create a new resource file |
| 69 |
FSpCreateResFile(&spec, 'LitO', 'pref', smRoman); |
| 70 |
err = ResError(); |
| 71 |
if (err != 0) |
| 72 |
die("error while creating resource file: %d", err); |
| 73 |
goto open; |
| 74 |
} |
| 75 |
|
| 76 |
prefHandle = Get1Resource('PREF', kPrefsId); |
| 77 |
|
| 78 |
if (!prefHandle) |
| 79 |
{ |
| 80 |
prefHandle = preferences_new(); |
| 81 |
AddResource(prefHandle, 'PREF', kPrefsId, "\pPreferences"); |
| 82 |
UpdateResFile(refNum); |
| 83 |
// todo error handling here |
| 84 |
} |
| 85 |
|
| 86 |
return (PrefHandle)prefHandle; |
| 87 |
} |
| 88 |
|
| 89 |
short preferences_save(PrefHandle prefs) |
| 90 |
{ |
| 91 |
short refNum = CurResFile(); |
| 92 |
ChangedResource((Handle)prefs); |
| 93 |
UpdateResFile(refNum); |
| 94 |
return ResError(); |
| 95 |
} |
| 96 |
|
| 97 |
short preferences_dialog() |
| 98 |
{ |
| 99 |
DialogPtr dlog; |
| 100 |
GrafPtr oldPort; |
| 101 |
bool dialogDone = false; |
| 102 |
short itemHit; |
| 103 |
Handle addrHnd, portHnd, tokHnd, save, cancel; |
| 104 |
short addrType, portType, tokType, saveType, cancelType; |
| 105 |
short ret = 0; |
| 106 |
unsigned char portBuf[256]; |
| 107 |
|
| 108 |
dlog = GetNewDialog(kPreferencesDialogId, nil, (WindowPtr)-1); |
| 109 |
|
| 110 |
GetDialogItem(dlog, 1, &saveType, &save, nil); |
| 111 |
GetDialogItem(dlog, 2, &cancelType, &cancel, nil); |
| 112 |
GetDialogItem(dlog, 5, &addrType, &addrHnd, nil); |
| 113 |
GetDialogItem(dlog, 7, &portType, &portHnd, nil); |
| 114 |
GetDialogItem(dlog, 9, &tokType, &tokHnd, nil); |
| 115 |
|
| 116 |
SetDialogDefaultItem(dlog, 1); |
| 117 |
SetDialogCancelItem(dlog, 2); |
| 118 |
SetDialogTracksCursor(dlog, true); |
| 119 |
|
| 120 |
ShowWindow(dlog); |
| 121 |
GetPort(&oldPort); |
| 122 |
SetPort(dlog); |
| 123 |
|
| 124 |
while (!dialogDone) |
| 125 |
{ |
| 126 |
ModalDialog(nil, &itemHit); |
| 127 |
switch (itemHit) |
| 128 |
{ |
| 129 |
case 1: |
| 130 |
dialogDone = true; |
| 131 |
break; |
| 132 |
case 2: // cancel |
| 133 |
ret = -1; |
| 134 |
goto fail; |
| 135 |
break; |
| 136 |
} |
| 137 |
} |
| 138 |
|
| 139 |
HLock((Handle)gPreferences); |
| 140 |
|
| 141 |
GetDialogItemText(addrHnd, (u8*)(**gPreferences).server_name); |
| 142 |
GetDialogItemText(tokHnd, (u8*)(**gPreferences).token); |
| 143 |
GetDialogItemText(portHnd, portBuf); |
| 144 |
p2cstr((u8*)(**gPreferences).server_name); |
| 145 |
p2cstr((u8*)(**gPreferences).token); |
| 146 |
|
| 147 |
if (sscanf(p2cstr(portBuf), "%hu", &(**gPreferences).port) != 1) |
| 148 |
{ |
| 149 |
ret = -1; |
| 150 |
} |
| 151 |
|
| 152 |
HUnlock((Handle)gPreferences); |
| 153 |
|
| 154 |
fail: |
| 155 |
DisposeDialog(dlog); |
| 156 |
|
| 157 |
SetPort(oldPort); |
| 158 |
return ret; |
| 159 |
} |
| 160 |
|
| 161 |
short |
| 162 |
preferences_save_entities(list_t *entities) |
| 163 |
{ |
| 164 |
DB_INIT(entBuf, 1024); |
| 165 |
list_t *node; |
| 166 |
struct entity *ent; |
| 167 |
Handle entHandle, curHandle; |
| 168 |
short refNum = CurResFile(); |
| 169 |
|
| 170 |
list_foreach(entities, node) |
| 171 |
{ |
| 172 |
ent = container_of(node, struct entity, node); |
| 173 |
db_printf(&entBuf, "%s", ent->id); |
| 174 |
entBuf.len += 1; // skip null terminator |
| 175 |
} |
| 176 |
|
| 177 |
entHandle = NewHandle(entBuf.len); |
| 178 |
if (!entHandle) |
| 179 |
die("Unable to save currently active entities"); |
| 180 |
|
| 181 |
HLock(entHandle); |
| 182 |
memcpy(*entHandle, entBuf.buf, entBuf.len); |
| 183 |
HUnlock(entHandle); |
| 184 |
|
| 185 |
db_destroy(&entBuf); |
| 186 |
|
| 187 |
SetResLoad(false); |
| 188 |
|
| 189 |
if ((curHandle = GetResource('ENTR', kEntsId)) != nil) |
| 190 |
RemoveResource(curHandle); |
| 191 |
|
| 192 |
SetResLoad(true); |
| 193 |
AddResource(entHandle, 'ENTR', kEntsId, "\pSaved entries"); |
| 194 |
|
| 195 |
UpdateResFile(refNum); |
| 196 |
|
| 197 |
return ResError(); |
| 198 |
} |
| 199 |
|
| 200 |
Handle preferences_get_entities() |
| 201 |
{ |
| 202 |
Handle hnd = GetResource('ENTR', kEntsId); |
| 203 |
return hnd; |
| 204 |
} |