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