Merge branch 'translate-cursor-coords-when-reflowing'

This commit is contained in:
Daniel Eklöf 2020-04-17 21:16:38 +02:00
commit a9af8290ab
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
9 changed files with 236 additions and 195 deletions

View file

@ -50,6 +50,7 @@
* Alt+Return to emit "ESC \r".
* Trackpad sloooow scrolling to eventually scroll a line.
* Memory leak in terminal reset.
* Translation of cursor coordinates on resize
### Security

128
csi.c
View file

@ -382,7 +382,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* VPA - vertical line position absolute */
int rel_row = vt_param_get(term, 0, 1) - 1;
int row = term_row_rel_to_abs(term, rel_row);
term_cursor_to(term, row, term->cursor.point.col);
term_cursor_to(term, row, term->grid->cursor.point.col);
break;
}
@ -411,13 +411,13 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 'E':
/* CNL - Cursor Next Line */
term_cursor_down(term, vt_param_get(term, 0, 1));
term_cursor_left(term, term->cursor.point.col);
term_cursor_left(term, term->grid->cursor.point.col);
break;
case 'F':
/* CPL - Cursor Previous Line */
term_cursor_up(term, vt_param_get(term, 0, 1));
term_cursor_left(term, term->cursor.point.col);
term_cursor_left(term, term->grid->cursor.point.col);
break;
case 'g': {
@ -426,9 +426,9 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 0:
/* Clear tab stop at *current* column */
tll_foreach(term->tab_stops, it) {
if (it->item == term->cursor.point.col)
if (it->item == term->grid->cursor.point.col)
tll_remove(term->tab_stops, it);
else if (it->item > term->cursor.point.col)
else if (it->item > term->grid->cursor.point.col)
break;
}
@ -450,7 +450,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 'G': {
/* Cursor horizontal absolute */
int col = min(vt_param_get(term, 0, 1), term->cols) - 1;
term_cursor_to(term, term->cursor.point.row, col);
term_cursor_to(term, term->grid->cursor.point.row, col);
break;
}
@ -473,15 +473,15 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* From cursor to end of screen */
term_erase(
term,
&term->cursor.point,
&term->grid->cursor.point,
&(struct coord){term->cols - 1, term->rows - 1});
term->cursor.lcf = false;
term->grid->cursor.lcf = false;
break;
case 1:
/* From start of screen to cursor */
term_erase(term, &(struct coord){0, 0}, &term->cursor.point);
term->cursor.lcf = false;
term_erase(term, &(struct coord){0, 0}, &term->grid->cursor.point);
term->grid->cursor.lcf = false;
break;
case 2:
@ -490,7 +490,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
term,
&(struct coord){0, 0},
&(struct coord){term->cols - 1, term->rows - 1});
term->cursor.lcf = false;
term->grid->cursor.lcf = false;
break;
case 3: {
@ -531,25 +531,25 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* From cursor to end of line */
term_erase(
term,
&term->cursor.point,
&(struct coord){term->cols - 1, term->cursor.point.row});
term->cursor.lcf = false;
&term->grid->cursor.point,
&(struct coord){term->cols - 1, term->grid->cursor.point.row});
term->grid->cursor.lcf = false;
break;
case 1:
/* From start of line to cursor */
term_erase(
term, &(struct coord){0, term->cursor.point.row}, &term->cursor.point);
term->cursor.lcf = false;
term, &(struct coord){0, term->grid->cursor.point.row}, &term->grid->cursor.point);
term->grid->cursor.lcf = false;
break;
case 2:
/* Entire line */
term_erase(
term,
&(struct coord){0, term->cursor.point.row},
&(struct coord){term->cols - 1, term->cursor.point.row});
term->cursor.lcf = false;
&(struct coord){0, term->grid->cursor.point.row},
&(struct coord){term->cols - 1, term->grid->cursor.point.row});
term->grid->cursor.lcf = false;
break;
default:
@ -561,36 +561,36 @@ csi_dispatch(struct terminal *term, uint8_t final)
}
case 'L': {
if (term->cursor.point.row < term->scroll_region.start ||
term->cursor.point.row >= term->scroll_region.end)
if (term->grid->cursor.point.row < term->scroll_region.start ||
term->grid->cursor.point.row >= term->scroll_region.end)
break;
int count = min(
vt_param_get(term, 0, 1),
term->scroll_region.end - term->cursor.point.row);
term->scroll_region.end - term->grid->cursor.point.row);
term_scroll_reverse_partial(
term,
(struct scroll_region){
.start = term->cursor.point.row,
.start = term->grid->cursor.point.row,
.end = term->scroll_region.end},
count);
break;
}
case 'M': {
if (term->cursor.point.row < term->scroll_region.start ||
term->cursor.point.row >= term->scroll_region.end)
if (term->grid->cursor.point.row < term->scroll_region.start ||
term->grid->cursor.point.row >= term->scroll_region.end)
break;
int count = min(
vt_param_get(term, 0, 1),
term->scroll_region.end - term->cursor.point.row);
term->scroll_region.end - term->grid->cursor.point.row);
term_scroll_partial(
term,
(struct scroll_region){
.start = term->cursor.point.row,
.start = term->grid->cursor.point.row,
.end = term->scroll_region.end},
count);
break;
@ -601,26 +601,26 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* Number of characters to delete */
int count = min(
vt_param_get(term, 0, 1), term->cols - term->cursor.point.col);
vt_param_get(term, 0, 1), term->cols - term->grid->cursor.point.col);
/* Number of characters left after deletion (on current line) */
int remaining = term->cols - (term->cursor.point.col + count);
int remaining = term->cols - (term->grid->cursor.point.col + count);
/* 'Delete' characters by moving the remaining ones */
memmove(&term->grid->cur_row->cells[term->cursor.point.col],
&term->grid->cur_row->cells[term->cursor.point.col + count],
memmove(&term->grid->cur_row->cells[term->grid->cursor.point.col],
&term->grid->cur_row->cells[term->grid->cursor.point.col + count],
remaining * sizeof(term->grid->cur_row->cells[0]));
for (size_t c = 0; c < remaining; c++)
term->grid->cur_row->cells[term->cursor.point.col + c].attrs.clean = 0;
term->grid->cur_row->cells[term->grid->cursor.point.col + c].attrs.clean = 0;
term->grid->cur_row->dirty = true;
/* Erase the remainder of the line */
term_erase(
term,
&(struct coord){term->cursor.point.col + remaining, term->cursor.point.row},
&(struct coord){term->cols - 1, term->cursor.point.row});
term->cursor.lcf = false;
&(struct coord){term->grid->cursor.point.col + remaining, term->grid->cursor.point.row},
&(struct coord){term->cols - 1, term->grid->cursor.point.row});
term->grid->cursor.lcf = false;
break;
}
@ -629,25 +629,25 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* Number of characters to insert */
int count = min(
vt_param_get(term, 0, 1), term->cols - term->cursor.point.col);
vt_param_get(term, 0, 1), term->cols - term->grid->cursor.point.col);
/* Characters to move */
int remaining = term->cols - (term->cursor.point.col + count);
int remaining = term->cols - (term->grid->cursor.point.col + count);
/* Push existing characters */
memmove(&term->grid->cur_row->cells[term->cursor.point.col + count],
&term->grid->cur_row->cells[term->cursor.point.col],
memmove(&term->grid->cur_row->cells[term->grid->cursor.point.col + count],
&term->grid->cur_row->cells[term->grid->cursor.point.col],
remaining * sizeof(term->grid->cur_row->cells[0]));
for (size_t c = 0; c < remaining; c++)
term->grid->cur_row->cells[term->cursor.point.col + count + c].attrs.clean = 0;
term->grid->cur_row->cells[term->grid->cursor.point.col + count + c].attrs.clean = 0;
term->grid->cur_row->dirty = true;
/* Erase (insert space characters) */
term_erase(
term,
&term->cursor.point,
&(struct coord){term->cursor.point.col + count - 1, term->cursor.point.row});
term->cursor.lcf = false;
&term->grid->cursor.point,
&(struct coord){term->grid->cursor.point.col + count - 1, term->grid->cursor.point.row});
term->grid->cursor.lcf = false;
break;
}
@ -662,13 +662,13 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 'X': {
/* Erase chars */
int count = min(
vt_param_get(term, 0, 1), term->cols - term->cursor.point.col);
vt_param_get(term, 0, 1), term->cols - term->grid->cursor.point.col);
term_erase(
term,
&term->cursor.point,
&(struct coord){term->cursor.point.col + count - 1, term->cursor.point.row});
term->cursor.lcf = false;
&term->grid->cursor.point,
&(struct coord){term->grid->cursor.point.col + count - 1, term->grid->cursor.point.row});
term->grid->cursor.lcf = false;
break;
}
@ -677,13 +677,13 @@ csi_dispatch(struct terminal *term, uint8_t final)
for (int i = 0; i < vt_param_get(term, 0, 1); i++) {
int new_col = term->cols - 1;
tll_foreach(term->tab_stops, it) {
if (it->item > term->cursor.point.col) {
if (it->item > term->grid->cursor.point.col) {
new_col = it->item;
break;
}
}
assert(new_col >= term->cursor.point.col);
term_cursor_right(term, new_col - term->cursor.point.col);
assert(new_col >= term->grid->cursor.point.col);
term_cursor_right(term, new_col - term->grid->cursor.point.col);
}
break;
}
@ -693,13 +693,13 @@ csi_dispatch(struct terminal *term, uint8_t final)
for (int i = 0; i < vt_param_get(term, 0, 1); i++) {
int new_col = 0;
tll_rforeach(term->tab_stops, it) {
if (it->item < term->cursor.point.col) {
if (it->item < term->grid->cursor.point.col) {
new_col = it->item;
break;
}
}
assert(term->cursor.point.col >= new_col);
term_cursor_left(term, term->cursor.point.col - new_col);
assert(term->grid->cursor.point.col >= new_col);
term_cursor_left(term, term->grid->cursor.point.col - new_col);
}
break;
@ -757,11 +757,11 @@ csi_dispatch(struct terminal *term, uint8_t final)
}
case 's':
term->saved_cursor = term->cursor;
term->grid->saved_cursor = term->grid->cursor;
break;
case 'u':
term_restore_cursor(term, &term->saved_cursor);
term_restore_cursor(term, &term->grid->saved_cursor);
break;
case 't': {
@ -861,15 +861,15 @@ csi_dispatch(struct terminal *term, uint8_t final)
/* u7 - cursor position query */
int row = term->origin == ORIGIN_ABSOLUTE
? term->cursor.point.row
: term->cursor.point.row - term->scroll_region.start;
? term->grid->cursor.point.row
: term->grid->cursor.point.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",
row + 1, term->cursor.point.col + 1);
row + 1, term->grid->cursor.point.col + 1);
term_to_slave(term, reply, strlen(reply));
break;
}
@ -1014,9 +1014,11 @@ csi_dispatch(struct terminal *term, uint8_t final)
selection_cancel(term);
term->grid = &term->alt;
term->alt_saved_cursor = term->cursor;
term_cursor_to(term, term->cursor.point.row, term->cursor.point.col);
term_cursor_to(
term,
min(term->grid->cursor.point.row, term->rows - 1),
min(term->grid->cursor.point.col, term->cols - 1));
tll_free(term->alt.damage);
tll_free(term->alt.scroll_damage);
@ -1137,7 +1139,11 @@ csi_dispatch(struct terminal *term, uint8_t final)
selection_cancel(term);
term->grid = &term->normal;
term_restore_cursor(term, &term->alt_saved_cursor);
term_cursor_to(
term,
min(term->grid->cursor.point.row, term->rows - 1),
min(term->grid->cursor.point.col, term->cols - 1));
tll_free(term->alt.damage);
tll_free(term->alt.scroll_damage);

125
grid.c
View file

@ -53,16 +53,16 @@ grid_row_free(struct row *row)
free(row);
}
int
void
grid_reflow(struct grid *grid, int new_rows, int new_cols,
int old_screen_rows, int new_screen_rows)
int old_screen_rows, int new_screen_rows,
size_t tracking_points_count,
struct coord *_tracking_points[static tracking_points_count])
{
struct row *const *old_grid = grid->rows;
const int old_rows = grid->num_rows;
const int old_cols = grid->num_cols;
//assert(old_rows != new_rows || old_cols != new_cols);
int new_col_idx = 0;
int new_row_idx = 0;
@ -79,13 +79,31 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
tll(struct sixel) new_sixels = tll_init();
/* Turn cursor coordinates into grid absolute coordinates */
struct coord cursor = grid->cursor.point;
cursor.row += grid->offset;
cursor.row &= old_rows - 1;
struct coord saved_cursor = grid->saved_cursor.point;
saved_cursor.row += grid->offset;
saved_cursor.row &= old_rows - 1;
tll(struct coord *) tracking_points = tll_init();
tll_push_back(tracking_points, &cursor);
tll_push_back(tracking_points, &saved_cursor);
for (size_t i = 0; i < tracking_points_count; i++)
tll_push_back(tracking_points, _tracking_points[i]);
/*
* Walk the old grid
*/
for (int r = 0; r < old_rows; r++) {
const size_t old_row_idx = (offset + r) & (old_rows - 1);
/* Unallocated (empty) rows we can simply skip */
const struct row *old_row = old_grid[(offset + r) & (old_rows - 1)];
const struct row *old_row = old_grid[old_row_idx];
if (old_row == NULL)
continue;
@ -102,7 +120,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
* the "real" sixel list.
*/
tll_foreach(grid->sixel_images, it) {
if (it->item.pos.row == ((offset + r) & (old_rows - 1))) {
if (it->item.pos.row == old_row_idx) {
struct sixel six = it->item;
six.pos.row = new_row_idx;
@ -111,6 +129,21 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
}
}
#define line_wrap() \
do { \
new_col_idx = 0; \
new_row_idx = (new_row_idx + 1) & (new_rows - 1); \
\
new_row = new_grid[new_row_idx]; \
if (new_row == NULL) { \
new_row = grid_row_alloc(new_cols, true); \
new_grid[new_row_idx] = new_row; \
} else { \
memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0])); \
new_row->linebreak = false; \
} \
} while(0)
/*
* Keep track of empty cells. If the old line ends with a
* string of empty cells, we don't need to, nor do we want to,
@ -122,11 +155,23 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
/* Walk current line of the old grid */
for (int c = 0; c < old_cols; c++) {
if (old_row->cells[c].wc == 0) {
/* Check if this cell is one of the tracked cells */
bool is_tracking_point = false;
tll_foreach(tracking_points, it) {
if (it->item->row == old_row_idx && it->item->col == c) {
is_tracking_point = true;
break;
}
}
if (old_row->cells[c].wc == 0 && !is_tracking_point) {
empty_count++;
continue;
}
/* Allow left-adjusted and right-adjusted text, with empty
* cells in between, to be "pushed together" */
int old_cols_left = old_cols - c;
int cols_needed = empty_count + old_cols_left;
int new_cols_left = new_cols - new_col_idx;
@ -138,6 +183,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
/* Out of columns on current row in new grid? */
if (new_col_idx >= new_cols) {
#if 0
/*
* If last cell on last row and first cell on new
* row are non-empty, wrap the line, otherwise
@ -148,18 +194,8 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
{
new_row->linebreak = true;
}
new_col_idx = 0;
new_row_idx = (new_row_idx + 1) & (new_rows - 1);
new_row = new_grid[new_row_idx];
if (new_row == NULL) {
new_row = grid_row_alloc(new_cols, true);
new_grid[new_row_idx] = new_row;
} else {
memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0]));
new_row->linebreak = false;
}
#endif
line_wrap();
}
assert(new_row != NULL);
@ -168,6 +204,17 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
new_row->cells[new_col_idx] = *old_cell;
new_row->cells[new_col_idx].attrs.clean = 1;
/* Translate tracking point(s) */
if (is_tracking_point && i >= empty_count) {
tll_foreach(tracking_points, it) {
if (it->item->row == old_row_idx && it->item->col == c) {
it->item->row = new_row_idx;
it->item->col = new_col_idx;
tll_remove(tracking_points, it);
}
}
}
new_col_idx++;
}
@ -176,19 +223,10 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
if (old_row->linebreak) {
new_row->linebreak = true;
new_col_idx = 0;
new_row_idx = (new_row_idx + 1) & (new_rows - 1);
new_row = new_grid[new_row_idx];
if (new_row == NULL) {
new_row = grid_row_alloc(new_cols, true);
new_grid[new_row_idx] = new_row;
} else {
memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0]));
new_row->linebreak = false;
}
line_wrap();
}
#undef line_wrap
}
/* Set offset such that the last reflowed row is at the bottom */
@ -211,11 +249,32 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
grid_row_free(old_grid[r]);
free(grid->rows);
grid->cur_row = new_grid[new_row_idx];
grid->cur_row = new_grid[cursor.row];
grid->rows = new_grid;
grid->num_rows = new_rows;
grid->num_cols = new_cols;
/* Convert absolute coordinates to screen relative */
cursor.row -= grid->offset;
while (cursor.row < 0)
cursor.row += grid->num_rows;
assert(cursor.row >= 0);
assert(cursor.row < grid->num_rows);
saved_cursor.row -= grid->offset;
while (saved_cursor.row < 0)
saved_cursor.row += grid->num_rows;
assert(saved_cursor.row >= 0);
assert(saved_cursor.row < grid->num_rows);
grid->cursor.point = cursor;
grid->saved_cursor.point = saved_cursor;
grid->cursor.lcf = false;
grid->saved_cursor.lcf = false;
/* Destroy any non-moved sixels */
tll_foreach(grid->sixel_images, it)
sixel_destroy(&it->item);
@ -226,5 +285,5 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
tll_push_back(grid->sixel_images, it->item);
tll_free(new_sixels);
return new_row_idx;
tll_free(tracking_points);
}

6
grid.h
View file

@ -6,9 +6,11 @@
void grid_swap_row(struct grid *grid, int row_a, int row_b, bool initialize);
struct row *grid_row_alloc(int cols, bool initialize);
void grid_row_free(struct row *row);
int grid_reflow(
void grid_reflow(
struct grid *grid, int new_rows, int new_cols,
int old_screen_rows, int new_screen_rows);
int old_screen_rows, int new_screen_rows,
size_t tracking_points_count,
struct coord *tracking_points[static tracking_points_count]);
static inline int
grid_row_absolute(const struct grid *grid, int row_no)

View file

@ -1373,7 +1373,7 @@ grid_render(struct terminal *term)
*/
bool cursor_is_visible = false;
int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1);
int cursor_row = (term->grid->offset + term->cursor.point.row) & (term->grid->num_rows - 1);
int cursor_row = (term->grid->offset + term->grid->cursor.point.row) & (term->grid->num_rows - 1);
if (view_end >= term->grid->view) {
/* Not wrapped */
if (cursor_row >= term->grid->view && cursor_row <= view_end)
@ -1401,21 +1401,21 @@ grid_render(struct terminal *term)
int view_aligned_row
= (cursor_row - term->grid->view + term->grid->num_rows) & (term->grid->num_rows - 1);
term->render.last_cursor.actual = term->cursor.point;
term->render.last_cursor.actual = term->grid->cursor.point;
term->render.last_cursor.in_view = (struct coord) {
term->cursor.point.col, view_aligned_row};
term->grid->cursor.point.col, view_aligned_row};
struct row *row = grid_row_in_view(term->grid, view_aligned_row);
struct cell *cell = &row->cells[term->cursor.point.col];
struct cell *cell = &row->cells[term->grid->cursor.point.col];
cell->attrs.clean = 0;
term->render.last_cursor.cell = cell;
int cols_updated = render_cell(
term, buf->pix, cell, term->cursor.point.col, view_aligned_row, true);
term, buf->pix, cell, term->grid->cursor.point.col, view_aligned_row, true);
wl_surface_damage_buffer(
term->window->surface,
term->margins.left + term->cursor.point.col * term->cell_width,
term->margins.left + term->grid->cursor.point.col * term->cell_width,
term->margins.top + view_aligned_row * term->cell_height,
cols_updated * term->cell_width, term->cell_height);
}
@ -1711,8 +1711,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
if (!force && width == term->width && height == term->height && scale == term->scale)
return false;
selection_cancel(term);
/* Cancel an application initiated "Synchronized Update" */
term_disable_app_sync_updates(term);
@ -1754,10 +1752,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
}
/* Reflow grids */
int last_normal_row = grid_reflow(
&term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows);
int last_alt_row = grid_reflow(
&term->alt, new_alt_grid_rows, new_cols, old_rows, new_rows);
grid_reflow(&term->normal, new_normal_grid_rows, new_cols, old_rows, new_rows, 0, NULL);
grid_reflow(&term->alt, new_alt_grid_rows, new_cols, old_rows, new_rows, 0, NULL);
/* Reset tab stops */
tll_free(term->tab_stops);
@ -1789,36 +1785,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
if (term->scroll_region.end >= old_rows)
term->scroll_region.end = term->rows;
/* Position cursor at the last copied row */
/* TODO: can we do better? */
int cursor_row = term->grid == &term->normal
? last_normal_row - term->normal.offset
: last_alt_row - term->alt.offset;
while (cursor_row < 0)
cursor_row += term->grid->num_rows;
assert(cursor_row >= 0);
assert(cursor_row < term->rows);
term_cursor_to(
term,
cursor_row,
min(term->cursor.point.col, term->cols - 1));
/* If in alt screen, update the saved 'normal' cursor too */
if (term->grid == &term->alt) {
int cursor_row = last_normal_row - term->normal.offset;
while (cursor_row < 0)
cursor_row += term->grid->num_rows;
term->alt_saved_cursor.lcf = false;
term->alt_saved_cursor.point.row = cursor_row;
term->alt_saved_cursor.point.col = min(
term->alt_saved_cursor.point.col, term->cols - 1);
}
term->render.last_cursor.cell = NULL;
damage_view:
@ -1846,6 +1812,12 @@ damage_view:
term->height / term->scale + title_height);
}
/* Make sure selection is within bounds */
term->selection.start.row = min(term->selection.start.row, term->rows - 1);
term->selection.start.col = min(term->selection.start.col, term->cols - 1);
term->selection.end.row = min(term->selection.end.row, term->rows - 1);
term->selection.end.col = min(term->selection.end.col, term->cols - 1);
tll_free(term->normal.scroll_damage);
tll_free(term->alt.scroll_damage);

View file

@ -125,7 +125,7 @@ sixel_delete_in_range(struct terminal *term, int _start, int _end)
void
sixel_delete_at_cursor(struct terminal *term)
{
sixel_delete_at_row(term, term->cursor.point.row);
sixel_delete_at_row(term, term->grid->cursor.point.row);
}
void
@ -142,8 +142,8 @@ sixel_unhook(struct terminal *term)
.height = term->sixel.image.height,
.rows = (term->sixel.image.height + term->cell_height - 1) / term->cell_height,
.pos = (struct coord){
term->cursor.point.col,
(term->grid->offset + term->cursor.point.row) & (term->grid->num_rows - 1)},
term->grid->cursor.point.col,
(term->grid->offset + term->grid->cursor.point.row) & (term->grid->num_rows - 1)},
};
LOG_DBG("generating %dx%d pixman image", image.width, image.height);

View file

@ -354,7 +354,7 @@ term_arm_blink_timer(struct terminal *term)
static void
cursor_refresh(struct terminal *term)
{
term->grid->cur_row->cells[term->cursor.point.col].attrs.clean = 0;
term->grid->cur_row->cells[term->grid->cursor.point.col].attrs.clean = 0;
term->grid->cur_row->dirty = true;
render_refresh(term);
}
@ -1163,7 +1163,6 @@ term_reset(struct terminal *term, bool hard)
if (term->grid == &term->alt) {
term->grid = &term->normal;
term_restore_cursor(term, &term->alt_saved_cursor);
selection_cancel(term);
}
@ -1188,10 +1187,12 @@ term_reset(struct terminal *term, bool hard)
for (size_t i = 0; i < 256; i++)
term->colors.table[i] = term->colors.default_table[i];
term->origin = ORIGIN_ABSOLUTE;
term->cursor.lcf = false;
term->cursor = (struct cursor){.point = {0, 0}};
term->saved_cursor = (struct cursor){.point = {0, 0}};
term->alt_saved_cursor = (struct cursor){.point = {0, 0}};
term->normal.cursor.lcf = false;
term->alt.cursor.lcf = false;
term->normal.cursor = (struct cursor){.point = {0, 0}};
term->normal.saved_cursor = (struct cursor){.point = {0, 0}};
term->alt.cursor = (struct cursor){.point = {0, 0}};
term->alt.saved_cursor = (struct cursor){.point = {0, 0}};
term->cursor_style = term->default_cursor_style;
term_cursor_blink_disable(term);
term->cursor_color.text = term->default_cursor_color.text;
@ -1431,10 +1432,10 @@ term_cursor_to(struct terminal *term, int row, int col)
assert(row < term->rows);
assert(col < term->cols);
term->cursor.lcf = false;
term->grid->cursor.lcf = false;
term->cursor.point.col = col;
term->cursor.point.row = row;
term->grid->cursor.point.col = col;
term->grid->cursor.point.row = row;
term->grid->cur_row = grid_row(term->grid, row);
}
@ -1448,39 +1449,39 @@ term_cursor_home(struct terminal *term)
void
term_cursor_left(struct terminal *term, int count)
{
int move_amount = min(term->cursor.point.col, count);
term->cursor.point.col -= move_amount;
assert(term->cursor.point.col >= 0);
term->cursor.lcf = false;
int move_amount = min(term->grid->cursor.point.col, count);
term->grid->cursor.point.col -= move_amount;
assert(term->grid->cursor.point.col >= 0);
term->grid->cursor.lcf = false;
}
void
term_cursor_right(struct terminal *term, int count)
{
int move_amount = min(term->cols - term->cursor.point.col - 1, count);
term->cursor.point.col += move_amount;
assert(term->cursor.point.col < term->cols);
term->cursor.lcf = false;
int move_amount = min(term->cols - term->grid->cursor.point.col - 1, count);
term->grid->cursor.point.col += move_amount;
assert(term->grid->cursor.point.col < term->cols);
term->grid->cursor.lcf = false;
}
void
term_cursor_up(struct terminal *term, int count)
{
int top = term->origin == ORIGIN_ABSOLUTE ? 0 : term->scroll_region.start;
assert(term->cursor.point.row >= top);
assert(term->grid->cursor.point.row >= top);
int move_amount = min(term->cursor.point.row - top, count);
term_cursor_to(term, term->cursor.point.row - move_amount, term->cursor.point.col);
int move_amount = min(term->grid->cursor.point.row - top, count);
term_cursor_to(term, term->grid->cursor.point.row - move_amount, term->grid->cursor.point.col);
}
void
term_cursor_down(struct terminal *term, int count)
{
int bottom = term->origin == ORIGIN_ABSOLUTE ? term->rows : term->scroll_region.end;
assert(bottom >= term->cursor.point.row);
assert(bottom >= term->grid->cursor.point.row);
int move_amount = min(bottom - term->cursor.point.row - 1, count);
term_cursor_to(term, term->cursor.point.row + move_amount, term->cursor.point.col);
int move_amount = min(bottom - term->grid->cursor.point.row - 1, count);
term_cursor_to(term, term->grid->cursor.point.row + move_amount, term->grid->cursor.point.col);
}
static bool
@ -1569,7 +1570,7 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows
sixel_delete_in_range(term, max(region.end - rows, region.start), region.end - 1);
term_damage_scroll(term, DAMAGE_SCROLL, region, rows);
term->grid->cur_row = grid_row(term->grid, term->cursor.point.row);
term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row);
}
void
@ -1622,7 +1623,7 @@ term_scroll_reverse_partial(struct terminal *term,
sixel_delete_in_range(term, region.start, min(region.start + rows, region.end) - 1);
term_damage_scroll(term, DAMAGE_SCROLL_REVERSE, region, rows);
term->grid->cur_row = grid_row(term->grid, term->cursor.point.row);
term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row);
}
void
@ -1634,14 +1635,14 @@ term_scroll_reverse(struct terminal *term, int rows)
void
term_formfeed(struct terminal *term)
{
term_cursor_left(term, term->cursor.point.col);
term_cursor_left(term, term->grid->cursor.point.col);
}
void
term_linefeed(struct terminal *term)
{
term->grid->cur_row->linebreak = true;
if (term->cursor.point.row == term->scroll_region.end - 1)
if (term->grid->cursor.point.row == term->scroll_region.end - 1)
term_scroll(term, 1);
else
term_cursor_down(term, 1);
@ -1650,7 +1651,7 @@ term_linefeed(struct terminal *term)
void
term_reverse_index(struct terminal *term)
{
if (term->cursor.point.row == term->scroll_region.start)
if (term->grid->cursor.point.row == term->scroll_region.start)
term_scroll_reverse(term, 1);
else
term_cursor_up(term, 1);
@ -1672,7 +1673,7 @@ term_restore_cursor(struct terminal *term, const struct cursor *cursor)
int row = min(cursor->point.row, term->rows - 1);
int col = min(cursor->point.col, term->cols - 1);
term_cursor_to(term, row, col);
term->cursor.lcf = cursor->lcf;
term->grid->cursor.lcf = cursor->lcf;
}
void
@ -2095,7 +2096,7 @@ term_disable_app_sync_updates(struct terminal *term)
static inline void
print_linewrap(struct terminal *term)
{
if (likely(!term->cursor.lcf)) {
if (likely(!term->grid->cursor.lcf)) {
/* Not and end of line */
return;
}
@ -2105,11 +2106,11 @@ print_linewrap(struct terminal *term)
return;
}
if (term->cursor.point.row == term->scroll_region.end - 1) {
if (term->grid->cursor.point.row == term->scroll_region.end - 1) {
term_scroll(term, 1);
term_cursor_to(term, term->cursor.point.row, 0);
term_cursor_to(term, term->grid->cursor.point.row, 0);
} else
term_cursor_to(term, min(term->cursor.point.row + 1, term->rows - 1), 0);
term_cursor_to(term, min(term->grid->cursor.point.row + 1, term->rows - 1), 0);
}
static inline void
@ -2119,15 +2120,15 @@ print_insert(struct terminal *term, int width)
if (unlikely(term->insert_mode)) {
struct row *row = term->grid->cur_row;
const size_t move_count = max(0, term->cols - term->cursor.point.col - width);
const size_t move_count = max(0, term->cols - term->grid->cursor.point.col - width);
memmove(
&row->cells[term->cursor.point.col + width],
&row->cells[term->cursor.point.col],
&row->cells[term->grid->cursor.point.col + width],
&row->cells[term->grid->cursor.point.col],
move_count * sizeof(struct cell));
/* Mark moved cells as dirty */
for (size_t i = term->cursor.point.col + width; i < term->cols; i++)
for (size_t i = term->grid->cursor.point.col + width; i < term->cols; i++)
row->cells[i].attrs.clean = 0;
}
}
@ -2145,7 +2146,7 @@ term_print(struct terminal *term, wchar_t wc, int width)
/* *Must* get current cell *after* linewrap+insert */
struct row *row = term->grid->cur_row;
struct cell *cell = &row->cells[term->cursor.point.col];
struct cell *cell = &row->cells[term->grid->cursor.point.col];
cell->wc = term->vt.last_printed = wc;
cell->attrs = term->vt.attrs;
@ -2154,20 +2155,20 @@ term_print(struct terminal *term, wchar_t wc, int width)
cell->attrs.clean = 0;
/* Advance cursor the 'additional' columns while dirty:ing the cells */
for (int i = 1; i < width && term->cursor.point.col < term->cols - 1; i++) {
for (int i = 1; i < width && term->grid->cursor.point.col < term->cols - 1; i++) {
term_cursor_right(term, 1);
assert(term->cursor.point.col < term->cols);
struct cell *cell = &row->cells[term->cursor.point.col];
assert(term->grid->cursor.point.col < term->cols);
struct cell *cell = &row->cells[term->grid->cursor.point.col];
cell->wc = 0;
cell->attrs.clean = 0;
}
/* Advance cursor */
if (term->cursor.point.col < term->cols - 1)
if (term->grid->cursor.point.col < term->cols - 1)
term_cursor_right(term, 1);
else
term->cursor.lcf = true;
term->grid->cursor.lcf = true;
}
enum term_surface

View file

@ -101,6 +101,9 @@ struct grid {
int offset;
int view;
struct cursor cursor;
struct cursor saved_cursor;
struct row **rows;
struct row *cur_row;
@ -278,9 +281,6 @@ struct terminal {
} colors;
enum cursor_origin origin;
struct cursor cursor;
struct cursor saved_cursor;
struct cursor alt_saved_cursor;
enum cursor_style default_cursor_style;
enum cursor_style cursor_style;
struct {

16
vt.c
View file

@ -146,13 +146,13 @@ action_execute(struct terminal *term, uint8_t c)
/* HT - horizontal tab */
int new_col = term->cols - 1;
tll_foreach(term->tab_stops, it) {
if (it->item > term->cursor.point.col) {
if (it->item > term->grid->cursor.point.col) {
new_col = it->item;
break;
}
}
assert(new_col >= term->cursor.point.col);
term_cursor_right(term, new_col - term->cursor.point.col);
assert(new_col >= term->grid->cursor.point.col);
term_cursor_right(term, new_col - term->grid->cursor.point.col);
break;
}
@ -341,13 +341,13 @@ action_esc_dispatch(struct terminal *term, uint8_t final)
case 0:
switch (final) {
case '7':
term->saved_cursor = term->cursor;
term->grid->saved_cursor = term->grid->cursor;
term->vt.saved_attrs = term->vt.attrs;
term->saved_charsets = term->charsets;
break;
case '8':
term_restore_cursor(term, &term->saved_cursor);
term_restore_cursor(term, &term->grid->saved_cursor);
term->vt.attrs = term->vt.saved_attrs;
term->charsets = term->saved_charsets;
break;
@ -367,13 +367,13 @@ action_esc_dispatch(struct terminal *term, uint8_t final)
case 'H':
tll_foreach(term->tab_stops, it) {
if (it->item >= term->cursor.point.col) {
tll_insert_before(term->tab_stops, it, term->cursor.point.col);
if (it->item >= term->grid->cursor.point.col) {
tll_insert_before(term->tab_stops, it, term->grid->cursor.point.col);
break;
}
}
tll_push_back(term->tab_stops, term->cursor.point.col);
tll_push_back(term->tab_stops, term->grid->cursor.point.col);
break;
case 'M':