Mercurial > mxe-octave
view src/readline-2-event-hook.patch @ 6546:54f336bbb833
readline: Improve check for UTF-16 surrogates (bug #63400).
* src/readline-2-event-hook.patch: Avoid false positives for UTF-16 surrogate
halves.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Sun, 27 Nov 2022 19:08:31 +0100 |
parents | a76f513700df |
children | a6f1111a9f1d |
line wrap: on
line source
diff -urN readline-8.2/input.c.orig readline-8.2/input.c --- readline-8.2/input.c.orig 2022-04-08 21:43:24.000000000 +0200 +++ readline-8.2/input.c 2022-11-22 16:54:55.099070500 +0100 @@ -176,6 +176,12 @@ static unsigned char ibuffer[512]; static int ibuffer_len = sizeof (ibuffer) - 1; +#if defined (__MINGW32__) +#include <windows.h> +static int _win32_getch (int *const is_char); +static int _win32_kbhit (void); +#endif + #define any_typein (push_index != pop_index) int @@ -306,7 +311,7 @@ #if defined (__MINGW32__) /* Use getch/_kbhit to check for available console input, in the same way that we read it normally. */ - chars_avail = isatty (tty) ? _kbhit () : 0; + chars_avail = isatty (tty) ? _win32_kbhit () : 0; result = 0; #endif @@ -404,7 +409,7 @@ #if defined (__MINGW32__) if (isatty (tty)) - return (_kbhit ()); + return (_win32_kbhit ()); #endif return 0; @@ -799,6 +804,139 @@ return (c); } +#if defined (__MINGW32__) +#define _WIN32_READ_NOCHAR (-2) +static char _win32_buf[16] = {'0'}; +static int _win32_bufidx = 0; + +static int +_win32_getch_internal (int block, int *const is_char) +{ + INPUT_RECORD rec; + DWORD evRead, waitResult; + HANDLE hInput = (HANDLE) _get_osfhandle (fileno (rl_instream)); + *is_char = 1; + + if (_win32_bufidx > 0) + return _win32_buf[--_win32_bufidx]; + + hInput = (HANDLE) _get_osfhandle (fileno (rl_instream)); + + do + { + *is_char = 0; + if (! block) + { + if (WaitForSingleObject (hInput, _keyboard_input_timeout/1000) != WAIT_OBJECT_0) + return _WIN32_READ_NOCHAR; + } + + if (!ReadConsoleInputW (hInput, &rec, 1, &evRead) || evRead != 1) + return EOF; + + *is_char = 1; + switch (rec.EventType) + { + case KEY_EVENT: + if ((rec.Event.KeyEvent.bKeyDown && + (rec.Event.KeyEvent.wVirtualKeyCode < VK_SHIFT || + rec.Event.KeyEvent.wVirtualKeyCode > VK_MENU)) || + (!rec.Event.KeyEvent.bKeyDown && + rec.Event.KeyEvent.wVirtualKeyCode == VK_MENU && + rec.Event.KeyEvent.uChar.UnicodeChar)) + { + if (rec.Event.KeyEvent.uChar.UnicodeChar) + return (int) rec.Event.KeyEvent.uChar.UnicodeChar; + + *is_char = 0; + switch (rec.Event.KeyEvent.wVirtualKeyCode) + { + case VK_UP: + _win32_buf[_win32_bufidx++] = 'A'; + return 0340; + case VK_DOWN: + _win32_buf[_win32_bufidx++] = 'B'; + return 0340; + case VK_RIGHT: + _win32_buf[_win32_bufidx++] = 'C'; + return 0340; + case VK_LEFT: + _win32_buf[_win32_bufidx++] = 'D'; + return 0340; + case VK_HOME: + _win32_buf[_win32_bufidx++] = 'H'; + return 0340; + case VK_END: + _win32_buf[_win32_bufidx++] = 'F'; + return 0340; + case VK_DELETE: + _win32_buf[_win32_bufidx++] = 8; + _win32_buf[_win32_bufidx++] = 'C'; + return 0340; + default: + break; + } + } + break; + + case WINDOW_BUFFER_SIZE_EVENT: + rl_resize_terminal (); + break; + + default: + break; + } + } + while (1); +} + +static int +_win32_kbhit (void) +{ + int result; + int is_char; + + result = _win32_getch_internal (0, &is_char); + if (result == _WIN32_READ_NOCHAR + || result == EOF) + return 0; + + if (is_char) + { + char charbuf[5] = {0}; + wchar_t unicode[2] = {result, 0}; + int utf16_code_units = 1; + if ((unicode[0] & 0xF800) == 0xD800) /* outside BMP */ + { + unicode[1] = _win32_getch_internal (0, &is_char); + utf16_code_units++; + } + /* convert to UTF-8 byte sequence */ + int len = WideCharToMultiByte (CP_UTF8, 0, + (wchar_t *) &unicode, utf16_code_units, + charbuf, 5, NULL, NULL); + for (int i=0; i<len; i++) + { + _win32_buf[_win32_bufidx++] = (unsigned char) charbuf[len-i-1]; + } + } + else + { + /* buffer is read from back to front */ + _win32_buf[_win32_bufidx++] = 0x5b; /* "[" */ + _win32_buf[_win32_bufidx++] = 0x1b; /* ESC */ + } + + return _win32_bufidx; +} + +static int +_win32_getch (int *const is_char) +{ + return _win32_getch_internal (1, is_char); +} +#endif + int rl_getc (FILE *stream) { @@ -818,8 +937,11 @@ /* We know at this point that _rl_caught_signal == 0 */ #if defined (__MINGW32__) - if (isatty (fd) - return (_getch ()); /* "There is no error return." */ + if (isatty (fd)) + { + int is_char; + return (_win32_getch (&is_char)); + } #endif result = 0; #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)