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