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