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 * 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#include "tdef.h"
43#include <ctype.h>
44#include "ext.h"
45/*
46 * troff10.c
47 *
48 * typesetter interface
49 */
50
51int	vpos	 = 0;	/* absolute vertical position on page */
52int	hpos	 = 0;	/* ditto horizontal */
53
54short	*chtab;
55char	*chname;
56char	*fontab[NFONT+1];
57char	*kerntab[NFONT+1];
58char	*fitab[NFONT+1];
59char	*codetab[NFONT+1];
60
61int	Inch;
62int	Hor;
63int	Vert;
64int	Unitwidth;
65int	nfonts;
66int	nsizes;
67int	nchtab;
68
69/* these characters are used as various signals or values
70 * in miscellaneous places.
71 * values are set in specnames in t10.c
72 */
73
74int	c_hyphen;
75int	c_emdash;
76int	c_rule;
77int	c_minus;
78int	c_fi;
79int	c_fl;
80int	c_ff;
81int	c_ffi;
82int	c_ffl;
83int	c_acute;
84int	c_grave;
85int	c_under;
86int	c_rooten;
87int	c_boxrule;
88int	c_lefthand;
89int	c_dagger;
90
91#include "dev.h"
92struct dev dev;
93struct Font *fontbase[NFONT+1];
94
95tchar *ptout0();
96
97
98int
99ptinit()
100{
101	int	i, fin, nw;
102	char	*setbrk(), *filebase, *p;
103
104	/* open table for device,
105	 * read in resolution, size info, font info, etc.
106	 * and set params
107	 */
108	strcat(termtab, "/dev");
109	strcat(termtab, devname);
110	strcat(termtab, "/DESC.out");	/* makes "..../devXXX/DESC.out" */
111	if ((fin = open(termtab, 0)) < 0) {
112		errprint(gettext("can't open tables for %s"), termtab);
113		done3(1);
114	}
115	read(fin, (char *) &dev, sizeof(struct dev ));
116	Inch = dev.res;
117	Hor = dev.hor;
118	Vert = dev.vert;
119	Unitwidth = dev.unitwidth;
120	nfonts = dev.nfonts;
121	nsizes = dev.nsizes;
122	nchtab = dev.nchtab;
123	if (nchtab >= NCHARS - 128) {
124		errprint(gettext("too many special characters in file %s"),
125			termtab);
126		done3(1);
127	}
128	filebase = setbrk(dev.filesize + 2*EXTRAFONT);	/* enough room for whole file */
129	read(fin, filebase, dev.filesize);	/* all at once */
130	pstab = (short *) filebase;
131	chtab = pstab + nsizes + 1;
132	chname = (char *) (chtab + dev.nchtab);
133	p = chname + dev.lchname;
134	for (i = 1; i <= nfonts; i++) {
135		fontbase[i] = (struct Font *) p;
136		nw = *p & BYTEMASK;	/* 1st thing is width count */
137		fontlab[i] = PAIR(fontbase[i]->namefont[0], fontbase[i]->namefont[1]);
138		/* for now, still 2 char names */
139		if (smnt == 0 && fontbase[i]->specfont == 1)
140			smnt = i;	/* first special font */
141		p += sizeof(struct Font);	/* that's what's on the beginning */
142		fontab[i] = p;
143		kerntab[i] = p + nw;
144		codetab[i] = p + 2 * nw;
145		fitab[i] = p + 3 * nw;	/* skip width, kern, code */
146		p += 3 * nw + dev.nchtab + 128 - 32;
147	}
148	fontbase[0] = (struct Font *) p;	/* the last shall be first */
149	fontbase[0]->nwfont = EXTRAFONT - dev.nchtab - (128-32) - sizeof (struct Font);
150	fontab[0] = p + sizeof (struct Font);
151	close(fin);
152	/* there are a lot of things that used to be constant
153	 * that now require code to be executed.
154	 */
155	sps = SPS;
156	ics = ICS;
157	for (i = 0; i < 16; i++)
158		tabtab[i] = DTAB * (i + 1);
159	pl = 11 * INCH;
160	po = PO;
161	spacesz = SS;
162	lss = lss1 = VS;
163	ll = ll1 = lt = lt1 = LL;
164	specnames();	/* install names like "hyphen", etc. */
165	if (ascii)
166		return (0);
167	fdprintf(ptid, "x T %s\n", devname);
168	fdprintf(ptid, "x res %d %d %d\n", Inch, Hor, Vert);
169	fdprintf(ptid, "x init\n");	/* do initialization for particular device */
170  /*
171	for (i = 1; i <= nfonts; i++)
172		fdprintf(ptid, "x font %d %s\n", i, fontbase[i]->namefont);
173	fdprintf(ptid, "x xxx fonts=%d sizes=%d unit=%d\n", nfonts, nsizes, Unitwidth);
174	fdprintf(ptid, "x xxx nchtab=%d lchname=%d nfitab=%d\n",
175		dev.nchtab, dev.lchname, dev.nchtab+128-32);
176	fdprintf(ptid, "x xxx sizes:\nx xxx ");
177	for (i = 0; i < nsizes; i++)
178		fdprintf(ptid, " %d", pstab[i]);
179	fdprintf(ptid, "\nx xxx chars:\nx xxx ");
180	for (i = 0; i < dev.nchtab; i++)
181		fdprintf(ptid, " %s", &chname[chtab[i]]);
182	fdprintf(ptid, "\nx xxx\n");
183  */
184
185	return (0);
186}
187
188int
189specnames()
190{
191	static struct {
192		int	*n;
193		char	*v;
194	} spnames[] = {
195		&c_hyphen, "hy",
196		&c_emdash, "em",
197		&c_rule, "ru",
198		&c_minus, "\\-",
199		&c_fi, "fi",
200		&c_fl, "fl",
201		&c_ff, "ff",
202		&c_ffi, "Fi",
203		&c_ffl, "Fl",
204		&c_acute, "aa",
205		&c_grave, "ga",
206		&c_under, "ul",
207		&c_rooten, "rn",
208		&c_boxrule, "br",
209		&c_lefthand, "lh",
210		&c_dagger, "dg",
211		0, 0
212	};
213	int	i;
214
215	for (i = 0; spnames[i].n; i++)
216		*spnames[i].n = findch(spnames[i].v);
217
218	return (0);
219}
220
221int
222findch(s)	/* find char s in chname */
223char	*s;
224{
225	int	i;
226
227	for (i = 0; i < nchtab; i++)
228		if (strcmp(s, &chname[chtab[i]]) == 0)
229			return(i + 128);
230	return(0);
231}
232
233int
234ptout(i)
235tchar	i;
236{
237	int	dv;
238	tchar	*k;
239	int temp, a, b;
240
241	if (cbits(i) != '\n') {
242		*olinep++ = i;
243		return (0);
244	}
245	if (olinep == oline) {
246		lead += lss;
247		return (0);
248	}
249
250	hpos = po;	/* ??? */
251	esc = 0;	/* ??? */
252	ptesc();	/* the problem is to get back to the left end of the line */
253	dv = 0;
254	for (k = oline; k < olinep; k++) {
255		if (ismot(*k) && isvmot(*k)) {
256			temp = absmot(*k);
257			if (isnmot(*k))
258				temp = -temp;
259			dv += temp;
260		}
261	}
262	if (dv) {
263		vflag++;
264		*olinep++ = makem(-dv);
265		vflag = 0;
266	}
267
268	b = dip->blss + lss;
269	lead += dip->blss + lss;
270	dip->blss = 0;
271	for (k = oline; k < olinep; )
272		k = ptout0(k);	/* now passing a pointer! */
273	olinep = oline;
274	lead += dip->alss;
275	a = dip->alss;
276	dip->alss = 0;
277	/*
278	fdprintf(ptid, "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos);
279*/
280	fdprintf(ptid, "n%d %d\n", b, a);	/* be nice to chuck */
281
282	return (0);
283}
284
285tchar *
286ptout0(pi)
287tchar	*pi;
288{
289	short j, k, w;
290	short	z, dx, dy, dx2, dy2, n;
291	tchar	i;
292	int outsize;	/* size of object being printed */
293
294	outsize = 1;	/* default */
295	i = *pi;
296	k = cbits(i);
297	if (ismot(i)) {
298		j = absmot(i);
299		if (isnmot(i))
300			j = -j;
301		if (isvmot(i))
302			lead += j;
303		else
304			esc += j;
305		return(pi+outsize);
306	}
307	if (k == XON) {
308		if (xfont != mfont)
309			ptfont();
310		if (xpts != mpts)
311			ptps();
312		if (lead)
313			ptlead();
314		fdprintf(ptid, "x X ");
315		/*
316	     * not guaranteed of finding a XOFF if a word overflow
317		 * error occured, so also bound this loop by olinep
318		 */
319		pi++;
320		while( cbits(*pi) != XOFF && pi < olinep )
321			outascii(*pi++);
322		oput('\n');
323		if ( cbits(*pi) == XOFF )
324			pi++;
325		return pi;
326	}
327			;
328	if (k == CHARHT) {
329		if (xpts != mpts)
330			ptps();
331		fdprintf(ptid, "x H %d\n", sbits(i));
332		return(pi+outsize);
333	}
334	if (k == SLANT) {
335		fdprintf(ptid, "x S %d\n", sfbits(i)-180);
336		return(pi+outsize);
337	}
338	if (k == WORDSP) {
339		oput('w');
340		return(pi+outsize);
341	}
342	if (k == FONTPOS) {
343		char temp[3];
344		n = i >> 16;
345		temp[0] = n & BYTEMASK;
346		temp[1] = n >> BYTE;
347		temp[2] = 0;
348		ptfpcmd(0, temp);
349		return(pi+outsize);
350	}
351	if (sfbits(i) == oldbits) {
352		xfont = pfont;
353		xpts = ppts;
354	} else
355		xbits(i, 2);
356	if (k < 040 && k != DRAWFCN)
357		return(pi+outsize);
358	if (k >= 32) {
359		if (widcache[k-32].fontpts == (xfont<<8) + xpts  && !setwdf) {
360			w = widcache[k-32].width;
361			bd = 0;
362			cs = 0;
363		} else
364			w = getcw(k-32);
365	}
366	j = z = 0;
367	if (k != DRAWFCN) {
368		if (cs) {
369			if (bd)
370				w += (bd - 1) * HOR;
371			j = (cs - w) / 2;
372			w = cs - j;
373			if (bd)
374				w -= (bd - 1) * HOR;
375		}
376		if (iszbit(i)) {
377			if (cs)
378				w = -j;
379			else
380				w = 0;
381			z = 1;
382		}
383	}
384	esc += j;
385	if (xfont != mfont)
386		ptfont();
387	if (xpts != mpts)
388		ptps();
389	if (lead)
390		ptlead();
391	/* put out the real character here */
392	if (k == DRAWFCN) {
393		if (esc)
394			ptesc();
395		dx = absmot(pi[3]);
396		if (isnmot(pi[3]))
397			dx = -dx;
398		dy = absmot(pi[4]);
399		if (isnmot(pi[4]))
400			dy = -dy;
401		switch (cbits(pi[1])) {
402		case DRAWCIRCLE:	/* circle */
403			fdprintf(ptid, "D%c %d\n", DRAWCIRCLE, dx);	/* dx is diameter */
404			w = 0;
405			hpos += dx;
406			break;
407		case DRAWELLIPSE:
408			fdprintf(ptid, "D%c %d %d\n", DRAWELLIPSE, dx, dy);
409			w = 0;
410			hpos += dx;
411			break;
412		case DRAWLINE:	/* line */
413			k = cbits(pi[2]);
414			fdprintf(ptid, "D%c %d %d ", DRAWLINE, dx, dy);
415			if (k < 128)
416				fdprintf(ptid, "%c\n", k);
417			else
418				fdprintf(ptid, "%s\n", &chname[chtab[k - 128]]);
419			w = 0;
420			hpos += dx;
421			vpos += dy;
422			break;
423		case DRAWARC:	/* arc */
424			dx2 = absmot(pi[5]);
425			if (isnmot(pi[5]))
426				dx2 = -dx2;
427			dy2 = absmot(pi[6]);
428			if (isnmot(pi[6]))
429				dy2 = -dy2;
430			fdprintf(ptid, "D%c %d %d %d %d\n", DRAWARC,
431				dx, dy, dx2, dy2);
432			w = 0;
433			hpos += dx + dx2;
434			vpos += dy + dy2;
435			break;
436		case DRAWSPLINE:	/* spline */
437		default:	/* something else; copy it like spline */
438			fdprintf(ptid, "D%c %d %d", cbits(pi[1]), dx, dy);
439			w = 0;
440			hpos += dx;
441			vpos += dy;
442			if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) {
443				/* it was somehow defective */
444				fdprintf(ptid, "\n");
445				break;
446			}
447			for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) {
448				dx = absmot(pi[n]);
449				if (isnmot(pi[n]))
450					dx = -dx;
451				dy = absmot(pi[n+1]);
452				if (isnmot(pi[n+1]))
453					dy = -dy;
454				fdprintf(ptid, " %d %d", dx, dy);
455				hpos += dx;
456				vpos += dy;
457			}
458			fdprintf(ptid, "\n");
459			break;
460		}
461		for (n = 3; cbits(pi[n]) != DRAWFCN; n++)
462			;
463		outsize = n + 1;
464	} else if (k < 128) {
465		/* try to go faster and compress output */
466		/* by printing nnc for small positive motion followed by c */
467		/* kludgery; have to make sure set all the vars too */
468		if (esc > 0 && esc < 100) {
469			oput(esc / 10 + '0');
470			oput(esc % 10 + '0');
471			oput(k);
472			hpos += esc;
473			esc = 0;
474		} else {
475			if (esc)
476				ptesc();
477			oput('c');
478			oput(k);
479			oput('\n');
480		}
481	} else {
482		if (esc)
483			ptesc();
484		if (k >= nchtab + 128)
485			fdprintf(ptid, "N%d\n", k - (nchtab+128));
486		else
487			fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
488	}
489	if (bd) {
490		bd -= HOR;
491		if (esc += bd)
492			ptesc();
493		if (k < 128) {
494			fdprintf(ptid, "c%c\n", k);
495		} else if (k >= nchtab + 128) {
496			fdprintf(ptid, "N%d\n", k - (nchtab+128));
497		} else
498			fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
499		if (z)
500			esc -= bd;
501	}
502	esc += w;
503	return(pi+outsize);
504}
505
506int
507ptps()
508{
509	int	i, j, k;
510
511	i = xpts;
512	for (j = 0; i > (k = pstab[j]); j++)
513		if (!k) {
514			k = pstab[--j];
515			break;
516		}
517	fdprintf(ptid, "s%d\n", k);	/* really should put out string rep of size */
518	mpts = i;
519
520	return (0);
521}
522
523int
524ptfont()
525{
526	mfont = xfont;
527	fdprintf(ptid, "f%d\n", xfont);
528
529	return (0);
530}
531
532int
533ptfpcmd(f, s)
534int	f;
535char	*s;
536{
537	if (ascii)
538		return (0);
539	fdprintf(ptid, "x font %d %s\n", f, s);
540	ptfont();	/* make sure that it gets noticed */
541
542	return (0);
543}
544
545int
546ptlead()
547{
548	vpos += lead;
549	if (!ascii)
550		fdprintf(ptid, "V%d\n", vpos);
551	lead = 0;
552
553	return (0);
554}
555
556
557int
558ptesc()
559{
560	hpos += esc;
561	if (esc > 0) {
562		oput('h');
563		if (esc>=10 && esc<100) {
564			oput(esc/10 + '0');
565			oput(esc%10 + '0');
566		} else
567			fdprintf(ptid, "%d", esc);
568	} else
569		fdprintf(ptid, "H%d\n", hpos);
570	esc = 0;
571
572	return (0);
573}
574
575
576int
577newpage(n)	/* called at end of each output page (we hope) */
578{
579	int i;
580
581	ptlead();
582	vpos = 0;
583	if (ascii)
584		return (0);
585	fdprintf(ptid, "p%d\n", n);	/* new page */
586	for (i = 0; i <= nfonts; i++)
587		if (fontbase[i]->namefont && fontbase[i]->namefont[0])
588			fdprintf(ptid, "x font %d %s\n", i, fontbase[i]->namefont);
589	ptps();
590	ptfont();
591
592	return (0);
593}
594
595int
596pttrailer()
597{
598	fdprintf(ptid, "x trailer\n");
599
600	return (0);
601}
602
603int
604ptstop()
605{
606	fdprintf(ptid, "x stop\n");
607
608	return (0);
609}
610
611int
612dostop()
613{
614	if (ascii)
615		return (0);
616	ptlead();
617	vpos = 0;
618	/* fdprintf(ptid, "x xxx end of page\n");*/
619	if (!nofeed)
620		pttrailer();
621	ptlead();
622	fdprintf(ptid, "x pause\n");
623	flusho();
624	mpts = mfont = 0;
625	ptesc();
626	esc = po;
627	hpos = vpos = 0;	/* probably in wrong place */
628
629	return (0);
630}
631