mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
selection: extend: use scrollback relative coordinates
When extending a selection, we determine *how* to extend it (which endpoint to move, and whether to grow or shrink the selection) by comparing the extension point with the old start and end coordinates. For this to work correctly, we need to use scrollback relative coordinates. This fixes an issue where extending a very large selection (covering many pages) sometimes shrunk the selection instead of growing it, or just misbehaving in general.
This commit is contained in:
parent
6ebf55572e
commit
b8506bbea0
2 changed files with 34 additions and 15 deletions
|
|
@ -97,6 +97,7 @@
|
|||
* Search matches ending with a double-width character not being
|
||||
highlighted correctly.
|
||||
* Selection not being cancelled correctly when scrolled out.
|
||||
* Extending a multi-page selection behaving inconsistently.
|
||||
|
||||
[1055]: https://codeberg.org/dnkl/foot/issues/1055
|
||||
[1092]: https://codeberg.org/dnkl/foot/issues/1092
|
||||
|
|
|
|||
48
selection.c
48
selection.c
|
|
@ -1002,27 +1002,37 @@ selection_extend_normal(struct terminal *term, int col, int row,
|
|||
const struct coord *start = &term->selection.coords.start;
|
||||
const struct coord *end = &term->selection.coords.end;
|
||||
|
||||
if (start->row > end->row ||
|
||||
(start->row == end->row && start->col > end->col))
|
||||
const int rel_row = grid_row_abs_to_sb(term->grid, term->rows, row);
|
||||
int rel_start_row = grid_row_abs_to_sb(term->grid, term->rows, start->row);
|
||||
int rel_end_row = grid_row_abs_to_sb(term->grid, term->rows, end->row);
|
||||
|
||||
if (rel_start_row > rel_end_row ||
|
||||
(rel_start_row == rel_end_row && start->col > end->col))
|
||||
{
|
||||
const struct coord *tmp = start;
|
||||
start = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
xassert(start->row < end->row || start->col < end->col);
|
||||
int tmp_row = rel_start_row;
|
||||
rel_start_row = rel_end_row;
|
||||
rel_end_row = tmp_row;
|
||||
}
|
||||
|
||||
struct coord new_start, new_end;
|
||||
enum selection_direction direction;
|
||||
|
||||
if (row < start->row || (row == start->row && col < start->col)) {
|
||||
if (rel_row < rel_start_row ||
|
||||
(rel_row == rel_start_row && col < start->col))
|
||||
{
|
||||
/* Extend selection to start *before* current start */
|
||||
new_start = *end;
|
||||
new_end = (struct coord){col, row};
|
||||
direction = SELECTION_LEFT;
|
||||
}
|
||||
|
||||
else if (row > end->row || (row == end->row && col > end->col)) {
|
||||
else if (rel_row > rel_end_row ||
|
||||
(rel_row == rel_end_row && col > end->col))
|
||||
{
|
||||
/* Extend selection to end *after* current end */
|
||||
new_start = *start;
|
||||
new_end = (struct coord){col, row};
|
||||
|
|
@ -1032,10 +1042,10 @@ selection_extend_normal(struct terminal *term, int col, int row,
|
|||
else {
|
||||
/* Shrink selection from start or end, depending on which one is closest */
|
||||
|
||||
const int linear = row * term->cols + col;
|
||||
const int linear = rel_row * term->cols + col;
|
||||
|
||||
if (abs(linear - (start->row * term->cols + start->col)) <
|
||||
abs(linear - (end->row * term->cols + end->col)))
|
||||
if (abs(linear - (rel_start_row * term->cols + start->col)) <
|
||||
abs(linear - (rel_end_row * term->cols + end->col)))
|
||||
{
|
||||
/* Move start point */
|
||||
new_start = *end;
|
||||
|
|
@ -1110,33 +1120,41 @@ selection_extend_block(struct terminal *term, int col, int row)
|
|||
const struct coord *start = &term->selection.coords.start;
|
||||
const struct coord *end = &term->selection.coords.end;
|
||||
|
||||
const int rel_start_row =
|
||||
grid_row_abs_to_sb(term->grid, term->rows, start->row);
|
||||
const int rel_end_row =
|
||||
grid_row_abs_to_sb(term->grid, term->rows, end->row);
|
||||
|
||||
struct coord top_left = {
|
||||
.row = min(start->row, end->row),
|
||||
.row = rel_start_row < rel_end_row ? start->row : end->row,
|
||||
.col = min(start->col, end->col),
|
||||
};
|
||||
|
||||
struct coord top_right = {
|
||||
.row = min(start->row, end->row),
|
||||
.row = top_left.row,
|
||||
.col = max(start->col, end->col),
|
||||
};
|
||||
|
||||
struct coord bottom_left = {
|
||||
.row = max(start->row, end->row),
|
||||
.row = rel_start_row > rel_end_row ? start->row : end->row,
|
||||
.col = min(start->col, end->col),
|
||||
};
|
||||
|
||||
struct coord bottom_right = {
|
||||
.row = max(start->row, end->row),
|
||||
.row = bottom_left.row,
|
||||
.col = max(start->col, end->col),
|
||||
};
|
||||
|
||||
const int rel_row = grid_row_abs_to_sb(term->grid, term->rows, row);
|
||||
const int rel_top_row = grid_row_abs_to_sb(term->grid, term->rows, top_left.row);
|
||||
const int rel_bottom_row = grid_row_abs_to_sb(term->grid, term->rows, bottom_left.row);
|
||||
struct coord new_start;
|
||||
struct coord new_end;
|
||||
|
||||
enum selection_direction direction = SELECTION_UNDIR;
|
||||
|
||||
if (row <= top_left.row ||
|
||||
abs(row - top_left.row) < abs(row - bottom_left.row))
|
||||
if (rel_row <= rel_top_row ||
|
||||
abs(rel_row - rel_top_row) < abs(rel_row - rel_bottom_row))
|
||||
{
|
||||
/* Move one of the top corners */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue