diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 95 | ||||
-rw-r--r-- | src/app.h | 3 | ||||
-rw-r--r-- | src/gmdocument.c | 19 | ||||
-rw-r--r-- | src/gmdocument.h | 5 | ||||
-rw-r--r-- | src/prefs.c | 23 | ||||
-rw-r--r-- | src/prefs.h | 29 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 7 | ||||
-rw-r--r-- | src/ui/util.c | 16 |
8 files changed, 135 insertions, 62 deletions
@@ -94,17 +94,20 @@ struct Impl_App { | |||
94 | iTime lastDropTime; /* for detecting drops of multiple items */ | 94 | iTime lastDropTime; /* for detecting drops of multiple items */ |
95 | /* Preferences: */ | 95 | /* Preferences: */ |
96 | iBool commandEcho; /* --echo */ | 96 | iBool commandEcho; /* --echo */ |
97 | iBool retainWindowSize; | 97 | iBool forceSoftwareRender; /* --sw */ |
98 | iRect initialWindowRect; | 98 | iRect initialWindowRect; |
99 | iPrefs prefs; | ||
100 | #if 0 | ||
101 | iBool retainWindowSize; | ||
99 | float uiScale; | 102 | float uiScale; |
100 | int zoomPercent; | 103 | int zoomPercent; |
101 | iBool forceWrap; | 104 | iBool forceWrap; |
102 | iBool forceSoftwareRender; | ||
103 | enum iColorTheme theme; | 105 | enum iColorTheme theme; |
104 | iBool useSystemTheme; | 106 | iBool useSystemTheme; |
105 | iString gopherProxy; | 107 | iString gopherProxy; |
106 | iString httpProxy; | 108 | iString httpProxy; |
107 | iString downloadDir; | 109 | iString downloadDir; |
110 | #endif | ||
108 | }; | 111 | }; |
109 | 112 | ||
110 | static iApp app_; | 113 | static iApp app_; |
@@ -134,8 +137,8 @@ const iString *dateStr_(const iDate *date) { | |||
134 | static iString *serializePrefs_App_(const iApp *d) { | 137 | static iString *serializePrefs_App_(const iApp *d) { |
135 | iString *str = new_String(); | 138 | iString *str = new_String(); |
136 | const iSidebarWidget *sidebar = findWidget_App("sidebar"); | 139 | const iSidebarWidget *sidebar = findWidget_App("sidebar"); |
137 | appendFormat_String(str, "window.retain arg:%d\n", d->retainWindowSize); | 140 | appendFormat_String(str, "window.retain arg:%d\n", d->prefs.retainWindowSize); |
138 | if (d->retainWindowSize) { | 141 | if (d->prefs.retainWindowSize) { |
139 | int w, h, x, y; | 142 | int w, h, x, y; |
140 | SDL_GetWindowSize(d->window->win, &w, &h); | 143 | SDL_GetWindowSize(d->window->win, &w, &h); |
141 | SDL_GetWindowPosition(d->window->win, &x, &y); | 144 | SDL_GetWindowPosition(d->window->win, &x, &y); |
@@ -153,17 +156,17 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
153 | if (isVisible_Widget(sidebar)) { | 156 | if (isVisible_Widget(sidebar)) { |
154 | appendCStr_String(str, "sidebar.toggle\n"); | 157 | appendCStr_String(str, "sidebar.toggle\n"); |
155 | } | 158 | } |
156 | if (d->forceWrap) { | 159 | if (d->prefs.forceLineWrap) { |
157 | appendFormat_String(str, "forcewrap.toggle\n"); | 160 | appendFormat_String(str, "forcewrap.toggle\n"); |
158 | } | 161 | } |
159 | appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); | 162 | appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); |
160 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); | 163 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); |
161 | appendFormat_String(str, "zoom.set arg:%d\n", d->zoomPercent); | 164 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); |
162 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->theme); | 165 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->prefs.theme); |
163 | appendFormat_String(str, "ostheme arg:%d\n", d->useSystemTheme); | 166 | appendFormat_String(str, "ostheme arg:%d\n", d->prefs.useSystemTheme); |
164 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->gopherProxy)); | 167 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->prefs.gopherProxy)); |
165 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->httpProxy)); | 168 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->prefs.httpProxy)); |
166 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->downloadDir)); | 169 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->prefs.downloadDir)); |
167 | return str; | 170 | return str; |
168 | } | 171 | } |
169 | 172 | ||
@@ -299,24 +302,18 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
299 | d->lastTickerTime = SDL_GetTicks(); | 302 | d->lastTickerTime = SDL_GetTicks(); |
300 | d->elapsedSinceLastTicker = 0; | 303 | d->elapsedSinceLastTicker = 0; |
301 | d->commandEcho = checkArgument_CommandLine(&d->args, "echo") != NULL; | 304 | d->commandEcho = checkArgument_CommandLine(&d->args, "echo") != NULL; |
305 | d->forceSoftwareRender = checkArgument_CommandLine(&d->args, "sw") != NULL; | ||
302 | d->initialWindowRect = init_Rect(-1, -1, 900, 560); | 306 | d->initialWindowRect = init_Rect(-1, -1, 900, 560); |
303 | d->theme = dark_ColorTheme; | 307 | init_Prefs(&d->prefs); |
304 | d->useSystemTheme = iTrue; | 308 | setCStr_String(&d->prefs.downloadDir, downloadDir_App_); |
305 | d->running = iFalse; | 309 | d->running = iFalse; |
306 | d->window = NULL; | 310 | d->window = NULL; |
307 | d->retainWindowSize = iTrue; | ||
308 | d->pendingRefresh = iFalse; | 311 | d->pendingRefresh = iFalse; |
309 | d->zoomPercent = 100; | ||
310 | d->forceWrap = iFalse; | ||
311 | d->forceSoftwareRender = checkArgument_CommandLine(&d->args, "sw") != NULL; | ||
312 | d->certs = new_GmCerts(dataDir_App_); | 312 | d->certs = new_GmCerts(dataDir_App_); |
313 | d->visited = new_Visited(); | 313 | d->visited = new_Visited(); |
314 | d->bookmarks = new_Bookmarks(); | 314 | d->bookmarks = new_Bookmarks(); |
315 | d->tabEnum = 0; /* generates unique IDs for tab pages */ | 315 | d->tabEnum = 0; /* generates unique IDs for tab pages */ |
316 | init_String(&d->gopherProxy); | 316 | setThemePalette_Color(d->prefs.theme); |
317 | init_String(&d->httpProxy); | ||
318 | initCStr_String(&d->downloadDir, downloadDir_App_); | ||
319 | setThemePalette_Color(d->theme); | ||
320 | #if defined (iPlatformApple) | 317 | #if defined (iPlatformApple) |
321 | setupApplication_MacOS(); | 318 | setupApplication_MacOS(); |
322 | #endif | 319 | #endif |
@@ -390,9 +387,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
390 | static void deinit_App(iApp *d) { | 387 | static void deinit_App(iApp *d) { |
391 | saveState_App_(d); | 388 | saveState_App_(d); |
392 | savePrefs_App_(d); | 389 | savePrefs_App_(d); |
393 | deinit_String(&d->downloadDir); | 390 | deinit_Prefs(&d->prefs); |
394 | deinit_String(&d->httpProxy); | ||
395 | deinit_String(&d->gopherProxy); | ||
396 | save_Bookmarks(d->bookmarks, dataDir_App_); | 391 | save_Bookmarks(d->bookmarks, dataDir_App_); |
397 | delete_Bookmarks(d->bookmarks); | 392 | delete_Bookmarks(d->bookmarks); |
398 | save_Visited(d->visited, dataDir_App_); | 393 | save_Visited(d->visited, dataDir_App_); |
@@ -414,7 +409,7 @@ const iString *dataDir_App(void) { | |||
414 | } | 409 | } |
415 | 410 | ||
416 | const iString *downloadDir_App(void) { | 411 | const iString *downloadDir_App(void) { |
417 | return collect_String(cleaned_Path(&app_.downloadDir)); | 412 | return collect_String(cleaned_Path(&app_.prefs.downloadDir)); |
418 | } | 413 | } |
419 | 414 | ||
420 | const iString *debugInfo_App(void) { | 415 | const iString *debugInfo_App(void) { |
@@ -538,12 +533,12 @@ uint32_t elapsedSinceLastTicker_App(void) { | |||
538 | return app_.elapsedSinceLastTicker; | 533 | return app_.elapsedSinceLastTicker; |
539 | } | 534 | } |
540 | 535 | ||
541 | int zoom_App(void) { | 536 | const iPrefs *prefs_App(void) { |
542 | return app_.zoomPercent; | 537 | return &app_.prefs; |
543 | } | 538 | } |
544 | 539 | ||
545 | iBool forceLineWrap_App(void) { | 540 | iBool forceLineWrap_App(void) { |
546 | return app_.forceWrap; | 541 | return app_.prefs.forceLineWrap; |
547 | } | 542 | } |
548 | 543 | ||
549 | iBool forceSoftwareRender_App(void) { | 544 | iBool forceSoftwareRender_App(void) { |
@@ -559,16 +554,16 @@ iBool forceSoftwareRender_App(void) { | |||
559 | } | 554 | } |
560 | 555 | ||
561 | enum iColorTheme colorTheme_App(void) { | 556 | enum iColorTheme colorTheme_App(void) { |
562 | return app_.theme; | 557 | return app_.prefs.theme; |
563 | } | 558 | } |
564 | 559 | ||
565 | const iString *schemeProxy_App(iRangecc scheme) { | 560 | const iString *schemeProxy_App(iRangecc scheme) { |
566 | iApp *d = &app_; | 561 | iApp *d = &app_; |
567 | if (equalCase_Rangecc(scheme, "gopher")) { | 562 | if (equalCase_Rangecc(scheme, "gopher")) { |
568 | return &d->gopherProxy; | 563 | return &d->prefs.gopherProxy; |
569 | } | 564 | } |
570 | if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { | 565 | if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { |
571 | return &d->httpProxy; | 566 | return &d->prefs.httpProxy; |
572 | } | 567 | } |
573 | return NULL; | 568 | return NULL; |
574 | } | 569 | } |
@@ -801,11 +796,11 @@ static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) { | |||
801 | iBool handleCommand_App(const char *cmd) { | 796 | iBool handleCommand_App(const char *cmd) { |
802 | iApp *d = &app_; | 797 | iApp *d = &app_; |
803 | if (equal_Command(cmd, "window.retain")) { | 798 | if (equal_Command(cmd, "window.retain")) { |
804 | d->retainWindowSize = arg_Command(cmd); | 799 | d->prefs.retainWindowSize = arg_Command(cmd); |
805 | return iTrue; | 800 | return iTrue; |
806 | } | 801 | } |
807 | else if (equal_Command(cmd, "downloads")) { | 802 | else if (equal_Command(cmd, "downloads")) { |
808 | setCStr_String(&d->downloadDir, suffixPtr_Command(cmd, "path")); | 803 | setCStr_String(&d->prefs.downloadDir, suffixPtr_Command(cmd, "path")); |
809 | return iTrue; | 804 | return iTrue; |
810 | } | 805 | } |
811 | else if (equal_Command(cmd, "open")) { | 806 | else if (equal_Command(cmd, "open")) { |
@@ -813,8 +808,8 @@ iBool handleCommand_App(const char *cmd) { | |||
813 | iUrl parts; | 808 | iUrl parts; |
814 | init_Url(&parts, url); | 809 | init_Url(&parts, url); |
815 | if (equalCase_Rangecc(parts.scheme, "mailto") || | 810 | if (equalCase_Rangecc(parts.scheme, "mailto") || |
816 | (isEmpty_String(&d->httpProxy) && (equalCase_Rangecc(parts.scheme, "http") || | 811 | (isEmpty_String(&d->prefs.httpProxy) && (equalCase_Rangecc(parts.scheme, "http") || |
817 | equalCase_Rangecc(parts.scheme, "https")))) { | 812 | equalCase_Rangecc(parts.scheme, "https")))) { |
818 | openInDefaultBrowser_App(url); | 813 | openInDefaultBrowser_App(url); |
819 | return iTrue; | 814 | return iTrue; |
820 | } | 815 | } |
@@ -905,9 +900,9 @@ iBool handleCommand_App(const char *cmd) { | |||
905 | else if (equal_Command(cmd, "preferences")) { | 900 | else if (equal_Command(cmd, "preferences")) { |
906 | iWidget *dlg = makePreferences_Widget(); | 901 | iWidget *dlg = makePreferences_Widget(); |
907 | updatePrefsThemeButtons_(dlg); | 902 | updatePrefsThemeButtons_(dlg); |
908 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->downloadDir); | 903 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->prefs.downloadDir); |
909 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->useSystemTheme); | 904 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); |
910 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->retainWindowSize); | 905 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
911 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), | 906 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), |
912 | collectNewFormat_String("%g", uiScale_Window(d->window))); | 907 | collectNewFormat_String("%g", uiScale_Window(d->window))); |
913 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), | 908 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), |
@@ -943,8 +938,8 @@ iBool handleCommand_App(const char *cmd) { | |||
943 | } | 938 | } |
944 | else if (equal_Command(cmd, "zoom.set")) { | 939 | else if (equal_Command(cmd, "zoom.set")) { |
945 | setFreezeDraw_Window(get_Window(), iTrue); /* no intermediate draws before docs updated */ | 940 | setFreezeDraw_Window(get_Window(), iTrue); /* no intermediate draws before docs updated */ |
946 | d->zoomPercent = arg_Command(cmd); | 941 | d->prefs.zoomPercent = arg_Command(cmd); |
947 | setContentFontSize_Text((float) d->zoomPercent / 100.0f); | 942 | setContentFontSize_Text((float) d->prefs.zoomPercent / 100.0f); |
948 | postCommand_App("font.changed"); | 943 | postCommand_App("font.changed"); |
949 | postCommand_App("window.unfreeze"); | 944 | postCommand_App("window.unfreeze"); |
950 | return iTrue; | 945 | return iTrue; |
@@ -952,17 +947,17 @@ iBool handleCommand_App(const char *cmd) { | |||
952 | else if (equal_Command(cmd, "zoom.delta")) { | 947 | else if (equal_Command(cmd, "zoom.delta")) { |
953 | setFreezeDraw_Window(get_Window(), iTrue); /* no intermediate draws before docs updated */ | 948 | setFreezeDraw_Window(get_Window(), iTrue); /* no intermediate draws before docs updated */ |
954 | int delta = arg_Command(cmd); | 949 | int delta = arg_Command(cmd); |
955 | if (d->zoomPercent < 100 || (delta < 0 && d->zoomPercent == 100)) { | 950 | if (d->prefs.zoomPercent < 100 || (delta < 0 && d->prefs.zoomPercent == 100)) { |
956 | delta /= 2; | 951 | delta /= 2; |
957 | } | 952 | } |
958 | d->zoomPercent = iClamp(d->zoomPercent + delta, 50, 200); | 953 | d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200); |
959 | setContentFontSize_Text((float) d->zoomPercent / 100.0f); | 954 | setContentFontSize_Text((float) d->prefs.zoomPercent / 100.0f); |
960 | postCommand_App("font.changed"); | 955 | postCommand_App("font.changed"); |
961 | postCommand_App("window.unfreeze"); | 956 | postCommand_App("window.unfreeze"); |
962 | return iTrue; | 957 | return iTrue; |
963 | } | 958 | } |
964 | else if (equal_Command(cmd, "forcewrap.toggle")) { | 959 | else if (equal_Command(cmd, "forcewrap.toggle")) { |
965 | d->forceWrap = !d->forceWrap; | 960 | d->prefs.forceLineWrap = !d->prefs.forceLineWrap; |
966 | updateSize_DocumentWidget(document_App()); | 961 | updateSize_DocumentWidget(document_App()); |
967 | return iTrue; | 962 | return iTrue; |
968 | } | 963 | } |
@@ -1002,20 +997,20 @@ iBool handleCommand_App(const char *cmd) { | |||
1002 | } | 997 | } |
1003 | else if (equal_Command(cmd, "theme.set")) { | 998 | else if (equal_Command(cmd, "theme.set")) { |
1004 | const int isAuto = argLabel_Command(cmd, "auto"); | 999 | const int isAuto = argLabel_Command(cmd, "auto"); |
1005 | d->theme = arg_Command(cmd); | 1000 | d->prefs.theme = arg_Command(cmd); |
1006 | if (!isAuto) { | 1001 | if (!isAuto) { |
1007 | postCommand_App("ostheme arg:0"); | 1002 | postCommand_App("ostheme arg:0"); |
1008 | } | 1003 | } |
1009 | setThemePalette_Color(d->theme); | 1004 | setThemePalette_Color(d->prefs.theme); |
1010 | postCommandf_App("theme.changed auto:%d", isAuto); | 1005 | postCommandf_App("theme.changed auto:%d", isAuto); |
1011 | return iTrue; | 1006 | return iTrue; |
1012 | } | 1007 | } |
1013 | else if (equal_Command(cmd, "ostheme")) { | 1008 | else if (equal_Command(cmd, "ostheme")) { |
1014 | d->useSystemTheme = arg_Command(cmd); | 1009 | d->prefs.useSystemTheme = arg_Command(cmd); |
1015 | return iTrue; | 1010 | return iTrue; |
1016 | } | 1011 | } |
1017 | else if (equal_Command(cmd, "os.theme.changed")) { | 1012 | else if (equal_Command(cmd, "os.theme.changed")) { |
1018 | if (d->useSystemTheme) { | 1013 | if (d->prefs.useSystemTheme) { |
1019 | const int dark = argLabel_Command(cmd, "dark"); | 1014 | const int dark = argLabel_Command(cmd, "dark"); |
1020 | const int contrast = argLabel_Command(cmd, "contrast"); | 1015 | const int contrast = argLabel_Command(cmd, "contrast"); |
1021 | postCommandf_App("theme.set arg:%d auto:1", | 1016 | postCommandf_App("theme.set arg:%d auto:1", |
@@ -1025,11 +1020,11 @@ iBool handleCommand_App(const char *cmd) { | |||
1025 | return iFalse; | 1020 | return iFalse; |
1026 | } | 1021 | } |
1027 | else if (equal_Command(cmd, "proxy.gopher")) { | 1022 | else if (equal_Command(cmd, "proxy.gopher")) { |
1028 | setCStr_String(&d->gopherProxy, suffixPtr_Command(cmd, "address")); | 1023 | setCStr_String(&d->prefs.gopherProxy, suffixPtr_Command(cmd, "address")); |
1029 | return iTrue; | 1024 | return iTrue; |
1030 | } | 1025 | } |
1031 | else if (equal_Command(cmd, "proxy.http")) { | 1026 | else if (equal_Command(cmd, "proxy.http")) { |
1032 | setCStr_String(&d->httpProxy, suffixPtr_Command(cmd, "address")); | 1027 | setCStr_String(&d->prefs.httpProxy, suffixPtr_Command(cmd, "address")); |
1033 | return iTrue; | 1028 | return iTrue; |
1034 | } | 1029 | } |
1035 | else { | 1030 | else { |
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
28 | #include <the_Foundation/string.h> | 28 | #include <the_Foundation/string.h> |
29 | #include <the_Foundation/time.h> | 29 | #include <the_Foundation/time.h> |
30 | 30 | ||
31 | #include "prefs.h" | ||
31 | #include "ui/color.h" | 32 | #include "ui/color.h" |
32 | 33 | ||
33 | iDeclareType(Bookmarks) | 34 | iDeclareType(Bookmarks) |
@@ -58,7 +59,7 @@ void refresh_App (void); | |||
58 | iBool isRefreshPending_App (void); | 59 | iBool isRefreshPending_App (void); |
59 | uint32_t elapsedSinceLastTicker_App (void); /* milliseconds */ | 60 | uint32_t elapsedSinceLastTicker_App (void); /* milliseconds */ |
60 | 61 | ||
61 | int zoom_App (void); | 62 | const iPrefs * prefs_App (void); |
62 | iBool forceLineWrap_App (void); | 63 | iBool forceLineWrap_App (void); |
63 | iBool forceSoftwareRender_App(void); | 64 | iBool forceSoftwareRender_App(void); |
64 | enum iColorTheme colorTheme_App (void); | 65 | enum iColorTheme colorTheme_App (void); |
diff --git a/src/gmdocument.c b/src/gmdocument.c index 39c45c80..0129db64 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -331,6 +331,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
331 | static const char *globe = "\U0001f310"; | 331 | static const char *globe = "\U0001f310"; |
332 | static const char *quote = "\u201c"; | 332 | static const char *quote = "\u201c"; |
333 | const float midRunSkip = 0; /*0.120f;*/ /* extra space between wrapped text/quote lines */ | 333 | const float midRunSkip = 0; /*0.120f;*/ /* extra space between wrapped text/quote lines */ |
334 | const iPrefs *prefs = prefs_App(); | ||
334 | clear_Array(&d->layout); | 335 | clear_Array(&d->layout); |
335 | clearLinks_GmDocument_(d); | 336 | clearLinks_GmDocument_(d); |
336 | clear_Array(&d->headings); | 337 | clear_Array(&d->headings); |
@@ -341,7 +342,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
341 | const iRangecc content = range_String(&d->source); | 342 | const iRangecc content = range_String(&d->source); |
342 | iRangecc contentLine = iNullRange; | 343 | iRangecc contentLine = iNullRange; |
343 | iInt2 pos = zero_I2(); | 344 | iInt2 pos = zero_I2(); |
344 | iBool isFirstText = isGemini; | 345 | iBool isFirstText = isGemini && prefs->bigFirstParagraph; |
345 | iBool addQuoteIcon = iTrue; | 346 | iBool addQuoteIcon = iTrue; |
346 | iBool isPreformat = iFalse; | 347 | iBool isPreformat = iFalse; |
347 | iRangecc preAltText = iNullRange; | 348 | iRangecc preAltText = iNullRange; |
@@ -650,9 +651,11 @@ void reset_GmDocument(iGmDocument *d) { | |||
650 | } | 651 | } |
651 | 652 | ||
652 | void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | 653 | void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { |
653 | const float saturationLevel = 1.0f; /* TODO: user setting */ | 654 | const iPrefs * prefs = prefs_App(); |
654 | const iBool isLightMode = isLight_ColorTheme(colorTheme_App()); | 655 | enum iGmDocumentTheme theme = |
655 | const iBool isDarkMode = !isLightMode; | 656 | (isDark_ColorTheme(colorTheme_App()) ? prefs->docThemeDark : prefs->docThemeLight); |
657 | // const iBool isLightMode = isLight_ColorTheme(colorTheme_App()); | ||
658 | // const iBool isDarkMode = !isLightMode; | ||
656 | static const iChar siteIcons[] = { | 659 | static const iChar siteIcons[] = { |
657 | 0x203b, 0x2042, 0x205c, 0x2182, 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, | 660 | 0x203b, 0x2042, 0x205c, 0x2182, 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, |
658 | 0x265c, 0x265e, 0x2690, 0x2691, 0x2693, 0x2698, 0x2699, 0x26f0, 0x270e, 0x2728, | 661 | 0x265c, 0x265e, 0x2690, 0x2691, 0x2693, 0x2698, 0x2699, 0x26f0, 0x270e, 0x2728, |
@@ -662,7 +665,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
662 | 0x1f533, 0x1f657, 0x1f659, 0x1f665, 0x1f668, 0x1f66b, 0x1f78b, 0x1f796, 0x1f79c, | 665 | 0x1f533, 0x1f657, 0x1f659, 0x1f665, 0x1f668, 0x1f66b, 0x1f78b, 0x1f796, 0x1f79c, |
663 | }; | 666 | }; |
664 | /* Default colors. */ { | 667 | /* Default colors. */ { |
665 | if (isDarkMode) { | 668 | if (theme == colorfulDark_GmDocumentTheme) { |
666 | const iHSLColor base = { 200, 0, 0.15f, 1.0f }; | 669 | const iHSLColor base = { 200, 0, 0.15f, 1.0f }; |
667 | setHsl_Color(tmBackground_ColorId, base); | 670 | setHsl_Color(tmBackground_ColorId, base); |
668 | set_Color(tmParagraph_ColorId, get_Color(gray75_ColorId)); | 671 | set_Color(tmParagraph_ColorId, get_Color(gray75_ColorId)); |
@@ -784,7 +787,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
784 | // printf("background: %d %f %f\n", (int) base.hue, base.sat, base.lum); | 787 | // printf("background: %d %f %f\n", (int) base.hue, base.sat, base.lum); |
785 | // printf("isDarkBgSat: %d\n", isDarkBgSat); | 788 | // printf("isDarkBgSat: %d\n", isDarkBgSat); |
786 | 789 | ||
787 | if (isDarkMode) { | 790 | if (theme == colorfulDark_GmDocumentTheme) { |
788 | iHSLColor base = { hues[primIndex], | 791 | iHSLColor base = { hues[primIndex], |
789 | 0.8f * (d->themeSeed >> 24) / 255.0f, | 792 | 0.8f * (d->themeSeed >> 24) / 255.0f, |
790 | 0.06f + 0.09f * ((d->themeSeed >> 5) & 0x7) / 7.0f, | 793 | 0.06f + 0.09f * ((d->themeSeed >> 5) & 0x7) / 7.0f, |
@@ -836,7 +839,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
836 | /* Adjust colors based on light/dark mode. */ | 839 | /* Adjust colors based on light/dark mode. */ |
837 | for (int i = tmFirst_ColorId; i < max_ColorId; i++) { | 840 | for (int i = tmFirst_ColorId; i < max_ColorId; i++) { |
838 | iHSLColor color = hsl_Color(get_Color(i)); | 841 | iHSLColor color = hsl_Color(get_Color(i)); |
839 | if (isLightMode) { | 842 | if (theme == white_GmDocumentTheme) { |
840 | #if 0 | 843 | #if 0 |
841 | if (isLink_ColorId(i)) continue; | 844 | if (isLink_ColorId(i)) continue; |
842 | color.lum = 1.0f - color.lum; /* All colors invert lightness. */ | 845 | color.lum = 1.0f - color.lum; /* All colors invert lightness. */ |
@@ -894,7 +897,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
894 | } | 897 | } |
895 | } | 898 | } |
896 | /* Modify overall saturation. */ | 899 | /* Modify overall saturation. */ |
897 | color.sat *= saturationLevel; | 900 | color.sat *= prefs->saturation; |
898 | setHsl_Color(i, color); | 901 | setHsl_Color(i, color); |
899 | } | 902 | } |
900 | } | 903 | } |
diff --git a/src/gmdocument.h b/src/gmdocument.h index b453fba9..b16df677 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -35,6 +35,11 @@ iDeclareType(GmImageInfo) | |||
35 | iDeclareType(GmHeading) | 35 | iDeclareType(GmHeading) |
36 | iDeclareType(GmRun) | 36 | iDeclareType(GmRun) |
37 | 37 | ||
38 | enum iGmDocumentTheme { | ||
39 | colorfulDark_GmDocumentTheme, | ||
40 | white_GmDocumentTheme, | ||
41 | }; | ||
42 | |||
38 | typedef uint16_t iGmLinkId; | 43 | typedef uint16_t iGmLinkId; |
39 | 44 | ||
40 | enum iGmLinkFlags { | 45 | enum iGmLinkFlags { |
diff --git a/src/prefs.c b/src/prefs.c new file mode 100644 index 00000000..d773acbd --- /dev/null +++ b/src/prefs.c | |||
@@ -0,0 +1,23 @@ | |||
1 | #include "prefs.h" | ||
2 | |||
3 | void init_Prefs(iPrefs *d) { | ||
4 | d->theme = dark_ColorTheme; | ||
5 | d->useSystemTheme = iTrue; | ||
6 | d->retainWindowSize = iTrue; | ||
7 | d->zoomPercent = 100; | ||
8 | d->forceLineWrap = iFalse; | ||
9 | d->lineWidth = 40; | ||
10 | d->bigFirstParagraph = iTrue; | ||
11 | d->docThemeDark = colorfulDark_GmDocumentTheme; | ||
12 | d->docThemeLight = white_GmDocumentTheme; | ||
13 | d->saturation = 1.0f; | ||
14 | init_String(&d->gopherProxy); | ||
15 | init_String(&d->httpProxy); | ||
16 | init_String(&d->downloadDir); | ||
17 | } | ||
18 | |||
19 | void deinit_Prefs(iPrefs *d) { | ||
20 | deinit_String(&d->gopherProxy); | ||
21 | deinit_String(&d->httpProxy); | ||
22 | deinit_String(&d->downloadDir); | ||
23 | } | ||
diff --git a/src/prefs.h b/src/prefs.h new file mode 100644 index 00000000..d4e300ec --- /dev/null +++ b/src/prefs.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #pragma once | ||
2 | #include <the_Foundation/string.h> | ||
3 | |||
4 | #include "ui/color.h" | ||
5 | #include "gmdocument.h" | ||
6 | |||
7 | /* User preferences */ | ||
8 | |||
9 | iDeclareType(Prefs) | ||
10 | |||
11 | struct Impl_Prefs { | ||
12 | iBool retainWindowSize; | ||
13 | float uiScale; | ||
14 | int zoomPercent; | ||
15 | iBool useSystemTheme; | ||
16 | enum iColorTheme theme; | ||
17 | iString gopherProxy; | ||
18 | iString httpProxy; | ||
19 | iString downloadDir; | ||
20 | /* Content */ | ||
21 | int lineWidth; | ||
22 | iBool bigFirstParagraph; | ||
23 | iBool forceLineWrap; | ||
24 | enum iGmDocumentTheme docThemeDark; | ||
25 | enum iGmDocumentTheme docThemeLight; | ||
26 | float saturation; | ||
27 | }; | ||
28 | |||
29 | iDeclareTypeConstruction(Prefs) | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 735a7214..69dde8c7 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -243,10 +243,11 @@ static void resetSmoothScroll_DocumentWidget_(iDocumentWidget *d) { | |||
243 | } | 243 | } |
244 | 244 | ||
245 | static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | 245 | static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { |
246 | const iWidget *w = constAs_Widget(d); | 246 | const iWidget *w = constAs_Widget(d); |
247 | const iRect bounds = bounds_Widget(w); | 247 | const iRect bounds = bounds_Widget(w); |
248 | const iPrefs * prefs = prefs_App(); | ||
248 | return iMini(bounds.size.x - gap_UI * d->pageMargin * 2, | 249 | return iMini(bounds.size.x - gap_UI * d->pageMargin * 2, |
249 | fontSize_UI * 40 * zoom_App() / 100); /* TODO: Add user preference .*/ | 250 | fontSize_UI * prefs->lineWidth * prefs->zoomPercent / 100); |
250 | } | 251 | } |
251 | 252 | ||
252 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | 253 | static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { |
diff --git a/src/ui/util.c b/src/ui/util.c index bdc1c813..52107d81 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -878,6 +878,22 @@ iWidget *makePreferences_Widget(void) { | |||
878 | addChild_Widget(headings, iClob(makeHeading_Widget("UI scale factor:"))); | 878 | addChild_Widget(headings, iClob(makeHeading_Widget("UI scale factor:"))); |
879 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(8))), "prefs.uiscale"); | 879 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(8))), "prefs.uiscale"); |
880 | } | 880 | } |
881 | /* Layout. */ { | ||
882 | appendTwoColumnPage_(tabs, "Layout", &headings, &values); | ||
883 | addChild_Widget(headings, iClob(makeHeading_Widget("Line width:"))); | ||
884 | addChild_Widget(values, iClob(new_LabelWidget("Normal", 0, 0, NULL))); | ||
885 | addChild_Widget(headings, iClob(makeHeading_Widget("First paragaph:"))); | ||
886 | addChild_Widget(values, iClob(new_LabelWidget("Emphasized", 0, 0, NULL))); | ||
887 | } | ||
888 | /* Colors. */ { | ||
889 | appendTwoColumnPage_(tabs, "Colors", &headings, &values); | ||
890 | addChild_Widget(headings, iClob(makeHeading_Widget("Saturation:"))); | ||
891 | addChild_Widget(values, iClob(new_LabelWidget("Full", 0, 0, 0))); | ||
892 | addChild_Widget(headings, iClob(makeHeading_Widget("Dark theme:"))); | ||
893 | addChild_Widget(values, iClob(new_LabelWidget("Colorful", 0, 0, 0))); | ||
894 | addChild_Widget(headings, iClob(makeHeading_Widget("Light theme:"))); | ||
895 | addChild_Widget(values, iClob(new_LabelWidget("White", 0, 0, 0))); | ||
896 | } | ||
881 | /* Proxies. */ { | 897 | /* Proxies. */ { |
882 | appendTwoColumnPage_(tabs, "Proxies", &headings, &values); | 898 | appendTwoColumnPage_(tabs, "Proxies", &headings, &values); |
883 | addChild_Widget(headings, iClob(makeHeading_Widget("Gopher proxy:"))); | 899 | addChild_Widget(headings, iClob(makeHeading_Widget("Gopher proxy:"))); |