รจ
[deliverable/binutils-gdb.git] / readline / search.c
CommitLineData
d60d9f65
SS
1/* search.c - code for non-incremental searching in emacs and vi modes. */
2
3/* Copyright (C) 1992 Free Software Foundation, Inc.
4
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
7 for it.
8
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)
12 any later version.
13
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.
18
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
24
25#if defined (HAVE_CONFIG_H)
26# include <config.h>
27#endif
28
29#include <sys/types.h>
30#include <stdio.h>
31
32#if defined (HAVE_UNISTD_H)
33# include <unistd.h>
34#endif
35
36#if defined (HAVE_STDLIB_H)
37# include <stdlib.h>
38#else
39# include "ansi_stdlib.h"
40#endif
41
42#include "rldefs.h"
43#include "readline.h"
44#include "history.h"
45
46#ifdef abs
47# undef abs
48#endif
49#define abs(x) (((x) >= 0) ? (x) : -(x))
50
51extern char *xmalloc (), *xrealloc ();
52
53/* Variables imported from readline.c */
54extern int rl_point, rl_end, rl_line_buffer_len;
55extern int rl_editing_mode;
56extern char *rl_prompt;
57extern char *rl_line_buffer;
58extern HIST_ENTRY *saved_line_for_history;
59extern Function *rl_last_func;
60
61/* Functions imported from the rest of the library. */
62extern int _rl_free_history_entry ();
63extern char *_rl_make_prompt_for_search ();
64extern void _rl_restore_prompt ();
65extern void rl_extend_line_buffer ();
66
67static char *noninc_search_string = (char *) NULL;
68static int noninc_history_pos;
69static char *prev_line_found = (char *) NULL;
70
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. */
76static int
77noninc_search_from_pos (string, pos, dir)
78 char *string;
79 int pos, dir;
80{
81 int ret, old;
82
83 old = where_history ();
84 history_set_pos (pos);
85
86 if (*string == '^')
87 ret = history_search_prefix (string + 1, dir);
88 else
89 ret = history_search (string, dir);
90
91 if (ret != -1)
92 ret = where_history ();
93
94 history_set_pos (old);
95 return (ret);
96}
97
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
100 entries. */
101static void
102noninc_dosearch (string, dir)
103 char *string;
104 int dir;
105{
106 int oldpos, pos, line_len;
107 HIST_ENTRY *entry;
108
109 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
110 {
111 ding ();
112 return;
113 }
114
115 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
116 if (pos == -1)
117 {
118 /* Search failed, current history position unchanged. */
119 maybe_unsave_line ();
120 rl_clear_message ();
121 rl_point = 0;
122 ding ();
123 return;
124 }
125
126 noninc_history_pos = pos;
127
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)
133#endif
134 history_set_pos (oldpos);
135
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);
140
141 rl_undo_list = (UNDO_LIST *)entry->data;
142 rl_end = strlen (rl_line_buffer);
143 rl_point = 0;
144 rl_clear_message ();
145
146 if (saved_line_for_history)
147 _rl_free_history_entry (saved_line_for_history);
148 saved_line_for_history = (HIST_ENTRY *)NULL;
149}
150
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 `:'. */
156static void
157noninc_search (dir, pchar)
158 int dir;
159 int pchar;
160{
161 int saved_point, c;
162 char *p;
163
164 maybe_save_line ();
165 saved_point = rl_point;
166
167 /* Use the line buffer to read the search string. */
168 rl_line_buffer[0] = 0;
169 rl_end = rl_point = 0;
170
171 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
172 rl_message (p, 0, 0);
173 free (p);
174
175#define SEARCH_RETURN _rl_restore_prompt (); return
176
177 /* Read the search string. */
178 while (c = rl_read_key ())
179 {
180 switch (c)
181 {
182 case CTRL('H'):
183 case RUBOUT:
184 if (rl_point == 0)
185 {
186 maybe_unsave_line ();
187 rl_clear_message ();
188 rl_point = saved_point;
189 SEARCH_RETURN;
190 }
191 rl_rubout (1, c);
192 break;
193
194 case CTRL('W'):
195 rl_unix_word_rubout (1, c);
196 break;
197
198 case CTRL('U'):
199 rl_unix_line_discard (1, c);
200 break;
201
202 case RETURN:
203 case NEWLINE:
204 goto dosearch;
205 /* NOTREACHED */
206 break;
207
208 case CTRL('C'):
209 case CTRL('G'):
210 maybe_unsave_line ();
211 rl_clear_message ();
212 rl_point = saved_point;
213 ding ();
214 SEARCH_RETURN;
215
216 default:
217 rl_insert (1, c);
218 break;
219 }
220 (*rl_redisplay_function) ();
221 }
222
223 dosearch:
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
226 string, punt. */
227 if (rl_point == 0)
228 {
229 if (!noninc_search_string)
230 {
231 ding ();
232 SEARCH_RETURN;
233 }
234 }
235 else
236 {
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);
242 }
243
244 _rl_restore_prompt ();
245 noninc_dosearch (noninc_search_string, dir);
246}
247
248/* Search forward through the history list for a string. If the vi-mode
249 code calls this, KEY will be `?'. */
250int
251rl_noninc_forward_search (count, key)
252 int count, key;
253{
254 noninc_search (1, (key == '?') ? '?' : 0);
255 return 0;
256}
257
258/* Reverse search the history list for a string. If the vi-mode code
259 calls this, KEY will be `/'. */
260int
261rl_noninc_reverse_search (count, key)
262 int count, key;
263{
264 noninc_search (-1, (key == '/') ? '/' : 0);
265 return 0;
266}
267
268/* Search forward through the history list for the last string searched
269 for. If there is no saved search string, abort. */
270int
271rl_noninc_forward_search_again (count, key)
272 int count, key;
273{
274 if (!noninc_search_string)
275 {
276 ding ();
277 return (-1);
278 }
279 noninc_dosearch (noninc_search_string, 1);
280 return 0;
281}
282
283/* Reverse search in the history list for the last string searched
284 for. If there is no saved search string, abort. */
285int
286rl_noninc_reverse_search_again (count, key)
287 int count, key;
288{
289 if (!noninc_search_string)
290 {
291 ding ();
292 return (-1);
293 }
294 noninc_dosearch (noninc_search_string, -1);
295 return 0;
296}
297
298static int
299rl_history_search_internal (count, direction)
300 int count, direction;
301{
302 HIST_ENTRY *temp, *old_temp;
303 int line_len;
304
305 maybe_save_line ();
306
307 temp = old_temp = (HIST_ENTRY *)NULL;
308 while (count)
309 {
310 temp = (direction < 0) ? previous_history () : next_history ();
311 if (temp == 0)
312 break;
313 /* On an empty prefix, make this the same as previous-history. */
314 if (rl_point == 0)
315 {
316 count--;
317 continue;
318 }
319 if (STREQN (rl_line_buffer, temp->line, rl_point))
320 {
321 /* Don't find multiple instances of the same line. */
322 if (prev_line_found && STREQ (prev_line_found, temp->line))
323 continue;
324 if (direction < 0)
325 old_temp = temp;
326 prev_line_found = temp->line;
327 count--;
328 }
329 }
330
331 if (temp == 0)
332 {
333 if (direction < 0 && old_temp)
334 temp = old_temp;
335 else
336 {
337 maybe_unsave_line ();
338 ding ();
339 return 1;
340 }
341 }
342
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;
348 rl_end = line_len;
349 return 0;
350}
351
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
354 search. */
355int
356rl_history_search_forward (count, ignore)
357 int count, ignore;
358{
359 if (count == 0)
360 return (0);
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));
364}
365
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
368 search. */
369int
370rl_history_search_backward (count, ignore)
371 int count, ignore;
372{
373 if (count == 0)
374 return (0);
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));
378}
This page took 0.038251 seconds and 4 git commands to generate.