xref: /csrg-svn/local/transcript/src/psdit.c (revision 30595)
130594Ssam #ifndef lint
230594Ssam static char Notice[] = "Copyright (c) 1984, 1985 Adobe Systems Incorporated";
330594Ssam static char *RCSID="$Header: psdit.c,v 2.1 85/11/24 11:50:41 shore Rel $";
430594Ssam #endif
5*30595Ssam # define XMOD
630594Ssam /* psdit.c
730594Ssam  *
830594Ssam  * Copyright (c) 1984, 1985 Adobe Systems Incorporated
930594Ssam  *
1030594Ssam  * ditroff intermediate file to PostScript translator
1130594Ssam  *
1230594Ssam  * Original Version: Barry Hayes spring/summer 1984
1330594Ssam  * Edit History:
1430594Ssam  * Andrew Shore: Sat Nov 23 20:05:26 1985
1530594Ssam  * End Edit History.
1630594Ssam  *
1730594Ssam  * RCSLOG:
1830594Ssam  * $Log:	psdit.c,v $
1930594Ssam  * Revision 2.1  85/11/24  11:50:41  shore
2030594Ssam  * Product Release 2.0
2130594Ssam  *
2230594Ssam  * Revision 1.8  85/11/23  20:09:44  shore
2330594Ssam  * test for termination of included PostScript was bad
2430594Ssam  *
2530594Ssam  * Revision 1.7  85/11/21  14:23:56  shore
2630594Ssam  * added envget check for PSLIBDIR
2730594Ssam  *
2830594Ssam  * Revision 1.6  85/11/20  00:43:43  shore
2930594Ssam  * support for included PostScript
3030594Ssam  * big rework on FlushShow, word "breaks"
3130594Ssam  * removed FlushFont and made them instant
3230594Ssam  * Still no Gremlin support yet
3330594Ssam  *
3430594Ssam  * Revision 1.5  85/10/03  10:48:09  shore
3530594Ssam  * added FlushShow to xf fix !
3630594Ssam  *
3730594Ssam  * Revision 1.4  85/10/02  16:20:32  shore
3830594Ssam  * fixed xf bug
3930594Ssam  * mounting a font causes a font switch!
4030594Ssam  *
4130594Ssam  * Revision 1.3  85/07/09  13:10:20  shore
4230594Ssam  * added fclose on map file
4330594Ssam  *
4430594Ssam  * Revision 1.2  85/05/14  11:24:23  shore
4530594Ssam  * added flush to trailer
4630594Ssam  * fixed read bug when mounting fonts
4730594Ssam  *
4830594Ssam  *
4930594Ssam  */
5030594Ssam 
5130594Ssam /*
5230594Ssam output language from troff:
5330594Ssam all numbers are character strings
5430594Ssam 
5530594Ssam sn	size in points
5630594Ssam fn	font as number from 1-n
5730594Ssam cx	ascii character x
5830594Ssam Cxyz	funny char xyz. terminated by white space
5930594Ssam Hn	go to absolute horizontal position n
6030594Ssam Vn	go to absolute vertical position n (down is positive)
6130594Ssam hn	go n units horizontally (relative)
6230594Ssam vn	ditto vertically
6330594Ssam nnc	move right nn, then print c (exactly 2 digits!)
6430594Ssam 		(this wart is an optimization that shrinks output file size
6530594Ssam 		 about 35% and run-time about 15% while preserving ascii-ness)
6630594Ssam Dt ...\n	draw operation 't':
6730594Ssam 	Dl x y		line from here by x,y
6830594Ssam 	Dc d		circle of diameter d with left side here
6930594Ssam 	De x y		ellipse of axes x,y with left side here
7030594Ssam 	Da x y r	arc counter-clockwise by x,y of radius r
7130594Ssam 	D~ x y x y ...	wiggly line by x,y then x,y ...
7230594Ssam nb a	end of line (information only -- no action needed)
7330594Ssam 	a = space before line, a = after
7430594Ssam w	paddable word space -- no action needed
7530594Ssam pn	new page begins -- set v to 0
7630594Ssam {	push current environment (font info & location)
7730594Ssam }	pop a saved environment
7830594Ssam txxxx	print string xxxx using natural widths
7930594Ssam #...\n	comment
8030594Ssam x ...\n	device control functions:
8130594Ssam 	x i[nit]	init
8230594Ssam 	x T s		name of device is s
8330594Ssam 	x r[es] n h v	resolution is n/inch
8430594Ssam 			h = min horizontal motion, v = min vert
8530594Ssam 	x p[ause]	pause (can restart)
8630594Ssam 	x s[top]	stop -- done for ever
8730594Ssam 	x t[railer]	generate trailer
8830594Ssam 	x f[font] n s	font position n contains font s
8930594Ssam 	x H[eight] n	set character height to n
9030594Ssam 	x S[slant] n	set slant to N
9130594Ssam 
9230594Ssam Adobe Extension for included PostScript:
9330594Ssam %
9430594Ssam (raw postscript...)
9530594Ssam .\n
9630594Ssam 
9730594Ssam */
9830594Ssam 
9930594Ssam #include <stdio.h>
10030594Ssam #include <ctype.h>
10130594Ssam #include <signal.h>
10230594Ssam #include <pwd.h>
10330594Ssam #ifdef SYSV
10430594Ssam extern struct passwd *getpwuid();
10530594Ssam #endif
10630594Ssam #include "transcript.h"
10730594Ssam 
10830594Ssam #include "dev.h"
10930594Ssam 
11030594Ssam char *malloc();
11130594Ssam 
11230594Ssam #define	NFONT	10
11330594Ssam 
11430594Ssam /* DIT state consists of: */
11530594Ssam private int	hpos;		/* current horizontal position */
11630594Ssam private int	vpos;		/* current vertical position */
11730594Ssam private int	fontsize;	/* current font size */
11830594Ssam private int	fontheight;	/* current character height */
11930594Ssam private int	fontslant;	/* current font slant */
12030594Ssam private int	font;		/* current font */
12130594Ssam private int	resolution;	/* device resolution */
12230594Ssam private int	minhoriz;	/* minimum horizontal motion */
12330594Ssam private int	minvert;	/* minimum vertical motion */
12430594Ssam 
12530594Ssam private int	onspecial;
12630594Ssam private int	specfont;
12730594Ssam private int	prevfont;
12830594Ssam private int 	pfont;
12930594Ssam 
13030594Ssam /* {} push/pop stack */
13130594Ssam #define DSTACK 10
13230594Ssam private struct ditstack {
13330594Ssam     int hpos, vpos, fontsize, fontheight, fontslant, font;
13430594Ssam } ditstack[DSTACK];
13530594Ssam private int dlevel = 0;
13630594Ssam 
13730594Ssam #define ErrorTolerance 48
13830594Ssam #define PSWID 0x00000FFF
13930594Ssam #define ISPSPROC 0x000FF000
14030594Ssam 
14130594Ssam 
14230594Ssam /* PSscale is equivalent to (x * PSmag / 72000) + 0.5 */
14330594Ssam #define PSmag 16
14430594Ssam #define PSscale(x) (((x)+2250)/4500)
14530594Ssam 
14630594Ssam /* we maintain PS coords with PSmag times the precision */
14730594Ssam /* current PS state is: */
14830594Ssam 
14930594Ssam private int	PSx;		/* current horizontal position */
15030594Ssam private int	PSy;		/* current vertical position */
15130594Ssam private int	savex, savey;	/* position of start of current show string */
15230594Ssam 
15330594Ssam /* ps move types -- note that XMOVE|YMOVE == XYMOVE ! */
15430594Ssam #define NONE 0
15530594Ssam #define XMOVE 1
15630594Ssam #define YMOVE 2
15730594Ssam #define XYMOVE 3
15830594Ssam 
15930594Ssam private int movepending = NONE;
16030594Ssam 
16130594Ssam /* buffer string for show -- save up adjacent chars */
16230594Ssam #define SHOWSIZE 400
16330594Ssam private char showbuf[SHOWSIZE + 3]; /* extras are for quoting */
16430594Ssam private int showind = 0;	/* index into string of next available byte */
16530594Ssam private int PSshowlen = 0;	/* size in big units of buffered string */
16630594Ssam private int nshow = 0;		/* actual number of show chars in showbuf */
16730594Ssam private int startx;		/* troff starting pos of current string */
16830594Ssam private int thisw;
16930594Ssam 
17030594Ssam /* #define NONE 0 */
17130594Ssam #define HMOT 1
17230594Ssam #define VMOT 2
17330594Ssam #define CPUT 4
17430594Ssam #define BRK  8
17530594Ssam #define FNT  16
17630594Ssam private int lastcmd;
17730594Ssam 
17830594Ssam private int	output	= 0;	/* do we do output at all? */
17930594Ssam private int	nolist	= 0;	/* output page list if > 0 */
18030594Ssam private int	olist[20];	/* pairs of page numbers */
18130594Ssam private int	spage	= 9999;	/* stop every spage pages */
18230594Ssam private int	scount	= 0;
18330594Ssam private int	stopped = 0;
18430594Ssam private int	pageno = 0;
18530594Ssam private int	firstpage = TRUE;
18630594Ssam 
18730594Ssam private struct	dev	dev;
18830594Ssam private struct font *fontbase[NFONT+1];
18930594Ssam private short	*pstab;
19030594Ssam private int	dres;	/* resolution from DESC */
19130594Ssam private int	nsizes; /* number of point sizes from DESC */
19230594Ssam private int	nfonts; /* number of fonts from DESC */
19330594Ssam private int	smnt;	/* index of first special font */
19430594Ssam private int	nchtab;
19530594Ssam private char	*chname;
19630594Ssam private short	*chtab;
19730594Ssam private char	*fitab[NFONT+1];
19830594Ssam private char	*widthtab[NFONT+1];	/* widtab would be a better name */
19930594Ssam private char	*codetab[NFONT+1];	/* device codes */
20030594Ssam 
20130594Ssam private int     *pswidths[NFONT+1]; /* ps width tables */
20230594Ssam private int	fontdelta[NFONT+1]; /* nonzero if xf overwrites font i */
20330594Ssam 
20430594Ssam /* font position info: */
20530594Ssam private struct {
20630594Ssam 	char *name;
20730594Ssam 	int number;
20830594Ssam } fontname[NFONT+1];
20930594Ssam 
21030594Ssam #define	FATAL	1
21130594Ssam #define	BMASK	0377
21230594Ssam 
21330594Ssam #ifdef DEBUG
21430594Ssam int	dbg	= 0;
21530594Ssam int	fdbg = 0;
21630594Ssam #define debugp(xxx) {if(dbg != 0){dbg--; printf xxx ; VOIDC fflush(stdout);}}
21730594Ssam #else
21830594Ssam #define debugp(x)
21930594Ssam #endif
22030594Ssam 
22130594Ssam private FILE	*tf = stdout;	/* output file */
22230594Ssam private char devname[20] = "psc";
22330594Ssam 
22430594Ssam private char	*infilename = "stdin"; /* input file name */
22530594Ssam private char	*prologfile = PSDITPRO;
22630594Ssam private char	*ditdir = DitDir;
22730594Ssam 
22830594Ssam private char	*prog;		/* argv[0] - program name */
22930594Ssam 
23030594Ssam main(argc, argv)
23130594Ssam int argc;
23230594Ssam char *argv[];
23330594Ssam {
23430594Ssam     FILE *fp;
23530594Ssam     VOID done();
23630594Ssam 
23730594Ssam     prog = argv[0];
23830594Ssam     while (argc > 1 && argv[1][0] == '-') {
23930594Ssam 	switch (argv[1][1]) {
24030594Ssam 	    case 'f':
24130594Ssam 	    case 'F':
24230594Ssam 		if (argv[1][2])
24330594Ssam 		    ditdir = &argv[1][2];
24430594Ssam 		else {
24530594Ssam 		    ditdir = argv[2];
24630594Ssam 		    argv++;
24730594Ssam 		    argc--;
24830594Ssam 		}
24930594Ssam 		break;
25030594Ssam 	    case 'p':
25130594Ssam 		if (argv[1][2])
25230594Ssam 		    prologfile = &argv[1][2];
25330594Ssam 		break;
25430594Ssam 	    case 'o':
25530594Ssam 		outlist (&argv[1][2]);
25630594Ssam 		break;
25730594Ssam 	    case 'd':
25830594Ssam #ifdef DEBUG
25930594Ssam 		dbg = atoi (&argv[1][2]);
26030594Ssam 		if (dbg == 0)
26130594Ssam 		    dbg = 1;
26230594Ssam 		tf = stdout;
26330594Ssam #endif DEBUG
26430594Ssam 		break;
26530594Ssam 	    case 'b': 		/* ignore busy */
26630594Ssam 		break;
26730594Ssam 	    case 'w': 		/* ignore wait */
26830594Ssam 		break;
26930594Ssam 	    case 's':
27030594Ssam 		spage = atoi (&argv[1][2]);
27130594Ssam 		if (spage <= 0)
27230594Ssam 		    spage = 9999;
27330594Ssam 		break;
27430594Ssam 	}
27530594Ssam 	argc--;
27630594Ssam 	argv++;
27730594Ssam     }
27830594Ssam 
27930594Ssam     if (signal (SIGINT, done) == SIG_IGN) {
28030594Ssam 	signal (SIGINT, SIG_IGN);
28130594Ssam 	signal (SIGQUIT, SIG_IGN);
28230594Ssam 	signal (SIGHUP, SIG_IGN);
28330594Ssam     }
28430594Ssam     else {
28530594Ssam 	signal (SIGQUIT, done);
28630594Ssam 	signal (SIGHUP, done);
28730594Ssam     }
28830594Ssam     signal (SIGTERM, done);
28930594Ssam 
29030594Ssam     preface ();
29130594Ssam 
29230594Ssam     if (argc <= 1)
29330594Ssam 	conv (stdin);
29430594Ssam     else
29530594Ssam 	while (--argc > 0) {
29630594Ssam 	    if (strcmp (*++argv, "-") == 0)
29730594Ssam 		fp = stdin;
29830594Ssam 	    else if ((fp = fopen (*argv, "r")) == NULL) {
29930594Ssam 		fprintf (stderr, "%s: can't open %s\n", prog, *argv);
30030594Ssam 		pexit(prog,2);
30130594Ssam 	    }
30230594Ssam 	    infilename = *argv;
30330594Ssam 	    conv (fp);
30430594Ssam 	    VOIDC fclose (fp);
30530594Ssam 	}
30630594Ssam     done ();
30730594Ssam }
30830594Ssam 
30930594Ssam private outlist(s)	/* process list of page numbers to be printed */
31030594Ssam char *s;
31130594Ssam {
31230594Ssam     int     n1, n2, i;
31330594Ssam 
31430594Ssam     nolist = 0;
31530594Ssam     while (*s) {
31630594Ssam 	n1 = 0;
31730594Ssam 	if (isdigit (*s)) {
31830594Ssam 	    do {
31930594Ssam 		n1 = 10 * n1 + *s++ - '0';
32030594Ssam 	    }
32130594Ssam 	    while (isdigit (*s));
32230594Ssam 	}
32330594Ssam 	else {
32430594Ssam 	    n1 = -9999;
32530594Ssam 	}
32630594Ssam 	n2 = n1;
32730594Ssam 	if (*s == '-') {
32830594Ssam 	    s++;
32930594Ssam 	    n2 = 0;
33030594Ssam 	    if (isdigit (*s)) {
33130594Ssam 		do {
33230594Ssam 		    n2 = 10 * n2 + *s++ - '0';
33330594Ssam 		}
33430594Ssam 		while (isdigit (*s));
33530594Ssam 	    }
33630594Ssam 	    else {
33730594Ssam 		n2 = 9999;
33830594Ssam 	    }
33930594Ssam 	}
34030594Ssam 	olist[nolist++] = n1;
34130594Ssam 	olist[nolist++] = n2;
34230594Ssam 	if (*s != '\0') {
34330594Ssam 	    s++;
34430594Ssam 	}
34530594Ssam     }
34630594Ssam     olist[nolist] = 0;
34730594Ssam #ifdef DEBUG
34830594Ssam     if (dbg)
34930594Ssam 	for (i = 0; i < nolist; i += 2)
35030594Ssam 	    printf ("%3d %3d\n", olist[i], olist[i + 1]);
35130594Ssam #endif
35230594Ssam }
35330594Ssam 
35430594Ssam private conv(fp)	/* convert a file */
35530594Ssam register FILE *fp;
35630594Ssam {
35730594Ssam     register int    c, k;
35830594Ssam     int     m, n, n1, m1;
35930594Ssam     char    str[100], buf[300];
36030594Ssam 
36130594Ssam     while ((c = getc(fp)) != EOF) {
36230594Ssam 	switch (c) {
36330594Ssam 	    case '\n': case ' ': case '\0':
36430594Ssam 		break;
36530594Ssam 	    case '{': 		/* push down current environment */
36630594Ssam 		t_push();
36730594Ssam 		break;
36830594Ssam 	    case '}':
36930594Ssam 		t_pop();
37030594Ssam 		break;
37130594Ssam 	    case '0': case '1': case '2': case '3': case '4':
37230594Ssam 	    case '5': case '6': case '7': case '8': case '9':
37330594Ssam 	    /* two motion digits plus a character */
37430594Ssam 		hmot((c - '0') * 10 + getc (fp) - '0');
37530594Ssam 		lastcmd = HMOT;
37630594Ssam 		put1(getc(fp), (char *) 0);
37730594Ssam 		lastcmd = CPUT;
37830594Ssam 		break;
37930594Ssam 	    case 'c': 		/* single ascii character */
38030594Ssam 		put1(getc(fp), (char *) 0);
38130594Ssam 		lastcmd = CPUT;
38230594Ssam 		break;
38330594Ssam 	    case 'C':
38430594Ssam 		fscanf(fp, "%s", str);
38530594Ssam 		put1s(str);
38630594Ssam 		lastcmd = CPUT;
38730594Ssam 		break;
38830594Ssam 	    case 't': 		/* straight text */
38930594Ssam 		fgets(buf, sizeof (buf), fp);
39030594Ssam 		t_text (buf);
39130594Ssam 		lastcmd = CPUT;
39230594Ssam 		break;
39330594Ssam 	    case 'D': 		/* draw function */
39430594Ssam 		fgets(buf, sizeof (buf), fp);
39530594Ssam 		switch (buf[0]) {
39630594Ssam 		    case 'l': 	/* draw a line */
39730594Ssam 			sscanf (buf + 1, "%d %d", &n, &m);
39830594Ssam 			drawline (n, m);
39930594Ssam 			break;
40030594Ssam 		    case 'c': 	/* circle */
40130594Ssam 			sscanf (buf + 1, "%d", &n);
40230594Ssam 			drawcirc (n);
40330594Ssam 			break;
40430594Ssam 		    case 'e': 	/* ellipse */
40530594Ssam 			sscanf (buf + 1, "%d %d", &m, &n);
40630594Ssam 			drawellip (m, n);
40730594Ssam 			break;
40830594Ssam 		    case 'a': 	/* arc */
40930594Ssam 			sscanf (buf + 1, "%d %d %d %d", &n, &m, &n1, &m1);
41030594Ssam 			drawarc (n, m, n1, m1);
41130594Ssam 			break;
41230594Ssam 		    case '~': 	/* wiggly line */
41330594Ssam 			drawwig (buf + 1);
41430594Ssam 			break;
41530594Ssam 		    default:
41630594Ssam 			fprintf(stderr,"%s: unknown drawing function %s\n",
41730594Ssam 				prog,buf);
41830594Ssam 			exit(2);
41930594Ssam 			break;
42030594Ssam 		}
42130594Ssam 		break;
42230594Ssam 	    case 's':
42330594Ssam 		fscanf (fp, "%d", &n);
42430594Ssam 		t_size (n);
42530594Ssam 		lastcmd = FNT;
42630594Ssam 		break;
42730594Ssam 	    case 'f':
42830594Ssam 		fscanf (fp, "%s", str);
42930594Ssam 		setfont (t_font (str));
43030594Ssam 		lastcmd = FNT;
43130594Ssam 		break;
43230594Ssam 	    case 'H': 		/* absolute horizontal motion */
43330594Ssam 		while ((c = getc (fp)) == ' ');
43430594Ssam 		k = 0;
43530594Ssam 		do {
43630594Ssam 		    k = 10 * k + c - '0';
43730594Ssam 		} while (isdigit (c = getc (fp)));
43830594Ssam 		ungetc (c, fp);
43930594Ssam 		hgoto (k);
44030594Ssam 		lastcmd = HMOT;
44130594Ssam 		break;
44230594Ssam 	    case 'h': 		/* relative horizontal motion */
44330594Ssam 		while ((c = getc (fp)) == ' ');
44430594Ssam 		k = 0;
44530594Ssam 		do {
44630594Ssam 		    k = 10 * k + c - '0';
44730594Ssam 		} while (isdigit (c = getc (fp)));
44830594Ssam 		ungetc (c, fp);
44930594Ssam 		hmot (k);
45030594Ssam 		lastcmd = HMOT;
45130594Ssam 		break;
45230594Ssam 	    case 'w':
45330594Ssam 		FlushShow(1);
45430594Ssam 		lastcmd = BRK;
45530594Ssam 		break;
45630594Ssam 	    case 'V':
45730594Ssam 		fscanf (fp, "%d", &n);
45830594Ssam 		vgoto (n);
45930594Ssam 		lastcmd = VMOT;
46030594Ssam 		break;
46130594Ssam 	    case 'v':
46230594Ssam 		fscanf (fp, "%d", &n);
46330594Ssam 		vmot (n);
46430594Ssam 		lastcmd = VMOT;
46530594Ssam 		break;
46630594Ssam 	    case 'p': 		/* new page */
46730594Ssam 		fscanf (fp, "%d", &n);
46830594Ssam 		t_page (n);
46930594Ssam 		lastcmd = NONE;
47030594Ssam 		break;
47130594Ssam 	    case 'n': 		/* end of line -- ignore */
47230594Ssam 		while (getc (fp) != '\n');
47330594Ssam 		FlushShow(1);
47430594Ssam 		lastcmd = BRK;
47530594Ssam 		break;
47630594Ssam 	    case '#': 		/* comment */
47730594Ssam 	    /* maybe should pass through as a PS comment */
47830594Ssam 		while (getc (fp) != '\n');
47930594Ssam 		break;
48030594Ssam 	    case 'x': 		/* device control */
48130594Ssam 		devcntrl (fp);
48230594Ssam 		break;
48330594Ssam 	    case '%':		/* imbedded PostScript */
48430594Ssam 	    /* copy everything up to but NOT including a line */
48530594Ssam 	    /* with at single "." */
48630594Ssam 	    FlushShow(0);MoveTo();DoMove();
48730594Ssam 	    printf("\n%% included PostScript\n");
48830594Ssam 	    while (fgets(buf, sizeof buf, fp) != NULL) {
48930594Ssam 		if (strcmp(".\n",buf) == 0) break;
49030594Ssam 		fputs(buf,stdout);
49130594Ssam 	    }
49230594Ssam 	    break;
49330594Ssam 	    default:
49430594Ssam 		fprintf(stderr,"%s: bad input char \\%03o (%c)\n",prog,c,c);
49530594Ssam 		exit(2);
49630594Ssam 		done ();
49730594Ssam 	}
49830594Ssam     }
49930594Ssam }
50030594Ssam 
50130594Ssam 
50230594Ssam /* put in PostScript prolog */
50330594Ssam private preface()
50430594Ssam {
50530594Ssam     register    FILE *prolog;
50630594Ssam     char    hostname[256];
50730594Ssam     char tempfile[512];
50830594Ssam     struct passwd  *pswd;
50930594Ssam     long    clock;
51030594Ssam     char *libdir;
51130594Ssam 
51230594Ssam     fprintf (tf, "%%!%s\n", COMMENTVERSION);
51330594Ssam     pswd = getpwuid (getuid ());
51430594Ssam     VOIDC gethostname (hostname, sizeof hostname);
51530594Ssam     fprintf (tf, "%%%%Creator: %s:%s (%s)\n", hostname,
51630594Ssam 	    pswd->pw_name, pswd->pw_gecos);
51730594Ssam     fprintf (tf, "%%%%Title: %s (ditroff)\n", infilename);
51830594Ssam     fprintf (tf, "%%%%CreationDate: %s",
51930594Ssam 		(time (&clock), ctime (&clock)));
52030594Ssam     fprintf (tf, "%%%%EndComments\n");
52130594Ssam 
52230594Ssam     if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir;
52330594Ssam     mstrcat(tempfile, libdir, prologfile, sizeof tempfile);
52430594Ssam     if ((copyfile(tempfile, stdout)) != 0) {
52530594Ssam 	fprintf(stderr,"%s: can't copy prolog file %s\n",prog, tempfile);
52630594Ssam 	exit(2);
52730594Ssam     }
52830594Ssam     printf ("ditstart\n");
52930594Ssam }
53030594Ssam 
53130594Ssam private devcntrl(fp)	/* interpret device control functions */
53230594Ssam FILE *fp;
53330594Ssam {
53430594Ssam     char    str[20], str1[50], buf[50];
53530594Ssam     int     c, n, res, minh, minv;
53630594Ssam 
53730594Ssam     fscanf (fp, "%s", str);
53830594Ssam     switch (str[0]) {		/* crude for now */
53930594Ssam 	case 'i': 		/* initialize */
54030594Ssam 	    fileinit ();
54130594Ssam 	    t_init ();
54230594Ssam 	    lastcmd = NONE;
54330594Ssam 	    break;
54430594Ssam 	case 'T': 		/* device name */
54530594Ssam 	    fscanf (fp, "%s", devname);
54630594Ssam 	    if (strcmp (devname, "psc")) {
54730594Ssam 		fprintf(stderr,"%s: device not psc\n",prog);
54830594Ssam 		exit(2);
54930594Ssam 	    }
55030594Ssam 	    printf ("(%s)xT\n", devname);
55130594Ssam 	    lastcmd = NONE;
55230594Ssam 	    break;
55330594Ssam 	case 't': 		/* trailer */
55430594Ssam 	    t_trailer ();
55530594Ssam 	    lastcmd = NONE;
55630594Ssam 	    break;
55730594Ssam 	case 'p': 		/* pause -- can restart */
55830594Ssam 	    t_reset ('p');
55930594Ssam 	    lastcmd = NONE;
56030594Ssam 	    break;
56130594Ssam 	case 's': 		/* stop */
56230594Ssam 	    t_reset ('s');
56330594Ssam 	    lastcmd = NONE;
56430594Ssam 	    break;
56530594Ssam 	case 'r': 		/* resolution assumed when prepared */
56630594Ssam 	    fscanf (fp, "%d %d %d", &res, &minh, &minv);
56730594Ssam 	    t_res (res, minh, minv);
56830594Ssam 	    lastcmd = NONE;
56930594Ssam 	    break;
57030594Ssam 	case 'f': 		/* font used */
57130594Ssam 	    fscanf (fp, "%d %s", &n, str);
57230594Ssam 	    fgets (buf, sizeof buf, fp);/* in case theres a filename */
57330594Ssam 	    ungetc ('\n', fp);	/* fgets goes too far */
57430594Ssam 	    str1[0] = 0;	/* in case there is nothing to come in */
57530594Ssam 	    sscanf (buf, "%s", str1);
57630594Ssam 	    loadfont (n, str, str1);
57730594Ssam 	    lastcmd = FNT;
57830594Ssam 	    break;
57930594Ssam 	case 'H': 		/* char height */
58030594Ssam 	    fscanf (fp, "%d", &n);
58130594Ssam 	    t_charht (n);
58230594Ssam 	    lastcmd = FNT;
58330594Ssam 	    break;
58430594Ssam 	case 'S': 		/* slant */
58530594Ssam 	    fscanf (fp, "%d", &n);
58630594Ssam 	    t_slant (n);
58730594Ssam 	    lastcmd = FNT;
58830594Ssam 	    break;
589*30595Ssam #ifdef XMOD
590*30595Ssam 	case 'X': {		/* \X command from ditroff */
591*30595Ssam             int last;
592*30595Ssam 	    char largebuf[128];
593*30595Ssam 	    fscanf (fp, "%1s", str);
594*30595Ssam 	    switch (str[0]) {
595*30595Ssam 		case 'p' :
596*30595Ssam 		    FlushShow(0);MoveTo();DoMove();
597*30595Ssam 		    fgets(largebuf, sizeof(largebuf), fp);
598*30595Ssam 		    last = strlen(largebuf) - 1;
599*30595Ssam 		    if (last >= 0 && largebuf[last] == '\n') {
600*30595Ssam 			ungetc('\n', fp);
601*30595Ssam 			largebuf[last] = ' ';
602*30595Ssam 		    }
603*30595Ssam 		    fputs(largebuf, tf);
604*30595Ssam 		    putc('\n', tf);
605*30595Ssam 		    break;
606*30595Ssam 		case 'f' :
607*30595Ssam 		    FlushShow(0);MoveTo();DoMove();
608*30595Ssam 		    if (fscanf(fp, "%s", largebuf) == 1) {
609*30595Ssam 			char *nl = (char *) index(largebuf, '\n');
610*30595Ssam 			if (nl) *nl = '\0';
611*30595Ssam 			includefile(largebuf);
612*30595Ssam 		    } else
613*30595Ssam 			fprintf(stderr, "warning - include cmd w/o path.\n");
614*30595Ssam 		    break;
615*30595Ssam 	    }
616*30595Ssam 	}
617*30595Ssam 	break;
618*30595Ssam #endif
61930594Ssam     }
62030594Ssam     /* skip rest of input line */
62130594Ssam     while ((c = getc (fp)) != '\n') {if (c == EOF) break;};
62230594Ssam }
62330594Ssam 
624*30595Ssam #ifdef XMOD
625*30595Ssam includefile(filenm)
626*30595Ssam char *filenm; {
627*30595Ssam 
628*30595Ssam 	FILE *inf;
629*30595Ssam 	int ch, c1, c2, firstch = 0;
630*30595Ssam 
631*30595Ssam 	if (!(inf = fopen(filenm, "r"))) {
632*30595Ssam 		fprintf(stderr, "psdit: fopen(%s): ", filenm);
633*30595Ssam 		perror();
634*30595Ssam 		exit(1);
635*30595Ssam 	}
636*30595Ssam 	c1 = fgetc(inf); c2 = fgetc(inf);
637*30595Ssam 	if (c1 != '%' || c2 != '!')
638*30595Ssam 		fprintf(stderr, "psdit: %s not a postscript file.\n", filenm),
639*30595Ssam 		exit(1);
640*30595Ssam 
641*30595Ssam 	fputs("%!", tf);
642*30595Ssam 	while ((ch = fgetc(inf)) != EOF) {
643*30595Ssam 		fputc(ch, tf);
644*30595Ssam 		if (firstch && ch == '%') {
645*30595Ssam 			/* we have to double leading '%'s */
646*30595Ssam 			fputc('%', tf);
647*30595Ssam 		}
648*30595Ssam 		firstch = (ch == '\n');
649*30595Ssam 	}
650*30595Ssam 	fclose(inf);
651*30595Ssam }
652*30595Ssam #endif
65330594Ssam private fileinit()	/* read in font and code files, etc. */
65430594Ssam {
65530594Ssam     int     i, fin, nw;
65630594Ssam     char    *filebase, *p;
65730594Ssam     char    temp[60];
65830594Ssam     unsigned msize;
65930594Ssam 
66030594Ssam     /* open table for device,
66130594Ssam      * read in resolution, size info, font info,   etc. and set params */
66230594Ssam 
66330594Ssam     sprintf (temp, "%s/dev%s/DESC.out", ditdir, devname);
66430594Ssam     if ((fin = open (temp, 0)) < 0) {
66530594Ssam 	fprintf (stderr, "%s: can't open %s - %s\n", prog, devname, temp);
66630594Ssam 	pexit(prog,2);
66730594Ssam     }
66830594Ssam     if (read(fin,(char *)&dev, (int) sizeof(struct dev)) != sizeof(struct dev)) {
66930594Ssam 	fprintf (stderr, "%s: can't read %s\n", prog, temp);
67030594Ssam 	pexit(prog,2);
67130594Ssam     }
67230594Ssam     dres = dev.res;
67330594Ssam     nfonts = dev.nfonts;
67430594Ssam     nsizes = dev.nsizes;
67530594Ssam     nchtab = dev.nchtab;
67630594Ssam     /* enough room for whole file */
67730594Ssam     filebase = malloc ((unsigned) dev.filesize);
67830594Ssam     if (read (fin, filebase, dev.filesize) != dev.filesize) {
67930594Ssam 	fprintf (stderr, "%s: trouble reading %s\n", prog, temp);
68030594Ssam 	pexit(prog,2);
68130594Ssam     }
68230594Ssam     pstab = (short *) filebase;		/* point size table */
68330594Ssam     chtab = pstab + nsizes + 1;		/* char index table */
68430594Ssam     chname = (char *) (chtab + dev.nchtab);	/* char name table */
68530594Ssam     p = chname + dev.lchname;		/* end of char name table */
68630594Ssam     /* parse the preloaded font tables */
68730594Ssam     for (i = 1; i <= nfonts; i++) {
68830594Ssam 	fontdelta[i] = 0;
68930594Ssam 	fontbase[i] = (struct font *) p;
69030594Ssam 	nw = *p & BMASK;	/* number of width entries */
69130594Ssam 	if ((smnt == 0) && (fontbase[i]->specfont == 1))
69230594Ssam 	    smnt = i;		/* first special font */
69330594Ssam 	p += sizeof (struct font); /* skip header */
69430594Ssam 	widthtab[i] = p;		/* width table */
69530594Ssam 					/* kern table is next */
69630594Ssam 	codetab[i] = p + 2 * nw;	/* device codes */
69730594Ssam 	fitab[i] = p + 3 * nw;		/* font index table */
69830594Ssam 
69930594Ssam 	p += 3 * nw + dev.nchtab + (128 - 32);	/* next font */
70030594Ssam 	t_fp (i, fontbase[i]->namefont, fontbase[i]->intname);
70130594Ssam 	loadpswidths (i, fontbase[i]->namefont);
70230594Ssam 	sayload (i, fontbase[i]->namefont, (char *) 0);
70330594Ssam #ifdef DEBUG
70430594Ssam 	if (fdbg > 1)
70530594Ssam 	    fontprint (i);
70630594Ssam #endif
70730594Ssam     }
70830594Ssam     fontdelta[0] = 0;
70930594Ssam     msize = 3*255 + dev.nchtab + (128-32) + sizeof (struct font);
71030594Ssam     fontbase[0] = (struct font *) malloc(msize);
71130594Ssam     widthtab[0] = (char *) fontbase[0] + sizeof (struct font);
71230594Ssam     fontbase[0]->nwfont = 255;
71330594Ssam     close (fin);
71430594Ssam }
71530594Ssam 
71630594Ssam private loadpswidths(i,name)
71730594Ssam int i;
71830594Ssam char *name;
71930594Ssam {
72030594Ssam     char temp[60];
72130594Ssam     register FILE *auxin;
72230594Ssam     register int j;
72330594Ssam     int cc, wid, funny;
72430594Ssam 
72530594Ssam     sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name);
72630594Ssam     auxin = fopen(temp, "r");
72730594Ssam     /* allocate table */
72830594Ssam     if (pswidths[i] == NULL) {
72930594Ssam 	pswidths[i] = (int *) malloc(256 * (sizeof (int)));
73030594Ssam     }
73130594Ssam     /* initialize to not-there */
73230594Ssam     for (j = 0; j <= 255; pswidths[i][j++] = -1);
73330594Ssam     /* read them in */
73430594Ssam     while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) {
73530594Ssam 	pswidths[i][cc] = wid | (funny << 12);
73630594Ssam     }
73730594Ssam     VOIDC fclose(auxin);
73830594Ssam }
73930594Ssam 
74030594Ssam #ifdef DEBUG
74130594Ssam private fontprint(i)	/* debugging print of font i (0,...) */
74230594Ssam int i;
74330594Ssam {
74430594Ssam     int     j, n;
74530594Ssam     char   *p;
74630594Ssam 
74730594Ssam     printf ("font %d:\n", i);
74830594Ssam     p = (char *) fontbase[i];
74930594Ssam     n = fontbase[i]->nwfont & BMASK;
75030594Ssam     printf ("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
75130594Ssam 	    p, n, fontbase[i]->specfont,
75230594Ssam 	    fontbase[i]->namefont, widthtab[i], fitab[i]);
75330594Ssam     printf ("widths:\n");
75430594Ssam     for (j = 0; j <= n; j++) {
75530594Ssam 	printf (" %2d", widthtab[i][j] & BMASK);
75630594Ssam 	if (j % 20 == 19)
75730594Ssam 	    printf ("\n");
75830594Ssam     }
75930594Ssam     printf ("\ncodetab:\n");
76030594Ssam     for (j = 0; j <= n; j++) {
76130594Ssam 	printf (" %2d", codetab[i][j] & BMASK);
76230594Ssam 	if (j % 20 == 19)
76330594Ssam 	    printf ("\n");
76430594Ssam     }
76530594Ssam     printf ("\nfitab:\n");
76630594Ssam     for (j = 0; j <= dev.nchtab + 128 - 32; j++) {
76730594Ssam 	printf (" %2d", fitab[i][j] & BMASK);
76830594Ssam 	if (j % 20 == 19)
76930594Ssam 	    printf ("\n");
77030594Ssam     }
77130594Ssam     printf ("\n");
77230594Ssam }
77330594Ssam #endif
77430594Ssam 
77530594Ssam private loadfont(n, s, s1) /* load font info for font s on position n */
77630594Ssam int n;
77730594Ssam char *s, *s1;
77830594Ssam {
77930594Ssam     char    temp[60];
78030594Ssam     int     fin, nw, norig;
78130594Ssam     int     bcount;
78230594Ssam 
78330594Ssam     if (n < 0 || n > NFONT) {
78430594Ssam 	fprintf(stderr,"%s: illegal fp command %d %s\n", prog, n, s);
78530594Ssam 	exit(2);
78630594Ssam     }
78730594Ssam     if (strcmp(s, fontbase[n]->namefont) == 0) return;
78830594Ssam     if (fontbase[n]->namefont != 0) {
78930594Ssam 	fontdelta[n] = 1;
79030594Ssam     }
79130594Ssam     if (s1 == NULL || s1[0] == '\0') {
79230594Ssam 	sprintf (temp, "%s/dev%s/%s.out", ditdir, devname, s);
79330594Ssam     }
79430594Ssam     else {
79530594Ssam 	sprintf (temp, "%s/%s.out", s1, s);
79630594Ssam     }
79730594Ssam     if ((fin = open (temp, 0)) < 0) {
79830594Ssam 	fprintf(stderr,"%s: can't open font table %s\n", prog, temp);
79930594Ssam 	pexit(prog,2);
80030594Ssam     }
80130594Ssam     norig = fontbase[n]->nwfont & BMASK;
80230594Ssam     bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font);
80330594Ssam     VOIDC read (fin, (char *)fontbase[n], bcount);
80430594Ssam     if ((fontbase[n]->nwfont & BMASK) > norig) {
80530594Ssam 	fprintf(stderr,"%s: Font %s too big for position %d\n", prog, s, n);
80630594Ssam 	exit(2);
80730594Ssam     }
80830594Ssam     close (fin);
80930594Ssam     nw = fontbase[n]->nwfont & BMASK;
81030594Ssam     widthtab[n] = (char *) fontbase[n] + sizeof (struct font);
81130594Ssam     codetab[n] = (char *) widthtab[n] + 2 * nw;
81230594Ssam     fitab[n] = (char *) widthtab[n] + 3 * nw;
81330594Ssam     t_fp (n, fontbase[n]->namefont, fontbase[n]->intname);
81430594Ssam     loadpswidths (n, fontbase[n]->namefont);
81530594Ssam     sayload (n, s, s1);
81630594Ssam     fontbase[n]->nwfont = norig; /* so can later use full original size */
81730594Ssam #ifdef DEBUG
81830594Ssam     if (fdbg > 1)
81930594Ssam 	fontprint (n);
82030594Ssam #endif
82130594Ssam }
82230594Ssam 
82330594Ssam private sayload(n, s, s1)	/* position n contains font s (internal s1) */
82430594Ssam int n;
82530594Ssam char *s, *s1;
82630594Ssam {
82730594Ssam     char    pass[60];
82830594Ssam     FILE    *ptrfile;
82930594Ssam     char    Adobefont[60];
83030594Ssam 
83130594Ssam     if (s1 == NULL || s1[0] == '\0') {
83230594Ssam 	sprintf (pass, "%s/dev%s/%s.map", ditdir, devname, s);
83330594Ssam     }
83430594Ssam     else {
83530594Ssam 	sprintf (pass, "%s/%s.map", s1, s);
83630594Ssam     }
83730594Ssam 
83830594Ssam     if ((ptrfile = fopen (pass, "r")) == NULL) {
83930594Ssam 	fprintf(stderr,"%s: can't open font map file %s\n", prog, pass);
84030594Ssam 	pexit(prog,2);
84130594Ssam     }
84230594Ssam 
84330594Ssam     fscanf (ptrfile, "%s", Adobefont);
84430594Ssam     FlushShow(0);
84530594Ssam     printf ("%d(%s)xf %d f\n", n, Adobefont, n);
84630594Ssam     font = n;
84730594Ssam     VOIDC fclose(ptrfile);
84830594Ssam }
84930594Ssam 
85030594Ssam private VOID done()
85130594Ssam {
85230594Ssam     if (tf == NULL)
85330594Ssam 	exit (1);
85430594Ssam     t_reset ('s');
85530594Ssam     exit (0);
85630594Ssam }
85730594Ssam 
85830594Ssam private t_init()	/* "x i" - initialize device */
85930594Ssam {
86030594Ssam     movepending = NONE;
86130594Ssam     savex = savey = 0;
86230594Ssam 
86330594Ssam     t_size (10);		/* start somewhere */
86430594Ssam     t_slant (0);
86530594Ssam     setfont (1);		/* set font */
86630594Ssam     printf("xi\n");
86730594Ssam     printf("%%%%EndProlog\n");
86830594Ssam }
86930594Ssam 
87030594Ssam private t_push()	/* begin a new block */
87130594Ssam {
87230594Ssam     FlushShow(1);MoveTo();DoMove();
87330594Ssam     if (dlevel == DSTACK) {
87430594Ssam 	fprintf(stderr,"%s: ditroff push/pop overflow!\n",prog);
87530594Ssam 	exit(2);
87630594Ssam     }
87730594Ssam     ditstack[dlevel].hpos = hpos;
87830594Ssam     ditstack[dlevel].vpos = vpos;
87930594Ssam     ditstack[dlevel].fontsize = fontsize;
88030594Ssam     ditstack[dlevel].fontheight = fontheight;
88130594Ssam     ditstack[dlevel].fontslant = fontslant;
88230594Ssam     ditstack[dlevel].font = font;
88330594Ssam     dlevel++;
88430594Ssam     printf ("\nditpush\n");
88530594Ssam }
88630594Ssam 
88730594Ssam private t_pop()	/* pop to previous state */
88830594Ssam {
88930594Ssam     FlushShow(1);MoveTo();DoMove();
89030594Ssam     if (dlevel == 0) {
89130594Ssam 	fprintf(stderr,"%s: ditroff push/pop underflow!\n",prog);
89230594Ssam 	exit(2);
89330594Ssam     }
89430594Ssam     dlevel--;
89530594Ssam     hpos = ditstack[dlevel].hpos;
89630594Ssam     vpos = ditstack[dlevel].vpos;
89730594Ssam     fontsize = ditstack[dlevel].fontsize;
89830594Ssam     fontheight = ditstack[dlevel].fontheight;
89930594Ssam     fontslant = ditstack[dlevel].fontslant;
90030594Ssam     font = ditstack[dlevel].font;
90130594Ssam     printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font);
90230594Ssam     startx = savex = hpos;
90330594Ssam     savey = vpos;
90430594Ssam     PSx = hpos * PSmag;
90530594Ssam     PSy = vpos * PSmag;
90630594Ssam     printf("%d %d MXY\n",savex,savey);
90730594Ssam     movepending = NONE;
90830594Ssam     printf("\nditpop\n");
90930594Ssam }
91030594Ssam 
91130594Ssam private t_page(n)	/* do whatever new page functions */
91230594Ssam {
91330594Ssam     int     i;
91430594Ssam 
91530594Ssam     if (output) {
91630594Ssam 	if (++scount >= spage) {
91730594Ssam 	    t_reset ('p');
91830594Ssam 	    scount = 0;
91930594Ssam 	}
92030594Ssam     }
92130594Ssam     output = 1;
92230594Ssam     FlushShow(0);
92330594Ssam     if (!firstpage) {
92430594Ssam 	printf("\n%d p",n);
92530594Ssam     }
92630594Ssam     firstpage = FALSE;
92730594Ssam     printf ("\n%%%%Page: %d %d\n", n, ++pageno, n);
92830594Ssam     for (i = 0; i <= nfonts; i++) {
92930594Ssam 	if (fontdelta[i] != 0) {
93030594Ssam 	    sayload (i, fontname[i].name, (char *) 0);
93130594Ssam 	}
93230594Ssam     }
93330594Ssam     vpos = 0;
93430594Ssam     PSy = 0;
93530594Ssam     printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font);
93630594Ssam     if (nolist == 0)
93730594Ssam 	return;
93830594Ssam     output = 0;
93930594Ssam     for (i = 0; i < nolist; i += 2)
94030594Ssam 	if (n >= olist[i] && n <= olist[i + 1]) {
94130594Ssam 	    output = 1;
94230594Ssam 	    break;
94330594Ssam 	}
94430594Ssam }
94530594Ssam 
94630594Ssam private t_size(n)	/* convert integer to internal size number*/
94730594Ssam int n;
94830594Ssam {
94930594Ssam     FlushShow(1);
95030594Ssam     if (fontsize != n) {
95130594Ssam 	fontsize = n;
952*30595Ssam #ifdef XMOD
953*30595Ssam 	fontheight = n;
954*30595Ssam #endif
95530594Ssam 	printf("%d s\n",fontsize);
95630594Ssam     }
95730594Ssam }
95830594Ssam 
95930594Ssam private t_charht(n)	/* set character height to n */
96030594Ssam int n;
96130594Ssam {
96230594Ssam     FlushShow(1);
96330594Ssam     if (fontheight != n) {
96430594Ssam 	fontheight = n;
96530594Ssam 	printf("%d xH\n",fontheight);
96630594Ssam     }
96730594Ssam }
96830594Ssam 
96930594Ssam private t_slant(n)	/* set slant to n */
97030594Ssam int n;
97130594Ssam {
97230594Ssam     FlushShow(1);
97330594Ssam     if (fontslant != n) {
97430594Ssam 	fontslant = n;
97530594Ssam 	printf("%d xS\n",fontslant);
97630594Ssam     }
97730594Ssam }
97830594Ssam 
97930594Ssam private t_font(s)	/* convert string to internal font number */
98030594Ssam char *s;
98130594Ssam {
98230594Ssam     int     n;
98330594Ssam 
98430594Ssam     n = atoi (s);
98530594Ssam     if (n < 0 || n > nfonts) n = 1;
98630594Ssam     return (n);
98730594Ssam }
98830594Ssam 
98930594Ssam private t_text(s)	/* print string s as text??? */
99030594Ssam char *s;
99130594Ssam {
99230594Ssam 	fprintf(stderr,"%s: ditroff t <%s> unimplemented!\n",prog,s);
99330594Ssam }
99430594Ssam 
99530594Ssam private t_reset(c)
99630594Ssam {
99730594Ssam     output = 1;			/* by God */
99830594Ssam     if (c == 'p') {
99930594Ssam 	printf ("\nxp\n");
100030594Ssam     }
100130594Ssam     else {
100230594Ssam 	if (!stopped)
100330594Ssam 	    printf ("\nxs\n");
100430594Ssam 	stopped = 1;
100530594Ssam     }
100630594Ssam     fflush (tf);
100730594Ssam }
100830594Ssam 
100930594Ssam private t_res(res, minh, minv)
101030594Ssam int res, minh, minv;
101130594Ssam {
101230594Ssam     resolution = res;
101330594Ssam     minhoriz = minh;
101430594Ssam     minvert = minv;
101530594Ssam     printf ("%d %d %d xr\n", res, minh, minv);
101630594Ssam }
101730594Ssam 
101830594Ssam private t_trailer()
101930594Ssam {
102030594Ssam     FlushShow(0);
102130594Ssam     printf("\n%d p",pageno);
102230594Ssam     printf("\n%%%%Trailer\n");
102330594Ssam     printf("xt\n");
102430594Ssam }
102530594Ssam 
102630594Ssam private put1s(s)	/* s is a funny char name */
102730594Ssam char *s;
102830594Ssam {
102930594Ssam     int     i;
103030594Ssam 
103130594Ssam     if (!output) return;
103230594Ssam     debugp(("%s ", s));
103330594Ssam 
103430594Ssam     /* search for s in the funny char name table */
103530594Ssam     for (i = 0; i < nchtab; i++) {
103630594Ssam 	if (strcmp(&chname[chtab[i]], s) == 0) break;
103730594Ssam     }
103830594Ssam 
103930594Ssam     if (i < nchtab) {
104030594Ssam 	put1(i + 128, s);
104130594Ssam     }
104230594Ssam     else {
104330594Ssam 	debugp(("not found "));
104430594Ssam 	putnf (0, s);
104530594Ssam     }
104630594Ssam }
104730594Ssam 
104830594Ssam #define needsescape(c) ((c=='\\') || (c=='(') || (c==')'))
104930594Ssam 
105030594Ssam private put1(c, s)	/* output char c */
105130594Ssam int c;
105230594Ssam char *s;
105330594Ssam {
105430594Ssam     char *pw;
105530594Ssam     register char *p;
105630594Ssam     register int i, k;
105730594Ssam     register int cc;
105830594Ssam     int ofont, code;
105930594Ssam     int psinfo, pswid, tw;
106030594Ssam 
106130594Ssam     if (!output) return;
106230594Ssam     if (c == 32) {
106330594Ssam 	thisw = 0;
106430594Ssam 	FlushShow(0);
106530594Ssam 	return;
106630594Ssam     }
106730594Ssam     if (c < 32) {
106830594Ssam 	debugp(("non-exist 0%o\n",c));
106930594Ssam 	return;
107030594Ssam     }
107130594Ssam 
107230594Ssam     c -= 32;	/* offset char code */
107330594Ssam     k = ofont = pfont = font;
107430594Ssam     if (onspecial) pfont = prevfont;
107530594Ssam 
107630594Ssam     if ((i = (fitab[pfont][c] & BMASK)) != 0) {/* char on this font */
107730594Ssam 	p = codetab[pfont];
107830594Ssam 	pw = widthtab[pfont];
107930594Ssam 	if (onspecial) {
108030594Ssam 	    setfont(prevfont);
108130594Ssam 	    thisw = 0;
108230594Ssam 	    onspecial = 0;
108330594Ssam 	}
108430594Ssam     }
108530594Ssam     else if (smnt > 0) {	/* on special (we hope) */
108630594Ssam 	for (k = smnt; k <= nfonts; k += 1)
108730594Ssam 	    if ((i = (fitab[k][c] & BMASK)) != 0) {
108830594Ssam 		p = codetab[k];
108930594Ssam 		pw = widthtab[k];
109030594Ssam 		prevfont = pfont;
109130594Ssam 		if (onspecial && (k == specfont)) break;
109230594Ssam 		setfont (k);
109330594Ssam 		thisw = 0;
109430594Ssam 		onspecial = 1;
109530594Ssam 		specfont = k;
109630594Ssam 		break;
109730594Ssam 	    }
109830594Ssam     }
109930594Ssam     if ((i == 0) || (k > nfonts) || ((code = p[i] & BMASK) == 0)) {
110030594Ssam 	debugp(("not found 0%o\n", c+32));
110130594Ssam 	putnf (c + 32, s);
110230594Ssam 	return;
110330594Ssam     }
110430594Ssam     /* when we get here,
110530594Ssam      *  c == biased character code
110630594Ssam      *	k == font number
110730594Ssam      *  i == index into codetab and widthtab for this character
110830594Ssam      *  p == codetab for this font
110930594Ssam      *  pw == width tab for this font
111030594Ssam      *  code == character code for this char
111130594Ssam      */
111230594Ssam 
111330594Ssam     cc = c + 32;
111430594Ssam     debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n",
111530594Ssam     		cc, code));
111630594Ssam     psinfo = pswidths[font][code];	/* PS specific char info */
111730594Ssam     pswid = psinfo & PSWID;		/* PS character width */
111830594Ssam     thisw = pw[i] & BMASK;		/* troff char width */
111930594Ssam     tw = thisw = (thisw * fontsize + dev.unitwidth/2) / dev.unitwidth;
112030594Ssam 
112130594Ssam     if ((psinfo & ISPSPROC) && (psinfo != -1)) {
112230594Ssam 	/* character is implemented by a PostScript proc */
112330594Ssam 	showspecial(s, code, pswid);
112430594Ssam 	if (pswid > 0) {
112530594Ssam 	    PSx += PSscale(pswid * fontsize * dres);
112630594Ssam 	}
112730594Ssam 	thisw = 0;
112830594Ssam     }
112930594Ssam     else {
113030594Ssam 	showchar(code);
113130594Ssam 	if (pswid > 0) {
113230594Ssam 	    PSshowlen += PSscale(pswid * fontsize * dres);
113330594Ssam 	}
113430594Ssam     }
113530594Ssam 
113630594Ssam /*
113730594Ssam     if (font != ofont) {
113830594Ssam 	setfont(ofont);
113930594Ssam 	startx = hpos + tw;
114030594Ssam 	thisw = 0;
114130594Ssam 	lastcmd = FNT;
114230594Ssam     }
114330594Ssam */
114430594Ssam     debugp(("...width (%d)\n", pw[i]&BMASK));
114530594Ssam }
114630594Ssam 
114730594Ssam 
114830594Ssam private putnf(c, s)	/* note that a character wasnt found */
114930594Ssam int c;
115030594Ssam char *s;
115130594Ssam {
115230594Ssam 
115330594Ssam     FlushShow(0);
115430594Ssam     thisw = 0;
115530594Ssam     if ((s == NULL) || (*s == '\0')) printf("(\%3o)cb\n", c);
115630594Ssam     else if ((strcmp(s, "\\|") == 0) || (strcmp(s, "\\^") == 0)
115730594Ssam     || (strcmp (s, "\\&") == 0))
115830594Ssam 	return;
115930594Ssam     else
116030594Ssam 	printf("(%s)cb\n", s);
116130594Ssam }
116230594Ssam 
116330594Ssam 
116430594Ssam private t_fp(n, s, si)	/* font position n now contains font s, intname si */
116530594Ssam int n;		/* position */
116630594Ssam char *s;	/* font (ditname) */
116730594Ssam char *si;	/* font (intname = number) */
116830594Ssam {
116930594Ssam     fontname[n].name = s;
117030594Ssam     fontname[n].number = atoi (si);
117130594Ssam }
117230594Ssam 
117330594Ssam private setfont(n)	/* set font to n */
117430594Ssam int n;
117530594Ssam {
117630594Ssam     FlushShow(1);
117730594Ssam 
117830594Ssam     if (n < 0 || n > NFONT) {
117930594Ssam 	fprintf(stderr,"%s: illegal font %d\n", prog,n);
118030594Ssam     }
118130594Ssam     if (font != n) {
118230594Ssam 	font = n;
118330594Ssam 	printf("%d f\n",font);
118430594Ssam     }
118530594Ssam     onspecial = 0;
118630594Ssam }
118730594Ssam 
118830594Ssam private drawline(dx, dy)	/* draw line from here to dx, dy */
118930594Ssam int dx, dy;
119030594Ssam {
119130594Ssam     FlushShow(0); MoveTo(); DoMove();
119230594Ssam     printf("%d %d Dl\n", dx, dy);
119330594Ssam     hpos += dx;
119430594Ssam     PSx = hpos * PSmag;
119530594Ssam     vpos += dy;
119630594Ssam     PSy = vpos * PSmag;
119730594Ssam }
119830594Ssam 
119930594Ssam private drawwig(s)	/* draw wiggly line */
120030594Ssam char *s;
120130594Ssam {
120230594Ssam     FlushShow(0); MoveTo(); DoMove();
120330594Ssam     printf("D~ %s D~~\n",s);
120430594Ssam }
120530594Ssam 
120630594Ssam private drawcirc(d)
120730594Ssam int d;
120830594Ssam {
120930594Ssam     FlushShow(0); MoveTo(); DoMove();
121030594Ssam     printf("%d Dc\n",d);
121130594Ssam }
121230594Ssam 
121330594Ssam private drawarc(dx1, dy1, dx2, dy2)
121430594Ssam int dx1, dy1, dx2, dy2;
121530594Ssam {
121630594Ssam     FlushShow(0); MoveTo(); DoMove();
121730594Ssam     printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2);
121830594Ssam     hpos += dx1 + dx2;
121930594Ssam     PSx = hpos * PSmag;
122030594Ssam     vpos += dy1 + dy2;
122130594Ssam     PSy = vpos * PSmag;
122230594Ssam }
122330594Ssam 
122430594Ssam private drawellip(a, b)
122530594Ssam int a, b;
122630594Ssam {
122730594Ssam     FlushShow(0);MoveTo();DoMove();
122830594Ssam     printf("%d %d De\n",a,b);
122930594Ssam }
123030594Ssam 
123130594Ssam private hmot(a)	/* relative horizontal motion */
123230594Ssam int a;
123330594Ssam {
123430594Ssam     register int aa;
123530594Ssam     aa = abs(a);
123630594Ssam     if ((aa < 8) || (aa > (10 * thisw)) || (a >= 100)
123730594Ssam     || ((thisw != 0) && (abs(thisw - a) > 4))) {
123830594Ssam 	FlushShow(1);
123930594Ssam     }
124030594Ssam     hpos += a;
124130594Ssam     if (lastcmd != CPUT) startx = hpos;
124230594Ssam }
124330594Ssam 
124430594Ssam private hgoto(a) /* absolute horizontal motion */
124530594Ssam int a;
124630594Ssam {
124730594Ssam     FlushShow(1);
124830594Ssam     startx = hpos = a;
124930594Ssam     thisw = 0;
125030594Ssam }
125130594Ssam 
125230594Ssam private vmot(a) /* relative vertical motion */
125330594Ssam int a;
125430594Ssam {
125530594Ssam     FlushShow(1);
125630594Ssam     vpos += a;
125730594Ssam     thisw = 0;
125830594Ssam }
125930594Ssam 
126030594Ssam private vgoto(a) /* absolute vertical motion */
126130594Ssam int a;
126230594Ssam {
126330594Ssam     FlushShow(1);
126430594Ssam     vpos = a;
126530594Ssam     thisw = 0;
126630594Ssam }
126730594Ssam 
126830594Ssam private showspecial(s,cc,wid)
126930594Ssam char *s;
127030594Ssam int cc;
127130594Ssam int wid;
127230594Ssam {
127330594Ssam     char *sp;
127430594Ssam 
127530594Ssam     FlushShow(0);
127630594Ssam     MoveTo();
127730594Ssam     DoMove();
127830594Ssam     putchar('(');
127930594Ssam     for (sp = s; *sp != '\0'; sp++) {
128030594Ssam 	if (needsescape(*sp)) {
128130594Ssam 	    putchar('\\');
128230594Ssam 	}
128330594Ssam 	putchar(*sp);
128430594Ssam     }
128530594Ssam     printf(")%d %d oc\n",cc,wid);
128630594Ssam }
128730594Ssam 
128830594Ssam private showchar(c)
128930594Ssam int c;
129030594Ssam {
129130594Ssam     if (showind == 0) {MoveTo();}
129230594Ssam     else if ((vpos * PSmag) != PSy) {
129330594Ssam 	FlushShow(0);
129430594Ssam 	MoveTo();
129530594Ssam     }
129630594Ssam     if (showind >= SHOWSIZE) FlushShow(0);
129730594Ssam     if (isascii(c) && isprint(c)) {
129830594Ssam 	switch (c) {
129930594Ssam 	    case '\\': case '(': case ')':
130030594Ssam 	        showbuf[showind++] = '\\';
130130594Ssam 		/* fall through */
130230594Ssam 
130330594Ssam 	    default:
130430594Ssam 		showbuf[showind++] = c;
130530594Ssam 	}
130630594Ssam     }
130730594Ssam     else {
130830594Ssam 	showbuf[showind++] = '\\';
130930594Ssam 	showbuf[showind++] = ((c>>6)&03) + '0';
131030594Ssam 	showbuf[showind++] = ((c>>3)&07) + '0';
131130594Ssam 	showbuf[showind++] = (c&07) + '0';
131230594Ssam     }
131330594Ssam     showbuf[showind] = '\0';
131430594Ssam     nshow++;
131530594Ssam }
131630594Ssam 
131730594Ssam private MoveTo() {
131830594Ssam     int x, y;
131930594Ssam     x = hpos * PSmag;
132030594Ssam     y = vpos * PSmag;
132130594Ssam 
132230594Ssam     if (x != PSx) {
132330594Ssam 	startx = savex = hpos;
132430594Ssam 	PSx = x;
132530594Ssam 	movepending |= XMOVE;
132630594Ssam     }
132730594Ssam     if (y != PSy) {
132830594Ssam 	savey = vpos;
132930594Ssam 	PSy = y;
133030594Ssam 	movepending |= YMOVE;
133130594Ssam     }
133230594Ssam }
133330594Ssam 
133430594Ssam private FlushMove() {
133530594Ssam     switch (movepending) {
133630594Ssam 	case NONE:
133730594Ssam 	    break;
133830594Ssam 	case XMOVE:
133930594Ssam 	    printf("%d",savex);
134030594Ssam 	    break;
134130594Ssam 	case YMOVE:
134230594Ssam 	    printf("%d",savey);
134330594Ssam 	    break;
134430594Ssam 	case XYMOVE:
134530594Ssam 	    printf("%d %d",savex,savey);
134630594Ssam 	    break;
134730594Ssam 	default:
134830594Ssam 	    fprintf(stderr,"%s: invalid move code %d\n",prog, movepending);
134930594Ssam 	    exit(2);
135030594Ssam     }
135130594Ssam }
135230594Ssam 
135330594Ssam private char *movecmds[] = {
135430594Ssam     "MX","MY","MXY"
135530594Ssam };
135630594Ssam 
135730594Ssam private DoMove() {
135830594Ssam     FlushMove();
135930594Ssam     if (movepending != NONE) {
136030594Ssam 	printf(" %s\n",movecmds[movepending-1]);
136130594Ssam 	movepending = NONE;
136230594Ssam     }
136330594Ssam }
136430594Ssam 
136530594Ssam private char showops[] = "SXYN";
136630594Ssam 
136730594Ssam private FlushShow(t) int t; {
136830594Ssam     long err, tlen;
136930594Ssam     float cerror;
137030594Ssam 
137130594Ssam     if (showind == 0) {thisw = 0; return;}
137230594Ssam     if (movepending != NONE) {
137330594Ssam 	FlushMove();
137430594Ssam     }
137530594Ssam     tlen = hpos - startx;
137630594Ssam     if (lastcmd == CPUT) tlen += thisw;
137730594Ssam     err = tlen * PSmag - PSshowlen;
137830594Ssam     if ((nshow != 1) && (abs(err) > ErrorTolerance)) {
137930594Ssam 	cerror = ((float) err) / ((nshow - 1) * PSmag);
138030594Ssam #ifdef DEBUG
138130594Ssam 	fprintf(stderr,"F%d lc %d thisw %d ",t,lastcmd,thisw);
138230594Ssam         fprintf(stderr,"x %ld h %ld tn %ld %ld ",
138330594Ssam 		startx, hpos, tlen*PSmag,PSshowlen);
138430594Ssam 	fprintf(stderr,"error %d %.4f %s\n",nshow,cerror,showbuf);
138530594Ssam 	fflush(stderr);
138630594Ssam #endif
138730594Ssam 	printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]);
138830594Ssam     }
138930594Ssam     else {
139030594Ssam 	printf("(%s)%c\n", showbuf, showops[movepending]);
139130594Ssam     }
139230594Ssam 
139330594Ssam     showind = 0;
139430594Ssam     nshow = 0;
139530594Ssam     showbuf[showind] = '\0';
139630594Ssam     PSx += PSshowlen;
139730594Ssam     PSshowlen = 0;
139830594Ssam     startx = hpos;
139930594Ssam     if (lastcmd == CPUT) startx += thisw;
140030594Ssam     thisw = 0;
140130594Ssam     movepending = NONE;
140230594Ssam }
1403