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