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