Commit: fdcd02004956cbc600ecf952a5a19c9fe6a23cdb
Parent: 6554a03245002e17fcad62279eccf79c5ae1fdb4
Author: Randy Palamar
Date: Sun, 1 Sep 2024 13:36:05 -0600
support DECOM (cursor origin mode)
Diffstat:
M | terminal.c | | | 67 | +++++++++++++++++++++++++++++++++++++++++++------------------------ |
M | util.h | | | 3 | ++- |
2 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/terminal.c b/terminal.c
@@ -235,12 +235,25 @@ cursor_reset(Term *t)
static void
cursor_move_to(Term *t, i32 row, i32 col)
{
- t->cursor.pos.y = CLAMP(row, 0, t->size.h - 1);
+ i32 minr = 0, maxr = t->size.h - 1;
+ if (t->cursor.state & CURSOR_ORIGIN) {
+ minr = t->top;
+ maxr = t->bot;
+ }
+ t->cursor.pos.y = CLAMP(row, minr, maxr);
t->cursor.pos.x = CLAMP(col, 0, t->size.w - 1);
t->cursor.state &= ~CURSOR_WRAP_NEXT;
}
static void
+cursor_move_abs_to(Term *t, i32 row, i32 col)
+{
+ if (t->cursor.state & CURSOR_ORIGIN)
+ row += t->top;
+ cursor_move_to(t, row, col);
+}
+
+static void
cursor_alt(Term *t, b32 save)
{
i32 mode = t->view_idx;
@@ -404,6 +417,11 @@ set_mode(Term *t, CSI *csi, b32 set)
if (set) t->gl.mode |= WIN_MODE_APPCURSOR;
else t->gl.mode &= ~WIN_MODE_APPCURSOR;
break;
+ case PRIV(6): /* DECOM: Cursor Origin Mode */
+ if (set) t->cursor.state |= CURSOR_ORIGIN;
+ else t->cursor.state &= ~CURSOR_ORIGIN;
+ cursor_move_abs_to(t, 0, 0);
+ break;
case PRIV(7): /* DECAWM: Auto-Wrap Mode */
if (set) t->mode |= TM_AUTO_WRAP;
else t->mode &= ~TM_AUTO_WRAP;
@@ -688,33 +706,34 @@ handle_csi(Term *t, CSI *csi)
u8 next;
switch (csi->mode) {
- case 'A': cursor_step_raw(t, ORONE(csi->argv[0]), -1, 0); break;
- case 'B': cursor_step_raw(t, ORONE(csi->argv[0]), 1, 0); break;
- case 'C': cursor_step_raw(t, ORONE(csi->argv[0]), 0, 1); break;
- case 'D': cursor_step_raw(t, ORONE(csi->argv[0]), 0, -1); break;
- case 'E': cursor_move_to(t, p.y + ORONE(csi->argv[0]), 0); break;
- case 'F': cursor_move_to(t, p.y - ORONE(csi->argv[0]), 0); break;
- case 'G': cursor_move_to(t, p.y, csi->argv[0] - 1); 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 'L': insert_blank_lines(t, ORONE(csi->argv[0])); break;
- case 'M': erase_lines(t, ORONE(csi->argv[0])); break;
- case 'P': erase_characters(t, ORONE(csi->argv[0])); break;
- case 'X': erase_characters(t, ORONE(csi->argv[0])); break;
- case 'T': insert_blank_lines(t, ORONE(csi->argv[0])); break;
- case 'Z': push_tab(t, -(ORONE(csi->argv[0]))); break;
- case 'a': cursor_step_raw(t, ORONE(csi->argv[0]), 0, 1); break;
- case 'd': cursor_move_to(t, csi->argv[0] - 1, p.x); break;
- case 'e': cursor_step_raw(t, ORONE(csi->argv[0]), 1, 0); break;
- case 'f': cursor_move_to(t, csi->argv[0] - 1, csi->argv[1] - 1); 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 'A': cursor_step_raw(t, ORONE(csi->argv[0]), -1, 0); break;
+ case 'B': cursor_step_raw(t, ORONE(csi->argv[0]), 1, 0); break;
+ case 'C': cursor_step_raw(t, ORONE(csi->argv[0]), 0, 1); break;
+ case 'D': cursor_step_raw(t, ORONE(csi->argv[0]), 0, -1); break;
+ case 'E': cursor_move_to(t, p.y + ORONE(csi->argv[0]), 0); break;
+ case 'F': cursor_move_to(t, p.y - ORONE(csi->argv[0]), 0); break;
+ case 'G': cursor_move_to(t, p.y, csi->argv[0] - 1); break;
+ case 'H': cursor_move_abs_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 'L': insert_blank_lines(t, ORONE(csi->argv[0])); break;
+ case 'M': erase_lines(t, ORONE(csi->argv[0])); break;
+ case 'P': erase_characters(t, ORONE(csi->argv[0])); break;
+ case 'X': erase_characters(t, ORONE(csi->argv[0])); break;
+ case 'T': insert_blank_lines(t, ORONE(csi->argv[0])); break;
+ case 'Z': push_tab(t, -(ORONE(csi->argv[0]))); break;
+ case 'a': cursor_step_raw(t, ORONE(csi->argv[0]), 0, 1); break;
+ case 'd': cursor_move_abs_to(t, csi->argv[0] - 1, p.x); break;
+ case 'e': cursor_step_raw(t, ORONE(csi->argv[0]), 1, 0); break;
+ case 'f': cursor_move_abs_to(t, csi->argv[0] - 1, csi->argv[1] - 1); 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 'r':
if (csi->priv)
goto unknown;
set_scrolling_region(t, csi);
+ cursor_move_abs_to(t, 0, 0);
break;
case 't': window_manipulation(t, csi); break;
case '!':
diff --git a/util.h b/util.h
@@ -123,7 +123,8 @@ typedef struct {
enum cursor_state {
CURSOR_NORMAL = 0 << 0,
- CURSOR_WRAP_NEXT = 1 << 1,
+ CURSOR_WRAP_NEXT = 1 << 0,
+ CURSOR_ORIGIN = 1 << 1,
};
typedef struct {