vtgl

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

Commit: 7691b8a01f9d841cd1c9ac0d66aa0aa37b385df4
Parent: d8353baac949359f4b4a29985b9719320658222c
Author: Randy Palamar
Date:   Sun, 25 Aug 2024 15:24:35 -0600

csi scrolling region support

Diffstat:
Mterminal.c | 56+++++++++++++++++++++++++++++++++++++++-----------------
Mutil.h | 2++
2 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/terminal.c b/terminal.c @@ -131,15 +131,15 @@ selection_scroll(Term *t, u32 origin, i32 n) if (!is_valid_range(s->range)) return; - b32 start_in_bounds = BETWEEN(s->range.start.y, origin, t->size.h - 1); - b32 end_in_bounds = BETWEEN(s->range.end.y, origin, t->size.h - 1); + b32 start_in_bounds = BETWEEN(s->range.start.y, origin, t->bot); + b32 end_in_bounds = BETWEEN(s->range.end.y, origin, t->bot); if (start_in_bounds != end_in_bounds) { selection_clear(s); } else if (start_in_bounds) { s->range.start.y += n; s->range.end.y += n; - if (s->range.start.y > t->size.h - 1 || s->range.start.y < 0 || - s->range.end.y > t->size.h - 1 || s->range.end.y < 0) + if (s->range.start.y > t->bot || s->range.start.y < t->top || + s->range.end.y > t->bot || s->range.end.y < t->top) selection_clear(s); } } @@ -190,10 +190,9 @@ static void fb_scroll_down(Term *t, u32 top, u32 n) { TermView *tv = t->views + t->view_idx; - // TODO: CLAMP? - u32 bottom = t->size.h - 1; - fb_clear_region(t, bottom - n + 1, bottom, 0, t->size.w); - for (u32 i = bottom; i >= top + n; i--) { + CLAMP(n, 0, t->bot - top + 1); + fb_clear_region(t, t->bot - n + 1, t->bot, 0, t->size.w); + for (u32 i = t->bot; i >= top + n; i--) { Row tmp = tv->fb.rows[i]; tv->fb.rows[i] = tv->fb.rows[i - n]; tv->fb.rows[i - n] = tmp; @@ -205,10 +204,9 @@ static void fb_scroll_up(Term *t, u32 top, u32 n) { TermView *tv = t->views + t->view_idx; - // TODO: CLAMP? - u32 bottom = t->size.h - 1; + CLAMP(n, 0, t->bot - top + 1); fb_clear_region(t, top, top + n - 1, 0, t->size.w); - for (u32 i = top; i <= bottom - n; i++) { + for (u32 i = top; i <= t->bot - n; i++) { Row tmp = tv->fb.rows[i]; tv->fb.rows[i] = tv->fb.rows[i + n]; tv->fb.rows[i + n] = tmp; @@ -264,7 +262,7 @@ cursor_step_column(Term *t, i32 n) row++; col = 0; if (row >= t->size.h) - fb_scroll_up(t, 0, 1); + fb_scroll_up(t, t->top, 1); } cursor_move_to(t, row, col); } @@ -289,6 +287,8 @@ term_reset(Term *t) swap_screen(t); fb_clear_region(t, 0, t->size.h, 0, t->size.w); } + 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; } @@ -570,6 +570,20 @@ set_colours(Term *t, CSI *csi) } static void +set_scrolling_region(Term *t, CSI *csi) +{ + t->top = csi->argv[0]? csi->argv[0] : 0; + t->bot = csi->argv[1]? csi->argv[1] : t->size.h - 1; + CLAMP(t->top, 0, t->size.h - 1); + CLAMP(t->bot, 0, t->size.h - 1); + if (t->top > t->bot) { + i32 tmp = t->top; + t->top = t->bot; + t->bot = tmp; + } +} + +static void window_manipulation(Term *t, CSI *csi) { const char *s; @@ -592,9 +606,11 @@ window_manipulation(Term *t, CSI *csi) static void push_newline(Term *t, b32 move_to_first_col) { - i32 row = t->cursor.pos.y + 1; - if (row == t->size.h) - fb_scroll_up(t, 0, 1); + i32 row = t->cursor.pos.y; + if (row == t->bot) + fb_scroll_up(t, t->top, 1); + else + row++; cursor_move_to(t, row, move_to_first_col? 0 : t->cursor.pos.x); } @@ -673,6 +689,11 @@ handle_csi(Term *t, s8 *raw) case 'h': set_mode(t, &csi, 1); break; case 'l': set_mode(t, &csi, 0); break; case 'm': set_colours(t, &csi); break; + case 'r': + if (csi.priv) + goto unknown; + set_scrolling_region(t, &csi); + break; case 't': window_manipulation(t, &csi); break; case '!': next = get_ascii(raw); @@ -682,6 +703,7 @@ handle_csi(Term *t, s8 *raw) } /* FALLTHROUGH */ default: + unknown: fputs("unknown csi: ", stderr); dump_csi(&csi); } @@ -793,8 +815,8 @@ handle_escape(Term *t, s8 *raw, Arena a) push_newline(t, 1); break; case 'M': /* RI -- Reverse Index */ - if (t->cursor.pos.y == 0) { - fb_scroll_down(t, 0, 1); + if (t->cursor.pos.y == t->top) { + fb_scroll_down(t, t->top, 1); } else { cursor_move_to(t, t->cursor.pos.y - 1, t->cursor.pos.x); } diff --git a/util.h b/util.h @@ -355,6 +355,8 @@ typedef struct { os_child child; uv2 size; + /* NOTE: scrolling region */ + u32 top, bot; enum terminal_mode mode;