From 8e05f42a1ccdc882a10e88f85a10cab61605a88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 14 May 2021 16:32:06 +0200 Subject: [PATCH] =?UTF-8?q?grid:=20don=E2=80=99t=20depend=20on=20wcwidth()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling wcwidth() on every character in the entire scrollback history is slow. We already have the character width encoded in the grid; it’s in the CELL_SPACERs following a multi-column character. Thus, when we see a non-SPACER character, that isn’t in the last column, peek the next character. If it’s a SPACER, get the current characters width from it. The only thing we need the width for, is to be able to print padding SPACERS in the right margin, if the there isn’t enough space on the current row for the current character. --- grid.c | 88 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/grid.c b/grid.c index ab8135f0..45f4d37f 100644 --- a/grid.c +++ b/grid.c @@ -525,6 +525,17 @@ grid_resize_and_reflow( if (new_cols_left < cols_needed && new_cols_left >= old_cols_left) empty_count = max(0, empty_count - (cols_needed - new_cols_left)); + for (int i = 0; i < empty_count; i++) { + if (new_col_idx + 1 > new_cols) + line_wrap(); + + new_row->cells[new_col_idx] = old_row->cells[c - empty_count + i]; + new_row->cells[new_col_idx].attrs.clean = 1; + new_col_idx++; + } + + empty_count = 0; + wchar_t wc = old_row->cells[c].wc; if (wc >= CELL_COMB_CHARS_LO && wc < (CELL_COMB_CHARS_LO + compose_count)) @@ -532,65 +543,58 @@ grid_resize_and_reflow( wc = composed[wc - CELL_COMB_CHARS_LO].base; } - int width = max(1, wcwidth(wc)); + const struct cell *old_cell = &old_row->cells[c]; + wc = old_cell->wc; - /* Multi-column characters are never cut in half */ - xassert(c + width <= old_cols); + if (wc == CELL_SPACER) + continue; - for (int i = 0; i < empty_count + 1; i++) { - const struct cell *old_cell = &old_row->cells[c - empty_count + i]; - wc = old_cell->wc; + if (wc >= CELL_COMB_CHARS_LO && + wc < (CELL_COMB_CHARS_LO + compose_count)) + { + wc = composed[wc - CELL_COMB_CHARS_LO].base; + } - if (wc >= CELL_SPACER) - continue; - - if (wc >= CELL_COMB_CHARS_LO && - wc < (CELL_COMB_CHARS_LO + compose_count)) - { - wc = composed[wc - CELL_COMB_CHARS_LO].base; - } + if (wc < CELL_SPACER && + c + 1 < old_cols && + old_row->cells[c + 1].wc > CELL_SPACER) + { + int width = old_row->cells[c + 1].wc - CELL_SPACER + 1; + assert(wcwidth(wc) == width); /* Out of columns on current row in new grid? */ - if (new_col_idx + max(1, wcwidth(wc)) > new_cols) { + if (new_col_idx + width > new_cols) { /* Pad to end-of-line with spacers, then line-wrap */ for (;new_col_idx < new_cols; new_col_idx++) print_spacer(0); line_wrap(); } + } - xassert(new_row != NULL); - xassert(new_col_idx >= 0); - xassert(new_col_idx < new_cols); + if (new_col_idx + 1 > new_cols) + line_wrap(); - new_row->cells[new_col_idx] = *old_cell; - new_row->cells[new_col_idx].attrs.clean = 1; + xassert(new_row != NULL); + xassert(new_col_idx >= 0); + xassert(new_col_idx < new_cols); - /* Translate tracking point(s) */ - if (is_tracking_point && i >= empty_count) { - tll_foreach(tracking_points, it) { - if (it->item->row == old_row_idx && it->item->col == c) { - it->item->row = new_row_idx; - it->item->col = new_col_idx; - tll_remove(tracking_points, it); - } + new_row->cells[new_col_idx] = *old_cell; + new_row->cells[new_col_idx].attrs.clean = 1; + + /* Translate tracking point(s) */ + if (is_tracking_point) { + tll_foreach(tracking_points, it) { + if (it->item->row == old_row_idx && it->item->col == c) { + it->item->row = new_row_idx; + it->item->col = new_col_idx; + tll_remove(tracking_points, it); } - - reflow_uri_ranges(old_row, new_row, c, new_col_idx); } - new_col_idx++; + + reflow_uri_ranges(old_row, new_row, c, new_col_idx); } - /* For multi-column characters, insert spacers in the - * subsequent cells */ - const struct cell *old_cell = &old_row->cells[c]; - for (size_t i = 0; i < width - 1; i++) { - xassert(new_col_idx < new_cols); - print_spacer(width - i + 1); - new_col_idx++; - } - - c += width - 1; - empty_count = 0; + new_col_idx++; } if (old_row->linebreak) {