From e8e9cd559529b91968af9f776df8b87751df7b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 18 Jul 2021 16:31:33 +0200 Subject: [PATCH] term: erase_scrollback(): destroy sixels that touch the scrollback --- CHANGELOG.md | 2 +- terminal.c | 66 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11dce7f7..7e44d8a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,7 +74,7 @@ very small. * Reduced memory usage in URL mode. * Crash when the `E3` escape (`\E[3J`) was executed, and there was a - selection in the scrollback + selection, or sixel image, in the scrollback (https://codeberg.org/dnkl/foot/issues/633). diff --git a/terminal.c b/terminal.c index b16cf19a..af5172bb 100644 --- a/terminal.c +++ b/terminal.c @@ -2014,9 +2014,16 @@ term_erase(struct terminal *term, const struct coord *start, const struct coord void term_erase_scrollback(struct terminal *term) { - const int mask = term->grid->num_rows - 1; + const int num_rows = term->grid->num_rows; + const int mask = num_rows - 1; + const int start = (term->grid->offset + term->rows) & mask; const int end = (term->grid->offset - 1) & mask; + + const int scrollback_start = term->grid->offset + term->rows; + const int rel_start = (start - scrollback_start + num_rows) & mask; + const int rel_end = (end - scrollback_start + num_rows) & mask; + const int sel_start = term->selection.start.row; const int sel_end = term->selection.end.row; @@ -2035,18 +2042,9 @@ term_erase_scrollback(struct terminal *term) * thus means the row is further *down* in the scrollback, * closer to the screen bottom. */ - int scrollback_start = term->grid->offset + term->rows; - int rel_sel_start = sel_start - scrollback_start + term->grid->num_rows; - int rel_sel_end = sel_end - scrollback_start + term->grid->num_rows; - - int rel_start = start - scrollback_start + term->grid->num_rows; - int rel_end = end - scrollback_start + term->grid->num_rows; - - rel_sel_start &= mask; - rel_sel_end &= mask; - rel_start &= mask; - rel_end &= mask; + const int rel_sel_start = (sel_start - scrollback_start + num_rows) & mask; + const int rel_sel_end = (sel_end - scrollback_start + num_rows) & mask; if ((rel_sel_start <= rel_start && rel_sel_end >= rel_start) || (rel_sel_start <= rel_end && rel_sel_end >= rel_end) || @@ -2056,6 +2054,20 @@ term_erase_scrollback(struct terminal *term) } } + tll_foreach(term->grid->sixel_images, it) { + struct sixel *six = &it->item; + const int six_start = (six->pos.row - scrollback_start + num_rows) & mask; + const int six_end = (six->pos.row + six->rows - 1 - scrollback_start + num_rows) & mask; + + if ((six_start <= rel_start && six_end >= rel_start) || + (six_start <= rel_end && six_end >= rel_end) || + (six_start >= rel_start && six_end <= rel_end)) + { + sixel_destroy(six); + tll_remove(term->grid->sixel_images, it); + } + } + for (int i = start;; i = (i + 1) & mask) { struct row *row = term->grid->rows[i]; if (row != NULL) { @@ -2164,6 +2176,36 @@ UNITTEST xassert(term.selection.end.row == 16); xassert(term.selection.kind == SELECTION_CHAR_WISE); + term.selection.start = (struct coord){-1, -1}; + term.selection.end = (struct coord){-1, -1}; + term.selection.kind = SELECTION_NONE; + + /* + * Test case 4 - sixel that touch the scrollback + */ + + struct sixel six = { + .rows = 5, + .pos = { + .row = 15, + }, + }; + tll_push_back(term.normal.sixel_images, six); + populate_scrollback(); + term_erase_scrollback(&term); + xassert(tll_length(term.normal.sixel_images) == 0); + + /* + * Test case 5 - sixel that does *not* touch the scrollback + */ + six.rows = 3; + tll_push_back(term.normal.sixel_images, six); + populate_scrollback(); + term_erase_scrollback(&term); + xassert(tll_length(term.normal.sixel_images) == 1); + + /* Cleanup */ + tll_free(term.normal.sixel_images); close(term.selection.auto_scroll.fd); for (int i = 0; i < scrollback_rows; i++) grid_row_free(term.normal.rows[i]);