1 /* $OpenBSD: common.c,v 1.7 2009/10/27 23:59:28 deraadt Exp $ */ 2 /* $NetBSD: common.c,v 1.16 2003/08/07 16:44:30 agc 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 "el.h" 42 43 /* ed_end_of_file(): 44 * Indicate end of file 45 * [^D] 46 */ 47 protected el_action_t 48 /*ARGSUSED*/ 49 ed_end_of_file(EditLine *el, int c __attribute__((__unused__))) 50 { 51 52 re_goto_bottom(el); 53 *el->el_line.lastchar = '\0'; 54 return (CC_EOF); 55 } 56 57 58 /* ed_insert(): 59 * Add character to the line 60 * Insert a character [bound to all insert keys] 61 */ 62 protected el_action_t 63 ed_insert(EditLine *el, int c) 64 { 65 int count = el->el_state.argument; 66 67 if (c == '\0') 68 return (CC_ERROR); 69 70 if (el->el_line.lastchar + el->el_state.argument >= 71 el->el_line.limit) { 72 /* end of buffer space, try to allocate more */ 73 if (!ch_enlargebufs(el, (size_t) count)) 74 return CC_ERROR; /* error allocating more */ 75 } 76 77 if (count == 1) { 78 if (el->el_state.inputmode == MODE_INSERT 79 || el->el_line.cursor >= el->el_line.lastchar) 80 c_insert(el, 1); 81 82 *el->el_line.cursor++ = c; 83 re_fastaddc(el); /* fast refresh for one char. */ 84 } else { 85 if (el->el_state.inputmode != MODE_REPLACE_1) 86 c_insert(el, el->el_state.argument); 87 88 while (count-- && el->el_line.cursor < el->el_line.lastchar) 89 *el->el_line.cursor++ = c; 90 re_refresh(el); 91 } 92 93 if (el->el_state.inputmode == MODE_REPLACE_1) 94 return vi_command_mode(el, 0); 95 96 return (CC_NORM); 97 } 98 99 100 /* ed_delete_prev_word(): 101 * Delete from beginning of current word to cursor 102 * [M-^?] [^W] 103 */ 104 protected el_action_t 105 /*ARGSUSED*/ 106 ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__))) 107 { 108 char *cp, *p, *kp; 109 110 if (el->el_line.cursor == el->el_line.buffer) 111 return (CC_ERROR); 112 113 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 114 el->el_state.argument, ce__isword); 115 116 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 117 *kp++ = *p; 118 el->el_chared.c_kill.last = kp; 119 120 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */ 121 el->el_line.cursor = cp; 122 if (el->el_line.cursor < el->el_line.buffer) 123 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 124 return (CC_REFRESH); 125 } 126 127 128 /* ed_delete_next_char(): 129 * Delete character under cursor 130 * [^D] [x] 131 */ 132 protected el_action_t 133 /*ARGSUSED*/ 134 ed_delete_next_char(EditLine *el, int c __attribute__((__unused__))) 135 { 136 #ifdef notdef /* XXX */ 137 #define EL el->el_line 138 (void) fprintf(el->el_errlfile, 139 "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", 140 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 141 EL.lastchar, EL.limit, EL.limit); 142 #endif 143 if (el->el_line.cursor == el->el_line.lastchar) { 144 /* if I'm at the end */ 145 if (el->el_map.type == MAP_VI) { 146 if (el->el_line.cursor == el->el_line.buffer) { 147 /* if I'm also at the beginning */ 148 #ifdef KSHVI 149 return (CC_ERROR); 150 #else 151 term_overwrite(el, STReof, 4); 152 /* then do a EOF */ 153 term__flush(); 154 return (CC_EOF); 155 #endif 156 } else { 157 #ifdef KSHVI 158 el->el_line.cursor--; 159 #else 160 return (CC_ERROR); 161 #endif 162 } 163 } else { 164 if (el->el_line.cursor != el->el_line.buffer) 165 el->el_line.cursor--; 166 else 167 return (CC_ERROR); 168 } 169 } 170 c_delafter(el, el->el_state.argument); /* delete after dot */ 171 if (el->el_line.cursor >= el->el_line.lastchar && 172 el->el_line.cursor > el->el_line.buffer) 173 /* bounds check */ 174 el->el_line.cursor = el->el_line.lastchar - 1; 175 return (CC_REFRESH); 176 } 177 178 179 /* ed_kill_line(): 180 * Cut to the end of line 181 * [^K] [^K] 182 */ 183 protected el_action_t 184 /*ARGSUSED*/ 185 ed_kill_line(EditLine *el, int c __attribute__((__unused__))) 186 { 187 char *kp, *cp; 188 189 cp = el->el_line.cursor; 190 kp = el->el_chared.c_kill.buf; 191 while (cp < el->el_line.lastchar) 192 *kp++ = *cp++; /* copy it */ 193 el->el_chared.c_kill.last = kp; 194 /* zap! -- delete to end */ 195 el->el_line.lastchar = el->el_line.cursor; 196 return (CC_REFRESH); 197 } 198 199 200 /* ed_move_to_end(): 201 * Move cursor to the end of line 202 * [^E] [^E] 203 */ 204 protected el_action_t 205 /*ARGSUSED*/ 206 ed_move_to_end(EditLine *el, int c __attribute__((__unused__))) 207 { 208 209 el->el_line.cursor = el->el_line.lastchar; 210 if (el->el_map.type == MAP_VI) { 211 #ifdef VI_MOVE 212 el->el_line.cursor--; 213 #endif 214 if (el->el_chared.c_vcmd.action != NOP) { 215 cv_delfini(el); 216 return (CC_REFRESH); 217 } 218 } 219 return (CC_CURSOR); 220 } 221 222 223 /* ed_move_to_beg(): 224 * Move cursor to the beginning of line 225 * [^A] [^A] 226 */ 227 protected el_action_t 228 /*ARGSUSED*/ 229 ed_move_to_beg(EditLine *el, int 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 (isspace((unsigned char) *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, int 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 /*ARGSUSED*/ 278 ed_next_char(EditLine *el, int c __attribute__((__unused__))) 279 { 280 char *lim = el->el_line.lastchar; 281 282 if (el->el_line.cursor >= lim || 283 (el->el_line.cursor == lim - 1 && 284 el->el_map.type == MAP_VI && 285 el->el_chared.c_vcmd.action == NOP)) 286 return (CC_ERROR); 287 288 el->el_line.cursor += el->el_state.argument; 289 if (el->el_line.cursor > lim) 290 el->el_line.cursor = lim; 291 292 if (el->el_map.type == MAP_VI) 293 if (el->el_chared.c_vcmd.action != NOP) { 294 cv_delfini(el); 295 return (CC_REFRESH); 296 } 297 return (CC_CURSOR); 298 } 299 300 301 /* ed_prev_word(): 302 * Move to the beginning of the current word 303 * [M-b] [b] 304 */ 305 protected el_action_t 306 /*ARGSUSED*/ 307 ed_prev_word(EditLine *el, int c __attribute__((__unused__))) 308 { 309 310 if (el->el_line.cursor == el->el_line.buffer) 311 return (CC_ERROR); 312 313 el->el_line.cursor = c__prev_word(el->el_line.cursor, 314 el->el_line.buffer, 315 el->el_state.argument, 316 ce__isword); 317 318 if (el->el_map.type == MAP_VI) 319 if (el->el_chared.c_vcmd.action != NOP) { 320 cv_delfini(el); 321 return (CC_REFRESH); 322 } 323 return (CC_CURSOR); 324 } 325 326 327 /* ed_prev_char(): 328 * Move to the left one character 329 * [^B] [^B] 330 */ 331 protected el_action_t 332 /*ARGSUSED*/ 333 ed_prev_char(EditLine *el, int c __attribute__((__unused__))) 334 { 335 336 if (el->el_line.cursor > el->el_line.buffer) { 337 el->el_line.cursor -= el->el_state.argument; 338 if (el->el_line.cursor < el->el_line.buffer) 339 el->el_line.cursor = el->el_line.buffer; 340 341 if (el->el_map.type == MAP_VI) 342 if (el->el_chared.c_vcmd.action != NOP) { 343 cv_delfini(el); 344 return (CC_REFRESH); 345 } 346 return (CC_CURSOR); 347 } else 348 return (CC_ERROR); 349 } 350 351 352 /* ed_quoted_insert(): 353 * Add the next character typed verbatim 354 * [^V] [^V] 355 */ 356 protected el_action_t 357 ed_quoted_insert(EditLine *el, int c) 358 { 359 int num; 360 char tc; 361 362 tty_quotemode(el); 363 num = el_getc(el, &tc); 364 c = (unsigned char) tc; 365 tty_noquotemode(el); 366 if (num == 1) 367 return (ed_insert(el, c)); 368 else 369 return (ed_end_of_file(el, 0)); 370 } 371 372 373 /* ed_digit(): 374 * Adds to argument or enters a digit 375 */ 376 protected el_action_t 377 ed_digit(EditLine *el, int c) 378 { 379 380 if (!isdigit(c)) 381 return (CC_ERROR); 382 383 if (el->el_state.doingarg) { 384 /* if doing an arg, add this in... */ 385 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 386 el->el_state.argument = c - '0'; 387 else { 388 if (el->el_state.argument > 1000000) 389 return (CC_ERROR); 390 el->el_state.argument = 391 (el->el_state.argument * 10) + (c - '0'); 392 } 393 return (CC_ARGHACK); 394 } 395 396 return ed_insert(el, c); 397 } 398 399 400 /* ed_argument_digit(): 401 * Digit that starts argument 402 * For ESC-n 403 */ 404 protected el_action_t 405 ed_argument_digit(EditLine *el, int c) 406 { 407 408 if (!isdigit(c)) 409 return (CC_ERROR); 410 411 if (el->el_state.doingarg) { 412 if (el->el_state.argument > 1000000) 413 return (CC_ERROR); 414 el->el_state.argument = (el->el_state.argument * 10) + 415 (c - '0'); 416 } else { /* else starting an argument */ 417 el->el_state.argument = c - '0'; 418 el->el_state.doingarg = 1; 419 } 420 return (CC_ARGHACK); 421 } 422 423 424 /* ed_unassigned(): 425 * Indicates unbound character 426 * Bound to keys that are not assigned 427 */ 428 protected el_action_t 429 /*ARGSUSED*/ 430 ed_unassigned(EditLine *el, int c __attribute__((__unused__))) 431 { 432 433 return (CC_ERROR); 434 } 435 436 437 /** 438 ** TTY key handling. 439 **/ 440 441 /* ed_tty_sigint(): 442 * Tty interrupt character 443 * [^C] 444 */ 445 protected el_action_t 446 /*ARGSUSED*/ 447 ed_tty_sigint(EditLine *el __attribute__((__unused__)), 448 int c __attribute__((__unused__))) 449 { 450 451 return (CC_NORM); 452 } 453 454 455 /* ed_tty_dsusp(): 456 * Tty delayed suspend character 457 * [^Y] 458 */ 459 protected el_action_t 460 /*ARGSUSED*/ 461 ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 462 int c __attribute__((__unused__))) 463 { 464 465 return (CC_NORM); 466 } 467 468 469 /* ed_tty_flush_output(): 470 * Tty flush output characters 471 * [^O] 472 */ 473 protected el_action_t 474 /*ARGSUSED*/ 475 ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 476 int c __attribute__((__unused__))) 477 { 478 479 return (CC_NORM); 480 } 481 482 483 /* ed_tty_sigquit(): 484 * Tty quit character 485 * [^\] 486 */ 487 protected el_action_t 488 /*ARGSUSED*/ 489 ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 490 int c __attribute__((__unused__))) 491 { 492 493 return (CC_NORM); 494 } 495 496 497 /* ed_tty_sigtstp(): 498 * Tty suspend character 499 * [^Z] 500 */ 501 protected el_action_t 502 /*ARGSUSED*/ 503 ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 504 int c __attribute__((__unused__))) 505 { 506 507 return (CC_NORM); 508 } 509 510 511 /* ed_tty_stop_output(): 512 * Tty disallow output characters 513 * [^S] 514 */ 515 protected el_action_t 516 /*ARGSUSED*/ 517 ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 518 int c __attribute__((__unused__))) 519 { 520 521 return (CC_NORM); 522 } 523 524 525 /* ed_tty_start_output(): 526 * Tty allow output characters 527 * [^Q] 528 */ 529 protected el_action_t 530 /*ARGSUSED*/ 531 ed_tty_start_output(EditLine *el __attribute__((__unused__)), 532 int c __attribute__((__unused__))) 533 { 534 535 return (CC_NORM); 536 } 537 538 539 /* ed_newline(): 540 * Execute command 541 * [^J] 542 */ 543 protected el_action_t 544 /*ARGSUSED*/ 545 ed_newline(EditLine *el, int c __attribute__((__unused__))) 546 { 547 548 re_goto_bottom(el); 549 *el->el_line.lastchar++ = '\n'; 550 *el->el_line.lastchar = '\0'; 551 return (CC_NEWLINE); 552 } 553 554 555 /* ed_delete_prev_char(): 556 * Delete the character to the left of the cursor 557 * [^?] 558 */ 559 protected el_action_t 560 /*ARGSUSED*/ 561 ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) 562 { 563 564 if (el->el_line.cursor <= el->el_line.buffer) 565 return (CC_ERROR); 566 567 c_delbefore(el, el->el_state.argument); 568 el->el_line.cursor -= el->el_state.argument; 569 if (el->el_line.cursor < el->el_line.buffer) 570 el->el_line.cursor = el->el_line.buffer; 571 return (CC_REFRESH); 572 } 573 574 575 /* ed_clear_screen(): 576 * Clear screen leaving current line at the top 577 * [^L] 578 */ 579 protected el_action_t 580 /*ARGSUSED*/ 581 ed_clear_screen(EditLine *el, int c __attribute__((__unused__))) 582 { 583 584 term_clear_screen(el); /* clear the whole real screen */ 585 re_clear_display(el); /* reset everything */ 586 return (CC_REFRESH); 587 } 588 589 590 /* ed_redisplay(): 591 * Redisplay everything 592 * ^R 593 */ 594 protected el_action_t 595 /*ARGSUSED*/ 596 ed_redisplay(EditLine *el __attribute__((__unused__)), 597 int c __attribute__((__unused__))) 598 { 599 600 return (CC_REDISPLAY); 601 } 602 603 604 /* ed_start_over(): 605 * Erase current line and start from scratch 606 * [^G] 607 */ 608 protected el_action_t 609 /*ARGSUSED*/ 610 ed_start_over(EditLine *el, int c __attribute__((__unused__))) 611 { 612 613 ch_reset(el); 614 return (CC_REFRESH); 615 } 616 617 618 /* ed_sequence_lead_in(): 619 * First character in a bound sequence 620 * Placeholder for external keys 621 */ 622 protected el_action_t 623 /*ARGSUSED*/ 624 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 625 int c __attribute__((__unused__))) 626 { 627 628 return (CC_NORM); 629 } 630 631 632 /* ed_prev_history(): 633 * Move to the previous history line 634 * [^P] [k] 635 */ 636 protected el_action_t 637 /*ARGSUSED*/ 638 ed_prev_history(EditLine *el, int c __attribute__((__unused__))) 639 { 640 char beep = 0; 641 int sv_event = el->el_history.eventno; 642 643 el->el_chared.c_undo.len = -1; 644 *el->el_line.lastchar = '\0'; /* just in case */ 645 646 if (el->el_history.eventno == 0) { /* save the current buffer 647 * away */ 648 (void) strncpy(el->el_history.buf, el->el_line.buffer, 649 EL_BUFSIZ); 650 el->el_history.last = el->el_history.buf + 651 (el->el_line.lastchar - el->el_line.buffer); 652 } 653 el->el_history.eventno += el->el_state.argument; 654 655 if (hist_get(el) == CC_ERROR) { 656 if (el->el_map.type == MAP_VI) { 657 el->el_history.eventno = sv_event; 658 return CC_ERROR; 659 } 660 beep = 1; 661 /* el->el_history.eventno was fixed by first call */ 662 (void) hist_get(el); 663 } 664 if (beep) 665 return CC_REFRESH_BEEP; 666 return CC_REFRESH; 667 } 668 669 670 /* ed_next_history(): 671 * Move to the next history line 672 * [^N] [j] 673 */ 674 protected el_action_t 675 /*ARGSUSED*/ 676 ed_next_history(EditLine *el, int c __attribute__((__unused__))) 677 { 678 el_action_t beep = CC_REFRESH, rval; 679 680 el->el_chared.c_undo.len = -1; 681 *el->el_line.lastchar = '\0'; /* just in case */ 682 683 el->el_history.eventno -= el->el_state.argument; 684 685 if (el->el_history.eventno < 0) { 686 el->el_history.eventno = 0; 687 beep = CC_REFRESH_BEEP; 688 } 689 rval = hist_get(el); 690 if (rval == CC_REFRESH) 691 return beep; 692 return rval; 693 694 } 695 696 697 /* ed_search_prev_history(): 698 * Search previous in history for a line matching the current 699 * next search history [M-P] [K] 700 */ 701 protected el_action_t 702 /*ARGSUSED*/ 703 ed_search_prev_history(EditLine *el, int c __attribute__((__unused__))) 704 { 705 const char *hp; 706 int h; 707 bool_t found = 0; 708 709 el->el_chared.c_vcmd.action = NOP; 710 el->el_chared.c_undo.len = -1; 711 *el->el_line.lastchar = '\0'; /* just in case */ 712 if (el->el_history.eventno < 0) { 713 #ifdef DEBUG_EDIT 714 (void) fprintf(el->el_errfile, 715 "e_prev_search_hist(): eventno < 0;\n"); 716 #endif 717 el->el_history.eventno = 0; 718 return (CC_ERROR); 719 } 720 if (el->el_history.eventno == 0) { 721 (void) strncpy(el->el_history.buf, el->el_line.buffer, 722 EL_BUFSIZ); 723 el->el_history.last = el->el_history.buf + 724 (el->el_line.lastchar - el->el_line.buffer); 725 } 726 if (el->el_history.ref == NULL) 727 return (CC_ERROR); 728 729 hp = HIST_FIRST(el); 730 if (hp == NULL) 731 return (CC_ERROR); 732 733 c_setpat(el); /* Set search pattern !! */ 734 735 for (h = 1; h <= el->el_history.eventno; h++) 736 hp = HIST_NEXT(el); 737 738 while (hp != NULL) { 739 #ifdef SDEBUG 740 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 741 #endif 742 if ((strncmp(hp, el->el_line.buffer, (size_t) 743 (el->el_line.lastchar - el->el_line.buffer)) || 744 hp[el->el_line.lastchar - el->el_line.buffer]) && 745 c_hmatch(el, hp)) { 746 found++; 747 break; 748 } 749 h++; 750 hp = HIST_NEXT(el); 751 } 752 753 if (!found) { 754 #ifdef SDEBUG 755 (void) fprintf(el->el_errfile, "not found\n"); 756 #endif 757 return (CC_ERROR); 758 } 759 el->el_history.eventno = h; 760 761 return (hist_get(el)); 762 } 763 764 765 /* ed_search_next_history(): 766 * Search next in history for a line matching the current 767 * [M-N] [J] 768 */ 769 protected el_action_t 770 /*ARGSUSED*/ 771 ed_search_next_history(EditLine *el, int c __attribute__((__unused__))) 772 { 773 const char *hp; 774 int h; 775 bool_t found = 0; 776 777 el->el_chared.c_vcmd.action = NOP; 778 el->el_chared.c_undo.len = -1; 779 *el->el_line.lastchar = '\0'; /* just in case */ 780 781 if (el->el_history.eventno == 0) 782 return (CC_ERROR); 783 784 if (el->el_history.ref == NULL) 785 return (CC_ERROR); 786 787 hp = HIST_FIRST(el); 788 if (hp == NULL) 789 return (CC_ERROR); 790 791 c_setpat(el); /* Set search pattern !! */ 792 793 for (h = 1; h < el->el_history.eventno && hp; h++) { 794 #ifdef SDEBUG 795 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 796 #endif 797 if ((strncmp(hp, el->el_line.buffer, (size_t) 798 (el->el_line.lastchar - el->el_line.buffer)) || 799 hp[el->el_line.lastchar - el->el_line.buffer]) && 800 c_hmatch(el, hp)) 801 found = h; 802 hp = HIST_NEXT(el); 803 } 804 805 if (!found) { /* is it the current history number? */ 806 if (!c_hmatch(el, el->el_history.buf)) { 807 #ifdef SDEBUG 808 (void) fprintf(el->el_errfile, "not found\n"); 809 #endif 810 return (CC_ERROR); 811 } 812 } 813 el->el_history.eventno = found; 814 815 return (hist_get(el)); 816 } 817 818 819 /* ed_prev_line(): 820 * Move up one line 821 * Could be [k] [^p] 822 */ 823 protected el_action_t 824 /*ARGSUSED*/ 825 ed_prev_line(EditLine *el, int c __attribute__((__unused__))) 826 { 827 char *ptr; 828 int nchars = c_hpos(el); 829 830 /* 831 * Move to the line requested 832 */ 833 if (*(ptr = el->el_line.cursor) == '\n') 834 ptr--; 835 836 for (; ptr >= el->el_line.buffer; ptr--) 837 if (*ptr == '\n' && --el->el_state.argument <= 0) 838 break; 839 840 if (el->el_state.argument > 0) 841 return (CC_ERROR); 842 843 /* 844 * Move to the beginning of the line 845 */ 846 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 847 continue; 848 849 /* 850 * Move to the character requested 851 */ 852 for (ptr++; 853 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 854 ptr++) 855 continue; 856 857 el->el_line.cursor = ptr; 858 return (CC_CURSOR); 859 } 860 861 862 /* ed_next_line(): 863 * Move down one line 864 * Could be [j] [^n] 865 */ 866 protected el_action_t 867 /*ARGSUSED*/ 868 ed_next_line(EditLine *el, int c __attribute__((__unused__))) 869 { 870 char *ptr; 871 int nchars = c_hpos(el); 872 873 /* 874 * Move to the line requested 875 */ 876 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 877 if (*ptr == '\n' && --el->el_state.argument <= 0) 878 break; 879 880 if (el->el_state.argument > 0) 881 return (CC_ERROR); 882 883 /* 884 * Move to the character requested 885 */ 886 for (ptr++; 887 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 888 ptr++) 889 continue; 890 891 el->el_line.cursor = ptr; 892 return (CC_CURSOR); 893 } 894 895 896 /* ed_command(): 897 * Editline extended command 898 * [M-X] [:] 899 */ 900 protected el_action_t 901 /*ARGSUSED*/ 902 ed_command(EditLine *el, int c __attribute__((__unused__))) 903 { 904 char tmpbuf[EL_BUFSIZ]; 905 int tmplen; 906 907 tmplen = c_gets(el, tmpbuf, "\n: "); 908 term__putc('\n'); 909 910 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 911 term_beep(el); 912 913 el->el_map.current = el->el_map.key; 914 re_clear_display(el); 915 return CC_REFRESH; 916 } 917