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