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