1 /* t6.c 1.8 (Berkeley) 85/04/30 */
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
width(j)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
getcw(i)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
xbits(i)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
setch()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
absch()187 tchar absch() /* absolute character number */
188 {
189 fprintf(stderr, "troff: no \\C yet\n");
190 return(0);
191 }
192
193
findft(i)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
caseps()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
casps1(i)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
findps(i)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
mchbits()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
setps()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
setht()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
setslant()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
casest()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
caseft()369 caseft()
370 {
371 skip();
372 setfont(1);
373 }
374
375
setfont(a)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
setwd()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
vmot()462 tchar vmot()
463 {
464 dfact = lss;
465 vflag++;
466 return(mot());
467 }
468
469
hmot()470 tchar hmot()
471 {
472 dfact = EM;
473 return(mot());
474 }
475
476
mot()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
sethl(k)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
makem(i)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
getlg(i)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
caselg()565 caselg()
566 {
567
568 lg = 1;
569 if (skip())
570 return;
571 lg = atoi();
572 }
573
574
casefp()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
setfp(pos,font)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 if (pos == i) return(i); /* already there, forget it */
614
615 #define ptrswap(x, y) { c = x; x = y; y = c; }
616 #define fptrswap(x, y) { c = (char*) (x); x = y; y = (struct font *) c; }
617
618 fptrswap(fontbase[pos], fontbase[i]);
619 ptrswap(fontab[pos], fontab[i]);
620 ptrswap(kerntab[pos], kerntab[i]);
621 ptrswap(fitab[pos], fitab[i]);
622 ptfpcmd(pos, shortname);
623 fontlab[i] = fontlab[pos];
624 /* tell driver about the swap */
625 shortname[0] = fontlab[pos] & BMASK;
626 shortname[1] = fontlab[pos] >> BYTE;
627 ptfpcmd(i, shortname);
628 fontlab[pos] = font;
629 if (pos == 0)
630 ch = (tchar) FONTPOS | (tchar) font << 16;
631 return(pos);
632 }
633
634 sprintf(longname, "%s/dev%s/%s.out", fontfile, devname, shortname);
635 if ((file = open(longname, 0)) < 0) {
636 fprintf(stderr, "troff: Can't open %s\n", longname);
637 return(-1);
638 }
639 n = fontbase[pos]->nwfont & BMASK;
640 read(file, fontbase[pos], 3*n + nchtab + 96 + sizeof(struct font));
641 kerntab[pos] = (char *) fontab[pos] + (fontbase[pos]->nwfont & BMASK);
642 /* have to reset the fitab pointer because the width may be different */
643 fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BMASK);
644 if ((fontbase[pos]->nwfont & BMASK) > n) {
645 fprintf(stderr, "troff: Font %s too big for position %d\n",
646 shortname, pos);
647 return(-1);
648 }
649 fontbase[pos]->nwfont = n; /* for loading a larger one later */
650 close(file);
651
652 fontlab[pos] = font;
653 bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
654 /* if position isn't zero, no place to store its value. */
655 /* only time a FONTPOS is pushed back is if it's a */
656 /* standard font on position 0 (i.e., mounted implicitly. */
657 /* there's a bug here: if there are several input lines */
658 /* that look like .ft XX in short successtion, the output */
659 /* will all be in the last one because the "x font ..." */
660 /* comes out too soon. pushing back FONTPOS doesn't work */
661 /* with .ft commands because input is flushed after .xx cmds */
662 ptfpcmd(pos, shortname);
663 if (pos == 0)
664 ch = (tchar) FONTPOS | (tchar) font << 16;
665 return(pos);
666 }
667
668
casecs()669 casecs()
670 {
671 register i, j;
672
673 noscale++;
674 skip();
675 if (!(i = getrq()) || (i = findft(i)) < 0)
676 goto rtn;
677 skip();
678 cstab[i] = atoi();
679 skip();
680 j = atoi();
681 if (nonumb)
682 ccstab[i] = 0;
683 else
684 ccstab[i] = findps(j);
685 rtn:
686 noscale = 0;
687 }
688
689
casebd()690 casebd()
691 {
692 register i, j, k;
693
694 k = 0;
695 bd0:
696 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
697 if (k)
698 goto bd1;
699 else
700 return;
701 }
702 if (k) {
703 sbold = j;
704 j = k;
705 }
706 bd1:
707 skip();
708 noscale++;
709 bdtab[j] = atoi();
710 noscale = 0;
711 }
712
713
casevs()714 casevs()
715 {
716 register i;
717
718 skip();
719 vflag++;
720 dfact = INCH; /* default scaling is points! */
721 dfactd = 72;
722 res = VERT;
723 i = inumb(&lss);
724 if (nonumb)
725 i = lss1;
726 /* if(i < VERT)i = VERT; */
727 if (i < VERT)
728 i = 0;
729 lss1 = lss;
730 lss = i;
731 }
732
733
casess()734 casess()
735 {
736 register i;
737
738 noscale++;
739 skip();
740 if (i = atoi()) {
741 spacesz = i & 0177;
742 sps = width(' ' | chbits);
743 }
744 noscale = 0;
745 }
746
747
xlss()748 tchar xlss()
749 {
750 /* stores \x'...' into
751 /* two successive tchars.
752 /* the first contains HX, the second the value,
753 /* encoded as a vertical motion.
754 /* decoding is done in n2.c by pchar().
755 */
756 int i;
757 tchar c;
758
759 getch();
760 dfact = lss;
761 i = quant(atoi(), VERT);
762 dfact = 1;
763 getch();
764 if (i >= 0)
765 ch0 = MOT | VMOT | i;
766 else
767 ch0 = MOT | VMOT | NMOT | -i;
768 c = HX;
769 dummy();
770 return(c);
771 }
772