vi.c revision 37199
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) 38static 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 47private el_action_t cv_action __P((EditLine *, int)); 48 49/* cv_action(): 50 * Handle vi actions. 51 */ 52private el_action_t 53cv_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 */ 106protected el_action_t 107cv_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 */ 136protected el_action_t 137/*ARGSUSED*/ 138vi_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 */ 150protected el_action_t 151/*ARGSUSED*/ 152vi_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 */ 164protected el_action_t 165/*ARGSUSED*/ 166vi_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 c___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 */ 191protected el_action_t 192/*ARGSUSED*/ 193vi_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 cv__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 */ 218protected el_action_t 219/*ARGSUSED*/ 220vi_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 c___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 */ 245protected el_action_t 246/*ARGSUSED*/ 247vi_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 cv__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 */ 274protected el_action_t 275vi_change_case(el, c) 276 EditLine *el; 277 int c; 278{ 279 if (el->el_line.cursor < el->el_line.lastchar) { 280 c = (unsigned char)*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 */ 298protected el_action_t 299/*ARGSUSED*/ 300vi_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 */ 316protected el_action_t 317/*ARGSUSED*/ 318vi_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 */ 337protected el_action_t 338/*ARGSUSED*/ 339vi_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_ARGHACK; 350} 351 352 353/* vi_replace_mode(): 354 * Vi enter replace mode 355 * [R] 356 */ 357protected el_action_t 358/*ARGSUSED*/ 359vi_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_ARGHACK; 370} 371 372 373/* vi_substitute_char(): 374 * Vi replace character under the cursor and enter insert mode 375 * [s] 376 */ 377protected el_action_t 378/*ARGSUSED*/ 379vi_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 */ 393protected el_action_t 394/*ARGSUSED*/ 395vi_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 */ 409protected el_action_t 410/*ARGSUSED*/ 411vi_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 */ 425protected el_action_t 426/*ARGSUSED*/ 427vi_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 */ 445protected el_action_t 446/*ARGSUSED*/ 447vi_add(el, c) 448 EditLine *el; 449 int c; 450{ 451 el_action_t ret; 452 453 el->el_map.current = el->el_map.key; 454 if (el->el_line.cursor < el->el_line.lastchar) { 455 el->el_line.cursor++; 456 if (el->el_line.cursor > el->el_line.lastchar) 457 el->el_line.cursor = el->el_line.lastchar; 458 ret = CC_CURSOR; 459 } 460 else 461 ret = CC_NORM; 462 463 el->el_chared.c_vcmd.ins = el->el_line.cursor; 464 el->el_chared.c_undo.ptr = el->el_line.cursor; 465 el->el_chared.c_undo.action = DELETE; 466 467 return ret; 468} 469 470 471/* vi_add_at_eol(): 472 * Vi enter insert mode at end of line 473 * [A] 474 */ 475protected el_action_t 476/*ARGSUSED*/ 477vi_add_at_eol(el, c) 478 EditLine *el; 479 int c; 480{ 481 el->el_map.current = el->el_map.key; 482 el->el_line.cursor = el->el_line.lastchar; 483 484 /* Mark where insertion begins */ 485 el->el_chared.c_vcmd.ins = el->el_line.lastchar; 486 el->el_chared.c_undo.ptr = el->el_line.lastchar; 487 el->el_chared.c_undo.action = DELETE; 488 return CC_CURSOR; 489} 490 491 492/* vi_delete_meta(): 493 * Vi delete prefix command 494 * [d] 495 */ 496protected el_action_t 497/*ARGSUSED*/ 498vi_delete_meta(el, c) 499 EditLine *el; 500 int c; 501{ 502 return cv_action(el, DELETE); 503} 504 505 506/* vi_end_word(): 507 * Vi move to the end of the current space delimited word 508 * [E] 509 */ 510protected el_action_t 511/*ARGSUSED*/ 512vi_end_word(el, c) 513 EditLine *el; 514 int c; 515{ 516 if (el->el_line.cursor == el->el_line.lastchar) 517 return CC_ERROR; 518 519 el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, 520 el->el_state.argument); 521 522 if (el->el_chared.c_vcmd.action & DELETE) { 523 el->el_line.cursor++; 524 cv_delfini(el); 525 return CC_REFRESH; 526 } 527 528 return CC_CURSOR; 529} 530 531 532/* vi_to_end_word(): 533 * Vi move to the end of the current word 534 * [e] 535 */ 536protected el_action_t 537/*ARGSUSED*/ 538vi_to_end_word(el, c) 539 EditLine *el; 540 int c; 541{ 542 if (el->el_line.cursor == el->el_line.lastchar) 543 return CC_ERROR; 544 545 el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, 546 el->el_state.argument); 547 548 if (el->el_chared.c_vcmd.action & DELETE) { 549 el->el_line.cursor++; 550 cv_delfini(el); 551 return CC_REFRESH; 552 } 553 554 return CC_CURSOR; 555} 556 557 558/* vi_undo(): 559 * Vi undo last change 560 * [u] 561 */ 562protected el_action_t 563/*ARGSUSED*/ 564vi_undo(el, c) 565 EditLine *el; 566 int c; 567{ 568 char *cp, *kp; 569 char temp; 570 int i, size; 571 c_undo_t *un = &el->el_chared.c_undo; 572 573#ifdef DEBUG_UNDO 574 (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n", 575 un->action, un->buf, un->isize, un->dsize); 576#endif 577 switch (un->action) { 578 case DELETE: 579 if (un->dsize == 0) 580 return CC_NORM; 581 582 (void) memcpy(un->buf, un->ptr, un->dsize); 583 for (cp = un->ptr; cp <= el->el_line.lastchar; cp++) 584 *cp = cp[un->dsize]; 585 586 el->el_line.lastchar -= un->dsize; 587 el->el_line.cursor = un->ptr; 588 589 un->action = INSERT; 590 un->isize = un->dsize; 591 un->dsize = 0; 592 break; 593 594 case DELETE|INSERT: 595 size = un->isize - un->dsize; 596 if (size > 0) 597 i = un->dsize; 598 else 599 i = un->isize; 600 cp = un->ptr; 601 kp = un->buf; 602 while (i-- > 0) { 603 temp = *kp; 604 *kp++ = *cp; 605 *cp++ = temp; 606 } 607 if (size > 0) { 608 el->el_line.cursor = cp; 609 c_insert(el, size); 610 while (size-- > 0 && cp < el->el_line.lastchar) { 611 temp = *kp; 612 *kp++ = *cp; 613 *cp++ = temp; 614 } 615 } 616 else if (size < 0) { 617 size = -size; 618 for (; cp <= el->el_line.lastchar; cp++) { 619 *kp++ = *cp; 620 *cp = cp[size]; 621 } 622 el->el_line.lastchar -= size; 623 } 624 el->el_line.cursor = un->ptr; 625 i = un->dsize; 626 un->dsize = un->isize; 627 un->isize = i; 628 break; 629 630 case INSERT: 631 if (un->isize == 0) 632 return CC_NORM; 633 634 el->el_line.cursor = un->ptr; 635 c_insert(el, un->isize); 636 memcpy(un->ptr, un->buf, un->isize); 637 un->action = DELETE; 638 un->dsize = un->isize; 639 un->isize = 0; 640 break; 641 642 case CHANGE: 643 if (un->isize == 0) 644 return CC_NORM; 645 646 el->el_line.cursor = un->ptr; 647 size = (int) (el->el_line.cursor - el->el_line.lastchar); 648 if (size < un->isize) 649 size = un->isize; 650 cp = un->ptr; 651 kp = un->buf; 652 for(i = 0; i < size; i++) { 653 temp = *kp; 654 *kp++ = *cp; 655 *cp++ = temp; 656 } 657 un->dsize = 0; 658 break; 659 660 default: 661 return CC_ERROR; 662 } 663 664 return CC_REFRESH; 665} 666 667 668/* vi_undo_line(): 669 * Vi undo all changes 670 * [U] 671 */ 672protected el_action_t 673/*ARGSUSED*/ 674vi_undo_line(el, c) 675 EditLine *el; 676 int c; 677{ 678 679 return hist_get(el); 680} 681 682 683/* vi_command_mode(): 684 * Vi enter command mode (use alternative key bindings) 685 * [<ESC>] 686 */ 687protected el_action_t 688/*ARGSUSED*/ 689vi_command_mode(el, c) 690 EditLine *el; 691 int c; 692{ 693 int size; 694 /* [Esc] cancels pending action */ 695 el->el_chared.c_vcmd.ins = 0; 696 el->el_chared.c_vcmd.action = NOP; 697 el->el_chared.c_vcmd.pos = 0; 698 699 el->el_state.doingarg = 0; 700 size = el->el_chared.c_undo.ptr - el->el_line.cursor; 701 if (size < 0) 702 size = -size; 703 if (el->el_chared.c_undo.action == (INSERT|DELETE) || 704 el->el_chared.c_undo.action == DELETE) 705 el->el_chared.c_undo.dsize = size; 706 else 707 el->el_chared.c_undo.isize = size; 708 709 el->el_state.inputmode = MODE_INSERT; 710 el->el_map.current = el->el_map.alt; 711#ifdef VI_MOVE 712 if (el->el_line.cursor > el->el_line.buffer) 713 el->el_line.cursor--; 714#endif 715 return CC_CURSOR; 716} 717 718/* vi_zero(): 719 * Vi move to the beginning of line 720 * [0] 721 */ 722protected el_action_t 723vi_zero(el, c) 724 EditLine *el; 725 int c; 726{ 727 if (el->el_state.doingarg) { 728 if (el->el_state.argument > 1000000) 729 return CC_ERROR; 730 el->el_state.argument = 731 (el->el_state.argument * 10) + (c - '0'); 732 return CC_ARGHACK; 733 } 734 else { 735 el->el_line.cursor = el->el_line.buffer; 736 if (el->el_chared.c_vcmd.action & DELETE) { 737 cv_delfini(el); 738 return CC_REFRESH; 739 } 740 return CC_CURSOR; 741 } 742} 743 744 745/* vi_delete_prev_char(): 746 * Vi move to previous character (backspace) 747 * [^H] 748 */ 749protected el_action_t 750/*ARGSUSED*/ 751vi_delete_prev_char(el, c) 752 EditLine *el; 753 int c; 754{ 755 if (el->el_chared.c_vcmd.ins == 0) 756 return CC_ERROR; 757 758 if (el->el_chared.c_vcmd.ins > 759 el->el_line.cursor - el->el_state.argument) 760 return CC_ERROR; 761 762 c_delbefore(el, el->el_state.argument); 763 el->el_line.cursor -= el->el_state.argument; 764 765 return CC_REFRESH; 766} /* end v_del_char_prev */ 767 768 769/* vi_list_or_eof(): 770 * Vi list choices for completion or indicate end of file if empty line 771 * [^D] 772 */ 773protected el_action_t 774/*ARGSUSED*/ 775vi_list_or_eof(el, c) 776 EditLine *el; 777 int c; 778{ 779#ifdef notyet 780 if (el->el_line.cursor == el->el_line.lastchar && 781 el->el_line.cursor == el->el_line.buffer) { 782#endif 783 term_overwrite(el, STReof, 4); /* then do a EOF */ 784 term__flush(); 785 return CC_EOF; 786#ifdef notyet 787 } 788 else { 789 re_goto_bottom(el); 790 *el->el_line.lastchar = '\0'; /* just in case */ 791 return CC_LIST_CHOICES; 792 } 793#endif 794} 795 796 797/* vi_kill_line_prev(): 798 * Vi cut from beginning of line to cursor 799 * [^U] 800 */ 801protected el_action_t 802/*ARGSUSED*/ 803vi_kill_line_prev(el, c) 804 EditLine *el; 805 int c; 806{ 807 char *kp, *cp; 808 809 cp = el->el_line.buffer; 810 kp = el->el_chared.c_kill.buf; 811 while (cp < el->el_line.cursor) 812 *kp++ = *cp++; /* copy it */ 813 el->el_chared.c_kill.last = kp; 814 c_delbefore(el, el->el_line.cursor - el->el_line.buffer); 815 el->el_line.cursor = el->el_line.buffer; /* zap! */ 816 return CC_REFRESH; 817} 818 819 820/* vi_search_prev(): 821 * Vi search history previous 822 * [?] 823 */ 824protected el_action_t 825/*ARGSUSED*/ 826vi_search_prev(el, c) 827 EditLine *el; 828 int c; 829{ 830 return cv_search(el, ED_SEARCH_PREV_HISTORY); 831} 832 833 834/* vi_search_next(): 835 * Vi search history next 836 * [/] 837 */ 838protected el_action_t 839/*ARGSUSED*/ 840vi_search_next(el, c) 841 EditLine *el; 842 int c; 843{ 844 return cv_search(el, ED_SEARCH_NEXT_HISTORY); 845} 846 847 848/* vi_repeat_search_next(): 849 * Vi repeat current search in the same search direction 850 * [n] 851 */ 852protected el_action_t 853/*ARGSUSED*/ 854vi_repeat_search_next(el, c) 855 EditLine *el; 856 int c; 857{ 858 if (el->el_search.patlen == 0) 859 return CC_ERROR; 860 else 861 return cv_repeat_srch(el, el->el_search.patdir); 862} 863 864 865/* vi_repeat_search_prev(): 866 * Vi repeat current search in the opposite search direction 867 * [N] 868 */ 869/*ARGSUSED*/ 870protected el_action_t 871vi_repeat_search_prev(el, c) 872 EditLine *el; 873 int c; 874{ 875 if (el->el_search.patlen == 0) 876 return CC_ERROR; 877 else 878 return cv_repeat_srch(el, 879 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? 880 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY); 881} 882 883 884/* vi_next_char(): 885 * Vi move to the character specified next 886 * [f] 887 */ 888protected el_action_t 889/*ARGSUSED*/ 890vi_next_char(el, c) 891 EditLine *el; 892 int c; 893{ 894 char ch; 895 896 if (el_getc(el, &ch) != 1) 897 return ed_end_of_file(el, 0); 898 899 el->el_search.chadir = CHAR_FWD; 900 el->el_search.chacha = ch; 901 902 return cv_csearch_fwd(el, ch, el->el_state.argument, 0); 903 904} 905 906 907/* vi_prev_char(): 908 * Vi move to the character specified previous 909 * [F] 910 */ 911protected el_action_t 912/*ARGSUSED*/ 913vi_prev_char(el, c) 914 EditLine *el; 915 int c; 916{ 917 char ch; 918 919 if (el_getc(el, &ch) != 1) 920 return ed_end_of_file(el, 0); 921 922 el->el_search.chadir = CHAR_BACK; 923 el->el_search.chacha = ch; 924 925 return cv_csearch_back(el, ch, el->el_state.argument, 0); 926} 927 928 929/* vi_to_next_char(): 930 * Vi move up to the character specified next 931 * [t] 932 */ 933protected el_action_t 934/*ARGSUSED*/ 935vi_to_next_char(el, c) 936 EditLine *el; 937 int c; 938{ 939 char ch; 940 941 if (el_getc(el, &ch) != 1) 942 return ed_end_of_file(el, 0); 943 944 return cv_csearch_fwd(el, ch, el->el_state.argument, 1); 945 946} 947 948 949/* vi_to_prev_char(): 950 * Vi move up to the character specified previous 951 * [T] 952 */ 953protected el_action_t 954/*ARGSUSED*/ 955vi_to_prev_char(el, c) 956 EditLine *el; 957 int c; 958{ 959 char ch; 960 if (el_getc(el, &ch) != 1) 961 return ed_end_of_file(el, 0); 962 963 return cv_csearch_back(el, ch, el->el_state.argument, 1); 964} 965 966 967/* vi_repeat_next_char(): 968 * Vi repeat current character search in the same search direction 969 * [;] 970 */ 971protected el_action_t 972/*ARGSUSED*/ 973vi_repeat_next_char(el, c) 974 EditLine *el; 975 int c; 976{ 977 if (el->el_search.chacha == 0) 978 return CC_ERROR; 979 980 return el->el_search.chadir == CHAR_FWD ? 981 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : 982 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); 983} 984 985 986/* vi_repeat_prev_char(): 987 * Vi repeat current character search in the opposite search direction 988 * [,] 989 */ 990protected el_action_t 991/*ARGSUSED*/ 992vi_repeat_prev_char(el, c) 993 EditLine *el; 994 int c; 995{ 996 if (el->el_search.chacha == 0) 997 return CC_ERROR; 998 999 return el->el_search.chadir == CHAR_BACK ? 1000 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : 1001 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); 1002} 1003