vtgl

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

Commit: c6d3f5262b88548410a0a49408b605f3021636f7
Parent: 6bfd5ccf1c1e40677b1b5a8d39eff986b75c4d62
Author: Randy Palamar
Date:   Tue, 20 Aug 2024 06:37:22 -0600

basic scrollback support

There are still some things to work out but this is a starting point.

Diffstat:
Mconfig.def.h | 16++++++++++------
Mterminal.c | 5+++--
Mutil.h | 1+
Mvtgl.c | 54+++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -32,7 +32,7 @@ struct { u8 bgidx; } g_colours = {base16_colours, 7, 0}; -#define KEYBIND_FN(name) void name(Term *t, Arg *a) +#define KEYBIND_FN(name) b32 name(Term *t, Arg *a) typedef KEYBIND_FN(KeyBind_Fn); /* NOTE: Bindable Functions */ @@ -49,9 +49,13 @@ struct hotkey { KeyBind_Fn *fn; Arg arg; } g_hotkeys[] = { - {ENCODE_KEY(GLFW_PRESS, MODKEY, GLFW_KEY_V), paste, {0}}, - {ENCODE_KEY(GLFW_PRESS, TERMMOD, GLFW_KEY_MINUS), zoom, {.i = -1}}, - {ENCODE_KEY(GLFW_REPEAT, TERMMOD, GLFW_KEY_MINUS), zoom, {.i = -1}}, - {ENCODE_KEY(GLFW_PRESS, TERMMOD, GLFW_KEY_EQUAL), zoom, {.i = +1}}, - {ENCODE_KEY(GLFW_REPEAT, TERMMOD, GLFW_KEY_EQUAL), zoom, {.i = +1}}, + {ENCODE_KEY(GLFW_PRESS, MODKEY, GLFW_KEY_V), paste, {0}}, + {ENCODE_KEY(GLFW_PRESS, 0, GLFW_KEY_PAGE_UP), scroll, {.i = +3}}, + {ENCODE_KEY(GLFW_REPEAT, 0, GLFW_KEY_PAGE_UP), scroll, {.i = +3}}, + {ENCODE_KEY(GLFW_PRESS, 0, GLFW_KEY_PAGE_DOWN), scroll, {.i = -3}}, + {ENCODE_KEY(GLFW_REPEAT, 0, GLFW_KEY_PAGE_DOWN), scroll, {.i = -3}}, + {ENCODE_KEY(GLFW_PRESS, TERMMOD, GLFW_KEY_MINUS), zoom, {.i = -1}}, + {ENCODE_KEY(GLFW_REPEAT, TERMMOD, GLFW_KEY_MINUS), zoom, {.i = -1}}, + {ENCODE_KEY(GLFW_PRESS, TERMMOD, GLFW_KEY_EQUAL), zoom, {.i = +1}}, + {ENCODE_KEY(GLFW_REPEAT, TERMMOD, GLFW_KEY_EQUAL), zoom, {.i = +1}}, }; diff --git a/terminal.c b/terminal.c @@ -942,9 +942,10 @@ blit_lines(Term *t, Arena a, size line_count) line_count = t->size.h - 1; } + size off = t->scroll_offset; CLAMP(line_count, 0, tv->lines.filled); - for (size i = 0; i <= line_count; i++) { - size line_idx = get_line_idx(&tv->lines, -line_count + i); + for (size idx = -line_count; idx <= 0; idx++) { + size line_idx = get_line_idx(&tv->lines, idx - off); if (line_idx == tv->last_line_idx) t->cursor.pos = tv->last_cursor_pos; tv->last_cursor_pos = t->cursor.pos; diff --git a/util.h b/util.h @@ -291,6 +291,7 @@ typedef struct { Cursor saved_cursors[2]; TermView views[2]; i32 view_idx; + i32 scroll_offset; size unprocessed_bytes; diff --git a/vtgl.c b/vtgl.c @@ -305,6 +305,22 @@ KEYBIND_FN(paste) text.len++; os_child_put_s8(t->child, text); } + return 1; +} + +KEYBIND_FN(scroll) +{ + if (t->mode & TM_ALTSCREEN) + return 0; + + TermView *tv = t->views + t->view_idx; + + t->scroll_offset += a.i; + CLAMP(t->scroll_offset, 0, tv->lines.filled - (t->size.h - 1)); + + t->gl.flags |= NEEDS_FULL_BLIT; + + return 1; } KEYBIND_FN(zoom) @@ -312,6 +328,7 @@ KEYBIND_FN(zoom) shift_font_sizes(&t->fa, a.i); update_font_textures(t); t->gl.flags |= NEEDS_RESIZE; + return 1; } /* NOTE: called when the window was resized */ @@ -360,8 +377,9 @@ key_callback(GLFWwindow *win, i32 key, i32 sc, i32 act, i32 mods) for (u32 i = 0; i < ARRAY_COUNT(g_hotkeys); i++) { struct hotkey *hk = g_hotkeys + i; if (hk->key == enc) { - hk->fn(t, hk->arg); - return; + b32 handled = hk->fn(t, hk->arg); + if (handled) + return; } } @@ -413,9 +431,39 @@ static void char_callback(GLFWwindow *win, u32 codepoint) { Term *t = glfwGetWindowUserPointer(win); + if (t->scroll_offset) { + t->scroll_offset = 0; + t->gl.flags |= NEEDS_FULL_BLIT; + } os_child_put_char(t->child, codepoint); } +static void +scroll_callback(GLFWwindow *win, f64 xoff, f64 yoff) +{ + (void)xoff; + + Term *t = glfwGetWindowUserPointer(win); + if (t->mode & TM_ALTSCREEN) { + b32 left_shift_state = glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + b32 right_shift_state = glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + b32 shift_down = left_shift_state || right_shift_state; + if (yoff > 0) { + if (shift_down) os_child_put_s8(t->child, s8("\x1B[5;2~")); + else os_child_put_s8(t->child, s8("\x19")); + } else { + if (shift_down) os_child_put_s8(t->child, s8("\x1B[6;2~")); + else os_child_put_s8(t->child, s8("\x05")); + } + } else { + Arg a = {.i = (i32)yoff}; + if (glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) || + glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT)) + a.i *= 5; + scroll(t, a); + } +} + DEBUG_EXPORT void init_term(Term *t, Arena *a) { @@ -434,7 +482,7 @@ init_callbacks(GLCtx *gl) glfwSetFramebufferSizeCallback(gl->window, fb_callback); glfwSetKeyCallback(gl->window, key_callback); //glfwSetWindowRefreshCallback(gl->window, refresh_callback); - //glfwSetScrollCallback(gl->window, scroll_callback); + glfwSetScrollCallback(gl->window, scroll_callback); } DEBUG_EXPORT void