From f71e266764a139c73dc2bd2d2314507e853e2bca Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 30 Nov 2016 11:12:34 +0530 Subject: [PATCH] Implement reverse video and DECSCNM --- kitty/data-types.h | 2 +- kitty/screen.c | 15 +++++++-------- kitty/sprites.c | 23 +++++------------------ kitty/tracker.c | 23 ++--------------------- kitty/tracker.h | 2 +- 5 files changed, 16 insertions(+), 49 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index befa12953..88c36f1e3 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -307,7 +307,7 @@ void cursor_reset(Cursor*); Cursor* cursor_copy(Cursor*); void cursor_copy_to(Cursor *src, Cursor *dest); void cursor_reset_display_attrs(Cursor*); -bool update_cell_range_data(SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, const uint32_t, const uint32_t, unsigned int *); +bool update_cell_range_data(ScreenModes *modes, SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, const uint32_t, const uint32_t, unsigned int *); uint32_t to_color(ColorProfile *, uint32_t, uint32_t); PyObject* line_text_at(char_type, combining_type); diff --git a/kitty/screen.c b/kitty/screen.c index eb435e3c1..e87e5b045 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -331,12 +331,11 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) { } break; case DECSCNM: - // Mark all displayed characters as reverse. - self->modes.mDECSCNM = val; - linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 0); - tracker_update_screen(self->change_tracker); - self->cursor->reverse = val; - tracker_cursor_changed(self->change_tracker); + // Render screen in reverse video + if (self->modes.mDECSCNM != val) { + self->modes.mDECSCNM = val; + tracker_update_screen(self->change_tracker); + } break; case DECOM: self->modes.mDECOM = val; @@ -965,7 +964,7 @@ screen_update_cell_data(Screen *self, PyObject *args) { PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False; unsigned int history_line_added_count = self->change_tracker->history_line_added_count; - if (!tracker_update_cell_data(self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; + if (!tracker_update_cell_data(&(self->modes), self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; return Py_BuildValue("OI", cursor_changed, history_line_added_count); } @@ -985,7 +984,7 @@ set_scroll_cell_data(Screen *self, PyObject *args) { for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) { historybuf_init_line(self->historybuf, scrolled_by - y, self->historybuf->line); self->historybuf->line->ynum = y; - if (!update_cell_range_data(spm, self->historybuf->line, 0, self->columns - 1, color_profile, default_bg, default_fg, data)) return NULL; + if (!update_cell_range_data(&(self->modes), spm, self->historybuf->line, 0, self->columns - 1, color_profile, default_bg, default_fg, data)) return NULL; } if (scrolled_by < self->lines) { // Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer diff --git a/kitty/sprites.c b/kitty/sprites.c index 9c4c21ed5..89b1a88f3 100644 --- a/kitty/sprites.c +++ b/kitty/sprites.c @@ -140,11 +140,12 @@ position_for(SpriteMap *self, PyObject *args) { } bool -update_cell_range_data(SpriteMap *self, Line *line, unsigned int xstart, unsigned int xmax, ColorProfile *color_profile, const uint32_t default_bg, const uint32_t default_fg, unsigned int *data) { +update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned int xstart, unsigned int xmax, ColorProfile *color_profile, const uint32_t default_bg, const uint32_t default_fg, unsigned int *data) { SpritePosition *sp; char_type previous_ch=0, ch; uint8_t previous_width = 0; int err = 0; + const bool screen_reversed = modes->mDECSCNM; size_t base = line->ynum * line->xnum * DATA_CELL_SIZE; for (size_t i = xstart, offset = base + xstart * DATA_CELL_SIZE; i <= xmax; i++, offset += DATA_CELL_SIZE) { @@ -155,11 +156,12 @@ update_cell_range_data(SpriteMap *self, Line *line, unsigned int xstart, unsigne char_type attrs = ch >> ATTRS_SHIFT; unsigned int decoration = (attrs >> DECORATION_SHIFT) & DECORATION_MASK; unsigned int strikethrough = ((attrs >> STRIKE_SHIFT) & 1) ? 3 : 0; + bool reverse = ((attrs >> REVERSE_SHIFT) & 1) ^ screen_reversed; data[offset] = sp->x; data[offset+1] = sp->y; data[offset+2] = sp->z; - data[offset+3] = to_color(color_profile, line->colors[i] & COL_MASK, default_fg); - data[offset+4] = to_color(color_profile, line->colors[i] >> COL_SHIFT, default_bg); + data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->colors[i] & COL_MASK, default_fg); + data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->colors[i] >> COL_SHIFT, default_bg); unsigned int decoration_fg = decoration > 1 ? to_color(color_profile, line->decoration_fg[i] & COL_MASK, data[offset+3]) : data[offset+3]; data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26); previous_ch = ch; previous_width = (attrs) & WIDTH_MASK; @@ -167,20 +169,6 @@ update_cell_range_data(SpriteMap *self, Line *line, unsigned int xstart, unsigne return true; } -static PyObject* -update_cell_data(SpriteMap *self, PyObject *args) { -#define update_cell_data_doc "update_cell_data(line, xstart, xmax, color_profile, default_bg, default_fg, data_pointer) -> Update the range [xstart, xmax] in data_pointer with the data from line" - unsigned int xstart, xmax; - uint32_t default_fg, default_bg; - Line *line; ColorProfile *color_profile; - PyObject *data_pointer; - - if (!PyArg_ParseTuple(args, "O!IIO!IIO!", &Line_Type, &line, &xstart, &xmax, &ColorProfile_Type, &color_profile, &default_bg, &default_fg, &PyLong_Type, &data_pointer)) return NULL; - unsigned int *dp = PyLong_AsVoidPtr(data_pointer); - if (!update_cell_range_data(self, line, xstart, xmax, color_profile, default_bg, default_fg, dp)) return NULL; - Py_RETURN_NONE; -} - static PyObject* render_dirty_cells(SpriteMap *self, PyObject *args) { #define render_dirty_cells_doc "Render all cells that are marked as dirty" @@ -230,7 +218,6 @@ static PyMethodDef methods[] = { METHOD(layout, METH_VARARGS) METHOD(position_for, METH_VARARGS) METHOD(render_dirty_cells, METH_VARARGS) - METHOD(update_cell_data, METH_VARARGS) METHOD(increment, METH_NOARGS) {NULL} /* Sentinel */ }; diff --git a/kitty/tracker.c b/kitty/tracker.c index 05db625ef..516cb1b9a 100644 --- a/kitty/tracker.c +++ b/kitty/tracker.c @@ -97,7 +97,7 @@ update_cell_range(ChangeTracker *self, PyObject *args) { Py_RETURN_NONE; } -bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm, ColorProfile *color_profile, unsigned int *data, unsigned long default_fg, unsigned long default_bg, bool force_screen_refresh) { +bool tracker_update_cell_data(ScreenModes *modes, ChangeTracker *self, LineBuf *lb, SpriteMap *spm, ColorProfile *color_profile, unsigned int *data, unsigned long default_fg, unsigned long default_bg, bool force_screen_refresh) { unsigned int y; Py_ssize_t start; default_fg &= COL_MASK; @@ -105,7 +105,7 @@ bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm, #define UPDATE_RANGE(xstart, xmax) \ linebuf_init_line(lb, y); \ - if (!update_cell_range_data(spm, lb->line, (xstart), (xmax), color_profile, default_bg, default_fg, data)) return false; + if (!update_cell_range_data(modes, spm, lb->line, (xstart), (xmax), color_profile, default_bg, default_fg, data)) return false; if (self->screen_changed || force_screen_refresh) { for (y = 0; y < self->ynum; y++) { @@ -140,24 +140,6 @@ bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm, return true; } -PyObject* -update_cell_data(ChangeTracker *self, PyObject *args) { -#define update_cell_data_doc "update_cell_data(line_buf, sprite_map, color_profile, data_ptr, default_fg, default_bg, force_screen_refresh)" - SpriteMap *spm; - LineBuf *lb; - ColorProfile *color_profile; - PyObject *dp; - unsigned int *data; - unsigned long default_bg, default_fg; - int force_screen_refresh; - if (!PyArg_ParseTuple(args, "O!O!O!O!kkp", &LineBuf_Type, &lb, &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL; - data = PyLong_AsVoidPtr(dp); - PyObject *cursor_changed = self->cursor_changed ? Py_True : Py_False; - if (!tracker_update_cell_data(self, lb, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; - Py_INCREF(cursor_changed); - return cursor_changed; -} - static inline PyObject* get_ranges(bool *line, unsigned int xnum) { PyObject *ans = PyList_New(0), *t; @@ -252,7 +234,6 @@ static PyGetSetDef getseters[] = { static PyMethodDef methods[] = { METHOD(resize, METH_VARARGS) - METHOD(update_cell_data, METH_VARARGS) METHOD(reset, METH_NOARGS) METHOD(cursor_changed, METH_NOARGS) {"consolidate_changes", (PyCFunction)tracker_consolidate_changes, METH_NOARGS, ""}, diff --git a/kitty/tracker.h b/kitty/tracker.h index 94fb3ab6a..7557e815b 100644 --- a/kitty/tracker.h +++ b/kitty/tracker.h @@ -52,4 +52,4 @@ static inline void tracker_reset(ChangeTracker *self) { PyObject* tracker_consolidate_changes(ChangeTracker *self); bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum); -bool tracker_update_cell_data(ChangeTracker *, LineBuf *, SpriteMap *, ColorProfile *, unsigned int *, unsigned long, unsigned long, bool); +bool tracker_update_cell_data(ScreenModes*, ChangeTracker *, LineBuf *, SpriteMap *, ColorProfile *, unsigned int *, unsigned long, unsigned long, bool);