aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Halachmi (:avih) <avihpit@yahoo.com>2023-07-20 22:48:41 +0300
committerAvi Halachmi (:avih) <avihpit@yahoo.com>2023-07-21 10:13:12 +0300
commit4fe7e7cdd0441e9455cc93c17b40a7a96704e61f (patch)
tree7facce159f51486696dd2adf180800c32b3f9444
parent72b97c86c6c1a1902d6dcda3da7c38db13585cdc (diff)
downloadbusybox-w32-4fe7e7cdd0441e9455cc93c17b40a7a96704e61f.tar.gz
busybox-w32-4fe7e7cdd0441e9455cc93c17b40a7a96704e61f.tar.bz2
busybox-w32-4fe7e7cdd0441e9455cc93c17b40a7a96704e61f.zip
win32: UTF8 input: improve missing-key-down hack
The UTF8 input code works around an issue when pasting at the windows console (but not terminal) that sometimes we get key-up without a prior matching key-down - at which case it generates down. However, previously it detected this by comparing an up-event to the last down-event, which could result in false-positive in cases like: X-down Y-down X-up Y-up (e.g. when typing quickly). Now it remembers the last 8 key-down events when searching a prior matching key-down, which fixes an issue of incorrect repeated keys (in the example above Y-up was incorrectly changed to Y-down).
-rw-r--r--win32/winansi.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/win32/winansi.c b/win32/winansi.c
index bc3e69163..f280177e6 100644
--- a/win32/winansi.c
+++ b/win32/winansi.c
@@ -1284,6 +1284,44 @@ static void maybeEatUpto2ndHalfUp(HANDLE h, DWORD *ph1)
1284 } 1284 }
1285} 1285}
1286 1286
1287// if the codepoint is a key-down event, remember it, else if
1288// it's a key-up event with matching prior down - forget the down,
1289// else (up without matching prior key-down) - change it to down.
1290// We remember few prior key-down events so that a sequence
1291// like X-down Y-down X-up Y-up won't trigger this hack for Y-up.
1292// When up is changed into down there won't be further key-up event,
1293// but that's OK because the caller ignores key-up events anyway.
1294static void maybe_change_up_to_down(wchar_t key, BOOL *isdown)
1295{
1296 #define DOWN_BUF_SIZ 8
1297 static wchar_t downbuf[DOWN_BUF_SIZ] = {0};
1298 static int pos = 0;
1299
1300 if (*isdown) {
1301 downbuf[pos++] = key;
1302 pos = pos % DOWN_BUF_SIZ;
1303 return;
1304 }
1305
1306 // the missing-key-down issue was only observed with unicode values,
1307 // so limit this hack to non-ASCII-7 values.
1308 // also, launching a new shell/read process from CLI captures
1309 // an ENTER-up event without prior down at this new process, which
1310 // would otherwise change it to down - creating a wrong ENTER keypress.
1311 if (key <= 127)
1312 return;
1313
1314 // key up, try to match a prior down
1315 for (int i = 0; i < DOWN_BUF_SIZ; ++i) {
1316 if (downbuf[i] == key) {
1317 downbuf[i] = 0; // "forget" this down
1318 return;
1319 }
1320 }
1321
1322 // no prior key-down - replace the up with down
1323 *isdown = TRUE;
1324}
1287 1325
1288/* 1326/*
1289 * readConsoleInput_utf8 behaves similar enough to ReadConsoleInputA when 1327 * readConsoleInput_utf8 behaves similar enough to ReadConsoleInputA when
@@ -1355,20 +1393,18 @@ BOOL readConsoleInput_utf8(HANDLE h, INPUT_RECORD *r, DWORD len, DWORD *got)
1355 srec = *r; 1393 srec = *r;
1356 codepoint = srec.Event.KeyEvent.uChar.UnicodeChar; 1394 codepoint = srec.Event.KeyEvent.uChar.UnicodeChar;
1357 1395
1358 // At the cmd.exe console (but not windows terminal) we sometimes 1396 // Observed when pasting unicode at cmd.exe console (but not
1359 // get key-up without the prior expected key-down event, sometimes 1397 // windows terminal), we sometimes get key-up event without
1360 // with UnicodeChar of 0 instead the key-down event. work around it. 1398 // a prior matching key-down (or with key-down codepoint 0),
1361 if (codepoint) { 1399 // so this call would change the up into down in such case.
1362 static wchar_t last_down = 0; 1400 // E.g. pastes fixed by this hack: U+1F600 "😀", or U+0C80 "ಀ"
1363 1401 if (codepoint)
1364 if (srec.Event.KeyEvent.bKeyDown) 1402 maybe_change_up_to_down(codepoint, &srec.Event.KeyEvent.bKeyDown);
1365 last_down = codepoint;
1366 else if (codepoint > 127 && codepoint != last_down)
1367 srec.Event.KeyEvent.bKeyDown = TRUE;
1368 }
1369 1403
1370 // if it's a 1st (high) surrogate pair half, try to eat upto and 1404 // if it's a 1st (high) surrogate pair half, try to eat upto and
1371 // excluding the 2nd (low) half, and combine them into codepoint. 1405 // excluding the 2nd (low) half, and combine them into codepoint.
1406 // this does not interfere with the missing-key-down workaround
1407 // (no issue if the down-buffer has 1st-half-down without up).
1372 if (codepoint >= 0xD800 && codepoint <= 0xDBFF) 1408 if (codepoint >= 0xD800 && codepoint <= 0xDBFF)
1373 maybeEatUpto2ndHalfUp(h, &codepoint); 1409 maybeEatUpto2ndHalfUp(h, &codepoint);
1374 1410