commit 7a5f4cd
uint
·
2026-05-16 13:52:33 +0000 UTC
parent 7a30e87
add dec line drawing character set support
2 files changed,
+52,
-1
+5,
-0
1@@ -18,6 +18,8 @@ enum TState {
2 TSTATE_CSI,
3 TSTATE_OSC,
4 TSTATE_OSC_ESC,
5+ TSTATE_CHARSET,
6+ TSTATE_CHARSET_SKIP,
7 };
8
9 typedef struct {
10@@ -51,6 +53,9 @@ typedef struct {
11 pid_t ptypid;
12
13 enum TState state;
14+ bool acs[2];
15+ int charset;
16+ int charset_target;
17 bool wrapnext;
18 bool cursor_visible;
19 int csi_params[CSI_PARAMS_MAX];
+47,
-1
1@@ -12,6 +12,7 @@ static int csi_arg(Term* t, int i, int fallback);
2 static void alt_screen(Term* t, Caret* c, bool on);
3 static void chars_insert(Term* t, Caret* c, int n);
4 static void chars_delete(Term* t, Caret* c, int n);
5+static uint32_t acs_map(unsigned char ch);
6 static void csi_dispatch(Term* t, Caret* c, unsigned char ch);
7 static void csi_reset(Term* t);
8 static int cp_width(uint32_t cp);
9@@ -32,6 +33,25 @@ static const uint32_t ansi_colours[16] = { /* TODO */
10 0xffff5c5c, 0xffff00ff, 0xffffff00, 0xffffffff,
11 };
12
13+/** TODO
14+ */
15+static uint32_t acs_map(unsigned char ch)
16+{
17+ switch (ch) {
18+ case '`': return 0x25c6; /* ◆ */ case 'a': return 0x2592; /* ▒ */
19+ case 'f': return 0x00b0; /* ° */ case 'g': return 0x00b1; /* ± */
20+ case 'j': return 0x2518; /* ┘ */ case 'k': return 0x2510; /* ┐ */
21+ case 'l': return 0x250c; /* ┌ */ case 'm': return 0x2514; /* └ */
22+ case 'n': return 0x253c; /* ┼ */ case 'q': return 0x2500; /* ─ */
23+ case 't': return 0x251c; /* ├ */ case 'u': return 0x2524; /* ┤ */
24+ case 'v': return 0x2534; /* ┴ */ case 'w': return 0x252c; /* ┬ */
25+ case 'x': return 0x2502; /* │ */ case 'y': return 0x2264; /* ≤ */
26+ case 'z': return 0x2265; /* ≥ */ case '{': return 0x03c0; /* π */
27+ case '|': return 0x2260; /* ≠ */ case '}': return 0x00a3; /* £ */
28+ case '~': return 0x00b7; /* · */ default: return ch;
29+ }
30+}
31+
32 /** TODO
33 */
34 static int csi_arg(Term* t, int i, int fallback)
35@@ -485,7 +505,7 @@ static void utf8_putc(Term* t, Caret* c, unsigned char ch)
36
37 if (ch < 0x80) {
38 utf8_flush(t, c);
39- term_putc(t, c, ch);
40+ term_putc(t, c, t->acs[t->charset] ? acs_map(ch) : ch);
41 return;
42 }
43
44@@ -718,6 +738,12 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
45 utf8_flush(t, c);
46 t->state = TSTATE_ESC;
47 }
48+ else if (ch == '\x0E') {
49+ t->charset = 1;
50+ }
51+ else if (ch == '\x0F') {
52+ t->charset = 0;
53+ }
54 else {
55 utf8_putc(t, c, ch);
56 }
57@@ -731,6 +757,17 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
58 else if (ch == ']') {
59 t->state = TSTATE_OSC;
60 }
61+ else if (ch == '(') {
62+ t->charset_target = 0;
63+ t->state = TSTATE_CHARSET;
64+ }
65+ else if (ch == ')') {
66+ t->charset_target = 1;
67+ t->state = TSTATE_CHARSET;
68+ }
69+ else if (ch == '*' || ch == '+') {
70+ t->state = TSTATE_CHARSET_SKIP;
71+ }
72 else if (ch == '7') {
73 t->saved = *c;
74 t->state = TSTATE_NORMAL;
75@@ -790,6 +827,15 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
76 case TSTATE_OSC_ESC:
77 t->state = ch == '\\' ? TSTATE_NORMAL : TSTATE_OSC;
78 break;
79+
80+ case TSTATE_CHARSET:
81+ t->acs[t->charset_target] = ch == '0';
82+ t->state = TSTATE_NORMAL;
83+ break;
84+
85+ case TSTATE_CHARSET_SKIP:
86+ t->state = TSTATE_NORMAL;
87+ break;
88 }
89
90 if (old.x != c->x || old.y != c->y)