File: | src/gnu/lib/libreadline/vi_mode.c |
Warning: | line 1200, column 4 Value stored to 'tmp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 2, 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 | 59 Temple Place, Suite 330, Boston, MA 02111 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 | #if defined (HAVE_CONFIG_H1) |
35 | # include <config.h> |
36 | #endif |
37 | |
38 | #include <sys/types.h> |
39 | |
40 | #if defined (HAVE_STDLIB_H1) |
41 | # include <stdlib.h> |
42 | #else |
43 | # include "ansi_stdlib.h" |
44 | #endif /* HAVE_STDLIB_H */ |
45 | |
46 | #if defined (HAVE_UNISTD_H1) |
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 *)((void *)0) : 0) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL((void *)0) : 0) |
64 | #endif |
65 | |
66 | /* Non-zero means enter insertion mode. */ |
67 | static int _rl_vi_doing_insert; |
68 | |
69 | /* Command keys which do movement for xxx_to commands. */ |
70 | static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; |
71 | |
72 | /* Keymap used for vi replace characters. Created dynamically since |
73 | rarely used. */ |
74 | static Keymap vi_replace_map; |
75 | |
76 | /* The number of characters inserted in the last replace operation. */ |
77 | static int vi_replace_count; |
78 | |
79 | /* If non-zero, we have text inserted after a c[motion] command that put |
80 | us implicitly into insert mode. Some people want this text to be |
81 | attached to the command so that it is `redoable' with `.'. */ |
82 | static int vi_continued_command; |
83 | static char *vi_insert_buffer; |
84 | static int vi_insert_buffer_size; |
85 | |
86 | static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ |
87 | static int _rl_vi_last_repeat = 1; |
88 | static int _rl_vi_last_arg_sign = 1; |
89 | static int _rl_vi_last_motion; |
90 | #if defined (HANDLE_MULTIBYTE) |
91 | static char _rl_vi_last_search_mbchar[MB_LEN_MAX1]; |
92 | #else |
93 | static int _rl_vi_last_search_char; |
94 | #endif |
95 | static int _rl_vi_last_replacement; |
96 | |
97 | static int _rl_vi_last_key_before_insert; |
98 | |
99 | static int vi_redoing; |
100 | |
101 | /* Text modification commands. These are the `redoable' commands. */ |
102 | static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; |
103 | |
104 | /* Arrays for the saved marks. */ |
105 | static int vi_mark_chars['z' - 'a' + 1]; |
106 | |
107 | static void _rl_vi_stuff_insert PARAMS((int))(int); |
108 | static void _rl_vi_save_insert PARAMS((UNDO_LIST *))(UNDO_LIST *); |
109 | static int rl_digit_loop1 PARAMS((void))(void); |
110 | |
111 | void |
112 | _rl_vi_initialize_line () |
113 | { |
114 | register int i; |
115 | |
116 | for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) |
117 | vi_mark_chars[i] = -1; |
118 | } |
119 | |
120 | void |
121 | _rl_vi_reset_last () |
122 | { |
123 | _rl_vi_last_command = 'i'; |
124 | _rl_vi_last_repeat = 1; |
125 | _rl_vi_last_arg_sign = 1; |
126 | _rl_vi_last_motion = 0; |
127 | } |
128 | |
129 | void |
130 | _rl_vi_set_last (key, repeat, sign) |
131 | int key, repeat, sign; |
132 | { |
133 | _rl_vi_last_command = key; |
134 | _rl_vi_last_repeat = repeat; |
135 | _rl_vi_last_arg_sign = sign; |
136 | } |
137 | |
138 | /* Is the command C a VI mode text modification command? */ |
139 | int |
140 | _rl_vi_textmod_command (c) |
141 | int c; |
142 | { |
143 | return (member (c, vi_textmod)((c) ? (char *)strchr ((vi_textmod), (c)) != (char *)((void * )0) : 0)); |
144 | } |
145 | |
146 | static void |
147 | _rl_vi_stuff_insert (count) |
148 | int count; |
149 | { |
150 | rl_begin_undo_group (); |
151 | while (count--) |
152 | rl_insert_text (vi_insert_buffer); |
153 | rl_end_undo_group (); |
154 | } |
155 | |
156 | /* Bound to `.'. Called from command mode, so we know that we have to |
157 | redo a text modification command. The default for _rl_vi_last_command |
158 | puts you back into insert mode. */ |
159 | int |
160 | rl_vi_redo (count, c) |
161 | int count, c; |
162 | { |
163 | int r; |
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 | r = 0; |
172 | vi_redoing = 1; |
173 | /* If we're redoing an insert with `i', stuff in the inserted text |
174 | and do not go into insertion mode. */ |
175 | if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) |
176 | { |
177 | _rl_vi_stuff_insert (count); |
178 | /* And back up point over the last character inserted. */ |
179 | if (rl_point > 0) |
180 | rl_point--; |
181 | } |
182 | else |
183 | r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); |
184 | vi_redoing = 0; |
185 | |
186 | return (r); |
187 | } |
188 | |
189 | /* A placeholder for further expansion. */ |
190 | int |
191 | rl_vi_undo (count, key) |
192 | int count, key; |
193 | { |
194 | return (rl_undo_command (count, key)); |
195 | } |
196 | |
197 | /* Yank the nth arg from the previous line into this line at point. */ |
198 | int |
199 | rl_vi_yank_arg (count, key) |
200 | int count, key; |
201 | { |
202 | /* Readline thinks that the first word on a line is the 0th, while vi |
203 | thinks the first word on a line is the 1st. Compensate. */ |
204 | if (rl_explicit_arg) |
205 | rl_yank_nth_arg (count - 1, 0); |
206 | else |
207 | rl_yank_nth_arg ('$', 0); |
208 | |
209 | return (0); |
210 | } |
211 | |
212 | /* With an argument, move back that many history lines, else move to the |
213 | beginning of history. */ |
214 | int |
215 | rl_vi_fetch_history (count, c) |
216 | int count, c; |
217 | { |
218 | int wanted; |
219 | |
220 | /* Giving an argument of n means we want the nth command in the history |
221 | file. The command number is interpreted the same way that the bash |
222 | `history' command does it -- that is, giving an argument count of 450 |
223 | to this command would get the command listed as number 450 in the |
224 | output of `history'. */ |
225 | if (rl_explicit_arg) |
226 | { |
227 | wanted = history_base + where_history () - count; |
228 | if (wanted <= 0) |
229 | rl_beginning_of_history (0, 0); |
230 | else |
231 | rl_get_previous_history (wanted, c); |
232 | } |
233 | else |
234 | rl_beginning_of_history (count, 0); |
235 | return (0); |
236 | } |
237 | |
238 | /* Search again for the last thing searched for. */ |
239 | int |
240 | rl_vi_search_again (count, key) |
241 | int count, key; |
242 | { |
243 | switch (key) |
244 | { |
245 | case 'n': |
246 | rl_noninc_reverse_search_again (count, key); |
247 | break; |
248 | |
249 | case 'N': |
250 | rl_noninc_forward_search_again (count, key); |
251 | break; |
252 | } |
253 | return (0); |
254 | } |
255 | |
256 | /* Do a vi style search. */ |
257 | int |
258 | rl_vi_search (count, key) |
259 | int count, key; |
260 | { |
261 | switch (key) |
262 | { |
263 | case '?': |
264 | rl_noninc_forward_search (count, key); |
265 | break; |
266 | |
267 | case '/': |
268 | rl_noninc_reverse_search (count, key); |
269 | break; |
270 | |
271 | default: |
272 | rl_ding (); |
273 | break; |
274 | } |
275 | return (0); |
276 | } |
277 | |
278 | /* Completion, from vi's point of view. */ |
279 | int |
280 | rl_vi_complete (ignore, key) |
281 | int ignore, key; |
282 | { |
283 | if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')))) |
284 | { |
285 | if (!whitespace (rl_line_buffer[rl_point + 1])(((rl_line_buffer[rl_point + 1]) == ' ') || ((rl_line_buffer[ rl_point + 1]) == '\t'))) |
286 | rl_vi_end_word (1, 'E'); |
287 | rl_point++; |
288 | } |
289 | |
290 | if (key == '*') |
291 | rl_complete_internal ('*'); /* Expansion and replacement. */ |
292 | else if (key == '=') |
293 | rl_complete_internal ('?'); /* List possible completions. */ |
294 | else if (key == '\\') |
295 | rl_complete_internal (TAB'\t'); /* Standard Readline completion. */ |
296 | else |
297 | rl_complete (0, key); |
298 | |
299 | if (key == '*' || key == '\\') |
300 | { |
301 | _rl_vi_set_last (key, 1, rl_arg_sign); |
302 | rl_vi_insertion_mode (1, key); |
303 | } |
304 | return (0); |
305 | } |
306 | |
307 | /* Tilde expansion for vi mode. */ |
308 | int |
309 | rl_vi_tilde_expand (ignore, key) |
310 | int ignore, key; |
311 | { |
312 | rl_tilde_expand (0, key); |
313 | _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ |
314 | rl_vi_insertion_mode (1, key); |
315 | return (0); |
316 | } |
317 | |
318 | /* Previous word in vi mode. */ |
319 | int |
320 | rl_vi_prev_word (count, key) |
321 | int count, key; |
322 | { |
323 | if (count < 0) |
324 | return (rl_vi_next_word (-count, key)); |
325 | |
326 | if (rl_point == 0) |
327 | { |
328 | rl_ding (); |
329 | return (0); |
330 | } |
331 | |
332 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
333 | rl_vi_bWord (count, key); |
334 | else |
335 | rl_vi_bword (count, key); |
336 | |
337 | return (0); |
338 | } |
339 | |
340 | /* Next word in vi mode. */ |
341 | int |
342 | rl_vi_next_word (count, key) |
343 | int count, key; |
344 | { |
345 | if (count < 0) |
346 | return (rl_vi_prev_word (-count, key)); |
347 | |
348 | if (rl_point >= (rl_end - 1)) |
349 | { |
350 | rl_ding (); |
351 | return (0); |
352 | } |
353 | |
354 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
355 | rl_vi_fWord (count, key); |
356 | else |
357 | rl_vi_fword (count, key); |
358 | return (0); |
359 | } |
360 | |
361 | /* Move to the end of the ?next? word. */ |
362 | int |
363 | rl_vi_end_word (count, key) |
364 | int count, key; |
365 | { |
366 | if (count < 0) |
367 | { |
368 | rl_ding (); |
369 | return -1; |
370 | } |
371 | |
372 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
373 | rl_vi_eWord (count, key); |
374 | else |
375 | rl_vi_eword (count, key); |
376 | return (0); |
377 | } |
378 | |
379 | /* Move forward a word the way that 'W' does. */ |
380 | int |
381 | rl_vi_fWord (count, ignore) |
382 | int count, ignore; |
383 | { |
384 | while (count-- && rl_point < (rl_end - 1)) |
385 | { |
386 | /* Skip until whitespace. */ |
387 | while (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && rl_point < rl_end) |
388 | rl_point++; |
389 | |
390 | /* Now skip whitespace. */ |
391 | while (whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && rl_point < rl_end) |
392 | rl_point++; |
393 | } |
394 | return (0); |
395 | } |
396 | |
397 | int |
398 | rl_vi_bWord (count, ignore) |
399 | int count, ignore; |
400 | { |
401 | while (count-- && rl_point > 0) |
402 | { |
403 | /* If we are at the start of a word, move back to whitespace so |
404 | we will go back to the start of the previous word. */ |
405 | if (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && |
406 | whitespace (rl_line_buffer[rl_point - 1])(((rl_line_buffer[rl_point - 1]) == ' ') || ((rl_line_buffer[ rl_point - 1]) == '\t'))) |
407 | rl_point--; |
408 | |
409 | while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
410 | rl_point--; |
411 | |
412 | if (rl_point > 0) |
413 | { |
414 | while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))); |
415 | rl_point++; |
416 | } |
417 | } |
418 | return (0); |
419 | } |
420 | |
421 | int |
422 | rl_vi_eWord (count, ignore) |
423 | int count, ignore; |
424 | { |
425 | while (count-- && rl_point < (rl_end - 1)) |
426 | { |
427 | if (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
428 | rl_point++; |
429 | |
430 | /* Move to the next non-whitespace character (to the start of the |
431 | next word). */ |
432 | while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))); |
433 | |
434 | if (rl_point && rl_point < rl_end) |
435 | { |
436 | /* Skip whitespace. */ |
437 | while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
438 | rl_point++; |
439 | |
440 | /* Skip until whitespace. */ |
441 | while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
442 | rl_point++; |
443 | |
444 | /* Move back to the last character of the word. */ |
445 | rl_point--; |
446 | } |
447 | } |
448 | return (0); |
449 | } |
450 | |
451 | int |
452 | rl_vi_fword (count, ignore) |
453 | int count, ignore; |
454 | { |
455 | while (count-- && rl_point < (rl_end - 1)) |
456 | { |
457 | /* Move to white space (really non-identifer). */ |
458 | if (_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_')) |
459 | { |
460 | while (_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') && rl_point < rl_end) |
461 | rl_point++; |
462 | } |
463 | else /* if (!whitespace (rl_line_buffer[rl_point])) */ |
464 | { |
465 | while (!_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') && |
466 | !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && rl_point < rl_end) |
467 | rl_point++; |
468 | } |
469 | |
470 | /* Move past whitespace. */ |
471 | while (whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && rl_point < rl_end) |
472 | rl_point++; |
473 | } |
474 | return (0); |
475 | } |
476 | |
477 | int |
478 | rl_vi_bword (count, ignore) |
479 | int count, ignore; |
480 | { |
481 | while (count-- && rl_point > 0) |
482 | { |
483 | int last_is_ident; |
484 | |
485 | /* If we are at the start of a word, move back to whitespace |
486 | so we will go back to the start of the previous word. */ |
487 | if (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t')) && |
488 | whitespace (rl_line_buffer[rl_point - 1])(((rl_line_buffer[rl_point - 1]) == ' ') || ((rl_line_buffer[ rl_point - 1]) == '\t'))) |
489 | rl_point--; |
490 | |
491 | /* If this character and the previous character are `opposite', move |
492 | back so we don't get messed up by the rl_point++ down there in |
493 | the while loop. Without this code, words like `l;' screw up the |
494 | function. */ |
495 | last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1])((isascii(rl_line_buffer[rl_point - 1]) && isalnum (rl_line_buffer [rl_point - 1])) || (rl_line_buffer[rl_point - 1]) == '_'); |
496 | if ((_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') && !last_is_ident) || |
497 | (!_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') && last_is_ident)) |
498 | rl_point--; |
499 | |
500 | while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
501 | rl_point--; |
502 | |
503 | if (rl_point > 0) |
504 | { |
505 | if (_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_')) |
506 | while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_')); |
507 | else |
508 | while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') && |
509 | !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))); |
510 | rl_point++; |
511 | } |
512 | } |
513 | return (0); |
514 | } |
515 | |
516 | int |
517 | rl_vi_eword (count, ignore) |
518 | int count, ignore; |
519 | { |
520 | while (count-- && rl_point < rl_end - 1) |
521 | { |
522 | if (!whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
523 | rl_point++; |
524 | |
525 | while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
526 | rl_point++; |
527 | |
528 | if (rl_point < rl_end) |
529 | { |
530 | if (_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_')) |
531 | while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_')); |
532 | else |
533 | while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])((isascii(rl_line_buffer[rl_point]) && isalnum (rl_line_buffer [rl_point])) || (rl_line_buffer[rl_point]) == '_') |
534 | && !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))); |
535 | } |
536 | rl_point--; |
537 | } |
538 | return (0); |
539 | } |
540 | |
541 | int |
542 | rl_vi_insert_beg (count, key) |
543 | int count, key; |
544 | { |
545 | rl_beg_of_line (1, key); |
546 | rl_vi_insertion_mode (1, key); |
547 | return (0); |
548 | } |
549 | |
550 | int |
551 | rl_vi_append_mode (count, key) |
552 | int count, key; |
553 | { |
554 | if (rl_point < rl_end) |
555 | { |
556 | if (MB_CUR_MAX1 == 1 || rl_byte_oriented) |
557 | rl_point++; |
558 | else |
559 | { |
560 | int point = rl_point; |
561 | rl_forward_char (1, key); |
562 | if (point == rl_point) |
563 | rl_point = rl_end; |
564 | } |
565 | } |
566 | rl_vi_insertion_mode (1, key); |
567 | return (0); |
568 | } |
569 | |
570 | int |
571 | rl_vi_append_eol (count, key) |
572 | int count, key; |
573 | { |
574 | rl_end_of_line (1, key); |
575 | rl_vi_append_mode (1, key); |
576 | return (0); |
577 | } |
578 | |
579 | /* What to do in the case of C-d. */ |
580 | int |
581 | rl_vi_eof_maybe (count, c) |
582 | int count, c; |
583 | { |
584 | return (rl_newline (1, '\n')); |
585 | } |
586 | |
587 | /* Insertion mode stuff. */ |
588 | |
589 | /* Switching from one mode to the other really just involves |
590 | switching keymaps. */ |
591 | int |
592 | rl_vi_insertion_mode (count, key) |
593 | int count, key; |
594 | { |
595 | _rl_keymap = vi_insertion_keymap; |
596 | _rl_vi_last_key_before_insert = key; |
597 | return (0); |
598 | } |
599 | |
600 | static void |
601 | _rl_vi_save_insert (up) |
602 | UNDO_LIST *up; |
603 | { |
604 | int len, start, end; |
605 | |
606 | if (up == 0) |
607 | { |
608 | if (vi_insert_buffer_size >= 1) |
609 | vi_insert_buffer[0] = '\0'; |
610 | return; |
611 | } |
612 | |
613 | start = up->start; |
614 | end = up->end; |
615 | len = end - start + 1; |
616 | if (len >= vi_insert_buffer_size) |
617 | { |
618 | vi_insert_buffer_size += (len + 32) - (len % 32); |
619 | vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); |
620 | } |
621 | strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); |
622 | vi_insert_buffer[len-1] = '\0'; |
623 | } |
624 | |
625 | void |
626 | _rl_vi_done_inserting () |
627 | { |
628 | if (_rl_vi_doing_insert) |
629 | { |
630 | /* The `C', `s', and `S' commands set this. */ |
631 | rl_end_undo_group (); |
632 | /* Now, the text between rl_undo_list->next->start and |
633 | rl_undo_list->next->end is what was inserted while in insert |
634 | mode. It gets copied to VI_INSERT_BUFFER because it depends |
635 | on absolute indices into the line which may change (though they |
636 | probably will not). */ |
637 | _rl_vi_doing_insert = 0; |
638 | _rl_vi_save_insert (rl_undo_list->next); |
639 | vi_continued_command = 1; |
640 | } |
641 | else |
642 | { |
643 | if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list) |
644 | _rl_vi_save_insert (rl_undo_list); |
645 | /* XXX - Other keys probably need to be checked. */ |
646 | else if (_rl_vi_last_key_before_insert == 'C') |
647 | rl_end_undo_group (); |
648 | while (_rl_undo_group_level > 0) |
649 | rl_end_undo_group (); |
650 | vi_continued_command = 0; |
651 | } |
652 | } |
653 | |
654 | int |
655 | rl_vi_movement_mode (count, key) |
656 | int count, key; |
657 | { |
658 | if (rl_point > 0) |
659 | rl_backward_char (1, key); |
660 | |
661 | _rl_keymap = vi_movement_keymap; |
662 | _rl_vi_done_inserting (); |
663 | return (0); |
664 | } |
665 | |
666 | int |
667 | rl_vi_arg_digit (count, c) |
668 | int count, c; |
669 | { |
670 | if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) |
671 | return (rl_beg_of_line (1, c)); |
672 | else |
673 | return (rl_digit_argument (count, c)); |
674 | } |
675 | |
676 | /* Change the case of the next COUNT characters. */ |
677 | #if defined (HANDLE_MULTIBYTE) |
678 | static int |
679 | _rl_vi_change_mbchar_case (count) |
680 | int count; |
681 | { |
682 | wchar_t wc; |
683 | char mb[MB_LEN_MAX1+1]; |
684 | int mblen; |
685 | mbstate_t ps; |
686 | |
687 | memset (&ps, 0, sizeof (mbstate_t)); |
688 | if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) |
689 | count--; |
690 | while (count-- && rl_point < rl_end) |
691 | { |
692 | mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); |
693 | if (iswupper (wc)) |
694 | wc = towlower (wc); |
695 | else if (iswlower (wc)) |
696 | wc = towupper (wc); |
697 | else |
698 | { |
699 | /* Just skip over chars neither upper nor lower case */ |
700 | rl_forward_char (1, 0); |
701 | continue; |
702 | } |
703 | |
704 | /* Vi is kind of strange here. */ |
705 | if (wc) |
706 | { |
707 | mblen = wctomb (mb, wc); |
708 | if (mblen >= 0) |
709 | mb[mblen] = '\0'; |
710 | rl_begin_undo_group (); |
711 | rl_delete (1, 0); |
712 | rl_insert_text (mb); |
713 | rl_end_undo_group (); |
714 | rl_vi_check (); |
715 | } |
716 | else |
717 | rl_forward_char (1, 0); |
718 | } |
719 | |
720 | return 0; |
721 | } |
722 | #endif |
723 | |
724 | int |
725 | rl_vi_change_case (count, ignore) |
726 | int count, ignore; |
727 | { |
728 | char c = 0; |
729 | |
730 | /* Don't try this on an empty line. */ |
731 | if (rl_point >= rl_end) |
732 | return (0); |
733 | |
734 | #if defined (HANDLE_MULTIBYTE) |
735 | if (MB_CUR_MAX1 > 1 && rl_byte_oriented == 0) |
736 | return (_rl_vi_change_mbchar_case (count)); |
737 | #endif |
738 | |
739 | while (count-- && rl_point < rl_end) |
740 | { |
741 | if (_rl_uppercase_p (rl_line_buffer[rl_point])(((unsigned char)(rl_line_buffer[rl_point]) == (rl_line_buffer [rl_point])) && (isascii(rl_line_buffer[rl_point]) && isupper (rl_line_buffer[rl_point])))) |
742 | c = _rl_to_lower (rl_line_buffer[rl_point])((((unsigned char)(rl_line_buffer[rl_point]) == (rl_line_buffer [rl_point])) && (isascii(rl_line_buffer[rl_point]) && isupper (rl_line_buffer[rl_point]))) ? tolower((unsigned char )rl_line_buffer[rl_point]) : (rl_line_buffer[rl_point])); |
743 | else if (_rl_lowercase_p (rl_line_buffer[rl_point])(((unsigned char)(rl_line_buffer[rl_point]) == (rl_line_buffer [rl_point])) && (isascii(rl_line_buffer[rl_point]) && islower (rl_line_buffer[rl_point])))) |
744 | c = _rl_to_upper (rl_line_buffer[rl_point])((((unsigned char)(rl_line_buffer[rl_point]) == (rl_line_buffer [rl_point])) && (isascii(rl_line_buffer[rl_point]) && islower (rl_line_buffer[rl_point]))) ? toupper((unsigned char )rl_line_buffer[rl_point]) : (rl_line_buffer[rl_point])); |
745 | else |
746 | { |
747 | /* Just skip over characters neither upper nor lower case. */ |
748 | rl_forward_char (1, c); |
749 | continue; |
750 | } |
751 | |
752 | /* Vi is kind of strange here. */ |
753 | if (c) |
754 | { |
755 | rl_begin_undo_group (); |
756 | rl_delete (1, c); |
757 | _rl_insert_char (1, c); |
758 | rl_end_undo_group (); |
759 | rl_vi_check (); |
760 | } |
761 | else |
762 | rl_forward_char (1, c); |
763 | } |
764 | return (0); |
765 | } |
766 | |
767 | int |
768 | rl_vi_put (count, key) |
769 | int count, key; |
770 | { |
771 | if (!_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key))) && (rl_point + 1 <= rl_end)) |
772 | rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO)((rl_point) + (1)); |
773 | |
774 | rl_yank (1, key); |
775 | rl_backward_char (1, key); |
776 | return (0); |
777 | } |
778 | |
779 | int |
780 | rl_vi_check () |
781 | { |
782 | if (rl_point && rl_point == rl_end) |
783 | { |
784 | if (MB_CUR_MAX1 > 1 && rl_byte_oriented == 0) |
785 | rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO)(((rl_point) == 0) ? (rl_point) : ((rl_point) - 1)); |
786 | else |
787 | rl_point--; |
788 | } |
789 | return (0); |
790 | } |
791 | |
792 | int |
793 | rl_vi_column (count, key) |
794 | int count, key; |
795 | { |
796 | if (count > rl_end) |
797 | rl_end_of_line (1, key); |
798 | else |
799 | rl_point = count - 1; |
800 | return (0); |
801 | } |
802 | |
803 | int |
804 | rl_vi_domove (key, nextkey) |
805 | int key, *nextkey; |
806 | { |
807 | int c, save; |
808 | int old_end; |
809 | |
810 | rl_mark = rl_point; |
811 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
812 | c = rl_read_key (); |
813 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
814 | *nextkey = c; |
815 | |
816 | if (!member (c, vi_motion)((c) ? (char *)strchr ((vi_motion), (c)) != (char *)((void *) 0) : 0)) |
817 | { |
818 | if (_rl_digit_p (c)((c) >= '0' && (c) <= '9')) |
819 | { |
820 | save = rl_numeric_arg; |
821 | rl_numeric_arg = _rl_digit_value (c)((c) - '0'); |
822 | rl_digit_loop1 (); |
823 | rl_numeric_arg *= save; |
824 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
825 | c = rl_read_key (); /* real command */ |
826 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
827 | *nextkey = c; |
828 | } |
829 | else if (key == c && (key == 'd' || key == 'y' || key == 'c')) |
830 | { |
831 | rl_mark = rl_end; |
832 | rl_beg_of_line (1, c); |
833 | _rl_vi_last_motion = c; |
834 | return (0); |
835 | } |
836 | else |
837 | return (-1); |
838 | } |
839 | |
840 | _rl_vi_last_motion = c; |
841 | |
842 | /* Append a blank character temporarily so that the motion routines |
843 | work right at the end of the line. */ |
844 | old_end = rl_end; |
845 | rl_line_buffer[rl_end++] = ' '; |
846 | rl_line_buffer[rl_end] = '\0'; |
847 | |
848 | _rl_dispatch (c, _rl_keymap); |
849 | |
850 | /* Remove the blank that we added. */ |
851 | rl_end = old_end; |
852 | rl_line_buffer[rl_end] = '\0'; |
853 | if (rl_point > rl_end) |
854 | rl_point = rl_end; |
855 | |
856 | /* No change in position means the command failed. */ |
857 | if (rl_mark == rl_point) |
858 | return (-1); |
859 | |
860 | /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next |
861 | word. If we are not at the end of the line, and we are on a |
862 | non-whitespace character, move back one (presumably to whitespace). */ |
863 | if ((_rl_to_upper (c)((((unsigned char)(c) == (c)) && (isascii(c) && islower (c))) ? toupper((unsigned char)c) : (c)) == 'W') && rl_point < rl_end && rl_point > rl_mark && |
864 | !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
865 | rl_point--; |
866 | |
867 | /* If cw or cW, back up to the end of a word, so the behaviour of ce |
868 | or cE is the actual result. Brute-force, no subtlety. */ |
869 | if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c)((((unsigned char)(c) == (c)) && (isascii(c) && islower (c))) ? toupper((unsigned char)c) : (c)) == 'W')) |
870 | { |
871 | /* Don't move farther back than where we started. */ |
872 | while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
873 | rl_point--; |
874 | |
875 | /* Posix.2 says that if cw or cW moves the cursor towards the end of |
876 | the line, the character under the cursor should be deleted. */ |
877 | if (rl_point == rl_mark) |
878 | rl_point++; |
879 | else |
880 | { |
881 | /* Move past the end of the word so that the kill doesn't |
882 | remove the last letter of the previous word. Only do this |
883 | if we are not at the end of the line. */ |
884 | if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
885 | rl_point++; |
886 | } |
887 | } |
888 | |
889 | if (rl_mark < rl_point) |
890 | SWAP (rl_point, rl_mark)do { int t; t = rl_point; rl_point = rl_mark; rl_mark = t; } while (0); |
891 | |
892 | return (0); |
893 | } |
894 | |
895 | /* A simplified loop for vi. Don't dispatch key at end. |
896 | Don't recognize minus sign? |
897 | Should this do rl_save_prompt/rl_restore_prompt? */ |
898 | static int |
899 | rl_digit_loop1 () |
900 | { |
901 | int key, c; |
902 | |
903 | RL_SETSTATE(RL_STATE_NUMERICARG)(rl_readline_state |= (0x00400)); |
904 | while (1) |
905 | { |
906 | if (rl_numeric_arg > 1000000) |
907 | { |
908 | rl_explicit_arg = rl_numeric_arg = 0; |
909 | rl_ding (); |
910 | rl_clear_message (); |
911 | RL_UNSETSTATE(RL_STATE_NUMERICARG)(rl_readline_state &= ~(0x00400)); |
912 | return 1; |
913 | } |
914 | rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); |
915 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
916 | key = c = rl_read_key (); |
917 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
918 | |
919 | if (c >= 0 && _rl_keymap[c].type == ISFUNC0 && |
920 | _rl_keymap[c].function == rl_universal_argument) |
921 | { |
922 | rl_numeric_arg *= 4; |
923 | continue; |
924 | } |
925 | |
926 | c = UNMETA (c)((c) & (~0x080)); |
927 | if (_rl_digit_p (c)((c) >= '0' && (c) <= '9')) |
928 | { |
929 | if (rl_explicit_arg) |
930 | rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c)((c) - '0'); |
931 | else |
932 | rl_numeric_arg = _rl_digit_value (c)((c) - '0'); |
933 | rl_explicit_arg = 1; |
934 | } |
935 | else |
936 | { |
937 | rl_clear_message (); |
938 | rl_stuff_char (key); |
939 | break; |
940 | } |
941 | } |
942 | |
943 | RL_UNSETSTATE(RL_STATE_NUMERICARG)(rl_readline_state &= ~(0x00400)); |
944 | return (0); |
945 | } |
946 | |
947 | int |
948 | rl_vi_delete_to (count, key) |
949 | int count, key; |
950 | { |
951 | int c; |
952 | |
953 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
954 | rl_stuff_char ('$'); |
955 | else if (vi_redoing) |
956 | rl_stuff_char (_rl_vi_last_motion); |
957 | |
958 | if (rl_vi_domove (key, &c)) |
959 | { |
960 | rl_ding (); |
961 | return -1; |
962 | } |
963 | |
964 | /* These are the motion commands that do not require adjusting the |
965 | mark. */ |
966 | if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) |
967 | rl_mark++; |
968 | |
969 | rl_kill_text (rl_point, rl_mark); |
970 | return (0); |
971 | } |
972 | |
973 | int |
974 | rl_vi_change_to (count, key) |
975 | int count, key; |
976 | { |
977 | int c, start_pos; |
978 | |
979 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
980 | rl_stuff_char ('$'); |
981 | else if (vi_redoing) |
982 | rl_stuff_char (_rl_vi_last_motion); |
983 | |
984 | start_pos = rl_point; |
985 | |
986 | if (rl_vi_domove (key, &c)) |
987 | { |
988 | rl_ding (); |
989 | return -1; |
990 | } |
991 | |
992 | /* These are the motion commands that do not require adjusting the |
993 | mark. c[wW] are handled by special-case code in rl_vi_domove(), |
994 | and already leave the mark at the correct location. */ |
995 | if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) |
996 | rl_mark++; |
997 | |
998 | /* The cursor never moves with c[wW]. */ |
999 | if ((_rl_to_upper (c)((((unsigned char)(c) == (c)) && (isascii(c) && islower (c))) ? toupper((unsigned char)c) : (c)) == 'W') && rl_point < start_pos) |
1000 | rl_point = start_pos; |
1001 | |
1002 | if (vi_redoing) |
1003 | { |
1004 | if (vi_insert_buffer && *vi_insert_buffer) |
1005 | rl_begin_undo_group (); |
1006 | rl_delete_text (rl_point, rl_mark); |
1007 | if (vi_insert_buffer && *vi_insert_buffer) |
1008 | { |
1009 | rl_insert_text (vi_insert_buffer); |
1010 | rl_end_undo_group (); |
1011 | } |
1012 | } |
1013 | else |
1014 | { |
1015 | rl_begin_undo_group (); /* to make the `u' command work */ |
1016 | rl_kill_text (rl_point, rl_mark); |
1017 | /* `C' does not save the text inserted for undoing or redoing. */ |
1018 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key))) == 0) |
1019 | _rl_vi_doing_insert = 1; |
1020 | _rl_vi_set_last (key, count, rl_arg_sign); |
1021 | rl_vi_insertion_mode (1, key); |
1022 | } |
1023 | |
1024 | return (0); |
1025 | } |
1026 | |
1027 | int |
1028 | rl_vi_yank_to (count, key) |
1029 | int count, key; |
1030 | { |
1031 | int c, save = rl_point; |
1032 | |
1033 | if (_rl_uppercase_p (key)(((unsigned char)(key) == (key)) && (isascii(key) && isupper (key)))) |
1034 | rl_stuff_char ('$'); |
1035 | |
1036 | if (rl_vi_domove (key, &c)) |
1037 | { |
1038 | rl_ding (); |
1039 | return -1; |
1040 | } |
1041 | |
1042 | /* These are the motion commands that do not require adjusting the |
1043 | mark. */ |
1044 | if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) |
1045 | rl_mark++; |
1046 | |
1047 | rl_begin_undo_group (); |
1048 | rl_kill_text (rl_point, rl_mark); |
1049 | rl_end_undo_group (); |
1050 | rl_do_undo (); |
1051 | rl_point = save; |
1052 | |
1053 | return (0); |
1054 | } |
1055 | |
1056 | int |
1057 | rl_vi_delete (count, key) |
1058 | int count, key; |
1059 | { |
1060 | int end; |
1061 | |
1062 | if (rl_end == 0) |
1063 | { |
1064 | rl_ding (); |
1065 | return -1; |
1066 | } |
1067 | |
1068 | if (MB_CUR_MAX1 > 1 && rl_byte_oriented == 0) |
1069 | end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO)((rl_point) + (count)); |
1070 | else |
1071 | end = rl_point + count; |
1072 | |
1073 | if (end >= rl_end) |
1074 | end = rl_end; |
1075 | |
1076 | rl_kill_text (rl_point, end); |
1077 | |
1078 | if (rl_point > 0 && rl_point == rl_end) |
1079 | rl_backward_char (1, key); |
1080 | return (0); |
1081 | } |
1082 | |
1083 | int |
1084 | rl_vi_back_to_indent (count, key) |
1085 | int count, key; |
1086 | { |
1087 | rl_beg_of_line (1, key); |
1088 | while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])(((rl_line_buffer[rl_point]) == ' ') || ((rl_line_buffer[rl_point ]) == '\t'))) |
1089 | rl_point++; |
1090 | return (0); |
1091 | } |
1092 | |
1093 | int |
1094 | rl_vi_first_print (count, key) |
1095 | int count, key; |
1096 | { |
1097 | return (rl_vi_back_to_indent (1, key)); |
1098 | } |
1099 | |
1100 | int |
1101 | rl_vi_char_search (count, key) |
1102 | int count, key; |
1103 | { |
1104 | #if defined (HANDLE_MULTIBYTE) |
1105 | static char *target; |
1106 | static int mb_len; |
1107 | #else |
1108 | static char target; |
1109 | #endif |
1110 | static int orig_dir, dir; |
1111 | |
1112 | if (key == ';' || key == ',') |
1113 | dir = key == ';' ? orig_dir : -orig_dir; |
1114 | else |
1115 | { |
1116 | if (vi_redoing) |
1117 | #if defined (HANDLE_MULTIBYTE) |
1118 | target = _rl_vi_last_search_mbchar; |
1119 | #else |
1120 | target = _rl_vi_last_search_char; |
1121 | #endif |
1122 | else |
1123 | { |
1124 | #if defined (HANDLE_MULTIBYTE) |
1125 | mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX1); |
1126 | target = _rl_vi_last_search_mbchar; |
1127 | #else |
1128 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
1129 | _rl_vi_last_search_char = target = rl_read_key (); |
1130 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
1131 | #endif |
1132 | } |
1133 | |
1134 | switch (key) |
1135 | { |
1136 | case 't': |
1137 | orig_dir = dir = FTO1; |
1138 | break; |
1139 | |
1140 | case 'T': |
1141 | orig_dir = dir = BTO-1; |
1142 | break; |
1143 | |
1144 | case 'f': |
1145 | orig_dir = dir = FFIND2; |
1146 | break; |
1147 | |
1148 | case 'F': |
1149 | orig_dir = dir = BFIND-2; |
1150 | break; |
1151 | } |
1152 | } |
1153 | |
1154 | #if defined (HANDLE_MULTIBYTE) |
1155 | return (_rl_char_search_internal (count, dir, target, mb_len)); |
1156 | #else |
1157 | return (_rl_char_search_internal (count, dir, target)); |
1158 | #endif |
1159 | } |
1160 | |
1161 | /* Match brackets */ |
1162 | int |
1163 | rl_vi_match (ignore, key) |
1164 | int ignore, key; |
1165 | { |
1166 | int count = 1, brack, pos, tmp, pre; |
1167 | |
1168 | pos = rl_point; |
1169 | if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) |
1170 | { |
1171 | if (MB_CUR_MAX1 > 1 && rl_byte_oriented == 0) |
1172 | { |
1173 | while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) |
1174 | { |
1175 | pre = rl_point; |
1176 | rl_forward_char (1, key); |
1177 | if (pre == rl_point) |
1178 | break; |
1179 | } |
1180 | } |
1181 | else |
1182 | while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && |
1183 | rl_point < rl_end - 1) |
1184 | rl_forward_char (1, key); |
1185 | |
1186 | if (brack <= 0) |
1187 | { |
1188 | rl_point = pos; |
1189 | rl_ding (); |
1190 | return -1; |
1191 | } |
1192 | } |
1193 | |
1194 | pos = rl_point; |
1195 | |
1196 | if (brack < 0) |
1197 | { |
1198 | while (count) |
1199 | { |
1200 | tmp = pos; |
Value stored to 'tmp' is never read | |
1201 | if (MB_CUR_MAX1 == 1 || rl_byte_oriented) |
1202 | pos--; |
1203 | else |
1204 | { |
1205 | pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)(((pos) == 0) ? (pos) : ((pos) - 1)); |
1206 | if (tmp == pos) |
1207 | pos--; |
1208 | } |
1209 | if (pos >= 0) |
1210 | { |
1211 | int b = rl_vi_bracktype (rl_line_buffer[pos]); |
1212 | if (b == -brack) |
1213 | count--; |
1214 | else if (b == brack) |
1215 | count++; |
1216 | } |
1217 | else |
1218 | { |
1219 | rl_ding (); |
1220 | return -1; |
1221 | } |
1222 | } |
1223 | } |
1224 | else |
1225 | { /* brack > 0 */ |
1226 | while (count) |
1227 | { |
1228 | if (MB_CUR_MAX1 == 1 || rl_byte_oriented) |
1229 | pos++; |
1230 | else |
1231 | pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)((pos) + (1)); |
1232 | |
1233 | if (pos < rl_end) |
1234 | { |
1235 | int b = rl_vi_bracktype (rl_line_buffer[pos]); |
1236 | if (b == -brack) |
1237 | count--; |
1238 | else if (b == brack) |
1239 | count++; |
1240 | } |
1241 | else |
1242 | { |
1243 | rl_ding (); |
1244 | return -1; |
1245 | } |
1246 | } |
1247 | } |
1248 | rl_point = pos; |
1249 | return (0); |
1250 | } |
1251 | |
1252 | int |
1253 | rl_vi_bracktype (c) |
1254 | int c; |
1255 | { |
1256 | switch (c) |
1257 | { |
1258 | case '(': return 1; |
1259 | case ')': return -1; |
1260 | case '[': return 2; |
1261 | case ']': return -2; |
1262 | case '{': return 3; |
1263 | case '}': return -3; |
1264 | default: return 0; |
1265 | } |
1266 | } |
1267 | |
1268 | /* XXX - think about reading an entire mbchar with _rl_read_mbchar and |
1269 | inserting it in one bunch instead of the loop below (like in |
1270 | rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0] |
1271 | for test against 033 or ^C. Make sure that _rl_read_mbchar does |
1272 | this right. */ |
1273 | int |
1274 | rl_vi_change_char (count, key) |
1275 | int count, key; |
1276 | { |
1277 | int c; |
1278 | |
1279 | if (vi_redoing) |
1280 | c = _rl_vi_last_replacement; |
1281 | else |
1282 | { |
1283 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
1284 | _rl_vi_last_replacement = c = rl_read_key (); |
1285 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
1286 | } |
1287 | |
1288 | if (c == '\033' || c == CTRL ('C')(('C') & 0x1f)) |
1289 | return -1; |
1290 | |
1291 | while (count-- && rl_point < rl_end) |
1292 | { |
1293 | rl_begin_undo_group (); |
1294 | |
1295 | rl_delete (1, c); |
1296 | #if defined (HANDLE_MULTIBYTE) |
1297 | if (MB_CUR_MAX1 > 1 && rl_byte_oriented == 0) |
1298 | while (_rl_insert_char (1, c)) |
1299 | { |
1300 | RL_SETSTATE (RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
1301 | c = rl_read_key (); |
1302 | RL_UNSETSTATE (RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
1303 | } |
1304 | else |
1305 | #endif |
1306 | _rl_insert_char (1, c); |
1307 | if (count == 0) |
1308 | rl_backward_char (1, c); |
1309 | |
1310 | rl_end_undo_group (); |
1311 | } |
1312 | return (0); |
1313 | } |
1314 | |
1315 | int |
1316 | rl_vi_subst (count, key) |
1317 | int count, key; |
1318 | { |
1319 | /* If we are redoing, rl_vi_change_to will stuff the last motion char */ |
1320 | if (vi_redoing == 0) |
1321 | rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */ |
1322 | |
1323 | return (rl_vi_change_to (count, 'c')); |
1324 | } |
1325 | |
1326 | int |
1327 | rl_vi_overstrike (count, key) |
1328 | int count, key; |
1329 | { |
1330 | if (_rl_vi_doing_insert == 0) |
1331 | { |
1332 | _rl_vi_doing_insert = 1; |
1333 | rl_begin_undo_group (); |
1334 | } |
1335 | |
1336 | if (count > 0) |
1337 | { |
1338 | _rl_overwrite_char (count, key); |
1339 | vi_replace_count += count; |
1340 | } |
1341 | |
1342 | return (0); |
1343 | } |
1344 | |
1345 | int |
1346 | rl_vi_overstrike_delete (count, key) |
1347 | int count, key; |
1348 | { |
1349 | int i, s; |
1350 | |
1351 | for (i = 0; i < count; i++) |
1352 | { |
1353 | if (vi_replace_count == 0) |
1354 | { |
1355 | rl_ding (); |
1356 | break; |
1357 | } |
1358 | s = rl_point; |
1359 | |
1360 | if (rl_do_undo ()) |
1361 | vi_replace_count--; |
1362 | |
1363 | if (rl_point == s) |
1364 | rl_backward_char (1, key); |
1365 | } |
1366 | |
1367 | if (vi_replace_count == 0 && _rl_vi_doing_insert) |
1368 | { |
1369 | rl_end_undo_group (); |
1370 | rl_do_undo (); |
1371 | _rl_vi_doing_insert = 0; |
1372 | } |
1373 | return (0); |
1374 | } |
1375 | |
1376 | int |
1377 | rl_vi_replace (count, key) |
1378 | int count, key; |
1379 | { |
1380 | int i; |
1381 | |
1382 | vi_replace_count = 0; |
1383 | |
1384 | if (!vi_replace_map) |
1385 | { |
1386 | vi_replace_map = rl_make_bare_keymap (); |
1387 | |
1388 | for (i = ' '; i < KEYMAP_SIZE257; i++) |
1389 | vi_replace_map[i].function = rl_vi_overstrike; |
1390 | |
1391 | vi_replace_map[RUBOUT0x7f].function = rl_vi_overstrike_delete; |
1392 | vi_replace_map[ESC(('[') & 0x1f)].function = rl_vi_movement_mode; |
1393 | vi_replace_map[RETURN(('M') & 0x1f)].function = rl_newline; |
1394 | vi_replace_map[NEWLINE'\n'].function = rl_newline; |
1395 | |
1396 | /* If the normal vi insertion keymap has ^H bound to erase, do the |
1397 | same here. Probably should remove the assignment to RUBOUT up |
1398 | there, but I don't think it will make a difference in real life. */ |
1399 | if (vi_insertion_keymap[CTRL ('H')(('H') & 0x1f)].type == ISFUNC0 && |
1400 | vi_insertion_keymap[CTRL ('H')(('H') & 0x1f)].function == rl_rubout) |
1401 | vi_replace_map[CTRL ('H')(('H') & 0x1f)].function = rl_vi_overstrike_delete; |
1402 | |
1403 | } |
1404 | _rl_keymap = vi_replace_map; |
1405 | return (0); |
1406 | } |
1407 | |
1408 | #if 0 |
1409 | /* Try to complete the word we are standing on or the word that ends with |
1410 | the previous character. A space matches everything. Word delimiters are |
1411 | space and ;. */ |
1412 | int |
1413 | rl_vi_possible_completions() |
1414 | { |
1415 | int save_pos = rl_point; |
1416 | |
1417 | if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') |
1418 | { |
1419 | while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && |
1420 | rl_line_buffer[rl_point] != ';') |
1421 | rl_point++; |
1422 | } |
1423 | else if (rl_line_buffer[rl_point - 1] == ';') |
1424 | { |
1425 | rl_ding (); |
1426 | return (0); |
1427 | } |
1428 | |
1429 | rl_possible_completions (); |
1430 | rl_point = save_pos; |
1431 | |
1432 | return (0); |
1433 | } |
1434 | #endif |
1435 | |
1436 | /* Functions to save and restore marks. */ |
1437 | int |
1438 | rl_vi_set_mark (count, key) |
1439 | int count, key; |
1440 | { |
1441 | int ch; |
1442 | |
1443 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
1444 | ch = rl_read_key (); |
1445 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
1446 | |
1447 | if (ch < 'a' || ch > 'z') |
1448 | { |
1449 | rl_ding (); |
1450 | return -1; |
1451 | } |
1452 | ch -= 'a'; |
1453 | vi_mark_chars[ch] = rl_point; |
1454 | return 0; |
1455 | } |
1456 | |
1457 | int |
1458 | rl_vi_goto_mark (count, key) |
1459 | int count, key; |
1460 | { |
1461 | int ch; |
1462 | |
1463 | RL_SETSTATE(RL_STATE_MOREINPUT)(rl_readline_state |= (0x00040)); |
1464 | ch = rl_read_key (); |
1465 | RL_UNSETSTATE(RL_STATE_MOREINPUT)(rl_readline_state &= ~(0x00040)); |
1466 | |
1467 | if (ch == '`') |
1468 | { |
1469 | rl_point = rl_mark; |
1470 | return 0; |
1471 | } |
1472 | else if (ch < 'a' || ch > 'z') |
1473 | { |
1474 | rl_ding (); |
1475 | return -1; |
1476 | } |
1477 | |
1478 | ch -= 'a'; |
1479 | if (vi_mark_chars[ch] == -1) |
1480 | { |
1481 | rl_ding (); |
1482 | return -1; |
1483 | } |
1484 | rl_point = vi_mark_chars[ch]; |
1485 | return 0; |
1486 | } |
1487 | |
1488 | #endif /* VI_MODE */ |