From c06f141189c51450be3bfd896b9df7a9d423e79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Aug 2019 20:16:17 +0200 Subject: [PATCH] term: cancel selection when scrolling wraps If we scroll enough, we'll eventually end up wrapping around the entire scrollback buffer. At this point, a selection is no longer valid, so cancel it. Note: this was very obvious when scrolling in the alt screen, since its scrollback buffer is what you see on the screen (i.e. it has no scrollback). --- selection.c | 14 ++++++++++++++ selection.h | 1 + terminal.c | 10 ++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/selection.c b/selection.c index fe4f4297..f69338a4 100644 --- a/selection.c +++ b/selection.c @@ -24,6 +24,20 @@ selection_enabled(const struct terminal *term) term->mouse_tracking != MOUSE_MOTION); } +bool +selection_on_row_in_view(const struct terminal *term, int row_no) +{ + if (term->selection.start.row == -1 || term->selection.end.row == -1) + return false; + + const struct coord *start = &term->selection.start; + const struct coord *end = &term->selection.end; + assert(start->row <= end->row); + + row_no += term->grid->view; + return row_no >= start->row && row_no <= end->row; +} + static char * extract_selection(const struct terminal *term) { diff --git a/selection.h b/selection.h index 9d712da1..2e574b0b 100644 --- a/selection.h +++ b/selection.h @@ -18,6 +18,7 @@ void selection_mark_word(struct terminal *term, int col, int row, void selection_to_clipboard(struct terminal *term, uint32_t serial); void selection_from_clipboard(struct terminal *term, uint32_t serial); void selection_from_primary(struct terminal *term); +bool selection_on_row_in_view(const struct terminal *term, int row_no); bool text_to_clipboard(struct terminal *term, char *text, uint32_t serial); void text_from_clipboard( diff --git a/terminal.c b/terminal.c index e8811ce5..622cd47a 100644 --- a/terminal.c +++ b/terminal.c @@ -282,8 +282,11 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows grid_swap_row(term->grid, i - rows, i); /* Erase scrolled in lines */ - for (int r = max(region.end - rows, 0); r < region.end; r++) + for (int r = max(region.end - rows, 0); r < region.end; r++) { erase_line(term, grid_row(term->grid, r)); + if (selection_on_row_in_view(term, r)) + selection_cancel(term); + } term_damage_scroll(term, DAMAGE_SCROLL, region, rows); term->grid->cur_row = grid_row(term->grid, term->cursor.row); @@ -325,8 +328,11 @@ term_scroll_reverse_partial(struct terminal *term, grid_swap_row(term->grid, i, i - rows); /* Erase scrolled in lines */ - for (int r = region.start; r < min(region.start + rows, region.end); r++) + for (int r = region.start; r < min(region.start + rows, region.end); r++) { erase_line(term, grid_row(term->grid, r)); + if (selection_on_row_in_view(term, r)) + selection_cancel(term); + } term_damage_scroll(term, DAMAGE_SCROLL_REVERSE, region, rows); term->grid->cur_row = grid_row(term->grid, term->cursor.row);