summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r--src/gmdocument.c86
1 files changed, 18 insertions, 68 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 19230392..b5e71e21 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -547,9 +547,11 @@ static void clear_RunTypesetter_(iRunTypesetter *d) {
547 clear_Array(&d->layout); 547 clear_Array(&d->layout);
548} 548}
549 549
550static void commit_RunTypesetter_(iRunTypesetter *d, iGmDocument *doc) { 550static size_t commit_RunTypesetter_(iRunTypesetter *d, iGmDocument *doc) {
551 const size_t n = size_Array(&d->layout);
551 pushBackN_Array(&doc->layout, constData_Array(&d->layout), size_Array(&d->layout)); 552 pushBackN_Array(&doc->layout, constData_Array(&d->layout), size_Array(&d->layout));
552 clear_RunTypesetter_(d); 553 clear_RunTypesetter_(d);
554 return n;
553} 555}
554 556
555static const int maxLedeLines_ = 10; 557static const int maxLedeLines_ = 10;
@@ -611,6 +613,10 @@ static iBool typesetOneLine_RunTypesetter_(iWrapText *wrap, iRangecc wrapRange,
611} 613}
612 614
613static void doLayout_GmDocument_(iGmDocument *d) { 615static void doLayout_GmDocument_(iGmDocument *d) {
616 static iRegExp *ansiPattern_;
617 if (!ansiPattern_) {
618 ansiPattern_ = makeAnsiEscapePattern_Text(iTrue /* with ESC */);
619 }
614 const iPrefs *prefs = prefs_App(); 620 const iPrefs *prefs = prefs_App();
615 const iBool isMono = isForcedMonospace_GmDocument_(d); 621 const iBool isMono = isForcedMonospace_GmDocument_(d);
616 const iBool isGopher = isGopher_GmDocument_(d); 622 const iBool isGopher = isGopher_GmDocument_(d);
@@ -618,8 +624,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
618 const iBool isVeryNarrow = d->size.x <= 70 * gap_Text; 624 const iBool isVeryNarrow = d->size.x <= 70 * gap_Text;
619 const iBool isExtremelyNarrow = d->size.x <= 60 * gap_Text; 625 const iBool isExtremelyNarrow = d->size.x <= 60 * gap_Text;
620 const iBool isFullWidthImages = (d->outsideMargin < 5 * gap_UI); 626 const iBool isFullWidthImages = (d->outsideMargin < 5 * gap_UI);
621// const iBool isDarkBg = isDark_GmDocumentTheme( 627
622// isDark_ColorTheme(colorTheme_App()) ? prefs->docThemeDark : prefs->docThemeLight);
623 initTheme_GmDocument_(d); 628 initTheme_GmDocument_(d);
624 d->isLayoutInvalidated = iFalse; 629 d->isLayoutInvalidated = iFalse;
625 /* TODO: Collect these parameters into a GmTheme. */ 630 /* TODO: Collect these parameters into a GmTheme. */
@@ -657,7 +662,6 @@ static void doLayout_GmDocument_(iGmDocument *d) {
657 const iArray *oldPreMeta = collect_Array(copy_Array(&d->preMeta)); /* remember fold states */ 662 const iArray *oldPreMeta = collect_Array(copy_Array(&d->preMeta)); /* remember fold states */
658 clear_Array(&d->preMeta); 663 clear_Array(&d->preMeta);
659 clear_String(&d->title); 664 clear_String(&d->title);
660// clear_String(&d->bannerText);
661 if (d->size.x <= 0 || isEmpty_String(&d->source)) { 665 if (d->size.x <= 0 || isEmpty_String(&d->source)) {
662 return; 666 return;
663 } 667 }
@@ -671,7 +675,6 @@ static void doLayout_GmDocument_(iGmDocument *d) {
671 int preFont = preformatted_FontId; 675 int preFont = preformatted_FontId;
672 uint16_t preId = 0; 676 uint16_t preId = 0;
673 iBool enableIndents = iFalse; 677 iBool enableIndents = iFalse;
674// iBool addSiteBanner = d->bannerType != none_GmDocumentBanner;
675 const iBool isNormalized = isNormalized_GmDocument_(d); 678 const iBool isNormalized = isNormalized_GmDocument_(d);
676 enum iGmLineType prevType = text_GmLineType; 679 enum iGmLineType prevType = text_GmLineType;
677 enum iGmLineType prevNonBlankType = text_GmLineType; 680 enum iGmLineType prevNonBlankType = text_GmLineType;
@@ -755,7 +758,6 @@ static void doLayout_GmDocument_(iGmDocument *d) {
755 if (d->format == gemini_SourceFormat && 758 if (d->format == gemini_SourceFormat &&
756 startsWithSc_Rangecc(line, "```", &iCaseSensitive)) { 759 startsWithSc_Rangecc(line, "```", &iCaseSensitive)) {
757 isPreformat = iFalse; 760 isPreformat = iFalse;
758// addSiteBanner = iFalse; /* overrides the banner */
759 continue; 761 continue;
760 } 762 }
761 run.mediaType = max_MediaType; /* preformatted block */ 763 run.mediaType = max_MediaType; /* preformatted block */
@@ -763,28 +765,6 @@ static void doLayout_GmDocument_(iGmDocument *d) {
763 run.font = (d->format == plainText_SourceFormat ? plainText_FontId : preFont); 765 run.font = (d->format == plainText_SourceFormat ? plainText_FontId : preFont);
764 indent = indents[type]; 766 indent = indents[type];
765 } 767 }
766#if 0
767 if (addSiteBanner) {
768 addSiteBanner = iFalse;
769 const iRangecc bannerText = urlHost_String(&d->url);
770 if (!isEmpty_Range(&bannerText)) {
771 setRange_String(&d->bannerText, bannerText);
772 iGmRun banner = { .flags = decoration_GmRunFlag | siteBanner_GmRunFlag };
773 banner.bounds = zero_Rect();
774 banner.visBounds = init_Rect(0, 0, d->size.x, lineHeight_Text(banner_FontId) * 2);
775 if (d->bannerType == certificateWarning_GmDocumentBanner) {
776 banner.visBounds.size.y += iMaxi(6000 * lineHeight_Text(uiLabel_FontId) /
777 d->size.x, lineHeight_Text(uiLabel_FontId) * 5);
778 }
779 banner.text = bannerText;
780 banner.font = banner_FontId;
781 banner.color = tmBannerTitle_ColorId;
782 pushBack_Array(&d->layout, &banner);
783 pos.y += height_Rect(banner.visBounds) +
784 1.5f * lineHeight_Text(paragraph_FontId) * prefs->lineSpacing;
785 }
786 }
787#endif
788 /* Empty lines don't produce text runs. */ 768 /* Empty lines don't produce text runs. */
789 if (isEmpty_Range(&line)) { 769 if (isEmpty_Range(&line)) {
790 if (type == quote_GmLineType && !prefs->quoteIcon) { 770 if (type == quote_GmLineType && !prefs->quoteIcon) {
@@ -865,6 +845,8 @@ static void doLayout_GmDocument_(iGmDocument *d) {
865 if ((type == heading1_GmLineType || type == heading2_GmLineType) && 845 if ((type == heading1_GmLineType || type == heading2_GmLineType) &&
866 isEmpty_String(&d->title)) { 846 isEmpty_String(&d->title)) {
867 setRange_String(&d->title, line); 847 setRange_String(&d->title, line);
848 /* Get rid of ANSI escapes. */
849 replaceRegExp_String(&d->title, ansiPattern_, "", NULL, NULL);
868 } 850 }
869 /* List bullet. */ 851 /* List bullet. */
870 if (type == bullet_GmLineType) { 852 if (type == bullet_GmLineType) {
@@ -964,6 +946,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
964 } 946 }
965 } 947 }
966 iAssert(!isEmpty_Range(&line)); /* must have something at this point */ 948 iAssert(!isEmpty_Range(&line)); /* must have something at this point */
949 size_t numRunsAdded = 0;
967 /* Typeset the paragraph. */ { 950 /* Typeset the paragraph. */ {
968 iRunTypesetter rts; 951 iRunTypesetter rts;
969 init_RunTypesetter_(&rts); 952 init_RunTypesetter_(&rts);
@@ -1036,7 +1019,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
1036 : 1.0f); 1019 : 1.0f);
1037 } 1020 }
1038 } 1021 }
1039 commit_RunTypesetter_(&rts, d); 1022 numRunsAdded = commit_RunTypesetter_(&rts, d);
1040 break; 1023 break;
1041 } 1024 }
1042 /* Try again... */ 1025 /* Try again... */
@@ -1050,6 +1033,11 @@ static void doLayout_GmDocument_(iGmDocument *d) {
1050 deinit_RunTypesetter_(&rts); 1033 deinit_RunTypesetter_(&rts);
1051 } 1034 }
1052 /* Flag the end of line, too. */ 1035 /* Flag the end of line, too. */
1036 if (numRunsAdded == 0) {
1037 pos.y += lineHeight_Text(run.font) * prefs->lineSpacing;
1038 followsBlank = iTrue;
1039 continue;
1040 }
1053 iGmRun *lastRun = back_Array(&d->layout); 1041 iGmRun *lastRun = back_Array(&d->layout);
1054 lastRun->flags |= endOfLine_GmRunFlag; 1042 lastRun->flags |= endOfLine_GmRunFlag;
1055 if (lastRun->linkId && lastRun->flags & startOfLine_GmRunFlag) { 1043 if (lastRun->linkId && lastRun->flags & startOfLine_GmRunFlag) {
@@ -1301,7 +1289,7 @@ void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) {
1301 0x203b, 0x2042, 0x205c, 0x2182, 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, 1289 0x203b, 0x2042, 0x205c, 0x2182, 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606,
1302 0x265c, 0x265e, 0x2690, 0x2691, 0x2693, 0x2698, 0x2699, 0x26f0, 0x270e, 0x2728, 1290 0x265c, 0x265e, 0x2690, 0x2691, 0x2693, 0x2698, 0x2699, 0x26f0, 0x270e, 0x2728,
1303 0x272a, 0x272f, 0x2731, 0x2738, 0x273a, 0x273e, 0x2740, 0x2742, 0x2744, 0x2748, 1291 0x272a, 0x272f, 0x2731, 0x2738, 0x273a, 0x273e, 0x2740, 0x2742, 0x2744, 0x2748,
1304 0x274a, 0x2751, 0x2756, 0x2766, 0x27bd, 0x27c1, 0x27d0, 0x2b19, 0x1f300, 0x1f303, 1292 0x274a, 0x2318, 0x2756, 0x2766, 0x27bd, 0x27c1, 0x27d0, 0x2b19, 0x1f300, 0x1f303,
1305 0x1f306, 0x1f308, 0x1f30a, 0x1f319, 0x1f31f, 0x1f320, 0x1f340, 0x1f4cd, 0x1f4e1, 0x1f531, 1293 0x1f306, 0x1f308, 0x1f30a, 0x1f319, 0x1f31f, 0x1f320, 0x1f340, 0x1f4cd, 0x1f4e1, 0x1f531,
1306 0x1f533, 0x1f657, 0x1f659, 0x1f665, 0x1f668, 0x1f66b, 0x1f78b, 0x1f796, 0x1f79c, 1294 0x1f533, 0x1f657, 0x1f659, 0x1f665, 0x1f668, 0x1f66b, 0x1f78b, 0x1f796, 0x1f79c,
1307 }; 1295 };
@@ -1951,44 +1939,6 @@ void setUrl_GmDocument(iGmDocument *d, const iString *url) {
1951 } 1939 }
1952} 1940}
1953 1941
1954int replaceRegExp_String(iString *d, const iRegExp *regexp, const char *replacement,
1955 void (*matchHandler)(void *, const iRegExpMatch *),
1956 void *context) {
1957 iRegExpMatch m;
1958 iString result;
1959 int numMatches = 0;
1960 const char *pos = constBegin_String(d);
1961 init_RegExpMatch(&m);
1962 init_String(&result);
1963 while (matchString_RegExp(regexp, d, &m)) {
1964 appendRange_String(&result, (iRangecc){ pos, begin_RegExpMatch(&m) });
1965 /* Replace any capture group back-references. */
1966 for (const char *ch = replacement; *ch; ch++) {
1967 if (*ch == '\\') {
1968 ch++;
1969 if (*ch == '\\') {
1970 appendCStr_String(&result, "\\");
1971 }
1972 else if (*ch >= '0' && *ch <= '9') {
1973 appendRange_String(&result, capturedRange_RegExpMatch(&m, *ch - '0'));
1974 }
1975 }
1976 else {
1977 appendData_Block(&result.chars, ch, 1);
1978 }
1979 }
1980 if (matchHandler) {
1981 matchHandler(context, &m);
1982 }
1983 pos = end_RegExpMatch(&m);
1984 numMatches++;
1985 }
1986 appendRange_String(&result, (iRangecc){ pos, constEnd_String(d) });
1987 set_String(d, &result);
1988 deinit_String(&result);
1989 return numMatches;
1990}
1991
1992iDeclareType(PendingLink) 1942iDeclareType(PendingLink)
1993struct Impl_PendingLink { 1943struct Impl_PendingLink {
1994 iString *url; 1944 iString *url;