1 /*	$OpenBSD: ttzapple.c,v 1.6 2003/06/03 02:56:23 millert Exp $	*/
2 /*	$NetBSD: ttzapple.c,v 1.3 1995/09/28 10:34:57 tls Exp $	*/
3 
4 /*
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Edward Wang at The University of California, Berkeley.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)ttzapple.c	8.1 (Berkeley) 6/6/93";
39 #else
40 static char rcsid[] = "$OpenBSD: ttzapple.c,v 1.6 2003/06/03 02:56:23 millert Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include "ww.h"
45 #include "tt.h"
46 #include "char.h"
47 
48 /*
49 zz|zapple|perfect apple:\
50 	:am:pt:co#80:li#24:le=^H:nd=^F:up=^K:do=^J:\
51 	:ho=\E0:ll=\E1:cm=\E=%+ %+ :ch=\E<%+ :cv=\E>%+ :\
52 	:cl=\E4:ce=\E2:cd=\E3:rp=\E@%.%+ :\
53 	:so=\E+:se=\E-:\
54 	:dc=\Ec:DC=\EC%+ :ic=\Ei:IC=\EI%+ :\
55 	:al=\Ea:AL=\EA%+ :dl=\Ed:DL=\ED%+ :\
56 	:sf=\Ef:SF=\EF%+ :sr=\Er:SR=\ER%+ :cs=\E?%+ %+ :\
57 	:is=\E-\ET :
58 */
59 
60 #define NCOL		80
61 #define NROW		24
62 #define TOKEN_MAX	32
63 
64 extern short gen_frame[];
65 
66 	/* for error correction */
67 int zz_ecc;
68 int zz_lastc;
69 
70 	/* for checkpointing */
71 int zz_sum;
72 
zz_setmodes(new)73 zz_setmodes(new)
74 {
75 	if (new & WWM_REV) {
76 		if ((tt.tt_modes & WWM_REV) == 0)
77 			ttesc('+');
78 	} else
79 		if (tt.tt_modes & WWM_REV)
80 			ttesc('-');
81 	tt.tt_modes = new;
82 }
83 
zz_insline(n)84 zz_insline(n)
85 {
86 	if (n == 1)
87 		ttesc('a');
88 	else {
89 		ttesc('A');
90 		ttputc(n + ' ');
91 	}
92 }
93 
zz_delline(n)94 zz_delline(n)
95 {
96 	if (n == 1)
97 		ttesc('d');
98 	else {
99 		ttesc('D');
100 		ttputc(n + ' ');
101 	}
102 }
103 
zz_putc(c)104 zz_putc(c)
105 	char c;
106 {
107 	if (tt.tt_nmodes != tt.tt_modes)
108 		zz_setmodes(tt.tt_nmodes);
109 	ttputc(c);
110 	if (++tt.tt_col == NCOL)
111 		tt.tt_col = 0, tt.tt_row++;
112 }
113 
zz_write(p,n)114 zz_write(p, n)
115 	char *p;
116 	int n;
117 {
118 	if (tt.tt_nmodes != tt.tt_modes)
119 		zz_setmodes(tt.tt_nmodes);
120 	ttwrite(p, n);
121 	tt.tt_col += n;
122 	if (tt.tt_col == NCOL)
123 		tt.tt_col = 0, tt.tt_row++;
124 }
125 
zz_move(row,col)126 zz_move(row, col)
127 	int row, col;
128 {
129 	int x;
130 
131 	if (tt.tt_row == row) {
132 same_row:
133 		if ((x = col - tt.tt_col) == 0)
134 			return;
135 		if (col == 0) {
136 			ttctrl('m');
137 			goto out;
138 		}
139 		switch (x) {
140 		case 2:
141 			ttctrl('f');
142 		case 1:
143 			ttctrl('f');
144 			goto out;
145 		case -2:
146 			ttctrl('h');
147 		case -1:
148 			ttctrl('h');
149 			goto out;
150 		}
151 		if ((col & 7) == 0 && x > 0 && x <= 16) {
152 			ttctrl('i');
153 			if (x > 8)
154 				ttctrl('i');
155 			goto out;
156 		}
157 		ttesc('<');
158 		ttputc(col + ' ');
159 		goto out;
160 	}
161 	if (tt.tt_col == col) {
162 		switch (row - tt.tt_row) {
163 		case 2:
164 			ttctrl('j');
165 		case 1:
166 			ttctrl('j');
167 			goto out;
168 		case -2:
169 			ttctrl('k');
170 		case -1:
171 			ttctrl('k');
172 			goto out;
173 		}
174 		if (col == 0) {
175 			if (row == 0)
176 				goto home;
177 			if (row == NROW - 1)
178 				goto ll;
179 		}
180 		ttesc('>');
181 		ttputc(row + ' ');
182 		goto out;
183 	}
184 	if (col == 0) {
185 		if (row == 0) {
186 home:
187 			ttesc('0');
188 			goto out;
189 		}
190 		if (row == tt.tt_row + 1) {
191 			/*
192 			 * Do newline first to match the sequence
193 			 * for scroll down and return
194 			 */
195 			ttctrl('j');
196 			ttctrl('m');
197 			goto out;
198 		}
199 		if (row == NROW - 1) {
200 ll:
201 			ttesc('1');
202 			goto out;
203 		}
204 	}
205 	/* favor local motion for better compression */
206 	if (row == tt.tt_row + 1) {
207 		ttctrl('j');
208 		goto same_row;
209 	}
210 	if (row == tt.tt_row - 1) {
211 		ttctrl('k');
212 		goto same_row;
213 	}
214 	ttesc('=');
215 	ttputc(' ' + row);
216 	ttputc(' ' + col);
217 out:
218 	tt.tt_col = col;
219 	tt.tt_row = row;
220 }
221 
zz_start()222 zz_start()
223 {
224 	ttesc('T');
225 	ttputc(TOKEN_MAX + ' ');
226 	ttesc('U');
227 	ttputc('!');
228 	zz_ecc = 1;
229 	zz_lastc = -1;
230 	ttesc('v');
231 	ttflush();
232 	zz_sum = 0;
233 	zz_setscroll(0, NROW - 1);
234 	zz_clear();
235 	zz_setmodes(0);
236 }
237 
zz_reset()238 zz_reset()
239 {
240 	zz_setscroll(0, NROW - 1);
241 	tt.tt_modes = WWM_REV;
242 	zz_setmodes(0);
243 	tt.tt_col = tt.tt_row = -10;
244 }
245 
zz_end()246 zz_end()
247 {
248 	ttesc('T');
249 	ttputc(' ');
250 	ttesc('U');
251 	ttputc(' ');
252 	zz_ecc = 0;
253 }
254 
zz_clreol()255 zz_clreol()
256 {
257 	ttesc('2');
258 }
259 
zz_clreos()260 zz_clreos()
261 {
262 	ttesc('3');
263 }
264 
zz_clear()265 zz_clear()
266 {
267 	ttesc('4');
268 	tt.tt_col = tt.tt_row = 0;
269 }
270 
zz_insspace(n)271 zz_insspace(n)
272 {
273 	if (n == 1)
274 		ttesc('i');
275 	else {
276 		ttesc('I');
277 		ttputc(n + ' ');
278 	}
279 }
280 
zz_delchar(n)281 zz_delchar(n)
282 {
283 	if (n == 1)
284 		ttesc('c');
285 	else {
286 		ttesc('C');
287 		ttputc(n + ' ');
288 	}
289 }
290 
zz_scroll_down(n)291 zz_scroll_down(n)
292 {
293 	if (n == 1)
294 		if (tt.tt_row == NROW - 1)
295 			ttctrl('j');
296 		else
297 			ttesc('f');
298 	else {
299 		ttesc('F');
300 		ttputc(n + ' ');
301 	}
302 }
303 
zz_scroll_up(n)304 zz_scroll_up(n)
305 {
306 	if (n == 1)
307 		ttesc('r');
308 	else {
309 		ttesc('R');
310 		ttputc(n + ' ');
311 	}
312 }
313 
zz_setscroll(top,bot)314 zz_setscroll(top, bot)
315 {
316 	ttesc('?');
317 	ttputc(top + ' ');
318 	ttputc(bot + ' ');
319 	tt.tt_scroll_top = top;
320 	tt.tt_scroll_bot = bot;
321 }
322 
323 int zz_debug = 0;
324 
zz_set_token(t,s,n)325 zz_set_token(t, s, n)
326 	char *s;
327 {
328 	if (tt.tt_nmodes != tt.tt_modes)
329 		zz_setmodes(tt.tt_nmodes);
330 	if (zz_debug) {
331 		char buf[100];
332 		zz_setmodes(WWM_REV);
333 		(void) snprintf(buf, sizeof(buf), "%02x=", t);
334 		ttputs(buf);
335 		tt.tt_col += 3;
336 	}
337 	ttputc(0x80);
338 	ttputc(t + 1);
339 	s[n - 1] |= 0x80;
340 	ttwrite(s, n);
341 	s[n - 1] &= ~0x80;
342 }
343 
344 /*ARGSUSED*/
zz_put_token(t,s,n)345 zz_put_token(t, s, n)
346 	char *s;
347 {
348 	if (tt.tt_nmodes != tt.tt_modes)
349 		zz_setmodes(tt.tt_nmodes);
350 	if (zz_debug) {
351 		char buf[100];
352 		zz_setmodes(WWM_REV);
353 		(void) snprintf(buf, sizeof(buf), "%02x>", t);
354 		ttputs(buf);
355 		tt.tt_col += 3;
356 	}
357 	ttputc(t + 0x81);
358 }
359 
zz_rint(p,n)360 zz_rint(p, n)
361 	char *p;
362 {
363 	int i;
364 	char *q;
365 
366 	if (!zz_ecc)
367 		return n;
368 	for (i = n, q = p; --i >= 0;) {
369 		int c = (unsigned char) *p++;
370 
371 		if (zz_lastc == 0) {
372 			switch (c) {
373 			case 0:
374 				*q++ = 0;
375 				zz_lastc = -1;
376 				break;
377 			case 1:		/* start input ecc */
378 				zz_ecc = 2;
379 				zz_lastc = -1;
380 				wwnreadstat++;
381 				break;
382 			case 2:		/* ack checkpoint */
383 				tt.tt_ack = 1;
384 				zz_lastc = -1;
385 				wwnreadack++;
386 				break;
387 			case 3:		/* nack checkpoint */
388 				tt.tt_ack = -1;
389 				zz_lastc = -1;
390 				wwnreadnack++;
391 				break;
392 			default:
393 				zz_lastc = c;
394 				wwnreadec++;
395 			}
396 		} else if (zz_ecc == 1) {
397 			if (c)
398 				*q++ = c;
399 			else
400 				zz_lastc = 0;
401 		} else {
402 			if (zz_lastc < 0) {
403 				zz_lastc = c;
404 			} else if (zz_lastc == c) {
405 				*q++ = zz_lastc;
406 				zz_lastc = -1;
407 			} else {
408 				wwnreadec++;
409 				zz_lastc = c;
410 			}
411 		}
412 	}
413 	return q - (p - n);
414 }
415 
zz_checksum(p,n)416 zz_checksum(p, n)
417 	char *p;
418 	int n;
419 {
420 	while (--n >= 0) {
421 		int c = *p++ & 0x7f;
422 		c ^= zz_sum;
423 		zz_sum = c << 1 | c >> 11 & 1;
424 	}
425 }
426 
zz_compress(flag)427 zz_compress(flag)
428 {
429 	if (flag)
430 		tt.tt_checksum = 0;
431 	else
432 		tt.tt_checksum = zz_checksum;
433 }
434 
zz_checkpoint()435 zz_checkpoint()
436 {
437 	static char x[] = { ctrl('['), 'V', 0, 0 };
438 
439 	zz_checksum(x, sizeof x);
440 	ttesc('V');
441 	ttputc(' ' + (zz_sum & 0x3f));
442 	ttputc(' ' + (zz_sum >> 6 & 0x3f));
443 	ttflush();
444 	zz_sum = 0;
445 }
446 
tt_zapple()447 tt_zapple()
448 {
449 	tt.tt_insspace = zz_insspace;
450 	tt.tt_delchar = zz_delchar;
451 	tt.tt_insline = zz_insline;
452 	tt.tt_delline = zz_delline;
453 	tt.tt_clreol = zz_clreol;
454 	tt.tt_clreos = zz_clreos;
455 	tt.tt_scroll_down = zz_scroll_down;
456 	tt.tt_scroll_up = zz_scroll_up;
457 	tt.tt_setscroll = zz_setscroll;
458 	tt.tt_availmodes = WWM_REV;
459 	tt.tt_wrap = 1;
460 	tt.tt_retain = 0;
461 	tt.tt_ncol = NCOL;
462 	tt.tt_nrow = NROW;
463 	tt.tt_start = zz_start;
464 	tt.tt_reset = zz_reset;
465 	tt.tt_end = zz_end;
466 	tt.tt_write = zz_write;
467 	tt.tt_putc = zz_putc;
468 	tt.tt_move = zz_move;
469 	tt.tt_clear = zz_clear;
470 	tt.tt_setmodes = zz_setmodes;
471 	tt.tt_frame = gen_frame;
472 	tt.tt_padc = TT_PADC_NONE;
473 	tt.tt_ntoken = 127;
474 	tt.tt_set_token = zz_set_token;
475 	tt.tt_put_token = zz_put_token;
476 	tt.tt_token_min = 1;
477 	tt.tt_token_max = TOKEN_MAX;
478 	tt.tt_set_token_cost = 2;
479 	tt.tt_put_token_cost = 1;
480 	tt.tt_compress = zz_compress;
481 	tt.tt_checksum = zz_checksum;
482 	tt.tt_checkpoint = zz_checkpoint;
483 	tt.tt_reset = zz_reset;
484 	tt.tt_rint = zz_rint;
485 	return 0;
486 }
487