source: trunk/third/nvi/vi/v_ch.c @ 14302

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