Skip to content

Commit 8fe096c

Browse files
authored
Increase stdin chunksize from 16 to 1024 chars (#771)
1 parent b36bc85 commit 8fe096c

File tree

3 files changed

+79
-21
lines changed

3 files changed

+79
-21
lines changed

contrib/win32/win32compat/termio.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@
4848
#include "tnnet.h"
4949
#include "misc_internal.h"
5050

51-
#define TERM_IO_BUF_SIZE 2048
52-
5351
extern int in_raw_mode;
5452
BOOL isFirstTime = TRUE;
5553

contrib/win32/win32compat/tncon.c

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,84 @@ GetModifierKey(DWORD dwControlKeyState)
124124
return modKey;
125125
}
126126

127+
// ReadConsoleForTermEmul() but for ENABLE_VIRTUAL_TERMINAL_INPUT.
128+
static int
129+
ReadConsoleForTermEmulModern(HANDLE hInput, char *destin, int destinlen)
130+
{
131+
// If the previous input ended on a lead (high) surrogate,
132+
// we stash it here to combine it with the next input.
133+
static wchar_t s_previous_lead;
134+
135+
INPUT_RECORD records[TERM_IO_BUF_SIZE_UTF16];
136+
DWORD records_cap = ARRAYSIZE(records);
137+
DWORD records_len = 0;
138+
wchar_t text[TERM_IO_BUF_SIZE_UTF16];
139+
int text_len = 0;
140+
141+
// If we'll restore the previous lead surrogate, we can only read
142+
// ARRAYSIZE(records)-1 records before the storage overflows.
143+
if (s_previous_lead) {
144+
records_cap--;
145+
}
146+
147+
// As this application heavily relies on APCs, it's important that we call
148+
// DataAvailable(), because it calls WaitForSingleObjectEx with bAlertable=TRUE.
149+
if (!DataAvailable(hInput) ||
150+
!ReadConsoleInputW(hInput, records, records_cap, &records_len) ||
151+
records_len == 0)
152+
return 0;
153+
154+
// Restore the previous lead surrogate if we have one.
155+
if (s_previous_lead) {
156+
text[text_len++] = s_previous_lead;
157+
s_previous_lead = 0;
158+
}
159+
160+
// Accumulate the UTF-16 text.
161+
for (DWORD i = 0; i < records_len; i++) {
162+
switch (records[i].EventType) {
163+
case WINDOW_BUFFER_SIZE_EVENT:
164+
queue_terminal_window_change_event();
165+
break;
166+
case KEY_EVENT: {
167+
const KEY_EVENT_RECORD* k = &records[i].Event.KeyEvent;
168+
if (
169+
// The old Windows console added support for Unicode by encoding the characters in the
170+
// current code page as usual, while stuffing a UCS2 value into a trailing VK_MENU event.
171+
// Modern terminals on Windows stopped doing this and the Windows console may as well at some point.
172+
(k->bKeyDown || k->wVirtualKeyCode == VK_MENU) &&
173+
// Current versions of ConPTY suffer from a bug where pressing modifier keys enqueues
174+
// a KEY_EVENT with UnicodeChar=0 despite ENABLE_VIRTUAL_TERMINAL_INPUT being enabled.
175+
// They can be identified by the fact that their UnicodeChar value is zero,
176+
// but they still have a non-zero wVirtualScanCode.
177+
(k->uChar.UnicodeChar != L'\0' || k->wVirtualScanCode == 0))
178+
text[text_len++] = k->uChar.UnicodeChar;
179+
break;
180+
}
181+
default:
182+
break;
183+
}
184+
}
185+
186+
// Pop any lone lead surrogate from the input for later.
187+
const wchar_t last_char = text[text_len - 1];
188+
if (IS_HIGH_SURROGATE(last_char)) {
189+
s_previous_lead = last_char;
190+
text_len--;
191+
}
192+
193+
// ...and finally convert everything to UTF-8.
194+
// It'll always fit, because we sized TERM_IO_BUF_SIZE to be large enough.
195+
return WideCharToMultiByte(CP_UTF8, 0, text, text_len, destin, destinlen, NULL, NULL);
196+
}
197+
127198
int
128199
ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
129200
{
130-
HANDLE hHandle[] = { hInput, NULL };
131-
DWORD nHandle = 1;
201+
if (isConsoleVTSeqAvailable) {
202+
return ReadConsoleForTermEmulModern(hInput, destin, destinlen);
203+
}
204+
132205
DWORD dwInput = 0;
133206
DWORD rc = 0;
134207
unsigned char octets[20];
@@ -187,23 +260,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
187260
break;
188261
}
189262

190-
if (isConsoleVTSeqAvailable) {
191-
if (inputRecord.Event.KeyEvent.uChar.UnicodeChar != L'\0' || inputRecord.Event.KeyEvent.wVirtualScanCode == 0) {
192-
n = WideCharToMultiByte(
193-
CP_UTF8,
194-
0,
195-
&(inputRecord.Event.KeyEvent.uChar.UnicodeChar),
196-
1,
197-
(LPSTR)octets,
198-
20,
199-
NULL,
200-
NULL);
201-
202-
WriteToBuffer((char *)octets, n);
203-
}
204-
} else {
205-
GetVTSeqFromKeyStroke(inputRecord);
206-
}
263+
GetVTSeqFromKeyStroke(inputRecord);
207264
}
208265
break;
209266
}

contrib/win32/win32compat/tncon.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737

3838
#include "console.h"
3939

40+
#define TERM_IO_BUF_SIZE_UTF16 1024
41+
#define TERM_IO_BUF_SIZE (3 * TERM_IO_BUF_SIZE_UTF16)
42+
4043
#define UP_ARROW "\x1b[A"
4144
#define DOWN_ARROW "\x1b[B"
4245
#define RIGHT_ARROW "\x1b[C"

0 commit comments

Comments
 (0)