11acd27e7Smillert /* input.c -- character input functions for readline. */
21acd27e7Smillert
31acd27e7Smillert /* Copyright (C) 1994 Free Software Foundation, Inc.
41acd27e7Smillert
51acd27e7Smillert This file is part of the GNU Readline Library, a library for
61acd27e7Smillert reading lines of text with interactive input and history editing.
71acd27e7Smillert
81acd27e7Smillert The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert (at your option) any later version.
121acd27e7Smillert
131acd27e7Smillert The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161acd27e7Smillert GNU General Public License for more details.
171acd27e7Smillert
181acd27e7Smillert The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert is generally kept in a file called COPYING or LICENSE. If you do not
201acd27e7Smillert have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert # include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert #include <fcntl.h>
301acd27e7Smillert #if defined (HAVE_SYS_FILE_H)
311acd27e7Smillert # include <sys/file.h>
321acd27e7Smillert #endif /* HAVE_SYS_FILE_H */
331acd27e7Smillert
341acd27e7Smillert #if defined (HAVE_UNISTD_H)
351acd27e7Smillert # include <unistd.h>
361acd27e7Smillert #endif /* HAVE_UNISTD_H */
371acd27e7Smillert
381acd27e7Smillert #if defined (HAVE_STDLIB_H)
391acd27e7Smillert # include <stdlib.h>
401acd27e7Smillert #else
411acd27e7Smillert # include "ansi_stdlib.h"
421acd27e7Smillert #endif /* HAVE_STDLIB_H */
431acd27e7Smillert
441acd27e7Smillert #if defined (HAVE_SELECT)
451acd27e7Smillert # if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
461acd27e7Smillert # include <sys/time.h>
471acd27e7Smillert # endif
481acd27e7Smillert #endif /* HAVE_SELECT */
491acd27e7Smillert #if defined (HAVE_SYS_SELECT_H)
501acd27e7Smillert # include <sys/select.h>
511acd27e7Smillert #endif
521acd27e7Smillert
531acd27e7Smillert #if defined (FIONREAD_IN_SYS_IOCTL)
541acd27e7Smillert # include <sys/ioctl.h>
551acd27e7Smillert #endif
561acd27e7Smillert
571acd27e7Smillert #include <stdio.h>
581acd27e7Smillert #include <errno.h>
591acd27e7Smillert
601acd27e7Smillert #if !defined (errno)
611acd27e7Smillert extern int errno;
621acd27e7Smillert #endif /* !errno */
631acd27e7Smillert
641acd27e7Smillert /* System-specific feature definitions and include files. */
651acd27e7Smillert #include "rldefs.h"
6615b117eaSkettenis #include "rlmbutil.h"
671acd27e7Smillert
681acd27e7Smillert /* Some standard library routines. */
691acd27e7Smillert #include "readline.h"
701acd27e7Smillert
711acd27e7Smillert #include "rlprivate.h"
721acd27e7Smillert #include "rlshell.h"
731acd27e7Smillert #include "xmalloc.h"
741acd27e7Smillert
751acd27e7Smillert /* What kind of non-blocking I/O do we have? */
761acd27e7Smillert #if !defined (O_NDELAY) && defined (O_NONBLOCK)
771acd27e7Smillert # define O_NDELAY O_NONBLOCK /* Posix style */
781acd27e7Smillert #endif
791acd27e7Smillert
801acd27e7Smillert /* Non-null means it is a pointer to a function to run while waiting for
811acd27e7Smillert character input. */
8215b117eaSkettenis rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
831acd27e7Smillert
8415b117eaSkettenis rl_getc_func_t *rl_getc_function = rl_getc;
8515b117eaSkettenis
8615b117eaSkettenis static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
8715b117eaSkettenis
8815b117eaSkettenis static int ibuffer_space PARAMS((void));
8915b117eaSkettenis static int rl_get_char PARAMS((int *));
9015b117eaSkettenis static int rl_gather_tyi PARAMS((void));
911acd27e7Smillert
921acd27e7Smillert /* **************************************************************** */
931acd27e7Smillert /* */
941acd27e7Smillert /* Character Input Buffering */
951acd27e7Smillert /* */
961acd27e7Smillert /* **************************************************************** */
971acd27e7Smillert
981acd27e7Smillert static int pop_index, push_index;
991acd27e7Smillert static unsigned char ibuffer[512];
1001acd27e7Smillert static int ibuffer_len = sizeof (ibuffer) - 1;
1011acd27e7Smillert
1021acd27e7Smillert #define any_typein (push_index != pop_index)
1031acd27e7Smillert
1041acd27e7Smillert int
_rl_any_typein()1051acd27e7Smillert _rl_any_typein ()
1061acd27e7Smillert {
1071acd27e7Smillert return any_typein;
1081acd27e7Smillert }
1091acd27e7Smillert
1101acd27e7Smillert /* Return the amount of space available in the buffer for stuffing
1111acd27e7Smillert characters. */
1121acd27e7Smillert static int
ibuffer_space()1131acd27e7Smillert ibuffer_space ()
1141acd27e7Smillert {
1151acd27e7Smillert if (pop_index > push_index)
1161acd27e7Smillert return (pop_index - push_index - 1);
1171acd27e7Smillert else
1181acd27e7Smillert return (ibuffer_len - (push_index - pop_index));
1191acd27e7Smillert }
1201acd27e7Smillert
1211acd27e7Smillert /* Get a key from the buffer of characters to be read.
1221acd27e7Smillert Return the key in KEY.
1231acd27e7Smillert Result is KEY if there was a key, or 0 if there wasn't. */
1241acd27e7Smillert static int
rl_get_char(key)1251acd27e7Smillert rl_get_char (key)
1261acd27e7Smillert int *key;
1271acd27e7Smillert {
1281acd27e7Smillert if (push_index == pop_index)
1291acd27e7Smillert return (0);
1301acd27e7Smillert
1311acd27e7Smillert *key = ibuffer[pop_index++];
1321acd27e7Smillert
1331acd27e7Smillert if (pop_index >= ibuffer_len)
1341acd27e7Smillert pop_index = 0;
1351acd27e7Smillert
1361acd27e7Smillert return (1);
1371acd27e7Smillert }
1381acd27e7Smillert
1391acd27e7Smillert /* Stuff KEY into the *front* of the input buffer.
1401acd27e7Smillert Returns non-zero if successful, zero if there is
1411acd27e7Smillert no space left in the buffer. */
14215b117eaSkettenis int
_rl_unget_char(key)14315b117eaSkettenis _rl_unget_char (key)
1441acd27e7Smillert int key;
1451acd27e7Smillert {
1461acd27e7Smillert if (ibuffer_space ())
1471acd27e7Smillert {
1481acd27e7Smillert pop_index--;
1491acd27e7Smillert if (pop_index < 0)
1501acd27e7Smillert pop_index = ibuffer_len - 1;
1511acd27e7Smillert ibuffer[pop_index] = key;
1521acd27e7Smillert return (1);
1531acd27e7Smillert }
1541acd27e7Smillert return (0);
1551acd27e7Smillert }
1561acd27e7Smillert
15727b28cd4Snicm int
_rl_pushed_input_available()15827b28cd4Snicm _rl_pushed_input_available ()
15927b28cd4Snicm {
16027b28cd4Snicm return (push_index != pop_index);
16127b28cd4Snicm }
16227b28cd4Snicm
16315b117eaSkettenis /* If a character is available to be read, then read it and stuff it into
16415b117eaSkettenis IBUFFER. Otherwise, just return. Returns number of characters read
16515b117eaSkettenis (0 if none available) and -1 on error (EIO). */
16615b117eaSkettenis static int
rl_gather_tyi()1671acd27e7Smillert rl_gather_tyi ()
1681acd27e7Smillert {
1691acd27e7Smillert int tty;
1701acd27e7Smillert register int tem, result;
1711acd27e7Smillert int chars_avail;
1721acd27e7Smillert char input;
1731acd27e7Smillert #if defined(HAVE_SELECT)
1741acd27e7Smillert fd_set readfds, exceptfds;
1751acd27e7Smillert struct timeval timeout;
1761acd27e7Smillert #endif
1771acd27e7Smillert
1781acd27e7Smillert tty = fileno (rl_instream);
1791acd27e7Smillert
1801acd27e7Smillert #if defined (HAVE_SELECT)
1811acd27e7Smillert FD_ZERO (&readfds);
1821acd27e7Smillert FD_ZERO (&exceptfds);
1831acd27e7Smillert FD_SET (tty, &readfds);
1841acd27e7Smillert FD_SET (tty, &exceptfds);
1851acd27e7Smillert timeout.tv_sec = 0;
18615b117eaSkettenis timeout.tv_usec = _keyboard_input_timeout;
18715b117eaSkettenis result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
18815b117eaSkettenis if (result <= 0)
18915b117eaSkettenis return 0; /* Nothing to read. */
1901acd27e7Smillert #endif
1911acd27e7Smillert
1921acd27e7Smillert result = -1;
1931acd27e7Smillert #if defined (FIONREAD)
19415b117eaSkettenis errno = 0;
1951acd27e7Smillert result = ioctl (tty, FIONREAD, &chars_avail);
19615b117eaSkettenis if (result == -1 && errno == EIO)
19715b117eaSkettenis return -1;
1981acd27e7Smillert #endif
1991acd27e7Smillert
2001acd27e7Smillert #if defined (O_NDELAY)
2011acd27e7Smillert if (result == -1)
2021acd27e7Smillert {
2031acd27e7Smillert tem = fcntl (tty, F_GETFL, 0);
2041acd27e7Smillert
2051acd27e7Smillert fcntl (tty, F_SETFL, (tem | O_NDELAY));
2061acd27e7Smillert chars_avail = read (tty, &input, 1);
2071acd27e7Smillert
2081acd27e7Smillert fcntl (tty, F_SETFL, tem);
2091acd27e7Smillert if (chars_avail == -1 && errno == EAGAIN)
21015b117eaSkettenis return 0;
2111acd27e7Smillert }
2121acd27e7Smillert #endif /* O_NDELAY */
2131acd27e7Smillert
2141acd27e7Smillert /* If there's nothing available, don't waste time trying to read
2151acd27e7Smillert something. */
2161acd27e7Smillert if (chars_avail <= 0)
21715b117eaSkettenis return 0;
2181acd27e7Smillert
2191acd27e7Smillert tem = ibuffer_space ();
2201acd27e7Smillert
2211acd27e7Smillert if (chars_avail > tem)
2221acd27e7Smillert chars_avail = tem;
2231acd27e7Smillert
2241acd27e7Smillert /* One cannot read all of the available input. I can only read a single
2251acd27e7Smillert character at a time, or else programs which require input can be
2261acd27e7Smillert thwarted. If the buffer is larger than one character, I lose.
2271acd27e7Smillert Damn! */
2281acd27e7Smillert if (tem < ibuffer_len)
2291acd27e7Smillert chars_avail = 0;
2301acd27e7Smillert
2311acd27e7Smillert if (result != -1)
2321acd27e7Smillert {
2331acd27e7Smillert while (chars_avail--)
2341acd27e7Smillert rl_stuff_char ((*rl_getc_function) (rl_instream));
2351acd27e7Smillert }
2361acd27e7Smillert else
2371acd27e7Smillert {
2381acd27e7Smillert if (chars_avail)
2391acd27e7Smillert rl_stuff_char (input);
2401acd27e7Smillert }
24115b117eaSkettenis
24215b117eaSkettenis return 1;
24315b117eaSkettenis }
24415b117eaSkettenis
24515b117eaSkettenis int
rl_set_keyboard_input_timeout(u)24615b117eaSkettenis rl_set_keyboard_input_timeout (u)
24715b117eaSkettenis int u;
24815b117eaSkettenis {
24915b117eaSkettenis int o;
25015b117eaSkettenis
25115b117eaSkettenis o = _keyboard_input_timeout;
25215b117eaSkettenis if (u > 0)
25315b117eaSkettenis _keyboard_input_timeout = u;
25415b117eaSkettenis return (o);
2551acd27e7Smillert }
2561acd27e7Smillert
2571acd27e7Smillert /* Is there input available to be read on the readline input file
25815b117eaSkettenis descriptor? Only works if the system has select(2) or FIONREAD.
25915b117eaSkettenis Uses the value of _keyboard_input_timeout as the timeout; if another
26015b117eaSkettenis readline function wants to specify a timeout and not leave it up to
26115b117eaSkettenis the user, it should use _rl_input_queued(timeout_value_in_microseconds)
26215b117eaSkettenis instead. */
2631acd27e7Smillert int
_rl_input_available()2641acd27e7Smillert _rl_input_available ()
2651acd27e7Smillert {
2661acd27e7Smillert #if defined(HAVE_SELECT)
2671acd27e7Smillert fd_set readfds, exceptfds;
2681acd27e7Smillert struct timeval timeout;
2691acd27e7Smillert #endif
27015b117eaSkettenis #if !defined (HAVE_SELECT) && defined(FIONREAD)
2711acd27e7Smillert int chars_avail;
2721acd27e7Smillert #endif
2731acd27e7Smillert int tty;
2741acd27e7Smillert
2751acd27e7Smillert tty = fileno (rl_instream);
2761acd27e7Smillert
2771acd27e7Smillert #if defined (HAVE_SELECT)
2781acd27e7Smillert FD_ZERO (&readfds);
2791acd27e7Smillert FD_ZERO (&exceptfds);
2801acd27e7Smillert FD_SET (tty, &readfds);
2811acd27e7Smillert FD_SET (tty, &exceptfds);
2821acd27e7Smillert timeout.tv_sec = 0;
28315b117eaSkettenis timeout.tv_usec = _keyboard_input_timeout;
2841acd27e7Smillert return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
28515b117eaSkettenis #else
2861acd27e7Smillert
2871acd27e7Smillert #if defined (FIONREAD)
2881acd27e7Smillert if (ioctl (tty, FIONREAD, &chars_avail) == 0)
2891acd27e7Smillert return (chars_avail);
2901acd27e7Smillert #endif
2911acd27e7Smillert
29215b117eaSkettenis #endif
29315b117eaSkettenis
2941acd27e7Smillert return 0;
2951acd27e7Smillert }
2961acd27e7Smillert
29715b117eaSkettenis int
_rl_input_queued(t)29815b117eaSkettenis _rl_input_queued (t)
29915b117eaSkettenis int t;
30015b117eaSkettenis {
30115b117eaSkettenis int old_timeout, r;
30215b117eaSkettenis
30315b117eaSkettenis old_timeout = rl_set_keyboard_input_timeout (t);
30415b117eaSkettenis r = _rl_input_available ();
30515b117eaSkettenis rl_set_keyboard_input_timeout (old_timeout);
30615b117eaSkettenis return r;
30715b117eaSkettenis }
30815b117eaSkettenis
3091acd27e7Smillert void
_rl_insert_typein(c)3101acd27e7Smillert _rl_insert_typein (c)
3111acd27e7Smillert int c;
3121acd27e7Smillert {
3131acd27e7Smillert int key, t, i;
3141acd27e7Smillert char *string;
3151acd27e7Smillert
3161acd27e7Smillert i = key = 0;
31715b117eaSkettenis string = (char *)xmalloc (ibuffer_len + 1);
3181acd27e7Smillert string[i++] = (char) c;
3191acd27e7Smillert
3201acd27e7Smillert while ((t = rl_get_char (&key)) &&
3211acd27e7Smillert _rl_keymap[key].type == ISFUNC &&
3221acd27e7Smillert _rl_keymap[key].function == rl_insert)
3231acd27e7Smillert string[i++] = key;
3241acd27e7Smillert
3251acd27e7Smillert if (t)
32615b117eaSkettenis _rl_unget_char (key);
3271acd27e7Smillert
3281acd27e7Smillert string[i] = '\0';
3291acd27e7Smillert rl_insert_text (string);
3301acd27e7Smillert free (string);
3311acd27e7Smillert }
3321acd27e7Smillert
3331acd27e7Smillert /* Add KEY to the buffer of characters to be read. Returns 1 if the
3341acd27e7Smillert character was stuffed correctly; 0 otherwise. */
3351acd27e7Smillert int
rl_stuff_char(key)3361acd27e7Smillert rl_stuff_char (key)
3371acd27e7Smillert int key;
3381acd27e7Smillert {
3391acd27e7Smillert if (ibuffer_space () == 0)
3401acd27e7Smillert return 0;
3411acd27e7Smillert
3421acd27e7Smillert if (key == EOF)
3431acd27e7Smillert {
3441acd27e7Smillert key = NEWLINE;
3451acd27e7Smillert rl_pending_input = EOF;
34615b117eaSkettenis RL_SETSTATE (RL_STATE_INPUTPENDING);
3471acd27e7Smillert }
3481acd27e7Smillert ibuffer[push_index++] = key;
3491acd27e7Smillert if (push_index >= ibuffer_len)
3501acd27e7Smillert push_index = 0;
3511acd27e7Smillert
3521acd27e7Smillert return 1;
3531acd27e7Smillert }
3541acd27e7Smillert
3551acd27e7Smillert /* Make C be the next command to be executed. */
3561acd27e7Smillert int
rl_execute_next(c)3571acd27e7Smillert rl_execute_next (c)
3581acd27e7Smillert int c;
3591acd27e7Smillert {
3601acd27e7Smillert rl_pending_input = c;
36115b117eaSkettenis RL_SETSTATE (RL_STATE_INPUTPENDING);
36215b117eaSkettenis return 0;
36315b117eaSkettenis }
36415b117eaSkettenis
36515b117eaSkettenis /* Clear any pending input pushed with rl_execute_next() */
36615b117eaSkettenis int
rl_clear_pending_input()36715b117eaSkettenis rl_clear_pending_input ()
36815b117eaSkettenis {
36915b117eaSkettenis rl_pending_input = 0;
37015b117eaSkettenis RL_UNSETSTATE (RL_STATE_INPUTPENDING);
3711acd27e7Smillert return 0;
3721acd27e7Smillert }
3731acd27e7Smillert
3741acd27e7Smillert /* **************************************************************** */
3751acd27e7Smillert /* */
3761acd27e7Smillert /* Character Input */
3771acd27e7Smillert /* */
3781acd27e7Smillert /* **************************************************************** */
3791acd27e7Smillert
3801acd27e7Smillert /* Read a key, including pending input. */
3811acd27e7Smillert int
rl_read_key()3821acd27e7Smillert rl_read_key ()
3831acd27e7Smillert {
3841acd27e7Smillert int c;
3851acd27e7Smillert
3861acd27e7Smillert rl_key_sequence_length++;
3871acd27e7Smillert
3881acd27e7Smillert if (rl_pending_input)
3891acd27e7Smillert {
3901acd27e7Smillert c = rl_pending_input;
39115b117eaSkettenis rl_clear_pending_input ();
3921acd27e7Smillert }
3931acd27e7Smillert else
3941acd27e7Smillert {
3951acd27e7Smillert /* If input is coming from a macro, then use that. */
396*af1e7b8cSkrw if ((c = _rl_next_macro_key ()))
3971acd27e7Smillert return (c);
3981acd27e7Smillert
3991acd27e7Smillert /* If the user has an event function, then call it periodically. */
4001acd27e7Smillert if (rl_event_hook)
4011acd27e7Smillert {
4021acd27e7Smillert while (rl_event_hook && rl_get_char (&c) == 0)
4031acd27e7Smillert {
4041acd27e7Smillert (*rl_event_hook) ();
40515b117eaSkettenis if (rl_done) /* XXX - experimental */
40615b117eaSkettenis return ('\n');
40715b117eaSkettenis if (rl_gather_tyi () < 0) /* XXX - EIO */
40815b117eaSkettenis {
40915b117eaSkettenis rl_done = 1;
41015b117eaSkettenis return ('\n');
41115b117eaSkettenis }
4121acd27e7Smillert }
4131acd27e7Smillert }
4141acd27e7Smillert else
4151acd27e7Smillert {
4161acd27e7Smillert if (rl_get_char (&c) == 0)
4171acd27e7Smillert c = (*rl_getc_function) (rl_instream);
4181acd27e7Smillert }
4191acd27e7Smillert }
4201acd27e7Smillert
4211acd27e7Smillert return (c);
4221acd27e7Smillert }
4231acd27e7Smillert
4241acd27e7Smillert int
rl_getc(stream)4251acd27e7Smillert rl_getc (stream)
4261acd27e7Smillert FILE *stream;
4271acd27e7Smillert {
4281acd27e7Smillert int result;
4291acd27e7Smillert unsigned char c;
4301acd27e7Smillert
4311acd27e7Smillert while (1)
4321acd27e7Smillert {
4331acd27e7Smillert result = read (fileno (stream), &c, sizeof (unsigned char));
4341acd27e7Smillert
4351acd27e7Smillert if (result == sizeof (unsigned char))
4361acd27e7Smillert return (c);
4371acd27e7Smillert
4381acd27e7Smillert /* If zero characters are returned, then the file that we are
4391acd27e7Smillert reading from is empty! Return EOF in that case. */
4401acd27e7Smillert if (result == 0)
4411acd27e7Smillert return (EOF);
4421acd27e7Smillert
4431acd27e7Smillert #if defined (__BEOS__)
4441acd27e7Smillert if (errno == EINTR)
4451acd27e7Smillert continue;
4461acd27e7Smillert #endif
4471acd27e7Smillert
4481acd27e7Smillert #if defined (EWOULDBLOCK)
4491acd27e7Smillert # define X_EWOULDBLOCK EWOULDBLOCK
4501acd27e7Smillert #else
4511acd27e7Smillert # define X_EWOULDBLOCK -99
4521acd27e7Smillert #endif
4531acd27e7Smillert
4541acd27e7Smillert #if defined (EAGAIN)
4551acd27e7Smillert # define X_EAGAIN EAGAIN
4561acd27e7Smillert #else
4571acd27e7Smillert # define X_EAGAIN -99
4581acd27e7Smillert #endif
4591acd27e7Smillert
4601acd27e7Smillert if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
4611acd27e7Smillert {
46215b117eaSkettenis if (sh_unset_nodelay_mode (fileno (stream)) < 0)
4631acd27e7Smillert return (EOF);
4641acd27e7Smillert continue;
4651acd27e7Smillert }
4661acd27e7Smillert
4671acd27e7Smillert #undef X_EWOULDBLOCK
4681acd27e7Smillert #undef X_EAGAIN
4691acd27e7Smillert
4701acd27e7Smillert /* If the error that we received was SIGINT, then try again,
4711acd27e7Smillert this is simply an interrupted system call to read ().
4721acd27e7Smillert Otherwise, some error ocurred, also signifying EOF. */
4731acd27e7Smillert if (errno != EINTR)
4741acd27e7Smillert return (EOF);
4751acd27e7Smillert }
4761acd27e7Smillert }
47715b117eaSkettenis
47815b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
47915b117eaSkettenis /* read multibyte char */
48015b117eaSkettenis int
_rl_read_mbchar(mbchar,size)48115b117eaSkettenis _rl_read_mbchar (mbchar, size)
48215b117eaSkettenis char *mbchar;
48315b117eaSkettenis int size;
48415b117eaSkettenis {
48515b117eaSkettenis int mb_len = 0;
48615b117eaSkettenis size_t mbchar_bytes_length;
48715b117eaSkettenis wchar_t wc;
48815b117eaSkettenis mbstate_t ps, ps_back;
48915b117eaSkettenis
49015b117eaSkettenis memset(&ps, 0, sizeof (mbstate_t));
49115b117eaSkettenis memset(&ps_back, 0, sizeof (mbstate_t));
49215b117eaSkettenis
49315b117eaSkettenis while (mb_len < size)
49415b117eaSkettenis {
49515b117eaSkettenis RL_SETSTATE(RL_STATE_MOREINPUT);
49615b117eaSkettenis mbchar[mb_len++] = rl_read_key ();
49715b117eaSkettenis RL_UNSETSTATE(RL_STATE_MOREINPUT);
49815b117eaSkettenis
49915b117eaSkettenis mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
50015b117eaSkettenis if (mbchar_bytes_length == (size_t)(-1))
50115b117eaSkettenis break; /* invalid byte sequence for the current locale */
50215b117eaSkettenis else if (mbchar_bytes_length == (size_t)(-2))
50315b117eaSkettenis {
50415b117eaSkettenis /* shorted bytes */
50515b117eaSkettenis ps = ps_back;
50615b117eaSkettenis continue;
50715b117eaSkettenis }
50815b117eaSkettenis else if (mbchar_bytes_length > (size_t)(0))
50915b117eaSkettenis break;
51015b117eaSkettenis }
51115b117eaSkettenis
51215b117eaSkettenis return mb_len;
51315b117eaSkettenis }
51415b117eaSkettenis
51515b117eaSkettenis /* Read a multibyte-character string whose first character is FIRST into
51615b117eaSkettenis the buffer MB of length MBLEN. Returns the last character read, which
51715b117eaSkettenis may be FIRST. Used by the search functions, among others. Very similar
51815b117eaSkettenis to _rl_read_mbchar. */
51915b117eaSkettenis int
_rl_read_mbstring(first,mb,mblen)52015b117eaSkettenis _rl_read_mbstring (first, mb, mblen)
52115b117eaSkettenis int first;
52215b117eaSkettenis char *mb;
52315b117eaSkettenis int mblen;
52415b117eaSkettenis {
52515b117eaSkettenis int i, c;
52615b117eaSkettenis mbstate_t ps;
52715b117eaSkettenis
52815b117eaSkettenis c = first;
52915b117eaSkettenis memset (mb, 0, mblen);
53015b117eaSkettenis for (i = 0; i < mblen; i++)
53115b117eaSkettenis {
53215b117eaSkettenis mb[i] = (char)c;
53315b117eaSkettenis memset (&ps, 0, sizeof (mbstate_t));
53415b117eaSkettenis if (_rl_get_char_len (mb, &ps) == -2)
53515b117eaSkettenis {
53615b117eaSkettenis /* Read more for multibyte character */
53715b117eaSkettenis RL_SETSTATE (RL_STATE_MOREINPUT);
53815b117eaSkettenis c = rl_read_key ();
53915b117eaSkettenis RL_UNSETSTATE (RL_STATE_MOREINPUT);
54015b117eaSkettenis }
54115b117eaSkettenis else
54215b117eaSkettenis break;
54315b117eaSkettenis }
54415b117eaSkettenis return c;
54515b117eaSkettenis }
54615b117eaSkettenis #endif /* HANDLE_MULTIBYTE */
547