changeset 6545:a76f513700df

readline: Fix issue with arrow keys in Octave CLI (bug #63400). * src/readline-0-001-upstream.patch: Fix intentation. * src/readline-2-event-hook.patch: Replace another instance of "_kbhit" with "_win32_kbhit". Use "ReadConsoleInputW" to also catch non-ASCII character keys. Convert wchar_t encoded characters (UTF-16) to UTF-8. Overhaul escape sequence handling. * src/readline-1-locale.patch: Remove patch that's no longer needed. * dist-files.mk: Remove file from list.
author Markus Mützel <markus.muetzel@gmx.de>
date Sun, 27 Nov 2022 19:08:31 +0100
parents 5409aa8dd237
children 54f336bbb833
files dist-files.mk src/readline-0-001-upstream.patch src/readline-1-input.patch src/readline-2-event-hook.patch
diffstat 4 files changed, 104 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/dist-files.mk	Sat Nov 26 22:07:12 2022 +0100
+++ b/dist-files.mk	Sun Nov 27 19:08:31 2022 +0100
@@ -666,7 +666,6 @@
   readline-0-001-upstream.patch \
   readline-1-display.patch \
   readline-1-fixes.patch \
-  readline-1-input.patch \
   readline-1-sigwinch.patch \
   readline-2-event-hook.patch \
   readline-3-fd_set.patch \
--- a/src/readline-0-001-upstream.patch	Sat Nov 26 22:07:12 2022 +0100
+++ b/src/readline-0-001-upstream.patch	Sun Nov 27 19:08:31 2022 +0100
@@ -17,14 +17,14 @@
 --- a/nls.c	2022-08-15 09:38:51.000000000 -0400
 +++ b/nls.c	2021-01-18 2022-10-05 09:23:22.000000000 -0400
 @@ -142,4 +142,8 @@
-      lspec = "";
-    ret = setlocale (LC_CTYPE, lspec);	/* ok, since it does not change locale */
-+   if (ret == 0 || *ret == 0)
-+     ret = setlocale (LC_CTYPE, (char *)NULL);
-+   if (ret == 0 || *ret == 0)
-+     ret = RL_DEFAULT_LOCALE;
-  #else
-    ret = (lspec == 0 || *lspec == 0) ? RL_DEFAULT_LOCALE : lspec;
+     lspec = "";
+   ret = setlocale (LC_CTYPE, lspec);	/* ok, since it does not change locale */
++  if (ret == 0 || *ret == 0)
++    ret = setlocale (LC_CTYPE, (char *)NULL);
++  if (ret == 0 || *ret == 0)
++    ret = RL_DEFAULT_LOCALE;
+ #else
+   ret = (lspec == 0 || *lspec == 0) ? RL_DEFAULT_LOCALE : lspec;
 
 diff -ur a/patchlevel b/patchlevel
 --- a/patchlevel	2013-11-15 08:11:11.000000000 -0500
--- a/src/readline-1-input.patch	Sat Nov 26 22:07:12 2022 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-diff -ur readline-8.1.1/input.c readline-8.1.2/input.c
---- readline-8.1.1/input.c	2020-12-19 07:54:06.883500144 -0500
-+++ readline-8.1.2/input.c	2020-12-19 07:55:29.042995655 -0500
-@@ -819,7 +819,12 @@
- 
- #if defined (__MINGW32__)
--      if (isatty (fd)
--	return (_getch ());	/* "There is no error return." */
-+      if (isatty (fd))
-+        {
-+          int c = _getch ();
-+          if (c == 0xe0)
-+            rl_execute_next (_getch ());
-+          return (c);
-+        }
- #endif
-       result = 0;
- #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
--- a/src/readline-2-event-hook.patch	Sat Nov 26 22:07:12 2022 +0100
+++ b/src/readline-2-event-hook.patch	Sun Nov 27 19:08:31 2022 +0100
@@ -1,19 +1,20 @@
-diff -ur readline-8.1.3/input.c readline-8.1.4/input.c
---- readline-8.1.3/input.c	2020-12-19 07:56:01.572775578 -0500
-+++ readline-8.1.4/input.c	2020-12-19 07:57:24.608319024 -0500
-@@ -142,6 +142,11 @@
+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__)
-+static int _win32_getch (void);
++#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
-@@ -268,7 +273,7 @@
+@@ -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. */
@@ -22,7 +23,16 @@
     result = 0;
  #endif
  
-@@ -520,6 +525,120 @@
+@@ -404,7 +409,7 @@
+ 
+ #if defined (__MINGW32__)
+   if (isatty (tty))
+-    return (_kbhit ());
++    return (_win32_kbhit ());
+ #endif
+ 
+   return 0;
+@@ -799,6 +804,139 @@
    return (c);
  }
  
@@ -32,11 +42,12 @@
 +static int _win32_bufidx = 0;
 +
 +static int
-+_win32_getch_internal (int block)
++_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];
@@ -45,15 +56,17 @@
 +
 +  do
 +    {
++      *is_char = 0;
 +      if (! block)
 +        {
-+          if (WaitForSingleObject(hInput, _keyboard_input_timeout/1000) != WAIT_OBJECT_0)
++          if (WaitForSingleObject (hInput, _keyboard_input_timeout/1000) != WAIT_OBJECT_0)
 +            return _WIN32_READ_NOCHAR;
 +        }
 +
-+      if (!ReadConsoleInput(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:
@@ -62,49 +75,39 @@
 +                rec.Event.KeyEvent.wVirtualKeyCode > VK_MENU)) ||
 +               (!rec.Event.KeyEvent.bKeyDown &&
 +                rec.Event.KeyEvent.wVirtualKeyCode == VK_MENU &&
-+                rec.Event.KeyEvent.uChar.AsciiChar))
++                rec.Event.KeyEvent.uChar.UnicodeChar))
 +              {
-+                if (rec.Event.KeyEvent.uChar.AsciiChar)
++                if (rec.Event.KeyEvent.uChar.UnicodeChar)
++                  return (int) rec.Event.KeyEvent.uChar.UnicodeChar;
++
++                *is_char = 0;
++                switch (rec.Event.KeyEvent.wVirtualKeyCode)
 +                  {
-+                    if (rec.Event.KeyEvent.uChar.AsciiChar < 0 ||
-+                        (rec.Event.KeyEvent.uChar.AsciiChar < 32 &&
-+                         !(rec.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))))
-+                      {
-+                        char c = rec.Event.KeyEvent.uChar.AsciiChar;
-+                        if (GetOEMCP () == GetConsoleCP ())
-+                          OemToCharBuff (&c, &c, 1);
-+                        return (int)(unsigned char)c;
-+                      }
-+                    else
-+                      return (int)rec.Event.KeyEvent.uChar.UnicodeChar;
++                    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;
 +                  }
-+                else
-+                  switch (rec.Event.KeyEvent.wVirtualKeyCode)
-+                    {
-+                      case VK_UP:
-+                        _win32_buf[_win32_bufidx++] = 'H';
-+                        return 0340;
-+                      case VK_DOWN:
-+                        _win32_buf[_win32_bufidx++] = 'P';
-+                        return 0340;
-+                      case VK_RIGHT:
-+                        _win32_buf[_win32_bufidx++] = 'M';
-+                        return 0340;
-+                      case VK_LEFT:
-+                        _win32_buf[_win32_bufidx++] = 'K';
-+                        return 0340;
-+                      case VK_HOME:
-+                        _win32_buf[_win32_bufidx++] = 'G';
-+                        return 0340;
-+                      case VK_END:
-+                        _win32_buf[_win32_bufidx++] = 'O';
-+                        return 0340;
-+                      case VK_DELETE:
-+                        _win32_buf[_win32_bufidx++] = 'S';
-+                        return 0340;
-+                      default:
-+                        break;
-+                    }
 +              }
 +            break;
 +
@@ -115,7 +118,7 @@
 +          default:
 +            break;
 +        }
-+   }
++    }
 +  while (1);
 +}
 +
@@ -123,35 +126,63 @@
 +_win32_kbhit (void)
 +{
 +  int result;
++  int is_char;
 +
-+  result = _win32_getch_internal (0);
++  result = _win32_getch_internal (0, &is_char);
 +  if (result == _WIN32_READ_NOCHAR
 +      || result == EOF)
 +    return 0;
-+  _win32_buf[_win32_bufidx++] = result;
++
++  if (is_char)
++  {
++      char charbuf[5] = {0};
++      wchar_t unicode[2] = {result, 0};
++      int utf16_code_units = 1;
++      if (unicode[0] & 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 (void)
++_win32_getch (int *const is_char)
 +{
-+  return _win32_getch_internal (1);
++  return _win32_getch_internal (1, is_char);
 +}
 +#endif
 +
  int
  rl_getc (FILE *stream)
  {
-@@ -539,9 +658,9 @@
+@@ -818,8 +937,11 @@
+       /* We know at this point that _rl_caught_signal == 0 */
+ 
  #if defined (__MINGW32__)
-       if (isatty (fileno (stream)))
-         {
--          int c = _getch ();
-+          int c = _win32_getch ();
-           if (c == 0xe0)
--            rl_execute_next (_getch ());
-+            rl_execute_next (_win32_getch ());
-           return (c);
-         }
+-      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)