mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-23 08:47:47 +02:00
Allow parameter less CSI sequences
This commit is contained in:
@@ -314,6 +314,12 @@ void screen_index(Screen *self);
|
|||||||
void screen_reset(Screen *self);
|
void screen_reset(Screen *self);
|
||||||
void screen_set_tab_stop(Screen *self);
|
void screen_set_tab_stop(Screen *self);
|
||||||
void screen_insert_characters(Screen *self, unsigned int count);
|
void screen_insert_characters(Screen *self, unsigned int count);
|
||||||
|
void screen_cursor_up(Screen *self, unsigned int count/*=1*/, bool do_carriage_return/*=false*/, int move_direction/*=-1*/);
|
||||||
|
void screen_cursor_to_column(Screen *self, unsigned int column);
|
||||||
|
void screen_cursor_down(Screen *self, unsigned int count/*=1*/);
|
||||||
|
void screen_cursor_forward(Screen *self, unsigned int count/*=1*/);
|
||||||
|
void screen_cursor_down1(Screen *self, unsigned int count/*=1*/);
|
||||||
|
void screen_cursor_up1(Screen *self, unsigned int count/*=1*/);
|
||||||
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen, uint8_t ch);
|
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen, uint8_t ch);
|
||||||
DECLARE_CH_SCREEN_HANDLER(bell)
|
DECLARE_CH_SCREEN_HANDLER(bell)
|
||||||
DECLARE_CH_SCREEN_HANDLER(backspace)
|
DECLARE_CH_SCREEN_HANDLER(backspace)
|
||||||
|
|||||||
@@ -220,10 +220,10 @@ HANDLER(esc) {
|
|||||||
|
|
||||||
static inline unsigned int fill_params(Screen *screen, unsigned int *params, unsigned int expect) {
|
static inline unsigned int fill_params(Screen *screen, unsigned int *params, unsigned int expect) {
|
||||||
unsigned int start_pos = 1, i = 1, pi = 0;
|
unsigned int start_pos = 1, i = 1, pi = 0;
|
||||||
uint8_t ch;
|
uint8_t ch = 1;
|
||||||
screen->parser_buf[screen->parser_buf_pos++] = ';';
|
screen->parser_buf[screen->parser_buf_pos] = 0;
|
||||||
|
|
||||||
while (pi < MIN(MAX_PARAMS, expect) && i < PARSER_BUF_SZ - 1) {
|
while (pi < MIN(MAX_PARAMS, expect) && i < PARSER_BUF_SZ - 1 && ch != 0) {
|
||||||
ch = screen->parser_buf[i++];
|
ch = screen->parser_buf[i++];
|
||||||
if (ch == 0 || ch == ';') {
|
if (ch == 0 || ch == ';') {
|
||||||
if (start_pos < i - 1) {
|
if (start_pos < i - 1) {
|
||||||
@@ -235,6 +235,9 @@ static inline unsigned int fill_params(Screen *screen, unsigned int *params, uns
|
|||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void screen_cursor_up2(Screen *s, unsigned int count) { screen_cursor_up(s, count, false, -1); }
|
||||||
|
static inline void screen_cursor_back1(Screen *s, unsigned int count) { screen_cursor_back(s, count, -1); }
|
||||||
|
|
||||||
HANDLER(csi) {
|
HANDLER(csi) {
|
||||||
#define CALL_BASIC_HANDLER(name) REPORT_COMMAND(screen, ch); name(screen, ch); break;
|
#define CALL_BASIC_HANDLER(name) REPORT_COMMAND(screen, ch); name(screen, ch); break;
|
||||||
#define HANDLE_BASIC_CH \
|
#define HANDLE_BASIC_CH \
|
||||||
@@ -253,17 +256,44 @@ HANDLER(csi) {
|
|||||||
case NUL: \
|
case NUL: \
|
||||||
case DEL: \
|
case DEL: \
|
||||||
break; // no-op
|
break; // no-op
|
||||||
#define CALL_CSI_HANDLER1(name) \
|
#define CALL_CSI_HANDLER1(name, defval) \
|
||||||
if (fill_params(screen, params, 1) != 1) { REPORT_ERROR("Expected parameter for CSI escape sequence: %s missing", #name); } \
|
p1 = fill_params(screen, params, 1) > 0 ? params[0] : defval; \
|
||||||
else { \
|
REPORT_COMMAND(name, p1); \
|
||||||
REPORT_COMMAND(name, params[0]); \
|
name(screen, p1); \
|
||||||
screen_insert_characters(screen, params[0]); \
|
|
||||||
} \
|
|
||||||
SET_STATE(NORMAL_STATE); \
|
SET_STATE(NORMAL_STATE); \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#define CALL_CSI_HANDLER2(name, defval1, defval2) \
|
||||||
|
count = fill_params(screen, params, 2); \
|
||||||
|
p1 = count > 0 ? params[0] : defval1; \
|
||||||
|
p2 = count > 1 ? params[1] : defval2; \
|
||||||
|
REPORT_COMMAND(name, p1, p2); \
|
||||||
|
name(screen, p1, p2); \
|
||||||
|
SET_STATE(NORMAL_STATE); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
#define DISPATCH_CSI \
|
||||||
|
case ICH: \
|
||||||
|
CALL_CSI_HANDLER1(screen_insert_characters, 1); \
|
||||||
|
case CUU: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_up2, 1); \
|
||||||
|
case CUD: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_down, 1); \
|
||||||
|
case CUF: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_forward, 1); \
|
||||||
|
case CUB: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_back1, 1); \
|
||||||
|
case CNL: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_down1, 1); \
|
||||||
|
case CPL: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_up1, 1); \
|
||||||
|
case CHA: \
|
||||||
|
CALL_CSI_HANDLER1(screen_cursor_to_column, 1); \
|
||||||
|
case CUP: \
|
||||||
|
CALL_CSI_HANDLER2(screen_cursor_position, 1, 1);
|
||||||
|
|
||||||
uint8_t ch = buf[(*pos)++];
|
uint8_t ch = buf[(*pos)++];
|
||||||
unsigned int params[MAX_PARAMS];
|
unsigned int params[MAX_PARAMS], p1, p2, count;
|
||||||
switch(screen->parser_buf_pos) {
|
switch(screen->parser_buf_pos) {
|
||||||
case 0: // CSI starting
|
case 0: // CSI starting
|
||||||
screen->parser_buf[0] = 0;
|
screen->parser_buf[0] = 0;
|
||||||
@@ -279,6 +309,7 @@ HANDLER(csi) {
|
|||||||
screen->parser_buf[0] = ch; screen->parser_buf_pos = 1;
|
screen->parser_buf[0] = ch; screen->parser_buf_pos = 1;
|
||||||
break;
|
break;
|
||||||
HANDLE_BASIC_CH
|
HANDLE_BASIC_CH
|
||||||
|
DISPATCH_CSI
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Invalid first character for CSI: 0x%x", ch);
|
REPORT_ERROR("Invalid first character for CSI: 0x%x", ch);
|
||||||
SET_STATE(NORMAL_STATE);
|
SET_STATE(NORMAL_STATE);
|
||||||
@@ -295,12 +326,11 @@ HANDLER(csi) {
|
|||||||
} else screen->parser_buf[screen->parser_buf_pos++] = ch;
|
} else screen->parser_buf[screen->parser_buf_pos++] = ch;
|
||||||
break;
|
break;
|
||||||
HANDLE_BASIC_CH
|
HANDLE_BASIC_CH
|
||||||
|
DISPATCH_CSI
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Invalid character for CSI: 0x%x", ch);
|
REPORT_ERROR("Invalid character for CSI: 0x%x", ch);
|
||||||
SET_STATE(NORMAL_STATE);
|
SET_STATE(NORMAL_STATE);
|
||||||
break;
|
break;
|
||||||
case ICH:
|
|
||||||
CALL_CSI_HANDLER1(screen_insert_characters);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -399,6 +399,15 @@ void screen_cursor_down1(Screen *self, unsigned int count/*=1*/) {
|
|||||||
screen_cursor_up(self, count, true, 1);
|
screen_cursor_up(self, count, true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void screen_cursor_to_column(Screen *self, unsigned int column) {
|
||||||
|
unsigned int x = MAX(column, 1) - 1;
|
||||||
|
if (x != (unsigned int)self->cursor->x) {
|
||||||
|
self->cursor->x = x;
|
||||||
|
screen_ensure_bounds(self, false);
|
||||||
|
tracker_cursor_changed(self->change_tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void screen_index(Screen *self) {
|
void screen_index(Screen *self) {
|
||||||
// Move cursor down one line, scrolling screen if needed
|
// Move cursor down one line, scrolling screen if needed
|
||||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||||
@@ -485,8 +494,8 @@ void screen_ensure_bounds(Screen *self, bool use_margins/*=false*/) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
void screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
||||||
line = (line || 1) - 1;
|
line = (line == 0 ? 1 : line) - 1;
|
||||||
column = (column || 1) - 1;
|
column = (column == 0 ? 1: column) - 1;
|
||||||
if (self->modes.mDECOM) {
|
if (self->modes.mDECOM) {
|
||||||
line += self->margin_top;
|
line += self->margin_top;
|
||||||
if (line < self->margin_bottom || line > self->margin_top) return;
|
if (line < self->margin_bottom || line > self->margin_top) return;
|
||||||
|
|||||||
@@ -63,6 +63,14 @@ class TestScreen(BaseTest):
|
|||||||
s.cursor_back(5)
|
s.cursor_back(5)
|
||||||
pb('x\033[2@y', ('screen_insert_characters', 2))
|
pb('x\033[2@y', ('screen_insert_characters', 2))
|
||||||
self.ae(str(s.line(0)), 'xy bc')
|
self.ae(str(s.line(0)), 'xy bc')
|
||||||
pb('x\033[2;3@y', ('screen_insert_characters', 2))
|
pb('x\033[2;7@y', ('screen_insert_characters', 2))
|
||||||
pb('x\033[@y', 'Invalid first character for CSI: 0x%x' % ord('@'))
|
pb('x\033[@y', ('screen_insert_characters', 1))
|
||||||
|
pb('x\033[345@y', ('screen_insert_characters', 345))
|
||||||
|
pb('x\033[345;@y', ('screen_insert_characters', 345))
|
||||||
|
pb('\033[H', ('screen_cursor_position', 1, 1))
|
||||||
|
self.ae(s.cursor.x, 0), self.ae(s.cursor.y, 0)
|
||||||
|
pb('\033[4H', ('screen_cursor_position', 4, 1))
|
||||||
|
pb('\033[3;2H', ('screen_cursor_position', 3, 2))
|
||||||
|
pb('\033[3;2;H', ('screen_cursor_position', 3, 2))
|
||||||
|
self.ae(s.cursor.x, 1), self.ae(s.cursor.y, 2)
|
||||||
s.reset()
|
s.reset()
|
||||||
|
|||||||
Reference in New Issue
Block a user