summaryrefslogtreecommitdiff
path: root/deps/uv/src/win/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/win/tty.c')
-rw-r--r--deps/uv/src/win/tty.c110
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. */