-> 1.03
[nvi.git] / vi / v_ch.c
blobf753edd1fa9acfa93e890988e1a111c9b3bb920c
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: v_ch.c,v 8.2 1993/12/20 12:23:03 bostic Exp $ (Berkeley) $Date: 1993/12/20 12:23:03 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <stdlib.h>
16 #include "vi.h"
17 #include "vcmd.h"
19 #define NOPREV { \
20 msgq(sp, M_BERR, "No previous F, f, T or t search."); \
21 return (1); \
24 #define NOTFOUND(ch) { \
25 msgq(sp, M_BERR, "%s not found.", charname(sp, ch)); \
26 return (1); \
30 * v_chrepeat -- [count];
31 * Repeat the last F, f, T or t search.
33 int
34 v_chrepeat(sp, ep, vp, fm, tm, rp)
35 SCR *sp;
36 EXF *ep;
37 VICMDARG *vp;
38 MARK *fm, *tm, *rp;
40 vp->character = sp->lastckey;
42 switch (sp->csearchdir) {
43 case CNOTSET:
44 NOPREV;
45 case FSEARCH:
46 return (v_chF(sp, ep, vp, fm, tm, rp));
47 case fSEARCH:
48 return (v_chf(sp, ep, vp, fm, tm, rp));
49 case TSEARCH:
50 return (v_chT(sp, ep, vp, fm, tm, rp));
51 case tSEARCH:
52 return (v_cht(sp, ep, vp, fm, tm, rp));
53 default:
54 abort();
56 /* NOTREACHED */
60 * v_chrrepeat -- [count],
61 * Repeat the last F, f, T or t search in the reverse direction.
63 int
64 v_chrrepeat(sp, ep, vp, fm, tm, rp)
65 SCR *sp;
66 EXF *ep;
67 VICMDARG *vp;
68 MARK *fm, *tm, *rp;
70 int rval;
71 enum cdirection savedir;
73 vp->character = sp->lastckey;
74 savedir = sp->csearchdir;
76 switch (sp->csearchdir) {
77 case CNOTSET:
78 NOPREV;
79 case FSEARCH:
80 rval = v_chf(sp, ep, vp, fm, tm, rp);
81 break;
82 case fSEARCH:
83 rval = v_chF(sp, ep, vp, fm, tm, rp);
84 break;
85 case TSEARCH:
86 rval = v_cht(sp, ep, vp, fm, tm, rp);
87 break;
88 case tSEARCH:
89 rval = v_chT(sp, ep, vp, fm, tm, rp);
90 break;
91 default:
92 abort();
94 sp->csearchdir = savedir;
95 return (rval);
99 * v_cht -- [count]tc
100 * Search forward in the line for the next occurrence of the character.
101 * Place the cursor on it if a motion command, to its left if its not.
104 v_cht(sp, ep, vp, fm, tm, rp)
105 SCR *sp;
106 EXF *ep;
107 VICMDARG *vp;
108 MARK *fm, *tm, *rp;
110 int rval;
112 rval = v_chf(sp, ep, vp, fm, tm, rp);
113 if (!rval)
114 --rp->cno; /* XXX: Motion interaction with v_chf. */
115 sp->csearchdir = tSEARCH;
116 return (rval);
120 * v_chf -- [count]fc
121 * Search forward in the line for the next occurrence of the character.
122 * Place the cursor to its right if a motion command, on it if its not.
125 v_chf(sp, ep, vp, fm, tm, rp)
126 SCR *sp;
127 EXF *ep;
128 VICMDARG *vp;
129 MARK *fm, *tm, *rp;
131 size_t len;
132 recno_t lno;
133 u_long cnt;
134 int key;
135 char *endp, *p, *startp;
138 * !!!
139 * If it's a dot command, it doesn't reset the key for which
140 * we're searching, e.g. in "df1|f2|.|;", the ';' searches
141 * for a '2'.
143 key = vp->character;
144 if (!F_ISSET(vp, VC_ISDOT))
145 sp->lastckey = key;
146 sp->csearchdir = fSEARCH;
148 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
149 if (file_lline(sp, ep, &lno))
150 return (1);
151 if (lno == 0)
152 NOTFOUND(key);
153 GETLINE_ERR(sp, fm->lno);
154 return (1);
157 if (len == 0)
158 NOTFOUND(key);
160 startp = p;
161 endp = p + len;
162 p += fm->cno;
163 for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
164 while (++p < endp && *p != key);
165 if (p == endp)
166 NOTFOUND(key);
168 rp->lno = fm->lno;
169 rp->cno = p - startp;
170 if (F_ISSET(vp, VC_C | VC_D | VC_Y))
171 ++rp->cno;
172 return (0);
176 * v_chT -- [count]Tc
177 * Search backward in the line for the next occurrence of the character.
178 * Place the cursor to its right.
181 v_chT(sp, ep, vp, fm, tm, rp)
182 SCR *sp;
183 EXF *ep;
184 VICMDARG *vp;
185 MARK *fm, *tm, *rp;
187 int rval;
189 rval = v_chF(sp, ep, vp, fm, tm, rp);
190 if (!rval)
191 ++rp->cno;
192 sp->csearchdir = TSEARCH;
193 return (0);
197 * v_chF -- [count]Fc
198 * Search backward in the line for the next occurrence of the character.
199 * Place the cursor on it.
202 v_chF(sp, ep, vp, fm, tm, rp)
203 SCR *sp;
204 EXF *ep;
205 VICMDARG *vp;
206 MARK *fm, *tm, *rp;
208 recno_t lno;
209 size_t len;
210 u_long cnt;
211 int key;
212 char *p, *endp;
215 * !!!
216 * If it's a dot command, it doesn't reset the key for which
217 * we're searching, e.g. in "df1|f2|.|;", the ';' searches
218 * for a '2'.
220 key = vp->character;
221 if (!F_ISSET(vp, VC_ISDOT))
222 sp->lastckey = key;
223 sp->csearchdir = FSEARCH;
225 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
226 if (file_lline(sp, ep, &lno))
227 return (1);
228 if (lno == 0)
229 NOTFOUND(key);
230 GETLINE_ERR(sp, fm->lno);
231 return (1);
234 if (len == 0)
235 NOTFOUND(key);
237 endp = p - 1;
238 p += fm->cno;
239 for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
240 while (--p > endp && *p != key);
241 if (p == endp)
242 NOTFOUND(key);
244 rp->lno = fm->lno;
245 rp->cno = (p - endp) - 1;
246 return (0);