isearch.c revision 165670
121308Sache/* **************************************************************** */ 221308Sache/* */ 321308Sache/* I-Search and Searching */ 421308Sache/* */ 521308Sache/* **************************************************************** */ 621308Sache 7157184Sache/* Copyright (C) 1987-2005 Free Software Foundation, Inc. 821308Sache 921308Sache This file contains the Readline Library (the Library), a set of 1021308Sache routines for providing Emacs style line input to programs that ask 1121308Sache for it. 1221308Sache 1321308Sache The Library is free software; you can redistribute it and/or modify 1421308Sache it under the terms of the GNU General Public License as published by 1558310Sache the Free Software Foundation; either version 2, or (at your option) 1621308Sache any later version. 1721308Sache 1821308Sache The Library is distributed in the hope that it will be useful, but 1921308Sache WITHOUT ANY WARRANTY; without even the implied warranty of 2021308Sache MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2121308Sache General Public License for more details. 2221308Sache 2321308Sache The GNU General Public License is often shipped with GNU software, and 2421308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2521308Sache have a copy of the license, write to the Free Software Foundation, 2658310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2721308Sache#define READLINE_LIBRARY 2821308Sache 2921308Sache#if defined (HAVE_CONFIG_H) 3021308Sache# include <config.h> 3121308Sache#endif 3221308Sache 3326497Sache#include <sys/types.h> 3426497Sache 3521308Sache#include <stdio.h> 3621308Sache 3721308Sache#if defined (HAVE_UNISTD_H) 3821308Sache# include <unistd.h> 3921308Sache#endif 4021308Sache 4126497Sache#if defined (HAVE_STDLIB_H) 4226497Sache# include <stdlib.h> 4326497Sache#else 4426497Sache# include "ansi_stdlib.h" 4526497Sache#endif 4621308Sache 4721308Sache#include "rldefs.h" 48119610Sache#include "rlmbutil.h" 49119610Sache 5021308Sache#include "readline.h" 5121308Sache#include "history.h" 5221308Sache 5358310Sache#include "rlprivate.h" 5458310Sache#include "xmalloc.h" 5558310Sache 5647558Sache/* Variables exported to other files in the readline library. */ 57119610Sachechar *_rl_isearch_terminators = (char *)NULL; 5847558Sache 59157184Sache_rl_search_cxt *_rl_iscxt = 0; 60157184Sache 6121308Sache/* Variables imported from other files in the readline library. */ 6275406Sacheextern HIST_ENTRY *_rl_saved_line_for_history; 6321308Sache 64119610Sachestatic int rl_search_history PARAMS((int, int)); 6521308Sache 66157184Sachestatic _rl_search_cxt *_rl_isearch_init PARAMS((int)); 67157184Sachestatic void _rl_isearch_fini PARAMS((_rl_search_cxt *)); 68157184Sachestatic int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int)); 69157184Sache 7021308Sache/* Last line found by the current incremental search, so we don't `find' 71165670Sache identical lines many times in a row. Now part of isearch context. */ 72165670Sache/* static char *prev_line_found; */ 7321308Sache 74119610Sache/* Last search string and its length. */ 75119610Sachestatic char *last_isearch_string; 76119610Sachestatic int last_isearch_string_len; 7775406Sache 78119610Sachestatic char *default_isearch_terminators = "\033\012"; 79119610Sache 80157184Sache_rl_search_cxt * 81157184Sache_rl_scxt_alloc (type, flags) 82157184Sache int type, flags; 83157184Sache{ 84157184Sache _rl_search_cxt *cxt; 85157184Sache 86157184Sache cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt)); 87157184Sache 88157184Sache cxt->type = type; 89157184Sache cxt->sflags = flags; 90157184Sache 91157184Sache cxt->search_string = 0; 92157184Sache cxt->search_string_size = cxt->search_string_index = 0; 93157184Sache 94157184Sache cxt->lines = 0; 95157184Sache cxt->allocated_line = 0; 96157184Sache cxt->hlen = cxt->hindex = 0; 97157184Sache 98157184Sache cxt->save_point = rl_point; 99157184Sache cxt->save_mark = rl_mark; 100157184Sache cxt->save_line = where_history (); 101157184Sache cxt->last_found_line = cxt->save_line; 102157184Sache cxt->prev_line_found = 0; 103157184Sache 104157184Sache cxt->save_undo_list = 0; 105157184Sache 106157184Sache cxt->history_pos = 0; 107157184Sache cxt->direction = 0; 108157184Sache 109157184Sache cxt->lastc = 0; 110157184Sache 111157184Sache cxt->sline = 0; 112157184Sache cxt->sline_len = cxt->sline_index = 0; 113157184Sache 114157184Sache cxt->search_terminators = 0; 115157184Sache 116157184Sache return cxt; 117157184Sache} 118157184Sache 119157184Sachevoid 120157184Sache_rl_scxt_dispose (cxt, flags) 121157184Sache _rl_search_cxt *cxt; 122157184Sache int flags; 123157184Sache{ 124157184Sache FREE (cxt->search_string); 125157184Sache FREE (cxt->allocated_line); 126157184Sache FREE (cxt->lines); 127157184Sache 128157184Sache free (cxt); 129157184Sache} 130157184Sache 13121308Sache/* Search backwards through the history looking for a string which is typed 13221308Sache interactively. Start with the current line. */ 13321308Sacheint 13421308Sacherl_reverse_search_history (sign, key) 13521308Sache int sign, key; 13621308Sache{ 13721308Sache return (rl_search_history (-sign, key)); 13821308Sache} 13921308Sache 14021308Sache/* Search forwards through the history looking for a string which is typed 14121308Sache interactively. Start with the current line. */ 14221308Sacheint 14321308Sacherl_forward_search_history (sign, key) 14421308Sache int sign, key; 14521308Sache{ 14621308Sache return (rl_search_history (sign, key)); 14721308Sache} 14821308Sache 14921308Sache/* Display the current state of the search in the echo-area. 15021308Sache SEARCH_STRING contains the string that is being searched for, 151157184Sache DIRECTION is zero for forward, or non-zero for reverse, 15221308Sache WHERE is the history list number of the current line. If it is 15321308Sache -1, then this line is the starting one. */ 15421308Sachestatic void 15521308Sacherl_display_search (search_string, reverse_p, where) 15621308Sache char *search_string; 15721308Sache int reverse_p, where; 15821308Sache{ 15921308Sache char *message; 16021308Sache int msglen, searchlen; 16121308Sache 16221308Sache searchlen = (search_string && *search_string) ? strlen (search_string) : 0; 16321308Sache 164119610Sache message = (char *)xmalloc (searchlen + 33); 16521308Sache msglen = 0; 16621308Sache 16721308Sache#if defined (NOTDEF) 16821308Sache if (where != -1) 16921308Sache { 17021308Sache sprintf (message, "[%d]", where + history_base); 17121308Sache msglen = strlen (message); 17221308Sache } 17321308Sache#endif /* NOTDEF */ 17421308Sache 17521308Sache message[msglen++] = '('; 17621308Sache 17721308Sache if (reverse_p) 17821308Sache { 17921308Sache strcpy (message + msglen, "reverse-"); 18021308Sache msglen += 8; 18121308Sache } 18221308Sache 18321308Sache strcpy (message + msglen, "i-search)`"); 18421308Sache msglen += 10; 18521308Sache 18621308Sache if (search_string) 18721308Sache { 18821308Sache strcpy (message + msglen, search_string); 18921308Sache msglen += searchlen; 19021308Sache } 19121308Sache 19221308Sache strcpy (message + msglen, "': "); 19321308Sache 194119610Sache rl_message ("%s", message); 19521308Sache free (message); 19621308Sache (*rl_redisplay_function) (); 19721308Sache} 19821308Sache 199157184Sachestatic _rl_search_cxt * 200157184Sache_rl_isearch_init (direction) 201157184Sache int direction; 20221308Sache{ 203157184Sache _rl_search_cxt *cxt; 204157184Sache register int i; 20521308Sache HIST_ENTRY **hlist; 20621308Sache 207157184Sache cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0); 208157184Sache if (direction < 0) 209157184Sache cxt->sflags |= SF_REVERSE; 21021308Sache 211157184Sache cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators 21275406Sache : default_isearch_terminators; 21347558Sache 21421308Sache /* Create an arrary of pointers to the lines that we want to search. */ 215157184Sache hlist = history_list (); 21675406Sache rl_maybe_replace_line (); 21721308Sache i = 0; 21821308Sache if (hlist) 21921308Sache for (i = 0; hlist[i]; i++); 22021308Sache 22121308Sache /* Allocate space for this many lines, +1 for the current input line, 22221308Sache and remember those lines. */ 223157184Sache cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *)); 224157184Sache for (i = 0; i < cxt->hlen; i++) 225157184Sache cxt->lines[i] = hlist[i]->line; 22621308Sache 22775406Sache if (_rl_saved_line_for_history) 228157184Sache cxt->lines[i] = _rl_saved_line_for_history->line; 22921308Sache else 23021308Sache { 23121308Sache /* Keep track of this so we can free it. */ 232157184Sache cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); 233157184Sache strcpy (cxt->allocated_line, &rl_line_buffer[0]); 234157184Sache cxt->lines[i] = cxt->allocated_line; 23521308Sache } 23621308Sache 237157184Sache cxt->hlen++; 23821308Sache 23921308Sache /* The line where we start the search. */ 240157184Sache cxt->history_pos = cxt->save_line; 24121308Sache 24247558Sache rl_save_prompt (); 24321308Sache 24421308Sache /* Initialize search parameters. */ 245157184Sache cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128); 246157184Sache cxt->search_string[cxt->search_string_index = 0] = '\0'; 24721308Sache 24821308Sache /* Normalize DIRECTION into 1 or -1. */ 249157184Sache cxt->direction = (direction >= 0) ? 1 : -1; 25021308Sache 251157184Sache cxt->sline = rl_line_buffer; 252157184Sache cxt->sline_len = strlen (cxt->sline); 253157184Sache cxt->sline_index = rl_point; 25421308Sache 255157184Sache _rl_iscxt = cxt; /* save globally */ 25621308Sache 257157184Sache return cxt; 258157184Sache} 259157184Sache 260157184Sachestatic void 261157184Sache_rl_isearch_fini (cxt) 262157184Sache _rl_search_cxt *cxt; 263157184Sache{ 264157184Sache /* First put back the original state. */ 265157184Sache strcpy (rl_line_buffer, cxt->lines[cxt->save_line]); 266157184Sache 267157184Sache rl_restore_prompt (); 268157184Sache 269157184Sache /* Save the search string for possible later use. */ 270157184Sache FREE (last_isearch_string); 271157184Sache last_isearch_string = cxt->search_string; 272157184Sache last_isearch_string_len = cxt->search_string_index; 273157184Sache cxt->search_string = 0; 274157184Sache 275157184Sache if (cxt->last_found_line < cxt->save_line) 276157184Sache rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0); 277157184Sache else 278157184Sache rl_get_next_history (cxt->last_found_line - cxt->save_line, 0); 279157184Sache 280157184Sache /* If the string was not found, put point at the end of the last matching 281157184Sache line. If last_found_line == orig_line, we didn't find any matching 282157184Sache history lines at all, so put point back in its original position. */ 283157184Sache if (cxt->sline_index < 0) 28421308Sache { 285157184Sache if (cxt->last_found_line == cxt->save_line) 286157184Sache cxt->sline_index = cxt->save_point; 287157184Sache else 288157184Sache cxt->sline_index = strlen (rl_line_buffer); 289157184Sache rl_mark = cxt->save_mark; 290157184Sache } 29121308Sache 292157184Sache rl_point = cxt->sline_index; 293157184Sache /* Don't worry about where to put the mark here; rl_get_previous_history 294157184Sache and rl_get_next_history take care of it. */ 29521308Sache 296157184Sache rl_clear_message (); 297157184Sache} 298157184Sache 299157184Sacheint 300157184Sache_rl_search_getchar (cxt) 301157184Sache _rl_search_cxt *cxt; 302157184Sache{ 303157184Sache int c; 304157184Sache 305157184Sache /* Read a key and decide how to proceed. */ 306157184Sache RL_SETSTATE(RL_STATE_MOREINPUT); 307157184Sache c = cxt->lastc = rl_read_key (); 308157184Sache RL_UNSETSTATE(RL_STATE_MOREINPUT); 309157184Sache 310119610Sache#if defined (HANDLE_MULTIBYTE) 311157184Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 312157184Sache c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX); 313119610Sache#endif 314119610Sache 315157184Sache return c; 316157184Sache} 31721308Sache 318157184Sache/* Process just-read character C according to isearch context CXT. Return 319157184Sache -1 if the caller should just free the context and return, 0 if we should 320157184Sache break out of the loop, and 1 if we should continue to read characters. */ 321157184Sacheint 322157184Sache_rl_isearch_dispatch (cxt, c) 323157184Sache _rl_search_cxt *cxt; 324157184Sache int c; 325157184Sache{ 326157184Sache int n, wstart, wlen, limit, cval; 327157184Sache rl_command_func_t *f; 32821308Sache 329157184Sache f = (rl_command_func_t *)NULL; 330157184Sache 331157184Sache /* Translate the keys we do something with to opcodes. */ 332157184Sache if (c >= 0 && _rl_keymap[c].type == ISFUNC) 333157184Sache { 334157184Sache f = _rl_keymap[c].function; 33521308Sache 336157184Sache if (f == rl_reverse_search_history) 337157184Sache cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2; 338157184Sache else if (f == rl_forward_search_history) 339157184Sache cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1; 340157184Sache else if (f == rl_rubout) 341157184Sache cxt->lastc = -3; 342157184Sache else if (c == CTRL ('G')) 343157184Sache cxt->lastc = -4; 344157184Sache else if (c == CTRL ('W')) /* XXX */ 345157184Sache cxt->lastc = -5; 346157184Sache else if (c == CTRL ('Y')) /* XXX */ 347157184Sache cxt->lastc = -6; 348157184Sache } 349157184Sache 350157184Sache /* The characters in isearch_terminators (set from the user-settable 351157184Sache variable isearch-terminators) are used to terminate the search but 352157184Sache not subsequently execute the character as a command. The default 353157184Sache value is "\033\012" (ESC and C-J). */ 354157184Sache if (strchr (cxt->search_terminators, cxt->lastc)) 355157184Sache { 356157184Sache /* ESC still terminates the search, but if there is pending 357157184Sache input or if input arrives within 0.1 seconds (on systems 358157184Sache with select(2)) it is used as a prefix character 359157184Sache with rl_execute_next. WATCH OUT FOR THIS! This is intended 360157184Sache to allow the arrow keys to be used like ^F and ^B are used 361157184Sache to terminate the search and execute the movement command. 362157184Sache XXX - since _rl_input_available depends on the application- 363157184Sache settable keyboard timeout value, this could alternatively 364157184Sache use _rl_input_queued(100000) */ 365157184Sache if (cxt->lastc == ESC && _rl_input_available ()) 366157184Sache rl_execute_next (ESC); 367157184Sache return (0); 368157184Sache } 369157184Sache 370119610Sache#define ENDSRCH_CHAR(c) \ 371119610Sache ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) 372119610Sache 373119610Sache#if defined (HANDLE_MULTIBYTE) 374157184Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 375157184Sache { 376157184Sache if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc)) 37721308Sache { 37875406Sache /* This sets rl_pending_input to c; it will be picked up the next 37975406Sache time rl_read_key is called. */ 380157184Sache rl_execute_next (cxt->lastc); 381157184Sache return (0); 38221308Sache } 383157184Sache } 384157184Sache else 385157184Sache#endif 386157184Sache if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc)) 387157184Sache { 388157184Sache /* This sets rl_pending_input to LASTC; it will be picked up the next 389157184Sache time rl_read_key is called. */ 390157184Sache rl_execute_next (cxt->lastc); 391157184Sache return (0); 392157184Sache } 39321308Sache 394157184Sache /* Now dispatch on the character. `Opcodes' affect the search string or 395157184Sache state. Other characters are added to the string. */ 396157184Sache switch (cxt->lastc) 397157184Sache { 398157184Sache /* search again */ 399157184Sache case -1: 400157184Sache if (cxt->search_string_index == 0) 40121308Sache { 402157184Sache if (last_isearch_string) 403119610Sache { 404157184Sache cxt->search_string_size = 64 + last_isearch_string_len; 405157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 406157184Sache strcpy (cxt->search_string, last_isearch_string); 407157184Sache cxt->search_string_index = last_isearch_string_len; 408157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); 409157184Sache break; 410119610Sache } 411157184Sache return (1); 412157184Sache } 413157184Sache else if (cxt->sflags & SF_REVERSE) 414157184Sache cxt->sline_index--; 415157184Sache else if (cxt->sline_index != cxt->sline_len) 416157184Sache cxt->sline_index++; 417157184Sache else 418157184Sache rl_ding (); 419157184Sache break; 42021308Sache 421157184Sache /* switch directions */ 422157184Sache case -2: 423157184Sache cxt->direction = -cxt->direction; 424157184Sache if (cxt->direction < 0) 425157184Sache cxt->sflags |= SF_REVERSE; 426157184Sache else 427157184Sache cxt->sflags &= ~SF_REVERSE; 428157184Sache break; 42921308Sache 430157184Sache /* delete character from search string. */ 431157184Sache case -3: /* C-H, DEL */ 432157184Sache /* This is tricky. To do this right, we need to keep a 433157184Sache stack of search positions for the current search, with 434157184Sache sentinels marking the beginning and end. But this will 435157184Sache do until we have a real isearch-undo. */ 436157184Sache if (cxt->search_string_index == 0) 437157184Sache rl_ding (); 438157184Sache else 439157184Sache cxt->search_string[--cxt->search_string_index] = '\0'; 440157184Sache break; 441119610Sache 442157184Sache case -4: /* C-G, abort */ 443157184Sache rl_replace_line (cxt->lines[cxt->save_line], 0); 444157184Sache rl_point = cxt->save_point; 445157184Sache rl_mark = cxt->save_mark; 446157184Sache rl_restore_prompt(); 447157184Sache rl_clear_message (); 448119610Sache 449157184Sache return -1; 45021308Sache 451157184Sache case -5: /* C-W */ 452157184Sache /* skip over portion of line we already matched and yank word */ 453157184Sache wstart = rl_point + cxt->search_string_index; 454157184Sache if (wstart >= rl_end) 455157184Sache { 456157184Sache rl_ding (); 457157184Sache break; 458157184Sache } 459119610Sache 460157184Sache /* if not in a word, move to one. */ 461157184Sache cval = _rl_char_value (rl_line_buffer, wstart); 462157184Sache if (_rl_walphabetic (cval) == 0) 463157184Sache { 464157184Sache rl_ding (); 46535486Sache break; 466157184Sache } 467157184Sache n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);; 468157184Sache while (n < rl_end) 469157184Sache { 470157184Sache cval = _rl_char_value (rl_line_buffer, n); 471157184Sache if (_rl_walphabetic (cval) == 0) 472157184Sache break; 473157184Sache n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);; 474157184Sache } 475157184Sache wlen = n - wstart + 1; 476157184Sache if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size) 477157184Sache { 478157184Sache cxt->search_string_size += wlen + 1; 479157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 480157184Sache } 481157184Sache for (; wstart < n; wstart++) 482157184Sache cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart]; 483157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 484157184Sache break; 48535486Sache 486157184Sache case -6: /* C-Y */ 487157184Sache /* skip over portion of line we already matched and yank rest */ 488157184Sache wstart = rl_point + cxt->search_string_index; 489157184Sache if (wstart >= rl_end) 490157184Sache { 491157184Sache rl_ding (); 492119610Sache break; 493157184Sache } 494157184Sache n = rl_end - wstart + 1; 495157184Sache if (cxt->search_string_index + n + 1 >= cxt->search_string_size) 496157184Sache { 497157184Sache cxt->search_string_size += n + 1; 498157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 499157184Sache } 500157184Sache for (n = wstart; n < rl_end; n++) 501157184Sache cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n]; 502157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 503157184Sache break; 504119610Sache 505157184Sache /* Add character to search string and continue search. */ 506157184Sache default: 507157184Sache if (cxt->search_string_index + 2 >= cxt->search_string_size) 508157184Sache { 509157184Sache cxt->search_string_size += 128; 510157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 511157184Sache } 512119610Sache#if defined (HANDLE_MULTIBYTE) 513157184Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 514157184Sache { 515157184Sache int j, l; 516157184Sache for (j = 0, l = strlen (cxt->mb); j < l; ) 517157184Sache cxt->search_string[cxt->search_string_index++] = cxt->mb[j++]; 518157184Sache } 519157184Sache else 520157184Sache#endif 521157184Sache cxt->search_string[cxt->search_string_index++] = c; 522157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 523157184Sache break; 524157184Sache } 525157184Sache 526157184Sache for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; ) 527157184Sache { 528157184Sache limit = cxt->sline_len - cxt->search_string_index + 1; 529157184Sache 530157184Sache /* Search the current line. */ 531157184Sache while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit)) 532157184Sache { 533157184Sache if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index)) 534119610Sache { 535157184Sache cxt->sflags |= SF_FOUND; 536157184Sache break; 537119610Sache } 538119610Sache else 539157184Sache cxt->sline_index += cxt->direction; 54021308Sache } 541157184Sache if (cxt->sflags & SF_FOUND) 542157184Sache break; 54321308Sache 544157184Sache /* Move to the next line, but skip new copies of the line 545157184Sache we just found and lines shorter than the string we're 546157184Sache searching for. */ 547157184Sache do 54821308Sache { 549157184Sache /* Move to the next line. */ 550157184Sache cxt->history_pos += cxt->direction; 55121308Sache 552157184Sache /* At limit for direction? */ 553157184Sache if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen)) 55421308Sache { 555157184Sache cxt->sflags |= SF_FAILED; 556157184Sache break; 55721308Sache } 55821308Sache 559157184Sache /* We will need these later. */ 560157184Sache cxt->sline = cxt->lines[cxt->history_pos]; 561157184Sache cxt->sline_len = strlen (cxt->sline); 562157184Sache } 563157184Sache while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) || 564157184Sache (cxt->search_string_index > cxt->sline_len)); 56521308Sache 566157184Sache if (cxt->sflags & SF_FAILED) 567157184Sache break; 56821308Sache 569157184Sache /* Now set up the line for searching... */ 570157184Sache cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0; 571157184Sache } 57221308Sache 573157184Sache if (cxt->sflags & SF_FAILED) 574157184Sache { 575157184Sache /* We cannot find the search string. Ding the bell. */ 576157184Sache rl_ding (); 577157184Sache cxt->history_pos = cxt->last_found_line; 578157184Sache return 1; 579157184Sache } 58021308Sache 581157184Sache /* We have found the search string. Just display it. But don't 582157184Sache actually move there in the history list until the user accepts 583157184Sache the location. */ 584157184Sache if (cxt->sflags & SF_FOUND) 585157184Sache { 586157184Sache cxt->prev_line_found = cxt->lines[cxt->history_pos]; 587157184Sache rl_replace_line (cxt->lines[cxt->history_pos], 0); 588157184Sache rl_point = cxt->sline_index; 589157184Sache cxt->last_found_line = cxt->history_pos; 590157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos); 591157184Sache } 59221308Sache 593157184Sache return 1; 594157184Sache} 59521308Sache 596157184Sachestatic int 597157184Sache_rl_isearch_cleanup (cxt, r) 598157184Sache _rl_search_cxt *cxt; 599157184Sache int r; 600157184Sache{ 601157184Sache if (r >= 0) 602157184Sache _rl_isearch_fini (cxt); 603157184Sache _rl_scxt_dispose (cxt, 0); 604157184Sache _rl_iscxt = 0; 60521308Sache 606157184Sache RL_UNSETSTATE(RL_STATE_ISEARCH); 60721308Sache 608157184Sache return (r != 0); 609157184Sache} 61021308Sache 611157184Sache/* Search through the history looking for an interactively typed string. 612157184Sache This is analogous to i-search. We start the search in the current line. 613157184Sache DIRECTION is which direction to search; >= 0 means forward, < 0 means 614157184Sache backwards. */ 615157184Sachestatic int 616157184Sacherl_search_history (direction, invoking_key) 617157184Sache int direction, invoking_key; 618157184Sache{ 619157184Sache _rl_search_cxt *cxt; /* local for now, but saved globally */ 620157184Sache int c, r; 62121308Sache 622157184Sache RL_SETSTATE(RL_STATE_ISEARCH); 623157184Sache cxt = _rl_isearch_init (direction); 62421308Sache 625157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); 62621308Sache 627157184Sache /* If we are using the callback interface, all we do is set up here and 628157184Sache return. The key is that we leave RL_STATE_ISEARCH set. */ 629157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 630157184Sache return (0); 631157184Sache 632157184Sache r = -1; 633157184Sache for (;;) 634119610Sache { 635157184Sache c = _rl_search_getchar (cxt); 636157184Sache /* We might want to handle EOF here (c == 0) */ 637157184Sache r = _rl_isearch_dispatch (cxt, cxt->lastc); 638157184Sache if (r <= 0) 639157184Sache break; 640119610Sache } 641119610Sache 642157184Sache /* The searching is over. The user may have found the string that she 643157184Sache was looking for, or else she may have exited a failing search. If 644157184Sache LINE_INDEX is -1, then that shows that the string searched for was 645157184Sache not found. We use this to determine where to place rl_point. */ 646157184Sache return (_rl_isearch_cleanup (cxt, r)); 647157184Sache} 648119610Sache 649157184Sache#if defined (READLINE_CALLBACKS) 650157184Sache/* Called from the callback functions when we are ready to read a key. The 651157184Sache callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH). 652157184Sache If _rl_isearch_dispatch finishes searching, this function is responsible 653157184Sache for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */ 654157184Sacheint 655157184Sache_rl_isearch_callback (cxt) 656157184Sache _rl_search_cxt *cxt; 657157184Sache{ 658157184Sache int c, r; 65921308Sache 660157184Sache c = _rl_search_getchar (cxt); 661157184Sache /* We might want to handle EOF here */ 662157184Sache r = _rl_isearch_dispatch (cxt, cxt->lastc); 66321308Sache 664157184Sache return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0; 66521308Sache} 666157184Sache#endif 667