xref: /csrg-svn/local/transcript/src/psdit.c (revision 30594)
1*30594Ssam /*	psdit.c	1.1	87/03/08	*/
2*30594Ssam #ifndef lint
3*30594Ssam static char Notice[] = "Copyright (c) 1984, 1985 Adobe Systems Incorporated";
4*30594Ssam static char *RCSID="$Header: psdit.c,v 2.1 85/11/24 11:50:41 shore Rel $";
5*30594Ssam #endif
6*30594Ssam /* psdit.c
7*30594Ssam  *
8*30594Ssam  * Copyright (c) 1984, 1985 Adobe Systems Incorporated
9*30594Ssam  *
10*30594Ssam  * ditroff intermediate file to PostScript translator
11*30594Ssam  *
12*30594Ssam  * Original Version: Barry Hayes spring/summer 1984
13*30594Ssam  * Edit History:
14*30594Ssam  * Andrew Shore: Sat Nov 23 20:05:26 1985
15*30594Ssam  * End Edit History.
16*30594Ssam  *
17*30594Ssam  * RCSLOG:
18*30594Ssam  * $Log:	psdit.c,v $
19*30594Ssam  * Revision 2.1  85/11/24  11:50:41  shore
20*30594Ssam  * Product Release 2.0
21*30594Ssam  *
22*30594Ssam  * Revision 1.8  85/11/23  20:09:44  shore
23*30594Ssam  * test for termination of included PostScript was bad
24*30594Ssam  *
25*30594Ssam  * Revision 1.7  85/11/21  14:23:56  shore
26*30594Ssam  * added envget check for PSLIBDIR
27*30594Ssam  *
28*30594Ssam  * Revision 1.6  85/11/20  00:43:43  shore
29*30594Ssam  * support for included PostScript
30*30594Ssam  * big rework on FlushShow, word "breaks"
31*30594Ssam  * removed FlushFont and made them instant
32*30594Ssam  * Still no Gremlin support yet
33*30594Ssam  *
34*30594Ssam  * Revision 1.5  85/10/03  10:48:09  shore
35*30594Ssam  * added FlushShow to xf fix !
36*30594Ssam  *
37*30594Ssam  * Revision 1.4  85/10/02  16:20:32  shore
38*30594Ssam  * fixed xf bug
39*30594Ssam  * mounting a font causes a font switch!
40*30594Ssam  *
41*30594Ssam  * Revision 1.3  85/07/09  13:10:20  shore
42*30594Ssam  * added fclose on map file
43*30594Ssam  *
44*30594Ssam  * Revision 1.2  85/05/14  11:24:23  shore
45*30594Ssam  * added flush to trailer
46*30594Ssam  * fixed read bug when mounting fonts
47*30594Ssam  *
48*30594Ssam  *
49*30594Ssam  */
50*30594Ssam 
51*30594Ssam /*
52*30594Ssam output language from troff:
53*30594Ssam all numbers are character strings
54*30594Ssam 
55*30594Ssam sn	size in points
56*30594Ssam fn	font as number from 1-n
57*30594Ssam cx	ascii character x
58*30594Ssam Cxyz	funny char xyz. terminated by white space
59*30594Ssam Hn	go to absolute horizontal position n
60*30594Ssam Vn	go to absolute vertical position n (down is positive)
61*30594Ssam hn	go n units horizontally (relative)
62*30594Ssam vn	ditto vertically
63*30594Ssam nnc	move right nn, then print c (exactly 2 digits!)
64*30594Ssam 		(this wart is an optimization that shrinks output file size
65*30594Ssam 		 about 35% and run-time about 15% while preserving ascii-ness)
66*30594Ssam Dt ...\n	draw operation 't':
67*30594Ssam 	Dl x y		line from here by x,y
68*30594Ssam 	Dc d		circle of diameter d with left side here
69*30594Ssam 	De x y		ellipse of axes x,y with left side here
70*30594Ssam 	Da x y r	arc counter-clockwise by x,y of radius r
71*30594Ssam 	D~ x y x y ...	wiggly line by x,y then x,y ...
72*30594Ssam nb a	end of line (information only -- no action needed)
73*30594Ssam 	a = space before line, a = after
74*30594Ssam w	paddable word space -- no action needed
75*30594Ssam pn	new page begins -- set v to 0
76*30594Ssam {	push current environment (font info & location)
77*30594Ssam }	pop a saved environment
78*30594Ssam txxxx	print string xxxx using natural widths
79*30594Ssam #...\n	comment
80*30594Ssam x ...\n	device control functions:
81*30594Ssam 	x i[nit]	init
82*30594Ssam 	x T s		name of device is s
83*30594Ssam 	x r[es] n h v	resolution is n/inch
84*30594Ssam 			h = min horizontal motion, v = min vert
85*30594Ssam 	x p[ause]	pause (can restart)
86*30594Ssam 	x s[top]	stop -- done for ever
87*30594Ssam 	x t[railer]	generate trailer
88*30594Ssam 	x f[font] n s	font position n contains font s
89*30594Ssam 	x H[eight] n	set character height to n
90*30594Ssam 	x S[slant] n	set slant to N
91*30594Ssam 
92*30594Ssam Adobe Extension for included PostScript:
93*30594Ssam %
94*30594Ssam (raw postscript...)
95*30594Ssam .\n
96*30594Ssam 
97*30594Ssam */
98*30594Ssam 
99*30594Ssam #include <stdio.h>
100*30594Ssam #include <ctype.h>
101*30594Ssam #include <signal.h>
102*30594Ssam #include <pwd.h>
103*30594Ssam #ifdef SYSV
104*30594Ssam extern struct passwd *getpwuid();
105*30594Ssam #endif
106*30594Ssam #include "transcript.h"
107*30594Ssam 
108*30594Ssam #include "dev.h"
109*30594Ssam 
110*30594Ssam char *malloc();
111*30594Ssam 
112*30594Ssam #define	NFONT	10
113*30594Ssam 
114*30594Ssam /* DIT state consists of: */
115*30594Ssam private int	hpos;		/* current horizontal position */
116*30594Ssam private int	vpos;		/* current vertical position */
117*30594Ssam private int	fontsize;	/* current font size */
118*30594Ssam private int	fontheight;	/* current character height */
119*30594Ssam private int	fontslant;	/* current font slant */
120*30594Ssam private int	font;		/* current font */
121*30594Ssam private int	resolution;	/* device resolution */
122*30594Ssam private int	minhoriz;	/* minimum horizontal motion */
123*30594Ssam private int	minvert;	/* minimum vertical motion */
124*30594Ssam 
125*30594Ssam private int	onspecial;
126*30594Ssam private int	specfont;
127*30594Ssam private int	prevfont;
128*30594Ssam private int 	pfont;
129*30594Ssam 
130*30594Ssam /* {} push/pop stack */
131*30594Ssam #define DSTACK 10
132*30594Ssam private struct ditstack {
133*30594Ssam     int hpos, vpos, fontsize, fontheight, fontslant, font;
134*30594Ssam } ditstack[DSTACK];
135*30594Ssam private int dlevel = 0;
136*30594Ssam 
137*30594Ssam #define ErrorTolerance 48
138*30594Ssam #define PSWID 0x00000FFF
139*30594Ssam #define ISPSPROC 0x000FF000
140*30594Ssam 
141*30594Ssam 
142*30594Ssam /* PSscale is equivalent to (x * PSmag / 72000) + 0.5 */
143*30594Ssam #define PSmag 16
144*30594Ssam #define PSscale(x) (((x)+2250)/4500)
145*30594Ssam 
146*30594Ssam /* we maintain PS coords with PSmag times the precision */
147*30594Ssam /* current PS state is: */
148*30594Ssam 
149*30594Ssam private int	PSx;		/* current horizontal position */
150*30594Ssam private int	PSy;		/* current vertical position */
151*30594Ssam private int	savex, savey;	/* position of start of current show string */
152*30594Ssam 
153*30594Ssam /* ps move types -- note that XMOVE|YMOVE == XYMOVE ! */
154*30594Ssam #define NONE 0
155*30594Ssam #define XMOVE 1
156*30594Ssam #define YMOVE 2
157*30594Ssam #define XYMOVE 3
158*30594Ssam 
159*30594Ssam private int movepending = NONE;
160*30594Ssam 
161*30594Ssam /* buffer string for show -- save up adjacent chars */
162*30594Ssam #define SHOWSIZE 400
163*30594Ssam private char showbuf[SHOWSIZE + 3]; /* extras are for quoting */
164*30594Ssam private int showind = 0;	/* index into string of next available byte */
165*30594Ssam private int PSshowlen = 0;	/* size in big units of buffered string */
166*30594Ssam private int nshow = 0;		/* actual number of show chars in showbuf */
167*30594Ssam private int startx;		/* troff starting pos of current string */
168*30594Ssam private int thisw;
169*30594Ssam 
170*30594Ssam /* #define NONE 0 */
171*30594Ssam #define HMOT 1
172*30594Ssam #define VMOT 2
173*30594Ssam #define CPUT 4
174*30594Ssam #define BRK  8
175*30594Ssam #define FNT  16
176*30594Ssam private int lastcmd;
177*30594Ssam 
178*30594Ssam private int	output	= 0;	/* do we do output at all? */
179*30594Ssam private int	nolist	= 0;	/* output page list if > 0 */
180*30594Ssam private int	olist[20];	/* pairs of page numbers */
181*30594Ssam private int	spage	= 9999;	/* stop every spage pages */
182*30594Ssam private int	scount	= 0;
183*30594Ssam private int	stopped = 0;
184*30594Ssam private int	pageno = 0;
185*30594Ssam private int	firstpage = TRUE;
186*30594Ssam 
187*30594Ssam private struct	dev	dev;
188*30594Ssam private struct font *fontbase[NFONT+1];
189*30594Ssam private short	*pstab;
190*30594Ssam private int	dres;	/* resolution from DESC */
191*30594Ssam private int	nsizes; /* number of point sizes from DESC */
192*30594Ssam private int	nfonts; /* number of fonts from DESC */
193*30594Ssam private int	smnt;	/* index of first special font */
194*30594Ssam private int	nchtab;
195*30594Ssam private char	*chname;
196*30594Ssam private short	*chtab;
197*30594Ssam private char	*fitab[NFONT+1];
198*30594Ssam private char	*widthtab[NFONT+1];	/* widtab would be a better name */
199*30594Ssam private char	*codetab[NFONT+1];	/* device codes */
200*30594Ssam 
201*30594Ssam private int     *pswidths[NFONT+1]; /* ps width tables */
202*30594Ssam private int	fontdelta[NFONT+1]; /* nonzero if xf overwrites font i */
203*30594Ssam 
204*30594Ssam /* font position info: */
205*30594Ssam private struct {
206*30594Ssam 	char *name;
207*30594Ssam 	int number;
208*30594Ssam } fontname[NFONT+1];
209*30594Ssam 
210*30594Ssam #define	FATAL	1
211*30594Ssam #define	BMASK	0377
212*30594Ssam 
213*30594Ssam #ifdef DEBUG
214*30594Ssam int	dbg	= 0;
215*30594Ssam int	fdbg = 0;
216*30594Ssam #define debugp(xxx) {if(dbg != 0){dbg--; printf xxx ; VOIDC fflush(stdout);}}
217*30594Ssam #else
218*30594Ssam #define debugp(x)
219*30594Ssam #endif
220*30594Ssam 
221*30594Ssam private FILE	*tf = stdout;	/* output file */
222*30594Ssam private char devname[20] = "psc";
223*30594Ssam 
224*30594Ssam private char	*infilename = "stdin"; /* input file name */
225*30594Ssam private char	*prologfile = PSDITPRO;
226*30594Ssam private char	*ditdir = DitDir;
227*30594Ssam 
228*30594Ssam private char	*prog;		/* argv[0] - program name */
229*30594Ssam 
230*30594Ssam main(argc, argv)
231*30594Ssam int argc;
232*30594Ssam char *argv[];
233*30594Ssam {
234*30594Ssam     FILE *fp;
235*30594Ssam     VOID done();
236*30594Ssam 
237*30594Ssam     prog = argv[0];
238*30594Ssam     while (argc > 1 && argv[1][0] == '-') {
239*30594Ssam 	switch (argv[1][1]) {
240*30594Ssam 	    case 'f':
241*30594Ssam 	    case 'F':
242*30594Ssam 		if (argv[1][2])
243*30594Ssam 		    ditdir = &argv[1][2];
244*30594Ssam 		else {
245*30594Ssam 		    ditdir = argv[2];
246*30594Ssam 		    argv++;
247*30594Ssam 		    argc--;
248*30594Ssam 		}
249*30594Ssam 		break;
250*30594Ssam 	    case 'p':
251*30594Ssam 		if (argv[1][2])
252*30594Ssam 		    prologfile = &argv[1][2];
253*30594Ssam 		break;
254*30594Ssam 	    case 'o':
255*30594Ssam 		outlist (&argv[1][2]);
256*30594Ssam 		break;
257*30594Ssam 	    case 'd':
258*30594Ssam #ifdef DEBUG
259*30594Ssam 		dbg = atoi (&argv[1][2]);
260*30594Ssam 		if (dbg == 0)
261*30594Ssam 		    dbg = 1;
262*30594Ssam 		tf = stdout;
263*30594Ssam #endif DEBUG
264*30594Ssam 		break;
265*30594Ssam 	    case 'b': 		/* ignore busy */
266*30594Ssam 		break;
267*30594Ssam 	    case 'w': 		/* ignore wait */
268*30594Ssam 		break;
269*30594Ssam 	    case 's':
270*30594Ssam 		spage = atoi (&argv[1][2]);
271*30594Ssam 		if (spage <= 0)
272*30594Ssam 		    spage = 9999;
273*30594Ssam 		break;
274*30594Ssam 	}
275*30594Ssam 	argc--;
276*30594Ssam 	argv++;
277*30594Ssam     }
278*30594Ssam 
279*30594Ssam     if (signal (SIGINT, done) == SIG_IGN) {
280*30594Ssam 	signal (SIGINT, SIG_IGN);
281*30594Ssam 	signal (SIGQUIT, SIG_IGN);
282*30594Ssam 	signal (SIGHUP, SIG_IGN);
283*30594Ssam     }
284*30594Ssam     else {
285*30594Ssam 	signal (SIGQUIT, done);
286*30594Ssam 	signal (SIGHUP, done);
287*30594Ssam     }
288*30594Ssam     signal (SIGTERM, done);
289*30594Ssam 
290*30594Ssam     preface ();
291*30594Ssam 
292*30594Ssam     if (argc <= 1)
293*30594Ssam 	conv (stdin);
294*30594Ssam     else
295*30594Ssam 	while (--argc > 0) {
296*30594Ssam 	    if (strcmp (*++argv, "-") == 0)
297*30594Ssam 		fp = stdin;
298*30594Ssam 	    else if ((fp = fopen (*argv, "r")) == NULL) {
299*30594Ssam 		fprintf (stderr, "%s: can't open %s\n", prog, *argv);
300*30594Ssam 		pexit(prog,2);
301*30594Ssam 	    }
302*30594Ssam 	    infilename = *argv;
303*30594Ssam 	    conv (fp);
304*30594Ssam 	    VOIDC fclose (fp);
305*30594Ssam 	}
306*30594Ssam     done ();
307*30594Ssam }
308*30594Ssam 
309*30594Ssam private outlist(s)	/* process list of page numbers to be printed */
310*30594Ssam char *s;
311*30594Ssam {
312*30594Ssam     int     n1, n2, i;
313*30594Ssam 
314*30594Ssam     nolist = 0;
315*30594Ssam     while (*s) {
316*30594Ssam 	n1 = 0;
317*30594Ssam 	if (isdigit (*s)) {
318*30594Ssam 	    do {
319*30594Ssam 		n1 = 10 * n1 + *s++ - '0';
320*30594Ssam 	    }
321*30594Ssam 	    while (isdigit (*s));
322*30594Ssam 	}
323*30594Ssam 	else {
324*30594Ssam 	    n1 = -9999;
325*30594Ssam 	}
326*30594Ssam 	n2 = n1;
327*30594Ssam 	if (*s == '-') {
328*30594Ssam 	    s++;
329*30594Ssam 	    n2 = 0;
330*30594Ssam 	    if (isdigit (*s)) {
331*30594Ssam 		do {
332*30594Ssam 		    n2 = 10 * n2 + *s++ - '0';
333*30594Ssam 		}
334*30594Ssam 		while (isdigit (*s));
335*30594Ssam 	    }
336*30594Ssam 	    else {
337*30594Ssam 		n2 = 9999;
338*30594Ssam 	    }
339*30594Ssam 	}
340*30594Ssam 	olist[nolist++] = n1;
341*30594Ssam 	olist[nolist++] = n2;
342*30594Ssam 	if (*s != '\0') {
343*30594Ssam 	    s++;
344*30594Ssam 	}
345*30594Ssam     }
346*30594Ssam     olist[nolist] = 0;
347*30594Ssam #ifdef DEBUG
348*30594Ssam     if (dbg)
349*30594Ssam 	for (i = 0; i < nolist; i += 2)
350*30594Ssam 	    printf ("%3d %3d\n", olist[i], olist[i + 1]);
351*30594Ssam #endif
352*30594Ssam }
353*30594Ssam 
354*30594Ssam private conv(fp)	/* convert a file */
355*30594Ssam register FILE *fp;
356*30594Ssam {
357*30594Ssam     register int    c, k;
358*30594Ssam     int     m, n, n1, m1;
359*30594Ssam     char    str[100], buf[300];
360*30594Ssam 
361*30594Ssam     while ((c = getc(fp)) != EOF) {
362*30594Ssam 	switch (c) {
363*30594Ssam 	    case '\n': case ' ': case '\0':
364*30594Ssam 		break;
365*30594Ssam 	    case '{': 		/* push down current environment */
366*30594Ssam 		t_push();
367*30594Ssam 		break;
368*30594Ssam 	    case '}':
369*30594Ssam 		t_pop();
370*30594Ssam 		break;
371*30594Ssam 	    case '0': case '1': case '2': case '3': case '4':
372*30594Ssam 	    case '5': case '6': case '7': case '8': case '9':
373*30594Ssam 	    /* two motion digits plus a character */
374*30594Ssam 		hmot((c - '0') * 10 + getc (fp) - '0');
375*30594Ssam 		lastcmd = HMOT;
376*30594Ssam 		put1(getc(fp), (char *) 0);
377*30594Ssam 		lastcmd = CPUT;
378*30594Ssam 		break;
379*30594Ssam 	    case 'c': 		/* single ascii character */
380*30594Ssam 		put1(getc(fp), (char *) 0);
381*30594Ssam 		lastcmd = CPUT;
382*30594Ssam 		break;
383*30594Ssam 	    case 'C':
384*30594Ssam 		fscanf(fp, "%s", str);
385*30594Ssam 		put1s(str);
386*30594Ssam 		lastcmd = CPUT;
387*30594Ssam 		break;
388*30594Ssam 	    case 't': 		/* straight text */
389*30594Ssam 		fgets(buf, sizeof (buf), fp);
390*30594Ssam 		t_text (buf);
391*30594Ssam 		lastcmd = CPUT;
392*30594Ssam 		break;
393*30594Ssam 	    case 'D': 		/* draw function */
394*30594Ssam 		fgets(buf, sizeof (buf), fp);
395*30594Ssam 		switch (buf[0]) {
396*30594Ssam 		    case 'l': 	/* draw a line */
397*30594Ssam 			sscanf (buf + 1, "%d %d", &n, &m);
398*30594Ssam 			drawline (n, m);
399*30594Ssam 			break;
400*30594Ssam 		    case 'c': 	/* circle */
401*30594Ssam 			sscanf (buf + 1, "%d", &n);
402*30594Ssam 			drawcirc (n);
403*30594Ssam 			break;
404*30594Ssam 		    case 'e': 	/* ellipse */
405*30594Ssam 			sscanf (buf + 1, "%d %d", &m, &n);
406*30594Ssam 			drawellip (m, n);
407*30594Ssam 			break;
408*30594Ssam 		    case 'a': 	/* arc */
409*30594Ssam 			sscanf (buf + 1, "%d %d %d %d", &n, &m, &n1, &m1);
410*30594Ssam 			drawarc (n, m, n1, m1);
411*30594Ssam 			break;
412*30594Ssam 		    case '~': 	/* wiggly line */
413*30594Ssam 			drawwig (buf + 1);
414*30594Ssam 			break;
415*30594Ssam 		    default:
416*30594Ssam 			fprintf(stderr,"%s: unknown drawing function %s\n",
417*30594Ssam 				prog,buf);
418*30594Ssam 			exit(2);
419*30594Ssam 			break;
420*30594Ssam 		}
421*30594Ssam 		break;
422*30594Ssam 	    case 's':
423*30594Ssam 		fscanf (fp, "%d", &n);
424*30594Ssam 		t_size (n);
425*30594Ssam 		lastcmd = FNT;
426*30594Ssam 		break;
427*30594Ssam 	    case 'f':
428*30594Ssam 		fscanf (fp, "%s", str);
429*30594Ssam 		setfont (t_font (str));
430*30594Ssam 		lastcmd = FNT;
431*30594Ssam 		break;
432*30594Ssam 	    case 'H': 		/* absolute horizontal motion */
433*30594Ssam 		while ((c = getc (fp)) == ' ');
434*30594Ssam 		k = 0;
435*30594Ssam 		do {
436*30594Ssam 		    k = 10 * k + c - '0';
437*30594Ssam 		} while (isdigit (c = getc (fp)));
438*30594Ssam 		ungetc (c, fp);
439*30594Ssam 		hgoto (k);
440*30594Ssam 		lastcmd = HMOT;
441*30594Ssam 		break;
442*30594Ssam 	    case 'h': 		/* relative horizontal motion */
443*30594Ssam 		while ((c = getc (fp)) == ' ');
444*30594Ssam 		k = 0;
445*30594Ssam 		do {
446*30594Ssam 		    k = 10 * k + c - '0';
447*30594Ssam 		} while (isdigit (c = getc (fp)));
448*30594Ssam 		ungetc (c, fp);
449*30594Ssam 		hmot (k);
450*30594Ssam 		lastcmd = HMOT;
451*30594Ssam 		break;
452*30594Ssam 	    case 'w':
453*30594Ssam 		FlushShow(1);
454*30594Ssam 		lastcmd = BRK;
455*30594Ssam 		break;
456*30594Ssam 	    case 'V':
457*30594Ssam 		fscanf (fp, "%d", &n);
458*30594Ssam 		vgoto (n);
459*30594Ssam 		lastcmd = VMOT;
460*30594Ssam 		break;
461*30594Ssam 	    case 'v':
462*30594Ssam 		fscanf (fp, "%d", &n);
463*30594Ssam 		vmot (n);
464*30594Ssam 		lastcmd = VMOT;
465*30594Ssam 		break;
466*30594Ssam 	    case 'p': 		/* new page */
467*30594Ssam 		fscanf (fp, "%d", &n);
468*30594Ssam 		t_page (n);
469*30594Ssam 		lastcmd = NONE;
470*30594Ssam 		break;
471*30594Ssam 	    case 'n': 		/* end of line -- ignore */
472*30594Ssam 		while (getc (fp) != '\n');
473*30594Ssam 		FlushShow(1);
474*30594Ssam 		lastcmd = BRK;
475*30594Ssam 		break;
476*30594Ssam 	    case '#': 		/* comment */
477*30594Ssam 	    /* maybe should pass through as a PS comment */
478*30594Ssam 		while (getc (fp) != '\n');
479*30594Ssam 		break;
480*30594Ssam 	    case 'x': 		/* device control */
481*30594Ssam 		devcntrl (fp);
482*30594Ssam 		break;
483*30594Ssam 	    case '%':		/* imbedded PostScript */
484*30594Ssam 	    /* copy everything up to but NOT including a line */
485*30594Ssam 	    /* with at single "." */
486*30594Ssam 	    FlushShow(0);MoveTo();DoMove();
487*30594Ssam 	    printf("\n%% included PostScript\n");
488*30594Ssam 	    while (fgets(buf, sizeof buf, fp) != NULL) {
489*30594Ssam 		if (strcmp(".\n",buf) == 0) break;
490*30594Ssam 		fputs(buf,stdout);
491*30594Ssam 	    }
492*30594Ssam 	    break;
493*30594Ssam 	    default:
494*30594Ssam 		fprintf(stderr,"%s: bad input char \\%03o (%c)\n",prog,c,c);
495*30594Ssam 		exit(2);
496*30594Ssam 		done ();
497*30594Ssam 	}
498*30594Ssam     }
499*30594Ssam }
500*30594Ssam 
501*30594Ssam 
502*30594Ssam /* put in PostScript prolog */
503*30594Ssam private preface()
504*30594Ssam {
505*30594Ssam     register    FILE *prolog;
506*30594Ssam     char    hostname[256];
507*30594Ssam     char tempfile[512];
508*30594Ssam     struct passwd  *pswd;
509*30594Ssam     long    clock;
510*30594Ssam     char *libdir;
511*30594Ssam 
512*30594Ssam     fprintf (tf, "%%!%s\n", COMMENTVERSION);
513*30594Ssam     pswd = getpwuid (getuid ());
514*30594Ssam     VOIDC gethostname (hostname, sizeof hostname);
515*30594Ssam     fprintf (tf, "%%%%Creator: %s:%s (%s)\n", hostname,
516*30594Ssam 	    pswd->pw_name, pswd->pw_gecos);
517*30594Ssam     fprintf (tf, "%%%%Title: %s (ditroff)\n", infilename);
518*30594Ssam     fprintf (tf, "%%%%CreationDate: %s",
519*30594Ssam 		(time (&clock), ctime (&clock)));
520*30594Ssam     fprintf (tf, "%%%%EndComments\n");
521*30594Ssam 
522*30594Ssam     if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir;
523*30594Ssam     mstrcat(tempfile, libdir, prologfile, sizeof tempfile);
524*30594Ssam     if ((copyfile(tempfile, stdout)) != 0) {
525*30594Ssam 	fprintf(stderr,"%s: can't copy prolog file %s\n",prog, tempfile);
526*30594Ssam 	exit(2);
527*30594Ssam     }
528*30594Ssam     printf ("ditstart\n");
529*30594Ssam }
530*30594Ssam 
531*30594Ssam private devcntrl(fp)	/* interpret device control functions */
532*30594Ssam FILE *fp;
533*30594Ssam {
534*30594Ssam     char    str[20], str1[50], buf[50];
535*30594Ssam     int     c, n, res, minh, minv;
536*30594Ssam 
537*30594Ssam     fscanf (fp, "%s", str);
538*30594Ssam     switch (str[0]) {		/* crude for now */
539*30594Ssam 	case 'i': 		/* initialize */
540*30594Ssam 	    fileinit ();
541*30594Ssam 	    t_init ();
542*30594Ssam 	    lastcmd = NONE;
543*30594Ssam 	    break;
544*30594Ssam 	case 'T': 		/* device name */
545*30594Ssam 	    fscanf (fp, "%s", devname);
546*30594Ssam 	    if (strcmp (devname, "psc")) {
547*30594Ssam 		fprintf(stderr,"%s: device not psc\n",prog);
548*30594Ssam 		exit(2);
549*30594Ssam 	    }
550*30594Ssam 	    printf ("(%s)xT\n", devname);
551*30594Ssam 	    lastcmd = NONE;
552*30594Ssam 	    break;
553*30594Ssam 	case 't': 		/* trailer */
554*30594Ssam 	    t_trailer ();
555*30594Ssam 	    lastcmd = NONE;
556*30594Ssam 	    break;
557*30594Ssam 	case 'p': 		/* pause -- can restart */
558*30594Ssam 	    t_reset ('p');
559*30594Ssam 	    lastcmd = NONE;
560*30594Ssam 	    break;
561*30594Ssam 	case 's': 		/* stop */
562*30594Ssam 	    t_reset ('s');
563*30594Ssam 	    lastcmd = NONE;
564*30594Ssam 	    break;
565*30594Ssam 	case 'r': 		/* resolution assumed when prepared */
566*30594Ssam 	    fscanf (fp, "%d %d %d", &res, &minh, &minv);
567*30594Ssam 	    t_res (res, minh, minv);
568*30594Ssam 	    lastcmd = NONE;
569*30594Ssam 	    break;
570*30594Ssam 	case 'f': 		/* font used */
571*30594Ssam 	    fscanf (fp, "%d %s", &n, str);
572*30594Ssam 	    fgets (buf, sizeof buf, fp);/* in case theres a filename */
573*30594Ssam 	    ungetc ('\n', fp);	/* fgets goes too far */
574*30594Ssam 	    str1[0] = 0;	/* in case there is nothing to come in */
575*30594Ssam 	    sscanf (buf, "%s", str1);
576*30594Ssam 	    loadfont (n, str, str1);
577*30594Ssam 	    lastcmd = FNT;
578*30594Ssam 	    break;
579*30594Ssam 	case 'H': 		/* char height */
580*30594Ssam 	    fscanf (fp, "%d", &n);
581*30594Ssam 	    t_charht (n);
582*30594Ssam 	    lastcmd = FNT;
583*30594Ssam 	    break;
584*30594Ssam 	case 'S': 		/* slant */
585*30594Ssam 	    fscanf (fp, "%d", &n);
586*30594Ssam 	    t_slant (n);
587*30594Ssam 	    lastcmd = FNT;
588*30594Ssam 	    break;
589*30594Ssam     }
590*30594Ssam     /* skip rest of input line */
591*30594Ssam     while ((c = getc (fp)) != '\n') {if (c == EOF) break;};
592*30594Ssam }
593*30594Ssam 
594*30594Ssam private fileinit()	/* read in font and code files, etc. */
595*30594Ssam {
596*30594Ssam     int     i, fin, nw;
597*30594Ssam     char    *filebase, *p;
598*30594Ssam     char    temp[60];
599*30594Ssam     unsigned msize;
600*30594Ssam 
601*30594Ssam     /* open table for device,
602*30594Ssam      * read in resolution, size info, font info,   etc. and set params */
603*30594Ssam 
604*30594Ssam     sprintf (temp, "%s/dev%s/DESC.out", ditdir, devname);
605*30594Ssam     if ((fin = open (temp, 0)) < 0) {
606*30594Ssam 	fprintf (stderr, "%s: can't open %s - %s\n", prog, devname, temp);
607*30594Ssam 	pexit(prog,2);
608*30594Ssam     }
609*30594Ssam     if (read(fin,(char *)&dev, (int) sizeof(struct dev)) != sizeof(struct dev)) {
610*30594Ssam 	fprintf (stderr, "%s: can't read %s\n", prog, temp);
611*30594Ssam 	pexit(prog,2);
612*30594Ssam     }
613*30594Ssam     dres = dev.res;
614*30594Ssam     nfonts = dev.nfonts;
615*30594Ssam     nsizes = dev.nsizes;
616*30594Ssam     nchtab = dev.nchtab;
617*30594Ssam     /* enough room for whole file */
618*30594Ssam     filebase = malloc ((unsigned) dev.filesize);
619*30594Ssam     if (read (fin, filebase, dev.filesize) != dev.filesize) {
620*30594Ssam 	fprintf (stderr, "%s: trouble reading %s\n", prog, temp);
621*30594Ssam 	pexit(prog,2);
622*30594Ssam     }
623*30594Ssam     pstab = (short *) filebase;		/* point size table */
624*30594Ssam     chtab = pstab + nsizes + 1;		/* char index table */
625*30594Ssam     chname = (char *) (chtab + dev.nchtab);	/* char name table */
626*30594Ssam     p = chname + dev.lchname;		/* end of char name table */
627*30594Ssam     /* parse the preloaded font tables */
628*30594Ssam     for (i = 1; i <= nfonts; i++) {
629*30594Ssam 	fontdelta[i] = 0;
630*30594Ssam 	fontbase[i] = (struct font *) p;
631*30594Ssam 	nw = *p & BMASK;	/* number of width entries */
632*30594Ssam 	if ((smnt == 0) && (fontbase[i]->specfont == 1))
633*30594Ssam 	    smnt = i;		/* first special font */
634*30594Ssam 	p += sizeof (struct font); /* skip header */
635*30594Ssam 	widthtab[i] = p;		/* width table */
636*30594Ssam 					/* kern table is next */
637*30594Ssam 	codetab[i] = p + 2 * nw;	/* device codes */
638*30594Ssam 	fitab[i] = p + 3 * nw;		/* font index table */
639*30594Ssam 
640*30594Ssam 	p += 3 * nw + dev.nchtab + (128 - 32);	/* next font */
641*30594Ssam 	t_fp (i, fontbase[i]->namefont, fontbase[i]->intname);
642*30594Ssam 	loadpswidths (i, fontbase[i]->namefont);
643*30594Ssam 	sayload (i, fontbase[i]->namefont, (char *) 0);
644*30594Ssam #ifdef DEBUG
645*30594Ssam 	if (fdbg > 1)
646*30594Ssam 	    fontprint (i);
647*30594Ssam #endif
648*30594Ssam     }
649*30594Ssam     fontdelta[0] = 0;
650*30594Ssam     msize = 3*255 + dev.nchtab + (128-32) + sizeof (struct font);
651*30594Ssam     fontbase[0] = (struct font *) malloc(msize);
652*30594Ssam     widthtab[0] = (char *) fontbase[0] + sizeof (struct font);
653*30594Ssam     fontbase[0]->nwfont = 255;
654*30594Ssam     close (fin);
655*30594Ssam }
656*30594Ssam 
657*30594Ssam private loadpswidths(i,name)
658*30594Ssam int i;
659*30594Ssam char *name;
660*30594Ssam {
661*30594Ssam     char temp[60];
662*30594Ssam     register FILE *auxin;
663*30594Ssam     register int j;
664*30594Ssam     int cc, wid, funny;
665*30594Ssam 
666*30594Ssam     sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name);
667*30594Ssam     auxin = fopen(temp, "r");
668*30594Ssam     /* allocate table */
669*30594Ssam     if (pswidths[i] == NULL) {
670*30594Ssam 	pswidths[i] = (int *) malloc(256 * (sizeof (int)));
671*30594Ssam     }
672*30594Ssam     /* initialize to not-there */
673*30594Ssam     for (j = 0; j <= 255; pswidths[i][j++] = -1);
674*30594Ssam     /* read them in */
675*30594Ssam     while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) {
676*30594Ssam 	pswidths[i][cc] = wid | (funny << 12);
677*30594Ssam     }
678*30594Ssam     VOIDC fclose(auxin);
679*30594Ssam }
680*30594Ssam 
681*30594Ssam #ifdef DEBUG
682*30594Ssam private fontprint(i)	/* debugging print of font i (0,...) */
683*30594Ssam int i;
684*30594Ssam {
685*30594Ssam     int     j, n;
686*30594Ssam     char   *p;
687*30594Ssam 
688*30594Ssam     printf ("font %d:\n", i);
689*30594Ssam     p = (char *) fontbase[i];
690*30594Ssam     n = fontbase[i]->nwfont & BMASK;
691*30594Ssam     printf ("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
692*30594Ssam 	    p, n, fontbase[i]->specfont,
693*30594Ssam 	    fontbase[i]->namefont, widthtab[i], fitab[i]);
694*30594Ssam     printf ("widths:\n");
695*30594Ssam     for (j = 0; j <= n; j++) {
696*30594Ssam 	printf (" %2d", widthtab[i][j] & BMASK);
697*30594Ssam 	if (j % 20 == 19)
698*30594Ssam 	    printf ("\n");
699*30594Ssam     }
700*30594Ssam     printf ("\ncodetab:\n");
701*30594Ssam     for (j = 0; j <= n; j++) {
702*30594Ssam 	printf (" %2d", codetab[i][j] & BMASK);
703*30594Ssam 	if (j % 20 == 19)
704*30594Ssam 	    printf ("\n");
705*30594Ssam     }
706*30594Ssam     printf ("\nfitab:\n");
707*30594Ssam     for (j = 0; j <= dev.nchtab + 128 - 32; j++) {
708*30594Ssam 	printf (" %2d", fitab[i][j] & BMASK);
709*30594Ssam 	if (j % 20 == 19)
710*30594Ssam 	    printf ("\n");
711*30594Ssam     }
712*30594Ssam     printf ("\n");
713*30594Ssam }
714*30594Ssam #endif
715*30594Ssam 
716*30594Ssam private loadfont(n, s, s1) /* load font info for font s on position n */
717*30594Ssam int n;
718*30594Ssam char *s, *s1;
719*30594Ssam {
720*30594Ssam     char    temp[60];
721*30594Ssam     int     fin, nw, norig;
722*30594Ssam     int     bcount;
723*30594Ssam 
724*30594Ssam     if (n < 0 || n > NFONT) {
725*30594Ssam 	fprintf(stderr,"%s: illegal fp command %d %s\n", prog, n, s);
726*30594Ssam 	exit(2);
727*30594Ssam     }
728*30594Ssam     if (strcmp(s, fontbase[n]->namefont) == 0) return;
729*30594Ssam     if (fontbase[n]->namefont != 0) {
730*30594Ssam 	fontdelta[n] = 1;
731*30594Ssam     }
732*30594Ssam     if (s1 == NULL || s1[0] == '\0') {
733*30594Ssam 	sprintf (temp, "%s/dev%s/%s.out", ditdir, devname, s);
734*30594Ssam     }
735*30594Ssam     else {
736*30594Ssam 	sprintf (temp, "%s/%s.out", s1, s);
737*30594Ssam     }
738*30594Ssam     if ((fin = open (temp, 0)) < 0) {
739*30594Ssam 	fprintf(stderr,"%s: can't open font table %s\n", prog, temp);
740*30594Ssam 	pexit(prog,2);
741*30594Ssam     }
742*30594Ssam     norig = fontbase[n]->nwfont & BMASK;
743*30594Ssam     bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font);
744*30594Ssam     VOIDC read (fin, (char *)fontbase[n], bcount);
745*30594Ssam     if ((fontbase[n]->nwfont & BMASK) > norig) {
746*30594Ssam 	fprintf(stderr,"%s: Font %s too big for position %d\n", prog, s, n);
747*30594Ssam 	exit(2);
748*30594Ssam     }
749*30594Ssam     close (fin);
750*30594Ssam     nw = fontbase[n]->nwfont & BMASK;
751*30594Ssam     widthtab[n] = (char *) fontbase[n] + sizeof (struct font);
752*30594Ssam     codetab[n] = (char *) widthtab[n] + 2 * nw;
753*30594Ssam     fitab[n] = (char *) widthtab[n] + 3 * nw;
754*30594Ssam     t_fp (n, fontbase[n]->namefont, fontbase[n]->intname);
755*30594Ssam     loadpswidths (n, fontbase[n]->namefont);
756*30594Ssam     sayload (n, s, s1);
757*30594Ssam     fontbase[n]->nwfont = norig; /* so can later use full original size */
758*30594Ssam #ifdef DEBUG
759*30594Ssam     if (fdbg > 1)
760*30594Ssam 	fontprint (n);
761*30594Ssam #endif
762*30594Ssam }
763*30594Ssam 
764*30594Ssam private sayload(n, s, s1)	/* position n contains font s (internal s1) */
765*30594Ssam int n;
766*30594Ssam char *s, *s1;
767*30594Ssam {
768*30594Ssam     char    pass[60];
769*30594Ssam     FILE    *ptrfile;
770*30594Ssam     char    Adobefont[60];
771*30594Ssam 
772*30594Ssam     if (s1 == NULL || s1[0] == '\0') {
773*30594Ssam 	sprintf (pass, "%s/dev%s/%s.map", ditdir, devname, s);
774*30594Ssam     }
775*30594Ssam     else {
776*30594Ssam 	sprintf (pass, "%s/%s.map", s1, s);
777*30594Ssam     }
778*30594Ssam 
779*30594Ssam     if ((ptrfile = fopen (pass, "r")) == NULL) {
780*30594Ssam 	fprintf(stderr,"%s: can't open font map file %s\n", prog, pass);
781*30594Ssam 	pexit(prog,2);
782*30594Ssam     }
783*30594Ssam 
784*30594Ssam     fscanf (ptrfile, "%s", Adobefont);
785*30594Ssam     FlushShow(0);
786*30594Ssam     printf ("%d(%s)xf %d f\n", n, Adobefont, n);
787*30594Ssam     font = n;
788*30594Ssam     VOIDC fclose(ptrfile);
789*30594Ssam }
790*30594Ssam 
791*30594Ssam private VOID done()
792*30594Ssam {
793*30594Ssam     if (tf == NULL)
794*30594Ssam 	exit (1);
795*30594Ssam     t_reset ('s');
796*30594Ssam     exit (0);
797*30594Ssam }
798*30594Ssam 
799*30594Ssam private t_init()	/* "x i" - initialize device */
800*30594Ssam {
801*30594Ssam     movepending = NONE;
802*30594Ssam     savex = savey = 0;
803*30594Ssam 
804*30594Ssam     t_size (10);		/* start somewhere */
805*30594Ssam     t_slant (0);
806*30594Ssam     setfont (1);		/* set font */
807*30594Ssam     printf("xi\n");
808*30594Ssam     printf("%%%%EndProlog\n");
809*30594Ssam }
810*30594Ssam 
811*30594Ssam private t_push()	/* begin a new block */
812*30594Ssam {
813*30594Ssam     FlushShow(1);MoveTo();DoMove();
814*30594Ssam     if (dlevel == DSTACK) {
815*30594Ssam 	fprintf(stderr,"%s: ditroff push/pop overflow!\n",prog);
816*30594Ssam 	exit(2);
817*30594Ssam     }
818*30594Ssam     ditstack[dlevel].hpos = hpos;
819*30594Ssam     ditstack[dlevel].vpos = vpos;
820*30594Ssam     ditstack[dlevel].fontsize = fontsize;
821*30594Ssam     ditstack[dlevel].fontheight = fontheight;
822*30594Ssam     ditstack[dlevel].fontslant = fontslant;
823*30594Ssam     ditstack[dlevel].font = font;
824*30594Ssam     dlevel++;
825*30594Ssam     printf ("\nditpush\n");
826*30594Ssam }
827*30594Ssam 
828*30594Ssam private t_pop()	/* pop to previous state */
829*30594Ssam {
830*30594Ssam     FlushShow(1);MoveTo();DoMove();
831*30594Ssam     if (dlevel == 0) {
832*30594Ssam 	fprintf(stderr,"%s: ditroff push/pop underflow!\n",prog);
833*30594Ssam 	exit(2);
834*30594Ssam     }
835*30594Ssam     dlevel--;
836*30594Ssam     hpos = ditstack[dlevel].hpos;
837*30594Ssam     vpos = ditstack[dlevel].vpos;
838*30594Ssam     fontsize = ditstack[dlevel].fontsize;
839*30594Ssam     fontheight = ditstack[dlevel].fontheight;
840*30594Ssam     fontslant = ditstack[dlevel].fontslant;
841*30594Ssam     font = ditstack[dlevel].font;
842*30594Ssam     printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font);
843*30594Ssam     startx = savex = hpos;
844*30594Ssam     savey = vpos;
845*30594Ssam     PSx = hpos * PSmag;
846*30594Ssam     PSy = vpos * PSmag;
847*30594Ssam     printf("%d %d MXY\n",savex,savey);
848*30594Ssam     movepending = NONE;
849*30594Ssam     printf("\nditpop\n");
850*30594Ssam }
851*30594Ssam 
852*30594Ssam private t_page(n)	/* do whatever new page functions */
853*30594Ssam {
854*30594Ssam     int     i;
855*30594Ssam 
856*30594Ssam     if (output) {
857*30594Ssam 	if (++scount >= spage) {
858*30594Ssam 	    t_reset ('p');
859*30594Ssam 	    scount = 0;
860*30594Ssam 	}
861*30594Ssam     }
862*30594Ssam     output = 1;
863*30594Ssam     FlushShow(0);
864*30594Ssam     if (!firstpage) {
865*30594Ssam 	printf("\n%d p",n);
866*30594Ssam     }
867*30594Ssam     firstpage = FALSE;
868*30594Ssam     printf ("\n%%%%Page: %d %d\n", n, ++pageno, n);
869*30594Ssam     for (i = 0; i <= nfonts; i++) {
870*30594Ssam 	if (fontdelta[i] != 0) {
871*30594Ssam 	    sayload (i, fontname[i].name, (char *) 0);
872*30594Ssam 	}
873*30594Ssam     }
874*30594Ssam     vpos = 0;
875*30594Ssam     PSy = 0;
876*30594Ssam     printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font);
877*30594Ssam     if (nolist == 0)
878*30594Ssam 	return;
879*30594Ssam     output = 0;
880*30594Ssam     for (i = 0; i < nolist; i += 2)
881*30594Ssam 	if (n >= olist[i] && n <= olist[i + 1]) {
882*30594Ssam 	    output = 1;
883*30594Ssam 	    break;
884*30594Ssam 	}
885*30594Ssam }
886*30594Ssam 
887*30594Ssam private t_size(n)	/* convert integer to internal size number*/
888*30594Ssam int n;
889*30594Ssam {
890*30594Ssam     FlushShow(1);
891*30594Ssam     if (fontsize != n) {
892*30594Ssam 	fontsize = n;
893*30594Ssam 	printf("%d s\n",fontsize);
894*30594Ssam     }
895*30594Ssam }
896*30594Ssam 
897*30594Ssam private t_charht(n)	/* set character height to n */
898*30594Ssam int n;
899*30594Ssam {
900*30594Ssam     FlushShow(1);
901*30594Ssam     if (fontheight != n) {
902*30594Ssam 	fontheight = n;
903*30594Ssam 	printf("%d xH\n",fontheight);
904*30594Ssam     }
905*30594Ssam }
906*30594Ssam 
907*30594Ssam private t_slant(n)	/* set slant to n */
908*30594Ssam int n;
909*30594Ssam {
910*30594Ssam     FlushShow(1);
911*30594Ssam     if (fontslant != n) {
912*30594Ssam 	fontslant = n;
913*30594Ssam 	printf("%d xS\n",fontslant);
914*30594Ssam     }
915*30594Ssam }
916*30594Ssam 
917*30594Ssam private t_font(s)	/* convert string to internal font number */
918*30594Ssam char *s;
919*30594Ssam {
920*30594Ssam     int     n;
921*30594Ssam 
922*30594Ssam     n = atoi (s);
923*30594Ssam     if (n < 0 || n > nfonts) n = 1;
924*30594Ssam     return (n);
925*30594Ssam }
926*30594Ssam 
927*30594Ssam private t_text(s)	/* print string s as text??? */
928*30594Ssam char *s;
929*30594Ssam {
930*30594Ssam 	fprintf(stderr,"%s: ditroff t <%s> unimplemented!\n",prog,s);
931*30594Ssam }
932*30594Ssam 
933*30594Ssam private t_reset(c)
934*30594Ssam {
935*30594Ssam     output = 1;			/* by God */
936*30594Ssam     if (c == 'p') {
937*30594Ssam 	printf ("\nxp\n");
938*30594Ssam     }
939*30594Ssam     else {
940*30594Ssam 	if (!stopped)
941*30594Ssam 	    printf ("\nxs\n");
942*30594Ssam 	stopped = 1;
943*30594Ssam     }
944*30594Ssam     fflush (tf);
945*30594Ssam }
946*30594Ssam 
947*30594Ssam private t_res(res, minh, minv)
948*30594Ssam int res, minh, minv;
949*30594Ssam {
950*30594Ssam     resolution = res;
951*30594Ssam     minhoriz = minh;
952*30594Ssam     minvert = minv;
953*30594Ssam     printf ("%d %d %d xr\n", res, minh, minv);
954*30594Ssam }
955*30594Ssam 
956*30594Ssam private t_trailer()
957*30594Ssam {
958*30594Ssam     FlushShow(0);
959*30594Ssam     printf("\n%d p",pageno);
960*30594Ssam     printf("\n%%%%Trailer\n");
961*30594Ssam     printf("xt\n");
962*30594Ssam }
963*30594Ssam 
964*30594Ssam private put1s(s)	/* s is a funny char name */
965*30594Ssam char *s;
966*30594Ssam {
967*30594Ssam     int     i;
968*30594Ssam 
969*30594Ssam     if (!output) return;
970*30594Ssam     debugp(("%s ", s));
971*30594Ssam 
972*30594Ssam     /* search for s in the funny char name table */
973*30594Ssam     for (i = 0; i < nchtab; i++) {
974*30594Ssam 	if (strcmp(&chname[chtab[i]], s) == 0) break;
975*30594Ssam     }
976*30594Ssam 
977*30594Ssam     if (i < nchtab) {
978*30594Ssam 	put1(i + 128, s);
979*30594Ssam     }
980*30594Ssam     else {
981*30594Ssam 	debugp(("not found "));
982*30594Ssam 	putnf (0, s);
983*30594Ssam     }
984*30594Ssam }
985*30594Ssam 
986*30594Ssam #define needsescape(c) ((c=='\\') || (c=='(') || (c==')'))
987*30594Ssam 
988*30594Ssam private put1(c, s)	/* output char c */
989*30594Ssam int c;
990*30594Ssam char *s;
991*30594Ssam {
992*30594Ssam     char *pw;
993*30594Ssam     register char *p;
994*30594Ssam     register int i, k;
995*30594Ssam     register int cc;
996*30594Ssam     int ofont, code;
997*30594Ssam     int psinfo, pswid, tw;
998*30594Ssam 
999*30594Ssam     if (!output) return;
1000*30594Ssam     if (c == 32) {
1001*30594Ssam 	thisw = 0;
1002*30594Ssam 	FlushShow(0);
1003*30594Ssam 	return;
1004*30594Ssam     }
1005*30594Ssam     if (c < 32) {
1006*30594Ssam 	debugp(("non-exist 0%o\n",c));
1007*30594Ssam 	return;
1008*30594Ssam     }
1009*30594Ssam 
1010*30594Ssam     c -= 32;	/* offset char code */
1011*30594Ssam     k = ofont = pfont = font;
1012*30594Ssam     if (onspecial) pfont = prevfont;
1013*30594Ssam 
1014*30594Ssam     if ((i = (fitab[pfont][c] & BMASK)) != 0) {/* char on this font */
1015*30594Ssam 	p = codetab[pfont];
1016*30594Ssam 	pw = widthtab[pfont];
1017*30594Ssam 	if (onspecial) {
1018*30594Ssam 	    setfont(prevfont);
1019*30594Ssam 	    thisw = 0;
1020*30594Ssam 	    onspecial = 0;
1021*30594Ssam 	}
1022*30594Ssam     }
1023*30594Ssam     else if (smnt > 0) {	/* on special (we hope) */
1024*30594Ssam 	for (k = smnt; k <= nfonts; k += 1)
1025*30594Ssam 	    if ((i = (fitab[k][c] & BMASK)) != 0) {
1026*30594Ssam 		p = codetab[k];
1027*30594Ssam 		pw = widthtab[k];
1028*30594Ssam 		prevfont = pfont;
1029*30594Ssam 		if (onspecial && (k == specfont)) break;
1030*30594Ssam 		setfont (k);
1031*30594Ssam 		thisw = 0;
1032*30594Ssam 		onspecial = 1;
1033*30594Ssam 		specfont = k;
1034*30594Ssam 		break;
1035*30594Ssam 	    }
1036*30594Ssam     }
1037*30594Ssam     if ((i == 0) || (k > nfonts) || ((code = p[i] & BMASK) == 0)) {
1038*30594Ssam 	debugp(("not found 0%o\n", c+32));
1039*30594Ssam 	putnf (c + 32, s);
1040*30594Ssam 	return;
1041*30594Ssam     }
1042*30594Ssam     /* when we get here,
1043*30594Ssam      *  c == biased character code
1044*30594Ssam      *	k == font number
1045*30594Ssam      *  i == index into codetab and widthtab for this character
1046*30594Ssam      *  p == codetab for this font
1047*30594Ssam      *  pw == width tab for this font
1048*30594Ssam      *  code == character code for this char
1049*30594Ssam      */
1050*30594Ssam 
1051*30594Ssam     cc = c + 32;
1052*30594Ssam     debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n",
1053*30594Ssam     		cc, code));
1054*30594Ssam     psinfo = pswidths[font][code];	/* PS specific char info */
1055*30594Ssam     pswid = psinfo & PSWID;		/* PS character width */
1056*30594Ssam     thisw = pw[i] & BMASK;		/* troff char width */
1057*30594Ssam     tw = thisw = (thisw * fontsize + dev.unitwidth/2) / dev.unitwidth;
1058*30594Ssam 
1059*30594Ssam     if ((psinfo & ISPSPROC) && (psinfo != -1)) {
1060*30594Ssam 	/* character is implemented by a PostScript proc */
1061*30594Ssam 	showspecial(s, code, pswid);
1062*30594Ssam 	if (pswid > 0) {
1063*30594Ssam 	    PSx += PSscale(pswid * fontsize * dres);
1064*30594Ssam 	}
1065*30594Ssam 	thisw = 0;
1066*30594Ssam     }
1067*30594Ssam     else {
1068*30594Ssam 	showchar(code);
1069*30594Ssam 	if (pswid > 0) {
1070*30594Ssam 	    PSshowlen += PSscale(pswid * fontsize * dres);
1071*30594Ssam 	}
1072*30594Ssam     }
1073*30594Ssam 
1074*30594Ssam /*
1075*30594Ssam     if (font != ofont) {
1076*30594Ssam 	setfont(ofont);
1077*30594Ssam 	startx = hpos + tw;
1078*30594Ssam 	thisw = 0;
1079*30594Ssam 	lastcmd = FNT;
1080*30594Ssam     }
1081*30594Ssam */
1082*30594Ssam     debugp(("...width (%d)\n", pw[i]&BMASK));
1083*30594Ssam }
1084*30594Ssam 
1085*30594Ssam 
1086*30594Ssam private putnf(c, s)	/* note that a character wasnt found */
1087*30594Ssam int c;
1088*30594Ssam char *s;
1089*30594Ssam {
1090*30594Ssam 
1091*30594Ssam     FlushShow(0);
1092*30594Ssam     thisw = 0;
1093*30594Ssam     if ((s == NULL) || (*s == '\0')) printf("(\%3o)cb\n", c);
1094*30594Ssam     else if ((strcmp(s, "\\|") == 0) || (strcmp(s, "\\^") == 0)
1095*30594Ssam     || (strcmp (s, "\\&") == 0))
1096*30594Ssam 	return;
1097*30594Ssam     else
1098*30594Ssam 	printf("(%s)cb\n", s);
1099*30594Ssam }
1100*30594Ssam 
1101*30594Ssam 
1102*30594Ssam private t_fp(n, s, si)	/* font position n now contains font s, intname si */
1103*30594Ssam int n;		/* position */
1104*30594Ssam char *s;	/* font (ditname) */
1105*30594Ssam char *si;	/* font (intname = number) */
1106*30594Ssam {
1107*30594Ssam     fontname[n].name = s;
1108*30594Ssam     fontname[n].number = atoi (si);
1109*30594Ssam }
1110*30594Ssam 
1111*30594Ssam private setfont(n)	/* set font to n */
1112*30594Ssam int n;
1113*30594Ssam {
1114*30594Ssam     FlushShow(1);
1115*30594Ssam 
1116*30594Ssam     if (n < 0 || n > NFONT) {
1117*30594Ssam 	fprintf(stderr,"%s: illegal font %d\n", prog,n);
1118*30594Ssam     }
1119*30594Ssam     if (font != n) {
1120*30594Ssam 	font = n;
1121*30594Ssam 	printf("%d f\n",font);
1122*30594Ssam     }
1123*30594Ssam     onspecial = 0;
1124*30594Ssam }
1125*30594Ssam 
1126*30594Ssam private drawline(dx, dy)	/* draw line from here to dx, dy */
1127*30594Ssam int dx, dy;
1128*30594Ssam {
1129*30594Ssam     FlushShow(0); MoveTo(); DoMove();
1130*30594Ssam     printf("%d %d Dl\n", dx, dy);
1131*30594Ssam     hpos += dx;
1132*30594Ssam     PSx = hpos * PSmag;
1133*30594Ssam     vpos += dy;
1134*30594Ssam     PSy = vpos * PSmag;
1135*30594Ssam }
1136*30594Ssam 
1137*30594Ssam private drawwig(s)	/* draw wiggly line */
1138*30594Ssam char *s;
1139*30594Ssam {
1140*30594Ssam     FlushShow(0); MoveTo(); DoMove();
1141*30594Ssam     printf("D~ %s D~~\n",s);
1142*30594Ssam }
1143*30594Ssam 
1144*30594Ssam private drawcirc(d)
1145*30594Ssam int d;
1146*30594Ssam {
1147*30594Ssam     FlushShow(0); MoveTo(); DoMove();
1148*30594Ssam     printf("%d Dc\n",d);
1149*30594Ssam }
1150*30594Ssam 
1151*30594Ssam private drawarc(dx1, dy1, dx2, dy2)
1152*30594Ssam int dx1, dy1, dx2, dy2;
1153*30594Ssam {
1154*30594Ssam     FlushShow(0); MoveTo(); DoMove();
1155*30594Ssam     printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2);
1156*30594Ssam     hpos += dx1 + dx2;
1157*30594Ssam     PSx = hpos * PSmag;
1158*30594Ssam     vpos += dy1 + dy2;
1159*30594Ssam     PSy = vpos * PSmag;
1160*30594Ssam }
1161*30594Ssam 
1162*30594Ssam private drawellip(a, b)
1163*30594Ssam int a, b;
1164*30594Ssam {
1165*30594Ssam     FlushShow(0);MoveTo();DoMove();
1166*30594Ssam     printf("%d %d De\n",a,b);
1167*30594Ssam }
1168*30594Ssam 
1169*30594Ssam private hmot(a)	/* relative horizontal motion */
1170*30594Ssam int a;
1171*30594Ssam {
1172*30594Ssam     register int aa;
1173*30594Ssam     aa = abs(a);
1174*30594Ssam     if ((aa < 8) || (aa > (10 * thisw)) || (a >= 100)
1175*30594Ssam     || ((thisw != 0) && (abs(thisw - a) > 4))) {
1176*30594Ssam 	FlushShow(1);
1177*30594Ssam     }
1178*30594Ssam     hpos += a;
1179*30594Ssam     if (lastcmd != CPUT) startx = hpos;
1180*30594Ssam }
1181*30594Ssam 
1182*30594Ssam private hgoto(a) /* absolute horizontal motion */
1183*30594Ssam int a;
1184*30594Ssam {
1185*30594Ssam     FlushShow(1);
1186*30594Ssam     startx = hpos = a;
1187*30594Ssam     thisw = 0;
1188*30594Ssam }
1189*30594Ssam 
1190*30594Ssam private vmot(a) /* relative vertical motion */
1191*30594Ssam int a;
1192*30594Ssam {
1193*30594Ssam     FlushShow(1);
1194*30594Ssam     vpos += a;
1195*30594Ssam     thisw = 0;
1196*30594Ssam }
1197*30594Ssam 
1198*30594Ssam private vgoto(a) /* absolute vertical motion */
1199*30594Ssam int a;
1200*30594Ssam {
1201*30594Ssam     FlushShow(1);
1202*30594Ssam     vpos = a;
1203*30594Ssam     thisw = 0;
1204*30594Ssam }
1205*30594Ssam 
1206*30594Ssam private showspecial(s,cc,wid)
1207*30594Ssam char *s;
1208*30594Ssam int cc;
1209*30594Ssam int wid;
1210*30594Ssam {
1211*30594Ssam     char *sp;
1212*30594Ssam 
1213*30594Ssam     FlushShow(0);
1214*30594Ssam     MoveTo();
1215*30594Ssam     DoMove();
1216*30594Ssam     putchar('(');
1217*30594Ssam     for (sp = s; *sp != '\0'; sp++) {
1218*30594Ssam 	if (needsescape(*sp)) {
1219*30594Ssam 	    putchar('\\');
1220*30594Ssam 	}
1221*30594Ssam 	putchar(*sp);
1222*30594Ssam     }
1223*30594Ssam     printf(")%d %d oc\n",cc,wid);
1224*30594Ssam }
1225*30594Ssam 
1226*30594Ssam private showchar(c)
1227*30594Ssam int c;
1228*30594Ssam {
1229*30594Ssam     if (showind == 0) {MoveTo();}
1230*30594Ssam     else if ((vpos * PSmag) != PSy) {
1231*30594Ssam 	FlushShow(0);
1232*30594Ssam 	MoveTo();
1233*30594Ssam     }
1234*30594Ssam     if (showind >= SHOWSIZE) FlushShow(0);
1235*30594Ssam     if (isascii(c) && isprint(c)) {
1236*30594Ssam 	switch (c) {
1237*30594Ssam 	    case '\\': case '(': case ')':
1238*30594Ssam 	        showbuf[showind++] = '\\';
1239*30594Ssam 		/* fall through */
1240*30594Ssam 
1241*30594Ssam 	    default:
1242*30594Ssam 		showbuf[showind++] = c;
1243*30594Ssam 	}
1244*30594Ssam     }
1245*30594Ssam     else {
1246*30594Ssam 	showbuf[showind++] = '\\';
1247*30594Ssam 	showbuf[showind++] = ((c>>6)&03) + '0';
1248*30594Ssam 	showbuf[showind++] = ((c>>3)&07) + '0';
1249*30594Ssam 	showbuf[showind++] = (c&07) + '0';
1250*30594Ssam     }
1251*30594Ssam     showbuf[showind] = '\0';
1252*30594Ssam     nshow++;
1253*30594Ssam }
1254*30594Ssam 
1255*30594Ssam private MoveTo() {
1256*30594Ssam     int x, y;
1257*30594Ssam     x = hpos * PSmag;
1258*30594Ssam     y = vpos * PSmag;
1259*30594Ssam 
1260*30594Ssam     if (x != PSx) {
1261*30594Ssam 	startx = savex = hpos;
1262*30594Ssam 	PSx = x;
1263*30594Ssam 	movepending |= XMOVE;
1264*30594Ssam     }
1265*30594Ssam     if (y != PSy) {
1266*30594Ssam 	savey = vpos;
1267*30594Ssam 	PSy = y;
1268*30594Ssam 	movepending |= YMOVE;
1269*30594Ssam     }
1270*30594Ssam }
1271*30594Ssam 
1272*30594Ssam private FlushMove() {
1273*30594Ssam     switch (movepending) {
1274*30594Ssam 	case NONE:
1275*30594Ssam 	    break;
1276*30594Ssam 	case XMOVE:
1277*30594Ssam 	    printf("%d",savex);
1278*30594Ssam 	    break;
1279*30594Ssam 	case YMOVE:
1280*30594Ssam 	    printf("%d",savey);
1281*30594Ssam 	    break;
1282*30594Ssam 	case XYMOVE:
1283*30594Ssam 	    printf("%d %d",savex,savey);
1284*30594Ssam 	    break;
1285*30594Ssam 	default:
1286*30594Ssam 	    fprintf(stderr,"%s: invalid move code %d\n",prog, movepending);
1287*30594Ssam 	    exit(2);
1288*30594Ssam     }
1289*30594Ssam }
1290*30594Ssam 
1291*30594Ssam private char *movecmds[] = {
1292*30594Ssam     "MX","MY","MXY"
1293*30594Ssam };
1294*30594Ssam 
1295*30594Ssam private DoMove() {
1296*30594Ssam     FlushMove();
1297*30594Ssam     if (movepending != NONE) {
1298*30594Ssam 	printf(" %s\n",movecmds[movepending-1]);
1299*30594Ssam 	movepending = NONE;
1300*30594Ssam     }
1301*30594Ssam }
1302*30594Ssam 
1303*30594Ssam private char showops[] = "SXYN";
1304*30594Ssam 
1305*30594Ssam private FlushShow(t) int t; {
1306*30594Ssam     long err, tlen;
1307*30594Ssam     float cerror;
1308*30594Ssam 
1309*30594Ssam     if (showind == 0) {thisw = 0; return;}
1310*30594Ssam     if (movepending != NONE) {
1311*30594Ssam 	FlushMove();
1312*30594Ssam     }
1313*30594Ssam     tlen = hpos - startx;
1314*30594Ssam     if (lastcmd == CPUT) tlen += thisw;
1315*30594Ssam     err = tlen * PSmag - PSshowlen;
1316*30594Ssam     if ((nshow != 1) && (abs(err) > ErrorTolerance)) {
1317*30594Ssam 	cerror = ((float) err) / ((nshow - 1) * PSmag);
1318*30594Ssam #ifdef DEBUG
1319*30594Ssam 	fprintf(stderr,"F%d lc %d thisw %d ",t,lastcmd,thisw);
1320*30594Ssam         fprintf(stderr,"x %ld h %ld tn %ld %ld ",
1321*30594Ssam 		startx, hpos, tlen*PSmag,PSshowlen);
1322*30594Ssam 	fprintf(stderr,"error %d %.4f %s\n",nshow,cerror,showbuf);
1323*30594Ssam 	fflush(stderr);
1324*30594Ssam #endif
1325*30594Ssam 	printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]);
1326*30594Ssam     }
1327*30594Ssam     else {
1328*30594Ssam 	printf("(%s)%c\n", showbuf, showops[movepending]);
1329*30594Ssam     }
1330*30594Ssam 
1331*30594Ssam     showind = 0;
1332*30594Ssam     nshow = 0;
1333*30594Ssam     showbuf[showind] = '\0';
1334*30594Ssam     PSx += PSshowlen;
1335*30594Ssam     PSshowlen = 0;
1336*30594Ssam     startx = hpos;
1337*30594Ssam     if (lastcmd == CPUT) startx += thisw;
1338*30594Ssam     thisw = 0;
1339*30594Ssam     movepending = NONE;
1340*30594Ssam }
1341