Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* move2.c */ |
2 | ||
3 | /* Author: | |
4 | * Steve Kirkendall | |
5 | * 14407 SW Teal Blvd. #C | |
6 | * Beaverton, OR 97005 | |
7 | * kirkenda@cs.pdx.edu | |
8 | */ | |
9 | ||
10 | ||
11 | /* This function contains the movement functions that perform RE searching */ | |
12 | ||
13 | #include "config.h" | |
14 | #include "vi.h" | |
15 | #include "regexp.h" | |
16 | ||
17 | extern long atol(); | |
18 | ||
19 | static regexp *re; /* compiled version of the pattern to search for */ | |
20 | static prevsf; /* boolean: previous search direction was forward? */ | |
21 | ||
22 | #ifndef NO_EXTENSIONS | |
23 | /*ARGSUSED*/ | |
24 | MARK m_wsrch(word, m, cnt) | |
25 | char *word; /* the word to search for */ | |
26 | MARK m; /* the starting point */ | |
27 | int cnt; /* ignored */ | |
28 | { | |
29 | char buffer[30]; | |
30 | ||
31 | /* wrap \< and \> around the word */ | |
32 | strcpy(buffer, "/\\<"); | |
33 | strcat(buffer, word); | |
34 | strcat(buffer, "\\>"); | |
35 | ||
36 | /* show the searched-for word on the bottom line */ | |
37 | move(LINES - 1, 0); | |
38 | qaddstr(buffer); | |
39 | clrtoeol(); | |
40 | refresh(); | |
41 | ||
42 | /* search for the word */ | |
43 | return m_fsrch(m, buffer); | |
44 | } | |
45 | #endif | |
46 | ||
08746e8b | 47 | MARK m_nsrch(m, cnt, cmd) |
15637ed4 | 48 | MARK m; /* where to start searching */ |
08746e8b AM |
49 | long cnt; /* number of searches to do */ |
50 | int cmd; /* command character -- 'n' or 'N' */ | |
15637ed4 | 51 | { |
08746e8b | 52 | int oldprevsf; /* original value of prevsf, so we can fix any changes */ |
15637ed4 | 53 | |
08746e8b AM |
54 | DEFAULT(1L); |
55 | ||
56 | /* clear the bottom line. In particular, we want to loose any | |
57 | * "(wrapped)" notice. | |
58 | */ | |
59 | move(LINES - 1, 0); | |
60 | clrtoeol(); | |
61 | ||
62 | /* if 'N' command, then invert the "prevsf" variable */ | |
63 | oldprevsf = prevsf; | |
64 | if (cmd == 'N') | |
15637ed4 | 65 | { |
08746e8b | 66 | prevsf = !prevsf; |
15637ed4 | 67 | } |
08746e8b AM |
68 | |
69 | /* search forward if prevsf -- i.e., if previous search was forward */ | |
70 | while (--cnt >= 0L && m != MARK_UNSET) | |
15637ed4 | 71 | { |
08746e8b AM |
72 | if (prevsf) |
73 | { | |
74 | m = m_fsrch(m, (char *)0); | |
75 | } | |
76 | else | |
77 | { | |
78 | m = m_bsrch(m, (char *)0); | |
79 | } | |
15637ed4 | 80 | } |
08746e8b AM |
81 | |
82 | /* restore the old value of prevsf -- if cmd=='N' then it was inverted, | |
83 | * and the m_fsrch() and m_bsrch() functions force it to a (possibly | |
84 | * incorrect) value. The value of prevsf isn't supposed to be changed | |
85 | * at all here! | |
86 | */ | |
87 | prevsf = oldprevsf; | |
15637ed4 RG |
88 | return m; |
89 | } | |
90 | ||
08746e8b | 91 | |
15637ed4 RG |
92 | MARK m_fsrch(m, ptrn) |
93 | MARK m; /* where to start searching */ | |
94 | char *ptrn; /* pattern to search for */ | |
95 | { | |
96 | long l; /* line# of line to be searched */ | |
97 | char *line; /* text of line to be searched */ | |
98 | int wrapped;/* boolean: has our search wrapped yet? */ | |
99 | int pos; /* where we are in the line */ | |
100 | #ifndef CRUNCH | |
101 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */ | |
102 | #endif | |
103 | ||
104 | /* remember: "previous search was forward" */ | |
105 | prevsf = TRUE; | |
106 | ||
107 | if (ptrn && *ptrn) | |
108 | { | |
109 | /* locate the closing '/', if any */ | |
110 | line = parseptrn(ptrn); | |
111 | #ifndef CRUNCH | |
112 | if (*line) | |
113 | { | |
114 | delta = atol(line); | |
115 | } | |
116 | #endif | |
117 | ptrn++; | |
118 | ||
119 | /* free the previous pattern */ | |
08746e8b | 120 | if (re) _free_(re); |
15637ed4 RG |
121 | |
122 | /* compile the pattern */ | |
123 | re = regcomp(ptrn); | |
124 | if (!re) | |
125 | { | |
126 | return MARK_UNSET; | |
127 | } | |
128 | } | |
129 | else if (!re) | |
130 | { | |
131 | msg("No previous expression"); | |
132 | return MARK_UNSET; | |
133 | } | |
134 | ||
135 | /* search forward for the pattern */ | |
136 | pos = markidx(m) + 1; | |
137 | pfetch(markline(m)); | |
138 | if (pos >= plen) | |
139 | { | |
140 | pos = 0; | |
141 | m = (m | (BLKSIZE - 1)) + 1; | |
142 | } | |
143 | wrapped = FALSE; | |
144 | for (l = markline(m); l != markline(m) + 1 || !wrapped; l++) | |
145 | { | |
146 | /* wrap search */ | |
147 | if (l > nlines) | |
148 | { | |
149 | /* if we wrapped once already, then the search failed */ | |
150 | if (wrapped) | |
151 | { | |
152 | break; | |
153 | } | |
154 | ||
155 | /* else maybe we should wrap now? */ | |
156 | if (*o_wrapscan) | |
157 | { | |
158 | l = 0; | |
159 | wrapped = TRUE; | |
160 | continue; | |
161 | } | |
162 | else | |
163 | { | |
164 | break; | |
165 | } | |
166 | } | |
167 | ||
168 | /* get this line */ | |
169 | line = fetchline(l); | |
170 | ||
171 | /* check this line */ | |
172 | if (regexec(re, &line[pos], (pos == 0))) | |
173 | { | |
174 | /* match! */ | |
175 | if (wrapped && *o_warn) | |
176 | msg("(wrapped)"); | |
177 | #ifndef CRUNCH | |
178 | if (delta != INFINITY) | |
179 | { | |
180 | l += delta; | |
181 | if (l < 1 || l > nlines) | |
182 | { | |
183 | msg("search offset too big"); | |
184 | return MARK_UNSET; | |
185 | } | |
186 | force_flags = LNMD|INCL; | |
187 | return MARK_AT_LINE(l); | |
188 | } | |
189 | #endif | |
190 | return MARK_AT_LINE(l) + (int)(re->startp[0] - line); | |
191 | } | |
192 | pos = 0; | |
193 | } | |
194 | ||
195 | /* not found */ | |
196 | msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE"); | |
197 | return MARK_UNSET; | |
198 | } | |
199 | ||
200 | MARK m_bsrch(m, ptrn) | |
201 | MARK m; /* where to start searching */ | |
202 | char *ptrn; /* pattern to search for */ | |
203 | { | |
204 | long l; /* line# of line to be searched */ | |
205 | char *line; /* text of line to be searched */ | |
206 | int wrapped;/* boolean: has our search wrapped yet? */ | |
207 | int pos; /* last acceptable idx for a match on this line */ | |
208 | int last; /* remembered idx of the last acceptable match on this line */ | |
209 | int try; /* an idx at which we strat searching for another match */ | |
210 | #ifndef CRUNCH | |
211 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */ | |
212 | #endif | |
213 | ||
214 | /* remember: "previous search was not forward" */ | |
215 | prevsf = FALSE; | |
216 | ||
217 | if (ptrn && *ptrn) | |
218 | { | |
219 | /* locate the closing '?', if any */ | |
220 | line = parseptrn(ptrn); | |
221 | #ifndef CRUNCH | |
222 | if (*line) | |
223 | { | |
224 | delta = atol(line); | |
225 | } | |
226 | #endif | |
227 | ptrn++; | |
228 | ||
229 | /* free the previous pattern, if any */ | |
08746e8b | 230 | if (re) _free_(re); |
15637ed4 RG |
231 | |
232 | /* compile the pattern */ | |
233 | re = regcomp(ptrn); | |
234 | if (!re) | |
235 | { | |
236 | return MARK_UNSET; | |
237 | } | |
238 | } | |
239 | else if (!re) | |
240 | { | |
241 | msg("No previous expression"); | |
242 | return MARK_UNSET; | |
243 | } | |
244 | ||
245 | /* search backward for the pattern */ | |
246 | pos = markidx(m); | |
247 | wrapped = FALSE; | |
248 | for (l = markline(m); l != markline(m) - 1 || !wrapped; l--) | |
249 | { | |
250 | /* wrap search */ | |
251 | if (l < 1) | |
252 | { | |
253 | if (*o_wrapscan) | |
254 | { | |
255 | l = nlines + 1; | |
256 | wrapped = TRUE; | |
257 | continue; | |
258 | } | |
259 | else | |
260 | { | |
261 | break; | |
262 | } | |
263 | } | |
264 | ||
265 | /* get this line */ | |
266 | line = fetchline(l); | |
267 | ||
268 | /* check this line */ | |
269 | if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos) | |
270 | { | |
271 | /* match! now find the last acceptable one in this line */ | |
272 | do | |
273 | { | |
274 | last = (int)(re->startp[0] - line); | |
275 | try = (int)(re->endp[0] - line); | |
276 | } while (try > 0 | |
277 | && regexec(re, &line[try], FALSE) | |
278 | && (int)(re->startp[0] - line) < pos); | |
279 | ||
280 | if (wrapped && *o_warn) | |
281 | msg("(wrapped)"); | |
282 | #ifndef CRUNCH | |
283 | if (delta != INFINITY) | |
284 | { | |
285 | l += delta; | |
286 | if (l < 1 || l > nlines) | |
287 | { | |
288 | msg("search offset too big"); | |
289 | return MARK_UNSET; | |
290 | } | |
291 | force_flags = LNMD|INCL; | |
292 | return MARK_AT_LINE(l); | |
293 | } | |
294 | #endif | |
295 | return MARK_AT_LINE(l) + last; | |
296 | } | |
297 | pos = BLKSIZE; | |
298 | } | |
299 | ||
300 | /* not found */ | |
301 | msg(*o_wrapscan ? "Not found" : "Hit top without finding RE"); | |
302 | return MARK_UNSET; | |
303 | } | |
304 |