diff options
Diffstat (limited to 'readline/text.c')
-rw-r--r-- | readline/text.c | 327 |
1 files changed, 213 insertions, 114 deletions
diff --git a/readline/text.c b/readline/text.c index 2a7b724..9053e96 100644 --- a/readline/text.c +++ b/readline/text.c @@ -1,6 +1,6 @@ /* text.c -- text handling commands for readline. */ -/* Copyright (C) 1987-2002 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 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. @@ -62,6 +62,11 @@ static int rl_change_case PARAMS((int, int)); static int _rl_char_search PARAMS((int, int, int)); +#if defined (READLINE_CALLBACKS) +static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *)); +static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *)); +#endif + /* **************************************************************** */ /* */ /* Insert and Delete */ @@ -170,6 +175,9 @@ _rl_fix_point (fix_mark_too) } #undef _RL_FIX_POINT +/* Replace the contents of the line buffer between START and END with + TEXT. The operation is undoable. To replace the entire line in an + undoable mode, use _rl_replace_text(text, 0, rl_end); */ int _rl_replace_text (text, start, end) const char *text; @@ -417,8 +425,7 @@ rl_end_of_line (count, key) return 0; } -/* XXX - these might need changes for multibyte characters */ -/* Move forward a word. We do what Emacs does. */ +/* Move forward a word. We do what Emacs does. Handles multibyte chars. */ int rl_forward_word (count, key) int count, key; @@ -435,68 +442,80 @@ rl_forward_word (count, key) /* If we are not in a word, move forward until we are in one. Then, move forward until we hit a non-alphabetic character. */ - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c) == 0) + c = _rl_char_value (rl_line_buffer, rl_point); + + if (_rl_walphabetic (c) == 0) { - while (++rl_point < rl_end) + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + while (rl_point < rl_end) { - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c)) + c = _rl_char_value (rl_line_buffer, rl_point); + if (_rl_walphabetic (c)) break; + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); } } if (rl_point == rl_end) return 0; - while (++rl_point < rl_end) + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + while (rl_point < rl_end) { - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c) == 0) + c = _rl_char_value (rl_line_buffer, rl_point); + if (_rl_walphabetic (c) == 0) break; + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); } + --count; } return 0; } -/* Move backward a word. We do what Emacs does. */ +/* Move backward a word. We do what Emacs does. Handles multibyte chars. */ int rl_backward_word (count, key) int count, key; { - int c; + int c, p; if (count < 0) return (rl_forward_word (-count, key)); while (count) { - if (!rl_point) + if (rl_point == 0) return 0; /* Like rl_forward_word (), except that we look at the characters just before point. */ - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c) == 0) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + + if (_rl_walphabetic (c) == 0) { - while (--rl_point) + rl_point = p; + while (rl_point > 0) { - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c)) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + if (_rl_walphabetic (c)) break; + rl_point = p; } } while (rl_point) { - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c) == 0) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + if (_rl_walphabetic (c) == 0) break; else - --rl_point; + rl_point = p; } --count; @@ -753,10 +772,8 @@ _rl_insert_char (count, c) return 0; } -#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX == 1 || rl_byte_oriented) { -#endif /* We are inserting a single character. If there is pending input, then make a string of all of the pending characters that are bound to rl_insert, and insert @@ -772,8 +789,8 @@ _rl_insert_char (count, c) str[0] = c; rl_insert_text (str); } -#if defined (HANDLE_MULTIBYTE) } +#if defined (HANDLE_MULTIBYTE) else { rl_insert_text (incoming); @@ -801,13 +818,10 @@ _rl_overwrite_char (count, c) k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); #endif + rl_begin_undo_group (); + for (i = 0; i < count; i++) { - rl_begin_undo_group (); - - if (rl_point < rl_end) - rl_delete (1, c); - #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_insert_text (mbkey); @@ -815,9 +829,12 @@ _rl_overwrite_char (count, c) #endif _rl_insert_char (1, c); - rl_end_undo_group (); + if (rl_point < rl_end) + rl_delete (1, c); } + rl_end_undo_group (); + return 0; } @@ -830,27 +847,63 @@ rl_insert (count, c) } /* Insert the next typed character verbatim. */ -int -rl_quoted_insert (count, key) - int count, key; +static int +_rl_insert_next (count) + int count; { int c; -#if defined (HANDLE_SIGNALS) - _rl_disable_tty_signals (); -#endif - RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); #if defined (HANDLE_SIGNALS) - _rl_restore_tty_signals (); + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) + _rl_restore_tty_signals (); #endif return (_rl_insert_char (count, c)); } +#if defined (READLINE_CALLBACKS) +static int +_rl_insert_next_callback (data) + _rl_callback_generic_arg *data; +{ + int count; + + count = data->count; + + /* Deregister function, let rl_callback_read_char deallocate data */ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return _rl_insert_next (count); +} +#endif + +int +rl_quoted_insert (count, key) + int count, key; +{ + /* Let's see...should the callback interface futz with signal handling? */ +#if defined (HANDLE_SIGNALS) + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) + _rl_disable_tty_signals (); +#endif + +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_func = _rl_insert_next_callback; + return (0); + } +#endif + + return _rl_insert_next (count); +} + /* Insert a tab character. */ int rl_tab_insert (count, key) @@ -877,7 +930,8 @@ rl_newline (count, key) if (rl_editing_mode == vi_mode) { _rl_vi_done_inserting (); - _rl_vi_reset_last (); + if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */ + _rl_vi_reset_last (); } #endif /* VI_MODE */ @@ -935,9 +989,12 @@ _rl_overwrite_rubout (count, key) rl_delete_text (opoint, rl_point); /* Emacs puts point at the beginning of the sequence of spaces. */ - opoint = rl_point; - _rl_insert_char (l, ' '); - rl_point = opoint; + if (rl_point < rl_end) + { + opoint = rl_point; + _rl_insert_char (l, ' '); + rl_point = opoint; + } rl_end_undo_group (); @@ -981,43 +1038,17 @@ _rl_rubout_char (count, key) return -1; } + orig_point = rl_point; if (count > 1 || rl_explicit_arg) { - orig_point = rl_point; -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_backward_char (count, key); - else -#endif - rl_backward_byte (count, key); + rl_backward_char (count, key); rl_kill_text (orig_point, rl_point); } - else + else if (MB_CUR_MAX == 1 || rl_byte_oriented) { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX == 1 || rl_byte_oriented) - { -#endif - c = rl_line_buffer[--rl_point]; - rl_delete_text (rl_point, rl_point + 1); -#if defined (HANDLE_MULTIBYTE) - } - else - { - int orig_point; - - orig_point = rl_point; - rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); - c = rl_line_buffer[rl_point]; - rl_delete_text (rl_point, orig_point); - } -#endif /* HANDLE_MULTIBYTE */ - - /* I don't think that the hack for end of line is needed for - multibyte chars. */ -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX == 1 || rl_byte_oriented) -#endif + c = rl_line_buffer[--rl_point]; + rl_delete_text (rl_point, orig_point); + /* The erase-at-end-of-line hack is of questionable merit now. */ if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) { int l; @@ -1025,6 +1056,11 @@ _rl_rubout_char (count, key) _rl_erase_at_end_of_line (l); } } + else + { + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + rl_delete_text (rl_point, orig_point); + } return 0; } @@ -1049,11 +1085,9 @@ rl_delete (count, key) if (count > 1 || rl_explicit_arg) { int orig_point = rl_point; -#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_forward_char (count, key); else -#endif rl_forward_byte (count, key); r = rl_kill_text (orig_point, rl_point); @@ -1063,11 +1097,8 @@ rl_delete (count, key) else { int new_point; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); - else - new_point = rl_point + 1; - + + new_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); return (rl_delete_text (rl_point, new_point)); } } @@ -1106,6 +1137,10 @@ rl_delete_horizontal_space (count, ignore) rl_delete_text (start, rl_point); rl_point = start; } + + if (rl_point < 0) + rl_point = 0; + return 0; } @@ -1199,42 +1234,80 @@ static int rl_change_case (count, op) int count, op; { - register int start, end; - int inword, c; + int start, next, end; + int inword, c, nc, nop; +#if defined (HANDLE_MULTIBYTE) + wchar_t wc, nwc; + char mb[MB_LEN_MAX+1]; + int mblen, p; + mbstate_t ps; +#endif start = rl_point; rl_forward_word (count, 0); end = rl_point; + if (op != UpCase && op != DownCase && op != CapCase) + { + rl_ding (); + return -1; + } + if (count < 0) SWAP (start, end); +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + /* We are going to modify some text, so let's prepare to undo it. */ rl_modifying (start, end); - for (inword = 0; start < end; start++) + inword = 0; + while (start < end) { - c = rl_line_buffer[start]; - switch (op) - { - case UpCase: - rl_line_buffer[start] = _rl_to_upper (c); - break; - - case DownCase: - rl_line_buffer[start] = _rl_to_lower (c); - break; + c = _rl_char_value (rl_line_buffer, start); + /* This assumes that the upper and lower case versions are the same width. */ + next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO); - case CapCase: - rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); - inword = rl_alphabetic (rl_line_buffer[start]); - break; + if (_rl_walphabetic (c) == 0) + { + inword = 0; + start = next; + continue; + } - default: - rl_ding (); - return -1; + if (op == CapCase) + { + nop = inword ? DownCase : UpCase; + inword = 1; + } + else + nop = op; + if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c)) + { + nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); + rl_line_buffer[start] = nc; + } +#if defined (HANDLE_MULTIBYTE) + else + { + mbrtowc (&wc, rl_line_buffer + start, end - start, &ps); + nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); + if (nwc != wc) /* just skip unchanged characters */ + { + mblen = wcrtomb (mb, nwc, &ps); + if (mblen > 0) + mb[mblen] = '\0'; + /* Assume the same width */ + strncpy (rl_line_buffer + start, mb, mblen); + } } +#endif + + start = next; } + rl_point = end; return 0; } @@ -1314,11 +1387,11 @@ rl_transpose_chars (count, key) { #if defined (HANDLE_MULTIBYTE) char *dummy; - int i, prev_point; + int i; #else char dummy[2]; #endif - int char_length; + int char_length, prev_point; if (count == 0) return 0; @@ -1333,20 +1406,12 @@ rl_transpose_chars (count, key) if (rl_point == rl_end) { - 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 = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); count = 1; } -#if defined (HANDLE_MULTIBYTE) prev_point = rl_point; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); - else -#endif - rl_point--; + rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); #if defined (HANDLE_MULTIBYTE) char_length = prev_point - rl_point; @@ -1480,10 +1545,33 @@ _rl_char_search (count, fdir, bdir) } #endif /* !HANDLE_MULTIBYTE */ +#if defined (READLINE_CALLBACKS) +static int +_rl_char_search_callback (data) + _rl_callback_generic_arg *data; +{ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_char_search (data->count, data->i1, data->i2)); +} +#endif + int rl_char_search (count, key) int count, key; { +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = FFIND; + _rl_callback_data->i2 = BFIND; + _rl_callback_func = _rl_char_search_callback; + return (0); + } +#endif + return (_rl_char_search (count, FFIND, BFIND)); } @@ -1491,6 +1579,17 @@ int rl_backward_char_search (count, key) int count, key; { +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = BFIND; + _rl_callback_data->i2 = FFIND; + _rl_callback_func = _rl_char_search_callback; + return (0); + } +#endif + return (_rl_char_search (count, BFIND, FFIND)); } |