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