vtgl

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

Commit: 0b2029e8c1e0a921d674643938032ad7965740f7
Parent: fa47b8d2a6a4a13ae11edec23f8fe8e193d20f99
Author: Randy Palamar
Date:   Tue, 25 Jun 2024 21:26:10 -0600

add basic cursor wrapping and screen clearing

Diffstat:
Mmain.c | 4+++-
Mterminal.c | 39++++++++++++++++++++++++++++++++++++++-
Mutil.h | 4++--
Mvtgl.c | 21+++++++++++++++------
4 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/main.c b/main.c @@ -96,7 +96,9 @@ init_window(Term *t) die("Failed to get GLFW monitor\n"); } - glfwGetMonitorWorkarea(mon, NULL, NULL, &t->gl.window_size.w, &t->gl.window_size.h); + iv2 ws; + glfwGetMonitorWorkarea(mon, NULL, NULL, &ws.w, &ws.h); + t->gl.window_size = (v2){.w = ws.w, .h = ws.h}; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); diff --git a/terminal.c b/terminal.c @@ -88,6 +88,20 @@ cursor_move_to(Term *t, i32 row, i32 col) } static void +cursor_step_column(Term *t, i32 step) +{ + t->cursor.col += step; + if (t->cursor.col < t->size.w) + return; + t->cursor.col = 0; + t->cursor.row++; + if (t->cursor.row < t->size.h) + return; + t->cursor.row = t->size.h - 1; + /* TODO: scroll term up by a line */ +} + +static void dump_csi(CSI *csi) { fputs("raw: ESC[", stderr); @@ -113,6 +127,27 @@ dump_csi(CSI *csi) fputs(" } }\n", stderr); } +static void +erase_in_display(Term *t, CSI *csi) +{ + switch(csi->argv[0]) { + case 0: /* Erase Below (default) */ + /* TODO: can we actually ignore this? */ + break; + case 1: /* Erase Above */ + t->gl.flags |= DISCARD_BUFFER; + break; + case 2: /* Erase All */ + t->gl.flags |= DISCARD_BUFFER; + break; + case 3: /* Erase Saved Lines (xterm) */ + /* NOTE: ignored; we don't save lines in the way xterm does */ + break; + default: ASSERT(0); break; + } +} + + /* SGR: Select Graphic Rendition */ static void set_colours(Term *t, CSI *csi) @@ -178,7 +213,9 @@ handle_csi(Term *t, s8 *raw) CSI csi = parse_csi(raw); switch (csi.mode) { - case 'm': set_colours(t, &csi); break; + case 'm': set_colours(t, &csi); break; + case 'H': cursor_move_to(t, csi.argv[0], csi.argv[1]); break; + case 'J': erase_in_display(t, &csi); break; default: fputs("unknown csi: ", stderr); dump_csi(&csi); diff --git a/util.h b/util.h @@ -129,7 +129,7 @@ typedef struct { enum gl_flags { NEEDS_RESIZE = 1 << 0, - NEEDS_BLIT = 1 << 1, + DISCARD_BUFFER = 1 << 1, UPDATE_UNIFORMS = 1 << 30, }; @@ -142,7 +142,7 @@ typedef struct { typedef struct { GLFWwindow *window; - iv2 window_size; + v2 window_size; f32 dt; diff --git a/vtgl.c b/vtgl.c @@ -32,7 +32,7 @@ clear_colour(void) static void resize(GLCtx *gl) { - iv2 ws = gl->window_size; + v2 ws = gl->window_size; glViewport(0, 0, ws.w, ws.h); f32 pmat[4 * 4] = { 2.0 / ws.w, 0.0, 0.0, -1.0, @@ -196,10 +196,9 @@ line_to_s8(Line *l) static void push_tab(Term *t) { - u32 col = t->cursor.col; - u32 advance = g_tabstop - col % g_tabstop; - t->cursor.col += advance; - /* TODO: wrap cursor if it goes of edge of terminal */ + u32 col = t->cursor.col; + u32 advance = g_tabstop - col % g_tabstop; + cursor_step_column(t, advance); } static void @@ -226,9 +225,15 @@ push_line(Term *t, Line *line, v2 start_pos) /* TODO properly make characters are printable */ CLAMP(cp, ' ', '~'); cr.pos.w = cs.w * t->cursor.col; + cr.pos.h = t->gl.window_size.h - (t->cursor.row + 1) * cs.h; push_cell(t, cp, cr, t->cursor.state.bg.rgba, t->cursor.state.fg.rgba); /* TODO: properly advance cursor */ - t->cursor.col++; + cursor_step_column(t, 1); + } + + if (t->gl.flags & DISCARD_BUFFER) { + t->gl.flags &= ~DISCARD_BUFFER; + clear_colour(); } } } @@ -280,6 +285,10 @@ key_callback(GLFWwindow *win, i32 key, i32 sc, i32 act, i32 mods) case ENCODE_KEY(GLFW_REPEAT, 0, GLFW_KEY_ESCAPE): glfwSetWindowShouldClose(win, GL_TRUE); break; + case ENCODE_KEY(GLFW_PRESS, 0, GLFW_KEY_TAB): + case ENCODE_KEY(GLFW_REPEAT, 0, GLFW_KEY_TAB): + os_child_put_char(t->child, '\t'); + break; case ENCODE_KEY(GLFW_PRESS, 0, GLFW_KEY_ENTER): case ENCODE_KEY(GLFW_REPEAT, 0, GLFW_KEY_ENTER): os_child_put_char(t->child, '\r');