morse(6): correct email for original author
[dragonfly.git] / contrib / gdb-7 / readline / search.c
blob04468fc49017cabe66e2e3a467958ea56182827d
1 /* search.c - code for non-incremental searching in emacs and vi modes. */
3 /* Copyright (C) 1992-2009 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
22 #define READLINE_LIBRARY
24 #if defined (HAVE_CONFIG_H)
25 # include <config.h>
26 #endif
28 #include <sys/types.h>
29 #include <stdio.h>
31 #if defined (HAVE_UNISTD_H)
32 # include <unistd.h>
33 #endif
35 #if defined (HAVE_STDLIB_H)
36 # include <stdlib.h>
37 #else
38 # include "ansi_stdlib.h"
39 #endif
41 #include "rldefs.h"
42 #include "rlmbutil.h"
44 #include "readline.h"
45 #include "history.h"
47 #include "rlprivate.h"
48 #include "xmalloc.h"
50 #ifdef abs
51 # undef abs
52 #endif
53 #define abs(x) (((x) >= 0) ? (x) : -(x))
55 _rl_search_cxt *_rl_nscxt = 0;
57 extern HIST_ENTRY *_rl_saved_line_for_history;
59 /* Functions imported from the rest of the library. */
60 extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
62 static char *noninc_search_string = (char *) NULL;
63 static int noninc_history_pos;
65 static char *prev_line_found = (char *) NULL;
67 static int rl_history_search_len;
68 static int rl_history_search_pos;
69 static char *history_search_string;
70 static int history_string_size;
72 static void make_history_line_current PARAMS((HIST_ENTRY *));
73 static int noninc_search_from_pos PARAMS((char *, int, int));
74 static int noninc_dosearch PARAMS((char *, int));
75 static int noninc_search PARAMS((int, int));
76 static int rl_history_search_internal PARAMS((int, int));
77 static void rl_history_search_reinit PARAMS((void));
79 static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
80 static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
81 static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
82 static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
84 /* Make the data from the history entry ENTRY be the contents of the
85 current line. This doesn't do anything with rl_point; the caller
86 must set it. */
87 static void
88 make_history_line_current (entry)
89 HIST_ENTRY *entry;
91 _rl_replace_text (entry->line, 0, rl_end);
92 _rl_fix_point (1);
93 #if defined (VI_MODE)
94 if (rl_editing_mode == vi_mode)
95 /* POSIX.2 says that the `U' command doesn't affect the copy of any
96 command lines to the edit line. We're going to implement that by
97 making the undo list start after the matching line is copied to the
98 current editing buffer. */
99 rl_free_undo_list ();
100 #endif
102 if (_rl_saved_line_for_history)
103 _rl_free_history_entry (_rl_saved_line_for_history);
104 _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
107 /* Search the history list for STRING starting at absolute history position
108 POS. If STRING begins with `^', the search must match STRING at the
109 beginning of a history line, otherwise a full substring match is performed
110 for STRING. DIR < 0 means to search backwards through the history list,
111 DIR >= 0 means to search forward. */
112 static int
113 noninc_search_from_pos (string, pos, dir)
114 char *string;
115 int pos, dir;
117 int ret, old;
119 if (pos < 0)
120 return -1;
122 old = where_history ();
123 if (history_set_pos (pos) == 0)
124 return -1;
126 RL_SETSTATE(RL_STATE_SEARCH);
127 if (*string == '^')
128 ret = history_search_prefix (string + 1, dir);
129 else
130 ret = history_search (string, dir);
131 RL_UNSETSTATE(RL_STATE_SEARCH);
133 if (ret != -1)
134 ret = where_history ();
136 history_set_pos (old);
137 return (ret);
140 /* Search for a line in the history containing STRING. If DIR is < 0, the
141 search is backwards through previous entries, else through subsequent
142 entries. Returns 1 if the search was successful, 0 otherwise. */
143 static int
144 noninc_dosearch (string, dir)
145 char *string;
146 int dir;
148 int oldpos, pos;
149 HIST_ENTRY *entry;
151 if (string == 0 || *string == '\0' || noninc_history_pos < 0)
153 rl_ding ();
154 return 0;
157 pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
158 if (pos == -1)
160 /* Search failed, current history position unchanged. */
161 rl_maybe_unsave_line ();
162 rl_clear_message ();
163 rl_point = 0;
164 rl_ding ();
165 return 0;
168 noninc_history_pos = pos;
170 oldpos = where_history ();
171 history_set_pos (noninc_history_pos);
172 entry = current_history ();
173 #if defined (VI_MODE)
174 if (rl_editing_mode != vi_mode)
175 #endif
176 history_set_pos (oldpos);
178 make_history_line_current (entry);
180 rl_point = 0;
181 rl_mark = rl_end;
183 rl_clear_message ();
184 return 1;
187 static _rl_search_cxt *
188 _rl_nsearch_init (dir, pchar)
189 int dir, pchar;
191 _rl_search_cxt *cxt;
192 char *p;
194 cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
195 if (dir < 0)
196 cxt->sflags |= SF_REVERSE; /* not strictly needed */
198 cxt->direction = dir;
199 cxt->history_pos = cxt->save_line;
201 rl_maybe_save_line ();
203 /* Clear the undo list, since reading the search string should create its
204 own undo list, and the whole list will end up being freed when we
205 finish reading the search string. */
206 rl_undo_list = 0;
208 /* Use the line buffer to read the search string. */
209 rl_line_buffer[0] = 0;
210 rl_end = rl_point = 0;
212 p = _rl_make_prompt_for_search (pchar ? pchar : ':');
213 rl_message ("%s", p, 0);
214 xfree (p);
216 RL_SETSTATE(RL_STATE_NSEARCH);
218 _rl_nscxt = cxt;
220 return cxt;
223 static int
224 _rl_nsearch_cleanup (cxt, r)
225 _rl_search_cxt *cxt;
226 int r;
228 _rl_scxt_dispose (cxt, 0);
229 _rl_nscxt = 0;
231 RL_UNSETSTATE(RL_STATE_NSEARCH);
233 return (r != 1);
236 static void
237 _rl_nsearch_abort (cxt)
238 _rl_search_cxt *cxt;
240 rl_maybe_unsave_line ();
241 rl_clear_message ();
242 rl_point = cxt->save_point;
243 rl_mark = cxt->save_mark;
244 rl_restore_prompt ();
246 RL_UNSETSTATE (RL_STATE_NSEARCH);
249 /* Process just-read character C according to search context CXT. Return -1
250 if the caller should abort the search, 0 if we should break out of the
251 loop, and 1 if we should continue to read characters. */
252 static int
253 _rl_nsearch_dispatch (cxt, c)
254 _rl_search_cxt *cxt;
255 int c;
257 switch (c)
259 case CTRL('W'):
260 rl_unix_word_rubout (1, c);
261 break;
263 case CTRL('U'):
264 rl_unix_line_discard (1, c);
265 break;
267 case RETURN:
268 case NEWLINE:
269 return 0;
271 case CTRL('H'):
272 case RUBOUT:
273 if (rl_point == 0)
275 _rl_nsearch_abort (cxt);
276 return -1;
278 _rl_rubout_char (1, c);
279 break;
281 case CTRL('C'):
282 case CTRL('G'):
283 rl_ding ();
284 _rl_nsearch_abort (cxt);
285 return -1;
287 default:
288 #if defined (HANDLE_MULTIBYTE)
289 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
290 rl_insert_text (cxt->mb);
291 else
292 #endif
293 _rl_insert_char (1, c);
294 break;
297 (*rl_redisplay_function) ();
298 return 1;
301 /* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
302 -1 if the search should be aborted, any other value means to clean up
303 using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
304 0 otherwise. */
305 static int
306 _rl_nsearch_dosearch (cxt)
307 _rl_search_cxt *cxt;
309 rl_mark = cxt->save_mark;
311 /* If rl_point == 0, we want to re-use the previous search string and
312 start from the saved history position. If there's no previous search
313 string, punt. */
314 if (rl_point == 0)
316 if (noninc_search_string == 0)
318 rl_ding ();
319 rl_restore_prompt ();
320 RL_UNSETSTATE (RL_STATE_NSEARCH);
321 return -1;
324 else
326 /* We want to start the search from the current history position. */
327 noninc_history_pos = cxt->save_line;
328 FREE (noninc_search_string);
329 noninc_search_string = savestring (rl_line_buffer);
331 /* If we don't want the subsequent undo list generated by the search
332 matching a history line to include the contents of the search string,
333 we need to clear rl_line_buffer here. For now, we just clear the
334 undo list generated by reading the search string. (If the search
335 fails, the old undo list will be restored by rl_maybe_unsave_line.) */
336 rl_free_undo_list ();
339 rl_restore_prompt ();
340 return (noninc_dosearch (noninc_search_string, cxt->direction));
343 /* Search non-interactively through the history list. DIR < 0 means to
344 search backwards through the history of previous commands; otherwise
345 the search is for commands subsequent to the current position in the
346 history list. PCHAR is the character to use for prompting when reading
347 the search string; if not specified (0), it defaults to `:'. */
348 static int
349 noninc_search (dir, pchar)
350 int dir;
351 int pchar;
353 _rl_search_cxt *cxt;
354 int c, r;
356 cxt = _rl_nsearch_init (dir, pchar);
358 if (RL_ISSTATE (RL_STATE_CALLBACK))
359 return (0);
361 /* Read the search string. */
362 r = 0;
363 while (1)
365 c = _rl_search_getchar (cxt);
367 if (c == 0)
368 break;
370 r = _rl_nsearch_dispatch (cxt, c);
371 if (r < 0)
372 return 1;
373 else if (r == 0)
374 break;
377 r = _rl_nsearch_dosearch (cxt);
378 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
381 /* Search forward through the history list for a string. If the vi-mode
382 code calls this, KEY will be `?'. */
384 rl_noninc_forward_search (count, key)
385 int count, key;
387 return noninc_search (1, (key == '?') ? '?' : 0);
390 /* Reverse search the history list for a string. If the vi-mode code
391 calls this, KEY will be `/'. */
393 rl_noninc_reverse_search (count, key)
394 int count, key;
396 return noninc_search (-1, (key == '/') ? '/' : 0);
399 /* Search forward through the history list for the last string searched
400 for. If there is no saved search string, abort. */
402 rl_noninc_forward_search_again (count, key)
403 int count, key;
405 int r;
407 if (!noninc_search_string)
409 rl_ding ();
410 return (-1);
412 r = noninc_dosearch (noninc_search_string, 1);
413 return (r != 1);
416 /* Reverse search in the history list for the last string searched
417 for. If there is no saved search string, abort. */
419 rl_noninc_reverse_search_again (count, key)
420 int count, key;
422 int r;
424 if (!noninc_search_string)
426 rl_ding ();
427 return (-1);
429 r = noninc_dosearch (noninc_search_string, -1);
430 return (r != 1);
433 #if defined (READLINE_CALLBACKS)
435 _rl_nsearch_callback (cxt)
436 _rl_search_cxt *cxt;
438 int c, r;
440 c = _rl_search_getchar (cxt);
441 r = _rl_nsearch_dispatch (cxt, c);
442 if (r != 0)
443 return 1;
445 r = _rl_nsearch_dosearch (cxt);
446 return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
448 #endif
450 static int
451 rl_history_search_internal (count, dir)
452 int count, dir;
454 HIST_ENTRY *temp;
455 int ret, oldpos;
457 rl_maybe_save_line ();
458 temp = (HIST_ENTRY *)NULL;
460 /* Search COUNT times through the history for a line whose prefix
461 matches history_search_string. When this loop finishes, TEMP,
462 if non-null, is the history line to copy into the line buffer. */
463 while (count)
465 ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
466 if (ret == -1)
467 break;
469 /* Get the history entry we found. */
470 rl_history_search_pos = ret;
471 oldpos = where_history ();
472 history_set_pos (rl_history_search_pos);
473 temp = current_history ();
474 history_set_pos (oldpos);
476 /* Don't find multiple instances of the same line. */
477 if (prev_line_found && STREQ (prev_line_found, temp->line))
478 continue;
479 prev_line_found = temp->line;
480 count--;
483 /* If we didn't find anything at all, return. */
484 if (temp == 0)
486 rl_maybe_unsave_line ();
487 rl_ding ();
488 /* If you don't want the saved history line (last match) to show up
489 in the line buffer after the search fails, change the #if 0 to
490 #if 1 */
491 #if 0
492 if (rl_point > rl_history_search_len)
494 rl_point = rl_end = rl_history_search_len;
495 rl_line_buffer[rl_end] = '\0';
496 rl_mark = 0;
498 #else
499 rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
500 rl_mark = rl_end;
501 #endif
502 return 1;
505 /* Copy the line we found into the current line buffer. */
506 make_history_line_current (temp);
508 rl_point = rl_history_search_len;
509 rl_mark = rl_end;
511 return 0;
514 static void
515 rl_history_search_reinit ()
517 rl_history_search_pos = where_history ();
518 rl_history_search_len = rl_point;
519 prev_line_found = (char *)NULL;
520 if (rl_point)
522 if (rl_history_search_len >= history_string_size - 2)
524 history_string_size = rl_history_search_len + 2;
525 history_search_string = (char *)xrealloc (history_search_string, history_string_size);
527 history_search_string[0] = '^';
528 strncpy (history_search_string + 1, rl_line_buffer, rl_point);
529 history_search_string[rl_point + 1] = '\0';
531 _rl_free_saved_history_line ();
534 /* Search forward in the history for the string of characters
535 from the start of the line to rl_point. This is a non-incremental
536 search. */
538 rl_history_search_forward (count, ignore)
539 int count, ignore;
541 if (count == 0)
542 return (0);
544 if (rl_last_func != rl_history_search_forward &&
545 rl_last_func != rl_history_search_backward)
546 rl_history_search_reinit ();
548 if (rl_history_search_len == 0)
549 return (rl_get_next_history (count, ignore));
550 return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
553 /* Search backward through the history for the string of characters
554 from the start of the line to rl_point. This is a non-incremental
555 search. */
557 rl_history_search_backward (count, ignore)
558 int count, ignore;
560 if (count == 0)
561 return (0);
563 if (rl_last_func != rl_history_search_forward &&
564 rl_last_func != rl_history_search_backward)
565 rl_history_search_reinit ();
567 if (rl_history_search_len == 0)
568 return (rl_get_previous_history (count, ignore));
569 return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));