1*d0ef721eSBaptiste Daroussin /* $NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $ */ 2*d0ef721eSBaptiste Daroussin 3*d0ef721eSBaptiste Daroussin /*- 4*d0ef721eSBaptiste Daroussin * Copyright (c) 1992, 1993 5*d0ef721eSBaptiste Daroussin * The Regents of the University of California. All rights reserved. 6*d0ef721eSBaptiste Daroussin * 7*d0ef721eSBaptiste Daroussin * This code is derived from software contributed to Berkeley by 8*d0ef721eSBaptiste Daroussin * Christos Zoulas of Cornell University. 9*d0ef721eSBaptiste Daroussin * 10*d0ef721eSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 11*d0ef721eSBaptiste Daroussin * modification, are permitted provided that the following conditions 12*d0ef721eSBaptiste Daroussin * are met: 13*d0ef721eSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 14*d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 15*d0ef721eSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 16*d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 17*d0ef721eSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 18*d0ef721eSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 19*d0ef721eSBaptiste Daroussin * may be used to endorse or promote products derived from this software 20*d0ef721eSBaptiste Daroussin * without specific prior written permission. 21*d0ef721eSBaptiste Daroussin * 22*d0ef721eSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*d0ef721eSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*d0ef721eSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*d0ef721eSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*d0ef721eSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*d0ef721eSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*d0ef721eSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*d0ef721eSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*d0ef721eSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*d0ef721eSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*d0ef721eSBaptiste Daroussin * SUCH DAMAGE. 33*d0ef721eSBaptiste Daroussin */ 34*d0ef721eSBaptiste Daroussin 35*d0ef721eSBaptiste Daroussin #include "config.h" 36*d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID) 37*d0ef721eSBaptiste Daroussin #if 0 38*d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; 39*d0ef721eSBaptiste Daroussin #else 40*d0ef721eSBaptiste Daroussin __RCSID("$NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $"); 41*d0ef721eSBaptiste Daroussin #endif 42*d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */ 43*d0ef721eSBaptiste Daroussin 44*d0ef721eSBaptiste Daroussin /* 45*d0ef721eSBaptiste Daroussin * read.c: Terminal read functions 46*d0ef721eSBaptiste Daroussin */ 47*d0ef721eSBaptiste Daroussin #include <ctype.h> 48*d0ef721eSBaptiste Daroussin #include <errno.h> 49*d0ef721eSBaptiste Daroussin #include <fcntl.h> 50*d0ef721eSBaptiste Daroussin #include <limits.h> 51*d0ef721eSBaptiste Daroussin #include <stdlib.h> 52*d0ef721eSBaptiste Daroussin #include <string.h> 53*d0ef721eSBaptiste Daroussin #include <unistd.h> 54*d0ef721eSBaptiste Daroussin 55*d0ef721eSBaptiste Daroussin #include "el.h" 56*d0ef721eSBaptiste Daroussin #include "fcns.h" 57*d0ef721eSBaptiste Daroussin #include "read.h" 58*d0ef721eSBaptiste Daroussin 59*d0ef721eSBaptiste Daroussin #define EL_MAXMACRO 10 60*d0ef721eSBaptiste Daroussin 61*d0ef721eSBaptiste Daroussin struct macros { 62*d0ef721eSBaptiste Daroussin wchar_t **macro; 63*d0ef721eSBaptiste Daroussin int level; 64*d0ef721eSBaptiste Daroussin int offset; 65*d0ef721eSBaptiste Daroussin }; 66*d0ef721eSBaptiste Daroussin 67*d0ef721eSBaptiste Daroussin struct el_read_t { 68*d0ef721eSBaptiste Daroussin struct macros macros; 69*d0ef721eSBaptiste Daroussin el_rfunc_t read_char; /* Function to read a character. */ 70*d0ef721eSBaptiste Daroussin int read_errno; 71*d0ef721eSBaptiste Daroussin }; 72*d0ef721eSBaptiste Daroussin 73*d0ef721eSBaptiste Daroussin static int read__fixio(int, int); 74*d0ef721eSBaptiste Daroussin static int read_char(EditLine *, wchar_t *); 75*d0ef721eSBaptiste Daroussin static int read_getcmd(EditLine *, el_action_t *, wchar_t *); 76*d0ef721eSBaptiste Daroussin static void read_clearmacros(struct macros *); 77*d0ef721eSBaptiste Daroussin static void read_pop(struct macros *); 78*d0ef721eSBaptiste Daroussin static const wchar_t *noedit_wgets(EditLine *, int *); 79*d0ef721eSBaptiste Daroussin 80*d0ef721eSBaptiste Daroussin /* read_init(): 81*d0ef721eSBaptiste Daroussin * Initialize the read stuff 82*d0ef721eSBaptiste Daroussin */ 83*d0ef721eSBaptiste Daroussin libedit_private int 84*d0ef721eSBaptiste Daroussin read_init(EditLine *el) 85*d0ef721eSBaptiste Daroussin { 86*d0ef721eSBaptiste Daroussin struct macros *ma; 87*d0ef721eSBaptiste Daroussin 88*d0ef721eSBaptiste Daroussin if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL) 89*d0ef721eSBaptiste Daroussin return -1; 90*d0ef721eSBaptiste Daroussin 91*d0ef721eSBaptiste Daroussin ma = &el->el_read->macros; 92*d0ef721eSBaptiste Daroussin if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL) { 93*d0ef721eSBaptiste Daroussin free(el->el_read); 94*d0ef721eSBaptiste Daroussin return -1; 95*d0ef721eSBaptiste Daroussin } 96*d0ef721eSBaptiste Daroussin ma->level = -1; 97*d0ef721eSBaptiste Daroussin ma->offset = 0; 98*d0ef721eSBaptiste Daroussin 99*d0ef721eSBaptiste Daroussin /* builtin read_char */ 100*d0ef721eSBaptiste Daroussin el->el_read->read_char = read_char; 101*d0ef721eSBaptiste Daroussin return 0; 102*d0ef721eSBaptiste Daroussin } 103*d0ef721eSBaptiste Daroussin 104*d0ef721eSBaptiste Daroussin /* el_read_end(): 105*d0ef721eSBaptiste Daroussin * Free the data structures used by the read stuff. 106*d0ef721eSBaptiste Daroussin */ 107*d0ef721eSBaptiste Daroussin libedit_private void 108*d0ef721eSBaptiste Daroussin read_end(struct el_read_t *el_read) 109*d0ef721eSBaptiste Daroussin { 110*d0ef721eSBaptiste Daroussin read_clearmacros(&el_read->macros); 111*d0ef721eSBaptiste Daroussin el_free(el_read->macros.macro); 112*d0ef721eSBaptiste Daroussin el_read->macros.macro = NULL; 113*d0ef721eSBaptiste Daroussin el_free(el_read); 114*d0ef721eSBaptiste Daroussin } 115*d0ef721eSBaptiste Daroussin 116*d0ef721eSBaptiste Daroussin /* el_read_setfn(): 117*d0ef721eSBaptiste Daroussin * Set the read char function to the one provided. 118*d0ef721eSBaptiste Daroussin * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one. 119*d0ef721eSBaptiste Daroussin */ 120*d0ef721eSBaptiste Daroussin libedit_private int 121*d0ef721eSBaptiste Daroussin el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc) 122*d0ef721eSBaptiste Daroussin { 123*d0ef721eSBaptiste Daroussin el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc; 124*d0ef721eSBaptiste Daroussin return 0; 125*d0ef721eSBaptiste Daroussin } 126*d0ef721eSBaptiste Daroussin 127*d0ef721eSBaptiste Daroussin 128*d0ef721eSBaptiste Daroussin /* el_read_getfn(): 129*d0ef721eSBaptiste Daroussin * return the current read char function, or EL_BUILTIN_GETCFN 130*d0ef721eSBaptiste Daroussin * if it is the default one 131*d0ef721eSBaptiste Daroussin */ 132*d0ef721eSBaptiste Daroussin libedit_private el_rfunc_t 133*d0ef721eSBaptiste Daroussin el_read_getfn(struct el_read_t *el_read) 134*d0ef721eSBaptiste Daroussin { 135*d0ef721eSBaptiste Daroussin return el_read->read_char == read_char ? 136*d0ef721eSBaptiste Daroussin EL_BUILTIN_GETCFN : el_read->read_char; 137*d0ef721eSBaptiste Daroussin } 138*d0ef721eSBaptiste Daroussin 139*d0ef721eSBaptiste Daroussin 140*d0ef721eSBaptiste Daroussin /* read__fixio(): 141*d0ef721eSBaptiste Daroussin * Try to recover from a read error 142*d0ef721eSBaptiste Daroussin */ 143*d0ef721eSBaptiste Daroussin /* ARGSUSED */ 144*d0ef721eSBaptiste Daroussin static int 145*d0ef721eSBaptiste Daroussin read__fixio(int fd __attribute__((__unused__)), int e) 146*d0ef721eSBaptiste Daroussin { 147*d0ef721eSBaptiste Daroussin 148*d0ef721eSBaptiste Daroussin switch (e) { 149*d0ef721eSBaptiste Daroussin case -1: /* Make sure that the code is reachable */ 150*d0ef721eSBaptiste Daroussin 151*d0ef721eSBaptiste Daroussin #ifdef EWOULDBLOCK 152*d0ef721eSBaptiste Daroussin case EWOULDBLOCK: 153*d0ef721eSBaptiste Daroussin #ifndef TRY_AGAIN 154*d0ef721eSBaptiste Daroussin #define TRY_AGAIN 155*d0ef721eSBaptiste Daroussin #endif 156*d0ef721eSBaptiste Daroussin #endif /* EWOULDBLOCK */ 157*d0ef721eSBaptiste Daroussin 158*d0ef721eSBaptiste Daroussin #if defined(POSIX) && defined(EAGAIN) 159*d0ef721eSBaptiste Daroussin #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 160*d0ef721eSBaptiste Daroussin case EAGAIN: 161*d0ef721eSBaptiste Daroussin #ifndef TRY_AGAIN 162*d0ef721eSBaptiste Daroussin #define TRY_AGAIN 163*d0ef721eSBaptiste Daroussin #endif 164*d0ef721eSBaptiste Daroussin #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ 165*d0ef721eSBaptiste Daroussin #endif /* POSIX && EAGAIN */ 166*d0ef721eSBaptiste Daroussin 167*d0ef721eSBaptiste Daroussin e = 0; 168*d0ef721eSBaptiste Daroussin #ifdef TRY_AGAIN 169*d0ef721eSBaptiste Daroussin #if defined(F_SETFL) && defined(O_NDELAY) 170*d0ef721eSBaptiste Daroussin if ((e = fcntl(fd, F_GETFL, 0)) == -1) 171*d0ef721eSBaptiste Daroussin return -1; 172*d0ef721eSBaptiste Daroussin 173*d0ef721eSBaptiste Daroussin if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) 174*d0ef721eSBaptiste Daroussin return -1; 175*d0ef721eSBaptiste Daroussin else 176*d0ef721eSBaptiste Daroussin e = 1; 177*d0ef721eSBaptiste Daroussin #endif /* F_SETFL && O_NDELAY */ 178*d0ef721eSBaptiste Daroussin 179*d0ef721eSBaptiste Daroussin #ifdef FIONBIO 180*d0ef721eSBaptiste Daroussin { 181*d0ef721eSBaptiste Daroussin int zero = 0; 182*d0ef721eSBaptiste Daroussin 183*d0ef721eSBaptiste Daroussin if (ioctl(fd, FIONBIO, &zero) == -1) 184*d0ef721eSBaptiste Daroussin return -1; 185*d0ef721eSBaptiste Daroussin else 186*d0ef721eSBaptiste Daroussin e = 1; 187*d0ef721eSBaptiste Daroussin } 188*d0ef721eSBaptiste Daroussin #endif /* FIONBIO */ 189*d0ef721eSBaptiste Daroussin 190*d0ef721eSBaptiste Daroussin #endif /* TRY_AGAIN */ 191*d0ef721eSBaptiste Daroussin return e ? 0 : -1; 192*d0ef721eSBaptiste Daroussin 193*d0ef721eSBaptiste Daroussin case EINTR: 194*d0ef721eSBaptiste Daroussin return 0; 195*d0ef721eSBaptiste Daroussin 196*d0ef721eSBaptiste Daroussin default: 197*d0ef721eSBaptiste Daroussin return -1; 198*d0ef721eSBaptiste Daroussin } 199*d0ef721eSBaptiste Daroussin } 200*d0ef721eSBaptiste Daroussin 201*d0ef721eSBaptiste Daroussin 202*d0ef721eSBaptiste Daroussin /* el_push(): 203*d0ef721eSBaptiste Daroussin * Push a macro 204*d0ef721eSBaptiste Daroussin */ 205*d0ef721eSBaptiste Daroussin void 206*d0ef721eSBaptiste Daroussin el_wpush(EditLine *el, const wchar_t *str) 207*d0ef721eSBaptiste Daroussin { 208*d0ef721eSBaptiste Daroussin struct macros *ma = &el->el_read->macros; 209*d0ef721eSBaptiste Daroussin 210*d0ef721eSBaptiste Daroussin if (str != NULL && ma->level + 1 < EL_MAXMACRO) { 211*d0ef721eSBaptiste Daroussin ma->level++; 212*d0ef721eSBaptiste Daroussin if ((ma->macro[ma->level] = wcsdup(str)) != NULL) 213*d0ef721eSBaptiste Daroussin return; 214*d0ef721eSBaptiste Daroussin ma->level--; 215*d0ef721eSBaptiste Daroussin } 216*d0ef721eSBaptiste Daroussin terminal_beep(el); 217*d0ef721eSBaptiste Daroussin terminal__flush(el); 218*d0ef721eSBaptiste Daroussin } 219*d0ef721eSBaptiste Daroussin 220*d0ef721eSBaptiste Daroussin 221*d0ef721eSBaptiste Daroussin /* read_getcmd(): 222*d0ef721eSBaptiste Daroussin * Get next command from the input stream, 223*d0ef721eSBaptiste Daroussin * return 0 on success or -1 on EOF or error. 224*d0ef721eSBaptiste Daroussin * Character values > 255 are not looked up in the map, but inserted. 225*d0ef721eSBaptiste Daroussin */ 226*d0ef721eSBaptiste Daroussin static int 227*d0ef721eSBaptiste Daroussin read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch) 228*d0ef721eSBaptiste Daroussin { 229*d0ef721eSBaptiste Daroussin static const wchar_t meta = (wchar_t)0x80; 230*d0ef721eSBaptiste Daroussin el_action_t cmd; 231*d0ef721eSBaptiste Daroussin 232*d0ef721eSBaptiste Daroussin do { 233*d0ef721eSBaptiste Daroussin if (el_wgetc(el, ch) != 1) 234*d0ef721eSBaptiste Daroussin return -1; 235*d0ef721eSBaptiste Daroussin 236*d0ef721eSBaptiste Daroussin #ifdef KANJI 237*d0ef721eSBaptiste Daroussin if ((*ch & meta)) { 238*d0ef721eSBaptiste Daroussin el->el_state.metanext = 0; 239*d0ef721eSBaptiste Daroussin cmd = CcViMap[' ']; 240*d0ef721eSBaptiste Daroussin break; 241*d0ef721eSBaptiste Daroussin } else 242*d0ef721eSBaptiste Daroussin #endif /* KANJI */ 243*d0ef721eSBaptiste Daroussin 244*d0ef721eSBaptiste Daroussin if (el->el_state.metanext) { 245*d0ef721eSBaptiste Daroussin el->el_state.metanext = 0; 246*d0ef721eSBaptiste Daroussin *ch |= meta; 247*d0ef721eSBaptiste Daroussin } 248*d0ef721eSBaptiste Daroussin if (*ch >= N_KEYS) 249*d0ef721eSBaptiste Daroussin cmd = ED_INSERT; 250*d0ef721eSBaptiste Daroussin else 251*d0ef721eSBaptiste Daroussin cmd = el->el_map.current[(unsigned char) *ch]; 252*d0ef721eSBaptiste Daroussin if (cmd == ED_SEQUENCE_LEAD_IN) { 253*d0ef721eSBaptiste Daroussin keymacro_value_t val; 254*d0ef721eSBaptiste Daroussin switch (keymacro_get(el, ch, &val)) { 255*d0ef721eSBaptiste Daroussin case XK_CMD: 256*d0ef721eSBaptiste Daroussin cmd = val.cmd; 257*d0ef721eSBaptiste Daroussin break; 258*d0ef721eSBaptiste Daroussin case XK_STR: 259*d0ef721eSBaptiste Daroussin el_wpush(el, val.str); 260*d0ef721eSBaptiste Daroussin break; 261*d0ef721eSBaptiste Daroussin case XK_NOD: 262*d0ef721eSBaptiste Daroussin return -1; 263*d0ef721eSBaptiste Daroussin default: 264*d0ef721eSBaptiste Daroussin EL_ABORT((el->el_errfile, "Bad XK_ type \n")); 265*d0ef721eSBaptiste Daroussin break; 266*d0ef721eSBaptiste Daroussin } 267*d0ef721eSBaptiste Daroussin } 268*d0ef721eSBaptiste Daroussin } while (cmd == ED_SEQUENCE_LEAD_IN); 269*d0ef721eSBaptiste Daroussin *cmdnum = cmd; 270*d0ef721eSBaptiste Daroussin return 0; 271*d0ef721eSBaptiste Daroussin } 272*d0ef721eSBaptiste Daroussin 273*d0ef721eSBaptiste Daroussin /* read_char(): 274*d0ef721eSBaptiste Daroussin * Read a character from the tty. 275*d0ef721eSBaptiste Daroussin */ 276*d0ef721eSBaptiste Daroussin static int 277*d0ef721eSBaptiste Daroussin read_char(EditLine *el, wchar_t *cp) 278*d0ef721eSBaptiste Daroussin { 279*d0ef721eSBaptiste Daroussin ssize_t num_read; 280*d0ef721eSBaptiste Daroussin int tried = 0; 281*d0ef721eSBaptiste Daroussin char cbuf[MB_LEN_MAX]; 282*d0ef721eSBaptiste Daroussin size_t cbp = 0; 283*d0ef721eSBaptiste Daroussin int save_errno = errno; 284*d0ef721eSBaptiste Daroussin 285*d0ef721eSBaptiste Daroussin again: 286*d0ef721eSBaptiste Daroussin el->el_signal->sig_no = 0; 287*d0ef721eSBaptiste Daroussin while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) { 288*d0ef721eSBaptiste Daroussin int e = errno; 289*d0ef721eSBaptiste Daroussin switch (el->el_signal->sig_no) { 290*d0ef721eSBaptiste Daroussin case SIGCONT: 291*d0ef721eSBaptiste Daroussin el_wset(el, EL_REFRESH); 292*d0ef721eSBaptiste Daroussin /*FALLTHROUGH*/ 293*d0ef721eSBaptiste Daroussin case SIGWINCH: 294*d0ef721eSBaptiste Daroussin sig_set(el); 295*d0ef721eSBaptiste Daroussin goto again; 296*d0ef721eSBaptiste Daroussin default: 297*d0ef721eSBaptiste Daroussin break; 298*d0ef721eSBaptiste Daroussin } 299*d0ef721eSBaptiste Daroussin if (!tried && read__fixio(el->el_infd, e) == 0) { 300*d0ef721eSBaptiste Daroussin errno = save_errno; 301*d0ef721eSBaptiste Daroussin tried = 1; 302*d0ef721eSBaptiste Daroussin } else { 303*d0ef721eSBaptiste Daroussin errno = e; 304*d0ef721eSBaptiste Daroussin *cp = L'\0'; 305*d0ef721eSBaptiste Daroussin return -1; 306*d0ef721eSBaptiste Daroussin } 307*d0ef721eSBaptiste Daroussin } 308*d0ef721eSBaptiste Daroussin 309*d0ef721eSBaptiste Daroussin /* Test for EOF */ 310*d0ef721eSBaptiste Daroussin if (num_read == 0) { 311*d0ef721eSBaptiste Daroussin *cp = L'\0'; 312*d0ef721eSBaptiste Daroussin return 0; 313*d0ef721eSBaptiste Daroussin } 314*d0ef721eSBaptiste Daroussin 315*d0ef721eSBaptiste Daroussin for (;;) { 316*d0ef721eSBaptiste Daroussin mbstate_t mbs; 317*d0ef721eSBaptiste Daroussin 318*d0ef721eSBaptiste Daroussin ++cbp; 319*d0ef721eSBaptiste Daroussin /* This only works because UTF8 is stateless. */ 320*d0ef721eSBaptiste Daroussin memset(&mbs, 0, sizeof(mbs)); 321*d0ef721eSBaptiste Daroussin switch (mbrtowc(cp, cbuf, cbp, &mbs)) { 322*d0ef721eSBaptiste Daroussin case (size_t)-1: 323*d0ef721eSBaptiste Daroussin if (cbp > 1) { 324*d0ef721eSBaptiste Daroussin /* 325*d0ef721eSBaptiste Daroussin * Invalid sequence, discard all bytes 326*d0ef721eSBaptiste Daroussin * except the last one. 327*d0ef721eSBaptiste Daroussin */ 328*d0ef721eSBaptiste Daroussin cbuf[0] = cbuf[cbp - 1]; 329*d0ef721eSBaptiste Daroussin cbp = 0; 330*d0ef721eSBaptiste Daroussin break; 331*d0ef721eSBaptiste Daroussin } else { 332*d0ef721eSBaptiste Daroussin /* Invalid byte, discard it. */ 333*d0ef721eSBaptiste Daroussin cbp = 0; 334*d0ef721eSBaptiste Daroussin goto again; 335*d0ef721eSBaptiste Daroussin } 336*d0ef721eSBaptiste Daroussin case (size_t)-2: 337*d0ef721eSBaptiste Daroussin if (cbp >= MB_LEN_MAX) { 338*d0ef721eSBaptiste Daroussin errno = EILSEQ; 339*d0ef721eSBaptiste Daroussin *cp = L'\0'; 340*d0ef721eSBaptiste Daroussin return -1; 341*d0ef721eSBaptiste Daroussin } 342*d0ef721eSBaptiste Daroussin /* Incomplete sequence, read another byte. */ 343*d0ef721eSBaptiste Daroussin goto again; 344*d0ef721eSBaptiste Daroussin default: 345*d0ef721eSBaptiste Daroussin /* Valid character, process it. */ 346*d0ef721eSBaptiste Daroussin return 1; 347*d0ef721eSBaptiste Daroussin } 348*d0ef721eSBaptiste Daroussin } 349*d0ef721eSBaptiste Daroussin } 350*d0ef721eSBaptiste Daroussin 351*d0ef721eSBaptiste Daroussin /* read_pop(): 352*d0ef721eSBaptiste Daroussin * Pop a macro from the stack 353*d0ef721eSBaptiste Daroussin */ 354*d0ef721eSBaptiste Daroussin static void 355*d0ef721eSBaptiste Daroussin read_pop(struct macros *ma) 356*d0ef721eSBaptiste Daroussin { 357*d0ef721eSBaptiste Daroussin int i; 358*d0ef721eSBaptiste Daroussin 359*d0ef721eSBaptiste Daroussin el_free(ma->macro[0]); 360*d0ef721eSBaptiste Daroussin for (i = 0; i < ma->level; i++) 361*d0ef721eSBaptiste Daroussin ma->macro[i] = ma->macro[i + 1]; 362*d0ef721eSBaptiste Daroussin ma->level--; 363*d0ef721eSBaptiste Daroussin ma->offset = 0; 364*d0ef721eSBaptiste Daroussin } 365*d0ef721eSBaptiste Daroussin 366*d0ef721eSBaptiste Daroussin static void 367*d0ef721eSBaptiste Daroussin read_clearmacros(struct macros *ma) 368*d0ef721eSBaptiste Daroussin { 369*d0ef721eSBaptiste Daroussin while (ma->level >= 0) 370*d0ef721eSBaptiste Daroussin el_free(ma->macro[ma->level--]); 371*d0ef721eSBaptiste Daroussin ma->offset = 0; 372*d0ef721eSBaptiste Daroussin } 373*d0ef721eSBaptiste Daroussin 374*d0ef721eSBaptiste Daroussin /* el_wgetc(): 375*d0ef721eSBaptiste Daroussin * Read a wide character 376*d0ef721eSBaptiste Daroussin */ 377*d0ef721eSBaptiste Daroussin int 378*d0ef721eSBaptiste Daroussin el_wgetc(EditLine *el, wchar_t *cp) 379*d0ef721eSBaptiste Daroussin { 380*d0ef721eSBaptiste Daroussin struct macros *ma = &el->el_read->macros; 381*d0ef721eSBaptiste Daroussin int num_read; 382*d0ef721eSBaptiste Daroussin 383*d0ef721eSBaptiste Daroussin terminal__flush(el); 384*d0ef721eSBaptiste Daroussin for (;;) { 385*d0ef721eSBaptiste Daroussin if (ma->level < 0) 386*d0ef721eSBaptiste Daroussin break; 387*d0ef721eSBaptiste Daroussin 388*d0ef721eSBaptiste Daroussin if (ma->macro[0][ma->offset] == '\0') { 389*d0ef721eSBaptiste Daroussin read_pop(ma); 390*d0ef721eSBaptiste Daroussin continue; 391*d0ef721eSBaptiste Daroussin } 392*d0ef721eSBaptiste Daroussin 393*d0ef721eSBaptiste Daroussin *cp = ma->macro[0][ma->offset++]; 394*d0ef721eSBaptiste Daroussin 395*d0ef721eSBaptiste Daroussin if (ma->macro[0][ma->offset] == '\0') { 396*d0ef721eSBaptiste Daroussin /* Needed for QuoteMode On */ 397*d0ef721eSBaptiste Daroussin read_pop(ma); 398*d0ef721eSBaptiste Daroussin } 399*d0ef721eSBaptiste Daroussin 400*d0ef721eSBaptiste Daroussin return 1; 401*d0ef721eSBaptiste Daroussin } 402*d0ef721eSBaptiste Daroussin 403*d0ef721eSBaptiste Daroussin if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ 404*d0ef721eSBaptiste Daroussin return 0; 405*d0ef721eSBaptiste Daroussin 406*d0ef721eSBaptiste Daroussin num_read = (*el->el_read->read_char)(el, cp); 407*d0ef721eSBaptiste Daroussin 408*d0ef721eSBaptiste Daroussin /* 409*d0ef721eSBaptiste Daroussin * Remember the original reason of a read failure 410*d0ef721eSBaptiste Daroussin * such that el_wgets() can restore it after doing 411*d0ef721eSBaptiste Daroussin * various cleanup operation that might change errno. 412*d0ef721eSBaptiste Daroussin */ 413*d0ef721eSBaptiste Daroussin if (num_read < 0) 414*d0ef721eSBaptiste Daroussin el->el_read->read_errno = errno; 415*d0ef721eSBaptiste Daroussin 416*d0ef721eSBaptiste Daroussin return num_read; 417*d0ef721eSBaptiste Daroussin } 418*d0ef721eSBaptiste Daroussin 419*d0ef721eSBaptiste Daroussin libedit_private void 420*d0ef721eSBaptiste Daroussin read_prepare(EditLine *el) 421*d0ef721eSBaptiste Daroussin { 422*d0ef721eSBaptiste Daroussin if (el->el_flags & HANDLE_SIGNALS) 423*d0ef721eSBaptiste Daroussin sig_set(el); 424*d0ef721eSBaptiste Daroussin if (el->el_flags & NO_TTY) 425*d0ef721eSBaptiste Daroussin return; 426*d0ef721eSBaptiste Daroussin if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) 427*d0ef721eSBaptiste Daroussin tty_rawmode(el); 428*d0ef721eSBaptiste Daroussin 429*d0ef721eSBaptiste Daroussin /* This is relatively cheap, and things go terribly wrong if 430*d0ef721eSBaptiste Daroussin we have the wrong size. */ 431*d0ef721eSBaptiste Daroussin el_resize(el); 432*d0ef721eSBaptiste Daroussin re_clear_display(el); /* reset the display stuff */ 433*d0ef721eSBaptiste Daroussin ch_reset(el); 434*d0ef721eSBaptiste Daroussin re_refresh(el); /* print the prompt */ 435*d0ef721eSBaptiste Daroussin 436*d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED) 437*d0ef721eSBaptiste Daroussin terminal__flush(el); 438*d0ef721eSBaptiste Daroussin } 439*d0ef721eSBaptiste Daroussin 440*d0ef721eSBaptiste Daroussin libedit_private void 441*d0ef721eSBaptiste Daroussin read_finish(EditLine *el) 442*d0ef721eSBaptiste Daroussin { 443*d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) 444*d0ef721eSBaptiste Daroussin (void) tty_cookedmode(el); 445*d0ef721eSBaptiste Daroussin if (el->el_flags & HANDLE_SIGNALS) 446*d0ef721eSBaptiste Daroussin sig_clr(el); 447*d0ef721eSBaptiste Daroussin } 448*d0ef721eSBaptiste Daroussin 449*d0ef721eSBaptiste Daroussin static const wchar_t * 450*d0ef721eSBaptiste Daroussin noedit_wgets(EditLine *el, int *nread) 451*d0ef721eSBaptiste Daroussin { 452*d0ef721eSBaptiste Daroussin el_line_t *lp = &el->el_line; 453*d0ef721eSBaptiste Daroussin int num; 454*d0ef721eSBaptiste Daroussin 455*d0ef721eSBaptiste Daroussin while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) { 456*d0ef721eSBaptiste Daroussin if (lp->lastchar + 1 >= lp->limit && 457*d0ef721eSBaptiste Daroussin !ch_enlargebufs(el, (size_t)2)) 458*d0ef721eSBaptiste Daroussin break; 459*d0ef721eSBaptiste Daroussin lp->lastchar++; 460*d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED || 461*d0ef721eSBaptiste Daroussin lp->lastchar[-1] == '\r' || 462*d0ef721eSBaptiste Daroussin lp->lastchar[-1] == '\n') 463*d0ef721eSBaptiste Daroussin break; 464*d0ef721eSBaptiste Daroussin } 465*d0ef721eSBaptiste Daroussin if (num == -1 && errno == EINTR) 466*d0ef721eSBaptiste Daroussin lp->lastchar = lp->buffer; 467*d0ef721eSBaptiste Daroussin lp->cursor = lp->lastchar; 468*d0ef721eSBaptiste Daroussin *lp->lastchar = '\0'; 469*d0ef721eSBaptiste Daroussin *nread = (int)(lp->lastchar - lp->buffer); 470*d0ef721eSBaptiste Daroussin return *nread ? lp->buffer : NULL; 471*d0ef721eSBaptiste Daroussin } 472*d0ef721eSBaptiste Daroussin 473*d0ef721eSBaptiste Daroussin const wchar_t * 474*d0ef721eSBaptiste Daroussin el_wgets(EditLine *el, int *nread) 475*d0ef721eSBaptiste Daroussin { 476*d0ef721eSBaptiste Daroussin int retval; 477*d0ef721eSBaptiste Daroussin el_action_t cmdnum = 0; 478*d0ef721eSBaptiste Daroussin int num; /* how many chars we have read at NL */ 479*d0ef721eSBaptiste Daroussin wchar_t ch; 480*d0ef721eSBaptiste Daroussin int nrb; 481*d0ef721eSBaptiste Daroussin 482*d0ef721eSBaptiste Daroussin if (nread == NULL) 483*d0ef721eSBaptiste Daroussin nread = &nrb; 484*d0ef721eSBaptiste Daroussin *nread = 0; 485*d0ef721eSBaptiste Daroussin el->el_read->read_errno = 0; 486*d0ef721eSBaptiste Daroussin 487*d0ef721eSBaptiste Daroussin if (el->el_flags & NO_TTY) { 488*d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 489*d0ef721eSBaptiste Daroussin return noedit_wgets(el, nread); 490*d0ef721eSBaptiste Daroussin } 491*d0ef721eSBaptiste Daroussin 492*d0ef721eSBaptiste Daroussin #ifdef FIONREAD 493*d0ef721eSBaptiste Daroussin if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) { 494*d0ef721eSBaptiste Daroussin int chrs = 0; 495*d0ef721eSBaptiste Daroussin 496*d0ef721eSBaptiste Daroussin (void) ioctl(el->el_infd, FIONREAD, &chrs); 497*d0ef721eSBaptiste Daroussin if (chrs == 0) { 498*d0ef721eSBaptiste Daroussin if (tty_rawmode(el) < 0) { 499*d0ef721eSBaptiste Daroussin errno = 0; 500*d0ef721eSBaptiste Daroussin *nread = 0; 501*d0ef721eSBaptiste Daroussin return NULL; 502*d0ef721eSBaptiste Daroussin } 503*d0ef721eSBaptiste Daroussin } 504*d0ef721eSBaptiste Daroussin } 505*d0ef721eSBaptiste Daroussin #endif /* FIONREAD */ 506*d0ef721eSBaptiste Daroussin 507*d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) 508*d0ef721eSBaptiste Daroussin read_prepare(el); 509*d0ef721eSBaptiste Daroussin 510*d0ef721eSBaptiste Daroussin if (el->el_flags & EDIT_DISABLED) { 511*d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) 512*d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer; 513*d0ef721eSBaptiste Daroussin terminal__flush(el); 514*d0ef721eSBaptiste Daroussin return noedit_wgets(el, nread); 515*d0ef721eSBaptiste Daroussin } 516*d0ef721eSBaptiste Daroussin 517*d0ef721eSBaptiste Daroussin for (num = -1; num == -1;) { /* while still editing this line */ 518*d0ef721eSBaptiste Daroussin /* if EOF or error */ 519*d0ef721eSBaptiste Daroussin if (read_getcmd(el, &cmdnum, &ch) == -1) 520*d0ef721eSBaptiste Daroussin break; 521*d0ef721eSBaptiste Daroussin if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */ 522*d0ef721eSBaptiste Daroussin continue; /* try again */ 523*d0ef721eSBaptiste Daroussin /* now do the real command */ 524*d0ef721eSBaptiste Daroussin /* vi redo needs these way down the levels... */ 525*d0ef721eSBaptiste Daroussin el->el_state.thiscmd = cmdnum; 526*d0ef721eSBaptiste Daroussin el->el_state.thisch = ch; 527*d0ef721eSBaptiste Daroussin if (el->el_map.type == MAP_VI && 528*d0ef721eSBaptiste Daroussin el->el_map.current == el->el_map.key && 529*d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { 530*d0ef721eSBaptiste Daroussin if (cmdnum == VI_DELETE_PREV_CHAR && 531*d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos != el->el_chared.c_redo.buf 532*d0ef721eSBaptiste Daroussin && iswprint(el->el_chared.c_redo.pos[-1])) 533*d0ef721eSBaptiste Daroussin el->el_chared.c_redo.pos--; 534*d0ef721eSBaptiste Daroussin else 535*d0ef721eSBaptiste Daroussin *el->el_chared.c_redo.pos++ = ch; 536*d0ef721eSBaptiste Daroussin } 537*d0ef721eSBaptiste Daroussin retval = (*el->el_map.func[cmdnum]) (el, ch); 538*d0ef721eSBaptiste Daroussin 539*d0ef721eSBaptiste Daroussin /* save the last command here */ 540*d0ef721eSBaptiste Daroussin el->el_state.lastcmd = cmdnum; 541*d0ef721eSBaptiste Daroussin 542*d0ef721eSBaptiste Daroussin /* use any return value */ 543*d0ef721eSBaptiste Daroussin switch (retval) { 544*d0ef721eSBaptiste Daroussin case CC_CURSOR: 545*d0ef721eSBaptiste Daroussin re_refresh_cursor(el); 546*d0ef721eSBaptiste Daroussin break; 547*d0ef721eSBaptiste Daroussin 548*d0ef721eSBaptiste Daroussin case CC_REDISPLAY: 549*d0ef721eSBaptiste Daroussin re_clear_lines(el); 550*d0ef721eSBaptiste Daroussin re_clear_display(el); 551*d0ef721eSBaptiste Daroussin /* FALLTHROUGH */ 552*d0ef721eSBaptiste Daroussin 553*d0ef721eSBaptiste Daroussin case CC_REFRESH: 554*d0ef721eSBaptiste Daroussin re_refresh(el); 555*d0ef721eSBaptiste Daroussin break; 556*d0ef721eSBaptiste Daroussin 557*d0ef721eSBaptiste Daroussin case CC_REFRESH_BEEP: 558*d0ef721eSBaptiste Daroussin re_refresh(el); 559*d0ef721eSBaptiste Daroussin terminal_beep(el); 560*d0ef721eSBaptiste Daroussin break; 561*d0ef721eSBaptiste Daroussin 562*d0ef721eSBaptiste Daroussin case CC_NORM: /* normal char */ 563*d0ef721eSBaptiste Daroussin break; 564*d0ef721eSBaptiste Daroussin 565*d0ef721eSBaptiste Daroussin case CC_ARGHACK: /* Suggested by Rich Salz */ 566*d0ef721eSBaptiste Daroussin /* <rsalz@pineapple.bbn.com> */ 567*d0ef721eSBaptiste Daroussin continue; /* keep going... */ 568*d0ef721eSBaptiste Daroussin 569*d0ef721eSBaptiste Daroussin case CC_EOF: /* end of file typed */ 570*d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) 571*d0ef721eSBaptiste Daroussin num = 0; 572*d0ef721eSBaptiste Daroussin else if (num == -1) { 573*d0ef721eSBaptiste Daroussin *el->el_line.lastchar++ = CONTROL('d'); 574*d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 575*d0ef721eSBaptiste Daroussin num = 1; 576*d0ef721eSBaptiste Daroussin } 577*d0ef721eSBaptiste Daroussin break; 578*d0ef721eSBaptiste Daroussin 579*d0ef721eSBaptiste Daroussin case CC_NEWLINE: /* normal end of line */ 580*d0ef721eSBaptiste Daroussin num = (int)(el->el_line.lastchar - el->el_line.buffer); 581*d0ef721eSBaptiste Daroussin break; 582*d0ef721eSBaptiste Daroussin 583*d0ef721eSBaptiste Daroussin case CC_FATAL: /* fatal error, reset to known state */ 584*d0ef721eSBaptiste Daroussin /* put (real) cursor in a known place */ 585*d0ef721eSBaptiste Daroussin re_clear_display(el); /* reset the display stuff */ 586*d0ef721eSBaptiste Daroussin ch_reset(el); /* reset the input pointers */ 587*d0ef721eSBaptiste Daroussin read_clearmacros(&el->el_read->macros); 588*d0ef721eSBaptiste Daroussin re_refresh(el); /* print the prompt again */ 589*d0ef721eSBaptiste Daroussin break; 590*d0ef721eSBaptiste Daroussin 591*d0ef721eSBaptiste Daroussin case CC_ERROR: 592*d0ef721eSBaptiste Daroussin default: /* functions we don't know about */ 593*d0ef721eSBaptiste Daroussin terminal_beep(el); 594*d0ef721eSBaptiste Daroussin terminal__flush(el); 595*d0ef721eSBaptiste Daroussin break; 596*d0ef721eSBaptiste Daroussin } 597*d0ef721eSBaptiste Daroussin el->el_state.argument = 1; 598*d0ef721eSBaptiste Daroussin el->el_state.doingarg = 0; 599*d0ef721eSBaptiste Daroussin el->el_chared.c_vcmd.action = NOP; 600*d0ef721eSBaptiste Daroussin if (el->el_flags & UNBUFFERED) 601*d0ef721eSBaptiste Daroussin break; 602*d0ef721eSBaptiste Daroussin } 603*d0ef721eSBaptiste Daroussin 604*d0ef721eSBaptiste Daroussin terminal__flush(el); /* flush any buffered output */ 605*d0ef721eSBaptiste Daroussin /* make sure the tty is set up correctly */ 606*d0ef721eSBaptiste Daroussin if ((el->el_flags & UNBUFFERED) == 0) { 607*d0ef721eSBaptiste Daroussin read_finish(el); 608*d0ef721eSBaptiste Daroussin *nread = num != -1 ? num : 0; 609*d0ef721eSBaptiste Daroussin } else 610*d0ef721eSBaptiste Daroussin *nread = (int)(el->el_line.lastchar - el->el_line.buffer); 611*d0ef721eSBaptiste Daroussin 612*d0ef721eSBaptiste Daroussin if (*nread == 0) { 613*d0ef721eSBaptiste Daroussin if (num == -1) { 614*d0ef721eSBaptiste Daroussin *nread = -1; 615*d0ef721eSBaptiste Daroussin if (el->el_read->read_errno) 616*d0ef721eSBaptiste Daroussin errno = el->el_read->read_errno; 617*d0ef721eSBaptiste Daroussin } 618*d0ef721eSBaptiste Daroussin return NULL; 619*d0ef721eSBaptiste Daroussin } else 620*d0ef721eSBaptiste Daroussin return el->el_line.buffer; 621*d0ef721eSBaptiste Daroussin } 622