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