diff --git a/grid.c b/grid.c index 056dd791..b8659b55 100644 --- a/grid.c +++ b/grid.c @@ -53,7 +53,7 @@ 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) { @@ -79,13 +79,26 @@ 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; + struct coord new_cursor = {}; + cursor.row += grid->offset; + cursor.row &= old_rows - 1; + + struct coord saved_cursor = grid->saved_cursor.point; + struct coord new_saved_cursor = {}; + saved_cursor.row += grid->offset; + saved_cursor.row &= old_rows - 1; + /* * 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 +115,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; @@ -122,7 +135,13 @@ 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) { + bool has_cursor = cursor.row == old_row_idx && cursor.col == c; + bool has_saved_cursor + = saved_cursor.row == old_row_idx && saved_cursor.col == c; + + if (old_row->cells[c].wc == 0 && !has_cursor && !has_saved_cursor) { + assert(!has_cursor); + assert(!has_saved_cursor); empty_count++; continue; } @@ -168,6 +187,12 @@ 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; + + if (has_cursor) + new_cursor = (struct coord){new_col_idx, new_row_idx}; + if (has_saved_cursor) + new_saved_cursor = (struct coord){new_col_idx, new_row_idx}; + new_col_idx++; } @@ -211,11 +236,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[new_cursor.row]; grid->rows = new_grid; grid->num_rows = new_rows; grid->num_cols = new_cols; + /* Convert absolute coordinates to screen relative */ + new_cursor.row -= grid->offset; + while (new_cursor.row < 0) + new_cursor.row += grid->num_rows; + + assert(new_cursor.row >= 0); + assert(new_cursor.row < grid->num_rows); + + new_saved_cursor.row -= grid->offset; + while (new_saved_cursor.row < 0) + new_saved_cursor.row += grid->num_rows; + + assert(new_saved_cursor.row >= 0); + assert(new_saved_cursor.row < grid->num_rows); + + grid->cursor.point = new_cursor; + grid->saved_cursor.point = new_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); @@ -225,6 +271,4 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, tll_foreach(new_sixels, it) tll_push_back(grid->sixel_images, it->item); tll_free(new_sixels); - - return new_row_idx; } diff --git a/grid.h b/grid.h index 50e2c2b7..d4045189 100644 --- a/grid.h +++ b/grid.h @@ -6,7 +6,7 @@ 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); diff --git a/render.c b/render.c index f0decd93..ef0f0608 100644 --- a/render.c +++ b/render.c @@ -1754,10 +1754,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); + grid_reflow(&term->alt, new_alt_grid_rows, new_cols, old_rows, new_rows); /* Reset tab stops */ tll_free(term->tab_stops); @@ -1789,36 +1787,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->grid->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->normal.cursor.lcf = false; - term->normal.cursor.point.row = cursor_row; - term->normal.cursor.point.col = min( - term->normal.cursor.point.col, term->cols - 1); - } - term->render.last_cursor.cell = NULL; damage_view: