X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Freadline%2Fvi_mode.c;h=5f35cf080653ea5f3881a2b61343b439913d32aa;hb=3185942a5234e26ab13fa02f9c51d340cec514f8;hp=ac5fd7446dcf611d5cea7980e63c848c15233214;hpb=95732b497d12c98613bb3c5db16b61f377501a59;p=platform%2Fupstream%2Fbash.git diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index ac5fd74..5f35cf0 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]; @@ -109,12 +109,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) @@ -205,7 +209,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 +602,36 @@ 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; + point = rl_point; rl_forward_char (1, key); 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 +665,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,7 +716,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') @@ -716,7 +767,7 @@ _rl_vi_change_mbchar_case (count) { wchar_t wc; char mb[MB_LEN_MAX+1]; - int mblen, p; + int mlen, p; mbstate_t ps; memset (&ps, 0, sizeof (mbstate_t)); @@ -740,9 +791,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? */ @@ -820,6 +871,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 () { @@ -855,6 +915,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)) @@ -871,6 +938,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')) @@ -1002,13 +1074,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 (); @@ -1017,7 +1091,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); @@ -1046,7 +1121,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]. */ @@ -1081,12 +1157,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 (); @@ -1095,14 +1172,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); } @@ -1111,7 +1189,7 @@ 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 +1271,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 +1302,7 @@ int rl_vi_char_search (count, key) int count, key; { + int c; #if defined (HANDLE_MULTIBYTE) static char *target; static int tlen; @@ -1262,11 +1349,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 } } @@ -1426,9 +1519,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 +1529,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 +1550,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 +1584,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)); } @@ -1619,7 +1721,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 +1773,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;