Commit: 0b2029e8c1e0a921d674643938032ad7965740f7
Parent: fa47b8d2a6a4a13ae11edec23f8fe8e193d20f99
Author: Randy Palamar
Date: Tue, 25 Jun 2024 21:26:10 -0600
add basic cursor wrapping and screen clearing
Diffstat:
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');