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