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