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