diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-22 07:22:26 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-22 07:22:26 +0300 |
commit | c752568f1cc5cee1d1957644a20482501b96c25c (patch) | |
tree | 33e2deacb98db8598ab118158fd1f494fb6adfbd /src/app.c | |
parent | d14f9aebe27cd48a8d21c0eb691c8e7bf94722a8 (diff) | |
parent | b8471251e785c0c41fdb396c1c55a5fe76363dc2 (diff) |
Merge branch 'work/v1.8' into dev
Diffstat (limited to 'src/app.c')
-rw-r--r-- | src/app.c | 373 |
1 files changed, 278 insertions, 95 deletions
@@ -116,7 +116,7 @@ struct Impl_App { | |||
116 | iMimeHooks * mimehooks; | 116 | iMimeHooks * mimehooks; |
117 | iGmCerts * certs; | 117 | iGmCerts * certs; |
118 | iVisited * visited; | 118 | iVisited * visited; |
119 | iBookmarks * bookmarks; | 119 | iBookmarks * bookmarks; |
120 | iMainWindow *window; | 120 | iMainWindow *window; |
121 | iPtrArray popupWindows; | 121 | iPtrArray popupWindows; |
122 | iSortedArray tickers; /* per-frame callbacks, used for animations */ | 122 | iSortedArray tickers; /* per-frame callbacks, used for animations */ |
@@ -124,6 +124,7 @@ struct Impl_App { | |||
124 | uint32_t elapsedSinceLastTicker; | 124 | uint32_t elapsedSinceLastTicker; |
125 | iBool isRunning; | 125 | iBool isRunning; |
126 | iBool isRunningUnderWindowSystem; | 126 | iBool isRunningUnderWindowSystem; |
127 | iBool isDarkSystemTheme; | ||
127 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) | 128 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) |
128 | iBool isIdling; | 129 | iBool isIdling; |
129 | uint32_t lastEventTime; | 130 | uint32_t lastEventTime; |
@@ -209,12 +210,16 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
209 | } | 210 | } |
210 | #endif | 211 | #endif |
211 | } | 212 | } |
212 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage)); | 213 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.strings[uiLanguage_PrefsString])); |
213 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); | 214 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); |
214 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); | 215 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); |
215 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); | 216 | appendFormat_String(str, |
216 | appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath)); | 217 | "font.set ui:%s heading:%s body:%s mono:%s monodoc:%s\n", |
217 | appendFormat_String(str, "headingfont.set arg:%d\n", d->prefs.headingFont); | 218 | cstr_String(&d->prefs.strings[uiFont_PrefsString]), |
219 | cstr_String(&d->prefs.strings[headingFont_PrefsString]), | ||
220 | cstr_String(&d->prefs.strings[bodyFont_PrefsString]), | ||
221 | cstr_String(&d->prefs.strings[monospaceFont_PrefsString]), | ||
222 | cstr_String(&d->prefs.strings[monospaceDocumentFont_PrefsString])); | ||
218 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); | 223 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); |
219 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); | 224 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); |
220 | appendFormat_String(str, "scrollspeed arg:%d type:%d\n", d->prefs.smoothScrollSpeed[keyboard_ScrollType], keyboard_ScrollType); | 225 | appendFormat_String(str, "scrollspeed arg:%d type:%d\n", d->prefs.smoothScrollSpeed[keyboard_ScrollType], keyboard_ScrollType); |
@@ -226,37 +231,54 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
226 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); | 231 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); |
227 | appendFormat_String(str, "linespacing.set arg:%f\n", d->prefs.lineSpacing); | 232 | appendFormat_String(str, "linespacing.set arg:%f\n", d->prefs.lineSpacing); |
228 | appendFormat_String(str, "returnkey.set arg:%d\n", d->prefs.returnKey); | 233 | appendFormat_String(str, "returnkey.set arg:%d\n", d->prefs.returnKey); |
229 | /* TODO: Set up an array of booleans in Prefs and do these in a loop. */ | 234 | iConstForEach(StringSet, fp, d->prefs.disabledFontPacks) { |
230 | appendFormat_String(str, "prefs.animate.changed arg:%d\n", d->prefs.uiAnimations); | 235 | appendFormat_String(str, "fontpack.disable id:%s\n", cstr_String(fp.value)); |
231 | appendFormat_String(str, "prefs.mono.gemini.changed arg:%d\n", d->prefs.monospaceGemini); | 236 | } |
232 | appendFormat_String(str, "prefs.mono.gopher.changed arg:%d\n", d->prefs.monospaceGopher); | 237 | appendFormat_String(str, "ansiescape arg:%d\n", d->prefs.gemtextAnsiEscapes); |
233 | appendFormat_String(str, "prefs.boldlink.dark.changed arg:%d\n", d->prefs.boldLinkDark); | 238 | /* TODO: This array belongs in Prefs. It can then be used for command handling as well. */ |
234 | appendFormat_String(str, "prefs.boldlink.light.changed arg:%d\n", d->prefs.boldLinkLight); | 239 | const struct { |
235 | appendFormat_String(str, "prefs.biglede.changed arg:%d\n", d->prefs.bigFirstParagraph); | 240 | const char * id; |
236 | appendFormat_String(str, "prefs.plaintext.wrap.changed arg:%d\n", d->prefs.plainTextWrap); | 241 | const iBool *value; |
237 | appendFormat_String(str, "prefs.sideicon.changed arg:%d\n", d->prefs.sideIcon); | 242 | } boolPrefs[] = { |
238 | appendFormat_String(str, "prefs.centershort.changed arg:%d\n", d->prefs.centerShortDocs); | 243 | { "prefs.animate", &d->prefs.uiAnimations }, |
239 | appendFormat_String(str, "prefs.collapsepreonload.changed arg:%d\n", d->prefs.collapsePreOnLoad); | 244 | { "prefs.font.smooth", &d->prefs.fontSmoothing }, |
240 | appendFormat_String(str, "prefs.hoverlink.changed arg:%d\n", d->prefs.hoverLink); | 245 | { "prefs.mono.gemini", &d->prefs.monospaceGemini }, |
241 | appendFormat_String(str, "prefs.bookmarks.addbottom.changed arg:%d\n", d->prefs.addBookmarksToBottom); | 246 | { "prefs.mono.gopher", &d->prefs.monospaceGopher }, |
242 | appendFormat_String(str, "prefs.archive.openindex.changed arg:%d\n", d->prefs.openArchiveIndexPages); | 247 | { "prefs.boldlink.visited", &d->prefs.boldLinkVisited }, |
248 | { "prefs.boldlink.dark", &d->prefs.boldLinkDark }, | ||
249 | { "prefs.boldlink.light", &d->prefs.boldLinkLight }, | ||
250 | { "prefs.biglede", &d->prefs.bigFirstParagraph }, | ||
251 | { "prefs.plaintext.wrap", &d->prefs.plainTextWrap }, | ||
252 | { "prefs.sideicon", &d->prefs.sideIcon }, | ||
253 | { "prefs.centershort", &d->prefs.centerShortDocs }, | ||
254 | { "prefs.collapsepreonload", &d->prefs.collapsePreOnLoad }, | ||
255 | { "prefs.hoverlink", &d->prefs.hoverLink }, | ||
256 | { "prefs.bookmarks.addbottom", &d->prefs.addBookmarksToBottom }, | ||
257 | { "prefs.archive.openindex", &d->prefs.openArchiveIndexPages }, | ||
258 | }; | ||
259 | iForIndices(i, boolPrefs) { | ||
260 | appendFormat_String(str, "%s.changed arg:%d\n", boolPrefs[i].id, *boolPrefs[i].value); | ||
261 | } | ||
243 | appendFormat_String(str, "quoteicon.set arg:%d\n", d->prefs.quoteIcon ? 1 : 0); | 262 | appendFormat_String(str, "quoteicon.set arg:%d\n", d->prefs.quoteIcon ? 1 : 0); |
244 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->prefs.theme); | 263 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->prefs.theme); |
245 | appendFormat_String(str, "accent.set arg:%d\n", d->prefs.accent); | 264 | appendFormat_String(str, "accent.set arg:%d\n", d->prefs.accent); |
246 | appendFormat_String(str, "ostheme arg:%d\n", d->prefs.useSystemTheme); | 265 | appendFormat_String(str, "ostheme arg:%d preferdark:%d preferlight:%d\n", |
266 | d->prefs.useSystemTheme, | ||
267 | d->prefs.systemPreferredColorTheme[0], | ||
268 | d->prefs.systemPreferredColorTheme[1]); | ||
247 | appendFormat_String(str, "doctheme.dark.set arg:%d\n", d->prefs.docThemeDark); | 269 | appendFormat_String(str, "doctheme.dark.set arg:%d\n", d->prefs.docThemeDark); |
248 | appendFormat_String(str, "doctheme.light.set arg:%d\n", d->prefs.docThemeLight); | 270 | appendFormat_String(str, "doctheme.light.set arg:%d\n", d->prefs.docThemeLight); |
249 | appendFormat_String(str, "saturation.set arg:%d\n", (int) ((d->prefs.saturation * 100) + 0.5f)); | 271 | appendFormat_String(str, "saturation.set arg:%d\n", (int) ((d->prefs.saturation * 100) + 0.5f)); |
250 | appendFormat_String(str, "imagestyle.set arg:%d\n", d->prefs.imageStyle); | 272 | appendFormat_String(str, "imagestyle.set arg:%d\n", d->prefs.imageStyle); |
251 | appendFormat_String(str, "ca.file noset:1 path:%s\n", cstr_String(&d->prefs.caFile)); | 273 | appendFormat_String(str, "ca.file noset:1 path:%s\n", cstr_String(&d->prefs.strings[caFile_PrefsString])); |
252 | appendFormat_String(str, "ca.path path:%s\n", cstr_String(&d->prefs.caPath)); | 274 | appendFormat_String(str, "ca.path path:%s\n", cstr_String(&d->prefs.strings[caPath_PrefsString])); |
253 | appendFormat_String(str, "proxy.gemini address:%s\n", cstr_String(&d->prefs.geminiProxy)); | 275 | appendFormat_String(str, "proxy.gemini address:%s\n", cstr_String(&d->prefs.strings[geminiProxy_PrefsString])); |
254 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->prefs.gopherProxy)); | 276 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->prefs.strings[gopherProxy_PrefsString])); |
255 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->prefs.httpProxy)); | 277 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->prefs.strings[httpProxy_PrefsString])); |
256 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) | 278 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) |
257 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->prefs.downloadDir)); | 279 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->prefs.strings[downloadDir_PrefsString])); |
258 | #endif | 280 | #endif |
259 | appendFormat_String(str, "searchurl address:%s\n", cstr_String(&d->prefs.searchUrl)); | 281 | appendFormat_String(str, "searchurl address:%s\n", cstr_String(&d->prefs.strings[searchUrl_PrefsString])); |
260 | appendFormat_String(str, "translation.languages from:%d to:%d\n", d->prefs.langFrom, d->prefs.langTo); | 282 | appendFormat_String(str, "translation.languages from:%d to:%d\n", d->prefs.langFrom, d->prefs.langTo); |
261 | return str; | 283 | return str; |
262 | } | 284 | } |
@@ -330,7 +352,7 @@ static void loadPrefs_App_(iApp *d) { | |||
330 | } | 352 | } |
331 | else if (equal_Command(cmd, "uilang")) { | 353 | else if (equal_Command(cmd, "uilang")) { |
332 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); | 354 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); |
333 | setCStr_String(&d->prefs.uiLanguage, id); | 355 | setCStr_String(&d->prefs.strings[uiLanguage_PrefsString], id); |
334 | setCurrent_Lang(id); | 356 | setCurrent_Lang(id); |
335 | } | 357 | } |
336 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { | 358 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { |
@@ -347,6 +369,10 @@ static void loadPrefs_App_(iApp *d) { | |||
347 | d->initialWindowRect = init_Rect( | 369 | d->initialWindowRect = init_Rect( |
348 | pos.x, pos.y, argLabel_Command(cmd, "width"), argLabel_Command(cmd, "height")); | 370 | pos.x, pos.y, argLabel_Command(cmd, "width"), argLabel_Command(cmd, "height")); |
349 | } | 371 | } |
372 | else if (equal_Command(cmd, "fontpack.disable")) { | ||
373 | insert_StringSet(d->prefs.disabledFontPacks, | ||
374 | collect_String(suffix_Command(cmd, "id"))); | ||
375 | } | ||
350 | #if !defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) | 376 | #if !defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) |
351 | else if (equal_Command(cmd, "downloads")) { | 377 | else if (equal_Command(cmd, "downloads")) { |
352 | continue; /* can't change downloads directory */ | 378 | continue; /* can't change downloads directory */ |
@@ -361,7 +387,8 @@ static void loadPrefs_App_(iApp *d) { | |||
361 | } | 387 | } |
362 | if (!haveCA) { | 388 | if (!haveCA) { |
363 | /* Default CA setup. */ | 389 | /* Default CA setup. */ |
364 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 390 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], |
391 | &d->prefs.strings[caPath_PrefsString]); | ||
365 | } | 392 | } |
366 | #if !defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 393 | #if !defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
367 | d->prefs.customFrame = iFalse; | 394 | d->prefs.customFrame = iFalse; |
@@ -653,6 +680,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
653 | #else | 680 | #else |
654 | d->isRunningUnderWindowSystem = iTrue; | 681 | d->isRunningUnderWindowSystem = iTrue; |
655 | #endif | 682 | #endif |
683 | d->isDarkSystemTheme = iTrue; /* will be updated by system later on, if supported */ | ||
656 | init_CommandLine(&d->args, argc, argv); | 684 | init_CommandLine(&d->args, argc, argv); |
657 | /* Where was the app started from? We ask SDL first because the command line alone is | 685 | /* Where was the app started from? We ask SDL first because the command line alone is |
658 | not a reliable source of this information, particularly when it comes to different | 686 | not a reliable source of this information, particularly when it comes to different |
@@ -759,7 +787,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
759 | listen_Ipc(); /* We'll respond to commands from other instances. */ | 787 | listen_Ipc(); /* We'll respond to commands from other instances. */ |
760 | } | 788 | } |
761 | #endif | 789 | #endif |
762 | printf("Lagrange: A Beautiful Gemini Client\n"); | 790 | puts("Lagrange: A Beautiful Gemini Client"); |
763 | const iBool isFirstRun = | 791 | const iBool isFirstRun = |
764 | !fileExistsCStr_FileInfo(cleanedPath_CStr(concatPath_CStr(dataDir_App_(), "prefs.cfg"))); | 792 | !fileExistsCStr_FileInfo(cleanedPath_CStr(concatPath_CStr(dataDir_App_(), "prefs.cfg"))); |
765 | d->isFinishedLaunching = iFalse; | 793 | d->isFinishedLaunching = iFalse; |
@@ -788,7 +816,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
788 | #endif | 816 | #endif |
789 | init_Prefs(&d->prefs); | 817 | init_Prefs(&d->prefs); |
790 | init_SiteSpec(dataDir_App_()); | 818 | init_SiteSpec(dataDir_App_()); |
791 | setCStr_String(&d->prefs.downloadDir, downloadDir_App_()); | 819 | setCStr_String(&d->prefs.strings[downloadDir_PrefsString], downloadDir_App_()); |
792 | set_Atomic(&d->pendingRefresh, iFalse); | 820 | set_Atomic(&d->pendingRefresh, iFalse); |
793 | d->isRunning = iFalse; | 821 | d->isRunning = iFalse; |
794 | d->window = NULL; | 822 | d->window = NULL; |
@@ -804,9 +832,11 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
804 | setupApplication_iOS(); | 832 | setupApplication_iOS(); |
805 | #endif | 833 | #endif |
806 | init_Keys(); | 834 | init_Keys(); |
835 | init_Fonts(dataDir_App_()); | ||
807 | loadPalette_Color(dataDir_App_()); | 836 | loadPalette_Color(dataDir_App_()); |
808 | setThemePalette_Color(d->prefs.theme); /* default UI colors */ | 837 | setThemePalette_Color(d->prefs.theme); /* default UI colors */ |
809 | loadPrefs_App_(d); | 838 | loadPrefs_App_(d); |
839 | updateActive_Fonts(); | ||
810 | load_Keys(dataDir_App_()); | 840 | load_Keys(dataDir_App_()); |
811 | /* See if the user wants to override the window size. */ { | 841 | /* See if the user wants to override the window size. */ { |
812 | iCommandLineArg *arg = iClob(checkArgument_CommandLine(&d->args, windowWidth_CommandLineOption)); | 842 | iCommandLineArg *arg = iClob(checkArgument_CommandLine(&d->args, windowWidth_CommandLineOption)); |
@@ -881,11 +911,14 @@ static void deinit_App(iApp *d) { | |||
881 | #endif | 911 | #endif |
882 | SDL_RemoveTimer(d->autoReloadTimer); | 912 | SDL_RemoveTimer(d->autoReloadTimer); |
883 | saveState_App_(d); | 913 | saveState_App_(d); |
914 | savePrefs_App_(d); | ||
915 | delete_MainWindow(d->window); | ||
916 | d->window = NULL; | ||
884 | deinit_Feeds(); | 917 | deinit_Feeds(); |
885 | save_Keys(dataDir_App_()); | 918 | save_Keys(dataDir_App_()); |
886 | deinit_Keys(); | 919 | deinit_Keys(); |
920 | deinit_Fonts(); | ||
887 | deinit_SiteSpec(); | 921 | deinit_SiteSpec(); |
888 | savePrefs_App_(d); | ||
889 | deinit_Prefs(&d->prefs); | 922 | deinit_Prefs(&d->prefs); |
890 | save_Bookmarks(d->bookmarks, dataDir_App_()); | 923 | save_Bookmarks(d->bookmarks, dataDir_App_()); |
891 | delete_Bookmarks(d->bookmarks); | 924 | delete_Bookmarks(d->bookmarks); |
@@ -894,7 +927,6 @@ static void deinit_App(iApp *d) { | |||
894 | delete_GmCerts(d->certs); | 927 | delete_GmCerts(d->certs); |
895 | save_MimeHooks(d->mimehooks); | 928 | save_MimeHooks(d->mimehooks); |
896 | delete_MimeHooks(d->mimehooks); | 929 | delete_MimeHooks(d->mimehooks); |
897 | delete_MainWindow(d->window); | ||
898 | d->window = NULL; | 930 | d->window = NULL; |
899 | deinit_CommandLine(&d->args); | 931 | deinit_CommandLine(&d->args); |
900 | iRelease(d->launchCommands); | 932 | iRelease(d->launchCommands); |
@@ -917,7 +949,7 @@ const iString *dataDir_App(void) { | |||
917 | } | 949 | } |
918 | 950 | ||
919 | const iString *downloadDir_App(void) { | 951 | const iString *downloadDir_App(void) { |
920 | return collect_String(cleaned_Path(&app_.prefs.downloadDir)); | 952 | return collect_String(cleaned_Path(&app_.prefs.strings[downloadDir_PrefsString])); |
921 | } | 953 | } |
922 | 954 | ||
923 | const iString *downloadPathForUrl_App(const iString *url, const iString *mime) { | 955 | const iString *downloadPathForUrl_App(const iString *url, const iString *mime) { |
@@ -1080,6 +1112,20 @@ void trimMemory_App(void) { | |||
1080 | iRelease(docs); | 1112 | iRelease(docs); |
1081 | } | 1113 | } |
1082 | 1114 | ||
1115 | #if 0 | ||
1116 | iBool findCachedContent_App(const iString *url, iString *mime_out, iBlock *data_out) { | ||
1117 | /* Cached content can be found in MediaRequests of DocumentWidgets (loaded on the currently | ||
1118 | open page) and the DocumentWidget itself. `Media` doesn't store source data, only | ||
1119 | presentation data. */ | ||
1120 | iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { | ||
1121 | if (findCachedContent_DocumentWidget(i.object, url, mime_out, data_out)) { | ||
1122 | return iTrue; | ||
1123 | } | ||
1124 | } | ||
1125 | return iFalse; | ||
1126 | } | ||
1127 | #endif | ||
1128 | |||
1083 | iLocalDef iBool isWaitingAllowed_App_(iApp *d) { | 1129 | iLocalDef iBool isWaitingAllowed_App_(iApp *d) { |
1084 | if (!isEmpty_Periodic(&d->periodic)) { | 1130 | if (!isEmpty_Periodic(&d->periodic)) { |
1085 | return iFalse; | 1131 | return iFalse; |
@@ -1516,13 +1562,13 @@ const iString *schemeProxy_App(iRangecc scheme) { | |||
1516 | iApp *d = &app_; | 1562 | iApp *d = &app_; |
1517 | const iString *proxy = NULL; | 1563 | const iString *proxy = NULL; |
1518 | if (equalCase_Rangecc(scheme, "gemini")) { | 1564 | if (equalCase_Rangecc(scheme, "gemini")) { |
1519 | proxy = &d->prefs.geminiProxy; | 1565 | proxy = &d->prefs.strings[geminiProxy_PrefsString]; |
1520 | } | 1566 | } |
1521 | else if (equalCase_Rangecc(scheme, "gopher")) { | 1567 | else if (equalCase_Rangecc(scheme, "gopher")) { |
1522 | proxy = &d->prefs.gopherProxy; | 1568 | proxy = &d->prefs.strings[gopherProxy_PrefsString]; |
1523 | } | 1569 | } |
1524 | else if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { | 1570 | else if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { |
1525 | proxy = &d->prefs.httpProxy; | 1571 | proxy = &d->prefs.strings[httpProxy_PrefsString]; |
1526 | } | 1572 | } |
1527 | return isEmpty_String(proxy) ? NULL : proxy; | 1573 | return isEmpty_String(proxy) ? NULL : proxy; |
1528 | } | 1574 | } |
@@ -1726,9 +1772,9 @@ static void updateColorThemeButton_(iLabelWidget *button, int theme) { | |||
1726 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", theme)); | 1772 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", theme)); |
1727 | } | 1773 | } |
1728 | 1774 | ||
1729 | static void updateFontButton_(iLabelWidget *button, int font) { | 1775 | static void updateFontButton_(iLabelWidget *button, const iString *fontId) { |
1730 | if (!button) return; | 1776 | if (!button || isEmpty_String(fontId)) return; |
1731 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", font)); | 1777 | updateDropdownSelection_LabelWidget(button, format_CStr(":%s", cstr_String(fontId))); |
1732 | } | 1778 | } |
1733 | 1779 | ||
1734 | static void updateImageStyleButton_(iLabelWidget *button, int style) { | 1780 | static void updateImageStyleButton_(iLabelWidget *button, int style) { |
@@ -1822,11 +1868,11 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1822 | return iFalse; | 1868 | return iFalse; |
1823 | } | 1869 | } |
1824 | else if (equal_Command(cmd, "font.set")) { | 1870 | else if (equal_Command(cmd, "font.set")) { |
1825 | updateFontButton_(findChild_Widget(d, "prefs.font"), arg_Command(cmd)); | 1871 | updateFontButton_(findChild_Widget(d, "prefs.font.ui"), string_Command(cmd, "ui")); |
1826 | return iFalse; | 1872 | updateFontButton_(findChild_Widget(d, "prefs.font.heading"), string_Command(cmd, "heading")); |
1827 | } | 1873 | updateFontButton_(findChild_Widget(d, "prefs.font.body"), string_Command(cmd, "body")); |
1828 | else if (equal_Command(cmd, "headingfont.set")) { | 1874 | updateFontButton_(findChild_Widget(d, "prefs.font.mono"), string_Command(cmd, "mono")); |
1829 | updateFontButton_(findChild_Widget(d, "prefs.headingfont"), arg_Command(cmd)); | 1875 | updateFontButton_(findChild_Widget(d, "prefs.font.monodoc"), string_Command(cmd, "monodoc")); |
1830 | return iFalse; | 1876 | return iFalse; |
1831 | } | 1877 | } |
1832 | else if (startsWith_CStr(cmd, "input.ended id:prefs.linespacing")) { | 1878 | else if (startsWith_CStr(cmd, "input.ended id:prefs.linespacing")) { |
@@ -1841,7 +1887,7 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1841 | else if (equal_Command(cmd, "theme.changed")) { | 1887 | else if (equal_Command(cmd, "theme.changed")) { |
1842 | updatePrefsThemeButtons_(d); | 1888 | updatePrefsThemeButtons_(d); |
1843 | if (!argLabel_Command(cmd, "auto")) { | 1889 | if (!argLabel_Command(cmd, "auto")) { |
1844 | setToggle_Widget(findChild_Widget(d, "prefs.ostheme"), iFalse); | 1890 | setToggle_Widget(findChild_Widget(d, "prefs.ostheme"), prefs_App()->useSystemTheme); |
1845 | } | 1891 | } |
1846 | } | 1892 | } |
1847 | else if (equalWidget_Command(cmd, d, "input.resized")) { | 1893 | else if (equalWidget_Command(cmd, d, "input.resized")) { |
@@ -2040,14 +2086,16 @@ iBool willUseProxy_App(const iRangecc scheme) { | |||
2040 | 2086 | ||
2041 | const iString *searchQueryUrl_App(const iString *queryStringUnescaped) { | 2087 | const iString *searchQueryUrl_App(const iString *queryStringUnescaped) { |
2042 | iApp *d = &app_; | 2088 | iApp *d = &app_; |
2043 | if (isEmpty_String(&d->prefs.searchUrl)) { | 2089 | if (isEmpty_String(&d->prefs.strings[searchUrl_PrefsString])) { |
2044 | return collectNew_String(); | 2090 | return collectNew_String(); |
2045 | } | 2091 | } |
2046 | const iString *escaped = urlEncode_String(queryStringUnescaped); | 2092 | const iString *escaped = urlEncode_String(queryStringUnescaped); |
2047 | return collectNewFormat_String("%s?%s", cstr_String(&d->prefs.searchUrl), cstr_String(escaped)); | 2093 | return collectNewFormat_String( |
2094 | "%s?%s", cstr_String(&d->prefs.strings[searchUrl_PrefsString]), cstr_String(escaped)); | ||
2048 | } | 2095 | } |
2049 | 2096 | ||
2050 | static void resetFonts_App_(iApp *d) { | 2097 | void resetFonts_App(void) { |
2098 | iApp *d = &app_; | ||
2051 | iConstForEach(PtrArray, win, listWindows_App_(d)) { | 2099 | iConstForEach(PtrArray, win, listWindows_App_(d)) { |
2052 | resetFonts_Text(text_Window(win.ptr)); | 2100 | resetFonts_Text(text_Window(win.ptr)); |
2053 | } | 2101 | } |
@@ -2074,9 +2122,10 @@ iBool handleCommand_App(const char *cmd) { | |||
2074 | } | 2122 | } |
2075 | else if (equal_Command(cmd, "uilang")) { | 2123 | else if (equal_Command(cmd, "uilang")) { |
2076 | const iString *lang = string_Command(cmd, "id"); | 2124 | const iString *lang = string_Command(cmd, "id"); |
2077 | if (!equal_String(lang, &d->prefs.uiLanguage)) { | 2125 | iString *val = &d->prefs.strings[uiLanguage_PrefsString]; |
2078 | set_String(&d->prefs.uiLanguage, lang); | 2126 | if (!equal_String(lang, val)) { |
2079 | setCurrent_Lang(cstr_String(&d->prefs.uiLanguage)); | 2127 | set_String(val, lang); |
2128 | setCurrent_Lang(cstr_String(val)); | ||
2080 | postCommand_App("lang.changed"); | 2129 | postCommand_App("lang.changed"); |
2081 | } | 2130 | } |
2082 | return iTrue; | 2131 | return iTrue; |
@@ -2123,9 +2172,14 @@ iBool handleCommand_App(const char *cmd) { | |||
2123 | return iTrue; | 2172 | return iTrue; |
2124 | } | 2173 | } |
2125 | else if (equal_Command(cmd, "font.reset")) { | 2174 | else if (equal_Command(cmd, "font.reset")) { |
2126 | resetFonts_App_(d); | 2175 | resetFonts_App(); |
2176 | return iTrue; | ||
2177 | } | ||
2178 | else if (equal_Command(cmd, "font.reload")) { | ||
2179 | reload_Fonts(); /* also does font cache reset, window invalidation */ | ||
2127 | return iTrue; | 2180 | return iTrue; |
2128 | } | 2181 | } |
2182 | #if 0 | ||
2129 | else if (equal_Command(cmd, "font.user")) { | 2183 | else if (equal_Command(cmd, "font.user")) { |
2130 | const char *path = suffixPtr_Command(cmd, "path"); | 2184 | const char *path = suffixPtr_Command(cmd, "path"); |
2131 | if (cmp_String(&d->prefs.symbolFontPath, path)) { | 2185 | if (cmp_String(&d->prefs.symbolFontPath, path)) { |
@@ -2134,7 +2188,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2134 | } | 2188 | } |
2135 | setCStr_String(&d->prefs.symbolFontPath, path); | 2189 | setCStr_String(&d->prefs.symbolFontPath, path); |
2136 | loadUserFonts_Text(); | 2190 | loadUserFonts_Text(); |
2137 | resetFonts_App_(d); | 2191 | resetFonts_App(d); |
2138 | if (!isFrozen) { | 2192 | if (!isFrozen) { |
2139 | postCommand_App("font.changed"); | 2193 | postCommand_App("font.changed"); |
2140 | postCommand_App("window.unfreeze"); | 2194 | postCommand_App("window.unfreeze"); |
@@ -2142,18 +2196,43 @@ iBool handleCommand_App(const char *cmd) { | |||
2142 | } | 2196 | } |
2143 | return iTrue; | 2197 | return iTrue; |
2144 | } | 2198 | } |
2199 | #endif | ||
2145 | else if (equal_Command(cmd, "font.set")) { | 2200 | else if (equal_Command(cmd, "font.set")) { |
2146 | if (!isFrozen) { | 2201 | if (!isFrozen) { |
2147 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); | 2202 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); |
2148 | } | 2203 | } |
2149 | d->prefs.font = arg_Command(cmd); | 2204 | struct { |
2150 | setContentFont_Text(text_Window(d->window), d->prefs.font); | 2205 | const char *label; |
2206 | enum iPrefsString ps; | ||
2207 | int fontId; | ||
2208 | } params[] = { | ||
2209 | { "ui", uiFont_PrefsString, default_FontId }, | ||
2210 | { "mono", monospaceFont_PrefsString, monospace_FontId }, | ||
2211 | { "heading", headingFont_PrefsString, documentHeading_FontId }, | ||
2212 | { "body", bodyFont_PrefsString, documentBody_FontId }, | ||
2213 | { "monodoc", monospaceDocumentFont_PrefsString, documentMonospace_FontId }, | ||
2214 | }; | ||
2215 | iBool wasChanged = iFalse; | ||
2216 | iForIndices(i, params) { | ||
2217 | if (hasLabel_Command(cmd, params[i].label)) { | ||
2218 | iString *ps = &d->prefs.strings[params[i].ps]; | ||
2219 | const iString *newFont = string_Command(cmd, params[i].label); | ||
2220 | if (!equal_String(ps, newFont)) { | ||
2221 | set_String(ps, newFont); | ||
2222 | wasChanged = iTrue; | ||
2223 | } | ||
2224 | } | ||
2225 | } | ||
2226 | if (wasChanged) { | ||
2227 | resetFonts_Text(text_Window(get_MainWindow())); | ||
2228 | } | ||
2151 | if (!isFrozen) { | 2229 | if (!isFrozen) { |
2152 | postCommand_App("font.changed"); | 2230 | postCommand_App("font.changed"); |
2153 | postCommand_App("window.unfreeze"); | 2231 | postCommand_App("window.unfreeze"); |
2154 | } | 2232 | } |
2155 | return iTrue; | 2233 | return iTrue; |
2156 | } | 2234 | } |
2235 | #if 0 | ||
2157 | else if (equal_Command(cmd, "headingfont.set")) { | 2236 | else if (equal_Command(cmd, "headingfont.set")) { |
2158 | if (!isFrozen) { | 2237 | if (!isFrozen) { |
2159 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); | 2238 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); |
@@ -2166,12 +2245,13 @@ iBool handleCommand_App(const char *cmd) { | |||
2166 | } | 2245 | } |
2167 | return iTrue; | 2246 | return iTrue; |
2168 | } | 2247 | } |
2248 | #endif | ||
2169 | else if (equal_Command(cmd, "zoom.set")) { | 2249 | else if (equal_Command(cmd, "zoom.set")) { |
2170 | if (!isFrozen) { | 2250 | if (!isFrozen) { |
2171 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */ | 2251 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */ |
2172 | } | 2252 | } |
2173 | d->prefs.zoomPercent = arg_Command(cmd); | 2253 | d->prefs.zoomPercent = arg_Command(cmd); |
2174 | setContentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); | 2254 | setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); |
2175 | if (!isFrozen) { | 2255 | if (!isFrozen) { |
2176 | postCommand_App("font.changed"); | 2256 | postCommand_App("font.changed"); |
2177 | postCommand_App("window.unfreeze"); | 2257 | postCommand_App("window.unfreeze"); |
@@ -2187,7 +2267,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2187 | delta /= 2; | 2267 | delta /= 2; |
2188 | } | 2268 | } |
2189 | d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200); | 2269 | d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200); |
2190 | setContentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); | 2270 | setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); |
2191 | if (!isFrozen) { | 2271 | if (!isFrozen) { |
2192 | postCommand_App("font.changed"); | 2272 | postCommand_App("font.changed"); |
2193 | postCommand_App("window.unfreeze"); | 2273 | postCommand_App("window.unfreeze"); |
@@ -2232,7 +2312,15 @@ iBool handleCommand_App(const char *cmd) { | |||
2232 | const int isAuto = argLabel_Command(cmd, "auto"); | 2312 | const int isAuto = argLabel_Command(cmd, "auto"); |
2233 | d->prefs.theme = arg_Command(cmd); | 2313 | d->prefs.theme = arg_Command(cmd); |
2234 | if (!isAuto) { | 2314 | if (!isAuto) { |
2235 | postCommand_App("ostheme arg:0"); | 2315 | if (isDark_ColorTheme(d->prefs.theme) && d->isDarkSystemTheme) { |
2316 | d->prefs.systemPreferredColorTheme[0] = d->prefs.theme; | ||
2317 | } | ||
2318 | else if (!isDark_ColorTheme(d->prefs.theme) && !d->isDarkSystemTheme) { | ||
2319 | d->prefs.systemPreferredColorTheme[1] = d->prefs.theme; | ||
2320 | } | ||
2321 | else { | ||
2322 | postCommand_App("ostheme arg:0"); | ||
2323 | } | ||
2236 | } | 2324 | } |
2237 | setThemePalette_Color(d->prefs.theme); | 2325 | setThemePalette_Color(d->prefs.theme); |
2238 | postCommandf_App("theme.changed auto:%d", isAuto); | 2326 | postCommandf_App("theme.changed auto:%d", isAuto); |
@@ -2248,6 +2336,12 @@ iBool handleCommand_App(const char *cmd) { | |||
2248 | } | 2336 | } |
2249 | else if (equal_Command(cmd, "ostheme")) { | 2337 | else if (equal_Command(cmd, "ostheme")) { |
2250 | d->prefs.useSystemTheme = arg_Command(cmd); | 2338 | d->prefs.useSystemTheme = arg_Command(cmd); |
2339 | if (hasLabel_Command(cmd, "preferdark")) { | ||
2340 | d->prefs.systemPreferredColorTheme[0] = argLabel_Command(cmd, "preferdark"); | ||
2341 | } | ||
2342 | if (hasLabel_Command(cmd, "preferlight")) { | ||
2343 | d->prefs.systemPreferredColorTheme[1] = argLabel_Command(cmd, "preferlight"); | ||
2344 | } | ||
2251 | return iTrue; | 2345 | return iTrue; |
2252 | } | 2346 | } |
2253 | else if (equal_Command(cmd, "doctheme.dark.set")) { | 2347 | else if (equal_Command(cmd, "doctheme.dark.set")) { |
@@ -2280,7 +2374,31 @@ iBool handleCommand_App(const char *cmd) { | |||
2280 | } | 2374 | } |
2281 | else if (equal_Command(cmd, "quoteicon.set")) { | 2375 | else if (equal_Command(cmd, "quoteicon.set")) { |
2282 | d->prefs.quoteIcon = arg_Command(cmd) != 0; | 2376 | d->prefs.quoteIcon = arg_Command(cmd) != 0; |
2283 | postCommand_App("document.layout.changed"); | 2377 | postCommand_App("document.layout.changed redo:1"); |
2378 | return iTrue; | ||
2379 | } | ||
2380 | else if (equal_Command(cmd, "prefs.font.smooth.changed")) { | ||
2381 | if (!isFrozen) { | ||
2382 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); | ||
2383 | } | ||
2384 | d->prefs.fontSmoothing = arg_Command(cmd) != 0; | ||
2385 | if (!isFrozen) { | ||
2386 | resetFonts_Text(text_Window(get_MainWindow())); /* clear the glyph cache */ | ||
2387 | postCommand_App("font.changed"); | ||
2388 | postCommand_App("window.unfreeze"); | ||
2389 | } | ||
2390 | return iTrue; | ||
2391 | } | ||
2392 | else if (equal_Command(cmd, "ansiescape")) { | ||
2393 | d->prefs.gemtextAnsiEscapes = arg_Command(cmd); | ||
2394 | return iTrue; | ||
2395 | } | ||
2396 | else if (equal_Command(cmd, "prefs.gemtext.ansi.fg.changed")) { | ||
2397 | iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFg_AnsiFlag, arg_Command(cmd)); | ||
2398 | return iTrue; | ||
2399 | } | ||
2400 | else if (equal_Command(cmd, "prefs.gemtext.ansi.fontstyle.changed")) { | ||
2401 | iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFontStyle_AnsiFlag, arg_Command(cmd)); | ||
2284 | return iTrue; | 2402 | return iTrue; |
2285 | } | 2403 | } |
2286 | else if (equal_Command(cmd, "prefs.mono.gemini.changed") || | 2404 | else if (equal_Command(cmd, "prefs.mono.gemini.changed") || |
@@ -2303,9 +2421,13 @@ iBool handleCommand_App(const char *cmd) { | |||
2303 | return iTrue; | 2421 | return iTrue; |
2304 | } | 2422 | } |
2305 | else if (equal_Command(cmd, "prefs.boldlink.dark.changed") || | 2423 | else if (equal_Command(cmd, "prefs.boldlink.dark.changed") || |
2306 | equal_Command(cmd, "prefs.boldlink.light.changed")) { | 2424 | equal_Command(cmd, "prefs.boldlink.light.changed") || |
2425 | equal_Command(cmd, "prefs.boldlink.visited.changed")) { | ||
2307 | const iBool isSet = (arg_Command(cmd) != 0); | 2426 | const iBool isSet = (arg_Command(cmd) != 0); |
2308 | if (startsWith_CStr(cmd, "prefs.boldlink.dark")) { | 2427 | if (startsWith_CStr(cmd, "prefs.boldlink.visited")) { |
2428 | d->prefs.boldLinkVisited = isSet; | ||
2429 | } | ||
2430 | else if (startsWith_CStr(cmd, "prefs.boldlink.dark")) { | ||
2309 | d->prefs.boldLinkDark = isSet; | 2431 | d->prefs.boldLinkDark = isSet; |
2310 | } | 2432 | } |
2311 | else { | 2433 | else { |
@@ -2390,7 +2512,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2390 | return iTrue; | 2512 | return iTrue; |
2391 | } | 2513 | } |
2392 | else if (equal_Command(cmd, "searchurl")) { | 2514 | else if (equal_Command(cmd, "searchurl")) { |
2393 | iString *url = &d->prefs.searchUrl; | 2515 | iString *url = &d->prefs.strings[searchUrl_PrefsString]; |
2394 | setCStr_String(url, suffixPtr_Command(cmd, "address")); | 2516 | setCStr_String(url, suffixPtr_Command(cmd, "address")); |
2395 | if (startsWith_String(url, "//")) { | 2517 | if (startsWith_String(url, "//")) { |
2396 | prependCStr_String(url, "gemini:"); | 2518 | prependCStr_String(url, "gemini:"); |
@@ -2401,20 +2523,20 @@ iBool handleCommand_App(const char *cmd) { | |||
2401 | return iTrue; | 2523 | return iTrue; |
2402 | } | 2524 | } |
2403 | else if (equal_Command(cmd, "proxy.gemini")) { | 2525 | else if (equal_Command(cmd, "proxy.gemini")) { |
2404 | setCStr_String(&d->prefs.geminiProxy, suffixPtr_Command(cmd, "address")); | 2526 | setCStr_String(&d->prefs.strings[geminiProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2405 | return iTrue; | 2527 | return iTrue; |
2406 | } | 2528 | } |
2407 | else if (equal_Command(cmd, "proxy.gopher")) { | 2529 | else if (equal_Command(cmd, "proxy.gopher")) { |
2408 | setCStr_String(&d->prefs.gopherProxy, suffixPtr_Command(cmd, "address")); | 2530 | setCStr_String(&d->prefs.strings[gopherProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2409 | return iTrue; | 2531 | return iTrue; |
2410 | } | 2532 | } |
2411 | else if (equal_Command(cmd, "proxy.http")) { | 2533 | else if (equal_Command(cmd, "proxy.http")) { |
2412 | setCStr_String(&d->prefs.httpProxy, suffixPtr_Command(cmd, "address")); | 2534 | setCStr_String(&d->prefs.strings[httpProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2413 | return iTrue; | 2535 | return iTrue; |
2414 | } | 2536 | } |
2415 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) | 2537 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) |
2416 | else if (equal_Command(cmd, "downloads")) { | 2538 | else if (equal_Command(cmd, "downloads")) { |
2417 | setCStr_String(&d->prefs.downloadDir, suffixPtr_Command(cmd, "path")); | 2539 | setCStr_String(&d->prefs.strings[downloadDir_PrefsString], suffixPtr_Command(cmd, "path")); |
2418 | return iTrue; | 2540 | return iTrue; |
2419 | } | 2541 | } |
2420 | #endif | 2542 | #endif |
@@ -2423,16 +2545,16 @@ iBool handleCommand_App(const char *cmd) { | |||
2423 | return iTrue; | 2545 | return iTrue; |
2424 | } | 2546 | } |
2425 | else if (equal_Command(cmd, "ca.file")) { | 2547 | else if (equal_Command(cmd, "ca.file")) { |
2426 | setCStr_String(&d->prefs.caFile, suffixPtr_Command(cmd, "path")); | 2548 | setCStr_String(&d->prefs.strings[caFile_PrefsString], suffixPtr_Command(cmd, "path")); |
2427 | if (!argLabel_Command(cmd, "noset")) { | 2549 | if (!argLabel_Command(cmd, "noset")) { |
2428 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 2550 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]); |
2429 | } | 2551 | } |
2430 | return iTrue; | 2552 | return iTrue; |
2431 | } | 2553 | } |
2432 | else if (equal_Command(cmd, "ca.path")) { | 2554 | else if (equal_Command(cmd, "ca.path")) { |
2433 | setCStr_String(&d->prefs.caPath, suffixPtr_Command(cmd, "path")); | 2555 | setCStr_String(&d->prefs.strings[caPath_PrefsString], suffixPtr_Command(cmd, "path")); |
2434 | if (!argLabel_Command(cmd, "noset")) { | 2556 | if (!argLabel_Command(cmd, "noset")) { |
2435 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 2557 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]); |
2436 | } | 2558 | } |
2437 | return iTrue; | 2559 | return iTrue; |
2438 | } | 2560 | } |
@@ -2456,18 +2578,29 @@ iBool handleCommand_App(const char *cmd) { | |||
2456 | const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0; | 2578 | const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0; |
2457 | iUrl parts; | 2579 | iUrl parts; |
2458 | init_Url(&parts, url); | 2580 | init_Url(&parts, url); |
2581 | if (equal_Rangecc(parts.scheme, "about") && equal_Rangecc(parts.path, "command") && | ||
2582 | !isEmpty_Range(&parts.query)) { | ||
2583 | /* NOTE: Careful here! `about:command` allows issuing UI events via links on the page. | ||
2584 | There is a special set of pages where these are allowed (e.g., "about:fonts"). | ||
2585 | On every other page, `about:command` links will not be clickable. */ | ||
2586 | iString *query = collectNewRange_String((iRangecc){ | ||
2587 | parts.query.start + 1, parts.query.end | ||
2588 | }); | ||
2589 | replace_String(query, "%20", " "); | ||
2590 | postCommandString_Root(NULL, query); | ||
2591 | return iTrue; | ||
2592 | } | ||
2459 | if (equalCase_Rangecc(parts.scheme, "titan")) { | 2593 | if (equalCase_Rangecc(parts.scheme, "titan")) { |
2460 | iUploadWidget *upload = new_UploadWidget(); | 2594 | iUploadWidget *upload = new_UploadWidget(); |
2461 | setUrl_UploadWidget(upload, url); | 2595 | setUrl_UploadWidget(upload, url); |
2462 | setResponseViewer_UploadWidget(upload, document_App()); | 2596 | setResponseViewer_UploadWidget(upload, document_App()); |
2463 | addChild_Widget(get_Root()->widget, iClob(upload)); | 2597 | addChild_Widget(get_Root()->widget, iClob(upload)); |
2464 | // finalizeSheet_Mobile(as_Widget(upload)); | ||
2465 | setupSheetTransition_Mobile(as_Widget(upload), iTrue); | 2598 | setupSheetTransition_Mobile(as_Widget(upload), iTrue); |
2466 | postRefresh_App(); | 2599 | postRefresh_App(); |
2467 | return iTrue; | 2600 | return iTrue; |
2468 | } | 2601 | } |
2469 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || | 2602 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || |
2470 | ((noProxy || isEmpty_String(&d->prefs.httpProxy)) && | 2603 | ((noProxy || isEmpty_String(&d->prefs.strings[httpProxy_PrefsString])) && |
2471 | (equalCase_Rangecc(parts.scheme, "http") || | 2604 | (equalCase_Rangecc(parts.scheme, "http") || |
2472 | equalCase_Rangecc(parts.scheme, "https")))) { | 2605 | equalCase_Rangecc(parts.scheme, "https")))) { |
2473 | openInDefaultBrowser_App(url); | 2606 | openInDefaultBrowser_App(url); |
@@ -2620,6 +2753,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2620 | const iBool isSplit = numRoots_Window(get_Window()) > 1; | 2753 | const iBool isSplit = numRoots_Window(get_Window()) > 1; |
2621 | if (tabCount_Widget(tabs) > 1 || isSplit) { | 2754 | if (tabCount_Widget(tabs) > 1 || isSplit) { |
2622 | iWidget *closed = removeTabPage_Widget(tabs, index); | 2755 | iWidget *closed = removeTabPage_Widget(tabs, index); |
2756 | cancelAllRequests_DocumentWidget((iDocumentWidget *) closed); | ||
2623 | destroy_Widget(closed); /* released later */ | 2757 | destroy_Widget(closed); /* released later */ |
2624 | if (index == tabCount_Widget(tabs)) { | 2758 | if (index == tabCount_Widget(tabs)) { |
2625 | index--; | 2759 | index--; |
@@ -2655,7 +2789,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2655 | else if (equal_Command(cmd, "preferences")) { | 2789 | else if (equal_Command(cmd, "preferences")) { |
2656 | iWidget *dlg = makePreferences_Widget(); | 2790 | iWidget *dlg = makePreferences_Widget(); |
2657 | updatePrefsThemeButtons_(dlg); | 2791 | updatePrefsThemeButtons_(dlg); |
2658 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->prefs.downloadDir); | 2792 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->prefs.strings[downloadDir_PrefsString]); |
2659 | setToggle_Widget(findChild_Widget(dlg, "prefs.hoverlink"), d->prefs.hoverLink); | 2793 | setToggle_Widget(findChild_Widget(dlg, "prefs.hoverlink"), d->prefs.hoverLink); |
2660 | setToggle_Widget(findChild_Widget(dlg, "prefs.smoothscroll"), d->prefs.smoothScrolling); | 2794 | setToggle_Widget(findChild_Widget(dlg, "prefs.smoothscroll"), d->prefs.smoothScrolling); |
2661 | setToggle_Widget(findChild_Widget(dlg, "prefs.imageloadscroll"), d->prefs.loadImageInsteadOfScrolling); | 2795 | setToggle_Widget(findChild_Widget(dlg, "prefs.imageloadscroll"), d->prefs.loadImageInsteadOfScrolling); |
@@ -2665,36 +2799,44 @@ iBool handleCommand_App(const char *cmd) { | |||
2665 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); | 2799 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); |
2666 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); | 2800 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); |
2667 | setToggle_Widget(findChild_Widget(dlg, "prefs.animate"), d->prefs.uiAnimations); | 2801 | setToggle_Widget(findChild_Widget(dlg, "prefs.animate"), d->prefs.uiAnimations); |
2668 | setText_InputWidget(findChild_Widget(dlg, "prefs.userfont"), &d->prefs.symbolFontPath); | 2802 | // setText_InputWidget(findChild_Widget(dlg, "prefs.userfont"), &d->prefs.symbolFontPath); |
2669 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); | 2803 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); |
2670 | updateScrollSpeedButtons_(dlg, mouse_ScrollType, d->prefs.smoothScrollSpeed[mouse_ScrollType]); | 2804 | updateScrollSpeedButtons_(dlg, mouse_ScrollType, d->prefs.smoothScrollSpeed[mouse_ScrollType]); |
2671 | updateScrollSpeedButtons_(dlg, keyboard_ScrollType, d->prefs.smoothScrollSpeed[keyboard_ScrollType]); | 2805 | updateScrollSpeedButtons_(dlg, keyboard_ScrollType, d->prefs.smoothScrollSpeed[keyboard_ScrollType]); |
2672 | updateDropdownSelection_LabelWidget(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); | 2806 | updateDropdownSelection_LabelWidget(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.strings[uiLanguage_PrefsString])); |
2673 | updateDropdownSelection_LabelWidget( | 2807 | updateDropdownSelection_LabelWidget( |
2674 | findChild_Widget(dlg, "prefs.returnkey"), | 2808 | findChild_Widget(dlg, "prefs.returnkey"), |
2675 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); | 2809 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); |
2676 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); | 2810 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
2677 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), | 2811 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), |
2678 | collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); | 2812 | collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); |
2679 | setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), | 2813 | // setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), |
2680 | selected_WidgetFlag, | 2814 | // selected_WidgetFlag, |
2681 | iTrue); | 2815 | // iTrue); |
2682 | setFlags_Widget( | 2816 | // setFlags_Widget( |
2683 | findChild_Widget(dlg, format_CStr("prefs.headingfont.%d", d->prefs.headingFont)), | 2817 | // findChild_Widget(dlg, format_CStr("prefs.headingfont.%d", d->prefs.headingFont)), |
2684 | selected_WidgetFlag, | 2818 | // selected_WidgetFlag, |
2685 | iTrue); | 2819 | // iTrue); |
2686 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gemini"), | 2820 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gemini"), |
2687 | selected_WidgetFlag, | 2821 | selected_WidgetFlag, |
2688 | d->prefs.monospaceGemini); | 2822 | d->prefs.monospaceGemini); |
2689 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gopher"), | 2823 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gopher"), |
2690 | selected_WidgetFlag, | 2824 | selected_WidgetFlag, |
2691 | d->prefs.monospaceGopher); | 2825 | d->prefs.monospaceGopher); |
2826 | setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.visited"), | ||
2827 | selected_WidgetFlag, | ||
2828 | d->prefs.boldLinkVisited); | ||
2692 | setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.dark"), | 2829 | setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.dark"), |
2693 | selected_WidgetFlag, | 2830 | selected_WidgetFlag, |
2694 | d->prefs.boldLinkDark); | 2831 | d->prefs.boldLinkDark); |
2695 | setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.light"), | 2832 | setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.light"), |
2696 | selected_WidgetFlag, | 2833 | selected_WidgetFlag, |
2697 | d->prefs.boldLinkLight); | 2834 | d->prefs.boldLinkLight); |
2835 | setToggle_Widget(findChild_Widget(dlg, "prefs.gemtext.ansi.fg"), | ||
2836 | d->prefs.gemtextAnsiEscapes & allowFg_AnsiFlag); | ||
2837 | setToggle_Widget(findChild_Widget(dlg, "prefs.gemtext.ansi.fontstyle"), | ||
2838 | d->prefs.gemtextAnsiEscapes & allowFontStyle_AnsiFlag); | ||
2839 | setToggle_Widget(findChild_Widget(dlg, "prefs.font.smooth"), d->prefs.fontSmoothing); | ||
2698 | setFlags_Widget( | 2840 | setFlags_Widget( |
2699 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), | 2841 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), |
2700 | selected_WidgetFlag, | 2842 | selected_WidgetFlag, |
@@ -2713,8 +2855,11 @@ iBool handleCommand_App(const char *cmd) { | |||
2713 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); | 2855 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); |
2714 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.light"), d->prefs.docThemeLight); | 2856 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.light"), d->prefs.docThemeLight); |
2715 | updateImageStyleButton_(findChild_Widget(dlg, "prefs.imagestyle"), d->prefs.imageStyle); | 2857 | updateImageStyleButton_(findChild_Widget(dlg, "prefs.imagestyle"), d->prefs.imageStyle); |
2716 | updateFontButton_(findChild_Widget(dlg, "prefs.font"), d->prefs.font); | 2858 | updateFontButton_(findChild_Widget(dlg, "prefs.font.ui"), &d->prefs.strings[uiFont_PrefsString]); |
2717 | updateFontButton_(findChild_Widget(dlg, "prefs.headingfont"), d->prefs.headingFont); | 2859 | updateFontButton_(findChild_Widget(dlg, "prefs.font.heading"), &d->prefs.strings[headingFont_PrefsString]); |
2860 | updateFontButton_(findChild_Widget(dlg, "prefs.font.body"), &d->prefs.strings[bodyFont_PrefsString]); | ||
2861 | updateFontButton_(findChild_Widget(dlg, "prefs.font.mono"), &d->prefs.strings[monospaceFont_PrefsString]); | ||
2862 | updateFontButton_(findChild_Widget(dlg, "prefs.font.monodoc"), &d->prefs.strings[monospaceDocumentFont_PrefsString]); | ||
2718 | setFlags_Widget( | 2863 | setFlags_Widget( |
2719 | findChild_Widget( | 2864 | findChild_Widget( |
2720 | dlg, format_CStr("prefs.saturation.%d", (int) (d->prefs.saturation * 3.99f))), | 2865 | dlg, format_CStr("prefs.saturation.%d", (int) (d->prefs.saturation * 3.99f))), |
@@ -2725,12 +2870,12 @@ iBool handleCommand_App(const char *cmd) { | |||
2725 | setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"), | 2870 | setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"), |
2726 | collectNewFormat_String("%d", d->prefs.maxMemorySize)); | 2871 | collectNewFormat_String("%d", d->prefs.maxMemorySize)); |
2727 | setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); | 2872 | setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); |
2728 | setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.searchUrl); | 2873 | setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.strings[searchUrl_PrefsString]); |
2729 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.caFile); | 2874 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.strings[caFile_PrefsString]); |
2730 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.path"), &d->prefs.caPath); | 2875 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.path"), &d->prefs.strings[caPath_PrefsString]); |
2731 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gemini"), &d->prefs.geminiProxy); | 2876 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gemini"), &d->prefs.strings[geminiProxy_PrefsString]); |
2732 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gopher"), &d->prefs.gopherProxy); | 2877 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gopher"), &d->prefs.strings[gopherProxy_PrefsString]); |
2733 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), &d->prefs.httpProxy); | 2878 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), &d->prefs.strings[httpProxy_PrefsString]); |
2734 | iWidget *tabs = findChild_Widget(dlg, "prefs.tabs"); | 2879 | iWidget *tabs = findChild_Widget(dlg, "prefs.tabs"); |
2735 | if (tabs) { | 2880 | if (tabs) { |
2736 | showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); | 2881 | showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); |
@@ -2912,15 +3057,53 @@ iBool handleCommand_App(const char *cmd) { | |||
2912 | return iFalse; | 3057 | return iFalse; |
2913 | } | 3058 | } |
2914 | else if (equal_Command(cmd, "os.theme.changed")) { | 3059 | else if (equal_Command(cmd, "os.theme.changed")) { |
3060 | const int dark = argLabel_Command(cmd, "dark"); | ||
3061 | d->isDarkSystemTheme = dark; | ||
2915 | if (d->prefs.useSystemTheme) { | 3062 | if (d->prefs.useSystemTheme) { |
2916 | const int dark = argLabel_Command(cmd, "dark"); | 3063 | const int contrast = argLabel_Command(cmd, "contrast"); |
2917 | const int contrast = argLabel_Command(cmd, "contrast"); | 3064 | const int preferred = d->prefs.systemPreferredColorTheme[dark ^ 1]; |
2918 | postCommandf_App("theme.set arg:%d auto:1", | 3065 | postCommandf_App("theme.set arg:%d auto:1", |
2919 | dark ? (contrast ? pureBlack_ColorTheme : dark_ColorTheme) | 3066 | preferred >= 0 ? preferred |
2920 | : (contrast ? pureWhite_ColorTheme : light_ColorTheme)); | 3067 | : dark ? (contrast ? pureBlack_ColorTheme : dark_ColorTheme) |
3068 | : (contrast ? pureWhite_ColorTheme : light_ColorTheme)); | ||
2921 | } | 3069 | } |
2922 | return iFalse; | 3070 | return iFalse; |
2923 | } | 3071 | } |
3072 | else if (equal_Command(cmd, "fontpack.enable")) { | ||
3073 | const iString *packId = collect_String(suffix_Command(cmd, "id")); | ||
3074 | enablePack_Fonts(packId, arg_Command(cmd)); | ||
3075 | postCommand_App("navigate.reload"); | ||
3076 | return iTrue; | ||
3077 | } | ||
3078 | else if (equal_Command(cmd, "fontpack.delete")) { | ||
3079 | const iString *packId = collect_String(suffix_Command(cmd, "id")); | ||
3080 | if (isEmpty_String(packId)) { | ||
3081 | return iTrue; | ||
3082 | } | ||
3083 | const iFontPack *pack = pack_Fonts(cstr_String(packId)); | ||
3084 | if (pack && loadPath_FontPack(pack)) { | ||
3085 | if (argLabel_Command(cmd, "confirmed")) { | ||
3086 | remove_StringSet(d->prefs.disabledFontPacks, packId); | ||
3087 | remove(cstr_String(loadPath_FontPack(pack))); | ||
3088 | reload_Fonts(); | ||
3089 | postCommand_App("navigate.reload"); | ||
3090 | } | ||
3091 | else { | ||
3092 | makeQuestion_Widget( | ||
3093 | uiTextCaution_ColorEscape "${heading.fontpack.delete}", | ||
3094 | format_Lang("${dlg.fontpack.delete.confirm}", | ||
3095 | cstr_String(packId)), | ||
3096 | (iMenuItem[]){ { "${cancel}" }, | ||
3097 | { uiTextCaution_ColorEscape " ${dlg.fontpack.delete}", | ||
3098 | 0, | ||
3099 | 0, | ||
3100 | format_CStr("!fontpack.delete confirmed:1 id:%s", | ||
3101 | cstr_String(packId)) } }, | ||
3102 | 2); | ||
3103 | } | ||
3104 | } | ||
3105 | return iTrue; | ||
3106 | } | ||
2924 | #if defined (LAGRANGE_ENABLE_IPC) | 3107 | #if defined (LAGRANGE_ENABLE_IPC) |
2925 | else if (equal_Command(cmd, "ipc.list.urls")) { | 3108 | else if (equal_Command(cmd, "ipc.list.urls")) { |
2926 | iProcessId pid = argLabel_Command(cmd, "pid"); | 3109 | iProcessId pid = argLabel_Command(cmd, "pid"); |