1 #ifndef lint 2 /* 3 static char sccsid[]="@(#)n10.c 1.2 (CWI) 86/08/15"; 4 */ 5 static char sccsid[] = "@(#)n10.c 1.3 (Berkeley) 11/03/90"; 6 #endif 7 8 /* 9 n10.c 10 11 Device interfaces 12 */ 13 14 #include "tdef.h" 15 #include "ext.h" 16 #include "tw.h" 17 #include <sgtty.h> 18 #include <ctype.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 22 struct t t; /* terminal characteristics */ 23 24 int dtab; 25 int plotmode; 26 int esct; 27 28 char xchname[4 * (NROFFCHARS-128)]; /* hy, em, etc. */ 29 short xchtab[NROFFCHARS-128]; /* indexes into chname[] */ 30 char *codestr; 31 char *chname = xchname; 32 short *chtab = xchtab; 33 34 35 int Inch; 36 int Hor; 37 int Vert; 38 int nfonts = 4; /* R, I, B, S */ 39 40 /* these characters are used as various signals or values 41 /* in miscellaneous places. 42 /* values are set in specnames in t10.c 43 */ 44 45 int c_hyphen; 46 int c_emdash; 47 int c_rule; 48 int c_minus; 49 int c_fi; 50 int c_fl; 51 int c_ff; 52 int c_ffi; 53 int c_ffl; 54 int c_acute; 55 int c_grave; 56 int c_under; 57 int c_rooten; 58 int c_boxrule; 59 int c_lefthand; 60 int c_dagger; 61 int c_isalnum; 62 63 ptinit() 64 { 65 register int i, j; 66 register char *p, *cp, *q; 67 int nread, fd; 68 extern char *skipstr(), *getstr(), *getint(); 69 struct stat stbuf; 70 char check[50]; 71 72 strcat(termtab, devname); 73 if ((fd = open(termtab, 0)) < 0) { 74 errprint("cannot open %s", termtab); 75 exit(-1); 76 } 77 78 fstat(fd, &stbuf); 79 codestr = malloc((int) stbuf.st_size); 80 81 nread = read(fd, codestr, (int) stbuf.st_size); 82 close(fd); 83 84 p = codestr; 85 p = skipstr(p); /* skip over type, could check */ 86 p = skipstr(p); p = getint(p, &t.bset); 87 p = skipstr(p); p = getint(p, &t.breset); 88 p = skipstr(p); p = getint(p, &t.Hor); 89 p = skipstr(p); p = getint(p, &t.Vert); 90 p = skipstr(p); p = getint(p, &t.Newline); 91 p = skipstr(p); p = getint(p, &t.Char); 92 p = skipstr(p); p = getint(p, &t.Em); 93 p = skipstr(p); p = getint(p, &t.Halfline); 94 p = skipstr(p); p = getint(p, &t.Adj); 95 p = skipstr(p); p = getstr(p, t.twinit = p); 96 p = skipstr(p); p = getstr(p, t.twrest = p); 97 p = skipstr(p); p = getstr(p, t.twnl = p); 98 p = skipstr(p); p = getstr(p, t.hlr = p); 99 p = skipstr(p); p = getstr(p, t.hlf = p); 100 p = skipstr(p); p = getstr(p, t.flr = p); 101 p = skipstr(p); p = getstr(p, t.bdon = p); 102 p = skipstr(p); p = getstr(p, t.bdoff = p); 103 p = skipstr(p); p = getstr(p, t.iton = p); 104 p = skipstr(p); p = getstr(p, t.itoff = p); 105 p = skipstr(p); p = getstr(p, t.ploton = p); 106 p = skipstr(p); p = getstr(p, t.plotoff = p); 107 p = skipstr(p); p = getstr(p, t.up = p); 108 p = skipstr(p); p = getstr(p, t.down = p); 109 p = skipstr(p); p = getstr(p, t.right = p); 110 p = skipstr(p); p = getstr(p, t.left = p); 111 p = skipstr(p); p = getstr(p, t.eject = p); 112 113 getstr(p, check); 114 if (strcmp(check, "charset") != 0) { 115 errprint("device table apparently curdled"); 116 exit(1); 117 } 118 119 for (i = 0; i < 128; i++) 120 t.width[i] = 1; /* default ascii widths */ 121 122 i = 0; 123 /* this ought to be a pointer array and in place in codestr */ 124 cp = chname + 1; /* bug if starts at 0, in setch */ 125 while (p < codestr + nread) { 126 while (*p == ' ' || *p == '\t' || *p == '\n') 127 p++; 128 chtab[i] = cp - chname; /* index, not pointer */ 129 *cp++ = *p++; /* 2-char names */ 130 *cp++ = *p++; 131 *cp++ = '\0'; 132 while (*p == ' ' || *p == '\t') 133 p++; 134 t.width[i+128] = *p++ - '0'; 135 while (*p == ' ' || *p == '\t') 136 p++; 137 t.codetab[i] = p; 138 p = getstr(p, p); /* compress string */ 139 p++; 140 i++; 141 } 142 143 sps = EM; 144 ics = EM * 2; 145 dtab = 8 * t.Em; 146 for (i = 0; i < 16; i++) 147 tabtab[i] = dtab * (i + 1); 148 pl = 11 * INCH; 149 po = PO; 150 spacesz = SS; 151 lss = lss1 = VS; 152 ll = ll1 = lt = lt1 = LL; 153 smnt = nfonts = 5; /* R I B BI S */ 154 specnames(); /* install names like "hyphen", etc. */ 155 if (eqflg) 156 t.Adj = t.Hor; 157 } 158 159 char *skipstr(s) /* skip over leading space plus string */ 160 char *s; 161 { 162 while (*s == ' ' || *s == '\t' || *s == '\n') 163 s++; 164 while (*s != ' ' && *s != '\t' && *s != '\n') 165 if (*s++ == '\\') 166 s++; 167 return s; 168 } 169 170 char *getstr(s, t) /* find next string in s, copy to t */ 171 char *s, *t; 172 { 173 int quote = 0; 174 175 while (*s == ' ' || *s == '\t' || *s == '\n') 176 s++; 177 if (*s == '"') { 178 s++; 179 quote = 1; 180 } 181 for (;;) { 182 if (quote && *s == '"') { 183 s++; 184 break; 185 } 186 if (!quote && (*s == ' ' || *s == '\t' || *s == '\n')) 187 break; 188 if (*s != '\\') 189 *t++ = *s++; 190 else { 191 s++; /* skip \\ */ 192 if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) { 193 *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; 194 s += 2; 195 } else if (isdigit(s[0])) { 196 *t++ = *s - '0'; 197 } else if (*s == 'b') { 198 *t++ = '\b'; 199 } else if (*s == 'n') { 200 *t++ = '\n'; 201 } else if (*s == 'r') { 202 *t++ = '\r'; 203 } else if (*s == 't') { 204 *t++ = '\t'; 205 } else { 206 *t++ = *s; 207 } 208 s++; 209 } 210 } 211 *t = '\0'; 212 return s; 213 } 214 215 char *getint(s, pn) /* find integer at s */ 216 char *s; 217 int *pn; 218 { 219 while (*s == ' ' || *s == '\t' || *s == '\n') 220 s++; 221 *pn = 0; 222 while (isdigit(*s)) 223 *pn = 10 * *pn + *s++ - '0'; 224 return s; 225 } 226 227 specnames() 228 { 229 static struct { 230 int *n; 231 char *v; 232 } spnames[] = { 233 &c_hyphen, "hy", 234 &c_emdash, "em", 235 &c_rule, "ru", 236 &c_minus, "\\-", 237 &c_fi, "fi", 238 &c_fl, "fl", 239 &c_ff, "ff", 240 &c_ffi, "Fi", 241 &c_ffl, "Fl", 242 &c_acute, "aa", 243 &c_grave, "ga", 244 &c_under, "ul", 245 &c_rooten, "rn", 246 &c_boxrule, "br", 247 &c_lefthand, "lh", 248 &c_isalnum, "__", 249 0, 0 250 }; 251 int i; 252 253 for (i = 0; spnames[i].n; i++) 254 *spnames[i].n = findch(spnames[i].v); 255 if (c_isalnum == 0) 256 c_isalnum = NROFFCHARS; 257 } 258 259 260 findch(s) /* find char s in chname */ 261 register char *s; 262 { 263 register int i; 264 265 for (i = 0; chtab[i] != 0; i++) 266 if (strcmp(s, &chname[chtab[i]]) == 0) 267 return(i + 128); 268 return(0); 269 } 270 271 twdone() 272 { 273 int waitf; 274 275 oputs(t.twrest); 276 flusho(); 277 if (pipeflg) { 278 close(fileno(ptid)); 279 wait(&waitf); 280 } 281 if (ttysave != -1) { 282 ttys.sg_flags = ttysave; 283 stty(1, &ttys); 284 } 285 } 286 287 288 ptout(i) 289 tchar i; 290 { 291 *olinep++ = i; 292 if (olinep >= &oline[LNSIZE]) 293 olinep--; 294 if (cbits(i) != '\n') 295 return; 296 olinep--; 297 lead += dip->blss + lss - t.Newline; 298 dip->blss = 0; 299 esct = esc = 0; 300 if (olinep > oline) { 301 move(); 302 ptout1(); 303 oputs(t.twnl); 304 } else { 305 lead += t.Newline; 306 move(); 307 } 308 lead += dip->alss; 309 dip->alss = 0; 310 olinep = oline; 311 } 312 313 314 ptout1() 315 { 316 register k; 317 register char *codep; 318 extern char *plot(); 319 int w, j, phyw; 320 tchar * q, i; 321 static int oxfont = FT; /* start off in roman */ 322 323 for (q = oline; q < olinep; q++) { 324 i = *q; 325 if (ismot(i)) { 326 j = absmot(i); 327 if (isnmot(i)) 328 j = -j; 329 if (isvmot(i)) 330 lead += j; 331 else 332 esc += j; 333 continue; 334 } 335 if ((k = cbits(i)) <= 040) { 336 switch (k) { 337 case ' ': /*space*/ 338 esc += t.Char; 339 break; 340 case '\033': 341 case '\007': 342 case '\016': 343 case '\017': 344 oput(k); 345 break; 346 } 347 continue; 348 } 349 phyw = w = t.Char * t.width[k]; 350 if (iszbit(i)) 351 w = 0; 352 if (esc || lead) 353 move(); 354 esct += w; 355 xfont = fbits(i); 356 if (xfont != oxfont) { 357 switch (oxfont) { 358 case ULFONT: oputs(t.itoff); break; 359 case BDFONT: oputs(t.bdoff); break; 360 case BIFONT: oputs(t.itoff); oputs(t.bdoff); break; 361 } 362 switch (xfont) { 363 case ULFONT: 364 if (*t.iton & 0377) oputs(t.iton); break; 365 case BDFONT: 366 if (*t.bdon & 0377) oputs(t.bdon); break; 367 case BIFONT: 368 if (*t.bdon & 0377) oputs(t.bdon); 369 if (*t.iton & 0377) oputs(t.iton); 370 break; 371 } 372 oxfont = xfont; 373 } 374 if ((xfont == ULFONT || xfont == BIFONT) && !(*t.iton & 0377)) { 375 for (j = w / t.Char; j > 0; j--) 376 oput('_'); 377 for (j = w / t.Char; j > 0; j--) 378 oput('\b'); 379 } 380 if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT)) 381 j++; 382 else 383 j = 1; /* number of overstrikes for bold */ 384 if (k < 128) { /* ordinary ascii */ 385 oput(k); 386 while (--j > 0) { 387 oput('\b'); 388 oput(k); 389 } 390 } else { 391 int oj = j; 392 codep = t.codetab[k-128]; 393 while (*codep != 0) { 394 if (*codep & 0200) { 395 codep = plot(codep); 396 oput(' '); 397 } else { 398 if (*codep == '%') /* escape */ 399 codep++; 400 oput(*codep); 401 if (*codep != '\b') 402 for (j = oj; --j > 0; ) { 403 oput('\b'); 404 oput(*codep); 405 } 406 codep++; 407 } 408 } 409 } 410 if (!w) 411 for (j = phyw / t.Char; j > 0; j--) 412 oput('\b'); 413 } 414 } 415 416 417 char *plot(x) 418 char *x; 419 { 420 register int i; 421 register char *j, *k; 422 423 oputs(t.ploton); 424 k = x; 425 if ((*k & 0377) == 0200) 426 k++; 427 for (; *k; k++) { 428 if (*k == '%') { /* quote char within plot mode */ 429 oput(*++k); 430 } else if (*k & 0200) { 431 if (*k & 0100) { 432 if (*k & 040) 433 j = t.up; 434 else 435 j = t.down; 436 } else { 437 if (*k & 040) 438 j = t.left; 439 else 440 j = t.right; 441 } 442 if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ 443 ++k; 444 break; 445 } 446 while (i--) 447 oputs(j); 448 } else 449 oput(*k); 450 } 451 oputs(t.plotoff); 452 return(k); 453 } 454 455 456 move() 457 { 458 register k; 459 register char *i, *j; 460 char *p, *q; 461 int iesct, dt; 462 463 iesct = esct; 464 if (esct += esc) 465 i = "\0"; 466 else 467 i = "\n\0"; 468 j = t.hlf; 469 p = t.right; 470 q = t.down; 471 if (lead) { 472 if (lead < 0) { 473 lead = -lead; 474 i = t.flr; 475 /* if(!esct)i = t.flr; else i = "\0";*/ 476 j = t.hlr; 477 q = t.up; 478 } 479 if (*i & 0377) { 480 k = lead / t.Newline; 481 lead = lead % t.Newline; 482 while (k--) 483 oputs(i); 484 } 485 if (*j & 0377) { 486 k = lead / t.Halfline; 487 lead = lead % t.Halfline; 488 while (k--) 489 oputs(j); 490 } else { /* no half-line forward, not at line begining */ 491 k = lead / t.Newline; 492 lead = lead % t.Newline; 493 if (k > 0) 494 esc = esct; 495 i = "\n"; 496 while (k--) 497 oputs(i); 498 } 499 } 500 if (esc) { 501 if (esc < 0) { 502 esc = -esc; 503 j = "\b"; 504 p = t.left; 505 } else { 506 j = " "; 507 if (hflg) 508 while ((dt = dtab - (iesct % dtab)) <= esc) { 509 if (dt % t.Em) 510 break; 511 oput(TAB); 512 esc -= dt; 513 iesct += dt; 514 } 515 } 516 k = esc / t.Em; 517 esc = esc % t.Em; 518 while (k--) 519 oputs(j); 520 } 521 if ((*t.ploton & 0377) && (esc || lead)) { 522 oputs(t.ploton); 523 esc /= t.Hor; 524 lead /= t.Vert; 525 while (esc--) 526 oputs(p); 527 while (lead--) 528 oputs(q); 529 oputs(t.plotoff); 530 } 531 esc = lead = 0; 532 } 533 534 535 ptlead() 536 { 537 move(); 538 } 539 540 541 dostop() 542 { 543 char junk; 544 545 flusho(); 546 read(2, &junk, 1); 547 } 548 549 550 newpage(){;} 551 pttrailer(){;} 552