diff --git a/kitty/rewrap.c b/kitty/rewrap.c index edd87f766..778e76580 100644 --- a/kitty/rewrap.c +++ b/kitty/rewrap.c @@ -84,6 +84,8 @@ typedef struct Rewrap { init_line_func_t init_line; first_dest_line_func_t first_dest_line; next_dest_line_func_t next_dest_line; + LineBuf *scratch; + bool current_dest_line_has_multiline_cells, current_src_line_has_multline_cells, prev_src_line_ended_with_wrap; } Rewrap; static void @@ -93,7 +95,7 @@ copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_t } static void -init_line(TextCache *tc, index_type xnum, Line *l) { +setup_line(TextCache *tc, index_type xnum, Line *l) { l->text_cache = tc; l->xnum = xnum; } @@ -102,6 +104,18 @@ static void next_dest_line(Rewrap *r, bool continued) { r->dest_y = r->next_dest_line(r->dest_buf, r->historybuf, r->as_ansi_buf, &r->src, r->dest_y, &r->dest, continued); r->dest_x = 0; + r->current_dest_line_has_multiline_cells = false; + if (r->scratch->line_attrs[0].has_dirty_text) { + CPUCell *cpu_cells; GPUCell *gpu_cells; + linebuf_init_cells(r->scratch, 0, &cpu_cells, &gpu_cells); + memcpy(r->dest.cpu_cells, cpu_cells, r->dest_xnum * sizeof(cpu_cells[0])); + memcpy(r->dest.gpu_cells, gpu_cells, r->dest_xnum * sizeof(gpu_cells[0])); + r->current_dest_line_has_multiline_cells = true; + } + linebuf_index(r->scratch, 0, r->scratch->ynum - 1); + if (r->scratch->line_attrs[r->scratch->ynum - 1].has_dirty_text) { + linebuf_clear_line(r->scratch, r->scratch->ynum - 1, true); + } } static void @@ -109,45 +123,52 @@ first_dest_line(Rewrap *r) { r->dest_y = r->first_dest_line(r->dest_buf, r->as_ansi_buf, &r->src, &r->dest); } +static bool +init_src_line(Rewrap *r) { + bool newline_needed = !r->prev_src_line_ended_with_wrap; + r->init_line(r->src_buf, r->src_y, &r->src); + r->src_x_limit = r->src_xnum; + if (!r->src.cpu_cells[r->src_xnum-1].next_char_was_wrapped) { + // Trim trailing blanks since there is a hard line break at the end of this line + while(r->src_x_limit && r->src.cpu_cells[r->src_x_limit - 1].ch_and_idx == BLANK_CHAR) r->src_x_limit--; + } + r->prev_src_line_ended_with_wrap = r->src.cpu_cells[r->src_xnum - 1].next_char_was_wrapped; + r->src.cpu_cells[r->src_xnum - 1].next_char_was_wrapped = false; + r->src_x = 0; + for (TrackCursor *t = r->cursors; !t->is_sentinel; t++) { + if (r->src_y == t->y) { + t->is_tracked_line = true; + if (t->x >= r->src_x_limit) t->x = MAX(1u, r->src_x_limit) - 1; + } else t->is_tracked_line = false; + } + return newline_needed; +} + static index_type rewrap_inner(Rewrap r) { - init_line(r.text_cache, r.src_xnum, &r.src); init_line(r.text_cache, r.dest_xnum, &r.dest); + setup_line(r.text_cache, r.src_xnum, &r.src); setup_line(r.text_cache, r.dest_xnum, &r.dest); static TrackCursor tc_end = {.is_sentinel = true }; if (!r.cursors) r.cursors = &tc_end; - bool is_first_line = true, src_line_is_continued = false; - while (r.src_y < r.src_limit) { - for (TrackCursor *t = r.cursors; !t->is_sentinel; t++) t->is_tracked_line = r.src_y == t->y; - r.init_line(r.src_buf, r.src_y, &r.src); - r.src_x_limit = r.src.xnum; - if (!src_line_is_continued) { - if (is_first_line) { is_first_line = false; first_dest_line(&r); } - else next_dest_line(&r, false); + r.scratch = alloc_linebuf(SCALE_BITS << 1, r.dest_xnum, r.text_cache); + if (!r.scratch) fatal("Out of memory"); + RAII_PyObject(scratch, (PyObject*)r.scratch); + for (; r.src_y < r.src_limit; r.src_y++) { + if (init_src_line(&r)) { + if (r.src_y) next_dest_line(&r, false); + else first_dest_line(&r); } - src_line_is_continued = r.src.cpu_cells[r.src.xnum-1].next_char_was_wrapped; - if (!src_line_is_continued) { - // Trim trailing blanks since there is a hard line break at the end of this line - while(r.src_x_limit && r.src.cpu_cells[r.src_x_limit - 1].ch_and_idx == BLANK_CHAR) r.src_x_limit--; - } else { - r.src.cpu_cells[r.src.xnum-1].next_char_was_wrapped = false; - } - if (r.src_x_limit) { + while (r.src_x < r.src_x_limit) { + if (r.dest_x >= r.dest_xnum) next_dest_line(&r, true); + index_type num = MIN(r.src.xnum - r.src_x, r.dest_xnum - r.dest_x); + copy_range(&r.src, r.src_x, &r.dest, r.dest_x, num); for (TrackCursor *t = r.cursors; !t->is_sentinel; t++) { - if (t->is_tracked_line && t->x >= r.src_x_limit) t->x = MAX(1u, r.src_x_limit) - 1; - } - while (r.src_x < r.src_x_limit) { - if (r.dest_x >= r.dest.xnum) next_dest_line(&r, true); - index_type num = MIN(r.src.xnum - r.src_x, r.dest.xnum - r.dest_x); - copy_range(&r.src, r.src_x, &r.dest, r.dest_x, num); - for (TrackCursor *t = r.cursors; !t->is_sentinel; t++) { - if (t->is_tracked_line && r.src_x <= t->x && t->x < r.src_x + num) { - t->y = r.dest_y; - t->x = r.dest_x + (t->x - r.src_x + (t->x > 0)); - } + if (t->is_tracked_line && r.src_x <= t->x && t->x < r.src_x + num) { + t->y = r.dest_y; + t->x = r.dest_x + (t->x - r.src_x + (t->x > 0)); } - r.src_x += num; r.dest_x += num; } + r.src_x += num; r.dest_x += num; } - r.src_y++; r.src_x = 0; } return r.dest_y; }