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