Bring implementation of XTSAVE and XTRESTORE into line with xterm
Now a stack of depth 1 is used to save/restore private mode values. And saving/restoring individual modes is supported. This latter is used by midnight commander.
This commit is contained in:
parent
4c25ceff29
commit
2a8fd278c1
@ -92,10 +92,18 @@ def screen_set_mode(x: int, private: bool) -> None:
|
||||
write(CSI + ('?' if private else '') + str(x) + 'h')
|
||||
|
||||
|
||||
def screen_save_mode(x: int, private: bool) -> None:
|
||||
write(CSI + ('?' if private else '') + str(x) + 's')
|
||||
|
||||
|
||||
def screen_reset_mode(x: int, private: bool) -> None:
|
||||
write(CSI + ('?' if private else '') + str(x) + 'l')
|
||||
|
||||
|
||||
def screen_restore_mode(x: int, private: bool) -> None:
|
||||
write(CSI + ('?' if private else '') + str(x) + 'r')
|
||||
|
||||
|
||||
def screen_set_margins(t: int, b: int) -> None:
|
||||
write(CSI + '%d;%dr' % (t, b))
|
||||
|
||||
|
||||
@ -885,9 +885,11 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
||||
REPORT_COMMAND(screen_save_cursor);
|
||||
screen_save_cursor(screen);
|
||||
break;
|
||||
} else if (start_modifier == '?' && !end_modifier && !num_params) {
|
||||
REPORT_COMMAND(screen_save_modes);
|
||||
screen_save_modes(screen);
|
||||
} else if (start_modifier == '?' && !end_modifier) {
|
||||
if (!num_params) {
|
||||
REPORT_COMMAND(screen_save_modes);
|
||||
screen_save_modes(screen);
|
||||
} else { SET_MODE(screen_save_mode); }
|
||||
break;
|
||||
}
|
||||
REPORT_ERROR("Unknown CSI s sequence with start and end modifiers: '%c' '%c' and %u parameters", start_modifier, end_modifier, num_params);
|
||||
@ -949,9 +951,11 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
||||
if (!start_modifier && !end_modifier) {
|
||||
// DECSTBM
|
||||
CALL_CSI_HANDLER2(screen_set_margins, 0, 0);
|
||||
} else if (start_modifier == '?' && !end_modifier && !num_params) {
|
||||
REPORT_COMMAND(screen_restore_modes);
|
||||
screen_restore_modes(screen);
|
||||
} else if (start_modifier == '?' && !end_modifier) {
|
||||
if (!num_params) {
|
||||
REPORT_COMMAND(screen_restore_modes);
|
||||
screen_restore_modes(screen);
|
||||
} else { SET_MODE(screen_restore_mode); }
|
||||
break;
|
||||
}
|
||||
REPORT_ERROR("Unknown CSI r sequence with start and end modifiers: '%c' '%c' and %u parameters", start_modifier, end_modifier, num_params);
|
||||
|
||||
@ -105,6 +105,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
if (self->write_buf == NULL) { Py_CLEAR(self); return PyErr_NoMemory(); }
|
||||
self->write_buf_sz = BUFSIZ;
|
||||
self->modes = empty_modes;
|
||||
self->saved_modes = empty_modes;
|
||||
self->is_dirty = true;
|
||||
self->scroll_changed = false;
|
||||
self->margin_top = 0; self->margin_bottom = self->lines - 1;
|
||||
@ -163,6 +164,7 @@ screen_reset(Screen *self) {
|
||||
clear_hyperlink_pool(self->hyperlink_pool);
|
||||
grman_clear(self->grman, false, self->cell_size);
|
||||
self->modes = empty_modes;
|
||||
self->saved_modes = empty_modes;
|
||||
self->active_hyperlink_id = 0;
|
||||
#define R(name) self->color_profile->overridden.name = 0
|
||||
R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg);
|
||||
@ -912,7 +914,7 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
||||
case DECOM:
|
||||
self->modes.mDECOM = val;
|
||||
// According to `vttest`, DECOM should also home the cursor, see
|
||||
// vttest/main.c:303.
|
||||
// vttest/main.c:369.
|
||||
screen_cursor_position(self, 1, 1);
|
||||
break;
|
||||
case DECAWM:
|
||||
@ -1295,11 +1297,71 @@ screen_save_cursor(Screen *self) {
|
||||
sp->is_valid = true;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_specific_mode(Screen *self, unsigned int mode, const ScreenModes *src, ScreenModes *dest) {
|
||||
#define SIMPLE_MODE(name) case name: dest->m##name = src->m##name; break;
|
||||
#define SIDE_EFFECTS(name) case name: if (do_side_effects) set_mode_from_const(self, name, src->m##name); else dest->m##name = src->m##name; break;
|
||||
|
||||
const bool do_side_effects = dest == &self->modes;
|
||||
|
||||
switch(mode) {
|
||||
SIMPLE_MODE(LNM) // kitty extension
|
||||
SIMPLE_MODE(IRM) // kitty extension
|
||||
SIMPLE_MODE(DECARM)
|
||||
SIMPLE_MODE(BRACKETED_PASTE)
|
||||
SIMPLE_MODE(FOCUS_TRACKING)
|
||||
SIMPLE_MODE(DECCKM)
|
||||
SIMPLE_MODE(DECTCEM)
|
||||
SIMPLE_MODE(DECAWM)
|
||||
case MOUSE_BUTTON_TRACKING: case MOUSE_MOTION_TRACKING: case MOUSE_MOVE_TRACKING:
|
||||
dest->mouse_tracking_mode = src->mouse_tracking_mode; break;
|
||||
case MOUSE_UTF8_MODE: case MOUSE_SGR_MODE: case MOUSE_URXVT_MODE:
|
||||
dest->mouse_tracking_protocol = src->mouse_tracking_protocol; break;
|
||||
case DECSCLM:
|
||||
case DECNRCM:
|
||||
break; // we ignore these modes
|
||||
case DECSCNM:
|
||||
if (dest->mDECSCNM != src->mDECSCNM) {
|
||||
dest->mDECSCNM = src->mDECSCNM;
|
||||
if (do_side_effects) self->is_dirty = true;
|
||||
}
|
||||
break;
|
||||
SIDE_EFFECTS(DECOM)
|
||||
SIDE_EFFECTS(DECCOLM)
|
||||
}
|
||||
#undef SIMPLE_MODE
|
||||
#undef SIDE_EFFECTS
|
||||
}
|
||||
|
||||
void
|
||||
screen_save_mode(Screen *self, unsigned int mode) { // XTSAVE
|
||||
copy_specific_mode(self, mode, &self->modes, &self->saved_modes);
|
||||
}
|
||||
|
||||
void
|
||||
screen_restore_mode(Screen *self, unsigned int mode) { // XTRESTORE
|
||||
copy_specific_mode(self, mode, &self->saved_modes, &self->modes);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_specific_modes(Screen *self, const ScreenModes *src, ScreenModes *dest) {
|
||||
copy_specific_mode(self, LNM, src, dest);
|
||||
copy_specific_mode(self, IRM, src, dest);
|
||||
copy_specific_mode(self, DECARM, src, dest);
|
||||
copy_specific_mode(self, BRACKETED_PASTE, src, dest);
|
||||
copy_specific_mode(self, FOCUS_TRACKING, src, dest);
|
||||
copy_specific_mode(self, DECCKM, src, dest);
|
||||
copy_specific_mode(self, DECTCEM, src, dest);
|
||||
copy_specific_mode(self, DECAWM, src, dest);
|
||||
copy_specific_mode(self, MOUSE_BUTTON_TRACKING, src, dest);
|
||||
copy_specific_mode(self, MOUSE_UTF8_MODE, src, dest);
|
||||
copy_specific_mode(self, DECSCNM, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
screen_save_modes(Screen *self) {
|
||||
ScreenModes *m;
|
||||
buffer_push(&self->modes_savepoints, m);
|
||||
*m = self->modes;
|
||||
// kitty extension to XTSAVE that saves a bunch of no side-effect modes
|
||||
copy_specific_modes(self, &self->modes, &self->saved_modes);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1323,15 +1385,8 @@ screen_restore_cursor(Screen *self) {
|
||||
|
||||
void
|
||||
screen_restore_modes(Screen *self) {
|
||||
const ScreenModes *m;
|
||||
buffer_pop(&self->modes_savepoints, m);
|
||||
if (m == NULL) m = &empty_modes;
|
||||
#define S(name) set_mode_from_const(self, name, m->m##name)
|
||||
S(DECTCEM); S(DECSCNM); S(DECSCNM); S(DECOM); S(DECAWM); S(DECARM); S(DECCKM);
|
||||
S(BRACKETED_PASTE); S(FOCUS_TRACKING);
|
||||
self->modes.mouse_tracking_mode = m->mouse_tracking_mode;
|
||||
self->modes.mouse_tracking_protocol = m->mouse_tracking_protocol;
|
||||
#undef S
|
||||
// kitty extension to XTRESTORE that saves a bunch of no side-effect modes
|
||||
copy_specific_modes(self, &self->saved_modes, &self->modes);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@ -67,11 +67,6 @@ typedef struct {
|
||||
} Savepoint;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ScreenModes buf[SAVEPOINTS_SZ];
|
||||
index_type start_of_data, count;
|
||||
} SavemodesBuffer;
|
||||
|
||||
typedef struct {
|
||||
CPUCell *cpu_cells;
|
||||
GPUCell *gpu_cells;
|
||||
@ -98,14 +93,13 @@ typedef struct {
|
||||
bool use_latin1, is_dirty, scroll_changed, reload_all_gpu_data;
|
||||
Cursor *cursor;
|
||||
Savepoint main_savepoint, alt_savepoint;
|
||||
SavemodesBuffer modes_savepoints;
|
||||
PyObject *callbacks, *test_child;
|
||||
LineBuf *linebuf, *main_linebuf, *alt_linebuf;
|
||||
GraphicsManager *grman, *main_grman, *alt_grman;
|
||||
HistoryBuf *historybuf;
|
||||
unsigned int history_line_added_count;
|
||||
bool *tabstops, *main_tabstops, *alt_tabstops;
|
||||
ScreenModes modes;
|
||||
ScreenModes modes, saved_modes;
|
||||
ColorProfile *color_profile;
|
||||
monotonic_t start_visual_bell_at;
|
||||
|
||||
@ -143,7 +137,9 @@ void screen_align(Screen*);
|
||||
void screen_restore_cursor(Screen *);
|
||||
void screen_save_cursor(Screen *);
|
||||
void screen_restore_modes(Screen *);
|
||||
void screen_restore_mode(Screen *, unsigned int);
|
||||
void screen_save_modes(Screen *);
|
||||
void screen_save_mode(Screen *, unsigned int);
|
||||
bool write_escape_code_to_child(Screen *self, unsigned char which, const char *data);
|
||||
void screen_cursor_position(Screen*, unsigned int, unsigned int);
|
||||
void screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user