Import readline 7.0 (patch 5)
[deliverable/binutils-gdb.git] / readline / isearch.c
CommitLineData
cc88a640
JK
1/* isearch.c - incremental searching */
2
d60d9f65
SS
3/* **************************************************************** */
4/* */
5/* I-Search and Searching */
6/* */
7/* **************************************************************** */
8
775e241e 9/* Copyright (C) 1987-2015 Free Software Foundation, Inc.
d60d9f65 10
cc88a640
JK
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.
d60d9f65 13
cc88a640 14 Readline is free software: you can redistribute it and/or modify
d60d9f65 15 it under the terms of the GNU General Public License as published by
cc88a640
JK
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
d60d9f65
SS
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"
9255ee31
EZ
49#include "rlmbutil.h"
50
d60d9f65
SS
51#include "readline.h"
52#include "history.h"
53
1b17e766
EZ
54#include "rlprivate.h"
55#include "xmalloc.h"
56
c862e87b 57/* Variables exported to other files in the readline library. */
9255ee31 58char *_rl_isearch_terminators = (char *)NULL;
c862e87b 59
5bdf8622
DJ
60_rl_search_cxt *_rl_iscxt = 0;
61
d60d9f65 62/* Variables imported from other files in the readline library. */
9255ee31 63extern HIST_ENTRY *_rl_saved_line_for_history;
d60d9f65 64
9255ee31 65static int rl_search_history PARAMS((int, int));
d60d9f65 66
5bdf8622
DJ
67static _rl_search_cxt *_rl_isearch_init PARAMS((int));
68static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
5bdf8622 69
d60d9f65 70/* Last line found by the current incremental search, so we don't `find'
cc88a640
JK
71 identical lines many times in a row. Now part of isearch context. */
72/* static char *prev_line_found; */
d60d9f65 73
9255ee31
EZ
74/* Last search string and its length. */
75static char *last_isearch_string;
76static int last_isearch_string_len;
77
cc88a640 78static char * const default_isearch_terminators = "\033\012";
9255ee31 79
5bdf8622
DJ
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
cc88a640
JK
106 cxt->keymap = _rl_keymap;
107 cxt->okeymap = _rl_keymap;
108
5bdf8622
DJ
109 cxt->history_pos = 0;
110 cxt->direction = 0;
111
775e241e 112 cxt->prevc = cxt->lastc = 0;
5bdf8622
DJ
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
122void
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
cc88a640 131 xfree (cxt);
5bdf8622
DJ
132}
133
d60d9f65
SS
134/* Search backwards through the history looking for a string which is typed
135 interactively. Start with the current line. */
136int
137rl_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. */
145int
146rl_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,
5bdf8622 154 DIRECTION is zero for forward, or non-zero for reverse,
d60d9f65
SS
155 WHERE is the history list number of the current line. If it is
156 -1, then this line is the starting one. */
157static void
775e241e 158rl_display_search (search_string, flags, where)
d60d9f65 159 char *search_string;
775e241e 160 int flags, where;
d60d9f65
SS
161{
162 char *message;
163 int msglen, searchlen;
164
165 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
166
775e241e 167 message = (char *)xmalloc (searchlen + 64);
d60d9f65
SS
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
775e241e
TT
180 if (flags & SF_FAILED)
181 {
182 strcpy (message + msglen, "failed ");
183 msglen += 7;
184 }
185
186 if (flags & SF_REVERSE)
d60d9f65
SS
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
9255ee31 203 rl_message ("%s", message);
cc88a640 204 xfree (message);
d60d9f65
SS
205 (*rl_redisplay_function) ();
206}
207
5bdf8622
DJ
208static _rl_search_cxt *
209_rl_isearch_init (direction)
210 int direction;
d60d9f65 211{
5bdf8622 212 _rl_search_cxt *cxt;
d60d9f65 213 register int i;
5bdf8622 214 HIST_ENTRY **hlist;
d60d9f65 215
5bdf8622
DJ
216 cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
217 if (direction < 0)
218 cxt->sflags |= SF_REVERSE;
c862e87b 219
5bdf8622 220 cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
9255ee31 221 : default_isearch_terminators;
c862e87b 222
775e241e 223 /* Create an array of pointers to the lines that we want to search. */
5bdf8622 224 hlist = history_list ();
9255ee31 225 rl_maybe_replace_line ();
d60d9f65
SS
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. */
5bdf8622
DJ
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;
d60d9f65 235
9255ee31 236 if (_rl_saved_line_for_history)
5bdf8622 237 cxt->lines[i] = _rl_saved_line_for_history->line;
d60d9f65
SS
238 else
239 {
240 /* Keep track of this so we can free it. */
5bdf8622
DJ
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;
d60d9f65
SS
244 }
245
5bdf8622 246 cxt->hlen++;
d60d9f65
SS
247
248 /* The line where we start the search. */
5bdf8622 249 cxt->history_pos = cxt->save_line;
d60d9f65 250
c862e87b 251 rl_save_prompt ();
d60d9f65
SS
252
253 /* Initialize search parameters. */
5bdf8622
DJ
254 cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
255 cxt->search_string[cxt->search_string_index = 0] = '\0';
d60d9f65
SS
256
257 /* Normalize DIRECTION into 1 or -1. */
5bdf8622 258 cxt->direction = (direction >= 0) ? 1 : -1;
d60d9f65 259
5bdf8622
DJ
260 cxt->sline = rl_line_buffer;
261 cxt->sline_len = strlen (cxt->sline);
262 cxt->sline_index = rl_point;
d60d9f65 263
5bdf8622 264 _rl_iscxt = cxt; /* save globally */
d60d9f65 265
5bdf8622
DJ
266 return cxt;
267}
268
269static 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)
d60d9f65 293 {
5bdf8622
DJ
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 }
d60d9f65 300
5bdf8622
DJ
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
308int
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);
d60d9f65 318
9255ee31 319#if defined (HANDLE_MULTIBYTE)
775e241e
TT
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] */
5bdf8622
DJ
322 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
323 c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
9255ee31
EZ
324#endif
325
775e241e 326 RL_CHECK_SIGNALS ();
5bdf8622
DJ
327 return c;
328}
d60d9f65 329
775e241e
TT
330#define ENDSRCH_CHAR(c) \
331 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
332
5bdf8622
DJ
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. */
336int
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;
cc88a640
JK
345
346 if (c < 0)
5bdf8622 347 {
cc88a640
JK
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 {
775e241e
TT
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;
cc88a640
JK
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
775e241e
TT
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
cc88a640
JK
390 return 1;
391 }
392
775e241e
TT
393add_character:
394
cc88a640
JK
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;
5bdf8622
DJ
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;
cc88a640 406 else if (c == CTRL ('G') || f == rl_abort)
5bdf8622 407 cxt->lastc = -4;
cc88a640 408 else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
5bdf8622 409 cxt->lastc = -5;
cc88a640 410 else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
5bdf8622
DJ
411 cxt->lastc = -6;
412 }
413
cc88a640
JK
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;
775e241e
TT
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 }
cc88a640
JK
468 }
469
5bdf8622
DJ
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). */
cc88a640 474 if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
5bdf8622
DJ
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) */
775e241e 485 if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
5bdf8622
DJ
486 rl_execute_next (ESC);
487 return (0);
488 }
d60d9f65 489
9255ee31 490#if defined (HANDLE_MULTIBYTE)
5bdf8622
DJ
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 {
cc88a640 495 /* This sets rl_pending_input to LASTC; it will be picked up the next
5bdf8622
DJ
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)
9255ee31 518 {
5bdf8622 519 if (last_isearch_string)
9255ee31 520 {
5bdf8622
DJ
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;
775e241e 525 rl_display_search (cxt->search_string, cxt->sflags, -1);
9255ee31
EZ
526 break;
527 }
5bdf8622 528 return (1);
9255ee31 529 }
5bdf8622
DJ
530 else if (cxt->sflags & SF_REVERSE)
531 cxt->sline_index--;
532 else if (cxt->sline_index != cxt->sline_len)
533 cxt->sline_index++;
9255ee31 534 else
5bdf8622
DJ
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 ();
775e241e 555 else if (MB_CUR_MAX == 1 || rl_byte_oriented)
5836a818 556 cxt->search_string[--cxt->search_string_index] = '\0';
775e241e
TT
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 cxt->search_string[cxt->search_string_index = 0] = '\0';
564 }
565
566 if (cxt->search_string_index == 0)
567 rl_ding ();
568
5bdf8622
DJ
569 break;
570
571 case -4: /* C-G, abort */
572 rl_replace_line (cxt->lines[cxt->save_line], 0);
573 rl_point = cxt->save_point;
574 rl_mark = cxt->save_mark;
575 rl_restore_prompt();
576 rl_clear_message ();
577
578 return -1;
579
580 case -5: /* C-W */
581 /* skip over portion of line we already matched and yank word */
582 wstart = rl_point + cxt->search_string_index;
583 if (wstart >= rl_end)
d60d9f65 584 {
5bdf8622 585 rl_ding ();
d60d9f65
SS
586 break;
587 }
588
5bdf8622
DJ
589 /* if not in a word, move to one. */
590 cval = _rl_char_value (rl_line_buffer, wstart);
591 if (_rl_walphabetic (cval) == 0)
d60d9f65 592 {
5bdf8622 593 rl_ding ();
d60d9f65 594 break;
5bdf8622
DJ
595 }
596 n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
597 while (n < rl_end)
598 {
599 cval = _rl_char_value (rl_line_buffer, n);
600 if (_rl_walphabetic (cval) == 0)
601 break;
602 n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
603 }
604 wlen = n - wstart + 1;
605 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
606 {
607 cxt->search_string_size += wlen + 1;
608 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
609 }
610 for (; wstart < n; wstart++)
611 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
612 cxt->search_string[cxt->search_string_index] = '\0';
613 break;
614
615 case -6: /* C-Y */
616 /* skip over portion of line we already matched and yank rest */
617 wstart = rl_point + cxt->search_string_index;
618 if (wstart >= rl_end)
619 {
620 rl_ding ();
d60d9f65 621 break;
5bdf8622
DJ
622 }
623 n = rl_end - wstart + 1;
624 if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
625 {
626 cxt->search_string_size += n + 1;
627 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
628 }
629 for (n = wstart; n < rl_end; n++)
630 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
631 cxt->search_string[cxt->search_string_index] = '\0';
632 break;
633
634 /* Add character to search string and continue search. */
635 default:
636 if (cxt->search_string_index + 2 >= cxt->search_string_size)
637 {
638 cxt->search_string_size += 128;
639 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
640 }
641#if defined (HANDLE_MULTIBYTE)
642 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
643 {
644 int j, l;
775e241e
TT
645
646 if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
647 cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
648 else
649 for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
650 cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
5bdf8622
DJ
651 }
652 else
653#endif
775e241e 654 cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
5bdf8622
DJ
655 cxt->search_string[cxt->search_string_index] = '\0';
656 break;
657 }
d60d9f65 658
5bdf8622
DJ
659 for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
660 {
775e241e
TT
661 if (cxt->search_string_index == 0)
662 {
663 cxt->sflags |= SF_FAILED;
664 break;
665 }
666
5bdf8622 667 limit = cxt->sline_len - cxt->search_string_index + 1;
9255ee31 668
5bdf8622
DJ
669 /* Search the current line. */
670 while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
671 {
672 if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
9255ee31 673 {
5bdf8622 674 cxt->sflags |= SF_FOUND;
9255ee31
EZ
675 break;
676 }
5bdf8622
DJ
677 else
678 cxt->sline_index += cxt->direction;
679 }
680 if (cxt->sflags & SF_FOUND)
681 break;
9255ee31 682
5bdf8622
DJ
683 /* Move to the next line, but skip new copies of the line
684 we just found and lines shorter than the string we're
685 searching for. */
686 do
687 {
688 /* Move to the next line. */
689 cxt->history_pos += cxt->direction;
9255ee31 690
5bdf8622
DJ
691 /* At limit for direction? */
692 if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
9255ee31 693 {
5bdf8622 694 cxt->sflags |= SF_FAILED;
9255ee31
EZ
695 break;
696 }
d60d9f65 697
5bdf8622
DJ
698 /* We will need these later. */
699 cxt->sline = cxt->lines[cxt->history_pos];
700 cxt->sline_len = strlen (cxt->sline);
d60d9f65 701 }
5bdf8622
DJ
702 while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
703 (cxt->search_string_index > cxt->sline_len));
d60d9f65 704
5bdf8622
DJ
705 if (cxt->sflags & SF_FAILED)
706 break;
d60d9f65 707
5bdf8622
DJ
708 /* Now set up the line for searching... */
709 cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
710 }
d60d9f65 711
5bdf8622
DJ
712 if (cxt->sflags & SF_FAILED)
713 {
714 /* We cannot find the search string. Ding the bell. */
715 rl_ding ();
716 cxt->history_pos = cxt->last_found_line;
775e241e 717 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
5bdf8622
DJ
718 return 1;
719 }
d60d9f65 720
5bdf8622
DJ
721 /* We have found the search string. Just display it. But don't
722 actually move there in the history list until the user accepts
723 the location. */
724 if (cxt->sflags & SF_FOUND)
725 {
726 cxt->prev_line_found = cxt->lines[cxt->history_pos];
727 rl_replace_line (cxt->lines[cxt->history_pos], 0);
728 rl_point = cxt->sline_index;
729 cxt->last_found_line = cxt->history_pos;
775e241e 730 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
5bdf8622 731 }
d60d9f65 732
5bdf8622
DJ
733 return 1;
734}
d60d9f65 735
775e241e 736int
5bdf8622
DJ
737_rl_isearch_cleanup (cxt, r)
738 _rl_search_cxt *cxt;
739 int r;
740{
741 if (r >= 0)
742 _rl_isearch_fini (cxt);
743 _rl_scxt_dispose (cxt, 0);
744 _rl_iscxt = 0;
d60d9f65 745
5bdf8622 746 RL_UNSETSTATE(RL_STATE_ISEARCH);
d60d9f65 747
5bdf8622
DJ
748 return (r != 0);
749}
d60d9f65 750
5bdf8622
DJ
751/* Search through the history looking for an interactively typed string.
752 This is analogous to i-search. We start the search in the current line.
753 DIRECTION is which direction to search; >= 0 means forward, < 0 means
754 backwards. */
755static int
756rl_search_history (direction, invoking_key)
757 int direction, invoking_key;
758{
759 _rl_search_cxt *cxt; /* local for now, but saved globally */
760 int c, r;
d60d9f65 761
5bdf8622
DJ
762 RL_SETSTATE(RL_STATE_ISEARCH);
763 cxt = _rl_isearch_init (direction);
d60d9f65 764
775e241e 765 rl_display_search (cxt->search_string, cxt->sflags, -1);
d60d9f65 766
5bdf8622
DJ
767 /* If we are using the callback interface, all we do is set up here and
768 return. The key is that we leave RL_STATE_ISEARCH set. */
769 if (RL_ISSTATE (RL_STATE_CALLBACK))
770 return (0);
d60d9f65 771
5bdf8622
DJ
772 r = -1;
773 for (;;)
9255ee31 774 {
5bdf8622
DJ
775 c = _rl_search_getchar (cxt);
776 /* We might want to handle EOF here (c == 0) */
777 r = _rl_isearch_dispatch (cxt, cxt->lastc);
778 if (r <= 0)
779 break;
9255ee31
EZ
780 }
781
5bdf8622
DJ
782 /* The searching is over. The user may have found the string that she
783 was looking for, or else she may have exited a failing search. If
784 LINE_INDEX is -1, then that shows that the string searched for was
785 not found. We use this to determine where to place rl_point. */
786 return (_rl_isearch_cleanup (cxt, r));
787}
d60d9f65 788
5bdf8622
DJ
789#if defined (READLINE_CALLBACKS)
790/* Called from the callback functions when we are ready to read a key. The
791 callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
792 If _rl_isearch_dispatch finishes searching, this function is responsible
793 for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
794int
795_rl_isearch_callback (cxt)
796 _rl_search_cxt *cxt;
797{
798 int c, r;
d60d9f65 799
5bdf8622
DJ
800 c = _rl_search_getchar (cxt);
801 /* We might want to handle EOF here */
802 r = _rl_isearch_dispatch (cxt, cxt->lastc);
9255ee31 803
5bdf8622 804 return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
d60d9f65 805}
5bdf8622 806#endif
This page took 0.893958 seconds and 4 git commands to generate.