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