2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
9 static char sccsid
[] = "$Id: v_search.c,v 8.16 1993/12/09 19:43:18 bostic Exp $ (Berkeley) $Date: 1993/12/09 19:43:18 $";
12 #include <sys/types.h>
21 static int bcorrect
__P((SCR
*, EXF
*, VICMDARG
*, MARK
*, MARK
*, u_int
));
22 static int fcorrect
__P((SCR
*, EXF
*, VICMDARG
*, MARK
*, MARK
*, u_int
));
23 static int getptrn
__P((SCR
*, EXF
*, int, char **));
30 v_searchn(sp
, ep
, vp
, fm
, tm
, rp
)
39 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
))
41 switch (sp
->searchdir
) {
43 if (b_search(sp
, ep
, fm
, rp
, NULL
, NULL
, &flags
))
45 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
46 bcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
50 if (f_search(sp
, ep
, fm
, rp
, NULL
, NULL
, &flags
))
52 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
53 fcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
57 msgq(sp
, M_ERR
, "No previous search pattern.");
67 * Reverse last search.
70 v_searchN(sp
, ep
, vp
, fm
, tm
, rp
)
79 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
))
81 switch (sp
->searchdir
) {
83 if (f_search(sp
, ep
, fm
, rp
, NULL
, NULL
, &flags
))
85 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
86 fcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
90 if (b_search(sp
, ep
, fm
, rp
, NULL
, NULL
, &flags
))
92 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
93 bcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
97 msgq(sp
, M_ERR
, "No previous search pattern.");
106 * v_searchw -- [count]^A
107 * Search for the word under the cursor.
110 v_searchw(sp
, ep
, vp
, fm
, tm
, rp
)
121 len
= vp
->kbuflen
+ sizeof(RE_WSTART
) + sizeof(RE_WSTOP
);
122 GET_SPACE_RET(sp
, bp
, blen
, len
);
123 (void)snprintf(bp
, blen
, "%s%s%s", RE_WSTART
, vp
->keyword
, RE_WSTOP
);
126 rval
= f_search(sp
, ep
, fm
, rp
, bp
, NULL
, &flags
);
128 FREE_SPACE(sp
, bp
, blen
);
131 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
132 fcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
138 * v_searchb -- [count]?RE[? offset]
142 v_searchb(sp
, ep
, vp
, fm
, tm
, rp
)
151 if (F_ISSET(vp
, VC_ISDOT
))
154 if (getptrn(sp
, ep
, '?', &ptrn
))
160 flags
= SEARCH_MSG
| SEARCH_PARSE
| SEARCH_SET
| SEARCH_TERM
;
161 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
))
163 if (b_search(sp
, ep
, fm
, rp
, ptrn
, NULL
, &flags
))
165 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
166 bcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
172 * v_searchf -- [count]/RE[/ offset]
176 v_searchf(sp
, ep
, vp
, fm
, tm
, rp
)
185 if (F_ISSET(vp
, VC_ISDOT
))
188 if (getptrn(sp
, ep
, '/', &ptrn
))
194 flags
= SEARCH_MSG
| SEARCH_PARSE
| SEARCH_SET
| SEARCH_TERM
;
195 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
))
197 if (f_search(sp
, ep
, fm
, rp
, ptrn
, NULL
, &flags
))
199 if (F_ISSET(vp
, VC_C
| VC_D
| VC_Y
| VC_SH
) &&
200 fcorrect(sp
, ep
, vp
, fm
, rp
, flags
))
207 * Get the search pattern.
210 getptrn(sp
, ep
, prompt
, storep
)
218 if (sp
->s_get(sp
, ep
, &sp
->tiq
, prompt
,
219 TXT_BS
| TXT_CR
| TXT_ESCAPE
| TXT_PROMPT
) != INP_OK
)
222 /* Len is 0 if backspaced over the prompt, 1 if only CR entered. */
223 tp
= sp
->tiq
.cqh_first
;
233 * Historically, commands didn't affect the line searched to if the motion
234 * command was a search and the pattern match was the start or end of the
235 * line. There were some special cases, however, concerning search to the
236 * start of end of a line.
238 * Vi was not, however, consistent, and it was fairly easy to confuse it.
239 * For example, given the two lines:
244 * placing the cursor on the 'A' and doing y?$ would so confuse it that 'h'
245 * 'k' and put would no longer work correctly. In any case, we try to do
246 * the right thing, but it's not likely exactly match historic practice.
251 * Handle command with a backward search as the motion.
254 bcorrect(sp
, ep
, vp
, fm
, rp
, flags
)
266 * Correct backward searches which start at column 0 to be one
267 * past the last column of the previous line.
269 * Backward searches become line mode operations if they start
270 * at column 0 and end at column 0 of another line.
272 if (fm
->lno
> rp
->lno
&& fm
->cno
== 0) {
273 if ((p
= file_gline(sp
, ep
, --fm
->lno
, &len
)) == NULL
) {
274 GETLINE_ERR(sp
, rp
->lno
);
284 * Commands would become line mode operations if there was a delta
285 * specified to the search pattern.
287 if (LF_ISSET(SEARCH_DELTA
)) {
296 * Handle command with a forward search as the motion.
299 fcorrect(sp
, ep
, vp
, fm
, rp
, flags
)
311 * Correct forward searches which end at column 0 to be one
312 * past the last column of the previous line.
314 * Forward searches become line mode operations if they start
315 * at column 0 and end at column 0 of another line.
317 if (fm
->lno
< rp
->lno
&& rp
->cno
== 0) {
318 if ((p
= file_gline(sp
, ep
, --rp
->lno
, &len
)) == NULL
) {
319 GETLINE_ERR(sp
, rp
->lno
);
329 * Commands would become line mode operations if there was a delta
330 * specified to the search pattern.
332 if (LF_ISSET(SEARCH_DELTA
)) {