56
56
#define ANSI_BACKSLASH_SEEN 0x80
57
57
58
58
#define MAX_INPUT_BUFFER_LENGTH 8192
59
+ #define MAX_CONSOLE_CHAR 8192
59
60
61
+ #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
62
+ #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
63
+ #endif
60
64
61
65
static void uv_tty_capture_initial_style (CONSOLE_SCREEN_BUFFER_INFO * info );
62
66
static void uv_tty_update_virtual_window (CONSOLE_SCREEN_BUFFER_INFO * info );
@@ -125,6 +129,14 @@ static char uv_tty_default_fg_bright = 0;
125
129
static char uv_tty_default_bg_bright = 0 ;
126
130
static char uv_tty_default_inverse = 0 ;
127
131
132
+ typedef enum {
133
+ UV_SUPPORTED ,
134
+ UV_UNCHECKED ,
135
+ UV_UNSUPPORTED
136
+ } uv_vtermstate_t ;
137
+ /* Determine whether or not ANSI support is enabled. */
138
+ static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED ;
139
+ static void uv__determine_vterm_state (HANDLE handle );
128
140
129
141
void uv_console_init () {
130
142
if (uv_sem_init (& uv_tty_output_lock , 1 ))
@@ -168,6 +180,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
168
180
/* shared between all uv_tty_t handles. */
169
181
uv_sem_wait (& uv_tty_output_lock );
170
182
183
+ if (uv__vterm_state == UV_UNCHECKED )
184
+ uv__determine_vterm_state (handle );
185
+
171
186
/* Store the global tty output handle. This handle is used by TTY read */
172
187
/* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */
173
188
/* is received. */
@@ -989,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
989
1004
if (handle -> tty .rd .last_key_len > 0 ) {
990
1005
SET_REQ_SUCCESS (& handle -> read_req );
991
1006
uv_insert_pending_req (handle -> loop , (uv_req_t * ) & handle -> read_req );
1007
+ /* Make sure no attempt is made to insert it again until it's handled. */
1008
+ handle -> flags |= UV_HANDLE_READ_PENDING ;
1009
+ handle -> reqs_pending ++ ;
992
1010
return 0 ;
993
1011
}
994
1012
@@ -1602,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
1602
1620
DWORD * error ) {
1603
1621
/* We can only write 8k characters at a time. Windows can't handle */
1604
1622
/* much more characters in a single console write anyway. */
1605
- WCHAR utf16_buf [8192 ];
1623
+ WCHAR utf16_buf [MAX_CONSOLE_CHAR ];
1624
+ WCHAR * utf16_buffer ;
1606
1625
DWORD utf16_buf_used = 0 ;
1607
- unsigned int i ;
1608
-
1609
- #define FLUSH_TEXT () \
1610
- do { \
1611
- if (utf16_buf_used > 0) { \
1612
- uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
1613
- utf16_buf_used = 0; \
1614
- } \
1615
- } while (0)
1626
+ unsigned int i , len , max_len , pos ;
1627
+ int allocate = 0 ;
1628
+
1629
+ #define FLUSH_TEXT () \
1630
+ do { \
1631
+ pos = 0; \
1632
+ do { \
1633
+ len = utf16_buf_used - pos; \
1634
+ if (len > MAX_CONSOLE_CHAR) \
1635
+ len = MAX_CONSOLE_CHAR; \
1636
+ uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \
1637
+ pos += len; \
1638
+ } while (pos < utf16_buf_used); \
1639
+ if (allocate) { \
1640
+ uv__free(utf16_buffer); \
1641
+ allocate = 0; \
1642
+ utf16_buffer = utf16_buf; \
1643
+ } \
1644
+ utf16_buf_used = 0; \
1645
+ } while (0)
1616
1646
1617
1647
#define ENSURE_BUFFER_SPACE (wchars_needed ) \
1618
1648
if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \
@@ -1630,12 +1660,48 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
1630
1660
/* state. */
1631
1661
* error = ERROR_SUCCESS ;
1632
1662
1663
+ utf16_buffer = utf16_buf ;
1664
+
1633
1665
uv_sem_wait (& uv_tty_output_lock );
1634
1666
1635
1667
for (i = 0 ; i < nbufs ; i ++ ) {
1636
1668
uv_buf_t buf = bufs [i ];
1637
1669
unsigned int j ;
1638
1670
1671
+ if (uv__vterm_state == UV_SUPPORTED && buf .len > 0 ) {
1672
+ utf16_buf_used = MultiByteToWideChar (CP_UTF8 ,
1673
+ 0 ,
1674
+ buf .base ,
1675
+ buf .len ,
1676
+ NULL ,
1677
+ 0 );
1678
+
1679
+ if (utf16_buf_used == 0 ) {
1680
+ * error = GetLastError ();
1681
+ break ;
1682
+ }
1683
+
1684
+ max_len = (utf16_buf_used + 1 ) * sizeof (WCHAR );
1685
+ allocate = max_len > MAX_CONSOLE_CHAR ;
1686
+ if (allocate )
1687
+ utf16_buffer = uv__malloc (max_len );
1688
+ if (!MultiByteToWideChar (CP_UTF8 ,
1689
+ 0 ,
1690
+ buf .base ,
1691
+ buf .len ,
1692
+ utf16_buffer ,
1693
+ utf16_buf_used )) {
1694
+ if (allocate )
1695
+ uv__free (utf16_buffer );
1696
+ * error = GetLastError ();
1697
+ break ;
1698
+ }
1699
+
1700
+ FLUSH_TEXT ();
1701
+
1702
+ continue ;
1703
+ }
1704
+
1639
1705
for (j = 0 ; j < buf .len ; j ++ ) {
1640
1706
unsigned char c = buf .base [j ];
1641
1707
@@ -2193,3 +2259,24 @@ int uv_tty_reset_mode(void) {
2193
2259
/* Not necessary to do anything. */
2194
2260
return 0 ;
2195
2261
}
2262
+
2263
+ /* Determine whether or not this version of windows supports
2264
+ * proper ANSI color codes. Should be supported as of windows
2265
+ * 10 version 1511, build number 10.0.10586.
2266
+ */
2267
+ static void uv__determine_vterm_state (HANDLE handle ) {
2268
+ DWORD dwMode = 0 ;
2269
+
2270
+ if (!GetConsoleMode (handle , & dwMode )) {
2271
+ uv__vterm_state = UV_UNSUPPORTED ;
2272
+ return ;
2273
+ }
2274
+
2275
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING ;
2276
+ if (!SetConsoleMode (handle , dwMode )) {
2277
+ uv__vterm_state = UV_UNSUPPORTED ;
2278
+ return ;
2279
+ }
2280
+
2281
+ uv__vterm_state = UV_SUPPORTED ;
2282
+ }
0 commit comments