diff options
Diffstat (limited to 'deps/uv/src/win/tty.c')
-rw-r--r-- | deps/uv/src/win/tty.c | 110 |
1 files changed, 102 insertions, 8 deletions
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 7840fb2861..87e3eb5d8a 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -48,6 +48,8 @@ #define ANSI_IN_STRING 0x40 #define ANSI_BACKSLASH_SEEN 0x80 +#define MAX_INPUT_BUFFER_LENGTH 8192 + static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); @@ -303,6 +305,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { uv_tty_t* handle; uv_req_t* req; DWORD bytes, read_bytes; + WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3]; + DWORD chars, read_chars; assert(data); @@ -314,18 +318,29 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { assert(handle->read_line_buffer.len > 0); /* ReadConsole can't handle big buffers. */ - if (handle->read_line_buffer.len < 8192) { + if (handle->read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) { bytes = handle->read_line_buffer.len; } else { - bytes = 8192; + bytes = MAX_INPUT_BUFFER_LENGTH; } - /* Todo: Unicode */ - if (ReadConsoleA(handle->read_line_handle, - (void*) handle->read_line_buffer.base, - bytes, - &read_bytes, + /* At last, unicode! */ + /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ + chars = bytes / 3; + + if (ReadConsoleW(handle->read_line_handle, + (void*) utf16, + chars, + &read_chars, NULL)) { + read_bytes = WideCharToMultiByte(CP_UTF8, + 0, + utf16, + read_chars, + handle->read_line_buffer.base, + bytes, + NULL, + NULL); SET_REQ_SUCCESS(req); req->overlapped.InternalHigh = read_bytes; } else { @@ -1117,6 +1132,14 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, return 0; } +#define FLIP_FGBG \ + do { \ + WORD fg = info.wAttributes & 0xF; \ + WORD bg = info.wAttributes & 0xF0; \ + info.wAttributes &= 0xFF00; \ + info.wAttributes |= fg << 4; \ + info.wAttributes |= bg >> 4; \ + } while (0) static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { unsigned short argc = handle->ansi_csi_argc; @@ -1126,6 +1149,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { char fg_color = -1, bg_color = -1; char fg_bright = -1, bg_bright = -1; + char inverse = -1; if (argc == 0) { /* Reset mode */ @@ -1133,6 +1157,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { bg_color = 0; fg_bright = 0; bg_bright = 0; + inverse = 0; } for (i = 0; i < argc; i++) { @@ -1144,6 +1169,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { bg_color = 0; fg_bright = 0; bg_bright = 0; + inverse = 0; } else if (arg == 1) { /* Foreground bright on */ @@ -1158,6 +1184,10 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { /* Background bright on */ bg_bright = 1; + } else if (arg == 7) { + /* Inverse: on */ + inverse = 1; + } else if (arg == 21 || arg == 22) { /* Foreground bright off */ fg_bright = 0; @@ -1166,6 +1196,10 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { /* Background bright off */ bg_bright = 0; + } else if (arg == 27) { + /* Inverse: off */ + inverse = 0; + } else if (arg >= 30 && arg <= 37) { /* Set foreground color */ fg_color = arg - 30; @@ -1198,7 +1232,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { } if (fg_color == -1 && bg_color == -1 && fg_bright == -1 && - bg_bright == -1) { + bg_bright == -1 && inverse == -1) { /* Nothing changed */ return 0; } @@ -1208,6 +1242,10 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { return -1; } + if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { + FLIP_FGBG; + } + if (fg_color != -1) { info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); if (fg_color & 1) info.wAttributes |= FOREGROUND_RED; @@ -1238,6 +1276,18 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { } } + if (inverse != -1) { + if (inverse) { + info.wAttributes |= COMMON_LVB_REVERSE_VIDEO; + } else { + info.wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; + } + } + + if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { + FLIP_FGBG; + } + if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) { *error = GetLastError(); return -1; @@ -1316,6 +1366,25 @@ static int uv_tty_restore_state(uv_tty_t* handle, return 0; } +static int uv_tty_set_cursor_visibility(uv_tty_t* handle, + BOOL visible, + DWORD* error) { + CONSOLE_CURSOR_INFO cursor_info; + + if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) { + *error = GetLastError(); + return -1; + } + + cursor_info.bVisible = visible; + + if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) { + *error = GetLastError(); + return -1; + } + + return 0; +} static int uv_tty_write_bufs(uv_tty_t* handle, const uv_buf_t bufs[], @@ -1527,6 +1596,13 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } + } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && + handle->ansi_csi_argc == 0) { + /* Ignores '?' if it is the first character after CSI[ */ + /* This is an extension character from the VT100 codeset */ + /* that is supported and used by most ANSI terminals today. */ + continue; + } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && (handle->ansi_csi_argc > 0 || utf8_codepoint != '[')) { int x, y, d; @@ -1629,6 +1705,24 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); uv_tty_restore_state(handle, 0, error); break; + + case 'l': + /* Hide the cursor */ + if (handle->ansi_csi_argc == 1 && + handle->ansi_csi_argv[0] == 25) { + FLUSH_TEXT(); + uv_tty_set_cursor_visibility(handle, 0, error); + } + break; + + case 'h': + /* Show the cursor */ + if (handle->ansi_csi_argc == 1 && + handle->ansi_csi_argv[0] == 25) { + FLUSH_TEXT(); + uv_tty_set_cursor_visibility(handle, 1, error); + } + break; } /* Sequence ended - go back to normal state. */ |