1 /* isearch.c - incremental searching */
3 /* **************************************************************** */
5 /* I-Search and Searching */
7 /* **************************************************************** */
9 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
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.
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.
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.
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/>.
28 #define READLINE_LIBRARY
30 #if defined (HAVE_CONFIG_H)
34 #include <sys/types.h>
38 #if defined (HAVE_UNISTD_H)
42 #if defined (HAVE_STDLIB_H)
45 # include "ansi_stdlib.h"
54 #include "rlprivate.h"
57 /* Variables exported to other files in the readline library. */
58 char *_rl_isearch_terminators
= (char *)NULL
;
60 _rl_search_cxt
*_rl_iscxt
= 0;
62 /* Variables imported from other files in the readline library. */
63 extern HIST_ENTRY
*_rl_saved_line_for_history
;
65 static int rl_search_history
PARAMS((int, int));
67 static _rl_search_cxt
*_rl_isearch_init
PARAMS((int));
68 static void _rl_isearch_fini
PARAMS((_rl_search_cxt
*));
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; */
74 /* Last search string and its length. */
75 static char *last_isearch_string
;
76 static int last_isearch_string_len
;
78 static char * const default_isearch_terminators
= "\033\012";
81 _rl_scxt_alloc (int type
, int flags
)
85 cxt
= (_rl_search_cxt
*)xmalloc (sizeof (_rl_search_cxt
));
90 cxt
->search_string
= 0;
91 cxt
->search_string_size
= cxt
->search_string_index
= 0;
94 cxt
->allocated_line
= 0;
95 cxt
->hlen
= cxt
->hindex
= 0;
97 cxt
->save_point
= rl_point
;
98 cxt
->save_mark
= rl_mark
;
99 cxt
->save_line
= where_history ();
100 cxt
->last_found_line
= cxt
->save_line
;
101 cxt
->prev_line_found
= 0;
103 cxt
->save_undo_list
= 0;
105 cxt
->keymap
= _rl_keymap
;
106 cxt
->okeymap
= _rl_keymap
;
108 cxt
->history_pos
= 0;
111 cxt
->prevc
= cxt
->lastc
= 0;
114 cxt
->sline_len
= cxt
->sline_index
= 0;
116 cxt
->search_terminators
= 0;
122 _rl_scxt_dispose (_rl_search_cxt
*cxt
, int flags
)
124 FREE (cxt
->search_string
);
125 FREE (cxt
->allocated_line
);
131 /* Search backwards through the history looking for a string which is typed
132 interactively. Start with the current line. */
134 rl_reverse_search_history (int sign
, int key
)
136 return (rl_search_history (-sign
, key
));
139 /* Search forwards through the history looking for a string which is typed
140 interactively. Start with the current line. */
142 rl_forward_search_history (int sign
, int key
)
144 return (rl_search_history (sign
, key
));
147 /* Display the current state of the search in the echo-area.
148 SEARCH_STRING contains the string that is being searched for,
149 DIRECTION is zero for forward, or non-zero for reverse,
150 WHERE is the history list number of the current line. If it is
151 -1, then this line is the starting one. */
153 rl_display_search (char *search_string
, int flags
, int where
)
156 int msglen
, searchlen
;
158 searchlen
= (search_string
&& *search_string
) ? strlen (search_string
) : 0;
160 message
= (char *)xmalloc (searchlen
+ 64);
166 sprintf (message
, "[%d]", where
+ history_base
);
167 msglen
= strlen (message
);
171 message
[msglen
++] = '(';
173 if (flags
& SF_FAILED
)
175 strcpy (message
+ msglen
, "failed ");
179 if (flags
& SF_REVERSE
)
181 strcpy (message
+ msglen
, "reverse-");
185 strcpy (message
+ msglen
, "i-search)`");
188 if (search_string
&& *search_string
)
190 strcpy (message
+ msglen
, search_string
);
194 _rl_optimize_redisplay ();
196 strcpy (message
+ msglen
, "': ");
198 rl_message ("%s", message
);
200 (*rl_redisplay_function
) ();
203 static _rl_search_cxt
*
204 _rl_isearch_init (int direction
)
210 cxt
= _rl_scxt_alloc (RL_SEARCH_ISEARCH
, 0);
212 cxt
->sflags
|= SF_REVERSE
;
214 cxt
->search_terminators
= _rl_isearch_terminators
? _rl_isearch_terminators
215 : default_isearch_terminators
;
217 /* Create an array of pointers to the lines that we want to search. */
218 hlist
= history_list ();
219 rl_maybe_replace_line ();
222 for (i
= 0; hlist
[i
]; i
++);
224 /* Allocate space for this many lines, +1 for the current input line,
225 and remember those lines. */
226 cxt
->lines
= (char **)xmalloc ((1 + (cxt
->hlen
= i
)) * sizeof (char *));
227 for (i
= 0; i
< cxt
->hlen
; i
++)
228 cxt
->lines
[i
] = hlist
[i
]->line
;
230 if (_rl_saved_line_for_history
)
231 cxt
->lines
[i
] = _rl_saved_line_for_history
->line
;
234 /* Keep track of this so we can free it. */
235 cxt
->allocated_line
= (char *)xmalloc (1 + strlen (rl_line_buffer
));
236 strcpy (cxt
->allocated_line
, &rl_line_buffer
[0]);
237 cxt
->lines
[i
] = cxt
->allocated_line
;
242 /* The line where we start the search. */
243 cxt
->history_pos
= cxt
->save_line
;
247 /* Initialize search parameters. */
248 cxt
->search_string
= (char *)xmalloc (cxt
->search_string_size
= 128);
249 cxt
->search_string
[cxt
->search_string_index
= 0] = '\0';
251 /* Normalize DIRECTION into 1 or -1. */
252 cxt
->direction
= (direction
>= 0) ? 1 : -1;
254 cxt
->sline
= rl_line_buffer
;
255 cxt
->sline_len
= strlen (cxt
->sline
);
256 cxt
->sline_index
= rl_point
;
258 _rl_iscxt
= cxt
; /* save globally */
260 /* experimental right now */
261 _rl_init_executing_keyseq ();
267 _rl_isearch_fini (_rl_search_cxt
*cxt
)
269 /* First put back the original state. */
270 rl_replace_line (cxt
->lines
[cxt
->save_line
], 0);
272 rl_restore_prompt ();
274 /* Save the search string for possible later use. */
275 FREE (last_isearch_string
);
276 last_isearch_string
= cxt
->search_string
;
277 last_isearch_string_len
= cxt
->search_string_index
;
278 cxt
->search_string
= 0;
280 if (cxt
->last_found_line
< cxt
->save_line
)
281 rl_get_previous_history (cxt
->save_line
- cxt
->last_found_line
, 0);
283 rl_get_next_history (cxt
->last_found_line
- cxt
->save_line
, 0);
285 /* If the string was not found, put point at the end of the last matching
286 line. If last_found_line == orig_line, we didn't find any matching
287 history lines at all, so put point back in its original position. */
288 if (cxt
->sline_index
< 0)
290 if (cxt
->last_found_line
== cxt
->save_line
)
291 cxt
->sline_index
= cxt
->save_point
;
293 cxt
->sline_index
= strlen (rl_line_buffer
);
294 rl_mark
= cxt
->save_mark
;
295 rl_deactivate_mark ();
298 rl_point
= cxt
->sline_index
;
299 /* Don't worry about where to put the mark here; rl_get_previous_history
300 and rl_get_next_history take care of it.
301 If we want to highlight the search string, this is where to set the
302 point and mark to do it. */
304 rl_deactivate_mark ();
306 /* _rl_optimize_redisplay (); */
310 /* XXX - we could use _rl_bracketed_read_mbstring () here. */
312 _rl_search_getchar (_rl_search_cxt
*cxt
)
316 /* Read a key and decide how to proceed. */
317 RL_SETSTATE(RL_STATE_MOREINPUT
);
318 c
= cxt
->lastc
= rl_read_key ();
319 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
321 #if defined (HANDLE_MULTIBYTE)
322 /* This ends up with C (and LASTC) being set to the last byte of the
323 multibyte character. In most cases c == lastc == mb[0] */
324 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
325 c
= cxt
->lastc
= _rl_read_mbstring (cxt
->lastc
, cxt
->mb
, MB_LEN_MAX
);
332 #define ENDSRCH_CHAR(c) \
333 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
335 /* Process just-read character C according to isearch context CXT. Return
336 -1 if the caller should just free the context and return, 0 if we should
337 break out of the loop, and 1 if we should continue to read characters. */
339 _rl_isearch_dispatch (_rl_search_cxt
*cxt
, int c
)
341 int n
, wstart
, wlen
, limit
, cval
, incr
;
345 rl_command_func_t
*f
;
347 f
= (rl_command_func_t
*)NULL
;
351 cxt
->sflags
|= SF_FAILED
;
352 cxt
->history_pos
= cxt
->last_found_line
;
356 _rl_add_executing_keyseq (c
);
358 /* XXX - experimental code to allow users to bracketed-paste into the search
359 string even when ESC is one of the isearch-terminators. Not perfect yet. */
360 if (_rl_enable_bracketed_paste
&& c
== ESC
&& strchr (cxt
->search_terminators
, c
) && (n
= _rl_nchars_available ()) > (BRACK_PASTE_SLEN
-1))
362 j
= _rl_read_bracketed_paste_prefix (c
);
365 cxt
->lastc
= -7; /* bracketed paste, see below */
366 goto opcode_dispatch
;
368 else if (_rl_pushed_input_available ()) /* eat extra char we pushed back */
369 c
= cxt
->lastc
= rl_read_key ();
371 c
= cxt
->lastc
; /* last ditch */
374 /* If we are moving into a new keymap, modify cxt->keymap and go on.
375 This can be a problem if c == ESC and we want to terminate the
376 incremental search, so we check */
377 if (c
>= 0 && cxt
->keymap
[c
].type
== ISKMAP
&& strchr (cxt
->search_terminators
, cxt
->lastc
) == 0)
379 /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
380 takes microseconds, so multiply by 1000. If we don't get any
381 additional input and this keymap shadows another function, process
382 that key as if it was all we read. */
383 if (_rl_keyseq_timeout
> 0 &&
384 RL_ISSTATE (RL_STATE_CALLBACK
) == 0 &&
385 RL_ISSTATE (RL_STATE_INPUTPENDING
) == 0 &&
386 _rl_pushed_input_available () == 0 &&
387 ((Keymap
)(cxt
->keymap
[c
].function
))[ANYOTHERKEY
].function
&&
388 _rl_input_queued (_rl_keyseq_timeout
*1000) == 0)
391 cxt
->okeymap
= cxt
->keymap
;
392 cxt
->keymap
= FUNCTION_TO_KEYMAP (cxt
->keymap
, c
);
393 cxt
->sflags
|= SF_CHGKMAP
;
394 /* XXX - we should probably save this sequence, so we can do
395 something useful if this doesn't end up mapping to a command we
396 interpret here. Right now we just save the most recent character
397 that caused the index into a new keymap. */
399 #if defined (HANDLE_MULTIBYTE)
400 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
404 cxt
->pmb
[0] = c
; /* XXX should be == cxt->mb[0] */
408 memcpy (cxt
->pmb
, cxt
->mb
, sizeof (cxt
->pmb
));
416 /* Translate the keys we do something with to opcodes. */
417 if (c
>= 0 && cxt
->keymap
[c
].type
== ISFUNC
)
419 /* If we have a multibyte character, see if it's bound to something that
420 affects the search. */
421 #if defined (HANDLE_MULTIBYTE)
422 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0 && cxt
->mb
[1])
423 f
= rl_function_of_keyseq (cxt
->mb
, cxt
->keymap
, (int *)NULL
);
427 f
= cxt
->keymap
[c
].function
;
428 if (f
== rl_do_lowercase_version
)
429 f
= cxt
->keymap
[_rl_to_lower (c
)].function
;
432 if (f
== rl_reverse_search_history
)
433 cxt
->lastc
= (cxt
->sflags
& SF_REVERSE
) ? -1 : -2;
434 else if (f
== rl_forward_search_history
)
435 cxt
->lastc
= (cxt
->sflags
& SF_REVERSE
) ? -2 : -1;
436 else if (f
== rl_rubout
)
438 else if (c
== CTRL ('G') || f
== rl_abort
)
440 else if (c
== CTRL ('W') || f
== rl_unix_word_rubout
) /* XXX */
442 else if (c
== CTRL ('Y') || f
== rl_yank
) /* XXX */
444 else if (f
== rl_bracketed_paste_begin
)
448 /* If we changed the keymap earlier while translating a key sequence into
449 a command, restore it now that we've succeeded. */
450 if (cxt
->sflags
& SF_CHGKMAP
)
452 cxt
->keymap
= cxt
->okeymap
;
453 cxt
->sflags
&= ~SF_CHGKMAP
;
454 /* If we indexed into a new keymap, but didn't map to a command that
455 affects the search (lastc > 0), and the character that mapped to a
456 new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
457 handle that now as if the previous char would have ended the search
458 and we would have read the current character. */
459 /* XXX - should we check cxt->mb? */
460 if (cxt
->lastc
> 0 && ENDSRCH_CHAR (cxt
->prevc
))
462 rl_stuff_char (cxt
->lastc
);
463 rl_execute_next (cxt
->prevc
);
464 /* XXX - do we insert everything in cxt->pmb? */
467 /* Otherwise, if the current character is mapped to self-insert or
468 nothing (i.e., not an editing command), and the previous character
469 was a keymap index, then we need to insert both the previous
470 character and the current character into the search string. */
471 else if (cxt
->lastc
> 0 && cxt
->prevc
> 0 &&
472 cxt
->keymap
[cxt
->prevc
].type
== ISKMAP
&&
473 (f
== 0 || f
== rl_insert
))
475 /* Make lastc be the next character read */
476 /* XXX - do we insert everything in cxt->mb? */
477 rl_execute_next (cxt
->lastc
);
478 /* Dispatch on the previous character (insert into search string) */
479 cxt
->lastc
= cxt
->prevc
;
480 #if defined (HANDLE_MULTIBYTE)
481 /* Have to overwrite cxt->mb here because dispatch uses it below */
482 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
484 if (cxt
->pmb
[1] == 0)
486 cxt
->mb
[0] = cxt
->lastc
; /* == cxt->prevc */
490 memcpy (cxt
->mb
, cxt
->pmb
, sizeof (cxt
->mb
));
495 else if (cxt
->lastc
> 0 && cxt
->prevc
> 0 && f
&& f
!= rl_insert
)
497 _rl_term_executing_keyseq (); /* should this go in the caller? */
499 _rl_pending_command
.map
= cxt
->keymap
;
500 _rl_pending_command
.count
= 1; /* XXX */
501 _rl_pending_command
.key
= cxt
->lastc
;
502 _rl_pending_command
.func
= f
;
503 _rl_command_to_execute
= &_rl_pending_command
;
509 /* The characters in isearch_terminators (set from the user-settable
510 variable isearch-terminators) are used to terminate the search but
511 not subsequently execute the character as a command. The default
512 value is "\033\012" (ESC and C-J). */
513 if (cxt
->lastc
> 0 && strchr (cxt
->search_terminators
, cxt
->lastc
))
515 /* ESC still terminates the search, but if there is pending
516 input or if input arrives within 0.1 seconds (on systems
517 with select(2)) it is used as a prefix character
518 with rl_execute_next. WATCH OUT FOR THIS! This is intended
519 to allow the arrow keys to be used like ^F and ^B are used
520 to terminate the search and execute the movement command.
521 XXX - since _rl_input_available depends on the application-
522 settable keyboard timeout value, this could alternatively
523 use _rl_input_queued(100000) */
524 if (cxt
->lastc
== ESC
&& (_rl_pushed_input_available () || _rl_input_available ()))
525 rl_execute_next (ESC
);
529 #if defined (HANDLE_MULTIBYTE)
530 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
532 if (cxt
->lastc
>= 0 && (cxt
->mb
[0] && cxt
->mb
[1] == '\0') && ENDSRCH_CHAR (cxt
->lastc
))
534 /* This sets rl_pending_input to LASTC; it will be picked up the next
535 time rl_read_key is called. */
536 rl_execute_next (cxt
->lastc
);
542 if (cxt
->lastc
>= 0 && ENDSRCH_CHAR (cxt
->lastc
))
544 /* This sets rl_pending_input to LASTC; it will be picked up the next
545 time rl_read_key is called. */
546 rl_execute_next (cxt
->lastc
);
550 _rl_init_executing_keyseq ();
553 /* Now dispatch on the character. `Opcodes' affect the search string or
554 state. Other characters are added to the string. */
559 if (cxt
->search_string_index
== 0)
561 if (last_isearch_string
)
563 cxt
->search_string_size
= 64 + last_isearch_string_len
;
564 cxt
->search_string
= (char *)xrealloc (cxt
->search_string
, cxt
->search_string_size
);
565 strcpy (cxt
->search_string
, last_isearch_string
);
566 cxt
->search_string_index
= last_isearch_string_len
;
567 rl_display_search (cxt
->search_string
, cxt
->sflags
, -1);
570 /* XXX - restore keymap here? */
573 else if ((cxt
->sflags
& SF_REVERSE
) && cxt
->sline_index
>= 0)
575 else if (cxt
->sline_index
!= cxt
->sline_len
)
581 /* switch directions */
583 cxt
->direction
= -cxt
->direction
;
584 if (cxt
->direction
< 0)
585 cxt
->sflags
|= SF_REVERSE
;
587 cxt
->sflags
&= ~SF_REVERSE
;
590 /* delete character from search string. */
591 case -3: /* C-H, DEL */
592 /* This is tricky. To do this right, we need to keep a
593 stack of search positions for the current search, with
594 sentinels marking the beginning and end. But this will
595 do until we have a real isearch-undo. */
596 if (cxt
->search_string_index
== 0)
598 else if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
599 cxt
->search_string
[--cxt
->search_string_index
] = '\0';
602 wstart
= _rl_find_prev_mbchar (cxt
->search_string
, cxt
->search_string_index
, MB_FIND_NONZERO
);
604 cxt
->search_string
[cxt
->search_string_index
= wstart
] = '\0';
606 cxt
->search_string
[cxt
->search_string_index
= 0] = '\0';
609 if (cxt
->search_string_index
== 0)
614 case -4: /* C-G, abort */
615 rl_replace_line (cxt
->lines
[cxt
->save_line
], 0);
616 rl_point
= cxt
->save_point
;
617 rl_mark
= cxt
->save_mark
;
618 rl_deactivate_mark ();
622 _rl_fix_point (1); /* in case save_line and save_point are out of sync */
626 /* skip over portion of line we already matched and yank word */
627 wstart
= rl_point
+ cxt
->search_string_index
;
628 if (wstart
>= rl_end
)
634 /* if not in a word, move to one. */
635 cval
= _rl_char_value (rl_line_buffer
, wstart
);
636 if (_rl_walphabetic (cval
) == 0)
641 n
= MB_NEXTCHAR (rl_line_buffer
, wstart
, 1, MB_FIND_NONZERO
);;
644 cval
= _rl_char_value (rl_line_buffer
, n
);
645 if (_rl_walphabetic (cval
) == 0)
647 n
= MB_NEXTCHAR (rl_line_buffer
, n
, 1, MB_FIND_NONZERO
);;
649 wlen
= n
- wstart
+ 1;
650 if (cxt
->search_string_index
+ wlen
+ 1 >= cxt
->search_string_size
)
652 cxt
->search_string_size
+= wlen
+ 1;
653 cxt
->search_string
= (char *)xrealloc (cxt
->search_string
, cxt
->search_string_size
);
655 for (; wstart
< n
; wstart
++)
656 cxt
->search_string
[cxt
->search_string_index
++] = rl_line_buffer
[wstart
];
657 cxt
->search_string
[cxt
->search_string_index
] = '\0';
661 /* skip over portion of line we already matched and yank rest */
662 wstart
= rl_point
+ cxt
->search_string_index
;
663 if (wstart
>= rl_end
)
668 n
= rl_end
- wstart
+ 1;
669 if (cxt
->search_string_index
+ n
+ 1 >= cxt
->search_string_size
)
671 cxt
->search_string_size
+= n
+ 1;
672 cxt
->search_string
= (char *)xrealloc (cxt
->search_string
, cxt
->search_string_size
);
674 for (n
= wstart
; n
< rl_end
; n
++)
675 cxt
->search_string
[cxt
->search_string_index
++] = rl_line_buffer
[n
];
676 cxt
->search_string
[cxt
->search_string_index
] = '\0';
679 case -7: /* bracketed paste */
680 paste
= _rl_bracketed_text (&pastelen
);
681 if (paste
== 0 || *paste
== 0)
686 if (_rl_enable_active_region
)
688 if (cxt
->search_string_index
+ pastelen
+ 1 >= cxt
->search_string_size
)
690 cxt
->search_string_size
+= pastelen
+ 2;
691 cxt
->search_string
= (char *)xrealloc (cxt
->search_string
, cxt
->search_string_size
);
693 strcpy (cxt
->search_string
+ cxt
->search_string_index
, paste
);
694 cxt
->search_string_index
+= pastelen
;
698 /* Add character to search string and continue search. */
700 #if defined (HANDLE_MULTIBYTE)
701 wlen
= (cxt
->mb
[0] == 0 || cxt
->mb
[1] == 0) ? 1 : RL_STRLEN (cxt
->mb
);
705 if (cxt
->search_string_index
+ wlen
+ 1 >= cxt
->search_string_size
)
707 cxt
->search_string_size
+= 128; /* 128 much greater than MB_CUR_MAX */
708 cxt
->search_string
= (char *)xrealloc (cxt
->search_string
, cxt
->search_string_size
);
710 #if defined (HANDLE_MULTIBYTE)
711 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
715 if (cxt
->mb
[0] == 0 || cxt
->mb
[1] == 0)
716 cxt
->search_string
[cxt
->search_string_index
++] = cxt
->mb
[0];
718 for (j
= 0; j
< wlen
; )
719 cxt
->search_string
[cxt
->search_string_index
++] = cxt
->mb
[j
++];
723 cxt
->search_string
[cxt
->search_string_index
++] = cxt
->lastc
; /* XXX - was c instead of lastc */
724 cxt
->search_string
[cxt
->search_string_index
] = '\0';
728 for (cxt
->sflags
&= ~(SF_FOUND
|SF_FAILED
);; )
730 if (cxt
->search_string_index
== 0)
732 cxt
->sflags
|= SF_FAILED
;
736 limit
= cxt
->sline_len
- cxt
->search_string_index
+ 1;
738 /* Search the current line. */
739 while ((cxt
->sflags
& SF_REVERSE
) ? (cxt
->sline_index
>= 0) : (cxt
->sline_index
< limit
))
741 if (STREQN (cxt
->search_string
, cxt
->sline
+ cxt
->sline_index
, cxt
->search_string_index
))
743 cxt
->sflags
|= SF_FOUND
;
747 cxt
->sline_index
+= cxt
->direction
;
749 if (cxt
->sline_index
< 0)
751 cxt
->sline_index
= 0;
755 if (cxt
->sflags
& SF_FOUND
)
758 /* Move to the next line, but skip new copies of the line
759 we just found and lines shorter than the string we're
763 /* Move to the next line. */
764 cxt
->history_pos
+= cxt
->direction
;
766 /* At limit for direction? */
767 if ((cxt
->sflags
& SF_REVERSE
) ? (cxt
->history_pos
< 0) : (cxt
->history_pos
== cxt
->hlen
))
769 cxt
->sflags
|= SF_FAILED
;
773 /* We will need these later. */
774 cxt
->sline
= cxt
->lines
[cxt
->history_pos
];
775 cxt
->sline_len
= strlen (cxt
->sline
);
777 while ((cxt
->prev_line_found
&& STREQ (cxt
->prev_line_found
, cxt
->lines
[cxt
->history_pos
])) ||
778 (cxt
->search_string_index
> cxt
->sline_len
));
780 if (cxt
->sflags
& SF_FAILED
)
782 /* XXX - reset sline_index if < 0 */
783 if (cxt
->sline_index
< 0)
784 cxt
->sline_index
= 0;
788 /* Now set up the line for searching... */
789 cxt
->sline_index
= (cxt
->sflags
& SF_REVERSE
) ? cxt
->sline_len
- cxt
->search_string_index
: 0;
792 /* reset the keymaps for the next time through the loop */
793 cxt
->keymap
= cxt
->okeymap
= _rl_keymap
;
795 if (cxt
->sflags
& SF_FAILED
)
797 /* We cannot find the search string. Ding the bell. */
799 cxt
->history_pos
= cxt
->last_found_line
;
800 rl_deactivate_mark ();
801 rl_display_search (cxt
->search_string
, cxt
->sflags
, (cxt
->history_pos
== cxt
->save_line
) ? -1 : cxt
->history_pos
);
805 /* We have found the search string. Just display it. But don't
806 actually move there in the history list until the user accepts
808 if (cxt
->sflags
& SF_FOUND
)
810 cxt
->prev_line_found
= cxt
->lines
[cxt
->history_pos
];
811 rl_replace_line (cxt
->lines
[cxt
->history_pos
], 0);
812 if (_rl_enable_active_region
)
814 rl_point
= cxt
->sline_index
;
815 if (rl_mark_active_p () && cxt
->search_string_index
> 0)
816 rl_mark
= rl_point
+ cxt
->search_string_index
;
817 cxt
->last_found_line
= cxt
->history_pos
;
818 rl_display_search (cxt
->search_string
, cxt
->sflags
, (cxt
->history_pos
== cxt
->save_line
) ? -1 : cxt
->history_pos
);
825 _rl_isearch_cleanup (_rl_search_cxt
*cxt
, int r
)
828 _rl_isearch_fini (cxt
);
829 _rl_scxt_dispose (cxt
, 0);
832 RL_UNSETSTATE(RL_STATE_ISEARCH
);
837 /* Search through the history looking for an interactively typed string.
838 This is analogous to i-search. We start the search in the current line.
839 DIRECTION is which direction to search; >= 0 means forward, < 0 means
842 rl_search_history (int direction
, int invoking_key
)
844 _rl_search_cxt
*cxt
; /* local for now, but saved globally */
847 RL_SETSTATE(RL_STATE_ISEARCH
);
848 cxt
= _rl_isearch_init (direction
);
850 rl_display_search (cxt
->search_string
, cxt
->sflags
, -1);
852 /* If we are using the callback interface, all we do is set up here and
853 return. The key is that we leave RL_STATE_ISEARCH set. */
854 if (RL_ISSTATE (RL_STATE_CALLBACK
))
860 c
= _rl_search_getchar (cxt
);
861 /* We might want to handle EOF here (c == 0) */
862 r
= _rl_isearch_dispatch (cxt
, cxt
->lastc
);
867 /* The searching is over. The user may have found the string that she
868 was looking for, or else she may have exited a failing search. If
869 LINE_INDEX is -1, then that shows that the string searched for was
870 not found. We use this to determine where to place rl_point. */
871 return (_rl_isearch_cleanup (cxt
, r
));
874 #if defined (READLINE_CALLBACKS)
875 /* Called from the callback functions when we are ready to read a key. The
876 callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
877 If _rl_isearch_dispatch finishes searching, this function is responsible
878 for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
880 _rl_isearch_callback (_rl_search_cxt
*cxt
)
884 c
= _rl_search_getchar (cxt
);
885 /* We might want to handle EOF here */
886 r
= _rl_isearch_dispatch (cxt
, cxt
->lastc
);
888 return (r
<= 0) ? _rl_isearch_cleanup (cxt
, r
) : 0;