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