diff --git a/kitty/data-types.h b/kitty/data-types.h index 5b7ba18e4..523531951 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -361,6 +361,7 @@ void screen_set_margins(Screen *self, unsigned int top, unsigned int bottom); void set_title(Screen *self, PyObject*); void set_icon(Screen *self, PyObject*); void set_dynamic_color(Screen *self, unsigned int code, PyObject*); +void screen_request_capabilities(Screen *, PyObject *); void report_device_attributes(Screen *self, unsigned int UNUSED mode, bool UNUSED secondary); void select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count); void report_device_status(Screen *self, unsigned int which, bool UNUSED); diff --git a/kitty/parser.c b/kitty/parser.c index 9d538e53b..351e92a04 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -204,29 +204,31 @@ dispatch_osc(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { if (i < limit - 1 && screen->parser_buf[i] == ';') i++; } PyObject *string = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, screen->parser_buf + i, limit - i); - switch(code) { - case 0: - DISPATCH_OSC(set_title); - DISPATCH_OSC(set_icon); - break; - case 1: - DISPATCH_OSC(set_icon); - break; - case 2: - DISPATCH_OSC(set_title); - break; - case 10: - case 11: - case 110: - case 111: - REPORT_OSC(set_dynamic_color, string); - set_dynamic_color(screen, code, string); - break; - default: - REPORT_ERROR("Unknown OSC code: %u", code); - break; + if (string != NULL) { + switch(code) { + case 0: + DISPATCH_OSC(set_title); + DISPATCH_OSC(set_icon); + break; + case 1: + DISPATCH_OSC(set_icon); + break; + case 2: + DISPATCH_OSC(set_title); + break; + case 10: + case 11: + case 110: + case 111: + REPORT_OSC(set_dynamic_color, string); + set_dynamic_color(screen, code, string); + break; + default: + REPORT_ERROR("Unknown OSC code: %u", code); + break; + } + Py_CLEAR(string); } - Py_CLEAR(string); #undef DISPATCH_OSC } // }}} @@ -376,8 +378,26 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { // DCS mode {{{ static inline void -dispatch_dcs(Screen *screen) { - screen->parser_buf_pos++; +dispatch_dcs(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { + PyObject *string = NULL; + if (screen->parser_buf_pos < 2) return; + switch(screen->parser_buf[0]) { + case '+': + if (screen->parser_buf[1] == 'q') { + string = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, screen->parser_buf + 2, screen->parser_buf_pos - 2); + if (string != NULL) { + REPORT_OSC(screen_request_capabilities, string); + screen_request_capabilities(screen, string); + Py_CLEAR(string); + } + } else { + REPORT_ERROR("Unrecognized DCS+ code: 0x%x", screen->parser_buf[1]); + } + break; + default: + REPORT_ERROR("Unrecognized DCS code: 0x%x", screen->parser_buf[0]); + break; + } } // }}} @@ -521,7 +541,7 @@ _parse_bytes(Screen *screen, uint8_t *buf, Py_ssize_t len, PyObject DUMP_UNUSED if (accumulate_osc(screen, codepoint, dump_callback)) { dispatch_osc(screen, dump_callback); SET_STATE(0); } break; case DCS: - if (accumulate_dcs(screen, codepoint, dump_callback)) { dispatch_dcs(screen); SET_STATE(0); } + if (accumulate_dcs(screen, codepoint, dump_callback)) { dispatch_dcs(screen, dump_callback); SET_STATE(0); } if (screen->parser_state == ESC) { HANDLE(esc_mode_char); } break; default: diff --git a/kitty/screen.c b/kitty/screen.c index 2e614fa39..33a524220 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -810,6 +810,11 @@ void set_dynamic_color(Screen *self, unsigned int code, PyObject *color) { if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } } +void screen_request_capabilities(Screen *self, PyObject *q) { + PyObject_CallMethod(self->callbacks, "request_capabilities", "O", q); + if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } +} + // }}} // Python interface {{{ diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index 2c50916ec..9f65002be 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -32,9 +32,12 @@ class Callbacks: def set_dynamic_color(self, code, data): self.colorbuf += data + def request_capabilities(self, q): + self.qbuf += q + def clear(self): self.wtcbuf = b'' - self.iconbuf = self.titlebuf = self.colorbuf = '' + self.iconbuf = self.titlebuf = self.colorbuf = self.qbuf = '' class TestParser(BaseTest): @@ -168,5 +171,5 @@ class TestParser(BaseTest): def test_dcs_codes(self): s = self.create_screen() pb = partial(self.parse_bytes_dump, s) - pb('a\033P2;xyz\x9cbcde', 'abcde') + pb('a\033P+q436f\x9cbcde', 'a', ('screen_request_capabilities', '436f'), 'bcde') self.ae(str(s.line(0)), 'abcde')