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