diff options
-rw-r--r-- | src/app.c | 14 | ||||
-rw-r--r-- | src/app.h | 1 | ||||
-rw-r--r-- | src/gmdocument.c | 16 | ||||
-rw-r--r-- | src/gmdocument.h | 4 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 23 | ||||
-rw-r--r-- | src/ui/window.c | 2 |
6 files changed, 44 insertions, 16 deletions
@@ -94,6 +94,7 @@ struct Impl_App { | |||
94 | iRect initialWindowRect; | 94 | iRect initialWindowRect; |
95 | float uiScale; | 95 | float uiScale; |
96 | int zoomPercent; | 96 | int zoomPercent; |
97 | iBool forceWrap; | ||
97 | enum iColorTheme theme; | 98 | enum iColorTheme theme; |
98 | iBool useSystemTheme; | 99 | iBool useSystemTheme; |
99 | iString gopherProxy; | 100 | iString gopherProxy; |
@@ -146,6 +147,9 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
146 | if (isVisible_Widget(constAs_Widget(sidebar))) { | 147 | if (isVisible_Widget(constAs_Widget(sidebar))) { |
147 | appendCStr_String(str, "sidebar.toggle\n"); | 148 | appendCStr_String(str, "sidebar.toggle\n"); |
148 | } | 149 | } |
150 | if (d->forceWrap) { | ||
151 | appendFormat_String(str, "forcewrap.toggle\n"); | ||
152 | } | ||
149 | appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); | 153 | appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); |
150 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); | 154 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); |
151 | appendFormat_String(str, "zoom.set arg:%d\n", d->zoomPercent); | 155 | appendFormat_String(str, "zoom.set arg:%d\n", d->zoomPercent); |
@@ -281,6 +285,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
281 | d->retainWindowSize = iTrue; | 285 | d->retainWindowSize = iTrue; |
282 | d->pendingRefresh = iFalse; | 286 | d->pendingRefresh = iFalse; |
283 | d->zoomPercent = 100; | 287 | d->zoomPercent = 100; |
288 | d->forceWrap = iFalse; | ||
284 | d->certs = new_GmCerts(dataDir_App_); | 289 | d->certs = new_GmCerts(dataDir_App_); |
285 | d->visited = new_Visited(); | 290 | d->visited = new_Visited(); |
286 | d->bookmarks = new_Bookmarks(); | 291 | d->bookmarks = new_Bookmarks(); |
@@ -431,6 +436,10 @@ int zoom_App(void) { | |||
431 | return app_.zoomPercent; | 436 | return app_.zoomPercent; |
432 | } | 437 | } |
433 | 438 | ||
439 | iBool isLineWrapForced_App(void) { | ||
440 | return app_.forceWrap; | ||
441 | } | ||
442 | |||
434 | enum iColorTheme colorTheme_App(void) { | 443 | enum iColorTheme colorTheme_App(void) { |
435 | return app_.theme; | 444 | return app_.theme; |
436 | } | 445 | } |
@@ -793,6 +802,11 @@ iBool handleCommand_App(const char *cmd) { | |||
793 | postCommand_App("window.unfreeze"); | 802 | postCommand_App("window.unfreeze"); |
794 | return iTrue; | 803 | return iTrue; |
795 | } | 804 | } |
805 | else if (equal_Command(cmd, "forcewrap.toggle")) { | ||
806 | d->forceWrap = !d->forceWrap; | ||
807 | updateSize_DocumentWidget(document_App()); | ||
808 | return iTrue; | ||
809 | } | ||
796 | else if (equal_Command(cmd, "bookmark.add")) { | 810 | else if (equal_Command(cmd, "bookmark.add")) { |
797 | iDocumentWidget *doc = document_App(); | 811 | iDocumentWidget *doc = document_App(); |
798 | makeBookmarkCreation_Widget(url_DocumentWidget(doc), | 812 | makeBookmarkCreation_Widget(url_DocumentWidget(doc), |
@@ -56,6 +56,7 @@ iBool isRefreshPending_App (void); | |||
56 | uint32_t elapsedSinceLastTicker_App (void); /* milliseconds */ | 56 | uint32_t elapsedSinceLastTicker_App (void); /* milliseconds */ |
57 | 57 | ||
58 | int zoom_App (void); | 58 | int zoom_App (void); |
59 | iBool isLineWrapForced_App(void); | ||
59 | enum iColorTheme colorTheme_App (void); | 60 | enum iColorTheme colorTheme_App (void); |
60 | const iString * schemeProxy_App (iRangecc scheme); | 61 | const iString * schemeProxy_App (iRangecc scheme); |
61 | 62 | ||
diff --git a/src/gmdocument.c b/src/gmdocument.c index 924eee32..e4ae03a8 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -104,6 +104,7 @@ struct Impl_GmDocument { | |||
104 | iString source; | 104 | iString source; |
105 | iString url; /* for resolving relative links */ | 105 | iString url; /* for resolving relative links */ |
106 | iString localHost; | 106 | iString localHost; |
107 | int forceBreakWidth; /* force breaks on very long preformatted lines */ | ||
107 | iInt2 size; | 108 | iInt2 size; |
108 | iArray layout; /* contents of source, laid out in document space */ | 109 | iArray layout; /* contents of source, laid out in document space */ |
109 | iPtrArray links; | 110 | iPtrArray links; |
@@ -506,12 +507,11 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
506 | } | 507 | } |
507 | run.bounds.pos = addX_I2(pos, indent * gap_Text); | 508 | run.bounds.pos = addX_I2(pos, indent * gap_Text); |
508 | const char *contPos; | 509 | const char *contPos; |
509 | const int avail = d->size.x - run.bounds.pos.x; | 510 | const int avail = (isPreformat ? d->forceBreakWidth : d->size.x) - run.bounds.pos.x; |
510 | const iInt2 dims = | 511 | const iInt2 dims = tryAdvance_Text(run.font, runLine, avail, &contPos); |
511 | tryAdvance_Text(run.font, runLine, isPreformat ? 0 : avail, &contPos); | ||
512 | run.bounds.size.x = iMax(avail, dims.x); /* Extends to the right edge for selection. */ | 512 | run.bounds.size.x = iMax(avail, dims.x); /* Extends to the right edge for selection. */ |
513 | run.bounds.size.y = dims.y; | 513 | run.bounds.size.y = dims.y; |
514 | run.visBounds = run.bounds; | 514 | run.visBounds = run.bounds; |
515 | run.visBounds.size.x = dims.x; | 515 | run.visBounds.size.x = dims.x; |
516 | if (contPos > runLine.start) { | 516 | if (contPos > runLine.start) { |
517 | run.text = (iRangecc){ runLine.start, contPos }; | 517 | run.text = (iRangecc){ runLine.start, contPos }; |
@@ -866,7 +866,8 @@ void setFormat_GmDocument(iGmDocument *d, enum iGmDocumentFormat format) { | |||
866 | d->format = format; | 866 | d->format = format; |
867 | } | 867 | } |
868 | 868 | ||
869 | void setWidth_GmDocument(iGmDocument *d, int width) { | 869 | void setWidth_GmDocument(iGmDocument *d, int width, int forceBreakWidth) { |
870 | d->forceBreakWidth = forceBreakWidth; | ||
870 | d->size.x = width; | 871 | d->size.x = width; |
871 | doLayout_GmDocument_(d); /* TODO: just flag need-layout and do it later */ | 872 | doLayout_GmDocument_(d); /* TODO: just flag need-layout and do it later */ |
872 | } | 873 | } |
@@ -939,11 +940,10 @@ void setUrl_GmDocument(iGmDocument *d, const iString *url) { | |||
939 | setRange_String(&d->localHost, parts.host); | 940 | setRange_String(&d->localHost, parts.host); |
940 | } | 941 | } |
941 | 942 | ||
942 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width) { | 943 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width, int forceBreakWidth) { |
943 | set_String(&d->source, source); | 944 | set_String(&d->source, source); |
944 | normalize_GmDocument(d); | 945 | normalize_GmDocument(d); |
945 | setWidth_GmDocument(d, width); | 946 | setWidth_GmDocument(d, width, forceBreakWidth); /* re-do layout */ |
946 | /* TODO: just flag need-layout and do it later */ | ||
947 | } | 947 | } |
948 | 948 | ||
949 | void setImage_GmDocument(iGmDocument *d, iGmLinkId linkId, const iString *mime, const iBlock *data) { | 949 | void setImage_GmDocument(iGmDocument *d, iGmLinkId linkId, const iString *mime, const iBlock *data) { |
diff --git a/src/gmdocument.h b/src/gmdocument.h index b6c1c6ab..e3c21097 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -94,9 +94,9 @@ enum iGmDocumentFormat { | |||
94 | 94 | ||
95 | void setThemeSeed_GmDocument (iGmDocument *, const iBlock *seed); | 95 | void setThemeSeed_GmDocument (iGmDocument *, const iBlock *seed); |
96 | void setFormat_GmDocument (iGmDocument *, enum iGmDocumentFormat format); | 96 | void setFormat_GmDocument (iGmDocument *, enum iGmDocumentFormat format); |
97 | void setWidth_GmDocument (iGmDocument *, int width); | 97 | void setWidth_GmDocument (iGmDocument *, int width, int forceBreakWidth); |
98 | void setUrl_GmDocument (iGmDocument *, const iString *url); | 98 | void setUrl_GmDocument (iGmDocument *, const iString *url); |
99 | void setSource_GmDocument (iGmDocument *, const iString *source, int width); | 99 | void setSource_GmDocument (iGmDocument *, const iString *source, int width, int forceBreakWidth); |
100 | void setImage_GmDocument (iGmDocument *, iGmLinkId linkId, const iString *mime, const iBlock *data); | 100 | void setImage_GmDocument (iGmDocument *, iGmLinkId linkId, const iString *mime, const iBlock *data); |
101 | 101 | ||
102 | void reset_GmDocument (iGmDocument *); /* free images */ | 102 | void reset_GmDocument (iGmDocument *); /* free images */ |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 437e9468..2ccdc416 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -296,6 +296,15 @@ static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { | |||
296 | return rect; | 296 | return rect; |
297 | } | 297 | } |
298 | 298 | ||
299 | static int forceBreakWidth_DocumentWidget_(const iDocumentWidget *d) { | ||
300 | if (isLineWrapForced_App()) { | ||
301 | const iRect bounds = bounds_Widget(constAs_Widget(d)); | ||
302 | const iRect docBounds = documentBounds_DocumentWidget_(d); | ||
303 | return right_Rect(bounds) - left_Rect(docBounds) - gap_UI * d->pageMargin; | ||
304 | } | ||
305 | return 0; | ||
306 | } | ||
307 | |||
299 | iLocalDef int documentToWindowY_DocumentWidget_(const iDocumentWidget *d, int docY) { | 308 | iLocalDef int documentToWindowY_DocumentWidget_(const iDocumentWidget *d, int docY) { |
300 | return docY - d->scrollY + documentBounds_DocumentWidget_(d).pos.y; | 309 | return docY - d->scrollY + documentBounds_DocumentWidget_(d).pos.y; |
301 | } | 310 | } |
@@ -488,7 +497,8 @@ static void invalidate_DocumentWidget_(iDocumentWidget *d) { | |||
488 | 497 | ||
489 | static void setSource_DocumentWidget_(iDocumentWidget *d, const iString *source) { | 498 | static void setSource_DocumentWidget_(iDocumentWidget *d, const iString *source) { |
490 | setUrl_GmDocument(d->doc, d->mod.url); | 499 | setUrl_GmDocument(d->doc, d->mod.url); |
491 | setSource_GmDocument(d->doc, source, documentWidth_DocumentWidget_(d)); | 500 | setSource_GmDocument( |
501 | d->doc, source, documentWidth_DocumentWidget_(d), forceBreakWidth_DocumentWidget_(d)); | ||
492 | d->foundMark = iNullRange; | 502 | d->foundMark = iNullRange; |
493 | d->selectMark = iNullRange; | 503 | d->selectMark = iNullRange; |
494 | d->hoverLink = NULL; | 504 | d->hoverLink = NULL; |
@@ -1021,8 +1031,10 @@ static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) { | |||
1021 | } | 1031 | } |
1022 | 1032 | ||
1023 | void updateSize_DocumentWidget(iDocumentWidget *d) { | 1033 | void updateSize_DocumentWidget(iDocumentWidget *d) { |
1024 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | 1034 | setWidth_GmDocument( |
1035 | d->doc, documentWidth_DocumentWidget_(d), forceBreakWidth_DocumentWidget_(d)); | ||
1025 | updateVisible_DocumentWidget_(d); | 1036 | updateVisible_DocumentWidget_(d); |
1037 | invalidate_DocumentWidget_(d); | ||
1026 | } | 1038 | } |
1027 | 1039 | ||
1028 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 1040 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
@@ -1030,9 +1042,9 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1030 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { | 1042 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "font.changed")) { |
1031 | const iGmRun *mid = middleRun_DocumentWidget_(d); | 1043 | const iGmRun *mid = middleRun_DocumentWidget_(d); |
1032 | const char *midLoc = (mid ? mid->text.start : NULL); | 1044 | const char *midLoc = (mid ? mid->text.start : NULL); |
1033 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | 1045 | setWidth_GmDocument( |
1046 | d->doc, documentWidth_DocumentWidget_(d), forceBreakWidth_DocumentWidget_(d)); | ||
1034 | scroll_DocumentWidget_(d, 0); | 1047 | scroll_DocumentWidget_(d, 0); |
1035 | updateVisible_DocumentWidget_(d); | ||
1036 | if (midLoc) { | 1048 | if (midLoc) { |
1037 | mid = findRunAtLoc_GmDocument(d->doc, midLoc); | 1049 | mid = findRunAtLoc_GmDocument(d->doc, midLoc); |
1038 | if (mid) { | 1050 | if (mid) { |
@@ -1055,8 +1067,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1055 | /* Set palette for our document. */ | 1067 | /* Set palette for our document. */ |
1056 | updateTheme_DocumentWidget_(d); | 1068 | updateTheme_DocumentWidget_(d); |
1057 | updateTrust_DocumentWidget_(d, NULL); | 1069 | updateTrust_DocumentWidget_(d, NULL); |
1058 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | 1070 | updateSize_DocumentWidget(d); |
1059 | updateVisible_DocumentWidget_(d); | ||
1060 | } | 1071 | } |
1061 | updateWindowTitle_DocumentWidget_(d); | 1072 | updateWindowTitle_DocumentWidget_(d); |
1062 | allocVisBuffer_DocumentWidget_(d); | 1073 | allocVisBuffer_DocumentWidget_(d); |
diff --git a/src/ui/window.c b/src/ui/window.c index b7b4a8fd..66f1c513 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -141,6 +141,8 @@ static const iMenuItem viewMenuItems[] = { | |||
141 | { "Zoom In", SDLK_EQUALS, KMOD_PRIMARY, "zoom.delta arg:10" }, | 141 | { "Zoom In", SDLK_EQUALS, KMOD_PRIMARY, "zoom.delta arg:10" }, |
142 | { "Zoom Out", SDLK_MINUS, KMOD_PRIMARY, "zoom.delta arg:-10" }, | 142 | { "Zoom Out", SDLK_MINUS, KMOD_PRIMARY, "zoom.delta arg:-10" }, |
143 | { "Reset Zoom", SDLK_0, KMOD_PRIMARY, "zoom.set arg:100" }, | 143 | { "Reset Zoom", SDLK_0, KMOD_PRIMARY, "zoom.set arg:100" }, |
144 | { "---", 0, 0, NULL }, | ||
145 | { "Wrap Preformatted", 0, 0, "forcewrap.toggle" } | ||
144 | }; | 146 | }; |
145 | 147 | ||
146 | static const iMenuItem helpMenuItems[] = { | 148 | static const iMenuItem helpMenuItems[] = { |