1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Edward Wang at The University of California, Berkeley.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)wwwrite.c 8.1 (Berkeley) 06/06/93";
13 #endif /* not lint */
14
15 #include "ww.h"
16 #include "tt.h"
17 #include "char.h"
18
19 #define UPDATE() \
20 if (!w->ww_noupdate && w->ww_cur.r >= 0 && w->ww_cur.r < wwnrow && \
21 wwtouched[w->ww_cur.r]) \
22 wwupdate1(w->ww_cur.r, w->ww_cur.r + 1)
23
24 /*
25 * To support control character expansion, we save the old
26 * p and q values in r and s, and point p at the beginning
27 * of the expanded string, and q at some safe place beyond it
28 * (p + 10). At strategic points in the loops, we check
29 * for (r && !*p) and restore the saved values back into
30 * p and q. Essentially, we implement a stack of depth 2,
31 * to avoid recursion, which might be a better idea.
32 */
wwwrite(w,p,n)33 wwwrite(w, p, n)
34 register struct ww *w;
35 register char *p;
36 int n;
37 {
38 char hascursor;
39 char *savep = p;
40 char *q = p + n;
41 char *r = 0;
42 char *s;
43
44 #ifdef lint
45 s = 0; /* define it before possible use */
46 #endif
47 if (hascursor = w->ww_hascursor)
48 wwcursor(w, 0);
49 while (p < q && !w->ww_stopped && (!wwinterrupt() || w->ww_nointr)) {
50 if (r && !*p) {
51 p = r;
52 q = s;
53 r = 0;
54 continue;
55 }
56 if (w->ww_wstate == 0 &&
57 (isprt(*p) || w->ww_unctrl && isunctrl(*p))) {
58 register i;
59 register union ww_char *bp;
60 int col, col1;
61
62 if (w->ww_insert) { /* this is very slow */
63 if (*p == '\t') {
64 p++;
65 w->ww_cur.c += 8 -
66 (w->ww_cur.c - w->ww_w.l & 7);
67 goto chklf;
68 }
69 if (!isprt(*p)) {
70 r = p + 1;
71 s = q;
72 p = unctrl(*p);
73 q = p + 10;
74 }
75 wwinschar(w, w->ww_cur.r, w->ww_cur.c,
76 *p++, w->ww_modes);
77 goto right;
78 }
79
80 bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c];
81 i = w->ww_cur.c;
82 while (i < w->ww_w.r && p < q)
83 if (!*p && r) {
84 p = r;
85 q = s;
86 r = 0;
87 } else if (*p == '\t') {
88 register tmp = 8 - (i - w->ww_w.l & 7);
89 p++;
90 i += tmp;
91 bp += tmp;
92 } else if (isprt(*p)) {
93 bp++->c_w = *p++
94 | w->ww_modes << WWC_MSHIFT;
95 i++;
96 } else if (w->ww_unctrl && isunctrl(*p)) {
97 r = p + 1;
98 s = q;
99 p = unctrl(*p);
100 q = p + 10;
101 } else
102 break;
103 col = MAX(w->ww_cur.c, w->ww_i.l);
104 col1 = MIN(i, w->ww_i.r);
105 w->ww_cur.c = i;
106 if (w->ww_cur.r >= w->ww_i.t
107 && w->ww_cur.r < w->ww_i.b) {
108 register union ww_char *ns = wwns[w->ww_cur.r];
109 register char *smap = &wwsmap[w->ww_cur.r][col];
110 register char *win = w->ww_win[w->ww_cur.r];
111 int nchanged = 0;
112
113 bp = w->ww_buf[w->ww_cur.r];
114 for (i = col; i < col1; i++)
115 if (*smap++ == w->ww_index) {
116 nchanged++;
117 ns[i].c_w = bp[i].c_w
118 ^ win[i] << WWC_MSHIFT;
119 }
120 if (nchanged > 0)
121 wwtouched[w->ww_cur.r] |= WWU_TOUCHED;
122 }
123 chklf:
124 if (w->ww_cur.c >= w->ww_w.r)
125 goto crlf;
126 } else switch (w->ww_wstate) {
127 case 0:
128 switch (*p++) {
129 case '\n':
130 if (w->ww_mapnl)
131 crlf:
132 w->ww_cur.c = w->ww_w.l;
133 lf:
134 UPDATE();
135 if (++w->ww_cur.r >= w->ww_w.b) {
136 w->ww_cur.r = w->ww_w.b - 1;
137 if (w->ww_w.b < w->ww_b.b) {
138 (void) wwscroll1(w, w->ww_i.t,
139 w->ww_i.b, 1, 0);
140 w->ww_buf++;
141 w->ww_b.t--;
142 w->ww_b.b--;
143 } else
144 wwdelline(w, w->ww_b.t);
145 }
146 break;
147 case '\b':
148 if (--w->ww_cur.c < w->ww_w.l) {
149 w->ww_cur.c = w->ww_w.r - 1;
150 goto up;
151 }
152 break;
153 case '\r':
154 w->ww_cur.c = w->ww_w.l;
155 break;
156 case ctrl('g'):
157 ttputc(ctrl('g'));
158 break;
159 case ctrl('['):
160 w->ww_wstate = 1;
161 break;
162 }
163 break;
164 case 1:
165 w->ww_wstate = 0;
166 switch (*p++) {
167 case '@':
168 w->ww_insert = 1;
169 break;
170 case 'A':
171 up:
172 UPDATE();
173 if (--w->ww_cur.r < w->ww_w.t) {
174 w->ww_cur.r = w->ww_w.t;
175 if (w->ww_w.t > w->ww_b.t) {
176 (void) wwscroll1(w, w->ww_i.t,
177 w->ww_i.b, -1, 0);
178 w->ww_buf--;
179 w->ww_b.t++;
180 w->ww_b.b++;
181 } else
182 wwinsline(w, w->ww_b.t);
183 }
184 break;
185 case 'B':
186 goto lf;
187 case 'C':
188 right:
189 w->ww_cur.c++;
190 goto chklf;
191 case 'E':
192 w->ww_buf -= w->ww_w.t - w->ww_b.t;
193 w->ww_b.t = w->ww_w.t;
194 w->ww_b.b = w->ww_b.t + w->ww_b.nr;
195 w->ww_cur.r = w->ww_w.t;
196 w->ww_cur.c = w->ww_w.l;
197 wwclreos(w, w->ww_w.t, w->ww_w.l);
198 break;
199 case 'H':
200 UPDATE();
201 w->ww_cur.r = w->ww_w.t;
202 w->ww_cur.c = w->ww_w.l;
203 break;
204 case 'J':
205 wwclreos(w, w->ww_cur.r, w->ww_cur.c);
206 break;
207 case 'K':
208 wwclreol(w, w->ww_cur.r, w->ww_cur.c);
209 break;
210 case 'L':
211 UPDATE();
212 wwinsline(w, w->ww_cur.r);
213 break;
214 case 'M':
215 wwdelline(w, w->ww_cur.r);
216 break;
217 case 'N':
218 wwdelchar(w, w->ww_cur.r, w->ww_cur.c);
219 break;
220 case 'O':
221 w->ww_insert = 0;
222 break;
223 case 'P':
224 wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0);
225 break;
226 case 'X':
227 wwupdate();
228 break;
229 case 'Y':
230 UPDATE();
231 w->ww_wstate = 2;
232 break;
233 case 'Z':
234 wwupdate();
235 xxflush(0);
236 break;
237 case 's':
238 w->ww_wstate = 4;
239 break;
240 case 'r':
241 w->ww_wstate = 5;
242 break;
243 }
244 break;
245 case 2:
246 w->ww_cur.r = w->ww_w.t +
247 (unsigned)(*p++ - ' ') % w->ww_w.nr;
248 w->ww_wstate = 3;
249 break;
250 case 3:
251 w->ww_cur.c = w->ww_w.l +
252 (unsigned)(*p++ - ' ') % w->ww_w.nc;
253 w->ww_wstate = 0;
254 break;
255 case 4:
256 w->ww_modes |= *p++ & wwavailmodes;
257 w->ww_wstate = 0;
258 break;
259 case 5:
260 w->ww_modes &= ~*p++;
261 w->ww_wstate = 0;
262 break;
263 }
264 }
265 if (hascursor)
266 wwcursor(w, 1);
267 wwnwwr++;
268 wwnwwra += n;
269 n = p - savep;
270 wwnwwrc += n;
271 return n;
272 }
273