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