xref: /illumos-gate/usr/src/cmd/troff/troff.d/t6.c (revision 538aa54d819fa7751ca82bcc30d4ed8c57ec2ef2)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*
43  * t6.c
44  *
45  * width functions, sizes and fonts
46  */
47 
48 #include "tdef.h"
49 #include "dev.h"
50 #include <ctype.h>
51 #include "ext.h"
52 
53 /* fitab[f][c] is 0 if c is not on font f */
54 	/* if it's non-zero, c is in fontab[f] at position
55 	 * fitab[f][c].
56 	 */
57 extern	struct Font *fontbase[NFONT+1];
58 extern	char *codetab[NFONT+1];
59 extern int nchtab;
60 
61 int	fontlab[NFONT+1];
62 short	*pstab;
63 int	cstab[NFONT+1];
64 int	ccstab[NFONT+1];
65 int	bdtab[NFONT+1];
66 int	sbold = 0;
67 
68 int
69 width(j)
70 tchar j;
71 {
72 	int	i, k;
73 
74 	if (j & (ZBIT|MOT)) {
75 		if (iszbit(j))
76 			return(0);
77 		if (isvmot(j))
78 			return(0);
79 		k = absmot(j);
80 		if (isnmot(j))
81 			k = -k;
82 		return(k);
83 	}
84 	i = cbits(j);
85 	if (i < ' ') {
86 		if (i == '\b')
87 			return(-widthp);
88 		if (i == PRESC)
89 			i = eschar;
90 		else if (iscontrol(i))
91 			return(0);
92 	}
93 	if (i==ohc)
94 		return(0);
95 	i = trtab[i];
96 	if (i < 32)
97 		return(0);
98 	if (sfbits(j) == oldbits) {
99 		xfont = pfont;
100 		xpts = ppts;
101 	} else
102 		xbits(j, 0);
103 	if (widcache[i-32].fontpts == (xfont<<8) + xpts && !setwdf)
104 		k = widcache[i-32].width;
105 	else {
106 		k = getcw(i-32);
107 		if (bd)
108 			k += (bd - 1) * HOR;
109 		if (cs)
110 			k = cs;
111 	}
112 	widthp = k;
113 	return(k);
114 }
115 
116 /*
117  * clear width cache-- s means just space
118  */
119 int
120 zapwcache(s)
121 {
122 	int	i;
123 
124 	if (s) {
125 		widcache[0].fontpts = 0;
126 		return (0);
127 	}
128 	for (i=0; i<NWIDCACHE; i++)
129 		widcache[i].fontpts = 0;
130 
131 	return (0);
132 }
133 
134 int
135 getcw(i)
136 int	i;
137 {
138 	int	k;
139 	char	*p;
140 	int	x, j;
141 	int nocache = 0;
142 
143 	bd = 0;
144 	if (i >= nchtab + 128-32) {
145 		j = abscw(i + 32 - (nchtab+128));
146 		goto g0;
147 	}
148 	if (i == 0) {	/* a blank */
149 		k = (fontab[xfont][0] * spacesz + 6) / 12;
150 		/* this nonsense because .ss cmd uses 1/36 em as its units */
151 		/* and default is 12 */
152 		goto g1;
153 	}
154 	if ((j = fitab[xfont][i] & BYTEMASK) == 0) {	/* it's not on current font */
155 		/* search through search list of xfont
156 		 * to see what font it ought to be on.
157 		 * searches S, then remaining fonts in wraparound order.
158 		 */
159 		nocache = 1;
160 		if (smnt) {
161 			int ii, jj;
162 			for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) {
163 				j = fitab[ii][i] & BYTEMASK;
164 				if (j != 0) {
165 					p = fontab[ii];
166 					k = *(p + j);
167 					if (xfont == sbold)
168 						bd = bdtab[ii];
169 					if (setwdf)
170 						numtab[CT].val |= kerntab[ii][j];
171 					goto g1;
172 				}
173 			}
174 		}
175 		k = fontab[xfont][0];	/* leave a space-size space */
176 		goto g1;
177 	}
178  g0:
179 	p = fontab[xfont];
180 	if (setwdf)
181 		numtab[CT].val |= kerntab[xfont][j];
182 	k = *(p + j);
183  g1:
184 	if (!bd)
185 		bd = bdtab[xfont];
186 	if (cs = cstab[xfont]) {
187 		nocache = 1;
188 		if (ccs = ccstab[xfont])
189 			x = ccs;
190 		else
191 			x = xpts;
192 		cs = (cs * EMPTS(x)) / 36;
193 	}
194 	k = ((k&BYTEMASK) * xpts + (Unitwidth / 2)) / Unitwidth;
195 	if (nocache|bd)
196 		widcache[i].fontpts = 0;
197 	else {
198 		widcache[i].fontpts = (xfont<<8) + xpts;
199 		widcache[i].width = k;
200 	}
201 	return(k);
202 	/* Unitwidth is Units/Point, where
203 	 * Units is the fundamental digitization
204 	 * of the character set widths, and
205 	 * Point is the number of goobies in a point
206 	 * e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
207 	 * In effect, it's the size at which the widths
208 	 * translate directly into units.
209 	 */
210 }
211 
212 int
213 abscw(n)	/* return index of abs char n in fontab[], etc. */
214 {	int i, ncf;
215 
216 	ncf = fontbase[xfont]->nwfont & BYTEMASK;
217 	for (i = 0; i < ncf; i++)
218 		if (codetab[xfont][i] == n)
219 			return i;
220 	return 0;
221 }
222 
223 int
224 xbits(i, bitf)
225 tchar i;
226 {
227 	int	k;
228 
229 	xfont = fbits(i);
230 	k = sbits(i);
231 	if (k) {
232 		xpts = pstab[--k];
233 		oldbits = sfbits(i);
234 		pfont = xfont;
235 		ppts = xpts;
236 		return (0);
237 	}
238 	switch (bitf) {
239 	case 0:
240 		xfont = font;
241 		xpts = pts;
242 		break;
243 	case 1:
244 		xfont = pfont;
245 		xpts = ppts;
246 		break;
247 	case 2:
248 		xfont = mfont;
249 		xpts = mpts;
250 	}
251 
252 	return (0);
253 }
254 
255 
256 tchar setch()
257 {
258 	int	j;
259 	char	temp[10];
260 	char	*s;
261 	extern char	*chname;
262 	extern short	*chtab;
263 	extern int	nchtab;
264 
265 	s = temp;
266 	if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
267 		return(0);
268 	*s = '\0';
269 	for (j = 0; j < nchtab; j++)
270 		if (strcmp(&chname[chtab[j]], temp) == 0)
271 			return(j + 128 | chbits);
272 	return(0);
273 }
274 
275 tchar setabs()		/* set absolute char from \C'...' */
276 {
277 	int i, n, nf;
278 	extern int	nchtab;
279 
280 	getch();
281 	n = 0;
282 	n = inumb(&n);
283 	getch();
284 	if (nonumb)
285 		return 0;
286 	return n + nchtab + 128;
287 }
288 
289 
290 
291 int
292 findft(i)
293 int	i;
294 {
295 	int	k;
296 
297 	if ((k = i - '0') >= 0 && k <= nfonts && k < smnt)
298 		return(k);
299 	for (k = 0; fontlab[k] != i; k++)
300 		if (k > nfonts)
301 			return(-1);
302 	return(k);
303 }
304 
305 
306 int
307 caseps()
308 {
309 	int	i;
310 
311 	if (skip())
312 		i = apts1;
313 	else {
314 		noscale++;
315 		i = inumb(&apts);	/* this is a disaster for fractional point sizes */
316 		noscale = 0;
317 		if (nonumb)
318 			return (0);
319 	}
320 	casps1(i);
321 
322 	return (0);
323 }
324 
325 
326 int
327 casps1(i)
328 int	i;
329 {
330 
331 /*
332  * in olden times, it used to ignore changes to 0 or negative.
333  * this is meant to allow the requested size to be anything,
334  * in particular so eqn can generate lots of \s-3's and still
335  * get back by matching \s+3's.
336 
337 	if (i <= 0)
338 		return (0);
339 */
340 	apts1 = apts;
341 	apts = i;
342 	pts1 = pts;
343 	pts = findps(i);
344 	mchbits();
345 
346 	return (0);
347 }
348 
349 
350 int
351 findps(i)
352 int	i;
353 {
354 	int	j, k;
355 
356 	for (j=k=0 ; pstab[j] != 0 ; j++)
357 		if (abs(pstab[j]-i) < abs(pstab[k]-i))
358 			k = j;
359 
360 	return(pstab[k]);
361 }
362 
363 
364 int
365 mchbits()
366 {
367 	int	i, j, k;
368 
369 	i = pts;
370 	for (j = 0; i > (k = pstab[j]); j++)
371 		if (!k) {
372 			k = pstab[--j];
373 			break;
374 		}
375 	chbits = 0;
376 	setsbits(chbits, ++j);
377 	setfbits(chbits, font);
378 	sps = width(' ' | chbits);
379 	zapwcache(1);
380 
381 	return (0);
382 }
383 
384 int
385 setps()
386 {
387 	int i, j;
388 
389 	i = cbits(getch());
390 	if (ischar(i) && isdigit(i)) {		/* \sd or \sdd */
391 		i -= '0';
392 		if (i == 0)		/* \s0 */
393 			j = apts1;
394 		else if (i <= 3 && ischar(j = cbits(ch = getch())) &&
395 		    isdigit(j)) {	/* \sdd */
396 			j = 10 * i + j - '0';
397 			ch = 0;
398 		} else		/* \sd */
399 			j = i;
400 	} else if (i == '(') {		/* \s(dd */
401 		j = cbits(getch()) - '0';
402 		j = 10 * j + cbits(getch()) - '0';
403 		if (j == 0)		/* \s(00 */
404 			j = apts1;
405 	} else if (i == '+' || i == '-') {	/* \s+, \s- */
406 		j = cbits(getch());
407 		if (ischar(j) && isdigit(j)) {		/* \s+d, \s-d */
408 			j -= '0';
409 		} else if (j == '(') {		/* \s+(dd, \s-(dd */
410 			j = cbits(getch()) - '0';
411 			j = 10 * j + cbits(getch()) - '0';
412 		}
413 		if (i == '-')
414 			j = -j;
415 		j += apts;
416 	}
417 	casps1(j);
418 
419 	return (0);
420 }
421 
422 
423 tchar setht()		/* set character height from \H'...' */
424 {
425 	int n;
426 	tchar c;
427 
428 	getch();
429 	n = inumb(&apts);
430 	getch();
431 	if (n == 0 || nonumb)
432 		n = apts;	/* does this work? */
433 	c = CHARHT;
434 	c |= ZBIT;
435 	setsbits(c, n);
436 	return(c);
437 }
438 
439 tchar setslant()		/* set slant from \S'...' */
440 {
441 	int n;
442 	tchar c;
443 
444 	getch();
445 	n = 0;
446 	n = inumb(&n);
447 	getch();
448 	if (nonumb)
449 		n = 0;
450 	c = SLANT;
451 	c |= ZBIT;
452 	setsfbits(c, n+180);
453 	return(c);
454 }
455 
456 
457 int
458 caseft()
459 {
460 	skip();
461 	setfont(1);
462 
463 	return (0);
464 }
465 
466 
467 int
468 setfont(a)
469 int	a;
470 {
471 	int	i, j;
472 
473 	if (a)
474 		i = getrq();
475 	else
476 		i = getsn();
477 	if (!i || i == 'P') {
478 		j = font1;
479 		goto s0;
480 	}
481 	if (i == 'S' || i == '0')
482 		return (0);
483 	if ((j = findft(i)) == -1)
484 		if ((j = setfp(0, i, 0)) == -1)	/* try to put it in position 0 */
485 			return (0);
486 s0:
487 	font1 = font;
488 	font = j;
489 	mchbits();
490 
491 	return (0);
492 }
493 
494 
495 int
496 setwd()
497 {
498 	int	base, wid;
499 	tchar i;
500 	int	delim, emsz, k;
501 	int	savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
502 
503 	base = numtab[ST].val = numtab[ST].val = wid = numtab[CT].val = 0;
504 	if (ismot(i = getch()))
505 		return (0);
506 	delim = cbits(i);
507 	savhp = numtab[HP].val;
508 	numtab[HP].val = 0;
509 	savapts = apts;
510 	savapts1 = apts1;
511 	savfont = font;
512 	savfont1 = font1;
513 	savpts = pts;
514 	savpts1 = pts1;
515 	setwdf++;
516 	while (cbits(i = getch()) != delim && !nlflg) {
517 		k = width(i);
518 		wid += k;
519 		numtab[HP].val += k;
520 		if (!ismot(i)) {
521 			emsz = POINT * xpts;
522 		} else if (isvmot(i)) {
523 			k = absmot(i);
524 			if (isnmot(i))
525 				k = -k;
526 			base -= k;
527 			emsz = 0;
528 		} else
529 			continue;
530 		if (base < numtab[SB].val)
531 			numtab[SB].val = base;
532 		if ((k = base + emsz) > numtab[ST].val)
533 			numtab[ST].val = k;
534 	}
535 	setn1(wid, 0, (tchar) 0);
536 	numtab[HP].val = savhp;
537 	apts = savapts;
538 	apts1 = savapts1;
539 	font = savfont;
540 	font1 = savfont1;
541 	pts = savpts;
542 	pts1 = savpts1;
543 	mchbits();
544 	setwdf = 0;
545 
546 	return (0);
547 }
548 
549 
550 tchar vmot()
551 {
552 	dfact = lss;
553 	vflag++;
554 	return(mot());
555 }
556 
557 
558 tchar hmot()
559 {
560 	dfact = EM;
561 	return(mot());
562 }
563 
564 
565 tchar mot()
566 {
567 	int j, n;
568 	tchar i;
569 
570 	j = HOR;
571 	getch(); /*eat delim*/
572 	if (n = atoi()) {
573 		if (vflag)
574 			j = VERT;
575 		i = makem(quant(n, j));
576 	} else
577 		i = 0;
578 	getch();
579 	vflag = 0;
580 	dfact = 1;
581 	return(i);
582 }
583 
584 
585 tchar sethl(k)
586 int	k;
587 {
588 	int	j;
589 	tchar i;
590 
591 	j = EM / 2;
592 	if (k == 'u')
593 		j = -j;
594 	else if (k == 'r')
595 		j = -2 * j;
596 	vflag++;
597 	i = makem(j);
598 	vflag = 0;
599 	return(i);
600 }
601 
602 
603 tchar makem(i)
604 int	i;
605 {
606 	tchar j;
607 
608 	if ((j = i) < 0)
609 		j = -j;
610 	j |= MOT;
611 	if (i < 0)
612 		j |= NMOT;
613 	if (vflag)
614 		j |= VMOT;
615 	return(j);
616 }
617 
618 
619 tchar getlg(i)
620 tchar i;
621 {
622 	tchar j, k;
623 	int lf;
624 
625 	if ((lf = fontbase[fbits(i)]->ligfont) == 0) /* font lacks ligatures */
626 		return(i);
627 	j = getch0();
628 	if (cbits(j) == 'i' && (lf & LFI))
629 		j = LIG_FI;
630 	else if (cbits(j) == 'l' && (lf & LFL))
631 		j = LIG_FL;
632 	else if (cbits(j) == 'f' && (lf & LFF)) {
633 		if ((lf & (LFFI|LFFL)) && lg != 2) {
634 			k = getch0();
635 			if (cbits(k)=='i' && (lf&LFFI))
636 				j = LIG_FFI;
637 			else if (cbits(k)=='l' && (lf&LFFL))
638 				j = LIG_FFL;
639 			else {
640 				*pbp++ = k;
641 				j = LIG_FF;
642 			}
643 		} else
644 			j = LIG_FF;
645 	} else {
646 		*pbp++ = j;
647 		j = i;
648 	}
649 	return(i & SFMASK | j);
650 }
651 
652 
653 int
654 caselg()
655 {
656 
657 	lg = 1;
658 	if (skip())
659 		return (0);
660 	lg = atoi();
661 
662 	return (0);
663 }
664 
665 
666 int
667 casefp()
668 {
669 	int i, j;
670 	char *s;
671 
672 	skip();
673 	if ((i = cbits(getch()) - '0') <= 0 || i > nfonts)
674 		errprint(gettext("fp: bad font position %d"), i);
675 	else if (skip() || !(j = getrq()))
676 		errprint(gettext("fp: no font name"));
677 	else if (skip() || !getname())
678 		setfp(i, j, 0);
679 	else		/* 3rd argument = filename */
680 		setfp(i, j, nextf);
681 
682 	return (0);
683 }
684 
685 int
686 setfp(pos, f, truename)	/* mount font f at position pos[0...nfonts] */
687 int pos, f;
688 char *truename;
689 {
690 	int	k;
691 	int n;
692 	char longname[NS], shortname[20];
693 	extern int nchtab;
694 
695 	zapwcache(0);
696 	if (truename)
697 		strcpy(shortname, truename);
698 	else {
699 		shortname[0] = f & BYTEMASK;
700 		shortname[1] = f >> BYTE;
701 		shortname[2] = '\0';
702 	}
703 	sprintf(longname, "%s/dev%s/%s.out", fontfile, devname, shortname);
704 	if ((k = open(longname, 0)) < 0) {
705 		errprint(gettext("Can't open %s"), longname);
706 		return(-1);
707 	}
708 	n = fontbase[pos]->nwfont & BYTEMASK;
709 	read(k, (char *) fontbase[pos], 3*n + nchtab + 128 - 32 + sizeof(struct Font));
710 	kerntab[pos] = (char *) fontab[pos] + (fontbase[pos]->nwfont & BYTEMASK);
711 	/* have to reset the fitab pointer because the width may be different */
712 	fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BYTEMASK);
713 	if ((fontbase[pos]->nwfont & BYTEMASK) > n) {
714 		errprint(gettext("Font %s too big for position %d"), shortname,
715 			pos);
716 		return(-1);
717 	}
718 	fontbase[pos]->nwfont = n;	/* so can load a larger one again later */
719 	close(k);
720 	if (pos == smnt) {
721 		smnt = 0;
722 		sbold = 0;
723 	}
724 	if ((fontlab[pos] = f) == 'S')
725 		smnt = pos;
726 	bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
727 		/* if there is a directory, no place to store its name. */
728 		/* if position isn't zero, no place to store its value. */
729 		/* only time a FONTPOS is pushed back is if it's a */
730 		/* standard font on position 0 (i.e., mounted implicitly. */
731 		/* there's a bug here:  if there are several input lines */
732 		/* that look like .ft XX in short successtion, the output */
733 		/* will all be in the last one because the "x font ..." */
734 		/* comes out too soon.  pushing back FONTPOS doesn't work */
735 		/* with .ft commands because input is flushed after .xx cmds */
736 	ptfpcmd(pos, shortname);
737 	if (pos == 0)
738 		ch = (tchar) FONTPOS | (tchar) f << 16;
739 	return(pos);
740 }
741 
742 
743 int
744 casecs()
745 {
746 	int	i, j;
747 
748 	noscale++;
749 	skip();
750 	if (!(i = getrq()) || (i = findft(i)) < 0)
751 		goto rtn;
752 	skip();
753 	cstab[i] = atoi();
754 	skip();
755 	j = atoi();
756 	if (nonumb)
757 		ccstab[i] = 0;
758 	else
759 		ccstab[i] = findps(j);
760 rtn:
761 	zapwcache(0);
762 	noscale = 0;
763 
764 	return (0);
765 }
766 
767 
768 int
769 casebd()
770 {
771 	int	i, j, k;
772 
773 	zapwcache(0);
774 	k = 0;
775 bd0:
776 	if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
777 		if (k)
778 			goto bd1;
779 		else
780 			return (0);
781 	}
782 	if (j == smnt) {
783 		k = smnt;
784 		goto bd0;
785 	}
786 	if (k) {
787 		sbold = j;
788 		j = k;
789 	}
790 bd1:
791 	skip();
792 	noscale++;
793 	bdtab[j] = atoi();
794 	noscale = 0;
795 
796 	return (0);
797 }
798 
799 
800 int
801 casevs()
802 {
803 	int	i;
804 
805 	skip();
806 	vflag++;
807 	dfact = INCH; /* default scaling is points! */
808 	dfactd = 72;
809 	res = VERT;
810 	i = inumb(&lss);
811 	if (nonumb)
812 		i = lss1;
813 	if (i < VERT)
814 		i = VERT;
815 	lss1 = lss;
816 	lss = i;
817 
818 	return (0);
819 }
820 
821 
822 int
823 casess()
824 {
825 	int	i;
826 
827 	noscale++;
828 	skip();
829 	if (i = atoi()) {
830 		spacesz = i & 0177;
831 		zapwcache(0);
832 		sps = width(' ' | chbits);
833 	}
834 	noscale = 0;
835 
836 	return (0);
837 }
838 
839 
840 tchar xlss()
841 {
842 	/* stores \x'...' into
843 	 * two successive tchars.
844 	 * the first contains HX, the second the value,
845 	 * encoded as a vertical motion.
846 	 * decoding is done in n2.c by pchar().
847 	 */
848 	int	i;
849 
850 	getch();
851 	dfact = lss;
852 	i = quant(atoi(), VERT);
853 	dfact = 1;
854 	getch();
855 	if (i >= 0)
856 		*pbp++ = MOT | VMOT | i;
857 	else
858 		*pbp++ = MOT | VMOT | NMOT | -i;
859 	return(HX);
860 }
861