vi.c revision 1.1.1.1 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 cv__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 ce__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 cv__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 ce__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 = *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_NORM;
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_NORM;
370 }
371
372
373 /* vi_substitute_char():
374 * Vi replace character under the cursor and enter insert mode
375 * [r]
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 int ret;
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_command_mode():
668 * Vi enter command mode (use alternative key bindings)
669 * [<ESC>]
670 */
671 protected el_action_t
672 /*ARGSUSED*/
673 vi_command_mode(el, c)
674 EditLine *el;
675 int c;
676 {
677 int size;
678 /* [Esc] cancels pending action */
679 el->el_chared.c_vcmd.ins = 0;
680 el->el_chared.c_vcmd.action = NOP;
681 el->el_chared.c_vcmd.pos = 0;
682
683 el->el_state.doingarg = 0;
684 size = el->el_chared.c_undo.ptr - el->el_line.cursor;
685 if (size < 0)
686 size = -size;
687 if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
688 el->el_chared.c_undo.action == DELETE)
689 el->el_chared.c_undo.dsize = size;
690 else
691 el->el_chared.c_undo.isize = size;
692
693 el->el_state.inputmode = MODE_INSERT;
694 el->el_map.current = el->el_map.alt;
695 #ifdef VI_MOVE
696 if (el->el_line.cursor > el->el_line.buffer)
697 el->el_line.cursor--;
698 #endif
699 return CC_CURSOR;
700 }
701
702 /* vi_zero():
703 * Vi move to the beginning of line
704 * [0]
705 */
706 protected el_action_t
707 vi_zero(el, c)
708 EditLine *el;
709 int c;
710 {
711 if (el->el_state.doingarg) {
712 if (el->el_state.argument > 1000000)
713 return CC_ERROR;
714 el->el_state.argument =
715 (el->el_state.argument * 10) + (c - '0');
716 return CC_ARGHACK;
717 }
718 else {
719 el->el_line.cursor = el->el_line.buffer;
720 if (el->el_chared.c_vcmd.action & DELETE) {
721 cv_delfini(el);
722 return CC_REFRESH;
723 }
724 return CC_CURSOR;
725 }
726 }
727
728
729 /* vi_delete_prev_char():
730 * Vi move to previous character (backspace)
731 * [^H]
732 */
733 protected el_action_t
734 /*ARGSUSED*/
735 vi_delete_prev_char(el, c)
736 EditLine *el;
737 int c;
738 {
739 if (el->el_chared.c_vcmd.ins == 0)
740 return CC_ERROR;
741
742 if (el->el_chared.c_vcmd.ins >
743 el->el_line.cursor - el->el_state.argument)
744 return CC_ERROR;
745
746 c_delbefore(el, el->el_state.argument);
747 el->el_line.cursor -= el->el_state.argument;
748
749 return CC_REFRESH;
750 } /* end v_del_char_prev */
751
752
753 /* vi_list_or_eof():
754 * Vi list choices for completion or indicate end of file if empty line
755 * [^D]
756 */
757 protected el_action_t
758 /*ARGSUSED*/
759 vi_list_or_eof(el, c)
760 EditLine *el;
761 int c;
762 {
763 #ifdef notyet
764 if (el->el_line.cursor == el->el_line.lastchar &&
765 el->el_line.cursor == el->el_line.buffer) {
766 #endif
767 term_overwrite(el, STReof, 4); /* then do a EOF */
768 term__flush();
769 return CC_EOF;
770 #ifdef notyet
771 }
772 else {
773 re_goto_bottom(el);
774 *el->el_line.lastchar = '\0'; /* just in case */
775 return CC_LIST_CHOICES;
776 }
777 #endif
778 }
779
780
781 /* vi_kill_line_prev():
782 * Vi cut from beginning of line to cursor
783 * [^U]
784 */
785 protected el_action_t
786 /*ARGSUSED*/
787 vi_kill_line_prev(el, c)
788 EditLine *el;
789 int c;
790 {
791 char *kp, *cp;
792
793 cp = el->el_line.buffer;
794 kp = el->el_chared.c_kill.buf;
795 while (cp < el->el_line.cursor)
796 *kp++ = *cp++; /* copy it */
797 el->el_chared.c_kill.last = kp;
798 c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
799 el->el_line.cursor = el->el_line.buffer; /* zap! */
800 return CC_REFRESH;
801 }
802
803
804 /* vi_search_prev():
805 * Vi search history previous
806 * [?]
807 */
808 protected el_action_t
809 /*ARGSUSED*/
810 vi_search_prev(el, c)
811 EditLine *el;
812 int c;
813 {
814 return cv_search(el, ED_SEARCH_PREV_HISTORY);
815 }
816
817
818 /* vi_search_next():
819 * Vi search history next
820 * [/]
821 */
822 protected el_action_t
823 /*ARGSUSED*/
824 vi_search_next(el, c)
825 EditLine *el;
826 int c;
827 {
828 return cv_search(el, ED_SEARCH_NEXT_HISTORY);
829 }
830
831
832 /* vi_repeat_search_next():
833 * Vi repeat current search in the same search direction
834 * [n]
835 */
836 protected el_action_t
837 /*ARGSUSED*/
838 vi_repeat_search_next(el, c)
839 EditLine *el;
840 int c;
841 {
842 if (el->el_search.patlen == 0)
843 return CC_ERROR;
844 else
845 return cv_repeat_srch(el, el->el_search.patdir);
846 }
847
848
849 /* vi_repeat_search_prev():
850 * Vi repeat current search in the opposite search direction
851 * [N]
852 */
853 /*ARGSUSED*/
854 protected el_action_t
855 vi_repeat_search_prev(el, c)
856 EditLine *el;
857 int c;
858 {
859 if (el->el_search.patlen == 0)
860 return CC_ERROR;
861 else
862 return cv_repeat_srch(el,
863 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
864 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
865 }
866
867
868 /* vi_next_char():
869 * Vi move to the character specified next
870 * [f]
871 */
872 protected el_action_t
873 /*ARGSUSED*/
874 vi_next_char(el, c)
875 EditLine *el;
876 int c;
877 {
878 char ch;
879
880 if (el_getc(el, &ch) != 1)
881 return ed_end_of_file(el, 0);
882
883 el->el_search.chadir = CHAR_FWD;
884 el->el_search.chacha = ch;
885
886 return cv_csearch_fwd(el, ch, el->el_state.argument, 0);
887
888 }
889
890
891 /* vi_prev_char():
892 * Vi move to the character specified previous
893 * [F]
894 */
895 protected el_action_t
896 /*ARGSUSED*/
897 vi_prev_char(el, c)
898 EditLine *el;
899 int c;
900 {
901 char ch;
902
903 if (el_getc(el, &ch) != 1)
904 return ed_end_of_file(el, 0);
905
906 el->el_search.chadir = CHAR_BACK;
907 el->el_search.chacha = ch;
908
909 return cv_csearch_back(el, ch, el->el_state.argument, 0);
910 }
911
912
913 /* vi_to_next_char():
914 * Vi move up to the character specified next
915 * [t]
916 */
917 protected el_action_t
918 /*ARGSUSED*/
919 vi_to_next_char(el, c)
920 EditLine *el;
921 int c;
922 {
923 char ch;
924
925 if (el_getc(el, &ch) != 1)
926 return ed_end_of_file(el, 0);
927
928 return cv_csearch_fwd(el, ch, el->el_state.argument, 1);
929
930 }
931
932
933 /* vi_to_prev_char():
934 * Vi move up to the character specified previous
935 * [T]
936 */
937 protected el_action_t
938 /*ARGSUSED*/
939 vi_to_prev_char(el, c)
940 EditLine *el;
941 int c;
942 {
943 char ch;
944 if (el_getc(el, &ch) != 1)
945 return ed_end_of_file(el, 0);
946
947 return cv_csearch_back(el, ch, el->el_state.argument, 1);
948 }
949
950
951 /* vi_repeat_next_char():
952 * Vi repeat current character search in the same search direction
953 * [;]
954 */
955 protected el_action_t
956 /*ARGSUSED*/
957 vi_repeat_next_char(el, c)
958 EditLine *el;
959 int c;
960 {
961 if (el->el_search.chacha == 0)
962 return CC_ERROR;
963
964 return el->el_search.chadir == CHAR_FWD ?
965 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
966 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
967 }
968
969
970 /* vi_repeat_prev_char():
971 * Vi repeat current character search in the opposite search direction
972 * [,]
973 */
974 protected el_action_t
975 /*ARGSUSED*/
976 vi_repeat_prev_char(el, c)
977 EditLine *el;
978 int c;
979 {
980 if (el->el_search.chacha == 0)
981 return CC_ERROR;
982
983 return el->el_search.chadir == CHAR_BACK ?
984 cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
985 cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
986 }
987