From 1868fa27e444968cfd8a825d8c27a0187faf0730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 22 May 2021 20:19:48 +0200 Subject: [PATCH 1/3] term: osc8_close: debug: assert all URI coordinates are unique --- terminal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/terminal.c b/terminal.c index c16f025a..06eac0d6 100644 --- a/terminal.c +++ b/terminal.c @@ -3106,6 +3106,20 @@ term_osc8_close(struct terminal *term) .uri = xstrdup(term->vt.osc8.uri), }; grid_row_add_uri_range(row, range); + +#if defined(_DEBUG) + tll_foreach(row->extra->uri_ranges, it1) { + tll_foreach(row->extra->uri_ranges, it2) { + if (&it1->item == &it2->item) + continue; + + xassert(it1->item.start != it2->item.start); + xassert(it1->item.start != it2->item.end); + xassert(it1->item.end != it2->item.start); + xassert(it1->item.end != it2->item.end); + } + } +#endif start_col = 0; } while (r++ != end.row); From 25d43bd4c30e69c264b25b8af5321edfe8dc7995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 22 May 2021 20:20:45 +0200 Subject: [PATCH 2/3] grid: add grid_row_uri_range_destroy() --- grid.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/grid.h b/grid.h index 1131ac46..c41a5ba5 100644 --- a/grid.h +++ b/grid.h @@ -78,6 +78,12 @@ grid_row_in_view(struct grid *grid, int row_no) void grid_row_add_uri_range(struct row *row, struct row_uri_range range); +static inline void +grid_row_uri_range_destroy(struct row_uri_range *range) +{ + free(range->uri); +} + static inline void grid_row_reset_extra(struct row *row) { @@ -85,7 +91,7 @@ grid_row_reset_extra(struct row *row) return; tll_foreach(row->extra->uri_ranges, it) { - free(it->item.uri); + grid_row_uri_range_destroy(&it->item); tll_remove(row->extra->uri_ranges, it); } From 9a849b25cc01df9ace9dd775f72655a972bf5ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 22 May 2021 20:29:10 +0200 Subject: [PATCH 3/3] grid: reflow: uri-ranges: avoid looping URI ranges when reflowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we know the following: * URI ranges are sorted * URI coordinates are unique * URI ranges don’t cross rows We can optimize URI range reflowing by: * Checking if the *first* URI range’s start coordinate is on the current column. If so, keep a pointer to it. * Use this pointer as source when instantiating the reflowed URI range * If we already have a non-NULL range pointer, check its end coordinate instead. * If it matches, close the *last* URI range we inserted on the new row, and free/remove the range from the old row. * When line breaking, we only need to check if the *last* URI range is unclosed. --- grid.c | 111 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/grid.c b/grid.c index 8fb0c5c3..c9080347 100644 --- a/grid.c +++ b/grid.c @@ -289,45 +289,28 @@ grid_resize_without_reflow( } static void -reflow_uri_ranges(const struct row *old_row, struct row *new_row, - int old_col_idx, int new_col_idx) +reflow_uri_range_start(struct row_uri_range *range, struct row *new_row, + int new_col_idx) { - if (old_row->extra == NULL) - return; + struct row_uri_range new_range = { + .start = new_col_idx, + .end = -1, + .id = range->id, + .uri = xstrdup(range->uri), + }; + grid_row_add_uri_range(new_row, new_range); +} - /* - * Check for URI range start/end points on the “old” row, and - * open/close a corresponding URI range on the “new” row. - */ +static void +reflow_uri_range_end(struct row_uri_range *range, struct row *new_row, + int new_col_idx) +{ + xassert(tll_length(new_row->extra->uri_ranges) > 0); + struct row_uri_range *new_range = &tll_back(new_row->extra->uri_ranges); - tll_foreach(old_row->extra->uri_ranges, it) { - if (it->item.start == old_col_idx) { - struct row_uri_range new_range = { - .start = new_col_idx, - .end = -1, - .id = it->item.id, - .uri = xstrdup(it->item.uri), - }; - grid_row_add_uri_range(new_row, new_range); - } - - if (it->item.end == old_col_idx) { - xassert(new_row->extra != NULL); - - bool found_it = false; - tll_foreach(new_row->extra->uri_ranges, it2) { - if (it2->item.id != it->item.id) - continue; - if (it2->item.end >= 0) - continue; - - it2->item.end = new_col_idx; - found_it = true; - break; - } - xassert(found_it); - } - } + xassert(new_range->id == range->id); + xassert(new_range->end < 0); + new_range->end = new_col_idx; } static struct row * @@ -364,21 +347,22 @@ _line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row, * ranges on the previous row, and re-open them on the * next/current row. */ - tll_foreach(row->extra->uri_ranges, it) { - if (it->item.end >= 0) - continue; + if (tll_length(row->extra->uri_ranges) > 0) { + struct row_uri_range *range = &tll_back(row->extra->uri_ranges); + if (range->end < 0) { - /* Terminate URI range on the previous row */ - it->item.end = col_count - 1; + /* Terminate URI range on the previous row */ + range->end = col_count - 1; - /* Open a new range on the new/current row */ - struct row_uri_range new_range = { - .start = 0, - .end = -1, - .id = it->item.id, - .uri = xstrdup(it->item.uri), - }; - grid_row_add_uri_range(new_row, new_range); + /* Open a new range on the new/current row */ + struct row_uri_range new_range = { + .start = 0, + .end = -1, + .id = range->id, + .uri = xstrdup(range->uri), + }; + grid_row_add_uri_range(new_row, new_range); + } } return new_row; @@ -548,6 +532,8 @@ grid_resize_and_reflow( */ int empty_count = 0; + struct row_uri_range *uri_range = NULL; + /* Walk current line of the old grid */ for (int c = 0; c < old_cols; c++) { const struct cell *old_cell = &old_row->cells[c]; @@ -564,10 +550,16 @@ grid_resize_and_reflow( * sure we handle it */ bool on_uri = false; if (old_row->extra != NULL) { - tll_foreach(old_row->extra->uri_ranges, it) { - if (unlikely(it->item.start == c || it->item.end == c)) { + if (uri_range != NULL) + on_uri = uri_range->end == c; + + else if (tll_length(old_row->extra->uri_ranges) > 0) { + struct row_uri_range *range = &tll_front( + old_row->extra->uri_ranges); + + if (range->start == c) { + uri_range = range; on_uri = true; - break; } } } @@ -641,8 +633,19 @@ grid_resize_and_reflow( } while (tp->row == old_row_idx && tp->col == c); } - if (unlikely(on_uri)) - reflow_uri_ranges(old_row, new_row, c, new_col_idx); + if (unlikely(on_uri)) { + if (uri_range->start == c) + reflow_uri_range_start(uri_range, new_row, new_col_idx); + if (uri_range->end == c) { + reflow_uri_range_end(uri_range, new_row, new_col_idx); + + xassert(&tll_front(old_row->extra->uri_ranges) == uri_range); + grid_row_uri_range_destroy(uri_range); + tll_pop_front(old_row->extra->uri_ranges); + + uri_range = NULL; + } + } new_col_idx++; }