histsearch.c revision 136644
172211Sasmodai/* histsearch.c -- searching the history list. */
272211Sasmodai
372211Sasmodai/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
472211Sasmodai
572211Sasmodai   This file contains the GNU History Library (the Library), a set of
672211Sasmodai   routines for managing the text of previously typed lines.
772211Sasmodai
872211Sasmodai   The Library is free software; you can redistribute it and/or modify
972211Sasmodai   it under the terms of the GNU General Public License as published by
1072211Sasmodai   the Free Software Foundation; either version 2, or (at your option)
1172211Sasmodai   any later version.
1272211Sasmodai
1372211Sasmodai   The Library is distributed in the hope that it will be useful, but
1472211Sasmodai   WITHOUT ANY WARRANTY; without even the implied warranty of
1572211Sasmodai   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1672211Sasmodai   General Public License for more details.
1772211Sasmodai
1872211Sasmodai   The GNU General Public License is often shipped with GNU software, and
1972211Sasmodai   is generally kept in a file called COPYING or LICENSE.  If you do not
2072211Sasmodai   have a copy of the license, write to the Free Software Foundation,
2172211Sasmodai   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2272211Sasmodai
2372211Sasmodai#define READLINE_LIBRARY
2472211Sasmodai
2572211Sasmodai#if defined (HAVE_CONFIG_H)
2672211Sasmodai#  include <config.h>
2772211Sasmodai#endif
2872211Sasmodai
2972211Sasmodai#include <stdio.h>
3072211Sasmodai#if defined (HAVE_STDLIB_H)
3172211Sasmodai#  include <stdlib.h>
3272211Sasmodai#else
3372211Sasmodai#  include "ansi_stdlib.h"
3472211Sasmodai#endif /* HAVE_STDLIB_H */
3572211Sasmodai
3672211Sasmodai#if defined (HAVE_UNISTD_H)
37#  ifdef _MINIX
38#    include <sys/types.h>
39#  endif
40#  include <unistd.h>
41#endif
42
43#include "history.h"
44#include "histlib.h"
45
46/* The list of alternate characters that can delimit a history search
47   string. */
48char *history_search_delimiter_chars = (char *)NULL;
49
50static int history_search_internal PARAMS((const char *, int, int));
51
52/* Search the history for STRING, starting at history_offset.
53   If DIRECTION < 0, then the search is through previous entries, else
54   through subsequent.  If ANCHORED is non-zero, the string must
55   appear at the beginning of a history line, otherwise, the string
56   may appear anywhere in the line.  If the string is found, then
57   current_history () is the history entry, and the value of this
58   function is the offset in the line of that history entry that the
59   string was found in.  Otherwise, nothing is changed, and a -1 is
60   returned. */
61
62static int
63history_search_internal (string, direction, anchored)
64     const char *string;
65     int direction, anchored;
66{
67  register int i, reverse;
68  register char *line;
69  register int line_index;
70  int string_len;
71  HIST_ENTRY **the_history; 	/* local */
72
73  i = history_offset;
74  reverse = (direction < 0);
75
76  /* Take care of trivial cases first. */
77  if (string == 0 || *string == '\0')
78    return (-1);
79
80  if (!history_length || ((i >= history_length) && !reverse))
81    return (-1);
82
83  if (reverse && (i >= history_length))
84    i = history_length - 1;
85
86#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
87
88  the_history = history_list ();
89  string_len = strlen (string);
90  while (1)
91    {
92      /* Search each line in the history list for STRING. */
93
94      /* At limit for direction? */
95      if ((reverse && i < 0) || (!reverse && i == history_length))
96	return (-1);
97
98      line = the_history[i]->line;
99      line_index = strlen (line);
100
101      /* If STRING is longer than line, no match. */
102      if (string_len > line_index)
103	{
104	  NEXT_LINE ();
105	  continue;
106	}
107
108      /* Handle anchored searches first. */
109      if (anchored == ANCHORED_SEARCH)
110	{
111	  if (STREQN (string, line, string_len))
112	    {
113	      history_offset = i;
114	      return (0);
115	    }
116
117	  NEXT_LINE ();
118	  continue;
119	}
120
121      /* Do substring search. */
122      if (reverse)
123	{
124	  line_index -= string_len;
125
126	  while (line_index >= 0)
127	    {
128	      if (STREQN (string, line + line_index, string_len))
129		{
130		  history_offset = i;
131		  return (line_index);
132		}
133	      line_index--;
134	    }
135	}
136      else
137	{
138	  register int limit;
139
140	  limit = line_index - string_len + 1;
141	  line_index = 0;
142
143	  while (line_index < limit)
144	    {
145	      if (STREQN (string, line + line_index, string_len))
146		{
147		  history_offset = i;
148		  return (line_index);
149		}
150	      line_index++;
151	    }
152	}
153      NEXT_LINE ();
154    }
155}
156
157/* Do a non-anchored search for STRING through the history in DIRECTION. */
158int
159history_search (string, direction)
160     const char *string;
161     int direction;
162{
163  return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
164}
165
166/* Do an anchored search for string through the history in DIRECTION. */
167int
168history_search_prefix (string, direction)
169     const char *string;
170     int direction;
171{
172  return (history_search_internal (string, direction, ANCHORED_SEARCH));
173}
174
175/* Search for STRING in the history list.  DIR is < 0 for searching
176   backwards.  POS is an absolute index into the history list at
177   which point to begin searching. */
178int
179history_search_pos (string, dir, pos)
180     const char *string;
181     int dir, pos;
182{
183  int ret, old;
184
185  old = where_history ();
186  history_set_pos (pos);
187  if (history_search (string, dir) == -1)
188    {
189      history_set_pos (old);
190      return (-1);
191    }
192  ret = where_history ();
193  history_set_pos (old);
194  return ret;
195}
196