Commit | Line | Data |
---|---|---|
f5bcab4b WJ |
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 | ||
47 | MARK m_nsrch(m) | |
48 | MARK m; /* where to start searching */ | |
49 | { | |
50 | if (prevsf) | |
51 | { | |
52 | m = m_fsrch(m, (char *)0); | |
53 | prevsf = TRUE; | |
54 | } | |
55 | else | |
56 | { | |
57 | m = m_bsrch(m, (char *)0); | |
58 | prevsf = FALSE; | |
59 | } | |
60 | return m; | |
61 | } | |
62 | ||
63 | MARK m_Nsrch(m) | |
64 | MARK m; /* where to start searching */ | |
65 | { | |
66 | if (prevsf) | |
67 | { | |
68 | m = m_bsrch(m, (char *)0); | |
69 | prevsf = TRUE; | |
70 | } | |
71 | else | |
72 | { | |
73 | m = m_fsrch(m, (char *)0); | |
74 | prevsf = FALSE; | |
75 | } | |
76 | return m; | |
77 | } | |
78 | ||
79 | MARK m_fsrch(m, ptrn) | |
80 | MARK m; /* where to start searching */ | |
81 | char *ptrn; /* pattern to search for */ | |
82 | { | |
83 | long l; /* line# of line to be searched */ | |
84 | char *line; /* text of line to be searched */ | |
85 | int wrapped;/* boolean: has our search wrapped yet? */ | |
86 | int pos; /* where we are in the line */ | |
87 | #ifndef CRUNCH | |
88 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */ | |
89 | #endif | |
90 | ||
91 | /* remember: "previous search was forward" */ | |
92 | prevsf = TRUE; | |
93 | ||
94 | if (ptrn && *ptrn) | |
95 | { | |
96 | /* locate the closing '/', if any */ | |
97 | line = parseptrn(ptrn); | |
98 | #ifndef CRUNCH | |
99 | if (*line) | |
100 | { | |
101 | delta = atol(line); | |
102 | } | |
103 | #endif | |
104 | ptrn++; | |
105 | ||
106 | /* free the previous pattern */ | |
107 | if (re) free(re); | |
108 | ||
109 | /* compile the pattern */ | |
110 | re = regcomp(ptrn); | |
111 | if (!re) | |
112 | { | |
113 | return MARK_UNSET; | |
114 | } | |
115 | } | |
116 | else if (!re) | |
117 | { | |
118 | msg("No previous expression"); | |
119 | return MARK_UNSET; | |
120 | } | |
121 | ||
122 | /* search forward for the pattern */ | |
123 | pos = markidx(m) + 1; | |
124 | pfetch(markline(m)); | |
125 | if (pos >= plen) | |
126 | { | |
127 | pos = 0; | |
128 | m = (m | (BLKSIZE - 1)) + 1; | |
129 | } | |
130 | wrapped = FALSE; | |
131 | for (l = markline(m); l != markline(m) + 1 || !wrapped; l++) | |
132 | { | |
133 | /* wrap search */ | |
134 | if (l > nlines) | |
135 | { | |
136 | /* if we wrapped once already, then the search failed */ | |
137 | if (wrapped) | |
138 | { | |
139 | break; | |
140 | } | |
141 | ||
142 | /* else maybe we should wrap now? */ | |
143 | if (*o_wrapscan) | |
144 | { | |
145 | l = 0; | |
146 | wrapped = TRUE; | |
147 | continue; | |
148 | } | |
149 | else | |
150 | { | |
151 | break; | |
152 | } | |
153 | } | |
154 | ||
155 | /* get this line */ | |
156 | line = fetchline(l); | |
157 | ||
158 | /* check this line */ | |
159 | if (regexec(re, &line[pos], (pos == 0))) | |
160 | { | |
161 | /* match! */ | |
162 | if (wrapped && *o_warn) | |
163 | msg("(wrapped)"); | |
164 | #ifndef CRUNCH | |
165 | if (delta != INFINITY) | |
166 | { | |
167 | l += delta; | |
168 | if (l < 1 || l > nlines) | |
169 | { | |
170 | msg("search offset too big"); | |
171 | return MARK_UNSET; | |
172 | } | |
173 | force_flags = LNMD|INCL; | |
174 | return MARK_AT_LINE(l); | |
175 | } | |
176 | #endif | |
177 | return MARK_AT_LINE(l) + (int)(re->startp[0] - line); | |
178 | } | |
179 | pos = 0; | |
180 | } | |
181 | ||
182 | /* not found */ | |
183 | msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE"); | |
184 | return MARK_UNSET; | |
185 | } | |
186 | ||
187 | MARK m_bsrch(m, ptrn) | |
188 | MARK m; /* where to start searching */ | |
189 | char *ptrn; /* pattern to search for */ | |
190 | { | |
191 | long l; /* line# of line to be searched */ | |
192 | char *line; /* text of line to be searched */ | |
193 | int wrapped;/* boolean: has our search wrapped yet? */ | |
194 | int pos; /* last acceptable idx for a match on this line */ | |
195 | int last; /* remembered idx of the last acceptable match on this line */ | |
196 | int try; /* an idx at which we strat searching for another match */ | |
197 | #ifndef CRUNCH | |
198 | long delta = INFINITY;/* line offset, for things like "/foo/+1" */ | |
199 | #endif | |
200 | ||
201 | /* remember: "previous search was not forward" */ | |
202 | prevsf = FALSE; | |
203 | ||
204 | if (ptrn && *ptrn) | |
205 | { | |
206 | /* locate the closing '?', if any */ | |
207 | line = parseptrn(ptrn); | |
208 | #ifndef CRUNCH | |
209 | if (*line) | |
210 | { | |
211 | delta = atol(line); | |
212 | } | |
213 | #endif | |
214 | ptrn++; | |
215 | ||
216 | /* free the previous pattern, if any */ | |
217 | if (re) free(re); | |
218 | ||
219 | /* compile the pattern */ | |
220 | re = regcomp(ptrn); | |
221 | if (!re) | |
222 | { | |
223 | return MARK_UNSET; | |
224 | } | |
225 | } | |
226 | else if (!re) | |
227 | { | |
228 | msg("No previous expression"); | |
229 | return MARK_UNSET; | |
230 | } | |
231 | ||
232 | /* search backward for the pattern */ | |
233 | pos = markidx(m); | |
234 | wrapped = FALSE; | |
235 | for (l = markline(m); l != markline(m) - 1 || !wrapped; l--) | |
236 | { | |
237 | /* wrap search */ | |
238 | if (l < 1) | |
239 | { | |
240 | if (*o_wrapscan) | |
241 | { | |
242 | l = nlines + 1; | |
243 | wrapped = TRUE; | |
244 | continue; | |
245 | } | |
246 | else | |
247 | { | |
248 | break; | |
249 | } | |
250 | } | |
251 | ||
252 | /* get this line */ | |
253 | line = fetchline(l); | |
254 | ||
255 | /* check this line */ | |
256 | if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos) | |
257 | { | |
258 | /* match! now find the last acceptable one in this line */ | |
259 | do | |
260 | { | |
261 | last = (int)(re->startp[0] - line); | |
262 | try = (int)(re->endp[0] - line); | |
263 | } while (try > 0 | |
264 | && regexec(re, &line[try], FALSE) | |
265 | && (int)(re->startp[0] - line) < pos); | |
266 | ||
267 | if (wrapped && *o_warn) | |
268 | msg("(wrapped)"); | |
269 | #ifndef CRUNCH | |
270 | if (delta != INFINITY) | |
271 | { | |
272 | l += delta; | |
273 | if (l < 1 || l > nlines) | |
274 | { | |
275 | msg("search offset too big"); | |
276 | return MARK_UNSET; | |
277 | } | |
278 | force_flags = LNMD|INCL; | |
279 | return MARK_AT_LINE(l); | |
280 | } | |
281 | #endif | |
282 | return MARK_AT_LINE(l) + last; | |
283 | } | |
284 | pos = BLKSIZE; | |
285 | } | |
286 | ||
287 | /* not found */ | |
288 | msg(*o_wrapscan ? "Not found" : "Hit top without finding RE"); | |
289 | return MARK_UNSET; | |
290 | } | |
291 |