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