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;