mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-07 04:06:07 -05:00
commit
b2d59a0e54
3 changed files with 67 additions and 30 deletions
|
|
@ -55,6 +55,8 @@
|
|||
about a non-monospaced primary font.
|
||||
* Rare crash when the window is resized while a mouse selection is
|
||||
ongoing (https://codeberg.org/dnkl/foot/issues/922).
|
||||
* Large selections crossing the scrollback wrap-around
|
||||
(https://codeberg.org/dnkl/foot/issues/924).
|
||||
|
||||
|
||||
### Security
|
||||
|
|
|
|||
7
grid.c
7
grid.c
|
|
@ -482,6 +482,13 @@ _line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
|||
tll_remove(old_grid->sixel_images, it);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: detect if the re-used row is covered by the
|
||||
* selection. Of so, cancel the selection. The problem: we
|
||||
* don’t know if we’ve translated the selection coordinates
|
||||
* yet.
|
||||
*/
|
||||
}
|
||||
|
||||
struct row_data *extra = row->extra;
|
||||
|
|
|
|||
88
selection.c
88
selection.c
|
|
@ -107,24 +107,34 @@ selection_view_down(struct terminal *term, int new_view)
|
|||
static void
|
||||
foreach_selected_normal(
|
||||
struct terminal *term, struct coord _start, struct coord _end,
|
||||
bool (*cb)(struct terminal *term, struct row *row, struct cell *cell, int row_no, int col, void *data),
|
||||
bool (*cb)(struct terminal *term, struct row *row, struct cell *cell,
|
||||
int row_no, int col, void *data),
|
||||
void *data)
|
||||
{
|
||||
const struct coord *start = &_start;
|
||||
const struct coord *end = &_end;
|
||||
|
||||
const int scrollback_start = term->grid->offset + term->rows;
|
||||
const int grid_rows = term->grid->num_rows;
|
||||
|
||||
/* Start/end rows, relative to the scrollback start */
|
||||
const int rel_start_row =
|
||||
(start->row - scrollback_start + grid_rows) & (grid_rows - 1);
|
||||
const int rel_end_row =
|
||||
(end->row - scrollback_start + grid_rows) & (grid_rows - 1);
|
||||
|
||||
int start_row, end_row;
|
||||
int start_col, end_col;
|
||||
|
||||
if (start->row < end->row) {
|
||||
if (rel_start_row < rel_end_row) {
|
||||
start_row = start->row;
|
||||
end_row = end->row;
|
||||
start_col = start->col;
|
||||
end_row = end->row;
|
||||
end_col = end->col;
|
||||
} else if (start->row > end->row) {
|
||||
} else if (rel_start_row > rel_end_row) {
|
||||
start_row = end->row;
|
||||
end_row = start->row;
|
||||
start_col = end->col;
|
||||
end_row = start->row;
|
||||
end_col = start->col;
|
||||
} else {
|
||||
start_row = end_row = start->row;
|
||||
|
|
@ -132,51 +142,77 @@ foreach_selected_normal(
|
|||
end_col = max(start->col, end->col);
|
||||
}
|
||||
|
||||
for (int r = start_row; r <= end_row; r++) {
|
||||
size_t real_r = r & (term->grid->num_rows - 1);
|
||||
struct row *row = term->grid->rows[real_r];
|
||||
start_row &= (grid_rows - 1);
|
||||
end_row &= (grid_rows - 1);
|
||||
|
||||
for (int r = start_row; r != end_row; r = (r + 1) & (grid_rows - 1)) {
|
||||
struct row *row = term->grid->rows[r];
|
||||
xassert(row != NULL);
|
||||
|
||||
for (int c = start_col;
|
||||
c <= (r == end_row ? end_col : term->cols - 1);
|
||||
c++)
|
||||
{
|
||||
if (!cb(term, row, &row->cells[c], real_r, c, data))
|
||||
for (int c = start_col; c <= term->cols - 1; c++) {
|
||||
if (!cb(term, row, &row->cells[c], r, c, data))
|
||||
return;
|
||||
}
|
||||
|
||||
start_col = 0;
|
||||
}
|
||||
|
||||
/* Last, partial row */
|
||||
struct row *row = term->grid->rows[end_row];
|
||||
xassert(row != NULL);
|
||||
|
||||
for (int c = start_col; c <= end_col; c++) {
|
||||
if (!cb(term, row, &row->cells[c], end_row, c, data))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
foreach_selected_block(
|
||||
struct terminal *term, struct coord _start, struct coord _end,
|
||||
bool (*cb)(struct terminal *term, struct row *row, struct cell *cell, int row_no, int col, void *data),
|
||||
bool (*cb)(struct terminal *term, struct row *row, struct cell *cell,
|
||||
int row_no, int col, void *data),
|
||||
void *data)
|
||||
{
|
||||
const struct coord *start = &_start;
|
||||
const struct coord *end = &_end;
|
||||
|
||||
const int scrollback_start = term->grid->offset + term->rows;
|
||||
const int grid_rows = term->grid->num_rows;
|
||||
|
||||
/* Start/end rows, relative to the scrollback start */
|
||||
const int rel_start_row =
|
||||
(start->row - scrollback_start + grid_rows) & (grid_rows - 1);
|
||||
const int rel_end_row =
|
||||
(end->row - scrollback_start + grid_rows) & (grid_rows - 1);
|
||||
|
||||
struct coord top_left = {
|
||||
.row = min(start->row, end->row),
|
||||
.row = (rel_start_row < rel_end_row
|
||||
? start->row : end->row) & (grid_rows - 1),
|
||||
.col = min(start->col, end->col),
|
||||
};
|
||||
|
||||
struct coord bottom_right = {
|
||||
.row = max(start->row, end->row),
|
||||
.row = (rel_start_row > rel_end_row
|
||||
? start->row : end->row) & (grid_rows - 1),
|
||||
.col = max(start->col, end->col),
|
||||
};
|
||||
|
||||
for (int r = top_left.row; r <= bottom_right.row; r++) {
|
||||
size_t real_r = r & (term->grid->num_rows - 1);
|
||||
struct row *row = term->grid->rows[real_r];
|
||||
int r = top_left.row;
|
||||
while (true) {
|
||||
struct row *row = term->grid->rows[r];
|
||||
xassert(row != NULL);
|
||||
|
||||
for (int c = top_left.col; c <= bottom_right.col; c++) {
|
||||
if (!cb(term, row, &row->cells[c], real_r, c, data))
|
||||
if (!cb(term, row, &row->cells[c], r, c, data))
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == bottom_right.row)
|
||||
break;
|
||||
|
||||
r++;
|
||||
r &= grid_rows - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1108,16 +1144,8 @@ selection_finalize(struct seat *seat, struct terminal *term, uint32_t serial)
|
|||
xassert(term->selection.start.row != -1);
|
||||
xassert(term->selection.end.row != -1);
|
||||
|
||||
if (term->selection.start.row > term->selection.end.row ||
|
||||
(term->selection.start.row == term->selection.end.row &&
|
||||
term->selection.start.col > term->selection.end.col))
|
||||
{
|
||||
struct coord tmp = term->selection.start;
|
||||
term->selection.start = term->selection.end;
|
||||
term->selection.end = tmp;
|
||||
}
|
||||
|
||||
xassert(term->selection.start.row <= term->selection.end.row);
|
||||
term->selection.start.row &= (term->grid->num_rows - 1);
|
||||
term->selection.end.row &= (term->grid->num_rows - 1);
|
||||
|
||||
switch (term->conf->selection_target) {
|
||||
case SELECTION_TARGET_NONE:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue