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 case 1: 162 ttctrl('f'); 163 goto out; 164 case -2: 165 ttctrl('h'); 166 case -1: 167 ttctrl('h'); 168 goto out; 169 } 170 if ((col & 7) == 0 && x > 0 && x <= 16) { 171 ttctrl('i'); 172 if (x > 8) 173 ttctrl('i'); 174 goto out; 175 } 176 ttesc('<'); 177 ttputc(col + ' '); 178 goto out; 179 } 180 if (tt.tt_col == col) { 181 switch (row - tt.tt_row) { 182 case 2: 183 ttctrl('j'); 184 case 1: 185 ttctrl('j'); 186 goto out; 187 case -2: 188 ttctrl('k'); 189 case -1: 190 ttctrl('k'); 191 goto out; 192 } 193 if (col == 0) { 194 if (row == 0) 195 goto home; 196 if (row == NROW - 1) 197 goto ll; 198 } 199 ttesc('>'); 200 ttputc(row + ' '); 201 goto out; 202 } 203 if (col == 0) { 204 if (row == 0) { 205 home: 206 ttesc('0'); 207 goto out; 208 } 209 if (row == tt.tt_row + 1) { 210 /* 211 * Do newline first to match the sequence 212 * for scroll down and return 213 */ 214 ttctrl('j'); 215 ttctrl('m'); 216 goto out; 217 } 218 if (row == NROW - 1) { 219 ll: 220 ttesc('1'); 221 goto out; 222 } 223 } 224 /* favor local motion for better compression */ 225 if (row == tt.tt_row + 1) { 226 ttctrl('j'); 227 goto same_row; 228 } 229 if (row == tt.tt_row - 1) { 230 ttctrl('k'); 231 goto same_row; 232 } 233 ttesc('='); 234 ttputc(' ' + row); 235 ttputc(' ' + col); 236 out: 237 tt.tt_col = col; 238 tt.tt_row = row; 239 } 240 241 void 242 zz_start(void) 243 { 244 ttesc('T'); 245 ttputc(TOKEN_MAX + ' '); 246 ttesc('U'); 247 ttputc('!'); 248 zz_ecc = 1; 249 zz_lastc = -1; 250 ttesc('v'); 251 ttflush(); 252 zz_sum = 0; 253 zz_setscroll(0, NROW - 1); 254 zz_clear(); 255 zz_setmodes(0); 256 } 257 258 void 259 zz_reset(void) 260 { 261 zz_setscroll(0, NROW - 1); 262 tt.tt_modes = WWM_REV; 263 zz_setmodes(0); 264 tt.tt_col = tt.tt_row = -10; 265 } 266 267 void 268 zz_end(void) 269 { 270 ttesc('T'); 271 ttputc(' '); 272 ttesc('U'); 273 ttputc(' '); 274 zz_ecc = 0; 275 } 276 277 void 278 zz_clreol(void) 279 { 280 ttesc('2'); 281 } 282 283 void 284 zz_clreos(void) 285 { 286 ttesc('3'); 287 } 288 289 void 290 zz_clear(void) 291 { 292 ttesc('4'); 293 tt.tt_col = tt.tt_row = 0; 294 } 295 296 void 297 zz_insspace(int n) 298 { 299 if (n == 1) 300 ttesc('i'); 301 else { 302 ttesc('I'); 303 ttputc(n + ' '); 304 } 305 } 306 307 void 308 zz_delchar(int n) 309 { 310 if (n == 1) 311 ttesc('c'); 312 else { 313 ttesc('C'); 314 ttputc(n + ' '); 315 } 316 } 317 318 void 319 zz_scroll_down(int n) 320 { 321 if (n == 1) { 322 if (tt.tt_row == NROW - 1) 323 ttctrl('j'); 324 else 325 ttesc('f'); 326 } else { 327 ttesc('F'); 328 ttputc(n + ' '); 329 } 330 } 331 332 void 333 zz_scroll_up(int n) 334 { 335 if (n == 1) 336 ttesc('r'); 337 else { 338 ttesc('R'); 339 ttputc(n + ' '); 340 } 341 } 342 343 void 344 zz_setscroll(int top, int bot) 345 { 346 ttesc('?'); 347 ttputc(top + ' '); 348 ttputc(bot + ' '); 349 tt.tt_scroll_top = top; 350 tt.tt_scroll_bot = bot; 351 } 352 353 int zz_debug = 0; 354 355 void 356 zz_set_token(int t, char *s, int n) 357 { 358 if (tt.tt_nmodes != tt.tt_modes) 359 zz_setmodes(tt.tt_nmodes); 360 if (zz_debug) { 361 char buf[100]; 362 zz_setmodes(WWM_REV); 363 (void) sprintf(buf, "%02x=", t); 364 ttputs(buf); 365 tt.tt_col += 3; 366 } 367 ttputc(0x80); 368 ttputc(t + 1); 369 s[n - 1] |= 0x80; 370 ttwrite(s, n); 371 s[n - 1] &= ~0x80; 372 } 373 374 void 375 zz_put_token(int t, const char *s __unused, int n __unused) 376 { 377 if (tt.tt_nmodes != tt.tt_modes) 378 zz_setmodes(tt.tt_nmodes); 379 if (zz_debug) { 380 char buf[100]; 381 zz_setmodes(WWM_REV); 382 (void) sprintf(buf, "%02x>", t); 383 ttputs(buf); 384 tt.tt_col += 3; 385 } 386 ttputc(t + 0x81); 387 } 388 389 int 390 zz_rint(char *p, int n) 391 { 392 int i; 393 char *q; 394 395 if (!zz_ecc) 396 return n; 397 for (i = n, q = p; --i >= 0;) { 398 int c = (unsigned char) *p++; 399 400 if (zz_lastc == 0) { 401 switch (c) { 402 case 0: 403 *q++ = 0; 404 zz_lastc = -1; 405 break; 406 case 1: /* start input ecc */ 407 zz_ecc = 2; 408 zz_lastc = -1; 409 wwnreadstat++; 410 break; 411 case 2: /* ack checkpoint */ 412 tt.tt_ack = 1; 413 zz_lastc = -1; 414 wwnreadack++; 415 break; 416 case 3: /* nack checkpoint */ 417 tt.tt_ack = -1; 418 zz_lastc = -1; 419 wwnreadnack++; 420 break; 421 default: 422 zz_lastc = c; 423 wwnreadec++; 424 } 425 } else if (zz_ecc == 1) { 426 if (c) 427 *q++ = c; 428 else 429 zz_lastc = 0; 430 } else { 431 if (zz_lastc < 0) { 432 zz_lastc = c; 433 } else if (zz_lastc == c) { 434 *q++ = zz_lastc; 435 zz_lastc = -1; 436 } else { 437 wwnreadec++; 438 zz_lastc = c; 439 } 440 } 441 } 442 return q - (p - n); 443 } 444 445 void 446 zz_checksum(char *p, int n) 447 { 448 while (--n >= 0) { 449 int c = *p++ & 0x7f; 450 c ^= zz_sum; 451 zz_sum = c << 1 | (c >> 11 & 1); 452 } 453 } 454 455 void 456 zz_compress(int flag) 457 { 458 if (flag) 459 tt.tt_checksum = 0; 460 else 461 tt.tt_checksum = zz_checksum; 462 } 463 464 void 465 zz_checkpoint(void) 466 { 467 static char x[] = { ctrl('['), 'V', 0, 0 }; 468 469 zz_checksum(x, sizeof x); 470 ttesc('V'); 471 ttputc(' ' + (zz_sum & 0x3f)); 472 ttputc(' ' + (zz_sum >> 6 & 0x3f)); 473 ttflush(); 474 zz_sum = 0; 475 } 476 477 int 478 tt_zapple(void) 479 { 480 tt.tt_insspace = zz_insspace; 481 tt.tt_delchar = zz_delchar; 482 tt.tt_insline = zz_insline; 483 tt.tt_delline = zz_delline; 484 tt.tt_clreol = zz_clreol; 485 tt.tt_clreos = zz_clreos; 486 tt.tt_scroll_down = zz_scroll_down; 487 tt.tt_scroll_up = zz_scroll_up; 488 tt.tt_setscroll = zz_setscroll; 489 tt.tt_availmodes = WWM_REV; 490 tt.tt_wrap = 1; 491 tt.tt_retain = 0; 492 tt.tt_ncol = NCOL; 493 tt.tt_nrow = NROW; 494 tt.tt_start = zz_start; 495 tt.tt_reset = zz_reset; 496 tt.tt_end = zz_end; 497 tt.tt_write = zz_write; 498 tt.tt_putc = zz_putc; 499 tt.tt_move = zz_move; 500 tt.tt_clear = zz_clear; 501 tt.tt_setmodes = zz_setmodes; 502 tt.tt_frame = gen_frame; 503 tt.tt_padc = TT_PADC_NONE; 504 tt.tt_ntoken = 127; 505 tt.tt_set_token = zz_set_token; 506 tt.tt_put_token = zz_put_token; 507 tt.tt_token_min = 1; 508 tt.tt_token_max = TOKEN_MAX; 509 tt.tt_set_token_cost = 2; 510 tt.tt_put_token_cost = 1; 511 tt.tt_compress = zz_compress; 512 tt.tt_checksum = zz_checksum; 513 tt.tt_checkpoint = zz_checkpoint; 514 tt.tt_reset = zz_reset; 515 tt.tt_rint = zz_rint; 516 return 0; 517 } 518