diff options
-rw-r--r-- | src/app.c | 14 | ||||
-rw-r--r-- | src/gmdocument.c | 17 | ||||
-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 | 1 |
6 files changed, 31 insertions, 14 deletions
@@ -215,6 +215,7 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
215 | appendFormat_String(str, "memorysize.set arg:%d\n", d->prefs.maxMemorySize); | 215 | appendFormat_String(str, "memorysize.set arg:%d\n", d->prefs.maxMemorySize); |
216 | appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs); | 216 | appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs); |
217 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); | 217 | appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); |
218 | appendFormat_String(str, "linespacing.set arg:%f\n", d->prefs.lineSpacing); | ||
218 | /* TODO: Set up an array of booleans in Prefs and do these in a loop. */ | 219 | /* TODO: Set up an array of booleans in Prefs and do these in a loop. */ |
219 | appendFormat_String(str, "prefs.animate.changed arg:%d\n", d->prefs.uiAnimations); | 220 | appendFormat_String(str, "prefs.animate.changed arg:%d\n", d->prefs.uiAnimations); |
220 | appendFormat_String(str, "prefs.mono.gemini.changed arg:%d\n", d->prefs.monospaceGemini); | 221 | appendFormat_String(str, "prefs.mono.gemini.changed arg:%d\n", d->prefs.monospaceGemini); |
@@ -1707,6 +1708,12 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1707 | updateFontButton_(findChild_Widget(d, "prefs.headingfont"), arg_Command(cmd)); | 1708 | updateFontButton_(findChild_Widget(d, "prefs.headingfont"), arg_Command(cmd)); |
1708 | return iFalse; | 1709 | return iFalse; |
1709 | } | 1710 | } |
1711 | else if (startsWith_CStr(cmd, "input.ended id:prefs.linespacing")) { | ||
1712 | /* Apply line spacing changes immediately. */ | ||
1713 | const iInputWidget *lineSpacing = findWidget_App("prefs.linespacing"); | ||
1714 | postCommandf_App("linespacing.set arg:%f", toFloat_String(text_InputWidget(lineSpacing))); | ||
1715 | return iTrue; | ||
1716 | } | ||
1710 | else if (equal_Command(cmd, "prefs.ostheme.changed")) { | 1717 | else if (equal_Command(cmd, "prefs.ostheme.changed")) { |
1711 | postCommandf_App("ostheme arg:%d", arg_Command(cmd)); | 1718 | postCommandf_App("ostheme arg:%d", arg_Command(cmd)); |
1712 | } | 1719 | } |
@@ -2118,6 +2125,11 @@ iBool handleCommand_App(const char *cmd) { | |||
2118 | postCommand_App("document.layout.changed"); | 2125 | postCommand_App("document.layout.changed"); |
2119 | return iTrue; | 2126 | return iTrue; |
2120 | } | 2127 | } |
2128 | else if (equal_Command(cmd, "linespacing.set")) { | ||
2129 | d->prefs.lineSpacing = iMax(0.5f, argf_Command(cmd)); | ||
2130 | postCommand_App("document.layout.changed redo:1"); | ||
2131 | return iTrue; | ||
2132 | } | ||
2121 | else if (equal_Command(cmd, "quoteicon.set")) { | 2133 | else if (equal_Command(cmd, "quoteicon.set")) { |
2122 | d->prefs.quoteIcon = arg_Command(cmd) != 0; | 2134 | d->prefs.quoteIcon = arg_Command(cmd) != 0; |
2123 | postCommand_App("document.layout.changed"); | 2135 | postCommand_App("document.layout.changed"); |
@@ -2516,6 +2528,8 @@ iBool handleCommand_App(const char *cmd) { | |||
2516 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), | 2528 | findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), |
2517 | selected_WidgetFlag, | 2529 | selected_WidgetFlag, |
2518 | iTrue); | 2530 | iTrue); |
2531 | setText_InputWidget(findChild_Widget(dlg, "prefs.linespacing"), | ||
2532 | collectNewFormat_String("%.2f", d->prefs.lineSpacing)); | ||
2519 | setFlags_Widget( | 2533 | setFlags_Widget( |
2520 | findChild_Widget(dlg, format_CStr("prefs.quoteicon.%d", d->prefs.quoteIcon)), | 2534 | findChild_Widget(dlg, format_CStr("prefs.quoteicon.%d", d->prefs.quoteIcon)), |
2521 | selected_WidgetFlag, | 2535 | selected_WidgetFlag, |
diff --git a/src/gmdocument.c b/src/gmdocument.c index a46e71cf..3d91fb34 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -147,7 +147,7 @@ static int lastVisibleRunBottom_GmDocument_(const iGmDocument *d) { | |||
147 | if (isEmpty_Range(&run->text)) { | 147 | if (isEmpty_Range(&run->text)) { |
148 | continue; | 148 | continue; |
149 | } | 149 | } |
150 | return bottom_Rect(run->bounds); | 150 | return top_Rect(run->bounds) + height_Rect(run->bounds) * prefs_App()->lineSpacing; |
151 | } | 151 | } |
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
@@ -546,7 +546,8 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
546 | banner.text = bannerText; | 546 | banner.text = bannerText; |
547 | banner.color = tmBannerTitle_ColorId; | 547 | banner.color = tmBannerTitle_ColorId; |
548 | pushBack_Array(&d->layout, &banner); | 548 | pushBack_Array(&d->layout, &banner); |
549 | pos.y += height_Rect(banner.visBounds) + lineHeight_Text(paragraph_FontId); | 549 | pos.y += height_Rect(banner.visBounds) + |
550 | lineHeight_Text(paragraph_FontId) * prefs->lineSpacing; | ||
550 | } | 551 | } |
551 | } | 552 | } |
552 | /* Empty lines don't produce text runs. */ | 553 | /* Empty lines don't produce text runs. */ |
@@ -560,7 +561,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
560 | run.text = iNullRange; | 561 | run.text = iNullRange; |
561 | pushBack_Array(&d->layout, &run); | 562 | pushBack_Array(&d->layout, &run); |
562 | } | 563 | } |
563 | pos.y += lineHeight_Text(run.font); | 564 | pos.y += lineHeight_Text(run.font) * prefs->lineSpacing; |
564 | prevType = type; | 565 | prevType = type; |
565 | if (type != quote_GmLineType) { | 566 | if (type != quote_GmLineType) { |
566 | addQuoteIcon = prefs->quoteIcon; | 567 | addQuoteIcon = prefs->quoteIcon; |
@@ -586,11 +587,6 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
586 | if (type == link_GmLineType && prevNonBlankType == link_GmLineType && followsBlank) { | 587 | if (type == link_GmLineType && prevNonBlankType == link_GmLineType && followsBlank) { |
587 | required = 1.25f * lineHeight_Text(paragraph_FontId); | 588 | required = 1.25f * lineHeight_Text(paragraph_FontId); |
588 | } | 589 | } |
589 | else if (type == link_GmLineType && prevType == link_GmLineType) { | ||
590 | /* Balance space between the link icons and the labels, both vertically | ||
591 | between icons and between the icon and the label. */ | ||
592 | //required *= 0.75f; | ||
593 | } | ||
594 | if (type == quote_GmLineType && prevType == quote_GmLineType) { | 590 | if (type == quote_GmLineType && prevType == quote_GmLineType) { |
595 | /* No margin between consecutive quote lines. */ | 591 | /* No margin between consecutive quote lines. */ |
596 | required = 0; | 592 | required = 0; |
@@ -598,9 +594,10 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
598 | if (isEmpty_Array(&d->layout)) { | 594 | if (isEmpty_Array(&d->layout)) { |
599 | required = 0; /* top of document */ | 595 | required = 0; /* top of document */ |
600 | } | 596 | } |
597 | required *= prefs->lineSpacing; | ||
601 | int delta = pos.y - lastVisibleRunBottom_GmDocument_(d); | 598 | int delta = pos.y - lastVisibleRunBottom_GmDocument_(d); |
602 | if (delta < required) { | 599 | if (delta < required) { |
603 | pos.y += required - delta; | 600 | pos.y += (required - delta); |
604 | } | 601 | } |
605 | } | 602 | } |
606 | /* Folded blocks are represented by a single run with the alt text. */ | 603 | /* Folded blocks are represented by a single run with the alt text. */ |
@@ -778,7 +775,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
778 | run.flags &= ~startOfLine_GmRunFlag; | 775 | run.flags &= ~startOfLine_GmRunFlag; |
779 | runLine.start = contPos; | 776 | runLine.start = contPos; |
780 | trimStart_Rangecc(&runLine); | 777 | trimStart_Rangecc(&runLine); |
781 | pos.y += lineHeight_Text(run.font); | 778 | pos.y += lineHeight_Text(run.font) * prefs->lineSpacing; |
782 | if (--bigCount == 0) { | 779 | if (--bigCount == 0) { |
783 | run.font = fonts[text_GmLineType]; | 780 | run.font = fonts[text_GmLineType]; |
784 | run.color = colors[text_GmLineType]; | 781 | run.color = colors[text_GmLineType]; |
diff --git a/src/prefs.c b/src/prefs.c index f1842e9a..557c6887 100644 --- a/src/prefs.c +++ b/src/prefs.c | |||
@@ -54,6 +54,7 @@ void init_Prefs(iPrefs *d) { | |||
54 | d->boldLinkDark = iTrue; | 54 | d->boldLinkDark = iTrue; |
55 | d->boldLinkLight = iTrue; | 55 | d->boldLinkLight = iTrue; |
56 | d->lineWidth = 38; | 56 | d->lineWidth = 38; |
57 | d->lineSpacing = 1.0f; | ||
57 | d->bigFirstParagraph = iTrue; | 58 | d->bigFirstParagraph = iTrue; |
58 | d->quoteIcon = iTrue; | 59 | d->quoteIcon = iTrue; |
59 | d->centerShortDocs = iTrue; | 60 | d->centerShortDocs = iTrue; |
diff --git a/src/prefs.h b/src/prefs.h index 655ec949..c1519459 100644 --- a/src/prefs.h +++ b/src/prefs.h | |||
@@ -79,6 +79,7 @@ struct Impl_Prefs { | |||
79 | iBool boldLinkDark; | 79 | iBool boldLinkDark; |
80 | iBool boldLinkLight; | 80 | iBool boldLinkLight; |
81 | int lineWidth; | 81 | int lineWidth; |
82 | float lineSpacing; | ||
82 | iBool bigFirstParagraph; | 83 | iBool bigFirstParagraph; |
83 | iBool quoteIcon; | 84 | iBool quoteIcon; |
84 | iBool centerShortDocs; | 85 | iBool centerShortDocs; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 5bded6c6..38f34c77 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1298,9 +1298,9 @@ static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool | |||
1298 | 2); | 1298 | 2); |
1299 | } | 1299 | } |
1300 | if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) { | 1300 | if (preloadCoverImage_Gempub(d->sourceGempub, d->doc)) { |
1301 | redoLayout_GmDocument(d->doc); | 1301 | redoLayout_GmDocument(d->doc); |
1302 | updateVisible_DocumentWidget_(d); | 1302 | updateVisible_DocumentWidget_(d); |
1303 | invalidate_DocumentWidget_(d); | 1303 | invalidate_DocumentWidget_(d); |
1304 | } | 1304 | } |
1305 | } | 1305 | } |
1306 | else if (equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { | 1306 | else if (equal_String(d->mod.url, indexPageUrl_Gempub(d->sourceGempub))) { |
@@ -2461,7 +2461,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2461 | invalidate_DocumentWidget_(d); | 2461 | invalidate_DocumentWidget_(d); |
2462 | refresh_Widget(w); | 2462 | refresh_Widget(w); |
2463 | } | 2463 | } |
2464 | else if (equal_Command(cmd, "document.layout.changed") && document_App() == d) { | 2464 | else if (equal_Command(cmd, "document.layout.changed") && document_Root(get_Root()) == d) { |
2465 | if (argLabel_Command(cmd, "redo")) { | ||
2466 | redoLayout_GmDocument(d->doc); | ||
2467 | } | ||
2465 | updateSize_DocumentWidget(d); | 2468 | updateSize_DocumentWidget(d); |
2466 | } | 2469 | } |
2467 | else if (equal_Command(cmd, "pinsplit.set")) { | 2470 | else if (equal_Command(cmd, "pinsplit.set")) { |
diff --git a/src/ui/util.c b/src/ui/util.c index 5aea4f11..d68274ad 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1809,6 +1809,7 @@ iWidget *makePreferences_Widget(void) { | |||
1809 | addRadioButton_(widths, "prefs.linewidth.1000", "${prefs.linewidth.fill}", "linewidth.set arg:1000"); | 1809 | addRadioButton_(widths, "prefs.linewidth.1000", "${prefs.linewidth.fill}", "linewidth.set arg:1000"); |
1810 | } | 1810 | } |
1811 | addChildFlags_Widget(values, iClob(widths), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 1811 | addChildFlags_Widget(values, iClob(widths), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
1812 | addPrefsInputWithHeading_(headings, values, "prefs.linespacing", iClob(new_InputWidget(5))); | ||
1812 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.quoteicon}"))); | 1813 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.quoteicon}"))); |
1813 | iWidget *quote = new_Widget(); { | 1814 | iWidget *quote = new_Widget(); { |
1814 | addRadioButton_(quote, "prefs.quoteicon.1", "${prefs.quoteicon.icon}", "quoteicon.set arg:1"); | 1815 | addRadioButton_(quote, "prefs.quoteicon.1", "${prefs.quoteicon.icon}", "quoteicon.set arg:1"); |