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