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