terminal: move cursor from grid to terminal

This commit is contained in:
Daniel Eklöf 2019-06-29 21:15:32 +02:00
parent 8723098cda
commit a8f4cb55af
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 61 additions and 66 deletions

56
csi.c
View file

@ -297,7 +297,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
if (row > term->rows) if (row > term->rows)
row = term->rows; row = term->rows;
term_cursor_to(term, row - 1, term->grid.cursor.col); term_cursor_to(term, row - 1, term->cursor.col);
break; break;
} }
@ -328,7 +328,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
if (col > term->cols) if (col > term->cols)
col = term->cols; col = term->cols;
term_cursor_to(term, term->grid.cursor.row, col); term_cursor_to(term, term->cursor.row, col);
break; break;
} }
@ -355,14 +355,14 @@ csi_dispatch(struct terminal *term, uint8_t final)
switch (param) { switch (param) {
case 0: case 0:
/* From cursor to end of screen */ /* From cursor to end of screen */
start = term->grid.linear_cursor; start = term->cursor.linear;
end = term->cols * term->rows; end = term->cols * term->rows;
break; break;
case 1: case 1:
/* From start of screen to cursor */ /* From start of screen to cursor */
start = 0; start = 0;
end = term->grid.linear_cursor; end = term->cursor.linear;
break; break;
case 2: case 2:
@ -389,20 +389,20 @@ csi_dispatch(struct terminal *term, uint8_t final)
switch (param) { switch (param) {
case 0: case 0:
/* From cursor to end of line */ /* From cursor to end of line */
start = term->grid.linear_cursor; start = term->cursor.linear;
end = term_cursor_linear(term, term->grid.cursor.row, term->cols); end = term_cursor_linear(term, term->cursor.row, term->cols);
break; break;
case 1: case 1:
/* From start of line to cursor */ /* From start of line to cursor */
start = term_cursor_linear(term, term->grid.cursor.row, 0); start = term_cursor_linear(term, term->cursor.row, 0);
end = term->grid.linear_cursor; end = term->cursor.linear;
break; break;
case 2: case 2:
/* Entire line */ /* Entire line */
start = term_cursor_linear(term, term->grid.cursor.row, 0); start = term_cursor_linear(term, term->cursor.row, 0);
end = term_cursor_linear(term, term->grid.cursor.row, term->cols); end = term_cursor_linear(term, term->cursor.row, term->cols);
break; break;
default: default:
@ -415,36 +415,36 @@ csi_dispatch(struct terminal *term, uint8_t final)
} }
case 'L': { case 'L': {
if (term->grid.cursor.row < term->scroll_region.start || if (term->cursor.row < term->scroll_region.start ||
term->grid.cursor.row >= term->scroll_region.end) term->cursor.row >= term->scroll_region.end)
break; break;
int count = min( int count = min(
param_get(term, 0, 1), param_get(term, 0, 1),
term->scroll_region.end - term->grid.cursor.row); term->scroll_region.end - term->cursor.row);
term_scroll_reverse_partial( term_scroll_reverse_partial(
term, term,
(struct scroll_region){ (struct scroll_region){
.start = term->grid.cursor.row, .start = term->cursor.row,
.end = term->scroll_region.end}, .end = term->scroll_region.end},
count); count);
break; break;
} }
case 'M': { case 'M': {
if (term->grid.cursor.row < term->scroll_region.start || if (term->cursor.row < term->scroll_region.start ||
term->grid.cursor.row >= term->scroll_region.end) term->cursor.row >= term->scroll_region.end)
break; break;
int count = min( int count = min(
param_get(term, 0, 1), param_get(term, 0, 1),
term->scroll_region.end - term->grid.cursor.row); term->scroll_region.end - term->cursor.row);
term_scroll_partial( term_scroll_partial(
term, term,
(struct scroll_region){ (struct scroll_region){
.start = term->grid.cursor.row, .start = term->cursor.row,
.end = term->scroll_region.end}, .end = term->scroll_region.end},
count); count);
break; break;
@ -456,9 +456,9 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* Only delete up to the right margin */ /* Only delete up to the right margin */
const int max_end = term_cursor_linear( const int max_end = term_cursor_linear(
term, term->grid.cursor.row, term->cols); term, term->cursor.row, term->cols);
int start = term->grid.linear_cursor; int start = term->cursor.linear;
int end = min(start + count, max_end); int end = min(start + count, max_end);
/* Erase the requested number of characters */ /* Erase the requested number of characters */
@ -469,7 +469,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
memmove(&term->grid.cells[start], memmove(&term->grid.cells[start],
&term->grid.cells[end], &term->grid.cells[end],
remaining * sizeof(term->grid.cells[0])); remaining * sizeof(term->grid.cells[0]));
term_damage_update(term, term->grid.linear_cursor, remaining); term_damage_update(term, term->cursor.linear, remaining);
break; break;
} }
@ -508,8 +508,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
* decrement, hence we must add 1 */ * decrement, hence we must add 1 */
char reply[64]; char reply[64];
snprintf(reply, sizeof(reply), "\x1b[%d;%dR", snprintf(reply, sizeof(reply), "\x1b[%d;%dR",
term->grid.cursor.row + 1, term->cursor.row + 1,
term->grid.cursor.col + 1); term->cursor.col + 1);
write(term->ptmx, reply, strlen(reply)); write(term->ptmx, reply, strlen(reply));
break; break;
} }
@ -583,10 +583,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 1049: case 1049:
if (term->grid.cells != term->grid.alt_grid) { if (term->grid.cells != term->grid.alt_grid) {
term->grid.cells = term->grid.alt_grid; term->grid.cells = term->grid.alt_grid;
term->saved_cursor = term->cursor;
term->grid.alt_saved_cursor.row = term->grid.cursor.row;
term->grid.alt_saved_cursor.col = term->grid.cursor.col;
term_damage_all(term); term_damage_all(term);
} }
break; break;
@ -640,10 +637,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
if (term->grid.cells == term->grid.alt_grid) { if (term->grid.cells == term->grid.alt_grid) {
term->grid.cells = term->grid.normal_grid; term->grid.cells = term->grid.normal_grid;
term->grid.cursor.row = term->grid.alt_saved_cursor.row; term->cursor = term->saved_cursor;
term->grid.cursor.col = term->grid.alt_saved_cursor.col;
term->grid.linear_cursor = term_cursor_linear(
term, term->grid.cursor.row, term->grid.cursor.col);
/* Should these be restored from saved values? */ /* Should these be restored from saved values? */
term->scroll_region.start = 0; term->scroll_region.start = 0;

8
main.c
View file

@ -96,7 +96,7 @@ grid_render_update(struct context *c, struct buffer *buf, const struct damage *d
//LOG_DBG("UPDATE: %d (%dx%d)", linear_cursor, row, col); //LOG_DBG("UPDATE: %d (%dx%d)", linear_cursor, row, col);
const struct cell *cell = &c->term.grid.cells[linear_cursor]; const struct cell *cell = &c->term.grid.cells[linear_cursor];
bool has_cursor = c->term.grid.linear_cursor == linear_cursor; bool has_cursor = c->term.cursor.linear == linear_cursor;
int x = col * c->term.cell_width; int x = col * c->term.cell_width;
int y = row * c->term.cell_height; int y = row * c->term.cell_height;
@ -240,14 +240,14 @@ grid_render_erase(struct context *c, struct buffer *buf, const struct damage *dm
} }
/* Redraw cursor, if it's inside the erased range */ /* Redraw cursor, if it's inside the erased range */
if (c->term.grid.linear_cursor >= dmg->range.start && if (c->term.cursor.linear >= dmg->range.start &&
c->term.grid.linear_cursor < dmg->range.start + dmg->range.length) c->term.cursor.linear < dmg->range.start + dmg->range.length)
{ {
grid_render_update( grid_render_update(
c, buf, c, buf,
&(struct damage){ &(struct damage){
.type = DAMAGE_UPDATE, .type = DAMAGE_UPDATE,
.range = {.start = c->term.grid.linear_cursor, .length = 1}}); .range = {.start = c->term.cursor.linear, .length = 1}});
} }
} }

View file

@ -208,41 +208,41 @@ term_cursor_to(struct terminal *term, int row, int col)
assert(new_linear >= 0); assert(new_linear >= 0);
assert(new_linear < term->rows * term->cols); assert(new_linear < term->rows * term->cols);
term_damage_update(term, term->grid.linear_cursor, 1); term_damage_update(term, term->cursor.linear, 1);
term_damage_update(term, new_linear, 1); term_damage_update(term, new_linear, 1);
term->grid.print_needs_wrap = false; term->grid.print_needs_wrap = false;
term->grid.linear_cursor = new_linear; term->cursor.linear = new_linear;
term->grid.cursor.col = col; term->cursor.col = col;
term->grid.cursor.row = row; term->cursor.row = row;
} }
void void
term_cursor_left(struct terminal *term, int count) term_cursor_left(struct terminal *term, int count)
{ {
int move_amount = min(term->grid.cursor.col, count); int move_amount = min(term->cursor.col, count);
term_cursor_to(term, term->grid.cursor.row, term->grid.cursor.col - move_amount); term_cursor_to(term, term->cursor.row, term->cursor.col - move_amount);
} }
void void
term_cursor_right(struct terminal *term, int count) term_cursor_right(struct terminal *term, int count)
{ {
int move_amount = min(term->cols - term->grid.cursor.col - 1, count); int move_amount = min(term->cols - term->cursor.col - 1, count);
term_cursor_to(term, term->grid.cursor.row, term->grid.cursor.col + move_amount); term_cursor_to(term, term->cursor.row, term->cursor.col + move_amount);
} }
void void
term_cursor_up(struct terminal *term, int count) term_cursor_up(struct terminal *term, int count)
{ {
int move_amount = min(term->grid.cursor.row, count); int move_amount = min(term->cursor.row, count);
term_cursor_to(term, term->grid.cursor.row - move_amount, term->grid.cursor.col); term_cursor_to(term, term->cursor.row - move_amount, term->cursor.col);
} }
void void
term_cursor_down(struct terminal *term, int count) term_cursor_down(struct terminal *term, int count)
{ {
int move_amount = min(term->rows - term->grid.cursor.row - 1, count); int move_amount = min(term->rows - term->cursor.row - 1, count);
term_cursor_to(term, term->grid.cursor.row + move_amount, term->grid.cursor.col); term_cursor_to(term, term->cursor.row + move_amount, term->cursor.col);
} }
void void

View file

@ -37,6 +37,12 @@ struct scroll_region {
int end; int end;
}; };
struct cursor {
int row;
int col;
int linear;
};
enum damage_type {DAMAGE_UPDATE, DAMAGE_ERASE, DAMAGE_SCROLL, DAMAGE_SCROLL_REVERSE}; enum damage_type {DAMAGE_UPDATE, DAMAGE_ERASE, DAMAGE_SCROLL, DAMAGE_SCROLL_REVERSE};
struct damage { struct damage {
enum damage_type type; enum damage_type type;
@ -56,20 +62,11 @@ struct damage {
}; };
struct grid { struct grid {
int linear_cursor;
struct {
int row;
int col;
} cursor;
bool print_needs_wrap; bool print_needs_wrap;
struct cell *cells; struct cell *cells;
struct cell *normal_grid; struct cell *normal_grid;
struct cell *alt_grid; struct cell *alt_grid;
struct {
int row;
int col;
} alt_saved_cursor;
tll(struct damage) damage; tll(struct damage) damage;
tll(struct damage) scroll_damage; tll(struct damage) scroll_damage;
@ -151,6 +148,10 @@ struct terminal {
struct rgba foreground; struct rgba foreground;
struct rgba background; struct rgba background;
struct cursor cursor;
struct cursor saved_cursor;
struct cursor alt_saved_cursor;
}; };
void term_damage_all(struct terminal *term); void term_damage_all(struct terminal *term);

20
vt.c
View file

@ -626,7 +626,7 @@ action(struct terminal *term, enum action action, uint8_t c)
switch (c) { switch (c) {
case '\n': case '\n':
/* LF - line feed */ /* LF - line feed */
if (term->grid.cursor.row == term->scroll_region.end - 1) { if (term->cursor.row == term->scroll_region.end - 1) {
term_scroll(term, 1); term_scroll(term, 1);
} else } else
term_cursor_down(term, 1); term_cursor_down(term, 1);
@ -634,7 +634,7 @@ action(struct terminal *term, enum action action, uint8_t c)
case '\r': case '\r':
/* FF - form feed */ /* FF - form feed */
term_cursor_left(term, term->grid.cursor.col); term_cursor_left(term, term->cursor.col);
break; break;
case '\b': case '\b':
@ -649,9 +649,9 @@ action(struct terminal *term, enum action action, uint8_t c)
case '\x09': { case '\x09': {
/* HT - horizontal tab */ /* HT - horizontal tab */
int col = term->grid.cursor.col; int col = term->cursor.col;
col = (col + 8) / 8 * 8; col = (col + 8) / 8 * 8;
term_cursor_right(term, col - term->grid.cursor.col); term_cursor_right(term, col - term->cursor.col);
break; break;
} }
@ -671,15 +671,15 @@ action(struct terminal *term, enum action action, uint8_t c)
case ACTION_PRINT: { case ACTION_PRINT: {
if (term->grid.print_needs_wrap) { if (term->grid.print_needs_wrap) {
if (term->grid.cursor.row == term->scroll_region.end - 1) { if (term->cursor.row == term->scroll_region.end - 1) {
term_scroll(term, 1); term_scroll(term, 1);
term_cursor_to(term, term->grid.cursor.row, 0); term_cursor_to(term, term->cursor.row, 0);
} else } else
term_cursor_to(term, term->grid.cursor.row + 1, 0); term_cursor_to(term, term->cursor.row + 1, 0);
} }
struct cell *cell = &term->grid.cells[term->grid.linear_cursor]; struct cell *cell = &term->grid.cells[term->cursor.linear];
term_damage_update(term, term->grid.linear_cursor, 1); term_damage_update(term, term->cursor.linear, 1);
if (term->vt.utf8.idx > 0) { if (term->vt.utf8.idx > 0) {
//LOG_DBG("print: UTF8: %.*s", (int)term->vt.utf8.idx, term->vt.utf8.data); //LOG_DBG("print: UTF8: %.*s", (int)term->vt.utf8.idx, term->vt.utf8.data);
@ -694,7 +694,7 @@ action(struct terminal *term, enum action action, uint8_t c)
cell->attrs = term->vt.attrs; cell->attrs = term->vt.attrs;
if (term->grid.cursor.col < term->cols - 1) if (term->cursor.col < term->cols - 1)
term_cursor_right(term, 1); term_cursor_right(term, 1);
else else
term->grid.print_needs_wrap = true; term->grid.print_needs_wrap = true;