From 586304ad6c0260f24ad30a95a7ef58a91ef4aeb4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 17 Nov 2016 10:59:15 +0530 Subject: [PATCH] Implement DSR --- kitty/data-types.h | 1 + kitty/parser.c | 2 ++ kitty/screen.c | 23 +++++++++++++++++++++++ kitty_tests/parser.py | 23 +++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/kitty/data-types.h b/kitty/data-types.h index 9af24e49d..46ce2a447 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -332,6 +332,7 @@ void screen_delete_characters(Screen *self, unsigned int count); void screen_erase_characters(Screen *self, unsigned int count); 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); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen, uint8_t ch); DECLARE_CH_SCREEN_HANDLER(bell) DECLARE_CH_SCREEN_HANDLER(backspace) diff --git a/kitty/parser.c b/kitty/parser.c index c3b6ac853..b8649e29a 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -342,6 +342,8 @@ HANDLER(csi) { SET_MODE(screen_reset_mode); \ case SGR: \ CSI_HANDLER_MULTIPLE(select_graphic_rendition); \ + case DSR: \ + CALL_CSI_HANDLER1P(report_device_status, 0, '?'); \ uint8_t ch = buf[(*pos)++]; unsigned int params[MAX_PARAMS], p1, p2, count, i; diff --git a/kitty/screen.c b/kitty/screen.c index 1ae97842c..ca533dcb7 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -753,6 +753,28 @@ void report_device_attributes(Screen *self, unsigned int UNUSED mode, bool UNUSE write_to_child(self, "\x1b[?62c", 0); // Corresponds to VT-220 } +void report_device_status(Screen *self, unsigned int which, bool UNUSED private) { + // We dont implement the private device status codes, since I haven;t come + // across any programs that use them + unsigned int x, y; + char buf[50] = {0}; + switch(which) { + case 5: // device status + write_to_child(self, "\x1b[0n", 0); + break; + case 6: // cursor position + x = self->cursor->x; y = self->cursor->y; + if (x >= self->columns) { + if (y < self->lines - 1) { x = 0; y++; } + else x--; + } + if (self->modes.mDECOM) y -= MAX(y, self->margin_top); + x++; y++; // 1-based indexing + if (snprintf(buf, sizeof(buf) - 1, "\x1b[%u;%uR", y, x) > 0) write_to_child(self, buf, 0); + break; + } +} + // }}} // Python interface {{{ @@ -915,6 +937,7 @@ static PyMethodDef methods[] = { }; static PyMemberDef members[] = { + {"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"}, {"cursor", T_OBJECT_EX, offsetof(Screen, cursor), 0, "cursor"}, {"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), 0, "linebuf"}, {"lines", T_UINT, offsetof(Screen, lines), 0, "lines"}, diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index d1ccaf7c9..aff2060c8 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -17,6 +17,18 @@ class CmdDump(list): self.append(a) +class Callbacks: + + def __init__(self): + self.clear() + + def write_to_child(self, data): + self.wtcbuf += data + + def clear(self): + self.wtcbuf = b'' + + class TestScreen(BaseTest): def parse_buytes_dump(self, s, x, *cmds): @@ -93,3 +105,14 @@ class TestScreen(BaseTest): pb('\033[38;2;1;2;3;48;2;7;8;9m', ('select_graphic_rendition', 10)) self.ae(s.cursor.fg, 1 << 24 | 2 << 16 | 3 << 8 | 3) self.ae(s.cursor.bg, 7 << 24 | 8 << 16 | 9 << 8 | 3) + c = Callbacks() + s.callbacks = c + pb('\033[5n', ('report_device_status', 5, 0)) + self.ae(c.wtcbuf, b'\033[0n') + c.clear() + pb('\033[6n', ('report_device_status', 6, 0)) + self.ae(c.wtcbuf, b'\033[1;1R') + pb('12345') + c.clear() + pb('\033[6n', ('report_device_status', 6, 0)) + self.ae(c.wtcbuf, b'\033[2;1R')