diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2011-05-11 23:38:44 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2011-05-11 23:38:44 +0000 |
commit | cc88a640ca1d0356c5feb40bb48869bab5a2bdce (patch) | |
tree | 2b845ec3c6b554e4fe702a48844fe13330c0f58c /readline/vi_mode.c | |
parent | 4cab4add34b167b3902b1cb2873738914103f6ff (diff) | |
download | gdb-cc88a640ca1d0356c5feb40bb48869bab5a2bdce.zip gdb-cc88a640ca1d0356c5feb40bb48869bab5a2bdce.tar.gz gdb-cc88a640ca1d0356c5feb40bb48869bab5a2bdce.tar.bz2 |
Imported readline 6.2, and upstream patch 001.
[patch 0/3] readline-6.2 rebase
http://sourceware.org/ml/gdb-patches/2011-05/msg00003.html
[patch 1/3] readline-6.2: Merge of already posted patches
http://sourceware.org/ml/gdb-patches/2011-05/msg00004.html
=
[Bug-readline] [RFC/readline] bind.c, rl_function_dumper, Free allocated
http://lists.gnu.org/archive/html/bug-readline/2011-03/msg00000.html
[Bug-readline] [patch] Fix underquotation in readline/examples/rlfe/conf
http://lists.gnu.org/archive/html/bug-readline/2011-04/msg00001.html
[Bug-readline] [patch] Makefile.in htm<->html
http://lists.gnu.org/archive/html/bug-readline/2011-04/msg00002.html
Re: [Bug-readline] [patch] Makefile.in dependency: callback.o: xmalloc.h
http://lists.gnu.org/archive/html/bug-readline/2011-04/msg00004.html
[Bug-readline] [patch] Remove . from the VPATH directive
http://lists.gnu.org/archive/html/bug-readline/2011-04/msg00005.html
Eli Zaretskii's __MSDOS__ / __GO32__ / __MINGW32__ / __DJGPP__ stuff:
http://sourceware.org/ml/gdb/2011-04/msg00002.html
Jan Kratochvil's patch for FSF GDB tree local-specific changes:
http://sourceware.org/ml/gdb/2011-04/msg00006.html
Preservation of existing ChangeLog.gdb files, their updates.
[patch 2/3] readline-6.2: Workaround "ask" regression
http://sourceware.org/ml/gdb-patches/2011-05/msg00005.html
[patch 3/3] readline-6.2: Revert 5.x compat., apply 6.x compat.
http://sourceware.org/ml/gdb-patches/2011-05/msg00006.html
[patch 4/3] readline-6.2: Substitute inc-hist.texinfo
http://sourceware.org/ml/gdb-patches/2011-05/msg00010.html
readline/
Workaround gdb.base/completion.exp regression on readline-6.2.
* complete.c (get_y_or_n): Disable the return on RL_STATE_CALLBACK.
Imported readline 6.2, and upstream patch 001.
* configure: Regenerate.
readline/doc/
* hsuser.texi (Using History Interactively): Disable !BashFeatures
@defcodeindex. Make the `Programming with GNU History' reference
external.
* inc-hist.texinfo: Remove.
Imported readline 6.2, and upstream patch 001.
readline/examples/
Imported readline 6.2, and upstream patch 001.
readline/examples/rlfe/
Imported readline 6.2, and upstream patch 001.
gdb/
* config.in: Regenerate.
* configure: Regenerate.
* configure.ac <--with-system-readline> (for readline_echoing_p):
Remove the test.
* tui/tui-io.c (tui_old_readline_echoing_p): Rename to ...
(tui_old_rl_echoing_p): ... here.
(tui_setup_io): Rename extern declaration readline_echoing_p to
_rl_echoing_p. Adjust assignments for the both renames.
gdb/doc/
* Makefile.in (GDB_DOC_SOURCE_INCLUDES): Rename inc-hist.texinfo to
hsuser.texi.
* gdb.texinfo <!SYSTEM_READLINE>: Rename inc-hist.texinfo inclusion and
comment to hsuser.texi. Change rluser.texi name in the comment.
Diffstat (limited to 'readline/vi_mode.c')
-rw-r--r-- | readline/vi_mode.c | 718 |
1 files changed, 536 insertions, 182 deletions
diff --git a/readline/vi_mode.c b/readline/vi_mode.c index ac5fd74..a3c3578 100644 --- a/readline/vi_mode.c +++ b/readline/vi_mode.c @@ -1,25 +1,25 @@ /* vi_mode.c -- A vi emulation mode for Bash. Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ -/* Copyright (C) 1987-2005 Free Software Foundation, Inc. +/* Copyright (C) 1987-2010 Free Software Foundation, Inc. - This file is part of the GNU Readline Library, a library for - reading lines of text with interactive input and history editing. + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. - The GNU Readline Library is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2, or + Readline is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - The GNU Readline Library is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + Readline is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - The GNU General Public License is often shipped with GNU software, and - is generally kept in a file called COPYING or LICENSE. If you do not - have a copy of the license, write to the Free Software Foundation, - 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + You should have received a copy of the GNU General Public License + along with Readline. If not, see <http://www.gnu.org/licenses/>. +*/ + #define READLINE_LIBRARY /* **************************************************************** */ @@ -65,11 +65,13 @@ int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ +_rl_vimotion_cxt *_rl_vimvcxt = 0; + /* Non-zero means enter insertion mode. */ static int _rl_vi_doing_insert; /* Command keys which do movement for xxx_to commands. */ -static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|"; +static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`"; /* Keymap used for vi replace characters. Created dynamically since rarely used. */ @@ -101,7 +103,7 @@ static int _rl_vi_last_key_before_insert; static int vi_redoing; /* Text modification commands. These are the `redoable' commands. */ -static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; +static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; /* Arrays for the saved marks. */ static int vi_mark_chars['z' - 'a' + 1]; @@ -109,12 +111,16 @@ static int vi_mark_chars['z' - 'a' + 1]; static void _rl_vi_stuff_insert PARAMS((int)); static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); +static void _rl_vi_backup PARAMS((void)); + static int _rl_vi_arg_dispatch PARAMS((int)); static int rl_digit_loop1 PARAMS((void)); static int _rl_vi_set_mark PARAMS((void)); static int _rl_vi_goto_mark PARAMS((void)); +static void _rl_vi_append_forward PARAMS((int)); + static int _rl_vi_callback_getchar PARAMS((char *, int)); #if defined (READLINE_CALLBACKS) @@ -124,12 +130,23 @@ static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *)); static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); #endif +static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *)); +static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *)); +static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *)); + +static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *)); +static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *)); +static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *)); + +static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *)); + void _rl_vi_initialize_line () { - register int i; + register int i, n; - for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) + n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]); + for (i = 0; i < n; i++) vi_mark_chars[i] = -1; RL_UNSETSTATE(RL_STATE_VICMDONCE); @@ -205,7 +222,34 @@ rl_vi_redo (count, c) _rl_vi_stuff_insert (count); /* And back up point over the last character inserted. */ if (rl_point > 0) - rl_point--; + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `I', but move to the beginning of the + line like the `I' command does. */ + else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer) + { + rl_beg_of_line (1, 'I'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `a', but move forward a character first + like the `a' command does. */ + else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_append_forward ('a'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `A', but move to the end of the line + like the `A' command does. */ + else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer) + { + rl_end_of_line (1, 'A'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); } else r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); @@ -571,27 +615,40 @@ rl_vi_insert_beg (count, key) int count, key; { rl_beg_of_line (1, key); - rl_vi_insertion_mode (1, key); + rl_vi_insert_mode (1, key); return (0); } -int -rl_vi_append_mode (count, key) - int count, key; +static void +_rl_vi_append_forward (key) + int key; { + int point; + if (rl_point < rl_end) { if (MB_CUR_MAX == 1 || rl_byte_oriented) rl_point++; else - { - int point = rl_point; - rl_forward_char (1, key); - if (point == rl_point) - rl_point = rl_end; - } + { + point = rl_point; +#if 0 + rl_forward_char (1, key); +#else + rl_point = _rl_forward_char_internal (1); +#endif + if (point == rl_point) + rl_point = rl_end; + } } - rl_vi_insertion_mode (1, key); +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + _rl_vi_append_forward (key); + rl_vi_start_inserting (key, 1, rl_arg_sign); return (0); } @@ -625,13 +682,21 @@ rl_vi_insertion_mode (count, key) return (0); } +int +rl_vi_insert_mode (count, key) + int count, key; +{ + rl_vi_start_inserting (key, 1, rl_arg_sign); + return (0); +} + static void _rl_vi_save_insert (up) UNDO_LIST *up; { int len, start, end; - if (up == 0) + if (up == 0 || up->what != UNDO_INSERT) { if (vi_insert_buffer_size >= 1) vi_insert_buffer[0] = '\0'; @@ -668,8 +733,11 @@ _rl_vi_done_inserting () } else { - if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list) - _rl_vi_save_insert (rl_undo_list); + if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' || + _rl_vi_last_key_before_insert == 'a' || + _rl_vi_last_key_before_insert == 'I' || + _rl_vi_last_key_before_insert == 'A')) + _rl_vi_save_insert (rl_undo_list); /* XXX - Other keys probably need to be checked. */ else if (_rl_vi_last_key_before_insert == 'C') rl_end_undo_group (); @@ -716,7 +784,8 @@ _rl_vi_change_mbchar_case (count) { wchar_t wc; char mb[MB_LEN_MAX+1]; - int mblen, p; + int mlen, p; + size_t m; mbstate_t ps; memset (&ps, 0, sizeof (mbstate_t)); @@ -724,7 +793,11 @@ _rl_vi_change_mbchar_case (count) count--; while (count-- && rl_point < rl_end) { - mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); + if (MB_INVALIDCH (m)) + wc = (wchar_t)rl_line_buffer[rl_point]; + else if (MB_NULLWCH (m)) + wc = L'\0'; if (iswupper (wc)) wc = towlower (wc); else if (iswlower (wc)) @@ -740,9 +813,9 @@ _rl_vi_change_mbchar_case (count) if (wc) { p = rl_point; - mblen = wcrtomb (mb, wc, &ps); - if (mblen >= 0) - mb[mblen] = '\0'; + mlen = wcrtomb (mb, wc, &ps); + if (mlen >= 0) + mb[mlen] = '\0'; rl_begin_undo_group (); rl_vi_delete (1, 0); if (rl_point < p) /* Did we retreat at EOL? */ @@ -752,7 +825,7 @@ _rl_vi_change_mbchar_case (count) rl_vi_check (); } else - rl_forward_char (1, 0); + rl_forward_char (1, 0); } return 0; @@ -799,7 +872,7 @@ rl_vi_change_case (count, ignore) _rl_insert_char (1, c); rl_end_undo_group (); rl_vi_check (); - } + } else rl_forward_char (1, c); } @@ -820,6 +893,15 @@ rl_vi_put (count, key) return (0); } +static void +_rl_vi_backup () +{ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; +} + int rl_vi_check () { @@ -828,7 +910,7 @@ rl_vi_check () if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); else - rl_point--; + rl_point--; } return (0); } @@ -844,47 +926,106 @@ rl_vi_column (count, key) return (0); } -int -rl_vi_domove (key, nextkey) - int key, *nextkey; +/* Process C as part of the current numeric argument. Return -1 if the + argument should be aborted, 0 if we should not read any more chars, and + 1 if we should continue to read chars. */ +static int +_rl_vi_arg_dispatch (c) + int c; { - int c, save; - int old_end; + int key; - rl_mark = rl_point; - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - *nextkey = c; + key = c; + if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + return 1; + } + + c = UNMETA (c); - if (!member (c, vi_motion)) + if (_rl_digit_p (c)) { - if (_rl_digit_p (c)) - { - save = rl_numeric_arg; - rl_numeric_arg = _rl_digit_value (c); - rl_explicit_arg = 1; - RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION); - rl_digit_loop1 (); - RL_UNSETSTATE (RL_STATE_VIMOTION); - rl_numeric_arg *= save; - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); /* real command */ - RL_UNSETSTATE(RL_STATE_MOREINPUT); - *nextkey = c; - } - else if (key == c && (key == 'd' || key == 'y' || key == 'c')) - { - rl_mark = rl_end; - rl_beg_of_line (1, c); - _rl_vi_last_motion = c; - return (0); - } + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); else - return (-1); + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + return 1; /* keep going */ + } + else + { + rl_clear_message (); + rl_stuff_char (key); + return 0; /* done */ + } +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? + Should this do rl_save_prompt/rl_restore_prompt? */ +static int +rl_digit_loop1 () +{ + int c, r; + + while (1) + { + if (_rl_arg_overflow ()) + return 1; + + c = _rl_arg_getchar (); + + r = _rl_vi_arg_dispatch (c); + if (r <= 0) + break; } - _rl_vi_last_motion = c; + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return (0); +} + +static void +_rl_mvcxt_init (m, op, key) + _rl_vimotion_cxt *m; + int op, key; +{ + m->op = op; + m->state = m->flags = 0; + m->ncxt = 0; + m->numeric_arg = -1; + m->start = rl_point; + m->end = rl_end; + m->key = key; + m->motion = -1; +} + +static _rl_vimotion_cxt * +_rl_mvcxt_alloc (op, key) + int op, key; +{ + _rl_vimotion_cxt *m; + + m = xmalloc (sizeof (_rl_vimotion_cxt)); + _rl_mvcxt_init (m, op, key); + return m; +} + +static void +_rl_mvcxt_dispose (m) + _rl_vimotion_cxt *m; +{ + xfree (m); +} + +static int +rl_domove_motion_callback (m) + _rl_vimotion_cxt *m; +{ + int c, save, r; + int old_end; + + _rl_vi_last_motion = c = m->motion; /* Append a blank character temporarily so that the motion routines work right at the end of the line. */ @@ -913,7 +1054,7 @@ rl_vi_domove (key, nextkey) /* If cw or cW, back up to the end of a word, so the behaviour of ce or cE is the actual result. Brute-force, no subtlety. */ - if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) + if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) { /* Don't move farther back than where we started. */ while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) @@ -922,7 +1063,7 @@ rl_vi_domove (key, nextkey) /* Posix.2 says that if cw or cW moves the cursor towards the end of the line, the character under the cursor should be deleted. */ if (rl_point == rl_mark) - rl_point++; + rl_point++; else { /* Move past the end of the word so that the kill doesn't @@ -936,88 +1077,142 @@ rl_vi_domove (key, nextkey) if (rl_mark < rl_point) SWAP (rl_point, rl_mark); - return (0); +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + (*rl_redisplay_function)(); /* make sure motion is displayed */ +#endif + + r = vidomove_dispatch (m); + + return (r); } -/* Process C as part of the current numeric argument. Return -1 if the - argument should be aborted, 0 if we should not read any more chars, and - 1 if we should continue to read chars. */ +#define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG)) + static int -_rl_vi_arg_dispatch (c) - int c; +rl_domove_read_callback (m) + _rl_vimotion_cxt *m; { - int key; + int c, save; - key = c; - if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) + c = m->motion; + + if (member (c, vi_motion)) { - rl_numeric_arg *= 4; - return 1; +#if defined (READLINE_CALLBACKS) + /* If we just read a vi-mode motion command numeric argument, turn off + the `reading numeric arg' state */ + if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) + RL_UNSETSTATE (RL_STATE_NUMERICARG); +#endif + /* Should do everything, including turning off RL_STATE_VIMOTION */ + return (rl_domove_motion_callback (m)); } - - c = UNMETA (c); - - if (_rl_digit_p (c)) + else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c')) { - if (rl_explicit_arg) - rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); - else - rl_numeric_arg = _rl_digit_value (c); + rl_mark = rl_end; + rl_beg_of_line (1, c); + _rl_vi_last_motion = c; + RL_UNSETSTATE (RL_STATE_VIMOTION); + return (vidomove_dispatch (m)); + } +#if defined (READLINE_CALLBACKS) + /* XXX - these need to handle rl_universal_argument bindings */ + /* Reading vi motion char continuing numeric argument */ + else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) + { + return (_rl_vi_arg_dispatch (c)); + } + /* Readine vi motion char starting numeric argument */ + else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) + { + RL_SETSTATE (RL_STATE_NUMERICARG); + return (_rl_vi_arg_dispatch (c)); + } +#endif + else if (_rl_digit_p (c)) + { + /* This code path taken when not in callback mode */ + save = rl_numeric_arg; + rl_numeric_arg = _rl_digit_value (c); rl_explicit_arg = 1; - return 1; + RL_SETSTATE (RL_STATE_NUMERICARG); + rl_digit_loop1 (); + rl_numeric_arg *= save; + c = rl_vi_domove_getchar (m); + if (c < 0) + { + m->motion = 0; + return -1; + } + m->motion = c; + return (rl_domove_motion_callback (m)); } else { - rl_clear_message (); - rl_stuff_char (key); - return 0; + RL_UNSETSTATE (RL_STATE_VIMOTION); + RL_UNSETSTATE (RL_STATE_NUMERICARG); + return (1); } } -/* A simplified loop for vi. Don't dispatch key at end. - Don't recognize minus sign? - Should this do rl_save_prompt/rl_restore_prompt? */ static int -rl_digit_loop1 () +rl_vi_domove_getchar (m) + _rl_vimotion_cxt *m; { - int c, r; + int c; - while (1) - { - if (_rl_arg_overflow ()) - return 1; + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); - c = _rl_arg_getchar (); + return c; +} - r = _rl_vi_arg_dispatch (c); - if (r <= 0) - break; - } +#if defined (READLINE_CALLBACKS) +int +_rl_vi_domove_callback (m) + _rl_vimotion_cxt *m; +{ + int c, r; - RL_UNSETSTATE(RL_STATE_NUMERICARG); - return (0); + m->motion = c = rl_vi_domove_getchar (m); + /* XXX - what to do if this returns -1? Should we return 1 for eof to + callback code? */ + r = rl_domove_read_callback (m); + + return ((r == 0) ? r : 1); /* normalize return values */ } +#endif +/* This code path taken when not in callback mode. */ int -rl_vi_delete_to (count, key) - int count, key; +rl_vi_domove (x, ignore) + int x, *ignore; { - int c; + int r; + _rl_vimotion_cxt *m; - if (_rl_uppercase_p (key)) - rl_stuff_char ('$'); - else if (vi_redoing) - rl_stuff_char (_rl_vi_last_motion); + m = _rl_vimvcxt; + *ignore = m->motion = rl_vi_domove_getchar (m); - if (rl_vi_domove (key, &c)) + if (m->motion < 0) { - rl_ding (); + m->motion = 0; return -1; } + return (rl_domove_read_callback (m)); +} + +static int +vi_delete_dispatch (m) + _rl_vimotion_cxt *m; +{ /* These are the motion commands that do not require adjusting the mark. */ - if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end)) + if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) rl_mark++; rl_kill_text (rl_point, rl_mark); @@ -1025,33 +1220,61 @@ rl_vi_delete_to (count, key) } int -rl_vi_change_to (count, key) +rl_vi_delete_to (count, key) int count, key; { - int c, start_pos; + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key); + _rl_vimvcxt->start = rl_point; + rl_mark = rl_point; if (_rl_uppercase_p (key)) - rl_stuff_char ('$'); + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } else if (vi_redoing) - rl_stuff_char (_rl_vi_last_motion); - - start_pos = rl_point; + { + _rl_vimvcxt->motion = _rl_vi_last_motion; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); - if (rl_vi_domove (key, &c)) + if (r < 0) { rl_ding (); - return -1; + r = -1; } + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vi_change_dispatch (m) + _rl_vimotion_cxt *m; +{ /* These are the motion commands that do not require adjusting the mark. c[wW] are handled by special-case code in rl_vi_domove(), and already leave the mark at the correct location. */ - if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end)) + if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) rl_mark++; /* The cursor never moves with c[wW]. */ - if ((_rl_to_upper (c) == 'W') && rl_point < start_pos) - rl_point = start_pos; + if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start) + rl_point = m->start; if (vi_redoing) { @@ -1069,49 +1292,145 @@ rl_vi_change_to (count, key) rl_begin_undo_group (); /* to make the `u' command work */ rl_kill_text (rl_point, rl_mark); /* `C' does not save the text inserted for undoing or redoing. */ - if (_rl_uppercase_p (key) == 0) - _rl_vi_doing_insert = 1; - rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign); + if (_rl_uppercase_p (m->key) == 0) + _rl_vi_doing_insert = 1; + /* XXX -- TODO -- use m->numericarg? */ + rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign); } return (0); } int -rl_vi_yank_to (count, key) +rl_vi_change_to (count, key) int count, key; { - int c, save; + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key); + _rl_vimvcxt->start = rl_point; - save = rl_point; + rl_mark = rl_point; if (_rl_uppercase_p (key)) - rl_stuff_char ('$'); + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } + else if (vi_redoing) + { + _rl_vimvcxt->motion = _rl_vi_last_motion; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); - if (rl_vi_domove (key, &c)) + if (r < 0) { rl_ding (); - return -1; + r = -1; /* normalize return value */ } + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vi_yank_dispatch (m) + _rl_vimotion_cxt *m; +{ /* These are the motion commands that do not require adjusting the mark. */ - if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) && + (rl_mark < rl_end)) rl_mark++; rl_begin_undo_group (); rl_kill_text (rl_point, rl_mark); rl_end_undo_group (); rl_do_undo (); - rl_point = save; + rl_point = m->start; return (0); } int +rl_vi_yank_to (count, key) + int count, key; +{ + int c, r; + + _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key); + _rl_vimvcxt->start = rl_point; + + rl_mark = rl_point; + if (_rl_uppercase_p (key)) + { + _rl_vimvcxt->motion = '$'; + r = rl_domove_motion_callback (_rl_vimvcxt); + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + RL_SETSTATE (RL_STATE_VIMOTION); + return (0); + } +#endif + else + r = rl_vi_domove (key, &c); + + if (r < 0) + { + rl_ding (); + r = -1; + } + + _rl_mvcxt_dispose (_rl_vimvcxt); + _rl_vimvcxt = 0; + + return r; +} + +static int +vidomove_dispatch (m) + _rl_vimotion_cxt *m; +{ + int r; + + switch (m->op) + { + case VIM_DELETE: + r = vi_delete_dispatch (m); + break; + case VIM_CHANGE: + r = vi_change_dispatch (m); + break; + case VIM_YANK: + r = vi_yank_dispatch (m); + break; + default: + _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op); + r = 1; + break; + } + + RL_UNSETSTATE (RL_STATE_VIMOTION); + return r; +} + +int rl_vi_rubout (count, key) int count, key; { - int p, opoint; + int opoint; if (count < 0) return (rl_vi_delete (-count, key)); @@ -1193,14 +1512,22 @@ static int _rl_vi_callback_char_search (data) _rl_callback_generic_arg *data; { + int c; #if defined (HANDLE_MULTIBYTE) - _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); #else RL_SETSTATE(RL_STATE_MOREINPUT); - _rl_vi_last_search_char = rl_read_key (); + c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); #endif + if (c <= 0) + return -1; + +#if !defined (HANDLE_MULTIBYTE) + _rl_vi_last_search_char = c; +#endif + _rl_callback_func = 0; _rl_want_redisplay = 1; @@ -1216,6 +1543,7 @@ int rl_vi_char_search (count, key) int count, key; { + int c; #if defined (HANDLE_MULTIBYTE) static char *target; static int tlen; @@ -1224,27 +1552,38 @@ rl_vi_char_search (count, key) #endif if (key == ';' || key == ',') - _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; + { + if (_rl_cs_orig_dir == 0) + return -1; +#if defined (HANDLE_MULTIBYTE) + if (_rl_vi_last_search_mblen == 0) + return -1; +#else + if (_rl_vi_last_search_char == 0) + return -1; +#endif + _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; + } else { switch (key) - { - case 't': - _rl_cs_orig_dir = _rl_cs_dir = FTO; - break; + { + case 't': + _rl_cs_orig_dir = _rl_cs_dir = FTO; + break; - case 'T': - _rl_cs_orig_dir = _rl_cs_dir = BTO; - break; + case 'T': + _rl_cs_orig_dir = _rl_cs_dir = BTO; + break; - case 'f': - _rl_cs_orig_dir = _rl_cs_dir = FFIND; - break; + case 'f': + _rl_cs_orig_dir = _rl_cs_dir = FFIND; + break; - case 'F': - _rl_cs_orig_dir = _rl_cs_dir = BFIND; - break; - } + case 'F': + _rl_cs_orig_dir = _rl_cs_dir = BFIND; + break; + } if (vi_redoing) { @@ -1252,21 +1591,27 @@ rl_vi_char_search (count, key) } #if defined (READLINE_CALLBACKS) else if (RL_ISSTATE (RL_STATE_CALLBACK)) - { - _rl_callback_data = _rl_callback_data_alloc (count); - _rl_callback_data->i1 = _rl_cs_dir; - _rl_callback_func = _rl_vi_callback_char_search; - return (0); - } + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = _rl_cs_dir; + _rl_callback_func = _rl_vi_callback_char_search; + return (0); + } #endif else { #if defined (HANDLE_MULTIBYTE) - _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); + if (c <= 0) + return -1; + _rl_vi_last_search_mblen = c; #else RL_SETSTATE(RL_STATE_MOREINPUT); - _rl_vi_last_search_char = rl_read_key (); + c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + return -1; + _rl_vi_last_search_char = c; #endif } } @@ -1302,7 +1647,7 @@ rl_vi_match (ignore, key) pre = rl_point; rl_forward_char (1, key); if (pre == rl_point) - break; + break; } } else @@ -1331,7 +1676,7 @@ rl_vi_match (ignore, key) { pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); if (tmp == pos) - pos--; + pos--; } if (pos >= 0) { @@ -1426,9 +1771,9 @@ _rl_vi_change_char (count, c, mb) } static int -_rl_vi_callback_getchar (mb, mblen) +_rl_vi_callback_getchar (mb, mlen) char *mb; - int mblen; + int mlen; { int c; @@ -1436,9 +1781,12 @@ _rl_vi_callback_getchar (mb, mblen) c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + return -1; + #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - c = _rl_read_mbstring (c, mb, mblen); + c = _rl_read_mbstring (c, mb, mlen); #endif return c; @@ -1454,6 +1802,9 @@ _rl_vi_callback_change_char (data) _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + if (c < 0) + return -1; + _rl_callback_func = 0; _rl_want_redisplay = 1; @@ -1485,6 +1836,9 @@ rl_vi_change_char (count, key) else _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + if (c < 0) + return -1; + return (_rl_vi_change_char (count, c, mb)); } @@ -1570,8 +1924,8 @@ rl_vi_replace (count, key) vi_replace_map[NEWLINE].function = rl_newline; /* If the normal vi insertion keymap has ^H bound to erase, do the - same here. Probably should remove the assignment to RUBOUT up - there, but I don't think it will make a difference in real life. */ + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && vi_insertion_keymap[CTRL ('H')].function == rl_rubout) vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; @@ -1619,7 +1973,7 @@ _rl_vi_set_mark () ch = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (ch < 'a' || ch > 'z') + if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ { rl_ding (); return -1; @@ -1671,7 +2025,7 @@ _rl_vi_goto_mark () rl_point = rl_mark; return 0; } - else if (ch < 'a' || ch > 'z') + else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ { rl_ding (); return -1; |