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