d0b931079c59b0fdb3788b9788c582201cc0d76c
[platform/upstream/bash.git] / lib / 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, 1989, 1992 Free Software Foundation, Inc.
5
6    This file is part of the GNU Readline Library, a library for
7    reading lines of text with interactive input and history editing.
8
9    The GNU Readline Library is free software; you can redistribute it
10    and/or modify it under the terms of the GNU General Public License
11    as published by the Free Software Foundation; either version 1, or
12    (at your option) any later version.
13
14    The GNU Readline Library is distributed in the hope that it will be
15    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    The GNU General Public License is often shipped with GNU software, and
20    is generally kept in a file called COPYING or LICENSE.  If you do not
21    have a copy of the license, write to the Free Software Foundation,
22    675 Mass Ave, Cambridge, MA 02139, USA. */
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 #include <sys/types.h>
35
36 #if defined (HAVE_STDLIB_H)
37 #  include <stdlib.h>
38 #else
39 #  include "ansi_stdlib.h"
40 #endif /* HAVE_STDLIB_H */
41
42 #if defined (HAVE_UNISTD_H)
43 #  include <unistd.h>
44 #endif
45
46 #include <stdio.h>
47
48 /* Some standard library routines. */
49 #include "rldefs.h"
50 #include "readline.h"
51 #include "history.h"
52
53 #ifndef digit_p
54 #define digit_p(c)  ((c) >= '0' && (c) <= '9')
55 #endif
56
57 #ifndef digit_value
58 #define digit_value(c) ((c) - '0')
59 #endif
60
61 #ifndef member
62 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
63 #endif
64
65 #ifndef isident
66 #define isident(c) ((pure_alphabetic (c) || digit_p (c) || c == '_'))
67 #endif
68
69 #ifndef exchange
70 #define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
71 #endif
72
73 #ifndef VI_COMMENT_BEGIN_DEFAULT
74 #define VI_COMMENT_BEGIN_DEFAULT "#"
75 #endif
76
77 #if defined (STATIC_MALLOC)
78 static char *xmalloc (), *xrealloc ();
79 #else
80 extern char *xmalloc (), *xrealloc ();
81 #endif /* STATIC_MALLOC */
82
83 /* Variables imported from readline.c */
84 extern int rl_point, rl_end, rl_mark, rl_done;
85 extern FILE *rl_instream;
86 extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg;
87 extern Keymap _rl_keymap;
88 extern char *rl_prompt;
89 extern char *rl_line_buffer;
90 extern int rl_arg_sign;
91
92 extern void _rl_dispatch ();
93
94 extern void rl_extend_line_buffer ();
95 extern int rl_vi_check ();
96
97 /* Non-zero means enter insertion mode. */
98 static int _rl_vi_doing_insert = 0;
99
100 /* String inserted into the line by rl_vi_comment (). */
101 char *rl_vi_comment_begin = (char *)NULL;
102
103 /* *** UNCLEAN *** */
104 /* Command keys which do movement for xxx_to commands. */
105 static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
106
107 /* Keymap used for vi replace characters.  Created dynamically since
108    rarely used. */
109 static Keymap vi_replace_map = (Keymap)NULL;
110
111 /* The number of characters inserted in the last replace operation. */
112 static int vi_replace_count = 0;
113
114 /* If non-zero, we have text inserted after a c[motion] command that put
115    us implicitly into insert mode.  Some people want this text to be
116    attached to the command so that it is `redoable' with `.'. */
117 static int vi_continued_command = 0;
118
119 static int _rl_vi_last_command = 'i';   /* default `.' puts you in insert mode */
120 static int _rl_vi_last_repeat = 1;
121 static int _rl_vi_last_arg_sign = 1;
122 static int _rl_vi_last_motion = 0;
123 static int _rl_vi_last_search_char = 0;
124 static int _rl_vi_last_replacement = 0;
125
126 static int vi_redoing = 0;
127
128 /* Text modification commands.  These are the `redoable' commands. */
129 static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
130
131 static int rl_digit_loop1 ();
132
133 void
134 _rl_vi_reset_last ()
135 {
136   _rl_vi_last_command = 'i';
137   _rl_vi_last_repeat = 1;
138   _rl_vi_last_arg_sign = 1;
139   _rl_vi_last_motion = 0;
140 }
141
142 void
143 _rl_vi_set_last (key, repeat, sign)
144      int key, repeat, sign;
145 {
146   _rl_vi_last_command = key;
147   _rl_vi_last_repeat = repeat;
148   _rl_vi_last_arg_sign = sign;
149 }
150
151 /* Is the command C a VI mode text modification command? */
152 int
153 rl_vi_textmod_command (c)
154      int c;
155 {
156   return (member (c, vi_textmod));
157 }
158
159 /* Bound to `.'.  Called from command mode, so we know that we have to
160    redo a text modification command.  The default for _rl_vi_last_command
161    puts you back into insert mode. */
162 rl_vi_redo (count, c)
163      int count, c;
164 {
165   if (!rl_explicit_arg)
166     {
167       rl_numeric_arg = _rl_vi_last_repeat;
168       rl_arg_sign = _rl_vi_last_arg_sign;
169     }
170
171   vi_redoing = 1;
172   _rl_dispatch (_rl_vi_last_command, _rl_keymap);
173   vi_redoing = 0;
174
175   return (0);
176 }
177     
178 /* Yank the nth arg from the previous line into this line at point. */
179 rl_vi_yank_arg (count, key)
180      int count, key;
181 {
182   /* Readline thinks that the first word on a line is the 0th, while vi
183      thinks the first word on a line is the 1st.  Compensate. */
184   if (rl_explicit_arg)
185     rl_yank_nth_arg (count - 1, 0);
186   else
187     rl_yank_nth_arg ('$', 0);
188
189   return (0);
190 }
191
192 /* With an argument, move back that many history lines, else move to the
193    beginning of history. */
194 rl_vi_fetch_history (count, c)
195      int count, c;
196 {
197   int current = where_history ();
198
199   /* Giving an argument of n means we want the nth command in the history
200      file.  The command number is interpreted the same way that the bash
201      `history' command does it -- that is, giving an argument count of 450
202      to this command would get the command listed as number 450 in the
203      output of `history'. */
204   if (rl_explicit_arg)
205     {
206       int wanted = history_base + current - count;
207       if (wanted <= 0)
208         rl_beginning_of_history (0, 0);
209       else
210         rl_get_previous_history (wanted);
211     }
212   else
213     rl_beginning_of_history (count, 0);
214   return (0);
215 }
216
217 /* Search again for the last thing searched for. */
218 rl_vi_search_again (count, key)
219      int count, key;
220 {
221   switch (key)
222     {
223     case 'n':
224       rl_noninc_reverse_search_again (count, key);
225       break;
226
227     case 'N':
228       rl_noninc_forward_search_again (count, key);
229       break;
230     }
231   return (0);
232 }
233
234 /* Do a vi style search. */
235 rl_vi_search (count, key)
236      int count, key;
237 {
238   switch (key)
239     {
240     case '?':
241       rl_noninc_forward_search (count, key);
242       break;
243
244     case '/':
245       rl_noninc_reverse_search (count, key);
246       break;
247
248     default:
249       ding ();
250       break;
251     }
252   return (0);
253 }
254
255 /* Completion, from vi's point of view. */
256 rl_vi_complete (ignore, key)
257      int ignore, key;
258 {
259   if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
260     {
261       if (!whitespace (rl_line_buffer[rl_point + 1]))
262         rl_vi_end_word (1, 'E');
263       rl_point++;
264     }
265
266   if (key == '*')
267     rl_complete_internal ('*'); /* Expansion and replacement. */
268   else if (key == '=')
269     rl_complete_internal ('?'); /* List possible completions. */
270   else if (key == '\\')
271     rl_complete_internal (TAB); /* Standard Readline completion. */
272   else
273     rl_complete (0, key);
274
275   if (key == '*' || key == '\\')
276     {
277       _rl_vi_set_last (key, 1, rl_arg_sign);
278       rl_vi_insertion_mode (1, key);
279     }
280   return (0);
281 }
282
283 /* Tilde expansion for vi mode. */
284 rl_vi_tilde_expand (ignore, key)
285      int ignore, key;
286 {
287   rl_tilde_expand (0, key);
288   _rl_vi_set_last (key, 1, rl_arg_sign);        /* XXX */
289   rl_vi_insertion_mode (1, key);
290   return (0);
291 }
292
293 /* Previous word in vi mode. */
294 rl_vi_prev_word (count, key)
295      int count, key;
296 {
297   if (count < 0)
298     return (rl_vi_next_word (-count, key));
299
300   if (rl_point == 0)
301     {
302       ding ();
303       return (0);
304     }
305
306   if (uppercase_p (key))
307     rl_vi_bWord (count);
308   else
309     rl_vi_bword (count);
310
311   return (0);
312 }
313
314 /* Next word in vi mode. */
315 rl_vi_next_word (count, key)
316      int count, key;
317 {
318   if (count < 0)
319     return (rl_vi_prev_word (-count, key));
320
321   if (rl_point >= (rl_end - 1))
322     {
323       ding ();
324       return (0);
325     }
326
327   if (uppercase_p (key))
328     rl_vi_fWord (count);
329   else
330     rl_vi_fword (count);
331   return (0);
332 }
333
334 /* Move to the end of the ?next? word. */
335 rl_vi_end_word (count, key)
336      int count, key;
337 {
338   if (count < 0)
339     {
340       ding ();
341       return -1;
342     }
343
344   if (uppercase_p (key))
345     rl_vi_eWord (count);
346   else
347     rl_vi_eword (count);
348   return (0);
349 }
350
351 /* Move forward a word the way that 'W' does. */
352 rl_vi_fWord (count)
353      int count;
354 {
355   while (count-- && rl_point < (rl_end - 1))
356     {
357       /* Skip until whitespace. */
358       while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
359         rl_point++;
360
361       /* Now skip whitespace. */
362       while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
363         rl_point++;
364     }
365   return (0);
366 }
367
368 rl_vi_bWord (count)
369      int count;
370 {
371   while (count-- && rl_point > 0)
372     {
373       /* If we are at the start of a word, move back to whitespace so
374          we will go back to the start of the previous word. */
375       if (!whitespace (rl_line_buffer[rl_point]) &&
376           whitespace (rl_line_buffer[rl_point - 1]))
377         rl_point--;
378
379       while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
380         rl_point--;
381
382       if (rl_point > 0)
383         {
384           while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
385           rl_point++;
386         }
387     }
388   return (0);
389 }
390
391 rl_vi_eWord (count)
392      int count;
393 {
394   while (count-- && rl_point < (rl_end - 1))
395     {
396       if (!whitespace (rl_line_buffer[rl_point]))
397         rl_point++;
398
399       /* Move to the next non-whitespace character (to the start of the
400          next word). */
401       while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
402
403       if (rl_point && rl_point < rl_end)
404         {
405           /* Skip whitespace. */
406           while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
407             rl_point++;
408
409           /* Skip until whitespace. */
410           while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
411             rl_point++;
412
413           /* Move back to the last character of the word. */
414           rl_point--;
415         }
416     }
417   return (0);
418 }
419
420 rl_vi_fword (count)
421      int count;
422 {
423   while (count-- && rl_point < (rl_end - 1))
424     {
425       /* Move to white space (really non-identifer). */
426       if (isident (rl_line_buffer[rl_point]))
427         {
428           while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
429             rl_point++;
430         }
431       else /* if (!whitespace (rl_line_buffer[rl_point])) */
432         {
433           while (!isident (rl_line_buffer[rl_point]) &&
434                  !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
435             rl_point++;
436         }
437
438       /* Move past whitespace. */
439       while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
440         rl_point++;
441     }
442   return (0);
443 }
444
445 rl_vi_bword (count)
446      int count;
447 {
448   while (count-- && rl_point > 0)
449     {
450       int last_is_ident;
451
452       /* If we are at the start of a word, move back to whitespace
453          so we will go back to the start of the previous word. */
454       if (!whitespace (rl_line_buffer[rl_point]) &&
455           whitespace (rl_line_buffer[rl_point - 1]))
456         rl_point--;
457
458       /* If this character and the previous character are `opposite', move
459          back so we don't get messed up by the rl_point++ down there in
460          the while loop.  Without this code, words like `l;' screw up the
461          function. */
462       last_is_ident = isident (rl_line_buffer[rl_point - 1]);
463       if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
464           (!isident (rl_line_buffer[rl_point]) && last_is_ident))
465         rl_point--;
466
467       while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
468         rl_point--;
469
470       if (rl_point > 0)
471         {
472           if (isident (rl_line_buffer[rl_point]))
473             while (--rl_point >= 0 && isident (rl_line_buffer[rl_point]));
474           else
475             while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) &&
476                    !whitespace (rl_line_buffer[rl_point]));
477           rl_point++;
478         }
479     }
480   return (0);
481 }
482
483 rl_vi_eword (count)
484      int count;
485 {
486   while (count-- && rl_point < rl_end - 1)
487     {
488       if (!whitespace (rl_line_buffer[rl_point]))
489         rl_point++;
490
491       while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
492         rl_point++;
493
494       if (rl_point < rl_end)
495         {
496           if (isident (rl_line_buffer[rl_point]))
497             while (++rl_point < rl_end && isident (rl_line_buffer[rl_point]));
498           else
499             while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point])
500                    && !whitespace (rl_line_buffer[rl_point]));
501         }
502       rl_point--;
503     }
504   return (0);
505 }
506
507 rl_vi_insert_beg (count, key)
508      int count, key;
509 {
510   rl_beg_of_line (1, key);
511   rl_vi_insertion_mode (1, key);
512   return (0);
513 }
514
515 rl_vi_append_mode (count, key)
516      int count, key;
517 {
518   if (rl_point < rl_end)
519     rl_point++;
520   rl_vi_insertion_mode (1, key);
521   return (0);
522 }
523
524 rl_vi_append_eol (count, key)
525      int count, key;
526 {
527   rl_end_of_line (1, key);
528   rl_vi_append_mode (1, key);
529   return (0);
530 }
531
532 /* What to do in the case of C-d. */
533 rl_vi_eof_maybe (count, c)
534      int count, c;
535 {
536   return (rl_newline (1, '\n'));
537 }
538
539 /* Insertion mode stuff. */
540
541 /* Switching from one mode to the other really just involves
542    switching keymaps. */
543 rl_vi_insertion_mode (count, key)
544      int count, key;
545 {
546   _rl_keymap = vi_insertion_keymap;
547   return (0);
548 }
549
550 void
551 _rl_vi_done_inserting ()
552 {
553   if (_rl_vi_doing_insert)
554     {
555       rl_end_undo_group ();
556       /* Now, the text between rl_undo_list->next->start and
557          rl_undo_list->next->end is what was inserted while in insert
558          mode. */
559       _rl_vi_doing_insert = 0;
560       vi_continued_command = 1;
561     }
562   else
563     vi_continued_command = 0;
564 }
565
566 rl_vi_movement_mode (count, key)
567      int count, key;
568 {
569   if (rl_point > 0)
570     rl_backward (1);
571
572 #if 0
573   _rl_vi_reset_last ();
574 #endif
575
576   _rl_keymap = vi_movement_keymap;
577   _rl_vi_done_inserting ();
578   return (0);
579 }
580
581 rl_vi_arg_digit (count, c)
582      int count, c;
583 {
584   if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
585     return (rl_beg_of_line ());
586   else
587     return (rl_digit_argument (count, c));
588 }
589
590 rl_vi_change_case (count, ignore)
591      int count, ignore;
592 {
593   char c = 0;
594
595   /* Don't try this on an empty line. */
596   if (rl_point >= rl_end)
597     return (0);
598
599   while (count-- && rl_point < rl_end)
600     {
601       if (uppercase_p (rl_line_buffer[rl_point]))
602         c = to_lower (rl_line_buffer[rl_point]);
603       else if (lowercase_p (rl_line_buffer[rl_point]))
604         c = to_upper (rl_line_buffer[rl_point]);
605       else
606         {
607           /* Just skip over characters neither upper nor lower case. */
608           rl_forward (1);
609           continue;
610         }
611
612       /* Vi is kind of strange here. */
613       if (c)
614         {
615           rl_begin_undo_group ();
616           rl_delete (1, c);
617           rl_insert (1, c);
618           rl_end_undo_group ();
619           rl_vi_check ();
620         }
621       else
622         rl_forward (1);
623     }
624   return (0);
625 }
626
627 rl_vi_put (count, key)
628      int count, key;
629 {
630   if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
631     rl_point++;
632
633   rl_yank ();
634   rl_backward (1);
635   return (0);
636 }
637
638 rl_vi_check ()
639 {
640   if (rl_point && rl_point == rl_end)
641     rl_point--;
642   return (0);
643 }
644
645 rl_vi_column (count, key)
646      int count, key;
647 {
648   if (count > rl_end)
649     rl_end_of_line ();
650   else
651     rl_point = count - 1;
652   return (0);
653 }
654
655 int
656 rl_vi_domove (key, nextkey)
657      int key, *nextkey;
658 {
659   int c, save;
660   int old_end;
661
662   rl_mark = rl_point;
663   c = rl_read_key ();
664   *nextkey = c;
665
666   if (!member (c, vi_motion))
667     {
668       if (digit_p (c))
669         {
670           save = rl_numeric_arg;
671           rl_numeric_arg = digit_value (c);
672           rl_digit_loop1 ();
673           rl_numeric_arg *= save;
674           c = rl_read_key ();   /* real command */
675           *nextkey = c;
676         }
677       else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
678         {
679           rl_mark = rl_end;
680           rl_beg_of_line ();
681           _rl_vi_last_motion = c;
682           return (0);
683         }
684       else
685         return (-1);
686     }
687
688   _rl_vi_last_motion = c;
689
690   /* Append a blank character temporarily so that the motion routines
691      work right at the end of the line. */
692   old_end = rl_end;
693   rl_line_buffer[rl_end++] = ' ';
694   rl_line_buffer[rl_end] = '\0';
695
696   _rl_dispatch (c, _rl_keymap);
697
698   /* Remove the blank that we added. */
699   rl_end = old_end;
700   rl_line_buffer[rl_end] = '\0';
701   if (rl_point > rl_end)
702     rl_point = rl_end;
703
704   /* No change in position means the command failed. */
705   if (rl_mark == rl_point)
706     return (-1);
707
708   /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
709      word.  If we are not at the end of the line, and we are on a
710      non-whitespace character, move back one (presumably to whitespace). */
711   if ((to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
712       !whitespace (rl_line_buffer[rl_point]))
713     rl_point--;
714
715   /* If cw or cW, back up to the end of a word, so the behaviour of ce
716      or cE is the actual result.  Brute-force, no subtlety. */
717   if (key == 'c' && rl_point >= rl_mark && (to_upper (c) == 'W'))
718     {
719       /* Don't move farther back than where we started. */
720       while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
721         rl_point--;
722
723       /* Posix.2 says that if cw or cW moves the cursor towards the end of
724          the line, the character under the cursor should be deleted. */
725       if (rl_point == rl_mark)
726         rl_point++;
727       else
728         {
729           /* Move past the end of the word so that the kill doesn't
730              remove the last letter of the previous word.  Only do this
731              if we are not at the end of the line. */
732           if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
733             rl_point++;
734         }
735     }
736
737   if (rl_mark < rl_point)
738     exchange (rl_point, rl_mark);
739
740   return (0);
741 }
742
743 /* A simplified loop for vi. Don't dispatch key at end.
744    Don't recognize minus sign? */
745 static int
746 rl_digit_loop1 ()
747 {
748   int key, c;
749
750   while (1)
751     {
752       rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0);
753       key = c = rl_read_key ();
754
755       if (_rl_keymap[c].type == ISFUNC &&
756           _rl_keymap[c].function == rl_universal_argument)
757         {
758           rl_numeric_arg *= 4;
759           continue;
760         }
761
762       c = UNMETA (c);
763       if (digit_p (c))
764         {
765           if (rl_explicit_arg)
766             rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c);
767           else
768             rl_numeric_arg = digit_value (c);
769           rl_explicit_arg = 1;
770         }
771       else
772         {
773           rl_clear_message ();
774           rl_stuff_char (key);
775           break;
776         }
777     }
778   return (0);
779 }
780
781 rl_vi_delete_to (count, key)
782      int count, key;
783 {
784   int c;
785
786   if (uppercase_p (key))
787     rl_stuff_char ('$');
788   else if (vi_redoing)
789     rl_stuff_char (_rl_vi_last_motion);
790
791   if (rl_vi_domove (key, &c))
792     {
793       ding ();
794       return -1;
795     }
796
797   /* These are the motion commands that do not require adjusting the
798      mark. */
799   if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
800     rl_mark++;
801
802   rl_kill_text (rl_point, rl_mark);
803   return (0);
804 }
805
806 rl_vi_change_to (count, key)
807      int count, key;
808 {
809   int c, start_pos;
810
811   if (uppercase_p (key))
812     rl_stuff_char ('$');
813   else if (vi_redoing)
814     rl_stuff_char (_rl_vi_last_motion);
815
816   start_pos = rl_point;
817
818   if (rl_vi_domove (key, &c))
819     {
820       ding ();
821       return -1;
822     }
823
824   /* These are the motion commands that do not require adjusting the
825      mark.  c[wW] are handled by special-case code in rl_vi_domove(),
826      and already leave the mark at the correct location. */
827   if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
828     rl_mark++;
829
830   /* The cursor never moves with c[wW]. */
831   if ((to_upper (c) == 'W') && rl_point < start_pos)
832     rl_point = start_pos;
833
834   rl_kill_text (rl_point, rl_mark);
835
836   rl_begin_undo_group ();
837   _rl_vi_doing_insert = 1;
838   _rl_vi_set_last (key, count, rl_arg_sign);
839   rl_vi_insertion_mode (1, key);
840
841   return (0);
842 }
843
844 rl_vi_yank_to (count, key)
845      int count, key;
846 {
847   int c, save = rl_point;
848
849   if (uppercase_p (key))
850     rl_stuff_char ('$');
851
852   if (rl_vi_domove (key, &c))
853     {
854       ding ();
855       return -1;
856     }
857
858   /* These are the motion commands that do not require adjusting the
859      mark. */
860   if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
861     rl_mark++;
862
863   rl_begin_undo_group ();
864   rl_kill_text (rl_point, rl_mark);
865   rl_end_undo_group ();
866   rl_do_undo ();
867   rl_point = save;
868
869   return (0);
870 }
871
872 rl_vi_delete (count, key)
873      int count, key;
874 {
875   int end;
876
877   if (rl_end == 0)
878     {
879       ding ();
880       return -1;
881     }
882
883   end = rl_point + count;
884
885   if (end >= rl_end)
886     end = rl_end;
887
888   rl_kill_text (rl_point, end);
889   
890   if (rl_point > 0 && rl_point == rl_end)
891     rl_backward (1);
892   return (0);
893 }
894
895 /* Turn the current line into a comment in shell history.
896    A K*rn shell style function. */
897 rl_vi_comment (count, key)
898      int count, key;
899 {
900   rl_beg_of_line ();
901
902   if (rl_vi_comment_begin != (char *)NULL)
903     rl_insert_text (rl_vi_comment_begin);
904   else
905     rl_insert_text (VI_COMMENT_BEGIN_DEFAULT);  /* Default. */
906
907   rl_redisplay ();
908   rl_newline (1, '\n');
909   return (0);
910 }
911
912 rl_vi_first_print (count, key)
913      int count, key;
914 {
915   return (rl_back_to_indent ());
916 }
917
918 rl_back_to_indent (ignore1, ignore2)
919      int ignore1, ignore2;
920 {
921   rl_beg_of_line ();
922   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
923     rl_point++;
924   return (0);
925 }
926
927 /* NOTE: it is necessary that opposite directions are inverses */
928 #define FTO      1              /* forward to */
929 #define BTO     -1              /* backward to */
930 #define FFIND    2              /* forward find */
931 #define BFIND   -2              /* backward find */
932
933 rl_vi_char_search (count, key)
934      int count, key;
935 {
936   static char target;
937   static int orig_dir, dir;
938   int pos;
939
940   if (key == ';' || key == ',')
941     dir = (key == ';' ? orig_dir : -orig_dir);
942   else
943     {
944       if (vi_redoing)
945         target = _rl_vi_last_search_char;
946       else
947         _rl_vi_last_search_char = target = rl_getc (rl_instream);
948
949       switch (key)
950         {
951         case 't':
952           orig_dir = dir = FTO;
953           break;
954
955         case 'T':
956           orig_dir = dir = BTO;
957           break;
958
959         case 'f':
960           orig_dir = dir = FFIND;
961           break;
962
963         case 'F':
964           orig_dir = dir = BFIND;
965           break;
966         }
967     }
968
969   pos = rl_point;
970
971   while (count--)
972     {
973       if (dir < 0)
974         {
975           if (pos == 0)
976             {
977               ding ();
978               return -1;
979             }
980
981           pos--;
982           do
983             {
984               if (rl_line_buffer[pos] == target)
985                 {
986                   if (dir == BTO)
987                     rl_point = pos + 1;
988                   else
989                     rl_point = pos;
990                   break;
991                 }
992             }
993           while (pos--);
994
995           if (pos < 0)
996             {
997               ding ();
998               return -1;
999             }
1000         }
1001       else
1002         {                       /* dir > 0 */
1003           if (pos >= rl_end)
1004             {
1005               ding ();
1006               return -1;
1007             }
1008
1009           pos++;
1010           do
1011             {
1012               if (rl_line_buffer[pos] == target)
1013                 {
1014                   if (dir == FTO)
1015                     rl_point = pos - 1;
1016                   else
1017                     rl_point = pos;
1018                   break;
1019                 }
1020             }
1021           while (++pos < rl_end);
1022
1023           if (pos >= (rl_end - 1))
1024             {
1025               ding ();
1026               return -1;
1027             }
1028         }
1029     }
1030   return (0);
1031 }
1032
1033 /* Match brackets */
1034 rl_vi_match (ignore, key)
1035      int ignore, key;
1036 {
1037   int count = 1, brack, pos;
1038
1039   pos = rl_point;
1040   if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1041     {
1042       while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1043              rl_point < rl_end - 1)
1044         rl_forward (1);
1045
1046       if (brack <= 0)
1047         {
1048           rl_point = pos;
1049           ding ();
1050           return -1;
1051         }
1052     }
1053
1054   pos = rl_point;
1055
1056   if (brack < 0)
1057     {
1058       while (count)
1059         {
1060           if (--pos >= 0)
1061             {
1062               int b = rl_vi_bracktype (rl_line_buffer[pos]);
1063               if (b == -brack)
1064                 count--;
1065               else if (b == brack)
1066                 count++;
1067             }
1068           else
1069             {
1070               ding ();
1071               return -1;
1072             }
1073         }
1074     }
1075   else
1076     {                   /* brack > 0 */
1077       while (count)
1078         {
1079           if (++pos < rl_end)
1080             {
1081               int b = rl_vi_bracktype (rl_line_buffer[pos]);
1082               if (b == -brack)
1083                 count--;
1084               else if (b == brack)
1085                 count++;
1086             }
1087           else
1088             {
1089               ding ();
1090               return -1;
1091             }
1092         }
1093     }
1094   rl_point = pos;
1095   return (0);
1096 }
1097
1098 int
1099 rl_vi_bracktype (c)
1100      int c;
1101 {
1102   switch (c)
1103     {
1104     case '(': return  1;
1105     case ')': return -1;
1106     case '[': return  2;
1107     case ']': return -2;
1108     case '{': return  3;
1109     case '}': return -3;
1110     default:  return  0;
1111     }
1112 }
1113
1114 rl_vi_change_char (count, key)
1115      int count, key;
1116 {
1117   int c;
1118
1119   if (vi_redoing)
1120     c = _rl_vi_last_replacement;
1121   else
1122     _rl_vi_last_replacement = c = rl_getc (rl_instream);
1123
1124   if (c == '\033' || c == CTRL ('C'))
1125     return -1;
1126
1127   while (count-- && rl_point < rl_end)
1128     {
1129       rl_begin_undo_group ();
1130
1131       rl_delete (1, c);
1132       rl_insert (1, c);
1133       if (count == 0)
1134         rl_backward (1);
1135
1136       rl_end_undo_group ();
1137     }
1138   return (0);
1139 }
1140
1141 rl_vi_subst (count, key)
1142      int count, key;
1143 {
1144   rl_begin_undo_group ();
1145
1146   if (uppercase_p (key))
1147     {
1148       rl_beg_of_line ();
1149       rl_kill_line (1);
1150     }
1151   else
1152     rl_delete_text (rl_point, rl_point+count);
1153
1154   rl_end_undo_group ();
1155
1156   _rl_vi_set_last (key, count, rl_arg_sign);
1157
1158   rl_begin_undo_group ();
1159   _rl_vi_doing_insert = 1;
1160   rl_vi_insertion_mode (1, key);
1161
1162   return (0);
1163 }
1164
1165 rl_vi_overstrike (count, key)
1166      int count, key;
1167 {
1168   int i;
1169
1170   if (_rl_vi_doing_insert == 0)
1171     {
1172       _rl_vi_doing_insert = 1;
1173       rl_begin_undo_group ();
1174     }
1175
1176   for (i = 0; i < count; i++)
1177     {
1178       vi_replace_count++;
1179       rl_begin_undo_group ();
1180
1181       if (rl_point < rl_end)
1182         {
1183           rl_delete (1, key);
1184           rl_insert (1, key);
1185         }
1186       else
1187         rl_insert (1, key);
1188
1189       rl_end_undo_group ();
1190     }
1191   return (0);
1192 }
1193
1194 rl_vi_overstrike_delete (count)
1195      int count;
1196 {
1197   int i, s;
1198
1199   for (i = 0; i < count; i++)
1200     {
1201       if (vi_replace_count == 0)
1202         {
1203           ding ();
1204           break;
1205         }
1206       s = rl_point;
1207
1208       if (rl_do_undo ())
1209         vi_replace_count--;
1210
1211       if (rl_point == s)
1212         rl_backward (1);
1213     }
1214
1215   if (vi_replace_count == 0 && _rl_vi_doing_insert)
1216     {
1217       rl_end_undo_group ();
1218       rl_do_undo ();
1219       _rl_vi_doing_insert = 0;
1220     }
1221   return (0);
1222 }
1223
1224 rl_vi_replace (count, key)
1225      int count, key;
1226 {
1227   int i;
1228
1229   vi_replace_count = 0;
1230
1231   if (!vi_replace_map)
1232     {
1233       vi_replace_map = rl_make_bare_keymap ();
1234
1235       for (i = ' '; i < KEYMAP_SIZE; i++)
1236         vi_replace_map[i].function = rl_vi_overstrike;
1237
1238       vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1239       vi_replace_map[ESC].function = rl_vi_movement_mode;
1240       vi_replace_map[RETURN].function = rl_newline;
1241       vi_replace_map[NEWLINE].function = rl_newline;
1242
1243       /* If the normal vi insertion keymap has ^H bound to erase, do the
1244          same here.  Probably should remove the assignment to RUBOUT up
1245          there, but I don't think it will make a difference in real life. */
1246       if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1247           vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1248         vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1249
1250     }
1251   _rl_keymap = vi_replace_map;
1252   return (0);
1253 }
1254
1255 #if 0
1256 /* Try to complete the word we are standing on or the word that ends with
1257    the previous character.  A space matches everything.  Word delimiters are
1258    space and ;. */
1259 rl_vi_possible_completions()
1260 {
1261   int save_pos = rl_point;
1262
1263   if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1264     {
1265       while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1266              rl_line_buffer[rl_point] != ';')
1267         rl_point++;
1268     }
1269   else if (rl_line_buffer[rl_point - 1] == ';')
1270     {
1271       ding ();
1272       return (0);
1273     }
1274
1275   rl_possible_completions ();
1276   rl_point = save_pos;
1277
1278   return (0);
1279 }
1280 #endif
1281
1282 #if defined (STATIC_MALLOC)
1283 \f
1284 /* **************************************************************** */
1285 /*                                                                  */
1286 /*                      xmalloc and xrealloc ()                     */
1287 /*                                                                  */
1288 /* **************************************************************** */
1289
1290 static void memory_error_and_abort ();
1291
1292 static char *
1293 xmalloc (bytes)
1294      int bytes;
1295 {
1296   char *temp = (char *)malloc (bytes);
1297
1298   if (!temp)
1299     memory_error_and_abort ();
1300   return (temp);
1301 }
1302
1303 static char *
1304 xrealloc (pointer, bytes)
1305      char *pointer;
1306      int bytes;
1307 {
1308   char *temp;
1309
1310   if (!pointer)
1311     temp = (char *)xmalloc (bytes);
1312   else
1313     temp = (char *)realloc (pointer, bytes);
1314
1315   if (!temp)
1316     memory_error_and_abort ();
1317
1318   return (temp);
1319 }
1320
1321 static void
1322 memory_error_and_abort ()
1323 {
1324   fprintf (stderr, "readline: Out of virtual memory!\n");
1325   abort ();
1326 }
1327 #endif /* STATIC_MALLOC */
1328
1329 #endif /* VI_MODE */