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