This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / elvis / move2.c
CommitLineData
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
17extern long atol();
18
19static regexp *re; /* compiled version of the pattern to search for */
20static prevsf; /* boolean: previous search direction was forward? */
21
22#ifndef NO_EXTENSIONS
23/*ARGSUSED*/
24MARK 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 47MARK 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
92MARK 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
200MARK 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