From 8808dd28f21f7a8d75e9f0561ae5ed4a67d27895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 12 Aug 2020 18:50:49 +0200 Subject: [PATCH] selection: adjust start point when the selection changes direction Without this, the initial cell will always be selected, regardless of how the selection is moved to the left or right. With this patch, the initial cell will only be selected while the selection is being made in the original direction. Changing direction of the selection moves the start point to next/previous character. --- CHANGELOG.md | 2 ++ selection.c | 37 +++++++++++++++++++++++++++++++++++++ terminal.h | 2 ++ 3 files changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aac7cfa..421c2aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ * Viewport sometimes not moving when doing a scrollback search. * Crash when cancelling a scrollback search and the window had been resized while searching. +* Selection start point not moving when the selection changes + direction. ### Security diff --git a/selection.c b/selection.c index 356e675d..ef1269fa 100644 --- a/selection.c +++ b/selection.c @@ -320,11 +320,47 @@ selection_update(struct terminal *term, int col, int row) struct coord new_start = term->selection.start; struct coord new_end = {col, term->grid->view + row}; + /* Adjust start point if the selection has changed 'direction' */ + if (!(new_end.row == new_start.row && new_end.col == new_start.col)) { + enum selection_direction new_direction; + + if (new_end.row > new_start.row || + (new_end.row == new_start.row && new_end.col > new_start.col)) + { + /* New end point is before the start point */ + new_direction = SELECTION_RIGHT; + } else { + /* The new end point is after the start point */ + new_direction = SELECTION_LEFT; + } + + if (term->selection.direction != new_direction) { + if (term->selection.direction != SELECTION_UNDIR) { + if (new_direction == SELECTION_LEFT) { + new_start.col--; + if (new_start.col < 0) { + new_start.col = term->cols - 1; + new_start.row--; + } + } else { + new_start.col++; + if (new_start.col >= term->cols) { + new_start.col = 0; + new_start.row++; + } + } + } + + term->selection.direction = new_direction; + } + } + size_t start_row_idx = new_start.row & (term->grid->num_rows - 1); size_t end_row_idx = new_end.row & (term->grid->num_rows - 1); const struct row *row_start = term->grid->rows[start_row_idx]; const struct row *row_end = term->grid->rows[end_row_idx]; + /* Handle double-width characters */ if (new_start.row < new_end.row || (new_start.row == new_end.row && new_start.col <= new_end.col)) @@ -548,6 +584,7 @@ selection_cancel(struct terminal *term) term->selection.kind = SELECTION_NONE; term->selection.start = (struct coord){-1, -1}; term->selection.end = (struct coord){-1, -1}; + term->selection.direction = SELECTION_UNDIR; } void diff --git a/terminal.h b/terminal.h index 1b41848d..14c12a62 100644 --- a/terminal.h +++ b/terminal.h @@ -181,6 +181,7 @@ enum mouse_reporting { enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR }; enum selection_kind { SELECTION_NONE, SELECTION_NORMAL, SELECTION_BLOCK }; +enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT}; struct ptmx_buffer { void *data; @@ -306,6 +307,7 @@ struct terminal { struct { enum selection_kind kind; + enum selection_direction direction; struct coord start; struct coord end; } selection;