* readline/terminal.c (_rl_get_screen_size): Get console size from
[deliverable/binutils-gdb.git] / readline / isearch.c
CommitLineData
d60d9f65
SS
1/* **************************************************************** */
2/* */
3/* I-Search and Searching */
4/* */
5/* **************************************************************** */
6
9255ee31 7/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
d60d9f65
SS
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
1b17e766 15 the Free Software Foundation; either version 2, or (at your option)
d60d9f65
SS
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,
1b17e766 26 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
d60d9f65
SS
27#define READLINE_LIBRARY
28
29#if defined (HAVE_CONFIG_H)
30# include <config.h>
31#endif
32
33#include <sys/types.h>
34
35#include <stdio.h>
36
37#if defined (HAVE_UNISTD_H)
38# include <unistd.h>
39#endif
40
41#if defined (HAVE_STDLIB_H)
42# include <stdlib.h>
43#else
44# include "ansi_stdlib.h"
45#endif
46
47#include "rldefs.h"
9255ee31
EZ
48#include "rlmbutil.h"
49
d60d9f65
SS
50#include "readline.h"
51#include "history.h"
52
1b17e766
EZ
53#include "rlprivate.h"
54#include "xmalloc.h"
55
c862e87b 56/* Variables exported to other files in the readline library. */
9255ee31 57char *_rl_isearch_terminators = (char *)NULL;
c862e87b 58
d60d9f65 59/* Variables imported from other files in the readline library. */
9255ee31 60extern HIST_ENTRY *_rl_saved_line_for_history;
d60d9f65 61
1b17e766 62/* Forward declarations */
9255ee31 63static int rl_search_history PARAMS((int, int));
d60d9f65
SS
64
65/* Last line found by the current incremental search, so we don't `find'
66 identical lines many times in a row. */
67static char *prev_line_found;
68
9255ee31
EZ
69/* Last search string and its length. */
70static char *last_isearch_string;
71static int last_isearch_string_len;
72
73static char *default_isearch_terminators = "\033\012";
74
d60d9f65
SS
75/* Search backwards through the history looking for a string which is typed
76 interactively. Start with the current line. */
77int
78rl_reverse_search_history (sign, key)
79 int sign, key;
80{
81 return (rl_search_history (-sign, key));
82}
83
84/* Search forwards through the history looking for a string which is typed
85 interactively. Start with the current line. */
86int
87rl_forward_search_history (sign, key)
88 int sign, key;
89{
90 return (rl_search_history (sign, key));
91}
92
93/* Display the current state of the search in the echo-area.
94 SEARCH_STRING contains the string that is being searched for,
95 DIRECTION is zero for forward, or 1 for reverse,
96 WHERE is the history list number of the current line. If it is
97 -1, then this line is the starting one. */
98static void
99rl_display_search (search_string, reverse_p, where)
100 char *search_string;
101 int reverse_p, where;
102{
103 char *message;
104 int msglen, searchlen;
105
106 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
107
9255ee31 108 message = (char *)xmalloc (searchlen + 33);
d60d9f65
SS
109 msglen = 0;
110
111#if defined (NOTDEF)
112 if (where != -1)
113 {
114 sprintf (message, "[%d]", where + history_base);
115 msglen = strlen (message);
116 }
117#endif /* NOTDEF */
118
119 message[msglen++] = '(';
120
121 if (reverse_p)
122 {
123 strcpy (message + msglen, "reverse-");
124 msglen += 8;
125 }
126
127 strcpy (message + msglen, "i-search)`");
128 msglen += 10;
129
130 if (search_string)
131 {
132 strcpy (message + msglen, search_string);
133 msglen += searchlen;
134 }
135
136 strcpy (message + msglen, "': ");
137
9255ee31 138 rl_message ("%s", message);
d60d9f65
SS
139 free (message);
140 (*rl_redisplay_function) ();
141}
142
143/* Search through the history looking for an interactively typed string.
144 This is analogous to i-search. We start the search in the current line.
145 DIRECTION is which direction to search; >= 0 means forward, < 0 means
146 backwards. */
147static int
148rl_search_history (direction, invoking_key)
149 int direction, invoking_key;
150{
151 /* The string that the user types in to search for. */
152 char *search_string;
153
154 /* The current length of SEARCH_STRING. */
155 int search_string_index;
156
157 /* The amount of space that SEARCH_STRING has allocated to it. */
158 int search_string_size;
159
160 /* The list of lines to search through. */
161 char **lines, *allocated_line;
162
163 /* The length of LINES. */
164 int hlen;
165
166 /* Where we get LINES from. */
167 HIST_ENTRY **hlist;
168
169 register int i;
9255ee31 170 int orig_point, orig_mark, orig_line, last_found_line;
d60d9f65 171 int c, found, failed, sline_len;
9255ee31
EZ
172 int n, wstart, wlen;
173#if defined (HANDLE_MULTIBYTE)
174 char mb[MB_LEN_MAX];
175#endif
d60d9f65
SS
176
177 /* The line currently being searched. */
178 char *sline;
179
180 /* Offset in that line. */
181 int line_index;
182
183 /* Non-zero if we are doing a reverse search. */
184 int reverse;
185
c862e87b
JM
186 /* The list of characters which terminate the search, but are not
187 subsequently executed. If the variable isearch-terminators has
188 been set, we use that value, otherwise we use ESC and C-J. */
9255ee31 189 char *isearch_terminators;
c862e87b 190
9255ee31 191 RL_SETSTATE(RL_STATE_ISEARCH);
d60d9f65 192 orig_point = rl_point;
9255ee31 193 orig_mark = rl_mark;
d60d9f65
SS
194 last_found_line = orig_line = where_history ();
195 reverse = direction < 0;
196 hlist = history_list ();
197 allocated_line = (char *)NULL;
198
c862e87b 199 isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
9255ee31 200 : default_isearch_terminators;
c862e87b 201
d60d9f65 202 /* Create an arrary of pointers to the lines that we want to search. */
9255ee31 203 rl_maybe_replace_line ();
d60d9f65
SS
204 i = 0;
205 if (hlist)
206 for (i = 0; hlist[i]; i++);
207
208 /* Allocate space for this many lines, +1 for the current input line,
209 and remember those lines. */
210 lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
211 for (i = 0; i < hlen; i++)
212 lines[i] = hlist[i]->line;
213
9255ee31
EZ
214 if (_rl_saved_line_for_history)
215 lines[i] = _rl_saved_line_for_history->line;
d60d9f65
SS
216 else
217 {
218 /* Keep track of this so we can free it. */
9255ee31 219 allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
d60d9f65
SS
220 strcpy (allocated_line, &rl_line_buffer[0]);
221 lines[i] = allocated_line;
222 }
223
224 hlen++;
225
226 /* The line where we start the search. */
227 i = orig_line;
228
c862e87b 229 rl_save_prompt ();
d60d9f65
SS
230
231 /* Initialize search parameters. */
9255ee31 232 search_string = (char *)xmalloc (search_string_size = 128);
d60d9f65
SS
233 *search_string = '\0';
234 search_string_index = 0;
235 prev_line_found = (char *)0; /* XXX */
236
237 /* Normalize DIRECTION into 1 or -1. */
238 direction = (direction >= 0) ? 1 : -1;
239
240 rl_display_search (search_string, reverse, -1);
241
242 sline = rl_line_buffer;
243 sline_len = strlen (sline);
244 line_index = rl_point;
245
246 found = failed = 0;
247 for (;;)
248 {
9255ee31 249 rl_command_func_t *f = (rl_command_func_t *)NULL;
d60d9f65
SS
250
251 /* Read a key and decide how to proceed. */
9255ee31 252 RL_SETSTATE(RL_STATE_MOREINPUT);
d60d9f65 253 c = rl_read_key ();
9255ee31 254 RL_UNSETSTATE(RL_STATE_MOREINPUT);
d60d9f65 255
9255ee31
EZ
256#if defined (HANDLE_MULTIBYTE)
257 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
258 c = _rl_read_mbstring (c, mb, MB_LEN_MAX);
259#endif
260
261 /* Translate the keys we do something with to opcodes. */
262 if (c >= 0 && _rl_keymap[c].type == ISFUNC)
d60d9f65
SS
263 {
264 f = _rl_keymap[c].function;
265
266 if (f == rl_reverse_search_history)
267 c = reverse ? -1 : -2;
268 else if (f == rl_forward_search_history)
269 c = !reverse ? -1 : -2;
9255ee31
EZ
270 else if (f == rl_rubout)
271 c = -3;
272 else if (c == CTRL ('G'))
273 c = -4;
274 else if (c == CTRL ('W')) /* XXX */
275 c = -5;
276 else if (c == CTRL ('Y')) /* XXX */
277 c = -6;
d60d9f65
SS
278 }
279
c862e87b
JM
280 /* The characters in isearch_terminators (set from the user-settable
281 variable isearch-terminators) are used to terminate the search but
282 not subsequently execute the character as a command. The default
283 value is "\033\012" (ESC and C-J). */
284 if (strchr (isearch_terminators, c))
d60d9f65
SS
285 {
286 /* ESC still terminates the search, but if there is pending
287 input or if input arrives within 0.1 seconds (on systems
288 with select(2)) it is used as a prefix character
289 with rl_execute_next. WATCH OUT FOR THIS! This is intended
290 to allow the arrow keys to be used like ^F and ^B are used
9255ee31
EZ
291 to terminate the search and execute the movement command.
292 XXX - since _rl_input_available depends on the application-
293 settable keyboard timeout value, this could alternatively
294 use _rl_input_queued(100000) */
295 if (c == ESC && _rl_input_available ())
d60d9f65
SS
296 rl_execute_next (ESC);
297 break;
298 }
299
9255ee31
EZ
300#define ENDSRCH_CHAR(c) \
301 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
302
303#if defined (HANDLE_MULTIBYTE)
304 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
305 {
306 if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c))
307 {
308 /* This sets rl_pending_input to c; it will be picked up the next
309 time rl_read_key is called. */
310 rl_execute_next (c);
311 break;
312 }
313 }
314 else
315#endif
316 if (c >= 0 && ENDSRCH_CHAR (c))
d60d9f65 317 {
9255ee31
EZ
318 /* This sets rl_pending_input to c; it will be picked up the next
319 time rl_read_key is called. */
d60d9f65
SS
320 rl_execute_next (c);
321 break;
322 }
323
324 switch (c)
325 {
326 case -1:
327 if (search_string_index == 0)
9255ee31
EZ
328 {
329 if (last_isearch_string)
330 {
331 search_string_size = 64 + last_isearch_string_len;
332 search_string = (char *)xrealloc (search_string, search_string_size);
333 strcpy (search_string, last_isearch_string);
334 search_string_index = last_isearch_string_len;
335 rl_display_search (search_string, reverse, -1);
336 break;
337 }
338 continue;
339 }
d60d9f65
SS
340 else if (reverse)
341 --line_index;
342 else if (line_index != sline_len)
343 ++line_index;
344 else
9255ee31 345 rl_ding ();
d60d9f65
SS
346 break;
347
348 /* switch directions */
349 case -2:
350 direction = -direction;
351 reverse = direction < 0;
352 break;
353
9255ee31
EZ
354 /* delete character from search string. */
355 case -3: /* C-H, DEL */
356 /* This is tricky. To do this right, we need to keep a
357 stack of search positions for the current search, with
358 sentinels marking the beginning and end. But this will
359 do until we have a real isearch-undo. */
360 if (search_string_index == 0)
361 rl_ding ();
362 else
363 search_string[--search_string_index] = '\0';
364
365 break;
366
367 case -4: /* C-G */
368 rl_replace_line (lines[orig_line], 0);
d60d9f65 369 rl_point = orig_point;
9255ee31 370 rl_mark = orig_mark;
c862e87b 371 rl_restore_prompt();
d60d9f65
SS
372 rl_clear_message ();
373 if (allocated_line)
374 free (allocated_line);
375 free (lines);
9255ee31 376 RL_UNSETSTATE(RL_STATE_ISEARCH);
d60d9f65
SS
377 return 0;
378
9255ee31
EZ
379 case -5: /* C-W */
380 /* skip over portion of line we already matched */
381 wstart = rl_point + search_string_index;
382 if (wstart >= rl_end)
383 {
384 rl_ding ();
385 break;
386 }
387
388 /* if not in a word, move to one. */
389 if (rl_alphabetic(rl_line_buffer[wstart]) == 0)
d60d9f65 390 {
9255ee31
EZ
391 rl_ding ();
392 break;
d60d9f65 393 }
9255ee31
EZ
394 n = wstart;
395 while (n < rl_end && rl_alphabetic(rl_line_buffer[n]))
396 n++;
397 wlen = n - wstart + 1;
398 if (search_string_index + wlen + 1 >= search_string_size)
399 {
400 search_string_size += wlen + 1;
401 search_string = (char *)xrealloc (search_string, search_string_size);
402 }
403 for (; wstart < n; wstart++)
404 search_string[search_string_index++] = rl_line_buffer[wstart];
405 search_string[search_string_index] = '\0';
406 break;
407
408 case -6: /* C-Y */
409 /* skip over portion of line we already matched */
410 wstart = rl_point + search_string_index;
411 if (wstart >= rl_end)
412 {
413 rl_ding ();
414 break;
415 }
416 n = rl_end - wstart + 1;
417 if (search_string_index + n + 1 >= search_string_size)
418 {
419 search_string_size += n + 1;
420 search_string = (char *)xrealloc (search_string, search_string_size);
421 }
422 for (n = wstart; n < rl_end; n++)
423 search_string[search_string_index++] = rl_line_buffer[n];
424 search_string[search_string_index] = '\0';
d60d9f65 425 break;
d60d9f65
SS
426
427 default:
428 /* Add character to search string and continue search. */
429 if (search_string_index + 2 >= search_string_size)
430 {
431 search_string_size += 128;
9255ee31
EZ
432 search_string = (char *)xrealloc (search_string, search_string_size);
433 }
434#if defined (HANDLE_MULTIBYTE)
435 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
436 {
437 int j, l;
438 for (j = 0, l = strlen (mb); j < l; )
439 search_string[search_string_index++] = mb[j++];
d60d9f65 440 }
9255ee31
EZ
441 else
442#endif
443 search_string[search_string_index++] = c;
d60d9f65
SS
444 search_string[search_string_index] = '\0';
445 break;
446 }
447
448 for (found = failed = 0;;)
449 {
450 int limit = sline_len - search_string_index + 1;
451
452 /* Search the current line. */
453 while (reverse ? (line_index >= 0) : (line_index < limit))
454 {
455 if (STREQN (search_string, sline + line_index, search_string_index))
456 {
457 found++;
458 break;
459 }
460 else
461 line_index += direction;
462 }
463 if (found)
464 break;
465
466 /* Move to the next line, but skip new copies of the line
467 we just found and lines shorter than the string we're
468 searching for. */
469 do
470 {
471 /* Move to the next line. */
472 i += direction;
473
474 /* At limit for direction? */
475 if (reverse ? (i < 0) : (i == hlen))
476 {
477 failed++;
478 break;
479 }
480
481 /* We will need these later. */
482 sline = lines[i];
483 sline_len = strlen (sline);
484 }
485 while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
486 (search_string_index > sline_len));
487
488 if (failed)
489 break;
490
491 /* Now set up the line for searching... */
492 line_index = reverse ? sline_len - search_string_index : 0;
493 }
494
495 if (failed)
496 {
497 /* We cannot find the search string. Ding the bell. */
9255ee31 498 rl_ding ();
d60d9f65
SS
499 i = last_found_line;
500 continue; /* XXX - was break */
501 }
502
503 /* We have found the search string. Just display it. But don't
504 actually move there in the history list until the user accepts
505 the location. */
506 if (found)
507 {
d60d9f65 508 prev_line_found = lines[i];
9255ee31 509 rl_replace_line (lines[i], 0);
d60d9f65 510 rl_point = line_index;
d60d9f65
SS
511 last_found_line = i;
512 rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
513 }
514 }
515
516 /* The searching is over. The user may have found the string that she
517 was looking for, or else she may have exited a failing search. If
518 LINE_INDEX is -1, then that shows that the string searched for was
519 not found. We use this to determine where to place rl_point. */
520
521 /* First put back the original state. */
522 strcpy (rl_line_buffer, lines[orig_line]);
523
c862e87b 524 rl_restore_prompt ();
d60d9f65 525
9255ee31
EZ
526 /* Save the search string for possible later use. */
527 FREE (last_isearch_string);
528 last_isearch_string = search_string;
529 last_isearch_string_len = search_string_index;
d60d9f65
SS
530
531 if (last_found_line < orig_line)
c862e87b 532 rl_get_previous_history (orig_line - last_found_line, 0);
d60d9f65 533 else
c862e87b 534 rl_get_next_history (last_found_line - orig_line, 0);
d60d9f65 535
9255ee31
EZ
536 /* If the string was not found, put point at the end of the last matching
537 line. If last_found_line == orig_line, we didn't find any matching
538 history lines at all, so put point back in its original position. */
d60d9f65 539 if (line_index < 0)
9255ee31
EZ
540 {
541 if (last_found_line == orig_line)
542 line_index = orig_point;
543 else
544 line_index = strlen (rl_line_buffer);
545 rl_mark = orig_mark;
546 }
547
d60d9f65 548 rl_point = line_index;
9255ee31
EZ
549 /* Don't worry about where to put the mark here; rl_get_previous_history
550 and rl_get_next_history take care of it. */
551
d60d9f65
SS
552 rl_clear_message ();
553
9255ee31 554 FREE (allocated_line);
d60d9f65
SS
555 free (lines);
556
9255ee31
EZ
557 RL_UNSETSTATE(RL_STATE_ISEARCH);
558
d60d9f65
SS
559 return 0;
560}
This page took 0.294938 seconds and 4 git commands to generate.