]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - readline/isearch.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / readline / isearch.c
CommitLineData
5e98bbab
PB
1/* **************************************************************** */
2/* */
3/* I-Search and Searching */
4/* */
5/* **************************************************************** */
6
7/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
8
9 This file contains the Readline Library (the Library), a set of
10 routines for providing Emacs style line input to programs that ask
11 for it.
12
13 The Library is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 1, or (at your option)
16 any later version.
17
18 The Library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 The GNU General Public License is often shipped with GNU software, and
24 is generally kept in a file called COPYING or LICENSE. If you do not
25 have a copy of the license, write to the Free Software Foundation,
26 675 Mass Ave, Cambridge, MA 02139, USA. */
27
28#include <stdio.h>
29
30#if defined (__GNUC__)
31# define alloca __builtin_alloca
32#else
33# if defined (sparc) || defined (HAVE_ALLOCA_H)
34# include <alloca.h>
35# endif
36#endif
37
38#include "readline.h"
39#include "history.h"
40
41extern Keymap _rl_keymap;
42extern HIST_ENTRY *saved_line_for_history;
43extern int rl_line_buffer_len;
44extern int rl_point, rl_end;
45extern char *rl_prompt, *rl_line_buffer;
46
47/* Remove these declarations when we have a complete libgnu.a. */
48extern char *xmalloc (), *xrealloc ();
49
50static void rl_search_history ();
51
52/* Search backwards through the history looking for a string which is typed
53 interactively. Start with the current line. */
54rl_reverse_search_history (sign, key)
55 int sign;
56 int key;
57{
58 rl_search_history (-sign, key);
59}
60
61/* Search forwards through the history looking for a string which is typed
62 interactively. Start with the current line. */
63rl_forward_search_history (sign, key)
64 int sign;
65 int key;
66{
67 rl_search_history (sign, key);
68}
69
70/* Display the current state of the search in the echo-area.
71 SEARCH_STRING contains the string that is being searched for,
72 DIRECTION is zero for forward, or 1 for reverse,
73 WHERE is the history list number of the current line. If it is
74 -1, then this line is the starting one. */
75static void
76rl_display_search (search_string, reverse_p, where)
77 char *search_string;
78 int reverse_p, where;
79{
80 char *message = (char *)NULL;
81
82 message =
83 (char *)xmalloc (1 + (search_string ? strlen (search_string) : 0) + 30);
84
85 *message = '\0';
86
87#if defined (NOTDEF)
88 if (where != -1)
89 sprintf (message, "[%d]", where + history_base);
90#endif /* NOTDEF */
91
92 strcat (message, "(");
93
94 if (reverse_p)
95 strcat (message, "reverse-");
96
97 strcat (message, "i-search)`");
98
99 if (search_string)
100 strcat (message, search_string);
101
102 strcat (message, "': ");
103 rl_message ("%s", message, 0);
104 free (message);
105 rl_redisplay ();
106}
107
108/* Search through the history looking for an interactively typed string.
109 This is analogous to i-search. We start the search in the current line.
110 DIRECTION is which direction to search; >= 0 means forward, < 0 means
111 backwards. */
112static void
113rl_search_history (direction, invoking_key)
114 int direction;
115 int invoking_key;
116{
117 /* The string that the user types in to search for. */
118 char *search_string;
119
120 /* The current length of SEARCH_STRING. */
121 int search_string_index;
122
123 /* The amount of space that SEARCH_STRING has allocated to it. */
124 int search_string_size;
125
126 /* The list of lines to search through. */
127 char **lines;
128
129 /* The length of LINES. */
130 int hlen;
131
132 /* Where we get LINES from. */
133 HIST_ENTRY **hlist = history_list ();
134
135 register int i = 0;
136 int orig_point = rl_point;
137 int orig_line = where_history ();
138 int last_found_line = orig_line;
139 int c, done = 0;
140
141 /* The line currently being searched. */
142 char *sline;
143
144 /* Offset in that line. */
145 int index;
146
147 /* Non-zero if we are doing a reverse search. */
148 int reverse = (direction < 0);
149
150 /* Create an arrary of pointers to the lines that we want to search. */
151 maybe_replace_line ();
152 if (hlist)
153 for (i = 0; hlist[i]; i++);
154
155 /* Allocate space for this many lines, +1 for the current input line,
156 and remember those lines. */
157 lines = (char **)alloca ((1 + (hlen = i)) * sizeof (char *));
158 for (i = 0; i < hlen; i++)
159 lines[i] = hlist[i]->line;
160
161 if (saved_line_for_history)
162 lines[i] = saved_line_for_history->line;
163 else
164 /* So I have to type it in this way instead. */
165 {
166 char *alloced_line;
167
168 /* Keep that MIPS alloca () happy. */
169 alloced_line = (char *)alloca (1 + strlen (rl_line_buffer));
170 lines[i] = alloced_line;
171 strcpy (lines[i], &rl_line_buffer[0]);
172 }
173
174 hlen++;
175
176 /* The line where we start the search. */
177 i = orig_line;
178
179 /* Initialize search parameters. */
180 search_string = (char *)xmalloc (search_string_size = 128);
181 *search_string = '\0';
182 search_string_index = 0;
183
184 /* Normalize DIRECTION into 1 or -1. */
185 if (direction >= 0)
186 direction = 1;
187 else
188 direction = -1;
189
190 rl_display_search (search_string, reverse, -1);
191
192 sline = rl_line_buffer;
193 index = rl_point;
194
195 while (!done)
196 {
197 c = rl_read_key ();
198
199 /* Hack C to Do What I Mean. */
200 {
201 Function *f = (Function *)NULL;
202
203 if (_rl_keymap[c].type == ISFUNC)
204 {
205 f = _rl_keymap[c].function;
206
207 if (f == rl_reverse_search_history)
208 c = reverse ? -1 : -2;
209 else if (f == rl_forward_search_history)
210 c = !reverse ? -1 : -2;
211 }
212 }
213
214 switch (c)
215 {
216 case ESC:
217 done = 1;
218 continue;
219
220 /* case invoking_key: */
221 case -1:
222 goto search_again;
223
224 /* switch directions */
225 case -2:
226 direction = -direction;
227 reverse = (direction < 0);
228
229 goto do_search;
230
231 case CTRL ('G'):
232 strcpy (rl_line_buffer, lines[orig_line]);
233 rl_point = orig_point;
234 rl_end = strlen (rl_line_buffer);
235 rl_clear_message ();
236 return;
237
238 default:
239 if (c < 32 || c > 126)
240 {
241 rl_execute_next (c);
242 done = 1;
243 continue;
244 }
245 else
246 {
247 if (search_string_index + 2 >= search_string_size)
248 search_string = (char *)xrealloc
249 (search_string, (search_string_size += 128));
250 search_string[search_string_index++] = c;
251 search_string[search_string_index] = '\0';
252 goto do_search;
253
254 search_again:
255
256 if (!search_string_index)
257 continue;
258 else
259 {
260 if (reverse)
261 --index;
262 else
263 if (index != strlen (sline))
264 ++index;
265 else
266 ding ();
267 }
268 do_search:
269
270 while (1)
271 {
272 if (reverse)
273 {
274 while (index >= 0)
275 if (strncmp
276 (search_string, sline + index, search_string_index)
277 == 0)
278 goto string_found;
279 else
280 index--;
281 }
282 else
283 {
284 register int limit =
285 (strlen (sline) - search_string_index) + 1;
286
287 while (index < limit)
288 {
289 if (strncmp (search_string,
290 sline + index,
291 search_string_index) == 0)
292 goto string_found;
293 index++;
294 }
295 }
296
297 next_line:
298 i += direction;
299
300 /* At limit for direction? */
301 if ((reverse && i < 0) ||
302 (!reverse && i == hlen))
303 goto search_failed;
304
305 sline = lines[i];
306 if (reverse)
307 index = strlen (sline);
308 else
309 index = 0;
310
311 /* If the search string is longer than the current
312 line, no match. */
313 if (search_string_index > (int)strlen (sline))
314 goto next_line;
315
316 /* Start actually searching. */
317 if (reverse)
318 index -= search_string_index;
319 }
320
321 search_failed:
322 /* We cannot find the search string. Ding the bell. */
323 ding ();
324 i = last_found_line;
325 break;
326
327 string_found:
328 /* We have found the search string. Just display it. But don't
329 actually move there in the history list until the user accepts
330 the location. */
331 {
332 int line_len;
333
334 line_len = strlen (lines[i]);
335
336 if (line_len >= rl_line_buffer_len)
337 rl_extend_line_buffer (line_len);
338
339 strcpy (rl_line_buffer, lines[i]);
340 rl_point = index;
341 rl_end = line_len;
342 last_found_line = i;
343 rl_display_search
344 (search_string, reverse, (i == orig_line) ? -1 : i);
345 }
346 }
347 }
348 continue;
349 }
350
351 /* The searching is over. The user may have found the string that she
352 was looking for, or else she may have exited a failing search. If
353 INDEX is -1, then that shows that the string searched for was not
354 found. We use this to determine where to place rl_point. */
355 {
356 int now = last_found_line;
357
358 /* First put back the original state. */
359 strcpy (rl_line_buffer, lines[orig_line]);
360
361 /* Free the search string. */
362 free (search_string);
363
364 if (now < orig_line)
365 rl_get_previous_history (orig_line - now);
366 else
367 rl_get_next_history (now - orig_line);
368
369 /* If the index of the "matched" string is less than zero, then the
370 final search string was never matched, so put point somewhere
371 reasonable. */
372 if (index < 0)
373 index = strlen (rl_line_buffer);
374
375 rl_point = index;
376 rl_clear_message ();
377 }
378}