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