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