Initial revision
[nvi.git] / vi / v_search.c
bloba50c0ea895ec9a72fb0181f401bf5ef74d65994f
1 /* move2.c */
3 /* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
11 /* This function contains the movement functions that perform RE searching */
13 #include "config.h"
14 #include "vi.h"
15 #include "regexp.h"
17 extern long atol();
19 static regexp *re; /* compiled version of the pattern to search for */
20 static prevsf; /* boolean: previous search direction was forward? */
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 */
29 char buffer[30];
31 /* wrap \< and \> around the word */
32 strcpy(buffer, "/\\<");
33 strcat(buffer, word);
34 strcat(buffer, "\\>");
36 /* show the searched-for word on the bottom line */
37 move(LINES - 1, 0);
38 qaddstr(buffer);
39 clrtoeol();
40 refresh();
42 /* search for the word */
43 return m_fsrch(m, buffer);
45 #endif
47 MARK m_nsrch(m)
48 MARK m; /* where to start searching */
50 if (prevsf)
52 m = m_fsrch(m, (char *)0);
53 prevsf = TRUE;
55 else
57 m = m_bsrch(m, (char *)0);
58 prevsf = FALSE;
60 return m;
63 MARK m_Nsrch(m)
64 MARK m; /* where to start searching */
66 if (prevsf)
68 m = m_bsrch(m, (char *)0);
69 prevsf = TRUE;
71 else
73 m = m_fsrch(m, (char *)0);
74 prevsf = FALSE;
76 return m;
79 MARK m_fsrch(m, ptrn)
80 MARK m; /* where to start searching */
81 char *ptrn; /* pattern to search for */
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
91 /* remember: "previous search was forward" */
92 prevsf = TRUE;
94 if (ptrn && *ptrn)
96 /* locate the closing '/', if any */
97 line = parseptrn(ptrn);
98 #ifndef CRUNCH
99 if (*line)
101 delta = atol(line);
103 #endif
104 ptrn++;
106 /* free the previous pattern */
107 if (re) free(re);
109 /* compile the pattern */
110 re = regcomp(ptrn);
111 if (!re)
113 return MARK_UNSET;
116 else if (!re)
118 msg("No previous expression");
119 return MARK_UNSET;
122 /* search forward for the pattern */
123 pos = markidx(m) + 1;
124 pfetch(markline(m));
125 if (pos >= plen)
127 pos = 0;
128 m = (m | (BLKSIZE - 1)) + 1;
130 wrapped = FALSE;
131 for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
133 /* wrap search */
134 if (l > nlines)
136 /* if we wrapped once already, then the search failed */
137 if (wrapped)
139 break;
142 /* else maybe we should wrap now? */
143 if (*o_wrapscan)
145 l = 0;
146 wrapped = TRUE;
147 continue;
149 else
151 break;
155 /* get this line */
156 line = fetchline(l);
158 /* check this line */
159 if (regexec(re, &line[pos], (pos == 0)))
161 /* match! */
162 if (wrapped && *o_warn)
163 msg("(wrapped)");
164 #ifndef CRUNCH
165 if (delta != INFINITY)
167 l += delta;
168 if (l < 1 || l > nlines)
170 msg("search offset too big");
171 return MARK_UNSET;
173 force_lnmd = TRUE;
174 return MARK_AT_LINE(l);
176 #endif
177 return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
179 pos = 0;
182 /* not found */
183 msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
184 return MARK_UNSET;
187 MARK m_bsrch(m, ptrn)
188 MARK m; /* where to start searching */
189 char *ptrn; /* pattern to search for */
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
201 /* remember: "previous search was not forward" */
202 prevsf = FALSE;
204 if (ptrn && *ptrn)
206 /* locate the closing '?', if any */
207 line = parseptrn(ptrn);
208 #ifndef CRUNCH
209 if (*line)
211 delta = atol(line);
213 #endif
214 ptrn++;
216 /* free the previous pattern, if any */
217 if (re) free(re);
219 /* compile the pattern */
220 re = regcomp(ptrn);
221 if (!re)
223 return MARK_UNSET;
226 else if (!re)
228 msg("No previous expression");
229 return MARK_UNSET;
232 /* search backward for the pattern */
233 pos = markidx(m);
234 wrapped = FALSE;
235 for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
237 /* wrap search */
238 if (l < 1)
240 if (*o_wrapscan)
242 l = nlines + 1;
243 wrapped = TRUE;
244 continue;
246 else
248 break;
252 /* get this line */
253 line = fetchline(l);
255 /* check this line */
256 if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
258 /* match! now find the last acceptable one in this line */
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);
267 if (wrapped && *o_warn)
268 msg("(wrapped)");
269 #ifndef CRUNCH
270 if (delta != INFINITY)
272 l += delta;
273 if (l < 1 || l > nlines)
275 msg("search offset too big");
276 return MARK_UNSET;
278 force_lnmd = TRUE;
279 return MARK_AT_LINE(l);
281 #endif
282 return MARK_AT_LINE(l) + last;
284 pos = BLKSIZE;
287 /* not found */
288 msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
289 return MARK_UNSET;