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