Clean up the mode handling code
This commit is contained in:
parent
d6782d002b
commit
4f5daa94d0
@ -224,7 +224,9 @@ PyTypeObject ChangeTracker_Type;
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mBRACKETED_PASTE, mFOCUS_TRACKING;
|
||||
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM,
|
||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mMOUSE_BUTTON_TRACKING,
|
||||
mMOUSE_MOTION_TRACKING, mMOUSE_SGR_MODE;
|
||||
} ScreenModes;
|
||||
PyTypeObject ScreenModes_Type;
|
||||
|
||||
|
||||
@ -23,8 +23,13 @@
|
||||
|
||||
// Private modes.
|
||||
|
||||
// *Text Cursor Enable Mode*: determines if the text cursor is visible.
|
||||
#define DECTCEM (25 << 5)
|
||||
// Arrow keys send application sequences or cursor movement commands
|
||||
#define DECCKM (1 << 5)
|
||||
|
||||
// *Column Mode*: selects the number of columns per line (80 or 132)
|
||||
// on the screen.
|
||||
#define DECCOLM (3 << 5)
|
||||
|
||||
|
||||
// *Screen Mode*: toggles screen-wide reverse-video mode.
|
||||
#define DECSCNM (5 << 5)
|
||||
@ -39,23 +44,23 @@
|
||||
// when the cursor is at the right margin.
|
||||
#define DECAWM (7 << 5)
|
||||
|
||||
// *Column Mode*: selects the number of columns per line (80 or 132)
|
||||
// on the screen.
|
||||
#define DECCOLM (3 << 5)
|
||||
// Toggle cursor blinking
|
||||
#define CONTROL_CURSOR_BLINK (12 << 5)
|
||||
|
||||
// *Text Cursor Enable Mode*: determines if the text cursor is visible.
|
||||
#define DECTCEM (25 << 5)
|
||||
|
||||
// Xterm mouse protocol
|
||||
#define MOUSE_BUTTON_TRACKING (1000 << 5)
|
||||
#define MOUSE_MOTION_TRACKING (1002 << 5)
|
||||
#define FOCUS_TRACKING (1004 << 5)
|
||||
#define MOUSE_SGR_MODE (1006 << 6)
|
||||
|
||||
// Alternate screen buffer
|
||||
#define ALTERNATE_SCREEN (1049 << 5)
|
||||
|
||||
// Bracketed paste mode
|
||||
// http://cirw.in/blog/bracketed-paste
|
||||
#define BRACKETED_PASTE (2004 << 5)
|
||||
#define BRACKETED_PASTE_START "\033[200~"
|
||||
#define BRACKETED_PASTE_END "\033[201~"
|
||||
|
||||
// Alternate screen buffer
|
||||
#define ALTERNATE_SCREEN (1049 << 5)
|
||||
|
||||
// Xterm mouse protocol
|
||||
#define SEND_MOUSE_ON_PRESS_AND_RELEASE (1000 << 5)
|
||||
#define HILITE_MOUSE_TRACKING (1001 << 5)
|
||||
#define CELL_MOTION_MOUSE_TRACKING (1002 << 5)
|
||||
#define FOCUS_TRACKING (1004 << 5)
|
||||
#define SGR_MOUSE_MODE (1006 << 6)
|
||||
|
||||
|
||||
154
kitty/screen.c
154
kitty/screen.c
@ -294,105 +294,78 @@ void screen_toggle_screen_buffer(Screen *self) {
|
||||
void screen_normal_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
||||
void screen_alternate_keypad_mode(Screen UNUSED *self) {} // Not implemented as this is handled by the GUI
|
||||
|
||||
static inline void set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
||||
static inline void
|
||||
set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
||||
#define SIMPLE_MODE(name) \
|
||||
case name: \
|
||||
self->modes.m##name = val; break;
|
||||
|
||||
bool private;
|
||||
switch(mode) {
|
||||
case LNM:
|
||||
self->modes.mLNM = val; break;
|
||||
case IRM:
|
||||
self->modes.mIRM = val; break;
|
||||
SIMPLE_MODE(LNM)
|
||||
SIMPLE_MODE(IRM)
|
||||
SIMPLE_MODE(BRACKETED_PASTE)
|
||||
SIMPLE_MODE(MOUSE_BUTTON_TRACKING)
|
||||
SIMPLE_MODE(MOUSE_MOTION_TRACKING)
|
||||
SIMPLE_MODE(MOUSE_SGR_MODE)
|
||||
SIMPLE_MODE(FOCUS_TRACKING)
|
||||
|
||||
case DECCKM:
|
||||
break; // we ignore this mode
|
||||
case DECTCEM:
|
||||
self->modes.mDECTCEM = val; break;
|
||||
self->modes.mDECTCEM = val;
|
||||
if ((val && self->cursor->hidden) || (!val && !self->cursor->hidden)) {
|
||||
self->cursor->hidden = !val;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
}
|
||||
break;
|
||||
case DECSCNM:
|
||||
self->modes.mDECSCNM = val; break;
|
||||
// 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);
|
||||
break;
|
||||
case DECOM:
|
||||
self->modes.mDECOM = val; break;
|
||||
self->modes.mDECOM = val;
|
||||
// According to `vttest`, DECOM should also home the cursor, see
|
||||
// vttest/main.c:303.
|
||||
screen_cursor_position(self, 1, 1);
|
||||
break;
|
||||
case DECAWM:
|
||||
self->modes.mDECAWM = val; break;
|
||||
case DECCOLM:
|
||||
self->modes.mDECCOLM = val; break;
|
||||
case BRACKETED_PASTE:
|
||||
self->modes.mBRACKETED_PASTE = val; break;
|
||||
case FOCUS_TRACKING:
|
||||
self->modes.mFOCUS_TRACKING = val; break;
|
||||
// When DECCOLM mode is set, the screen is erased and the cursor
|
||||
// moves to the home position.
|
||||
self->modes.mDECCOLM = val;
|
||||
screen_erase_in_display(self, 2, false);
|
||||
screen_cursor_position(self, 1, 1);
|
||||
break;
|
||||
case CONTROL_CURSOR_BLINK:
|
||||
self->cursor->blink = val;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
break;
|
||||
case ALTERNATE_SCREEN:
|
||||
if (val && self->linebuf == self->main_linebuf) screen_toggle_screen_buffer(self);
|
||||
else if (!val && self->linebuf != self->main_linebuf) screen_toggle_screen_buffer(self);
|
||||
break;
|
||||
default:
|
||||
private = mode >= 1 << 5;
|
||||
if (private) mode >>= 5;
|
||||
fprintf(stderr, "%s %s %u %s\n", ERROR_PREFIX, "Unsupported screen mode: ", mode, private ? "(private)" : "");
|
||||
}
|
||||
#undef SIMPLE_MODE
|
||||
}
|
||||
|
||||
void screen_set_mode(Screen *self, unsigned int mode) {
|
||||
if (mode == DECCOLM) {
|
||||
// When DECCOLM mode is set, the screen is erased and the cursor
|
||||
// moves to the home position.
|
||||
screen_erase_in_display(self, 2, false);
|
||||
screen_cursor_position(self, 1, 1);
|
||||
}
|
||||
// According to `vttest`, DECOM should also home the cursor, see
|
||||
// vttest/main.c:303.
|
||||
if (mode == DECOM) screen_cursor_position(self, 1, 1);
|
||||
|
||||
if (mode == DECSCNM) {
|
||||
// Mark all displayed characters as reverse.
|
||||
linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 1);
|
||||
tracker_update_screen(self->change_tracker);
|
||||
self->cursor->reverse = true;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
}
|
||||
|
||||
if (mode == DECTCEM && self->cursor->hidden) {
|
||||
self->cursor->hidden = false;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
}
|
||||
|
||||
if (mode == ALTERNATE_SCREEN && self->linebuf == self->main_linebuf) {
|
||||
screen_toggle_screen_buffer(self);
|
||||
}
|
||||
set_mode_from_const(self, mode, true);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
in_bracketed_paste_mode(Screen *self) {
|
||||
#define in_bracketed_paste_mode_doc ""
|
||||
PyObject *ans = self->modes.mBRACKETED_PASTE ? Py_True : Py_False;
|
||||
Py_INCREF(ans);
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
focus_tracking_enabled(Screen *self) {
|
||||
#define focus_tracking_enabled_doc ""
|
||||
PyObject *ans = self->modes.mFOCUS_TRACKING ? Py_True : Py_False;
|
||||
Py_INCREF(ans);
|
||||
return ans;
|
||||
}
|
||||
|
||||
void screen_reset_mode(Screen *self, unsigned int mode) {
|
||||
if (mode == DECCOLM) {
|
||||
// When DECCOLM mode is set, the screen is erased and the cursor
|
||||
// moves to the home position.
|
||||
screen_erase_in_display(self, 2, false);
|
||||
screen_cursor_position(self, 1, 1);
|
||||
}
|
||||
// According to `vttest`, DECOM should also home the cursor, see
|
||||
// vttest/main.c:303.
|
||||
if (mode == DECOM) screen_cursor_position(self, 1, 1);
|
||||
|
||||
if (mode == DECSCNM) {
|
||||
// Mark all displayed characters as reverse.
|
||||
linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 0);
|
||||
tracker_update_screen(self->change_tracker);
|
||||
self->cursor->reverse = false;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
}
|
||||
|
||||
if (mode == DECTCEM && !self->cursor->hidden) {
|
||||
self->cursor->hidden = true;
|
||||
tracker_cursor_changed(self->change_tracker);
|
||||
}
|
||||
|
||||
if (mode == ALTERNATE_SCREEN && self->linebuf != self->main_linebuf) {
|
||||
screen_toggle_screen_buffer(self);
|
||||
}
|
||||
|
||||
set_mode_from_const(self, mode, false);
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
// Cursor {{{
|
||||
@ -934,6 +907,16 @@ erase_in_display(Screen *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#define MODE_GETTER(name, uname) \
|
||||
static PyObject* name(Screen *self) { PyObject *ans = self->modes.m##uname ? Py_True : Py_False; Py_INCREF(ans); return ans; }
|
||||
|
||||
MODE_GETTER(in_bracketed_paste, BRACKETED_PASTE)
|
||||
MODE_GETTER(focus_tracking_enabled, FOCUS_TRACKING)
|
||||
MODE_GETTER(mouse_button_tracking_enabled, MOUSE_BUTTON_TRACKING)
|
||||
MODE_GETTER(mouse_motion_tracking_enabled, MOUSE_MOTION_TRACKING)
|
||||
MODE_GETTER(mouse_in_sgr_mode, MOUSE_SGR_MODE)
|
||||
|
||||
|
||||
static PyObject*
|
||||
cursor_up(Screen *self, PyObject *args) {
|
||||
unsigned int count = 1;
|
||||
@ -1059,8 +1042,6 @@ static PyMethodDef methods[] = {
|
||||
METHOD(draw, METH_O)
|
||||
METHOD(set_mode, METH_VARARGS)
|
||||
METHOD(reset_mode, METH_VARARGS)
|
||||
METHOD(focus_tracking_enabled, METH_NOARGS)
|
||||
METHOD(in_bracketed_paste_mode, METH_NOARGS)
|
||||
METHOD(reset, METH_NOARGS)
|
||||
METHOD(reset_dirty, METH_NOARGS)
|
||||
METHOD(consolidate_changes, METH_NOARGS)
|
||||
@ -1085,6 +1066,11 @@ static PyMethodDef methods[] = {
|
||||
MND(mark_as_dirty, METH_NOARGS)
|
||||
MND(resize, METH_VARARGS)
|
||||
MND(set_scroll_cell_data, METH_VARARGS)
|
||||
MND(in_bracketed_paste, METH_NOARGS)
|
||||
MND(focus_tracking_enabled, METH_NOARGS)
|
||||
MND(mouse_button_tracking_enabled, METH_NOARGS)
|
||||
MND(mouse_motion_tracking_enabled, METH_NOARGS)
|
||||
MND(mouse_in_sgr_mode, METH_NOARGS)
|
||||
{"update_cell_data", (PyCFunction)screen_update_cell_data, METH_VARARGS, ""},
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
|
||||
@ -91,8 +91,8 @@ class TestParser(BaseTest):
|
||||
pb('\033[?2J', ('screen_erase_in_display', 2, 1))
|
||||
pb('\033[h')
|
||||
pb('\033[20;4h', ('screen_set_mode', 20), ('screen_set_mode', 4))
|
||||
pb('\033[?20;5h', ('screen_set_mode', 20 << 5), ('screen_set_mode', 5 << 5))
|
||||
pb('\033[20;4;145l', ('screen_reset_mode', 20), ('screen_reset_mode', 4), ('screen_reset_mode', 145))
|
||||
pb('\033[?1000;1004h', ('screen_set_mode', 1000 << 5), ('screen_set_mode', 1004 << 5))
|
||||
pb('\033[20;4;20l', ('screen_reset_mode', 20), ('screen_reset_mode', 4), ('screen_reset_mode', 20))
|
||||
s.reset()
|
||||
pb('\033[1;3;4;7;9;34;44m', ('select_graphic_rendition', 7))
|
||||
for attr in 'bold italic reverse strikethrough'.split():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user