diff options
-rw-r--r-- | res/about/version.gmi | 2 | ||||
-rw-r--r-- | src/app.c | 16 | ||||
-rw-r--r-- | src/gmdocument.c | 9 | ||||
-rw-r--r-- | src/gmdocument.h | 1 | ||||
-rw-r--r-- | src/prefs.c | 1 | ||||
-rw-r--r-- | src/prefs.h | 1 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 11 | ||||
-rw-r--r-- | src/ui/util.c | 6 | ||||
-rw-r--r-- | src/ui/window.c | 12 | ||||
-rw-r--r-- | src/ui/window.h | 1 |
10 files changed, 55 insertions, 5 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi index 488db36c..70f6135f 100644 --- a/res/about/version.gmi +++ b/res/about/version.gmi | |||
@@ -9,7 +9,9 @@ | |||
9 | ## 0.6 | 9 | ## 0.6 |
10 | * Added new color themes for page content: Colorful Light, Black, Gray, Sepia, High Contrast. | 10 | * Added new color themes for page content: Colorful Light, Black, Gray, Sepia, High Contrast. |
11 | * Dark and light mode page content themes can be chosen in Preferences. | 11 | * Dark and light mode page content themes can be chosen in Preferences. |
12 | * Added quote indicator option: icon or vertical line. | ||
12 | * macOS: Fixed glitchy window dragging during audio playback. | 13 | * macOS: Fixed glitchy window dragging during audio playback. |
14 | * Fixed cached page timestamps. | ||
13 | 15 | ||
14 | ## 0.5 | 16 | ## 0.5 |
15 | * Added MP3 support in the audio player (using mpg123). | 17 | * Added MP3 support in the audio player (using mpg123). |
@@ -182,6 +182,7 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
182 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); | 182 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); |
183 | appendFormat_String(str, "prefs.biglede.changed arg:%d\n", d->prefs.bigFirstParagraph); | 183 | appendFormat_String(str, "prefs.biglede.changed arg:%d\n", d->prefs.bigFirstParagraph); |
184 | appendFormat_String(str, "prefs.sideicon.changed arg:%d\n", d->prefs.sideIcon); | 184 | appendFormat_String(str, "prefs.sideicon.changed arg:%d\n", d->prefs.sideIcon); |
185 | appendFormat_String(str, "quoteicon.set arg:%d\n", d->prefs.quoteIcon ? 1 : 0); | ||
185 | appendFormat_String(str, "prefs.hoveroutline.changed arg:%d\n", d->prefs.hoverOutline); | 186 | appendFormat_String(str, "prefs.hoveroutline.changed arg:%d\n", d->prefs.hoverOutline); |
186 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->prefs.theme); | 187 | appendFormat_String(str, "theme.set arg:%d auto:1\n", d->prefs.theme); |
187 | appendFormat_String(str, "ostheme arg:%d\n", d->prefs.useSystemTheme); | 188 | appendFormat_String(str, "ostheme arg:%d\n", d->prefs.useSystemTheme); |
@@ -735,6 +736,12 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
735 | destroy_Widget(d); | 736 | destroy_Widget(d); |
736 | return iTrue; | 737 | return iTrue; |
737 | } | 738 | } |
739 | else if (equal_Command(cmd, "quoteicon.set")) { | ||
740 | const int arg = arg_Command(cmd); | ||
741 | setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.0"), selected_WidgetFlag, arg == 0); | ||
742 | setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.1"), selected_WidgetFlag, arg == 1); | ||
743 | return iFalse; | ||
744 | } | ||
738 | else if (equal_Command(cmd, "doctheme.dark.set")) { | 745 | else if (equal_Command(cmd, "doctheme.dark.set")) { |
739 | updateColorThemeButton_(findChild_Widget(d, "prefs.doctheme.dark"), arg_Command(cmd)); | 746 | updateColorThemeButton_(findChild_Widget(d, "prefs.doctheme.dark"), arg_Command(cmd)); |
740 | return iFalse; | 747 | return iFalse; |
@@ -946,6 +953,11 @@ iBool handleCommand_App(const char *cmd) { | |||
946 | postCommand_App("document.layout.changed"); | 953 | postCommand_App("document.layout.changed"); |
947 | return iTrue; | 954 | return iTrue; |
948 | } | 955 | } |
956 | else if (equal_Command(cmd, "quoteicon.set")) { | ||
957 | d->prefs.quoteIcon = arg_Command(cmd) != 0; | ||
958 | postCommand_App("document.layout.changed"); | ||
959 | return iTrue; | ||
960 | } | ||
949 | else if (equal_Command(cmd, "prefs.biglede.changed")) { | 961 | else if (equal_Command(cmd, "prefs.biglede.changed")) { |
950 | d->prefs.bigFirstParagraph = arg_Command(cmd) != 0; | 962 | d->prefs.bigFirstParagraph = arg_Command(cmd) != 0; |
951 | postCommand_App("document.layout.changed"); | 963 | postCommand_App("document.layout.changed"); |
@@ -1091,6 +1103,10 @@ iBool handleCommand_App(const char *cmd) { | |||
1091 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), | 1103 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), |
1092 | selected_WidgetFlag, | 1104 | selected_WidgetFlag, |
1093 | iTrue); | 1105 | iTrue); |
1106 | setFlags_Widget( | ||
1107 | findChild_Widget(dlg, format_CStr("prefs.quoteicon.%d", d->prefs.quoteIcon)), | ||
1108 | selected_WidgetFlag, | ||
1109 | iTrue); | ||
1094 | setToggle_Widget(findChild_Widget(dlg, "prefs.biglede"), d->prefs.bigFirstParagraph); | 1110 | setToggle_Widget(findChild_Widget(dlg, "prefs.biglede"), d->prefs.bigFirstParagraph); |
1095 | setToggle_Widget(findChild_Widget(dlg, "prefs.sideicon"), d->prefs.sideIcon); | 1111 | setToggle_Widget(findChild_Widget(dlg, "prefs.sideicon"), d->prefs.sideIcon); |
1096 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); | 1112 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); |
diff --git a/src/gmdocument.c b/src/gmdocument.c index 7982d57b..f2ac936f 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -290,7 +290,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
290 | iRangecc contentLine = iNullRange; | 290 | iRangecc contentLine = iNullRange; |
291 | iInt2 pos = zero_I2(); | 291 | iInt2 pos = zero_I2(); |
292 | iBool isFirstText = isGemini && prefs->bigFirstParagraph; | 292 | iBool isFirstText = isGemini && prefs->bigFirstParagraph; |
293 | iBool addQuoteIcon = iTrue; | 293 | iBool addQuoteIcon = prefs->quoteIcon; |
294 | iBool isPreformat = iFalse; | 294 | iBool isPreformat = iFalse; |
295 | iRangecc preAltText = iNullRange; | 295 | iRangecc preAltText = iNullRange; |
296 | int preFont = preformatted_FontId; | 296 | int preFont = preformatted_FontId; |
@@ -446,7 +446,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
446 | pushBack_Array(&d->layout, "eRun); | 446 | pushBack_Array(&d->layout, "eRun); |
447 | } | 447 | } |
448 | else if (type != quote_GmLineType) { | 448 | else if (type != quote_GmLineType) { |
449 | addQuoteIcon = iTrue; | 449 | addQuoteIcon = prefs->quoteIcon; |
450 | } | 450 | } |
451 | /* Link icon. */ | 451 | /* Link icon. */ |
452 | if (type == link_GmLineType) { | 452 | if (type == link_GmLineType) { |
@@ -485,6 +485,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
485 | iRangecc runLine = line; | 485 | iRangecc runLine = line; |
486 | /* Create one or more text runs for this line. */ | 486 | /* Create one or more text runs for this line. */ |
487 | run.flags |= startOfLine_GmRunFlag; | 487 | run.flags |= startOfLine_GmRunFlag; |
488 | if (!prefs->quoteIcon && type == quote_GmLineType) { | ||
489 | run.flags |= quoteBorder_GmRunFlag; | ||
490 | } | ||
488 | iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ | 491 | iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ |
489 | while (!isEmpty_Range(&runLine)) { | 492 | while (!isEmpty_Range(&runLine)) { |
490 | /* Little bit of breathing space between wrapped lines. */ | 493 | /* Little bit of breathing space between wrapped lines. */ |
@@ -835,7 +838,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | |||
835 | violet_Hue, | 838 | violet_Hue, |
836 | pink_Hue | 839 | pink_Hue |
837 | }; | 840 | }; |
838 | static const float hues[] = { 5, 25, 40, 56, 80, 120, 160, 180, 208, 231, 270, 324 }; | 841 | static const float hues[] = { 5, 25, 40, 56, 80, 120, 160, 180, 208, 231, 270, 324 }; |
839 | static const struct { | 842 | static const struct { |
840 | int index[2]; | 843 | int index[2]; |
841 | } altHues[iElemCount(hues)] = { | 844 | } altHues[iElemCount(hues)] = { |
diff --git a/src/gmdocument.h b/src/gmdocument.h index 05bf026c..f27446ab 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -79,6 +79,7 @@ enum iGmRunFlags { | |||
79 | startOfLine_GmRunFlag = iBit(2), | 79 | startOfLine_GmRunFlag = iBit(2), |
80 | endOfLine_GmRunFlag = iBit(3), | 80 | endOfLine_GmRunFlag = iBit(3), |
81 | siteBanner_GmRunFlag = iBit(4), /* area reserved for the site banner */ | 81 | siteBanner_GmRunFlag = iBit(4), /* area reserved for the site banner */ |
82 | quoteBorder_GmRunFlag = iBit(5), | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | struct Impl_GmRun { | 85 | struct Impl_GmRun { |
diff --git a/src/prefs.c b/src/prefs.c index 146f3838..1fcb1b8e 100644 --- a/src/prefs.c +++ b/src/prefs.c | |||
@@ -7,6 +7,7 @@ void init_Prefs(iPrefs *d) { | |||
7 | d->retainWindowSize = iTrue; | 7 | d->retainWindowSize = iTrue; |
8 | d->zoomPercent = 100; | 8 | d->zoomPercent = 100; |
9 | d->forceLineWrap = iFalse; | 9 | d->forceLineWrap = iFalse; |
10 | d->quoteIcon = iTrue; | ||
10 | d->font = nunito_TextFont; | 11 | d->font = nunito_TextFont; |
11 | d->headingFont = nunito_TextFont; | 12 | d->headingFont = nunito_TextFont; |
12 | d->lineWidth = 40; | 13 | d->lineWidth = 40; |
diff --git a/src/prefs.h b/src/prefs.h index a19cc0ca..bfc0c174 100644 --- a/src/prefs.h +++ b/src/prefs.h | |||
@@ -25,6 +25,7 @@ struct Impl_Prefs { | |||
25 | int lineWidth; | 25 | int lineWidth; |
26 | iBool bigFirstParagraph; | 26 | iBool bigFirstParagraph; |
27 | iBool forceLineWrap; | 27 | iBool forceLineWrap; |
28 | iBool quoteIcon; | ||
28 | iBool sideIcon; | 29 | iBool sideIcon; |
29 | iBool hoverOutline; | 30 | iBool hoverOutline; |
30 | enum iGmDocumentTheme docThemeDark; | 31 | enum iGmDocumentTheme docThemeDark; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 558c320d..8d3716a6 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1234,6 +1234,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1234 | refresh_Widget(w); | 1234 | refresh_Widget(w); |
1235 | updateWindowTitle_DocumentWidget_(d); | 1235 | updateWindowTitle_DocumentWidget_(d); |
1236 | } | 1236 | } |
1237 | else if (equal_Command(cmd, "window.mouse.exited")) { | ||
1238 | updateOutlineOpacity_DocumentWidget_(d); | ||
1239 | return iFalse; | ||
1240 | } | ||
1237 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { | 1241 | else if (equal_Command(cmd, "theme.changed") && document_App() == d) { |
1238 | updateTheme_DocumentWidget_(d); | 1242 | updateTheme_DocumentWidget_(d); |
1239 | invalidate_DocumentWidget_(d); | 1243 | invalidate_DocumentWidget_(d); |
@@ -2116,7 +2120,6 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
2116 | } | 2120 | } |
2117 | else if (run->audioId) { | 2121 | else if (run->audioId) { |
2118 | /* Audio player UI is drawn afterwards as a dynamic overlay. */ | 2122 | /* Audio player UI is drawn afterwards as a dynamic overlay. */ |
2119 | //fillRect_Paint(&d->paint, moved_Rect(run->visBounds, origin), red_ColorId); | ||
2120 | return; | 2123 | return; |
2121 | } | 2124 | } |
2122 | enum iColorId fg = run->color; | 2125 | enum iColorId fg = run->color; |
@@ -2181,6 +2184,12 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
2181 | goto runDrawn; | 2184 | goto runDrawn; |
2182 | } | 2185 | } |
2183 | } | 2186 | } |
2187 | if (run->flags & quoteBorder_GmRunFlag) { | ||
2188 | drawVLine_Paint(&d->paint, | ||
2189 | addX_I2(visPos, -gap_Text * 5 / 2), | ||
2190 | height_Rect(run->visBounds), | ||
2191 | tmQuoteIcon_ColorId); | ||
2192 | } | ||
2184 | drawRange_Text(run->font, visPos, fg, run->text); | 2193 | drawRange_Text(run->font, visPos, fg, run->text); |
2185 | // printf("{%s}\n", cstr_Rangecc(run->text)); | 2194 | // printf("{%s}\n", cstr_Rangecc(run->text)); |
2186 | runDrawn:; | 2195 | runDrawn:; |
diff --git a/src/ui/util.c b/src/ui/util.c index 35eea9c3..bef839dc 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -991,6 +991,12 @@ iWidget *makePreferences_Widget(void) { | |||
991 | addRadioButton_(widths, "prefs.linewidth.1000", "Window", "linewidth.set arg:1000"); | 991 | addRadioButton_(widths, "prefs.linewidth.1000", "Window", "linewidth.set arg:1000"); |
992 | } | 992 | } |
993 | addChildFlags_Widget(values, iClob(widths), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 993 | addChildFlags_Widget(values, iClob(widths), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
994 | addChild_Widget(headings, iClob(makeHeading_Widget("Quote indicator:"))); | ||
995 | iWidget *quote = new_Widget(); { | ||
996 | addRadioButton_(quote, "prefs.quoteicon.1", "Icon", "quoteicon.set arg:1"); | ||
997 | addRadioButton_(quote, "prefs.quoteicon.0", "Line", "quoteicon.set arg:0"); | ||
998 | } | ||
999 | addChildFlags_Widget(values, iClob(quote), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | ||
994 | addChild_Widget(headings, iClob(makeHeading_Widget("Big 1st paragaph:"))); | 1000 | addChild_Widget(headings, iClob(makeHeading_Widget("Big 1st paragaph:"))); |
995 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.biglede"))); | 1001 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.biglede"))); |
996 | makeTwoColumnHeading_("WIDE LAYOUT", headings, values); | 1002 | makeTwoColumnHeading_("WIDE LAYOUT", headings, values); |
diff --git a/src/ui/window.c b/src/ui/window.c index 40215506..c5194ea0 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -524,6 +524,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
524 | d->lastRect = rect; | 524 | d->lastRect = rect; |
525 | d->pendingCursor = NULL; | 525 | d->pendingCursor = NULL; |
526 | d->isDrawFrozen = iTrue; | 526 | d->isDrawFrozen = iTrue; |
527 | d->isMouseInside = iTrue; | ||
527 | uint32_t flags = 0; | 528 | uint32_t flags = 0; |
528 | #if defined (iPlatformApple) | 529 | #if defined (iPlatformApple) |
529 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); | 530 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); |
@@ -543,7 +544,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
543 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { | 544 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { |
544 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); | 545 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); |
545 | } | 546 | } |
546 | const iInt2 minSize = init_I2(425, 250); | 547 | const iInt2 minSize = init_I2(425, 300); |
547 | SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); | 548 | SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); |
548 | SDL_SetWindowTitle(d->win, "Lagrange"); | 549 | SDL_SetWindowTitle(d->win, "Lagrange"); |
549 | /* Some info. */ { | 550 | /* Some info. */ { |
@@ -655,6 +656,12 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
655 | return iTrue; | 656 | return iTrue; |
656 | case SDL_WINDOWEVENT_LEAVE: | 657 | case SDL_WINDOWEVENT_LEAVE: |
657 | unhover_Widget(); | 658 | unhover_Widget(); |
659 | d->isMouseInside = iFalse; | ||
660 | postCommand_App("window.mouse.exited"); | ||
661 | return iTrue; | ||
662 | case SDL_WINDOWEVENT_ENTER: | ||
663 | d->isMouseInside = iTrue; | ||
664 | postCommand_App("window.mouse.entered"); | ||
658 | return iTrue; | 665 | return iTrue; |
659 | default: | 666 | default: |
660 | break; | 667 | break; |
@@ -812,6 +819,9 @@ iInt2 coord_Window(const iWindow *d, int x, int y) { | |||
812 | } | 819 | } |
813 | 820 | ||
814 | iInt2 mouseCoord_Window(const iWindow *d) { | 821 | iInt2 mouseCoord_Window(const iWindow *d) { |
822 | if (!d->isMouseInside) { | ||
823 | return init_I2(-1000000, -1000000); | ||
824 | } | ||
815 | int x, y; | 825 | int x, y; |
816 | SDL_GetMouseState(&x, &y); | 826 | SDL_GetMouseState(&x, &y); |
817 | return coord_Window(d, x, y); | 827 | return coord_Window(d, x, y); |
diff --git a/src/ui/window.h b/src/ui/window.h index da4a2123..3ede1578 100644 --- a/src/ui/window.h +++ b/src/ui/window.h | |||
@@ -37,6 +37,7 @@ struct Impl_Window { | |||
37 | iInt2 initialPos; | 37 | iInt2 initialPos; |
38 | iRect lastRect; /* updated when window is moved/resized */ | 38 | iRect lastRect; /* updated when window is moved/resized */ |
39 | iBool isDrawFrozen; /* avoids premature draws while restoring window state */ | 39 | iBool isDrawFrozen; /* avoids premature draws while restoring window state */ |
40 | iBool isMouseInside; | ||
40 | SDL_Renderer *render; | 41 | SDL_Renderer *render; |
41 | iWidget * root; | 42 | iWidget * root; |
42 | float pixelRatio; | 43 | float pixelRatio; |