Sync readline/ to version 7.0 alpha
[external/binutils.git] / readline / isearch.c
1 /* isearch.c - incremental searching */
2
3 /* **************************************************************** */
4 /*                                                                  */
5 /*                      I-Search and Searching                      */
6 /*                                                                  */
7 /* **************************************************************** */
8
9 /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
10
11    This file is part of the GNU Readline Library (Readline), a library
12    for reading lines of text with interactive input and history editing.      
13
14    Readline is free software: you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation, either version 3 of the License, or
17    (at your option) any later version.
18
19    Readline is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23
24    You should have received a copy of the GNU General Public License
25    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #define READLINE_LIBRARY
29
30 #if defined (HAVE_CONFIG_H)
31 #  include <config.h>
32 #endif
33
34 #include <sys/types.h>
35
36 #include <stdio.h>
37
38 #if defined (HAVE_UNISTD_H)
39 #  include <unistd.h>
40 #endif
41
42 #if defined (HAVE_STDLIB_H)
43 #  include <stdlib.h>
44 #else
45 #  include "ansi_stdlib.h"
46 #endif
47
48 #include "rldefs.h"
49 #include "rlmbutil.h"
50
51 #include "readline.h"
52 #include "history.h"
53
54 #include "rlprivate.h"
55 #include "xmalloc.h"
56
57 /* Variables exported to other files in the readline library. */
58 char *_rl_isearch_terminators = (char *)NULL;
59
60 _rl_search_cxt *_rl_iscxt = 0;
61
62 /* Variables imported from other files in the readline library. */
63 extern HIST_ENTRY *_rl_saved_line_for_history;
64
65 static int rl_search_history PARAMS((int, int));
66
67 static _rl_search_cxt *_rl_isearch_init PARAMS((int));
68 static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
69
70 /* Last line found by the current incremental search, so we don't `find'
71    identical lines many times in a row.  Now part of isearch context. */
72 /* static char *prev_line_found; */
73
74 /* Last search string and its length. */
75 static char *last_isearch_string;
76 static int last_isearch_string_len;
77
78 static char * const default_isearch_terminators = "\033\012";
79
80 _rl_search_cxt *
81 _rl_scxt_alloc (type, flags)
82      int type, flags;
83 {
84   _rl_search_cxt *cxt;
85
86   cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
87
88   cxt->type = type;
89   cxt->sflags = flags;
90
91   cxt->search_string = 0;
92   cxt->search_string_size = cxt->search_string_index = 0;
93
94   cxt->lines = 0;
95   cxt->allocated_line = 0;
96   cxt->hlen = cxt->hindex = 0;
97
98   cxt->save_point = rl_point;
99   cxt->save_mark = rl_mark;
100   cxt->save_line = where_history ();
101   cxt->last_found_line = cxt->save_line;
102   cxt->prev_line_found = 0;
103
104   cxt->save_undo_list = 0;
105
106   cxt->keymap = _rl_keymap;
107   cxt->okeymap = _rl_keymap;
108
109   cxt->history_pos = 0;
110   cxt->direction = 0;
111
112   cxt->prevc = cxt->lastc = 0;
113
114   cxt->sline = 0;
115   cxt->sline_len = cxt->sline_index = 0;
116
117   cxt->search_terminators = 0;
118
119   return cxt;
120 }
121
122 void
123 _rl_scxt_dispose (cxt, flags)
124      _rl_search_cxt *cxt;
125      int flags;
126 {
127   FREE (cxt->search_string);
128   FREE (cxt->allocated_line);
129   FREE (cxt->lines);
130
131   xfree (cxt);
132 }
133
134 /* Search backwards through the history looking for a string which is typed
135    interactively.  Start with the current line. */
136 int
137 rl_reverse_search_history (sign, key)
138      int sign, key;
139 {
140   return (rl_search_history (-sign, key));
141 }
142
143 /* Search forwards through the history looking for a string which is typed
144    interactively.  Start with the current line. */
145 int
146 rl_forward_search_history (sign, key)
147      int sign, key;
148 {
149   return (rl_search_history (sign, key));
150 }
151
152 /* Display the current state of the search in the echo-area.
153    SEARCH_STRING contains the string that is being searched for,
154    DIRECTION is zero for forward, or non-zero for reverse,
155    WHERE is the history list number of the current line.  If it is
156    -1, then this line is the starting one. */
157 static void
158 rl_display_search (search_string, flags, where)
159      char *search_string;
160      int flags, where;
161 {
162   char *message;
163   int msglen, searchlen;
164
165   searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
166
167   message = (char *)xmalloc (searchlen + 64);
168   msglen = 0;
169
170 #if defined (NOTDEF)
171   if (where != -1)
172     {
173       sprintf (message, "[%d]", where + history_base);
174       msglen = strlen (message);
175     }
176 #endif /* NOTDEF */
177
178   message[msglen++] = '(';
179
180   if (flags & SF_FAILED)
181     {
182       strcpy (message + msglen, "failed ");
183       msglen += 7;
184     }
185
186   if (flags & SF_REVERSE)
187     {
188       strcpy (message + msglen, "reverse-");
189       msglen += 8;
190     }
191
192   strcpy (message + msglen, "i-search)`");
193   msglen += 10;
194
195   if (search_string)
196     {
197       strcpy (message + msglen, search_string);
198       msglen += searchlen;
199     }
200
201   strcpy (message + msglen, "': ");
202
203   rl_message ("%s", message);
204   xfree (message);
205   (*rl_redisplay_function) ();
206 }
207
208 static _rl_search_cxt *
209 _rl_isearch_init (direction)
210      int direction;
211 {
212   _rl_search_cxt *cxt;
213   register int i;
214   HIST_ENTRY **hlist;
215
216   cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
217   if (direction < 0)
218     cxt->sflags |= SF_REVERSE;
219
220   cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
221                                                 : default_isearch_terminators;
222
223   /* Create an array of pointers to the lines that we want to search. */
224   hlist = history_list ();
225   rl_maybe_replace_line ();
226   i = 0;
227   if (hlist)
228     for (i = 0; hlist[i]; i++);
229
230   /* Allocate space for this many lines, +1 for the current input line,
231      and remember those lines. */
232   cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
233   for (i = 0; i < cxt->hlen; i++)
234     cxt->lines[i] = hlist[i]->line;
235
236   if (_rl_saved_line_for_history)
237     cxt->lines[i] = _rl_saved_line_for_history->line;
238   else
239     {
240       /* Keep track of this so we can free it. */
241       cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
242       strcpy (cxt->allocated_line, &rl_line_buffer[0]);
243       cxt->lines[i] = cxt->allocated_line;
244     }
245
246   cxt->hlen++;
247
248   /* The line where we start the search. */
249   cxt->history_pos = cxt->save_line;
250
251   rl_save_prompt ();
252
253   /* Initialize search parameters. */
254   cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
255   cxt->search_string[cxt->search_string_index = 0] = '\0';
256
257   /* Normalize DIRECTION into 1 or -1. */
258   cxt->direction = (direction >= 0) ? 1 : -1;
259
260   cxt->sline = rl_line_buffer;
261   cxt->sline_len = strlen (cxt->sline);
262   cxt->sline_index = rl_point;
263
264   _rl_iscxt = cxt;              /* save globally */
265
266   return cxt;
267 }
268
269 static void
270 _rl_isearch_fini (cxt)
271      _rl_search_cxt *cxt;
272 {
273   /* First put back the original state. */
274   strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
275
276   rl_restore_prompt ();
277
278   /* Save the search string for possible later use. */
279   FREE (last_isearch_string);
280   last_isearch_string = cxt->search_string;
281   last_isearch_string_len = cxt->search_string_index;
282   cxt->search_string = 0;
283
284   if (cxt->last_found_line < cxt->save_line)
285     rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
286   else
287     rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
288
289   /* If the string was not found, put point at the end of the last matching
290      line.  If last_found_line == orig_line, we didn't find any matching
291      history lines at all, so put point back in its original position. */
292   if (cxt->sline_index < 0)
293     {
294       if (cxt->last_found_line == cxt->save_line)
295         cxt->sline_index = cxt->save_point;
296       else
297         cxt->sline_index = strlen (rl_line_buffer);
298       rl_mark = cxt->save_mark;
299     }
300
301   rl_point = cxt->sline_index;
302   /* Don't worry about where to put the mark here; rl_get_previous_history
303      and rl_get_next_history take care of it. */
304
305   rl_clear_message ();
306 }
307
308 int
309 _rl_search_getchar (cxt)
310      _rl_search_cxt *cxt;
311 {
312   int c;
313
314   /* Read a key and decide how to proceed. */
315   RL_SETSTATE(RL_STATE_MOREINPUT);
316   c = cxt->lastc = rl_read_key ();
317   RL_UNSETSTATE(RL_STATE_MOREINPUT);
318
319 #if defined (HANDLE_MULTIBYTE)
320   /* This ends up with C (and LASTC) being set to the last byte of the
321      multibyte character.  In most cases c == lastc == mb[0] */
322   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
323     c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
324 #endif
325
326   RL_CHECK_SIGNALS ();
327   return c;
328 }
329
330 #define ENDSRCH_CHAR(c) \
331   ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
332
333 /* Process just-read character C according to isearch context CXT.  Return
334    -1 if the caller should just free the context and return, 0 if we should
335    break out of the loop, and 1 if we should continue to read characters. */
336 int
337 _rl_isearch_dispatch (cxt, c)
338      _rl_search_cxt *cxt;
339      int c;
340 {
341   int n, wstart, wlen, limit, cval;
342   rl_command_func_t *f;
343
344   f = (rl_command_func_t *)NULL;
345
346   if (c < 0)
347     {
348       cxt->sflags |= SF_FAILED;
349       cxt->history_pos = cxt->last_found_line;
350       return -1;
351     }
352
353   /* If we are moving into a new keymap, modify cxt->keymap and go on.
354      This can be a problem if c == ESC and we want to terminate the
355      incremental search, so we check */
356   if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
357     {
358       /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
359          takes microseconds, so multiply by 1000.  If we don't get any
360          additional input and this keymap shadows another function, process
361          that key as if it was all we read. */
362       if (_rl_keyseq_timeout > 0 &&
363             RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
364             RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
365             _rl_pushed_input_available () == 0 &&
366             ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
367             _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
368         goto add_character;
369
370       cxt->okeymap = cxt->keymap;
371       cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
372       cxt->sflags |= SF_CHGKMAP;
373       /* XXX - we should probably save this sequence, so we can do
374          something useful if this doesn't end up mapping to a command we
375          interpret here.  Right now we just save the most recent character
376          that caused the index into a new keymap. */
377       cxt->prevc = c;
378 #if defined (HANDLE_MULTIBYTE)
379       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
380         {
381           if (cxt->mb[1] == 0)
382             {
383               cxt->pmb[0] = c;          /* XXX should be == cxt->mb[0] */
384               cxt->pmb[1] = '\0';
385             }
386           else
387             memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
388         }
389 #endif
390       return 1;
391     }
392
393 add_character:
394
395   /* Translate the keys we do something with to opcodes. */
396   if (c >= 0 && cxt->keymap[c].type == ISFUNC)
397     {
398       f = cxt->keymap[c].function;
399
400       if (f == rl_reverse_search_history)
401         cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
402       else if (f == rl_forward_search_history)
403         cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
404       else if (f == rl_rubout)
405         cxt->lastc = -3;
406       else if (c == CTRL ('G') || f == rl_abort)
407         cxt->lastc = -4;
408       else if (c == CTRL ('W') || f == rl_unix_word_rubout)     /* XXX */
409         cxt->lastc = -5;
410       else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
411         cxt->lastc = -6;
412     }
413
414   /* If we changed the keymap earlier while translating a key sequence into
415      a command, restore it now that we've succeeded. */
416   if (cxt->sflags & SF_CHGKMAP)
417     {
418       cxt->keymap = cxt->okeymap;
419       cxt->sflags &= ~SF_CHGKMAP;
420       /* If we indexed into a new keymap, but didn't map to a command that
421          affects the search (lastc > 0), and the character that mapped to a
422          new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
423          handle that now as if the previous char would have ended the search
424          and we would have read the current character. */
425       /* XXX - should we check cxt->mb? */
426       if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
427         {
428           rl_stuff_char (cxt->lastc);
429           rl_execute_next (cxt->prevc);
430           /* XXX - do we insert everything in cxt->pmb? */
431           return (0);
432         }
433       /* Otherwise, if the current character is mapped to self-insert or
434          nothing (i.e., not an editing command), and the previous character
435          was a keymap index, then we need to insert both the previous
436          character and the current character into the search string. */
437       else if (cxt->lastc > 0 && cxt->prevc > 0 &&
438                cxt->keymap[cxt->prevc].type == ISKMAP &&
439                (f == 0 || f == rl_insert))
440         {
441           /* Make lastc be the next character read */
442           /* XXX - do we insert everything in cxt->mb? */
443           rl_execute_next (cxt->lastc);
444           /* Dispatch on the previous character (insert into search string) */
445           cxt->lastc = cxt->prevc;
446 #if defined (HANDLE_MULTIBYTE)
447           /* Have to overwrite cxt->mb here because dispatch uses it below */
448           if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
449             {  
450               if (cxt->pmb[1] == 0)       
451                 {
452                   cxt->mb[0] = cxt->lastc;      /* == cxt->prevc */
453                   cxt->mb[1] = '\0';
454                 }
455               else
456                 memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
457             }
458 #endif
459           cxt->prevc = 0;         
460         }
461       else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
462         {
463           rl_stuff_char (cxt->lastc);
464           rl_execute_next (cxt->prevc);
465           /* XXX - do we insert everything in cxt->pmb? */
466           return (0);
467         }
468     }
469
470   /* The characters in isearch_terminators (set from the user-settable
471      variable isearch-terminators) are used to terminate the search but
472      not subsequently execute the character as a command.  The default
473      value is "\033\012" (ESC and C-J). */
474   if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
475     {
476       /* ESC still terminates the search, but if there is pending
477          input or if input arrives within 0.1 seconds (on systems
478          with select(2)) it is used as a prefix character
479          with rl_execute_next.  WATCH OUT FOR THIS!  This is intended
480          to allow the arrow keys to be used like ^F and ^B are used
481          to terminate the search and execute the movement command.
482          XXX - since _rl_input_available depends on the application-
483          settable keyboard timeout value, this could alternatively
484          use _rl_input_queued(100000) */
485       if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
486         rl_execute_next (ESC);
487       return (0);
488     }
489
490 #if defined (HANDLE_MULTIBYTE)
491   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
492     {
493       if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
494         {
495           /* This sets rl_pending_input to LASTC; it will be picked up the next
496              time rl_read_key is called. */
497           rl_execute_next (cxt->lastc);
498           return (0);
499         }
500     }
501   else
502 #endif
503     if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
504       {
505         /* This sets rl_pending_input to LASTC; it will be picked up the next
506            time rl_read_key is called. */
507         rl_execute_next (cxt->lastc);
508         return (0);
509       }
510
511   /* Now dispatch on the character.  `Opcodes' affect the search string or
512      state.  Other characters are added to the string.  */
513   switch (cxt->lastc)
514     {
515     /* search again */
516     case -1:
517       if (cxt->search_string_index == 0)
518         {
519           if (last_isearch_string)
520             {
521               cxt->search_string_size = 64 + last_isearch_string_len;
522               cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
523               strcpy (cxt->search_string, last_isearch_string);
524               cxt->search_string_index = last_isearch_string_len;
525               rl_display_search (cxt->search_string, cxt->sflags, -1);
526               break;
527             }
528           return (1);
529         }
530       else if (cxt->sflags & SF_REVERSE)
531         cxt->sline_index--;
532       else if (cxt->sline_index != cxt->sline_len)
533         cxt->sline_index++;
534       else
535         rl_ding ();
536       break;
537
538     /* switch directions */
539     case -2:
540       cxt->direction = -cxt->direction;
541       if (cxt->direction < 0)
542         cxt->sflags |= SF_REVERSE;
543       else
544         cxt->sflags &= ~SF_REVERSE;
545       break;
546
547     /* delete character from search string. */
548     case -3:    /* C-H, DEL */
549       /* This is tricky.  To do this right, we need to keep a
550          stack of search positions for the current search, with
551          sentinels marking the beginning and end.  But this will
552          do until we have a real isearch-undo. */
553       if (cxt->search_string_index == 0)
554         rl_ding ();
555       else if (MB_CUR_MAX == 1 || rl_byte_oriented)
556         cxt->search_string[--cxt->search_string_index] = '\0';
557       else
558         {
559           wstart = _rl_find_prev_mbchar (cxt->search_string, cxt->search_string_index, MB_FIND_NONZERO);
560           if (wstart >= 0)
561             cxt->search_string[cxt->search_string_index = wstart] = '\0';
562           else
563             rl_ding ();
564         }
565       break;
566
567     case -4:    /* C-G, abort */
568       rl_replace_line (cxt->lines[cxt->save_line], 0);
569       rl_point = cxt->save_point;
570       rl_mark = cxt->save_mark;
571       rl_restore_prompt();
572       rl_clear_message ();
573
574       return -1;
575
576     case -5:    /* C-W */
577       /* skip over portion of line we already matched and yank word */
578       wstart = rl_point + cxt->search_string_index;
579       if (wstart >= rl_end)
580         {
581           rl_ding ();
582           break;
583         }
584
585       /* if not in a word, move to one. */
586       cval = _rl_char_value (rl_line_buffer, wstart);
587       if (_rl_walphabetic (cval) == 0)
588         {
589           rl_ding ();
590           break;
591         }
592       n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
593       while (n < rl_end)
594         {
595           cval = _rl_char_value (rl_line_buffer, n);
596           if (_rl_walphabetic (cval) == 0)
597             break;
598           n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
599         }
600       wlen = n - wstart + 1;
601       if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
602         {
603           cxt->search_string_size += wlen + 1;
604           cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
605         }
606       for (; wstart < n; wstart++)
607         cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
608       cxt->search_string[cxt->search_string_index] = '\0';
609       break;
610
611     case -6:    /* C-Y */
612       /* skip over portion of line we already matched and yank rest */
613       wstart = rl_point + cxt->search_string_index;
614       if (wstart >= rl_end)
615         {
616           rl_ding ();
617           break;
618         }
619       n = rl_end - wstart + 1;
620       if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
621         {
622           cxt->search_string_size += n + 1;
623           cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
624         }
625       for (n = wstart; n < rl_end; n++)
626         cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
627       cxt->search_string[cxt->search_string_index] = '\0';
628       break;
629
630     /* Add character to search string and continue search. */
631     default:
632       if (cxt->search_string_index + 2 >= cxt->search_string_size)
633         {
634           cxt->search_string_size += 128;
635           cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
636         }
637 #if defined (HANDLE_MULTIBYTE)
638       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
639         {
640           int j, l;
641
642           if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
643             cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
644           else
645             for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
646               cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
647         }
648       else
649 #endif
650         cxt->search_string[cxt->search_string_index++] = cxt->lastc;    /* XXX - was c instead of lastc */
651       cxt->search_string[cxt->search_string_index] = '\0';
652       break;
653     }
654
655   for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
656     {
657       limit = cxt->sline_len - cxt->search_string_index + 1;
658
659       /* Search the current line. */
660       while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
661         {
662           if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
663             {
664               cxt->sflags |= SF_FOUND;
665               break;
666             }
667           else
668             cxt->sline_index += cxt->direction;
669         }
670       if (cxt->sflags & SF_FOUND)
671         break;
672
673       /* Move to the next line, but skip new copies of the line
674          we just found and lines shorter than the string we're
675          searching for. */
676       do
677         {
678           /* Move to the next line. */
679           cxt->history_pos += cxt->direction;
680
681           /* At limit for direction? */
682           if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
683             {
684               cxt->sflags |= SF_FAILED;
685               break;
686             }
687
688           /* We will need these later. */
689           cxt->sline = cxt->lines[cxt->history_pos];
690           cxt->sline_len = strlen (cxt->sline);
691         }
692       while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
693              (cxt->search_string_index > cxt->sline_len));
694
695       if (cxt->sflags & SF_FAILED)
696         break;
697
698       /* Now set up the line for searching... */
699       cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
700     }
701
702   if (cxt->sflags & SF_FAILED)
703     {
704       /* We cannot find the search string.  Ding the bell. */
705       rl_ding ();
706       cxt->history_pos = cxt->last_found_line;
707       rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
708       return 1;
709     }
710
711   /* We have found the search string.  Just display it.  But don't
712      actually move there in the history list until the user accepts
713      the location. */
714   if (cxt->sflags & SF_FOUND)
715     {
716       cxt->prev_line_found = cxt->lines[cxt->history_pos];
717       rl_replace_line (cxt->lines[cxt->history_pos], 0);
718       rl_point = cxt->sline_index;
719       cxt->last_found_line = cxt->history_pos;
720       rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
721     }
722
723   return 1;
724 }
725
726 int
727 _rl_isearch_cleanup (cxt, r)
728      _rl_search_cxt *cxt;
729      int r;
730 {
731   if (r >= 0)
732     _rl_isearch_fini (cxt);
733   _rl_scxt_dispose (cxt, 0);
734   _rl_iscxt = 0;
735
736   RL_UNSETSTATE(RL_STATE_ISEARCH);
737
738   return (r != 0);
739 }
740
741 /* Search through the history looking for an interactively typed string.
742    This is analogous to i-search.  We start the search in the current line.
743    DIRECTION is which direction to search; >= 0 means forward, < 0 means
744    backwards. */
745 static int
746 rl_search_history (direction, invoking_key)
747      int direction, invoking_key;
748 {
749   _rl_search_cxt *cxt;          /* local for now, but saved globally */
750   int c, r;
751
752   RL_SETSTATE(RL_STATE_ISEARCH);
753   cxt = _rl_isearch_init (direction);
754
755   rl_display_search (cxt->search_string, cxt->sflags, -1);
756
757   /* If we are using the callback interface, all we do is set up here and
758       return.  The key is that we leave RL_STATE_ISEARCH set. */
759   if (RL_ISSTATE (RL_STATE_CALLBACK))
760     return (0);
761
762   r = -1;
763   for (;;)
764     {
765       c = _rl_search_getchar (cxt);
766       /* We might want to handle EOF here (c == 0) */
767       r = _rl_isearch_dispatch (cxt, cxt->lastc);
768       if (r <= 0)
769         break;
770     }
771
772   /* The searching is over.  The user may have found the string that she
773      was looking for, or else she may have exited a failing search.  If
774      LINE_INDEX is -1, then that shows that the string searched for was
775      not found.  We use this to determine where to place rl_point. */
776   return (_rl_isearch_cleanup (cxt, r));
777 }
778
779 #if defined (READLINE_CALLBACKS)
780 /* Called from the callback functions when we are ready to read a key.  The
781    callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
782    If _rl_isearch_dispatch finishes searching, this function is responsible
783    for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
784 int
785 _rl_isearch_callback (cxt)
786      _rl_search_cxt *cxt;
787 {
788   int c, r;
789
790   c = _rl_search_getchar (cxt);
791   /* We might want to handle EOF here */
792   r = _rl_isearch_dispatch (cxt, cxt->lastc);
793
794   return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
795 }
796 #endif