From 011c1d1c0766c65517ebd495465c99e86edb63ec Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 11 Oct 2010 14:49:26 -0700 Subject: Update to bash-4.1 --- lib/readline/vi_mode.c | 143 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 33 deletions(-) (limited to 'lib/readline/vi_mode.c') diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index d0b7e33..2a120c0 100644 --- a/lib/readline/vi_mode.c +++ b/lib/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-2009 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 . +*/ + #define READLINE_LIBRARY /* **************************************************************** */ @@ -69,7 +69,7 @@ int _rl_vi_last_command = 'i'; /* default `.' puts you in insert 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 +101,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]; @@ -131,9 +131,10 @@ static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); 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); @@ -211,6 +212,15 @@ rl_vi_redo (count, c) if (rl_point > 0) _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) @@ -220,6 +230,15 @@ rl_vi_redo (count, c) 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); vi_redoing = 0; @@ -584,7 +603,7 @@ 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); } @@ -647,6 +666,14 @@ 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; @@ -690,7 +717,10 @@ _rl_vi_done_inserting () } else { - if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && 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') @@ -739,6 +769,7 @@ _rl_vi_change_mbchar_case (count) wchar_t wc; char mb[MB_LEN_MAX+1]; int mlen, p; + size_t m; mbstate_t ps; memset (&ps, 0, sizeof (mbstate_t)); @@ -746,7 +777,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)) @@ -886,6 +921,13 @@ rl_vi_domove (key, nextkey) RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c < 0) + { + *nextkey = 0; + return -1; + } + *nextkey = c; if (!member (c, vi_motion)) @@ -902,6 +944,11 @@ rl_vi_domove (key, nextkey) RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); /* real command */ RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + { + *nextkey = 0; + return -1; + } *nextkey = c; } else if (key == c && (key == 'd' || key == 'y' || key == 'c')) @@ -1033,13 +1080,15 @@ int rl_vi_delete_to (count, key) int count, key; { - int c; + int c, start_pos; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); else if (vi_redoing) rl_stuff_char (_rl_vi_last_motion); + start_pos = rl_point; + if (rl_vi_domove (key, &c)) { rl_ding (); @@ -1048,7 +1097,8 @@ rl_vi_delete_to (count, key) /* 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`", c) == 0) && (rl_point >= start_pos)) && + (rl_mark < rl_end)) rl_mark++; rl_kill_text (rl_point, rl_mark); @@ -1077,7 +1127,8 @@ rl_vi_change_to (count, key) /* 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`", c) == 0) && (rl_point >= start_pos)) && + (rl_mark < rl_end)) rl_mark++; /* The cursor never moves with c[wW]. */ @@ -1112,12 +1163,13 @@ int rl_vi_yank_to (count, key) int count, key; { - int c, save; + int c, start_pos; - save = rl_point; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); + start_pos = rl_point; + if (rl_vi_domove (key, &c)) { rl_ding (); @@ -1126,14 +1178,15 @@ rl_vi_yank_to (count, key) /* 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`", c) == 0) && (rl_point >= start_pos)) && + (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 = start_pos; return (0); } @@ -1224,14 +1277,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; @@ -1247,6 +1308,7 @@ int rl_vi_char_search (count, key) int count, key; { + int c; #if defined (HANDLE_MULTIBYTE) static char *target; static int tlen; @@ -1293,11 +1355,17 @@ rl_vi_char_search (count, key) 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 } } @@ -1467,6 +1535,9 @@ _rl_vi_callback_getchar (mb, mlen) 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, mlen); @@ -1485,6 +1556,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; @@ -1516,6 +1590,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)); } @@ -1650,7 +1727,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; @@ -1702,7 +1779,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; -- cgit v1.2.3