1/* $OpenBSD: common.c,v 1.23 2023/03/08 04:43:05 guenther Exp $ */ 2/* $NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $ */ 3 4/*- 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Christos Zoulas of Cornell University. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "config.h" 37 38/* 39 * common.c: Common Editor functions 40 */ 41#include <ctype.h> 42#include <string.h> 43 44#include "el.h" 45#include "common.h" 46#include "fcns.h" 47#include "parse.h" 48#include "vi.h" 49 50/* ed_end_of_file(): 51 * Indicate end of file 52 * [^D] 53 */ 54protected el_action_t 55ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) 56{ 57 58 re_goto_bottom(el); 59 *el->el_line.lastchar = '\0'; 60 return CC_EOF; 61} 62 63 64/* ed_insert(): 65 * Add character to the line 66 * Insert a character [bound to all insert keys] 67 */ 68protected el_action_t 69ed_insert(EditLine *el, wint_t c) 70{ 71 int count = el->el_state.argument; 72 73 if (c == '\0') 74 return CC_ERROR; 75 76 if (el->el_line.lastchar + el->el_state.argument >= 77 el->el_line.limit) { 78 /* end of buffer space, try to allocate more */ 79 if (!ch_enlargebufs(el, (size_t) count)) 80 return CC_ERROR; /* error allocating more */ 81 } 82 83 if (count == 1) { 84 if (el->el_state.inputmode == MODE_INSERT 85 || el->el_line.cursor >= el->el_line.lastchar) 86 c_insert(el, 1); 87 88 *el->el_line.cursor++ = c; 89 re_fastaddc(el); /* fast refresh for one char. */ 90 } else { 91 if (el->el_state.inputmode != MODE_REPLACE_1) 92 c_insert(el, el->el_state.argument); 93 94 while (count-- && el->el_line.cursor < el->el_line.lastchar) 95 *el->el_line.cursor++ = c; 96 re_refresh(el); 97 } 98 99 if (el->el_state.inputmode == MODE_REPLACE_1) 100 return vi_command_mode(el, 0); 101 102 return CC_NORM; 103} 104 105 106/* ed_delete_prev_word(): 107 * Delete from beginning of current word to cursor 108 * [M-^?] [^W] 109 */ 110protected el_action_t 111ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 112{ 113 wchar_t *cp, *p, *kp; 114 115 if (el->el_line.cursor == el->el_line.buffer) 116 return CC_ERROR; 117 118 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 119 el->el_state.argument, ce__isword); 120 121 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 122 *kp++ = *p; 123 el->el_chared.c_kill.last = kp; 124 125 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ 126 el->el_line.cursor = cp; 127 if (el->el_line.cursor < el->el_line.buffer) 128 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 129 return CC_REFRESH; 130} 131 132 133/* ed_delete_next_char(): 134 * Delete character under cursor 135 * [^D] [x] 136 */ 137protected el_action_t 138ed_delete_next_char(EditLine *el, wint_t c) 139{ 140#ifdef notdef /* XXX */ 141#define EL el->el_line 142 (void) fprintf(el->el_errfile, 143 "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n", 144 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 145 EL.lastchar, EL.limit, EL.limit); 146#endif 147 if (el->el_line.cursor == el->el_line.lastchar) { 148 /* if I'm at the end */ 149 if (el->el_map.type == MAP_VI) { 150 if (el->el_line.cursor == el->el_line.buffer) { 151 /* if I'm also at the beginning */ 152#ifdef KSHVI 153 return CC_ERROR; 154#else 155 /* then do an EOF */ 156 terminal_writec(el, c); 157 return CC_EOF; 158#endif 159 } else { 160#ifdef KSHVI 161 el->el_line.cursor--; 162#else 163 return CC_ERROR; 164#endif 165 } 166 } else { 167 if (el->el_line.cursor != el->el_line.buffer) 168 el->el_line.cursor--; 169 else 170 return CC_ERROR; 171 } 172 } 173 c_delafter(el, el->el_state.argument); /* delete after dot */ 174 if (el->el_line.cursor >= el->el_line.lastchar && 175 el->el_line.cursor > el->el_line.buffer) 176 /* bounds check */ 177 el->el_line.cursor = el->el_line.lastchar - 1; 178 return CC_REFRESH; 179} 180 181 182/* ed_kill_line(): 183 * Cut to the end of line 184 * [^K] [^K] 185 */ 186protected el_action_t 187ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__))) 188{ 189 wchar_t *kp, *cp; 190 191 cp = el->el_line.cursor; 192 kp = el->el_chared.c_kill.buf; 193 while (cp < el->el_line.lastchar) 194 *kp++ = *cp++; /* copy it */ 195 el->el_chared.c_kill.last = kp; 196 /* zap! -- delete to end */ 197 el->el_line.lastchar = el->el_line.cursor; 198 return CC_REFRESH; 199} 200 201 202/* ed_move_to_end(): 203 * Move cursor to the end of line 204 * [^E] [^E] 205 */ 206protected el_action_t 207ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) 208{ 209 210 el->el_line.cursor = el->el_line.lastchar; 211 if (el->el_map.type == MAP_VI) { 212 if (el->el_chared.c_vcmd.action != NOP) { 213 cv_delfini(el); 214 return CC_REFRESH; 215 } 216#ifdef VI_MOVE 217 el->el_line.cursor--; 218#endif 219 } 220 return CC_CURSOR; 221} 222 223 224/* ed_move_to_beg(): 225 * Move cursor to the beginning of line 226 * [^A] [^A] 227 */ 228protected el_action_t 229ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) 230{ 231 232 el->el_line.cursor = el->el_line.buffer; 233 234 if (el->el_map.type == MAP_VI) { 235 /* We want FIRST non space character */ 236 while (iswspace(*el->el_line.cursor)) 237 el->el_line.cursor++; 238 if (el->el_chared.c_vcmd.action != NOP) { 239 cv_delfini(el); 240 return CC_REFRESH; 241 } 242 } 243 return CC_CURSOR; 244} 245 246 247/* ed_transpose_chars(): 248 * Exchange the character to the left of the cursor with the one under it 249 * [^T] [^T] 250 */ 251protected el_action_t 252ed_transpose_chars(EditLine *el, wint_t c) 253{ 254 255 if (el->el_line.cursor < el->el_line.lastchar) { 256 if (el->el_line.lastchar <= &el->el_line.buffer[1]) 257 return CC_ERROR; 258 else 259 el->el_line.cursor++; 260 } 261 if (el->el_line.cursor > &el->el_line.buffer[1]) { 262 /* must have at least two chars entered */ 263 c = el->el_line.cursor[-2]; 264 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 265 el->el_line.cursor[-1] = c; 266 return CC_REFRESH; 267 } else 268 return CC_ERROR; 269} 270 271 272/* ed_next_char(): 273 * Move to the right one character 274 * [^F] [^F] 275 */ 276protected el_action_t 277ed_next_char(EditLine *el, wint_t c __attribute__((__unused__))) 278{ 279 wchar_t *lim = el->el_line.lastchar; 280 281 if (el->el_line.cursor >= lim || 282 (el->el_line.cursor == lim - 1 && 283 el->el_map.type == MAP_VI && 284 el->el_chared.c_vcmd.action == NOP)) 285 return CC_ERROR; 286 287 el->el_line.cursor += el->el_state.argument; 288 if (el->el_line.cursor > lim) 289 el->el_line.cursor = lim; 290 291 if (el->el_map.type == MAP_VI) 292 if (el->el_chared.c_vcmd.action != NOP) { 293 cv_delfini(el); 294 return CC_REFRESH; 295 } 296 return CC_CURSOR; 297} 298 299 300/* ed_prev_word(): 301 * Move to the beginning of the current word 302 * [M-b] [b] 303 */ 304protected el_action_t 305ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) 306{ 307 308 if (el->el_line.cursor == el->el_line.buffer) 309 return CC_ERROR; 310 311 el->el_line.cursor = c__prev_word(el->el_line.cursor, 312 el->el_line.buffer, 313 el->el_state.argument, 314 ce__isword); 315 316 if (el->el_map.type == MAP_VI) 317 if (el->el_chared.c_vcmd.action != NOP) { 318 cv_delfini(el); 319 return CC_REFRESH; 320 } 321 return CC_CURSOR; 322} 323 324 325/* ed_prev_char(): 326 * Move to the left one character 327 * [^B] [^B] 328 */ 329protected el_action_t 330ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 331{ 332 333 if (el->el_line.cursor > el->el_line.buffer) { 334 el->el_line.cursor -= el->el_state.argument; 335 if (el->el_line.cursor < el->el_line.buffer) 336 el->el_line.cursor = el->el_line.buffer; 337 338 if (el->el_map.type == MAP_VI) 339 if (el->el_chared.c_vcmd.action != NOP) { 340 cv_delfini(el); 341 return CC_REFRESH; 342 } 343 return CC_CURSOR; 344 } else 345 return CC_ERROR; 346} 347 348 349/* ed_quoted_insert(): 350 * Add the next character typed verbatim 351 * [^V] [^V] 352 */ 353protected el_action_t 354ed_quoted_insert(EditLine *el, wint_t c) 355{ 356 int num; 357 358 tty_quotemode(el); 359 num = el_wgetc(el, &c); 360 tty_noquotemode(el); 361 if (num == 1) 362 return ed_insert(el, c); 363 else 364 return ed_end_of_file(el, 0); 365} 366 367 368/* ed_digit(): 369 * Adds to argument or enters a digit 370 */ 371protected el_action_t 372ed_digit(EditLine *el, wint_t c) 373{ 374 375 if (!iswdigit(c)) 376 return CC_ERROR; 377 378 if (el->el_state.doingarg) { 379 /* if doing an arg, add this in... */ 380 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 381 el->el_state.argument = c - '0'; 382 else { 383 if (el->el_state.argument > 1000000) 384 return CC_ERROR; 385 el->el_state.argument = 386 (el->el_state.argument * 10) + (c - '0'); 387 } 388 return CC_ARGHACK; 389 } 390 391 return ed_insert(el, c); 392} 393 394 395/* ed_argument_digit(): 396 * Digit that starts argument 397 * For ESC-n 398 */ 399protected el_action_t 400ed_argument_digit(EditLine *el, wint_t c) 401{ 402 403 if (!iswdigit(c)) 404 return CC_ERROR; 405 406 if (el->el_state.doingarg) { 407 if (el->el_state.argument > 1000000) 408 return CC_ERROR; 409 el->el_state.argument = (el->el_state.argument * 10) + 410 (c - '0'); 411 } else { /* else starting an argument */ 412 el->el_state.argument = c - '0'; 413 el->el_state.doingarg = 1; 414 } 415 return CC_ARGHACK; 416} 417 418 419/* ed_unassigned(): 420 * Indicates unbound character 421 * Bound to keys that are not assigned 422 */ 423protected el_action_t 424ed_unassigned(EditLine *el, wint_t c __attribute__((__unused__))) 425{ 426 427 return CC_ERROR; 428} 429 430 431/* ed_ignore(): 432 * Input characters that have no effect 433 * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\] 434 */ 435protected el_action_t 436ed_ignore(EditLine *el __attribute__((__unused__)), 437 wint_t c __attribute__((__unused__))) 438{ 439 440 return CC_NORM; 441} 442 443 444/* ed_newline(): 445 * Execute command 446 * [^J] 447 */ 448protected el_action_t 449ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) 450{ 451 452 re_goto_bottom(el); 453 *el->el_line.lastchar++ = '\n'; 454 *el->el_line.lastchar = '\0'; 455 return CC_NEWLINE; 456} 457 458 459/* ed_delete_prev_char(): 460 * Delete the character to the left of the cursor 461 * [^?] 462 */ 463protected el_action_t 464ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) 465{ 466 467 if (el->el_line.cursor <= el->el_line.buffer) 468 return CC_ERROR; 469 470 c_delbefore(el, el->el_state.argument); 471 el->el_line.cursor -= el->el_state.argument; 472 if (el->el_line.cursor < el->el_line.buffer) 473 el->el_line.cursor = el->el_line.buffer; 474 return CC_REFRESH; 475} 476 477 478/* ed_clear_screen(): 479 * Clear screen leaving current line at the top 480 * [^L] 481 */ 482protected el_action_t 483ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) 484{ 485 486 terminal_clear_screen(el); /* clear the whole real screen */ 487 re_clear_display(el); /* reset everything */ 488 return CC_REFRESH; 489} 490 491 492/* ed_redisplay(): 493 * Redisplay everything 494 * ^R 495 */ 496protected el_action_t 497ed_redisplay(EditLine *el __attribute__((__unused__)), 498 wint_t c __attribute__((__unused__))) 499{ 500 501 return CC_REDISPLAY; 502} 503 504 505/* ed_start_over(): 506 * Erase current line and start from scratch 507 * [^G] 508 */ 509protected el_action_t 510ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) 511{ 512 513 ch_reset(el); 514 return CC_REFRESH; 515} 516 517 518/* ed_sequence_lead_in(): 519 * First character in a bound sequence 520 * Placeholder for external keys 521 */ 522protected el_action_t 523ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 524 wint_t c __attribute__((__unused__))) 525{ 526 527 return CC_NORM; 528} 529 530 531/* ed_prev_history(): 532 * Move to the previous history line 533 * [^P] [k] 534 */ 535protected el_action_t 536ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 537{ 538 char beep = 0; 539 int sv_event = el->el_history.eventno; 540 541 el->el_chared.c_undo.len = -1; 542 *el->el_line.lastchar = '\0'; /* just in case */ 543 544 if (el->el_history.eventno == 0) { /* save the current buffer 545 * away */ 546 (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 547 EL_BUFSIZ); 548 el->el_history.last = el->el_history.buf + 549 (el->el_line.lastchar - el->el_line.buffer); 550 } 551 el->el_history.eventno += el->el_state.argument; 552 553 if (hist_get(el) == CC_ERROR) { 554 if (el->el_map.type == MAP_VI) { 555 el->el_history.eventno = sv_event; 556 } 557 beep = 1; 558 /* el->el_history.eventno was fixed by first call */ 559 (void) hist_get(el); 560 } 561 if (beep) 562 return CC_REFRESH_BEEP; 563 return CC_REFRESH; 564} 565 566 567/* ed_next_history(): 568 * Move to the next history line 569 * [^N] [j] 570 */ 571protected el_action_t 572ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 573{ 574 el_action_t beep = CC_REFRESH, rval; 575 576 el->el_chared.c_undo.len = -1; 577 *el->el_line.lastchar = '\0'; /* just in case */ 578 579 el->el_history.eventno -= el->el_state.argument; 580 581 if (el->el_history.eventno < 0) { 582 el->el_history.eventno = 0; 583 beep = CC_REFRESH_BEEP; 584 } 585 rval = hist_get(el); 586 if (rval == CC_REFRESH) 587 return beep; 588 return rval; 589 590} 591 592 593/* ed_search_prev_history(): 594 * Search previous in history for a line matching the current 595 * next search history [M-P] [K] 596 */ 597protected el_action_t 598ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) 599{ 600 const wchar_t *hp; 601 int h; 602 int found = 0; 603 604 el->el_chared.c_vcmd.action = NOP; 605 el->el_chared.c_undo.len = -1; 606 *el->el_line.lastchar = '\0'; /* just in case */ 607 if (el->el_history.eventno < 0) { 608#ifdef DEBUG_EDIT 609 (void) fprintf(el->el_errfile, 610 "e_prev_search_hist(): eventno < 0;\n"); 611#endif 612 el->el_history.eventno = 0; 613 return CC_ERROR; 614 } 615 if (el->el_history.eventno == 0) { 616 (void) wcsncpy(el->el_history.buf, el->el_line.buffer, 617 EL_BUFSIZ); 618 el->el_history.last = el->el_history.buf + 619 (el->el_line.lastchar - el->el_line.buffer); 620 } 621 if (el->el_history.ref == NULL) 622 return CC_ERROR; 623 624 hp = HIST_FIRST(el); 625 if (hp == NULL) 626 return CC_ERROR; 627 628 c_setpat(el); /* Set search pattern !! */ 629 630 for (h = 1; h <= el->el_history.eventno; h++) 631 hp = HIST_NEXT(el); 632 633 while (hp != NULL) { 634#ifdef SDEBUG 635 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 636#endif 637 if ((wcsncmp(hp, el->el_line.buffer, (size_t) 638 (el->el_line.lastchar - el->el_line.buffer)) || 639 hp[el->el_line.lastchar - el->el_line.buffer]) && 640 c_hmatch(el, hp)) { 641 found = 1; 642 break; 643 } 644 h++; 645 hp = HIST_NEXT(el); 646 } 647 648 if (!found) { 649#ifdef SDEBUG 650 (void) fprintf(el->el_errfile, "not found\n"); 651#endif 652 return CC_ERROR; 653 } 654 el->el_history.eventno = h; 655 656 return hist_get(el); 657} 658 659 660/* ed_search_next_history(): 661 * Search next in history for a line matching the current 662 * [M-N] [J] 663 */ 664protected el_action_t 665ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) 666{ 667 const wchar_t *hp; 668 int h; 669 int found = 0; 670 671 el->el_chared.c_vcmd.action = NOP; 672 el->el_chared.c_undo.len = -1; 673 *el->el_line.lastchar = '\0'; /* just in case */ 674 675 if (el->el_history.eventno == 0) 676 return CC_ERROR; 677 678 if (el->el_history.ref == NULL) 679 return CC_ERROR; 680 681 hp = HIST_FIRST(el); 682 if (hp == NULL) 683 return CC_ERROR; 684 685 c_setpat(el); /* Set search pattern !! */ 686 687 for (h = 1; h < el->el_history.eventno && hp; h++) { 688#ifdef SDEBUG 689 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 690#endif 691 if ((wcsncmp(hp, el->el_line.buffer, (size_t) 692 (el->el_line.lastchar - el->el_line.buffer)) || 693 hp[el->el_line.lastchar - el->el_line.buffer]) && 694 c_hmatch(el, hp)) 695 found = h; 696 hp = HIST_NEXT(el); 697 } 698 699 if (!found) { /* is it the current history number? */ 700 if (!c_hmatch(el, el->el_history.buf)) { 701#ifdef SDEBUG 702 (void) fprintf(el->el_errfile, "not found\n"); 703#endif 704 return CC_ERROR; 705 } 706 } 707 el->el_history.eventno = found; 708 709 return hist_get(el); 710} 711 712 713/* ed_prev_line(): 714 * Move up one line 715 * Could be [k] [^p] 716 */ 717protected el_action_t 718ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) 719{ 720 wchar_t *ptr; 721 int nchars = c_hpos(el); 722 723 /* 724 * Move to the line requested 725 */ 726 if (*(ptr = el->el_line.cursor) == '\n') 727 ptr--; 728 729 for (; ptr >= el->el_line.buffer; ptr--) 730 if (*ptr == '\n' && --el->el_state.argument <= 0) 731 break; 732 733 if (el->el_state.argument > 0) 734 return CC_ERROR; 735 736 /* 737 * Move to the beginning of the line 738 */ 739 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 740 continue; 741 742 /* 743 * Move to the character requested 744 */ 745 for (ptr++; 746 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 747 ptr++) 748 continue; 749 750 el->el_line.cursor = ptr; 751 return CC_CURSOR; 752} 753 754 755/* ed_next_line(): 756 * Move down one line 757 * Could be [j] [^n] 758 */ 759protected el_action_t 760ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) 761{ 762 wchar_t *ptr; 763 int nchars = c_hpos(el); 764 765 /* 766 * Move to the line requested 767 */ 768 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 769 if (*ptr == '\n' && --el->el_state.argument <= 0) 770 break; 771 772 if (el->el_state.argument > 0) 773 return CC_ERROR; 774 775 /* 776 * Move to the character requested 777 */ 778 for (ptr++; 779 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 780 ptr++) 781 continue; 782 783 el->el_line.cursor = ptr; 784 return CC_CURSOR; 785} 786 787 788/* ed_command(): 789 * Editline extended command 790 * [M-X] [:] 791 */ 792protected el_action_t 793ed_command(EditLine *el, wint_t c __attribute__((__unused__))) 794{ 795 wchar_t tmpbuf[EL_BUFSIZ]; 796 int tmplen; 797 798 tmplen = c_gets(el, tmpbuf, L"\n: "); 799 terminal__putc(el, '\n'); 800 801 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 802 terminal_beep(el); 803 804 el->el_map.current = el->el_map.key; 805 re_clear_display(el); 806 return CC_REFRESH; 807} 808