diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-24 21:05:02 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-24 21:05:02 +0300 |
commit | e32fd4e7796d6e7c5a4803e45bc230378ec4dd0b (patch) | |
tree | 5232331654a977cf4ad1bf06eedc2f8752db6c32 | |
parent | 0f0b4250ca460d58edb61cc0dd509ba1980c3272 (diff) |
Font update; ANSI color escapes; fixed URL update
Newer version of the Fira fonts, and added a separate UI font (Source Sans Pro).
The text renderer checks for the 4-bit ANSI color escapes for the setting the foreground color.
InputWidget supports paste from clipboard.
The navbar updates the current URL when the page has been loaded.
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | res/FiraMono-Regular.ttf | bin | 132388 -> 174632 bytes | |||
-rw-r--r-- | res/FiraSans-Bold.ttf | bin | 208592 -> 438028 bytes | |||
-rw-r--r-- | res/FiraSans-LightItalic.ttf | bin | 197112 -> 404244 bytes | |||
-rw-r--r-- | res/FiraSans-Regular.ttf | bin | 194812 -> 403924 bytes | |||
-rw-r--r-- | res/SourceSansPro-Regular.ttf | bin | 0 -> 290156 bytes | |||
-rw-r--r-- | src/gmdocument.c | 10 | ||||
-rw-r--r-- | src/gmrequest.c | 8 | ||||
-rw-r--r-- | src/gmrequest.h | 1 | ||||
-rw-r--r-- | src/ui/color.c | 64 | ||||
-rw-r--r-- | src/ui/color.h | 3 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 1 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 62 | ||||
-rw-r--r-- | src/ui/metrics.c | 2 | ||||
-rw-r--r-- | src/ui/text.c | 21 | ||||
-rw-r--r-- | src/ui/text.h | 8 |
16 files changed, 153 insertions, 28 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index be56af23..0aaa2bb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -19,6 +19,7 @@ set (EMBED_RESOURCES | |||
19 | res/FiraSans-Bold.ttf | 19 | res/FiraSans-Bold.ttf |
20 | res/FiraSans-LightItalic.ttf | 20 | res/FiraSans-LightItalic.ttf |
21 | res/FiraMono-Regular.ttf | 21 | res/FiraMono-Regular.ttf |
22 | res/SourceSansPro-Regular.ttf | ||
22 | ) | 23 | ) |
23 | # if (UNIX AND NOT APPLE) | 24 | # if (UNIX AND NOT APPLE) |
24 | # list (APPEND EMBED_RESOURCES res/appicon-64.png) | 25 | # list (APPEND EMBED_RESOURCES res/appicon-64.png) |
diff --git a/res/FiraMono-Regular.ttf b/res/FiraMono-Regular.ttf index c4f34328..59e1e1a1 100644 --- a/res/FiraMono-Regular.ttf +++ b/res/FiraMono-Regular.ttf | |||
Binary files differ | |||
diff --git a/res/FiraSans-Bold.ttf b/res/FiraSans-Bold.ttf index 04830e7e..95e16602 100644 --- a/res/FiraSans-Bold.ttf +++ b/res/FiraSans-Bold.ttf | |||
Binary files differ | |||
diff --git a/res/FiraSans-LightItalic.ttf b/res/FiraSans-LightItalic.ttf index 3d3cc107..4b4c3a22 100644 --- a/res/FiraSans-LightItalic.ttf +++ b/res/FiraSans-LightItalic.ttf | |||
Binary files differ | |||
diff --git a/res/FiraSans-Regular.ttf b/res/FiraSans-Regular.ttf index a4e65638..d9fdc0e9 100644 --- a/res/FiraSans-Regular.ttf +++ b/res/FiraSans-Regular.ttf | |||
Binary files differ | |||
diff --git a/res/SourceSansPro-Regular.ttf b/res/SourceSansPro-Regular.ttf new file mode 100644 index 00000000..d9344ce8 --- /dev/null +++ b/res/SourceSansPro-Regular.ttf | |||
Binary files differ | |||
diff --git a/src/gmdocument.c b/src/gmdocument.c index 8355a0eb..6fde864a 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -151,7 +151,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
151 | header1_FontId, | 151 | header1_FontId, |
152 | header2_FontId, | 152 | header2_FontId, |
153 | header3_FontId, | 153 | header3_FontId, |
154 | default_FontId, | 154 | regular_FontId, |
155 | }; | 155 | }; |
156 | static const int colors[max_GmLineType] = { | 156 | static const int colors[max_GmLineType] = { |
157 | gray75_ColorId, | 157 | gray75_ColorId, |
@@ -267,7 +267,13 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
267 | const char *contPos; | 267 | const char *contPos; |
268 | run.bounds.size = tryAdvanceRange_Text( | 268 | run.bounds.size = tryAdvanceRange_Text( |
269 | run.font, runLine, isPreformat ? 0 : (d->size.x - run.bounds.pos.x), &contPos); | 269 | run.font, runLine, isPreformat ? 0 : (d->size.x - run.bounds.pos.x), &contPos); |
270 | run.text = (iRangecc){ runLine.start, contPos }; | 270 | if (contPos > runLine.start) { |
271 | run.text = (iRangecc){ runLine.start, contPos }; | ||
272 | } | ||
273 | else { | ||
274 | run.text = runLine; | ||
275 | contPos = runLine.end; | ||
276 | } | ||
271 | pushBack_Array(&d->layout, &run); | 277 | pushBack_Array(&d->layout, &run); |
272 | runLine.start = contPos; | 278 | runLine.start = contPos; |
273 | trimStart_Rangecc(&runLine); | 279 | trimStart_Rangecc(&runLine); |
diff --git a/src/gmrequest.c b/src/gmrequest.c index 2bda65e9..ce53abee 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -58,9 +58,9 @@ void deinit_GmRequest(iGmRequest *d) { | |||
58 | iDisconnectObject(TlsRequest, d->req, finished, d); | 58 | iDisconnectObject(TlsRequest, d->req, finished, d); |
59 | cancel_TlsRequest(d->req); | 59 | cancel_TlsRequest(d->req); |
60 | d->state = finished_GmRequestState; | 60 | d->state = finished_GmRequestState; |
61 | iRelease(d->req); | ||
62 | d->req = NULL; | ||
63 | } | 61 | } |
62 | iRelease(d->req); | ||
63 | d->req = NULL; | ||
64 | } | 64 | } |
65 | unlock_Mutex(&d->mutex); | 65 | unlock_Mutex(&d->mutex); |
66 | delete_Audience(d->finished); | 66 | delete_Audience(d->finished); |
@@ -237,4 +237,8 @@ const iBlock *body_GmRequest(const iGmRequest *d) { | |||
237 | return body; | 237 | return body; |
238 | } | 238 | } |
239 | 239 | ||
240 | const iString *url_GmRequest(const iGmRequest *d) { | ||
241 | return &d->url; | ||
242 | } | ||
243 | |||
240 | iDefineClass(GmRequest) | 244 | iDefineClass(GmRequest) |
diff --git a/src/gmrequest.h b/src/gmrequest.h index e7d5916b..b2cd339b 100644 --- a/src/gmrequest.h +++ b/src/gmrequest.h | |||
@@ -21,3 +21,4 @@ const char * error_GmRequest (const iGmRequest *); /* NULL if suc | |||
21 | enum iGmStatusCode status_GmRequest (const iGmRequest *); | 21 | enum iGmStatusCode status_GmRequest (const iGmRequest *); |
22 | const iString * meta_GmRequest (const iGmRequest *); | 22 | const iString * meta_GmRequest (const iGmRequest *); |
23 | const iBlock * body_GmRequest (const iGmRequest *); | 23 | const iBlock * body_GmRequest (const iGmRequest *); |
24 | const iString * url_GmRequest (const iGmRequest *); | ||
diff --git a/src/ui/color.c b/src/ui/color.c index d6a995c7..179006c1 100644 --- a/src/ui/color.c +++ b/src/ui/color.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include "color.h" | 1 | #include "color.h" |
2 | 2 | ||
3 | #include <the_Foundation/string.h> | ||
4 | |||
3 | static const iColor transparent_; | 5 | static const iColor transparent_; |
4 | 6 | ||
5 | iColor get_Color(int color) { | 7 | iColor get_Color(int color) { |
@@ -26,3 +28,65 @@ iColor get_Color(int color) { | |||
26 | } | 28 | } |
27 | return *clr; | 29 | return *clr; |
28 | } | 30 | } |
31 | |||
32 | iColor ansi_Color(iRangecc escapeSequence, int fallback) { | ||
33 | iColor clr = get_Color(fallback); | ||
34 | for (const char *ch = escapeSequence.start; ch < escapeSequence.end; ch++) { | ||
35 | char *endPtr; | ||
36 | unsigned long arg = strtoul(ch, &endPtr, 10); | ||
37 | ch = endPtr; | ||
38 | switch (arg) { | ||
39 | default: | ||
40 | break; | ||
41 | case 30: | ||
42 | clr = (iColor){ 0, 0, 0, 255 }; | ||
43 | break; | ||
44 | case 31: | ||
45 | clr = (iColor){ 170, 0, 0, 255 }; | ||
46 | break; | ||
47 | case 32: | ||
48 | clr = (iColor){ 0, 170, 0, 255 }; | ||
49 | break; | ||
50 | case 33: | ||
51 | clr = (iColor){ 170, 85, 0, 255 }; | ||
52 | break; | ||
53 | case 34: | ||
54 | clr = (iColor){ 0, 0, 170, 255 }; | ||
55 | break; | ||
56 | case 35: | ||
57 | clr = (iColor){ 170, 0, 170, 255 }; | ||
58 | break; | ||
59 | case 36: | ||
60 | clr = (iColor){ 0, 170, 170, 255 }; | ||
61 | break; | ||
62 | case 37: | ||
63 | clr = (iColor){ 170, 170, 170, 255 }; | ||
64 | break; | ||
65 | case 90: | ||
66 | clr = (iColor){ 85, 85, 85, 255 }; | ||
67 | break; | ||
68 | case 91: | ||
69 | clr = (iColor){ 255, 85, 85, 255 }; | ||
70 | break; | ||
71 | case 92: | ||
72 | clr = (iColor){ 85, 255, 85, 255 }; | ||
73 | break; | ||
74 | case 93: | ||
75 | clr = (iColor){ 255, 255, 85, 255 }; | ||
76 | break; | ||
77 | case 94: | ||
78 | clr = (iColor){ 85, 85, 255, 255 }; | ||
79 | break; | ||
80 | case 95: | ||
81 | clr = (iColor){ 255, 85, 255, 255 }; | ||
82 | break; | ||
83 | case 96: | ||
84 | clr = (iColor){ 85, 255, 255, 255 }; | ||
85 | break; | ||
86 | case 97: | ||
87 | clr = (iColor){ 255, 255, 255, 255 }; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | return clr; | ||
92 | } | ||
diff --git a/src/ui/color.h b/src/ui/color.h index aeb57375..7587e213 100644 --- a/src/ui/color.h +++ b/src/ui/color.h | |||
@@ -1,6 +1,6 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | 2 | ||
3 | #include <the_Foundation/defs.h> | 3 | #include <the_Foundation/range.h> |
4 | 4 | ||
5 | enum iColorId { | 5 | enum iColorId { |
6 | none_ColorId = -1, | 6 | none_ColorId = -1, |
@@ -48,3 +48,4 @@ struct Impl_Color { | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | iColor get_Color (int color); | 50 | iColor get_Color (int color); |
51 | iColor ansi_Color (iRangecc escapeSequence, int fallback); | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 121ca7cf..2466675e 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -368,6 +368,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
368 | checkResponseCode_DocumentWidget_(d); | 368 | checkResponseCode_DocumentWidget_(d); |
369 | d->state = ready_DocumentState; | 369 | d->state = ready_DocumentState; |
370 | iReleasePtr(&d->request); | 370 | iReleasePtr(&d->request); |
371 | postCommandf_App("document.changed url:%s", cstr_String(d->url)); | ||
371 | return iTrue; | 372 | return iTrue; |
372 | } | 373 | } |
373 | else if (isCommand_Widget(w, ev, "scroll.moved")) { | 374 | else if (isCommand_Widget(w, ev, "scroll.moved")) { |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index b73fac9e..22b30616 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "util.h" | 3 | #include "util.h" |
4 | 4 | ||
5 | #include <the_Foundation/array.h> | 5 | #include <the_Foundation/array.h> |
6 | #include <SDL_clipboard.h> | ||
6 | #include <SDL_timer.h> | 7 | #include <SDL_timer.h> |
7 | 8 | ||
8 | static const int REFRESH_INTERVAL = 256; | 9 | static const int REFRESH_INTERVAL = 256; |
@@ -132,6 +133,23 @@ void end_InputWidget(iInputWidget *d, iBool accept) { | |||
132 | postCommand_Widget(w, "input.ended id:%s arg:%d", id, accept ? 1 : 0); | 133 | postCommand_Widget(w, "input.ended id:%s arg:%d", id, accept ? 1 : 0); |
133 | } | 134 | } |
134 | 135 | ||
136 | static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { | ||
137 | if (d->mode == insert_InputMode) { | ||
138 | insert_Array(&d->text, d->cursor, &chr); | ||
139 | d->cursor++; | ||
140 | } | ||
141 | else if (d->maxLen == 0 || d->cursor < d->maxLen) { | ||
142 | if (d->cursor >= size_Array(&d->text)) { | ||
143 | resize_Array(&d->text, d->cursor + 1); | ||
144 | } | ||
145 | set_Array(&d->text, d->cursor++, &chr); | ||
146 | if (d->maxLen && d->cursor == d->maxLen) { | ||
147 | setFocus_Widget(NULL); | ||
148 | } | ||
149 | } | ||
150 | refresh_Widget(as_Widget(d)); | ||
151 | } | ||
152 | |||
135 | static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | 153 | static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { |
136 | iWidget *w = as_Widget(d); | 154 | iWidget *w = as_Widget(d); |
137 | if (isCommand_Widget(w, ev, "focus.gained")) { | 155 | if (isCommand_Widget(w, ev, "focus.gained")) { |
@@ -161,6 +179,20 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
161 | if (ev->type == SDL_KEYDOWN && isFocused_Widget(w)) { | 179 | if (ev->type == SDL_KEYDOWN && isFocused_Widget(w)) { |
162 | const int key = ev->key.keysym.sym; | 180 | const int key = ev->key.keysym.sym; |
163 | const int mods = keyMods_Sym(ev->key.keysym.mod); | 181 | const int mods = keyMods_Sym(ev->key.keysym.mod); |
182 | if (mods == KMOD_PRIMARY) { | ||
183 | switch (key) { | ||
184 | case 'v': | ||
185 | if (SDL_HasClipboardText()) { | ||
186 | char *text = SDL_GetClipboardText(); | ||
187 | iString *paste = collect_String(newCStr_String(text)); | ||
188 | SDL_free(text); | ||
189 | iConstForEach(String, i, paste) { | ||
190 | insertChar_InputWidget_(d, i.value); | ||
191 | } | ||
192 | } | ||
193 | return iTrue; | ||
194 | } | ||
195 | } | ||
164 | switch (key) { | 196 | switch (key) { |
165 | case SDLK_RETURN: | 197 | case SDLK_RETURN: |
166 | case SDLK_KP_ENTER: | 198 | case SDLK_KP_ENTER: |
@@ -237,21 +269,9 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
237 | } | 269 | } |
238 | else if (ev->type == SDL_TEXTINPUT && isFocused_Widget(w)) { | 270 | else if (ev->type == SDL_TEXTINPUT && isFocused_Widget(w)) { |
239 | const iString *uni = collectNewCStr_String(ev->text.text); | 271 | const iString *uni = collectNewCStr_String(ev->text.text); |
240 | const iChar chr = first_String(uni); | 272 | iConstForEach(String, i, uni) { |
241 | if (d->mode == insert_InputMode) { | 273 | insertChar_InputWidget_(d, i.value); |
242 | insert_Array(&d->text, d->cursor, &chr); | ||
243 | d->cursor++; | ||
244 | } | ||
245 | else { | ||
246 | if (d->cursor >= size_Array(&d->text)) { | ||
247 | resize_Array(&d->text, d->cursor + 1); | ||
248 | } | ||
249 | set_Array(&d->text, d->cursor++, &chr); | ||
250 | if (d->maxLen && d->cursor == d->maxLen) { | ||
251 | setFocus_Widget(NULL); | ||
252 | } | ||
253 | } | 274 | } |
254 | refresh_Widget(w); | ||
255 | return iTrue; | 275 | return iTrue; |
256 | } | 276 | } |
257 | return processEvent_Widget(w, ev); | 277 | return processEvent_Widget(w, ev); |
@@ -259,7 +279,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
259 | 279 | ||
260 | static void draw_InputWidget_(const iInputWidget *d) { | 280 | static void draw_InputWidget_(const iInputWidget *d) { |
261 | const uint32_t time = frameTime_Window(get_Window()); | 281 | const uint32_t time = frameTime_Window(get_Window()); |
262 | const iInt2 padding = init_I2(3 * gap_UI, gap_UI); | 282 | const iInt2 padding = init_I2(3 * gap_UI, gap_UI / 2); |
263 | iRect bounds = adjusted_Rect(bounds_Widget(constAs_Widget(d)), padding, neg_I2(padding)); | 283 | iRect bounds = adjusted_Rect(bounds_Widget(constAs_Widget(d)), padding, neg_I2(padding)); |
264 | const iBool isFocused = isFocused_Widget(constAs_Widget(d)); | 284 | const iBool isFocused = isFocused_Widget(constAs_Widget(d)); |
265 | const iBool isHover = isHover_Widget(constAs_Widget(d)) && | 285 | const iBool isHover = isHover_Widget(constAs_Widget(d)) && |
@@ -286,13 +306,19 @@ static void draw_InputWidget_(const iInputWidget *d) { | |||
286 | } | 306 | } |
287 | xOff = iMin(xOff, 0); | 307 | xOff = iMin(xOff, 0); |
288 | } | 308 | } |
289 | draw_Text(d->font, addX_I2(topLeft_Rect(bounds), xOff), white_ColorId, cstr_String(&text)); | 309 | const int yOff = (height_Rect(bounds) - lineHeight_Text(d->font)) / 2; |
310 | draw_Text(d->font, | ||
311 | add_I2(topLeft_Rect(bounds), | ||
312 | init_I2(xOff, yOff)), | ||
313 | white_ColorId, | ||
314 | cstr_String(&text)); | ||
290 | clearClip_Paint(&p); | 315 | clearClip_Paint(&p); |
291 | /* Cursor blinking. */ | 316 | /* Cursor blinking. */ |
292 | if (isFocused && (time & 256)) { | 317 | if (isFocused && (time & 256)) { |
293 | const iInt2 prefixSize = advanceN_Text(d->font, cstr_String(&text), d->cursor); | 318 | const iInt2 prefixSize = advanceN_Text(d->font, cstr_String(&text), d->cursor); |
294 | const iInt2 curPos = init_I2(xOff + left_Rect(bounds) + prefixSize.x, top_Rect(bounds)); | 319 | const iInt2 curPos = init_I2(xOff + left_Rect(bounds) + prefixSize.x, |
295 | const iRect curRect = { curPos, addX_I2(emSize, 1) }; | 320 | yOff + top_Rect(bounds)); |
321 | const iRect curRect = { curPos, addX_I2(emSize, 1) }; | ||
296 | iString cur; | 322 | iString cur; |
297 | if (d->cursor < size_Array(&d->text)) { | 323 | if (d->cursor < size_Array(&d->text)) { |
298 | initUnicodeN_String(&cur, constAt_Array(&d->text, d->cursor), 1); | 324 | initUnicodeN_String(&cur, constAt_Array(&d->text, d->cursor), 1); |
diff --git a/src/ui/metrics.c b/src/ui/metrics.c index 949daaff..3c4bfd75 100644 --- a/src/ui/metrics.c +++ b/src/ui/metrics.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | #include <the_Foundation/math.h> | 3 | #include <the_Foundation/math.h> |
4 | 4 | ||
5 | #define defaultFontSize_Metrics 20 | 5 | #define defaultFontSize_Metrics 18 |
6 | #define defaultGap_Metrics 4 | 6 | #define defaultGap_Metrics 4 |
7 | 7 | ||
8 | int gap_UI = defaultGap_Metrics; | 8 | int gap_UI = defaultGap_Metrics; |
diff --git a/src/ui/text.c b/src/ui/text.c index 27c41396..f1c2c947 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <the_Foundation/file.h> | 11 | #include <the_Foundation/file.h> |
12 | #include <the_Foundation/hash.h> | 12 | #include <the_Foundation/hash.h> |
13 | #include <the_Foundation/math.h> | 13 | #include <the_Foundation/math.h> |
14 | #include <the_Foundation/regexp.h> | ||
14 | #include <the_Foundation/path.h> | 15 | #include <the_Foundation/path.h> |
15 | #include <the_Foundation/vec2.h> | 16 | #include <the_Foundation/vec2.h> |
16 | 17 | ||
@@ -89,12 +90,14 @@ struct Impl_Text { | |||
89 | iInt2 cachePos; | 90 | iInt2 cachePos; |
90 | int cacheRowHeight; | 91 | int cacheRowHeight; |
91 | SDL_Palette * grayscale; | 92 | SDL_Palette * grayscale; |
93 | iRegExp * ansiEscape; | ||
92 | }; | 94 | }; |
93 | 95 | ||
94 | static iText text_; | 96 | static iText text_; |
95 | 97 | ||
96 | void init_Text(SDL_Renderer *render) { | 98 | void init_Text(SDL_Renderer *render) { |
97 | iText *d = &text_; | 99 | iText *d = &text_; |
100 | d->ansiEscape = new_RegExp("\\[([0-9;]+)m", 0); | ||
98 | d->render = render; | 101 | d->render = render; |
99 | /* A grayscale palette for rasterized glyphs. */ { | 102 | /* A grayscale palette for rasterized glyphs. */ { |
100 | SDL_Color colors[256]; | 103 | SDL_Color colors[256]; |
@@ -117,6 +120,7 @@ void init_Text(SDL_Renderer *render) { | |||
117 | } | 120 | } |
118 | /* Load the fonts. */ { | 121 | /* Load the fonts. */ { |
119 | const struct { const iBlock *ttf; int size; } fontData[max_FontId] = { | 122 | const struct { const iBlock *ttf; int size; } fontData[max_FontId] = { |
123 | { &fontSourceSansProRegular_Embedded, fontSize_UI }, | ||
120 | { &fontFiraSansRegular_Embedded, fontSize_UI }, | 124 | { &fontFiraSansRegular_Embedded, fontSize_UI }, |
121 | { &fontFiraMonoRegular_Embedded, fontSize_UI * 0.866f }, | 125 | { &fontFiraMonoRegular_Embedded, fontSize_UI * 0.866f }, |
122 | { &fontFiraMonoRegular_Embedded, fontSize_UI * 0.666f }, | 126 | { &fontFiraMonoRegular_Embedded, fontSize_UI * 0.666f }, |
@@ -141,6 +145,7 @@ void deinit_Text(void) { | |||
141 | } | 145 | } |
142 | SDL_DestroyTexture(d->cache); | 146 | SDL_DestroyTexture(d->cache); |
143 | d->render = NULL; | 147 | d->render = NULL; |
148 | iRelease(d->ansiEscape); | ||
144 | } | 149 | } |
145 | 150 | ||
146 | static SDL_Surface *rasterizeGlyph_Font_(const iFont *d, iChar ch, float xShift) { | 151 | static SDL_Surface *rasterizeGlyph_Font_(const iFont *d, iChar ch, float xShift) { |
@@ -414,6 +419,20 @@ static iInt2 run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe | |||
414 | iChar prevCh = 0; | 419 | iChar prevCh = 0; |
415 | for (const char *chPos = text.start; chPos != text.end; ) { | 420 | for (const char *chPos = text.start; chPos != text.end; ) { |
416 | iAssert(chPos < text.end); | 421 | iAssert(chPos < text.end); |
422 | if (*chPos == 0x1b) { | ||
423 | /* ANSI escape. */ | ||
424 | chPos++; | ||
425 | iRegExpMatch m; | ||
426 | if (match_RegExp(text_.ansiEscape, chPos, text.end - chPos, &m)) { | ||
427 | if (mode == draw_RunMode) { | ||
428 | /* Change the color. */ | ||
429 | const iColor clr = ansi_Color(capturedRange_RegExpMatch(&m, 1), gray75_ColorId); | ||
430 | SDL_SetTextureColorMod(text_.cache, clr.r, clr.g, clr.b); | ||
431 | } | ||
432 | chPos = end_RegExpMatch(&m); | ||
433 | continue; | ||
434 | } | ||
435 | } | ||
417 | iChar ch = nextChar_(&chPos, text.end); | 436 | iChar ch = nextChar_(&chPos, text.end); |
418 | /* Special instructions. */ { | 437 | /* Special instructions. */ { |
419 | if (ch == '\n') { | 438 | if (ch == '\n') { |
@@ -424,8 +443,8 @@ static iInt2 run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe | |||
424 | } | 443 | } |
425 | if (ch == '\r') { | 444 | if (ch == '\r') { |
426 | const iChar esc = nextChar_(&chPos, text.end); | 445 | const iChar esc = nextChar_(&chPos, text.end); |
427 | const iColor clr = get_Color(esc - '0'); | ||
428 | if (mode == draw_RunMode) { | 446 | if (mode == draw_RunMode) { |
447 | const iColor clr = get_Color(esc - '0'); | ||
429 | SDL_SetTextureColorMod(text_.cache, clr.r, clr.g, clr.b); | 448 | SDL_SetTextureColorMod(text_.cache, clr.r, clr.g, clr.b); |
430 | } | 449 | } |
431 | prevCh = 0; | 450 | prevCh = 0; |
diff --git a/src/ui/text.h b/src/ui/text.h index 2181fa34..be95e948 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | enum iFontId { | 8 | enum iFontId { |
9 | default_FontId, | 9 | default_FontId, |
10 | regular_FontId, | ||
10 | monospace_FontId, | 11 | monospace_FontId, |
11 | monospaceSmall_FontId, | 12 | monospaceSmall_FontId, |
12 | medium_FontId, | 13 | medium_FontId, |
@@ -17,9 +18,11 @@ enum iFontId { | |||
17 | hugeBold_FontId, | 18 | hugeBold_FontId, |
18 | max_FontId, | 19 | max_FontId, |
19 | /* UI fonts: */ | 20 | /* UI fonts: */ |
20 | uiInput_FontId = monospace_FontId, | 21 | uiLabel_FontId = default_FontId, |
22 | uiShortcuts_FontId = default_FontId, | ||
23 | uiInput_FontId = monospace_FontId, | ||
21 | /* Document fonts: */ | 24 | /* Document fonts: */ |
22 | paragraph_FontId = default_FontId, | 25 | paragraph_FontId = regular_FontId, |
23 | firstParagraph_FontId = medium_FontId, | 26 | firstParagraph_FontId = medium_FontId, |
24 | preformatted_FontId = monospace_FontId, | 27 | preformatted_FontId = monospace_FontId, |
25 | preformattedSmall_FontId = monospaceSmall_FontId, | 28 | preformattedSmall_FontId = monospaceSmall_FontId, |
@@ -27,7 +30,6 @@ enum iFontId { | |||
27 | header1_FontId = hugeBold_FontId, | 30 | header1_FontId = hugeBold_FontId, |
28 | header2_FontId = largeBold_FontId, | 31 | header2_FontId = largeBold_FontId, |
29 | header3_FontId = medium_FontId, | 32 | header3_FontId = medium_FontId, |
30 | uiShortcuts_FontId = default_FontId, | ||
31 | }; | 33 | }; |
32 | 34 | ||
33 | #define specialSymbol_Text 0x10 | 35 | #define specialSymbol_Text 0x10 |