Imported from ../bash-3.1.tar.gz.
[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-2005 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 2, 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    59 Temple Place, Suite 330, Boston, MA 02111 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 "rlmbutil.h"
44
45 #include "readline.h"
46 #include "history.h"
47
48 #include "rlprivate.h"
49 #include "xmalloc.h"
50
51 #ifdef abs
52 #  undef abs
53 #endif
54 #define abs(x)          (((x) >= 0) ? (x) : -(x))
55
56 _rl_search_cxt *_rl_nscxt = 0;
57
58 extern HIST_ENTRY *_rl_saved_line_for_history;
59
60 /* Functions imported from the rest of the library. */
61 extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
62
63 static char *noninc_search_string = (char *) NULL;
64 static int noninc_history_pos;
65
66 static char *prev_line_found = (char *) NULL;
67
68 static int rl_history_search_len;
69 static int rl_history_search_pos;
70 static char *history_search_string;
71 static int history_string_size;
72
73 static UNDO_LIST *noninc_saved_undo_list;
74 static void make_history_line_current PARAMS((HIST_ENTRY *));
75 static int noninc_search_from_pos PARAMS((char *, int, int));
76 static int noninc_dosearch PARAMS((char *, int));
77 static int noninc_search PARAMS((int, int));
78 static int rl_history_search_internal PARAMS((int, int));
79 static void rl_history_search_reinit PARAMS((void));
80
81 static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
82 static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
83 static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
84 static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
85
86 /* Make the data from the history entry ENTRY be the contents of the
87    current line.  This doesn't do anything with rl_point; the caller
88    must set it. */
89 static void
90 make_history_line_current (entry)
91      HIST_ENTRY *entry;
92 {
93   _rl_replace_text (entry->line, 0, rl_end);
94   _rl_fix_point (1);
95 #if defined (VI_MODE)
96   if (rl_editing_mode == vi_mode)
97     /* POSIX.2 says that the `U' command doesn't affect the copy of any
98        command lines to the edit line.  We're going to implement that by
99        making the undo list start after the matching line is copied to the
100        current editing buffer. */
101     rl_free_undo_list ();
102 #endif
103
104   if (_rl_saved_line_for_history)
105     _rl_free_history_entry (_rl_saved_line_for_history);
106   _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
107 }
108
109 /* Search the history list for STRING starting at absolute history position
110    POS.  If STRING begins with `^', the search must match STRING at the
111    beginning of a history line, otherwise a full substring match is performed
112    for STRING.  DIR < 0 means to search backwards through the history list,
113    DIR >= 0 means to search forward. */
114 static int
115 noninc_search_from_pos (string, pos, dir)
116      char *string;
117      int pos, dir;
118 {
119   int ret, old;
120
121   if (pos < 0)
122     return -1;
123
124   old = where_history ();
125   if (history_set_pos (pos) == 0)
126     return -1;
127
128   RL_SETSTATE(RL_STATE_SEARCH);
129   if (*string == '^')
130     ret = history_search_prefix (string + 1, dir);
131   else
132     ret = history_search (string, dir);
133   RL_UNSETSTATE(RL_STATE_SEARCH);
134
135   if (ret != -1)
136     ret = where_history ();
137
138   history_set_pos (old);
139   return (ret);
140 }
141
142 /* Search for a line in the history containing STRING.  If DIR is < 0, the
143    search is backwards through previous entries, else through subsequent
144    entries.  Returns 1 if the search was successful, 0 otherwise. */
145 static int
146 noninc_dosearch (string, dir)
147      char *string;
148      int dir;
149 {
150   int oldpos, pos;
151   HIST_ENTRY *entry;
152
153   if (string == 0 || *string == '\0' || noninc_history_pos < 0)
154     {
155       rl_ding ();
156       return 0;
157     }
158
159   pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
160   if (pos == -1)
161     {
162       /* Search failed, current history position unchanged. */
163       rl_maybe_unsave_line ();
164       rl_clear_message ();
165       rl_point = 0;
166       rl_ding ();
167       return 0;
168     }
169
170   noninc_history_pos = pos;
171
172   oldpos = where_history ();
173   history_set_pos (noninc_history_pos);
174   entry = current_history ();
175 #if defined (VI_MODE)
176   if (rl_editing_mode != vi_mode)
177 #endif
178     history_set_pos (oldpos);
179
180   make_history_line_current (entry);
181
182   rl_point = 0;
183   rl_mark = rl_end;
184
185   rl_clear_message ();
186   return 1;
187 }
188
189 static _rl_search_cxt *
190 _rl_nsearch_init (dir, pchar)
191      int dir, pchar;
192 {
193   _rl_search_cxt *cxt;
194   char *p;
195
196   cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
197   if (dir < 0)
198     cxt->sflags |= SF_REVERSE;          /* not strictly needed */
199
200   cxt->direction = dir;
201   cxt->history_pos = cxt->save_line;
202
203   rl_maybe_save_line ();
204
205   /* Clear the undo list, since reading the search string should create its
206      own undo list, and the whole list will end up being freed when we
207      finish reading the search string. */
208   rl_undo_list = 0;
209
210   /* Use the line buffer to read the search string. */
211   rl_line_buffer[0] = 0;
212   rl_end = rl_point = 0;
213
214   p = _rl_make_prompt_for_search (pchar ? pchar : ':');
215   rl_message (p, 0, 0);
216   free (p);
217
218   RL_SETSTATE(RL_STATE_NSEARCH);
219
220   _rl_nscxt = cxt;
221
222   return cxt;
223 }
224
225 static int
226 _rl_nsearch_cleanup (cxt, r)
227      _rl_search_cxt *cxt;
228      int r;
229 {
230   _rl_scxt_dispose (cxt, 0);
231   _rl_nscxt = 0;
232
233   RL_UNSETSTATE(RL_STATE_NSEARCH);
234
235   return (r != 1);
236 }
237
238 static void
239 _rl_nsearch_abort (cxt)
240      _rl_search_cxt *cxt;
241 {
242   rl_maybe_unsave_line ();
243   rl_clear_message ();
244   rl_point = cxt->save_point;
245   rl_mark = cxt->save_mark;
246   rl_restore_prompt ();
247
248   RL_UNSETSTATE (RL_STATE_NSEARCH);
249 }
250
251 /* Process just-read character C according to search context CXT.  Return -1
252    if the caller should abort the search, 0 if we should break out of the
253    loop, and 1 if we should continue to read characters. */
254 static int
255 _rl_nsearch_dispatch (cxt, c)
256      _rl_search_cxt *cxt;
257      int c;
258 {
259   switch (c)
260     {
261     case CTRL('W'):
262       rl_unix_word_rubout (1, c);
263       break;
264
265     case CTRL('U'):
266       rl_unix_line_discard (1, c);
267       break;
268
269     case RETURN:
270     case NEWLINE:
271       return 0;
272
273     case CTRL('H'):
274     case RUBOUT:
275       if (rl_point == 0)
276         {
277           _rl_nsearch_abort (cxt);
278           return -1;
279         }
280       _rl_rubout_char (1, c);
281       break;
282
283     case CTRL('C'):
284     case CTRL('G'):
285       rl_ding ();
286       _rl_nsearch_abort (cxt);
287       return -1;
288
289     default:
290 #if defined (HANDLE_MULTIBYTE)
291       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
292         rl_insert_text (cxt->mb);
293       else
294 #endif
295         _rl_insert_char (1, c);
296       break;
297     }
298
299   (*rl_redisplay_function) ();
300   return 1;
301 }
302
303 /* Perform one search according to CXT, using NONINC_SEARCH_STRING.  Return
304    -1 if the search should be aborted, any other value means to clean up
305    using _rl_nsearch_cleanup ().  Returns 1 if the search was successful,
306    0 otherwise. */
307 static int
308 _rl_nsearch_dosearch (cxt)
309      _rl_search_cxt *cxt;
310 {
311   rl_mark = cxt->save_mark;
312
313   /* If rl_point == 0, we want to re-use the previous search string and
314      start from the saved history position.  If there's no previous search
315      string, punt. */
316   if (rl_point == 0)
317     {
318       if (noninc_search_string == 0)
319         {
320           rl_ding ();
321           rl_restore_prompt ();
322           RL_UNSETSTATE (RL_STATE_NSEARCH);
323           return -1;
324         }
325     }
326   else
327     {
328       /* We want to start the search from the current history position. */
329       noninc_history_pos = cxt->save_line;
330       FREE (noninc_search_string);
331       noninc_search_string = savestring (rl_line_buffer);
332
333       /* If we don't want the subsequent undo list generated by the search
334          matching a history line to include the contents of the search string,
335          we need to clear rl_line_buffer here.  For now, we just clear the
336          undo list generated by reading the search string.  (If the search
337          fails, the old undo list will be restored by rl_maybe_unsave_line.) */
338       rl_free_undo_list ();
339     }
340
341   rl_restore_prompt ();
342   return (noninc_dosearch (noninc_search_string, cxt->direction));
343 }
344
345 /* Search non-interactively through the history list.  DIR < 0 means to
346    search backwards through the history of previous commands; otherwise
347    the search is for commands subsequent to the current position in the
348    history list.  PCHAR is the character to use for prompting when reading
349    the search string; if not specified (0), it defaults to `:'. */
350 static int
351 noninc_search (dir, pchar)
352      int dir;
353      int pchar;
354 {
355   _rl_search_cxt *cxt;
356   int c, r;
357
358   cxt = _rl_nsearch_init (dir, pchar);
359
360   if (RL_ISSTATE (RL_STATE_CALLBACK))
361     return (0);
362
363   /* Read the search string. */
364   r = 0;
365   while (1)
366     {
367       c = _rl_search_getchar (cxt);
368
369       if (c == 0)
370         break;
371
372       r = _rl_nsearch_dispatch (cxt, c);
373       if (r < 0)
374         return 1;
375       else if (r == 0)
376         break;        
377     }
378
379   r = _rl_nsearch_dosearch (cxt);
380   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
381 }
382
383 /* Search forward through the history list for a string.  If the vi-mode
384    code calls this, KEY will be `?'. */
385 int
386 rl_noninc_forward_search (count, key)
387      int count, key;
388 {
389   return noninc_search (1, (key == '?') ? '?' : 0);
390 }
391
392 /* Reverse search the history list for a string.  If the vi-mode code
393    calls this, KEY will be `/'. */
394 int
395 rl_noninc_reverse_search (count, key)
396      int count, key;
397 {
398   return noninc_search (-1, (key == '/') ? '/' : 0);
399 }
400
401 /* Search forward through the history list for the last string searched
402    for.  If there is no saved search string, abort. */
403 int
404 rl_noninc_forward_search_again (count, key)
405      int count, key;
406 {
407   int r;
408
409   if (!noninc_search_string)
410     {
411       rl_ding ();
412       return (-1);
413     }
414   r = noninc_dosearch (noninc_search_string, 1);
415   return (r != 1);
416 }
417
418 /* Reverse search in the history list for the last string searched
419    for.  If there is no saved search string, abort. */
420 int
421 rl_noninc_reverse_search_again (count, key)
422      int count, key;
423 {
424   int r;
425
426   if (!noninc_search_string)
427     {
428       rl_ding ();
429       return (-1);
430     }
431   r = noninc_dosearch (noninc_search_string, -1);
432   return (r != 1);
433 }
434
435 #if defined (READLINE_CALLBACKS)
436 int
437 _rl_nsearch_callback (cxt)
438      _rl_search_cxt *cxt;
439 {
440   int c, r;
441
442   c = _rl_search_getchar (cxt);
443   r = _rl_nsearch_dispatch (cxt, c);
444   if (r != 0)
445     return 1;
446
447   r = _rl_nsearch_dosearch (cxt);
448   return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
449 }
450 #endif
451   
452 static int
453 rl_history_search_internal (count, dir)
454      int count, dir;
455 {
456   HIST_ENTRY *temp;
457   int ret, oldpos;
458
459   rl_maybe_save_line ();
460   temp = (HIST_ENTRY *)NULL;
461
462   /* Search COUNT times through the history for a line whose prefix
463      matches history_search_string.  When this loop finishes, TEMP,
464      if non-null, is the history line to copy into the line buffer. */
465   while (count)
466     {
467       ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
468       if (ret == -1)
469         break;
470
471       /* Get the history entry we found. */
472       rl_history_search_pos = ret;
473       oldpos = where_history ();
474       history_set_pos (rl_history_search_pos);
475       temp = current_history ();
476       history_set_pos (oldpos);
477
478       /* Don't find multiple instances of the same line. */
479       if (prev_line_found && STREQ (prev_line_found, temp->line))
480         continue;
481       prev_line_found = temp->line;
482       count--;
483     }
484
485   /* If we didn't find anything at all, return. */
486   if (temp == 0)
487     {
488       rl_maybe_unsave_line ();
489       rl_ding ();
490       /* If you don't want the saved history line (last match) to show up
491          in the line buffer after the search fails, change the #if 0 to
492          #if 1 */
493 #if 0
494       if (rl_point > rl_history_search_len)
495         {
496           rl_point = rl_end = rl_history_search_len;
497           rl_line_buffer[rl_end] = '\0';
498           rl_mark = 0;
499         }
500 #else
501       rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
502       rl_mark = rl_end;
503 #endif
504       return 1;
505     }
506
507   /* Copy the line we found into the current line buffer. */
508   make_history_line_current (temp);
509
510   rl_point = rl_history_search_len;
511   rl_mark = rl_end;
512
513   return 0;
514 }
515
516 static void
517 rl_history_search_reinit ()
518 {
519   rl_history_search_pos = where_history ();
520   rl_history_search_len = rl_point;
521   prev_line_found = (char *)NULL;
522   if (rl_point)
523     {
524       if (rl_history_search_len >= history_string_size - 2)
525         {
526           history_string_size = rl_history_search_len + 2;
527           history_search_string = (char *)xrealloc (history_search_string, history_string_size);
528         }
529       history_search_string[0] = '^';
530       strncpy (history_search_string + 1, rl_line_buffer, rl_point);
531       history_search_string[rl_point + 1] = '\0';
532     }
533   _rl_free_saved_history_line ();
534 }
535
536 /* Search forward in the history for the string of characters
537    from the start of the line to rl_point.  This is a non-incremental
538    search. */
539 int
540 rl_history_search_forward (count, ignore)
541      int count, ignore;
542 {
543   if (count == 0)
544     return (0);
545
546   if (rl_last_func != rl_history_search_forward &&
547       rl_last_func != rl_history_search_backward)
548     rl_history_search_reinit ();
549
550   if (rl_history_search_len == 0)
551     return (rl_get_next_history (count, ignore));
552   return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
553 }
554
555 /* Search backward through the history for the string of characters
556    from the start of the line to rl_point.  This is a non-incremental
557    search. */
558 int
559 rl_history_search_backward (count, ignore)
560      int count, ignore;
561 {
562   if (count == 0)
563     return (0);
564
565   if (rl_last_func != rl_history_search_forward &&
566       rl_last_func != rl_history_search_backward)
567     rl_history_search_reinit ();
568
569   if (rl_history_search_len == 0)
570     return (rl_get_previous_history (count, ignore));
571   return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
572 }