Implement reverse video and DECSCNM
This commit is contained in:
parent
f0b1af964b
commit
f71e266764
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
};
|
||||
|
||||
@ -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, ""},
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user