Imported from ../bash-3.2.48.tar.gz.
[platform/upstream/bash.git] / lib / readline / input.c
index 7e3c0fe..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.
    The GNU General Public License is often shipped with GNU software, and
    is generally kept in a file called COPYING or LICENSE.  If you do not
    have a copy of the license, write to the Free Software Foundation,
-   675 Mass Ave, Cambridge, MA 02139, USA. */
+   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,48 +67,31 @@ extern int errno;
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Some standard library routines. */
 #include "readline.h"
 
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
 /* What kind of non-blocking I/O do we have? */
 #if !defined (O_NDELAY) && defined (O_NONBLOCK)
 #  define O_NDELAY O_NONBLOCK  /* Posix style */
 #endif
 
-/* Functions imported from other files in the library. */
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables and functions from macro.c. */
-extern void _rl_add_macro_char ();
-extern void _rl_with_macro_input ();
-extern int _rl_next_macro_key ();
-extern int _rl_defining_kbd_macro;
-
-#if defined (VI_MODE)
-extern void _rl_vi_set_last ();
-extern int _rl_vi_textmod_command ();
-#endif /* VI_MODE */
-
-extern FILE *rl_instream, *rl_outstream;
-extern Function *rl_last_func;
-extern int rl_key_sequence_length;
-extern int rl_pending_input;
-extern int rl_editing_mode;
-
-extern Keymap _rl_keymap;
-
-extern int _rl_convert_meta_chars_to_ascii;
-
-#if defined (__GO32__)
-#  include <pc.h>
-#endif /* __GO32__ */
-
 /* Non-null means it is a pointer to a function to run while waiting for
    character input. */
-Function *rl_event_hook = (Function *)NULL;
+rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
 
-Function *rl_getc_function = rl_getc;
+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));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -124,38 +111,13 @@ _rl_any_typein ()
   return any_typein;
 }
 
-/* Add KEY to the buffer of characters to be read. */
-int
-rl_stuff_char (key)
-     int key;
-{
-  if (key == EOF)
-    {
-      key = NEWLINE;
-      rl_pending_input = EOF;
-    }
-  ibuffer[push_index++] = key;
-  if (push_index >= ibuffer_len)
-    push_index = 0;
-  return push_index;
-}
-
-/* Make C be the next command to be executed. */
-int
-rl_execute_next (c)
-     int c;
-{
-  rl_pending_input = c;
-  return 0;
-}
-
-/* Return the amount of space available in the
-   buffer for stuffing characters. */
+/* Return the amount of space available in the buffer for stuffing
+   characters. */
 static int
 ibuffer_space ()
 {
   if (pop_index > push_index)
-    return (pop_index - push_index);
+    return (pop_index - push_index - 1);
   else
     return (ibuffer_len - (push_index - pop_index));
 }
@@ -171,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);
@@ -181,46 +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
-rl_gather_tyi ()
+int
+_rl_pushed_input_available ()
 {
-#if defined (__GO32__)
-  char input;
-
-  if (isatty (0) && kbhit () && ibuffer_space ())
-    {
-      int i;
-      i = (*rl_getc_function) (rl_instream);
-      rl_stuff_char (i);
-    }
-#else /* !__GO32__ */
+  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)
@@ -229,14 +191,18 @@ rl_gather_tyi ()
   FD_SET (tty, &readfds);
   FD_SET (tty, &exceptfds);
   timeout.tv_sec = 0;
-  timeout.tv_usec = 100000;    /* 0.1 seconds */
-  if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0)
-    return;    /* Nothing to read. */
+  timeout.tv_usec = _keyboard_input_timeout;
+  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)
@@ -249,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 ();
 
@@ -273,18 +251,41 @@ 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);
     }
-#endif /* !__GO32__ */
+
+  return 1;
+}
+
+int
+rl_set_keyboard_input_timeout (u)
+     int u;
+{
+  int o;
+
+  o = _keyboard_input_timeout;
+  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 ()
 {
@@ -292,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;
@@ -305,18 +306,37 @@ _rl_input_available ()
   FD_SET (tty, &readfds);
   FD_SET (tty, &exceptfds);
   timeout.tv_sec = 0;
-  timeout.tv_usec = 100000;    /* 0.1 seconds */
+  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;     
@@ -325,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)) &&
@@ -334,13 +354,58 @@ _rl_insert_typein (c)
     string[i++] = key;
 
   if (t)
-    rl_unget_char (key);
+    _rl_unget_char (key);
 
   string[i] = '\0';
   rl_insert_text (string);
   free (string);
 }
 
+/* Add KEY to the buffer of characters to be read.  Returns 1 if the
+   character was stuffed correctly; 0 otherwise. */
+int
+rl_stuff_char (key)
+     int key;
+{
+  if (ibuffer_space () == 0)
+    return 0;
+
+  if (key == EOF)
+    {
+      key = NEWLINE;
+      rl_pending_input = EOF;
+      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;
+}
+
+/* Make C be the next command to be executed. */
+int
+rl_execute_next (c)
+     int c;
+{
+  rl_pending_input = c;
+  RL_SETSTATE (RL_STATE_INPUTPENDING);
+  return 0;
+}
+
+/* Clear any pending input pushed with rl_execute_next() */
+int
+rl_clear_pending_input ()
+{
+  rl_pending_input = 0;
+  RL_UNSETSTATE (RL_STATE_INPUTPENDING);
+  return 0;
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*                          Character Input                        */
@@ -358,7 +423,7 @@ rl_read_key ()
   if (rl_pending_input)
     {
       c = rl_pending_input;
-      rl_pending_input = 0;
+      rl_clear_pending_input ();
     }
   else
     {
@@ -372,7 +437,13 @@ rl_read_key ()
          while (rl_event_hook && rl_get_char (&c) == 0)
            {
              (*rl_event_hook) ();
-             rl_gather_tyi ();
+             if (rl_done)              /* XXX - experimental */
+               return ('\n');
+             if (rl_gather_tyi () < 0) /* XXX - EIO */
+               {
+                 rl_done = 1;
+                 return ('\n');
+               }
            }
        }
       else
@@ -389,16 +460,15 @@ int
 rl_getc (stream)
      FILE *stream;
 {
-  int result, flags;
+  int result;
   unsigned char c;
 
-#if defined (__GO32__)
-  if (isatty (0))
-    return (getkey () & 0x7F);
-#endif /* __GO32__ */
-
   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))
@@ -409,41 +479,119 @@ rl_getc (stream)
       if (result == 0)
        return (EOF);
 
+#if defined (__BEOS__)
+      if (errno == EINTR)
+       continue;
+#endif
+
 #if defined (EWOULDBLOCK)
-      if (errno == EWOULDBLOCK)
+#  define X_EWOULDBLOCK EWOULDBLOCK
+#else
+#  define X_EWOULDBLOCK -99
+#endif
+
+#if defined (EAGAIN)
+#  define X_EAGAIN EAGAIN
+#else
+#  define X_EAGAIN -99
+#endif
+
+      if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
        {
-         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
+         if (sh_unset_nodelay_mode (fileno (stream)) < 0)
            return (EOF);
-         if (flags & O_NDELAY)
-           {
-             flags &= ~O_NDELAY;
-             fcntl (fileno (stream), F_SETFL, flags);
-             continue;
-           }
          continue;
        }
-#endif /* EWOULDBLOCK */
 
-#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK)
-      if (errno == EAGAIN)
-       {
-         if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0)
-           return (EOF);
-         if (flags & O_NONBLOCK)
-           {
-             flags &= ~O_NONBLOCK;
-             fcntl (fileno (stream), F_SETFL, flags);
-             continue;
-           }
-       }
-#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */
+#undef X_EWOULDBLOCK
+#undef X_EAGAIN
 
-#if !defined (__GO32__)
       /* If the error that we received was SIGINT, then try again,
         this is simply an interrupted system call to read ().
         Otherwise, some error ocurred, also signifying EOF. */
       if (errno != EINTR)
-       return (EOF);
-#endif /* !__GO32__ */
+       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 */