AmendHub

Download:

jcs

/

wikipedia

/

amendments

/

49

*: Make Wikipedia hostname configurable in a new settings window

Most of the settings dialog logic taken from Wallops

jcs made amendment 49 about 1 year ago
--- main.c Tue Aug 29 09:52:21 2023 +++ main.c Mon Oct 16 17:26:29 2023 @@ -22,10 +22,33 @@ #include "focusable.h" #include "util.h" +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[64]; + char password_storage[256]; +} config_fields[] = { + { "Hostname", CONFIG_TYPE_STRING, 1, 255, + SETTINGS_HOSTNAME_ID, STR_HOSTNAME_ID, DEFAULT_HOSTNAME }, +}; + MenuHandle apple_menu, file_menu, edit_menu, view_menu; bool quitting = false; void handle_menu(long menu_id); +void settings_apply_defaults(void); +void settings_show(void); int main(void) @@ -61,6 +84,8 @@ main(void) menu_defaults(); DrawMenuBar(); + settings_apply_defaults(); + if (_TCPInit() != 0) panic("Failed initializing MacTCP"); @@ -192,6 +217,9 @@ handle_menu(long menu_id) break; case FILE_MENU_ID: switch (item) { + case FILE_MENU_SETTINGS_ID: + settings_show(); + break; case FILE_MENU_QUIT_ID: if (focusables_quit()) quitting = true; @@ -211,4 +239,212 @@ menu_defaults(void) DisableItem(edit_menu, EDIT_MENU_COPY_ID); DisableItem(edit_menu, EDIT_MENU_PASTE_ID); DisableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID); +} + +void +settings_apply_defaults(void) +{ + Str255 txt; + StringHandle h; + DialogTHndl dlgh; + DialogPtr dlg; + Handle ihandle; + Rect irect; + size_t size, n, m; + short hit, itype, ret; + + for (n = 0; n < nitems(config_fields); n++) { + struct config_field *cf = &config_fields[n]; + long lval; + short sval; + + if (cf->sdefault[0] == '\0') + continue; + + h = GetString(cf->res_id); + if (h != NULL) { + HLock(h); + if ((*h)[0] > 0) + continue; + + RmveResource(h); + ReleaseResource(h); + } + + size = strlen(cf->sdefault); + h = (StringHandle)xNewHandle(size + 1); + HLock(h); + strlcpy(((char *)*h) + 1, cf->sdefault, size + 1); + (*h)[0] = size; + strlcpy((char *)txt, cf->name, sizeof(txt)); + CtoPstr(txt); + AddResource(h, 'STR ', cf->res_id, txt); + ReleaseResource(h); + } +} + +void +settings_show(void) +{ + Str255 txt, hostname; + GrafPtr old_port; + StringHandle h; + DialogTHndl dlgh; + DialogPtr dlg; + Handle ihandle; + Rect irect; + size_t size, n, m; + short hit, itype, ret; + + /* 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 connection DLOG %d", SETTINGS_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: + /* outline ok button */ + GetPort(&old_port); + SetPort(dlg); + GetDItem(dlg, ok, &itype, &ihandle, &irect); + PenSize(3, 3); + InsetRect(&irect, -4, -4); + FrameRoundRect(&irect, 16, 16); + PenNormal(); + + ModalDialog(PasswordDialogFieldFilter, &hit); + SetPort(old_port); + + switch (hit) { + case -1: + case cancel: + DisposeDialog(dlg); + ReleaseResource(dlgh); + return; + case OK: + goto verify; + default: + GetDItem(dlg, hit, &itype, &ihandle, &irect); + if (itype == (ctrlItem + chkCtrl)) + /* flip checkboxes */ + SetCtlValue(ihandle, 1 - GetCtlValue(ihandle)); + 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 SETTINGS_HOSTNAME_ID: + strlcpy((char *)&hostname, (char *)txt, sizeof(hostname)); + 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); } --- wikipedia.π.r Wed Sep 7 17:20:29 2022 +++ wikipedia.π.r Mon Oct 16 17:35:12 2023 @@ -5,8 +5,10 @@ data 'MENU' (128) { }; data 'MENU' (129) { - $"0081 0000 0000 0000 0000 FFFF FFFF 0446" /* .Å.............F */ - $"696C 6504 5175 6974 0051 0000 00" /* ile.Quit.Q... */ + $"0081 0000 0000 0000 0000 FFFF FFFB 0446" /* .Å.............F */ + $"696C 650B 5365 7474 696E 6773 2E2E 2E00" /* ile.Settings.... */ + $"0000 0001 2D00 0000 0004 5175 6974 0051" /* ....-.....Quit.Q */ + $"0000 00" /* ... */ }; data 'MENU' (130) { @@ -38,6 +40,15 @@ data 'DITL' (130, "ASK") { $"A002 0001" /* †... */ }; +data 'DITL' (129, "SETTINGS_DITL") { + $"0003 0000 0000 003C 00E6 0050 0130 0402" /* .......<...P.0.. */ + $"4F4B 0000 0000 003C 0064 0050 00AE 0406" /* OK.....<.d.P.Æ.. */ + $"4361 6E63 656C 0000 0000 0014 008C 0024" /* Cancel.......å.$ */ + $"0186 1000 0000 0000 000A 000A 002C 0083" /* .Ü...........,.É */ + $"8813 5769 6B69 7065 6469 6120 486F 7374" /* à.Wikipedia Host */ + $"6E61 6D65 3A6C" /* name:l */ +}; + data 'vers' (1) { $"0010 6000 0000 0330 2E31 2630 2E31 20A9" /* ..`....0.1&0.1 © */ $"2032 3032 322C 206A 6F73 6875 6120 7374" /* 2022, joshua st */ @@ -75,5 +86,11 @@ data 'WPDA' (0, "Owner resource") { data 'FREF' (128) { $"4150 504C 0000 7F" /* APPL... */ +}; + +data 'DLOG' (129, "SETTINGS_DLOG") { + $"0052 003C 00AA 01D1 0004 0000 0100 0000" /* .R.<.™.—........ */ + $"0000 0081 1143 6F6E 6E65 6374 2074 6F20" /* ...Å.Connect to */ + $"5365 7276 6572" /* Server */ }; --- wikipedia.c Wed Aug 30 17:51:12 2023 +++ wikipedia.c Mon Oct 16 17:30:54 2023 @@ -23,16 +23,13 @@ #include "utf8.h" #include "util.h" -/* en.wikipedia.org doesn't support non-TLS :( */ -#define WIKIPEDIA_HOST "wikipedia.jcs.org" - struct wikipedia_request * wikipedia_fetch_article(struct browser *browser, char *name) { static char url[256]; struct wikipedia_request *wpr; short state; - char *nencoded; + char *nencoded, *hostname; unsigned char *uname; progress("Fetching \"%s\"...", name); @@ -58,11 +55,20 @@ wikipedia_fetch_article(struct browser *browser, char xfree(&wpr); return NULL; } + + hostname = xGetStringAsChar(STR_HOSTNAME_ID); + if (hostname == NULL) { + progress(NULL); + warn("No Wikipedia hostname set, check Settings"); + xfree(&wpr); + return NULL; + } snprintf(url, sizeof(url), "http://%s/w/api.php?action=query&" "prop=revisions&rvslots=*&rvprop=size|content&" - "format=xml&titles=%s", WIKIPEDIA_HOST, nencoded); + "format=xml&titles=%s", hostname, nencoded); xfree(&nencoded); + xfree(&hostname); wpr->http_request = http_get(url); if (wpr->http_request == NULL) { progress(NULL); @@ -96,7 +102,7 @@ wikipedia_fetch_search_results(struct browser *browser { static char url[256]; struct http_request *req; - char *qencoded; + char *qencoded, *hostname; char **rets = NULL, **trets = NULL; char *str = NULL, *nstr = NULL, c; unsigned char *uquery; @@ -121,10 +127,17 @@ wikipedia_fetch_search_results(struct browser *browser if (qencoded == NULL) return 0; + hostname = xGetStringAsChar(STR_HOSTNAME_ID); + if (hostname == NULL) { + warn("No Wikipedia hostname set, check Settings"); + return 0; + } + len = snprintf(url, sizeof(url), "http://%s/w/api.php?" "action=opensearch&format=xml&namespace=0&limit=10&" - "redirects=return&search=%s", WIKIPEDIA_HOST, qencoded); + "redirects=return&search=%s", hostname, qencoded); xfree(&qencoded); + xfree(&hostname); if (len > sizeof(url)) return 0; --- wikipedia.h Wed Aug 30 14:19:31 2023 +++ wikipedia.h Mon Oct 16 17:11:46 2023 @@ -20,24 +20,31 @@ #include "browser.h" #include "http.h" -#define PROGRAM_NAME "Wikipedia" +#define PROGRAM_NAME "Wikipedia" -#define MBAR_ID 128 +#define MBAR_ID 128 -#define APPLE_MENU_ID 128 -#define APPLE_MENU_ABOUT_ID 1 +#define SETTINGS_DLOG_ID 129 +#define SETTINGS_HOSTNAME_ID 3 -#define FILE_MENU_ID 129 -#define FILE_MENU_QUIT_ID 1 +#define STR_HOSTNAME_ID 1000 +#define DEFAULT_HOSTNAME "wikipedia.jcs.org" -#define EDIT_MENU_ID 130 -#define EDIT_MENU_CUT_ID 1 -#define EDIT_MENU_COPY_ID 2 -#define EDIT_MENU_PASTE_ID 3 -#define EDIT_MENU_SELECT_ALL_ID 4 +#define APPLE_MENU_ID 128 +#define APPLE_MENU_ABOUT_ID 1 -#define VIEW_MENU_ID 131 -#define VIEW_MENU_DEBUG_ID 1 +#define FILE_MENU_ID 129 +#define FILE_MENU_SETTINGS_ID 1 +#define FILE_MENU_QUIT_ID 3 + +#define EDIT_MENU_ID 130 +#define EDIT_MENU_CUT_ID 1 +#define EDIT_MENU_COPY_ID 2 +#define EDIT_MENU_PASTE_ID 3 +#define EDIT_MENU_SELECT_ALL_ID 4 + +#define VIEW_MENU_ID 131 +#define VIEW_MENU_DEBUG_ID 1 extern MenuHandle file_menu, edit_menu, view_menu;