blob: 6f6a7a6583954940aee5e422a6e221c66c5d993a [file] [log] [blame]
Jari Aalto31859422009-01-12 13:36:28 +00001/* isearch.c - incremental searching */
2
Jari Aalto726f6381996-08-26 18:22:31 +00003/* **************************************************************** */
4/* */
5/* I-Search and Searching */
6/* */
7/* **************************************************************** */
8
Chet Rameyac50fba2014-02-26 09:36:43 -05009/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +000010
Jari Aalto31859422009-01-12 13:36:28 +000011 This file is part of the GNU Readline Library (Readline), a library
12 for reading lines of text with interactive input and history editing.
Jari Aalto726f6381996-08-26 18:22:31 +000013
Jari Aalto31859422009-01-12 13:36:28 +000014 Readline is free software: you can redistribute it and/or modify
Jari Aalto726f6381996-08-26 18:22:31 +000015 it under the terms of the GNU General Public License as published by
Jari Aalto31859422009-01-12 13:36:28 +000016 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
Jari Aalto726f6381996-08-26 18:22:31 +000018
Jari Aalto31859422009-01-12 13:36:28 +000019 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.
Jari Aalto726f6381996-08-26 18:22:31 +000023
Jari Aalto31859422009-01-12 13:36:28 +000024 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
Jari Aalto726f6381996-08-26 18:22:31 +000028#define READLINE_LIBRARY
29
Jari Aaltoccc6cda1996-12-23 17:02:34 +000030#if defined (HAVE_CONFIG_H)
31# include <config.h>
32#endif
33
Jari Aaltod166f041997-06-05 14:59:13 +000034#include <sys/types.h>
35
Jari Aalto726f6381996-08-26 18:22:31 +000036#include <stdio.h>
37
38#if defined (HAVE_UNISTD_H)
39# include <unistd.h>
40#endif
41
Jari Aaltod166f041997-06-05 14:59:13 +000042#if defined (HAVE_STDLIB_H)
43# include <stdlib.h>
44#else
45# include "ansi_stdlib.h"
46#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000047
48#include "rldefs.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000049#include "rlmbutil.h"
50
Jari Aalto726f6381996-08-26 18:22:31 +000051#include "readline.h"
52#include "history.h"
53
Jari Aaltobb706242000-03-17 21:46:59 +000054#include "rlprivate.h"
55#include "xmalloc.h"
56
Jari Aaltob72432f1999-02-19 17:11:39 +000057/* Variables exported to other files in the readline library. */
Jari Aaltof73dda02001-11-13 17:56:06 +000058char *_rl_isearch_terminators = (char *)NULL;
Jari Aaltob72432f1999-02-19 17:11:39 +000059
Jari Aalto95732b42005-12-07 14:08:12 +000060_rl_search_cxt *_rl_iscxt = 0;
61
Jari Aalto726f6381996-08-26 18:22:31 +000062/* Variables imported from other files in the readline library. */
Jari Aalto28ef6c32001-04-06 19:14:31 +000063extern HIST_ENTRY *_rl_saved_line_for_history;
Jari Aalto726f6381996-08-26 18:22:31 +000064
Jari Aaltof73dda02001-11-13 17:56:06 +000065static int rl_search_history PARAMS((int, int));
Jari Aalto726f6381996-08-26 18:22:31 +000066
Jari Aalto95732b42005-12-07 14:08:12 +000067static _rl_search_cxt *_rl_isearch_init PARAMS((int));
68static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
69static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
70
Jari Aalto726f6381996-08-26 18:22:31 +000071/* Last line found by the current incremental search, so we don't `find'
Jari Aalto06285672006-10-10 14:15:34 +000072 identical lines many times in a row. Now part of isearch context. */
73/* static char *prev_line_found; */
Jari Aalto726f6381996-08-26 18:22:31 +000074
Jari Aaltof73dda02001-11-13 17:56:06 +000075/* Last search string and its length. */
76static char *last_isearch_string;
77static int last_isearch_string_len;
78
Jari Aalto31859422009-01-12 13:36:28 +000079static char * const default_isearch_terminators = "\033\012";
Jari Aalto28ef6c32001-04-06 19:14:31 +000080
Jari Aalto95732b42005-12-07 14:08:12 +000081_rl_search_cxt *
82_rl_scxt_alloc (type, flags)
83 int type, flags;
84{
85 _rl_search_cxt *cxt;
86
87 cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
88
89 cxt->type = type;
90 cxt->sflags = flags;
91
92 cxt->search_string = 0;
93 cxt->search_string_size = cxt->search_string_index = 0;
94
95 cxt->lines = 0;
96 cxt->allocated_line = 0;
97 cxt->hlen = cxt->hindex = 0;
98
99 cxt->save_point = rl_point;
100 cxt->save_mark = rl_mark;
101 cxt->save_line = where_history ();
102 cxt->last_found_line = cxt->save_line;
103 cxt->prev_line_found = 0;
104
105 cxt->save_undo_list = 0;
106
Chet Ramey495aee42011-11-22 19:11:26 -0500107 cxt->keymap = _rl_keymap;
108 cxt->okeymap = _rl_keymap;
109
Jari Aalto95732b42005-12-07 14:08:12 +0000110 cxt->history_pos = 0;
111 cxt->direction = 0;
112
Chet Rameyac50fba2014-02-26 09:36:43 -0500113 cxt->prevc = cxt->lastc = 0;
Jari Aalto95732b42005-12-07 14:08:12 +0000114
115 cxt->sline = 0;
116 cxt->sline_len = cxt->sline_index = 0;
117
118 cxt->search_terminators = 0;
119
120 return cxt;
121}
122
123void
124_rl_scxt_dispose (cxt, flags)
125 _rl_search_cxt *cxt;
126 int flags;
127{
128 FREE (cxt->search_string);
129 FREE (cxt->allocated_line);
130 FREE (cxt->lines);
131
Jari Aalto31859422009-01-12 13:36:28 +0000132 xfree (cxt);
Jari Aalto95732b42005-12-07 14:08:12 +0000133}
134
Jari Aalto726f6381996-08-26 18:22:31 +0000135/* Search backwards through the history looking for a string which is typed
136 interactively. Start with the current line. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000137int
Jari Aalto726f6381996-08-26 18:22:31 +0000138rl_reverse_search_history (sign, key)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000139 int sign, key;
Jari Aalto726f6381996-08-26 18:22:31 +0000140{
141 return (rl_search_history (-sign, key));
142}
143
144/* Search forwards through the history looking for a string which is typed
145 interactively. Start with the current line. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000146int
Jari Aalto726f6381996-08-26 18:22:31 +0000147rl_forward_search_history (sign, key)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000148 int sign, key;
Jari Aalto726f6381996-08-26 18:22:31 +0000149{
150 return (rl_search_history (sign, key));
151}
152
153/* Display the current state of the search in the echo-area.
154 SEARCH_STRING contains the string that is being searched for,
Jari Aalto95732b42005-12-07 14:08:12 +0000155 DIRECTION is zero for forward, or non-zero for reverse,
Jari Aalto726f6381996-08-26 18:22:31 +0000156 WHERE is the history list number of the current line. If it is
157 -1, then this line is the starting one. */
158static void
Chet Rameyac50fba2014-02-26 09:36:43 -0500159rl_display_search (search_string, flags, where)
Jari Aalto726f6381996-08-26 18:22:31 +0000160 char *search_string;
Chet Rameyac50fba2014-02-26 09:36:43 -0500161 int flags, where;
Jari Aalto726f6381996-08-26 18:22:31 +0000162{
163 char *message;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000164 int msglen, searchlen;
Jari Aalto726f6381996-08-26 18:22:31 +0000165
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000166 searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
167
Chet Rameyac50fba2014-02-26 09:36:43 -0500168 message = (char *)xmalloc (searchlen + 64);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000169 msglen = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000170
171#if defined (NOTDEF)
172 if (where != -1)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000173 {
174 sprintf (message, "[%d]", where + history_base);
175 msglen = strlen (message);
176 }
Jari Aalto726f6381996-08-26 18:22:31 +0000177#endif /* NOTDEF */
178
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000179 message[msglen++] = '(';
Jari Aalto726f6381996-08-26 18:22:31 +0000180
Chet Rameyac50fba2014-02-26 09:36:43 -0500181 if (flags & SF_FAILED)
182 {
183 strcpy (message + msglen, "failed ");
184 msglen += 7;
185 }
186
187 if (flags & SF_REVERSE)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000188 {
189 strcpy (message + msglen, "reverse-");
190 msglen += 8;
191 }
Jari Aalto726f6381996-08-26 18:22:31 +0000192
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000193 strcpy (message + msglen, "i-search)`");
194 msglen += 10;
Jari Aalto726f6381996-08-26 18:22:31 +0000195
196 if (search_string)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000197 {
198 strcpy (message + msglen, search_string);
199 msglen += searchlen;
200 }
Jari Aalto726f6381996-08-26 18:22:31 +0000201
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000202 strcpy (message + msglen, "': ");
203
Jari Aaltof73dda02001-11-13 17:56:06 +0000204 rl_message ("%s", message);
Jari Aalto31859422009-01-12 13:36:28 +0000205 xfree (message);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000206 (*rl_redisplay_function) ();
Jari Aalto726f6381996-08-26 18:22:31 +0000207}
208
Jari Aalto95732b42005-12-07 14:08:12 +0000209static _rl_search_cxt *
210_rl_isearch_init (direction)
211 int direction;
212{
213 _rl_search_cxt *cxt;
214 register int i;
215 HIST_ENTRY **hlist;
216
217 cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
218 if (direction < 0)
219 cxt->sflags |= SF_REVERSE;
220
221 cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
222 : default_isearch_terminators;
223
Chet Rameyac50fba2014-02-26 09:36:43 -0500224 /* Create an array of pointers to the lines that we want to search. */
Jari Aalto95732b42005-12-07 14:08:12 +0000225 hlist = history_list ();
226 rl_maybe_replace_line ();
227 i = 0;
228 if (hlist)
229 for (i = 0; hlist[i]; i++);
230
231 /* Allocate space for this many lines, +1 for the current input line,
232 and remember those lines. */
233 cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
234 for (i = 0; i < cxt->hlen; i++)
235 cxt->lines[i] = hlist[i]->line;
236
237 if (_rl_saved_line_for_history)
238 cxt->lines[i] = _rl_saved_line_for_history->line;
239 else
240 {
241 /* Keep track of this so we can free it. */
242 cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
243 strcpy (cxt->allocated_line, &rl_line_buffer[0]);
244 cxt->lines[i] = cxt->allocated_line;
245 }
246
247 cxt->hlen++;
248
249 /* The line where we start the search. */
250 cxt->history_pos = cxt->save_line;
251
252 rl_save_prompt ();
253
254 /* Initialize search parameters. */
255 cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
256 cxt->search_string[cxt->search_string_index = 0] = '\0';
257
258 /* Normalize DIRECTION into 1 or -1. */
259 cxt->direction = (direction >= 0) ? 1 : -1;
260
261 cxt->sline = rl_line_buffer;
262 cxt->sline_len = strlen (cxt->sline);
263 cxt->sline_index = rl_point;
264
265 _rl_iscxt = cxt; /* save globally */
266
267 return cxt;
268}
269
270static void
271_rl_isearch_fini (cxt)
272 _rl_search_cxt *cxt;
273{
274 /* First put back the original state. */
275 strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
276
277 rl_restore_prompt ();
278
279 /* Save the search string for possible later use. */
280 FREE (last_isearch_string);
281 last_isearch_string = cxt->search_string;
282 last_isearch_string_len = cxt->search_string_index;
283 cxt->search_string = 0;
284
285 if (cxt->last_found_line < cxt->save_line)
286 rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
287 else
288 rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
289
290 /* If the string was not found, put point at the end of the last matching
291 line. If last_found_line == orig_line, we didn't find any matching
292 history lines at all, so put point back in its original position. */
293 if (cxt->sline_index < 0)
294 {
295 if (cxt->last_found_line == cxt->save_line)
296 cxt->sline_index = cxt->save_point;
297 else
298 cxt->sline_index = strlen (rl_line_buffer);
299 rl_mark = cxt->save_mark;
300 }
301
302 rl_point = cxt->sline_index;
303 /* Don't worry about where to put the mark here; rl_get_previous_history
304 and rl_get_next_history take care of it. */
305
306 rl_clear_message ();
307}
308
309int
310_rl_search_getchar (cxt)
311 _rl_search_cxt *cxt;
312{
313 int c;
314
315 /* Read a key and decide how to proceed. */
316 RL_SETSTATE(RL_STATE_MOREINPUT);
317 c = cxt->lastc = rl_read_key ();
318 RL_UNSETSTATE(RL_STATE_MOREINPUT);
319
320#if defined (HANDLE_MULTIBYTE)
Chet Rameyac50fba2014-02-26 09:36:43 -0500321 /* This ends up with C (and LASTC) being set to the last byte of the
322 multibyte character. In most cases c == lastc == mb[0] */
Jari Aalto95732b42005-12-07 14:08:12 +0000323 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
324 c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
325#endif
326
Chet Rameyac50fba2014-02-26 09:36:43 -0500327 RL_CHECK_SIGNALS ();
Jari Aalto95732b42005-12-07 14:08:12 +0000328 return c;
329}
330
Chet Rameyac50fba2014-02-26 09:36:43 -0500331#define ENDSRCH_CHAR(c) \
332 ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
333
Jari Aalto95732b42005-12-07 14:08:12 +0000334/* Process just-read character C according to isearch context CXT. Return
335 -1 if the caller should just free the context and return, 0 if we should
336 break out of the loop, and 1 if we should continue to read characters. */
337int
338_rl_isearch_dispatch (cxt, c)
339 _rl_search_cxt *cxt;
340 int c;
341{
342 int n, wstart, wlen, limit, cval;
343 rl_command_func_t *f;
344
345 f = (rl_command_func_t *)NULL;
Jari Aaltof1be6662008-11-18 13:15:12 +0000346
347 if (c < 0)
348 {
349 cxt->sflags |= SF_FAILED;
350 cxt->history_pos = cxt->last_found_line;
351 return -1;
352 }
353
Chet Ramey495aee42011-11-22 19:11:26 -0500354 /* If we are moving into a new keymap, modify cxt->keymap and go on.
355 This can be a problem if c == ESC and we want to terminate the
356 incremental search, so we check */
357 if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
Jari Aalto95732b42005-12-07 14:08:12 +0000358 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500359 /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
360 takes microseconds, so multiply by 1000. If we don't get any
361 additional input and this keymap shadows another function, process
362 that key as if it was all we read. */
363 if (_rl_keyseq_timeout > 0 &&
364 RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
365 RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
366 _rl_pushed_input_available () == 0 &&
367 ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
368 _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
369 goto add_character;
370
371 cxt->okeymap = cxt->keymap;
Chet Ramey495aee42011-11-22 19:11:26 -0500372 cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
373 cxt->sflags |= SF_CHGKMAP;
374 /* XXX - we should probably save this sequence, so we can do
Chet Rameyac50fba2014-02-26 09:36:43 -0500375 something useful if this doesn't end up mapping to a command we
376 interpret here. Right now we just save the most recent character
377 that caused the index into a new keymap. */
378 cxt->prevc = c;
379#if defined (HANDLE_MULTIBYTE)
380 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
381 {
382 if (cxt->mb[1] == 0)
383 {
384 cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
385 cxt->pmb[1] = '\0';
386 }
387 else
388 memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
389 }
390#endif
Chet Ramey495aee42011-11-22 19:11:26 -0500391 return 1;
392 }
393
Chet Rameyac50fba2014-02-26 09:36:43 -0500394add_character:
395
Chet Ramey495aee42011-11-22 19:11:26 -0500396 /* Translate the keys we do something with to opcodes. */
397 if (c >= 0 && cxt->keymap[c].type == ISFUNC)
398 {
399 f = cxt->keymap[c].function;
Jari Aalto95732b42005-12-07 14:08:12 +0000400
401 if (f == rl_reverse_search_history)
402 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
403 else if (f == rl_forward_search_history)
404 cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
405 else if (f == rl_rubout)
406 cxt->lastc = -3;
Chet Ramey495aee42011-11-22 19:11:26 -0500407 else if (c == CTRL ('G') || f == rl_abort)
Jari Aalto95732b42005-12-07 14:08:12 +0000408 cxt->lastc = -4;
Chet Ramey495aee42011-11-22 19:11:26 -0500409 else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
Jari Aalto95732b42005-12-07 14:08:12 +0000410 cxt->lastc = -5;
Chet Ramey495aee42011-11-22 19:11:26 -0500411 else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
Jari Aalto95732b42005-12-07 14:08:12 +0000412 cxt->lastc = -6;
413 }
414
Chet Ramey495aee42011-11-22 19:11:26 -0500415 /* If we changed the keymap earlier while translating a key sequence into
416 a command, restore it now that we've succeeded. */
417 if (cxt->sflags & SF_CHGKMAP)
418 {
419 cxt->keymap = cxt->okeymap;
420 cxt->sflags &= ~SF_CHGKMAP;
Chet Rameyac50fba2014-02-26 09:36:43 -0500421 /* If we indexed into a new keymap, but didn't map to a command that
422 affects the search (lastc > 0), and the character that mapped to a
423 new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
424 handle that now as if the previous char would have ended the search
425 and we would have read the current character. */
426 /* XXX - should we check cxt->mb? */
427 if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
428 {
429 rl_stuff_char (cxt->lastc);
430 rl_execute_next (cxt->prevc);
431 /* XXX - do we insert everything in cxt->pmb? */
432 return (0);
433 }
434 /* Otherwise, if the current character is mapped to self-insert or
435 nothing (i.e., not an editing command), and the previous character
436 was a keymap index, then we need to insert both the previous
437 character and the current character into the search string. */
438 else if (cxt->lastc > 0 && cxt->prevc > 0 &&
439 cxt->keymap[cxt->prevc].type == ISKMAP &&
440 (f == 0 || f == rl_insert))
441 {
442 /* Make lastc be the next character read */
443 /* XXX - do we insert everything in cxt->mb? */
444 rl_execute_next (cxt->lastc);
445 /* Dispatch on the previous character (insert into search string) */
446 cxt->lastc = cxt->prevc;
447#if defined (HANDLE_MULTIBYTE)
448 /* Have to overwrite cxt->mb here because dispatch uses it below */
449 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
450 {
451 if (cxt->pmb[1] == 0)
452 {
453 cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
454 cxt->mb[1] = '\0';
455 }
456 else
457 memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
458 }
459#endif
460 cxt->prevc = 0;
461 }
462 else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
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 }
Chet Ramey495aee42011-11-22 19:11:26 -0500469 }
470
Jari Aalto95732b42005-12-07 14:08:12 +0000471 /* The characters in isearch_terminators (set from the user-settable
472 variable isearch-terminators) are used to terminate the search but
473 not subsequently execute the character as a command. The default
474 value is "\033\012" (ESC and C-J). */
Chet Ramey495aee42011-11-22 19:11:26 -0500475 if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
Jari Aalto95732b42005-12-07 14:08:12 +0000476 {
477 /* ESC still terminates the search, but if there is pending
478 input or if input arrives within 0.1 seconds (on systems
479 with select(2)) it is used as a prefix character
480 with rl_execute_next. WATCH OUT FOR THIS! This is intended
481 to allow the arrow keys to be used like ^F and ^B are used
482 to terminate the search and execute the movement command.
483 XXX - since _rl_input_available depends on the application-
484 settable keyboard timeout value, this could alternatively
485 use _rl_input_queued(100000) */
Chet Rameyac50fba2014-02-26 09:36:43 -0500486 if (cxt->lastc == ESC && (_rl_pushed_input_available () || _rl_input_available ()))
Jari Aalto95732b42005-12-07 14:08:12 +0000487 rl_execute_next (ESC);
488 return (0);
489 }
490
Jari Aalto95732b42005-12-07 14:08:12 +0000491#if defined (HANDLE_MULTIBYTE)
492 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
493 {
494 if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
495 {
Jari Aalto17345e52009-02-19 22:21:29 +0000496 /* This sets rl_pending_input to LASTC; it will be picked up the next
Jari Aalto95732b42005-12-07 14:08:12 +0000497 time rl_read_key is called. */
498 rl_execute_next (cxt->lastc);
499 return (0);
500 }
501 }
502 else
503#endif
504 if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
505 {
506 /* This sets rl_pending_input to LASTC; it will be picked up the next
507 time rl_read_key is called. */
508 rl_execute_next (cxt->lastc);
509 return (0);
510 }
511
512 /* Now dispatch on the character. `Opcodes' affect the search string or
513 state. Other characters are added to the string. */
514 switch (cxt->lastc)
515 {
516 /* search again */
517 case -1:
518 if (cxt->search_string_index == 0)
519 {
520 if (last_isearch_string)
521 {
522 cxt->search_string_size = 64 + last_isearch_string_len;
523 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
524 strcpy (cxt->search_string, last_isearch_string);
525 cxt->search_string_index = last_isearch_string_len;
Chet Rameyac50fba2014-02-26 09:36:43 -0500526 rl_display_search (cxt->search_string, cxt->sflags, -1);
Jari Aalto95732b42005-12-07 14:08:12 +0000527 break;
528 }
529 return (1);
530 }
531 else if (cxt->sflags & SF_REVERSE)
532 cxt->sline_index--;
533 else if (cxt->sline_index != cxt->sline_len)
534 cxt->sline_index++;
535 else
536 rl_ding ();
537 break;
538
539 /* switch directions */
540 case -2:
541 cxt->direction = -cxt->direction;
542 if (cxt->direction < 0)
543 cxt->sflags |= SF_REVERSE;
544 else
545 cxt->sflags &= ~SF_REVERSE;
546 break;
547
548 /* delete character from search string. */
549 case -3: /* C-H, DEL */
550 /* This is tricky. To do this right, we need to keep a
551 stack of search positions for the current search, with
552 sentinels marking the beginning and end. But this will
553 do until we have a real isearch-undo. */
554 if (cxt->search_string_index == 0)
555 rl_ding ();
556 else
557 cxt->search_string[--cxt->search_string_index] = '\0';
558 break;
559
560 case -4: /* C-G, abort */
561 rl_replace_line (cxt->lines[cxt->save_line], 0);
562 rl_point = cxt->save_point;
563 rl_mark = cxt->save_mark;
564 rl_restore_prompt();
565 rl_clear_message ();
566
567 return -1;
568
569 case -5: /* C-W */
570 /* skip over portion of line we already matched and yank word */
571 wstart = rl_point + cxt->search_string_index;
572 if (wstart >= rl_end)
573 {
574 rl_ding ();
575 break;
576 }
577
578 /* if not in a word, move to one. */
579 cval = _rl_char_value (rl_line_buffer, wstart);
580 if (_rl_walphabetic (cval) == 0)
581 {
582 rl_ding ();
583 break;
584 }
585 n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
586 while (n < rl_end)
587 {
588 cval = _rl_char_value (rl_line_buffer, n);
589 if (_rl_walphabetic (cval) == 0)
590 break;
591 n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
592 }
593 wlen = n - wstart + 1;
594 if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
595 {
596 cxt->search_string_size += wlen + 1;
597 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
598 }
599 for (; wstart < n; wstart++)
600 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
601 cxt->search_string[cxt->search_string_index] = '\0';
602 break;
603
604 case -6: /* C-Y */
605 /* skip over portion of line we already matched and yank rest */
606 wstart = rl_point + cxt->search_string_index;
607 if (wstart >= rl_end)
608 {
609 rl_ding ();
610 break;
611 }
612 n = rl_end - wstart + 1;
613 if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
614 {
615 cxt->search_string_size += n + 1;
616 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
617 }
618 for (n = wstart; n < rl_end; n++)
619 cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
620 cxt->search_string[cxt->search_string_index] = '\0';
621 break;
622
623 /* Add character to search string and continue search. */
624 default:
625 if (cxt->search_string_index + 2 >= cxt->search_string_size)
626 {
627 cxt->search_string_size += 128;
628 cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
629 }
630#if defined (HANDLE_MULTIBYTE)
631 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
632 {
633 int j, l;
Chet Rameyac50fba2014-02-26 09:36:43 -0500634
635 if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
636 cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
637 else
638 for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
639 cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
Jari Aalto95732b42005-12-07 14:08:12 +0000640 }
641 else
642#endif
Chet Rameyac50fba2014-02-26 09:36:43 -0500643 cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
Jari Aalto95732b42005-12-07 14:08:12 +0000644 cxt->search_string[cxt->search_string_index] = '\0';
645 break;
646 }
647
648 for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
649 {
650 limit = cxt->sline_len - cxt->search_string_index + 1;
651
652 /* Search the current line. */
653 while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
654 {
655 if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
656 {
657 cxt->sflags |= SF_FOUND;
658 break;
659 }
660 else
661 cxt->sline_index += cxt->direction;
662 }
663 if (cxt->sflags & SF_FOUND)
664 break;
665
666 /* Move to the next line, but skip new copies of the line
667 we just found and lines shorter than the string we're
668 searching for. */
669 do
670 {
671 /* Move to the next line. */
672 cxt->history_pos += cxt->direction;
673
674 /* At limit for direction? */
675 if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
676 {
677 cxt->sflags |= SF_FAILED;
678 break;
679 }
680
681 /* We will need these later. */
682 cxt->sline = cxt->lines[cxt->history_pos];
683 cxt->sline_len = strlen (cxt->sline);
684 }
685 while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
686 (cxt->search_string_index > cxt->sline_len));
687
688 if (cxt->sflags & SF_FAILED)
689 break;
690
691 /* Now set up the line for searching... */
692 cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
693 }
694
695 if (cxt->sflags & SF_FAILED)
696 {
697 /* We cannot find the search string. Ding the bell. */
698 rl_ding ();
699 cxt->history_pos = cxt->last_found_line;
Chet Rameyac50fba2014-02-26 09:36:43 -0500700 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
Jari Aalto95732b42005-12-07 14:08:12 +0000701 return 1;
702 }
703
704 /* We have found the search string. Just display it. But don't
705 actually move there in the history list until the user accepts
706 the location. */
707 if (cxt->sflags & SF_FOUND)
708 {
709 cxt->prev_line_found = cxt->lines[cxt->history_pos];
710 rl_replace_line (cxt->lines[cxt->history_pos], 0);
711 rl_point = cxt->sline_index;
712 cxt->last_found_line = cxt->history_pos;
Chet Rameyac50fba2014-02-26 09:36:43 -0500713 rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
Jari Aalto95732b42005-12-07 14:08:12 +0000714 }
715
716 return 1;
717}
718
719static int
720_rl_isearch_cleanup (cxt, r)
721 _rl_search_cxt *cxt;
722 int r;
723{
724 if (r >= 0)
725 _rl_isearch_fini (cxt);
726 _rl_scxt_dispose (cxt, 0);
727 _rl_iscxt = 0;
728
729 RL_UNSETSTATE(RL_STATE_ISEARCH);
730
731 return (r != 0);
732}
733
Jari Aalto726f6381996-08-26 18:22:31 +0000734/* Search through the history looking for an interactively typed string.
735 This is analogous to i-search. We start the search in the current line.
736 DIRECTION is which direction to search; >= 0 means forward, < 0 means
737 backwards. */
738static int
739rl_search_history (direction, invoking_key)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000740 int direction, invoking_key;
Jari Aalto726f6381996-08-26 18:22:31 +0000741{
Jari Aalto95732b42005-12-07 14:08:12 +0000742 _rl_search_cxt *cxt; /* local for now, but saved globally */
743 int c, r;
Jari Aaltob72432f1999-02-19 17:11:39 +0000744
Jari Aalto28ef6c32001-04-06 19:14:31 +0000745 RL_SETSTATE(RL_STATE_ISEARCH);
Jari Aalto95732b42005-12-07 14:08:12 +0000746 cxt = _rl_isearch_init (direction);
Jari Aalto726f6381996-08-26 18:22:31 +0000747
Chet Rameyac50fba2014-02-26 09:36:43 -0500748 rl_display_search (cxt->search_string, cxt->sflags, -1);
Jari Aaltob72432f1999-02-19 17:11:39 +0000749
Jari Aalto95732b42005-12-07 14:08:12 +0000750 /* If we are using the callback interface, all we do is set up here and
751 return. The key is that we leave RL_STATE_ISEARCH set. */
752 if (RL_ISSTATE (RL_STATE_CALLBACK))
753 return (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000754
Jari Aalto95732b42005-12-07 14:08:12 +0000755 r = -1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000756 for (;;)
Jari Aalto726f6381996-08-26 18:22:31 +0000757 {
Jari Aalto95732b42005-12-07 14:08:12 +0000758 c = _rl_search_getchar (cxt);
759 /* We might want to handle EOF here (c == 0) */
760 r = _rl_isearch_dispatch (cxt, cxt->lastc);
761 if (r <= 0)
762 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000763 }
764
765 /* The searching is over. The user may have found the string that she
766 was looking for, or else she may have exited a failing search. If
767 LINE_INDEX is -1, then that shows that the string searched for was
768 not found. We use this to determine where to place rl_point. */
Jari Aalto95732b42005-12-07 14:08:12 +0000769 return (_rl_isearch_cleanup (cxt, r));
Jari Aalto726f6381996-08-26 18:22:31 +0000770}
Jari Aalto95732b42005-12-07 14:08:12 +0000771
772#if defined (READLINE_CALLBACKS)
773/* Called from the callback functions when we are ready to read a key. The
774 callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
775 If _rl_isearch_dispatch finishes searching, this function is responsible
776 for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
777int
778_rl_isearch_callback (cxt)
779 _rl_search_cxt *cxt;
780{
781 int c, r;
782
783 c = _rl_search_getchar (cxt);
784 /* We might want to handle EOF here */
785 r = _rl_isearch_dispatch (cxt, cxt->lastc);
786
787 return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
788}
789#endif