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