Track line dirty status in the line buffer

This commit is contained in:
Kovid Goyal
2017-11-09 09:22:58 +05:30
parent 71dcf13edf
commit 0277be5856
5 changed files with 62 additions and 50 deletions

View File

@@ -30,6 +30,7 @@ typedef uint32_t combining_type;
typedef unsigned int index_type; typedef unsigned int index_type;
typedef uint16_t sprite_index; typedef uint16_t sprite_index;
typedef uint16_t attrs_type; typedef uint16_t attrs_type;
typedef uint8_t line_attrs_type;
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape; typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape;
#define ERROR_PREFIX "[PARSE ERROR]" #define ERROR_PREFIX "[PARSE ERROR]"
@@ -56,6 +57,8 @@ typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
#define UNDERCURL_CODE 6 #define UNDERCURL_CODE 6
#define DECORATION_FG_CODE 58 #define DECORATION_FG_CODE 58
#define CHAR_IS_BLANK(ch) ((ch) == 32 || (ch) == 0) #define CHAR_IS_BLANK(ch) ((ch) == 32 || (ch) == 0)
#define CONTINUED_MASK 1
#define TEXT_DIRTY_MASK 2
#define FG 1 #define FG 1
#define BG 2 #define BG 2
@@ -134,8 +137,7 @@ typedef struct {
Cell *cells; Cell *cells;
index_type xnum, ynum; index_type xnum, ynum;
bool continued; bool continued, needs_free, has_dirty_text;
bool needs_free;
} Line; } Line;
@@ -144,7 +146,7 @@ typedef struct {
Cell *buf; Cell *buf;
index_type xnum, ynum, *line_map, *scratch; index_type xnum, ynum, *line_map, *scratch;
bool *continued_map; line_attrs_type *line_attrs;
Line *line; Line *line;
} LineBuf; } LineBuf;
@@ -156,7 +158,7 @@ typedef struct {
index_type xnum, ynum; index_type xnum, ynum;
Line *line; Line *line;
index_type start_of_data, count; index_type start_of_data, count;
bool *continued_map; line_attrs_type *line_attrs;
} HistoryBuf; } HistoryBuf;
typedef struct { typedef struct {

View File

@@ -33,11 +33,11 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->xnum = xnum; self->xnum = xnum;
self->ynum = ynum; self->ynum = ynum;
self->buf = PyMem_Calloc(xnum * ynum, sizeof(Cell)); self->buf = PyMem_Calloc(xnum * ynum, sizeof(Cell));
self->continued_map = PyMem_Calloc(ynum, sizeof(bool)); self->line_attrs = PyMem_Calloc(ynum, sizeof(line_attrs_type));
self->line = alloc_line(); self->line = alloc_line();
if (self->buf == NULL || self->line == NULL || self->continued_map == NULL) { if (self->buf == NULL || self->line == NULL || self->line_attrs == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
PyMem_Free(self->buf); Py_CLEAR(self->line); PyMem_Free(self->continued_map); PyMem_Free(self->buf); Py_CLEAR(self->line); PyMem_Free(self->line_attrs);
Py_CLEAR(self); Py_CLEAR(self);
} else { } else {
self->line->xnum = xnum; self->line->xnum = xnum;
@@ -54,7 +54,7 @@ static void
dealloc(HistoryBuf* self) { dealloc(HistoryBuf* self) {
Py_CLEAR(self->line); Py_CLEAR(self->line);
PyMem_Free(self->buf); PyMem_Free(self->buf);
PyMem_Free(self->continued_map); PyMem_Free(self->line_attrs);
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
@@ -71,7 +71,7 @@ static inline void
init_line(HistoryBuf *self, index_type num, Line *l) { init_line(HistoryBuf *self, index_type num, Line *l) {
// Initialize the line l, setting its pointer to the offsets for the line at index (buffer position) num // Initialize the line l, setting its pointer to the offsets for the line at index (buffer position) num
l->cells = lineptr(self, num); l->cells = lineptr(self, num);
l->continued = self->continued_map[num]; l->continued = self->line_attrs[num] & CONTINUED_MASK;
} }
void void
@@ -96,19 +96,19 @@ historybuf_resize(HistoryBuf *self, index_type lines) {
if (t.ynum > 0 && t.ynum != self->ynum) { if (t.ynum > 0 && t.ynum != self->ynum) {
t.buf = PyMem_Calloc(t.xnum * t.ynum, sizeof(Cell)); t.buf = PyMem_Calloc(t.xnum * t.ynum, sizeof(Cell));
if (t.buf == NULL) { PyErr_NoMemory(); return false; } if (t.buf == NULL) { PyErr_NoMemory(); return false; }
t.continued_map = PyMem_Calloc(t.ynum, sizeof(bool)); t.line_attrs = PyMem_Calloc(t.ynum, sizeof(line_attrs_type));
if (t.continued_map == NULL) { PyMem_Free(t.buf); PyErr_NoMemory(); return false; } if (t.line_attrs == NULL) { PyMem_Free(t.buf); PyErr_NoMemory(); return false; }
t.count = MIN(self->count, t.ynum); t.count = MIN(self->count, t.ynum);
for (index_type s=0; s < t.count; s++) { for (index_type s=0; s < t.count; s++) {
index_type si = index_of(self, s), ti = index_of(&t, s); index_type si = index_of(self, s), ti = index_of(&t, s);
copy_cells(lineptr(self, si), lineptr(&t, ti), t.xnum); copy_cells(lineptr(self, si), lineptr(&t, ti), t.xnum);
t.continued_map[ti] = self->continued_map[si]; t.line_attrs[ti] = self->line_attrs[si];
} }
self->count = t.count; self->count = t.count;
self->start_of_data = t.start_of_data; self->start_of_data = t.start_of_data;
self->ynum = t.ynum; self->ynum = t.ynum;
PyMem_Free(self->buf); PyMem_Free(self->continued_map); PyMem_Free(self->buf); PyMem_Free(self->line_attrs);
self->buf = t.buf; self->continued_map = t.continued_map; self->buf = t.buf; self->line_attrs = t.line_attrs;
} }
return true; return true;
} }
@@ -117,7 +117,7 @@ void
historybuf_add_line(HistoryBuf *self, const Line *line) { historybuf_add_line(HistoryBuf *self, const Line *line) {
index_type idx = historybuf_push(self); index_type idx = historybuf_push(self);
copy_line(line, self->line); copy_line(line, self->line);
self->continued_map[idx] = line->continued; self->line_attrs[idx] = (line->continued & CONTINUED_MASK) | (line->has_dirty_text ? TEXT_DIRTY_MASK : 0);
} }
static PyObject* static PyObject*
@@ -171,7 +171,7 @@ as_ansi(HistoryBuf *self, PyObject *callback) {
for(unsigned int i = 0; i < self->count; i++) { for(unsigned int i = 0; i < self->count; i++) {
init_line(self, i, &l); init_line(self, i, &l);
if (i < self->count - 1) { if (i < self->count - 1) {
l.continued = self->continued_map[index_of(self, i + 1)]; l.continued = self->line_attrs[index_of(self, i + 1)] & CONTINUED_MASK;
} else l.continued = false; } else l.continued = false;
index_type num = line_as_ansi(&l, t, 5120); index_type num = line_as_ansi(&l, t, 5120);
if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n
@@ -231,9 +231,9 @@ HistoryBuf *alloc_historybuf(unsigned int lines, unsigned int columns) {
#define init_src_line(src_y) init_line(src, map_src_index(src_y), src->line); #define init_src_line(src_y) init_line(src, map_src_index(src_y), src->line);
#define is_src_line_continued(src_y) (map_src_index(src_y) < src->ynum - 1 ? src->continued_map[map_src_index(src_y + 1)] : false) #define is_src_line_continued(src_y) (map_src_index(src_y) < src->ynum - 1 ? (src->line_attrs[map_src_index(src_y + 1)] & CONTINUED_MASK) : false)
#define next_dest_line(cont) dest->continued_map[historybuf_push(dest)] = cont; dest->line->continued = cont; #define next_dest_line(cont) dest->line_attrs[historybuf_push(dest)] = cont & CONTINUED_MASK; dest->line->continued = cont;
#define first_dest_line next_dest_line(false); #define first_dest_line next_dest_line(false);
@@ -243,7 +243,7 @@ void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other) {
// Fast path // Fast path
if (other->xnum == self->xnum && other->ynum == self->ynum) { if (other->xnum == self->xnum && other->ynum == self->ynum) {
memcpy(other->buf, self->buf, sizeof(Cell) * self->xnum * self->ynum); memcpy(other->buf, self->buf, sizeof(Cell) * self->xnum * self->ynum);
memcpy(other->continued_map, self->continued_map, sizeof(bool) * self->ynum); memcpy(other->line_attrs, self->line_attrs, sizeof(line_attrs_type) * self->ynum);
other->count = self->count; other->start_of_data = self->start_of_data; other->count = self->count; other->start_of_data = self->start_of_data;
return; return;
} }

View File

@@ -25,10 +25,13 @@ clear_chars_to(LineBuf* linebuf, index_type y, char_type ch) {
void void
linebuf_clear(LineBuf *self, char_type ch) { linebuf_clear(LineBuf *self, char_type ch) {
memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell)); memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell));
memset(self->continued_map, 0, self->ynum * sizeof(bool)); memset(self->line_attrs, 0, self->ynum * sizeof(line_attrs_type));
for (index_type i = 0; i < self->ynum; i++) self->line_map[i] = i; for (index_type i = 0; i < self->ynum; i++) self->line_map[i] = i;
if (ch != 0) { if (ch != 0) {
for (index_type i = 0; i < self->ynum; i++) clear_chars_to(self, i, ch); for (index_type i = 0; i < self->ynum; i++) {
clear_chars_to(self, i, ch);
self->line_attrs[i] = TEXT_DIRTY_MASK;
}
} }
} }
@@ -63,11 +66,11 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->buf = PyMem_Calloc(xnum * ynum, sizeof(Cell)); self->buf = PyMem_Calloc(xnum * ynum, sizeof(Cell));
self->line_map = PyMem_Calloc(ynum, sizeof(index_type)); self->line_map = PyMem_Calloc(ynum, sizeof(index_type));
self->scratch = PyMem_Calloc(ynum, sizeof(index_type)); self->scratch = PyMem_Calloc(ynum, sizeof(index_type));
self->continued_map = PyMem_Calloc(ynum, sizeof(bool)); self->line_attrs = PyMem_Calloc(ynum, sizeof(line_attrs_type));
self->line = alloc_line(); self->line = alloc_line();
if (self->buf == NULL || self->line_map == NULL || self->scratch == NULL || self->continued_map == NULL || self->line == NULL) { if (self->buf == NULL || self->line_map == NULL || self->scratch == NULL || self->line_attrs == NULL || self->line == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
PyMem_Free(self->buf); PyMem_Free(self->line_map); PyMem_Free(self->continued_map); Py_CLEAR(self->line); PyMem_Free(self->buf); PyMem_Free(self->line_map); PyMem_Free(self->line_attrs); Py_CLEAR(self->line);
Py_CLEAR(self); Py_CLEAR(self);
} else { } else {
self->line->xnum = xnum; self->line->xnum = xnum;
@@ -85,7 +88,7 @@ static void
dealloc(LineBuf* self) { dealloc(LineBuf* self) {
PyMem_Free(self->buf); PyMem_Free(self->buf);
PyMem_Free(self->line_map); PyMem_Free(self->line_map);
PyMem_Free(self->continued_map); PyMem_Free(self->line_attrs);
PyMem_Free(self->scratch); PyMem_Free(self->scratch);
Py_CLEAR(self->line); Py_CLEAR(self->line);
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
@@ -100,7 +103,8 @@ void
linebuf_init_line(LineBuf *self, index_type idx) { linebuf_init_line(LineBuf *self, index_type idx) {
self->line->ynum = idx; self->line->ynum = idx;
self->line->xnum = self->xnum; self->line->xnum = self->xnum;
self->line->continued = self->continued_map[idx]; self->line->continued = self->line_attrs[idx] & CONTINUED_MASK ? true : false;
self->line->has_dirty_text = self->line_attrs[idx] & TEXT_DIRTY_MASK ? true : false;
init_line(self, self->line, self->line_map[idx]); init_line(self, self->line, self->line_map[idx]);
} }
@@ -126,6 +130,7 @@ void
linebuf_set_attribute(LineBuf *self, unsigned int shift, unsigned int val) { linebuf_set_attribute(LineBuf *self, unsigned int shift, unsigned int val) {
for (index_type y = 0; y < self->ynum; y++) { for (index_type y = 0; y < self->ynum; y++) {
set_attribute_on_line(lineptr(self, y), shift, val, self->xnum); set_attribute_on_line(lineptr(self, y), shift, val, self->xnum);
self->line_attrs[y] |= TEXT_DIRTY_MASK;
} }
} }
@@ -146,7 +151,8 @@ set_continued(LineBuf *self, PyObject *args) {
int val; int val;
if (!PyArg_ParseTuple(args, "Ip", &y, &val)) return NULL; if (!PyArg_ParseTuple(args, "Ip", &y, &val)) return NULL;
if (y >= self->ynum) { PyErr_SetString(PyExc_ValueError, "Out of bounds."); return NULL; } if (y >= self->ynum) { PyErr_SetString(PyExc_ValueError, "Out of bounds."); return NULL; }
self->continued_map[y] = val & 1; if (val) self->line_attrs[y] |= CONTINUED_MASK;
else self->line_attrs[y] &= ~CONTINUED_MASK;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -172,7 +178,8 @@ create_line_copy_inner(LineBuf* self, index_type y) {
src.xnum = self->xnum; line->xnum = self->xnum; src.xnum = self->xnum; line->xnum = self->xnum;
if (!allocate_line_storage(line, 0)) { Py_CLEAR(line); return PyErr_NoMemory(); } if (!allocate_line_storage(line, 0)) { Py_CLEAR(line); return PyErr_NoMemory(); }
line->ynum = y; line->ynum = y;
line->continued = self->continued_map[y]; line->continued = self->line_attrs[y] & CONTINUED_MASK ? true : false;
line->has_dirty_text = self->line_attrs[y] & TEXT_DIRTY_MASK ? true : false;
init_line(self, &src, self->line_map[y]); init_line(self, &src, self->line_map[y]);
copy_line(&src, line); copy_line(&src, line);
return (PyObject*)line; return (PyObject*)line;
@@ -194,7 +201,8 @@ copy_line_to(LineBuf *self, PyObject *args) {
if (!PyArg_ParseTuple(args, "IO!", &y, &Line_Type, &dest)) return NULL; if (!PyArg_ParseTuple(args, "IO!", &y, &Line_Type, &dest)) return NULL;
src.xnum = self->xnum; dest->xnum = self->xnum; src.xnum = self->xnum; dest->xnum = self->xnum;
dest->ynum = y; dest->ynum = y;
dest->continued = self->continued_map[y]; dest->continued = self->line_attrs[y] & CONTINUED_MASK;
dest->has_dirty_text = self->line_attrs[y] & TEXT_DIRTY_MASK;
init_line(self, &src, self->line_map[y]); init_line(self, &src, self->line_map[y]);
copy_line(&src, dest); copy_line(&src, dest);
Py_RETURN_NONE; Py_RETURN_NONE;
@@ -204,13 +212,14 @@ static inline void
clear_line_(Line *l, index_type xnum) { clear_line_(Line *l, index_type xnum) {
memset(l->cells, 0, xnum * sizeof(Cell)); memset(l->cells, 0, xnum * sizeof(Cell));
if (BLANK_CHAR != 0) clear_chars_in_line(l->cells, xnum, BLANK_CHAR); if (BLANK_CHAR != 0) clear_chars_in_line(l->cells, xnum, BLANK_CHAR);
l->has_dirty_text = false;
} }
void linebuf_clear_line(LineBuf *self, index_type y) { void linebuf_clear_line(LineBuf *self, index_type y) {
Line l; Line l;
init_line(self, &l, self->line_map[y]); init_line(self, &l, self->line_map[y]);
clear_line_(&l, self->xnum); clear_line_(&l, self->xnum);
self->continued_map[y] = 0; self->line_attrs[y] = 0;
} }
static PyObject* static PyObject*
@@ -225,13 +234,13 @@ clear_line(LineBuf *self, PyObject *val) {
void linebuf_index(LineBuf* self, index_type top, index_type bottom) { void linebuf_index(LineBuf* self, index_type top, index_type bottom) {
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return; if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
index_type old_top = self->line_map[top]; index_type old_top = self->line_map[top];
bool old_cont = self->continued_map[top]; line_attrs_type old_attrs = self->line_attrs[top];
for (index_type i = top; i < bottom; i++) { for (index_type i = top; i < bottom; i++) {
self->line_map[i] = self->line_map[i + 1]; self->line_map[i] = self->line_map[i + 1];
self->continued_map[i] = self->continued_map[i + 1]; self->line_attrs[i] = self->line_attrs[i + 1];
} }
self->line_map[bottom] = old_top; self->line_map[bottom] = old_top;
self->continued_map[bottom] = old_cont; self->line_attrs[bottom] = old_attrs;
} }
static PyObject* static PyObject*
@@ -246,13 +255,13 @@ index(LineBuf *self, PyObject *args) {
void linebuf_reverse_index(LineBuf *self, index_type top, index_type bottom) { void linebuf_reverse_index(LineBuf *self, index_type top, index_type bottom) {
if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return; if (top >= self->ynum - 1 || bottom >= self->ynum || bottom <= top) return;
index_type old_bottom = self->line_map[bottom]; index_type old_bottom = self->line_map[bottom];
bool old_cont = self->continued_map[bottom]; line_attrs_type old_attrs = self->line_attrs[bottom];
for (index_type i = bottom; i > top; i--) { for (index_type i = bottom; i > top; i--) {
self->line_map[i] = self->line_map[i - 1]; self->line_map[i] = self->line_map[i - 1];
self->continued_map[i] = self->continued_map[i - 1]; self->line_attrs[i] = self->line_attrs[i - 1];
} }
self->line_map[top] = old_bottom; self->line_map[top] = old_bottom;
self->continued_map[top] = old_cont; self->line_attrs[top] = old_attrs;
} }
static PyObject* static PyObject*
@@ -270,11 +279,12 @@ is_continued(LineBuf *self, PyObject *val) {
#define is_continued_doc "is_continued(y) -> Whether the line y is continued or not" #define is_continued_doc "is_continued(y) -> Whether the line y is continued or not"
unsigned long y = PyLong_AsUnsignedLong(val); unsigned long y = PyLong_AsUnsignedLong(val);
if (y >= self->ynum) { PyErr_SetString(PyExc_ValueError, "Out of bounds."); return NULL; } if (y >= self->ynum) { PyErr_SetString(PyExc_ValueError, "Out of bounds."); return NULL; }
if (self->continued_map[y]) { Py_RETURN_TRUE; } if (self->line_attrs[y] & CONTINUED_MASK) { Py_RETURN_TRUE; }
Py_RETURN_FALSE; Py_RETURN_FALSE;
} }
void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom) { void
linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsigned int bottom) {
index_type i; index_type i;
if (y >= self->ynum || y > bottom || bottom >= self->ynum) return; if (y >= self->ynum || y > bottom || bottom >= self->ynum) return;
index_type ylimit = bottom + 1; index_type ylimit = bottom + 1;
@@ -285,9 +295,9 @@ void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsig
} }
for (i = ylimit - 1; i >= y + num; i--) { for (i = ylimit - 1; i >= y + num; i--) {
self->line_map[i] = self->line_map[i - num]; self->line_map[i] = self->line_map[i - num];
self->continued_map[i] = self->continued_map[i - num]; self->line_attrs[i] = self->line_attrs[i - num];
} }
if (y + num < self->ynum) self->continued_map[y + num] = 0; if (y + num < self->ynum) self->line_attrs[y + num] = 0;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
self->line_map[y + i] = self->scratch[ylimit - num + i]; self->line_map[y + i] = self->scratch[ylimit - num + i];
} }
@@ -295,7 +305,7 @@ void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsig
for (i = y; i < y + num; i++) { for (i = y; i < y + num; i++) {
init_line(self, &l, self->line_map[i]); init_line(self, &l, self->line_map[i]);
clear_line_(&l, self->xnum); clear_line_(&l, self->xnum);
self->continued_map[i] = 0; self->line_attrs[i] = 0;
} }
} }
} }
@@ -320,9 +330,9 @@ linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bot
} }
for (i = y; i < ylimit && i + num < self->ynum; i++) { for (i = y; i < ylimit && i + num < self->ynum; i++) {
self->line_map[i] = self->line_map[i + num]; self->line_map[i] = self->line_map[i + num];
self->continued_map[i] = self->continued_map[i + num]; self->line_attrs[i] = self->line_attrs[i + num];
} }
self->continued_map[y] = 0; self->line_attrs[y] = 0;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
self->line_map[ylimit - num + i] = self->scratch[y + i]; self->line_map[ylimit - num + i] = self->scratch[y + i];
} }
@@ -330,7 +340,7 @@ linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bot
for (i = ylimit - num; i < ylimit; i++) { for (i = ylimit - num; i < ylimit; i++) {
init_line(self, &l, self->line_map[i]); init_line(self, &l, self->line_map[i]);
clear_line_(&l, self->xnum); clear_line_(&l, self->xnum);
self->continued_map[i] = 0; self->line_attrs[i] = 0;
} }
} }
@@ -349,7 +359,7 @@ as_ansi(LineBuf *self, PyObject *callback) {
static Py_UCS4 t[5120]; static Py_UCS4 t[5120];
Line l = {.xnum=self->xnum}; Line l = {.xnum=self->xnum};
for(index_type i = 0; i < self->ynum; i++) { for(index_type i = 0; i < self->ynum; i++) {
l.continued = (i < self->ynum - 1) ? self->continued_map[i+1] : self->continued_map[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]); init_line(self, (&l), self->line_map[i]);
index_type num = line_as_ansi(&l, t, 5120); index_type num = line_as_ansi(&l, t, 5120);
if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n if (!(l.continued) && num < 5119) t[num++] = 10; // 10 = \n
@@ -439,7 +449,7 @@ copy_old(LineBuf *self, PyObject *y) {
for (index_type i = 0; i < MIN(self->ynum, other->ynum); i++) { for (index_type i = 0; i < MIN(self->ynum, other->ynum); i++) {
index_type s = self->ynum - 1 - i, o = other->ynum - 1 - i; index_type s = self->ynum - 1 - i, o = other->ynum - 1 - i;
self->continued_map[s] = other->continued_map[o]; self->line_attrs[s] = other->line_attrs[o];
s = self->line_map[s]; o = other->line_map[o]; s = self->line_map[s]; o = other->line_map[o];
init_line(self, &sl, s); init_line(other, &ol, o); init_line(self, &sl, s); init_line(other, &ol, o);
copy_line(&ol, &sl); copy_line(&ol, &sl);
@@ -457,7 +467,7 @@ linebuf_rewrap(LineBuf *self, LineBuf *other, index_type *num_content_lines_befo
// Fast path // Fast path
if (other->xnum == self->xnum && other->ynum == self->ynum) { if (other->xnum == self->xnum && other->ynum == self->ynum) {
memcpy(other->line_map, self->line_map, sizeof(index_type) * self->ynum); memcpy(other->line_map, self->line_map, sizeof(index_type) * self->ynum);
memcpy(other->continued_map, self->continued_map, sizeof(bool) * self->ynum); memcpy(other->line_attrs, self->line_attrs, sizeof(bool) * self->ynum);
memcpy(other->buf, self->buf, self->xnum * self->ynum * sizeof(Cell)); memcpy(other->buf, self->buf, self->xnum * self->ynum * sizeof(Cell));
*num_content_lines_before = self->ynum; *num_content_lines_after = self->ynum; *num_content_lines_before = self->ynum; *num_content_lines_after = self->ynum;
return; return;

View File

@@ -34,11 +34,11 @@
linebuf_clear_line(dest, dest->ynum - 1); \ linebuf_clear_line(dest, dest->ynum - 1); \
} else dest_y++; \ } else dest_y++; \
init_dest_line(dest_y); \ init_dest_line(dest_y); \
dest->continued_map[dest_y] = continued; dest->line_attrs[dest_y] = continued ? CONTINUED_MASK : 0;
#endif #endif
#ifndef is_src_line_continued #ifndef is_src_line_continued
#define is_src_line_continued(src_y) (src_y < src->ynum - 1 ? src->continued_map[src_y + 1] : false) #define is_src_line_continued(src_y) (src_y < src->ynum - 1 ? (src->line_attrs[src_y + 1] & CONTINUED_MASK) : false)
#endif #endif
static inline void static inline void

View File

@@ -275,7 +275,7 @@ screen_draw(Screen *self, uint32_t och) {
if (self->modes.mDECAWM) { if (self->modes.mDECAWM) {
screen_carriage_return(self); screen_carriage_return(self);
screen_linefeed(self); screen_linefeed(self);
self->linebuf->continued_map[self->cursor->y] = true; self->linebuf->line_attrs[self->cursor->y] |= CONTINUED_MASK;
} else { } else {
self->cursor->x = self->columns - char_width; self->cursor->x = self->columns - char_width;
} }