From 81172299261518f1790c1504280f24b56f24f44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Fri, 18 Aug 2017 00:38:46 +0200 Subject: [PATCH] moving some stuff around, removed "soft reset" seq, added server-side support for control key remaps --- user/ansi_parser_callbacks.c | 15 +- user/screen.c | 375 +++++++++++++++-------------------- user/screen.h | 13 +- user/wifimgr.c | 5 - 4 files changed, 171 insertions(+), 237 deletions(-) diff --git a/user/ansi_parser_callbacks.c b/user/ansi_parser_callbacks.c index b3e67fe..b67bfd5 100644 --- a/user/ansi_parser_callbacks.c +++ b/user/ansi_parser_callbacks.c @@ -251,13 +251,13 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar) int n = params[i]; if (leadchar == '?') { if (n == 25) { - screen_cursor_enable(yn); + screen_cursor_visible(yn); } else if (n == 7) { screen_wrap_enable(yn); } else if (n == 1) { - screen_set_cursor_application_mode(yn); + screen_set_cursors_alt_mode(yn); } else { ansi_warn("NOIMPL DEC opt %d", n); @@ -370,13 +370,6 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar) ansi_warn("NOIMPL cursor back tab"); break; - case 'p': - if (leadchar == '!') { - info("SOFT RESET!"); - screen_reset(); // TODO do soft reset - } - break; - case 'c': // CSI-c // report capabilities (pretend we're vt4xx) UART_WriteString(UART0, "\033[?64;22;c", UART_TIMEOUT_US); @@ -436,7 +429,7 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c) break; case '>': - screen_set_keypad_application_mode(false); + screen_set_numpad_alt_mode(false); break; case '<': @@ -444,7 +437,7 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c) break; case '=': - screen_set_keypad_application_mode(true); + screen_set_numpad_alt_mode(true); break; default: diff --git a/user/screen.c b/user/screen.c index 2e2fede..b01534e 100644 --- a/user/screen.c +++ b/user/screen.c @@ -3,8 +3,6 @@ #include "screen.h" #include "persist.h" -//region Data structures - TerminalConfigBundle * const termconf = &persist.current.termconf; TerminalConfigBundle termconf_scratch; @@ -35,55 +33,52 @@ typedef struct __attribute__((packed)){ static Cell screen[MAX_SCREEN_SIZE]; /** - * Cursor position and attributes + * Screen state structure */ static struct { - int x; //!< X coordinate - int y; //!< Y coordinate - bool hanging; //!< xenl state + bool numpad_alt_mode; //!< Application Mode - affects how user input of control keys is sent + bool cursors_alt_mode; //!< Application mode for cursor keys - bool autowrap; //!< Wrapping when EOL - bool insert_mode; //!< Insert mode (move rest of the line to the right) + char charset0; + char charset1; +} scr; - // TODO use those for input processing - bool kp_alternate; //!< Application Mode - affects how user input of control keys is sent - bool curs_alternate; //!< Application mode for cursor keys +typedef struct { + int x; //!< X coordinate + int y; //!< Y coordinate + bool hanging; //!< xenl state - cursor half-wrapped - bool visible; //!< Visible (not attribute, DEC special) - bool inverse; + // SGR + bool inverse; //!< not in attrs bc it's applied server-side (not sent to browser) u8 attrs; + Color fg; //!< Foreground color for writing + Color bg; //!< Background color for writing - char charset0; - char charset1; + // Other attribs int charsetN; + bool wraparound; //!< Wrapping when EOL - Color fg; //!< Foreground color for writing - Color bg; //!< Background color for writing -} cursor; + // Not saved/restored + bool insert_mode; //!< Insert mode (move rest of the line to the right) + bool visible; //!< Visible (not attribute, DEC special) +} CursorTypeDef; /** - * Saved cursor position, used with the SCP RCP commands + * Cursor position and attributes */ -static struct { - int x; - int y; - bool hanging; //!< xenl state +static CursorTypeDef cursor; - // mark that attrs are saved - bool withAttrs; - u8 attrs; - bool inverse; // attribute that's not in the bitfield - Color fg; - Color bg; -} cursor_sav; +/** + * Saved cursor position, used with the SCP RCP commands + */ +static CursorTypeDef cursor_sav; -// XXX volatile is probably not needed +/** + * This is used to prevent premature change notifications + * (from nested calls) + */ static volatile int notifyLock = 0; -//endregion - -//region Helpers - #define NOTIFY_LOCK() do { \ notifyLock++; \ } while(0) @@ -93,7 +88,12 @@ static volatile int notifyLock = 0; if (notifyLock == 0) screen_notifyChange(CHANGE_CONTENT); \ } while(0) -#define clear_invalid_hanging() do { if (cursor.hanging && cursor.x != W-1) cursor.hanging = false; } while(false) +/** Clear the hanging attribute if the cursor is no longer >= W */ +#define clear_invalid_hanging() do { \ + if (cursor.hanging && cursor.x != W-1) cursor.hanging = false; \ + } while(false) + +//region --- Settings --- /** * Restore hard defaults @@ -133,29 +133,19 @@ void terminal_apply_settings_noclear(void) screen_init(); } } +//endregion + +//region --- Reset / Init --- /** - * Clear range, inclusive + * Init the screen (entire mappable area - for consistency) */ -static inline void -clear_range(unsigned int from, unsigned int to) +void ICACHE_FLASH_ATTR +screen_init(void) { - if (to >= W*H) to = W*H-1; - Color fg = (cursor.inverse) ? cursor.bg : cursor.fg; - Color bg = (cursor.inverse) ? cursor.fg : cursor.bg; - - Cell sample; - sample.c[0] = ' '; - sample.c[1] = 0; - sample.c[2] = 0; - sample.c[3] = 0; - sample.fg = fg; - sample.bg = bg; - sample.attrs = 0; - - for (unsigned int i = from; i <= to; i++) { - memcpy(&screen[i], &sample, sizeof(Cell)); - } + NOTIFY_LOCK(); + screen_reset(); + NOTIFY_DONE(); } /** @@ -164,63 +154,77 @@ clear_range(unsigned int from, unsigned int to) static void ICACHE_FLASH_ATTR cursor_reset(void) { - // TODO this should probably be public and invoked by "soft reset" - cursor.x = 0; cursor.y = 0; cursor.hanging = false; - cursor.fg = termconf_scratch.default_fg; - cursor.bg = termconf_scratch.default_bg; cursor.visible = true; - cursor.autowrap = true; - cursor.attrs = false; cursor.insert_mode = false; - cursor.kp_alternate = false; - cursor.curs_alternate = false; - - cursor.charset0 = 'B'; - cursor.charset1 = '0'; cursor.charsetN = 0; -} + cursor.wraparound = true; -//endregion - -//region Screen clearing + screen_reset_sgr(); +} /** - * Init the screen (entire mappable area - for consistency) + * Reset the cursor (\e[0m) */ void ICACHE_FLASH_ATTR -screen_init(void) +screen_reset_sgr(void) { - NOTIFY_LOCK(); - screen_reset(); - NOTIFY_DONE(); + cursor.fg = termconf_scratch.default_fg; + cursor.bg = termconf_scratch.default_bg; + cursor.attrs = 0; + cursor.inverse = false; } /** - * Reset the screen (only the visible area) + * Reset the screen - called by ESC c */ void ICACHE_FLASH_ATTR screen_reset(void) { NOTIFY_LOCK(); + cursor_reset(); + + scr.numpad_alt_mode = false; + scr.cursors_alt_mode = false; + + scr.charset0 = 'B'; + scr.charset1 = '0'; + + // size is left unchanged screen_clear(CLEAR_ALL); + NOTIFY_DONE(); } +//endregion + +//region --- Clearing & inserting --- /** - * Reset the cursor + * Clear range, inclusive */ -void ICACHE_FLASH_ATTR -screen_reset_sgr(void) +static inline void +clear_range(unsigned int from, unsigned int to) { - cursor.fg = termconf_scratch.default_fg; - cursor.bg = termconf_scratch.default_bg; - cursor.attrs = 0; - cursor.inverse = false; + if (to >= W*H) to = W*H-1; + Color fg = (cursor.inverse) ? cursor.bg : cursor.fg; + Color bg = (cursor.inverse) ? cursor.fg : cursor.bg; + + Cell sample; + sample.c[0] = ' '; + sample.c[1] = 0; + sample.c[2] = 0; + sample.c[3] = 0; + sample.fg = fg; + sample.bg = bg; + sample.attrs = 0; + + for (unsigned int i = from; i <= to; i++) { + memcpy(&screen[i], &sample, sizeof(Cell)); + } } /** @@ -282,29 +286,6 @@ screen_clear_in_line(unsigned int count) } } -void ICACHE_FLASH_ATTR -screen_fill_with_E(void) -{ - NOTIFY_LOCK(); - Cell sample; - sample.c[0] = 'E'; - sample.c[1] = 0; - sample.c[2] = 0; - sample.c[3] = 0; - sample.fg = termconf_scratch.default_fg; - sample.bg = termconf_scratch.default_bg; - sample.attrs = 0; - - for (unsigned int i = 0; i <= W*H-1; i++) { - memcpy(&screen[i], &sample, sizeof(Cell)); - } - NOTIFY_DONE(); -} - -//endregion - -//region Screen manipulation - void screen_insert_lines(unsigned int lines) { NOTIFY_LOCK(); @@ -383,6 +364,28 @@ void screen_delete_characters(unsigned int count) } NOTIFY_DONE(); } +//endregion + +//region --- Entire screen manipulation --- + +void ICACHE_FLASH_ATTR +screen_fill_with_E(void) +{ + NOTIFY_LOCK(); + Cell sample; + sample.c[0] = 'E'; + sample.c[1] = 0; + sample.c[2] = 0; + sample.c[3] = 0; + sample.fg = termconf_scratch.default_fg; + sample.bg = termconf_scratch.default_bg; + sample.attrs = 0; + + for (unsigned int i = 0; i <= W*H-1; i++) { + memcpy(&screen[i], &sample, sizeof(Cell)); + } + NOTIFY_DONE(); +} /** * Change the screen size @@ -408,7 +411,7 @@ screen_resize(int rows, int cols) W = cols; H = rows; screen_reset(); -done: + done: NOTIFY_DONE(); } @@ -436,7 +439,7 @@ screen_scroll_up(unsigned int lines) clear_range(y * W, W * H - 1); -done: + done: NOTIFY_DONE(); } @@ -463,13 +466,12 @@ screen_scroll_down(unsigned int lines) } clear_range(0, lines * W-1); -done: + done: NOTIFY_DONE(); } - //endregion -//region Cursor manipulation +//region --- Cursor manipulation --- /** * Set cursor position @@ -563,21 +565,8 @@ screen_cursor_move(int dy, int dx, bool scroll) void ICACHE_FLASH_ATTR screen_cursor_save(bool withAttrs) { - cursor_sav.x = cursor.x; - cursor_sav.y = cursor.y; - cursor_sav.hanging = cursor.hanging; - - cursor_sav.withAttrs = withAttrs; - - if (withAttrs) { - cursor_sav.fg = cursor.fg; - cursor_sav.bg = cursor.bg; - cursor_sav.attrs = cursor.attrs; - } else { - cursor_sav.fg = termconf_scratch.default_fg; - cursor_sav.bg = termconf_scratch.default_bg; - cursor_sav.attrs = 0; // avoid leftovers if the wrong restore is used - } + // always save with attribs + memcpy(&cursor_sav, &cursor, sizeof(CursorTypeDef)); } /** @@ -587,27 +576,29 @@ void ICACHE_FLASH_ATTR screen_cursor_restore(bool withAttrs) { NOTIFY_LOCK(); - cursor.x = cursor_sav.x; - cursor.y = cursor_sav.y; - cursor.hanging = cursor_sav.hanging; if (withAttrs) { - cursor.fg = cursor_sav.fg; - cursor.bg = cursor_sav.bg; - cursor.attrs = cursor_sav.attrs; + memcpy(&cursor_sav, &cursor, sizeof(CursorTypeDef)); + } else { + cursor.x = cursor_sav.x; + cursor.y = cursor_sav.y; + cursor.hanging = cursor_sav.hanging; } NOTIFY_DONE(); } +//endregion + +//region --- Attribute setting --- /** * Enable cursor display */ void ICACHE_FLASH_ATTR -screen_cursor_enable(bool enable) +screen_cursor_visible(bool visible) { NOTIFY_LOCK(); - cursor.visible = enable; + cursor.visible = visible; NOTIFY_DONE(); } @@ -617,15 +608,9 @@ screen_cursor_enable(bool enable) void ICACHE_FLASH_ATTR screen_wrap_enable(bool enable) { - NOTIFY_LOCK(); - cursor.autowrap = enable; - NOTIFY_DONE(); + cursor.wraparound = enable; } -//endregion - -//region Colors - /** * Set cursor foreground color */ @@ -664,8 +649,6 @@ screen_inverse_enable(bool ena) cursor.inverse = ena; } -//endregion - /** * Check if coords are in range * @@ -689,8 +672,8 @@ screen_set_charset_n(int Gx) void ICACHE_FLASH_ATTR screen_set_charset(int Gx, char charset) { - if (Gx == 0) cursor.charset0 = charset; - if (Gx == 1) cursor.charset1 = charset; + if (Gx == 0) scr.charset0 = charset; + if (Gx == 1) scr.charset1 = charset; } void ICACHE_FLASH_ATTR @@ -700,16 +683,19 @@ screen_set_insert_mode(bool insert) } void ICACHE_FLASH_ATTR -screen_set_keypad_application_mode(bool app_mode) +screen_set_numpad_alt_mode(bool alt_mode) { - cursor.kp_alternate = app_mode; + scr.numpad_alt_mode = alt_mode; } void ICACHE_FLASH_ATTR -screen_set_cursor_application_mode(bool app_mode) +screen_set_cursors_alt_mode(bool alt_mode) { - cursor.curs_alternate = app_mode; + scr.cursors_alt_mode = alt_mode; } +//endregion + +//region --- Printing --- /** * Set a character in the cursor color, move to right with wrap. @@ -768,7 +754,7 @@ screen_putchar(const char *ch) if (cursor.hanging) { // perform the scheduled wrap if hanging // if autowrap = off, it overwrites the last char - if (cursor.autowrap) { + if (cursor.wraparound) { cursor.x = 0; cursor.y++; // Y wrap @@ -789,7 +775,7 @@ screen_putchar(const char *ch) if (ch[1] == 0 && ch[0] <= 0x7f) { // we have len=1 and ASCII - utf8_remap(c->c, ch[0], (cursor.charsetN == 0) ? cursor.charset0 : cursor.charset1); + utf8_remap(c->c, ch[0], (cursor.charsetN == 0) ? scr.charset0 : scr.charset1); } else { // copy unicode char @@ -812,7 +798,7 @@ screen_putchar(const char *ch) cursor.x = W - 1; } -done: + done: NOTIFY_DONE(); } @@ -821,32 +807,32 @@ done: * Based on rxvt-unicode screen.C table. */ static const u16 vt100_to_unicode[62] = -{ + { // ? ? ? ? ? ? ? // A=UPARR B=DNARR C=RTARR D=LFARR E=FLBLK F=3/4BL G=SNOMN - 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, + 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // H= I= J= K= L= M= N= - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, // O= P= Q= R= S= T= U= - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, // V= W= X= Y= Z= [= \= - 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, // ? ? v->0 v->1 v->2 v->3 v->4 // ]= ^= _=SPC `=DIAMN a=HSMED b=HT c=FF - 0, 0, 0x0020, 0x25c6, 0x2592, 0x2409, 0x240c, + 0, 0, 0x0020, 0x25c6, 0x2592, 0x2409, 0x240c, // v->5 v->6 v->7 v->8 v->9 v->a v->b // d=CR e=LF f=DEGRE g=PLSMN h=NL i=VT j=SL-BR - 0x240d, 0x240a, 0x00b0, 0x00b1, 0x2424, 0x240b, 0x2518, + 0x240d, 0x240a, 0x00b0, 0x00b1, 0x2424, 0x240b, 0x2518, // v->c v->d v->e v->f v->10 v->11 v->12 // k=SL-TR l=SL-TL m=SL-BL n=SL-+ o=SL-T1 p=SL-T2 q=SL-HZ - 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, 0x23bb, 0x2500, + 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, 0x23bb, 0x2500, // v->13 v->14 v->15 v->16 v->17 v->18 v->19 // r=SL-T4 s=SL-T5 t=SL-VR u=SL-VL v=SL-HU w=Sl-HD x=SL-VT - 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, 0x2502, + 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, 0x2502, // v->1a v->1b b->1c v->1d v->1e/a3 v->1f // y=LT-EQ z=GT-EQ {=PI |=NOTEQ }=POUND ~=DOT - 0x2264, 0x2265, 0x03c0, 0x2260, 0x20a4, 0x00b7 -}; + 0x2264, 0x2265, 0x03c0, 0x2260, 0x20a4, 0x00b7 + }; /** * UTF remap @@ -899,45 +885,9 @@ utf8_remap(char *out, char g, char table) out[1] = 0; } } +//endregion - - -//region Serialization - -#if 0 -/** - * Debug dump - */ -void screen_dd(void) -{ - for (int y = 0; y < H; y++) { - for (int x = 0; x < W; x++) { - Cell *cell = &screen[y * W + x]; - - // FG - printf("\033["); - if (cell->fg > 7) { - printf("%d", 90 + cell->fg - 8); - } else { - printf("%d", 30 + cell->fg); - } - printf("m"); - - // BG - printf("\033["); - if (cell->bg > 7) { - printf("%d", 100 + cell->bg - 8); - } else { - printf("%d", 40 + cell->bg); - } - printf("m"); - - printf("%c", cell->c); - } - printf("\033[0m\n"); - } -} -#endif +//region --- Serialization --- struct ScreenSerializeState { Color lastFg; @@ -1020,7 +970,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data) char *bb = buffer; // Ideally we'd use snprintf here! - #define bufprint(fmt, ...) do { \ +#define bufprint(fmt, ...) do { \ used = sprintf(bb, fmt, ##__VA_ARGS__); \ if(used>0) { bb += used; remain -= used; } \ } while(0) @@ -1038,11 +988,13 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data) encode2B((u16) cursor.y, &w3); encode2B((u16) cursor.x, &w4); encode2B((u16) ( - cursor.fg | - (cursor.bg<<4) | - (cursor.visible ? 1<<8 : 0) | - (cursor.hanging ? 1<<9 : 0) - ) + cursor.fg | + (cursor.bg<<4) | + (cursor.visible ? 1<<8 : 0) | + (cursor.hanging ? 1<<9 : 0) | + (scr.cursors_alt_mode ? 1<<10 : 0) | + (scr.numpad_alt_mode ? 1<<11 : 0) + ) , &w5); // H W X Y Attribs @@ -1056,10 +1008,10 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data) // Count how many times same as previous int repCnt = 0; while (i < W*H - && cell->fg == ss->lastFg - && cell->bg == ss->lastBg - && cell->attrs == ss->lastAttrs - && strneq(cell->c, ss->lastChar, 4)) { + && cell->fg == ss->lastFg + && cell->bg == ss->lastBg + && cell->attrs == ss->lastAttrs + && strneq(cell->c, ss->lastChar, 4)) { // Repeat repCnt++; cell = &screen[++i]; @@ -1116,5 +1068,4 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data) return HTTPD_CGI_DONE; } - //endregion diff --git a/user/screen.h b/user/screen.h index 750d3e0..65838bb 100644 --- a/user/screen.h +++ b/user/screen.h @@ -80,12 +80,7 @@ void terminal_restore_defaults(void); void terminal_apply_settings(void); void terminal_apply_settings_noclear(void); // the same, but with no screen reset / init -/** - * Maximum screen size (determines size of the static data array) - * - * TODO May need adjusting if there are size problems when flashing the ESP. - * We could also try to pack the Cell struct to a single 32bit word. - */ +/** Maximum screen size (determines size of the static data array) */ #define MAX_SCREEN_SIZE (80*30) typedef enum { @@ -161,7 +156,7 @@ void screen_cursor_save(bool withAttrs); /** Restore the cursor pos */ void screen_cursor_restore(bool withAttrs); /** Enable cursor display */ -void screen_cursor_enable(bool enable); +void screen_cursor_visible(bool visible); /** Enable auto wrap */ void screen_wrap_enable(bool enable); @@ -181,9 +176,9 @@ void screen_inverse_enable(bool ena); /** Toggle INSERT / REPLACE */ void screen_set_insert_mode(bool insert); /** Toggle application keypad mode */ -void screen_set_keypad_application_mode(bool app_mode); +void screen_set_numpad_alt_mode(bool app_mode); /** Toggle application cursor mode */ -void screen_set_cursor_application_mode(bool app_mode); +void screen_set_cursors_alt_mode(bool app_mode); void screen_set_charset_n(int Gx); void screen_set_charset(int Gx, char charset); diff --git a/user/wifimgr.c b/user/wifimgr.c index 5cfe327..058c45e 100644 --- a/user/wifimgr.c +++ b/user/wifimgr.c @@ -43,11 +43,6 @@ wifimgr_restore_defaults(void) IP4_ADDR(&wificonf->sta_addr.ip, 192, 168, 0, (mac[5] == 1 ? 2 : mac[5])); // avoid being the same as "default gw" IP4_ADDR(&wificonf->sta_addr.netmask, 255, 255, 255, 0); IP4_ADDR(&wificonf->sta_addr.gw, 192, 168, 0, 1); - - // DEBUG ONLY - TODO remove for release -// wificonf->opmode = STATION_MODE; -// sprintf((char*)wificonf->sta_ssid, "Chlivek"); -// sprintf((char*)wificonf->sta_password, "prase chrochta"); } static void ICACHE_FLASH_ATTR