Start work on connecting CSI callbacks

This commit is contained in:
Kovid Goyal 2016-11-16 13:40:38 +05:30
parent e50fc2067c
commit d0c2821339
3 changed files with 53 additions and 2 deletions

View File

@ -313,6 +313,7 @@ void screen_reverse_index(Screen *self);
void screen_index(Screen *self);
void screen_reset(Screen *self);
void screen_set_tab_stop(Screen *self);
void screen_insert_characters(Screen *self, unsigned int count);
#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

@ -6,6 +6,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include "data-types.h"
#include "control-codes.h"
@ -214,6 +215,26 @@ HANDLER(esc) {
// }}}
// Parse CSI {{{
#define MAX_PARAMS 8
static inline unsigned int fill_params(Screen *screen, unsigned int *params, unsigned int expect) {
unsigned int start_pos = 1, i = 1, pi = 0;
uint8_t ch;
screen->parser_buf[screen->parser_buf_pos++] = ';';
while (pi < MIN(MAX_PARAMS, expect) && i < PARSER_BUF_SZ - 1) {
ch = screen->parser_buf[i++];
if (ch == 0 || ch == ';') {
if (start_pos < i - 1) {
params[pi++] = atoi((const char *)screen->parser_buf + start_pos);
}
start_pos = i;
}
}
return pi;
}
HANDLER(csi) {
#define CALL_BASIC_HANDLER(name) REPORT_COMMAND(screen, ch); name(screen, ch); break;
#define HANDLE_BASIC_CH \
@ -232,8 +253,17 @@ HANDLER(csi) {
case NUL: \
case DEL: \
break; // no-op
#define CALL_CSI_HANDLER1(name) \
if (fill_params(screen, params, 1) != 1) { REPORT_ERROR("Expected parameter for CSI escape sequence: %s missing", #name); } \
else { \
REPORT_COMMAND(name, params[0]); \
screen_insert_characters(screen, params[0]); \
} \
SET_STATE(NORMAL_STATE); \
break;
uint8_t ch = buf[(*pos)++];
unsigned int params[MAX_PARAMS];
switch(screen->parser_buf_pos) {
case 0: // CSI starting
screen->parser_buf[0] = 0;
@ -250,9 +280,9 @@ HANDLER(csi) {
break;
HANDLE_BASIC_CH
default:
REPORT_ERROR("%s%d", "Invalid first character for CSI: ", (int)ch);
REPORT_ERROR("Invalid first character for CSI: 0x%x", ch);
SET_STATE(NORMAL_STATE);
return;
break;
}
break;
default: // CSI started
@ -264,12 +294,21 @@ HANDLER(csi) {
SET_STATE(NORMAL_STATE);
} else screen->parser_buf[screen->parser_buf_pos++] = ch;
break;
HANDLE_BASIC_CH
default:
REPORT_ERROR("Invalid character for CSI: 0x%x", ch);
SET_STATE(NORMAL_STATE);
break;
case ICH:
CALL_CSI_HANDLER1(screen_insert_characters);
}
break;
}
#undef CALL_BASIC_HANDLER
#undef HANDLE_BASIC_CH
#undef CALL_CSI_HANDLER1
}
#undef MAX_PARAMS
// }}}
// Parse OSC {{{

View File

@ -55,3 +55,14 @@ class TestScreen(BaseTest):
pb('\033x', 'Unknown char in escape_dispatch: %d' % ord('x'))
pb('\033c123', 'screen_reset')
self.ae(str(s.line(0)), '123 ')
def test_csi_codes(self):
s = self.create_screen()
pb = partial(self.parse_buytes_dump, s)
pb('abcde')
s.cursor_back(5)
pb('x\033[2@y', ('screen_insert_characters', 2))
self.ae(str(s.line(0)), 'xy bc')
pb('x\033[2;3@y', ('screen_insert_characters', 2))
pb('x\033[@y', 'Invalid first character for CSI: 0x%x' % ord('@'))
s.reset()