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