histsearch.c revision 75406
115845Splevart/* histsearch.c -- searching the history list. */ 215845Splevart 315845Splevart/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. 415845Splevart 515845Splevart This file contains the GNU History Library (the Library), a set of 615845Splevart routines for managing the text of previously typed lines. 715845Splevart 815845Splevart The Library is free software; you can redistribute it and/or modify 915845Splevart it under the terms of the GNU General Public License as published by 1015845Splevart the Free Software Foundation; either version 2, or (at your option) 1115845Splevart any later version. 1215845Splevart 1315845Splevart The Library is distributed in the hope that it will be useful, but 1415845Splevart WITHOUT ANY WARRANTY; without even the implied warranty of 1515845Splevart MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1615845Splevart General Public License for more details. 1715845Splevart 1815845Splevart The GNU General Public License is often shipped with GNU software, and 1915845Splevart is generally kept in a file called COPYING or LICENSE. If you do not 2015845Splevart have a copy of the license, write to the Free Software Foundation, 2115845Splevart 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2215845Splevart 2315845Splevart#define READLINE_LIBRARY 2415845Splevart 2515845Splevart#if defined (HAVE_CONFIG_H) 2615845Splevart# include <config.h> 2715845Splevart#endif 2815845Splevart 2915845Splevart#include <stdio.h> 3015845Splevart#if defined (HAVE_STDLIB_H) 3115845Splevart# include <stdlib.h> 3215845Splevart#else 3315845Splevart# include "ansi_stdlib.h" 3415845Splevart#endif /* HAVE_STDLIB_H */ 3515845Splevart#if defined (HAVE_UNISTD_H) 3615845Splevart# ifdef _MINIX 3715845Splevart# include <sys/types.h> 3815845Splevart# endif 3915845Splevart# include <unistd.h> 4015845Splevart#endif 4115845Splevart#if defined (HAVE_STRING_H) 4215845Splevart# include <string.h> 4315845Splevart#else 4415845Splevart# include <strings.h> 4515845Splevart#endif /* !HAVE_STRING_H */ 4615845Splevart 4715845Splevart#include "history.h" 4815845Splevart#include "histlib.h" 4915845Splevart 5015845Splevart/* The list of alternate characters that can delimit a history search 5115845Splevart string. */ 5215845Splevartchar *history_search_delimiter_chars = (char *)NULL; 5315845Splevart 5415845Splevart/* Search the history for STRING, starting at history_offset. 5515845Splevart If DIRECTION < 0, then the search is through previous entries, else 5615845Splevart through subsequent. If ANCHORED is non-zero, the string must 5715845Splevart appear at the beginning of a history line, otherwise, the string 5815845Splevart may appear anywhere in the line. If the string is found, then 5915845Splevart current_history () is the history entry, and the value of this 6015845Splevart function is the offset in the line of that history entry that the 6115845Splevart string was found in. Otherwise, nothing is changed, and a -1 is 6215845Splevart returned. */ 6315845Splevart 6415845Splevartstatic int 6515845Splevarthistory_search_internal (string, direction, anchored) 6615845Splevart const char *string; 6715845Splevart int direction, anchored; 6815845Splevart{ 6915845Splevart register int i, reverse; 7015845Splevart register char *line; 7115845Splevart register int line_index; 7215845Splevart int string_len; 7315845Splevart HIST_ENTRY **the_history; /* local */ 7415845Splevart 7515845Splevart i = history_offset; 7615845Splevart reverse = (direction < 0); 7715845Splevart 7815845Splevart /* Take care of trivial cases first. */ 7915845Splevart if (string == 0 || *string == '\0') 8015845Splevart return (-1); 8115845Splevart 8215845Splevart if (!history_length || ((i == history_length) && !reverse)) 83 return (-1); 84 85 if (reverse && (i == history_length)) 86 i--; 87 88#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) 89 90 the_history = history_list (); 91 string_len = strlen (string); 92 while (1) 93 { 94 /* Search each line in the history list for STRING. */ 95 96 /* At limit for direction? */ 97 if ((reverse && i < 0) || (!reverse && i == history_length)) 98 return (-1); 99 100 line = the_history[i]->line; 101 line_index = strlen (line); 102 103 /* If STRING is longer than line, no match. */ 104 if (string_len > line_index) 105 { 106 NEXT_LINE (); 107 continue; 108 } 109 110 /* Handle anchored searches first. */ 111 if (anchored == ANCHORED_SEARCH) 112 { 113 if (STREQN (string, line, string_len)) 114 { 115 history_offset = i; 116 return (0); 117 } 118 119 NEXT_LINE (); 120 continue; 121 } 122 123 /* Do substring search. */ 124 if (reverse) 125 { 126 line_index -= string_len; 127 128 while (line_index >= 0) 129 { 130 if (STREQN (string, line + line_index, string_len)) 131 { 132 history_offset = i; 133 return (line_index); 134 } 135 line_index--; 136 } 137 } 138 else 139 { 140 register int limit; 141 142 limit = line_index - string_len + 1; 143 line_index = 0; 144 145 while (line_index < limit) 146 { 147 if (STREQN (string, line + line_index, string_len)) 148 { 149 history_offset = i; 150 return (line_index); 151 } 152 line_index++; 153 } 154 } 155 NEXT_LINE (); 156 } 157} 158 159/* Do a non-anchored search for STRING through the history in DIRECTION. */ 160int 161history_search (string, direction) 162 const char *string; 163 int direction; 164{ 165 return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); 166} 167 168/* Do an anchored search for string through the history in DIRECTION. */ 169int 170history_search_prefix (string, direction) 171 const char *string; 172 int direction; 173{ 174 return (history_search_internal (string, direction, ANCHORED_SEARCH)); 175} 176 177/* Search for STRING in the history list. DIR is < 0 for searching 178 backwards. POS is an absolute index into the history list at 179 which point to begin searching. */ 180int 181history_search_pos (string, dir, pos) 182 const char *string; 183 int dir, pos; 184{ 185 int ret, old; 186 187 old = where_history (); 188 history_set_pos (pos); 189 if (history_search (string, dir) == -1) 190 { 191 history_set_pos (old); 192 return (-1); 193 } 194 ret = where_history (); 195 history_set_pos (old); 196 return ret; 197} 198