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