diff options
Diffstat (limited to 'readline/isearch.c')
-rw-r--r-- | readline/isearch.c | 238 |
1 files changed, 178 insertions, 60 deletions
diff --git a/readline/isearch.c b/readline/isearch.c index 952c10d..c1ea5b3 100644 --- a/readline/isearch.c +++ b/readline/isearch.c @@ -4,7 +4,7 @@ /* */ /* **************************************************************** */ -/* Copyright (C) 1987,1989 Free Software Foundation, Inc. +/* Copyright (C) 1987-2002 Free Software Foundation, Inc. This file contains the Readline Library (the Library), a set of routines for providing Emacs style line input to programs that ask @@ -45,6 +45,8 @@ #endif #include "rldefs.h" +#include "rlmbutil.h" + #include "readline.h" #include "history.h" @@ -52,18 +54,24 @@ #include "xmalloc.h" /* Variables exported to other files in the readline library. */ -unsigned char *_rl_isearch_terminators = (unsigned char *)NULL; +char *_rl_isearch_terminators = (char *)NULL; /* Variables imported from other files in the readline library. */ -extern HIST_ENTRY *saved_line_for_history; +extern HIST_ENTRY *_rl_saved_line_for_history; /* Forward declarations */ -static int rl_search_history __P((int, int)); +static int rl_search_history PARAMS((int, int)); /* Last line found by the current incremental search, so we don't `find' identical lines many times in a row. */ static char *prev_line_found; +/* Last search string and its length. */ +static char *last_isearch_string; +static int last_isearch_string_len; + +static char *default_isearch_terminators = "\033\012"; + /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ int @@ -97,7 +105,7 @@ rl_display_search (search_string, reverse_p, where) searchlen = (search_string && *search_string) ? strlen (search_string) : 0; - message = xmalloc (searchlen + 33); + message = (char *)xmalloc (searchlen + 33); msglen = 0; #if defined (NOTDEF) @@ -127,7 +135,7 @@ rl_display_search (search_string, reverse_p, where) strcpy (message + msglen, "': "); - rl_message ("%s", message, 0); + rl_message ("%s", message); free (message); (*rl_redisplay_function) (); } @@ -159,8 +167,12 @@ rl_search_history (direction, invoking_key) HIST_ENTRY **hlist; register int i; - int orig_point, orig_line, last_found_line; + int orig_point, orig_mark, orig_line, last_found_line; int c, found, failed, sline_len; + int n, wstart, wlen; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif /* The line currently being searched. */ char *sline; @@ -174,19 +186,21 @@ rl_search_history (direction, invoking_key) /* The list of characters which terminate the search, but are not subsequently executed. If the variable isearch-terminators has been set, we use that value, otherwise we use ESC and C-J. */ - unsigned char *isearch_terminators; + char *isearch_terminators; + RL_SETSTATE(RL_STATE_ISEARCH); orig_point = rl_point; + orig_mark = rl_mark; last_found_line = orig_line = where_history (); reverse = direction < 0; hlist = history_list (); allocated_line = (char *)NULL; isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators - : (unsigned char *)"\033\012"; + : default_isearch_terminators; /* Create an arrary of pointers to the lines that we want to search. */ - maybe_replace_line (); + rl_maybe_replace_line (); i = 0; if (hlist) for (i = 0; hlist[i]; i++); @@ -197,12 +211,12 @@ rl_search_history (direction, invoking_key) for (i = 0; i < hlen; i++) lines[i] = hlist[i]->line; - if (saved_line_for_history) - lines[i] = saved_line_for_history->line; + if (_rl_saved_line_for_history) + lines[i] = _rl_saved_line_for_history->line; else { /* Keep track of this so we can free it. */ - allocated_line = xmalloc (1 + strlen (rl_line_buffer)); + allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); strcpy (allocated_line, &rl_line_buffer[0]); lines[i] = allocated_line; } @@ -215,7 +229,7 @@ rl_search_history (direction, invoking_key) rl_save_prompt (); /* Initialize search parameters. */ - search_string = xmalloc (search_string_size = 128); + search_string = (char *)xmalloc (search_string_size = 128); *search_string = '\0'; search_string_index = 0; prev_line_found = (char *)0; /* XXX */ @@ -232,12 +246,20 @@ rl_search_history (direction, invoking_key) found = failed = 0; for (;;) { - Function *f = (Function *)NULL; + rl_command_func_t *f = (rl_command_func_t *)NULL; /* Read a key and decide how to proceed. */ + RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (_rl_keymap[c].type == ISFUNC) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, MB_LEN_MAX); +#endif + + /* Translate the keys we do something with to opcodes. */ + if (c >= 0 && _rl_keymap[c].type == ISFUNC) { f = _rl_keymap[c].function; @@ -245,34 +267,56 @@ rl_search_history (direction, invoking_key) c = reverse ? -1 : -2; else if (f == rl_forward_search_history) c = !reverse ? -1 : -2; + else if (f == rl_rubout) + c = -3; + else if (c == CTRL ('G')) + c = -4; + else if (c == CTRL ('W')) /* XXX */ + c = -5; + else if (c == CTRL ('Y')) /* XXX */ + c = -6; } -#if 0 - /* Let NEWLINE (^J) terminate the search for people who don't like - using ESC. ^M can still be used to terminate the search and - immediately execute the command. */ - if (c == ESC || c == NEWLINE) -#else /* The characters in isearch_terminators (set from the user-settable variable isearch-terminators) are used to terminate the search but not subsequently execute the character as a command. The default value is "\033\012" (ESC and C-J). */ if (strchr (isearch_terminators, c)) -#endif { /* ESC still terminates the search, but if there is pending input or if input arrives within 0.1 seconds (on systems with select(2)) it is used as a prefix character with rl_execute_next. WATCH OUT FOR THIS! This is intended to allow the arrow keys to be used like ^F and ^B are used - to terminate the search and execute the movement command. */ - if (c == ESC && _rl_input_available ()) /* XXX */ + to terminate the search and execute the movement command. + XXX - since _rl_input_available depends on the application- + settable keyboard timeout value, this could alternatively + use _rl_input_queued(100000) */ + if (c == ESC && _rl_input_available ()) rl_execute_next (ESC); break; } - if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G')) +#define ENDSRCH_CHAR(c) \ + ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (c); + break; + } + } + else +#endif + if (c >= 0 && ENDSRCH_CHAR (c)) { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ rl_execute_next (c); break; } @@ -281,13 +325,24 @@ rl_search_history (direction, invoking_key) { case -1: if (search_string_index == 0) - continue; + { + if (last_isearch_string) + { + search_string_size = 64 + last_isearch_string_len; + search_string = (char *)xrealloc (search_string, search_string_size); + strcpy (search_string, last_isearch_string); + search_string_index = last_isearch_string_len; + rl_display_search (search_string, reverse, -1); + break; + } + continue; + } else if (reverse) --line_index; else if (line_index != sline_len) ++line_index; else - ding (); + rl_ding (); break; /* switch directions */ @@ -296,40 +351,96 @@ rl_search_history (direction, invoking_key) reverse = direction < 0; break; - case CTRL ('G'): - strcpy (rl_line_buffer, lines[orig_line]); + /* delete character from search string. */ + case -3: /* C-H, DEL */ + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. But this will + do until we have a real isearch-undo. */ + if (search_string_index == 0) + rl_ding (); + else + search_string[--search_string_index] = '\0'; + + break; + + case -4: /* C-G */ + rl_replace_line (lines[orig_line], 0); rl_point = orig_point; - rl_end = strlen (rl_line_buffer); + rl_mark = orig_mark; rl_restore_prompt(); rl_clear_message (); if (allocated_line) free (allocated_line); free (lines); + RL_UNSETSTATE(RL_STATE_ISEARCH); return 0; -#if 0 - /* delete character from search string. */ - case -3: - if (search_string_index == 0) - ding (); - else + case -5: /* C-W */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + + /* if not in a word, move to one. */ + if (rl_alphabetic(rl_line_buffer[wstart]) == 0) { - search_string[--search_string_index] = '\0'; - /* This is tricky. To do this right, we need to keep a - stack of search positions for the current search, with - sentinels marking the beginning and end. */ + rl_ding (); + break; } + n = wstart; + while (n < rl_end && rl_alphabetic(rl_line_buffer[n])) + n++; + wlen = n - wstart + 1; + if (search_string_index + wlen + 1 >= search_string_size) + { + search_string_size += wlen + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (; wstart < n; wstart++) + search_string[search_string_index++] = rl_line_buffer[wstart]; + search_string[search_string_index] = '\0'; + break; + + case -6: /* C-Y */ + /* skip over portion of line we already matched */ + wstart = rl_point + search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + n = rl_end - wstart + 1; + if (search_string_index + n + 1 >= search_string_size) + { + search_string_size += n + 1; + search_string = (char *)xrealloc (search_string, search_string_size); + } + for (n = wstart; n < rl_end; n++) + search_string[search_string_index++] = rl_line_buffer[n]; + search_string[search_string_index] = '\0'; break; -#endif default: /* Add character to search string and continue search. */ if (search_string_index + 2 >= search_string_size) { search_string_size += 128; - search_string = xrealloc (search_string, search_string_size); + search_string = (char *)xrealloc (search_string, search_string_size); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int j, l; + for (j = 0, l = strlen (mb); j < l; ) + search_string[search_string_index++] = mb[j++]; } - search_string[search_string_index++] = c; + else +#endif + search_string[search_string_index++] = c; search_string[search_string_index] = '\0'; break; } @@ -384,7 +495,7 @@ rl_search_history (direction, invoking_key) if (failed) { /* We cannot find the search string. Ding the bell. */ - ding (); + rl_ding (); i = last_found_line; continue; /* XXX - was break */ } @@ -394,17 +505,9 @@ rl_search_history (direction, invoking_key) the location. */ if (found) { - int line_len; - prev_line_found = lines[i]; - line_len = strlen (lines[i]); - - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - - strcpy (rl_line_buffer, lines[i]); + rl_replace_line (lines[i], 0); rl_point = line_index; - rl_end = line_len; last_found_line = i; rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i); } @@ -420,23 +523,38 @@ rl_search_history (direction, invoking_key) rl_restore_prompt (); - /* Free the search string. */ - free (search_string); + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = search_string; + last_isearch_string_len = search_string_index; if (last_found_line < orig_line) rl_get_previous_history (orig_line - last_found_line, 0); else rl_get_next_history (last_found_line - orig_line, 0); - /* If the string was not found, put point at the end of the line. */ + /* If the string was not found, put point at the end of the last matching + line. If last_found_line == orig_line, we didn't find any matching + history lines at all, so put point back in its original position. */ if (line_index < 0) - line_index = strlen (rl_line_buffer); + { + if (last_found_line == orig_line) + line_index = orig_point; + else + line_index = strlen (rl_line_buffer); + rl_mark = orig_mark; + } + rl_point = line_index; + /* Don't worry about where to put the mark here; rl_get_previous_history + and rl_get_next_history take care of it. */ + rl_clear_message (); - if (allocated_line) - free (allocated_line); + FREE (allocated_line); free (lines); + RL_UNSETSTATE(RL_STATE_ISEARCH); + return 0; } |