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 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 n10.c 44 45 Device interfaces 46 */ 47 48 #include <limits.h> 49 #include <ctype.h> 50 #include <sys/types.h> 51 #include <sys/stat.h> 52 #ifdef EUC 53 #ifdef NROFF 54 #include <stdlib.h> 55 #endif /* NROFF */ 56 #endif /* EUC */ 57 #include "tdef.h" 58 #include "ext.h" 59 #include "tw.h" 60 61 struct t t; /* terminal characteristics */ 62 63 int dtab; 64 int plotmode; 65 int esct; 66 67 char xchname[4 * (NROFFCHARS-_SPECCHAR_ST)]; /* hy, em, etc. */ 68 short xchtab[NROFFCHARS-_SPECCHAR_ST]; /* indexes into chname[] */ 69 char *codestr; 70 char *chname = xchname; 71 short *chtab = xchtab; 72 int nchtab = 0; 73 74 75 int Inch; 76 int Hor; 77 int Vert; 78 int nfonts = 4; /* R, I, B, S */ 79 80 /* these characters are used as various signals or values 81 * in miscellaneous places. 82 * values are set in specnames in t10.c 83 */ 84 85 int c_hyphen; 86 int c_emdash; 87 int c_rule; 88 int c_minus; 89 int c_fi; 90 int c_fl; 91 int c_ff; 92 int c_ffi; 93 int c_ffl; 94 int c_acute; 95 int c_grave; 96 int c_under; 97 int c_rooten; 98 int c_boxrule; 99 int c_lefthand; 100 int c_dagger; 101 int c_isalnum; 102 103 int 104 ptinit() 105 { 106 int i, j; 107 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 return (0); 206 } 207 208 char *skipstr(s) /* skip over leading space plus string */ 209 char *s; 210 { 211 while (*s == ' ' || *s == '\t' || *s == '\n') 212 s++; 213 while (*s != ' ' && *s != '\t' && *s != '\n') 214 if (*s++ == '\\') 215 s++; 216 return s; 217 } 218 219 char *getstr(s, t) /* find next string in s, copy to t */ 220 char *s, *t; 221 { 222 int quote = 0; 223 224 while (*s == ' ' || *s == '\t' || *s == '\n') 225 s++; 226 if (*s == '"') { 227 s++; 228 quote = 1; 229 } 230 for (;;) { 231 if (quote && *s == '"') { 232 s++; 233 break; 234 } 235 if (!quote && (*s == ' ' || *s == '\t' || *s == '\n')) 236 break; 237 if (*s != '\\') 238 *t++ = *s++; 239 else { 240 s++; /* skip \\ */ 241 if (isdigit((unsigned char)s[0]) && 242 isdigit((unsigned char)s[1]) && 243 isdigit((unsigned char)s[2])) { 244 *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; 245 s += 2; 246 } else if (isdigit((unsigned char)s[0])) { 247 *t++ = *s - '0'; 248 } else if (*s == 'b') { 249 *t++ = '\b'; 250 } else if (*s == 'n') { 251 *t++ = '\n'; 252 } else if (*s == 'r') { 253 *t++ = '\r'; 254 } else if (*s == 't') { 255 *t++ = '\t'; 256 } else { 257 *t++ = *s; 258 } 259 s++; 260 } 261 } 262 *t = '\0'; 263 return s; 264 } 265 266 char *getint(s, pn) /* find integer at s */ 267 char *s; 268 int *pn; 269 { 270 int base; 271 272 while (*s == ' ' || *s == '\t' || *s == '\n') 273 s++; 274 base = (*s == '0') ? 8 : 10; 275 *pn = 0; 276 while (isdigit((unsigned char)*s)) 277 *pn = base * *pn + *s++ - '0'; 278 return s; 279 } 280 281 int 282 specnames() 283 { 284 static struct { 285 int *n; 286 char *v; 287 } spnames[] = { 288 &c_hyphen, "hy", 289 &c_emdash, "em", 290 &c_rule, "ru", 291 &c_minus, "\\-", 292 &c_fi, "fi", 293 &c_fl, "fl", 294 &c_ff, "ff", 295 &c_ffi, "Fi", 296 &c_ffl, "Fl", 297 &c_acute, "aa", 298 &c_grave, "ga", 299 &c_under, "ul", 300 &c_rooten, "rn", 301 &c_boxrule, "br", 302 &c_lefthand, "lh", 303 &c_isalnum, "__", 304 0, 0 305 }; 306 int i; 307 308 for (i = 0; spnames[i].n; i++) 309 *spnames[i].n = findch(spnames[i].v); 310 if (c_isalnum == 0) 311 c_isalnum = NROFFCHARS; 312 313 return (0); 314 } 315 316 317 int 318 findch(s) /* find char s in chname */ 319 char *s; 320 { 321 int i; 322 323 for (i = 0; chtab[i] != 0; i++) 324 if (strcmp(s, &chname[chtab[i]]) == 0) 325 return(i + _SPECCHAR_ST); 326 return(0); 327 } 328 329 int 330 twdone() 331 { 332 int waitf; 333 334 obufp = obuf; 335 if (t.twrest) /* has ptinit() been done yet? */ 336 oputs(t.twrest); 337 flusho(); 338 if (pipeflg) { 339 close(ptid); 340 wait(&waitf); 341 } 342 restore_tty(); 343 344 return (0); 345 } 346 347 348 int 349 ptout(i) 350 tchar i; 351 { 352 *olinep++ = i; 353 if (olinep >= &oline[LNSIZE]) 354 olinep--; 355 if (cbits(i) != '\n') 356 return (0); 357 olinep--; 358 lead += dip->blss + lss - t.Newline; 359 dip->blss = 0; 360 esct = esc = 0; 361 if (olinep > oline) { 362 move(); 363 ptout1(); 364 oputs(t.twnl); 365 } else { 366 lead += t.Newline; 367 move(); 368 } 369 lead += dip->alss; 370 dip->alss = 0; 371 olinep = oline; 372 373 return (0); 374 } 375 376 377 int 378 ptout1() 379 { 380 int k; 381 char *codep; 382 #ifdef EUC 383 #ifdef NROFF 384 int cnt; 385 tchar *qq; 386 #endif /* NROFF */ 387 #endif /* EUC */ 388 extern char *plot(); 389 int w, j, phyw; 390 #ifdef EUC 391 #ifdef NROFF 392 int jj; 393 #endif /* NROFF */ 394 #endif /* EUC */ 395 tchar * q, i; 396 static int oxfont = FT; /* start off in roman */ 397 398 for (q = oline; q < olinep; q++) { 399 i = *q; 400 if (ismot(i)) { 401 j = absmot(i); 402 if (isnmot(i)) 403 j = -j; 404 if (isvmot(i)) 405 lead += j; 406 else 407 esc += j; 408 continue; 409 } 410 if ((k = cbits(i)) <= 040) { 411 switch (k) { 412 case ' ': /*space*/ 413 esc += t.Char; 414 break; 415 case '\033': 416 case '\007': 417 case '\016': 418 case '\017': 419 oput(k); 420 break; 421 } 422 continue; 423 } 424 #ifdef EUC 425 #ifdef NROFF 426 if (multi_locale && ((k & MBMASK) || (k & CSMASK))) { 427 cnt = 0; 428 while ((*q & MBMASK1) && (cnt + 1 < (int)MB_CUR_MAX)) { 429 cnt++; 430 q++; 431 } 432 if ((cnt && !(*q & CSMASK)) || (*q & MBMASK1)) { 433 q -= cnt; 434 cnt = 0; 435 *q &= ~0xfe00; 436 } 437 k = cbits(i = *q); 438 phyw = w = t.Char * csi_width[cs(i)]; 439 } else { 440 #endif /* NROFF */ 441 #endif /* EUC */ 442 phyw = w = t.Char * t.width[k]; 443 if (iszbit(i)) 444 w = 0; 445 #ifdef EUC 446 #ifdef NROFF 447 } 448 #endif /* NROFF */ 449 #endif /* EUC */ 450 if (esc || lead) 451 move(); 452 esct += w; 453 #ifndef EUC 454 xfont = fbits(i); 455 #else 456 #ifndef NROFF 457 xfont = fbits(i); 458 #else 459 #endif /* NROFF */ 460 xfont = (fbits(*q) % NFONT); /* for invalid code */ 461 #endif /* EUC */ 462 if (xfont != oxfont) { 463 if (oxfont == ulfont || oxfont == BIFONT) 464 oputs(t.itoff); 465 if (bdtab[oxfont]) 466 oputs(t.bdoff); 467 if (xfont == ulfont || xfont == BIFONT) 468 oputs(t.iton); 469 if (bdtab[xfont]) 470 oputs(t.bdon); 471 oxfont = xfont; 472 } 473 if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) { 474 for (j = w / t.Char; j > 0; j--) 475 oput('_'); 476 for (j = w / t.Char; j > 0; j--) 477 oput('\b'); 478 } 479 if ((j = bdtab[xfont]) && !(*t.bdon & 0377)) 480 j++; 481 else 482 j = 1; /* number of overstrikes for bold */ 483 if (k < 128) { /* ordinary ascii */ 484 oput(k); 485 while (--j > 0) { 486 oput('\b'); 487 oput(k); 488 } 489 #ifdef EUC 490 #ifdef NROFF 491 } else if (multi_locale && (k & CSMASK)) { 492 for (qq = q - cnt; qq <= q;) 493 oput(cbits(*qq++)); 494 while (--j > 0) { 495 for (jj = cnt + 1; jj > 0; jj--) 496 oput('\b'); 497 for (qq = q - cnt; qq <= q;) 498 oput(cbits(*qq++)); 499 } 500 } else if (k < 256) { 501 /* 502 * Invalid character for C locale or 503 * non-printable 8-bit single byte 504 * character such as <no-break-sp> 505 * in ISO-8859-1 506 */ 507 oput(k); 508 while (--j > 0) { 509 oput('\b'); 510 oput(k); 511 } 512 #endif /* NROFF */ 513 #endif /* EUC */ 514 } else if (k >= nchtab + _SPECCHAR_ST) { 515 oput(k - nchtab - _SPECCHAR_ST); 516 } else { 517 int oj = j; 518 codep = t.codetab[k-_SPECCHAR_ST]; 519 while (*codep != 0) { 520 if (*codep & 0200) { 521 codep = plot(codep); 522 oput(' '); 523 } else { 524 if (*codep == '%') /* escape */ 525 codep++; 526 oput(*codep); 527 if (*codep == '\033') 528 oput(*++codep); 529 else if (*codep != '\b') 530 for (j = oj; --j > 0; ) { 531 oput('\b'); 532 oput(*codep); 533 } 534 codep++; 535 } 536 } 537 } 538 if (!w) 539 for (j = phyw / t.Char; j > 0; j--) 540 oput('\b'); 541 } 542 543 return (0); 544 } 545 546 547 char *plot(x) 548 char *x; 549 { 550 int i; 551 char *j, *k; 552 553 oputs(t.ploton); 554 k = x; 555 if ((*k & 0377) == 0200) 556 k++; 557 for (; *k; k++) { 558 if (*k == '%') { /* quote char within plot mode */ 559 oput(*++k); 560 } else if (*k & 0200) { 561 if (*k & 0100) { 562 if (*k & 040) 563 j = t.up; 564 else 565 j = t.down; 566 } else { 567 if (*k & 040) 568 j = t.left; 569 else 570 j = t.right; 571 } 572 if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ 573 ++k; 574 break; 575 } 576 while (i--) 577 oputs(j); 578 } else 579 oput(*k); 580 } 581 oputs(t.plotoff); 582 return(k); 583 } 584 585 586 int 587 move() 588 { 589 int k; 590 char *i, *j; 591 char *p, *q; 592 int iesct, dt; 593 594 iesct = esct; 595 if (esct += esc) 596 i = "\0"; 597 else 598 i = "\n\0"; 599 j = t.hlf; 600 p = t.right; 601 q = t.down; 602 if (lead) { 603 if (lead < 0) { 604 lead = -lead; 605 i = t.flr; 606 /* if(!esct)i = t.flr; else i = "\0";*/ 607 j = t.hlr; 608 q = t.up; 609 } 610 if (*i & 0377) { 611 k = lead / t.Newline; 612 lead = lead % t.Newline; 613 while (k--) 614 oputs(i); 615 } 616 if (*j & 0377) { 617 k = lead / t.Halfline; 618 lead = lead % t.Halfline; 619 while (k--) 620 oputs(j); 621 } else { /* no half-line forward, not at line begining */ 622 k = lead / t.Newline; 623 lead = lead % t.Newline; 624 if (k > 0) 625 esc = esct; 626 i = "\n"; 627 while (k--) 628 oputs(i); 629 } 630 } 631 if (esc) { 632 if (esc < 0) { 633 esc = -esc; 634 j = "\b"; 635 p = t.left; 636 } else { 637 j = " "; 638 if (hflg) 639 while ((dt = dtab - (iesct % dtab)) <= esc) { 640 if (dt % t.Em) 641 break; 642 oput(TAB); 643 esc -= dt; 644 iesct += dt; 645 } 646 } 647 k = esc / t.Em; 648 esc = esc % t.Em; 649 while (k--) 650 oputs(j); 651 } 652 if ((*t.ploton & 0377) && (esc || lead)) { 653 oputs(t.ploton); 654 esc /= t.Hor; 655 lead /= t.Vert; 656 while (esc--) 657 oputs(p); 658 while (lead--) 659 oputs(q); 660 oputs(t.plotoff); 661 } 662 esc = lead = 0; 663 664 return (0); 665 } 666 667 668 int 669 ptlead() 670 { 671 move(); 672 673 return (0); 674 } 675 676 677 int 678 dostop() 679 { 680 char junk; 681 682 flusho(); 683 read(2, &junk, 1); 684 685 return (0); 686 } 687 688 int 689 newpage() 690 { 691 return (0); 692 } 693 694 695 int 696 pttrailer() 697 { 698 return (0); 699 } 700