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