xref: /freebsd/contrib/nvi/vi/v_ch.c (revision b8ba871b)
1b8ba871bSPeter Wemm /*-
2b8ba871bSPeter Wemm  * Copyright (c) 1992, 1993, 1994
3b8ba871bSPeter Wemm  *	The Regents of the University of California.  All rights reserved.
4b8ba871bSPeter Wemm  * Copyright (c) 1992, 1993, 1994, 1995, 1996
5b8ba871bSPeter Wemm  *	Keith Bostic.  All rights reserved.
6b8ba871bSPeter Wemm  *
7b8ba871bSPeter Wemm  * See the LICENSE file for redistribution information.
8b8ba871bSPeter Wemm  */
9b8ba871bSPeter Wemm 
10b8ba871bSPeter Wemm #include "config.h"
11b8ba871bSPeter Wemm 
12b8ba871bSPeter Wemm #include <sys/types.h>
13b8ba871bSPeter Wemm #include <sys/queue.h>
14b8ba871bSPeter Wemm #include <sys/time.h>
15b8ba871bSPeter Wemm 
16b8ba871bSPeter Wemm #include <bitstring.h>
17b8ba871bSPeter Wemm #include <limits.h>
18b8ba871bSPeter Wemm #include <stdio.h>
19b8ba871bSPeter Wemm #include <stdlib.h>
20b8ba871bSPeter Wemm 
21b8ba871bSPeter Wemm #include "../common/common.h"
22b8ba871bSPeter Wemm #include "vi.h"
23b8ba871bSPeter Wemm 
24b8ba871bSPeter Wemm static void notfound(SCR *, ARG_CHAR_T);
25b8ba871bSPeter Wemm static void noprev(SCR *);
26b8ba871bSPeter Wemm 
27b8ba871bSPeter Wemm /*
28b8ba871bSPeter Wemm  * v_chrepeat -- [count];
29b8ba871bSPeter Wemm  *	Repeat the last F, f, T or t search.
30b8ba871bSPeter Wemm  *
31b8ba871bSPeter Wemm  * PUBLIC: int v_chrepeat(SCR *, VICMD *);
32b8ba871bSPeter Wemm  */
33b8ba871bSPeter Wemm int
v_chrepeat(SCR * sp,VICMD * vp)34b8ba871bSPeter Wemm v_chrepeat(SCR *sp, VICMD *vp)
35b8ba871bSPeter Wemm {
36b8ba871bSPeter Wemm 	vp->character = VIP(sp)->lastckey;
37b8ba871bSPeter Wemm 
38b8ba871bSPeter Wemm 	switch (VIP(sp)->csearchdir) {
39b8ba871bSPeter Wemm 	case CNOTSET:
40b8ba871bSPeter Wemm 		noprev(sp);
41b8ba871bSPeter Wemm 		return (1);
42b8ba871bSPeter Wemm 	case FSEARCH:
43b8ba871bSPeter Wemm 		return (v_chF(sp, vp));
44b8ba871bSPeter Wemm 	case fSEARCH:
45b8ba871bSPeter Wemm 		return (v_chf(sp, vp));
46b8ba871bSPeter Wemm 	case TSEARCH:
47b8ba871bSPeter Wemm 		return (v_chT(sp, vp));
48b8ba871bSPeter Wemm 	case tSEARCH:
49b8ba871bSPeter Wemm 		return (v_cht(sp, vp));
50b8ba871bSPeter Wemm 	default:
51b8ba871bSPeter Wemm 		abort();
52b8ba871bSPeter Wemm 	}
53b8ba871bSPeter Wemm 	/* NOTREACHED */
54b8ba871bSPeter Wemm }
55b8ba871bSPeter Wemm 
56b8ba871bSPeter Wemm /*
57b8ba871bSPeter Wemm  * v_chrrepeat -- [count],
58b8ba871bSPeter Wemm  *	Repeat the last F, f, T or t search in the reverse direction.
59b8ba871bSPeter Wemm  *
60b8ba871bSPeter Wemm  * PUBLIC: int v_chrrepeat(SCR *, VICMD *);
61b8ba871bSPeter Wemm  */
62b8ba871bSPeter Wemm int
v_chrrepeat(SCR * sp,VICMD * vp)63b8ba871bSPeter Wemm v_chrrepeat(SCR *sp, VICMD *vp)
64b8ba871bSPeter Wemm {
65b8ba871bSPeter Wemm 	cdir_t savedir;
66b8ba871bSPeter Wemm 	int rval;
67b8ba871bSPeter Wemm 
68b8ba871bSPeter Wemm 	vp->character = VIP(sp)->lastckey;
69b8ba871bSPeter Wemm 	savedir = VIP(sp)->csearchdir;
70b8ba871bSPeter Wemm 
71b8ba871bSPeter Wemm 	switch (VIP(sp)->csearchdir) {
72b8ba871bSPeter Wemm 	case CNOTSET:
73b8ba871bSPeter Wemm 		noprev(sp);
74b8ba871bSPeter Wemm 		return (1);
75b8ba871bSPeter Wemm 	case FSEARCH:
76b8ba871bSPeter Wemm 		rval = v_chf(sp, vp);
77b8ba871bSPeter Wemm 		break;
78b8ba871bSPeter Wemm 	case fSEARCH:
79b8ba871bSPeter Wemm 		rval = v_chF(sp, vp);
80b8ba871bSPeter Wemm 		break;
81b8ba871bSPeter Wemm 	case TSEARCH:
82b8ba871bSPeter Wemm 		rval = v_cht(sp, vp);
83b8ba871bSPeter Wemm 		break;
84b8ba871bSPeter Wemm 	case tSEARCH:
85b8ba871bSPeter Wemm 		rval = v_chT(sp, vp);
86b8ba871bSPeter Wemm 		break;
87b8ba871bSPeter Wemm 	default:
88b8ba871bSPeter Wemm 		abort();
89b8ba871bSPeter Wemm 	}
90b8ba871bSPeter Wemm 	VIP(sp)->csearchdir = savedir;
91b8ba871bSPeter Wemm 	return (rval);
92b8ba871bSPeter Wemm }
93b8ba871bSPeter Wemm 
94b8ba871bSPeter Wemm /*
95b8ba871bSPeter Wemm  * v_cht -- [count]tc
96b8ba871bSPeter Wemm  *	Search forward in the line for the character before the next
97b8ba871bSPeter Wemm  *	occurrence of the specified character.
98b8ba871bSPeter Wemm  *
99b8ba871bSPeter Wemm  * PUBLIC: int v_cht(SCR *, VICMD *);
100b8ba871bSPeter Wemm  */
101b8ba871bSPeter Wemm int
v_cht(SCR * sp,VICMD * vp)102b8ba871bSPeter Wemm v_cht(SCR *sp, VICMD *vp)
103b8ba871bSPeter Wemm {
104b8ba871bSPeter Wemm 	if (v_chf(sp, vp))
105b8ba871bSPeter Wemm 		return (1);
106b8ba871bSPeter Wemm 
107b8ba871bSPeter Wemm 	/*
108b8ba871bSPeter Wemm 	 * v_chf places the cursor on the character, where the 't'
109b8ba871bSPeter Wemm 	 * command wants it to its left.  We know this is safe since
110b8ba871bSPeter Wemm 	 * we had to move right for v_chf() to have succeeded.
111b8ba871bSPeter Wemm 	 */
112b8ba871bSPeter Wemm 	--vp->m_stop.cno;
113b8ba871bSPeter Wemm 
114b8ba871bSPeter Wemm 	/*
115b8ba871bSPeter Wemm 	 * Make any necessary correction to the motion decision made
116b8ba871bSPeter Wemm 	 * by the v_chf routine.
117b8ba871bSPeter Wemm 	 */
118b8ba871bSPeter Wemm 	if (!ISMOTION(vp))
119b8ba871bSPeter Wemm 		vp->m_final = vp->m_stop;
120b8ba871bSPeter Wemm 
121b8ba871bSPeter Wemm 	VIP(sp)->csearchdir = tSEARCH;
122b8ba871bSPeter Wemm 	return (0);
123b8ba871bSPeter Wemm }
124b8ba871bSPeter Wemm 
125b8ba871bSPeter Wemm /*
126b8ba871bSPeter Wemm  * v_chf -- [count]fc
127b8ba871bSPeter Wemm  *	Search forward in the line for the next occurrence of the
128b8ba871bSPeter Wemm  *	specified character.
129b8ba871bSPeter Wemm  *
130b8ba871bSPeter Wemm  * PUBLIC: int v_chf(SCR *, VICMD *);
131b8ba871bSPeter Wemm  */
132b8ba871bSPeter Wemm int
v_chf(SCR * sp,VICMD * vp)133b8ba871bSPeter Wemm v_chf(SCR *sp, VICMD *vp)
134b8ba871bSPeter Wemm {
135b8ba871bSPeter Wemm 	size_t len;
136b8ba871bSPeter Wemm 	u_long cnt;
137b8ba871bSPeter Wemm 	int isempty;
138b8ba871bSPeter Wemm 	ARG_CHAR_T key;
139b8ba871bSPeter Wemm 	CHAR_T *endp, *p, *startp;
140b8ba871bSPeter Wemm 
141b8ba871bSPeter Wemm 	/*
142b8ba871bSPeter Wemm 	 * !!!
143b8ba871bSPeter Wemm 	 * If it's a dot command, it doesn't reset the key for which we're
144b8ba871bSPeter Wemm 	 * searching, e.g. in "df1|f2|.|;", the ';' searches for a '2'.
145b8ba871bSPeter Wemm 	 */
146b8ba871bSPeter Wemm 	key = vp->character;
147b8ba871bSPeter Wemm 	if (!F_ISSET(vp, VC_ISDOT))
148b8ba871bSPeter Wemm 		VIP(sp)->lastckey = key;
149b8ba871bSPeter Wemm 	VIP(sp)->csearchdir = fSEARCH;
150b8ba871bSPeter Wemm 
151b8ba871bSPeter Wemm 	if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
152b8ba871bSPeter Wemm 		if (isempty)
153b8ba871bSPeter Wemm 			goto empty;
154b8ba871bSPeter Wemm 		return (1);
155b8ba871bSPeter Wemm 	}
156b8ba871bSPeter Wemm 
157b8ba871bSPeter Wemm 	if (len == 0) {
158b8ba871bSPeter Wemm empty:		notfound(sp, key);
159b8ba871bSPeter Wemm 		return (1);
160b8ba871bSPeter Wemm 	}
161b8ba871bSPeter Wemm 
162b8ba871bSPeter Wemm 	endp = (startp = p) + len;
163b8ba871bSPeter Wemm 	p += vp->m_start.cno;
164b8ba871bSPeter Wemm 	for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
165b8ba871bSPeter Wemm 		while (++p < endp && *p != key);
166b8ba871bSPeter Wemm 		if (p == endp) {
167b8ba871bSPeter Wemm 			notfound(sp, key);
168b8ba871bSPeter Wemm 			return (1);
169b8ba871bSPeter Wemm 		}
170b8ba871bSPeter Wemm 	}
171b8ba871bSPeter Wemm 
172b8ba871bSPeter Wemm 	vp->m_stop.cno = p - startp;
173b8ba871bSPeter Wemm 
174b8ba871bSPeter Wemm 	/*
175b8ba871bSPeter Wemm 	 * Non-motion commands move to the end of the range.
176b8ba871bSPeter Wemm 	 * Delete and yank stay at the start, ignore others.
177b8ba871bSPeter Wemm 	 */
178b8ba871bSPeter Wemm 	vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
179b8ba871bSPeter Wemm 	return (0);
180b8ba871bSPeter Wemm }
181b8ba871bSPeter Wemm 
182b8ba871bSPeter Wemm /*
183b8ba871bSPeter Wemm  * v_chT -- [count]Tc
184b8ba871bSPeter Wemm  *	Search backward in the line for the character after the next
185b8ba871bSPeter Wemm  *	occurrence of the specified character.
186b8ba871bSPeter Wemm  *
187b8ba871bSPeter Wemm  * PUBLIC: int v_chT(SCR *, VICMD *);
188b8ba871bSPeter Wemm  */
189b8ba871bSPeter Wemm int
v_chT(SCR * sp,VICMD * vp)190b8ba871bSPeter Wemm v_chT(SCR *sp, VICMD *vp)
191b8ba871bSPeter Wemm {
192b8ba871bSPeter Wemm 	if (v_chF(sp, vp))
193b8ba871bSPeter Wemm 		return (1);
194b8ba871bSPeter Wemm 
195b8ba871bSPeter Wemm 	/*
196b8ba871bSPeter Wemm 	 * Check whether the matching character is to the immediate left
197b8ba871bSPeter Wemm 	 * of the original cursor position, offset adjusted for a motion
198b8ba871bSPeter Wemm 	 * command.  If so, no movement is required.
199b8ba871bSPeter Wemm 	 */
200b8ba871bSPeter Wemm 	if (vp->m_start.cno == vp->m_stop.cno) {
201b8ba871bSPeter Wemm                 return (1);
202b8ba871bSPeter Wemm 	}
203b8ba871bSPeter Wemm 
204b8ba871bSPeter Wemm 	/*
205b8ba871bSPeter Wemm 	 * v_chF places the cursor on the character, where the 'T'
206b8ba871bSPeter Wemm 	 * command wants it to its right.  We know this is safe since
207b8ba871bSPeter Wemm 	 * we had to move left for v_chF() to have succeeded.
208b8ba871bSPeter Wemm 	 */
209b8ba871bSPeter Wemm 	++vp->m_stop.cno;
210b8ba871bSPeter Wemm 	vp->m_final = vp->m_stop;
211b8ba871bSPeter Wemm 
212b8ba871bSPeter Wemm 	VIP(sp)->csearchdir = TSEARCH;
213b8ba871bSPeter Wemm 	return (0);
214b8ba871bSPeter Wemm }
215b8ba871bSPeter Wemm 
216b8ba871bSPeter Wemm /*
217b8ba871bSPeter Wemm  * v_chF -- [count]Fc
218b8ba871bSPeter Wemm  *	Search backward in the line for the next occurrence of the
219b8ba871bSPeter Wemm  *	specified character.
220b8ba871bSPeter Wemm  *
221b8ba871bSPeter Wemm  * PUBLIC: int v_chF(SCR *, VICMD *);
222b8ba871bSPeter Wemm  */
223b8ba871bSPeter Wemm int
v_chF(SCR * sp,VICMD * vp)224b8ba871bSPeter Wemm v_chF(SCR *sp, VICMD *vp)
225b8ba871bSPeter Wemm {
226b8ba871bSPeter Wemm 	size_t len;
227b8ba871bSPeter Wemm 	u_long cnt;
228b8ba871bSPeter Wemm 	int isempty;
229b8ba871bSPeter Wemm 	ARG_CHAR_T key;
230b8ba871bSPeter Wemm 	CHAR_T *endp, *p;
231b8ba871bSPeter Wemm 
232b8ba871bSPeter Wemm 	/*
233b8ba871bSPeter Wemm 	 * !!!
234b8ba871bSPeter Wemm 	 * If it's a dot command, it doesn't reset the key for which
235b8ba871bSPeter Wemm 	 * we're searching, e.g. in "df1|f2|.|;", the ';' searches
236b8ba871bSPeter Wemm 	 * for a '2'.
237b8ba871bSPeter Wemm 	 */
238b8ba871bSPeter Wemm 	key = vp->character;
239b8ba871bSPeter Wemm 	if (!F_ISSET(vp, VC_ISDOT))
240b8ba871bSPeter Wemm 		VIP(sp)->lastckey = key;
241b8ba871bSPeter Wemm 	VIP(sp)->csearchdir = FSEARCH;
242b8ba871bSPeter Wemm 
243b8ba871bSPeter Wemm 	if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
244b8ba871bSPeter Wemm 		if (isempty)
245b8ba871bSPeter Wemm 			goto empty;
246b8ba871bSPeter Wemm 		return (1);
247b8ba871bSPeter Wemm 	}
248b8ba871bSPeter Wemm 
249b8ba871bSPeter Wemm 	if (len == 0) {
250b8ba871bSPeter Wemm empty:		notfound(sp, key);
251b8ba871bSPeter Wemm 		return (1);
252b8ba871bSPeter Wemm 	}
253b8ba871bSPeter Wemm 
254b8ba871bSPeter Wemm 	endp = p - 1;
255b8ba871bSPeter Wemm 	p += vp->m_start.cno;
256b8ba871bSPeter Wemm 	for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
257b8ba871bSPeter Wemm 		while (--p > endp && *p != key);
258b8ba871bSPeter Wemm 		if (p == endp) {
259b8ba871bSPeter Wemm 			notfound(sp, key);
260b8ba871bSPeter Wemm 			return (1);
261b8ba871bSPeter Wemm 		}
262b8ba871bSPeter Wemm 	}
263b8ba871bSPeter Wemm 
264b8ba871bSPeter Wemm 	vp->m_stop.cno = (p - endp) - 1;
265b8ba871bSPeter Wemm 
266b8ba871bSPeter Wemm 	/*
267b8ba871bSPeter Wemm 	 * All commands move to the end of the range.  Motion commands
268b8ba871bSPeter Wemm 	 * adjust the starting point to the character before the current
269b8ba871bSPeter Wemm 	 * one.
270b8ba871bSPeter Wemm 	 */
271b8ba871bSPeter Wemm 	vp->m_final = vp->m_stop;
272b8ba871bSPeter Wemm 	if (ISMOTION(vp))
273b8ba871bSPeter Wemm 		--vp->m_start.cno;
274b8ba871bSPeter Wemm 	return (0);
275b8ba871bSPeter Wemm }
276b8ba871bSPeter Wemm 
277b8ba871bSPeter Wemm static void
noprev(SCR * sp)278b8ba871bSPeter Wemm noprev(SCR *sp)
279b8ba871bSPeter Wemm {
280b8ba871bSPeter Wemm 	msgq(sp, M_BERR, "178|No previous F, f, T or t search");
281b8ba871bSPeter Wemm }
282b8ba871bSPeter Wemm 
283b8ba871bSPeter Wemm static void
notfound(SCR * sp,ARG_CHAR_T ch)284b8ba871bSPeter Wemm notfound(SCR *sp, ARG_CHAR_T ch)
285b8ba871bSPeter Wemm {
286b8ba871bSPeter Wemm 	msgq(sp, M_BERR, "179|%s not found", KEY_NAME(sp, ch));
287b8ba871bSPeter Wemm }
288b8ba871bSPeter Wemm