sim: mcore: invert sim_cpu storage
[binutils-gdb.git] / readline / readline / isearch.c
1 /* isearch.c - incremental searching */
2
3 /* **************************************************************** */
4 /* */
5 /* I-Search and Searching */
6 /* */
7 /* **************************************************************** */
8
9 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
10
11 This file is part of the GNU Readline Library (Readline), a library
12 for reading lines of text with interactive input and history editing.
13
14 Readline is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 Readline is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with Readline. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #define READLINE_LIBRARY
29
30 #if defined (HAVE_CONFIG_H)
31 # include <config.h>
32 #endif
33
34 #include <sys/types.h>
35
36 #include <stdio.h>
37
38 #if defined (HAVE_UNISTD_H)
39 # include <unistd.h>
40 #endif
41
42 #if defined (HAVE_STDLIB_H)
43 # include <stdlib.h>
44 #else
45 # include "ansi_stdlib.h"
46 #endif
47
48 #include "rldefs.h"
49 #include "rlmbutil.h"
50
51 #include "readline.h"
52 #include "history.h"
53
54 #include "rlprivate.h"
55 #include "xmalloc.h"
56
57 /* Variables exported to other files in the readline library. */
58 char *_rl_isearch_terminators = (char *)NULL;
59
60 _rl_search_cxt *_rl_iscxt = 0;
61
62 /* Variables imported from other files in the readline library. */
63 extern HIST_ENTRY *_rl_saved_line_for_history;
64
65 static int rl_search_history PARAMS((int, int));
66
67 static _rl_search_cxt *_rl_isearch_init PARAMS((int));
68 static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
69
70 /* Last line found by the current incremental search, so we don't `find'
71 identical lines many times in a row. Now part of isearch context. */
72 /* static char *prev_line_found; */
73
74 /* Last search string and its length. */
75 static char *last_isearch_string;
76 static int last_isearch_string_len;
77
78 static char * const default_isearch_terminators = "\033\012";
79
80 _rl_search_cxt *
81 _rl_scxt_alloc (int type, int flags)
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
105 cxt->keymap = _rl_keymap;
106 cxt->okeymap = _rl_keymap;
107
108 cxt->history_pos = 0;
109 cxt->direction = 0;
110
111 cxt->prevc = cxt->lastc = 0;
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
121 void
122 _rl_scxt_dispose (_rl_search_cxt *cxt, int flags)
123 {
124 FREE (cxt->search_string);
125 FREE (cxt->allocated_line);
126 FREE (cxt->lines);
127
128 xfree (cxt);
129 }
130
131 /* Search backwards through the history looking for a string which is typed
132 interactively. Start with the current line. */
133 int
134 rl_reverse_search_history (int sign, int key)
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. */
141 int
142 rl_forward_search_history (int sign, int key)
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,
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. */
152 static void
153 rl_display_search (char *search_string, int flags, int where)
154 {
155 char *message;
156 int msglen, searchlen;
157
158 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
159
160 message = (char *)xmalloc (searchlen + 64);
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
173 if (flags & SF_FAILED)
174 {
175 strcpy (message + msglen, "failed ");
176 msglen += 7;
177 }
178
179 if (flags & SF_REVERSE)
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 && *search_string)
189 {
190 strcpy (message + msglen, search_string);
191 msglen += searchlen;
192 }
193 else
194 _rl_optimize_redisplay ();
195
196 strcpy (message + msglen, "': ");
197
198 rl_message ("%s", message);
199 xfree (message);
200 (*rl_redisplay_function) ();
201 }
202
203 static _rl_search_cxt *
204 _rl_isearch_init (int direction)
205 {
206 _rl_search_cxt *cxt;
207 register int i;
208 HIST_ENTRY **hlist;
209
210 cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
211 if (direction < 0)
212 cxt->sflags |= SF_REVERSE;
213
214 cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
215 : default_isearch_terminators;
216
217 /* Create an array of pointers to the lines that we want to search. */
218 hlist = history_list ();
219 rl_maybe_replace_line ();
220 i = 0;
221 if (hlist)
222 for (i = 0; hlist[i]; i++);
223
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;
229
230 if (_rl_saved_line_for_history)
231 cxt->lines[i] = _rl_saved_line_for_history->line;
232 else
233 {
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;
238 }
239
240 cxt->hlen++;
241
242 /* The line where we start the search. */
243 cxt->history_pos = cxt->save_line;
244
245 rl_save_prompt ();
246
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';
250
251 /* Normalize DIRECTION into 1 or -1. */
252 cxt->direction = (direction >= 0) ? 1 : -1;
253
254 cxt->sline = rl_line_buffer;
255 cxt->sline_len = strlen (cxt->sline);
256 cxt->sline_index = rl_point;
257
258 _rl_iscxt = cxt; /* save globally */
259
260 /* experimental right now */
261 _rl_init_executing_keyseq ();
262
263 return cxt;
264 }
265
266 static void
267 _rl_isearch_fini (_rl_search_cxt *cxt)
268 {
269 /* First put back the original state. */
270 rl_replace_line (cxt->lines[cxt->save_line], 0);
271
272 rl_restore_prompt ();
273
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;
279
280 if (cxt->last_found_line < cxt->save_line)
281 rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
282 else
283 rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
284
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)
289 {
290 if (cxt->last_found_line == cxt->save_line)
291 cxt->sline_index = cxt->save_point;
292 else
293 cxt->sline_index = strlen (rl_line_buffer);
294 rl_mark = cxt->save_mark;
295 rl_deactivate_mark ();
296 }
297
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. */
303 _rl_fix_point (0);
304 rl_deactivate_mark ();
305
306 /* _rl_optimize_redisplay (); */
307 rl_clear_message ();
308 }
309
310 /* XXX - we could use _rl_bracketed_read_mbstring () here. */
311 int
312 _rl_search_getchar (_rl_search_cxt *cxt)
313 {
314 int c;
315
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);
320
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);
326 #endif
327
328 RL_CHECK_SIGNALS ();
329 return c;
330 }
331
332 #define ENDSRCH_CHAR(c) \
333 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
334
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. */
338 int
339 _rl_isearch_dispatch (_rl_search_cxt *cxt, int c)
340 {
341 int n, wstart, wlen, limit, cval, incr;
342 char *paste;
343 size_t pastelen;
344 int j;
345 rl_command_func_t *f;
346
347 f = (rl_command_func_t *)NULL;
348
349 if (c < 0)
350 {
351 cxt->sflags |= SF_FAILED;
352 cxt->history_pos = cxt->last_found_line;
353 return -1;
354 }
355
356 _rl_add_executing_keyseq (c);
357
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))
361 {
362 j = _rl_read_bracketed_paste_prefix (c);
363 if (j == 1)
364 {
365 cxt->lastc = -7; /* bracketed paste, see below */
366 goto opcode_dispatch;
367 }
368 else if (_rl_pushed_input_available ()) /* eat extra char we pushed back */
369 c = cxt->lastc = rl_read_key ();
370 else
371 c = cxt->lastc; /* last ditch */
372 }
373
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)
378 {
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)
389 goto add_character;
390
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. */
398 cxt->prevc = c;
399 #if defined (HANDLE_MULTIBYTE)
400 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
401 {
402 if (cxt->mb[1] == 0)
403 {
404 cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
405 cxt->pmb[1] = '\0';
406 }
407 else
408 memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
409 }
410 #endif
411 return 1;
412 }
413
414 add_character:
415
416 /* Translate the keys we do something with to opcodes. */
417 if (c >= 0 && cxt->keymap[c].type == ISFUNC)
418 {
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);
424 else
425 #endif
426 {
427 f = cxt->keymap[c].function;
428 if (f == rl_do_lowercase_version)
429 f = cxt->keymap[_rl_to_lower (c)].function;
430 }
431
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)
437 cxt->lastc = -3;
438 else if (c == CTRL ('G') || f == rl_abort)
439 cxt->lastc = -4;
440 else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
441 cxt->lastc = -5;
442 else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
443 cxt->lastc = -6;
444 else if (f == rl_bracketed_paste_begin)
445 cxt->lastc = -7;
446 }
447
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)
451 {
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))
461 {
462 rl_stuff_char (cxt->lastc);
463 rl_execute_next (cxt->prevc);
464 /* XXX - do we insert everything in cxt->pmb? */
465 return (0);
466 }
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))
474 {
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)
483 {
484 if (cxt->pmb[1] == 0)
485 {
486 cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
487 cxt->mb[1] = '\0';
488 }
489 else
490 memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
491 }
492 #endif
493 cxt->prevc = 0;
494 }
495 else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
496 {
497 _rl_term_executing_keyseq (); /* should this go in the caller? */
498
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;
504
505 return (0);
506 }
507 }
508
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))
514 {
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);
526 return (0);
527 }
528
529 #if defined (HANDLE_MULTIBYTE)
530 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
531 {
532 if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
533 {
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);
537 return (0);
538 }
539 }
540 else
541 #endif
542 if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
543 {
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);
547 return (0);
548 }
549
550 _rl_init_executing_keyseq ();
551
552 opcode_dispatch:
553 /* Now dispatch on the character. `Opcodes' affect the search string or
554 state. Other characters are added to the string. */
555 switch (cxt->lastc)
556 {
557 /* search again */
558 case -1:
559 if (cxt->search_string_index == 0)
560 {
561 if (last_isearch_string)
562 {
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);
568 break;
569 }
570 /* XXX - restore keymap here? */
571 return (1);
572 }
573 else if ((cxt->sflags & SF_REVERSE) && cxt->sline_index >= 0)
574 cxt->sline_index--;
575 else if (cxt->sline_index != cxt->sline_len)
576 cxt->sline_index++;
577 else
578 rl_ding ();
579 break;
580
581 /* switch directions */
582 case -2:
583 cxt->direction = -cxt->direction;
584 if (cxt->direction < 0)
585 cxt->sflags |= SF_REVERSE;
586 else
587 cxt->sflags &= ~SF_REVERSE;
588 break;
589
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)
597 rl_ding ();
598 else if (MB_CUR_MAX == 1 || rl_byte_oriented)
599 cxt->search_string[--cxt->search_string_index] = '\0';
600 else
601 {
602 wstart = _rl_find_prev_mbchar (cxt->search_string, cxt->search_string_index, MB_FIND_NONZERO);
603 if (wstart >= 0)
604 cxt->search_string[cxt->search_string_index = wstart] = '\0';
605 else
606 cxt->search_string[cxt->search_string_index = 0] = '\0';
607 }
608
609 if (cxt->search_string_index == 0)
610 rl_ding ();
611
612 break;
613
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 ();
619 rl_restore_prompt();
620 rl_clear_message ();
621
622 _rl_fix_point (1); /* in case save_line and save_point are out of sync */
623 return -1;
624
625 case -5: /* C-W */
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)
629 {
630 rl_ding ();
631 break;
632 }
633
634 /* if not in a word, move to one. */
635 cval = _rl_char_value (rl_line_buffer, wstart);
636 if (_rl_walphabetic (cval) == 0)
637 {
638 rl_ding ();
639 break;
640 }
641 n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
642 while (n < rl_end)
643 {
644 cval = _rl_char_value (rl_line_buffer, n);
645 if (_rl_walphabetic (cval) == 0)
646 break;
647 n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
648 }
649 wlen = n - wstart + 1;
650 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
651 {
652 cxt->search_string_size += wlen + 1;
653 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
654 }
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';
658 break;
659
660 case -6: /* C-Y */
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)
664 {
665 rl_ding ();
666 break;
667 }
668 n = rl_end - wstart + 1;
669 if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
670 {
671 cxt->search_string_size += n + 1;
672 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
673 }
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';
677 break;
678
679 case -7: /* bracketed paste */
680 paste = _rl_bracketed_text (&pastelen);
681 if (paste == 0 || *paste == 0)
682 {
683 free (paste);
684 break;
685 }
686 if (_rl_enable_active_region)
687 rl_activate_mark ();
688 if (cxt->search_string_index + pastelen + 1 >= cxt->search_string_size)
689 {
690 cxt->search_string_size += pastelen + 2;
691 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
692 }
693 strcpy (cxt->search_string + cxt->search_string_index, paste);
694 cxt->search_string_index += pastelen;
695 free (paste);
696 break;
697
698 /* Add character to search string and continue search. */
699 default:
700 #if defined (HANDLE_MULTIBYTE)
701 wlen = (cxt->mb[0] == 0 || cxt->mb[1] == 0) ? 1 : RL_STRLEN (cxt->mb);
702 #else
703 wlen = 1;
704 #endif
705 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
706 {
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);
709 }
710 #if defined (HANDLE_MULTIBYTE)
711 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
712 {
713 int j;
714
715 if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
716 cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
717 else
718 for (j = 0; j < wlen; )
719 cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
720 }
721 else
722 #endif
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';
725 break;
726 }
727
728 for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
729 {
730 if (cxt->search_string_index == 0)
731 {
732 cxt->sflags |= SF_FAILED;
733 break;
734 }
735
736 limit = cxt->sline_len - cxt->search_string_index + 1;
737
738 /* Search the current line. */
739 while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
740 {
741 if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
742 {
743 cxt->sflags |= SF_FOUND;
744 break;
745 }
746 else
747 cxt->sline_index += cxt->direction;
748
749 if (cxt->sline_index < 0)
750 {
751 cxt->sline_index = 0;
752 break;
753 }
754 }
755 if (cxt->sflags & SF_FOUND)
756 break;
757
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
760 searching for. */
761 do
762 {
763 /* Move to the next line. */
764 cxt->history_pos += cxt->direction;
765
766 /* At limit for direction? */
767 if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
768 {
769 cxt->sflags |= SF_FAILED;
770 break;
771 }
772
773 /* We will need these later. */
774 cxt->sline = cxt->lines[cxt->history_pos];
775 cxt->sline_len = strlen (cxt->sline);
776 }
777 while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
778 (cxt->search_string_index > cxt->sline_len));
779
780 if (cxt->sflags & SF_FAILED)
781 {
782 /* XXX - reset sline_index if < 0 */
783 if (cxt->sline_index < 0)
784 cxt->sline_index = 0;
785 break;
786 }
787
788 /* Now set up the line for searching... */
789 cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
790 }
791
792 /* reset the keymaps for the next time through the loop */
793 cxt->keymap = cxt->okeymap = _rl_keymap;
794
795 if (cxt->sflags & SF_FAILED)
796 {
797 /* We cannot find the search string. Ding the bell. */
798 rl_ding ();
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);
802 return 1;
803 }
804
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
807 the location. */
808 if (cxt->sflags & SF_FOUND)
809 {
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)
813 rl_activate_mark ();
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);
819 }
820
821 return 1;
822 }
823
824 int
825 _rl_isearch_cleanup (_rl_search_cxt *cxt, int r)
826 {
827 if (r >= 0)
828 _rl_isearch_fini (cxt);
829 _rl_scxt_dispose (cxt, 0);
830 _rl_iscxt = 0;
831
832 RL_UNSETSTATE(RL_STATE_ISEARCH);
833
834 return (r != 0);
835 }
836
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
840 backwards. */
841 static int
842 rl_search_history (int direction, int invoking_key)
843 {
844 _rl_search_cxt *cxt; /* local for now, but saved globally */
845 int c, r;
846
847 RL_SETSTATE(RL_STATE_ISEARCH);
848 cxt = _rl_isearch_init (direction);
849
850 rl_display_search (cxt->search_string, cxt->sflags, -1);
851
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))
855 return (0);
856
857 r = -1;
858 for (;;)
859 {
860 c = _rl_search_getchar (cxt);
861 /* We might want to handle EOF here (c == 0) */
862 r = _rl_isearch_dispatch (cxt, cxt->lastc);
863 if (r <= 0)
864 break;
865 }
866
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));
872 }
873
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. */
879 int
880 _rl_isearch_callback (_rl_search_cxt *cxt)
881 {
882 int c, r;
883
884 c = _rl_search_getchar (cxt);
885 /* We might want to handle EOF here */
886 r = _rl_isearch_dispatch (cxt, cxt->lastc);
887
888 return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
889 }
890 #endif