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