Commit: 7691b8a01f9d841cd1c9ac0d66aa0aa37b385df4
Parent: d8353baac949359f4b4a29985b9719320658222c
Author: Randy Palamar
Date: Sun, 25 Aug 2024 15:24:35 -0600
csi scrolling region support
Diffstat:
M | terminal.c | | | 56 | +++++++++++++++++++++++++++++++++++++++----------------- |
M | util.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;