Implement DSR

This commit is contained in:
Kovid Goyal 2016-11-17 10:59:15 +05:30
parent 4624525419
commit 586304ad6c
4 changed files with 49 additions and 0 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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"},

View File

@ -17,6 +17,18 @@ def __call__(self, *a):
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 @@ def test_csi_codes(self):
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')