mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
csi: implement DECOM - switch cursor origin between absolute and relative
The default is absolute mode, where 0,0 is the upper left corner of the screen. In relative mode, the origin is relative the top scroll margin. Internally, we always track the current cursor position in absolute mode. Every time we the client *sets* or *queries* the cursor position in relative mode, we translate it to absolute.
This commit is contained in:
parent
89dbc61a34
commit
95eaad7ce4
3 changed files with 64 additions and 14 deletions
40
csi.c
40
csi.c
|
|
@ -330,8 +330,9 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
case 'd': {
|
||||
/* VPA - vertical line position absolute */
|
||||
int row = min(vt_param_get(term, 0, 1), term->rows);
|
||||
term_cursor_to(term, row - 1, term->cursor.col);
|
||||
struct coord new_cursor = term_cursor_rel_to_abs(
|
||||
term, vt_param_get(term, 0, 1) - 1, term->cursor.col);
|
||||
term_cursor_to(term, new_cursor.row, new_cursor.col);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -358,17 +359,20 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
case 'G': {
|
||||
/* Cursor horizontal absolute */
|
||||
int col = min(vt_param_get(term, 0, 1), term->cols);
|
||||
term_cursor_to(term, term->cursor.row, col - 1);
|
||||
struct coord new_cursor = term_cursor_rel_to_abs(
|
||||
term, term->cursor.row, vt_param_get(term, 0, 1) - 1);
|
||||
term_cursor_to(term, new_cursor.row, new_cursor.col);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
case 'H': {
|
||||
/* Move cursor */
|
||||
int row = min(vt_param_get(term, 0, 1), term->rows);
|
||||
int col = min(vt_param_get(term, 1, 1), term->cols);
|
||||
term_cursor_to(term, row - 1, col - 1);
|
||||
struct coord new_cursor = term_cursor_rel_to_abs(
|
||||
term,
|
||||
vt_param_get(term, 0, 1) - 1,
|
||||
vt_param_get(term, 1, 1) - 1);
|
||||
term_cursor_to(term, new_cursor.row, new_cursor.col);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -623,8 +627,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
/* 1-based */
|
||||
term->scroll_region.start = start - 1;
|
||||
term->scroll_region.end = end;
|
||||
|
||||
term_cursor_to(term, start - 1, 0);
|
||||
term_cursor_home(term);
|
||||
|
||||
LOG_DBG("scroll region: %d-%d",
|
||||
term->scroll_region.start,
|
||||
|
|
@ -684,13 +687,17 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
switch (param) {
|
||||
case 6: {
|
||||
/* u7 - cursor position query */
|
||||
|
||||
int row = term->origin == ORIGIN_ABSOLUTE
|
||||
? term->cursor.row
|
||||
: term->cursor.row - term->scroll_region.start;
|
||||
|
||||
/* TODO: we use 0-based position, while the xterm
|
||||
* terminfo says the receiver of the reply should
|
||||
* decrement, hence we must add 1 */
|
||||
char reply[64];
|
||||
snprintf(reply, sizeof(reply), "\x1b[%d;%dR",
|
||||
term->cursor.row + 1,
|
||||
term->cursor.col + 1);
|
||||
row + 1, term->cursor.col + 1);
|
||||
term_to_slave(term, reply, strlen(reply));
|
||||
break;
|
||||
}
|
||||
|
|
@ -729,6 +736,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
term,
|
||||
&(struct coord){0, 0},
|
||||
&(struct coord){term->cols - 1, term->rows - 1});
|
||||
term_cursor_home(term);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
|
@ -736,6 +744,12 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
term_damage_all(term);
|
||||
break;
|
||||
|
||||
case 6: { /* DECOM */
|
||||
term->origin = ORIGIN_RELATIVE;
|
||||
term_cursor_home(term);
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
term->auto_margin = true;
|
||||
break;
|
||||
|
|
@ -839,6 +853,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
term,
|
||||
&(struct coord){0, 0},
|
||||
&(struct coord){term->cols - 1, term->rows - 1});
|
||||
term_cursor_home(term);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
|
@ -853,8 +868,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
case 6: { /* DECOM */
|
||||
term->origin = ORIGIN_ABSOLUTE;
|
||||
struct coord new_home = term_cursor_rel_to_abs(term, 0, 0);
|
||||
term_cursor_to(term, new_home.row, new_home.col);
|
||||
term_cursor_home(term);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
32
terminal.c
32
terminal.c
|
|
@ -486,6 +486,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
|||
},
|
||||
.alpha = conf->colors.alpha,
|
||||
},
|
||||
.origin = ORIGIN_ABSOLUTE,
|
||||
.default_cursor_style = conf->cursor.style,
|
||||
.cursor_style = conf->cursor.style,
|
||||
.default_cursor_color = {
|
||||
|
|
@ -991,6 +992,30 @@ term_erase(struct terminal *term, const struct coord *start, const struct coord
|
|||
erase_cell_range(term, grid_row(term->grid, end->row), 0, end->col);
|
||||
}
|
||||
|
||||
struct coord
|
||||
term_cursor_rel_to_abs(const struct terminal *term, int row, int col)
|
||||
{
|
||||
switch (term->origin) {
|
||||
case ORIGIN_ABSOLUTE:
|
||||
return (struct coord) {
|
||||
.col = min(col, term->cols - 1),
|
||||
.row = min(row, term->rows - 1),
|
||||
};
|
||||
break;
|
||||
|
||||
case ORIGIN_RELATIVE: {
|
||||
return (struct coord) {
|
||||
.col = min(col, term->cols - 1),
|
||||
.row = min(row + term->scroll_region.start, term->rows - 1),
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return (struct coord){-1, -1};
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_to(struct terminal *term, int row, int col)
|
||||
{
|
||||
|
|
@ -1005,6 +1030,13 @@ term_cursor_to(struct terminal *term, int row, int col)
|
|||
term->grid->cur_row = grid_row(term->grid, row);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_home(struct terminal *term)
|
||||
{
|
||||
struct coord new_cursor = term_cursor_rel_to_abs(term, 0, 0);
|
||||
term_cursor_to(term, new_cursor.row, new_cursor.col);
|
||||
}
|
||||
|
||||
void
|
||||
term_cursor_left(struct terminal *term, int count)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ struct vt {
|
|||
struct attributes saved_attrs;
|
||||
};
|
||||
|
||||
enum cursor_keys { CURSOR_KEYS_DONTCARE, CURSOR_KEYS_NORMAL, CURSOR_KEYS_APPLICATION};
|
||||
enum cursor_origin { ORIGIN_ABSOLUTE, ORIGIN_RELATIVE };
|
||||
enum cursor_keys { CURSOR_KEYS_DONTCARE, CURSOR_KEYS_NORMAL, CURSOR_KEYS_APPLICATION };
|
||||
enum keypad_keys { KEYPAD_DONTCARE, KEYPAD_NUMERICAL, KEYPAD_APPLICATION };
|
||||
enum charset { CHARSET_ASCII, CHARSET_GRAPHIC };
|
||||
|
||||
|
|
@ -214,6 +215,7 @@ struct terminal {
|
|||
uint32_t default_table[256];
|
||||
} colors;
|
||||
|
||||
enum cursor_origin origin;
|
||||
struct coord cursor;
|
||||
struct coord saved_cursor;
|
||||
struct coord alt_saved_cursor;
|
||||
|
|
@ -328,6 +330,8 @@ void term_damage_scroll(
|
|||
void term_erase(
|
||||
struct terminal *term, const struct coord *start, const struct coord *end);
|
||||
|
||||
struct coord term_cursor_rel_to_abs(const struct terminal *term, int row, int col);
|
||||
void term_cursor_home(struct terminal *term);
|
||||
void term_cursor_to(struct terminal *term, int row, int col);
|
||||
void term_cursor_left(struct terminal *term, int count);
|
||||
void term_cursor_right(struct terminal *term, int count);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue