Imported from ../bash-3.2.48.tar.gz.
[platform/upstream/bash.git] / lib / readline / input.c
index e5af52d..4206a3e 100644 (file)
@@ -1,6 +1,6 @@
 /* input.c -- character input functions for readline. */
 
-/* Copyright (C) 1994 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2005 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #define READLINE_LIBRARY
 
+#if defined (__TANDEM)
+#  include <floss.h>
+#endif
+
 #if defined (HAVE_CONFIG_H)
 #  include <config.h>
 #endif
@@ -63,6 +67,7 @@ extern int errno;
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Some standard library routines. */
 #include "readline.h"
@@ -84,6 +89,10 @@ rl_getc_func_t *rl_getc_function = rl_getc;
 
 static int _keyboard_input_timeout = 100000;           /* 0.1 seconds; it's in usec */
 
+static int ibuffer_space PARAMS((void));
+static int rl_get_char PARAMS((int *));
+static int rl_gather_tyi PARAMS((void));
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Character Input Buffering                   */
@@ -124,8 +133,11 @@ rl_get_char (key)
     return (0);
 
   *key = ibuffer[pop_index++];
-
+#if 0
   if (pop_index >= ibuffer_len)
+#else
+  if (pop_index > ibuffer_len)
+#endif
     pop_index = 0;
 
   return (1);
@@ -134,35 +146,43 @@ rl_get_char (key)
 /* Stuff KEY into the *front* of the input buffer.
    Returns non-zero if successful, zero if there is
    no space left in the buffer. */
-static int
-rl_unget_char (key)
+int
+_rl_unget_char (key)
      int key;
 {
   if (ibuffer_space ())
     {
       pop_index--;
       if (pop_index < 0)
-       pop_index = ibuffer_len - 1;
+       pop_index = ibuffer_len;
       ibuffer[pop_index] = key;
       return (1);
     }
   return (0);
 }
 
-/* If a character is available to be read, then read it
-   and stuff it into IBUFFER.  Otherwise, just return. */
-static void
+int
+_rl_pushed_input_available ()
+{
+  return (push_index != pop_index);
+}
+
+/* If a character is available to be read, then read it and stuff it into
+   IBUFFER.  Otherwise, just return.  Returns number of characters read
+   (0 if none available) and -1 on error (EIO). */
+static int
 rl_gather_tyi ()
 {
   int tty;
   register int tem, result;
-  int chars_avail;
+  int chars_avail, k;
   char input;
 #if defined(HAVE_SELECT)
   fd_set readfds, exceptfds;
   struct timeval timeout;
 #endif
 
+  chars_avail = 0;
   tty = fileno (rl_instream);
 
 #if defined (HAVE_SELECT)
@@ -172,13 +192,17 @@ rl_gather_tyi ()
   FD_SET (tty, &exceptfds);
   timeout.tv_sec = 0;
   timeout.tv_usec = _keyboard_input_timeout;
-  if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0)
-    return;    /* Nothing to read. */
+  result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
+  if (result <= 0)
+    return 0;  /* Nothing to read. */
 #endif
 
   result = -1;
 #if defined (FIONREAD)
+  errno = 0;
   result = ioctl (tty, FIONREAD, &chars_avail);
+  if (result == -1 && errno == EIO)
+    return -1;
 #endif
 
 #if defined (O_NDELAY)
@@ -191,14 +215,26 @@ rl_gather_tyi ()
 
       fcntl (tty, F_SETFL, tem);
       if (chars_avail == -1 && errno == EAGAIN)
-       return;
+       return 0;
+      if (chars_avail == 0)    /* EOF */
+       {
+         rl_stuff_char (EOF);
+         return (0);
+       }
     }
 #endif /* O_NDELAY */
 
+#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;
+   result = 0;
+#endif
+
   /* If there's nothing available, don't waste time trying to read
      something. */
   if (chars_avail <= 0)
-    return;
+    return 0;
 
   tem = ibuffer_space ();
 
@@ -215,13 +251,21 @@ rl_gather_tyi ()
   if (result != -1)
     {
       while (chars_avail--)
-       rl_stuff_char ((*rl_getc_function) (rl_instream));
+       {
+         k = (*rl_getc_function) (rl_instream);
+         if (rl_stuff_char (k) == 0)
+           break;                      /* some problem; no more room */
+         if (k == NEWLINE || k == RETURN)
+           break;
+       }
     }
   else
     {
       if (chars_avail)
        rl_stuff_char (input);
     }
+
+  return 1;
 }
 
 int
@@ -231,13 +275,17 @@ rl_set_keyboard_input_timeout (u)
   int o;
 
   o = _keyboard_input_timeout;
-  if (u > 0)
+  if (u >= 0)
     _keyboard_input_timeout = u;
   return (o);
 }
 
 /* Is there input available to be read on the readline input file
-   descriptor?  Only works if the system has select(2) or FIONREAD. */
+   descriptor?  Only works if the system has select(2) or FIONREAD.
+   Uses the value of _keyboard_input_timeout as the timeout; if another
+   readline function wants to specify a timeout and not leave it up to
+   the user, it should use _rl_input_queued(timeout_value_in_microseconds)
+   instead. */
 int
 _rl_input_available ()
 {
@@ -245,7 +293,7 @@ _rl_input_available ()
   fd_set readfds, exceptfds;
   struct timeval timeout;
 #endif
-#if defined(FIONREAD)
+#if !defined (HAVE_SELECT) && defined(FIONREAD)
   int chars_avail;
 #endif
   int tty;
@@ -260,16 +308,35 @@ _rl_input_available ()
   timeout.tv_sec = 0;
   timeout.tv_usec = _keyboard_input_timeout;
   return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
-#endif
+#else
 
 #if defined (FIONREAD)
   if (ioctl (tty, FIONREAD, &chars_avail) == 0)
     return (chars_avail);
 #endif
 
+#endif
+
+#if defined (__MINGW32__)
+  if (isatty (tty))
+    return (_kbhit ());
+#endif
+
   return 0;
 }
 
+int
+_rl_input_queued (t)
+     int t;
+{
+  int old_timeout, r;
+
+  old_timeout = rl_set_keyboard_input_timeout (t);
+  r = _rl_input_available ();
+  rl_set_keyboard_input_timeout (old_timeout);
+  return r;
+}
+
 void
 _rl_insert_typein (c)
      int c;     
@@ -278,7 +345,7 @@ _rl_insert_typein (c)
   char *string;
 
   i = key = 0;
-  string = xmalloc (ibuffer_len + 1);
+  string = (char *)xmalloc (ibuffer_len + 1);
   string[i++] = (char) c;
 
   while ((t = rl_get_char (&key)) &&
@@ -287,7 +354,7 @@ _rl_insert_typein (c)
     string[i++] = key;
 
   if (t)
-    rl_unget_char (key);
+    _rl_unget_char (key);
 
   string[i] = '\0';
   rl_insert_text (string);
@@ -310,7 +377,11 @@ rl_stuff_char (key)
       RL_SETSTATE (RL_STATE_INPUTPENDING);
     }
   ibuffer[push_index++] = key;
+#if 0
   if (push_index >= ibuffer_len)
+#else
+  if (push_index > ibuffer_len)
+#endif
     push_index = 0;
 
   return 1;
@@ -368,7 +439,11 @@ rl_read_key ()
              (*rl_event_hook) ();
              if (rl_done)              /* XXX - experimental */
                return ('\n');
-             rl_gather_tyi ();
+             if (rl_gather_tyi () < 0) /* XXX - EIO */
+               {
+                 rl_done = 1;
+                 return ('\n');
+               }
            }
        }
       else
@@ -390,6 +465,10 @@ rl_getc (stream)
 
   while (1)
     {
+#if defined (__MINGW32__)
+      if (isatty (fileno (stream)))
+       return (getch ());
+#endif
       result = read (fileno (stream), &c, sizeof (unsigned char));
 
       if (result == sizeof (unsigned char))
@@ -431,6 +510,88 @@ rl_getc (stream)
         this is simply an interrupted system call to read ().
         Otherwise, some error ocurred, also signifying EOF. */
       if (errno != EINTR)
-       return (EOF);
+       return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
+    }
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* read multibyte char */
+int
+_rl_read_mbchar (mbchar, size)
+     char *mbchar;
+     int size;
+{
+  int mb_len, c;
+  size_t mbchar_bytes_length;
+  wchar_t wc;
+  mbstate_t ps, ps_back;
+
+  memset(&ps, 0, sizeof (mbstate_t));
+  memset(&ps_back, 0, sizeof (mbstate_t));
+
+  mb_len = 0;  
+  while (mb_len < size)
+    {
+      RL_SETSTATE(RL_STATE_MOREINPUT);
+      c = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+      if (c < 0)
+       break;
+
+      mbchar[mb_len++] = c;
+
+      mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
+      if (mbchar_bytes_length == (size_t)(-1))
+       break;          /* invalid byte sequence for the current locale */
+      else if (mbchar_bytes_length == (size_t)(-2))
+       {
+         /* shorted bytes */
+         ps = ps_back;
+         continue;
+       } 
+      else if (mbchar_bytes_length == 0)
+       {
+         mbchar[0] = '\0';     /* null wide character */
+         mb_len = 1;
+         break;
+       }
+      else if (mbchar_bytes_length > (size_t)(0))
+       break;
+    }
+
+  return mb_len;
+}
+
+/* Read a multibyte-character string whose first character is FIRST into
+   the buffer MB of length MLEN.  Returns the last character read, which
+   may be FIRST.  Used by the search functions, among others.  Very similar
+   to _rl_read_mbchar. */
+int
+_rl_read_mbstring (first, mb, mlen)
+     int first;
+     char *mb;
+     int mlen;
+{
+  int i, c;
+  mbstate_t ps;
+
+  c = first;
+  memset (mb, 0, mlen);
+  for (i = 0; c >= 0 && i < mlen; i++)
+    {
+      mb[i] = (char)c;
+      memset (&ps, 0, sizeof (mbstate_t));
+      if (_rl_get_char_len (mb, &ps) == -2)
+       {
+         /* Read more for multibyte character */
+         RL_SETSTATE (RL_STATE_MOREINPUT);
+         c = rl_read_key ();
+         RL_UNSETSTATE (RL_STATE_MOREINPUT);
+       }
+      else
+       break;
     }
+  return c;
 }
+#endif /* HANDLE_MULTIBYTE */