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