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_extend_line_buffer ();
66
static char *noninc_search_string = (char *) NULL;
67
static int noninc_history_pos;
68
static char *prev_line_found = (char *) NULL;
70
/* Search the history list for STRING starting at absolute history position
71
POS. If STRING begins with `^', the search must match STRING at the
72
beginning of a history line, otherwise a full substring match is performed
73
for STRING. DIR < 0 means to search backwards through the history list,
74
DIR >= 0 means to search forward. */
76
noninc_search_from_pos (string, pos, dir)
82
old = where_history ();
83
history_set_pos (pos);
86
ret = history_search_prefix (string + 1, dir);
88
ret = history_search (string, dir);
91
ret = where_history ();
93
history_set_pos (old);
97
/* Search for a line in the history containing STRING. If DIR is < 0, the
98
search is backwards through previous entries, else through subsequent
101
noninc_dosearch (string, dir)
105
int oldpos, pos, line_len;
108
if (string == 0 || *string == '\0' || noninc_history_pos < 0)
114
pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
117
/* Search failed, current history position unchanged. */
118
maybe_unsave_line ();
125
noninc_history_pos = pos;
127
oldpos = where_history ();
128
history_set_pos (noninc_history_pos);
129
entry = current_history ();
130
#if defined (VI_MODE)
131
if (rl_editing_mode != vi_mode)
133
history_set_pos (oldpos);
135
line_len = strlen (entry->line);
136
if (line_len >= rl_line_buffer_len)
137
rl_extend_line_buffer (line_len);
138
strcpy (rl_line_buffer, entry->line);
140
rl_undo_list = (UNDO_LIST *)entry->data;
141
rl_end = strlen (rl_line_buffer);
145
if (saved_line_for_history)
146
_rl_free_history_entry (saved_line_for_history);
147
saved_line_for_history = (HIST_ENTRY *)NULL;
150
/* Search non-interactively through the history list. DIR < 0 means to
151
search backwards through the history of previous commands; otherwise
152
the search is for commands subsequent to the current position in the
153
history list. PCHAR is the character to use for prompting when reading
154
the search string; if not specified (0), it defaults to `:'. */
156
noninc_search (dir, pchar)
164
saved_point = rl_point;
166
/* Use the line buffer to read the search string. */
167
rl_line_buffer[0] = 0;
168
rl_end = rl_point = 0;
170
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
171
rl_message (p, 0, 0);
174
#define SEARCH_RETURN rl_restore_prompt (); return
176
/* Read the search string. */
177
while (c = rl_read_key ())
185
maybe_unsave_line ();
187
rl_point = saved_point;
194
rl_unix_word_rubout (1, c);
198
rl_unix_line_discard (1, c);
209
maybe_unsave_line ();
211
rl_point = saved_point;
219
(*rl_redisplay_function) ();
223
/* If rl_point == 0, we want to re-use the previous search string and
224
start from the saved history position. If there's no previous search
228
if (!noninc_search_string)
236
/* We want to start the search from the current history position. */
237
noninc_history_pos = where_history ();
238
if (noninc_search_string)
239
free (noninc_search_string);
240
noninc_search_string = savestring (rl_line_buffer);
243
rl_restore_prompt ();
244
noninc_dosearch (noninc_search_string, dir);
247
/* Search forward through the history list for a string. If the vi-mode
248
code calls this, KEY will be `?'. */
250
rl_noninc_forward_search (count, key)
253
noninc_search (1, (key == '?') ? '?' : 0);
257
/* Reverse search the history list for a string. If the vi-mode code
258
calls this, KEY will be `/'. */
260
rl_noninc_reverse_search (count, key)
263
noninc_search (-1, (key == '/') ? '/' : 0);
267
/* Search forward through the history list for the last string searched
268
for. If there is no saved search string, abort. */
270
rl_noninc_forward_search_again (count, key)
273
if (!noninc_search_string)
278
noninc_dosearch (noninc_search_string, 1);
282
/* Reverse search in the history list for the last string searched
283
for. If there is no saved search string, abort. */
285
rl_noninc_reverse_search_again (count, key)
288
if (!noninc_search_string)
293
noninc_dosearch (noninc_search_string, -1);
298
rl_history_search_internal (count, direction)
299
int count, direction;
301
HIST_ENTRY *temp, *old_temp;
306
temp = old_temp = (HIST_ENTRY *)NULL;
309
temp = (direction < 0) ? previous_history () : next_history ();
312
/* On an empty prefix, make this the same as previous-history. */
318
if (STREQN (rl_line_buffer, temp->line, rl_point))
320
/* Don't find multiple instances of the same line. */
321
if (prev_line_found && STREQ (prev_line_found, temp->line))
325
prev_line_found = temp->line;
332
if (direction < 0 && old_temp)
336
maybe_unsave_line ();
342
line_len = strlen (temp->line);
343
if (line_len >= rl_line_buffer_len)
344
rl_extend_line_buffer (line_len);
345
strcpy (rl_line_buffer, temp->line);
346
rl_undo_list = (UNDO_LIST *)temp->data;
351
/* Search forward in the history for the string of characters
352
from the start of the line to rl_point. This is a non-incremental
355
rl_history_search_forward (count, ignore)
360
if (rl_last_func != rl_history_search_forward)
361
prev_line_found = (char *)NULL;
362
return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
365
/* Search backward through the history for the string of characters
366
from the start of the line to rl_point. This is a non-incremental
369
rl_history_search_backward (count, ignore)
374
if (rl_last_func != rl_history_search_backward)
375
prev_line_found = (char *)NULL;
376
return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));