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 * t6.c 44 * 45 * width functions, sizes and fonts 46 */ 47 48 #include "tdef.h" 49 #include "dev.h" 50 #include <ctype.h> 51 #include "ext.h" 52 53 /* fitab[f][c] is 0 if c is not on font f */ 54 /* if it's non-zero, c is in fontab[f] at position 55 * fitab[f][c]. 56 */ 57 extern struct Font *fontbase[NFONT+1]; 58 extern char *codetab[NFONT+1]; 59 extern int nchtab; 60 61 int fontlab[NFONT+1]; 62 short *pstab; 63 int cstab[NFONT+1]; 64 int ccstab[NFONT+1]; 65 int bdtab[NFONT+1]; 66 int sbold = 0; 67 68 int 69 width(j) 70 tchar j; 71 { 72 int i, k; 73 74 if (j & (ZBIT|MOT)) { 75 if (iszbit(j)) 76 return(0); 77 if (isvmot(j)) 78 return(0); 79 k = absmot(j); 80 if (isnmot(j)) 81 k = -k; 82 return(k); 83 } 84 i = cbits(j); 85 if (i < ' ') { 86 if (i == '\b') 87 return(-widthp); 88 if (i == PRESC) 89 i = eschar; 90 else if (iscontrol(i)) 91 return(0); 92 } 93 if (i==ohc) 94 return(0); 95 i = trtab[i]; 96 if (i < 32) 97 return(0); 98 if (sfbits(j) == oldbits) { 99 xfont = pfont; 100 xpts = ppts; 101 } else 102 xbits(j, 0); 103 if (widcache[i-32].fontpts == (xfont<<8) + xpts && !setwdf) 104 k = widcache[i-32].width; 105 else { 106 k = getcw(i-32); 107 if (bd) 108 k += (bd - 1) * HOR; 109 if (cs) 110 k = cs; 111 } 112 widthp = k; 113 return(k); 114 } 115 116 /* 117 * clear width cache-- s means just space 118 */ 119 int 120 zapwcache(s) 121 { 122 int i; 123 124 if (s) { 125 widcache[0].fontpts = 0; 126 return (0); 127 } 128 for (i=0; i<NWIDCACHE; i++) 129 widcache[i].fontpts = 0; 130 131 return (0); 132 } 133 134 int 135 getcw(i) 136 int i; 137 { 138 int k; 139 char *p; 140 int x, j; 141 int nocache = 0; 142 143 bd = 0; 144 if (i >= nchtab + 128-32) { 145 j = abscw(i + 32 - (nchtab+128)); 146 goto g0; 147 } 148 if (i == 0) { /* a blank */ 149 k = (fontab[xfont][0] * spacesz + 6) / 12; 150 /* this nonsense because .ss cmd uses 1/36 em as its units */ 151 /* and default is 12 */ 152 goto g1; 153 } 154 if ((j = fitab[xfont][i] & BYTEMASK) == 0) { /* it's not on current font */ 155 /* search through search list of xfont 156 * to see what font it ought to be on. 157 * searches S, then remaining fonts in wraparound order. 158 */ 159 nocache = 1; 160 if (smnt) { 161 int ii, jj; 162 for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) { 163 j = fitab[ii][i] & BYTEMASK; 164 if (j != 0) { 165 p = fontab[ii]; 166 k = *(p + j); 167 if (xfont == sbold) 168 bd = bdtab[ii]; 169 if (setwdf) 170 numtab[CT].val |= kerntab[ii][j]; 171 goto g1; 172 } 173 } 174 } 175 k = fontab[xfont][0]; /* leave a space-size space */ 176 goto g1; 177 } 178 g0: 179 p = fontab[xfont]; 180 if (setwdf) 181 numtab[CT].val |= kerntab[xfont][j]; 182 k = *(p + j); 183 g1: 184 if (!bd) 185 bd = bdtab[xfont]; 186 if (cs = cstab[xfont]) { 187 nocache = 1; 188 if (ccs = ccstab[xfont]) 189 x = ccs; 190 else 191 x = xpts; 192 cs = (cs * EMPTS(x)) / 36; 193 } 194 k = ((k&BYTEMASK) * xpts + (Unitwidth / 2)) / Unitwidth; 195 if (nocache|bd) 196 widcache[i].fontpts = 0; 197 else { 198 widcache[i].fontpts = (xfont<<8) + xpts; 199 widcache[i].width = k; 200 } 201 return(k); 202 /* Unitwidth is Units/Point, where 203 * Units is the fundamental digitization 204 * of the character set widths, and 205 * Point is the number of goobies in a point 206 * e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6 207 * In effect, it's the size at which the widths 208 * translate directly into units. 209 */ 210 } 211 212 int 213 abscw(n) /* return index of abs char n in fontab[], etc. */ 214 { int i, ncf; 215 216 ncf = fontbase[xfont]->nwfont & BYTEMASK; 217 for (i = 0; i < ncf; i++) 218 if (codetab[xfont][i] == n) 219 return i; 220 return 0; 221 } 222 223 int 224 xbits(i, bitf) 225 tchar i; 226 { 227 int k; 228 229 xfont = fbits(i); 230 k = sbits(i); 231 if (k) { 232 xpts = pstab[--k]; 233 oldbits = sfbits(i); 234 pfont = xfont; 235 ppts = xpts; 236 return (0); 237 } 238 switch (bitf) { 239 case 0: 240 xfont = font; 241 xpts = pts; 242 break; 243 case 1: 244 xfont = pfont; 245 xpts = ppts; 246 break; 247 case 2: 248 xfont = mfont; 249 xpts = mpts; 250 } 251 252 return (0); 253 } 254 255 256 tchar setch() 257 { 258 int j; 259 char temp[10]; 260 char *s; 261 extern char *chname; 262 extern short *chtab; 263 extern int nchtab; 264 265 s = temp; 266 if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) 267 return(0); 268 *s = '\0'; 269 for (j = 0; j < nchtab; j++) 270 if (strcmp(&chname[chtab[j]], temp) == 0) 271 return(j + 128 | chbits); 272 return(0); 273 } 274 275 tchar setabs() /* set absolute char from \C'...' */ 276 { 277 int i, n, nf; 278 extern int nchtab; 279 280 getch(); 281 n = 0; 282 n = inumb(&n); 283 getch(); 284 if (nonumb) 285 return 0; 286 return n + nchtab + 128; 287 } 288 289 290 291 int 292 findft(i) 293 int i; 294 { 295 int k; 296 297 if ((k = i - '0') >= 0 && k <= nfonts && k < smnt) 298 return(k); 299 for (k = 0; fontlab[k] != i; k++) 300 if (k > nfonts) 301 return(-1); 302 return(k); 303 } 304 305 306 int 307 caseps() 308 { 309 int i; 310 311 if (skip()) 312 i = apts1; 313 else { 314 noscale++; 315 i = inumb(&apts); /* this is a disaster for fractional point sizes */ 316 noscale = 0; 317 if (nonumb) 318 return (0); 319 } 320 casps1(i); 321 322 return (0); 323 } 324 325 326 int 327 casps1(i) 328 int i; 329 { 330 331 /* 332 * in olden times, it used to ignore changes to 0 or negative. 333 * this is meant to allow the requested size to be anything, 334 * in particular so eqn can generate lots of \s-3's and still 335 * get back by matching \s+3's. 336 337 if (i <= 0) 338 return (0); 339 */ 340 apts1 = apts; 341 apts = i; 342 pts1 = pts; 343 pts = findps(i); 344 mchbits(); 345 346 return (0); 347 } 348 349 350 int 351 findps(i) 352 int i; 353 { 354 int j, k; 355 356 for (j=k=0 ; pstab[j] != 0 ; j++) 357 if (abs(pstab[j]-i) < abs(pstab[k]-i)) 358 k = j; 359 360 return(pstab[k]); 361 } 362 363 364 int 365 mchbits() 366 { 367 int i, j, k; 368 369 i = pts; 370 for (j = 0; i > (k = pstab[j]); j++) 371 if (!k) { 372 k = pstab[--j]; 373 break; 374 } 375 chbits = 0; 376 setsbits(chbits, ++j); 377 setfbits(chbits, font); 378 sps = width(' ' | chbits); 379 zapwcache(1); 380 381 return (0); 382 } 383 384 int 385 setps() 386 { 387 int i, j; 388 389 i = cbits(getch()); 390 if (ischar(i) && isdigit(i)) { /* \sd or \sdd */ 391 i -= '0'; 392 if (i == 0) /* \s0 */ 393 j = apts1; 394 else if (i <= 3 && ischar(j = cbits(ch = getch())) && 395 isdigit(j)) { /* \sdd */ 396 j = 10 * i + j - '0'; 397 ch = 0; 398 } else /* \sd */ 399 j = i; 400 } else if (i == '(') { /* \s(dd */ 401 j = cbits(getch()) - '0'; 402 j = 10 * j + cbits(getch()) - '0'; 403 if (j == 0) /* \s(00 */ 404 j = apts1; 405 } else if (i == '+' || i == '-') { /* \s+, \s- */ 406 j = cbits(getch()); 407 if (ischar(j) && isdigit(j)) { /* \s+d, \s-d */ 408 j -= '0'; 409 } else if (j == '(') { /* \s+(dd, \s-(dd */ 410 j = cbits(getch()) - '0'; 411 j = 10 * j + cbits(getch()) - '0'; 412 } 413 if (i == '-') 414 j = -j; 415 j += apts; 416 } 417 casps1(j); 418 419 return (0); 420 } 421 422 423 tchar setht() /* set character height from \H'...' */ 424 { 425 int n; 426 tchar c; 427 428 getch(); 429 n = inumb(&apts); 430 getch(); 431 if (n == 0 || nonumb) 432 n = apts; /* does this work? */ 433 c = CHARHT; 434 c |= ZBIT; 435 setsbits(c, n); 436 return(c); 437 } 438 439 tchar setslant() /* set slant from \S'...' */ 440 { 441 int n; 442 tchar c; 443 444 getch(); 445 n = 0; 446 n = inumb(&n); 447 getch(); 448 if (nonumb) 449 n = 0; 450 c = SLANT; 451 c |= ZBIT; 452 setsfbits(c, n+180); 453 return(c); 454 } 455 456 457 int 458 caseft() 459 { 460 skip(); 461 setfont(1); 462 463 return (0); 464 } 465 466 467 int 468 setfont(a) 469 int a; 470 { 471 int i, j; 472 473 if (a) 474 i = getrq(); 475 else 476 i = getsn(); 477 if (!i || i == 'P') { 478 j = font1; 479 goto s0; 480 } 481 if (i == 'S' || i == '0') 482 return (0); 483 if ((j = findft(i)) == -1) 484 if ((j = setfp(0, i, 0)) == -1) /* try to put it in position 0 */ 485 return (0); 486 s0: 487 font1 = font; 488 font = j; 489 mchbits(); 490 491 return (0); 492 } 493 494 495 int 496 setwd() 497 { 498 int base, wid; 499 tchar i; 500 int delim, emsz, k; 501 int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; 502 503 base = numtab[ST].val = numtab[ST].val = wid = numtab[CT].val = 0; 504 if (ismot(i = getch())) 505 return (0); 506 delim = cbits(i); 507 savhp = numtab[HP].val; 508 numtab[HP].val = 0; 509 savapts = apts; 510 savapts1 = apts1; 511 savfont = font; 512 savfont1 = font1; 513 savpts = pts; 514 savpts1 = pts1; 515 setwdf++; 516 while (cbits(i = getch()) != delim && !nlflg) { 517 k = width(i); 518 wid += k; 519 numtab[HP].val += k; 520 if (!ismot(i)) { 521 emsz = POINT * xpts; 522 } else if (isvmot(i)) { 523 k = absmot(i); 524 if (isnmot(i)) 525 k = -k; 526 base -= k; 527 emsz = 0; 528 } else 529 continue; 530 if (base < numtab[SB].val) 531 numtab[SB].val = base; 532 if ((k = base + emsz) > numtab[ST].val) 533 numtab[ST].val = k; 534 } 535 setn1(wid, 0, (tchar) 0); 536 numtab[HP].val = savhp; 537 apts = savapts; 538 apts1 = savapts1; 539 font = savfont; 540 font1 = savfont1; 541 pts = savpts; 542 pts1 = savpts1; 543 mchbits(); 544 setwdf = 0; 545 546 return (0); 547 } 548 549 550 tchar vmot() 551 { 552 dfact = lss; 553 vflag++; 554 return(mot()); 555 } 556 557 558 tchar hmot() 559 { 560 dfact = EM; 561 return(mot()); 562 } 563 564 565 tchar mot() 566 { 567 int j, n; 568 tchar i; 569 570 j = HOR; 571 getch(); /*eat delim*/ 572 if (n = atoi()) { 573 if (vflag) 574 j = VERT; 575 i = makem(quant(n, j)); 576 } else 577 i = 0; 578 getch(); 579 vflag = 0; 580 dfact = 1; 581 return(i); 582 } 583 584 585 tchar sethl(k) 586 int k; 587 { 588 int j; 589 tchar i; 590 591 j = EM / 2; 592 if (k == 'u') 593 j = -j; 594 else if (k == 'r') 595 j = -2 * j; 596 vflag++; 597 i = makem(j); 598 vflag = 0; 599 return(i); 600 } 601 602 603 tchar makem(i) 604 int i; 605 { 606 tchar j; 607 608 if ((j = i) < 0) 609 j = -j; 610 j |= MOT; 611 if (i < 0) 612 j |= NMOT; 613 if (vflag) 614 j |= VMOT; 615 return(j); 616 } 617 618 619 tchar getlg(i) 620 tchar i; 621 { 622 tchar j, k; 623 int lf; 624 625 if ((lf = fontbase[fbits(i)]->ligfont) == 0) /* font lacks ligatures */ 626 return(i); 627 j = getch0(); 628 if (cbits(j) == 'i' && (lf & LFI)) 629 j = LIG_FI; 630 else if (cbits(j) == 'l' && (lf & LFL)) 631 j = LIG_FL; 632 else if (cbits(j) == 'f' && (lf & LFF)) { 633 if ((lf & (LFFI|LFFL)) && lg != 2) { 634 k = getch0(); 635 if (cbits(k)=='i' && (lf&LFFI)) 636 j = LIG_FFI; 637 else if (cbits(k)=='l' && (lf&LFFL)) 638 j = LIG_FFL; 639 else { 640 *pbp++ = k; 641 j = LIG_FF; 642 } 643 } else 644 j = LIG_FF; 645 } else { 646 *pbp++ = j; 647 j = i; 648 } 649 return(i & SFMASK | j); 650 } 651 652 653 int 654 caselg() 655 { 656 657 lg = 1; 658 if (skip()) 659 return (0); 660 lg = atoi(); 661 662 return (0); 663 } 664 665 666 int 667 casefp() 668 { 669 int i, j; 670 char *s; 671 672 skip(); 673 if ((i = cbits(getch()) - '0') <= 0 || i > nfonts) 674 errprint(gettext("fp: bad font position %d"), i); 675 else if (skip() || !(j = getrq())) 676 errprint(gettext("fp: no font name")); 677 else if (skip() || !getname()) 678 setfp(i, j, 0); 679 else /* 3rd argument = filename */ 680 setfp(i, j, nextf); 681 682 return (0); 683 } 684 685 int 686 setfp(pos, f, truename) /* mount font f at position pos[0...nfonts] */ 687 int pos, f; 688 char *truename; 689 { 690 int k; 691 int n; 692 char longname[NS], shortname[20]; 693 extern int nchtab; 694 695 zapwcache(0); 696 if (truename) 697 strcpy(shortname, truename); 698 else { 699 shortname[0] = f & BYTEMASK; 700 shortname[1] = f >> BYTE; 701 shortname[2] = '\0'; 702 } 703 sprintf(longname, "%s/dev%s/%s.out", fontfile, devname, shortname); 704 if ((k = open(longname, 0)) < 0) { 705 errprint(gettext("Can't open %s"), longname); 706 return(-1); 707 } 708 n = fontbase[pos]->nwfont & BYTEMASK; 709 read(k, (char *) fontbase[pos], 3*n + nchtab + 128 - 32 + sizeof(struct Font)); 710 kerntab[pos] = (char *) fontab[pos] + (fontbase[pos]->nwfont & BYTEMASK); 711 /* have to reset the fitab pointer because the width may be different */ 712 fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BYTEMASK); 713 if ((fontbase[pos]->nwfont & BYTEMASK) > n) { 714 errprint(gettext("Font %s too big for position %d"), shortname, 715 pos); 716 return(-1); 717 } 718 fontbase[pos]->nwfont = n; /* so can load a larger one again later */ 719 close(k); 720 if (pos == smnt) { 721 smnt = 0; 722 sbold = 0; 723 } 724 if ((fontlab[pos] = f) == 'S') 725 smnt = pos; 726 bdtab[pos] = cstab[pos] = ccstab[pos] = 0; 727 /* if there is a directory, no place to store its name. */ 728 /* if position isn't zero, no place to store its value. */ 729 /* only time a FONTPOS is pushed back is if it's a */ 730 /* standard font on position 0 (i.e., mounted implicitly. */ 731 /* there's a bug here: if there are several input lines */ 732 /* that look like .ft XX in short successtion, the output */ 733 /* will all be in the last one because the "x font ..." */ 734 /* comes out too soon. pushing back FONTPOS doesn't work */ 735 /* with .ft commands because input is flushed after .xx cmds */ 736 ptfpcmd(pos, shortname); 737 if (pos == 0) 738 ch = (tchar) FONTPOS | (tchar) f << 16; 739 return(pos); 740 } 741 742 743 int 744 casecs() 745 { 746 int i, j; 747 748 noscale++; 749 skip(); 750 if (!(i = getrq()) || (i = findft(i)) < 0) 751 goto rtn; 752 skip(); 753 cstab[i] = atoi(); 754 skip(); 755 j = atoi(); 756 if (nonumb) 757 ccstab[i] = 0; 758 else 759 ccstab[i] = findps(j); 760 rtn: 761 zapwcache(0); 762 noscale = 0; 763 764 return (0); 765 } 766 767 768 int 769 casebd() 770 { 771 int i, j, k; 772 773 zapwcache(0); 774 k = 0; 775 bd0: 776 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { 777 if (k) 778 goto bd1; 779 else 780 return (0); 781 } 782 if (j == smnt) { 783 k = smnt; 784 goto bd0; 785 } 786 if (k) { 787 sbold = j; 788 j = k; 789 } 790 bd1: 791 skip(); 792 noscale++; 793 bdtab[j] = atoi(); 794 noscale = 0; 795 796 return (0); 797 } 798 799 800 int 801 casevs() 802 { 803 int i; 804 805 skip(); 806 vflag++; 807 dfact = INCH; /* default scaling is points! */ 808 dfactd = 72; 809 res = VERT; 810 i = inumb(&lss); 811 if (nonumb) 812 i = lss1; 813 if (i < VERT) 814 i = VERT; 815 lss1 = lss; 816 lss = i; 817 818 return (0); 819 } 820 821 822 int 823 casess() 824 { 825 int i; 826 827 noscale++; 828 skip(); 829 if (i = atoi()) { 830 spacesz = i & 0177; 831 zapwcache(0); 832 sps = width(' ' | chbits); 833 } 834 noscale = 0; 835 836 return (0); 837 } 838 839 840 tchar xlss() 841 { 842 /* stores \x'...' into 843 * two successive tchars. 844 * the first contains HX, the second the value, 845 * encoded as a vertical motion. 846 * decoding is done in n2.c by pchar(). 847 */ 848 int i; 849 850 getch(); 851 dfact = lss; 852 i = quant(atoi(), VERT); 853 dfact = 1; 854 getch(); 855 if (i >= 0) 856 *pbp++ = MOT | VMOT | i; 857 else 858 *pbp++ = MOT | VMOT | NMOT | -i; 859 return(HX); 860 } 861