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