From 8506d791786eea8ee55db5418a8f646bb2dd3a6d Mon Sep 17 00:00:00 2001 From: Leo C Date: Thu, 11 Jun 2015 17:30:49 +0200 Subject: [PATCH] VT100/ANSI parser --- avr/cli_readline.c | 270 ++++++++++++++++++++++++++++++--------------- 1 file changed, 184 insertions(+), 86 deletions(-) diff --git a/avr/cli_readline.c b/avr/cli_readline.c index 08d2c4b..8795a97 100644 --- a/avr/cli_readline.c +++ b/avr/cli_readline.c @@ -13,6 +13,7 @@ #include #include +#include #include "config.h" #include "con-utils.h" @@ -20,12 +21,180 @@ #include "command.h" #include "cli_readline.h" + + +/************************************************************************************************/ +/* TODO: + * + */ + +#define ESC 0x1b + +#define KEY_TAB '\t' // TAB key +#define KEY_CR '\r' // RETURN key +#define KEY_BACKSPACE '\b' // Backspace key +#define KEY_ESCAPE 0x1B // ESCAPE (pressed twice) + +#define KEY_DOWN 0x80 // Down arrow key +#define KEY_UP 0x81 // Up arrow key +#define KEY_LEFT 0x82 // Left arrow key +#define KEY_RIGHT 0x83 // Right arrow key +#define KEY_HOME 0x84 // Home key +#define KEY_DC 0x85 // Delete character key +#define KEY_IC 0x86 // Ins char/toggle ins mode key +#define KEY_NPAGE 0x87 // Next-page key +#define KEY_PPAGE 0x88 // Previous-page key +#define KEY_END 0x89 // End key +#define KEY_BTAB 0x8A // Back tab key +#define KEY_F1 0x8B // Function key F1 +#define KEY_F(n) (KEY_F1+(n)-1) // Space for additional 12 function keys + + +struct fkey_tbl_s { + const FLASH char *sequence; /* ESC Sequence */ + int code; /* Keycode */ +}; + +//typedef const FLASH struct fkey_tbl_s fkey_tbl_t; + +#define FKEY_TBL_ITEM(_seq, _code) { FSTR(#_seq), _code } + + + +static const FLASH struct fkey_tbl_s fkey_table[] = { + +FKEY_TBL_ITEM(B, KEY_DOWN), // Down arrow key +FKEY_TBL_ITEM(A, KEY_UP), // Up arrow key +FKEY_TBL_ITEM(D, KEY_LEFT), // Left arrow key +FKEY_TBL_ITEM(C, KEY_RIGHT), // Right arrow key +FKEY_TBL_ITEM(1~, KEY_HOME), // Home key +FKEY_TBL_ITEM(3~, KEY_DC), // Delete character key +FKEY_TBL_ITEM(2~, KEY_IC), // Ins char/toggle ins mode key +FKEY_TBL_ITEM(6~, KEY_NPAGE), // Next-page key +FKEY_TBL_ITEM(5~, KEY_PPAGE), // Previous-page key +FKEY_TBL_ITEM(4~, KEY_END), // End key +FKEY_TBL_ITEM(Z, KEY_BTAB), // Back tab key +/* VT400: */ +FKEY_TBL_ITEM(11~, KEY_F(1)), // Function key F1 +FKEY_TBL_ITEM(12~, KEY_F(2)), // Function key F2 +FKEY_TBL_ITEM(13~, KEY_F(3)), // Function key F3 +FKEY_TBL_ITEM(14~, KEY_F(4)), // Function key F4 +FKEY_TBL_ITEM(15~, KEY_F(5)), // Function key F5 +/* Linux consoe */ +FKEY_TBL_ITEM([A, KEY_F(1)), // Function key F1 +FKEY_TBL_ITEM([B, KEY_F(2)), // Function key F2 +FKEY_TBL_ITEM([C, KEY_F(3)), // Function key F3 +FKEY_TBL_ITEM([D, KEY_F(4)), // Function key F4 +FKEY_TBL_ITEM([E, KEY_F(5)), // Function key F5 + +FKEY_TBL_ITEM(17~, KEY_F(6)), // Function key F6 +FKEY_TBL_ITEM(18~, KEY_F(7)), // Function key F7 +FKEY_TBL_ITEM(19~, KEY_F(8)), // Function key F8 +FKEY_TBL_ITEM(20~, KEY_F(9)), // Function key F9 +FKEY_TBL_ITEM(21~, KEY_F(10)), // Function key F10 +FKEY_TBL_ITEM(23~, KEY_F(11)), // Function key F11 +FKEY_TBL_ITEM(24~, KEY_F(12)), // Function key F12 +{ NULL } /* Mark end of table */ +}; + + + +typedef enum { + STATE_GROUND, + STATE_ESCAPE, + STATE_CSI_ENTRY +} vtparse_state_t; + +#define CHB_SIZE 15 + +static +int vt_parse (void) +{ + static vtparse_state_t state = STATE_GROUND; + char buf[CHB_SIZE+1]; + uint8_t param[2]; + uint8_t i_buf; + uint8_t i_param; + int ch; + + + while (1) { + ch = my_getchar(1); +// debug_getch(state, ch); + + switch (state) { + case STATE_GROUND: + if (ch == ESC) { + state = STATE_ESCAPE; + continue; + } + if (ch == 0x7F) // BACKSPACE on VT200 sends DEL char + ch = KEY_BACKSPACE; // map it to '\b' + break; + case STATE_ESCAPE: + if (ch < 0) + continue; + + if (ch == '[') { + state = STATE_CSI_ENTRY; + param[0] = param[1] = 0; + i_buf = 0; + i_param = 0; + continue; + } + state = STATE_GROUND; + break; + case STATE_CSI_ENTRY: + if (ch < 0) + continue; + + buf[i_buf] = ch; + if (i_buf < CHB_SIZE) + i_buf++; + if (ch == ';') { + i_param++; + continue; + } + if (isdigit(ch)) { + if (i_param < 2) + param[i_param] = param[i_param] * 10 + ch - '0'; + continue; + } + if (ch >= '@' && ch <= '~' && ch != '[') { + buf[i_buf] = '\0'; + int_fast8_t i = 0; + while (fkey_table[i].sequence) { + if (! strcmp_P (buf, fkey_table[i].sequence)) { + ch = fkey_table[i].code; + break; + } + i++; + } + if (fkey_table[i].sequence == NULL) { + ch = '$'; /* KEY_ESCAPE; */ + } + } + state = STATE_GROUND; + break; + } + break; /* while */ + } + + return ch; +} + +/************************************************************************************************/ + + + + + char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ +#ifndef CONFIG_CMDLINE_EDITING static const FLASH char erase_seq[] = "\b \b"; /* erase sequence */ static const FLASH char tab_seq[] = " "; /* used to expand TABs */ -#ifndef CONFIG_CMDLINE_EDITING static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen) { char *s; @@ -80,7 +249,7 @@ static void putnstr(char *str, int n) #define CREAD_HIST_CHAR ('!') #define getcmd_putch(ch) putchar(ch) -#define getcmd_getch() my_getchar(1) +#define getcmd_getch() vt_parse() #define getcmd_cbeep() getcmd_putch('\a') #define HIST_MAX 5 @@ -167,26 +336,6 @@ static char *hist_next(void) return ret; } -#ifndef CONFIG_CMDLINE_EDITING -static void cread_print_hist_list(void) -{ - int i; - unsigned n; - - n = hist_num - hist_max; - - i = hist_add_idx + 1; - while (1) { - if (i > hist_max) - i = 0; - if (i == hist_add_idx) - break; - printf_P(PSTR("%s\n"), hist_list[i]); - n++; - i++; - } -} -#endif /* CONFIG_CMDLINE_EDITING */ #define BEGINNING_OF_LINE() { \ while (num) { \ @@ -261,10 +410,8 @@ static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *l unsigned int num = 0; unsigned int eol_num = 0; unsigned int wlen; - char ichar; + int ichar; int insert = 1; - int esc_len = 0; - char esc_save[8]; int init_len = strlen(buf); (void) prompt; @@ -280,82 +427,31 @@ static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *l break; } - /* - * handle standard linux xterm esc sequences for arrow key, etc. - */ - if (esc_len != 0) { - if (esc_len == 1) { - if (ichar == '[') { - esc_save[esc_len] = ichar; - esc_len = 2; - } else { - cread_add_str(esc_save, esc_len, - insert, &num, &eol_num, - buf, *len); - esc_len = 0; - } - continue; - } - - switch (ichar) { - case 'D': /* <- key */ - ichar = CTL_CH('b'); - esc_len = 0; - break; - case 'C': /* -> key */ - ichar = CTL_CH('f'); - esc_len = 0; - break; /* pass off to ^F handler */ - case 'H': /* Home key */ - ichar = CTL_CH('a'); - esc_len = 0; - break; /* pass off to ^A handler */ - case 'A': /* up arrow */ - ichar = CTL_CH('p'); - esc_len = 0; - break; /* pass off to ^P handler */ - case 'B': /* down arrow */ - ichar = CTL_CH('n'); - esc_len = 0; - break; /* pass off to ^N handler */ - default: - esc_save[esc_len++] = ichar; - cread_add_str(esc_save, esc_len, insert, - &num, &eol_num, buf, *len); - esc_len = 0; - continue; - } - } switch (ichar) { - case 0x1b: - if (esc_len == 0) { - esc_save[esc_len] = ichar; - esc_len = 1; - } else { - my_puts_P(PSTR("impossible condition #876\n")); - esc_len = 0; - } - break; + case KEY_HOME: case CTL_CH('a'): BEGINNING_OF_LINE(); break; case CTL_CH('c'): /* ^C - break */ *buf = '\0'; /* discard input */ return -1; + case KEY_RIGHT: case CTL_CH('f'): if (num < eol_num) { getcmd_putch(buf[num]); num++; } break; + case KEY_LEFT: case CTL_CH('b'): if (num) { getcmd_putch(CTL_BACKSPACE); num--; } break; + case KEY_DC: case CTL_CH('d'): if (num < eol_num) { wlen = eol_num - num - 1; @@ -377,6 +473,7 @@ static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *l case CTL_CH('e'): REFRESH_TO_EOL(); break; + case KEY_IC: case CTL_CH('o'): insert = !insert; break; @@ -401,14 +498,14 @@ static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *l eol_num--; } break; + case KEY_UP: case CTL_CH('p'): + case KEY_DOWN: case CTL_CH('n'): { char *hline; - esc_len = 0; - - if (ichar == CTL_CH('p')) + if (ichar == CTL_CH('p') || ichar == KEY_UP) hline = hist_prev(); else hline = hist_next(); @@ -453,15 +550,16 @@ static int cread_line(const FLASH char *const prompt, char *buf, unsigned int *l } #endif default: - cread_add_char(ichar, insert, &num, &eol_num, buf, - *len); + if (isprint(ichar)) + cread_add_char(ichar, insert, &num, &eol_num, buf, + *len); break; } } *len = eol_num; buf[eol_num] = '\0'; /* lose the newline */ - if (buf[0] && buf[0] != CREAD_HIST_CHAR) + if (buf[0] /* && buf[0] != CREAD_HIST_CHAR */) cread_add_to_hist(buf); hist_cur = hist_add_idx; -- 2.39.2