t6.c (15468B)
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 int j; 221 char temp[50]; 222 char *s; 223 224 j = 0; 225 s = temp; 226 if (c == '(') { /* \(xx */ 227 if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) 228 return(0); 229 } else { /* \C'...' */ 230 c = getach(); 231 while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1) 232 s++; 233 } 234 *s = '\0'; 235 #ifdef UNICODE 236 return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ 237 #else 238 if (NROFF) { 239 j = chadd(temp, Troffchar, Lookup); 240 if ( j == -1) 241 return 0; 242 else 243 return j | chbits; 244 } else 245 return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ 246 247 #endif /*UNICODE*/ 248 } 249 250 Tchar t_setabs(void) /* set absolute char from \N'...' */ 251 { 252 int n; 253 char temp[10]; 254 255 getch(); /* delim */ 256 n = 0; 257 n = inumb(&n); 258 getch(); /* delim */ 259 if (nonumb) 260 return 0; 261 sprintf(temp, "%d", n); /* convert into "#n" */ 262 n = chadd(temp, Number, Install); 263 return n | chbits; 264 } 265 266 267 /* 268 * fontlab[] is a cache that contains font information 269 * for each font. 270 * fontlab[] contains the 1- or 2-character name of the 271 * font current associated with that font. 272 * fonts 1..nfonts correspond to the mounted fonts; 273 * the last of these are the special fonts. 274 * If we don't use the (named) font in one of the 275 * standard positions, we install the name in the next 276 * free slot of fontlab[] and font[]. 277 * Whenever we need info about the font, we 278 * read in the data into the next free slot with getfont. 279 * The ptfont() (t10.c) routine will tell 280 * the device filter to put the font always at position 281 * zero if xfont > nfonts, so no need to change these filters. 282 * Yes, this is a bit kludgy. 283 * 284 * This gives the new specs of findft: 285 * find the font name i, where i also can be a number. 286 * Installs the font(name) i when not present 287 * returns -1 on error 288 */ 289 290 int 291 t_findft(int i) 292 { 293 int k; 294 Uchar *p; 295 296 p = unpair(i); 297 298 if (isdigit(p[0])) { /* first look for numbers */ 299 k = p[0] - '0'; 300 if (p[1] > 0 && isdigit(p[1])) 301 k = 10 * k + p[1] - '0'; 302 if (k > 0 && k <= nfonts && k < smnt) 303 return(k); /* mounted font: .ft 3 */ 304 if (fontlab[k] && k <= MAXFONTS) { /* translate */ 305 return(k); /*number to a name */ 306 } else { 307 fprintf(stderr, "troff: no font at position %d\n", k); 308 return(-1); /* wild number */ 309 } 310 } 311 312 /* 313 * Now we look for font names 314 */ 315 for (k = 1; fontlab[k] != i; k++) { 316 if (k > MAXFONTS) 317 return(-1); /* running out of fontlab space */ 318 if (fontlab[k] == 0) { /* passed all existing names */ 319 if (setfp(k, i, (char *) 0, 1) == -1) 320 return(-1); 321 else { 322 fontlab[k] = i; /* install the name */ 323 return(k); 324 } 325 } 326 } 327 return(k); /* was one of the existing names */ 328 } 329 330 331 void caseps(void) 332 { 333 int i; 334 335 if (TROFF) { 336 if(skip()) 337 i = apts1; 338 else { 339 noscale++; 340 i = inumb(&apts); /* this is a disaster for fractional point sizes */ 341 noscale = 0; 342 if(nonumb) 343 i = apts1; 344 } 345 casps1(i); 346 } 347 } 348 349 350 void casps1(int i) 351 { 352 353 /* 354 * in olden times, it used to ignore changes to 0 or negative. 355 * this is meant to allow the requested size to be anything, 356 * in particular so eqn can generate lots of \s-3's and still 357 * get back by matching \s+3's. 358 359 if (i <= 0) 360 return; 361 */ 362 apts1 = apts; 363 apts = i; 364 pts1 = pts; 365 pts = findps(i); 366 mchbits(); 367 } 368 369 int 370 findps(int i) 371 { 372 int j, k; 373 374 for (j=k=0 ; pstab[j] != 0 ; j++) 375 if (abs(pstab[j]-i) < abs(pstab[k]-i)) 376 k = j; 377 378 return(pstab[k]); 379 } 380 381 382 void t_mchbits(void) 383 { 384 int i, j, k; 385 386 i = pts; 387 for (j = 0; i > (k = pstab[j]); j++) 388 if (!k) { 389 j--; 390 break; 391 } 392 chbits = 0; 393 setsbits(chbits, ++j); 394 setfbits(chbits, font); 395 sps = width(' ' | chbits); 396 zapwcache(1); 397 } 398 399 void t_setps(void) 400 { 401 int i, j; 402 403 j = 0; 404 i = cbits(getch()); 405 if (isdigit(i)) { /* \sd or \sdd */ 406 i -= '0'; 407 if (i == 0) /* \s0 */ 408 j = apts1; 409 else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */ 410 j = 10 * i + j - '0'; 411 ch = 0; 412 } else /* \sd */ 413 j = i; 414 } else if (i == '(') { /* \s(dd */ 415 j = cbits(getch()) - '0'; 416 j = 10 * j + cbits(getch()) - '0'; 417 if (j == 0) /* \s(00 */ 418 j = apts1; 419 } else if (i == '+' || i == '-') { /* \s+, \s- */ 420 j = cbits(getch()); 421 if (isdigit(j)) { /* \s+d, \s-d */ 422 j -= '0'; 423 } else if (j == '(') { /* \s+(dd, \s-(dd */ 424 j = cbits(getch()) - '0'; 425 j = 10 * j + cbits(getch()) - '0'; 426 } 427 if (i == '-') 428 j = -j; 429 j += apts; 430 } 431 casps1(j); 432 } 433 434 435 Tchar t_setht(void) /* set character height from \H'...' */ 436 { 437 int n; 438 Tchar c; 439 440 getch(); 441 n = inumb(&apts); 442 getch(); 443 if (n == 0 || nonumb) 444 n = apts; /* does this work? */ 445 c = CHARHT; 446 c |= ZBIT; 447 setsbits(c, n); 448 setfbits(c, pts); /* sneaky, CHARHT font bits are size bits */ 449 return(c); 450 } 451 452 Tchar t_setslant(void) /* set slant from \S'...' */ 453 { 454 int n; 455 Tchar c; 456 457 getch(); 458 n = 0; 459 n = inumb(&n); 460 getch(); 461 if (nonumb) 462 n = 0; 463 c = SLANT; 464 c |= ZBIT; 465 setsfbits(c, n+180); 466 return(c); 467 } 468 469 470 void caseft(void) 471 { 472 if (!TROFF) { 473 n_caseft(); 474 return; 475 } 476 skip(); 477 setfont(1); 478 } 479 480 481 void t_setfont(int a) 482 { 483 int i, j; 484 485 if (a) 486 i = getrq(); 487 else 488 i = getsn(); 489 if (!i || i == 'P') { 490 j = font1; 491 goto s0; 492 } 493 if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */ 494 return; 495 if ((j = findft(i)) == -1) 496 if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */ 497 return; 498 s0: 499 font1 = font; 500 font = j; 501 mchbits(); 502 } 503 504 505 void t_setwd(void) 506 { 507 int base, wid; 508 Tchar i; 509 int delim, emsz, k; 510 int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; 511 512 base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0; 513 if (ismot(i = getch())) 514 return; 515 delim = cbits(i); 516 savhp = numtabp[HP].val; 517 numtabp[HP].val = 0; 518 savapts = apts; 519 savapts1 = apts1; 520 savfont = font; 521 savfont1 = font1; 522 savpts = pts; 523 savpts1 = pts1; 524 setwdf++; 525 while (cbits(i = getch()) != delim && !nlflg) { 526 k = width(i); 527 wid += k; 528 numtabp[HP].val += k; 529 if (!ismot(i)) { 530 emsz = (INCH/72) * xpts; 531 } else if (isvmot(i)) { 532 k = absmot(i); 533 if (isnmot(i)) 534 k = -k; 535 base -= k; 536 emsz = 0; 537 } else 538 continue; 539 if (base < numtabp[SB].val) 540 numtabp[SB].val = base; 541 if ((k = base + emsz) > numtabp[ST].val) 542 numtabp[ST].val = k; 543 } 544 setn1(wid, 0, (Tchar) 0); 545 numtabp[HP].val = savhp; 546 apts = savapts; 547 apts1 = savapts1; 548 font = savfont; 549 font1 = savfont1; 550 pts = savpts; 551 pts1 = savpts1; 552 mchbits(); 553 setwdf = 0; 554 } 555 556 557 Tchar t_vmot(void) 558 { 559 dfact = lss; 560 vflag++; 561 return t_mot(); 562 } 563 564 565 Tchar t_hmot(void) 566 { 567 dfact = EM; 568 return t_mot(); 569 } 570 571 572 Tchar t_mot(void) 573 { 574 int j, n; 575 Tchar i; 576 577 j = HOR; 578 getch(); /*eat delim*/ 579 if (n = atoi0()) { 580 if (vflag) 581 j = VERT; 582 i = makem(quant(n, j)); 583 } else 584 i = 0; 585 getch(); 586 vflag = 0; 587 dfact = 1; 588 return(i); 589 } 590 591 592 Tchar t_sethl(int k) 593 { 594 int j; 595 Tchar i; 596 597 j = EM / 2; 598 if (k == 'u') 599 j = -j; 600 else if (k == 'r') 601 j = -2 * j; 602 vflag++; 603 i = makem(j); 604 vflag = 0; 605 return(i); 606 } 607 608 609 Tchar t_makem(int i) 610 { 611 Tchar j; 612 613 if (i >= 0) 614 j = i; 615 else 616 j = -i; 617 if (Hor > 1 && !vflag) 618 j = (j + Hor/2)/Hor * Hor; 619 j |= MOT; 620 if (i < 0) 621 j |= NMOT; 622 if (vflag) 623 j |= VMOT; 624 return(j); 625 } 626 627 628 Tchar getlg(Tchar i) 629 { 630 Tchar j, k; 631 int lf; 632 633 if (!TROFF) 634 return i; 635 if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */ 636 return(i); 637 j = getch0(); 638 if (cbits(j) == 'i' && (lf & LFI)) 639 j = LIG_FI; 640 else if (cbits(j) == 'l' && (lf & LFL)) 641 j = LIG_FL; 642 else if (cbits(j) == 'f' && (lf & LFF)) { 643 if ((lf & (LFFI|LFFL)) && lg != 2) { 644 k = getch0(); 645 if (cbits(k)=='i' && (lf&LFFI)) 646 j = LIG_FFI; 647 else if (cbits(k)=='l' && (lf&LFFL)) 648 j = LIG_FFL; 649 else { 650 *pbp++ = k; 651 j = LIG_FF; 652 } 653 } else 654 j = LIG_FF; 655 } else { 656 *pbp++ = j; 657 j = i; 658 } 659 return(i & SFMASK | j); 660 } 661 662 663 void caselg(void) 664 { 665 666 if(TROFF) { 667 skip(); 668 lg = atoi0(); 669 if (nonumb) 670 lg = 1; 671 } 672 } 673 674 void casefp(void) 675 { 676 int i, j; 677 678 if (!TROFF) { 679 n_casefp(); 680 return; 681 } 682 skip(); 683 i = cbits(getch()); 684 if (isdigit(i)) { 685 i -= '0'; 686 j = cbits(getch()); 687 if (isdigit(j)) 688 i = 10 * i + j - '0'; 689 } 690 if (i <= 0 || i > nfonts) 691 ERROR "fp: bad font position %d", i WARN; 692 else if (skip() || !(j = getrq())) 693 ERROR "fp: no font name" WARN; 694 else if (skip() || !getname()) 695 setfp(i, j, (char*) 0, 1); 696 else /* 3rd argument = filename */ 697 setfp(i, j, nextf, 1); 698 } 699 700 char *strdupl(const char *s) /* make a copy of s */ 701 { 702 char *t; 703 704 t = (char *) malloc(strlen(s) + 1); 705 if (t == NULL) 706 ERROR "out of space in strdupl(%s)", s FATAL; 707 strcpy(t, s); 708 return t; 709 } 710 711 int 712 setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */ 713 { 714 char pathname[NS], shortname[NS], *sl; 715 716 sl = (char*)0; 717 zapwcache(0); 718 if (truename) 719 strcpy(shortname, truename); 720 else 721 strcpy(shortname, (char *) unpair(f)); 722 if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */ 723 sprintf(pathname, "%s", truename); 724 if (fonts[pos].truename) 725 free(fonts[pos].truename); 726 fonts[pos].truename = strdupl(truename); 727 } else if (truename) { /* synonym: .fp 1 R Avant */ 728 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename); 729 truename = 0; /* so doesn't get repeated by ptfpcmd */ 730 } else /* vanilla: .fp 5 XX */ 731 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname); 732 if (truename == 0 && fonts[pos].truename != 0) { 733 free(fonts[pos].truename); 734 fonts[pos].truename = 0; 735 } 736 if (getfont(pathname, pos) < 0) { 737 ERROR "Can't open font file %s", pathname WARN; 738 return -1; 739 } 740 if (print && !ascii) { 741 ptfpcmd(pos, fonts[pos].longname, truename); 742 ptfont(); 743 } 744 if (pos == smnt) { 745 smnt = 0; 746 sbold = 0; 747 } 748 fontlab[pos] = f; 749 if (smnt == 0 && fonts[pos].specfont) 750 smnt = pos; 751 bdtab[pos] = cstab[pos] = ccstab[pos] = 0; 752 return pos; 753 } 754 755 /* 756 * .cs request; don't check legality of optional arguments 757 */ 758 void casecs(void) 759 { 760 int i, j; 761 762 if (TROFF) { 763 int savtr = trace; 764 765 trace = 0; 766 noscale++; 767 skip(); 768 if (!(i = getrq()) || (i = findft(i)) < 0) 769 goto rtn; 770 skip(); 771 cstab[i] = atoi0(); 772 skip(); 773 j = atoi0(); 774 if(nonumb) 775 ccstab[i] = 0; 776 else 777 ccstab[i] = findps(j); 778 rtn: 779 zapwcache(0); 780 noscale = 0; 781 trace = savtr; 782 } 783 } 784 785 786 void casebd(void) 787 { 788 int i, j, k; 789 790 j=0; 791 if (!TROFF) { 792 n_casebd(); 793 return; 794 } 795 zapwcache(0); 796 k = 0; 797 bd0: 798 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { 799 if (k) 800 goto bd1; 801 else 802 return; 803 } 804 if (j == smnt) { 805 k = smnt; 806 goto bd0; 807 } 808 if (k) { 809 sbold = j; 810 j = k; 811 } 812 bd1: 813 skip(); 814 noscale++; 815 bdtab[j] = atoi0(); 816 noscale = 0; 817 } 818 819 820 void casevs(void) 821 { 822 int i; 823 824 if (!TROFF) { 825 n_casevs(); 826 return; 827 } 828 skip(); 829 vflag++; 830 dfact = INCH; /* default scaling is points! */ 831 dfactd = 72; 832 res = VERT; 833 i = inumb(&lss); 834 if (nonumb) 835 i = lss1; 836 if (i < VERT) 837 i = VERT; 838 lss1 = lss; 839 lss = i; 840 } 841 842 843 void casess(void) 844 { 845 int i; 846 847 if(TROFF) { 848 noscale++; 849 skip(); 850 if(i = atoi0()) { 851 spacesz = i & 0177; 852 zapwcache(0); 853 sps = width(' ' | chbits); 854 } 855 noscale = 0; 856 } 857 } 858 859 860 Tchar t_xlss(void) 861 { 862 /* stores \x'...' into two successive Tchars. 863 /* the first contains HX, the second the value, 864 /* encoded as a vertical motion. 865 /* decoding is done in n2.c by pchar(). 866 */ 867 int i; 868 869 getch(); 870 dfact = lss; 871 i = quant(atoi0(), VERT); 872 dfact = 1; 873 getch(); 874 if (i >= 0) 875 *pbp++ = MOT | VMOT | i; 876 else 877 *pbp++ = MOT | VMOT | NMOT | -i; 878 return(HX); 879 } 880 881 Uchar *unpair(int i) 882 { 883 static Uchar name[3]; 884 885 name[0] = i & SHORTMASK; 886 name[1] = (i >> SHORT) & SHORTMASK; 887 name[2] = 0; 888 return name; 889 }