mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
grid: reflow: translate URI ranges
URI ranges are per row. Translate by detecting URI range start/end coordinates, and opening and closing a corresponding URI range on the new grid. We need to take care when line-wrapping the new grid; here we need to manually close the still-open URI ranges (on the new grid), and re-opening them on the next row.
This commit is contained in:
parent
17f90eeec4
commit
3ca5a65c33
1 changed files with 137 additions and 22 deletions
159
grid.c
159
grid.c
|
|
@ -169,6 +169,109 @@ grid_resize_without_reflow(
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
reflow_uri_ranges(const struct row *old_row, struct row *new_row,
|
||||
int old_col_idx, int new_col_idx)
|
||||
{
|
||||
if (old_row->extra == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check for URI range start/end points on the “old” row, and
|
||||
* open/close a corresponding URI range on the “new” row.
|
||||
*/
|
||||
|
||||
tll_foreach(old_row->extra->uri_ranges, it) {
|
||||
if (it->item.start == old_col_idx) {
|
||||
struct row_uri_range new_range = {
|
||||
.start = new_col_idx,
|
||||
.end = -1,
|
||||
.id = it->item.id,
|
||||
.uri = xstrdup(it->item.uri),
|
||||
};
|
||||
|
||||
if (new_row->extra == NULL)
|
||||
new_row->extra = xcalloc(1, sizeof(*new_row->extra));
|
||||
tll_push_back(new_row->extra->uri_ranges, new_range);
|
||||
}
|
||||
|
||||
else if (it->item.end == old_col_idx) {
|
||||
xassert(new_row->extra != NULL);
|
||||
|
||||
bool found_it = false;
|
||||
tll_foreach(new_row->extra->uri_ranges, it2) {
|
||||
if (it2->item.id != it->item.id)
|
||||
continue;
|
||||
if (it2->item.end >= 0)
|
||||
continue;
|
||||
|
||||
it2->item.end = new_col_idx;
|
||||
found_it = true;
|
||||
break;
|
||||
}
|
||||
xassert(found_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct row *
|
||||
_line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
||||
int *row_idx, int *col_idx, int row_count, int col_count)
|
||||
{
|
||||
*col_idx = 0;
|
||||
*row_idx = (*row_idx + 1) & (row_count - 1);
|
||||
|
||||
struct row *new_row = new_grid[*row_idx];
|
||||
|
||||
if (new_row == NULL) {
|
||||
/* Scrollback not yet full, allocate a completely new row */
|
||||
new_row = grid_row_alloc(col_count, true);
|
||||
new_grid[*row_idx] = new_row;
|
||||
} else {
|
||||
/* Scrollback is full, need to re-use a row */
|
||||
memset(new_row->cells, 0, col_count * sizeof(new_row->cells[0]));
|
||||
grid_row_reset_extra(new_row);
|
||||
new_row->linebreak = false;
|
||||
|
||||
tll_foreach(old_grid->sixel_images, it) {
|
||||
if (it->item.pos.row == *row_idx) {
|
||||
sixel_destroy(&it->item);
|
||||
tll_remove(old_grid->sixel_images, it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (row->extra == NULL)
|
||||
return new_row;
|
||||
|
||||
/*
|
||||
* URI ranges are per row. Thus, we need to ‘close’ the still-open
|
||||
* ranges on the previous row, and re-open them on the
|
||||
* next/current row.
|
||||
*/
|
||||
tll_foreach(row->extra->uri_ranges, it) {
|
||||
if (it->item.end >= 0)
|
||||
continue;
|
||||
|
||||
/* Terminate URI range on the previous row */
|
||||
it->item.end = col_count - 1;
|
||||
|
||||
/* Open a new range on the new/current row */
|
||||
struct row_uri_range new_range = {
|
||||
.start = 0,
|
||||
.end = -1,
|
||||
.id = it->item.id,
|
||||
.uri = xstrdup(it->item.uri),
|
||||
};
|
||||
|
||||
if (new_row->extra == NULL)
|
||||
new_row->extra = xcalloc(1, sizeof(*new_row->extra));
|
||||
tll_push_back(new_row->extra->uri_ranges, new_range);
|
||||
}
|
||||
|
||||
return new_row;
|
||||
}
|
||||
|
||||
void
|
||||
grid_resize_and_reflow(
|
||||
struct grid *grid, int new_rows, int new_cols,
|
||||
|
|
@ -248,29 +351,13 @@ grid_resize_and_reflow(
|
|||
tll_remove(untranslated_sixels, it);
|
||||
}
|
||||
|
||||
#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; \
|
||||
tll_foreach(grid->sixel_images, it) { \
|
||||
if (it->item.pos.row == new_row_idx) { \
|
||||
sixel_destroy(&it->item); \
|
||||
tll_remove(grid->sixel_images, it); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
#define line_wrap() \
|
||||
new_row = _line_wrap( \
|
||||
grid, new_grid, new_row, &new_row_idx, &new_col_idx, \
|
||||
new_rows, new_cols)
|
||||
|
||||
#define print_spacer() \
|
||||
do { \
|
||||
#define print_spacer() \
|
||||
do { \
|
||||
new_row->cells[new_col_idx].wc = CELL_MULT_COL_SPACER; \
|
||||
new_row->cells[new_col_idx].attrs = old_cell->attrs; \
|
||||
new_row->cells[new_col_idx].attrs.clean = 1; \
|
||||
|
|
@ -297,6 +384,17 @@ grid_resize_and_reflow(
|
|||
}
|
||||
}
|
||||
|
||||
/* If there’s an URI start/end point here, we need to make
|
||||
* sure we handle it */
|
||||
if (old_row->extra != NULL) {
|
||||
tll_foreach(old_row->extra->uri_ranges, it) {
|
||||
if (it->item.start == c || it->item.end == c) {
|
||||
is_tracking_point = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (old_row->cells[c].wc == 0 && !is_tracking_point) {
|
||||
empty_count++;
|
||||
continue;
|
||||
|
|
@ -359,6 +457,8 @@ grid_resize_and_reflow(
|
|||
tll_remove(tracking_points, it);
|
||||
}
|
||||
}
|
||||
|
||||
reflow_uri_ranges(old_row, new_row, c, new_col_idx);
|
||||
}
|
||||
new_col_idx++;
|
||||
}
|
||||
|
|
@ -385,6 +485,21 @@ grid_resize_and_reflow(
|
|||
#undef line_wrap
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
/* Verify all URI ranges have been “closed” */
|
||||
for (int r = 0; r < new_rows; r++) {
|
||||
const struct row *row = new_grid[r];
|
||||
|
||||
if (row == NULL)
|
||||
continue;
|
||||
if (row->extra == NULL)
|
||||
continue;
|
||||
|
||||
tll_foreach(row->extra->uri_ranges, it)
|
||||
xassert(it->item.end >= 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set offset such that the last reflowed row is at the bottom */
|
||||
grid->offset = new_row_idx - new_screen_rows + 1;
|
||||
while (grid->offset < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue