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