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