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*);
|
Cursor* cursor_copy(Cursor*);
|
||||||
void cursor_copy_to(Cursor *src, Cursor *dest);
|
void cursor_copy_to(Cursor *src, Cursor *dest);
|
||||||
void cursor_reset_display_attrs(Cursor*);
|
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);
|
uint32_t to_color(ColorProfile *, uint32_t, uint32_t);
|
||||||
|
|
||||||
PyObject* line_text_at(char_type, combining_type);
|
PyObject* line_text_at(char_type, combining_type);
|
||||||
|
|||||||
@ -331,12 +331,11 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DECSCNM:
|
case DECSCNM:
|
||||||
// Mark all displayed characters as reverse.
|
// Render screen in reverse video
|
||||||
self->modes.mDECSCNM = val;
|
if (self->modes.mDECSCNM != val) {
|
||||||
linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 0);
|
self->modes.mDECSCNM = val;
|
||||||
tracker_update_screen(self->change_tracker);
|
tracker_update_screen(self->change_tracker);
|
||||||
self->cursor->reverse = val;
|
}
|
||||||
tracker_cursor_changed(self->change_tracker);
|
|
||||||
break;
|
break;
|
||||||
case DECOM:
|
case DECOM:
|
||||||
self->modes.mDECOM = val;
|
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;
|
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;
|
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);
|
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++) {
|
for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) {
|
||||||
historybuf_init_line(self->historybuf, scrolled_by - y, self->historybuf->line);
|
historybuf_init_line(self->historybuf, scrolled_by - y, self->historybuf->line);
|
||||||
self->historybuf->line->ynum = y;
|
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) {
|
if (scrolled_by < self->lines) {
|
||||||
// Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer
|
// 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
|
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;
|
SpritePosition *sp;
|
||||||
char_type previous_ch=0, ch;
|
char_type previous_ch=0, ch;
|
||||||
uint8_t previous_width = 0;
|
uint8_t previous_width = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
const bool screen_reversed = modes->mDECSCNM;
|
||||||
|
|
||||||
size_t base = line->ynum * line->xnum * DATA_CELL_SIZE;
|
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) {
|
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;
|
char_type attrs = ch >> ATTRS_SHIFT;
|
||||||
unsigned int decoration = (attrs >> DECORATION_SHIFT) & DECORATION_MASK;
|
unsigned int decoration = (attrs >> DECORATION_SHIFT) & DECORATION_MASK;
|
||||||
unsigned int strikethrough = ((attrs >> STRIKE_SHIFT) & 1) ? 3 : 0;
|
unsigned int strikethrough = ((attrs >> STRIKE_SHIFT) & 1) ? 3 : 0;
|
||||||
|
bool reverse = ((attrs >> REVERSE_SHIFT) & 1) ^ screen_reversed;
|
||||||
data[offset] = sp->x;
|
data[offset] = sp->x;
|
||||||
data[offset+1] = sp->y;
|
data[offset+1] = sp->y;
|
||||||
data[offset+2] = sp->z;
|
data[offset+2] = sp->z;
|
||||||
data[offset+3] = to_color(color_profile, line->colors[i] & COL_MASK, default_fg);
|
data[offset+(reverse ? 4 : 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 ? 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];
|
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);
|
data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26);
|
||||||
previous_ch = ch; previous_width = (attrs) & WIDTH_MASK;
|
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;
|
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*
|
static PyObject*
|
||||||
render_dirty_cells(SpriteMap *self, PyObject *args) {
|
render_dirty_cells(SpriteMap *self, PyObject *args) {
|
||||||
#define render_dirty_cells_doc "Render all cells that are marked as dirty"
|
#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(layout, METH_VARARGS)
|
||||||
METHOD(position_for, METH_VARARGS)
|
METHOD(position_for, METH_VARARGS)
|
||||||
METHOD(render_dirty_cells, METH_VARARGS)
|
METHOD(render_dirty_cells, METH_VARARGS)
|
||||||
METHOD(update_cell_data, METH_VARARGS)
|
|
||||||
METHOD(increment, METH_NOARGS)
|
METHOD(increment, METH_NOARGS)
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|||||||
@ -97,7 +97,7 @@ update_cell_range(ChangeTracker *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
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;
|
unsigned int y;
|
||||||
Py_ssize_t start;
|
Py_ssize_t start;
|
||||||
default_fg &= COL_MASK;
|
default_fg &= COL_MASK;
|
||||||
@ -105,7 +105,7 @@ bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm,
|
|||||||
|
|
||||||
#define UPDATE_RANGE(xstart, xmax) \
|
#define UPDATE_RANGE(xstart, xmax) \
|
||||||
linebuf_init_line(lb, y); \
|
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) {
|
if (self->screen_changed || force_screen_refresh) {
|
||||||
for (y = 0; y < self->ynum; y++) {
|
for (y = 0; y < self->ynum; y++) {
|
||||||
@ -140,24 +140,6 @@ bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm,
|
|||||||
return true;
|
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*
|
static inline PyObject*
|
||||||
get_ranges(bool *line, unsigned int xnum) {
|
get_ranges(bool *line, unsigned int xnum) {
|
||||||
PyObject *ans = PyList_New(0), *t;
|
PyObject *ans = PyList_New(0), *t;
|
||||||
@ -252,7 +234,6 @@ static PyGetSetDef getseters[] = {
|
|||||||
|
|
||||||
static PyMethodDef methods[] = {
|
static PyMethodDef methods[] = {
|
||||||
METHOD(resize, METH_VARARGS)
|
METHOD(resize, METH_VARARGS)
|
||||||
METHOD(update_cell_data, METH_VARARGS)
|
|
||||||
METHOD(reset, METH_NOARGS)
|
METHOD(reset, METH_NOARGS)
|
||||||
METHOD(cursor_changed, METH_NOARGS)
|
METHOD(cursor_changed, METH_NOARGS)
|
||||||
{"consolidate_changes", (PyCFunction)tracker_consolidate_changes, 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);
|
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
||||||
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
|
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