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