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