1*6b445a62SJohn Marino /* histsearch.c -- searching the history list. */
2*6b445a62SJohn Marino
3*6b445a62SJohn Marino /* Copyright (C) 1989, 1992-2009 Free Software Foundation, Inc.
4*6b445a62SJohn Marino
5*6b445a62SJohn Marino This file contains the GNU History Library (History), a set of
6*6b445a62SJohn Marino routines for managing the text of previously typed lines.
7*6b445a62SJohn Marino
8*6b445a62SJohn Marino History is free software: you can redistribute it and/or modify
9*6b445a62SJohn Marino it under the terms of the GNU General Public License as published by
10*6b445a62SJohn Marino the Free Software Foundation, either version 3 of the License, or
11*6b445a62SJohn Marino (at your option) any later version.
12*6b445a62SJohn Marino
13*6b445a62SJohn Marino History is distributed in the hope that it will be useful,
14*6b445a62SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*6b445a62SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*6b445a62SJohn Marino GNU General Public License for more details.
17*6b445a62SJohn Marino
18*6b445a62SJohn Marino You should have received a copy of the GNU General Public License
19*6b445a62SJohn Marino along with History. If not, see <http://www.gnu.org/licenses/>.
20*6b445a62SJohn Marino */
21*6b445a62SJohn Marino
22*6b445a62SJohn Marino #define READLINE_LIBRARY
23*6b445a62SJohn Marino
24*6b445a62SJohn Marino #if defined (HAVE_CONFIG_H)
25*6b445a62SJohn Marino # include <config.h>
26*6b445a62SJohn Marino #endif
27*6b445a62SJohn Marino
28*6b445a62SJohn Marino #include <stdio.h>
29*6b445a62SJohn Marino #if defined (HAVE_STDLIB_H)
30*6b445a62SJohn Marino # include <stdlib.h>
31*6b445a62SJohn Marino #else
32*6b445a62SJohn Marino # include "ansi_stdlib.h"
33*6b445a62SJohn Marino #endif /* HAVE_STDLIB_H */
34*6b445a62SJohn Marino
35*6b445a62SJohn Marino #if defined (HAVE_UNISTD_H)
36*6b445a62SJohn Marino # ifdef _MINIX
37*6b445a62SJohn Marino # include <sys/types.h>
38*6b445a62SJohn Marino # endif
39*6b445a62SJohn Marino # include <unistd.h>
40*6b445a62SJohn Marino #endif
41*6b445a62SJohn Marino
42*6b445a62SJohn Marino #include "history.h"
43*6b445a62SJohn Marino #include "histlib.h"
44*6b445a62SJohn Marino
45*6b445a62SJohn Marino /* The list of alternate characters that can delimit a history search
46*6b445a62SJohn Marino string. */
47*6b445a62SJohn Marino char *history_search_delimiter_chars = (char *)NULL;
48*6b445a62SJohn Marino
49*6b445a62SJohn Marino static int history_search_internal PARAMS((const char *, int, int));
50*6b445a62SJohn Marino
51*6b445a62SJohn Marino /* Search the history for STRING, starting at history_offset.
52*6b445a62SJohn Marino If DIRECTION < 0, then the search is through previous entries, else
53*6b445a62SJohn Marino through subsequent. If ANCHORED is non-zero, the string must
54*6b445a62SJohn Marino appear at the beginning of a history line, otherwise, the string
55*6b445a62SJohn Marino may appear anywhere in the line. If the string is found, then
56*6b445a62SJohn Marino current_history () is the history entry, and the value of this
57*6b445a62SJohn Marino function is the offset in the line of that history entry that the
58*6b445a62SJohn Marino string was found in. Otherwise, nothing is changed, and a -1 is
59*6b445a62SJohn Marino returned. */
60*6b445a62SJohn Marino
61*6b445a62SJohn Marino static int
history_search_internal(string,direction,anchored)62*6b445a62SJohn Marino history_search_internal (string, direction, anchored)
63*6b445a62SJohn Marino const char *string;
64*6b445a62SJohn Marino int direction, anchored;
65*6b445a62SJohn Marino {
66*6b445a62SJohn Marino register int i, reverse;
67*6b445a62SJohn Marino register char *line;
68*6b445a62SJohn Marino register int line_index;
69*6b445a62SJohn Marino int string_len;
70*6b445a62SJohn Marino HIST_ENTRY **the_history; /* local */
71*6b445a62SJohn Marino
72*6b445a62SJohn Marino i = history_offset;
73*6b445a62SJohn Marino reverse = (direction < 0);
74*6b445a62SJohn Marino
75*6b445a62SJohn Marino /* Take care of trivial cases first. */
76*6b445a62SJohn Marino if (string == 0 || *string == '\0')
77*6b445a62SJohn Marino return (-1);
78*6b445a62SJohn Marino
79*6b445a62SJohn Marino if (!history_length || ((i >= history_length) && !reverse))
80*6b445a62SJohn Marino return (-1);
81*6b445a62SJohn Marino
82*6b445a62SJohn Marino if (reverse && (i >= history_length))
83*6b445a62SJohn Marino i = history_length - 1;
84*6b445a62SJohn Marino
85*6b445a62SJohn Marino #define NEXT_LINE() do { if (reverse) i--; else i++; } while (0)
86*6b445a62SJohn Marino
87*6b445a62SJohn Marino the_history = history_list ();
88*6b445a62SJohn Marino string_len = strlen (string);
89*6b445a62SJohn Marino while (1)
90*6b445a62SJohn Marino {
91*6b445a62SJohn Marino /* Search each line in the history list for STRING. */
92*6b445a62SJohn Marino
93*6b445a62SJohn Marino /* At limit for direction? */
94*6b445a62SJohn Marino if ((reverse && i < 0) || (!reverse && i == history_length))
95*6b445a62SJohn Marino return (-1);
96*6b445a62SJohn Marino
97*6b445a62SJohn Marino line = the_history[i]->line;
98*6b445a62SJohn Marino line_index = strlen (line);
99*6b445a62SJohn Marino
100*6b445a62SJohn Marino /* If STRING is longer than line, no match. */
101*6b445a62SJohn Marino if (string_len > line_index)
102*6b445a62SJohn Marino {
103*6b445a62SJohn Marino NEXT_LINE ();
104*6b445a62SJohn Marino continue;
105*6b445a62SJohn Marino }
106*6b445a62SJohn Marino
107*6b445a62SJohn Marino /* Handle anchored searches first. */
108*6b445a62SJohn Marino if (anchored == ANCHORED_SEARCH)
109*6b445a62SJohn Marino {
110*6b445a62SJohn Marino if (STREQN (string, line, string_len))
111*6b445a62SJohn Marino {
112*6b445a62SJohn Marino history_offset = i;
113*6b445a62SJohn Marino return (0);
114*6b445a62SJohn Marino }
115*6b445a62SJohn Marino
116*6b445a62SJohn Marino NEXT_LINE ();
117*6b445a62SJohn Marino continue;
118*6b445a62SJohn Marino }
119*6b445a62SJohn Marino
120*6b445a62SJohn Marino /* Do substring search. */
121*6b445a62SJohn Marino if (reverse)
122*6b445a62SJohn Marino {
123*6b445a62SJohn Marino line_index -= string_len;
124*6b445a62SJohn Marino
125*6b445a62SJohn Marino while (line_index >= 0)
126*6b445a62SJohn Marino {
127*6b445a62SJohn Marino if (STREQN (string, line + line_index, string_len))
128*6b445a62SJohn Marino {
129*6b445a62SJohn Marino history_offset = i;
130*6b445a62SJohn Marino return (line_index);
131*6b445a62SJohn Marino }
132*6b445a62SJohn Marino line_index--;
133*6b445a62SJohn Marino }
134*6b445a62SJohn Marino }
135*6b445a62SJohn Marino else
136*6b445a62SJohn Marino {
137*6b445a62SJohn Marino register int limit;
138*6b445a62SJohn Marino
139*6b445a62SJohn Marino limit = line_index - string_len + 1;
140*6b445a62SJohn Marino line_index = 0;
141*6b445a62SJohn Marino
142*6b445a62SJohn Marino while (line_index < limit)
143*6b445a62SJohn Marino {
144*6b445a62SJohn Marino if (STREQN (string, line + line_index, string_len))
145*6b445a62SJohn Marino {
146*6b445a62SJohn Marino history_offset = i;
147*6b445a62SJohn Marino return (line_index);
148*6b445a62SJohn Marino }
149*6b445a62SJohn Marino line_index++;
150*6b445a62SJohn Marino }
151*6b445a62SJohn Marino }
152*6b445a62SJohn Marino NEXT_LINE ();
153*6b445a62SJohn Marino }
154*6b445a62SJohn Marino }
155*6b445a62SJohn Marino
156*6b445a62SJohn Marino /* Do a non-anchored search for STRING through the history in DIRECTION. */
157*6b445a62SJohn Marino int
history_search(string,direction)158*6b445a62SJohn Marino history_search (string, direction)
159*6b445a62SJohn Marino const char *string;
160*6b445a62SJohn Marino int direction;
161*6b445a62SJohn Marino {
162*6b445a62SJohn Marino return (history_search_internal (string, direction, NON_ANCHORED_SEARCH));
163*6b445a62SJohn Marino }
164*6b445a62SJohn Marino
165*6b445a62SJohn Marino /* Do an anchored search for string through the history in DIRECTION. */
166*6b445a62SJohn Marino int
history_search_prefix(string,direction)167*6b445a62SJohn Marino history_search_prefix (string, direction)
168*6b445a62SJohn Marino const char *string;
169*6b445a62SJohn Marino int direction;
170*6b445a62SJohn Marino {
171*6b445a62SJohn Marino return (history_search_internal (string, direction, ANCHORED_SEARCH));
172*6b445a62SJohn Marino }
173*6b445a62SJohn Marino
174*6b445a62SJohn Marino /* Search for STRING in the history list. DIR is < 0 for searching
175*6b445a62SJohn Marino backwards. POS is an absolute index into the history list at
176*6b445a62SJohn Marino which point to begin searching. */
177*6b445a62SJohn Marino int
history_search_pos(string,dir,pos)178*6b445a62SJohn Marino history_search_pos (string, dir, pos)
179*6b445a62SJohn Marino const char *string;
180*6b445a62SJohn Marino int dir, pos;
181*6b445a62SJohn Marino {
182*6b445a62SJohn Marino int ret, old;
183*6b445a62SJohn Marino
184*6b445a62SJohn Marino old = where_history ();
185*6b445a62SJohn Marino history_set_pos (pos);
186*6b445a62SJohn Marino if (history_search (string, dir) == -1)
187*6b445a62SJohn Marino {
188*6b445a62SJohn Marino history_set_pos (old);
189*6b445a62SJohn Marino return (-1);
190*6b445a62SJohn Marino }
191*6b445a62SJohn Marino ret = where_history ();
192*6b445a62SJohn Marino history_set_pos (old);
193*6b445a62SJohn Marino return ret;
194*6b445a62SJohn Marino }
195