Commit: 5396fbf72d4e7ed0384f542a8e4a34b61514b015
Parent: b9f18b0baef0e92d2f6cc1e96fbc2b7782559ca2
Author: Randy Palamar
Date: Sat, 6 Jul 2024 15:29:58 -0600
handle escapes through a different path when splitting raw input
The raw input path shouldn't be able to draw to the fb (via
clear_fb_region or otherwise).
Diffstat:
M | terminal.c | | | 96 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- |
1 file changed, 71 insertions(+), 25 deletions(-)
diff --git a/terminal.c b/terminal.c
@@ -103,8 +103,9 @@ static void
fb_scroll_down(Term *t, u32 top, u32 n)
{
// TODO: CLAMP?
- fb_clear_region(t, t->size.h - 1 - (n - 1), t->size.h - 1, 0, t->size.w);
- for (u32 i = t->size.h - 1; i >= top + n; i--) {
+ 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--) {
Row tmp = t->fb.rows[i];
t->fb.rows[i] = t->fb.rows[i - n];
t->fb.rows[i - n] = tmp;
@@ -115,8 +116,9 @@ static void
fb_scroll_up(Term *t, u32 top, u32 n)
{
// TODO: CLAMP?
+ u32 bottom = t->size.h - 1;
fb_clear_region(t, top, top + n - 1, 0, t->size.w);
- for (u32 i = top; i < t->size.h - n; i++) {
+ for (u32 i = top; i <= bottom - n; i++) {
Row tmp = t->fb.rows[i];
t->fb.rows[i] = t->fb.rows[i + n];
t->fb.rows[i + n] = tmp;
@@ -330,8 +332,9 @@ parse_csi(s8 *r)
return csi;
}
}
- /* TODO: error case: needs more chars! */
- ASSERT(0);
+
+ /* NOTE: Needs more characters! */
+ csi.argc = -1;
return csi;
}
@@ -339,30 +342,25 @@ static void
handle_csi(Term *t, s8 *raw)
{
CSI csi = parse_csi(raw);
+ ASSERT(csi.argc != -1);
switch (csi.mode) {
- case 'H': cursor_move_to(t, csi.argv[0], csi.argv[1]); break;
- case 'J': erase_in_display(t, &csi); break;
- case 'K': erase_in_line(t, &csi); break;
- case 'h': set_mode(t, &csi, 1); break;
- case 'l': set_mode(t, &csi, 0); break;
- case 'm': set_colours(t, &csi); break;
- case 't': window_manipulation(t, &csi); break;
+ case 'H': cursor_move_to(t, csi.argv[0] - 1, csi.argv[1] - 1); break;
+ case 'J': erase_in_display(t, &csi); break;
+ case 'K': erase_in_line(t, &csi); break;
+ case 'h': set_mode(t, &csi, 1); break;
+ case 'l': set_mode(t, &csi, 0); break;
+ case 'm': set_colours(t, &csi); break;
+ case 't': window_manipulation(t, &csi); break;
default:
fputs("unknown csi: ", stderr);
dump_csi(&csi);
}
}
-enum handle_escape_return {
- HESC_NORMAL_RETURN,
- HESC_NEEDS_MORE_BYTES,
- HESC_CURSOR_MOVED,
-};
-static enum handle_escape_return
+static void
handle_escape(Term *t, s8 *raw)
{
- enum handle_escape_return result = HESC_NORMAL_RETURN;
u32 cp = get_ascii(raw);
switch(cp) {
case '[': handle_csi(t, raw); break;
@@ -382,13 +380,61 @@ handle_escape(Term *t, s8 *raw)
fb_scroll_down(t, 0, 1);
} else {
cursor_move_to(t, t->cursor.row - 1, t->cursor.col);
- result = HESC_CURSOR_MOVED;
}
break;
default:
fprintf(stderr, "unknown escape sequence: ESC %c (0x%02x)\n", cp, cp);
break;
}
+}
+
+enum escape_moves_cursor_result {
+ EMC_NORMAL_RETURN,
+ EMC_NEEDS_MORE_BYTES,
+ EMC_CURSOR_MOVED,
+};
+
+static enum escape_moves_cursor_result
+check_if_csi_moves_cursor(Term *t, s8 *raw)
+{
+ enum escape_moves_cursor_result result = EMC_NORMAL_RETURN;
+ CSI csi = parse_csi(raw);
+
+ if (csi.argc == -1)
+ return EMC_NEEDS_MORE_BYTES;
+
+ switch (csi.mode) {
+ case 'H': result = EMC_CURSOR_MOVED; break;
+ case 'h': set_mode(t, &csi, 1); break;
+ case 'l': set_mode(t, &csi, 0); break;
+ default: break;
+ }
+
+ return result;
+}
+
+static enum escape_moves_cursor_result
+check_if_escape_moves_cursor(Term *t, s8 *raw)
+{
+ enum escape_moves_cursor_result result = EMC_NORMAL_RETURN;
+ u32 cp = get_ascii(raw);
+ switch(cp) {
+ case '[':
+ result = check_if_csi_moves_cursor(t, raw);
+ break;
+ case '(': /* GZD4 -- set primary charset G0 */
+ case ')': /* G1D4 -- set secondary charset G1 */
+ case '*': /* G2D4 -- set tertiary charset G2 */
+ case '+': /* G3D4 -- set quaternary charset G3 */
+ case '%': /* utf-8 mode */
+ get_ascii(raw);
+ break;
+ case 'M': /* RI -- Reverse Index */
+ if (t->cursor.row != 0)
+ result = EMC_CURSOR_MOVED;
+ break;
+ default: break;
+ }
return result;
}
@@ -434,11 +480,11 @@ split_raw_input_to_lines(Term *t, s8 raw)
if (peek(raw, 0) == 0x1B) {
s8 old = raw;
raw = consume(raw, 1);
- switch (handle_escape(t, &raw)) {
- case HESC_NEEDS_MORE_BYTES:
+ switch (check_if_escape_moves_cursor(t, &raw)) {
+ case EMC_NEEDS_MORE_BYTES:
t->unprocessed_bytes = old.len;
return parsed_lines;
- case HESC_CURSOR_MOVED:
+ case EMC_CURSOR_MOVED:
parsed_lines++;
feed_line(lb, old.data, t->cursor.state);
break;
@@ -478,7 +524,7 @@ static void
push_newline(Term *t)
{
t->cursor.row++;
- if (t->cursor.row >= t->size.h) {
+ if (t->cursor.row == t->size.h) {
t->cursor.row = t->size.h - 1;
fb_scroll_up(t, 0, 1);
}
@@ -488,7 +534,7 @@ static void
push_tab(Term *t)
{
u32 col = t->cursor.col;
- u32 advance = g_tabstop - col % g_tabstop;
+ u32 advance = g_tabstop - (col % g_tabstop);
fb_clear_region(t, t->cursor.row, t->cursor.row, t->cursor.col, t->cursor.col + advance);
cursor_step_column(t, advance);
}