commit aa0b633
uint
·
2026-05-14 16:29:09 +0000 UTC
parent dd33bbb
add proper utf8 decoding instead of calling raw grapheme_decode_utf8 also rename csi_param->csi_idx
4 files changed,
+66,
-16
+5,
-5
1@@ -55,12 +55,11 @@ static Glyph* get_glyph(Fontface* f, uint32_t cp)
2 SFT_Image img;
3 Glyph* g;
4
5- if (cp >= GLYPH_CACHE_MAX)
6- return NULL;
7-
8- g = &glyphs[cp];
9- if (g->valid)
10+ g = &glyphs[cp % GLYPH_CACHE_MAX];
11+ if (g->valid && g->cp == cp)
12 return g;
13+ free(g->bmp);
14+ memset(g, 0, sizeof(*g));
15
16 if (sft_lookup(&f->sft, cp, &glyph) < 0)
17 return NULL;
18@@ -87,6 +86,7 @@ static Glyph* get_glyph(Fontface* f, uint32_t cp)
19 g->h = gm.minHeight;
20 g->lsb = gm.leftSideBearing;
21 g->yoff = gm.yOffset;
22+ g->cp = cp;
23 g->valid = true;
24
25 return g;
+2,
-1
1@@ -10,6 +10,7 @@
2 #define Glyph _Glyph /* Xrender defines the same */
3 typedef struct {
4 bool valid;
5+ uint32_t cp;
6 int w;
7 int h;
8 int lsb;
9@@ -68,7 +69,7 @@ void draw_caret(uint32_t* dst, int w, int h, int cl, int rw, int cw, int ch,
10 * @param h buffer height
11 * @param x x-position to draw at
12 * @param baseline text baseline y-position
13- * @param cp (unicode) codepoint to draw
14+ * @param cp codepoint to draw
15 * @param fg foreground colour
16 */
17 void draw_codepoint(Fontface* face, uint32_t* dst, int w, int h, int x,
+3,
-1
1@@ -42,7 +42,9 @@ typedef struct {
2
3 enum TState state;
4 int csi_params[CSI_PARAMS_MAX];
5- int csi_param;
6+ int csi_idx;
7+ char utf8[4];
8+ size_t utf8_len;
9 } Term;
10
11 /**
+56,
-9
1@@ -14,6 +14,8 @@ static void erase_display(Term* t, Caret* c);
2 static void erase_line(Term* t, Caret* c);
3 static void reset_rune(Term* t, int x, int y);
4 static void sgr(Term* t);
5+static void utf8_flush(Term* t, Caret* c);
6+static void utf8_putc(Term* t, Caret* c, unsigned char ch);
7
8 static const uint32_t ansi_colours[16] = { /* TODO */
9 0xff000000, 0xff0000cd, 0xff00cd00, 0xff00cdcd,
10@@ -26,7 +28,7 @@ static const uint32_t ansi_colours[16] = { /* TODO */
11 */
12 static int csi_arg(Term* t, int i, int fallback)
13 {
14- if (i > t->csi_param)
15+ if (i > t->csi_idx)
16 return fallback;
17 if (t->csi_params[i] == 0)
18 return fallback;
19@@ -148,7 +150,7 @@ static void csi_reset(Term* t)
20 {
21 for (int i = 0; i < CSI_PARAMS_MAX; i++)
22 t->csi_params[i] = 0;
23- t->csi_param = 0;
24+ t->csi_idx = 0;
25 }
26
27 /** TODO
28@@ -209,7 +211,7 @@ static void reset_rune(Term* t, int x, int y)
29 */
30 static void sgr(Term* t)
31 {
32- for (int i = 0; i <= t->csi_param; i++) {
33+ for (int i = 0; i <= t->csi_idx; i++) {
34 int p = t->csi_params[i];
35
36 if (p == 0) {
37@@ -229,7 +231,7 @@ static void sgr(Term* t)
38 else if (p == 49)
39 t->bg = TERM_DEFAULT_BG;
40 else if ((p == 38 || p == 48) &&
41- i + 4 <= t->csi_param && t->csi_params[i + 1] == 2) {
42+ i + 4 <= t->csi_idx && t->csi_params[i + 1] == 2) {
43 uint32_t col = rgba(
44 t->csi_params[i + 2],
45 t->csi_params[i + 3],
46@@ -244,6 +246,50 @@ static void sgr(Term* t)
47 }
48 }
49
50+/** TODO
51+ */
52+static void utf8_flush(Term* t, Caret* c)
53+{
54+ if (t->utf8_len == 0)
55+ return;
56+ term_putc(t, c, GRAPHEME_INVALID_CODEPOINT);
57+ t->utf8_len = 0;
58+}
59+
60+/** TODO
61+ */
62+static void utf8_putc(Term* t, Caret* c, unsigned char ch)
63+{
64+ uint_least32_t cp;
65+ size_t ret;
66+
67+ if (ch < 0x80) {
68+ utf8_flush(t, c);
69+ term_putc(t, c, ch);
70+ return;
71+ }
72+
73+ if (t->utf8_len == sizeof(t->utf8))
74+ utf8_flush(t, c);
75+
76+ t->utf8[t->utf8_len++] = (char)ch;
77+ for (;;) {
78+ ret = grapheme_decode_utf8(t->utf8, t->utf8_len, &cp);
79+ if (ret > t->utf8_len)
80+ return;
81+ if (ret == 0) {
82+ t->utf8_len = 0;
83+ return;
84+ }
85+
86+ term_putc(t, c, (uint32_t)cp);
87+ t->utf8_len -= ret;
88+ if (t->utf8_len == 0)
89+ return;
90+ memmove(t->utf8, t->utf8 + ret, t->utf8_len);
91+ }
92+}
93+
94 void term_clear(Term* t, Caret* c)
95 {
96 for (int y = 0; y < t->rows; y++) {
97@@ -410,10 +456,11 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
98 switch (t->state) {
99 case TSTATE_NORMAL:
100 if (ch == '\x1B') {
101+ utf8_flush(t, c);
102 t->state = TSTATE_ESC;
103 }
104 else {
105- term_putc(t, c, ch);
106+ utf8_putc(t, c, ch);
107 }
108 break;
109
110@@ -429,12 +476,12 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
111
112 case TSTATE_CSI:
113 if (ch >= '0' && ch <= '9') {
114- t->csi_params[t->csi_param] *= 10;
115- t->csi_params[t->csi_param] += ch - '0';
116+ t->csi_params[t->csi_idx] *= 10;
117+ t->csi_params[t->csi_idx] += ch - '0';
118 }
119 else if (ch == ';') {
120- if (t->csi_param + 1 < CSI_PARAMS_MAX)
121- t->csi_param++;
122+ if (t->csi_idx + 1 < CSI_PARAMS_MAX)
123+ t->csi_idx++;
124 }
125 else if (ch == '?' || ch == '>' || ch == '=') {
126 /* private CSI marker */