BSD 4_3 development
[unix-history] / usr / contrib / jove / move.c
CommitLineData
fb51ca13
C
1/*************************************************************************
2 * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3 * provided to you without charge for use only on a licensed Unix *
4 * system. You may copy JOVE provided that this notice is included with *
5 * the copy. You may not sell copies of this program or versions *
6 * modified for use on microcomputer systems, unless the copies are *
7 * included with a Unix system distribution and the source is provided. *
8 *************************************************************************/
9
10#include "jove.h"
11#include "ctype.h"
12
13static int line_pos;
14
15ForChar()
16{
17 register int num = exp;
18
19 if (exp < 0) {
20 exp = -exp;
21 BackChar();
22 return;
23 }
24 exp = 1;
25 while (--num >= 0) {
26 if (eolp()) { /* Go to the next Line */
27 if (curline->l_next == 0)
28 break;
29 SetLine(curline->l_next);
30 } else
31 curchar++;
32 }
33}
34
35BackChar()
36{
37 register int num = exp;
38
39 if (exp < 0) {
40 exp = -exp;
41 ForChar();
42 return;
43 }
44 exp = 1;
45 while (--num >= 0) {
46 if (bolp()) {
47 if (curline->l_prev == 0)
48 break;
49 SetLine(curline->l_prev);
50 Eol();
51 } else
52 --curchar;
53 }
54}
55
56NextLine()
57{
58 if ((curline == curbuf->b_last) && eolp())
59 complain(NullStr);
60 line_move(FORWARD, YES);
61}
62
63PrevLine()
64{
65 if ((curline == curbuf->b_first) && bolp())
66 complain(NullStr);
67 line_move(BACKWARD, YES);
68}
69
70/* moves to a different line in DIR; LINE_CMD says whether this is
71 being called from NextLine() or PrevLine(), in which case it tries
72 to line up the column with the column of the current line */
73
74line_move(dir, line_cmd)
75{
76 Line *(*proc)() = (dir == FORWARD) ? next_line : prev_line;
77 Line *line;
78
79 line = (*proc)(curline, exp);
80 if (line == curline) {
81 (dir == FORWARD) ? Eol() : Bol();
82 return;
83 }
84
85 if (line_cmd) {
86 this_cmd = LINECMD;
87 if (last_cmd != LINECMD)
88 line_pos = calc_pos(linebuf, curchar);
89 }
90 SetLine(line); /* curline is in linebuf now */
91 if (line_cmd)
92 curchar = how_far(curline, line_pos);
93}
94
95/* returns what cur_char should be for that position col */
96
97how_far(line, col)
98Line *line;
99{
100 register char *lp;
101 register int pos,
102 c;
103 char *base;
104
105 base = lp = lcontents(line);
106 pos = 0;
107
108 while (pos < col && (c = (*lp & 0177))) {
109 if (c == '\t')
110 pos += (tabstop - (pos % tabstop));
111 else if (isctrl(c))
112 pos += 2;
113 else
114 pos++;
115 lp++;
116 }
117
118 return lp - base;
119}
120
121Bol()
122{
123 curchar = 0;
124}
125
126Eol()
127{
128 curchar = strlen(linebuf);
129}
130
131Eof()
132{
133 PushPntp(curbuf->b_last);
134 ToLast();
135}
136
137Bof()
138{
139 PushPntp(curbuf->b_first);
140 ToFirst();
141}
142
143/* Move forward (if dir > 0) or backward (if dir < 0) a sentence. Deals
144 with all the kludgery involved with paragraphs, and moving backwards
145 is particularly yucky. */
146
147to_sent(dir)
148{
149 Bufpos *new,
150 old;
151 extern char *ParaStr;
152
153 DOTsave(&old);
154
155 new = dosearch("^[ \t]*$\\|[?.!]", dir, 1);
156 if (new == 0) {
157 (dir < 0) ? ToFirst() : ToLast();
158 return;
159 }
160 SetDot(new);
161 if (dir < 0) {
162 to_word(1);
163 if ((old.p_line == curline && old.p_char <= curchar) ||
164 (inorder(new->p_line, new->p_char, old.p_line, old.p_char) &&
165 inorder(old.p_line, old.p_char, curline, curchar))) {
166 SetDot(new);
167 to_sent(dir);
168 }
169 return; /* We're there? */
170 }
171 if (blnkp(linebuf)) {
172 Bol();
173 BackChar();
174 if (old.p_line == curline && old.p_char >= curchar) {
175 to_word(1); /* Oh brother this is painful */
176 to_sent(1);
177 }
178 } else {
179 extern int REbom;
180
181 curchar = REbom + 1; /* Just after the [?.!] */
182 if (LookingAt("[\")] *\\|[\")]$", linebuf, curchar))
183 curchar++;
184 else if (!eolp() && !LookingAt(" *", linebuf, curchar))
185 to_sent(dir);
186 }
187}
188
189Bos()
190{
191 int num = exp;
192
193 if (exp < 0) {
194 exp = -exp;
195 Eos();
196 return;
197 }
198
199 exp = 1;
200
201 while (--num >= 0) {
202 to_sent(-1);
203 if (bobp())
204 break;
205 }
206}
207
208Eos()
209{
210 int num = exp;
211
212 if (exp < 0) {
213 exp = -exp;
214 Bos();
215 return;
216 }
217
218 exp = 1;
219
220 while (--num >= 0) {
221 to_sent(1);
222 if (eobp())
223 break;
224 }
225}
226
227ForWord()
228{
229 register char c;
230 register int num = exp;
231
232 if (exp < 0) {
233 exp = -exp;
234 BackWord();
235 return;
236 }
237 exp = 1;
238 while (--num >= 0) {
239 to_word(1);
240 while ((c = linebuf[curchar]) != 0 && isword(c))
241 curchar++;
242 if (eobp())
243 break;
244 }
245 this_cmd = 0; /* Semi kludge to stop some unfavorable behavior */
246}
247
248BackWord()
249{
250 register int num = exp;
251 register char c;
252
253 if (exp < 0) {
254 exp = -exp;
255 ForWord();
256 return;
257 }
258 exp = 1;
259 while (--num >= 0) {
260 to_word(-1);
261 while (!bolp() && (c = linebuf[curchar - 1], isword(c)))
262 --curchar;
263 if (bobp())
264 break;
265 }
266 this_cmd = 0;
267}