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 1989 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 /*	from OpenSolaris "t10.c	1.11	05/06/08 SMI"	*/
32 
33 /*
34  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35  *
36  * Sccsid @(#)t10.c	1.98 (gritter) 8/19/08
37  */
38 
39 /*
40  * Changes Copyright (c) 2014 Carsten Kunze (carsten.kunze at arcor.de)
41  */
42 
43 /*
44  * University Copyright- Copyright (c) 1982, 1986, 1988
45  * The Regents of the University of California
46  * All Rights Reserved
47  *
48  * University Acknowledgment- Portions of this document are derived from
49  * software developed by the University of California, Berkeley, and its
50  * contributors.
51  */
52 
53 #include <stdlib.h>
54 #include "tdef.h"
55 #include <ctype.h>
56 #include <fcntl.h>
57 #include <unistd.h>
58 #include <string.h>
59 #ifdef	EUC
60 #include <locale.h>
61 #endif
62 #include "ext.h"
63 #include "dev.h"
64 #include "afm.h"
65 #include "pt.h"
66 #include "troff.h"
67 #include "unimap.h"
68 #include "fontmap.h"
69 /*
70  * troff10.c
71  *
72  * typesetter interface
73  */
74 
75 int	vpos	 = 0;	/* absolute vertical position on page */
76 int	hpos	 = 0;	/* ditto horizontal */
77 
78 int	initbdtab[NFONT+1];
79 
80 short	*chtab;
81 char	*chname;
82 int	**fontab;
83 char	**kerntab;
84 unsigned short	**fitab;
85 unsigned short	**codetab;
86 
87 int	Inch;
88 int	Hor;
89 int	Vert;
90 int	Unitwidth;
91 int	nfonts;
92 int	nsizes;
93 int	nchtab;
94 int	lettrack;
95 float	horscale;
96 
97 static float	mzoom;
98 static int	mtrack;
99 static float	mhorscale;
100 
101 /* these characters are used as various signals or values
102  * in miscellaneous places.
103  * values are set in specnames in t10.c
104  */
105 
106 int	c_hyphen;
107 int	c_emdash;
108 int	c_endash;
109 int	c_rule;
110 int	c_minus;
111 int	c_fi;
112 int	c_fl;
113 int	c_ff;
114 int	c_ffi;
115 int	c_ffl;
116 int	c_acute;
117 int	c_grave;
118 int	c_under;
119 int	c_rooten;
120 int	c_boxrule;
121 int	c_lefthand;
122 int	c_dagger;
123 
124 struct dev dev;
125 struct Font **fontbase;
126 
127 int Nfont;
128 
129 static int	okern(tchar *, tchar *, int);
130 static void	pthorscale(int);
131 static void	pttrack(int);
132 static void	ptanchor(int);
133 static void	ptlink(int);
134 static void	ptulink(int);
135 static void	ptyon(int);
136 static void	ptchar(int, int);
137 static void	pnc(int, struct afmtab *);
138 
139 void
growfonts(int n)140 growfonts(int n)
141 {
142 	int	i, j;
143 
144 	fontbase = realloc(fontbase, n * sizeof *fontbase);
145 	memset(&fontbase[Nfont], 0, (n - Nfont) * sizeof *fontbase);
146 	fontab = realloc(fontab, n * sizeof *fontab);
147 	memset(&fontab[Nfont], 0, (n - Nfont) * sizeof *fontab);
148 	kerntab = realloc(kerntab, n * sizeof *kerntab);
149 	memset(&kerntab[Nfont], 0, (n - Nfont) * sizeof *kerntab);
150 	codetab = realloc(codetab, n * sizeof *codetab);
151 	memset(&codetab[Nfont], 0, (n - Nfont) * sizeof *codetab);
152 	fitab = realloc(fitab, n * sizeof *fitab);
153 	memset(&fitab[Nfont], 0, (n - Nfont) * sizeof *fitab);
154 	fontlab = realloc(fontlab, n * sizeof *fontlab);
155 	memset(&fontlab[Nfont], 0, (n - Nfont) * sizeof *fontlab);
156 	cstab = realloc(cstab, n * sizeof *cstab);
157 	memset(&cstab[Nfont], 0, (n - Nfont) * sizeof *cstab);
158 	ccstab = realloc(ccstab, n * sizeof *ccstab);
159 	memset(&ccstab[Nfont], 0, (n - Nfont) * sizeof *ccstab);
160 	bdtab = realloc(bdtab, n * sizeof *bdtab);
161 	memset(&bdtab[Nfont], 0, (n - Nfont) * sizeof *bdtab);
162 	tracktab = realloc(tracktab, n * sizeof *tracktab);
163 	memset(&tracktab[Nfont], 0, (n - Nfont) * sizeof *tracktab);
164 	fallbacktab = realloc(fallbacktab, n * sizeof *fallbacktab);
165 	memset(&fallbacktab[Nfont], 0, (n - Nfont) * sizeof *fallbacktab);
166 	zoomtab = realloc(zoomtab, n * sizeof *zoomtab);
167 	memset(&zoomtab[Nfont], 0, (n - Nfont) * sizeof *zoomtab);
168 	lhangtab = realloc(lhangtab, n * sizeof *lhangtab);
169 	memset(&lhangtab[Nfont], 0, (n - Nfont) * sizeof *lhangtab);
170 	rhangtab = realloc(rhangtab, n * sizeof *rhangtab);
171 	memset(&rhangtab[Nfont], 0, (n - Nfont) * sizeof *rhangtab);
172 	kernafter = realloc(kernafter, n * sizeof *kernafter);
173 	memset(&kernafter[Nfont], 0, (n - Nfont) * sizeof *kernafter);
174 	kernbefore = realloc(kernbefore, n * sizeof *kernbefore);
175 	memset(&kernbefore[Nfont], 0, (n - Nfont) * sizeof *kernbefore);
176 	ftrtab = realloc(ftrtab, n * sizeof *ftrtab);
177 	for (i = Nfont; i < n; i++) {
178 		ftrtab[i] = malloc(NCHARS * sizeof **ftrtab);
179 		for (j = 0; j < NCHARS; j++)
180 			ftrtab[i][j] = j;
181 	}
182 	lgtab = realloc(lgtab, n * sizeof *lgtab);
183 	memset(&lgtab[Nfont], 0, (n - Nfont) * sizeof *lgtab);
184 	lgrevtab = realloc(lgrevtab, n * sizeof *lgrevtab);
185 	memset(&lgrevtab[Nfont], 0, (n - Nfont) * sizeof *lgrevtab);
186 	Nfont = n;
187 }
188 
189 void
ptinit(void)190 ptinit(void)
191 {
192 	int	i, nw;
193 	char	*filebase, *p, *ap, *descp;
194 	char	*p2;
195 	size_t	l;
196 	size_t	l2;
197 
198 	if (!strcmp(devname, "html")) html = 1;
199 	growfonts(NFONT+1);
200 	memcpy(bdtab, initbdtab,
201 		max((NFONT+1) * sizeof *bdtab, sizeof initbdtab));
202 	uninit();
203 	/* open table for device,
204 	 * read in resolution, size info, font info, etc.
205 	 * and set params
206 	 */
207 	l = strlen(termtab) + strlen(devname) + 10;
208 	l2 = l + 3;
209 	p = malloc(l);
210 	p2 = malloc(l2);
211 	n_strcpy(p, termtab, l);
212 	termtab = p;
213 	n_strcat(termtab, "/dev", l);
214 	n_strcat(termtab, devname, l);
215 	n_strcpy(p2, termtab, l2);
216 	n_strcat(p2, "/FONTMAP", l2);
217 	rdftmap(p2);
218 	free(p2);
219 	n_strcat(termtab, "/DESC", l);	/* makes "..../devXXX/DESC" */
220 	if ((descp = readdesc(termtab)) == NULL)
221 		done3(1);
222 	memcpy(&dev, descp, sizeof dev);
223 	Inch = dev.res;
224 	Hor = dev.hor;
225 	Vert = dev.vert;
226 	Unitwidth = dev.unitwidth;
227 	nfonts = dev.nfonts;
228 	nsizes = dev.nsizes;
229 	nchtab = dev.nchtab;
230 	if (nchtab >= NCHARS - 128) {
231 		errprint("too many special characters in file %s",
232 			termtab);
233 		done3(1);
234 	}
235 	filebase = malloc(dev.filesize + 3*EXTRAFONT);	/* enough room for whole file */
236 	memcpy(filebase, &descp[sizeof dev], dev.filesize); /* all at once */
237 	free(descp);
238 	pstab = (int *) filebase;
239 	for (i = 0; pstab[i]; i++)
240 		pstab[i] = pts2u(pstab[i]);
241 	chtab = (short *)(pstab + nsizes + 1);
242 	chname = (char *) (chtab + dev.nchtab);
243 	p = chname + dev.lchname;
244 	specnames();	/* install names like "hyphen", etc. */
245 	for (i = 1; i <= nfonts; i++) {
246 		fontbase[i] = (struct Font *) p;
247 		nw = *p & BYTEMASK;	/* 1st thing is width count */
248 		fontlab[i] = PAIR(fontbase[i]->namefont[0], fontbase[i]->namefont[1]);
249 		/* for now, still 2 char names */
250 		if (smnt == 0 && fontbase[i]->specfont == 1)
251 			smnt = i;	/* first special font */
252 		p += sizeof(struct Font);	/* that's what's on the beginning */
253 		if ((ap = strstr(fontbase[i]->namefont, ".afm")) != NULL) {
254 			*ap = 0;
255 			if (ap == &fontbase[i]->namefont[1])
256 				fontlab[i] &= BYTEMASK;
257 			loadafm(i, fontlab[i], fontbase[i]->namefont, NULL,
258 					1, SPEC_NONE);
259 		} else {
260 			makefont(i, p, p + nw, p + 2 * nw, p + 3 * nw, nw);
261 		}
262 		p += 3 * nw + dev.nchtab + 128 - 32;
263 	}
264 	fontbase[0] = (struct Font *) p;	/* the last shall be first */
265 	memset(fontbase[0], 0, sizeof *fontbase[0]);
266 	nw = EXTRAFONT - dev.nchtab - (128-32) - sizeof (struct Font);
267 	fontbase[0]->nwfont = nw;
268 	makefont(0, p, p + nw, p + 2 * nw, p + 3 * nw, nw);
269 	/* there are a lot of things that used to be constant
270 	 * that now require code to be executed.
271 	 */
272 	sps = SPS;
273 	ses = SES;
274 	for (i = 0; i < 16; i++)
275 		tabtab[i] = DTAB * (i + 1);
276 	pl = 11 * INCH;
277 	po = PO;
278 	spacesz = SS;
279 	sesspsz = SSS;
280 	lss = lss1 = VS;
281 	ll = ll1 = lt = lt1 = LL;
282 	apts = pts2u(apts);
283 	apts1 = pts2u(apts1);
284 	pts = pts2u(pts);
285 	pts1 = pts2u(pts1);
286 	ics = ICS;
287 	for (i = 0; i <= nfonts; i++)
288 		setlig(i, fontbase[i]->ligfont);
289 	kern = xflag;
290 	if (ascii)
291 		return;
292 	fdprintf(ptid, "x T %s\n", devname);
293 	fdprintf(ptid, "x res %d %d %d\n", Inch, Hor, Vert);
294 	fdprintf(ptid, "x init\n");	/* do initialization for particular device */
295   /*
296 	for (i = 1; i <= nfonts; i++)
297 		fdprintf(ptid, "x font %d %s\n", i, fontbase[i]->namefont);
298 	fdprintf(ptid, "x xxx fonts=%d sizes=%d unit=%d\n", nfonts, nsizes, Unitwidth);
299 	fdprintf(ptid, "x xxx nchtab=%d lchname=%d nfitab=%d\n",
300 		dev.nchtab, dev.lchname, dev.nchtab+128-32);
301 	fdprintf(ptid, "x xxx sizes:\nx xxx ");
302 	for (i = 0; i < nsizes; i++)
303 		fdprintf(ptid, " %d", pstab[i]);
304 	fdprintf(ptid, "\nx xxx chars:\nx xxx ");
305 	for (i = 0; i < dev.nchtab; i++)
306 		fdprintf(ptid, " %s", &chname[chtab[i]]);
307 	fdprintf(ptid, "\nx xxx\n");
308   */
309 #ifdef	EUC
310 	ptlocale(setlocale(LC_CTYPE, NULL));
311 #endif	/* EUC */
312 	free(termtab);
313 }
314 
315 void
specnames(void)316 specnames(void)
317 {
318 	static struct {
319 		int	*n;
320 		char	*v;
321 	} spnames[] = {
322 		{ &c_hyphen  , "hy" },
323 		{ &c_emdash  , "em" },
324 		{ &c_endash  , "en" },
325 		{ &c_rule    , "ru" },
326 		{ &c_minus   , "\\-"},
327 		{ &c_fi      , "fi" },
328 		{ &c_fl      , "fl" },
329 		{ &c_ff      , "ff" },
330 		{ &c_ffi     , "Fi" },
331 		{ &c_ffl     , "Fl" },
332 		{ &c_acute   , "aa" },
333 		{ &c_grave   , "ga" },
334 		{ &c_under   , "ul" },
335 		{ &c_rooten  , "rn" },
336 		{ &c_boxrule , "br" },
337 		{ &c_lefthand, "lh" },
338 		{ &c_dagger  , "dg" },
339 		{ 0          , 0    }
340 	};
341 	static int	twice;
342 	int	i;
343 
344 	if (twice++)
345 		return;
346 	for (i = 0; spnames[i].n; i++)
347 		*spnames[i].n = findch(spnames[i].v);
348 }
349 
350 int
findch(register char * s)351 findch(register char *s)	/* find char s in chname */
352 {
353 	register int	i;
354 
355 	for (i = 0; i < nchtab; i++)
356 		if (strcmp(s, &chname[chtab[i]]) == 0)
357 			return(i + 128);
358 	return(0);
359 }
360 
361 void
ptout(register tchar i)362 ptout(register tchar i)
363 {
364 	register int dv;
365 	register tchar	*k;
366 	int temp, a, b;
367 
368 	if (isadjspc(i))
369 		return;
370 	if (olinep >= &oline[olinesz]) {
371 		olinesz += 100;
372 		k = realloc(oline, olinesz * sizeof *oline);
373 		olinep = (tchar *)((char *)olinep + ((char *)k-(char *)oline));
374 		oline = k;
375 	}
376 	if (cbits(i) != '\n') {
377 		*olinep++ = i;
378 		return;
379 	}
380 	if (olinep == oline) {
381 		lead += lss;
382 		return;
383 	}
384 
385 	hpos = po;	/* ??? */
386 	esc = 0;	/* ??? */
387 	ptesc();	/* the problem is to get back to the left end of the line */
388 	dv = 0;
389 	for (k = oline; k < olinep; k++) {
390 		if (ismot(*k) && isvmot(*k)) {
391 			temp = absmot(*k);
392 			if (isnmot(*k))
393 				temp = -temp;
394 			dv += temp;
395 		}
396 	}
397 	if (dv) {
398 		vflag++;
399 		*olinep++ = makem(-dv);
400 		vflag = 0;
401 	}
402 
403 	b = dip->blss + lss;
404 	lead += dip->blss + lss;
405 	dip->blss = 0;
406 	if (linkout)
407 		linkhp = hpos;
408 	for (k = oline; k < olinep; )
409 		k = ptout0(k, olinep);	/* now passing a pointer! */
410 	olinep = oline;
411 	lead += dip->alss;
412 	a = dip->alss;
413 	dip->alss = 0;
414 	if (linkout)
415 		ptlink(linkout);
416 	/*
417 	fdprintf(ptid, "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos);
418 */
419 	fdprintf(ptid, "n%d %d\n", b, a);	/* be nice to chuck */
420 }
421 
422 tchar *
ptout0(tchar * pi,tchar * pend)423 ptout0(tchar *pi, tchar *pend)
424 {
425 	struct afmtab	*a;
426 	register int j;
427 	register int k, w = 0;
428 	int	z, dx, dy, dx2, dy2, n, c;
429 	register tchar	i;
430 	int outsize;	/* size of object being printed */
431 	double	f;
432 	int tfont;
433 
434 	outsize = 1;	/* default */
435 	i = *pi;
436 	k = cbits(i);
437 	if (k == FILLER)
438 		return(pi+outsize);
439 	if (ismot(i)) {
440 		j = absmot(i);
441 		if (isnmot(i))
442 			j = -j;
443 		if (isvmot(i))
444 			lead += j;
445 		else
446 			esc += j;
447 		return(pi+outsize);
448 	}
449 	if (k == XON) {
450 		if (xfont != mfont)
451 			ptfont();
452 		if (xpts != mpts || zoomtab[xfont] != mzoom)
453 			ptps();
454 		if (lead)
455 			ptlead();
456 		if (esc)
457 			ptesc();
458 		fdprintf(ptid, "x X ");
459 		/*
460 	     * not guaranteed of finding a XOFF if a word overflow
461 		 * error occured, so also bound this loop by olinep
462 		 */
463 		pi++;
464 		while( cbits(*pi) != XOFF && pi < olinep )
465 			outascii(*pi++);
466 		oput('\n');
467 		if ( cbits(*pi) == XOFF )
468 			pi++;
469 		return pi;
470 	}
471 			;
472 	if (k == CHARHT) {
473 		if (xflag) {
474 			xfont = fbits(i);
475 			if (xfont != mfont)
476 				ptfont();
477 		}
478 		if (xpts != mpts || zoomtab[xfont] != mzoom)
479 			ptps();
480 		j = f = u2pts(sbits(i));
481 		if (j != f && xflag && dev.anysize)
482 			fdprintf(ptid, "x H -23 %g\n", f);
483 		else
484 			fdprintf(ptid, "x H %d\n", j);
485 		return(pi+outsize);
486 	}
487 	if (k == SLANT) {
488 		if (xflag) {
489 			xfont = fbits(i);
490 			if (xfont != mfont)
491 				ptfont();
492 		}
493 		fdprintf(ptid, "x S %d\n", (int)sbits(i)-180);
494 		return(pi+outsize);
495 	}
496 	if (k == WORDSP) {
497 		oput('w');
498 		return(pi+outsize);
499 	}
500 	if (k == FONTPOS) {
501 		n = i >> 22;
502 		ptfpcmd(0, macname(n), NULL, 0);
503 		return(pi+outsize);
504 	}
505 	if (k == XFUNC) {
506 		switch (fbits(i)) {
507 		case ANCHOR:
508 			ptanchor(sbits(i));
509 			return(pi+outsize);
510 		case LINKON:
511 			linkout = sbits(i);
512 			linkhp = hpos + esc;
513 			if (html) ptlink(sbits(i));
514 			return(pi+outsize);
515 		case LINKOFF:
516 			ptlink(html ? 0 : sbits(i));
517 			linkout = 0;
518 			return(pi+outsize);
519 		case ULINKON:
520 			linkout = sbits(i);
521 			linkhp = hpos + esc;
522 			if (html) ptulink(sbits(i));
523 			return(pi+outsize);
524 		case ULINKOFF:
525 			ptulink(html ? 0 : sbits(i));
526 			linkout = 0;
527 			return(pi+outsize);
528 		case INDENT:
529 			if (linkout)
530 				linkhp += sbits(i);
531 			return(pi+outsize);
532 		case LETSP:
533 			lettrack = sbits(i);
534 			return(pi+outsize);
535 		case NLETSP:
536 			lettrack = -sbits(i);
537 			return(pi+outsize);
538 		case LETSH:
539 			horscale = 1 + (double)sbits(i) / LAFACT;
540 			return(pi+outsize);
541 		case NLETSH:
542 			horscale = 1 - (double)sbits(i) / LAFACT;
543 			return(pi+outsize);
544 		case YON:
545 			if (&pi[outsize] >= pend)
546 				return(pi+outsize);
547 			ptyon(fetchrq(&pi[outsize]));
548 			return(pi+outsize+1);
549 		case CHAR:
550 			ptchar(sbits(i), iszbit(i) != 0);
551 			if (!iszbit(i))
552 				esc += okern(pi, pend, outsize);
553 			return(pi+outsize);
554 		default:
555 			return(pi+outsize);
556 		}
557 	}
558 	if (sfbits(i) == oldbits) {
559 		xfont = pfont;
560 		xpts = ppts;
561 	} else
562 		xbits(i, 2);
563 	if (k < 040 && k != DRAWFCN)
564 		return(pi+outsize);
565 	if (k >= 32) {
566 		if (html && k >= NCHARS)
567 			w = getcw(0);
568 		else
569 		if (widcache[k-32].fontpts == xfont + (xpts<<8)  && !setwdf &&
570 				kern == 0 && horscale == 0) {
571 			w = widcache[k-32].width;
572 			lasttrack = widcache[k-32].track;
573 			bd = 0;
574 			cs = 0;
575 		} else {
576 			tfont = xfont;
577 			w = getcw(k-32);
578 			if (tfont != xfont)
579 				k = ftrans(xfont, k);
580 		}
581 	}
582 	if (xfont != mfont)
583 		ptfont();
584 	if (xpts != mpts || zoomtab[xfont] != mzoom)
585 		ptps();
586 	if (lead)
587 		ptlead();
588 	if (lettrack || lasttrack || mtrack)
589 		pttrack(0);
590 	if (horscale || mhorscale)
591 		pthorscale(0);
592 	w += okern(pi, pend, outsize);
593 	if (afmtab && (j = (fontbase[xfont]->afmpos) - 1) >= 0)
594 		a = afmtab[j];
595 	else
596 		a = NULL;
597 	j = z = 0;
598 	if (k != DRAWFCN) {
599 		if (cs && !fmtchar) {
600 			if (bd)
601 				w += (bd - 1) * HOR;
602 			j = (cs - w) / 2;
603 			w = cs - j;
604 			if (bd)
605 				w -= (bd - 1) * HOR;
606 		}
607 		if (iszbit(i)) {
608 			if (cs && !fmtchar)
609 				w = -j;
610 			else
611 				w = 0;
612 			z = 1;
613 		}
614 	}
615 	esc += j;
616 	/* put out the real character here */
617 	if (k == DRAWFCN) {
618 		if (esc)
619 			ptesc();
620 		dx = absmot(pi[3]);
621 		if (isnmot(pi[3]))
622 			dx = -dx;
623 		dy = absmot(pi[4]);
624 		if (isnmot(pi[4]))
625 			dy = -dy;
626 		switch ((c=cbits(pi[1]))) {
627 		case DRAWCIRCLE:	/* circle */
628 		case DRAWCIRCLEFI:
629 			fdprintf(ptid, "D%c %d\n", c, dx);	/* dx is diameter */
630 			w = 0;
631 			hpos += dx;
632 			break;
633 		case DRAWELLIPSE:
634 		case DRAWELLIPSEFI:
635 			fdprintf(ptid, "D%c %d %d\n", c, dx, dy);
636 			w = 0;
637 			hpos += dx;
638 			break;
639 		case DRAWLINE:	/* line */
640 			k = cbits(pi[2]);
641 			fdprintf(ptid, "D%c %d %d ", DRAWLINE, dx, dy);
642 			if (k < 128)
643 				fdprintf(ptid, "%c\n", k);
644 			else
645 				fdprintf(ptid, "%s\n", &chname[chtab[k - 128]]);
646 			w = 0;
647 			hpos += dx;
648 			vpos += dy;
649 			break;
650 		case DRAWARC:	/* arc */
651 			dx2 = absmot(pi[5]);
652 			if (isnmot(pi[5]))
653 				dx2 = -dx2;
654 			dy2 = absmot(pi[6]);
655 			if (isnmot(pi[6]))
656 				dy2 = -dy2;
657 			fdprintf(ptid, "D%c %d %d %d %d\n", DRAWARC,
658 				dx, dy, dx2, dy2);
659 			w = 0;
660 			hpos += dx + dx2;
661 			vpos += dy + dy2;
662 			break;
663 		case DRAWSPLINE:	/* spline */
664 		default:	/* something else; copy it like spline */
665 			fdprintf(ptid, "D%c %d %d", (int)cbits(pi[1]), dx, dy);
666 			w = 0;
667 			hpos += dx;
668 			vpos += dy;
669 			if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) {
670 				/* it was somehow defective */
671 				fdprintf(ptid, "\n");
672 				break;
673 			}
674 			for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) {
675 				dx = absmot(pi[n]);
676 				if (isnmot(pi[n]))
677 					dx = -dx;
678 				dy = absmot(pi[n+1]);
679 				if (isnmot(pi[n+1]))
680 					dy = -dy;
681 				fdprintf(ptid, " %d %d", dx, dy);
682 				hpos += dx;
683 				vpos += dy;
684 			}
685 			fdprintf(ptid, "\n");
686 			break;
687 		}
688 		for (n = 3; cbits(pi[n]) != DRAWFCN; n++)
689 			;
690 		outsize = n + 1;
691 	} else if (k < 128) {
692 		/* try to go faster and compress output */
693 		/* by printing nnc for small positive motion followed by c */
694 		/* kludgery; have to make sure set all the vars too */
695 		if (esc > 0 && esc < 100) {
696 			oput(esc / 10 + '0');
697 			oput(esc % 10 + '0');
698 			oput(k);
699 			hpos += esc;
700 			esc = 0;
701 		} else {
702 			if (esc)
703 				ptesc();
704 			oput('c');
705 			oput(k);
706 			oput('\n');
707 		}
708 	} else {
709 		if (esc)
710 			ptesc();
711 		pnc(k, a);
712 	}
713 	if (bd && !fmtchar) {
714 		bd -= HOR;
715 		if (esc += bd)
716 			ptesc();
717 		if (k < 128) {
718 			fdprintf(ptid, "c%c\n", k);
719 		} else
720 			pnc(k, a);
721 		if (z)
722 			esc -= bd;
723 	}
724 	esc += w;
725 	lettrack = 0;
726 	horscale = 0;
727 	return(pi+outsize);
728 }
729 
730 static void
pnc(int k,struct afmtab * a)731 pnc(int k, struct afmtab *a) {
732 	int j;
733 
734 	if (k >= nchtab + 128) {
735 		if (a && (j = a->fitab[k-nchtab-128-32]) < a->nchars &&
736 		    a->nametab[j] != NULL) {
737 			fdprintf(ptid, "CPS%s\n", a->nametab[j]);
738 		} else {
739 			fdprintf(ptid, "N%d\n",
740 			    k - (html ? 0 : (nchtab + 128)) );
741 		}
742 	} else {
743 		fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
744 	}
745 }
746 
747 static int
okern(tchar * pi,tchar * pend,int outsize)748 okern(tchar *pi, tchar *pend, int outsize)
749 {
750 	int	j;
751 
752 	for (j = outsize; &pi[j] < pend; j++)
753 		if (cbits(pi[j]) != XFUNC || (fbits(pi[j]) != LETSP &&
754 				fbits(pi[j]) != NLETSP &&
755 				fbits(pi[j]) != LETSH &&
756 				fbits(pi[j]) != NLETSH))
757 			break;
758 	if (&pi[j] < pend)
759 		return getkw(pi[0], pi[j]);
760 	else
761 		return 0;
762 }
763 
764 static void
pthorscale(int always)765 pthorscale(int always)
766 {
767 	if (horscale || mhorscale) {
768 		if (always || mhorscale != horscale)
769 			fdprintf(ptid, "x X HorScale %g\n",
770 				horscale ? horscale : 1.0);
771 		mhorscale = horscale;
772 	} else
773 		mhorscale = 0;
774 }
775 
776 static void
pttrack(int always)777 pttrack(int always)
778 {
779 	if (xflag && (lasttrack || lettrack || mtrack)) {
780 		if (always || mtrack != (lasttrack + lettrack))
781 			fdprintf(ptid, "x X Track %d\n", lasttrack + lettrack);
782 		mtrack = lasttrack + lettrack;
783 	} else
784 		mtrack = 0;
785 }
786 
787 void
ptps(void)788 ptps(void)
789 {
790 	register int i, j, k;
791 	double	s, z;
792 	int	found;
793 
794 	i = xpts;
795 	for (j = 0; i > (k = pstab[j]); j++)
796 		if (!k) {
797 			k = pstab[--j];
798 			break;
799 		}
800 	found = k == i;
801 	if (dev.anysize && xflag)
802 		k = i;
803 	s = u2pts(k);
804 	if ((z = zoomtab[xfont]) != 0 && dev.anysize && xflag)
805 		s *= z;
806 	if (dev.anysize && xflag && (!found || (z != 0 && z != 1)))
807 		fdprintf(ptid, "s-23 %g\n", s);
808 	else
809 		fdprintf(ptid, "s%d\n", (int)s);	/* really should put out string rep of size */
810 	mpts = i;
811 	mzoom = z;
812 	pttrack(0);
813 	pthorscale(0);
814 }
815 
816 void
ptfont(void)817 ptfont(void)
818 {
819 	mfont = xfont;
820 	fdprintf(ptid, "f%d\n", xfont);
821 	mtrack = 0;
822 	pttrack(1);
823 	pthorscale(1);
824 }
825 
826 void
ptfpcmd(int f,char * s,char * path,int flags)827 ptfpcmd(int f, char *s, char *path, int flags)
828 {
829 	if (ascii)
830 		return;
831 	fdprintf(ptid, "x font %d %s", f, s);
832 	if (path) {
833 		fdprintf(ptid, " %s", path);
834 		if (flags)
835 			fdprintf(ptid, " %d", flags);
836 	}
837 	fdprintf(ptid, "\n");
838 	ptfont();	/* make sure that it gets noticed */
839 }
840 
841 void
ptlead(void)842 ptlead(void)
843 {
844 	vpos += lead;
845 	if (!ascii)
846 		fdprintf(ptid, "V%d\n", vpos);
847 	lead = 0;
848 }
849 
850 void
ptesc(void)851 ptesc(void)
852 {
853 	hpos += esc;
854 	if (esc > 0) {
855 		oput('h');
856 		if (esc>=10 && esc<100) {
857 			oput(esc/10 + '0');
858 			oput(esc%10 + '0');
859 		} else
860 			fdprintf(ptid, "%d", esc);
861 	} else
862 		fdprintf(ptid, "H%d\n", hpos);
863 	esc = 0;
864 }
865 
866 void
ptsupplyfont(char * fontname,char * file)867 ptsupplyfont(char *fontname, char *file)
868 {
869 	if (ascii)
870 		return;
871 	fdprintf(ptid, "x X SupplyFont %s %s\n", fontname, file);
872 }
873 
874 void
ptpapersize(void)875 ptpapersize(void)
876 {
877 	if (ascii || mediasize.flag == 0)
878 		return;
879 	fdprintf(ptid, "x X PaperSize %d %d %d\n",
880 			mediasize.val[2], mediasize.val[3],
881 			mediasize.flag&2?1:0);
882 }
883 
884 static void
cut1(const char * name,struct box * bp)885 cut1(const char *name, struct box *bp)
886 {
887 	if (bp->flag)
888 		fdprintf(ptid, "x X %s %d %d %d %d\n", name,
889 			bp->val[0], bp->val[1], bp->val[2], bp->val[3]);
890 }
891 
892 void
ptcut(void)893 ptcut(void)
894 {
895 	if (ascii)
896 		return;
897 	cut1("TrimAt", &trimat);
898 	cut1("BleedAt", &bleedat);
899 	cut1("CropAt", &cropat);
900 }
901 
902 void
ptlocale(const char * cp)903 ptlocale(const char *cp)
904 {
905 	static char	*lp;
906 
907 	if (cp != NULL) {
908 		size_t l;
909 		free(lp);
910 		l = strlen(cp) + 1;
911 		lp = malloc(l);
912 		n_strcpy(lp, cp, l);
913 	}
914 	if (ascii || realpage == 0 || lp == NULL || dev.lc_ctype == 0)
915 		return;
916 	fdprintf(ptid, "x X LC_CTYPE %s\n", lp);
917 }
918 
919 static void
ptanchor(int n)920 ptanchor(int n)
921 {
922 	struct ref	*rp;
923 
924 	if (ascii)
925 		return;
926 	for (rp = anchors; rp; rp = rp->next)
927 		if (rp->cnt == n) {
928 			if (html) {
929 				fdprintf(ptid, "x X Anchor %s\n", rp->name);
930 			} else {
931 				fdprintf(ptid, "x X Anchor %d,%d %s\n",
932 				    vpos + lead - lss, hpos + esc, rp->name);
933 			}
934 			break;
935 		}
936 }
937 
938 static void
_ptlink(int n,struct ref * rstart,const char * type)939 _ptlink(int n, struct ref *rstart, const char *type)
940 {
941 	struct ref	*rp;
942 
943 	if (ascii)
944 		return;
945 	if (html && !n) {
946 		fdprintf(ptid, "x X %s\n", type);
947 		return;
948 	}
949 	for (rp = rstart; rp; rp = rp->next)
950 		if (rp->cnt == n) {
951 			if (html)
952 				fdprintf(ptid, "x X %s %s\n", type, rp->name);
953 			else
954 				fdprintf(ptid, "x X %s %d,%d,%d,%d %s\n",
955 				    type,
956 				    linkhp, vpos + pts2u(1),
957 				    hpos + esc, vpos - pts * 8 / 10,
958 				    rp->name);
959 			break;
960 		}
961 }
962 
963 static void
ptlink(int n)964 ptlink(int n)
965 {
966 	_ptlink(n, links, "Link");
967 }
968 
969 static void
ptulink(int n)970 ptulink(int n)
971 {
972 	_ptlink(n, ulinks, "ULink");
973 }
974 
975 static void
ptyon(int i)976 ptyon(int i)
977 {
978 	struct contab	*cp;
979 	tchar	c;
980 	int	k, nl;
981 	filep	savip;
982 
983 	if ((cp = findmx(i)) == NULL || !cp->mx) {
984 		nosuch(i);
985 		return;
986 	}
987 	if (xfont != mfont)
988 		ptfont();
989 	if (xpts != mpts || zoomtab[xfont] != mzoom)
990 		ptps();
991 	if (lead)
992 		ptlead();
993 	if (esc)
994 		ptesc();
995 	fdprintf(ptid, "x X ");
996 	savip = ip;
997 	ip = (filep)cp->mx;
998 	app = 1;
999 	k = -1;
1000 	nl = 0;
1001 	while ((c = rbf()) != 0) {
1002 		if ((k = cbits(c)) != '\n') {
1003 			while (nl--)
1004 				oputs("\n+");
1005 			nl = 0;
1006 			outascii(c);
1007 		} else
1008 			nl++;
1009 	}
1010 	while (nl-- > 1)
1011 		oputs("\n+");
1012 	oput('\n');
1013 	app = 0;
1014 	ip = savip;
1015 }
1016 
1017 static void
ptchar1(struct charout * cp,int z)1018 ptchar1(struct charout *cp, int z)
1019 {
1020 	filep	savip;
1021 	tchar	i, *k, *savoline, *savolinep;
1022 	size_t	savolinesz;
1023 	int	savhpos, savvpos, savlettrack;
1024 
1025 	savoline = oline;
1026 	savolinep = olinep;
1027 	savolinesz = olinesz;
1028 	olinep = oline = NULL;
1029 	olinesz = 0;
1030 	savlettrack = lettrack;
1031 	lettrack = 0;
1032 	savhpos = hpos + esc;
1033 	savvpos = vpos + lead;
1034 	savip = ip;
1035 	ip = cp->op;
1036 	app++;
1037 	fmtchar++;
1038 	while ((i = rbf()) != 0 && cbits(i) != '\n' && cbits(i) != FLSS)
1039 		pchar(i);
1040 	for (k = oline; k < olinep; )
1041 		k = ptout0(k, olinep);
1042 	fmtchar--;
1043 	app--;
1044 	ip = savip;
1045 	free(oline);
1046 	oline = savoline;
1047 	olinep = savolinep;
1048 	olinesz = savolinesz;
1049 	lettrack = savlettrack;
1050 	esc = savhpos - hpos;
1051 	if (!z)
1052 		esc += cs ? cs : cp->width + lettrack;
1053 	lead = savvpos - vpos;
1054 }
1055 
1056 static void
ptchar(int n,int z)1057 ptchar(int n, int z)
1058 {
1059 	struct charout	*cp = &charout[n];
1060 	int	savbd;
1061 
1062 	ptchar1(cp, z);
1063 	if (bd) {
1064 		bd -= HOR;
1065 		if (esc += bd)
1066 			ptesc();
1067 		savbd = bd;
1068 		bd = 0;
1069 		ptchar1(cp, z);
1070 		bd = savbd;
1071 		if (iszbit(cp->ch))
1072 			esc -= bd;
1073 	}
1074 	lettrack = 0;
1075 }
1076 
1077 void
newpage(int n)1078 newpage(int n)	/* called at end of each output page (we hope) */
1079 {
1080 	int i;
1081 
1082 	realpage++;
1083 	ptlead();
1084 	vpos = 0;
1085 	if (ascii)
1086 		return;
1087 	fdprintf(ptid, "p%d\n", n);	/* new page */
1088 	for (i = 0; i <= nfonts; i++) {
1089 		if (fontbase[i] == NULL)
1090 			continue;
1091 		if (afmtab && fontbase[i]->afmpos) {
1092 			struct afmtab	*a = afmtab[(fontbase[i]->afmpos)-1];
1093 			if (a->encpath == NULL)
1094 				a->encpath = afmencodepath(a->path);
1095 			fdprintf(ptid, "x font %d %s %s %d\n", i,
1096 				macname(fontlab[i]),
1097 				a->encpath, (int)a->spec);
1098 			if (a->supply)
1099 				ptsupplyfont(a->fontname, a->supply);
1100 		} else if (fontbase[i]->namefont[0])
1101 			fdprintf(ptid, "x font %d %s\n", i, macname(fontlab[i]));
1102 	}
1103 	ptps();
1104 	ptfont();
1105 	ptpapersize();
1106 	ptcut();
1107 	ptlocale(NULL);
1108 }
1109 
1110 void
pttrailer(void)1111 pttrailer(void)
1112 {
1113 	fdprintf(ptid, "x trailer\n");
1114 }
1115 
1116 void
ptstop(void)1117 ptstop(void)
1118 {
1119 	fdprintf(ptid, "x stop\n");
1120 }
1121 
1122 void
dostop(void)1123 dostop(void)
1124 {
1125 	if (ascii)
1126 		return;
1127 	ptlead();
1128 	vpos = 0;
1129 	/* fdprintf(ptid, "x xxx end of page\n");*/
1130 	if (!nofeed)
1131 		pttrailer();
1132 	ptlead();
1133 	fdprintf(ptid, "x pause\n");
1134 	flusho();
1135 	mpts = mfont = 0;
1136 	ptesc();
1137 	esc = po;
1138 	hpos = vpos = 0;	/* probably in wrong place */
1139 }
1140