1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if !defined(lint) && !defined(SCCSID) 38 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; 39 #endif /* not lint && not SCCSID */ 40 41 /* 42 * vi.c: Vi mode commands. 43 */ 44 #include "sys.h" 45 #include "el.h" 46 47 private el_action_t cv_action __P((EditLine *, int)); 48 49 /* cv_action(): 50 * Handle vi actions. 51 */ 52 private el_action_t 53 cv_action(el, c) 54 EditLine *el; 55 int c; 56 { 57 register char *cp, *kp; 58 59 if (el->el_chared.c_vcmd.action & DELETE) { 60 el->el_chared.c_vcmd.action = NOP; 61 el->el_chared.c_vcmd.pos = 0; 62 63 el->el_chared.c_undo.isize = 0; 64 el->el_chared.c_undo.dsize = 0; 65 kp = el->el_chared.c_undo.buf; 66 for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) { 67 *kp++ = *cp; 68 el->el_chared.c_undo.dsize++; 69 } 70 71 el->el_chared.c_undo.action = INSERT; 72 el->el_chared.c_undo.ptr = el->el_line.buffer; 73 el->el_line.lastchar = el->el_line.buffer; 74 el->el_line.cursor = el->el_line.buffer; 75 if (c & INSERT) 76 el->el_map.current = el->el_map.key; 77 78 return CC_REFRESH; 79 } 80 81 el->el_chared.c_vcmd.pos = el->el_line.cursor; 82 el->el_chared.c_vcmd.action = c; 83 return CC_ARGHACK; 84 85 #ifdef notdef 86 /* 87 * I don't think that this is needed. But we keep it for now 88 */ 89 else if (el_chared.c_vcmd.action == NOP) { 90 el->el_chared.c_vcmd.pos = el->el_line.cursor; 91 el->el_chared.c_vcmd.action = c; 92 return CC_ARGHACK; 93 } 94 else { 95 el->el_chared.c_vcmd.action = 0; 96 el->el_chared.c_vcmd.pos = 0; 97 return CC_ERROR; 98 } 99 #endif 100 } 101 102 103 /* cv_paste(): 104 * Paste previous deletion before or after the cursor 105 */ 106 protected el_action_t 107 cv_paste(el, c) 108 EditLine *el; 109 int c; 110 { 111 char *ptr; 112 c_undo_t *un = &el->el_chared.c_undo; 113 #ifdef DEBUG_PASTE 114 (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n", 115 un->action, un->buf, un->isize, un->dsize); 116 #endif 117 if (un->isize == 0) 118 return CC_ERROR; 119 120 if (!c && el->el_line.cursor < el->el_line.lastchar) 121 el->el_line.cursor++; 122 ptr = el->el_line.cursor; 123 124 c_insert(el, un->isize); 125 if (el->el_line.cursor + un->isize > el->el_line.lastchar) 126 return CC_ERROR; 127 (void) memcpy(ptr, un->buf, un->isize); 128 return CC_REFRESH; 129 } 130 131 132 /* vi_paste_next(): 133 * Vi paste previous deletion to the right of the cursor 134 * [p] 135 */ 136 protected el_action_t 137 /*ARGSUSED*/ 138 vi_paste_next(el, c) 139 EditLine *el; 140 int c; 141 { 142 return cv_paste(el, 0); 143 } 144 145 146 /* vi_paste_prev(): 147 * Vi paste previous deletion to the left of the cursor 148 * [P] 149 */ 150 protected el_action_t 151 /*ARGSUSED*/ 152 vi_paste_prev(el, c) 153 EditLine *el; 154 int c; 155 { 156 return cv_paste(el, 1); 157 } 158 159 160 /* vi_prev_space_word(): 161 * Vi move to the previous space delimited word 162 * [B] 163 */ 164 protected el_action_t 165 /*ARGSUSED*/ 166 vi_prev_space_word(el, c) 167 EditLine *el; 168 int c; 169 { 170 if (el->el_line.cursor == el->el_line.buffer) 171 return CC_ERROR; 172 173 el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, 174 el->el_line.buffer, 175 el->el_state.argument, 176 cv__isword); 177 178 if (el->el_chared.c_vcmd.action & DELETE) { 179 cv_delfini(el); 180 return CC_REFRESH; 181 } 182 183 return CC_CURSOR; 184 } 185 186 187 /* vi_prev_word(): 188 * Vi move to the previous word 189 * [B] 190 */ 191 protected el_action_t 192 /*ARGSUSED*/ 193 vi_prev_word(el, c) 194 EditLine *el; 195 int c; 196 { 197 if (el->el_line.cursor == el->el_line.buffer) 198 return CC_ERROR; 199 200 el->el_line.cursor = cv_prev_word(el, el->el_line.cursor, 201 el->el_line.buffer, 202 el->el_state.argument, 203 ce__isword); 204 205 if (el->el_chared.c_vcmd.action & DELETE) { 206 cv_delfini(el); 207 return CC_REFRESH; 208 } 209 210 return CC_CURSOR; 211 } 212 213 214 /* vi_next_space_word(): 215 * Vi move to the next space delimited word 216 * [W] 217 */ 218 protected el_action_t 219 /*ARGSUSED*/ 220 vi_next_space_word(el, c) 221 EditLine *el; 222 int c; 223 { 224 if (el->el_line.cursor == el->el_line.lastchar) 225 return CC_ERROR; 226 227 el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 228 el->el_line.lastchar, 229 el->el_state.argument, 230 cv__isword); 231 232 if (el->el_map.type == MAP_VI) 233 if (el->el_chared.c_vcmd.action & DELETE) { 234 cv_delfini(el); 235 return CC_REFRESH; 236 } 237 238 return CC_CURSOR; 239 } 240 241 /* vi_next_word(): 242 * Vi move to the next word 243 * [w] 244 */ 245 protected el_action_t 246 /*ARGSUSED*/ 247 vi_next_word(el, c) 248 EditLine *el; 249 int c; 250 { 251 if (el->el_line.cursor == el->el_line.lastchar) 252 return CC_ERROR; 253 254 el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 255 el->el_line.lastchar, 256 el->el_state.argument, 257 ce__isword); 258 259 if (el->el_map.type == MAP_VI) 260 if (el->el_chared.c_vcmd.action & DELETE) { 261 cv_delfini(el); 262 return CC_REFRESH; 263 } 264 265 return CC_CURSOR; 266 } 267 268 269 270 /* vi_change_case(): 271 * Vi change case of character under the cursor and advance one character 272 * [~] 273 */ 274 protected el_action_t 275 vi_change_case(el, c) 276 EditLine *el; 277 int c; 278 { 279 if (el->el_line.cursor < el->el_line.lastchar) { 280 c = *el->el_line.cursor; 281 if (isupper(c)) 282 *el->el_line.cursor++ = tolower(c); 283 else if (islower(c)) 284 *el->el_line.cursor++ = toupper(c); 285 else 286 el->el_line.cursor++; 287 re_fastaddc(el); 288 return CC_NORM; 289 } 290 return CC_ERROR; 291 } 292 293 294 /* vi_change_meta(): 295 * Vi change prefix command 296 * [c] 297 */ 298 protected el_action_t 299 /*ARGSUSED*/ 300 vi_change_meta(el, c) 301 EditLine *el; 302 int c; 303 { 304 /* 305 * Delete with insert == change: first we delete and then we leave in 306 * insert mode. 307 */ 308 return cv_action(el, DELETE|INSERT); 309 } 310 311 312 /* vi_insert_at_bol(): 313 * Vi enter insert mode at the beginning of line 314 * [I] 315 */ 316 protected el_action_t 317 /*ARGSUSED*/ 318 vi_insert_at_bol(el, c) 319 EditLine *el; 320 int c; 321 { 322 el->el_line.cursor = el->el_line.buffer; 323 el->el_chared.c_vcmd.ins = el->el_line.cursor; 324 325 el->el_chared.c_undo.ptr = el->el_line.cursor; 326 el->el_chared.c_undo.action = DELETE; 327 328 el->el_map.current = el->el_map.key; 329 return CC_CURSOR; 330 } 331 332 333 /* vi_replace_char(): 334 * Vi replace character under the cursor with the next character typed 335 * [r] 336 */ 337 protected el_action_t 338 /*ARGSUSED*/ 339 vi_replace_char(el, c) 340 EditLine *el; 341 int c; 342 { 343 el->el_map.current = el->el_map.key; 344 el->el_state.inputmode = MODE_REPLACE_1; 345 el->el_chared.c_undo.action = CHANGE; 346 el->el_chared.c_undo.ptr = el->el_line.cursor; 347 el->el_chared.c_undo.isize = 0; 348 el->el_chared.c_undo.dsize = 0; 349 return CC_NORM; 350 } 351 352 353 /* vi_replace_mode(): 354 * Vi enter replace mode 355 * [R] 356 */ 357 protected el_action_t 358 /*ARGSUSED*/ 359 vi_replace_mode(el, c) 360 EditLine *el; 361 int c; 362 { 363 el->el_map.current = el->el_map.key; 364 el->el_state.inputmode = MODE_REPLACE; 365 el->el_chared.c_undo.action = CHANGE; 366 el->el_chared.c_undo.ptr = el->el_line.cursor; 367 el->el_chared.c_undo.isize = 0; 368 el->el_chared.c_undo.dsize = 0; 369 return CC_NORM; 370 } 371 372 373 /* vi_substitute_char(): 374 * Vi replace character under the cursor and enter insert mode 375 * [r] 376 */ 377 protected el_action_t 378 /*ARGSUSED*/ 379 vi_substitute_char(el, c) 380 EditLine *el; 381 int c; 382 { 383 c_delafter(el, el->el_state.argument); 384 el->el_map.current = el->el_map.key; 385 return CC_REFRESH; 386 } 387 388 389 /* vi_substitute_line(): 390 * Vi substitute entire line 391 * [S] 392 */ 393 protected el_action_t 394 /*ARGSUSED*/ 395 vi_substitute_line(el, c) 396 EditLine *el; 397 int c; 398 { 399 (void) em_kill_line(el, 0); 400 el->el_map.current = el->el_map.key; 401 return CC_REFRESH; 402 } 403 404 405 /* vi_change_to_eol(): 406 * Vi change to end of line 407 * [C] 408 */ 409 protected el_action_t 410 /*ARGSUSED*/ 411 vi_change_to_eol(el, c) 412 EditLine *el; 413 int c; 414 { 415 (void) ed_kill_line(el, 0); 416 el->el_map.current = el->el_map.key; 417 return CC_REFRESH; 418 } 419 420 421 /* vi_insert(): 422 * Vi enter insert mode 423 * [i] 424 */ 425 protected el_action_t 426 /*ARGSUSED*/ 427 vi_insert(el, c) 428 EditLine *el; 429 int c; 430 { 431 el->el_map.current = el->el_map.key; 432 433 el->el_chared.c_vcmd.ins = el->el_line.cursor; 434 el->el_chared.c_undo.ptr = el->el_line.cursor; 435 el->el_chared.c_undo.action = DELETE; 436 437 return CC_NORM; 438 } 439 440 441 /* vi_add(): 442 * Vi enter insert mode after the cursor 443 * [a] 444 */ 445 protected el_action_t 446 /*ARGSUSED*/ 447 vi_add(el, c) 448 EditLine *el; 449 int c; 450 { 451 int ret; 452 el->el_map.current = el->el_map.key; 453 if (el->el_line.cursor < el->el_line.lastchar) { 454 el->el_line.cursor++; 455 if (el->el_line.cursor > el->el_line.lastchar) 456 el->el_line.cursor = el->el_line.lastchar; 457 ret = CC_CURSOR; 458 } 459 else 460 ret = CC_NORM; 461 462 el->el_chared.c_vcmd.ins = el->el_line.cursor; 463 el->el_chared.c_undo.ptr = el->el_line.cursor; 464 el->el_chared.c_undo.action = DELETE; 465 466 return ret; 467 } 468 469 470 /* vi_add_at_eol(): 471 * Vi enter insert mode at end of line 472 * [A] 473 */ 474 protected el_action_t 475 /*ARGSUSED*/ 476 vi_add_at_eol(el, c) 477 EditLine *el; 478 int c; 479 { 480 el->el_map.current = el->el_map.key; 481 el->el_line.cursor = el->el_line.lastchar; 482 483 /* Mark where insertion begins */ 484 el->el_chared.c_vcmd.ins = el->el_line.lastchar; 485 el->el_chared.c_undo.ptr = el->el_line.lastchar; 486 el->el_chared.c_undo.action = DELETE; 487 return CC_CURSOR; 488 } 489 490 491 /* vi_delete_meta(): 492 * Vi delete prefix command 493 * [d] 494 */ 495 protected el_action_t 496 /*ARGSUSED*/ 497 vi_delete_meta(el, c) 498 EditLine *el; 499 int c; 500 { 501 return cv_action(el, DELETE); 502 } 503 504 505 /* vi_end_word(): 506 * Vi move to the end of the current space delimited word 507 * [E] 508 */ 509 protected el_action_t 510 /*ARGSUSED*/ 511 vi_end_word(el, c) 512 EditLine *el; 513 int c; 514 { 515 if (el->el_line.cursor == el->el_line.lastchar) 516 return CC_ERROR; 517 518 el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, 519 el->el_state.argument); 520 521 if (el->el_chared.c_vcmd.action & DELETE) { 522 el->el_line.cursor++; 523 cv_delfini(el); 524 return CC_REFRESH; 525 } 526 527 return CC_CURSOR; 528 } 529 530 531 /* vi_to_end_word(): 532 * Vi move to the end of the current word 533 * [e] 534 */ 535 protected el_action_t 536 /*ARGSUSED*/ 537 vi_to_end_word(el, c) 538 EditLine *el; 539 int c; 540 { 541 if (el->el_line.cursor == el->el_line.lastchar) 542 return CC_ERROR; 543 544 el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, 545 el->el_state.argument); 546 547 if (el->el_chared.c_vcmd.action & DELETE) { 548 el->el_line.cursor++; 549 cv_delfini(el); 550 return CC_REFRESH; 551 } 552 553 return CC_CURSOR; 554 } 555 556 557 /* vi_undo(): 558 * Vi undo last change 559 * [u] 560 */ 561 protected el_action_t 562 /*ARGSUSED*/ 563 vi_undo(el, c) 564 EditLine *el; 565 int c; 566 { 567 char *cp, *kp; 568 char temp; 569 int i, size; 570 c_undo_t *un = &el->el_chared.c_undo; 571 572 #ifdef DEBUG_UNDO 573 (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n", 574 un->action, un->buf, un->isize, un->dsize); 575 #endif 576 switch (un->action) { 577 case DELETE: 578 if (un->dsize == 0) 579 return CC_NORM; 580 581 (void) memcpy(un->buf, un->ptr, un->dsize); 582 for (cp = un->ptr; cp <= el->el_line.lastchar; cp++) 583 *cp = cp[un->dsize]; 584 585 el->el_line.lastchar -= un->dsize; 586 el->el_line.cursor = un->ptr; 587 588 un->action = INSERT; 589 un->isize = un->dsize; 590 un->dsize = 0; 591 break; 592 593 case DELETE|INSERT: 594 size = un->isize - un->dsize; 595 if (size > 0) 596 i = un->dsize; 597 else 598 i = un->isize; 599 cp = un->ptr; 600 kp = un->buf; 601 while (i-- > 0) { 602 temp = *kp; 603 *kp++ = *cp; 604 *cp++ = temp; 605 } 606 if (size > 0) { 607 el->el_line.cursor = cp; 608 c_insert(el, size); 609 while (size-- > 0 && cp < el->el_line.lastchar) { 610 temp = *kp; 611 *kp++ = *cp; 612 *cp++ = temp; 613 } 614 } 615 else if (size < 0) { 616 size = -size; 617 for (; cp <= el->el_line.lastchar; cp++) { 618 *kp++ = *cp; 619 *cp = cp[size]; 620 } 621 el->el_line.lastchar -= size; 622 } 623 el->el_line.cursor = un->ptr; 624 i = un->dsize; 625 un->dsize = un->isize; 626 un->isize = i; 627 break; 628 629 case INSERT: 630 if (un->isize == 0) 631 return CC_NORM; 632 633 el->el_line.cursor = un->ptr; 634 c_insert(el, un->isize); 635 memcpy(un->ptr, un->buf, un->isize); 636 un->action = DELETE; 637 un->dsize = un->isize; 638 un->isize = 0; 639 break; 640 641 case CHANGE: 642 if (un->isize == 0) 643 return CC_NORM; 644 645 el->el_line.cursor = un->ptr; 646 size = (int) (el->el_line.cursor - el->el_line.lastchar); 647 if (size < un->isize) 648 size = un->isize; 649 cp = un->ptr; 650 kp = un->buf; 651 for(i = 0; i < size; i++) { 652 temp = *kp; 653 *kp++ = *cp; 654 *cp++ = temp; 655 } 656 un->dsize = 0; 657 break; 658 659 default: 660 return CC_ERROR; 661 } 662 663 return CC_REFRESH; 664 } 665 666 667 /* vi_command_mode(): 668 * Vi enter command mode (use alternative key bindings) 669 * [<ESC>] 670 */ 671 protected el_action_t 672 /*ARGSUSED*/ 673 vi_command_mode(el, c) 674 EditLine *el; 675 int c; 676 { 677 int size; 678 /* [Esc] cancels pending action */ 679 el->el_chared.c_vcmd.ins = 0; 680 el->el_chared.c_vcmd.action = NOP; 681 el->el_chared.c_vcmd.pos = 0; 682 683 el->el_state.doingarg = 0; 684 size = el->el_chared.c_undo.ptr - el->el_line.cursor; 685 if (size < 0) 686 size = -size; 687 if (el->el_chared.c_undo.action == (INSERT|DELETE) || 688 el->el_chared.c_undo.action == DELETE) 689 el->el_chared.c_undo.dsize = size; 690 else 691 el->el_chared.c_undo.isize = size; 692 693 el->el_state.inputmode = MODE_INSERT; 694 el->el_map.current = el->el_map.alt; 695 #ifdef VI_MOVE 696 if (el->el_line.cursor > el->el_line.buffer) 697 el->el_line.cursor--; 698 #endif 699 return CC_CURSOR; 700 } 701 702 /* vi_zero(): 703 * Vi move to the beginning of line 704 * [0] 705 */ 706 protected el_action_t 707 vi_zero(el, c) 708 EditLine *el; 709 int c; 710 { 711 if (el->el_state.doingarg) { 712 if (el->el_state.argument > 1000000) 713 return CC_ERROR; 714 el->el_state.argument = 715 (el->el_state.argument * 10) + (c - '0'); 716 return CC_ARGHACK; 717 } 718 else { 719 el->el_line.cursor = el->el_line.buffer; 720 if (el->el_chared.c_vcmd.action & DELETE) { 721 cv_delfini(el); 722 return CC_REFRESH; 723 } 724 return CC_CURSOR; 725 } 726 } 727 728 729 /* vi_delete_prev_char(): 730 * Vi move to previous character (backspace) 731 * [^H] 732 */ 733 protected el_action_t 734 /*ARGSUSED*/ 735 vi_delete_prev_char(el, c) 736 EditLine *el; 737 int c; 738 { 739 if (el->el_chared.c_vcmd.ins == 0) 740 return CC_ERROR; 741 742 if (el->el_chared.c_vcmd.ins > 743 el->el_line.cursor - el->el_state.argument) 744 return CC_ERROR; 745 746 c_delbefore(el, el->el_state.argument); 747 el->el_line.cursor -= el->el_state.argument; 748 749 return CC_REFRESH; 750 } /* end v_del_char_prev */ 751 752 753 /* vi_list_or_eof(): 754 * Vi list choices for completion or indicate end of file if empty line 755 * [^D] 756 */ 757 protected el_action_t 758 /*ARGSUSED*/ 759 vi_list_or_eof(el, c) 760 EditLine *el; 761 int c; 762 { 763 #ifdef notyet 764 if (el->el_line.cursor == el->el_line.lastchar && 765 el->el_line.cursor == el->el_line.buffer) { 766 #endif 767 term_overwrite(el, STReof, 4); /* then do a EOF */ 768 term__flush(); 769 return CC_EOF; 770 #ifdef notyet 771 } 772 else { 773 re_goto_bottom(el); 774 *el->el_line.lastchar = '\0'; /* just in case */ 775 return CC_LIST_CHOICES; 776 } 777 #endif 778 } 779 780 781 /* vi_kill_line_prev(): 782 * Vi cut from beginning of line to cursor 783 * [^U] 784 */ 785 protected el_action_t 786 /*ARGSUSED*/ 787 vi_kill_line_prev(el, c) 788 EditLine *el; 789 int c; 790 { 791 char *kp, *cp; 792 793 cp = el->el_line.buffer; 794 kp = el->el_chared.c_kill.buf; 795 while (cp < el->el_line.cursor) 796 *kp++ = *cp++; /* copy it */ 797 el->el_chared.c_kill.last = kp; 798 c_delbefore(el, el->el_line.cursor - el->el_line.buffer); 799 el->el_line.cursor = el->el_line.buffer; /* zap! */ 800 return CC_REFRESH; 801 } 802 803 804 /* vi_search_prev(): 805 * Vi search history previous 806 * [?] 807 */ 808 protected el_action_t 809 /*ARGSUSED*/ 810 vi_search_prev(el, c) 811 EditLine *el; 812 int c; 813 { 814 return cv_search(el, ED_SEARCH_PREV_HISTORY); 815 } 816 817 818 /* vi_search_next(): 819 * Vi search history next 820 * [/] 821 */ 822 protected el_action_t 823 /*ARGSUSED*/ 824 vi_search_next(el, c) 825 EditLine *el; 826 int c; 827 { 828 return cv_search(el, ED_SEARCH_NEXT_HISTORY); 829 } 830 831 832 /* vi_repeat_search_next(): 833 * Vi repeat current search in the same search direction 834 * [n] 835 */ 836 protected el_action_t 837 /*ARGSUSED*/ 838 vi_repeat_search_next(el, c) 839 EditLine *el; 840 int c; 841 { 842 if (el->el_search.patlen == 0) 843 return CC_ERROR; 844 else 845 return cv_repeat_srch(el, el->el_search.patdir); 846 } 847 848 849 /* vi_repeat_search_prev(): 850 * Vi repeat current search in the opposite search direction 851 * [N] 852 */ 853 /*ARGSUSED*/ 854 protected el_action_t 855 vi_repeat_search_prev(el, c) 856 EditLine *el; 857 int c; 858 { 859 if (el->el_search.patlen == 0) 860 return CC_ERROR; 861 else 862 return cv_repeat_srch(el, 863 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? 864 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY); 865 } 866 867 868 /* vi_next_char(): 869 * Vi move to the character specified next 870 * [f] 871 */ 872 protected el_action_t 873 /*ARGSUSED*/ 874 vi_next_char(el, c) 875 EditLine *el; 876 int c; 877 { 878 char ch; 879 880 if (el_getc(el, &ch) != 1) 881 return ed_end_of_file(el, 0); 882 883 el->el_search.chadir = CHAR_FWD; 884 el->el_search.chacha = ch; 885 886 return cv_csearch_fwd(el, ch, el->el_state.argument, 0); 887 888 } 889 890 891 /* vi_prev_char(): 892 * Vi move to the character specified previous 893 * [F] 894 */ 895 protected el_action_t 896 /*ARGSUSED*/ 897 vi_prev_char(el, c) 898 EditLine *el; 899 int c; 900 { 901 char ch; 902 903 if (el_getc(el, &ch) != 1) 904 return ed_end_of_file(el, 0); 905 906 el->el_search.chadir = CHAR_BACK; 907 el->el_search.chacha = ch; 908 909 return cv_csearch_back(el, ch, el->el_state.argument, 0); 910 } 911 912 913 /* vi_to_next_char(): 914 * Vi move up to the character specified next 915 * [t] 916 */ 917 protected el_action_t 918 /*ARGSUSED*/ 919 vi_to_next_char(el, c) 920 EditLine *el; 921 int c; 922 { 923 char ch; 924 925 if (el_getc(el, &ch) != 1) 926 return ed_end_of_file(el, 0); 927 928 return cv_csearch_fwd(el, ch, el->el_state.argument, 1); 929 930 } 931 932 933 /* vi_to_prev_char(): 934 * Vi move up to the character specified previous 935 * [T] 936 */ 937 protected el_action_t 938 /*ARGSUSED*/ 939 vi_to_prev_char(el, c) 940 EditLine *el; 941 int c; 942 { 943 char ch; 944 if (el_getc(el, &ch) != 1) 945 return ed_end_of_file(el, 0); 946 947 return cv_csearch_back(el, ch, el->el_state.argument, 1); 948 } 949 950 951 /* vi_repeat_next_char(): 952 * Vi repeat current character search in the same search direction 953 * [;] 954 */ 955 protected el_action_t 956 /*ARGSUSED*/ 957 vi_repeat_next_char(el, c) 958 EditLine *el; 959 int c; 960 { 961 if (el->el_search.chacha == 0) 962 return CC_ERROR; 963 964 return el->el_search.chadir == CHAR_FWD ? 965 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : 966 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); 967 } 968 969 970 /* vi_repeat_prev_char(): 971 * Vi repeat current character search in the opposite search direction 972 * [,] 973 */ 974 protected el_action_t 975 /*ARGSUSED*/ 976 vi_repeat_prev_char(el, c) 977 EditLine *el; 978 int c; 979 { 980 if (el->el_search.chacha == 0) 981 return CC_ERROR; 982 983 return el->el_search.chadir == CHAR_BACK ? 984 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : 985 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); 986 } 987