diff --git a/kitty/history.c b/kitty/history.c index d19e7c66e..b02755bf7 100644 --- a/kitty/history.c +++ b/kitty/history.c @@ -179,6 +179,7 @@ pagerhist_push(HistoryBuf *self) { PagerHistoryBuf *ph = self->pagerhist; if (!ph) return; bool truncated; + GPUCell *prev_cell = NULL; Line l = {.xnum=self->xnum}; init_line(self, self->start_of_data, &l); #define EXPAND_IF_FULL(sz) { \ @@ -193,7 +194,7 @@ pagerhist_push(HistoryBuf *self) { ph->buffer[ph->end++] = '\n'; } while(sz < ph->maxsz - 2) { - size_t num = line_as_ansi(&l, ph->buffer + ph->end, ph->bufsize - ph->end - 2, &truncated); + size_t num = line_as_ansi(&l, ph->buffer + ph->end, ph->bufsize - ph->end - 2, &truncated, &prev_cell); if (!truncated) { ph->end += num; ph->buffer[ph->end++] = '\r'; @@ -270,12 +271,13 @@ as_ansi(HistoryBuf *self, PyObject *callback) { static Py_UCS4 t[5120]; Line l = {.xnum=self->xnum}; bool truncated; + GPUCell *prev_cell = NULL; for(unsigned int i = 0; i < self->count; i++) { init_line(self, i, &l); if (i < self->count - 1) { l.continued = *attrptr(self, index_of(self, i + 1)) & CONTINUED_MASK; } else l.continued = false; - index_type num = line_as_ansi(&l, t, 5120, &truncated); + index_type num = line_as_ansi(&l, t, 5120, &truncated, &prev_cell); if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, t, num); if (ans == NULL) return PyErr_NoMemory(); diff --git a/kitty/line-buf.c b/kitty/line-buf.c index 0add07d87..05492d8c5 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -398,16 +398,17 @@ as_ansi(LineBuf *self, PyObject *callback) { // remove trailing empty lines index_type ylimit = self->ynum - 1; bool truncated; + GPUCell *prev_cell = NULL; do { init_line(self, (&l), self->line_map[ylimit]); - if (line_as_ansi(&l, t, 5120, &truncated) != 0) break; + if (line_as_ansi(&l, t, 5120, &truncated, &prev_cell) != 0) break; ylimit--; } while(ylimit > 0); for(index_type i = 0; i <= ylimit; i++) { l.continued = ((i < self->ynum - 1) ? self->line_attrs[i+1] : self->line_attrs[i]) & CONTINUED_MASK; init_line(self, (&l), self->line_map[i]); - index_type num = line_as_ansi(&l, t, 5120, &truncated); + index_type num = line_as_ansi(&l, t, 5120, &truncated, &prev_cell); if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, t, num); if (ans == NULL) return PyErr_NoMemory(); diff --git a/kitty/line.c b/kitty/line.c index 5a2563db6..cb2e446e4 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -258,7 +258,7 @@ write_sgr(const char *val, Py_UCS4 *buf, index_type buflen, index_type *i) { } index_type -line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool *truncated) { +line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool *truncated, GPUCell** prev_cell) { #define WRITE_SGR(val) { if (!write_sgr(val, buf, buflen, &i)) { *truncated = true; return i; } } #define WRITE_CH(val) if (i > buflen - 1) { *truncated = true; return i; } buf[i++] = val; @@ -268,7 +268,10 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool *truncated) { char_type previous_width = 0; GPUCell blank_cell = { 0 }; - GPUCell *cell, *prev_cell = &blank_cell; + GPUCell *cell; + if (prev_cell == NULL || *prev_cell == NULL) { + *prev_cell = &blank_cell; + } for (index_type pos=0; pos < limit; pos++) { char_type ch = self->cpu_cells[pos].ch; @@ -279,13 +282,13 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool *truncated) { cell = &self->gpu_cells[pos]; -#define CMP_ATTRS (cell->attrs & ATTRS_MASK_WITHOUT_WIDTH) != (prev_cell->attrs & ATTRS_MASK_WITHOUT_WIDTH) -#define CMP(x) cell->x != prev_cell->x +#define CMP_ATTRS (cell->attrs & ATTRS_MASK_WITHOUT_WIDTH) != ((*prev_cell)->attrs & ATTRS_MASK_WITHOUT_WIDTH) +#define CMP(x) cell->x != (*prev_cell)->x if (CMP_ATTRS || CMP(fg) || CMP(bg) || CMP(decoration_fg)) { - const char *sgr = cell_as_sgr(cell, prev_cell); + const char *sgr = cell_as_sgr(cell, *prev_cell); if (*sgr) WRITE_SGR(sgr); } - prev_cell = cell; + *prev_cell = cell; WRITE_CH(ch); for(unsigned c = 0; c < arraysz(self->cpu_cells[pos].cc_idx) && self->cpu_cells[pos].cc_idx[c]; c++) { WRITE_CH(codepoint_for_mark(self->cpu_cells[pos].cc_idx[c])); @@ -304,7 +307,7 @@ as_ansi(Line* self, PyObject *a UNUSED) { #define as_ansi_doc "Return the line's contents with ANSI (SGR) escape codes for formatting" static Py_UCS4 t[5120] = {0}; bool truncated; - index_type num = line_as_ansi(self, t, 5120, &truncated); + index_type num = line_as_ansi(self, t, 5120, &truncated, NULL); PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, t, num); return ans; } diff --git a/kitty/lineops.h b/kitty/lineops.h index 14f070506..8cb6ed4fb 100644 --- a/kitty/lineops.h +++ b/kitty/lineops.h @@ -61,7 +61,7 @@ void line_right_shift(Line *, unsigned int , unsigned int ); void line_add_combining_char(Line *, uint32_t , unsigned int ); 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); -index_type line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool*); +index_type line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen, bool*, GPUCell**); unsigned int line_length(Line *self); size_t cell_as_unicode(CPUCell *cell, bool include_cc, Py_UCS4 *buf, char_type); size_t cell_as_unicode_for_fallback(CPUCell *cell, Py_UCS4 *buf); @@ -100,6 +100,7 @@ void historybuf_clear(HistoryBuf *self); Py_UCS4 *buf = NULL; \ PyObject *nl = PyUnicode_FromString("\n"); \ PyObject *cr = PyUnicode_FromString("\r"); \ + GPUCell *prev_cell = NULL; \ if (nl == NULL || cr == NULL) goto end; \ if (as_ansi) { \ buf = malloc(sizeof(Py_UCS4) * columns * 100); \ @@ -114,7 +115,7 @@ void historybuf_clear(HistoryBuf *self); } \ if (as_ansi) { \ bool truncated; \ - index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated); \ + index_type num = line_as_ansi(line, buf, columns * 100 - 2, &truncated, &prev_cell); \ t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num); \ } else { \ t = line_as_unicode(line); \