Revert: * Makefile.in (check/%.exp): Pass directory for GDB_PARALLEL.
[deliverable/binutils-gdb.git] / readline / vi_mode.c
1 /* vi_mode.c -- A vi emulation mode for Bash.
2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
3
4 /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
5
6 This file is part of the GNU Readline Library (Readline), a library
7 for reading lines of text with interactive input and history editing.
8
9 Readline is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Readline is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Readline. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #define READLINE_LIBRARY
24
25 /* **************************************************************** */
26 /* */
27 /* VI Emulation Mode */
28 /* */
29 /* **************************************************************** */
30 #include "rlconf.h"
31
32 #if defined (VI_MODE)
33
34 #if defined (HAVE_CONFIG_H)
35 # include <config.h>
36 #endif
37
38 #include <sys/types.h>
39
40 #if defined (HAVE_STDLIB_H)
41 # include <stdlib.h>
42 #else
43 # include "ansi_stdlib.h"
44 #endif /* HAVE_STDLIB_H */
45
46 #if defined (HAVE_UNISTD_H)
47 # include <unistd.h>
48 #endif
49
50 #include <stdio.h>
51
52 /* Some standard library routines. */
53 #include "rldefs.h"
54 #include "rlmbutil.h"
55
56 #include "readline.h"
57 #include "history.h"
58
59 #include "rlprivate.h"
60 #include "xmalloc.h"
61
62 #ifndef member
63 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
64 #endif
65
66 int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
67
68 _rl_vimotion_cxt *_rl_vimvcxt = 0;
69
70 /* Non-zero means enter insertion mode. */
71 static int _rl_vi_doing_insert;
72
73 /* Command keys which do movement for xxx_to commands. */
74 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
75
76 /* Keymap used for vi replace characters. Created dynamically since
77 rarely used. */
78 static Keymap vi_replace_map;
79
80 /* The number of characters inserted in the last replace operation. */
81 static int vi_replace_count;
82
83 /* If non-zero, we have text inserted after a c[motion] command that put
84 us implicitly into insert mode. Some people want this text to be
85 attached to the command so that it is `redoable' with `.'. */
86 static int vi_continued_command;
87 static char *vi_insert_buffer;
88 static int vi_insert_buffer_size;
89
90 static int _rl_vi_last_repeat = 1;
91 static int _rl_vi_last_arg_sign = 1;
92 static int _rl_vi_last_motion;
93 #if defined (HANDLE_MULTIBYTE)
94 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
95 static int _rl_vi_last_search_mblen;
96 #else
97 static int _rl_vi_last_search_char;
98 #endif
99 static int _rl_vi_last_replacement;
100
101 static int _rl_vi_last_key_before_insert;
102
103 static int vi_redoing;
104
105 /* Text modification commands. These are the `redoable' commands. */
106 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
107
108 /* Arrays for the saved marks. */
109 static int vi_mark_chars['z' - 'a' + 1];
110
111 static void _rl_vi_replace_insert PARAMS((int));
112 static void _rl_vi_save_replace PARAMS((void));
113 static void _rl_vi_stuff_insert PARAMS((int));
114 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
115
116 static void vi_save_insert_buffer PARAMS ((int, int));
117
118 static void _rl_vi_backup PARAMS((void));
119
120 static int _rl_vi_arg_dispatch PARAMS((int));
121 static int rl_digit_loop1 PARAMS((void));
122
123 static int _rl_vi_set_mark PARAMS((void));
124 static int _rl_vi_goto_mark PARAMS((void));
125
126 static void _rl_vi_append_forward PARAMS((int));
127
128 static int _rl_vi_callback_getchar PARAMS((char *, int));
129
130 #if defined (READLINE_CALLBACKS)
131 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
132 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
133 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
134 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
135 #endif
136
137 static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
138 static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
139 static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
140
141 static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
142 static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
143 static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
144
145 static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
146
147 void
148 _rl_vi_initialize_line ()
149 {
150 register int i, n;
151
152 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
153 for (i = 0; i < n; i++)
154 vi_mark_chars[i] = -1;
155
156 RL_UNSETSTATE(RL_STATE_VICMDONCE);
157 }
158
159 void
160 _rl_vi_reset_last ()
161 {
162 _rl_vi_last_command = 'i';
163 _rl_vi_last_repeat = 1;
164 _rl_vi_last_arg_sign = 1;
165 _rl_vi_last_motion = 0;
166 }
167
168 void
169 _rl_vi_set_last (key, repeat, sign)
170 int key, repeat, sign;
171 {
172 _rl_vi_last_command = key;
173 _rl_vi_last_repeat = repeat;
174 _rl_vi_last_arg_sign = sign;
175 }
176
177 /* A convenience function that calls _rl_vi_set_last to save the last command
178 information and enters insertion mode. */
179 void
180 rl_vi_start_inserting (key, repeat, sign)
181 int key, repeat, sign;
182 {
183 _rl_vi_set_last (key, repeat, sign);
184 rl_vi_insertion_mode (1, key);
185 }
186
187 /* Is the command C a VI mode text modification command? */
188 int
189 _rl_vi_textmod_command (c)
190 int c;
191 {
192 return (member (c, vi_textmod));
193 }
194
195 int
196 _rl_vi_motion_command (c)
197 int c;
198 {
199 return (member (c, vi_motion));
200 }
201
202 static void
203 _rl_vi_replace_insert (count)
204 int count;
205 {
206 int nchars;
207
208 nchars = strlen (vi_insert_buffer);
209
210 rl_begin_undo_group ();
211 while (count--)
212 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
213 to rl_delete_text */
214 _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
215 rl_end_undo_group ();
216 }
217
218 static void
219 _rl_vi_stuff_insert (count)
220 int count;
221 {
222 rl_begin_undo_group ();
223 while (count--)
224 rl_insert_text (vi_insert_buffer);
225 rl_end_undo_group ();
226 }
227
228 /* Bound to `.'. Called from command mode, so we know that we have to
229 redo a text modification command. The default for _rl_vi_last_command
230 puts you back into insert mode. */
231 int
232 rl_vi_redo (count, c)
233 int count, c;
234 {
235 int r;
236
237 if (rl_explicit_arg == 0)
238 {
239 rl_numeric_arg = _rl_vi_last_repeat;
240 rl_arg_sign = _rl_vi_last_arg_sign;
241 }
242
243 r = 0;
244 vi_redoing = 1;
245 /* If we're redoing an insert with `i', stuff in the inserted text
246 and do not go into insertion mode. */
247 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
248 {
249 _rl_vi_stuff_insert (count);
250 /* And back up point over the last character inserted. */
251 if (rl_point > 0)
252 _rl_vi_backup ();
253 }
254 else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
255 {
256 _rl_vi_replace_insert (count);
257 /* And back up point over the last character inserted. */
258 if (rl_point > 0)
259 _rl_vi_backup ();
260 }
261 /* Ditto for redoing an insert with `I', but move to the beginning of the
262 line like the `I' command does. */
263 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
264 {
265 rl_beg_of_line (1, 'I');
266 _rl_vi_stuff_insert (count);
267 if (rl_point > 0)
268 _rl_vi_backup ();
269 }
270 /* Ditto for redoing an insert with `a', but move forward a character first
271 like the `a' command does. */
272 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
273 {
274 _rl_vi_append_forward ('a');
275 _rl_vi_stuff_insert (count);
276 if (rl_point > 0)
277 _rl_vi_backup ();
278 }
279 /* Ditto for redoing an insert with `A', but move to the end of the line
280 like the `A' command does. */
281 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
282 {
283 rl_end_of_line (1, 'A');
284 _rl_vi_stuff_insert (count);
285 if (rl_point > 0)
286 _rl_vi_backup ();
287 }
288 else
289 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
290 vi_redoing = 0;
291
292 return (r);
293 }
294
295 /* A placeholder for further expansion. */
296 int
297 rl_vi_undo (count, key)
298 int count, key;
299 {
300 return (rl_undo_command (count, key));
301 }
302
303 /* Yank the nth arg from the previous line into this line at point. */
304 int
305 rl_vi_yank_arg (count, key)
306 int count, key;
307 {
308 /* Readline thinks that the first word on a line is the 0th, while vi
309 thinks the first word on a line is the 1st. Compensate. */
310 if (rl_explicit_arg)
311 rl_yank_nth_arg (count - 1, 0);
312 else
313 rl_yank_nth_arg ('$', 0);
314
315 return (0);
316 }
317
318 /* With an argument, move back that many history lines, else move to the
319 beginning of history. */
320 int
321 rl_vi_fetch_history (count, c)
322 int count, c;
323 {
324 int wanted;
325
326 /* Giving an argument of n means we want the nth command in the history
327 file. The command number is interpreted the same way that the bash
328 `history' command does it -- that is, giving an argument count of 450
329 to this command would get the command listed as number 450 in the
330 output of `history'. */
331 if (rl_explicit_arg)
332 {
333 wanted = history_base + where_history () - count;
334 if (wanted <= 0)
335 rl_beginning_of_history (0, 0);
336 else
337 rl_get_previous_history (wanted, c);
338 }
339 else
340 rl_beginning_of_history (count, 0);
341 return (0);
342 }
343
344 /* Search again for the last thing searched for. */
345 int
346 rl_vi_search_again (count, key)
347 int count, key;
348 {
349 switch (key)
350 {
351 case 'n':
352 rl_noninc_reverse_search_again (count, key);
353 break;
354
355 case 'N':
356 rl_noninc_forward_search_again (count, key);
357 break;
358 }
359 return (0);
360 }
361
362 /* Do a vi style search. */
363 int
364 rl_vi_search (count, key)
365 int count, key;
366 {
367 switch (key)
368 {
369 case '?':
370 _rl_free_saved_history_line ();
371 rl_noninc_forward_search (count, key);
372 break;
373
374 case '/':
375 _rl_free_saved_history_line ();
376 rl_noninc_reverse_search (count, key);
377 break;
378
379 default:
380 rl_ding ();
381 break;
382 }
383 return (0);
384 }
385
386 /* Completion, from vi's point of view. */
387 int
388 rl_vi_complete (ignore, key)
389 int ignore, key;
390 {
391 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
392 {
393 if (!whitespace (rl_line_buffer[rl_point + 1]))
394 rl_vi_end_word (1, 'E');
395 rl_point++;
396 }
397
398 if (key == '*')
399 rl_complete_internal ('*'); /* Expansion and replacement. */
400 else if (key == '=')
401 rl_complete_internal ('?'); /* List possible completions. */
402 else if (key == '\\')
403 rl_complete_internal (TAB); /* Standard Readline completion. */
404 else
405 rl_complete (0, key);
406
407 if (key == '*' || key == '\\')
408 rl_vi_start_inserting (key, 1, rl_arg_sign);
409
410 return (0);
411 }
412
413 /* Tilde expansion for vi mode. */
414 int
415 rl_vi_tilde_expand (ignore, key)
416 int ignore, key;
417 {
418 rl_tilde_expand (0, key);
419 rl_vi_start_inserting (key, 1, rl_arg_sign);
420 return (0);
421 }
422
423 /* Previous word in vi mode. */
424 int
425 rl_vi_prev_word (count, key)
426 int count, key;
427 {
428 if (count < 0)
429 return (rl_vi_next_word (-count, key));
430
431 if (rl_point == 0)
432 {
433 rl_ding ();
434 return (0);
435 }
436
437 if (_rl_uppercase_p (key))
438 rl_vi_bWord (count, key);
439 else
440 rl_vi_bword (count, key);
441
442 return (0);
443 }
444
445 /* Next word in vi mode. */
446 int
447 rl_vi_next_word (count, key)
448 int count, key;
449 {
450 if (count < 0)
451 return (rl_vi_prev_word (-count, key));
452
453 if (rl_point >= (rl_end - 1))
454 {
455 rl_ding ();
456 return (0);
457 }
458
459 if (_rl_uppercase_p (key))
460 rl_vi_fWord (count, key);
461 else
462 rl_vi_fword (count, key);
463 return (0);
464 }
465
466 /* Move to the end of the ?next? word. */
467 int
468 rl_vi_end_word (count, key)
469 int count, key;
470 {
471 if (count < 0)
472 {
473 rl_ding ();
474 return 1;
475 }
476
477 if (_rl_uppercase_p (key))
478 rl_vi_eWord (count, key);
479 else
480 rl_vi_eword (count, key);
481 return (0);
482 }
483
484 /* Move forward a word the way that 'W' does. */
485 int
486 rl_vi_fWord (count, ignore)
487 int count, ignore;
488 {
489 while (count-- && rl_point < (rl_end - 1))
490 {
491 /* Skip until whitespace. */
492 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
493 rl_point++;
494
495 /* Now skip whitespace. */
496 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
497 rl_point++;
498 }
499 return (0);
500 }
501
502 int
503 rl_vi_bWord (count, ignore)
504 int count, ignore;
505 {
506 while (count-- && rl_point > 0)
507 {
508 /* If we are at the start of a word, move back to whitespace so
509 we will go back to the start of the previous word. */
510 if (!whitespace (rl_line_buffer[rl_point]) &&
511 whitespace (rl_line_buffer[rl_point - 1]))
512 rl_point--;
513
514 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
515 rl_point--;
516
517 if (rl_point > 0)
518 {
519 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
520 rl_point++;
521 }
522 }
523 return (0);
524 }
525
526 int
527 rl_vi_eWord (count, ignore)
528 int count, ignore;
529 {
530 while (count-- && rl_point < (rl_end - 1))
531 {
532 if (!whitespace (rl_line_buffer[rl_point]))
533 rl_point++;
534
535 /* Move to the next non-whitespace character (to the start of the
536 next word). */
537 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
538 rl_point++;
539
540 if (rl_point && rl_point < rl_end)
541 {
542 /* Skip whitespace. */
543 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
544 rl_point++;
545
546 /* Skip until whitespace. */
547 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
548 rl_point++;
549
550 /* Move back to the last character of the word. */
551 rl_point--;
552 }
553 }
554 return (0);
555 }
556
557 int
558 rl_vi_fword (count, ignore)
559 int count, ignore;
560 {
561 while (count-- && rl_point < (rl_end - 1))
562 {
563 /* Move to white space (really non-identifer). */
564 if (_rl_isident (rl_line_buffer[rl_point]))
565 {
566 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
567 rl_point++;
568 }
569 else /* if (!whitespace (rl_line_buffer[rl_point])) */
570 {
571 while (!_rl_isident (rl_line_buffer[rl_point]) &&
572 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
573 rl_point++;
574 }
575
576 /* Move past whitespace. */
577 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
578 rl_point++;
579 }
580 return (0);
581 }
582
583 int
584 rl_vi_bword (count, ignore)
585 int count, ignore;
586 {
587 while (count-- && rl_point > 0)
588 {
589 int last_is_ident;
590
591 /* If we are at the start of a word, move back to whitespace
592 so we will go back to the start of the previous word. */
593 if (!whitespace (rl_line_buffer[rl_point]) &&
594 whitespace (rl_line_buffer[rl_point - 1]))
595 rl_point--;
596
597 /* If this character and the previous character are `opposite', move
598 back so we don't get messed up by the rl_point++ down there in
599 the while loop. Without this code, words like `l;' screw up the
600 function. */
601 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
602 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
603 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
604 rl_point--;
605
606 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
607 rl_point--;
608
609 if (rl_point > 0)
610 {
611 if (_rl_isident (rl_line_buffer[rl_point]))
612 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
613 else
614 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
615 !whitespace (rl_line_buffer[rl_point]));
616 rl_point++;
617 }
618 }
619 return (0);
620 }
621
622 int
623 rl_vi_eword (count, ignore)
624 int count, ignore;
625 {
626 while (count-- && rl_point < rl_end - 1)
627 {
628 if (!whitespace (rl_line_buffer[rl_point]))
629 rl_point++;
630
631 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
632 rl_point++;
633
634 if (rl_point < rl_end)
635 {
636 if (_rl_isident (rl_line_buffer[rl_point]))
637 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
638 else
639 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
640 && !whitespace (rl_line_buffer[rl_point]));
641 }
642 rl_point--;
643 }
644 return (0);
645 }
646
647 int
648 rl_vi_insert_beg (count, key)
649 int count, key;
650 {
651 rl_beg_of_line (1, key);
652 rl_vi_insert_mode (1, key);
653 return (0);
654 }
655
656 static void
657 _rl_vi_append_forward (key)
658 int key;
659 {
660 int point;
661
662 if (rl_point < rl_end)
663 {
664 if (MB_CUR_MAX == 1 || rl_byte_oriented)
665 rl_point++;
666 else
667 {
668 point = rl_point;
669 #if 0
670 rl_forward_char (1, key);
671 #else
672 rl_point = _rl_forward_char_internal (1);
673 #endif
674 if (point == rl_point)
675 rl_point = rl_end;
676 }
677 }
678 }
679
680 int
681 rl_vi_append_mode (count, key)
682 int count, key;
683 {
684 _rl_vi_append_forward (key);
685 rl_vi_start_inserting (key, 1, rl_arg_sign);
686 return (0);
687 }
688
689 int
690 rl_vi_append_eol (count, key)
691 int count, key;
692 {
693 rl_end_of_line (1, key);
694 rl_vi_append_mode (1, key);
695 return (0);
696 }
697
698 /* What to do in the case of C-d. */
699 int
700 rl_vi_eof_maybe (count, c)
701 int count, c;
702 {
703 return (rl_newline (1, '\n'));
704 }
705
706 /* Insertion mode stuff. */
707
708 /* Switching from one mode to the other really just involves
709 switching keymaps. */
710 int
711 rl_vi_insertion_mode (count, key)
712 int count, key;
713 {
714 _rl_keymap = vi_insertion_keymap;
715 _rl_vi_last_key_before_insert = key;
716 if (_rl_show_mode_in_prompt)
717 _rl_reset_prompt ();
718 return (0);
719 }
720
721 int
722 rl_vi_insert_mode (count, key)
723 int count, key;
724 {
725 rl_vi_start_inserting (key, 1, rl_arg_sign);
726 return (0);
727 }
728
729 static void
730 vi_save_insert_buffer (start, len)
731 int start, len;
732 {
733 /* Same code as _rl_vi_save_insert below */
734 if (len >= vi_insert_buffer_size)
735 {
736 vi_insert_buffer_size += (len + 32) - (len % 32);
737 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
738 }
739 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
740 vi_insert_buffer[len-1] = '\0';
741 }
742
743 static void
744 _rl_vi_save_replace ()
745 {
746 int len, start, end;
747 UNDO_LIST *up;
748
749 up = rl_undo_list;
750 if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
751 {
752 if (vi_insert_buffer_size >= 1)
753 vi_insert_buffer[0] = '\0';
754 return;
755 }
756 /* Let's try it the quick and easy way for now. This should essentially
757 accommodate every UNDO_INSERT and save the inserted text to
758 vi_insert_buffer */
759 end = rl_point;
760 start = end - vi_replace_count + 1;
761 len = vi_replace_count + 1;
762
763 vi_save_insert_buffer (start, len);
764 }
765
766 static void
767 _rl_vi_save_insert (up)
768 UNDO_LIST *up;
769 {
770 int len, start, end;
771
772 if (up == 0 || up->what != UNDO_INSERT)
773 {
774 if (vi_insert_buffer_size >= 1)
775 vi_insert_buffer[0] = '\0';
776 return;
777 }
778
779 start = up->start;
780 end = up->end;
781 len = end - start + 1;
782
783 vi_save_insert_buffer (start, len);
784 }
785
786 void
787 _rl_vi_done_inserting ()
788 {
789 if (_rl_vi_doing_insert)
790 {
791 /* The `C', `s', and `S' commands set this. */
792 rl_end_undo_group ();
793 /* Now, the text between rl_undo_list->next->start and
794 rl_undo_list->next->end is what was inserted while in insert
795 mode. It gets copied to VI_INSERT_BUFFER because it depends
796 on absolute indices into the line which may change (though they
797 probably will not). */
798 _rl_vi_doing_insert = 0;
799 if (_rl_vi_last_key_before_insert == 'R')
800 _rl_vi_save_replace (); /* Half the battle */
801 else
802 _rl_vi_save_insert (rl_undo_list->next);
803 vi_continued_command = 1;
804 }
805 else
806 {
807 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
808 _rl_vi_last_key_before_insert == 'a' ||
809 _rl_vi_last_key_before_insert == 'I' ||
810 _rl_vi_last_key_before_insert == 'A'))
811 _rl_vi_save_insert (rl_undo_list);
812 /* XXX - Other keys probably need to be checked. */
813 else if (_rl_vi_last_key_before_insert == 'C')
814 rl_end_undo_group ();
815 while (_rl_undo_group_level > 0)
816 rl_end_undo_group ();
817 vi_continued_command = 0;
818 }
819 }
820
821 int
822 rl_vi_movement_mode (count, key)
823 int count, key;
824 {
825 if (rl_point > 0)
826 rl_backward_char (1, key);
827
828 _rl_keymap = vi_movement_keymap;
829 _rl_vi_done_inserting ();
830
831 /* This is how POSIX.2 says `U' should behave -- everything up until the
832 first time you go into command mode should not be undone. */
833 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
834 rl_free_undo_list ();
835
836 if (_rl_show_mode_in_prompt)
837 _rl_reset_prompt ();
838
839 RL_SETSTATE (RL_STATE_VICMDONCE);
840 return (0);
841 }
842
843 int
844 rl_vi_arg_digit (count, c)
845 int count, c;
846 {
847 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
848 return (rl_beg_of_line (1, c));
849 else
850 return (rl_digit_argument (count, c));
851 }
852
853 /* Change the case of the next COUNT characters. */
854 #if defined (HANDLE_MULTIBYTE)
855 static int
856 _rl_vi_change_mbchar_case (count)
857 int count;
858 {
859 wchar_t wc;
860 char mb[MB_LEN_MAX+1];
861 int mlen, p;
862 size_t m;
863 mbstate_t ps;
864
865 memset (&ps, 0, sizeof (mbstate_t));
866 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
867 count--;
868 while (count-- && rl_point < rl_end)
869 {
870 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
871 if (MB_INVALIDCH (m))
872 wc = (wchar_t)rl_line_buffer[rl_point];
873 else if (MB_NULLWCH (m))
874 wc = L'\0';
875 if (iswupper (wc))
876 wc = towlower (wc);
877 else if (iswlower (wc))
878 wc = towupper (wc);
879 else
880 {
881 /* Just skip over chars neither upper nor lower case */
882 rl_forward_char (1, 0);
883 continue;
884 }
885
886 /* Vi is kind of strange here. */
887 if (wc)
888 {
889 p = rl_point;
890 mlen = wcrtomb (mb, wc, &ps);
891 if (mlen >= 0)
892 mb[mlen] = '\0';
893 rl_begin_undo_group ();
894 rl_vi_delete (1, 0);
895 if (rl_point < p) /* Did we retreat at EOL? */
896 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
897 rl_insert_text (mb);
898 rl_end_undo_group ();
899 rl_vi_check ();
900 }
901 else
902 rl_forward_char (1, 0);
903 }
904
905 return 0;
906 }
907 #endif
908
909 int
910 rl_vi_change_case (count, ignore)
911 int count, ignore;
912 {
913 int c, p;
914
915 /* Don't try this on an empty line. */
916 if (rl_point >= rl_end)
917 return (0);
918
919 c = 0;
920 #if defined (HANDLE_MULTIBYTE)
921 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
922 return (_rl_vi_change_mbchar_case (count));
923 #endif
924
925 while (count-- && rl_point < rl_end)
926 {
927 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
928 c = _rl_to_lower (rl_line_buffer[rl_point]);
929 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
930 c = _rl_to_upper (rl_line_buffer[rl_point]);
931 else
932 {
933 /* Just skip over characters neither upper nor lower case. */
934 rl_forward_char (1, c);
935 continue;
936 }
937
938 /* Vi is kind of strange here. */
939 if (c)
940 {
941 p = rl_point;
942 rl_begin_undo_group ();
943 rl_vi_delete (1, c);
944 if (rl_point < p) /* Did we retreat at EOL? */
945 rl_point++;
946 _rl_insert_char (1, c);
947 rl_end_undo_group ();
948 rl_vi_check ();
949 }
950 else
951 rl_forward_char (1, c);
952 }
953 return (0);
954 }
955
956 int
957 rl_vi_put (count, key)
958 int count, key;
959 {
960 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
961 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
962
963 while (count--)
964 rl_yank (1, key);
965
966 rl_backward_char (1, key);
967 return (0);
968 }
969
970 static void
971 _rl_vi_backup ()
972 {
973 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
974 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
975 else
976 rl_point--;
977 }
978
979 int
980 rl_vi_check ()
981 {
982 if (rl_point && rl_point == rl_end)
983 {
984 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
985 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
986 else
987 rl_point--;
988 }
989 return (0);
990 }
991
992 int
993 rl_vi_column (count, key)
994 int count, key;
995 {
996 if (count > rl_end)
997 rl_end_of_line (1, key);
998 else
999 rl_point = count - 1;
1000 return (0);
1001 }
1002
1003 /* Process C as part of the current numeric argument. Return -1 if the
1004 argument should be aborted, 0 if we should not read any more chars, and
1005 1 if we should continue to read chars. */
1006 static int
1007 _rl_vi_arg_dispatch (c)
1008 int c;
1009 {
1010 int key;
1011
1012 key = c;
1013 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1014 {
1015 rl_numeric_arg *= 4;
1016 return 1;
1017 }
1018
1019 c = UNMETA (c);
1020
1021 if (_rl_digit_p (c))
1022 {
1023 if (rl_explicit_arg)
1024 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1025 else
1026 rl_numeric_arg = _rl_digit_value (c);
1027 rl_explicit_arg = 1;
1028 return 1; /* keep going */
1029 }
1030 else
1031 {
1032 rl_clear_message ();
1033 rl_stuff_char (key);
1034 return 0; /* done */
1035 }
1036 }
1037
1038 /* A simplified loop for vi. Don't dispatch key at end.
1039 Don't recognize minus sign?
1040 Should this do rl_save_prompt/rl_restore_prompt? */
1041 static int
1042 rl_digit_loop1 ()
1043 {
1044 int c, r;
1045
1046 while (1)
1047 {
1048 if (_rl_arg_overflow ())
1049 return 1;
1050
1051 c = _rl_arg_getchar ();
1052
1053 r = _rl_vi_arg_dispatch (c);
1054 if (r <= 0)
1055 break;
1056 }
1057
1058 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1059 return (0);
1060 }
1061
1062 static void
1063 _rl_mvcxt_init (m, op, key)
1064 _rl_vimotion_cxt *m;
1065 int op, key;
1066 {
1067 m->op = op;
1068 m->state = m->flags = 0;
1069 m->ncxt = 0;
1070 m->numeric_arg = -1;
1071 m->start = rl_point;
1072 m->end = rl_end;
1073 m->key = key;
1074 m->motion = -1;
1075 }
1076
1077 static _rl_vimotion_cxt *
1078 _rl_mvcxt_alloc (op, key)
1079 int op, key;
1080 {
1081 _rl_vimotion_cxt *m;
1082
1083 m = xmalloc (sizeof (_rl_vimotion_cxt));
1084 _rl_mvcxt_init (m, op, key);
1085 return m;
1086 }
1087
1088 static void
1089 _rl_mvcxt_dispose (m)
1090 _rl_vimotion_cxt *m;
1091 {
1092 xfree (m);
1093 }
1094
1095 static int
1096 rl_domove_motion_callback (m)
1097 _rl_vimotion_cxt *m;
1098 {
1099 int c, save, r;
1100 int old_end;
1101
1102 _rl_vi_last_motion = c = m->motion;
1103
1104 /* Append a blank character temporarily so that the motion routines
1105 work right at the end of the line. */
1106 old_end = rl_end;
1107 rl_line_buffer[rl_end++] = ' ';
1108 rl_line_buffer[rl_end] = '\0';
1109
1110 _rl_dispatch (c, _rl_keymap);
1111
1112 /* Remove the blank that we added. */
1113 rl_end = old_end;
1114 rl_line_buffer[rl_end] = '\0';
1115 if (rl_point > rl_end)
1116 rl_point = rl_end;
1117
1118 /* No change in position means the command failed. */
1119 if (rl_mark == rl_point)
1120 return (-1);
1121
1122 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1123 word. If we are not at the end of the line, and we are on a
1124 non-whitespace character, move back one (presumably to whitespace). */
1125 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
1126 !whitespace (rl_line_buffer[rl_point]))
1127 rl_point--;
1128
1129 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1130 or cE is the actual result. Brute-force, no subtlety. */
1131 if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
1132 {
1133 /* Don't move farther back than where we started. */
1134 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
1135 rl_point--;
1136
1137 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1138 the line, the character under the cursor should be deleted. */
1139 if (rl_point == rl_mark)
1140 rl_point++;
1141 else
1142 {
1143 /* Move past the end of the word so that the kill doesn't
1144 remove the last letter of the previous word. Only do this
1145 if we are not at the end of the line. */
1146 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1147 rl_point++;
1148 }
1149 }
1150
1151 if (rl_mark < rl_point)
1152 SWAP (rl_point, rl_mark);
1153
1154 #if defined (READLINE_CALLBACKS)
1155 if (RL_ISSTATE (RL_STATE_CALLBACK))
1156 (*rl_redisplay_function)(); /* make sure motion is displayed */
1157 #endif
1158
1159 r = vidomove_dispatch (m);
1160
1161 return (r);
1162 }
1163
1164 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1165
1166 static int
1167 rl_domove_read_callback (m)
1168 _rl_vimotion_cxt *m;
1169 {
1170 int c, save;
1171
1172 c = m->motion;
1173
1174 if (member (c, vi_motion))
1175 {
1176 #if defined (READLINE_CALLBACKS)
1177 /* If we just read a vi-mode motion command numeric argument, turn off
1178 the `reading numeric arg' state */
1179 if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1180 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1181 #endif
1182 /* Should do everything, including turning off RL_STATE_VIMOTION */
1183 return (rl_domove_motion_callback (m));
1184 }
1185 else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
1186 {
1187 rl_mark = rl_end;
1188 rl_beg_of_line (1, c);
1189 _rl_vi_last_motion = c;
1190 RL_UNSETSTATE (RL_STATE_VIMOTION);
1191 return (vidomove_dispatch (m));
1192 }
1193 #if defined (READLINE_CALLBACKS)
1194 /* XXX - these need to handle rl_universal_argument bindings */
1195 /* Reading vi motion char continuing numeric argument */
1196 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1197 {
1198 return (_rl_vi_arg_dispatch (c));
1199 }
1200 /* Readine vi motion char starting numeric argument */
1201 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
1202 {
1203 RL_SETSTATE (RL_STATE_NUMERICARG);
1204 return (_rl_vi_arg_dispatch (c));
1205 }
1206 #endif
1207 else if (_rl_digit_p (c))
1208 {
1209 /* This code path taken when not in callback mode */
1210 save = rl_numeric_arg;
1211 rl_numeric_arg = _rl_digit_value (c);
1212 rl_explicit_arg = 1;
1213 RL_SETSTATE (RL_STATE_NUMERICARG);
1214 rl_digit_loop1 ();
1215 rl_numeric_arg *= save;
1216 c = rl_vi_domove_getchar (m);
1217 if (c < 0)
1218 {
1219 m->motion = 0;
1220 return -1;
1221 }
1222 m->motion = c;
1223 return (rl_domove_motion_callback (m));
1224 }
1225 else
1226 {
1227 RL_UNSETSTATE (RL_STATE_VIMOTION);
1228 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1229 return (1);
1230 }
1231 }
1232
1233 static int
1234 rl_vi_domove_getchar (m)
1235 _rl_vimotion_cxt *m;
1236 {
1237 int c;
1238
1239 RL_SETSTATE(RL_STATE_MOREINPUT);
1240 c = rl_read_key ();
1241 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1242
1243 return c;
1244 }
1245
1246 #if defined (READLINE_CALLBACKS)
1247 int
1248 _rl_vi_domove_callback (m)
1249 _rl_vimotion_cxt *m;
1250 {
1251 int c, r;
1252
1253 m->motion = c = rl_vi_domove_getchar (m);
1254 /* XXX - what to do if this returns -1? Should we return 1 for eof to
1255 callback code? */
1256 r = rl_domove_read_callback (m);
1257
1258 return ((r == 0) ? r : 1); /* normalize return values */
1259 }
1260 #endif
1261
1262 /* This code path taken when not in callback mode. */
1263 int
1264 rl_vi_domove (x, ignore)
1265 int x, *ignore;
1266 {
1267 int r;
1268 _rl_vimotion_cxt *m;
1269
1270 m = _rl_vimvcxt;
1271 *ignore = m->motion = rl_vi_domove_getchar (m);
1272
1273 if (m->motion < 0)
1274 {
1275 m->motion = 0;
1276 return -1;
1277 }
1278
1279 return (rl_domove_read_callback (m));
1280 }
1281
1282 static int
1283 vi_delete_dispatch (m)
1284 _rl_vimotion_cxt *m;
1285 {
1286 /* These are the motion commands that do not require adjusting the
1287 mark. */
1288 if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1289 (rl_mark < rl_end))
1290 rl_mark++;
1291
1292 rl_kill_text (rl_point, rl_mark);
1293 return (0);
1294 }
1295
1296 int
1297 rl_vi_delete_to (count, key)
1298 int count, key;
1299 {
1300 int c, r;
1301
1302 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
1303 _rl_vimvcxt->start = rl_point;
1304
1305 rl_mark = rl_point;
1306 if (_rl_uppercase_p (key))
1307 {
1308 _rl_vimvcxt->motion = '$';
1309 r = rl_domove_motion_callback (_rl_vimvcxt);
1310 }
1311 else if (vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
1312 {
1313 _rl_vimvcxt->motion = _rl_vi_last_motion;
1314 r = rl_domove_motion_callback (_rl_vimvcxt);
1315 }
1316 else if (vi_redoing) /* handle redoing `dd' here */
1317 {
1318 _rl_vimvcxt->motion = _rl_vi_last_motion;
1319 rl_mark = rl_end;
1320 rl_beg_of_line (1, key);
1321 RL_UNSETSTATE (RL_STATE_VIMOTION);
1322 r = vidomove_dispatch (_rl_vimvcxt);
1323 }
1324 #if defined (READLINE_CALLBACKS)
1325 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1326 {
1327 RL_SETSTATE (RL_STATE_VIMOTION);
1328 return (0);
1329 }
1330 #endif
1331 else
1332 r = rl_vi_domove (key, &c);
1333
1334 if (r < 0)
1335 {
1336 rl_ding ();
1337 r = -1;
1338 }
1339
1340 _rl_mvcxt_dispose (_rl_vimvcxt);
1341 _rl_vimvcxt = 0;
1342
1343 return r;
1344 }
1345
1346 static int
1347 vi_change_dispatch (m)
1348 _rl_vimotion_cxt *m;
1349 {
1350 /* These are the motion commands that do not require adjusting the
1351 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1352 and already leave the mark at the correct location. */
1353 if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1354 (rl_mark < rl_end))
1355 rl_mark++;
1356
1357 /* The cursor never moves with c[wW]. */
1358 if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
1359 rl_point = m->start;
1360
1361 if (vi_redoing)
1362 {
1363 if (vi_insert_buffer && *vi_insert_buffer)
1364 rl_begin_undo_group ();
1365 rl_delete_text (rl_point, rl_mark);
1366 if (vi_insert_buffer && *vi_insert_buffer)
1367 {
1368 rl_insert_text (vi_insert_buffer);
1369 rl_end_undo_group ();
1370 }
1371 }
1372 else
1373 {
1374 rl_begin_undo_group (); /* to make the `u' command work */
1375 rl_kill_text (rl_point, rl_mark);
1376 /* `C' does not save the text inserted for undoing or redoing. */
1377 if (_rl_uppercase_p (m->key) == 0)
1378 _rl_vi_doing_insert = 1;
1379 /* XXX -- TODO -- use m->numericarg? */
1380 rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
1381 }
1382
1383 return (0);
1384 }
1385
1386 int
1387 rl_vi_change_to (count, key)
1388 int count, key;
1389 {
1390 int c, r;
1391
1392 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
1393 _rl_vimvcxt->start = rl_point;
1394
1395 rl_mark = rl_point;
1396 if (_rl_uppercase_p (key))
1397 {
1398 _rl_vimvcxt->motion = '$';
1399 r = rl_domove_motion_callback (_rl_vimvcxt);
1400 }
1401 else if (vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
1402 {
1403 _rl_vimvcxt->motion = _rl_vi_last_motion;
1404 r = rl_domove_motion_callback (_rl_vimvcxt);
1405 }
1406 else if (vi_redoing) /* handle redoing `cc' here */
1407 {
1408 _rl_vimvcxt->motion = _rl_vi_last_motion;
1409 rl_mark = rl_end;
1410 rl_beg_of_line (1, key);
1411 RL_UNSETSTATE (RL_STATE_VIMOTION);
1412 r = vidomove_dispatch (_rl_vimvcxt);
1413 }
1414 #if defined (READLINE_CALLBACKS)
1415 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1416 {
1417 RL_SETSTATE (RL_STATE_VIMOTION);
1418 return (0);
1419 }
1420 #endif
1421 else
1422 r = rl_vi_domove (key, &c);
1423
1424 if (r < 0)
1425 {
1426 rl_ding ();
1427 r = -1; /* normalize return value */
1428 }
1429
1430 _rl_mvcxt_dispose (_rl_vimvcxt);
1431 _rl_vimvcxt = 0;
1432
1433 return r;
1434 }
1435
1436 static int
1437 vi_yank_dispatch (m)
1438 _rl_vimotion_cxt *m;
1439 {
1440 /* These are the motion commands that do not require adjusting the
1441 mark. */
1442 if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1443 (rl_mark < rl_end))
1444 rl_mark++;
1445
1446 rl_begin_undo_group ();
1447 rl_kill_text (rl_point, rl_mark);
1448 rl_end_undo_group ();
1449 rl_do_undo ();
1450 rl_point = m->start;
1451
1452 return (0);
1453 }
1454
1455 int
1456 rl_vi_yank_to (count, key)
1457 int count, key;
1458 {
1459 int c, r;
1460
1461 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
1462 _rl_vimvcxt->start = rl_point;
1463
1464 rl_mark = rl_point;
1465 if (_rl_uppercase_p (key))
1466 {
1467 _rl_vimvcxt->motion = '$';
1468 r = rl_domove_motion_callback (_rl_vimvcxt);
1469 }
1470 else if (vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
1471 {
1472 _rl_vimvcxt->motion = _rl_vi_last_motion;
1473 r = rl_domove_motion_callback (_rl_vimvcxt);
1474 }
1475 else if (vi_redoing) /* handle redoing `yy' here */
1476 {
1477 _rl_vimvcxt->motion = _rl_vi_last_motion;
1478 rl_mark = rl_end;
1479 rl_beg_of_line (1, key);
1480 RL_UNSETSTATE (RL_STATE_VIMOTION);
1481 r = vidomove_dispatch (_rl_vimvcxt);
1482 }
1483 #if defined (READLINE_CALLBACKS)
1484 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1485 {
1486 RL_SETSTATE (RL_STATE_VIMOTION);
1487 return (0);
1488 }
1489 #endif
1490 else
1491 r = rl_vi_domove (key, &c);
1492
1493 if (r < 0)
1494 {
1495 rl_ding ();
1496 r = -1;
1497 }
1498
1499 _rl_mvcxt_dispose (_rl_vimvcxt);
1500 _rl_vimvcxt = 0;
1501
1502 return r;
1503 }
1504
1505 static int
1506 vidomove_dispatch (m)
1507 _rl_vimotion_cxt *m;
1508 {
1509 int r;
1510
1511 switch (m->op)
1512 {
1513 case VIM_DELETE:
1514 r = vi_delete_dispatch (m);
1515 break;
1516 case VIM_CHANGE:
1517 r = vi_change_dispatch (m);
1518 break;
1519 case VIM_YANK:
1520 r = vi_yank_dispatch (m);
1521 break;
1522 default:
1523 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
1524 r = 1;
1525 break;
1526 }
1527
1528 RL_UNSETSTATE (RL_STATE_VIMOTION);
1529 return r;
1530 }
1531
1532 int
1533 rl_vi_rubout (count, key)
1534 int count, key;
1535 {
1536 int opoint;
1537
1538 if (count < 0)
1539 return (rl_vi_delete (-count, key));
1540
1541 if (rl_point == 0)
1542 {
1543 rl_ding ();
1544 return 1;
1545 }
1546
1547 opoint = rl_point;
1548 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1549 rl_backward_char (count, key);
1550 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1551 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1552 else
1553 rl_point -= count;
1554
1555 if (rl_point < 0)
1556 rl_point = 0;
1557
1558 rl_kill_text (rl_point, opoint);
1559
1560 return (0);
1561 }
1562
1563 int
1564 rl_vi_delete (count, key)
1565 int count, key;
1566 {
1567 int end;
1568
1569 if (count < 0)
1570 return (rl_vi_rubout (-count, key));
1571
1572 if (rl_end == 0)
1573 {
1574 rl_ding ();
1575 return 1;
1576 }
1577
1578 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1579 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1580 else
1581 end = rl_point + count;
1582
1583 if (end >= rl_end)
1584 end = rl_end;
1585
1586 rl_kill_text (rl_point, end);
1587
1588 if (rl_point > 0 && rl_point == rl_end)
1589 rl_backward_char (1, key);
1590
1591 return (0);
1592 }
1593
1594 int
1595 rl_vi_back_to_indent (count, key)
1596 int count, key;
1597 {
1598 rl_beg_of_line (1, key);
1599 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1600 rl_point++;
1601 return (0);
1602 }
1603
1604 int
1605 rl_vi_first_print (count, key)
1606 int count, key;
1607 {
1608 return (rl_vi_back_to_indent (1, key));
1609 }
1610
1611 static int _rl_cs_dir, _rl_cs_orig_dir;
1612
1613 #if defined (READLINE_CALLBACKS)
1614 static int
1615 _rl_vi_callback_char_search (data)
1616 _rl_callback_generic_arg *data;
1617 {
1618 int c;
1619 #if defined (HANDLE_MULTIBYTE)
1620 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1621 #else
1622 RL_SETSTATE(RL_STATE_MOREINPUT);
1623 c = rl_read_key ();
1624 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1625 #endif
1626
1627 if (c <= 0)
1628 return -1;
1629
1630 #if !defined (HANDLE_MULTIBYTE)
1631 _rl_vi_last_search_char = c;
1632 #endif
1633
1634 _rl_callback_func = 0;
1635 _rl_want_redisplay = 1;
1636
1637 #if defined (HANDLE_MULTIBYTE)
1638 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1639 #else
1640 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1641 #endif
1642 }
1643 #endif
1644
1645 int
1646 rl_vi_char_search (count, key)
1647 int count, key;
1648 {
1649 int c;
1650 #if defined (HANDLE_MULTIBYTE)
1651 static char *target;
1652 static int tlen;
1653 #else
1654 static char target;
1655 #endif
1656
1657 if (key == ';' || key == ',')
1658 {
1659 if (_rl_cs_orig_dir == 0)
1660 return 1;
1661 #if defined (HANDLE_MULTIBYTE)
1662 if (_rl_vi_last_search_mblen == 0)
1663 return 1;
1664 #else
1665 if (_rl_vi_last_search_char == 0)
1666 return 1;
1667 #endif
1668 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1669 }
1670 else
1671 {
1672 switch (key)
1673 {
1674 case 't':
1675 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1676 break;
1677
1678 case 'T':
1679 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1680 break;
1681
1682 case 'f':
1683 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1684 break;
1685
1686 case 'F':
1687 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1688 break;
1689 }
1690
1691 if (vi_redoing)
1692 {
1693 /* set target and tlen below */
1694 }
1695 #if defined (READLINE_CALLBACKS)
1696 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1697 {
1698 _rl_callback_data = _rl_callback_data_alloc (count);
1699 _rl_callback_data->i1 = _rl_cs_dir;
1700 _rl_callback_func = _rl_vi_callback_char_search;
1701 return (0);
1702 }
1703 #endif
1704 else
1705 {
1706 #if defined (HANDLE_MULTIBYTE)
1707 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1708 if (c <= 0)
1709 return -1;
1710 _rl_vi_last_search_mblen = c;
1711 #else
1712 RL_SETSTATE(RL_STATE_MOREINPUT);
1713 c = rl_read_key ();
1714 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1715 if (c < 0)
1716 return -1;
1717 _rl_vi_last_search_char = c;
1718 #endif
1719 }
1720 }
1721
1722 #if defined (HANDLE_MULTIBYTE)
1723 target = _rl_vi_last_search_mbchar;
1724 tlen = _rl_vi_last_search_mblen;
1725 #else
1726 target = _rl_vi_last_search_char;
1727 #endif
1728
1729 #if defined (HANDLE_MULTIBYTE)
1730 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1731 #else
1732 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1733 #endif
1734 }
1735
1736 /* Match brackets */
1737 int
1738 rl_vi_match (ignore, key)
1739 int ignore, key;
1740 {
1741 int count = 1, brack, pos, tmp, pre;
1742
1743 pos = rl_point;
1744 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1745 {
1746 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1747 {
1748 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1749 {
1750 pre = rl_point;
1751 rl_forward_char (1, key);
1752 if (pre == rl_point)
1753 break;
1754 }
1755 }
1756 else
1757 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1758 rl_point < rl_end - 1)
1759 rl_forward_char (1, key);
1760
1761 if (brack <= 0)
1762 {
1763 rl_point = pos;
1764 rl_ding ();
1765 return 1;
1766 }
1767 }
1768
1769 pos = rl_point;
1770
1771 if (brack < 0)
1772 {
1773 while (count)
1774 {
1775 tmp = pos;
1776 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1777 pos--;
1778 else
1779 {
1780 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1781 if (tmp == pos)
1782 pos--;
1783 }
1784 if (pos >= 0)
1785 {
1786 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1787 if (b == -brack)
1788 count--;
1789 else if (b == brack)
1790 count++;
1791 }
1792 else
1793 {
1794 rl_ding ();
1795 return 1;
1796 }
1797 }
1798 }
1799 else
1800 { /* brack > 0 */
1801 while (count)
1802 {
1803 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1804 pos++;
1805 else
1806 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1807
1808 if (pos < rl_end)
1809 {
1810 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1811 if (b == -brack)
1812 count--;
1813 else if (b == brack)
1814 count++;
1815 }
1816 else
1817 {
1818 rl_ding ();
1819 return 1;
1820 }
1821 }
1822 }
1823 rl_point = pos;
1824 return (0);
1825 }
1826
1827 int
1828 rl_vi_bracktype (c)
1829 int c;
1830 {
1831 switch (c)
1832 {
1833 case '(': return 1;
1834 case ')': return -1;
1835 case '[': return 2;
1836 case ']': return -2;
1837 case '{': return 3;
1838 case '}': return -3;
1839 default: return 0;
1840 }
1841 }
1842
1843 static int
1844 _rl_vi_change_char (count, c, mb)
1845 int count, c;
1846 char *mb;
1847 {
1848 int p;
1849
1850 if (c == '\033' || c == CTRL ('C'))
1851 return -1;
1852
1853 rl_begin_undo_group ();
1854 while (count-- && rl_point < rl_end)
1855 {
1856 p = rl_point;
1857 rl_vi_delete (1, c);
1858 if (rl_point < p) /* Did we retreat at EOL? */
1859 rl_point++;
1860 #if defined (HANDLE_MULTIBYTE)
1861 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1862 rl_insert_text (mb);
1863 else
1864 #endif
1865 _rl_insert_char (1, c);
1866 }
1867
1868 /* The cursor shall be left on the last character changed. */
1869 rl_backward_char (1, c);
1870
1871 rl_end_undo_group ();
1872
1873 return (0);
1874 }
1875
1876 static int
1877 _rl_vi_callback_getchar (mb, mlen)
1878 char *mb;
1879 int mlen;
1880 {
1881 int c;
1882
1883 RL_SETSTATE(RL_STATE_MOREINPUT);
1884 c = rl_read_key ();
1885 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1886
1887 if (c < 0)
1888 return -1;
1889
1890 #if defined (HANDLE_MULTIBYTE)
1891 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1892 c = _rl_read_mbstring (c, mb, mlen);
1893 #endif
1894
1895 return c;
1896 }
1897
1898 #if defined (READLINE_CALLBACKS)
1899 static int
1900 _rl_vi_callback_change_char (data)
1901 _rl_callback_generic_arg *data;
1902 {
1903 int c;
1904 char mb[MB_LEN_MAX];
1905
1906 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1907
1908 if (c < 0)
1909 return -1;
1910
1911 _rl_callback_func = 0;
1912 _rl_want_redisplay = 1;
1913
1914 return (_rl_vi_change_char (data->count, c, mb));
1915 }
1916 #endif
1917
1918 int
1919 rl_vi_change_char (count, key)
1920 int count, key;
1921 {
1922 int c;
1923 char mb[MB_LEN_MAX];
1924
1925 if (vi_redoing)
1926 {
1927 c = _rl_vi_last_replacement;
1928 mb[0] = c;
1929 mb[1] = '\0';
1930 }
1931 #if defined (READLINE_CALLBACKS)
1932 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1933 {
1934 _rl_callback_data = _rl_callback_data_alloc (count);
1935 _rl_callback_func = _rl_vi_callback_change_char;
1936 return (0);
1937 }
1938 #endif
1939 else
1940 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1941
1942 if (c < 0)
1943 return -1;
1944
1945 return (_rl_vi_change_char (count, c, mb));
1946 }
1947
1948 int
1949 rl_vi_subst (count, key)
1950 int count, key;
1951 {
1952 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1953 if (vi_redoing == 0)
1954 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1955
1956 return (rl_vi_change_to (count, 'c'));
1957 }
1958
1959 int
1960 rl_vi_overstrike (count, key)
1961 int count, key;
1962 {
1963 if (_rl_vi_doing_insert == 0)
1964 {
1965 _rl_vi_doing_insert = 1;
1966 rl_begin_undo_group ();
1967 }
1968
1969 if (count > 0)
1970 {
1971 _rl_overwrite_char (count, key);
1972 vi_replace_count += count;
1973 }
1974
1975 return (0);
1976 }
1977
1978 int
1979 rl_vi_overstrike_delete (count, key)
1980 int count, key;
1981 {
1982 int i, s;
1983
1984 for (i = 0; i < count; i++)
1985 {
1986 if (vi_replace_count == 0)
1987 {
1988 rl_ding ();
1989 break;
1990 }
1991 s = rl_point;
1992
1993 if (rl_do_undo ())
1994 vi_replace_count--;
1995
1996 if (rl_point == s)
1997 rl_backward_char (1, key);
1998 }
1999
2000 if (vi_replace_count == 0 && _rl_vi_doing_insert)
2001 {
2002 rl_end_undo_group ();
2003 rl_do_undo ();
2004 _rl_vi_doing_insert = 0;
2005 }
2006 return (0);
2007 }
2008
2009 int
2010 rl_vi_replace (count, key)
2011 int count, key;
2012 {
2013 int i;
2014
2015 vi_replace_count = 0;
2016
2017 if (vi_replace_map == 0)
2018 {
2019 vi_replace_map = rl_make_bare_keymap ();
2020
2021 for (i = 0; i < ' '; i++)
2022 if (vi_insertion_keymap[i].type == ISFUNC)
2023 vi_replace_map[i].function = vi_insertion_keymap[i].function;
2024
2025 for (i = ' '; i < KEYMAP_SIZE; i++)
2026 vi_replace_map[i].function = rl_vi_overstrike;
2027
2028 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
2029
2030 /* Make sure these are what we want. */
2031 vi_replace_map[ESC].function = rl_vi_movement_mode;
2032 vi_replace_map[RETURN].function = rl_newline;
2033 vi_replace_map[NEWLINE].function = rl_newline;
2034
2035 /* If the normal vi insertion keymap has ^H bound to erase, do the
2036 same here. Probably should remove the assignment to RUBOUT up
2037 there, but I don't think it will make a difference in real life. */
2038 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
2039 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
2040 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
2041
2042 }
2043
2044 rl_vi_start_inserting (key, 1, rl_arg_sign);
2045
2046 _rl_vi_last_key_before_insert = key;
2047 _rl_keymap = vi_replace_map;
2048
2049 return (0);
2050 }
2051
2052 #if 0
2053 /* Try to complete the word we are standing on or the word that ends with
2054 the previous character. A space matches everything. Word delimiters are
2055 space and ;. */
2056 int
2057 rl_vi_possible_completions()
2058 {
2059 int save_pos = rl_point;
2060
2061 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
2062 {
2063 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
2064 rl_line_buffer[rl_point] != ';')
2065 rl_point++;
2066 }
2067 else if (rl_line_buffer[rl_point - 1] == ';')
2068 {
2069 rl_ding ();
2070 return (0);
2071 }
2072
2073 rl_possible_completions ();
2074 rl_point = save_pos;
2075
2076 return (0);
2077 }
2078 #endif
2079
2080 /* Functions to save and restore marks. */
2081 static int
2082 _rl_vi_set_mark ()
2083 {
2084 int ch;
2085
2086 RL_SETSTATE(RL_STATE_MOREINPUT);
2087 ch = rl_read_key ();
2088 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2089
2090 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2091 {
2092 rl_ding ();
2093 return 1;
2094 }
2095 ch -= 'a';
2096 vi_mark_chars[ch] = rl_point;
2097 return 0;
2098 }
2099
2100 #if defined (READLINE_CALLBACKS)
2101 static int
2102 _rl_vi_callback_set_mark (data)
2103 _rl_callback_generic_arg *data;
2104 {
2105 _rl_callback_func = 0;
2106 _rl_want_redisplay = 1;
2107
2108 return (_rl_vi_set_mark ());
2109 }
2110 #endif
2111
2112 int
2113 rl_vi_set_mark (count, key)
2114 int count, key;
2115 {
2116 #if defined (READLINE_CALLBACKS)
2117 if (RL_ISSTATE (RL_STATE_CALLBACK))
2118 {
2119 _rl_callback_data = 0;
2120 _rl_callback_func = _rl_vi_callback_set_mark;
2121 return (0);
2122 }
2123 #endif
2124
2125 return (_rl_vi_set_mark ());
2126 }
2127
2128 static int
2129 _rl_vi_goto_mark ()
2130 {
2131 int ch;
2132
2133 RL_SETSTATE(RL_STATE_MOREINPUT);
2134 ch = rl_read_key ();
2135 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2136
2137 if (ch == '`')
2138 {
2139 rl_point = rl_mark;
2140 return 0;
2141 }
2142 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2143 {
2144 rl_ding ();
2145 return 1;
2146 }
2147
2148 ch -= 'a';
2149 if (vi_mark_chars[ch] == -1)
2150 {
2151 rl_ding ();
2152 return 1;
2153 }
2154 rl_point = vi_mark_chars[ch];
2155 return 0;
2156 }
2157
2158 #if defined (READLINE_CALLBACKS)
2159 static int
2160 _rl_vi_callback_goto_mark (data)
2161 _rl_callback_generic_arg *data;
2162 {
2163 _rl_callback_func = 0;
2164 _rl_want_redisplay = 1;
2165
2166 return (_rl_vi_goto_mark ());
2167 }
2168 #endif
2169
2170 int
2171 rl_vi_goto_mark (count, key)
2172 int count, key;
2173 {
2174 #if defined (READLINE_CALLBACKS)
2175 if (RL_ISSTATE (RL_STATE_CALLBACK))
2176 {
2177 _rl_callback_data = 0;
2178 _rl_callback_func = _rl_vi_callback_goto_mark;
2179 return (0);
2180 }
2181 #endif
2182
2183 return (_rl_vi_goto_mark ());
2184 }
2185 #endif /* VI_MODE */
This page took 0.122124 seconds and 4 git commands to generate.