Commit: 9bb775b76c7d37fa7ac446de2962846393119d27
Parent: ca530c87fdb664a63b74100be963687d498772eb
Author: Randy Palamar
Date: Sat, 16 Nov 2024 15:35:21 -0700
add GRAPHIC0 charset support
Diffstat:
M | terminal.c | | | 64 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | util.c | | | 4 | +--- |
M | util.h | | | 14 | ++++++++++++-- |
3 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/terminal.c b/terminal.c
@@ -289,6 +289,10 @@ cursor_reset(Term *t)
t->cursor.style.fg = g_colours.data[g_colours.fgidx];
t->cursor.style.bg = g_colours.data[g_colours.bgidx];
t->cursor.style.attr = ATTR_NULL;
+
+ t->cursor.charset_index = 0;
+ for (u32 i = 0; i < ARRAY_COUNT(t->cursor.charsets); i++)
+ t->cursor.charsets[i] = CS_USA;
}
static void
@@ -1049,13 +1053,29 @@ handle_escape(Term *t, s8 *raw, Arena a)
}
}
break;
- case '(': /* GZD4 -- set primary charset G0 */
- case ')': /* G1D4 -- set secondary charset G1 */
- case '*': /* G2D4 -- set tertiary charset G2 */
- case '+': /* G3D4 -- set quaternary charset G3 */
- if (!raw->len) result = 1;
- else get_ascii(raw);
- break;
+ case '(': /* GZD4 -- set primary charset G0 */
+ case ')': /* G1D4 -- set secondary charset G1 */
+ case '*': /* G2D4 -- set tertiary charset G2 */
+ case '+': { /* G3D4 -- set quaternary charset G3 */
+ i32 index = cp - '(';
+ /* TODO: should this really be done here? */
+ if (!raw->len) {
+ result = 1;
+ } else {
+ u32 cs = get_ascii(raw);
+ switch (cs) {
+ case '0': t->cursor.charsets[index] = CS_GRAPHIC0; break;
+ case 'B': t->cursor.charsets[index] = CS_USA; break;
+ default:
+ stream_push_s8(&t->error_stream, s8("unhandled charset: "));
+ stream_push_byte(&t->error_stream, cs);
+ stream_push_byte(&t->error_stream, '\n');
+ os_write_err_msg(stream_to_s8(&t->error_stream));
+ t->error_stream.widx = 0;
+ break;
+ }
+ }
+ } break;
case '=': /* DECPAM -- application keypad */
case '>': /* DECPNM -- normal keypad mode */
/* TODO: MODE_APPKEYPAD */
@@ -1115,6 +1135,10 @@ push_control(Term *t, s8 *line, u32 cp, Arena a)
case '\b':
cursor_move_to(t, t->cursor.pos.y, t->cursor.pos.x - 1);
break;
+ case 0x0E: /* SO (LS1: Locking Shift 1) */
+ case 0x0F: /* SI (LS0: Locking Shift 0) */
+ t->cursor.charset_index = 1 - (cp - 0x0E);
+ break;
default:
stream_push_s8(&t->error_stream, s8("unknown control code: 0x"));
stream_push_hex_u64(&t->error_stream, cp);
@@ -1146,6 +1170,32 @@ push_normal_cp(Term *t, TermView *tv, u32 cp)
width = cg->tile_count;
}
+ /* NOTE: graphic character rxvt extension */
+ /* | 0x41 - 0x7e
+ * "↑", "↓", "→", "←", "█", "▚", "☃", | A - G
+ * 0, 0, 0, 0, 0, 0, 0, 0, | H - O
+ * 0, 0, 0, 0, 0, 0, 0, 0, | P - W
+ * 0, 0, 0, 0, 0, 0, 0, " ", | X - _
+ * "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", | ` - g
+ * "", "␋", "┘", "┐", "┌", "└", "┼", "⎺", | h - o
+ * "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", | p - w
+ * "│", "≤", "≥", "π", "≠", "£", "·", | x - ~
+ */
+ static u16 graphic_0[62] = {
+ 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259A, 0x2603, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x25C6,
+ 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x00B0, 0x00B1, 0x2424,
+ 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, 0x23BB,
+ 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, 0x2502,
+ 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00B7,
+ };
+
+ if (t->cursor.charsets[t->cursor.charset_index] == CS_GRAPHIC0 &&
+ BETWEEN(cp, 0x41, 0x7e) && graphic_0[cp - 0x41])
+ cp = graphic_0[cp - 0x41];
+
/* NOTE: make this '>=' for fun in vis */
if (t->cursor.pos.x + width > t->size.w) {
/* NOTE: make space for character if mode enabled else
diff --git a/util.c b/util.c
@@ -302,10 +302,8 @@ stream_push_hex_u64(Stream *s, u64 n)
*--beg = hex[n & 0x0F];
n >>= 4;
}
- if (beg == end) {
+ while (end - beg < 2)
*--beg = '0';
- *--beg = '0';
- }
stream_push_s8(s, (s8){.len = end - beg, .data = beg});
}
diff --git a/util.h b/util.h
@@ -167,10 +167,15 @@ typedef struct {
u32 attr;
} CellStyle;
-typedef struct {
- iv2 pos;
+typedef __attribute__((aligned(32))) struct {
CellStyle style;
enum cursor_state state;
+ iv2 pos;
+
+ /* NOTE: 4 available charset slots and the selected charset slot to look in.
+ * xterm stores this as part of the cursor so we do here as well. */
+ u32 charset_index;
+ u8 charsets[4];
} Cursor;
typedef Cell *Row;
@@ -486,6 +491,11 @@ enum terminal_mode {
TM_UTF8 = 1 << 4,
};
+enum charsets {
+ CS_USA,
+ CS_GRAPHIC0,
+};
+
typedef struct RenderCtx {
RenderPushBuffer *rpb;
GLCtx *gl;