changeset 6566:7c302266a10b

readline: Fix handling of escape sequences in callback mode. * src/readline-2-event-hook.patch: Fix handling of escape sequences in callback mode (e.g., for gdb).
author Markus Mützel <markus.muetzel@gmx.de>
date Mon, 12 Dec 2022 12:37:25 +0100
parents c60bf74b03cd
children 31493bde29c1
files src/readline-2-event-hook.patch
diffstat 1 files changed, 68 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/src/readline-2-event-hook.patch	Wed Dec 07 09:31:20 2022 -0500
+++ b/src/readline-2-event-hook.patch	Mon Dec 12 12:37:25 2022 +0100
@@ -1,20 +1,35 @@
 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-12-01 19:16:34.989739900 +0100
-@@ -176,6 +178,12 @@
++++ readline-8.2/input.c	2022-12-12 09:58:00.410673600 +0100
+@@ -176,6 +176,14 @@
  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_getch (void);
 +static int _win32_kbhit (void);
++static char _win32_buf[16] = {'0'};
++static int _win32_bufidx = 0;
 +#endif
 +
  #define any_typein (push_index != pop_index)
  
  int
-@@ -306,7 +314,7 @@
+@@ -187,7 +195,11 @@
+ int
+ _rl_pushed_input_available (void)
+ {
+-  return (push_index != pop_index);
++  return ((push_index != pop_index)
++#if defined (__MINGW32__)
++          || (_win32_bufidx > 0)
++#endif
++          );
+ }
+ 
+ /* Return the amount of space available in the buffer for stuffing
+@@ -306,7 +318,7 @@
  #if defined (__MINGW32__)
    /* Use getch/_kbhit to check for available console input, in the same way
       that we read it normally. */
@@ -23,7 +38,7 @@
     result = 0;
  #endif
  
-@@ -404,7 +412,7 @@
+@@ -404,7 +416,7 @@
  
  #if defined (__MINGW32__)
    if (isatty (tty))
@@ -32,22 +47,19 @@
  #endif
  
    return 0;
-@@ -799,6 +807,142 @@
+@@ -799,6 +811,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)
++_win32_getch_internal (int block)
 +{
 +  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];
@@ -56,17 +68,15 @@
 +
 +  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)
++      if (! ReadConsoleInputW (hInput, &rec, 1, &evRead) || evRead != 1)
 +        return EOF;
 +
-+      *is_char = 1;
 +      switch (rec.EventType)
 +        {
 +          case KEY_EVENT:
@@ -78,33 +88,63 @@
 +                rec.Event.KeyEvent.uChar.UnicodeChar))
 +              {
 +                if (rec.Event.KeyEvent.uChar.UnicodeChar)
-+                  return (int) rec.Event.KeyEvent.uChar.UnicodeChar;
++                  {
++                    int result = (int) rec.Event.KeyEvent.uChar.UnicodeChar;
++                    char charbuf[5] = {0};
++                    wchar_t unicode[2] = {result, 0};
++                    int utf16_code_units = 1;
++                    if ((unicode[0] & 0xF800) == 0xD800)  /* outside BMP */
++                      {
++                        ReadConsoleInputW (hInput, &rec, 1, &evRead);
++                        unicode[1] = (int) rec.Event.KeyEvent.uChar.UnicodeChar;
++                        utf16_code_units++;
++                      }
++                    /* convert to current codepage or UTF-8 byte sequence */
++                    unsigned int codepage = CP_THREAD_ACP;
++                    if (_rl_utf8locale)
++                      codepage = CP_UTF8;
++                    int len = WideCharToMultiByte (codepage, 0,
++                                                   (wchar_t *) &unicode, utf16_code_units,
++                                                   charbuf, 5, NULL, NULL);
++                    /* buffer is read from back to front */
++                    for (int i=0; i<len-1; i++)
++                      _win32_buf[_win32_bufidx++] = (unsigned char) charbuf[len-i-1];
 +
-+                *is_char = 0;
++                    return (int) (unsigned char) charbuf[0];
++                  }
++
 +                switch (rec.Event.KeyEvent.wVirtualKeyCode)
 +                  {
++                    /* buffer is read from back to front */
 +                    case VK_UP:
 +                      _win32_buf[_win32_bufidx++] = 'A';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_DOWN:
 +                      _win32_buf[_win32_bufidx++] = 'B';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_RIGHT:
 +                      _win32_buf[_win32_bufidx++] = 'C';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_LEFT:
 +                      _win32_buf[_win32_bufidx++] = 'D';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_HOME:
 +                      _win32_buf[_win32_bufidx++] = 'H';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_END:
 +                      _win32_buf[_win32_bufidx++] = 'F';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    case VK_DELETE:
 +                      _win32_buf[_win32_bufidx++] = 8;
 +                      _win32_buf[_win32_bufidx++] = 'C';
-+                      return 0340;
++                      _win32_buf[_win32_bufidx++] = '[';
++                      return 0x1b;  /* ESC */
 +                    default:
 +                      break;
 +                  }
@@ -126,66 +166,35 @@
 +_win32_kbhit (void)
 +{
 +  int result;
-+  int is_char;
 +
-+  result = _win32_getch_internal (0, &is_char);
++  result = _win32_getch_internal (0);
 +  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 current codepage or UTF-8 byte sequence */
-+      unsigned int codepage = CP_THREAD_ACP;
-+      if (_rl_utf8locale)
-+        codepage = CP_UTF8;
-+      int len = WideCharToMultiByte (codepage, 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 */
-+    }
++  _win32_buf[_win32_bufidx++] = result;
 +
 +  return _win32_bufidx;
 +}
 +
 +static int
-+_win32_getch (int *const is_char)
++_win32_getch (void)
 +{
-+  return _win32_getch_internal (1, is_char);
++  return (_win32_getch_internal (1));
 +}
 +#endif
 +
  int
  rl_getc (FILE *stream)
  {
-@@ -818,8 +962,11 @@
+@@ -818,8 +963,8 @@
        /* 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));
-+        }
++        return (_win32_getch ());
  #endif
        result = 0;
  #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)