vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 9bb775b76c7d37fa7ac446de2962846393119d27
Parent: ca530c87fdb664a63b74100be963687d498772eb
Author: Randy Palamar
Date:   Sat, 16 Nov 2024 15:35:21 -0700

add GRAPHIC0 charset support

Diffstat:
Mterminal.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mutil.c | 4+---
Mutil.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;