diff --git a/grid.c b/grid.c index a79b4493..84ee5313 100644 --- a/grid.c +++ b/grid.c @@ -83,9 +83,10 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, * at the output that is *oldest* */ int offset = grid->offset + old_screen_rows; - tll(struct sixel) old_sixels = tll_init(); + tll(struct sixel) untranslated_sixels = tll_init(); + tll(struct sixel) translated_sixels = tll_init(); tll_foreach(grid->sixel_images, it) - tll_push_back(old_sixels, it->item); + tll_push_back(untranslated_sixels, it->item); tll_free(grid->sixel_images); /* Turn cursor coordinates into grid absolute coordinates */ @@ -108,7 +109,6 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, for (size_t i = 0; i < tracking_points_count; i++) tll_push_back(tracking_points, _tracking_points[i]); - /* * Walk the old grid */ @@ -122,7 +122,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, continue; /* Map sixels on current "old" row to current "new row" */ - tll_foreach(old_sixels, it) { + tll_foreach(untranslated_sixels, it) { if (it->item.pos.row != old_row_idx) continue; @@ -131,47 +131,17 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, /* Make sure it doesn't cross the wrap-around after being re-based */ int end = (sixel.pos.row + sixel.rows - 1) & (new_rows - 1); + if (end < sixel.pos.row) { /* TODO: split instead of destroying */ sixel_destroy(&it->item); } else { - - /* Insert sixel into the *sorted* list. */ - - /* Based on rebase_row() in sixel.c */ - /* Uses 'old' offset to ensure old sixels are treated as such */ -#define rebase_row(t, row) \ - (((row) - (grid->offset + new_screen_rows) + new_rows) & (new_rows - 1)) - - int end_row = rebase_row(term, sixel.pos.row + sixel.rows - 1); - - /* - * TODO: this is basically sixel_insert(), except we - * cannot use it since: - * - * a) we don't have a 'term' reference - * b) the grid hasn't been fully * updated yet - * (e.g. grid->num_rows is invalid etc). - */ - - bool inserted = false; - tll_foreach(grid->sixel_images, it2) { - const struct sixel *s = &it2->item; - if (rebase_row(term, s->pos.row + s->rows - 1) < end_row) { - tll_insert_before(grid->sixel_images, it2, sixel); - inserted = true; - break; - } - } - - if (!inserted) - tll_push_back(grid->sixel_images, sixel); - + /* Insert sixel into the translated, but *unsorted* list. */ + tll_push_back(translated_sixels, sixel); } /* Sixel has been either re-mapped, or destroyed */ - tll_remove(old_sixels, it); -#undef rebase_row + tll_remove(untranslated_sixels, it); } #define line_wrap() \ @@ -372,9 +342,50 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols, grid->saved_cursor.lcf = false; /* Free sixels we failed to "map" to the new grid */ - tll_foreach(old_sixels, it) + tll_foreach(untranslated_sixels, it) sixel_destroy(&it->item); - tll_free(old_sixels); + tll_free(untranslated_sixels); + + /* Based on rebase_row() in sixel.c */ + /* Uses 'old' offset to ensure old sixels are treated as such */ +#define rebase_row(t, row) \ + (((row) - (grid->offset + new_screen_rows) + new_rows) & (new_rows - 1)) + + /* Re-add translated sixels, sorted according to the new grid offset */ + tll_foreach(translated_sixels, it) { + int end_row = rebase_row(term, it->item.pos.row + it->item.rows - 1); + + /* + * TODO: this is basically sixel_insert(), except we + * cannot use it since: + * + * a) we don't have a 'term' reference + * b) the grid hasn't been fully * updated yet + * (e.g. grid->num_rows is invalid etc). + */ + + if (it->item.rows >= new_rows) { + sixel_destroy(&it->item); + continue; + } + + assert(it->item.rows < new_rows); + + bool inserted = false; + tll_foreach(grid->sixel_images, it2) { + const struct sixel *s = &it2->item; + if (rebase_row(term, s->pos.row + s->rows - 1) < end_row) { + tll_insert_before(grid->sixel_images, it2, it->item); + inserted = true; + break; + } + } + + if (!inserted) + tll_push_back(grid->sixel_images, it->item); + } + tll_free(translated_sixels); +#undef rebase_row tll_free(tracking_points); }