1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * University Copyright- Copyright (c) 1982, 1986, 1988 35 * The Regents of the University of California 36 * All Rights Reserved 37 * 38 * University Acknowledgment- Portions of this document are derived from 39 * software developed by the University of California, Berkeley, and its 40 * contributors. 41 */ 42 43 /* 44 n10.c 45 46 Device interfaces 47 */ 48 49 #include <limits.h> 50 #include <ctype.h> 51 #include <sys/types.h> 52 #include <sys/stat.h> 53 #ifdef EUC 54 #ifdef NROFF 55 #include <stdlib.h> 56 #endif /* NROFF */ 57 #endif /* EUC */ 58 #include "tdef.h" 59 #include "ext.h" 60 #include "tw.h" 61 62 struct t t; /* terminal characteristics */ 63 64 int dtab; 65 int plotmode; 66 int esct; 67 68 char xchname[4 * (NROFFCHARS-_SPECCHAR_ST)]; /* hy, em, etc. */ 69 short xchtab[NROFFCHARS-_SPECCHAR_ST]; /* indexes into chname[] */ 70 char *codestr; 71 char *chname = xchname; 72 short *chtab = xchtab; 73 int nchtab = 0; 74 75 76 int Inch; 77 int Hor; 78 int Vert; 79 int nfonts = 4; /* R, I, B, S */ 80 81 /* these characters are used as various signals or values 82 * in miscellaneous places. 83 * values are set in specnames in t10.c 84 */ 85 86 int c_hyphen; 87 int c_emdash; 88 int c_rule; 89 int c_minus; 90 int c_fi; 91 int c_fl; 92 int c_ff; 93 int c_ffi; 94 int c_ffl; 95 int c_acute; 96 int c_grave; 97 int c_under; 98 int c_rooten; 99 int c_boxrule; 100 int c_lefthand; 101 int c_dagger; 102 int c_isalnum; 103 104 ptinit() 105 { 106 register int i, j; 107 register char *p, *cp, *q; 108 int nread, fd; 109 extern char *skipstr(), *getstr(), *getint(); 110 extern char *setbrk(); 111 struct stat stbuf; 112 char check[50]; 113 114 strcat(termtab, devname); 115 if ((fd = open(termtab, 0)) < 0) { 116 errprint(gettext("cannot open %s"), termtab); 117 exit(-1); 118 } 119 120 fstat(fd, &stbuf); 121 codestr = setbrk((int) stbuf.st_size); 122 123 nread = read(fd, codestr, (int) stbuf.st_size); 124 close(fd); 125 126 p = codestr; 127 p = skipstr(p); /* skip over type, could check */ 128 p = skipstr(p); p = getint(p, &t.bset); 129 p = skipstr(p); p = getint(p, &t.breset); 130 p = skipstr(p); p = getint(p, &t.Hor); 131 p = skipstr(p); p = getint(p, &t.Vert); 132 p = skipstr(p); p = getint(p, &t.Newline); 133 p = skipstr(p); p = getint(p, &t.Char); 134 p = skipstr(p); p = getint(p, &t.Em); 135 p = skipstr(p); p = getint(p, &t.Halfline); 136 p = skipstr(p); p = getint(p, &t.Adj); 137 p = skipstr(p); p = getstr(p, t.twinit = p); 138 p = skipstr(p); p = getstr(p, t.twrest = p); 139 p = skipstr(p); p = getstr(p, t.twnl = p); 140 p = skipstr(p); p = getstr(p, t.hlr = p); 141 p = skipstr(p); p = getstr(p, t.hlf = p); 142 p = skipstr(p); p = getstr(p, t.flr = p); 143 p = skipstr(p); p = getstr(p, t.bdon = p); 144 p = skipstr(p); p = getstr(p, t.bdoff = p); 145 p = skipstr(p); p = getstr(p, t.iton = p); 146 p = skipstr(p); p = getstr(p, t.itoff = p); 147 p = skipstr(p); p = getstr(p, t.ploton = p); 148 p = skipstr(p); p = getstr(p, t.plotoff = p); 149 p = skipstr(p); p = getstr(p, t.up = p); 150 p = skipstr(p); p = getstr(p, t.down = p); 151 p = skipstr(p); p = getstr(p, t.right = p); 152 p = skipstr(p); p = getstr(p, t.left = p); 153 154 getstr(p, check); 155 if (strcmp(check, "charset") != 0) { 156 errprint(gettext("device table apparently curdled")); 157 exit(1); 158 } 159 160 for (i = 0; i < _SPECCHAR_ST; i++) 161 t.width[i] = 1; /* default widths */ 162 163 i = 0; 164 /* this ought to be a pointer array and in place in codestr */ 165 cp = chname + 1; /* bug if starts at 0, in setch */ 166 while (p < codestr + nread) { 167 while (*p == ' ' || *p == '\t' || *p == '\n') 168 p++; 169 if (i + _SPECCHAR_ST >= NROFFCHARS) { 170 errprint(gettext("too many names in charset for %s"), 171 termtab); 172 exit(1); 173 } 174 chtab[i] = cp - chname; /* index, not pointer */ 175 *cp++ = *p++; /* 2-char names */ 176 *cp++ = *p++; 177 *cp++ = '\0'; 178 while (*p == ' ' || *p == '\t') 179 p++; 180 t.width[i+_SPECCHAR_ST] = *p++ - '0'; 181 while (*p == ' ' || *p == '\t') 182 p++; 183 t.codetab[i] = p; 184 p = getstr(p, p); /* compress string */ 185 p++; 186 i++; 187 nchtab++; 188 } 189 190 sps = EM; 191 ics = EM * 2; 192 dtab = 8 * t.Em; 193 for (i = 0; i < 16; i++) 194 tabtab[i] = dtab * (i + 1); 195 pl = 11 * INCH; 196 po = PO; 197 spacesz = SS; 198 lss = lss1 = VS; 199 ll = ll1 = lt = lt1 = LL; 200 smnt = nfonts = 5; /* R I B BI S */ 201 specnames(); /* install names like "hyphen", etc. */ 202 if (eqflg) 203 t.Adj = t.Hor; 204 } 205 206 char *skipstr(s) /* skip over leading space plus string */ 207 char *s; 208 { 209 while (*s == ' ' || *s == '\t' || *s == '\n') 210 s++; 211 while (*s != ' ' && *s != '\t' && *s != '\n') 212 if (*s++ == '\\') 213 s++; 214 return s; 215 } 216 217 char *getstr(s, t) /* find next string in s, copy to t */ 218 char *s, *t; 219 { 220 int quote = 0; 221 222 while (*s == ' ' || *s == '\t' || *s == '\n') 223 s++; 224 if (*s == '"') { 225 s++; 226 quote = 1; 227 } 228 for (;;) { 229 if (quote && *s == '"') { 230 s++; 231 break; 232 } 233 if (!quote && (*s == ' ' || *s == '\t' || *s == '\n')) 234 break; 235 if (*s != '\\') 236 *t++ = *s++; 237 else { 238 s++; /* skip \\ */ 239 if (isdigit((unsigned char)s[0]) && 240 isdigit((unsigned char)s[1]) && 241 isdigit((unsigned char)s[2])) { 242 *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; 243 s += 2; 244 } else if (isdigit((unsigned char)s[0])) { 245 *t++ = *s - '0'; 246 } else if (*s == 'b') { 247 *t++ = '\b'; 248 } else if (*s == 'n') { 249 *t++ = '\n'; 250 } else if (*s == 'r') { 251 *t++ = '\r'; 252 } else if (*s == 't') { 253 *t++ = '\t'; 254 } else { 255 *t++ = *s; 256 } 257 s++; 258 } 259 } 260 *t = '\0'; 261 return s; 262 } 263 264 char *getint(s, pn) /* find integer at s */ 265 char *s; 266 int *pn; 267 { 268 int base; 269 270 while (*s == ' ' || *s == '\t' || *s == '\n') 271 s++; 272 base = (*s == '0') ? 8 : 10; 273 *pn = 0; 274 while (isdigit((unsigned char)*s)) 275 *pn = base * *pn + *s++ - '0'; 276 return s; 277 } 278 279 specnames() 280 { 281 static struct { 282 int *n; 283 char *v; 284 } spnames[] = { 285 &c_hyphen, "hy", 286 &c_emdash, "em", 287 &c_rule, "ru", 288 &c_minus, "\\-", 289 &c_fi, "fi", 290 &c_fl, "fl", 291 &c_ff, "ff", 292 &c_ffi, "Fi", 293 &c_ffl, "Fl", 294 &c_acute, "aa", 295 &c_grave, "ga", 296 &c_under, "ul", 297 &c_rooten, "rn", 298 &c_boxrule, "br", 299 &c_lefthand, "lh", 300 &c_isalnum, "__", 301 0, 0 302 }; 303 int i; 304 305 for (i = 0; spnames[i].n; i++) 306 *spnames[i].n = findch(spnames[i].v); 307 if (c_isalnum == 0) 308 c_isalnum = NROFFCHARS; 309 } 310 311 312 findch(s) /* find char s in chname */ 313 register char *s; 314 { 315 register int i; 316 317 for (i = 0; chtab[i] != 0; i++) 318 if (strcmp(s, &chname[chtab[i]]) == 0) 319 return(i + _SPECCHAR_ST); 320 return(0); 321 } 322 323 twdone() 324 { 325 int waitf; 326 327 obufp = obuf; 328 if (t.twrest) /* has ptinit() been done yet? */ 329 oputs(t.twrest); 330 flusho(); 331 if (pipeflg) { 332 close(ptid); 333 wait(&waitf); 334 } 335 restore_tty(); 336 } 337 338 339 ptout(i) 340 tchar i; 341 { 342 *olinep++ = i; 343 if (olinep >= &oline[LNSIZE]) 344 olinep--; 345 if (cbits(i) != '\n') 346 return; 347 olinep--; 348 lead += dip->blss + lss - t.Newline; 349 dip->blss = 0; 350 esct = esc = 0; 351 if (olinep > oline) { 352 move(); 353 ptout1(); 354 oputs(t.twnl); 355 } else { 356 lead += t.Newline; 357 move(); 358 } 359 lead += dip->alss; 360 dip->alss = 0; 361 olinep = oline; 362 } 363 364 365 ptout1() 366 { 367 register k; 368 register char *codep; 369 #ifdef EUC 370 #ifdef NROFF 371 register int cnt; 372 register tchar *qq; 373 #endif /* NROFF */ 374 #endif /* EUC */ 375 extern char *plot(); 376 int w, j, phyw; 377 #ifdef EUC 378 #ifdef NROFF 379 int jj; 380 #endif /* NROFF */ 381 #endif /* EUC */ 382 tchar * q, i; 383 static int oxfont = FT; /* start off in roman */ 384 385 for (q = oline; q < olinep; q++) { 386 i = *q; 387 if (ismot(i)) { 388 j = absmot(i); 389 if (isnmot(i)) 390 j = -j; 391 if (isvmot(i)) 392 lead += j; 393 else 394 esc += j; 395 continue; 396 } 397 if ((k = cbits(i)) <= 040) { 398 switch (k) { 399 case ' ': /*space*/ 400 esc += t.Char; 401 break; 402 case '\033': 403 case '\007': 404 case '\016': 405 case '\017': 406 oput(k); 407 break; 408 } 409 continue; 410 } 411 #ifdef EUC 412 #ifdef NROFF 413 if (multi_locale && ((k & MBMASK) || (k & CSMASK))) { 414 cnt = 0; 415 while ((*q & MBMASK1) && (cnt + 1 < (int)MB_CUR_MAX)) { 416 cnt++; 417 q++; 418 } 419 if ((cnt && !(*q & CSMASK)) || (*q & MBMASK1)) { 420 q -= cnt; 421 cnt = 0; 422 *q &= ~0xfe00; 423 } 424 k = cbits(i = *q); 425 phyw = w = t.Char * csi_width[cs(i)]; 426 } else { 427 #endif /* NROFF */ 428 #endif /* EUC */ 429 phyw = w = t.Char * t.width[k]; 430 if (iszbit(i)) 431 w = 0; 432 #ifdef EUC 433 #ifdef NROFF 434 } 435 #endif /* NROFF */ 436 #endif /* EUC */ 437 if (esc || lead) 438 move(); 439 esct += w; 440 #ifndef EUC 441 xfont = fbits(i); 442 #else 443 #ifndef NROFF 444 xfont = fbits(i); 445 #else 446 #endif /* NROFF */ 447 xfont = (fbits(*q) % NFONT); /* for invalid code */ 448 #endif /* EUC */ 449 if (xfont != oxfont) { 450 if (oxfont == ulfont || oxfont == BIFONT) 451 oputs(t.itoff); 452 if (bdtab[oxfont]) 453 oputs(t.bdoff); 454 if (xfont == ulfont || xfont == BIFONT) 455 oputs(t.iton); 456 if (bdtab[xfont]) 457 oputs(t.bdon); 458 oxfont = xfont; 459 } 460 if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) { 461 for (j = w / t.Char; j > 0; j--) 462 oput('_'); 463 for (j = w / t.Char; j > 0; j--) 464 oput('\b'); 465 } 466 if ((j = bdtab[xfont]) && !(*t.bdon & 0377)) 467 j++; 468 else 469 j = 1; /* number of overstrikes for bold */ 470 if (k < 128) { /* ordinary ascii */ 471 oput(k); 472 while (--j > 0) { 473 oput('\b'); 474 oput(k); 475 } 476 #ifdef EUC 477 #ifdef NROFF 478 } else if (multi_locale && (k & CSMASK)) { 479 for (qq = q - cnt; qq <= q;) 480 oput(cbits(*qq++)); 481 while (--j > 0) { 482 for (jj = cnt + 1; jj > 0; jj--) 483 oput('\b'); 484 for (qq = q - cnt; qq <= q;) 485 oput(cbits(*qq++)); 486 } 487 } else if (k < 256) { 488 /* 489 * Invalid character for C locale or 490 * non-printable 8-bit single byte 491 * character such as <no-break-sp> 492 * in ISO-8859-1 493 */ 494 oput(k); 495 while (--j > 0) { 496 oput('\b'); 497 oput(k); 498 } 499 #endif /* NROFF */ 500 #endif /* EUC */ 501 } else if (k >= nchtab + _SPECCHAR_ST) { 502 oput(k - nchtab - _SPECCHAR_ST); 503 } else { 504 int oj = j; 505 codep = t.codetab[k-_SPECCHAR_ST]; 506 while (*codep != 0) { 507 if (*codep & 0200) { 508 codep = plot(codep); 509 oput(' '); 510 } else { 511 if (*codep == '%') /* escape */ 512 codep++; 513 oput(*codep); 514 if (*codep == '\033') 515 oput(*++codep); 516 else if (*codep != '\b') 517 for (j = oj; --j > 0; ) { 518 oput('\b'); 519 oput(*codep); 520 } 521 codep++; 522 } 523 } 524 } 525 if (!w) 526 for (j = phyw / t.Char; j > 0; j--) 527 oput('\b'); 528 } 529 } 530 531 532 char *plot(x) 533 char *x; 534 { 535 register int i; 536 register char *j, *k; 537 538 oputs(t.ploton); 539 k = x; 540 if ((*k & 0377) == 0200) 541 k++; 542 for (; *k; k++) { 543 if (*k == '%') { /* quote char within plot mode */ 544 oput(*++k); 545 } else if (*k & 0200) { 546 if (*k & 0100) { 547 if (*k & 040) 548 j = t.up; 549 else 550 j = t.down; 551 } else { 552 if (*k & 040) 553 j = t.left; 554 else 555 j = t.right; 556 } 557 if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ 558 ++k; 559 break; 560 } 561 while (i--) 562 oputs(j); 563 } else 564 oput(*k); 565 } 566 oputs(t.plotoff); 567 return(k); 568 } 569 570 571 move() 572 { 573 register k; 574 register char *i, *j; 575 char *p, *q; 576 int iesct, dt; 577 578 iesct = esct; 579 if (esct += esc) 580 i = "\0"; 581 else 582 i = "\n\0"; 583 j = t.hlf; 584 p = t.right; 585 q = t.down; 586 if (lead) { 587 if (lead < 0) { 588 lead = -lead; 589 i = t.flr; 590 /* if(!esct)i = t.flr; else i = "\0";*/ 591 j = t.hlr; 592 q = t.up; 593 } 594 if (*i & 0377) { 595 k = lead / t.Newline; 596 lead = lead % t.Newline; 597 while (k--) 598 oputs(i); 599 } 600 if (*j & 0377) { 601 k = lead / t.Halfline; 602 lead = lead % t.Halfline; 603 while (k--) 604 oputs(j); 605 } else { /* no half-line forward, not at line begining */ 606 k = lead / t.Newline; 607 lead = lead % t.Newline; 608 if (k > 0) 609 esc = esct; 610 i = "\n"; 611 while (k--) 612 oputs(i); 613 } 614 } 615 if (esc) { 616 if (esc < 0) { 617 esc = -esc; 618 j = "\b"; 619 p = t.left; 620 } else { 621 j = " "; 622 if (hflg) 623 while ((dt = dtab - (iesct % dtab)) <= esc) { 624 if (dt % t.Em) 625 break; 626 oput(TAB); 627 esc -= dt; 628 iesct += dt; 629 } 630 } 631 k = esc / t.Em; 632 esc = esc % t.Em; 633 while (k--) 634 oputs(j); 635 } 636 if ((*t.ploton & 0377) && (esc || lead)) { 637 oputs(t.ploton); 638 esc /= t.Hor; 639 lead /= t.Vert; 640 while (esc--) 641 oputs(p); 642 while (lead--) 643 oputs(q); 644 oputs(t.plotoff); 645 } 646 esc = lead = 0; 647 } 648 649 650 ptlead() 651 { 652 move(); 653 } 654 655 656 dostop() 657 { 658 char junk; 659 660 flusho(); 661 read(2, &junk, 1); 662 } 663 664 665 newpage(){;} 666 pttrailer(){;} 667