BSD 4_4 release
[unix-history] / usr / src / contrib / nvi / nvi / vi / v_sentence.c
CommitLineData
ad787160
C
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)v_sentence.c 8.1 (Berkeley) 6/9/93";
36#endif /* not lint */
37
38#include <sys/types.h>
39
40#include "vi.h"
41#include "vcmd.h"
42
43/*
44 * Sentences are sequences of characters terminated by a period followed
45 * by at least two spaces or a newline.
46 *
47 * Historical vi mishandled lines with only white-space characters. Forward
48 * sentences treated them as part of the current sentence, backward sentences
49 * treated them as different sentences. This implementation treats lines with
50 * only white-space characters and empty lines as sentence delimiters, not
51 * sentences, in both directions.
52 */
53
54#define EATBLANK(sp) \
55 while (getc_next(sp, ep, FORWARD, &ch) && \
56 (ch == EMPTYLINE || ch == ' ' || ch == '\t'))
57
58#define ISSPACE(ch) \
59 (ch == EMPTYLINE || ch == ' ' || ch == '\t')
60
61/*
62 * v_sentencef -- [count])
63 * Move forward count sentences.
64 */
65int
66v_sentencef(sp, ep, vp, fm, tm, rp)
67 SCR *sp;
68 EXF *ep;
69 VICMDARG *vp;
70 MARK *fm, *tm, *rp;
71{
72 enum { NONE, PERIOD, BLANK } state;
73 int ch;
74 u_long cnt;
75
76 cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
77
78 if (getc_init(sp, ep, fm, &ch))
79 return (1);
80
81 /*
82 * If in white-space, the next start of sentence counts as one.
83 * This may not handle " . " correctly, but it's real unclear
84 * what correctly means in that case.
85 */
86 if (ISSPACE(ch)) {
87 EATBLANK(sp);
88 if (--cnt == 0) {
89 getc_set(sp, ep, rp);
90 if (fm->lno != rp->lno || fm->cno != rp->cno)
91 return (0);
92 v_eof(sp, ep, NULL);
93 return (1);
94 }
95 }
96 for (state = NONE; getc_next(sp, ep, FORWARD, &ch);)
97 switch(ch) {
98 case EMPTYLINE:
99 if ((state == PERIOD || state == BLANK) && --cnt == 0) {
100 EATBLANK(sp);
101 getc_set(sp, ep, rp);
102 return (0);
103 }
104 state = NONE;
105 break;
106 case '.':
107 case '?':
108 case '!':
109 state = PERIOD;
110 break;
111 case ' ':
112 case '\t':
113 if (state == PERIOD) {
114 state = BLANK;
115 break;
116 }
117 if (state == BLANK && --cnt == 0) {
118 EATBLANK(sp);
119 getc_set(sp, ep, rp);
120 return (0);
121 }
122 break;
123 default:
124 state = NONE;
125 break;
126 }
127
128 /* EOF is a movement sink. */
129 getc_set(sp, ep, rp);
130 if (fm->lno != rp->lno || fm->cno != rp->cno)
131 return (0);
132
133 v_eof(sp, ep, NULL);
134 return (1);
135}
136
137#undef EATBLANK
138#define EATBLANK(sp) \
139 while (getc_next(sp, ep, BACKWARD, &ch) && \
140 (ch == EMPTYLINE || ch == ' ' || ch == '\t'))
141
142/*
143 * v_sentenceb -- [count])
144 * Move forward count sentences.
145 */
146int
147v_sentenceb(sp, ep, vp, fm, tm, rp)
148 SCR *sp;
149 EXF *ep;
150 VICMDARG *vp;
151 MARK *fm, *tm, *rp;
152{
153 int ch, last1, last2;
154 u_long cnt;
155
156 if (fm->lno == 1 && fm->cno == 0) {
157 v_sof(sp, NULL);
158 return (1);
159 }
160
161 cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
162
163 if (getc_init(sp, ep, fm, &ch))
164 return (1);
165
166 /*
167 * Make ". xxx" with the cursor on the 'x', and "xxx. ", with the
168 * cursor in the spaces, work.
169 */
170 if (getc_next(sp, ep, BACKWARD, &ch) && ISSPACE(ch))
171 EATBLANK(sp);
172
173 for (last1 = last2 = 'a'; getc_next(sp, ep, BACKWARD, &ch);) {
174 if ((ch == '.' || ch == '?' || ch == '!') &&
175 ISSPACE(last1) && ISSPACE(last2) && --cnt == 0) {
176 while (getc_next(sp, ep, FORWARD, &ch) && ISSPACE(ch));
177 getc_set(sp, ep, rp);
178 return (0);
179 }
180 last2 = last1;
181 last1 = ch;
182 }
183
184 /* SOF is a movement sink. */
185 getc_set(sp, ep, rp);
186 return (0);
187}