AmendHub

Download:

jcs

/

wallops

/

amendments

/

57

settings: Move storage to preferences file

Storing in resources in the application was cleaner but each app
update would wipe them out. Since there is possibly a server
password being stored, a user might not clear the settings out
before sharing the binary.
 
Save the preferences file in the System folder on System 6, or
System:Preferences on System 7+.

jcs made amendment 57 3 months ago
--- chatter.c Fri Aug 30 16:38:16 2024 +++ chatter.c Fri Aug 30 20:08:34 2024 @@ -61,7 +61,7 @@ chatter_init(const char *server, const unsigned short struct chatter_tab *tab; char title[64]; Rect bounds = { 0 }; - short padding = 20; + short padding = 20, width, height; GetIndPattern(&tab_bar_pattern, sysPatListID, 23); @@ -76,12 +76,12 @@ chatter_init(const char *server, const unsigned short return NULL; } - bounds.left = padding; - bounds.top = screenBits.bounds.top + padding + - (GetMBarHeight() * 2) - 1; - bounds.right = screenBits.bounds.right - padding - 1; -// bounds.bottom = screenBits.bounds.bottom - padding - 1; - bounds.bottom = (screenBits.bounds.bottom / 2) - padding - 1; + width = screenBits.bounds.right - screenBits.bounds.left - padding; + width = MIN(width, 640); + height = screenBits.bounds.bottom - screenBits.bounds.top - + padding - (GetMBarHeight() * 2); + height = MIN(height, 350); + center_in_screen(width, height, true, &bounds); snprintf(title, sizeof(title), "%s: Disconnected", PROGRAM_NAME); chatter->win = NewWindow(0L, &bounds, CtoPstr(title), false, --- chatter.h Fri Sep 29 21:12:39 2023 +++ chatter.h Fri Aug 30 17:22:56 2024 @@ -44,32 +44,6 @@ #define EDIT_MENU_COPY_ID 2 #define EDIT_MENU_PASTE_ID 3 -#define CONNECT_DLOG_ID 129 -#define CONNECT_SERVER_ID 2 -#define CONNECT_PORT_ID 3 -#define CONNECT_PASSWORD_ID 4 -#define CONNECT_NICK_ID 5 -#define CONNECT_IDENT_ID 6 -#define CONNECT_REALNAME_ID 7 -#define CONNECT_HIDE_MOTD_ID 8 -#define CONNECT_CHANNEL_ID 9 - -#define STR_SERVER_ID 1000 -#define STR_PORT_ID 1001 -#define STR_NICK_ID 1002 -#define STR_IDENT_ID 1003 -#define STR_REALNAME_ID 1004 -#define STR_CHANNEL_ID 1005 -#define STR_PASSWORD_ID 1006 -#define STR_HIDE_MOTD_ID 1007 - -#define DEFAULT_SERVER_NAME "irc.libera.chat" -#define DEFAULT_PORT "6667" -#define DEFAULT_IDENT "wallops" -#define DEFAULT_REALNAME "A Macintosh User" -#define DEFAULT_CHANNEL "#cyberpals" -#define DEFAULT_HIDE_MOTD "0" - #define WAIT_TYPE_NONE (1 << 0) #define WAIT_TYPE_BACKGROUND (1 << 1) #define WAIT_TYPE_FOREGROUND (1 << 2) --- main.c Mon Jan 1 10:41:33 2024 +++ main.c Fri Aug 30 19:21:35 2024 @@ -17,53 +17,20 @@ #include <string.h> #include "chatter.h" #include "irc.h" +#include "settings.h" #include "tcp.h" #include "util.h" MenuHandle apple_menu, file_menu; NMRec notification = { 0 }; +struct settings settings; -enum { - CONFIG_TYPE_STRING, - CONFIG_TYPE_SHORT, - CONFIG_TYPE_PASSWORD, - CONFIG_TYPE_BOOL -}; - -struct config_field { - char name[32]; - short type; - unsigned short min; - unsigned short max; - short ditl_id; - short res_id; - char sdefault[32]; - char password_storage[256]; -} config_fields[] = { - { "Server Name", CONFIG_TYPE_STRING, 1, 0, - CONNECT_SERVER_ID, STR_SERVER_ID, DEFAULT_SERVER_NAME }, - { "Server Port", CONFIG_TYPE_SHORT, 1, 65535, - CONNECT_PORT_ID, STR_PORT_ID, DEFAULT_PORT }, - { "Server Password", CONFIG_TYPE_PASSWORD, 0, 0, - CONNECT_PASSWORD_ID, STR_PASSWORD_ID, "" }, - { "Nickname", CONFIG_TYPE_STRING, 1, 0, - CONNECT_NICK_ID, STR_NICK_ID, "" }, - { "Ident", CONFIG_TYPE_STRING, 1, 0, - CONNECT_IDENT_ID, STR_IDENT_ID, DEFAULT_IDENT }, - { "Realname", CONFIG_TYPE_STRING, 1, 0, - CONNECT_REALNAME_ID, STR_REALNAME_ID, DEFAULT_REALNAME }, - { "Hide MOTD", CONFIG_TYPE_BOOL, 0, 1, - CONNECT_HIDE_MOTD_ID, STR_HIDE_MOTD_ID, DEFAULT_HIDE_MOTD }, - { "Channel", CONFIG_TYPE_STRING, 0, 0, - CONNECT_CHANNEL_ID, STR_CHANNEL_ID, DEFAULT_CHANNEL }, -}; - void update_menu(void); void handle_exit(void); bool handle_menu(long menu_id); -short show_connect_dialog(void); +void show_connect_dialog(void); -int +short main(void) { Handle mbar; @@ -225,184 +192,17 @@ main(void) return 0; } -short +void show_connect_dialog(void) { - Str255 txt, server, ports, nick, ident, realname, channel, password; - struct chatter *chatter; - StringHandle h; - DialogTHndl dlgh; - DialogPtr dlg; - Handle ihandle; - Rect irect; - size_t size, n, m; - long port; - short hit, itype, ret, hide_motd; + bool valid; - /* center dialog in screen */ - dlgh = (DialogTHndl)xGetResource('DLOG', CONNECT_DLOG_ID); - HLock(dlgh); - center_in_screen((**dlgh).boundsRect.right - (**dlgh).boundsRect.left, - (**dlgh).boundsRect.bottom - (**dlgh).boundsRect.top, - true, &(**dlgh).boundsRect); - HUnlock(dlgh); - - if ((dlg = GetNewDialog(CONNECT_DLOG_ID, nil, (WindowPtr)-1)) == NULL) - panic("Can't find connection DLOG %d", CONNECT_DLOG_ID); - - for (n = 0; n < nitems(config_fields); n++) { - struct config_field *cf = &config_fields[n]; - short sval; - - GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect); - - if (cf->type == CONFIG_TYPE_PASSWORD) { - PasswordDialogFieldFilterSetup(cf->ditl_id, - cf->password_storage, sizeof(cf->password_storage)); - } - - if (cf->res_id && (h = GetString(cf->res_id))) { - HLock(h); - if (cf->type == CONFIG_TYPE_PASSWORD) { - size = (*h)[0]; - if (size >= sizeof(cf->password_storage) - 1) - size = 0; - for (m = 0; m < size; m++) - cf->password_storage[m] = '•'; - cf->password_storage[m] = '\0'; - CtoPstr(cf->password_storage); - SetIText(ihandle, cf->password_storage); - memcpy(cf->password_storage, *h, size); - cf->password_storage[size] = '\0'; - PtoCstr(cf->password_storage); - } else if (cf->type == CONFIG_TYPE_BOOL) { - SetCtlValue(ihandle, ((*h)[1] == '1')); - } else { - SetIText(ihandle, *h); - } - HUnlock(h); - ReleaseResource(h); - } else if (cf->type == CONFIG_TYPE_BOOL) { - SetCtlValue(ihandle, (cf->sdefault[0] == '1')); - } else if (cf->sdefault[0] != '\0') { - strlcpy((char *)&txt, cf->sdefault, sizeof(txt)); - CtoPstr(txt); - SetIText(ihandle, txt); - } - } - - ShowWindow(dlg); - -get_input: - ModalDialog(PasswordDialogFieldFilter, &hit); - switch (hit) { - case -1: - DisposeDialog(dlg); - ReleaseResource(dlgh); + if (!settings_edit(!settings_load())) return; - case OK: - goto verify; - case CONNECT_HIDE_MOTD_ID: - GetDItem(dlg, hit, &itype, &ihandle, &irect); - SetCtlValue(ihandle, 1 - GetCtlValue(ihandle)); - /* FALLTHROUGH */ - default: - goto get_input; - } - -verify: - for (n = 0; n < nitems(config_fields); n++) { - struct config_field *cf = &config_fields[n]; - long lval; - short sval; - - GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect); - if (cf->type == CONFIG_TYPE_PASSWORD) { - memcpy((char *)&txt, cf->password_storage, sizeof(txt)); - } else if (cf->type == CONFIG_TYPE_BOOL) { - snprintf((char *)&txt, sizeof(txt), "%d", - GetCtlValue(ihandle)); - } else { - GetIText(ihandle, txt); - PtoCstr(txt); - } - - switch (cf->type) { - case CONFIG_TYPE_STRING: - case CONFIG_TYPE_PASSWORD: - if (cf->min && strlen((char *)txt) < cf->min) { - warn("%s is too short (minimum %d)", cf->name, cf->min); - goto get_input; - } - if (cf->max && strlen((char *)txt) > cf->max) { - warn("%s is too long (maximum %d)", cf->name, cf->max); - goto get_input; - } - break; - case CONFIG_TYPE_SHORT: - lval = atol((char *)txt); - if (lval < cf->min) { - warn("%s must be at least %d", cf->name, cf->min); - goto get_input; - } - if (lval > cf->max) { - warn("%s must be less than %d", cf->name, cf->max); - goto get_input; - } - break; - case CONFIG_TYPE_BOOL: - break; - } - - switch (cf->ditl_id) { - case CONNECT_SERVER_ID: - strlcpy((char *)&server, (char *)txt, sizeof(server)); - break; - case CONNECT_PORT_ID: - port = atol((char *)txt); - break; - case CONNECT_PASSWORD_ID: - strlcpy((char *)&password, (char *)txt, sizeof(password)); - break; - case CONNECT_NICK_ID: - strlcpy((char *)&nick, (char *)txt, sizeof(nick)); - break; - case CONNECT_IDENT_ID: - strlcpy((char *)&ident, (char *)txt, sizeof(ident)); - break; - case CONNECT_REALNAME_ID: - strlcpy((char *)&realname, (char *)txt, sizeof(realname)); - break; - case CONNECT_HIDE_MOTD_ID: - hide_motd = (txt[0] == '1'); - break; - case CONNECT_CHANNEL_ID: - strlcpy((char *)&channel, (char *)txt, sizeof(channel)); - break; - } - - if ((h = GetString(cf->res_id)) != NULL) { - RmveResource(h); - ReleaseResource(h); - } - size = strlen((char *)txt) + 1; - h = (StringHandle)xNewHandle(size); - strlcpy((char *)*h, (char *)txt, size); - CtoPstr(*h); - strlcpy((char *)txt, cf->name, sizeof(txt)); - CtoPstr(txt); - AddResource(h, 'STR ', cf->res_id, txt); - ReleaseResource(h); - } - - PasswordDialogFieldFinish(); - DisposeDialog(dlg); - ReleaseResource(dlgh); - - chatter_init((char *)&server, port, (char *)&password, - (char *)&nick, (char *)&ident, (char *)&realname, - hide_motd, (char *)&channel); + chatter_init(settings.server, settings.port, settings.password, + settings.nick, settings.ident, settings.realname, + settings.hide_motd, settings.channel); } bool --- settings.c Fri Aug 30 19:15:47 2024 +++ settings.c Fri Aug 30 19:15:47 2024 @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2021-2024 joshua stein <jcs@jcs.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <OSUtils.h> +#include <Files.h> +#include <Folders.h> +#include <GestaltEqu.h> +#include <Traps.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "settings.h" +#include "util.h" + +enum { + SETTING_STRING, + SETTING_SHORT, + SETTING_USHORT, + SETTING_LONG, + SETTING_PASSWORD, + SETTING_BOOL +}; + +enum { + SETTING_FLAG_ALLOW_BLANK = (1 << 0) +}; + +struct setting { + char name[32]; + short type; + long flags; + long min; + long max; + char sdefault[32]; + short ditl_id; + unsigned long offset; + unsigned long size; + char password_storage[256]; +} settings_defs[] = { + { "Server Name", SETTING_STRING, 0, 1, 0, + DEFAULT_SERVER_NAME, SETTINGS_SERVER_ID, + offsetof(struct settings, server), + member_size(struct settings, server) }, + { "Server Port", SETTING_USHORT, 0, 1, 65535, + DEFAULT_PORT, SETTINGS_PORT_ID, + offsetof(struct settings, port), + member_size(struct settings, port) }, + { "Server Password", SETTING_PASSWORD, 0, 0, 0, + "", SETTINGS_PASSWORD_ID, + offsetof(struct settings, password), + member_size(struct settings, password) }, + { "Nickname", SETTING_STRING, 0, 1, 0, + "", SETTINGS_NICK_ID, + offsetof(struct settings, nick), + member_size(struct settings, nick) }, + { "Ident", SETTING_STRING, 0, 1, 0, + DEFAULT_IDENT, SETTINGS_IDENT_ID, + offsetof(struct settings, ident), + member_size(struct settings, ident) }, + { "Realname", SETTING_STRING, 0, 1, 0, + DEFAULT_REALNAME, SETTINGS_REALNAME_ID, + offsetof(struct settings, realname), + member_size(struct settings, realname) }, + { "Hide MOTD", SETTING_BOOL, 0, 0, 1, + DEFAULT_HIDE_MOTD, SETTINGS_HIDE_MOTD_ID, + offsetof(struct settings, hide_motd), + member_size(struct settings, hide_motd) }, + { "Channel", SETTING_STRING, 0, 0, 0, + DEFAULT_CHANNEL, SETTINGS_CHANNEL_ID, + offsetof(struct settings, channel), + member_size(struct settings, channel) }, +}; + +void settings_find_prefs_folder(short *vrefnum, long *dirid); + +bool +settings_load(void) +{ + HParamBlockRec pb = { 0 }; + struct settings tsettings = { 0 }; + char fn[] = SETTINGS_FILENAME; + char *res; + short error, vrefnum, prefrefnum; + long len, rlen, dirid; + Handle h; + + GetSystemSubfolder(kPreferencesFolderType, true, &vrefnum, &dirid); + + pb.ioParam.ioNamePtr = (StringPtr)&fn; + pb.ioParam.ioVRefNum = vrefnum; + pb.ioParam.ioPermssn = fsRdPerm; + pb.fileParam.ioDirID = dirid; + error = PBHOpen(&pb, false); + if (error) { + if (error != fnfErr) + panic("Failed reading preferences file: %d", error); + + return false; + } + + rlen = len = sizeof(struct settings); + FSRead(pb.ioParam.ioRefNum, &rlen, &tsettings); + + while (tsettings.version < SETTINGS_VERSION) { + switch (tsettings.version) { + default: + FSClose(pb.ioParam.ioRefNum); + + if (ask("Unknown preferences version (%d), reset?", + tsettings.version)) { + return false; + } + + ExitToShell(); + } + + tsettings.version++; + } + + FSClose(pb.ioParam.ioRefNum); + + settings = tsettings; + return true; +} + +void +settings_save(struct settings *tsettings) +{ + HParamBlockRec pb = { 0 }; + char fn[] = SETTINGS_FILENAME; + short error, vrefnum, prefrefnum; + long dirid, len; + Handle h; + + GetSystemSubfolder(kPreferencesFolderType, true, &vrefnum, &dirid); + + pb.ioParam.ioNamePtr = (StringPtr)&fn; + pb.ioParam.ioVRefNum = vrefnum; + pb.fileParam.ioDirID = dirid; + error = PBHCreate(&pb, false); + if (error && error != dupFNErr) + goto create_failed; + if (!error) { + memset(&pb, 0, sizeof(pb)); + pb.ioParam.ioNamePtr = (StringPtr)&fn; + pb.ioParam.ioVRefNum = vrefnum; + pb.fileParam.ioDirID = dirid; + if ((error = PBHGetFInfo(&pb, false))) + goto create_failed; + + pb.fileParam.ioDirID = dirid; /* required after PBHGetFInfo */ + pb.fileParam.ioFlFndrInfo.fdType = 'pref'; + pb.fileParam.ioFlFndrInfo.fdCreator = SETTINGS_FILE_CREATOR; + if ((error = PBHSetFInfo(&pb, false))) + goto create_failed; + + memset(&pb, 0, sizeof(pb)); + pb.ioParam.ioVRefNum = vrefnum; + PBFlushVol(&pb, false); + } + + memset(&pb, 0, sizeof(pb)); + pb.ioParam.ioNamePtr = (StringPtr)&fn; + pb.ioParam.ioVRefNum = vrefnum; + pb.ioParam.ioPermssn = fsWrPerm; + pb.fileParam.ioDirID = dirid; + error = PBHOpen(&pb, false); + if (error) + goto create_failed; + + len = sizeof(struct settings); + tsettings->version = SETTINGS_VERSION; + FSWrite(pb.ioParam.ioRefNum, &len, tsettings); + FSClose(pb.ioParam.ioRefNum); + + return; + +create_failed: + panic("Failed creating preferences file: %d", error); +} + +bool +settings_edit(bool use_defaults) +{ + struct settings tsettings = settings; + struct setting *s; + DialogTHndl dlgh; + DialogPtr dlg; + Handle ihandle; + Rect irect; + size_t size, n, m, slen; + long lval; + bool bval, save; + short hit, itype, ret; + char *sdata, *strval; + Str255 stmp; + + /* center dialog in screen */ + dlgh = (DialogTHndl)xGetResource('DLOG', SETTINGS_DLOG_ID); + HLock(dlgh); + center_in_screen((**dlgh).boundsRect.right - (**dlgh).boundsRect.left, + (**dlgh).boundsRect.bottom - (**dlgh).boundsRect.top, + true, &(**dlgh).boundsRect); + HUnlock(dlgh); + + if ((dlg = GetNewDialog(SETTINGS_DLOG_ID, nil, (WindowPtr)-1)) == NULL) + panic("Can't find settings DLOG %d", SETTINGS_DLOG_ID); + + for (n = 0; n < nitems(settings_defs); n++) { + s = &settings_defs[n]; + sdata = (char *)&tsettings + s->offset; + + GetDItem(dlg, s->ditl_id, &itype, &ihandle, &irect); + + switch (s->type) { + case SETTING_PASSWORD: + PasswordDialogFieldFilterSetup(s->ditl_id, + (char *)s->password_storage, sizeof(s->password_storage)); + + strval = (use_defaults ? (char *)s->sdefault : sdata); + size = strlen(strval); + if (size >= sizeof(s->password_storage) - 1) + size = 0; + + /* show a masked value */ + stmp[0] = size; + for (m = 1; m <= size; m++) + stmp[m] = '•'; + SetIText(ihandle, stmp); + + /* but store the actual password */ + memcpy(s->password_storage, strval, size); + s->password_storage[size] = '\0'; + break; + case SETTING_STRING: + strval = (use_defaults ? s->sdefault : sdata); + memcpy(stmp, strval, sizeof(stmp)); + stmp[sizeof(stmp) - 1] = '\0'; + CtoPstr(stmp); + SetIText(ihandle, stmp); + break; + case SETTING_SHORT: + case SETTING_USHORT: + case SETTING_LONG: + if (use_defaults) { + memcpy(stmp, s->sdefault, sizeof(stmp)); + stmp[sizeof(stmp) - 1] = '\0'; + } else if (s->type == SETTING_SHORT) { + snprintf((char *)stmp, sizeof(stmp), "%d", + BYTES_TO_SHORT(sdata[0], sdata[1])); + } else if (s->type == SETTING_USHORT) { + snprintf((char *)stmp, sizeof(stmp), "%u", + BYTES_TO_SHORT(sdata[0], sdata[1])); + } else if (s->type == SETTING_LONG) { + snprintf((char *)stmp, sizeof(stmp), "%ld", + BYTES_TO_LONG(sdata[0], sdata[1], sdata[2], sdata[3])); + } + CtoPstr(stmp); + SetIText(ihandle, stmp); + break; + case SETTING_BOOL: + SetCtlValue(ihandle, (use_defaults ? s->sdefault[0] : + sdata[0]) == 1); + break; + default: + panic("unknown setting type %d", s->type); + } + } + + ret = false; + ShowWindow(dlg); + +get_input: + GetDItem(dlg, ok, &itype, &ihandle, &irect); + outline_button((ControlHandle)ihandle); + ModalDialog(PasswordDialogFieldFilter, &hit); + switch (hit) { + case -1: + case cancel: + goto settings_done; + case OK: + goto verify; + default: + GetDItem(dlg, hit, &itype, &ihandle, &irect); + if (itype == (ctrlItem + chkCtrl)) + SetCtlValue(ihandle, !GetCtlValue(ihandle)); + goto get_input; + } + + save = false; +verify: + for (n = 0; n < nitems(settings_defs); n++) { + s = &settings_defs[n]; + sdata = (char *)&tsettings + s->offset; + + GetDItem(dlg, s->ditl_id, &itype, &ihandle, &irect); + + if (s->type == SETTING_PASSWORD) { + memcpy((char *)&stmp, s->password_storage, sizeof(stmp)); + } else if (s->type == SETTING_BOOL) { + snprintf((char *)&stmp, sizeof(stmp), "%d", + GetCtlValue(ihandle)); + } else { + GetIText(ihandle, stmp); + PtoCstr(stmp); + } + + switch (s->type) { + case SETTING_STRING: + case SETTING_PASSWORD: + slen = strlen((char *)stmp); + + if (slen == 0 && (s->flags & SETTING_FLAG_ALLOW_BLANK)) { + /* ok */ + } else { + if (s->min && s->max && s->min == s->max && + slen != s->min) { + warn("%s must be %ld character%s", s->name, s->min, + s->min == 1 ? "" : "s"); + goto get_input; + } + if (s->min && slen < s->min) { + warn("%s is too short (minimum %ld)", s->name, s->min); + goto get_input; + } + if (s->max && slen > s->max) { + warn("%s is too long (maximum %ld)", s->name, s->max); + goto get_input; + } + } + + if (save) { + memset(sdata, 0, s->size); + strlcpy(sdata, (char *)stmp, s->size); + } + break; + case SETTING_SHORT: + case SETTING_USHORT: + case SETTING_LONG: + lval = atol((char *)stmp); + if (lval < s->min) { + if (s->type == SETTING_USHORT) + warn("%s must be at least %ul", s->name, s->min); + else + warn("%s must be at least %ld", s->name, s->min); + goto get_input; + } + if (lval > s->max) { + if (s->type == SETTING_USHORT) + warn("%s must be less than %ul", s->name, s->max); + else + warn("%s must be less than %ld", s->name, s->max); + goto get_input; + } + if (save) { + if (s->type == SETTING_LONG) { + sdata[0] = (lval >> 24) & 0xff; + sdata[1] = (lval >> 16) & 0xff; + sdata[2] = (lval >> 8) & 0xff; + sdata[3] = lval & 0xff; + } else { + sdata[0] = (lval >> 8) & 0xff; + sdata[1] = lval & 0xff; + } + } + break; + case SETTING_BOOL: + if (save) + sdata[0] = (stmp[0] == '1'); + break; + } + } + + if (!save) { + save = true; + goto verify; + } + + /* all validated ok and fields written */ + settings_save(&tsettings); + settings = tsettings; + ret = true; + +settings_done: + PasswordDialogFieldFinish(); + DisposeDialog(dlg); + ReleaseResource(dlgh); + + return ret; +} --- settings.h Fri Aug 30 19:19:30 2024 +++ settings.h Fri Aug 30 19:19:30 2024 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 joshua stein <jcs@jcs.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __SETTINGS_H__ +#define __SETTINGS_H__ + +#include "stdint.h" + +#define SETTINGS_FILENAME "\pWallops Preferences" +#define SETTINGS_FILE_CREATOR 'WLOP' + +#define SETTINGS_DLOG_ID 129 +#define SETTINGS_SERVER_ID 2 +#define SETTINGS_PORT_ID 3 +#define SETTINGS_PASSWORD_ID 4 +#define SETTINGS_NICK_ID 5 +#define SETTINGS_IDENT_ID 6 +#define SETTINGS_REALNAME_ID 7 +#define SETTINGS_HIDE_MOTD_ID 8 +#define SETTINGS_CHANNEL_ID 9 + +#define DEFAULT_SERVER_NAME "irc.libera.chat" +#define DEFAULT_PORT "6667" +#define DEFAULT_IDENT "wallops" +#define DEFAULT_REALNAME "A Macintosh User" +#define DEFAULT_CHANNEL "#cyberpals" +#define DEFAULT_HIDE_MOTD "0" + +struct settings { + short version; +#define SETTINGS_VERSION 1 + char server[64]; + unsigned short port; + char password[32]; + char nick[32]; + char ident[32]; + char realname[32]; + char channel[32]; + unsigned char hide_motd; +}; + +extern struct settings settings; + +bool settings_load(void); +void settings_save(struct settings *tsettings); +bool settings_edit(bool use_defaults); + +#endif \ No newline at end of file