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