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; 330173403Sache 331173403Sache if (c < 0) 332173403Sache { 333173403Sache cxt->sflags |= SF_FAILED; 334173403Sache cxt->history_pos = cxt->last_found_line; 335173403Sache return -1; 336173403Sache } 337173403Sache 338173403Sache /* Translate the keys we do something with to opcodes. */ 339157184Sache if (c >= 0 && _rl_keymap[c].type == ISFUNC) 340157184Sache { 341157184Sache f = _rl_keymap[c].function; 34221308Sache 343157184Sache if (f == rl_reverse_search_history) 344157184Sache cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2; 345157184Sache else if (f == rl_forward_search_history) 346157184Sache cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1; 347157184Sache else if (f == rl_rubout) 348157184Sache cxt->lastc = -3; 349157184Sache else if (c == CTRL ('G')) 350157184Sache cxt->lastc = -4; 351157184Sache else if (c == CTRL ('W')) /* XXX */ 352157184Sache cxt->lastc = -5; 353157184Sache else if (c == CTRL ('Y')) /* XXX */ 354157184Sache cxt->lastc = -6; 355157184Sache } 356157184Sache 357157184Sache /* The characters in isearch_terminators (set from the user-settable 358157184Sache variable isearch-terminators) are used to terminate the search but 359157184Sache not subsequently execute the character as a command. The default 360157184Sache value is "\033\012" (ESC and C-J). */ 361157184Sache if (strchr (cxt->search_terminators, cxt->lastc)) 362157184Sache { 363157184Sache /* ESC still terminates the search, but if there is pending 364157184Sache input or if input arrives within 0.1 seconds (on systems 365157184Sache with select(2)) it is used as a prefix character 366157184Sache with rl_execute_next. WATCH OUT FOR THIS! This is intended 367157184Sache to allow the arrow keys to be used like ^F and ^B are used 368157184Sache to terminate the search and execute the movement command. 369157184Sache XXX - since _rl_input_available depends on the application- 370157184Sache settable keyboard timeout value, this could alternatively 371157184Sache use _rl_input_queued(100000) */ 372157184Sache if (cxt->lastc == ESC && _rl_input_available ()) 373157184Sache rl_execute_next (ESC); 374157184Sache return (0); 375157184Sache } 376157184Sache 377119610Sache#define ENDSRCH_CHAR(c) \ 378119610Sache ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) 379119610Sache 380119610Sache#if defined (HANDLE_MULTIBYTE) 381157184Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 382157184Sache { 383157184Sache if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc)) 38421308Sache { 38575406Sache /* This sets rl_pending_input to c; it will be picked up the next 38675406Sache time rl_read_key is called. */ 387157184Sache rl_execute_next (cxt->lastc); 388157184Sache return (0); 38921308Sache } 390157184Sache } 391157184Sache else 392157184Sache#endif 393157184Sache if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc)) 394157184Sache { 395157184Sache /* This sets rl_pending_input to LASTC; it will be picked up the next 396157184Sache time rl_read_key is called. */ 397157184Sache rl_execute_next (cxt->lastc); 398157184Sache return (0); 399157184Sache } 40021308Sache 401157184Sache /* Now dispatch on the character. `Opcodes' affect the search string or 402157184Sache state. Other characters are added to the string. */ 403157184Sache switch (cxt->lastc) 404157184Sache { 405157184Sache /* search again */ 406157184Sache case -1: 407157184Sache if (cxt->search_string_index == 0) 40821308Sache { 409157184Sache if (last_isearch_string) 410119610Sache { 411157184Sache cxt->search_string_size = 64 + last_isearch_string_len; 412157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 413157184Sache strcpy (cxt->search_string, last_isearch_string); 414157184Sache cxt->search_string_index = last_isearch_string_len; 415157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); 416157184Sache break; 417119610Sache } 418157184Sache return (1); 419157184Sache } 420157184Sache else if (cxt->sflags & SF_REVERSE) 421157184Sache cxt->sline_index--; 422157184Sache else if (cxt->sline_index != cxt->sline_len) 423157184Sache cxt->sline_index++; 424157184Sache else 425157184Sache rl_ding (); 426157184Sache break; 42721308Sache 428157184Sache /* switch directions */ 429157184Sache case -2: 430157184Sache cxt->direction = -cxt->direction; 431157184Sache if (cxt->direction < 0) 432157184Sache cxt->sflags |= SF_REVERSE; 433157184Sache else 434157184Sache cxt->sflags &= ~SF_REVERSE; 435157184Sache break; 43621308Sache 437157184Sache /* delete character from search string. */ 438157184Sache case -3: /* C-H, DEL */ 439157184Sache /* This is tricky. To do this right, we need to keep a 440157184Sache stack of search positions for the current search, with 441157184Sache sentinels marking the beginning and end. But this will 442157184Sache do until we have a real isearch-undo. */ 443157184Sache if (cxt->search_string_index == 0) 444157184Sache rl_ding (); 445157184Sache else 446157184Sache cxt->search_string[--cxt->search_string_index] = '\0'; 447157184Sache break; 448119610Sache 449157184Sache case -4: /* C-G, abort */ 450157184Sache rl_replace_line (cxt->lines[cxt->save_line], 0); 451157184Sache rl_point = cxt->save_point; 452157184Sache rl_mark = cxt->save_mark; 453157184Sache rl_restore_prompt(); 454157184Sache rl_clear_message (); 455119610Sache 456157184Sache return -1; 45721308Sache 458157184Sache case -5: /* C-W */ 459157184Sache /* skip over portion of line we already matched and yank word */ 460157184Sache wstart = rl_point + cxt->search_string_index; 461157184Sache if (wstart >= rl_end) 462157184Sache { 463157184Sache rl_ding (); 464157184Sache break; 465157184Sache } 466119610Sache 467157184Sache /* if not in a word, move to one. */ 468157184Sache cval = _rl_char_value (rl_line_buffer, wstart); 469157184Sache if (_rl_walphabetic (cval) == 0) 470157184Sache { 471157184Sache rl_ding (); 47235486Sache break; 473157184Sache } 474157184Sache n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);; 475157184Sache while (n < rl_end) 476157184Sache { 477157184Sache cval = _rl_char_value (rl_line_buffer, n); 478157184Sache if (_rl_walphabetic (cval) == 0) 479157184Sache break; 480157184Sache n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);; 481157184Sache } 482157184Sache wlen = n - wstart + 1; 483157184Sache if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size) 484157184Sache { 485157184Sache cxt->search_string_size += wlen + 1; 486157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 487157184Sache } 488157184Sache for (; wstart < n; wstart++) 489157184Sache cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart]; 490157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 491157184Sache break; 49235486Sache 493157184Sache case -6: /* C-Y */ 494157184Sache /* skip over portion of line we already matched and yank rest */ 495157184Sache wstart = rl_point + cxt->search_string_index; 496157184Sache if (wstart >= rl_end) 497157184Sache { 498157184Sache rl_ding (); 499119610Sache break; 500157184Sache } 501157184Sache n = rl_end - wstart + 1; 502157184Sache if (cxt->search_string_index + n + 1 >= cxt->search_string_size) 503157184Sache { 504157184Sache cxt->search_string_size += n + 1; 505157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 506157184Sache } 507157184Sache for (n = wstart; n < rl_end; n++) 508157184Sache cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n]; 509157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 510157184Sache break; 511119610Sache 512157184Sache /* Add character to search string and continue search. */ 513157184Sache default: 514157184Sache if (cxt->search_string_index + 2 >= cxt->search_string_size) 515157184Sache { 516157184Sache cxt->search_string_size += 128; 517157184Sache cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); 518157184Sache } 519119610Sache#if defined (HANDLE_MULTIBYTE) 520157184Sache if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 521157184Sache { 522157184Sache int j, l; 523157184Sache for (j = 0, l = strlen (cxt->mb); j < l; ) 524157184Sache cxt->search_string[cxt->search_string_index++] = cxt->mb[j++]; 525157184Sache } 526157184Sache else 527157184Sache#endif 528157184Sache cxt->search_string[cxt->search_string_index++] = c; 529157184Sache cxt->search_string[cxt->search_string_index] = '\0'; 530157184Sache break; 531157184Sache } 532157184Sache 533157184Sache for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; ) 534157184Sache { 535157184Sache limit = cxt->sline_len - cxt->search_string_index + 1; 536157184Sache 537157184Sache /* Search the current line. */ 538157184Sache while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit)) 539157184Sache { 540157184Sache if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index)) 541119610Sache { 542157184Sache cxt->sflags |= SF_FOUND; 543157184Sache break; 544119610Sache } 545119610Sache else 546157184Sache cxt->sline_index += cxt->direction; 54721308Sache } 548157184Sache if (cxt->sflags & SF_FOUND) 549157184Sache break; 55021308Sache 551157184Sache /* Move to the next line, but skip new copies of the line 552157184Sache we just found and lines shorter than the string we're 553157184Sache searching for. */ 554157184Sache do 55521308Sache { 556157184Sache /* Move to the next line. */ 557157184Sache cxt->history_pos += cxt->direction; 55821308Sache 559157184Sache /* At limit for direction? */ 560157184Sache if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen)) 56121308Sache { 562157184Sache cxt->sflags |= SF_FAILED; 563157184Sache break; 56421308Sache } 56521308Sache 566157184Sache /* We will need these later. */ 567157184Sache cxt->sline = cxt->lines[cxt->history_pos]; 568157184Sache cxt->sline_len = strlen (cxt->sline); 569157184Sache } 570157184Sache while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) || 571157184Sache (cxt->search_string_index > cxt->sline_len)); 57221308Sache 573157184Sache if (cxt->sflags & SF_FAILED) 574157184Sache break; 57521308Sache 576157184Sache /* Now set up the line for searching... */ 577157184Sache cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0; 578157184Sache } 57921308Sache 580157184Sache if (cxt->sflags & SF_FAILED) 581157184Sache { 582157184Sache /* We cannot find the search string. Ding the bell. */ 583157184Sache rl_ding (); 584157184Sache cxt->history_pos = cxt->last_found_line; 585157184Sache return 1; 586157184Sache } 58721308Sache 588157184Sache /* We have found the search string. Just display it. But don't 589157184Sache actually move there in the history list until the user accepts 590157184Sache the location. */ 591157184Sache if (cxt->sflags & SF_FOUND) 592157184Sache { 593157184Sache cxt->prev_line_found = cxt->lines[cxt->history_pos]; 594157184Sache rl_replace_line (cxt->lines[cxt->history_pos], 0); 595157184Sache rl_point = cxt->sline_index; 596157184Sache cxt->last_found_line = cxt->history_pos; 597157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos); 598157184Sache } 59921308Sache 600157184Sache return 1; 601157184Sache} 60221308Sache 603157184Sachestatic int 604157184Sache_rl_isearch_cleanup (cxt, r) 605157184Sache _rl_search_cxt *cxt; 606157184Sache int r; 607157184Sache{ 608157184Sache if (r >= 0) 609157184Sache _rl_isearch_fini (cxt); 610157184Sache _rl_scxt_dispose (cxt, 0); 611157184Sache _rl_iscxt = 0; 61221308Sache 613157184Sache RL_UNSETSTATE(RL_STATE_ISEARCH); 61421308Sache 615157184Sache return (r != 0); 616157184Sache} 61721308Sache 618157184Sache/* Search through the history looking for an interactively typed string. 619157184Sache This is analogous to i-search. We start the search in the current line. 620157184Sache DIRECTION is which direction to search; >= 0 means forward, < 0 means 621157184Sache backwards. */ 622157184Sachestatic int 623157184Sacherl_search_history (direction, invoking_key) 624157184Sache int direction, invoking_key; 625157184Sache{ 626157184Sache _rl_search_cxt *cxt; /* local for now, but saved globally */ 627157184Sache int c, r; 62821308Sache 629157184Sache RL_SETSTATE(RL_STATE_ISEARCH); 630157184Sache cxt = _rl_isearch_init (direction); 63121308Sache 632157184Sache rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); 63321308Sache 634157184Sache /* If we are using the callback interface, all we do is set up here and 635157184Sache return. The key is that we leave RL_STATE_ISEARCH set. */ 636157184Sache if (RL_ISSTATE (RL_STATE_CALLBACK)) 637157184Sache return (0); 638157184Sache 639157184Sache r = -1; 640157184Sache for (;;) 641119610Sache { 642157184Sache c = _rl_search_getchar (cxt); 643157184Sache /* We might want to handle EOF here (c == 0) */ 644157184Sache r = _rl_isearch_dispatch (cxt, cxt->lastc); 645157184Sache if (r <= 0) 646157184Sache break; 647119610Sache } 648119610Sache 649157184Sache /* The searching is over. The user may have found the string that she 650157184Sache was looking for, or else she may have exited a failing search. If 651157184Sache LINE_INDEX is -1, then that shows that the string searched for was 652157184Sache not found. We use this to determine where to place rl_point. */ 653157184Sache return (_rl_isearch_cleanup (cxt, r)); 654157184Sache} 655119610Sache 656157184Sache#if defined (READLINE_CALLBACKS) 657157184Sache/* Called from the callback functions when we are ready to read a key. The 658157184Sache callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH). 659157184Sache If _rl_isearch_dispatch finishes searching, this function is responsible 660157184Sache for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */ 661157184Sacheint 662157184Sache_rl_isearch_callback (cxt) 663157184Sache _rl_search_cxt *cxt; 664157184Sache{ 665157184Sache int c, r; 66621308Sache 667157184Sache c = _rl_search_getchar (cxt); 668157184Sache /* We might want to handle EOF here */ 669157184Sache r = _rl_isearch_dispatch (cxt, cxt->lastc); 67021308Sache 671157184Sache return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0; 67221308Sache} 673157184Sache#endif 674