diff --git a/kitty/cleanup.h b/kitty/cleanup.h index 906f24174..f5ac9f54e 100644 --- a/kitty/cleanup.h +++ b/kitty/cleanup.h @@ -19,7 +19,6 @@ typedef enum { FREETYPE_CLEANUP_FUNC, SYSTEMD_CLEANUP_FUNC, SHADERS_CLEANUP_FUNC, - LINE_CLEANUP_FUNC, NUM_CLEANUP_FUNCS } AtExitCleanupFunc; diff --git a/kitty/history.c b/kitty/history.c index 3de94527d..5538b1ffb 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -268,7 +268,7 @@ pagerhist_push(HistoryBuf *self, ANSIBuf *as_ansi_buf) { Line l = {.xnum=self->xnum, .text_cache=self->text_cache}; init_line(self, self->start_of_data, &l); ANSILineState s = {.output_buf=as_ansi_buf}; - line_as_ansi(&l, &s, 0, l.xnum, 0); + line_as_ansi(&l, &s, 0, l.xnum, 0, true); pagerhist_write_bytes(ph, (const uint8_t*)"\x1b[m", 3); if (pagerhist_write_ucs4(ph, as_ansi_buf->buf, as_ansi_buf->len)) { char line_end[2]; size_t num = 0; @@ -320,9 +320,10 @@ static PyObject* __str__(HistoryBuf *self) { PyObject *lines = PyTuple_New(self->count); if (lines == NULL) return PyErr_NoMemory(); + RAII_ANSIBuf(buf); for (index_type i = 0; i < self->count; i++) { init_line(self, index_of(self, i), self->line); - PyObject *t = line_as_unicode(self->line, false); + PyObject *t = line_as_unicode(self->line, false, &buf); if (t == NULL) { Py_CLEAR(lines); return NULL; } PyTuple_SET_ITEM(lines, i, t); } @@ -350,7 +351,7 @@ as_ansi(HistoryBuf *self, PyObject *callback) { ANSIBuf output = {0}; ANSILineState s = {.output_buf=&output}; for(unsigned int i = 0; i < self->count; i++) { init_line(self, i, &l); - line_as_ansi(&l, &s, 0, l.xnum, 0); + line_as_ansi(&l, &s, 0, l.xnum, 0, true); if (!l.cpu_cells[l.xnum - 1].next_char_was_wrapped) { ensure_space_for(&output, buf, Py_UCS4, output.len + 1, capacity, 2048, false); output.buf[output.len++] = '\n'; diff --git a/kitty/line-buf.c b/kitty/line-buf.c index 83373f8df..2c1fb746f 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -470,7 +470,7 @@ as_ansi(LineBuf *self, PyObject *callback) { ANSIBuf output = {0}; ANSILineState s = {.output_buf=&output}; do { init_line(self, &l, self->line_map[ylimit]); - line_as_ansi(&l, &s, 0, l.xnum, 0); + line_as_ansi(&l, &s, 0, l.xnum, 0, true); if (output.len) break; ylimit--; } while(ylimit > 0); @@ -478,7 +478,7 @@ as_ansi(LineBuf *self, PyObject *callback) { for(index_type i = 0; i <= ylimit; i++) { bool output_newline = !linebuf_line_ends_with_continuation(self, i); init_line(self, &l, self->line_map[i]); - line_as_ansi(&l, &s, 0, l.xnum, 0); + line_as_ansi(&l, &s, 0, l.xnum, 0, true); if (output_newline) { ensure_space_for(&output, buf, Py_UCS4, output.len + 1, capacity, 2048, false); output.buf[output.len++] = 10; // 10 = \n @@ -515,10 +515,11 @@ as_text(LineBuf *self, PyObject *args) { static PyObject* __str__(LineBuf *self) { RAII_PyObject(lines, PyTuple_New(self->ynum)); + RAII_ANSIBuf(buf); if (lines == NULL) return PyErr_NoMemory(); for (index_type i = 0; i < self->ynum; i++) { init_line(self, self->line, self->line_map[i]); - PyObject *t = line_as_unicode(self->line, false); + PyObject *t = line_as_unicode(self->line, false, &buf); if (t == NULL) return NULL; PyTuple_SET_ITEM(lines, i, t); } diff --git a/kitty/line.c b/kitty/line.c index e380fc49e..bee4514ea 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -5,8 +5,6 @@ * Distributed under terms of the GPL3 license. */ -#include "cleanup.h" -#define EXTRA_INIT register_at_exit_cleanup_func(LINE_CLEANUP_FUNC, cleanup_module); #include "state.h" #include "unicode-data.h" @@ -109,9 +107,9 @@ multicell_is_continuation_of_previous(const CPUCell *prev, const CPUCell *curr) } static void -text_in_cell_ansi(ANSILineState *s, const CPUCell *c, TextCache *tc) { +text_in_cell_ansi(ANSILineState *s, const CPUCell *c, TextCache *tc, bool skip_multiline_non_zero_lines) { if (c->is_multicell) { - if (c->x || c->y) return; + if (c->x || (skip_multiline_non_zero_lines && c->y)) return; if (s->current_multicell_state) { if (!multicell_is_continuation_of_previous(s->current_multicell_state, c)) { close_multicell(s); @@ -364,42 +362,43 @@ cell_as_utf8_for_fallback(const ListOfChars *lc, char *buf) { return n; } -static ListOfChars global_unicode_in_range_buf = {0}; - -PyObject* -unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells) { - size_t n = 0; +bool +unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells, bool skip_multiline_non_zero_lines, ANSIBuf *buf) { ListOfChars lc; for (index_type i = start; i < limit; i++) { - lc.chars = global_unicode_in_range_buf.chars + n; lc.capacity = global_unicode_in_range_buf.capacity - n; + lc.chars = buf->buf + buf->len; lc.capacity = buf->capacity - buf->len; while (!text_in_cell_without_alloc(self->cpu_cells + i, self->text_cache, &lc)) { - size_t ns = MAX(4096u, 2 * global_unicode_in_range_buf.capacity); - char_type *np = realloc(global_unicode_in_range_buf.chars, ns); - if (!np) return PyErr_NoMemory(); - global_unicode_in_range_buf.capacity = ns; global_unicode_in_range_buf.chars = np; - lc.chars = global_unicode_in_range_buf.chars + n; lc.capacity = global_unicode_in_range_buf.capacity - n; + size_t ns = MAX(4096u, 2 * buf->capacity); + char_type *np = realloc(buf->buf, ns); + if (!np) return false; + buf->capacity = ns; buf->buf = np; + lc.chars = buf->buf + buf->len; lc.capacity = buf->capacity - buf->len; } - if (self->cpu_cells[i].is_multicell && (self->cpu_cells[i].x || self->cpu_cells[i].y)) continue; + if (self->cpu_cells[i].is_multicell && (self->cpu_cells[i].x || (skip_multiline_non_zero_lines && self->cpu_cells[i].y))) continue; if (!lc.chars[0]) { if (skip_zero_cells) continue; lc.chars[0] = ' '; } if (lc.chars[0] == '\t') { - n++; + buf->len++; unsigned num_cells_to_skip_for_tab = lc.count > 1 ? lc.chars[1] : 0; while (num_cells_to_skip_for_tab && i + 1 < limit && cell_is_char(self->cpu_cells+i+1, ' ')) { i++; num_cells_to_skip_for_tab--; } - } else n += include_cc ? lc.count : 1; + } else buf->len += include_cc ? lc.count : 1; } - if (add_trailing_newline && !self->cpu_cells[self->xnum-1].next_char_was_wrapped && n < global_unicode_in_range_buf.capacity) global_unicode_in_range_buf.chars[n++] = '\n'; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, global_unicode_in_range_buf.chars, n); + if (add_trailing_newline && !self->cpu_cells[self->xnum-1].next_char_was_wrapped && buf->len < buf->capacity) buf->buf[buf->len++] = '\n'; + return true; } PyObject * -line_as_unicode(Line* self, bool skip_zero_cells) { - return unicode_in_range(self, 0, xlimit_for_line(self), true, false, skip_zero_cells); +line_as_unicode(Line* self, bool skip_zero_cells, ANSIBuf *buf) { + size_t before = buf->len; + if (!unicode_in_range(self, 0, xlimit_for_line(self), true, false, skip_zero_cells, true, buf)) return PyErr_NoMemory(); + PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf->buf + before, buf->len - before); + buf->len = before; + return ans; } static PyObject* @@ -485,7 +484,7 @@ write_mark_to_ansi_buf(ANSILineState *s, const char *m) { } bool -line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_before, char_type prefix_char) { +line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_before, char_type prefix_char, bool skip_multiline_non_zero_lines) { s->output_buf->len = 0; s->limit = MIN(stop_before, xlimit_for_line(self)); s->current_multicell_state = NULL; @@ -520,7 +519,7 @@ line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_ if (*sgr) write_sgr_to_ansi_buf(s, sgr); } - text_in_cell_ansi(s, self->cpu_cells + s->pos, self->text_cache); + text_in_cell_ansi(s, self->cpu_cells + s->pos, self->text_cache, skip_multiline_non_zero_lines); s->prev_gpu_cell = cell; } close_multicell(s); @@ -533,7 +532,7 @@ static PyObject* as_ansi(Line* self, PyObject *a UNUSED) { #define as_ansi_doc "Return the line's contents with ANSI (SGR) escape codes for formatting" ANSIBuf output = {0}; ANSILineState s = {.output_buf=&output}; - line_as_ansi(self, &s, 0, self->xnum, 0); + line_as_ansi(self, &s, 0, self->xnum, 0, true); PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output.buf, output.len); free(output.buf); return ans; @@ -554,7 +553,8 @@ set_wrapped_flag(Line* self, PyObject *is_wrapped) { static PyObject* __repr__(Line* self) { - PyObject *s = line_as_unicode(self, false); + RAII_ANSIBuf(buf); + PyObject *s = line_as_unicode(self, false, &buf); if (s == NULL) return NULL; PyObject *ans = PyObject_Repr(s); Py_CLEAR(s); @@ -563,7 +563,8 @@ __repr__(Line* self) { static PyObject* __str__(Line* self) { - return line_as_unicode(self, false); + RAII_ANSIBuf(buf); + return line_as_unicode(self, false, &buf); } @@ -938,12 +939,12 @@ apply_marker(PyObject *marker, Line *line, const PyObject *text) { } void -mark_text_in_line(PyObject *marker, Line *line) { +mark_text_in_line(PyObject *marker, Line *line, ANSIBuf *buf) { if (!marker) { for (index_type i = 0; i < line->xnum; i++) line->gpu_cells[i].attrs.mark = 0; return; } - PyObject *text = line_as_unicode(line, false); + PyObject *text = line_as_unicode(line, false, buf); if (PyUnicode_GET_LENGTH(text) > 0) { apply_marker(marker, line, text); } else { @@ -978,11 +979,11 @@ as_text_generic(PyObject *args, void *container, get_line_func get_line, index_t // makes writing pagers easier. // see https://github.com/kovidgoyal/kitty/issues/2381 s.prev_gpu_cell = NULL; - line_as_ansi(line, &s, 0, line->xnum, 0); + line_as_ansi(line, &s, 0, line->xnum, 0, true); t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, ansibuf->buf, ansibuf->len); if (t && ansibuf->len > 0) APPEND(sgr_reset); } else { - t = line_as_unicode(line, false); + t = line_as_unicode(line, false, ansibuf); } APPEND_AND_DECREF(t); if (insert_wrap_markers) APPEND(cr); @@ -1064,12 +1065,6 @@ Line *alloc_line(TextCache *tc) { return ans; } -static void -cleanup_module(void) { - free(global_unicode_in_range_buf.chars); - global_unicode_in_range_buf = (ListOfChars){0}; -} - RICHCMP(Line) INIT_TYPE(Line) // }}} diff --git a/kitty/line.h b/kitty/line.h index 1559514bc..f67fa7f60 100644 --- a/kitty/line.h +++ b/kitty/line.h @@ -108,6 +108,8 @@ typedef struct ANSILineOutput { bool escape_code_written; } ANSILineState; +static inline void cleanup_ansibuf(ANSIBuf *b) { free(b->buf); zero_at_ptr(b); } +#define RAII_ANSIBuf(name) __attribute__((cleanup(cleanup_ansibuf))) ANSIBuf name = {0} Line* alloc_line(TextCache *text_cache); void apply_sgr_to_cells(GPUCell *first_cell, unsigned int cell_count, int *params, unsigned int count, bool is_group); diff --git a/kitty/lineops.h b/kitty/lineops.h index a8bb7de47..85c6e7774 100644 --- a/kitty/lineops.h +++ b/kitty/lineops.h @@ -72,12 +72,12 @@ char_type line_get_char(Line *self, index_type at); index_type line_url_start_at(Line *self, index_type x); index_type line_url_end_at(Line *self, index_type x, bool, char_type, bool, bool, index_type); bool line_startswith_url_chars(Line*, bool); -bool line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_before, char_type prefix_char) __attribute__((nonnull)); +bool line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_before, char_type prefix_char, bool skip_multiline_non_zero_lines) __attribute__((nonnull)); unsigned int line_length(Line *self); size_t cell_as_unicode_for_fallback(const ListOfChars *lc, Py_UCS4 *buf); size_t cell_as_utf8_for_fallback(const ListOfChars *lc, char *buf); -PyObject* unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells); -PyObject* line_as_unicode(Line *, bool); +bool unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells, bool skip_multiline_non_zero_lines, ANSIBuf*); +PyObject* line_as_unicode(Line *, bool, ANSIBuf*); void linebuf_init_line(LineBuf *, index_type); void linebuf_init_line_at(LineBuf *, index_type, Line*); @@ -109,7 +109,7 @@ void historybuf_mark_line_dirty(HistoryBuf *self, index_type y); void historybuf_set_line_has_image_placeholders(HistoryBuf *self, index_type y, bool val); void historybuf_refresh_sprite_positions(HistoryBuf *self); void historybuf_clear(HistoryBuf *self); -void mark_text_in_line(PyObject *marker, Line *line); +void mark_text_in_line(PyObject *marker, Line *line, ANSIBuf *buf); bool line_has_mark(Line *, uint16_t mark); PyObject* as_text_generic(PyObject *args, void *container, get_line_func get_line, index_type lines, ANSIBuf *ansibuf, bool add_trailing_newline); bool colors_for_cell(Line *self, const ColorProfile *cp, index_type *x, color_type *fg, color_type *bg, bool *reversed); diff --git a/kitty/screen.c b/kitty/screen.c index 96beb517b..2378f59cc 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -601,12 +601,18 @@ zero_cells(text_loop_state *s, CPUCell *c, GPUCell *g) { *c = s->cc; *g = s->g; typedef Line*(linefunc_t)(Screen*, int); +static void +init_line_(Screen *self, index_type y, Line *line) { + linebuf_init_line_at(self->linebuf, y, line); + if (y == 0 && self->linebuf == self->main_linebuf) { + if (history_buf_endswith_wrap(self->historybuf)) line->attrs.is_continued = true; + } +} + + static Line* init_line(Screen *self, index_type y) { - linebuf_init_line(self->linebuf, y); - if (y == 0 && self->linebuf == self->main_linebuf) { - if (history_buf_endswith_wrap(self->historybuf)) self->linebuf->line->attrs.is_continued = true; - } + init_line_(self, y, self->linebuf->line); return self->linebuf->line; } @@ -632,6 +638,13 @@ range_line_(Screen *self, int y) { return init_line(self, y); } +static void +range_line(Screen *self, int y, Line *line) { + if (y < 0) historybuf_init_line(self->historybuf, -(y + 1), line); + else init_line_(self, y, line); +} + + static Line* checked_range_line(Screen *self, int y) { if ( @@ -3189,7 +3202,8 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat if (linebuf->line->attrs.has_dirty_text) { render_line(fonts_data, linebuf->line, y, &self->paused_rendering.cursor, self->disable_ligatures, self->lc); screen_render_line_graphics(self, linebuf->line, y); - if (linebuf->line->attrs.has_dirty_text && screen_has_marker(self)) mark_text_in_line(self->marker, linebuf->line); + if (linebuf->line->attrs.has_dirty_text && screen_has_marker(self)) mark_text_in_line( + self->marker, linebuf->line, &self->as_ansi_buf); linebuf_mark_line_clean(linebuf, y); } update_line_data(linebuf->line, y, address); @@ -3213,7 +3227,7 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat screen_render_line_graphics(self, self->historybuf->line, y - self->scrolled_by); if (self->historybuf->line->attrs.has_dirty_text) { render_line(fonts_data, self->historybuf->line, lnum, self->cursor, self->disable_ligatures, self->lc); - if (screen_has_marker(self)) mark_text_in_line(self->marker, self->historybuf->line); + if (screen_has_marker(self)) mark_text_in_line(self->marker, self->historybuf->line, &self->as_ansi_buf); historybuf_mark_line_clean(self->historybuf, lnum); } update_line_data(self->historybuf->line, y, address); @@ -3225,7 +3239,8 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat (cursor_has_moved && (self->cursor->y == lnum || self->last_rendered.cursor_y == lnum))) { render_line(fonts_data, self->linebuf->line, lnum, self->cursor, self->disable_ligatures, self->lc); screen_render_line_graphics(self, self->linebuf->line, y - self->scrolled_by); - if (self->linebuf->line->attrs.has_dirty_text && screen_has_marker(self)) mark_text_in_line(self->marker, self->linebuf->line); + if (self->linebuf->line->attrs.has_dirty_text && screen_has_marker(self)) mark_text_in_line( + self->marker, self->linebuf->line, &self->as_ansi_buf); if (is_overlay_active && lnum == self->overlay_line.ynum) render_overlay_line(self, self->linebuf->line, fonts_data); linebuf_mark_line_clean(self->linebuf, lnum); } @@ -3459,30 +3474,61 @@ static PyObject* text_for_range(Screen *self, const Selection *sel, bool insert_newlines, bool strip_trailing_whitespace) { IterationData idata; iteration_data(sel, &idata, self->columns, -self->historybuf->count, 0); - int limit = MIN((int)self->lines, idata.y_limit); - PyObject *ans = PyTuple_New(limit - idata.y); + Line line = {.xnum=self->columns, .text_cache=self->text_cache}, next_line = line; XRange xr, xrn = {0}; CPUCell *c; + size_t before = self->as_ansi_buf.len; + const int limit = MIN((int)self->lines, idata.y_limit); + if (idata.y >= limit) return PyTuple_New(0); + RAII_PyObject(ans, PyTuple_New(limit - idata.y)); if (!ans) return NULL; + range_line(self, idata.y, &next_line); + xrn = xrange_for_iteration_with_multicells(&idata, idata.y, &next_line); for (int i = 0, y = idata.y; y < limit; y++, i++) { - Line *line = range_line_(self, y); - XRange xr = xrange_for_iteration(&idata, y, line); + const bool is_first_line = y == idata.y, is_last_line = y + 1 >= limit; + xr = xrn; + line = next_line; index_type x_limit = xr.x_limit; + bool is_only_whitespace_line = false; if (strip_trailing_whitespace) { - index_type new_limit = limit_without_trailing_whitespace(line, x_limit); + index_type new_limit = limit_without_trailing_whitespace(&line, x_limit); if (new_limit != x_limit) { x_limit = new_limit; - if (!x_limit) { - PyObject *text = PyUnicode_FromString("\n"); - if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); } - PyTuple_SET_ITEM(ans, i, text); - continue; + is_only_whitespace_line = true; + } + } + const bool add_trailing_newline = insert_newlines && !is_last_line; + self->as_ansi_buf.len = before; + if (!is_last_line) { + range_line(self, y + 1, &next_line); + xrn = xrange_for_iteration_with_multicells(&idata, y+1, &next_line); + for (index_type x = 0; x < xr.x; x++) { + if ((c = &line.cpu_cells[x])->is_multicell && c->scale > 1 && c->y + 1 < c->scale && x <= xrn.x) { + index_type mc_limit = x + mcd_x_limit(c); + if (!unicode_in_range(&line, x, mc_limit, true, false, false, false, &self->as_ansi_buf)) return PyErr_NoMemory(); + x = mc_limit - 1; } } } - PyObject *text = unicode_in_range(line, xr.x, x_limit, true, insert_newlines && y != limit-1, false); - if (text == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); } + PyObject *text = NULL; + if (x_limit <= xr.x && is_only_whitespace_line) { // we want a newline on only whitespace lines even if they are continued + text = add_trailing_newline ? PyUnicode_FromString("\n") : PyUnicode_FromString(""); + } else { + if (!unicode_in_range(&line, xr.x, x_limit, true, add_trailing_newline, false, !is_first_line, &self->as_ansi_buf)) return PyErr_NoMemory(); + if (!is_last_line) { + for (index_type x = x_limit; x < MIN(line.xnum, xrn.x_limit); x++) { + if ((c = &line.cpu_cells[x])->is_multicell && c->scale > 1 && c->y + 1 < c->scale) { + index_type mc_limit = x + mcd_x_limit(c); + if (!unicode_in_range(&line, x, mc_limit, true, false, false, false, &self->as_ansi_buf)) return PyErr_NoMemory(); + x = mc_limit - 1; + } + } + } + text = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, self->as_ansi_buf.buf + before, self->as_ansi_buf.len - before); + } + if (!text) return NULL; PyTuple_SET_ITEM(ans, i, text); } - return ans; + self->as_ansi_buf.len = before; + return Py_NewRef(ans); } static PyObject* @@ -3499,7 +3545,7 @@ ansi_for_range(Screen *self, const Selection *sel, bool insert_newlines, bool st ANSILineState s = {.output_buf=&output}; for (int i = 0, y = idata.y; y < limit; y++, i++) { Line *line = range_line_(self, y); - XRange xr = xrange_for_iteration(&idata, y, line); + XRange xr = xrange_for_iteration_with_multicells(&idata, y, line); output.len = 0; char_type prefix_char = need_newline ? '\n' : 0; index_type x_limit = xr.x_limit; @@ -3513,7 +3559,10 @@ ansi_for_range(Screen *self, const Selection *sel, bool insert_newlines, bool st } } } - if (line_as_ansi(line, &s, xr.x, x_limit, prefix_char)) has_escape_codes = true; + const bool is_first_line = y == idata.y; + if (is_first_line) { + } + if (line_as_ansi(line, &s, xr.x, x_limit, prefix_char, !is_first_line)) has_escape_codes = true; need_newline = insert_newlines && !line->cpu_cells[line->xnum-1].next_char_was_wrapped; PyObject *t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output.buf, output.len); if (!t) return NULL; @@ -4928,15 +4977,15 @@ static void screen_mark_all(Screen *self) { for (index_type y = 0; y < self->main_linebuf->ynum; y++) { linebuf_init_line(self->main_linebuf, y); - mark_text_in_line(self->marker, self->main_linebuf->line); + mark_text_in_line(self->marker, self->main_linebuf->line, &self->as_ansi_buf); } for (index_type y = 0; y < self->alt_linebuf->ynum; y++) { linebuf_init_line(self->alt_linebuf, y); - mark_text_in_line(self->marker, self->alt_linebuf->line); + mark_text_in_line(self->marker, self->alt_linebuf->line, &self->as_ansi_buf); } for (index_type y = 0; y < self->historybuf->count; y++) { historybuf_init_line(self->historybuf, y, self->historybuf->line); - mark_text_in_line(self->marker, self->historybuf->line); + mark_text_in_line(self->marker, self->historybuf->line, &self->as_ansi_buf); } self->is_dirty = true; } @@ -5164,7 +5213,7 @@ dump_line_with_attrs(Screen *self, int y, PyObject *accum) { if (line->attrs.is_continued) call_string("continued "); if (line->attrs.has_dirty_text) call_string("dirty "); call_string("\n"); - RAII_PyObject(t, line_as_unicode(line, false)); if (!t) return; + RAII_PyObject(t, line_as_unicode(line, false, &self->as_ansi_buf)); if (!t) return; RAII_PyObject(r2, PyObject_CallOneArg(accum, t)); if (!r2) return; call_string("\n"); #undef call_string