vi.c revision 1.2 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