1*0a6a1f1dSLionel Sambuc /* $NetBSD: read.c,v 1.71 2014/07/06 18:15:34 christos Exp $ */
23e1db26aSLionel Sambuc
33e1db26aSLionel Sambuc /*-
43e1db26aSLionel Sambuc * Copyright (c) 1992, 1993
53e1db26aSLionel Sambuc * The Regents of the University of California. All rights reserved.
63e1db26aSLionel Sambuc *
73e1db26aSLionel Sambuc * This code is derived from software contributed to Berkeley by
83e1db26aSLionel Sambuc * Christos Zoulas of Cornell University.
93e1db26aSLionel Sambuc *
103e1db26aSLionel Sambuc * Redistribution and use in source and binary forms, with or without
113e1db26aSLionel Sambuc * modification, are permitted provided that the following conditions
123e1db26aSLionel Sambuc * are met:
133e1db26aSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
143e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer.
153e1db26aSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
163e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer in the
173e1db26aSLionel Sambuc * documentation and/or other materials provided with the distribution.
183e1db26aSLionel Sambuc * 3. Neither the name of the University nor the names of its contributors
193e1db26aSLionel Sambuc * may be used to endorse or promote products derived from this software
203e1db26aSLionel Sambuc * without specific prior written permission.
213e1db26aSLionel Sambuc *
223e1db26aSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
233e1db26aSLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
243e1db26aSLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
253e1db26aSLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
263e1db26aSLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
273e1db26aSLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
283e1db26aSLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
293e1db26aSLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
303e1db26aSLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
313e1db26aSLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323e1db26aSLionel Sambuc * SUCH DAMAGE.
333e1db26aSLionel Sambuc */
343e1db26aSLionel Sambuc
353e1db26aSLionel Sambuc #include "config.h"
363e1db26aSLionel Sambuc #if !defined(lint) && !defined(SCCSID)
373e1db26aSLionel Sambuc #if 0
383e1db26aSLionel Sambuc static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
393e1db26aSLionel Sambuc #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: read.c,v 1.71 2014/07/06 18:15:34 christos Exp $");
413e1db26aSLionel Sambuc #endif
423e1db26aSLionel Sambuc #endif /* not lint && not SCCSID */
433e1db26aSLionel Sambuc
443e1db26aSLionel Sambuc /*
453e1db26aSLionel Sambuc * read.c: Clean this junk up! This is horrible code.
463e1db26aSLionel Sambuc * Terminal read functions
473e1db26aSLionel Sambuc */
483e1db26aSLionel Sambuc #include <errno.h>
493e1db26aSLionel Sambuc #include <fcntl.h>
503e1db26aSLionel Sambuc #include <unistd.h>
513e1db26aSLionel Sambuc #include <stdlib.h>
523e1db26aSLionel Sambuc #include <limits.h>
533e1db26aSLionel Sambuc #include "el.h"
543e1db26aSLionel Sambuc
553e1db26aSLionel Sambuc #define OKCMD -1 /* must be -1! */
563e1db26aSLionel Sambuc
573e1db26aSLionel Sambuc private int read__fixio(int, int);
583e1db26aSLionel Sambuc private int read_preread(EditLine *);
593e1db26aSLionel Sambuc private int read_char(EditLine *, Char *);
603e1db26aSLionel Sambuc private int read_getcmd(EditLine *, el_action_t *, Char *);
613e1db26aSLionel Sambuc private void read_pop(c_macro_t *);
623e1db26aSLionel Sambuc
633e1db26aSLionel Sambuc /* read_init():
643e1db26aSLionel Sambuc * Initialize the read stuff
653e1db26aSLionel Sambuc */
663e1db26aSLionel Sambuc protected int
read_init(EditLine * el)673e1db26aSLionel Sambuc read_init(EditLine *el)
683e1db26aSLionel Sambuc {
693e1db26aSLionel Sambuc /* builtin read_char */
703e1db26aSLionel Sambuc el->el_read.read_char = read_char;
713e1db26aSLionel Sambuc return 0;
723e1db26aSLionel Sambuc }
733e1db26aSLionel Sambuc
743e1db26aSLionel Sambuc
753e1db26aSLionel Sambuc /* el_read_setfn():
763e1db26aSLionel Sambuc * Set the read char function to the one provided.
773e1db26aSLionel Sambuc * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
783e1db26aSLionel Sambuc */
793e1db26aSLionel Sambuc protected int
el_read_setfn(EditLine * el,el_rfunc_t rc)803e1db26aSLionel Sambuc el_read_setfn(EditLine *el, el_rfunc_t rc)
813e1db26aSLionel Sambuc {
823e1db26aSLionel Sambuc el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
833e1db26aSLionel Sambuc return 0;
843e1db26aSLionel Sambuc }
853e1db26aSLionel Sambuc
863e1db26aSLionel Sambuc
873e1db26aSLionel Sambuc /* el_read_getfn():
883e1db26aSLionel Sambuc * return the current read char function, or EL_BUILTIN_GETCFN
893e1db26aSLionel Sambuc * if it is the default one
903e1db26aSLionel Sambuc */
913e1db26aSLionel Sambuc protected el_rfunc_t
el_read_getfn(EditLine * el)923e1db26aSLionel Sambuc el_read_getfn(EditLine *el)
933e1db26aSLionel Sambuc {
943e1db26aSLionel Sambuc return el->el_read.read_char == read_char ?
953e1db26aSLionel Sambuc EL_BUILTIN_GETCFN : el->el_read.read_char;
963e1db26aSLionel Sambuc }
973e1db26aSLionel Sambuc
983e1db26aSLionel Sambuc
993e1db26aSLionel Sambuc #ifndef MIN
1003e1db26aSLionel Sambuc #define MIN(A,B) ((A) < (B) ? (A) : (B))
1013e1db26aSLionel Sambuc #endif
1023e1db26aSLionel Sambuc
1033e1db26aSLionel Sambuc #ifdef DEBUG_EDIT
1043e1db26aSLionel Sambuc private void
read_debug(EditLine * el)1053e1db26aSLionel Sambuc read_debug(EditLine *el)
1063e1db26aSLionel Sambuc {
1073e1db26aSLionel Sambuc
1083e1db26aSLionel Sambuc if (el->el_line.cursor > el->el_line.lastchar)
1093e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
1103e1db26aSLionel Sambuc if (el->el_line.cursor < el->el_line.buffer)
1113e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
1123e1db26aSLionel Sambuc if (el->el_line.cursor > el->el_line.limit)
1133e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "cursor > limit\r\n");
1143e1db26aSLionel Sambuc if (el->el_line.lastchar > el->el_line.limit)
1153e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
1163e1db26aSLionel Sambuc if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
1173e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
1183e1db26aSLionel Sambuc }
1193e1db26aSLionel Sambuc #endif /* DEBUG_EDIT */
1203e1db26aSLionel Sambuc
1213e1db26aSLionel Sambuc
1223e1db26aSLionel Sambuc /* read__fixio():
1233e1db26aSLionel Sambuc * Try to recover from a read error
1243e1db26aSLionel Sambuc */
1253e1db26aSLionel Sambuc /* ARGSUSED */
1263e1db26aSLionel Sambuc private int
read__fixio(int fd,int e)1273e1db26aSLionel Sambuc read__fixio(int fd __attribute__((__unused__)), int e)
1283e1db26aSLionel Sambuc {
1293e1db26aSLionel Sambuc
1303e1db26aSLionel Sambuc switch (e) {
1313e1db26aSLionel Sambuc case -1: /* Make sure that the code is reachable */
1323e1db26aSLionel Sambuc
1333e1db26aSLionel Sambuc #ifdef EWOULDBLOCK
1343e1db26aSLionel Sambuc case EWOULDBLOCK:
1353e1db26aSLionel Sambuc #ifndef TRY_AGAIN
1363e1db26aSLionel Sambuc #define TRY_AGAIN
1373e1db26aSLionel Sambuc #endif
1383e1db26aSLionel Sambuc #endif /* EWOULDBLOCK */
1393e1db26aSLionel Sambuc
1403e1db26aSLionel Sambuc #if defined(POSIX) && defined(EAGAIN)
1413e1db26aSLionel Sambuc #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1423e1db26aSLionel Sambuc case EAGAIN:
1433e1db26aSLionel Sambuc #ifndef TRY_AGAIN
1443e1db26aSLionel Sambuc #define TRY_AGAIN
1453e1db26aSLionel Sambuc #endif
1463e1db26aSLionel Sambuc #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
1473e1db26aSLionel Sambuc #endif /* POSIX && EAGAIN */
1483e1db26aSLionel Sambuc
1493e1db26aSLionel Sambuc e = 0;
1503e1db26aSLionel Sambuc #ifdef TRY_AGAIN
1513e1db26aSLionel Sambuc #if defined(F_SETFL) && defined(O_NDELAY)
1523e1db26aSLionel Sambuc if ((e = fcntl(fd, F_GETFL, 0)) == -1)
1533e1db26aSLionel Sambuc return -1;
1543e1db26aSLionel Sambuc
1553e1db26aSLionel Sambuc if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
1563e1db26aSLionel Sambuc return -1;
1573e1db26aSLionel Sambuc else
1583e1db26aSLionel Sambuc e = 1;
1593e1db26aSLionel Sambuc #endif /* F_SETFL && O_NDELAY */
1603e1db26aSLionel Sambuc
1613e1db26aSLionel Sambuc #ifdef FIONBIO
1623e1db26aSLionel Sambuc {
1633e1db26aSLionel Sambuc int zero = 0;
1643e1db26aSLionel Sambuc
1653e1db26aSLionel Sambuc if (ioctl(fd, FIONBIO, &zero) == -1)
1663e1db26aSLionel Sambuc return -1;
1673e1db26aSLionel Sambuc else
1683e1db26aSLionel Sambuc e = 1;
1693e1db26aSLionel Sambuc }
1703e1db26aSLionel Sambuc #endif /* FIONBIO */
1713e1db26aSLionel Sambuc
1723e1db26aSLionel Sambuc #endif /* TRY_AGAIN */
1733e1db26aSLionel Sambuc return e ? 0 : -1;
1743e1db26aSLionel Sambuc
1753e1db26aSLionel Sambuc case EINTR:
1763e1db26aSLionel Sambuc return 0;
1773e1db26aSLionel Sambuc
1783e1db26aSLionel Sambuc default:
1793e1db26aSLionel Sambuc return -1;
1803e1db26aSLionel Sambuc }
1813e1db26aSLionel Sambuc }
1823e1db26aSLionel Sambuc
1833e1db26aSLionel Sambuc
1843e1db26aSLionel Sambuc /* read_preread():
1853e1db26aSLionel Sambuc * Try to read the stuff in the input queue;
1863e1db26aSLionel Sambuc */
1873e1db26aSLionel Sambuc private int
read_preread(EditLine * el)1883e1db26aSLionel Sambuc read_preread(EditLine *el)
1893e1db26aSLionel Sambuc {
1903e1db26aSLionel Sambuc int chrs = 0;
1913e1db26aSLionel Sambuc
1923e1db26aSLionel Sambuc if (el->el_tty.t_mode == ED_IO)
1933e1db26aSLionel Sambuc return 0;
1943e1db26aSLionel Sambuc
1953e1db26aSLionel Sambuc #ifndef WIDECHAR
1963e1db26aSLionel Sambuc /* FIONREAD attempts to buffer up multiple bytes, and to make that work
1973e1db26aSLionel Sambuc * properly with partial wide/UTF-8 characters would need some careful work. */
1983e1db26aSLionel Sambuc #ifdef FIONREAD
1993e1db26aSLionel Sambuc (void) ioctl(el->el_infd, FIONREAD, &chrs);
2003e1db26aSLionel Sambuc if (chrs > 0) {
2013e1db26aSLionel Sambuc char buf[EL_BUFSIZ];
2023e1db26aSLionel Sambuc
2033e1db26aSLionel Sambuc chrs = read(el->el_infd, buf,
2043e1db26aSLionel Sambuc (size_t) MIN(chrs, EL_BUFSIZ - 1));
2053e1db26aSLionel Sambuc if (chrs > 0) {
2063e1db26aSLionel Sambuc buf[chrs] = '\0';
2073e1db26aSLionel Sambuc el_push(el, buf);
2083e1db26aSLionel Sambuc }
2093e1db26aSLionel Sambuc }
2103e1db26aSLionel Sambuc #endif /* FIONREAD */
2113e1db26aSLionel Sambuc #endif
2123e1db26aSLionel Sambuc return chrs > 0;
2133e1db26aSLionel Sambuc }
2143e1db26aSLionel Sambuc
2153e1db26aSLionel Sambuc
2163e1db26aSLionel Sambuc /* el_push():
2173e1db26aSLionel Sambuc * Push a macro
2183e1db26aSLionel Sambuc */
2193e1db26aSLionel Sambuc public void
FUN(el,push)2203e1db26aSLionel Sambuc FUN(el,push)(EditLine *el, const Char *str)
2213e1db26aSLionel Sambuc {
2223e1db26aSLionel Sambuc c_macro_t *ma = &el->el_chared.c_macro;
2233e1db26aSLionel Sambuc
2243e1db26aSLionel Sambuc if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
2253e1db26aSLionel Sambuc ma->level++;
2263e1db26aSLionel Sambuc if ((ma->macro[ma->level] = Strdup(str)) != NULL)
2273e1db26aSLionel Sambuc return;
2283e1db26aSLionel Sambuc ma->level--;
2293e1db26aSLionel Sambuc }
2303e1db26aSLionel Sambuc terminal_beep(el);
2313e1db26aSLionel Sambuc terminal__flush(el);
2323e1db26aSLionel Sambuc }
2333e1db26aSLionel Sambuc
2343e1db26aSLionel Sambuc
2353e1db26aSLionel Sambuc /* read_getcmd():
2363e1db26aSLionel Sambuc * Get next command from the input stream, return OKCMD on success.
2373e1db26aSLionel Sambuc * Character values > 255 are not looked up in the map, but inserted.
2383e1db26aSLionel Sambuc */
2393e1db26aSLionel Sambuc private int
read_getcmd(EditLine * el,el_action_t * cmdnum,Char * ch)2403e1db26aSLionel Sambuc read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
2413e1db26aSLionel Sambuc {
2423e1db26aSLionel Sambuc el_action_t cmd;
2433e1db26aSLionel Sambuc int num;
2443e1db26aSLionel Sambuc
2453e1db26aSLionel Sambuc el->el_errno = 0;
2463e1db26aSLionel Sambuc do {
2473e1db26aSLionel Sambuc if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */
2483e1db26aSLionel Sambuc el->el_errno = num == 0 ? 0 : errno;
2493e1db26aSLionel Sambuc return 0; /* not OKCMD */
2503e1db26aSLionel Sambuc }
2513e1db26aSLionel Sambuc
2523e1db26aSLionel Sambuc #ifdef KANJI
2533e1db26aSLionel Sambuc if ((*ch & 0200)) {
2543e1db26aSLionel Sambuc el->el_state.metanext = 0;
2553e1db26aSLionel Sambuc cmd = CcViMap[' '];
2563e1db26aSLionel Sambuc break;
2573e1db26aSLionel Sambuc } else
2583e1db26aSLionel Sambuc #endif /* KANJI */
2593e1db26aSLionel Sambuc
2603e1db26aSLionel Sambuc if (el->el_state.metanext) {
2613e1db26aSLionel Sambuc el->el_state.metanext = 0;
2623e1db26aSLionel Sambuc *ch |= 0200;
2633e1db26aSLionel Sambuc }
2643e1db26aSLionel Sambuc #ifdef WIDECHAR
2653e1db26aSLionel Sambuc if (*ch >= N_KEYS)
2663e1db26aSLionel Sambuc cmd = ED_INSERT;
2673e1db26aSLionel Sambuc else
2683e1db26aSLionel Sambuc #endif
2693e1db26aSLionel Sambuc cmd = el->el_map.current[(unsigned char) *ch];
2703e1db26aSLionel Sambuc if (cmd == ED_SEQUENCE_LEAD_IN) {
2713e1db26aSLionel Sambuc keymacro_value_t val;
2723e1db26aSLionel Sambuc switch (keymacro_get(el, ch, &val)) {
2733e1db26aSLionel Sambuc case XK_CMD:
2743e1db26aSLionel Sambuc cmd = val.cmd;
2753e1db26aSLionel Sambuc break;
2763e1db26aSLionel Sambuc case XK_STR:
2773e1db26aSLionel Sambuc FUN(el,push)(el, val.str);
2783e1db26aSLionel Sambuc break;
2793e1db26aSLionel Sambuc #ifdef notyet
2803e1db26aSLionel Sambuc case XK_EXE:
2813e1db26aSLionel Sambuc /* XXX: In the future to run a user function */
2823e1db26aSLionel Sambuc RunCommand(val.str);
2833e1db26aSLionel Sambuc break;
2843e1db26aSLionel Sambuc #endif
2853e1db26aSLionel Sambuc default:
2863e1db26aSLionel Sambuc EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
2873e1db26aSLionel Sambuc break;
2883e1db26aSLionel Sambuc }
2893e1db26aSLionel Sambuc }
2903e1db26aSLionel Sambuc if (el->el_map.alt == NULL)
2913e1db26aSLionel Sambuc el->el_map.current = el->el_map.key;
2923e1db26aSLionel Sambuc } while (cmd == ED_SEQUENCE_LEAD_IN);
2933e1db26aSLionel Sambuc *cmdnum = cmd;
2943e1db26aSLionel Sambuc return OKCMD;
2953e1db26aSLionel Sambuc }
2963e1db26aSLionel Sambuc
2973e1db26aSLionel Sambuc #ifdef WIDECHAR
2983e1db26aSLionel Sambuc /* utf8_islead():
2993e1db26aSLionel Sambuc * Test whether a byte is a leading byte of a UTF-8 sequence.
3003e1db26aSLionel Sambuc */
3013e1db26aSLionel Sambuc private int
utf8_islead(int c)3023e1db26aSLionel Sambuc utf8_islead(int c)
3033e1db26aSLionel Sambuc {
3043e1db26aSLionel Sambuc return c < 0x80 || /* single byte char */
3053e1db26aSLionel Sambuc (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */
3063e1db26aSLionel Sambuc }
3073e1db26aSLionel Sambuc #endif
3083e1db26aSLionel Sambuc
3093e1db26aSLionel Sambuc /* read_char():
3103e1db26aSLionel Sambuc * Read a character from the tty.
3113e1db26aSLionel Sambuc */
3123e1db26aSLionel Sambuc private int
read_char(EditLine * el,Char * cp)3133e1db26aSLionel Sambuc read_char(EditLine *el, Char *cp)
3143e1db26aSLionel Sambuc {
3153e1db26aSLionel Sambuc ssize_t num_read;
3163e1db26aSLionel Sambuc int tried = 0;
3173e1db26aSLionel Sambuc char cbuf[MB_LEN_MAX];
3183e1db26aSLionel Sambuc size_t cbp = 0;
3193e1db26aSLionel Sambuc int bytes = 0;
3203e1db26aSLionel Sambuc
3213e1db26aSLionel Sambuc again:
3223e1db26aSLionel Sambuc el->el_signal->sig_no = 0;
3233e1db26aSLionel Sambuc while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) {
3243e1db26aSLionel Sambuc int e = errno;
3253e1db26aSLionel Sambuc switch (el->el_signal->sig_no) {
3263e1db26aSLionel Sambuc case SIGCONT:
3273e1db26aSLionel Sambuc FUN(el,set)(el, EL_REFRESH);
3283e1db26aSLionel Sambuc /*FALLTHROUGH*/
3293e1db26aSLionel Sambuc case SIGWINCH:
3303e1db26aSLionel Sambuc sig_set(el);
3313e1db26aSLionel Sambuc goto again;
3323e1db26aSLionel Sambuc default:
3333e1db26aSLionel Sambuc break;
3343e1db26aSLionel Sambuc }
3353e1db26aSLionel Sambuc if (!tried && read__fixio(el->el_infd, e) == 0)
3363e1db26aSLionel Sambuc tried = 1;
3373e1db26aSLionel Sambuc else {
3383e1db26aSLionel Sambuc errno = e;
3393e1db26aSLionel Sambuc *cp = '\0';
3403e1db26aSLionel Sambuc return -1;
3413e1db26aSLionel Sambuc }
3423e1db26aSLionel Sambuc }
3433e1db26aSLionel Sambuc
34484d9c625SLionel Sambuc /* Test for EOF */
34584d9c625SLionel Sambuc if (num_read == 0) {
34684d9c625SLionel Sambuc errno = 0;
34784d9c625SLionel Sambuc *cp = '\0';
34884d9c625SLionel Sambuc return 0;
34984d9c625SLionel Sambuc }
35084d9c625SLionel Sambuc
3513e1db26aSLionel Sambuc #ifdef WIDECHAR
3523e1db26aSLionel Sambuc if (el->el_flags & CHARSET_IS_UTF8) {
3533e1db26aSLionel Sambuc if (!utf8_islead((unsigned char)cbuf[0]))
3543e1db26aSLionel Sambuc goto again; /* discard the byte we read and try again */
3553e1db26aSLionel Sambuc ++cbp;
3563e1db26aSLionel Sambuc if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) {
3573e1db26aSLionel Sambuc ct_mbtowc_reset;
3583e1db26aSLionel Sambuc if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */
3593e1db26aSLionel Sambuc errno = EILSEQ;
3603e1db26aSLionel Sambuc *cp = '\0';
3613e1db26aSLionel Sambuc return -1;
3623e1db26aSLionel Sambuc }
3633e1db26aSLionel Sambuc goto again;
3643e1db26aSLionel Sambuc }
3653e1db26aSLionel Sambuc } else if (isascii((unsigned char)cbuf[0]) ||
3663e1db26aSLionel Sambuc /* we don't support other multibyte charsets */
3673e1db26aSLionel Sambuc ++cbp != 1 ||
3683e1db26aSLionel Sambuc /* Try non-ASCII characters in a 8-bit character set */
3693e1db26aSLionel Sambuc (bytes = ct_mbtowc(cp, cbuf, cbp)) != 1)
3703e1db26aSLionel Sambuc #endif
3713e1db26aSLionel Sambuc *cp = (unsigned char)cbuf[0];
3723e1db26aSLionel Sambuc
3733e1db26aSLionel Sambuc if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) {
3743e1db26aSLionel Sambuc cbp = 0; /* skip this character */
3753e1db26aSLionel Sambuc goto again;
3763e1db26aSLionel Sambuc }
3773e1db26aSLionel Sambuc
3783e1db26aSLionel Sambuc return (int)num_read;
3793e1db26aSLionel Sambuc }
3803e1db26aSLionel Sambuc
3813e1db26aSLionel Sambuc /* read_pop():
3823e1db26aSLionel Sambuc * Pop a macro from the stack
3833e1db26aSLionel Sambuc */
3843e1db26aSLionel Sambuc private void
read_pop(c_macro_t * ma)3853e1db26aSLionel Sambuc read_pop(c_macro_t *ma)
3863e1db26aSLionel Sambuc {
3873e1db26aSLionel Sambuc int i;
3883e1db26aSLionel Sambuc
3893e1db26aSLionel Sambuc el_free(ma->macro[0]);
3903e1db26aSLionel Sambuc for (i = 0; i < ma->level; i++)
3913e1db26aSLionel Sambuc ma->macro[i] = ma->macro[i + 1];
3923e1db26aSLionel Sambuc ma->level--;
3933e1db26aSLionel Sambuc ma->offset = 0;
3943e1db26aSLionel Sambuc }
3953e1db26aSLionel Sambuc
3963e1db26aSLionel Sambuc /* el_getc():
3973e1db26aSLionel Sambuc * Read a character
3983e1db26aSLionel Sambuc */
3993e1db26aSLionel Sambuc public int
FUN(el,getc)4003e1db26aSLionel Sambuc FUN(el,getc)(EditLine *el, Char *cp)
4013e1db26aSLionel Sambuc {
4023e1db26aSLionel Sambuc int num_read;
4033e1db26aSLionel Sambuc c_macro_t *ma = &el->el_chared.c_macro;
4043e1db26aSLionel Sambuc
4053e1db26aSLionel Sambuc terminal__flush(el);
4063e1db26aSLionel Sambuc for (;;) {
4073e1db26aSLionel Sambuc if (ma->level < 0) {
4083e1db26aSLionel Sambuc if (!read_preread(el))
4093e1db26aSLionel Sambuc break;
4103e1db26aSLionel Sambuc }
4113e1db26aSLionel Sambuc
4123e1db26aSLionel Sambuc if (ma->level < 0)
4133e1db26aSLionel Sambuc break;
4143e1db26aSLionel Sambuc
4153e1db26aSLionel Sambuc if (ma->macro[0][ma->offset] == '\0') {
4163e1db26aSLionel Sambuc read_pop(ma);
4173e1db26aSLionel Sambuc continue;
4183e1db26aSLionel Sambuc }
4193e1db26aSLionel Sambuc
4203e1db26aSLionel Sambuc *cp = ma->macro[0][ma->offset++];
4213e1db26aSLionel Sambuc
4223e1db26aSLionel Sambuc if (ma->macro[0][ma->offset] == '\0') {
4233e1db26aSLionel Sambuc /* Needed for QuoteMode On */
4243e1db26aSLionel Sambuc read_pop(ma);
4253e1db26aSLionel Sambuc }
4263e1db26aSLionel Sambuc
4273e1db26aSLionel Sambuc return 1;
4283e1db26aSLionel Sambuc }
4293e1db26aSLionel Sambuc
4303e1db26aSLionel Sambuc #ifdef DEBUG_READ
4313e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "Turning raw mode on\n");
4323e1db26aSLionel Sambuc #endif /* DEBUG_READ */
4333e1db26aSLionel Sambuc if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
4343e1db26aSLionel Sambuc return 0;
4353e1db26aSLionel Sambuc
4363e1db26aSLionel Sambuc #ifdef DEBUG_READ
4373e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "Reading a character\n");
4383e1db26aSLionel Sambuc #endif /* DEBUG_READ */
4393e1db26aSLionel Sambuc num_read = (*el->el_read.read_char)(el, cp);
4403e1db26aSLionel Sambuc if (num_read < 0)
4413e1db26aSLionel Sambuc el->el_errno = errno;
4423e1db26aSLionel Sambuc #ifdef WIDECHAR
4433e1db26aSLionel Sambuc if (el->el_flags & NARROW_READ)
4443e1db26aSLionel Sambuc *cp = *(char *)(void *)cp;
4453e1db26aSLionel Sambuc #endif
4463e1db26aSLionel Sambuc #ifdef DEBUG_READ
4473e1db26aSLionel Sambuc (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
4483e1db26aSLionel Sambuc #endif /* DEBUG_READ */
4493e1db26aSLionel Sambuc return num_read;
4503e1db26aSLionel Sambuc }
4513e1db26aSLionel Sambuc
4523e1db26aSLionel Sambuc protected void
read_prepare(EditLine * el)4533e1db26aSLionel Sambuc read_prepare(EditLine *el)
4543e1db26aSLionel Sambuc {
4553e1db26aSLionel Sambuc if (el->el_flags & HANDLE_SIGNALS)
4563e1db26aSLionel Sambuc sig_set(el);
4573e1db26aSLionel Sambuc if (el->el_flags & NO_TTY)
4583e1db26aSLionel Sambuc return;
4593e1db26aSLionel Sambuc if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
4603e1db26aSLionel Sambuc tty_rawmode(el);
4613e1db26aSLionel Sambuc
4623e1db26aSLionel Sambuc /* This is relatively cheap, and things go terribly wrong if
4633e1db26aSLionel Sambuc we have the wrong size. */
4643e1db26aSLionel Sambuc el_resize(el);
4653e1db26aSLionel Sambuc re_clear_display(el); /* reset the display stuff */
4663e1db26aSLionel Sambuc ch_reset(el, 0);
4673e1db26aSLionel Sambuc re_refresh(el); /* print the prompt */
4683e1db26aSLionel Sambuc
4693e1db26aSLionel Sambuc if (el->el_flags & UNBUFFERED)
4703e1db26aSLionel Sambuc terminal__flush(el);
4713e1db26aSLionel Sambuc }
4723e1db26aSLionel Sambuc
4733e1db26aSLionel Sambuc protected void
read_finish(EditLine * el)4743e1db26aSLionel Sambuc read_finish(EditLine *el)
4753e1db26aSLionel Sambuc {
4763e1db26aSLionel Sambuc if ((el->el_flags & UNBUFFERED) == 0)
4773e1db26aSLionel Sambuc (void) tty_cookedmode(el);
4783e1db26aSLionel Sambuc if (el->el_flags & HANDLE_SIGNALS)
4793e1db26aSLionel Sambuc sig_clr(el);
4803e1db26aSLionel Sambuc }
4813e1db26aSLionel Sambuc
4823e1db26aSLionel Sambuc public const Char *
FUN(el,gets)4833e1db26aSLionel Sambuc FUN(el,gets)(EditLine *el, int *nread)
4843e1db26aSLionel Sambuc {
4853e1db26aSLionel Sambuc int retval;
4863e1db26aSLionel Sambuc el_action_t cmdnum = 0;
4873e1db26aSLionel Sambuc int num; /* how many chars we have read at NL */
4883e1db26aSLionel Sambuc Char ch, *cp;
4893e1db26aSLionel Sambuc int crlf = 0;
4903e1db26aSLionel Sambuc int nrb;
4913e1db26aSLionel Sambuc #ifdef FIONREAD
4923e1db26aSLionel Sambuc c_macro_t *ma = &el->el_chared.c_macro;
4933e1db26aSLionel Sambuc #endif /* FIONREAD */
4943e1db26aSLionel Sambuc
4953e1db26aSLionel Sambuc if (nread == NULL)
4963e1db26aSLionel Sambuc nread = &nrb;
4973e1db26aSLionel Sambuc *nread = 0;
4983e1db26aSLionel Sambuc
4993e1db26aSLionel Sambuc if (el->el_flags & NO_TTY) {
5003e1db26aSLionel Sambuc size_t idx;
5013e1db26aSLionel Sambuc
5023e1db26aSLionel Sambuc cp = el->el_line.buffer;
5033e1db26aSLionel Sambuc while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
5043e1db26aSLionel Sambuc /* make sure there is space for next character */
5053e1db26aSLionel Sambuc if (cp + 1 >= el->el_line.limit) {
5063e1db26aSLionel Sambuc idx = (size_t)(cp - el->el_line.buffer);
5073e1db26aSLionel Sambuc if (!ch_enlargebufs(el, (size_t)2))
5083e1db26aSLionel Sambuc break;
5093e1db26aSLionel Sambuc cp = &el->el_line.buffer[idx];
5103e1db26aSLionel Sambuc }
5113e1db26aSLionel Sambuc cp++;
5123e1db26aSLionel Sambuc if (el->el_flags & UNBUFFERED)
5133e1db26aSLionel Sambuc break;
5143e1db26aSLionel Sambuc if (cp[-1] == '\r' || cp[-1] == '\n')
5153e1db26aSLionel Sambuc break;
5163e1db26aSLionel Sambuc }
5173e1db26aSLionel Sambuc if (num == -1) {
5183e1db26aSLionel Sambuc if (errno == EINTR)
5193e1db26aSLionel Sambuc cp = el->el_line.buffer;
5203e1db26aSLionel Sambuc el->el_errno = errno;
5213e1db26aSLionel Sambuc }
5223e1db26aSLionel Sambuc
5233e1db26aSLionel Sambuc goto noedit;
5243e1db26aSLionel Sambuc }
5253e1db26aSLionel Sambuc
5263e1db26aSLionel Sambuc
5273e1db26aSLionel Sambuc #ifdef FIONREAD
5283e1db26aSLionel Sambuc if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
5293e1db26aSLionel Sambuc long chrs = 0;
5303e1db26aSLionel Sambuc
5313e1db26aSLionel Sambuc (void) ioctl(el->el_infd, FIONREAD, &chrs);
5323e1db26aSLionel Sambuc if (chrs == 0) {
5333e1db26aSLionel Sambuc if (tty_rawmode(el) < 0) {
5343e1db26aSLionel Sambuc errno = 0;
5353e1db26aSLionel Sambuc *nread = 0;
5363e1db26aSLionel Sambuc return NULL;
5373e1db26aSLionel Sambuc }
5383e1db26aSLionel Sambuc }
5393e1db26aSLionel Sambuc }
5403e1db26aSLionel Sambuc #endif /* FIONREAD */
5413e1db26aSLionel Sambuc
5423e1db26aSLionel Sambuc if ((el->el_flags & UNBUFFERED) == 0)
5433e1db26aSLionel Sambuc read_prepare(el);
5443e1db26aSLionel Sambuc
5453e1db26aSLionel Sambuc if (el->el_flags & EDIT_DISABLED) {
5463e1db26aSLionel Sambuc size_t idx;
5473e1db26aSLionel Sambuc
5483e1db26aSLionel Sambuc if ((el->el_flags & UNBUFFERED) == 0)
5493e1db26aSLionel Sambuc cp = el->el_line.buffer;
5503e1db26aSLionel Sambuc else
5513e1db26aSLionel Sambuc cp = el->el_line.lastchar;
5523e1db26aSLionel Sambuc
5533e1db26aSLionel Sambuc terminal__flush(el);
5543e1db26aSLionel Sambuc
5553e1db26aSLionel Sambuc while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
5563e1db26aSLionel Sambuc /* make sure there is space next character */
5573e1db26aSLionel Sambuc if (cp + 1 >= el->el_line.limit) {
5583e1db26aSLionel Sambuc idx = (size_t)(cp - el->el_line.buffer);
5593e1db26aSLionel Sambuc if (!ch_enlargebufs(el, (size_t)2))
5603e1db26aSLionel Sambuc break;
5613e1db26aSLionel Sambuc cp = &el->el_line.buffer[idx];
5623e1db26aSLionel Sambuc }
5633e1db26aSLionel Sambuc cp++;
5643e1db26aSLionel Sambuc crlf = cp[-1] == '\r' || cp[-1] == '\n';
5653e1db26aSLionel Sambuc if (el->el_flags & UNBUFFERED)
5663e1db26aSLionel Sambuc break;
5673e1db26aSLionel Sambuc if (crlf)
5683e1db26aSLionel Sambuc break;
5693e1db26aSLionel Sambuc }
5703e1db26aSLionel Sambuc
5713e1db26aSLionel Sambuc if (num == -1) {
5723e1db26aSLionel Sambuc if (errno == EINTR)
5733e1db26aSLionel Sambuc cp = el->el_line.buffer;
5743e1db26aSLionel Sambuc el->el_errno = errno;
5753e1db26aSLionel Sambuc }
5763e1db26aSLionel Sambuc
5773e1db26aSLionel Sambuc goto noedit;
5783e1db26aSLionel Sambuc }
5793e1db26aSLionel Sambuc
5803e1db26aSLionel Sambuc for (num = OKCMD; num == OKCMD;) { /* while still editing this
5813e1db26aSLionel Sambuc * line */
5823e1db26aSLionel Sambuc #ifdef DEBUG_EDIT
5833e1db26aSLionel Sambuc read_debug(el);
5843e1db26aSLionel Sambuc #endif /* DEBUG_EDIT */
5853e1db26aSLionel Sambuc /* if EOF or error */
5863e1db26aSLionel Sambuc if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
5873e1db26aSLionel Sambuc num = -1;
5883e1db26aSLionel Sambuc #ifdef DEBUG_READ
5893e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
5903e1db26aSLionel Sambuc "Returning from el_gets %d\n", num);
5913e1db26aSLionel Sambuc #endif /* DEBUG_READ */
5923e1db26aSLionel Sambuc break;
5933e1db26aSLionel Sambuc }
5943e1db26aSLionel Sambuc if (el->el_errno == EINTR) {
5953e1db26aSLionel Sambuc el->el_line.buffer[0] = '\0';
5963e1db26aSLionel Sambuc el->el_line.lastchar =
5973e1db26aSLionel Sambuc el->el_line.cursor = el->el_line.buffer;
5983e1db26aSLionel Sambuc break;
5993e1db26aSLionel Sambuc }
600*0a6a1f1dSLionel Sambuc if ((size_t)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
6013e1db26aSLionel Sambuc #ifdef DEBUG_EDIT
6023e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
6033e1db26aSLionel Sambuc "ERROR: illegal command from key 0%o\r\n", ch);
6043e1db26aSLionel Sambuc #endif /* DEBUG_EDIT */
6053e1db26aSLionel Sambuc continue; /* try again */
6063e1db26aSLionel Sambuc }
6073e1db26aSLionel Sambuc /* now do the real command */
6083e1db26aSLionel Sambuc #ifdef DEBUG_READ
6093e1db26aSLionel Sambuc {
6103e1db26aSLionel Sambuc el_bindings_t *b;
6113e1db26aSLionel Sambuc for (b = el->el_map.help; b->name; b++)
6123e1db26aSLionel Sambuc if (b->func == cmdnum)
6133e1db26aSLionel Sambuc break;
6143e1db26aSLionel Sambuc if (b->name)
6153e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
6163e1db26aSLionel Sambuc "Executing %s\n", b->name);
6173e1db26aSLionel Sambuc else
6183e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
6193e1db26aSLionel Sambuc "Error command = %d\n", cmdnum);
6203e1db26aSLionel Sambuc }
6213e1db26aSLionel Sambuc #endif /* DEBUG_READ */
6223e1db26aSLionel Sambuc /* vi redo needs these way down the levels... */
6233e1db26aSLionel Sambuc el->el_state.thiscmd = cmdnum;
6243e1db26aSLionel Sambuc el->el_state.thisch = ch;
6253e1db26aSLionel Sambuc if (el->el_map.type == MAP_VI &&
6263e1db26aSLionel Sambuc el->el_map.current == el->el_map.key &&
6273e1db26aSLionel Sambuc el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
6283e1db26aSLionel Sambuc if (cmdnum == VI_DELETE_PREV_CHAR &&
6293e1db26aSLionel Sambuc el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
6303e1db26aSLionel Sambuc && Isprint(el->el_chared.c_redo.pos[-1]))
6313e1db26aSLionel Sambuc el->el_chared.c_redo.pos--;
6323e1db26aSLionel Sambuc else
6333e1db26aSLionel Sambuc *el->el_chared.c_redo.pos++ = ch;
6343e1db26aSLionel Sambuc }
6353e1db26aSLionel Sambuc retval = (*el->el_map.func[cmdnum]) (el, ch);
6363e1db26aSLionel Sambuc #ifdef DEBUG_READ
6373e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
6383e1db26aSLionel Sambuc "Returned state %d\n", retval );
6393e1db26aSLionel Sambuc #endif /* DEBUG_READ */
6403e1db26aSLionel Sambuc
6413e1db26aSLionel Sambuc /* save the last command here */
6423e1db26aSLionel Sambuc el->el_state.lastcmd = cmdnum;
6433e1db26aSLionel Sambuc
6443e1db26aSLionel Sambuc /* use any return value */
6453e1db26aSLionel Sambuc switch (retval) {
6463e1db26aSLionel Sambuc case CC_CURSOR:
6473e1db26aSLionel Sambuc re_refresh_cursor(el);
6483e1db26aSLionel Sambuc break;
6493e1db26aSLionel Sambuc
6503e1db26aSLionel Sambuc case CC_REDISPLAY:
6513e1db26aSLionel Sambuc re_clear_lines(el);
6523e1db26aSLionel Sambuc re_clear_display(el);
6533e1db26aSLionel Sambuc /* FALLTHROUGH */
6543e1db26aSLionel Sambuc
6553e1db26aSLionel Sambuc case CC_REFRESH:
6563e1db26aSLionel Sambuc re_refresh(el);
6573e1db26aSLionel Sambuc break;
6583e1db26aSLionel Sambuc
6593e1db26aSLionel Sambuc case CC_REFRESH_BEEP:
6603e1db26aSLionel Sambuc re_refresh(el);
6613e1db26aSLionel Sambuc terminal_beep(el);
6623e1db26aSLionel Sambuc break;
6633e1db26aSLionel Sambuc
6643e1db26aSLionel Sambuc case CC_NORM: /* normal char */
6653e1db26aSLionel Sambuc break;
6663e1db26aSLionel Sambuc
6673e1db26aSLionel Sambuc case CC_ARGHACK: /* Suggested by Rich Salz */
6683e1db26aSLionel Sambuc /* <rsalz@pineapple.bbn.com> */
6693e1db26aSLionel Sambuc continue; /* keep going... */
6703e1db26aSLionel Sambuc
6713e1db26aSLionel Sambuc case CC_EOF: /* end of file typed */
6723e1db26aSLionel Sambuc if ((el->el_flags & UNBUFFERED) == 0)
6733e1db26aSLionel Sambuc num = 0;
6743e1db26aSLionel Sambuc else if (num == -1) {
6753e1db26aSLionel Sambuc *el->el_line.lastchar++ = CONTROL('d');
6763e1db26aSLionel Sambuc el->el_line.cursor = el->el_line.lastchar;
6773e1db26aSLionel Sambuc num = 1;
6783e1db26aSLionel Sambuc }
6793e1db26aSLionel Sambuc break;
6803e1db26aSLionel Sambuc
6813e1db26aSLionel Sambuc case CC_NEWLINE: /* normal end of line */
6823e1db26aSLionel Sambuc num = (int)(el->el_line.lastchar - el->el_line.buffer);
6833e1db26aSLionel Sambuc break;
6843e1db26aSLionel Sambuc
6853e1db26aSLionel Sambuc case CC_FATAL: /* fatal error, reset to known state */
6863e1db26aSLionel Sambuc #ifdef DEBUG_READ
6873e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
6883e1db26aSLionel Sambuc "*** editor fatal ERROR ***\r\n\n");
6893e1db26aSLionel Sambuc #endif /* DEBUG_READ */
6903e1db26aSLionel Sambuc /* put (real) cursor in a known place */
6913e1db26aSLionel Sambuc re_clear_display(el); /* reset the display stuff */
6923e1db26aSLionel Sambuc ch_reset(el, 1); /* reset the input pointers */
6933e1db26aSLionel Sambuc re_refresh(el); /* print the prompt again */
6943e1db26aSLionel Sambuc break;
6953e1db26aSLionel Sambuc
6963e1db26aSLionel Sambuc case CC_ERROR:
6973e1db26aSLionel Sambuc default: /* functions we don't know about */
6983e1db26aSLionel Sambuc #ifdef DEBUG_READ
6993e1db26aSLionel Sambuc (void) fprintf(el->el_errfile,
7003e1db26aSLionel Sambuc "*** editor ERROR ***\r\n\n");
7013e1db26aSLionel Sambuc #endif /* DEBUG_READ */
7023e1db26aSLionel Sambuc terminal_beep(el);
7033e1db26aSLionel Sambuc terminal__flush(el);
7043e1db26aSLionel Sambuc break;
7053e1db26aSLionel Sambuc }
7063e1db26aSLionel Sambuc el->el_state.argument = 1;
7073e1db26aSLionel Sambuc el->el_state.doingarg = 0;
7083e1db26aSLionel Sambuc el->el_chared.c_vcmd.action = NOP;
7093e1db26aSLionel Sambuc if (el->el_flags & UNBUFFERED)
7103e1db26aSLionel Sambuc break;
7113e1db26aSLionel Sambuc }
7123e1db26aSLionel Sambuc
7133e1db26aSLionel Sambuc terminal__flush(el); /* flush any buffered output */
7143e1db26aSLionel Sambuc /* make sure the tty is set up correctly */
7153e1db26aSLionel Sambuc if ((el->el_flags & UNBUFFERED) == 0) {
7163e1db26aSLionel Sambuc read_finish(el);
7173e1db26aSLionel Sambuc *nread = num != -1 ? num : 0;
7183e1db26aSLionel Sambuc } else {
7193e1db26aSLionel Sambuc *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
7203e1db26aSLionel Sambuc }
7213e1db26aSLionel Sambuc goto done;
7223e1db26aSLionel Sambuc noedit:
7233e1db26aSLionel Sambuc el->el_line.cursor = el->el_line.lastchar = cp;
7243e1db26aSLionel Sambuc *cp = '\0';
7253e1db26aSLionel Sambuc *nread = (int)(el->el_line.cursor - el->el_line.buffer);
7263e1db26aSLionel Sambuc done:
7273e1db26aSLionel Sambuc if (*nread == 0) {
7283e1db26aSLionel Sambuc if (num == -1) {
7293e1db26aSLionel Sambuc *nread = -1;
7303e1db26aSLionel Sambuc errno = el->el_errno;
7313e1db26aSLionel Sambuc }
7323e1db26aSLionel Sambuc return NULL;
7333e1db26aSLionel Sambuc } else
7343e1db26aSLionel Sambuc return el->el_line.buffer;
7353e1db26aSLionel Sambuc }
736