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