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