596 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			596 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* input.c -- character input functions for readline. */
 | 
						|
 | 
						|
/* Copyright (C) 1994-2010 Free Software Foundation, Inc.
 | 
						|
 | 
						|
   This file is part of the GNU Readline Library (Readline), a library
 | 
						|
   for reading lines of text with interactive input and history editing.      
 | 
						|
 | 
						|
   Readline is free software: you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation, either version 3 of the License, or
 | 
						|
   (at your option) any later version.
 | 
						|
 | 
						|
   Readline is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
#define READLINE_LIBRARY
 | 
						|
 | 
						|
#if defined (__TANDEM)
 | 
						|
#  include <floss.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined (HAVE_CONFIG_H)
 | 
						|
#  include <config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#if defined (HAVE_SYS_FILE_H)
 | 
						|
#  include <sys/file.h>
 | 
						|
#endif /* HAVE_SYS_FILE_H */
 | 
						|
 | 
						|
#if defined (HAVE_UNISTD_H)
 | 
						|
#  include <unistd.h>
 | 
						|
#endif /* HAVE_UNISTD_H */
 | 
						|
 | 
						|
#if defined (HAVE_STDLIB_H)
 | 
						|
#  include <stdlib.h>
 | 
						|
#else
 | 
						|
#  include "ansi_stdlib.h"
 | 
						|
#endif /* HAVE_STDLIB_H */
 | 
						|
 | 
						|
#include "posixselect.h"
 | 
						|
 | 
						|
#if defined (FIONREAD_IN_SYS_IOCTL)
 | 
						|
#  include <sys/ioctl.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#if !defined (errno)
 | 
						|
extern int errno;
 | 
						|
#endif /* !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
 | 
						|
 | 
						|
/* Non-null means it is a pointer to a function to run while waiting for
 | 
						|
   character input. */
 | 
						|
rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
 | 
						|
 | 
						|
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       	    */
 | 
						|
/*								    */
 | 
						|
/* **************************************************************** */
 | 
						|
 | 
						|
static int pop_index, push_index;
 | 
						|
static unsigned char ibuffer[512];
 | 
						|
static int ibuffer_len = sizeof (ibuffer) - 1;
 | 
						|
 | 
						|
#define any_typein (push_index != pop_index)
 | 
						|
 | 
						|
int
 | 
						|
_rl_any_typein ()
 | 
						|
{
 | 
						|
  return any_typein;
 | 
						|
}
 | 
						|
 | 
						|
/* 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 - 1);
 | 
						|
  else
 | 
						|
    return (ibuffer_len - (push_index - pop_index));
 | 
						|
}
 | 
						|
 | 
						|
/* Get a key from the buffer of characters to be read.
 | 
						|
   Return the key in KEY.
 | 
						|
   Result is KEY if there was a key, or 0 if there wasn't. */
 | 
						|
static int
 | 
						|
rl_get_char (key)
 | 
						|
     int *key;
 | 
						|
{
 | 
						|
  if (push_index == pop_index)
 | 
						|
    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);
 | 
						|
}
 | 
						|
 | 
						|
/* Stuff KEY into the *front* of the input buffer.
 | 
						|
   Returns non-zero if successful, zero if there is
 | 
						|
   no space left in the buffer. */
 | 
						|
int
 | 
						|
_rl_unget_char (key)
 | 
						|
     int key;
 | 
						|
{
 | 
						|
  if (ibuffer_space ())
 | 
						|
    {
 | 
						|
      pop_index--;
 | 
						|
      if (pop_index < 0)
 | 
						|
	pop_index = ibuffer_len;
 | 
						|
      ibuffer[pop_index] = key;
 | 
						|
      return (1);
 | 
						|
    }
 | 
						|
  return (0);
 | 
						|
}
 | 
						|
 | 
						|
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, 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)
 | 
						|
  FD_ZERO (&readfds);
 | 
						|
  FD_ZERO (&exceptfds);
 | 
						|
  FD_SET (tty, &readfds);
 | 
						|
  FD_SET (tty, &exceptfds);
 | 
						|
  USEC_TO_TIMEVAL (_keyboard_input_timeout, 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)
 | 
						|
  if (result == -1)
 | 
						|
    {
 | 
						|
      tem = fcntl (tty, F_GETFL, 0);
 | 
						|
 | 
						|
      fcntl (tty, F_SETFL, (tem | O_NDELAY));
 | 
						|
      chars_avail = read (tty, &input, 1);
 | 
						|
 | 
						|
      fcntl (tty, F_SETFL, tem);
 | 
						|
      if (chars_avail == -1 && errno == EAGAIN)
 | 
						|
	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 0;
 | 
						|
 | 
						|
  tem = ibuffer_space ();
 | 
						|
 | 
						|
  if (chars_avail > tem)
 | 
						|
    chars_avail = tem;
 | 
						|
 | 
						|
  /* One cannot read all of the available input.  I can only read a single
 | 
						|
     character at a time, or else programs which require input can be
 | 
						|
     thwarted.  If the buffer is larger than one character, I lose.
 | 
						|
     Damn! */
 | 
						|
  if (tem < ibuffer_len)
 | 
						|
    chars_avail = 0;
 | 
						|
 | 
						|
  if (result != -1)
 | 
						|
    {
 | 
						|
      while (chars_avail--)
 | 
						|
	{
 | 
						|
	  RL_CHECK_SIGNALS ();
 | 
						|
	  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
 | 
						|
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.
 | 
						|
   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 ()
 | 
						|
{
 | 
						|
#if defined(HAVE_SELECT)
 | 
						|
  fd_set readfds, exceptfds;
 | 
						|
  struct timeval timeout;
 | 
						|
#endif
 | 
						|
#if !defined (HAVE_SELECT) && defined(FIONREAD)
 | 
						|
  int chars_avail;
 | 
						|
#endif
 | 
						|
  int tty;
 | 
						|
 | 
						|
  tty = fileno (rl_instream);
 | 
						|
 | 
						|
#if defined (HAVE_SELECT)
 | 
						|
  FD_ZERO (&readfds);
 | 
						|
  FD_ZERO (&exceptfds);
 | 
						|
  FD_SET (tty, &readfds);
 | 
						|
  FD_SET (tty, &exceptfds);
 | 
						|
  timeout.tv_sec = 0;
 | 
						|
  timeout.tv_usec = _keyboard_input_timeout;
 | 
						|
  return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
 | 
						|
#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;     
 | 
						|
{    	
 | 
						|
  int key, t, i;
 | 
						|
  char *string;
 | 
						|
 | 
						|
  i = key = 0;
 | 
						|
  string = (char *)xmalloc (ibuffer_len + 1);
 | 
						|
  string[i++] = (char) c;
 | 
						|
 | 
						|
  while ((t = rl_get_char (&key)) &&
 | 
						|
	 _rl_keymap[key].type == ISFUNC &&
 | 
						|
	 _rl_keymap[key].function == rl_insert)
 | 
						|
    string[i++] = key;
 | 
						|
 | 
						|
  if (t)
 | 
						|
    _rl_unget_char (key);
 | 
						|
 | 
						|
  string[i] = '\0';
 | 
						|
  rl_insert_text (string);
 | 
						|
  xfree (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			    */
 | 
						|
/*								    */
 | 
						|
/* **************************************************************** */
 | 
						|
 | 
						|
/* Read a key, including pending input. */
 | 
						|
int
 | 
						|
rl_read_key ()
 | 
						|
{
 | 
						|
  int c;
 | 
						|
 | 
						|
  rl_key_sequence_length++;
 | 
						|
 | 
						|
  if (rl_pending_input)
 | 
						|
    {
 | 
						|
      c = rl_pending_input;
 | 
						|
      rl_clear_pending_input ();
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      /* If input is coming from a macro, then use that. */
 | 
						|
      if (c = _rl_next_macro_key ())
 | 
						|
	return (c);
 | 
						|
 | 
						|
      /* If the user has an event function, then call it periodically. */
 | 
						|
      if (rl_event_hook)
 | 
						|
	{
 | 
						|
	  while (rl_event_hook)
 | 
						|
	    {
 | 
						|
	      if (rl_gather_tyi () < 0)	/* XXX - EIO */
 | 
						|
		{
 | 
						|
		  rl_done = 1;
 | 
						|
		  return ('\n');
 | 
						|
		}
 | 
						|
	      RL_CHECK_SIGNALS ();
 | 
						|
	      if (rl_get_char (&c) != 0)
 | 
						|
		break;
 | 
						|
	      if (rl_done)		/* XXX - experimental */
 | 
						|
		return ('\n');
 | 
						|
	      (*rl_event_hook) ();
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  if (rl_get_char (&c) == 0)
 | 
						|
	    c = (*rl_getc_function) (rl_instream);
 | 
						|
	  RL_CHECK_SIGNALS ();
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  return (c);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
rl_getc (stream)
 | 
						|
     FILE *stream;
 | 
						|
{
 | 
						|
  int result;
 | 
						|
  unsigned char c;
 | 
						|
 | 
						|
  while (1)
 | 
						|
    {
 | 
						|
      RL_CHECK_SIGNALS ();
 | 
						|
 | 
						|
#if defined (__MINGW32__)
 | 
						|
      if (isatty (fileno (stream)))
 | 
						|
	return (getch ());
 | 
						|
#endif
 | 
						|
      result = read (fileno (stream), &c, sizeof (unsigned char));
 | 
						|
 | 
						|
      if (result == sizeof (unsigned char))
 | 
						|
	return (c);
 | 
						|
 | 
						|
      /* If zero characters are returned, then the file that we are
 | 
						|
	 reading from is empty!  Return EOF in that case. */
 | 
						|
      if (result == 0)
 | 
						|
	return (EOF);
 | 
						|
 | 
						|
#if defined (__BEOS__)
 | 
						|
      if (errno == EINTR)
 | 
						|
	continue;
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined (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 (sh_unset_nodelay_mode (fileno (stream)) < 0)
 | 
						|
	    return (EOF);
 | 
						|
	  continue;
 | 
						|
	}
 | 
						|
 | 
						|
#undef X_EWOULDBLOCK
 | 
						|
#undef X_EAGAIN
 | 
						|
 | 
						|
      /* 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 (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 */
 |