vtgl

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

Commit: ca530c87fdb664a63b74100be963687d498772eb
Parent: 9d6b945e72e4b3523cac1452d7f567abea8454d6
Author: Randy Palamar
Date:   Sat, 16 Nov 2024 13:37:55 -0700

add provisions for C1 control codes

we will see if these ever show up in practice but for now we will
at least print some info if we see one.

Diffstat:
Mterminal.c | 43++++++++++++++++++++++++++++++++-----------
Mutil.h | 4+++-
2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/terminal.c b/terminal.c @@ -407,7 +407,7 @@ term_reset(Term *t) t->top = 0; t->bot = t->size.h - 1; /* TODO: why is term_reset() being called when we are in the altscreen */ - t->mode = mode|TM_AUTO_WRAP; + t->mode = mode|TM_AUTO_WRAP|TM_UTF8; } static void @@ -1038,11 +1038,21 @@ handle_escape(Term *t, s8 *raw, Arena a) switch (cp) { case '[': reset_csi(&t->csi, raw); t->escape |= EM_CSI; break; case ']': handle_osc(t, raw, a); break; + case '%': /* utf-8 mode */ + /* TODO: should this really be done here? */ + if (!raw->len) { + result = 1; + } else { + switch (get_ascii(raw)) { + case 'G': t->mode |= TM_UTF8; break; + case '@': t->mode &= ~TM_UTF8; break; + } + } + 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 */ - case '%': /* utf-8 mode */ if (!raw->len) result = 1; else get_ascii(raw); break; @@ -1105,6 +1115,13 @@ 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; + default: + stream_push_s8(&t->error_stream, s8("unknown control code: 0x")); + stream_push_hex_u64(&t->error_stream, cp); + stream_push_byte(&t->error_stream, '\n'); + os_write_err_msg(stream_to_s8(&t->error_stream)); + t->error_stream.widx = 0; + break; } if (cp != 0x1B) { if (t->escape & EM_CSI) t->csi.raw.len++; @@ -1181,7 +1198,8 @@ push_line(Term *t, Line *line, Arena a) ASSERT(cp != (u32)-1); if (ISCONTROL(cp)) { - push_control(t, &l, cp, a); + if (!(t->mode & TM_UTF8) || !ISCONTROLC1(cp)) + push_control(t, &l, cp, a); continue; } else if (t->escape & EM_CSI) { t->csi.raw.len++; @@ -1242,7 +1260,9 @@ handle_input(Term *t, Arena a, s8 raw) while (raw.len) { size start_len = raw.len; u32 cp = peek(raw, 0); - if (cp & 0x80) { + /* TODO: this could be a performance issue; may need seperate code path for + * terminal when not in UTF8 mode */ + if (cp > 0x7F && (t->mode & TM_UTF8)) { cp = get_utf8(&raw); tv->lines.buf[tv->lines.widx].has_unicode = 1; if (cp == (u32)-1) { @@ -1257,14 +1277,15 @@ handle_input(Term *t, Arena a, s8 raw) ASSERT(cp != (u32)-1); if (ISCONTROL(cp)) { - i32 old_curs_y = t->cursor.pos.y; - if (push_control(t, &raw, cp, a)) { - raw.len = start_len; - goto end; + if (!(t->mode & TM_UTF8) || !ISCONTROLC1(cp)) { + i32 old_curs_y = t->cursor.pos.y; + if (push_control(t, &raw, cp, a)) { + raw.len = start_len; + goto end; + } + if (!t->escape && (cp == '\n' || t->cursor.pos.y != old_curs_y)) + feed_line(&tv->lines, raw.data, t->cursor.style); } - if (!t->escape && (cp == '\n' || t->cursor.pos.y != old_curs_y)) - feed_line(&tv->lines, raw.data, t->cursor.style); - continue; } else if (t->escape & EM_CSI) { t->csi.raw.len++; diff --git a/util.h b/util.h @@ -34,7 +34,8 @@ #define SAFE_RATIO_1(a, b) ((b) ? (a) / (b) : (a)) #define ISCONTROLC0(c) (BETWEEN((c), 0, 0x1F) || (c) == 0x7F) -#define ISCONTROL(c) (ISCONTROLC0(c)) +#define ISCONTROLC1(c) (BETWEEN((c), 0x80, 0x9F)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\t') #define ISPRINT(c) BETWEEN((c), ' ', '~') @@ -482,6 +483,7 @@ enum terminal_mode { TM_REPLACE = 1 << 1, TM_AUTO_WRAP = 1 << 2, TM_CRLF = 1 << 3, + TM_UTF8 = 1 << 4, }; typedef struct RenderCtx {