X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=readline%2Fsearch.c;h=112f8072866e1669ccab106a433739cb3384521d;hb=95fc45e66fe1363261130a27022cfff16e460289;hp=ea98c6f897577af7ff5a04705dc168d3f26194e2;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/readline/search.c b/readline/search.c index ea98c6f897..112f807286 100644 --- a/readline/search.c +++ b/readline/search.c @@ -8,7 +8,7 @@ The 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 1, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. The Library is distributed in the hope that it will be useful, but @@ -19,32 +19,74 @@ 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, - 675 Mass Ave, Cambridge, MA 02139, USA. */ + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include #include -#if defined (__GNUC__) -# define alloca __builtin_alloca +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include #else -# if defined (sparc) || defined (HAVE_ALLOCA_H) -# include -# endif +# include "ansi_stdlib.h" #endif +#include "rldefs.h" #include "readline.h" #include "history.h" -extern char *xmalloc (), *xrealloc (); +#include "rlprivate.h" +#include "xmalloc.h" + +#ifdef abs +# undef abs +#endif +#define abs(x) (((x) >= 0) ? (x) : -(x)) -/* Variables imported from readline.c */ -extern int rl_point, rl_end, rl_line_buffer_len; -extern Keymap _rl_keymap; -extern char *rl_prompt; -extern char *rl_line_buffer; extern HIST_ENTRY *saved_line_for_history; +/* Functions imported from the rest of the library. */ +extern int _rl_free_history_entry __P((HIST_ENTRY *)); + static char *noninc_search_string = (char *) NULL; -static int noninc_history_pos = 0; +static int noninc_history_pos; + +static char *prev_line_found = (char *) NULL; + +static int rl_history_search_len; +static int rl_history_search_pos; +static char *history_search_string; +static int history_string_size; + +/* Make the data from the history entry ENTRY be the contents of the + current line. This doesn't do anything with rl_point; the caller + must set it. */ +static void +make_history_line_current (entry) + HIST_ENTRY *entry; +{ + int line_len; + + line_len = strlen (entry->line); + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + strcpy (rl_line_buffer, entry->line); + + rl_undo_list = (UNDO_LIST *)entry->data; + rl_end = line_len; + + if (saved_line_for_history) + _rl_free_history_entry (saved_line_for_history); + saved_line_for_history = (HIST_ENTRY *)NULL; +} /* Search the history list for STRING starting at absolute history position POS. If STRING begins with `^', the search must match STRING at the @@ -84,7 +126,7 @@ noninc_dosearch (string, dir) int oldpos, pos; HIST_ENTRY *entry; - if (string == 0 || *string == 0 || noninc_history_pos < 0) + if (string == 0 || *string == '\0' || noninc_history_pos < 0) { ding (); return; @@ -106,25 +148,15 @@ noninc_dosearch (string, dir) oldpos = where_history (); history_set_pos (noninc_history_pos); entry = current_history (); +#if defined (VI_MODE) + if (rl_editing_mode != vi_mode) +#endif history_set_pos (oldpos); - { - int line_len; + make_history_line_current (entry); - line_len = strlen (entry->line); - if (line_len >= rl_line_buffer_len) - rl_extend_line_buffer (line_len); - strcpy (rl_line_buffer, entry->line); - } - - rl_undo_list = (UNDO_LIST *)entry->data; - rl_end = strlen (rl_line_buffer); rl_point = 0; rl_clear_message (); - - if (saved_line_for_history) - free_history_entry (saved_line_for_history); - saved_line_for_history = (HIST_ENTRY *)NULL; } /* Search non-interactively through the history list. DIR < 0 means to @@ -137,7 +169,7 @@ noninc_search (dir, pchar) int dir; int pchar; { - int saved_point, c, pmtlen; + int saved_point, c; char *p; maybe_save_line (); @@ -147,14 +179,11 @@ noninc_search (dir, pchar) rl_line_buffer[0] = 0; rl_end = rl_point = 0; - pmtlen = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; - p = (char *)alloca (2 + pmtlen); - if (pmtlen) - strcpy (p, rl_prompt); - p[pmtlen] = pchar ? pchar : ':'; - p[pmtlen + 1] = '\0'; - + p = _rl_make_prompt_for_search (pchar ? pchar : ':'); rl_message (p, 0, 0); + free (p); + +#define SEARCH_RETURN rl_restore_prompt (); return /* Read the search string. */ while (c = rl_read_key ()) @@ -168,13 +197,17 @@ noninc_search (dir, pchar) maybe_unsave_line (); rl_clear_message (); rl_point = saved_point; - return; + SEARCH_RETURN; } - /* FALLTHROUGH */ + rl_rubout (1, c); + break; case CTRL('W'): + rl_unix_word_rubout (1, c); + break; + case CTRL('U'): - rl_dispatch (c, _rl_keymap); + rl_unix_line_discard (1, c); break; case RETURN: @@ -189,13 +222,13 @@ noninc_search (dir, pchar) rl_clear_message (); rl_point = saved_point; ding (); - return; + SEARCH_RETURN; default: rl_insert (1, c); break; } - rl_redisplay (); + (*rl_redisplay_function) (); } dosearch: @@ -207,45 +240,44 @@ noninc_search (dir, pchar) if (!noninc_search_string) { ding (); - return; + SEARCH_RETURN; } } else { /* We want to start the search from the current history position. */ noninc_history_pos = where_history (); - if (noninc_search_string) - free (noninc_search_string); + FREE (noninc_search_string); noninc_search_string = savestring (rl_line_buffer); } + rl_restore_prompt (); noninc_dosearch (noninc_search_string, dir); } /* Search forward through the history list for a string. If the vi-mode code calls this, KEY will be `?'. */ +int rl_noninc_forward_search (count, key) int count, key; { - if (key == '?') - noninc_search (1, '?'); - else - noninc_search (1, 0); + noninc_search (1, (key == '?') ? '?' : 0); + return 0; } /* Reverse search the history list for a string. If the vi-mode code calls this, KEY will be `/'. */ +int rl_noninc_reverse_search (count, key) int count, key; { - if (key == '/') - noninc_search (-1, '/'); - else - noninc_search (-1, 0); + noninc_search (-1, (key == '/') ? '/' : 0); + return 0; } /* Search forward through the history list for the last string searched for. If there is no saved search string, abort. */ +int rl_noninc_forward_search_again (count, key) int count, key; { @@ -255,10 +287,12 @@ rl_noninc_forward_search_again (count, key) return (-1); } noninc_dosearch (noninc_search_string, 1); + return 0; } /* Reverse search in the history list for the last string searched for. If there is no saved search string, abort. */ +int rl_noninc_reverse_search_again (count, key) int count, key; { @@ -268,4 +302,122 @@ rl_noninc_reverse_search_again (count, key) return (-1); } noninc_dosearch (noninc_search_string, -1); + return 0; +} + +static int +rl_history_search_internal (count, dir) + int count, dir; +{ + HIST_ENTRY *temp; + int ret, oldpos; + + maybe_save_line (); + temp = (HIST_ENTRY *)NULL; + + /* Search COUNT times through the history for a line whose prefix + matches history_search_string. When this loop finishes, TEMP, + if non-null, is the history line to copy into the line buffer. */ + while (count) + { + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + if (ret == -1) + break; + + /* Get the history entry we found. */ + rl_history_search_pos = ret; + oldpos = where_history (); + history_set_pos (rl_history_search_pos); + temp = current_history (); + history_set_pos (oldpos); + + /* Don't find multiple instances of the same line. */ + if (prev_line_found && STREQ (prev_line_found, temp->line)) + continue; + prev_line_found = temp->line; + count--; + } + + /* If we didn't find anything at all, return. */ + if (temp == 0) + { + maybe_unsave_line (); + ding (); + /* If you don't want the saved history line (last match) to show up + in the line buffer after the search fails, change the #if 0 to + #if 1 */ +#if 0 + if (rl_point > rl_history_search_len) + { + rl_point = rl_end = rl_history_search_len; + rl_line_buffer[rl_end] = '\0'; + } +#else + rl_point = rl_history_search_len; /* maybe_unsave_line changes it */ +#endif + return 1; + } + + /* Copy the line we found into the current line buffer. */ + make_history_line_current (temp); + + rl_point = rl_history_search_len; + return 0; +} + +static void +rl_history_search_reinit () +{ + rl_history_search_pos = where_history (); + rl_history_search_len = rl_point; + prev_line_found = (char *)NULL; + if (rl_point) + { + if (rl_history_search_len >= history_string_size - 2) + { + history_string_size = rl_history_search_len + 2; + history_search_string = xrealloc (history_search_string, history_string_size); + } + history_search_string[0] = '^'; + strncpy (history_search_string + 1, rl_line_buffer, rl_point); + history_search_string[rl_point + 1] = '\0'; + } +} + +/* Search forward in the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_forward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_next_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); +} + +/* Search backward through the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_backward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_previous_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); }