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
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 "readline.h"
#include "history.h"
+#include "rlprivate.h"
+#include "xmalloc.h"
+
#ifdef abs
# undef abs
#endif
#define abs(x) (((x) >= 0) ? (x) : -(x))
-extern char *xmalloc (), *xrealloc ();
-
-/* Variables imported from readline.c */
-extern int rl_point, rl_end, rl_line_buffer_len;
-extern int rl_editing_mode;
-extern char *rl_prompt;
-extern char *rl_line_buffer;
extern HIST_ENTRY *saved_line_for_history;
-extern Function *rl_last_func;
/* Functions imported from the rest of the library. */
-extern int _rl_free_history_entry ();
-extern char *_rl_make_prompt_for_search ();
-extern void rl_extend_line_buffer ();
+extern int _rl_free_history_entry __P((HIST_ENTRY *));
static char *noninc_search_string = (char *) NULL;
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
beginning of a history line, otherwise a full substring match is performed
char *string;
int dir;
{
- int oldpos, pos, line_len;
+ int oldpos, pos;
HIST_ENTRY *entry;
if (string == 0 || *string == '\0' || noninc_history_pos < 0)
#endif
history_set_pos (oldpos);
- line_len = strlen (entry->line);
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
- strcpy (rl_line_buffer, entry->line);
+ make_history_line_current (entry);
- rl_undo_list = (UNDO_LIST *)entry->data;
- rl_end = strlen (rl_line_buffer);
rl_point = 0;
rl_clear_message ();
-
- if (saved_line_for_history)
- _rl_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
{
/* 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);
}
}
static int
-rl_history_search_internal (count, direction)
- int count, direction;
+rl_history_search_internal (count, dir)
+ int count, dir;
{
- HIST_ENTRY *temp, *old_temp;
- int line_len;
+ HIST_ENTRY *temp;
+ int ret, oldpos;
maybe_save_line ();
+ temp = (HIST_ENTRY *)NULL;
- temp = old_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)
{
- temp = (direction < 0) ? previous_history () : next_history ();
- if (temp == 0)
- break;
- /* On an empty prefix, make this the same as previous-history. */
- if (rl_point == 0)
- {
- count--;
- continue;
- }
- if (STREQN (rl_line_buffer, temp->line, rl_point))
- {
- /* Don't find multiple instances of the same line. */
- if (prev_line_found && STREQ (prev_line_found, temp->line))
- continue;
- if (direction < 0)
- old_temp = temp;
- prev_line_found = temp->line;
- 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)
{
- if (direction < 0 && old_temp)
- temp = old_temp;
- else
- {
- maybe_unsave_line ();
- ding ();
- return 1;
- }
+ 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;
}
- line_len = strlen (temp->line);
- if (line_len >= rl_line_buffer_len)
- rl_extend_line_buffer (line_len);
- strcpy (rl_line_buffer, temp->line);
- rl_undo_list = (UNDO_LIST *)temp->data;
- rl_end = line_len;
+ /* 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. */
{
if (count == 0)
return (0);
- if (rl_last_func != rl_history_search_forward)
- prev_line_found = (char *)NULL;
+
+ 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));
}
{
if (count == 0)
return (0);
- if (rl_last_func != rl_history_search_backward)
- prev_line_found = (char *)NULL;
+
+ 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));
}