1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992 Free Software Foundation, Inc.
5 This file is part of the Readline Library (the Library), a set of
6 routines for providing Emacs style line input to programs that ask
9 The Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 1, or (at your option)
14 The Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #define READLINE_LIBRARY
25 #if defined (HAVE_CONFIG_H)
29 #include <sys/types.h>
32 #if defined (HAVE_UNISTD_H)
36 #if defined (HAVE_STDLIB_H)
39 # include "ansi_stdlib.h"
49 #define abs(x) (((x) >= 0) ? (x) : -(x))
51 extern char *xmalloc (), *xrealloc ();
53 /* Variables imported from readline.c */
54 extern int rl_point, rl_end, rl_line_buffer_len;
55 extern int rl_editing_mode;
56 extern char *rl_prompt;
57 extern char *rl_line_buffer;
58 extern HIST_ENTRY *saved_line_for_history;
59 extern Function *rl_last_func;
61 /* Functions imported from the rest of the library. */
62 extern int _rl_free_history_entry ();
63 extern char *_rl_make_prompt_for_search ();
64 extern void _rl_restore_prompt ();
65 extern void rl_extend_line_buffer ();
67 static char *noninc_search_string = (char *) NULL;
68 static int noninc_history_pos;
69 static char *prev_line_found = (char *) NULL;
71 /* Search the history list for STRING starting at absolute history position
72 POS. If STRING begins with `^', the search must match STRING at the
73 beginning of a history line, otherwise a full substring match is performed
74 for STRING. DIR < 0 means to search backwards through the history list,
75 DIR >= 0 means to search forward. */
77 noninc_search_from_pos (string, pos, dir)
83 old = where_history ();
84 history_set_pos (pos);
87 ret = history_search_prefix (string + 1, dir);
89 ret = history_search (string, dir);
92 ret = where_history ();
94 history_set_pos (old);
98 /* Search for a line in the history containing STRING. If DIR is < 0, the
99 search is backwards through previous entries, else through subsequent
102 noninc_dosearch (string, dir)
106 int oldpos, pos, line_len;
109 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
115 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
118 /* Search failed, current history position unchanged. */
119 maybe_unsave_line ();
126 noninc_history_pos = pos;
128 oldpos = where_history ();
129 history_set_pos (noninc_history_pos);
130 entry = current_history ();
131 #if defined (VI_MODE)
132 if (rl_editing_mode != vi_mode)
134 history_set_pos (oldpos);
136 line_len = strlen (entry->line);
137 if (line_len >= rl_line_buffer_len)
138 rl_extend_line_buffer (line_len);
139 strcpy (rl_line_buffer, entry->line);
141 rl_undo_list = (UNDO_LIST *)entry->data;
142 rl_end = strlen (rl_line_buffer);
146 if (saved_line_for_history)
147 _rl_free_history_entry (saved_line_for_history);
148 saved_line_for_history = (HIST_ENTRY *)NULL;
151 /* Search non-interactively through the history list. DIR < 0 means to
152 search backwards through the history of previous commands; otherwise
153 the search is for commands subsequent to the current position in the
154 history list. PCHAR is the character to use for prompting when reading
155 the search string; if not specified (0), it defaults to `:'. */
157 noninc_search (dir, pchar)
165 saved_point = rl_point;
167 /* Use the line buffer to read the search string. */
168 rl_line_buffer[0] = 0;
169 rl_end = rl_point = 0;
171 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
172 rl_message (p, 0, 0);
175 #define SEARCH_RETURN _rl_restore_prompt (); return
177 /* Read the search string. */
178 while (c = rl_read_key ())
186 maybe_unsave_line ();
188 rl_point = saved_point;
195 rl_unix_word_rubout (1, c);
199 rl_unix_line_discard (1, c);
210 maybe_unsave_line ();
212 rl_point = saved_point;
220 (*rl_redisplay_function) ();
224 /* If rl_point == 0, we want to re-use the previous search string and
225 start from the saved history position. If there's no previous search
229 if (!noninc_search_string)
237 /* We want to start the search from the current history position. */
238 noninc_history_pos = where_history ();
239 if (noninc_search_string)
240 free (noninc_search_string);
241 noninc_search_string = savestring (rl_line_buffer);
244 _rl_restore_prompt ();
245 noninc_dosearch (noninc_search_string, dir);
248 /* Search forward through the history list for a string. If the vi-mode
249 code calls this, KEY will be `?'. */
251 rl_noninc_forward_search (count, key)
254 noninc_search (1, (key == '?') ? '?' : 0);
258 /* Reverse search the history list for a string. If the vi-mode code
259 calls this, KEY will be `/'. */
261 rl_noninc_reverse_search (count, key)
264 noninc_search (-1, (key == '/') ? '/' : 0);
268 /* Search forward through the history list for the last string searched
269 for. If there is no saved search string, abort. */
271 rl_noninc_forward_search_again (count, key)
274 if (!noninc_search_string)
279 noninc_dosearch (noninc_search_string, 1);
283 /* Reverse search in the history list for the last string searched
284 for. If there is no saved search string, abort. */
286 rl_noninc_reverse_search_again (count, key)
289 if (!noninc_search_string)
294 noninc_dosearch (noninc_search_string, -1);
299 rl_history_search_internal (count, direction)
300 int count, direction;
302 HIST_ENTRY *temp, *old_temp;
307 temp = old_temp = (HIST_ENTRY *)NULL;
310 temp = (direction < 0) ? previous_history () : next_history ();
313 /* On an empty prefix, make this the same as previous-history. */
319 if (STREQN (rl_line_buffer, temp->line, rl_point))
321 /* Don't find multiple instances of the same line. */
322 if (prev_line_found && STREQ (prev_line_found, temp->line))
326 prev_line_found = temp->line;
333 if (direction < 0 && old_temp)
337 maybe_unsave_line ();
343 line_len = strlen (temp->line);
344 if (line_len >= rl_line_buffer_len)
345 rl_extend_line_buffer (line_len);
346 strcpy (rl_line_buffer, temp->line);
347 rl_undo_list = (UNDO_LIST *)temp->data;
352 /* Search forward in the history for the string of characters
353 from the start of the line to rl_point. This is a non-incremental
356 rl_history_search_forward (count, ignore)
361 if (rl_last_func != rl_history_search_forward)
362 prev_line_found = (char *)NULL;
363 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
366 /* Search backward through the history for the string of characters
367 from the start of the line to rl_point. This is a non-incremental
370 rl_history_search_backward (count, ignore)
375 if (rl_last_func != rl_history_search_backward)
376 prev_line_found = (char *)NULL;
377 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));