From 445e3a1f06b2a049e2b50b7edf2992ce80167014 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Wed, 16 Nov 2016 16:16:54 +0100 Subject: [PATCH] Revert "Revert "win,tty: add support for ANSI codes in win10 v1511"" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To bring back support for ANSI codes in win10 v1511. This reverts commit 8cbabaa81709562de68bcac0554e4e7af2f72cf6. PR-URL: https://github.com/libuv/libuv/pull/1143 Refs: https://github.com/libuv/libuv/pull/1138 Refs: https://github.com/libuv/libuv/pull/889 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Imran Iqbal --- src/win/tty.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 2 ++ test/test-tty.c | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/src/win/tty.c b/src/win/tty.c index 76dc2fab..1e397b44 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -57,6 +57,9 @@ #define MAX_INPUT_BUFFER_LENGTH 8192 +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info); static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); @@ -125,6 +128,14 @@ static char uv_tty_default_fg_bright = 0; static char uv_tty_default_bg_bright = 0; static char uv_tty_default_inverse = 0; +typedef enum { + UV_SUPPORTED, + UV_UNCHECKED, + UV_UNSUPPORTED +} uv_vtermstate_t; +/* Determine whether or not ANSI support is enabled. */ +static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; +static void uv__determine_vterm_state(HANDLE handle); void uv_console_init() { if (uv_sem_init(&uv_tty_output_lock, 1)) @@ -168,6 +179,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { /* shared between all uv_tty_t handles. */ uv_sem_wait(&uv_tty_output_lock); + if (uv__vterm_state == UV_UNCHECKED) + uv__determine_vterm_state(handle); + /* Store the global tty output handle. This handle is used by TTY read */ /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */ /* is received. */ @@ -1636,6 +1650,33 @@ static int uv_tty_write_bufs(uv_tty_t* handle, uv_buf_t buf = bufs[i]; unsigned int j; + if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) { + utf16_buf_used = MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + NULL, + 0); + + if (utf16_buf_used == 0) { + *error = GetLastError(); + break; + } + + if (!MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + utf16_buf, + utf16_buf_used)) { + *error = GetLastError(); + break; + } + + FLUSH_TEXT(); + continue; + } + for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; @@ -2193,3 +2234,24 @@ int uv_tty_reset_mode(void) { /* Not necessary to do anything. */ return 0; } + +/* Determine whether or not this version of windows supports + * proper ANSI color codes. Should be supported as of windows + * 10 version 1511, build number 10.0.10586. + */ +static void uv__determine_vterm_state(HANDLE handle) { + DWORD dwMode = 0; + + if (!GetConsoleMode(handle, &dwMode)) { + uv__vterm_state = UV_UNSUPPORTED; + return; + } + + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(handle, dwMode)) { + uv__vterm_state = UV_UNSUPPORTED; + return; + } + + uv__vterm_state = UV_SUPPORTED; +} diff --git a/test/test-list.h b/test/test-list.h index 08886a6f..6ddd5ff2 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -47,6 +47,7 @@ TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) #ifdef _WIN32 TEST_DECLARE (tty_raw) +TEST_DECLARE (tty_empty_write) #endif TEST_DECLARE (tty_file) TEST_DECLARE (tty_pty) @@ -404,6 +405,7 @@ TASK_LIST_START TEST_ENTRY (tty) #ifdef _WIN32 TEST_ENTRY (tty_raw) + TEST_ENTRY (tty_empty_write) #endif TEST_ENTRY (tty_file) TEST_ENTRY (tty_pty) diff --git a/test/test-tty.c b/test/test-tty.c index d03f07a4..68a03cd1 100644 --- a/test/test-tty.c +++ b/test/test-tty.c @@ -212,6 +212,48 @@ TEST_IMPL(tty_raw) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(tty_empty_write) { + int r; + int ttyout_fd; + uv_tty_t tty_out; + uv_loop_t* loop = uv_default_loop(); + + /* Make sure we have an FD that refers to a tty */ + HANDLE handle; + + handle = CreateFileA("conout$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + ASSERT(handle != INVALID_HANDLE_VALUE); + ttyout_fd = _open_osfhandle((intptr_t) handle, 0); + + ASSERT(ttyout_fd >= 0); + + ASSERT(UV_TTY == uv_guess_handle(ttyout_fd)); + + r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */ + ASSERT(r == 0); + + char dummy[1]; + uv_buf_t bufs[1]; + bufs[0].len = 0; + bufs[0].base = &dummy; + + r = uv_try_write((uv_stream_t*) &tty_out, bufs, 1); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &tty_out, NULL); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} #endif