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