view src/readline-2-event-hook.patch @ 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 a6f1111a9f1d
children
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-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 (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
@@ -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. */
-   chars_avail = isatty (tty) ? _kbhit () : 0;
+   chars_avail = isatty (tty) ? _win32_kbhit () : 0;
    result = 0;
 #endif
 
@@ -404,7 +416,7 @@
 
 #if defined (__MINGW32__)
   if (isatty (tty))
-    return (_kbhit ());
+    return (_win32_kbhit ());
 #endif
 
   return 0;
@@ -799,6 +811,139 @@
   return (c);
 }
 
+#if defined (__MINGW32__)
+#define _WIN32_READ_NOCHAR (-2)
+
+static int
+_win32_getch_internal (int block)
+{
+  INPUT_RECORD rec;
+  DWORD evRead, waitResult;
+  HANDLE hInput = (HANDLE) _get_osfhandle (fileno (rl_instream));
+
+  if (_win32_bufidx > 0)
+    return _win32_buf[--_win32_bufidx];
+
+  hInput = (HANDLE) _get_osfhandle (fileno (rl_instream));
+
+  do
+    {
+      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;
+
+      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)
+                  {
+                    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];
+
+                    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';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_DOWN:
+                      _win32_buf[_win32_bufidx++] = 'B';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_RIGHT:
+                      _win32_buf[_win32_bufidx++] = 'C';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_LEFT:
+                      _win32_buf[_win32_bufidx++] = 'D';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_HOME:
+                      _win32_buf[_win32_bufidx++] = 'H';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_END:
+                      _win32_buf[_win32_bufidx++] = 'F';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    case VK_DELETE:
+                      _win32_buf[_win32_bufidx++] = 8;
+                      _win32_buf[_win32_bufidx++] = 'C';
+                      _win32_buf[_win32_bufidx++] = '[';
+                      return 0x1b;  /* ESC */
+                    default:
+                      break;
+                  }
+              }
+            break;
+
+          case WINDOW_BUFFER_SIZE_EVENT:
+            rl_resize_terminal ();
+            break;
+
+          default:
+            break;
+        }
+    }
+  while (1);
+}
+
+static int 
+_win32_kbhit (void)
+{
+  int result;
+
+  result = _win32_getch_internal (0);
+  if (result == _WIN32_READ_NOCHAR
+      || result == EOF)
+    return 0;
+
+  _win32_buf[_win32_bufidx++] = result;
+
+  return _win32_bufidx;
+}
+
+static int
+_win32_getch (void)
+{
+  return (_win32_getch_internal (1));
+}
+#endif
+
 int
 rl_getc (FILE *stream)
 {
@@ -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))
+        return (_win32_getch ());
 #endif
       result = 0;
 #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)