summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-10-18 09:07:21 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-10-18 09:07:21 +0300
commitbaf4f8d5b02952e4adfcf60acdd1ac904c132c89 (patch)
tree6a468ffdf3de63ec2f94508f5dbcd94a8ee6d1ac /src
parent3fb04c28f22475814708f69022eae5220d542108 (diff)
Preferences: ANSI escape flags
FG color and font style escapes can be enabled separately. FG color remains enabled by default like before.
Diffstat (limited to 'src')
-rw-r--r--src/app.c19
-rw-r--r--src/fontpack.c2
-rw-r--r--src/gmdocument.c24
-rw-r--r--src/gmdocument.h2
-rw-r--r--src/prefs.c2
-rw-r--r--src/prefs.h2
-rw-r--r--src/ui/documentwidget.c4
-rw-r--r--src/ui/text.c17
-rw-r--r--src/ui/text.h9
-rw-r--r--src/ui/util.c16
10 files changed, 65 insertions, 32 deletions
diff --git a/src/app.c b/src/app.c
index 5b12db14..485c2495 100644
--- a/src/app.c
+++ b/src/app.c
@@ -234,6 +234,7 @@ static iString *serializePrefs_App_(const iApp *d) {
234 iConstForEach(StringSet, fp, d->prefs.disabledFontPacks) { 234 iConstForEach(StringSet, fp, d->prefs.disabledFontPacks) {
235 appendFormat_String(str, "fontpack.disable id:%s\n", cstr_String(fp.value)); 235 appendFormat_String(str, "fontpack.disable id:%s\n", cstr_String(fp.value));
236 } 236 }
237 appendFormat_String(str, "ansiescape arg:%d\n", d->prefs.gemtextAnsiEscapes);
237 /* TODO: This array belongs in Prefs. It can then be used for command handling as well. */ 238 /* TODO: This array belongs in Prefs. It can then be used for command handling as well. */
238 const struct { 239 const struct {
239 const char * id; 240 const char * id;
@@ -241,7 +242,6 @@ static iString *serializePrefs_App_(const iApp *d) {
241 } boolPrefs[] = { 242 } boolPrefs[] = {
242 { "prefs.animate", &d->prefs.uiAnimations }, 243 { "prefs.animate", &d->prefs.uiAnimations },
243 { "prefs.font.smooth", &d->prefs.fontSmoothing }, 244 { "prefs.font.smooth", &d->prefs.fontSmoothing },
244 { "prefs.gemtext.ansi", &d->prefs.gemtextAnsiEscapes },
245 { "prefs.mono.gemini", &d->prefs.monospaceGemini }, 245 { "prefs.mono.gemini", &d->prefs.monospaceGemini },
246 { "prefs.mono.gopher", &d->prefs.monospaceGopher }, 246 { "prefs.mono.gopher", &d->prefs.monospaceGopher },
247 { "prefs.boldlink.visited", &d->prefs.boldLinkVisited }, 247 { "prefs.boldlink.visited", &d->prefs.boldLinkVisited },
@@ -2387,8 +2387,16 @@ iBool handleCommand_App(const char *cmd) {
2387 } 2387 }
2388 return iTrue; 2388 return iTrue;
2389 } 2389 }
2390 else if (equal_Command(cmd, "prefs.gemtext.ansi.changed")) { 2390 else if (equal_Command(cmd, "ansiescape")) {
2391 d->prefs.gemtextAnsiEscapes = arg_Command(cmd) != 0; 2391 d->prefs.gemtextAnsiEscapes = arg_Command(cmd);
2392 return iTrue;
2393 }
2394 else if (equal_Command(cmd, "prefs.gemtext.ansi.fg.changed")) {
2395 iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFg_AnsiFlag, arg_Command(cmd));
2396 return iTrue;
2397 }
2398 else if (equal_Command(cmd, "prefs.gemtext.ansi.fontstyle.changed")) {
2399 iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFontStyle_AnsiFlag, arg_Command(cmd));
2392 return iTrue; 2400 return iTrue;
2393 } 2401 }
2394 else if (equal_Command(cmd, "prefs.mono.gemini.changed") || 2402 else if (equal_Command(cmd, "prefs.mono.gemini.changed") ||
@@ -2822,7 +2830,10 @@ iBool handleCommand_App(const char *cmd) {
2822 setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.light"), 2830 setFlags_Widget(findChild_Widget(dlg, "prefs.boldlink.light"),
2823 selected_WidgetFlag, 2831 selected_WidgetFlag,
2824 d->prefs.boldLinkLight); 2832 d->prefs.boldLinkLight);
2825 setToggle_Widget(findChild_Widget(dlg, "prefs.gemtext.ansi"), d->prefs.gemtextAnsiEscapes); 2833 setToggle_Widget(findChild_Widget(dlg, "prefs.gemtext.ansi.fg"),
2834 d->prefs.gemtextAnsiEscapes & allowFg_AnsiFlag);
2835 setToggle_Widget(findChild_Widget(dlg, "prefs.gemtext.ansi.fontstyle"),
2836 d->prefs.gemtextAnsiEscapes & allowFontStyle_AnsiFlag);
2826 setToggle_Widget(findChild_Widget(dlg, "prefs.font.smooth"), d->prefs.fontSmoothing); 2837 setToggle_Widget(findChild_Widget(dlg, "prefs.font.smooth"), d->prefs.fontSmoothing);
2827 setFlags_Widget( 2838 setFlags_Widget(
2828 findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)), 2839 findChild_Widget(dlg, format_CStr("prefs.linewidth.%d", d->prefs.lineWidth)),
diff --git a/src/fontpack.c b/src/fontpack.c
index 7ed64113..b521147c 100644
--- a/src/fontpack.c
+++ b/src/fontpack.c
@@ -105,7 +105,7 @@ static void unload_FontFile_(iFontFile *d) {
105} 105}
106 106
107void deinit_FontFile(iFontFile *d) { 107void deinit_FontFile(iFontFile *d) {
108 printf("FontFile %p {%s} is DESTROYED\n", d, cstr_String(&d->id)); 108// printf("FontFile %p {%s} is DESTROYED\n", d, cstr_String(&d->id));
109 unload_FontFile_(d); 109 unload_FontFile_(d);
110 deinit_Block(&d->sourceData); 110 deinit_Block(&d->sourceData);
111 deinit_String(&d->id); 111 deinit_String(&d->id);
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 5d8c6e20..23ebace3 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -78,7 +78,7 @@ iDefineTypeConstruction(GmLink)
78iDeclareType(GmTheme) 78iDeclareType(GmTheme)
79 79
80struct Impl_GmTheme { 80struct Impl_GmTheme {
81 iBool ansiEscapesEnabled; 81 int ansiEscapes;
82 int colors[max_GmLineType]; 82 int colors[max_GmLineType];
83 int fonts[max_GmLineType]; 83 int fonts[max_GmLineType];
84}; 84};
@@ -596,7 +596,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
596 isPreformat = iTrue; 596 isPreformat = iTrue;
597 isFirstText = iFalse; 597 isFirstText = iFalse;
598 } 598 }
599 setAnsiEscapesEnabled_Text(d->theme.ansiEscapesEnabled); 599 setAnsiFlags_Text(d->theme.ansiEscapes);
600 while (nextSplit_Rangecc(content, "\n", &contentLine)) { 600 while (nextSplit_Rangecc(content, "\n", &contentLine)) {
601 iRangecc line = contentLine; /* `line` will be trimmed; modifying would confuse `nextSplit_Rangecc` */ 601 iRangecc line = contentLine; /* `line` will be trimmed; modifying would confuse `nextSplit_Rangecc` */
602 if (*line.end == '\r') { 602 if (*line.end == '\r') {
@@ -1057,7 +1057,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
1057 } 1057 }
1058 } 1058 }
1059 } 1059 }
1060 setAnsiEscapesEnabled_Text(iTrue); 1060 setAnsiFlags_Text(allowAll_AnsiFlag);
1061// printf("[GmDocument] layout size: %zu runs (%zu bytes)\n", 1061// printf("[GmDocument] layout size: %zu runs (%zu bytes)\n",
1062// size_Array(&d->layout), size_Array(&d->layout) * sizeof(iGmRun)); 1062// size_Array(&d->layout), size_Array(&d->layout) * sizeof(iGmRun));
1063} 1063}
@@ -1977,21 +1977,21 @@ void setSource_GmDocument(iGmDocument *d, const iString *source, int width, int
1977 set_String(&d->unormSource, source); 1977 set_String(&d->unormSource, source);
1978 set_String(&d->source, source); 1978 set_String(&d->source, source);
1979 if (d->format == gemini_SourceFormat) { 1979 if (d->format == gemini_SourceFormat) {
1980 d->theme.ansiEscapesEnabled = prefs_App()->gemtextAnsiEscapes; 1980 d->theme.ansiEscapes = prefs_App()->gemtextAnsiEscapes;
1981 } 1981 }
1982 else if (d->format == markdown_SourceFormat) { 1982 else if (d->format == markdown_SourceFormat) {
1983 /* Attempt a conversion to Gemtext when viewing local Markdown files. */ 1983 /* Attempt a conversion to Gemtext when viewing local Markdown files. */
1984 if (equalCase_Rangecc(urlScheme_String(&d->url), "file")) { 1984 if (equalCase_Rangecc(urlScheme_String(&d->url), "file")) {
1985 convertMarkdownToGemtext_GmDocument_(d); 1985 convertMarkdownToGemtext_GmDocument_(d);
1986 set_String(&d->unormSource, &d->source); /* use the converted source from now on */ 1986 set_String(&d->unormSource, &d->source); /* use the converted source from now on */
1987 d->theme.ansiEscapesEnabled = iTrue; /* escapes are used for styling */ 1987 d->theme.ansiEscapes = allowAll_AnsiFlag; /* escapes are used for styling */
1988 } 1988 }
1989 else { 1989 else {
1990 d->format = plainText_SourceFormat; /* just show as plain text */ 1990 d->format = plainText_SourceFormat; /* just show as plain text */
1991 } 1991 }
1992 } 1992 }
1993 else { 1993 else {
1994 d->theme.ansiEscapesEnabled = iTrue; 1994 d->theme.ansiEscapes = allowAll_AnsiFlag;
1995 } 1995 }
1996 if (isNormalized_GmDocument_(d)) { 1996 if (isNormalized_GmDocument_(d)) {
1997 normalize_GmDocument(d); 1997 normalize_GmDocument(d);
@@ -2033,7 +2033,7 @@ const iGmPreMeta *preMeta_GmDocument(const iGmDocument *d, uint16_t preId) {
2033void render_GmDocument(const iGmDocument *d, iRangei visRangeY, iGmDocumentRenderFunc render, 2033void render_GmDocument(const iGmDocument *d, iRangei visRangeY, iGmDocumentRenderFunc render,
2034 void *context) { 2034 void *context) {
2035 iBool isInside = iFalse; 2035 iBool isInside = iFalse;
2036 setAnsiEscapesEnabled_Text(d->theme.ansiEscapesEnabled); 2036 setAnsiFlags_Text(d->theme.ansiEscapes);
2037 /* TODO: Check lookup table for quick starting position. */ 2037 /* TODO: Check lookup table for quick starting position. */
2038 iConstForEach(Array, i, &d->layout) { 2038 iConstForEach(Array, i, &d->layout) {
2039 const iGmRun *run = i.value; 2039 const iGmRun *run = i.value;
@@ -2048,7 +2048,7 @@ void render_GmDocument(const iGmDocument *d, iRangei visRangeY, iGmDocumentRende
2048 render(context, run); 2048 render(context, run);
2049 } 2049 }
2050 } 2050 }
2051 setAnsiEscapesEnabled_Text(iTrue); 2051 setAnsiFlags_Text(allowAll_AnsiFlag);
2052} 2052}
2053 2053
2054static iBool isValidRun_GmDocument_(const iGmDocument *d, const iGmRun *run) { 2054static iBool isValidRun_GmDocument_(const iGmDocument *d, const iGmRun *run) {
@@ -2063,7 +2063,7 @@ const iGmRun *renderProgressive_GmDocument(const iGmDocument *d, const iGmRun *f
2063 size_t maxCount, 2063 size_t maxCount,
2064 iRangei visRangeY, iGmDocumentRenderFunc render, 2064 iRangei visRangeY, iGmDocumentRenderFunc render,
2065 void *context) { 2065 void *context) {
2066 setAnsiEscapesEnabled_Text(d->theme.ansiEscapesEnabled); 2066 setAnsiFlags_Text(d->theme.ansiEscapes);
2067 const iGmRun *run = first; 2067 const iGmRun *run = first;
2068 while (isValidRun_GmDocument_(d, run)) { 2068 while (isValidRun_GmDocument_(d, run)) {
2069 if ((dir < 0 && bottom_Rect(run->visBounds) < visRangeY.start) || 2069 if ((dir < 0 && bottom_Rect(run->visBounds) < visRangeY.start) ||
@@ -2076,7 +2076,7 @@ const iGmRun *renderProgressive_GmDocument(const iGmDocument *d, const iGmRun *f
2076 render(context, run); 2076 render(context, run);
2077 run += dir; 2077 run += dir;
2078 } 2078 }
2079 setAnsiEscapesEnabled_Text(iTrue); 2079 setAnsiFlags_Text(allowAll_AnsiFlag);
2080 return isValidRun_GmDocument_(d, run) ? run : NULL; 2080 return isValidRun_GmDocument_(d, run) ? run : NULL;
2081} 2081}
2082 2082
@@ -2337,8 +2337,8 @@ iChar siteIcon_GmDocument(const iGmDocument *d) {
2337 return d->siteIcon; 2337 return d->siteIcon;
2338} 2338}
2339 2339
2340iBool ansiEscapesEnabled_GmDocument(const iGmDocument *d) { 2340int ansiEscapes_GmDocument(const iGmDocument *d) {
2341 return d->theme.ansiEscapesEnabled; 2341 return d->theme.ansiEscapes;
2342} 2342}
2343 2343
2344void runBaseAttributes_GmDocument(const iGmDocument *d, const iGmRun *run, int *fontId_out, 2344void runBaseAttributes_GmDocument(const iGmDocument *d, const iGmRun *run, int *fontId_out,
diff --git a/src/gmdocument.h b/src/gmdocument.h
index 94a494e8..e6388fbd 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -225,7 +225,7 @@ iRangecc findText_GmDocument (const iGmDocument *, const
225iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before); 225iRangecc findTextBefore_GmDocument (const iGmDocument *, const iString *text, const char *before);
226iGmRunRange findPreformattedRange_GmDocument (const iGmDocument *, const iGmRun *run); 226iGmRunRange findPreformattedRange_GmDocument (const iGmDocument *, const iGmRun *run);
227 227
228iBool ansiEscapesEnabled_GmDocument (const iGmDocument *); 228int ansiEscapes_GmDocument (const iGmDocument *);
229void runBaseAttributes_GmDocument (const iGmDocument *, const iGmRun *run, 229void runBaseAttributes_GmDocument (const iGmDocument *, const iGmRun *run,
230 int *fontId_out, int *colorId_out); 230 int *fontId_out, int *colorId_out);
231 231
diff --git a/src/prefs.c b/src/prefs.c
index 523ec649..85936131 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -62,7 +62,7 @@ void init_Prefs(iPrefs *d) {
62 setCStr_String(&d->strings[monospaceDocumentFont_PrefsString], "iosevka-body"); 62 setCStr_String(&d->strings[monospaceDocumentFont_PrefsString], "iosevka-body");
63 d->disabledFontPacks = new_StringSet(); 63 d->disabledFontPacks = new_StringSet();
64 d->fontSmoothing = iTrue; 64 d->fontSmoothing = iTrue;
65 d->gemtextAnsiEscapes = iFalse; 65 d->gemtextAnsiEscapes = allowFg_AnsiFlag;
66 d->monospaceGemini = iFalse; 66 d->monospaceGemini = iFalse;
67 d->monospaceGopher = iFalse; 67 d->monospaceGopher = iFalse;
68 d->boldLinkVisited = iTrue; 68 d->boldLinkVisited = iTrue;
diff --git a/src/prefs.h b/src/prefs.h
index bbf98370..dc0914a6 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -89,7 +89,7 @@ struct Impl_Prefs {
89 /* Style */ 89 /* Style */
90 iStringSet * disabledFontPacks; 90 iStringSet * disabledFontPacks;
91 iBool fontSmoothing; 91 iBool fontSmoothing;
92 iBool gemtextAnsiEscapes; 92 int gemtextAnsiEscapes;
93 iBool monospaceGemini; 93 iBool monospaceGemini;
94 iBool monospaceGopher; 94 iBool monospaceGopher;
95 iBool boldLinkVisited; 95 iBool boldLinkVisited;
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index cf2dc5da..1039fc2b 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -4839,7 +4839,7 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx,
4839 } 4839 }
4840 } 4840 }
4841 } 4841 }
4842 setAnsiEscapesEnabled_Text(ansiEscapesEnabled_GmDocument(d->doc)); 4842 setAnsiFlags_Text(ansiEscapes_GmDocument(d->doc));
4843 iConstForEach(PtrSet, r, d->invalidRuns) { 4843 iConstForEach(PtrSet, r, d->invalidRuns) {
4844 const iGmRun *run = *r.value; 4844 const iGmRun *run = *r.value;
4845 if (isOverlapping_Rangei(bufRange, ySpan_Rect(run->visBounds))) { 4845 if (isOverlapping_Rangei(bufRange, ySpan_Rect(run->visBounds))) {
@@ -4847,7 +4847,7 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx,
4847 drawRun_DrawContext_(ctx, run); 4847 drawRun_DrawContext_(ctx, run);
4848 } 4848 }
4849 } 4849 }
4850 setAnsiEscapesEnabled_Text(iTrue); 4850 setAnsiFlags_Text(allowAll_AnsiFlag);
4851 } 4851 }
4852 endTarget_Paint(p); 4852 endTarget_Paint(p);
4853 if (prerenderExtra && didDraw) { 4853 if (prerenderExtra && didDraw) {
diff --git a/src/ui/text.c b/src/ui/text.c
index 6189c334..4baf60d3 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -261,7 +261,7 @@ struct Impl_Text {
261 SDL_Palette * grayscale; 261 SDL_Palette * grayscale;
262 SDL_Palette * blackAndWhite; /* unsmoothed glyph palette */ 262 SDL_Palette * blackAndWhite; /* unsmoothed glyph palette */
263 iRegExp * ansiEscape; 263 iRegExp * ansiEscape;
264 iBool enableAnsiEscapes; 264 int ansiFlags;
265 int baseFontId; /* base attributes (for restoring via escapes) */ 265 int baseFontId; /* base attributes (for restoring via escapes) */
266 int baseColorId; 266 int baseColorId;
267}; 267};
@@ -588,8 +588,8 @@ void setBaseAttributes_Text(int fontId, int colorId) {
588 activeText_->baseColorId = colorId; 588 activeText_->baseColorId = colorId;
589} 589}
590 590
591void setAnsiEscapesEnabled_Text(iBool enableAnsiEscapes) { 591void setAnsiFlags_Text(int ansiFlags) {
592 activeText_->enableAnsiEscapes = enableAnsiEscapes; 592 activeText_->ansiFlags = ansiFlags;
593} 593}
594 594
595void setDocumentFontSize_Text(iText *d, float fontSizeFactor) { 595void setDocumentFontSize_Text(iText *d, float fontSizeFactor) {
@@ -1057,10 +1057,11 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh
1057 init_RegExpMatch(&m); 1057 init_RegExpMatch(&m);
1058 if (match_RegExp(activeText_->ansiEscape, srcPos, d->source.end - srcPos, &m)) { 1058 if (match_RegExp(activeText_->ansiEscape, srcPos, d->source.end - srcPos, &m)) {
1059 finishRun_AttributedText_(d, &run, pos - 1); 1059 finishRun_AttributedText_(d, &run, pos - 1);
1060 if (activeText_->enableAnsiEscapes) { 1060 const int ansi = activeText_->ansiFlags;
1061 if (ansi) {
1061 const iRangecc sequence = capturedRange_RegExpMatch(&m, 1); 1062 const iRangecc sequence = capturedRange_RegExpMatch(&m, 1);
1062 /* Note: This styling is hardcoded to match `typesetOneLine_RunTypesetter_()`. */ 1063 /* Note: This styling is hardcoded to match `typesetOneLine_RunTypesetter_()`. */
1063 if (equal_Rangecc(sequence, "1")) { 1064 if (ansi & allowFontStyle_AnsiFlag && equal_Rangecc(sequence, "1")) {
1064 run.attrib.bold = iTrue; 1065 run.attrib.bold = iTrue;
1065 if (d->baseColorId == tmParagraph_ColorId) { 1066 if (d->baseColorId == tmParagraph_ColorId) {
1066 setFgColor_AttributedRun_(&run, tmFirstParagraph_ColorId); 1067 setFgColor_AttributedRun_(&run, tmFirstParagraph_ColorId);
@@ -1068,12 +1069,12 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh
1068 attribFont = font_Text_(fontWithStyle_Text(fontId_Text_(d->baseFont), 1069 attribFont = font_Text_(fontWithStyle_Text(fontId_Text_(d->baseFont),
1069 bold_FontStyle)); 1070 bold_FontStyle));
1070 } 1071 }
1071 else if (equal_Rangecc(sequence, "3")) { 1072 else if (ansi & allowFontStyle_AnsiFlag && equal_Rangecc(sequence, "3")) {
1072 run.attrib.italic = iTrue; 1073 run.attrib.italic = iTrue;
1073 attribFont = font_Text_(fontWithStyle_Text(fontId_Text_(d->baseFont), 1074 attribFont = font_Text_(fontWithStyle_Text(fontId_Text_(d->baseFont),
1074 italic_FontStyle)); 1075 italic_FontStyle));
1075 } 1076 }
1076 else if (equal_Rangecc(sequence, "4")) { 1077 else if (ansi & allowFontStyle_AnsiFlag && equal_Rangecc(sequence, "4")) {
1077 run.attrib.monospace = iTrue; 1078 run.attrib.monospace = iTrue;
1078 setFgColor_AttributedRun_(&run, tmPreformatted_ColorId); 1079 setFgColor_AttributedRun_(&run, tmPreformatted_ColorId);
1079 attribFont = font_Text_(fontWithFamily_Text(fontId_Text_(d->baseFont), 1080 attribFont = font_Text_(fontWithFamily_Text(fontId_Text_(d->baseFont),
@@ -1086,7 +1087,7 @@ static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir, iCh
1086 attribFont = run.font = d->baseFont; 1087 attribFont = run.font = d->baseFont;
1087 setFgColor_AttributedRun_(&run, d->baseColorId); 1088 setFgColor_AttributedRun_(&run, d->baseColorId);
1088 } 1089 }
1089 else { 1090 else if (ansi & allowFg_AnsiFlag) {
1090 run.fgColor_ = ansiForeground_Color(sequence, tmParagraph_ColorId); 1091 run.fgColor_ = ansiForeground_Color(sequence, tmParagraph_ColorId);
1091 } 1092 }
1092 } 1093 }
diff --git a/src/ui/text.h b/src/ui/text.h
index 36a16e2c..99ddb704 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -149,9 +149,16 @@ enum iAlignment {
149 right_Alignment, 149 right_Alignment,
150}; 150};
151 151
152enum iAnsiFlag {
153 allowFg_AnsiFlag = iBit(1),
154 allowBg_AnsiFlag = iBit(2),
155 allowFontStyle_AnsiFlag = iBit(3),
156 allowAll_AnsiFlag = 0x7,
157};
158
152void setOpacity_Text (float opacity); 159void setOpacity_Text (float opacity);
153void setBaseAttributes_Text (int fontId, int colorId); /* current "normal" text attributes */ 160void setBaseAttributes_Text (int fontId, int colorId); /* current "normal" text attributes */
154void setAnsiEscapesEnabled_Text(iBool enableAnsiEscapes); 161void setAnsiFlags_Text (int ansiFlags);
155 162
156void cache_Text (int fontId, iRangecc text); /* pre-render glyphs */ 163void cache_Text (int fontId, iRangecc text); /* pre-render glyphs */
157 164
diff --git a/src/ui/util.c b/src/ui/util.c
index 3b146155..e3759f09 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -2549,7 +2549,21 @@ iWidget *makePreferences_Widget(void) {
2549 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.monodoc}"))); 2549 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.monodoc}")));
2550 addFontButtons_(values, "monodoc"); 2550 addFontButtons_(values, "monodoc");
2551 addDialogPadding_(headings, values); 2551 addDialogPadding_(headings, values);
2552 addDialogToggle_(headings, values, "${prefs.gemtext.ansi}", "prefs.gemtext.ansi"); 2552 addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.gemtext.ansi}")));
2553 iWidget *ansi = new_Widget(); {
2554 iWidget *tog;
2555 setTextCStr_LabelWidget(
2556 addChild_Widget(ansi, tog = iClob(makeToggle_Widget("prefs.gemtext.ansi.fg"))),
2557 "${prefs.gemtext.ansi.fg}");
2558 setFlags_Widget(tog, fixedWidth_WidgetFlag, iFalse);
2559 updateSize_LabelWidget((iLabelWidget *) tog);
2560 setTextCStr_LabelWidget(
2561 addChild_Widget(ansi, tog = iClob(makeToggle_Widget("prefs.gemtext.ansi.fontstyle"))),
2562 "${prefs.gemtext.ansi.fontstyle}");
2563 setFlags_Widget(tog, fixedWidth_WidgetFlag, iFalse);
2564 updateSize_LabelWidget((iLabelWidget *) tog);
2565 }
2566 addChildFlags_Widget(values, iClob(ansi), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag);
2553 addDialogToggle_(headings, values, "${prefs.font.smooth}", "prefs.font.smooth"); 2567 addDialogToggle_(headings, values, "${prefs.font.smooth}", "prefs.font.smooth");
2554 addDialogPadding_(headings, values); 2568 addDialogPadding_(headings, values);
2555 addFontButtons_(values, "ui"); 2569 addFontButtons_(values, "ui");