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