04468fc49017cabe66e2e3a467958ea56182827d
[platform/upstream/bash.git] / lib / readline / search.c
1 /* search.c - code for non-incremental searching in emacs and vi modes. */
2
3 /* Copyright (C) 1992-2009 Free Software Foundation, Inc.
4
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.      
7
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.
12
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.
17
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/>.
20 */
21
22 #define READLINE_LIBRARY
23
24 #if defined (HAVE_CONFIG_H)
25 #  include <config.h>
26 #endif
27
28 #include <sys/types.h>
29 #include <stdio.h>
30
31 #if defined (HAVE_UNISTD_H)
32 #  include <unistd.h>
33 #endif
34
35 #if defined (HAVE_STDLIB_H)
36 #  include <stdlib.h>
37 #else
38 #  include "ansi_stdlib.h"
39 #endif
40
41 #include "rldefs.h"
42 #include "rlmbutil.h"
43
44 #include "readline.h"
45 #include "history.h"
46
47 #include "rlprivate.h"
48 #include "xmalloc.h"
49
50 #ifdef abs
51 #  undef abs
52 #endif
53 #define abs(x)          (((x) >= 0) ? (x) : -(x))
54
55 _rl_search_cxt *_rl_nscxt = 0;
56
57 extern HIST_ENTRY *_rl_saved_line_for_history;
58
59 /* Functions imported from the rest of the library. */
60 extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
61
62 static char *noninc_search_string = (char *) NULL;
63 static int noninc_history_pos;
64
65 static char *prev_line_found = (char *) NULL;
66
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;
71
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));
78
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));
83
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;
90 {
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
101
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;
105 }
106
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;
116 {
117   int ret, old;
118
119   if (pos < 0)
120     return -1;
121
122   old = where_history ();
123   if (history_set_pos (pos) == 0)
124     return -1;
125
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);
132
133   if (ret != -1)
134     ret = where_history ();
135
136   history_set_pos (old);
137   return (ret);
138 }
139
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;
147 {
148   int oldpos, pos;
149   HIST_ENTRY *entry;
150
151   if (string == 0 || *string == '\0' || noninc_history_pos < 0)
152     {
153       rl_ding ();
154       return 0;
155     }
156
157   pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
158   if (pos == -1)
159     {
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;
166     }
167
168   noninc_history_pos = pos;
169
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);
177
178   make_history_line_current (entry);
179
180   rl_point = 0;
181   rl_mark = rl_end;
182
183   rl_clear_message ();
184   return 1;
185 }
186
187 static _rl_search_cxt *
188 _rl_nsearch_init (dir, pchar)
189      int dir, pchar;
190 {
191   _rl_search_cxt *cxt;
192   char *p;
193
194   cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
195   if (dir < 0)
196     cxt->sflags |= SF_REVERSE;          /* not strictly needed */
197
198   cxt->direction = dir;
199   cxt->history_pos = cxt->save_line;
200
201   rl_maybe_save_line ();
202
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;
207
208   /* Use the line buffer to read the search string. */
209   rl_line_buffer[0] = 0;
210   rl_end = rl_point = 0;
211
212   p = _rl_make_prompt_for_search (pchar ? pchar : ':');
213   rl_message ("%s", p, 0);
214   xfree (p);
215
216   RL_SETSTATE(RL_STATE_NSEARCH);
217
218   _rl_nscxt = cxt;
219
220   return cxt;
221 }
222
223 static int
224 _rl_nsearch_cleanup (cxt, r)
225      _rl_search_cxt *cxt;
226      int r;
227 {
228   _rl_scxt_dispose (cxt, 0);
229   _rl_nscxt = 0;
230
231   RL_UNSETSTATE(RL_STATE_NSEARCH);
232
233   return (r != 1);
234 }
235
236 static void
237 _rl_nsearch_abort (cxt)
238      _rl_search_cxt *cxt;
239 {
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 ();
245
246   RL_UNSETSTATE (RL_STATE_NSEARCH);
247 }
248
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;
256 {
257   switch (c)
258     {
259     case CTRL('W'):
260       rl_unix_word_rubout (1, c);
261       break;
262
263     case CTRL('U'):
264       rl_unix_line_discard (1, c);
265       break;
266
267     case RETURN:
268     case NEWLINE:
269       return 0;
270
271     case CTRL('H'):
272     case RUBOUT:
273       if (rl_point == 0)
274         {
275           _rl_nsearch_abort (cxt);
276           return -1;
277         }
278       _rl_rubout_char (1, c);
279       break;
280
281     case CTRL('C'):
282     case CTRL('G'):
283       rl_ding ();
284       _rl_nsearch_abort (cxt);
285       return -1;
286
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;
295     }
296
297   (*rl_redisplay_function) ();
298   return 1;
299 }
300
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;
308 {
309   rl_mark = cxt->save_mark;
310
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)
315     {
316       if (noninc_search_string == 0)
317         {
318           rl_ding ();
319           rl_restore_prompt ();
320           RL_UNSETSTATE (RL_STATE_NSEARCH);
321           return -1;
322         }
323     }
324   else
325     {
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);
330
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 ();
337     }
338
339   rl_restore_prompt ();
340   return (noninc_dosearch (noninc_search_string, cxt->direction));
341 }
342
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;
352 {
353   _rl_search_cxt *cxt;
354   int c, r;
355
356   cxt = _rl_nsearch_init (dir, pchar);
357
358   if (RL_ISSTATE (RL_STATE_CALLBACK))
359     return (0);
360
361   /* Read the search string. */
362   r = 0;
363   while (1)
364     {
365       c = _rl_search_getchar (cxt);
366
367       if (c == 0)
368         break;
369
370       r = _rl_nsearch_dispatch (cxt, c);
371       if (r < 0)
372         return 1;
373       else if (r == 0)
374         break;        
375     }
376
377   r = _rl_nsearch_dosearch (cxt);
378   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
379 }
380
381 /* Search forward through the history list for a string.  If the vi-mode
382    code calls this, KEY will be `?'. */
383 int
384 rl_noninc_forward_search (count, key)
385      int count, key;
386 {
387   return noninc_search (1, (key == '?') ? '?' : 0);
388 }
389
390 /* Reverse search the history list for a string.  If the vi-mode code
391    calls this, KEY will be `/'. */
392 int
393 rl_noninc_reverse_search (count, key)
394      int count, key;
395 {
396   return noninc_search (-1, (key == '/') ? '/' : 0);
397 }
398
399 /* Search forward through the history list for the last string searched
400    for.  If there is no saved search string, abort. */
401 int
402 rl_noninc_forward_search_again (count, key)
403      int count, key;
404 {
405   int r;
406
407   if (!noninc_search_string)
408     {
409       rl_ding ();
410       return (-1);
411     }
412   r = noninc_dosearch (noninc_search_string, 1);
413   return (r != 1);
414 }
415
416 /* Reverse search in the history list for the last string searched
417    for.  If there is no saved search string, abort. */
418 int
419 rl_noninc_reverse_search_again (count, key)
420      int count, key;
421 {
422   int r;
423
424   if (!noninc_search_string)
425     {
426       rl_ding ();
427       return (-1);
428     }
429   r = noninc_dosearch (noninc_search_string, -1);
430   return (r != 1);
431 }
432
433 #if defined (READLINE_CALLBACKS)
434 int
435 _rl_nsearch_callback (cxt)
436      _rl_search_cxt *cxt;
437 {
438   int c, r;
439
440   c = _rl_search_getchar (cxt);
441   r = _rl_nsearch_dispatch (cxt, c);
442   if (r != 0)
443     return 1;
444
445   r = _rl_nsearch_dosearch (cxt);
446   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
447 }
448 #endif
449   
450 static int
451 rl_history_search_internal (count, dir)
452      int count, dir;
453 {
454   HIST_ENTRY *temp;
455   int ret, oldpos;
456
457   rl_maybe_save_line ();
458   temp = (HIST_ENTRY *)NULL;
459
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)
464     {
465       ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
466       if (ret == -1)
467         break;
468
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);
475
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--;
481     }
482
483   /* If we didn't find anything at all, return. */
484   if (temp == 0)
485     {
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)
493         {
494           rl_point = rl_end = rl_history_search_len;
495           rl_line_buffer[rl_end] = '\0';
496           rl_mark = 0;
497         }
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;
503     }
504
505   /* Copy the line we found into the current line buffer. */
506   make_history_line_current (temp);
507
508   rl_point = rl_history_search_len;
509   rl_mark = rl_end;
510
511   return 0;
512 }
513
514 static void
515 rl_history_search_reinit ()
516 {
517   rl_history_search_pos = where_history ();
518   rl_history_search_len = rl_point;
519   prev_line_found = (char *)NULL;
520   if (rl_point)
521     {
522       if (rl_history_search_len >= history_string_size - 2)
523         {
524           history_string_size = rl_history_search_len + 2;
525           history_search_string = (char *)xrealloc (history_search_string, history_string_size);
526         }
527       history_search_string[0] = '^';
528       strncpy (history_search_string + 1, rl_line_buffer, rl_point);
529       history_search_string[rl_point + 1] = '\0';
530     }
531   _rl_free_saved_history_line ();
532 }
533
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. */
537 int
538 rl_history_search_forward (count, ignore)
539      int count, ignore;
540 {
541   if (count == 0)
542     return (0);
543
544   if (rl_last_func != rl_history_search_forward &&
545       rl_last_func != rl_history_search_backward)
546     rl_history_search_reinit ();
547
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));
551 }
552
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. */
556 int
557 rl_history_search_backward (count, ignore)
558      int count, ignore;
559 {
560   if (count == 0)
561     return (0);
562
563   if (rl_last_func != rl_history_search_forward &&
564       rl_last_func != rl_history_search_backward)
565     rl_history_search_reinit ();
566
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));
570 }