commit 55b6cc3

uint  ·  2026-07-31 18:45:48 +0000 UTC
parent d647190
remove libgrapheme dependency, ignore utf8 characters
3 files changed,  +9, -89
+0, -1
1@@ -2,7 +2,6 @@ CC = cc
2 CFLAGS = -std=c99 -Wall -Wextra
3 CPPFLAGS = -Iinclude -Ilibmaus/include
4 LDFLAGS =
5-LDLIBS = -lgrapheme
6 
7 include platform.mk
8 
+1, -3
 1@@ -61,8 +61,6 @@ typedef struct {
 2 	bool    bracketed_paste;
 3 	int     csi_params[CSI_PARAMS_MAX];
 4 	int     csi_idx;
 5-	char    utf8[4];
 6-	size_t  utf8_len;
 7 } Term;
 8 
 9 /* clear screen by filling runes with ' ' and reseting
10@@ -86,7 +84,7 @@ int term_resize(Term* t, Caret* c, int cols, int rows);
11 /* scroll viewport up by one */
12 void term_scroll(Term* t);
13 
14-/* processes terminal input, parse utf8, escape sequences, update
15+/* processes terminal input, parse escape sequences, update
16    caret, screen state, and damage status. */
17 bool term_write(Term* t, Caret* c, const char* s, size_t n);
18 
+8, -85
  1@@ -1,9 +1,6 @@
  2 #include <stdbool.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5-#include <wchar.h>
  6-
  7-#include <grapheme.h>
  8 
  9 #include "../config.h"
 10 #include "term.h"
 11@@ -16,7 +13,6 @@ static void chars_delete(Term* t, Caret* c, int n);
 12 static uint32_t acs_map(unsigned char ch);
 13 static void csi_dispatch(Term* t, Caret* c, unsigned char ch);
 14 static void csi_reset(Term* t);
 15-static int cp_width(uint32_t cp);
 16 static void erase_display(Term* t, Caret* c);
 17 static void erase_line(Term* t, Caret* c);
 18 static void reset_rune(Term* t, int x, int y);
 19@@ -24,8 +20,6 @@ static void rune_prepare(Term* t, int x, int y);
 20 static void scroll_down(Term* t, int top, int bot, int n);
 21 static void scroll_up(Term* t, int top, int bot, int n);
 22 static void sgr(Term* t);
 23-static void utf8_flush(Term* t, Caret* c);
 24-static void utf8_putc(Term* t, Caret* c, unsigned char ch);
 25 
 26 /* TODO */
 27 static uint32_t acs_map(unsigned char ch)
 28@@ -305,18 +299,6 @@ static void csi_reset(Term* t)
 29 	t->csi_idx = 0;
 30 }
 31 
 32-/* TODO */
 33-static int cp_width(uint32_t cp)
 34-{
 35-	int w = wcwidth((wchar_t)cp);
 36-
 37-	if (w < 0)
 38-		return 1;
 39-	if (w > 2)
 40-		return 2;
 41-	return w;
 42-}
 43-
 44 /* TODO */
 45 static void erase_display(Term* t, Caret* c)
 46 {
 47@@ -464,49 +446,6 @@ static void sgr(Term* t)
 48 	}
 49 }
 50 
 51-/* TODO */
 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-/* buffer and decode utf8 to code points, then write
 61-   using current character set */
 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, t->acs[t->charset] ? acs_map(ch) : 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@@ -570,48 +509,30 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
 98 			term_putc(t, c, '\n');
 99 		break;
100 	default: {
101-		int w;
102-
103 		if (cp < 32)
104 			break;
105-		w = cp_width(cp);
106-		if (w == 0)
107-			break;
108-		if (w == 2 && t->cols < 2)
109-			w = 1;
110 
111 		if (t->wrapnext) {
112 			term_putc(t, c, '\n');
113 			t->wrapnext = false;
114 		}
115-		if (w == 2 && c->x == t->cols - 1)
116-			term_putc(t, c, '\n');
117 
118 		rune_prepare(t, c->x, c->y);
119 		Rune* r = &RUNE(t, c->x, c->y);
120 		if (r->cp != cp || r->fg != t->fg || r->bg != t->bg ||
121-		    r->attr != t->attr || r->width != w) {
122+		    r->attr != t->attr || r->width != 1) {
123 			r->cp = cp;
124 			r->fg = t->fg;
125 			r->bg = t->bg;
126 			r->attr = t->attr;
127-			r->width = w;
128+			r->width = 1;
129 			r->dmg = true;
130 		}
131-		if (w == 2) {
132-			Rune* spacer = &RUNE(t, c->x + 1, c->y);
133-			spacer->cp = ' ';
134-			spacer->fg = t->fg;
135-			spacer->bg = t->bg;
136-			spacer->attr = t->attr;
137-			spacer->width = 0;
138-			spacer->dmg = true;
139-		}
140 
141-		if (c->x + w >= t->cols)
142+		if (c->x + 1 >= t->cols)
143 			t->wrapnext = true;
144 		else
145-			c->x += w;
146+			c->x++;
147 
148 		break;
149 	}
150@@ -708,7 +629,6 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
151 		switch (t->state) {
152 		case TSTATE_NORMAL:
153 			if (ch == '\x1B') {
154-				utf8_flush(t, c);
155 				t->state = TSTATE_ESC;
156 			}
157 			else if (ch == '\x0E') {
158@@ -717,8 +637,11 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
159 			else if (ch == '\x0F') {
160 				t->charset = 0;
161 			}
162+			else if (ch >= 0x80) {
163+				/* utf8 unsupported . ignore high bit bytes */
164+			}
165 			else {
166-				utf8_putc(t, c, ch);
167+				term_putc(t, c, t->acs[t->charset] ? acs_map(ch) : ch);
168 			}
169 			break;
170