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 */ 54 protected el_action_t 55 ed_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 */ 68 protected el_action_t 69 ed_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 */ 110 protected el_action_t 111 ed_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 */ 137 protected el_action_t 138 ed_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 */ 186 protected el_action_t 187 ed_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 */ 206 protected el_action_t 207 ed_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 */ 228 protected el_action_t 229 ed_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 */ 251 protected el_action_t 252 ed_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 */ 276 protected el_action_t 277 ed_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 */ 304 protected el_action_t 305 ed_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 */ 329 protected el_action_t 330 ed_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 */ 353 protected el_action_t 354 ed_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 */ 371 protected el_action_t 372 ed_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 */ 399 protected el_action_t 400 ed_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 */ 423 protected el_action_t 424 ed_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 */ 435 protected el_action_t 436 ed_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 */ 448 protected el_action_t 449 ed_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 */ 463 protected el_action_t 464 ed_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 */ 482 protected el_action_t 483 ed_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 */ 496 protected el_action_t 497 ed_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 */ 509 protected el_action_t 510 ed_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 */ 522 protected el_action_t 523 ed_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 */ 535 protected el_action_t 536 ed_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 */ 571 protected el_action_t 572 ed_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 */ 597 protected el_action_t 598 ed_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 */ 664 protected el_action_t 665 ed_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 */ 717 protected el_action_t 718 ed_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 */ 759 protected el_action_t 760 ed_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 */ 792 protected el_action_t 793 ed_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