133295Skarels #ifndef lint
233295Skarels static char Notice[] = "Copyright (c) 1985 Adobe Systems Incorporated";
3*45863Skarels static char sccsid[] = "@(#)enscript.c	1.8 (Berkeley) 12/31/90";
440201Skarels static char *RCSID = "$Header: enscript.c,v 1.7 89/03/12 01:31:55 van Exp $";
540201Skarels 
633295Skarels #endif
740201Skarels /*
840201Skarels  * enscript.c
933295Skarels  *
1040201Skarels  * Copyright (c) 1985 Adobe Systems Incorporated
1133295Skarels  *
1240201Skarels  * inspired by Gosling's cz there have been major overhauls, but the input
1340201Skarels  * language is the same: new widths format generate PostScript (much easier
1440201Skarels  * than Press) new and renamed switches (to match 4.2bsd lpr spooler) obeys
1540201Skarels  * PostScript comment conventions doesn't worry so much about fonts
1640201Skarels  * (everything is scalable and rotatable, use PS font names, no face
1740201Skarels  * properties)
1833295Skarels  *
1940201Skarels  * enscript generates POSTSCRIPT print files of a special kind the coordinate
2040201Skarels  * system is in 20ths of a point. (1440 per inch)
2133295Skarels  *
2240201Skarels  * Edit History: Andrew Shore: Mon Nov 18 14:05:05 1985 End Edit History.
2333295Skarels  *
2440201Skarels  * RCSLOG: $Log:	enscript.c,v $
2540201Skarels  * Revision 1.7  89/03/12  01:31:55  van
2640201Skarels  * we have to escape special chars in title strings.
2733295Skarels  *
2840201Skarels  * Revision 1.6  89/03/10  00:30:39  van
2940201Skarels  * might as well let the user change everything.
3033295Skarels  *
3140201Skarels  * Revision 1.5  89/03/09  23:19:17  van
3240201Skarels  * gcc lint.
3333295Skarels  *
3440201Skarels  * Revision 1.4  89/03/09  23:08:50  van
3540201Skarels  * let user set the fonts used in 'gaudy' mode
3640201Skarels  *
3740201Skarels  * Revision 1.3  88/03/06  17:23:58  leres
3840201Skarels  * Fix logic bug; only spool output if that's want we want.
3940201Skarels  *
4040201Skarels  * Revision 1.2  86/07/03  00:06:31  van
4140201Skarels  * reformatted.  removed SYSV ifdefs.
4240201Skarels  *  Revision 1.1  86/07/03  00:03:12  van Initial
4340201Skarels  * revision
4433295Skarels  *
4540201Skarels  * Revision 2.1  85/11/24  11:48:55  shore Product Release 2.0
4640201Skarels  *
4740201Skarels  * Revision 1.3  85/11/20  00:10:01  shore Added System V support (input options
4840201Skarels  * and spooling) margins/linecount reworked (Dataproducts) incompatible
4940201Skarels  * options changes, getopt! Guy Riddle's Gaudy mode and other changes output
5040201Skarels  * spooling messages, pages, copies
5140201Skarels  *
5240201Skarels  * Revision 1.2  85/05/14  11:22:14  shore *** empty log message ***
5340201Skarels  *
5440201Skarels  *
5533295Skarels  */
5633295Skarels 
5733295Skarels #define POSTSCRIPTPRINTER "PostScript"
5833295Skarels 
5933295Skarels #define BODYROMAN "Courier"
6040521Skarels #define BODYSZ	  10
6140521Skarels #define HEADFONT  "Courier-Bold"
6240521Skarels #define HEADSZ	  10
6340521Skarels #define GHEADFONT "Helvetica-Bold"
6440521Skarels #define GHEADSZ	  14
6540201Skarels #define SHEADFONT "Times-Bold"
6640521Skarels #define SHEADSZ	  12
6740201Skarels #define PGNUMFONT "Helvetica-Bold"
6840521Skarels #define PGNUMSZ   24
6940521Skarels #define DATEFONT  "Times-Bold"
7040521Skarels #define DATESZ    12
7133295Skarels 
7233295Skarels #ifdef DEBUG
7333295Skarels #define debugp(x) {fprintf x ; VOIDC fflush(stderr);}
7433295Skarels #else
7533295Skarels #define debugp(x)
7633295Skarels #endif
7733295Skarels 
7833295Skarels #define UperInch (1440L)
7933295Skarels #define PtsPerInch 72
8033295Skarels #define UperPt 20
8133295Skarels 
8233295Skarels /* virtual page is 8 x 10.5 inches (for Toshiba compat) */
8333295Skarels #define PageWidth ((long) UperInch*8)
8433295Skarels #define PageLength ((long)((UperInch*21)/2))
8533295Skarels 
8640201Skarels /* #define PageLength ((long) ((long) (UperInch*(8*11-3)))/8) */
8740201Skarels /* #define PageWidth  ((long) ((long) (UperInch*(8*17-3)))/8) */
8833295Skarels 
8933295Skarels /* true page is 8.5 x 11 inches */
9033295Skarels #define TruePageWidth  (UperInch*17/2)
9133295Skarels #define TruePageLength ((long)(UperInch*11))
9233295Skarels 
9333295Skarels #include <stdio.h>
9433295Skarels #include <ctype.h>
9533295Skarels #include <pwd.h>
9633295Skarels #include <strings.h>
9733295Skarels #include <sys/time.h>
9833295Skarels #include <signal.h>
9933295Skarels #include <sys/types.h>
10033295Skarels #include <sys/stat.h>
10133295Skarels #include "transcript.h"
10233295Skarels 
10333295Skarels #define LPR "lpr"
10433295Skarels 
10540201Skarels #define MAXBAD 20		/* number of bad chars to pass before
10640201Skarels 				 * complaint */
10733295Skarels 
10833295Skarels private struct stat S;
10933295Skarels 
11040201Skarels extern double atof();
11133295Skarels extern char *optarg;		/* getopt current opt char */
11233295Skarels extern int optind;		/* getopt argv index */
11333295Skarels 
11440201Skarels private VOID int1 ();
11540201Skarels private FlushShow();
11633295Skarels 
11733295Skarels #define FSIZEMAX 256		/* number of chars per font */
11833295Skarels 
11933295Skarels /* the layout of a font information block */
12045782Skarels struct font {
12140201Skarels 	char    name[100];	/* PostScript font name */
12240201Skarels 	int     dsize;		/* size */
12340201Skarels 	int     Xwid[FSIZEMAX];	/* X widths for each character */
12433295Skarels };
12533295Skarels 
12640201Skarels private struct font fonts[16];	/* 16 possible fonts at one time */
12740201Skarels private int nf = 0;		/* number of fonts known about */
12833295Skarels 
129*45863Skarels private int TabWidth;		/* width of a tab */
13040201Skarels private int BSWidth;		/* width of a backspace */
13133295Skarels 
13233295Skarels private long UperLine = UperInch / 7;
13333295Skarels private long UperHLine = UperInch / 7;
13433295Skarels 
13533295Skarels private char *prog;		/* program name argv[0] */
13633295Skarels private char *libdir;		/* place for prolog and widths files */
13733295Skarels private char *tempdir;		/* place for temp file */
13833295Skarels private char TempName[100];	/* name of temporary PostScript file */
13933295Skarels private char OutName[256] = "";	/* filename for disk output */
14033295Skarels private int PipeOut = FALSE;	/* output to stdout (-p -) */
14133295Skarels private int ListOmitted = FALSE;/* list omitted chars on the tty */
14240521Skarels private int BeQuiet = FALSE;	/* suppress stderr error messages */
14340521Skarels private int Verbose = FALSE;	/* silly informational messages */
14433295Skarels private int Gaudy = FALSE;	/* pretty bars along the top */
14533295Skarels private int LPTsimulate = FALSE;/* an lpt should be simulated */
14633295Skarels private int Lines = 0;		/* max lines per page */
14733295Skarels private int LinesLeft = 66;	/* lines left on page when in LPT mode */
14833295Skarels private int LineMax = 64;	/* ? */
14933295Skarels private int SeenText = TRUE;	/* true if seen some text on this page */
15033295Skarels private int OutOnly = FALSE;	/* PS file only wanted */
15133295Skarels private int Rotated = FALSE;	/* pages to be rotated landscape */
15233295Skarels private int PreFeed = FALSE;	/* prefeed should be enabled */
15333295Skarels private int TwoColumn = FALSE;	/* two-column mode */
15433295Skarels private int FirstCol = TRUE;	/* we're printing column 1 */
15533295Skarels private int NoTitle = FALSE;	/* title line is suppressed */
15633295Skarels private int Cvted = FALSE;	/* converted a file to PS format */
15733295Skarels 
15840201Skarels private int IgnoreGarbage = FALSE;	/* garbage should be ignored */
15940521Skarels private int SeenFont = FALSE;	/* we've seen a font request */
16033295Skarels private int SeenFile = FALSE;	/* a file has been processed */
16140201Skarels private int ScannedFonts = FALSE;	/* we've scanned the font file */
16233295Skarels private char *FileName = 0;	/* name of file currently being PSed */
16333295Skarels private char *FileDate = 0;	/* last mod date of file being PSed */
16433295Skarels private char DateStr[27];	/* thanks, but no thanks ctime! */
16540201Skarels private int spoolNoBurst = FALSE;	/* no break page flag for spooler */
16633295Skarels 
16733295Skarels #ifdef BSD
16833295Skarels private char *spoolJobClass = NULL;
16933295Skarels private char *spoolJobName = NULL;
17040201Skarels 
17133295Skarels #endif
17233295Skarels private char *PrinterName = NULL;
17333295Skarels private int spoolNotify = 0;
17433295Skarels private char *spoolCopies = "1";
17533295Skarels 
17633295Skarels private char tempstr[256];	/* various path names */
17733295Skarels 
17833295Skarels private int CurFont;		/* current Font */
17940201Skarels private int fontindex[26];	/* table of fonts, indexed by font designator
18040201Skarels 				 * ('a' to 'z') */
18140201Skarels 
18233295Skarels /* indexes for default fonts */
18333295Skarels 
18433295Skarels #define Roman fontindex['r'-'a']
18533295Skarels #define HeaderFont fontindex['h'-'a']
18640201Skarels #define SHeaderFont fontindex['i'-'a']
18740201Skarels #define DateFont fontindex['j'-'a']
18840201Skarels #define PgNumFont fontindex['k'-'a']
18933295Skarels 
19033295Skarels private long cX, cY;		/* current page positions */
19133295Skarels private long dX, dY;		/* desired page positions */
19233295Skarels private long lX, lY;		/* page positions of the start of the line */
19333295Skarels private long crX, crY;		/* X and Y increments to apply to CR's */
19433295Skarels private long maxX;		/* maximum x coord on line */
19533295Skarels private long minY;		/* minimum y coord on page */
19640201Skarels private long Xoffset;		/* amount to offset left margin */
19733295Skarels 
19833295Skarels #define None	0
19933295Skarels #define RelX	1
20033295Skarels #define	RelY	2
20133295Skarels #define RelXY	3
20233295Skarels #define AbsX	4
20333295Skarels #define AbsY	8
20433295Skarels #define AbsXY	12
20533295Skarels 
20633295Skarels private int movepending;	/* moveto pending coords on stack */
20733295Skarels private int showpending;	/* number of characters waiting to be shown */
20840201Skarels private int pagepending;	/* start on next page when have something to
20940201Skarels 				 * print */
21040201Skarels private char *UsersHeader = NULL;	/* user specified heading */
21133295Skarels private char *Header = NULL;	/* generated header (usually FileName) */
21240521Skarels private char *Header2 = NULL;	/* second header line for Gaudy */
21333295Skarels private int Page = 0;		/* current page number */
21433295Skarels private int TotalPages = 0;	/* total number of pages printed */
21533295Skarels private int TruncChars = 0;	/* number of characters truncated */
21640201Skarels private int UndefChars = 0;	/* number of characters skipped because they
21740201Skarels 				 * weren't defined in some font */
21840201Skarels private int BadChars = 0;	/* number of bad characters seen so far */
21933295Skarels private FILE *OutFile = NULL;	/* output ps file */
22033295Skarels 
22133295Skarels 
22233295Skarels /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
22340201Skarels private
decodefont(name,f)22440201Skarels decodefont (name, f)
22540201Skarels 	register char *name;
22640201Skarels 	register struct font *f;
22740201Skarels {
22840201Skarels 	register char *d, *p;
22933295Skarels 
23040201Skarels 	p = name;
23140201Skarels 	d = f->name;
23240201Skarels 	f->dsize = 0;
23340201Skarels 	while (isascii (*p) && (isalpha (*p) || (*p == '-'))) {
23440201Skarels 		*d++ = *p++;
23540201Skarels 	}
23640201Skarels 	*d++ = '\0';
23740201Skarels 	while (isascii (*p) && isdigit (*p)) {
23840201Skarels 		f->dsize = f->dsize * 10 + *p++ - '0';
23940201Skarels 	}
24040201Skarels 	if (*p || !f->dsize || !f->name[0]) {
24140201Skarels 		fprintf (stderr, "%s: poorly formed font name & size: \"%s\"\n",
24240201Skarels 			 prog, name);
24340201Skarels 		exit (1);
24440201Skarels 	}
24533295Skarels }
24640201Skarels 
24740201Skarels 
24833295Skarels #define NOTDEF 0x8000
24933295Skarels #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
25033295Skarels 
25133295Skarels 
25240201Skarels /*
25340201Skarels  * Scan the font metrics directory looking for entries that match the entries
25440201Skarels  * in ``fonts''.  For entries that are found the data in the font description
25540201Skarels  * is filled in, if any are missing, it dies horribly.
25633295Skarels  */
ScanFont()25740201Skarels private VOID ScanFont ()
25840201Skarels {
25940201Skarels 	register struct font *f;
26040201Skarels 	register FILE *FontData;/* afm file */
26140201Skarels 	char   *c;
26240201Skarels 	int     ccode, cwidth, inChars;
26340201Skarels 	char    FontFile[512];	/* afm file name */
26440201Skarels 	char    afmbuf[BUFSIZ];
26533295Skarels 
26633295Skarels 
26740201Skarels 	if (!SeenFont) {
26840201Skarels 		if (Lines == 0)
26940201Skarels 			Lines = 64;
27040201Skarels 		if (Rotated && TwoColumn)
27140201Skarels 			fonts[Roman].dsize = 7;
27233295Skarels 	}
27340201Skarels 	/* loop through fonts, find and read metric entry in dir */
27440201Skarels 	ForAllFonts (f) {
27540201Skarels 		VOIDC   mstrcat (FontFile, libdir, "/", sizeof FontFile);
27633295Skarels 
27740201Skarels 		VOIDC   mstrcat (FontFile, FontFile, f->name, sizeof FontFile);
27840201Skarels 
27940201Skarels 		VOIDC   mstrcat (FontFile, FontFile, ".afm", sizeof FontFile);
28040201Skarels 
28140201Skarels 		if ((FontData = fopen (FontFile, "r")) == NULL) {
28240201Skarels 			fprintf (stderr, "%s: can't open font metrics file %s\n",
28340201Skarels 				 prog, FontFile);
28440201Skarels 			exit (1);
28533295Skarels 		}
28640201Skarels 		/* read the .afm file to get the widths */
28740201Skarels 		for (ccode = 0; ccode < FSIZEMAX; ccode++)
28840201Skarels 			f->Xwid[ccode] = NOTDEF;
28940201Skarels 
29040201Skarels 		inChars = 0;
29140201Skarels 		while (fgets (afmbuf, sizeof afmbuf, FontData) != NULL) {
29240201Skarels 			/* strip off newline */
29340201Skarels 			if ((c = INDEX (afmbuf, '\n')) == 0) {
29440201Skarels 				fprintf (stderr, "%s: AFM file %s line too long %s\n",
29540201Skarels 					 prog, FontFile, afmbuf);
29640201Skarels 				exit (1);
29740201Skarels 			}
29840201Skarels 			*c = '\0';
29940201Skarels 			if (*afmbuf == '\0')
30040201Skarels 				continue;
30140201Skarels 			if (strcmp (afmbuf, "StartCharMetrics") == 0) {
30240201Skarels 				inChars++;
30340201Skarels 				continue;
30440201Skarels 			}
30540201Skarels 			if (strcmp (afmbuf, "EndCharMetrics") == 0)
30640201Skarels 				break;
30740201Skarels 			if (inChars == 1) {
30840201Skarels 				if (sscanf (afmbuf, "C %d ; WX %d ;", &ccode, &cwidth) != 2) {
30940201Skarels 					fprintf (stderr, "%s: trouble with AFM file %s\n",
31040201Skarels 						 prog, FontFile);
31140201Skarels 					exit (1);
31240201Skarels 				}
31340201Skarels 				/* get out once we see an unencoded char */
31440201Skarels 				if (ccode == -1)
31540201Skarels 					break;
31640201Skarels 				if (ccode > 255)
31740201Skarels 					continue;
31840201Skarels 				f->Xwid[ccode] =
31940201Skarels 					(short) (((long) cwidth * (long) f->dsize * (long) UperPt)
32040201Skarels 						 / 1000L);
32140201Skarels 				continue;
32240201Skarels 			}
32340201Skarels 		}
32440201Skarels 		VOIDC   fclose (FontData);
32533295Skarels 	}
32633295Skarels 
32745782Skarels 	/*
32845782Skarels 	 * Tab width is problematical for proportionally-spaced fonts.
32945782Skarels 	 * Attempt to make tabs wide enough that things hand-tabulated
33045782Skarels 	 * for monospaced fonts still fit in columns.
33145782Skarels 	 */
33245782Skarels 	if (fonts[Roman].Xwid['0'] == fonts[Roman].Xwid['M'])
33345782Skarels 		TabWidth = fonts[Roman].Xwid['0'] * 8;	/* 8 * figure width */
33445782Skarels 	else
33545782Skarels 		TabWidth = fonts[Roman].Xwid['0'] * 10;	/* 10 * figure width */
33640201Skarels 	BSWidth = fonts[Roman].Xwid[' '];	/* space width */
33733295Skarels 
33840201Skarels 	UperLine = (fonts[Roman].dsize + 1) * UperPt;
33933295Skarels 
34040201Skarels 	if (LPTsimulate) {
34140201Skarels 		UperHLine = UperLine;
34240201Skarels 		Lines = LineMax = 66;
34340201Skarels 	} else {
34440201Skarels 		UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
34540201Skarels 	}
34633295Skarels 
34740201Skarels 	crX = 0;
34840201Skarels 	crY = -UperLine;
34933295Skarels 
35033295Skarels }
35133295Skarels 
35233295Skarels 
35340201Skarels /*
35440201Skarels  * Return a font number for the font with the indicated name and size.  Adds
35540201Skarels  * info to the font list for the eventual search.
35633295Skarels  */
35740201Skarels private int
DefineFont(name,size)35840201Skarels DefineFont (name, size)
35940201Skarels 	char   *name;
36040201Skarels {
36140201Skarels 	register struct font *p;
36240201Skarels 
36340201Skarels 	p = &fonts[nf];
36440201Skarels 	VOIDC   strcpy (p->name, name);
36540201Skarels 
36640201Skarels 	p->dsize = size;
36740201Skarels 	return (nf++);
36833295Skarels }
36933295Skarels 
ResetFont(indx,name,size)37040538Skarels ResetFont(indx, name, size)
37140538Skarels 	char   *name;
37240538Skarels {
37340538Skarels 	register struct font *p;
37433295Skarels 
37540538Skarels 	p = &fonts[indx];
37640538Skarels 	VOIDC   strcpy (p->name, name);
37740538Skarels 	p->dsize = size;
37840538Skarels }
37940538Skarels 
38033295Skarels /* dump the fonts to the PS file for setup */
38140201Skarels private VOID
DumpFonts()38240201Skarels DumpFonts ()
38340201Skarels {
38440201Skarels 	register struct font *f;
38533295Skarels 
38640201Skarels 	ForAllFonts (f) {
38740201Skarels 		fprintf (OutFile, "%d %d /%s\n", f - &fonts[0], f->dsize * UperPt, f->name);
38840201Skarels 	}
38940201Skarels 	fprintf (OutFile, "%d SetUpFonts\n", nf);
39033295Skarels }
39133295Skarels 
39233295Skarels /* add a shown character to the PS file */
39340201Skarels private VOID
OUTputc(c)39440201Skarels OUTputc (c)
39540201Skarels 	register int c;
39640201Skarels {
39740201Skarels 	if (!showpending) {
39840201Skarels 		putc ('(', OutFile);
39940201Skarels 		showpending = TRUE;
40040201Skarels 	}
40140201Skarels 	if (c == '\\' || c == '(' || c == ')')
40240201Skarels 		putc ('\\', OutFile);
40340201Skarels 	if ((c > 0176) || (c < 040)) {
40440201Skarels 		putc ('\\', OutFile);
40540201Skarels 		putc ((c >> 6) + '0', OutFile);
40640201Skarels 		putc (((c >> 3) & 07) + '0', OutFile);
40740201Skarels 		putc ((c & 07) + '0', OutFile);
40840201Skarels 	} else
40940201Skarels 		putc (c, OutFile);
41033295Skarels }
41133295Skarels 
41240201Skarels /* put a correctly escaped string to the PS file */
41340201Skarels private VOID
OUTstr(s)41440201Skarels OUTstr(s)
41540201Skarels 	register char *s;
41640201Skarels {
41740201Skarels 	if (!showpending) {
41840201Skarels 		putc ('(', OutFile);
41940201Skarels 		showpending = TRUE;
42040201Skarels 	}
42140201Skarels 	while (*s)
42240201Skarels 		OUTputc(*s++);
42340201Skarels 
42440201Skarels 	putc(')', OutFile);
42540201Skarels 	showpending = FALSE;
42640201Skarels }
42740201Skarels 
42833295Skarels /* Set the current font */
42940201Skarels private VOID
SetFont(f)43040201Skarels SetFont (f)
43140201Skarels 	int     f;
43240201Skarels {
43340201Skarels 	FlushShow ();
43440201Skarels 	CurFont = f;
43540201Skarels 	fprintf (OutFile, "%d F\n", f);
43633295Skarels }
43733295Skarels 
43840201Skarels /*
43940201Skarels  * put a character onto the page at the desired X and Y positions. If the
44040201Skarels  * current position doesn't agree with the desired position, put out movement
44140201Skarels  * directives.  Leave the current position updated to account for the
44240201Skarels  * character.
44333295Skarels  */
44440201Skarels private VOID
ShowChar(c)44540201Skarels ShowChar (c)
44640201Skarels 	register int c;
44740201Skarels {
44840201Skarels 	register struct font *f;
44940201Skarels 	register long nX, nY;
45040201Skarels 	static  level = 0;
45140564Skarels 	VOID PageEject(), InitPage();
45233295Skarels 
45340201Skarels 	level++;
45440201Skarels 	f = &fonts[CurFont];
45533295Skarels 
45640201Skarels 	if (f->Xwid[c] == NOTDEF) {
45740201Skarels 		UndefChars++;
45840201Skarels 		if (ListOmitted)
45940201Skarels 			fprintf (stderr, "%s: \\%03o not found in font %s\n",
46040201Skarels 				 prog, c, f->name);
46140201Skarels 		if (level <= 1) {
46240201Skarels 			ShowChar ('\\');
46340201Skarels 			ShowChar ((c >> 6) + '0');
46440201Skarels 			ShowChar (((c >> 3) & 07) + '0');
46540201Skarels 			ShowChar ((c & 07) + '0');
46640201Skarels 		}
46740201Skarels 		level--;
46840201Skarels 		return;
46933295Skarels 	}
47040201Skarels 	nX = dX + f->Xwid[c];	/* resulting position after showing this char */
47140201Skarels 	nY = dY;
47233295Skarels 
47340201Skarels 	if (c != ' ' || ((cX == dX) && (cY == dY))) {
47440521Skarels 		/*
47540521Skarels 		 * If character doesn't fit on this line
47640521Skarels 		 * (and we're not at left margin), simulate newline
47740521Skarels 		 * and then call ourselves recursively.
47840521Skarels 		 */
47940521Skarels 		if (nX > maxX && dX > lX) {
48040521Skarels 			SeenText = TRUE;
48140521Skarels 			dY = lY = lY + crY;
48240521Skarels 			dX = lX = lX + crX;
48340564Skarels 			if ((dY < minY) || (--LinesLeft <= 0)) {
48440521Skarels 				PageEject ();
48540564Skarels 				if (pagepending)
48640564Skarels 					InitPage ();
48740564Skarels 			}
48840521Skarels 			ShowChar(c);
48940521Skarels 			level--;
49040521Skarels 			return;
49140521Skarels 		}
49240521Skarels 		if (cX != dX) {
49340521Skarels 			if (cY != dY) {
49440201Skarels 				FlushShow ();
49540521Skarels 				/* absolute x, relative y */
49640521Skarels 				fprintf (OutFile, "%ld %ld", dX, dY);
49740521Skarels 				movepending = AbsXY;
49840521Skarels 			} else {
49940521Skarels 				FlushShow ();
50040521Skarels 				fprintf (OutFile, "%ld", dX - cX);	/* relative x */
50140521Skarels 				movepending = RelX;
50240201Skarels 			}
50340521Skarels 		} else if (cY != dY) {
50440521Skarels 			FlushShow ();
50540521Skarels 			fprintf (OutFile, "%ld", dY - cY);	/* relative y */
50640521Skarels 			movepending = RelY;
50740521Skarels 		}
50840521Skarels 		OUTputc (c);
50940521Skarels 		showpending = TRUE;
51040521Skarels 		cX = nX;
51140521Skarels 		cY = nY;
51233295Skarels 	}
51340201Skarels 	dX = nX;
51440201Skarels 	dY = nY;
51533295Skarels 
51640201Skarels 	level--;
51733295Skarels }
51833295Skarels 
51933295Skarels /* put out a shown string to the PS file */
52040201Skarels private VOID
ShowStr(s)52140201Skarels ShowStr (s)
52240201Skarels 	register char *s;
52340201Skarels {
52440201Skarels 	while (*s) {
52540201Skarels 		if (*s >= 040)
52640201Skarels 			ShowChar (*s);
52740201Skarels 		s++;
52840201Skarels 	}
52933295Skarels }
53033295Skarels 
53133295Skarels /* flush pending show */
53240201Skarels private
FlushShow()53340201Skarels FlushShow ()
53440201Skarels {
53540201Skarels 	if (showpending) {
53640201Skarels 		putc (')', OutFile);
53740201Skarels 		switch (movepending) {
53840201Skarels 		case RelX:
53940201Skarels 			putc ('X', OutFile);
54040201Skarels 			break;
54140201Skarels 		case RelY:
54240201Skarels 			putc ('Y', OutFile);
54340201Skarels 			break;
54440201Skarels 		case AbsXY:
54540201Skarels 			putc ('B', OutFile);
54640201Skarels 			break;
54740201Skarels 		case None:
54840201Skarels 			putc ('S', OutFile);
54940201Skarels 			break;
55040201Skarels 		}
55140201Skarels 		putc ('\n', OutFile);
55240201Skarels 		movepending = None;
55340201Skarels 		showpending = FALSE;
55433295Skarels 	}
55533295Skarels }
55633295Skarels 
55733295Skarels /* put out a page heading to the PS file */
55840201Skarels private VOID
InitPage()55940201Skarels InitPage ()
56040201Skarels {
56140201Skarels 	char    header[200];
56240201Skarels 	register int OldFont = CurFont;
56333295Skarels 
56440201Skarels 	TotalPages++;
56540201Skarels 	fprintf (OutFile, "%%%%Page: ? %d\n", TotalPages);
56640201Skarels 	fprintf (OutFile, "StartPage\n");
56740201Skarels 	SeenText = FALSE;
56840201Skarels 	cX = cY = -1;
56940201Skarels 	showpending = pagepending = FALSE;
57040201Skarels 	FirstCol = TRUE;
57140201Skarels 	if (Rotated) {
57240201Skarels 		fprintf (OutFile, "Landscape\n");
57340201Skarels 		lX = dX = UperInch / 4 + Xoffset;
57440201Skarels 		lY = dY = PageLength - (UperHLine * 3) / 2;
57540201Skarels 		maxX = TruePageLength;
57640201Skarels 		/* minY = (PageLength - TruePageWidth) + 3*UperLine+480; */
57740201Skarels 		minY = (TruePageLength - TruePageWidth) + (TruePageWidth - PageWidth) / 2;
57840201Skarels 	} else {
57940201Skarels 		lX = dX = Xoffset +
58040201Skarels 			   (TwoColumn? (UperInch * 0.3) : ((UperInch * 5) / 8));
58140201Skarels 		lY = dY = PageLength - UperHLine;
58240201Skarels 		maxX = TruePageWidth;
58340201Skarels 		minY = (UperInch / 4);	/* 0.25 inches */
58440201Skarels 	}
58540201Skarels 	movepending = None;
58640201Skarels 	cX = dX;
58740201Skarels 	cY = dY;
58833295Skarels 
58940201Skarels 	if (!NoTitle) {
59040201Skarels 		if (Gaudy) {
59140201Skarels 			OUTstr(UsersHeader);
59240521Skarels 			if (Header2)
59340521Skarels 			    OUTstr(Header2);
59440521Skarels 			else
59540521Skarels 			    OUTstr(Header);
59640201Skarels 			fprintf (OutFile, "[%s](%d)Gaudy\n", FileDate, ++Page);
59740201Skarels 			cX = cY = 0;	/* force moveto here */
59840201Skarels 		} else {
59940201Skarels 			SetFont (HeaderFont);
60040201Skarels 			fprintf (OutFile, "%ld %ld ", cX, cY);
60140201Skarels 			movepending = AbsXY;
60240201Skarels 			if (UsersHeader) {
60340201Skarels 				if (*UsersHeader == 0) {
60440201Skarels 					fprintf (OutFile, "()B\n");
60540201Skarels 					movepending = None;
60640201Skarels 					showpending = FALSE;
60740201Skarels 				} else
60840201Skarels 					ShowStr (UsersHeader);
60940201Skarels 			} else {
61040201Skarels 				VOIDC sprintf (header, "%s        %s        %d",
61140201Skarels 					       Header? Header : "              ", FileDate, ++Page);
61240201Skarels 
61340201Skarels 				ShowStr (header);
61440201Skarels 			}
61540201Skarels 			FlushShow ();
61633295Skarels 		}
61740201Skarels 		dX = lX = lX + crX * 2;
61840201Skarels 		dY = lY = lY + crY * 2;
61940201Skarels 	} else {
62040201Skarels 		/* fake it to force a moveto */
62140201Skarels 		cX = cY = 0;
62233295Skarels 	}
62340201Skarels 	if (TwoColumn)
62440201Skarels 		maxX = maxX / 2 - BSWidth;
62540201Skarels 	else
62640201Skarels 		maxX -= ((long) (UperInch * 0.3));
62740201Skarels 	LineMax = (lY - minY) / (-crY);
62840201Skarels 	if ((Lines <= 0) || (Lines > LineMax))
62940201Skarels 		Lines = LinesLeft = LineMax;
63040201Skarels 	else
63140201Skarels 		LinesLeft = Lines;
63240201Skarels 	SetFont (OldFont);
63333295Skarels }
63433295Skarels 
63540201Skarels private VOID
ClosePage()63640201Skarels ClosePage ()
63740201Skarels {
63840201Skarels 	FlushShow ();
63940201Skarels 	if (!pagepending)
64040201Skarels 		fprintf (OutFile, "EndPage\n");
64140201Skarels 	pagepending = TRUE;
64233295Skarels }
64333295Skarels 
64433295Skarels /* skip to a new page */
64540201Skarels private VOID
PageEject()64640201Skarels PageEject ()
64740201Skarels {
64840201Skarels 	if (TwoColumn && FirstCol) {
64940201Skarels 		FirstCol = FALSE;
65040201Skarels 		if (Rotated) {
65140201Skarels 			lY = dY = PageLength - (UperHLine * 3) / 2;
65240201Skarels 			lX = dX = Xoffset + TruePageLength / 2;
65340201Skarels 			maxX = TruePageLength - UperInch * 0.3;
65440201Skarels 		} else {
65540201Skarels 			lY = dY = PageLength - UperHLine;
65640201Skarels 			lX = dX = Xoffset + TruePageWidth / 2;
65740201Skarels 			maxX = TruePageWidth - UperInch * 0.3;
65840201Skarels 		}
65940201Skarels 		if (!NoTitle) {
66040201Skarels 			dX = lX = lX + crX * 2;
66140201Skarels 			dY = lY = lY + crY * 2;
66240201Skarels 		}
66340201Skarels 	} else
66440201Skarels 		ClosePage ();
66540201Skarels 	LinesLeft = Lines;
66640201Skarels 	SeenText = FALSE;
66733295Skarels }
66833295Skarels 
66940201Skarels private VOID
CommentHeader()67040201Skarels CommentHeader ()
67140201Skarels {
67240201Skarels 	long    clock;
67340201Skarels 	struct passwd *pswd;
67440201Skarels 	char    hostname[40];
67540201Skarels 
67640201Skarels 	/* copy the file, prepending a new comment header */
67740201Skarels 	fprintf (OutFile, "%%!%s\n", COMMENTVERSION);
67840201Skarels 	fprintf (OutFile, "%%%%Creator: ");
67940201Skarels 	pswd = getpwuid ((int) getuid ());
68040201Skarels 	VOIDC   gethostname (hostname, (int) sizeof hostname);
68140201Skarels 
68240201Skarels 	fprintf (OutFile, "%s:%s (%s)\n", hostname, pswd->pw_name, pswd->pw_gecos);
68340201Skarels 	fprintf (OutFile, "%%%%Title: %s\n", (FileName ? FileName : "stdin"));
68440201Skarels 	fprintf (OutFile, "%%%%CreationDate: %s", (VOIDC time (&clock), ctime (&clock)));
68533295Skarels }
68633295Skarels 
68733295Skarels /* Copy the standard input file to the PS file */
68840201Skarels private VOID
CopyFile()68940201Skarels CopyFile ()
69040201Skarels {
69140201Skarels 	register int c;
69233295Skarels 
69340201Skarels 	if (OutFile == 0) {
69440201Skarels 		if (OutOnly) {
69540201Skarels 			OutFile = PipeOut ? stdout : fopen (OutName, "w");
69640201Skarels 		} else {
69740201Skarels 			VOIDC   mktemp (mstrcat (TempName, tempdir,
69840201Skarels 				            ENSCRIPTTEMP, sizeof TempName));
69940201Skarels 			VOIDC   strcpy (OutName, TempName);
70040201Skarels 
70140201Skarels 			VOIDC   umask (077);
70240201Skarels 
70340201Skarels 			OutFile = fopen (TempName, "w");
70440201Skarels 		}
70533295Skarels 	}
70640201Skarels 	if (OutFile == NULL) {
70740201Skarels 		fprintf (stderr, "%s: can't create PS file %s\n", prog, TempName);
70840201Skarels 		exit (1);
70933295Skarels 	}
71040201Skarels 	if (!ScannedFonts) {
71140201Skarels 		ScannedFonts = TRUE;
71240201Skarels 		ScanFont ();
71333295Skarels 	}
71440201Skarels 	if (!Cvted) {
71540201Skarels 		CommentHeader ();
71640201Skarels 		if (nf) {
71740201Skarels 			register struct font *f;
71840201Skarels 
71940201Skarels 			fprintf (OutFile, "%%%%DocumentFonts:");
72040201Skarels 			ForAllFonts (f) {
72140201Skarels 				fprintf (OutFile, " %s", f->name);
72240201Skarels 			}
72340201Skarels 			fprintf (OutFile, "\n");
72440201Skarels 		}
72540201Skarels 		/* copy in fixed prolog */
72640201Skarels 		if (copyfile (mstrcat (tempstr, libdir, ENSCRIPTPRO, sizeof tempstr),
72740201Skarels 			      OutFile)) {
72840201Skarels 			fprintf (stderr, "%s: trouble copying prolog file\n", prog);
72940201Skarels 			exit (1);
73040201Skarels 		}
73140201Skarels 		fprintf (OutFile, "StartEnscriptDoc %% end fixed prolog\n");
73240201Skarels 		DumpFonts ();
73340201Skarels 		if (Gaudy)
73440201Skarels 			fprintf (OutFile, "%s %s InitGaudy\n",
73540201Skarels 				 Rotated ? "10.55" : "8.0", TwoColumn ? "true" : "false");
73640201Skarels 		if (PreFeed) {
73740201Skarels 			fprintf (OutFile, "true DoPreFeed\n");
73840201Skarels 		}
73940201Skarels 		fprintf (OutFile, "%%%%EndProlog\n");
74033295Skarels 	}
74140201Skarels 	Cvted = TRUE;
74233295Skarels 
74340201Skarels 	Page = 0;
74440201Skarels 	BadChars = 0;		/* give each file a clean slate */
74540201Skarels 	pagepending = TRUE;
74640201Skarels 	while ((c = getchar ()) != EOF)
74740201Skarels 		if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
74840201Skarels 			if (BadChars++ > MAXBAD) {	/* allow some kruft but
74940201Skarels 							 * not much */
75040201Skarels 				fprintf (stderr, "%s: \"%s\" not a text file? Try -g.\n",
75140201Skarels 				     prog, FileName ? FileName : "(stdin)");
75240201Skarels 				if (!PipeOut)
75340201Skarels 					VOIDC   unlink (OutName);
75440201Skarels 
75540201Skarels 				exit (1);
75640201Skarels 			}
75740201Skarels 		} else if (c >= ' ') {
75840201Skarels 			if (pagepending)
75940201Skarels 				InitPage ();
76040201Skarels 			ShowChar (c);
76140201Skarels 		} else
76240201Skarels 			switch (c) {
76340201Skarels 			case 010:	/* backspace */
76440201Skarels 				dX -= BSWidth;
76533295Skarels 				break;
76640201Skarels 			case 015:	/* carriage return ^M */
76740201Skarels 				dY = lY;
76840201Skarels 				dX = lX;
76933295Skarels 				break;
77040201Skarels 			case 012:	/* linefeed ^J */
77140201Skarels 				if (pagepending)
77240201Skarels 					InitPage ();
77340201Skarels 				if (dX != lX || dY != lY || !LPTsimulate || SeenText) {
77440201Skarels 					SeenText = TRUE;
77540201Skarels 					dY = lY = lY + crY;
77640201Skarels 					dX = lX = lX + crX;
77740201Skarels 				} else
77840201Skarels 					LinesLeft = LineMax;
77940201Skarels 				if ((dY < minY) || (--LinesLeft <= 0))
78040201Skarels 					PageEject ();
78140201Skarels 				break;
78240201Skarels 			case 033:	/* escape */
78340201Skarels 				switch (c = getchar ()) {
78440201Skarels 				case '7':	/* backup one line */
78540201Skarels 					dY = lY = lY - crY;
78640201Skarels 					dX = lX = lX - crX;
78740201Skarels 					break;
78840201Skarels 				case '8':	/* backup 1/2 line */
78940201Skarels 					dY -= crY / 2;
79040201Skarels 					dX -= crX / 2;
79140201Skarels 					break;
79240201Skarels 				case '9':	/* forward 1/2 linefeed */
79340201Skarels 					dY += crY / 2;
79440201Skarels 					dX += crX / 2;
79540201Skarels 					break;
79640201Skarels 				case 'F':	/* font setting */
79740201Skarels 					c = getchar ();
79840201Skarels 					if ('a' <= c && c <= 'z')
79940201Skarels 						if (fontindex[c - 'a'] >= 0)
80040201Skarels 							SetFont (fontindex[c - 'a']);
80140201Skarels 						else {
80240201Skarels 							fprintf (stderr, "%s: font '%c' not defined\n",
80340201Skarels 								 prog, c);
80440201Skarels 							exit (1);
80540201Skarels 						}
80640201Skarels 					else {
80740201Skarels 						fprintf (stderr, "%s: bad font code in file: '%c'\n",
80840201Skarels 							 prog, c);
80940201Skarels 						exit (1);
81040201Skarels 					}
81140201Skarels 					break;
81240201Skarels 				case 'D':	/* date string */
81340201Skarels 					VOIDC fgets (DateStr, sizeof(DateStr), stdin);
81440201Skarels 					FileDate = DateStr;
81540201Skarels 					break;
81640201Skarels 				case 'U':	/* new "user's" heading */
81740201Skarels 					{
81840201Skarels 						static char header[100];
81940201Skarels 						VOIDC   fgets (header, sizeof(header), stdin);
82033295Skarels 
82140201Skarels 						UsersHeader = header;
82240201Skarels 						break;
82340201Skarels 					}
82440201Skarels 				case 'H':	/* new heading */
82540201Skarels 					{
82640201Skarels 						static char header[100];
82740201Skarels 
82840201Skarels 						VOIDC   fgets (header, sizeof(header), stdin);
82940201Skarels 
83040201Skarels 						ClosePage ();
83140521Skarels 						Header2 = header;
83240201Skarels 						Page = 0;
83340201Skarels 						break;
83440201Skarels 					}
83540201Skarels 				}
83633295Skarels 				break;
83740201Skarels 			case '%':	/* included PostScript line */
83840201Skarels 				{
83940201Skarels 					char    psline[200];
84040201Skarels 					VOIDC   fgets (psline, sizeof(psline), stdin);
84140201Skarels 
84240201Skarels 					fprintf (OutFile, "%s\n", psline);
84340201Skarels 					break;
84440201Skarels 				}
84540201Skarels 			case 014:	/* form feed ^L */
84640201Skarels 				PageEject ();
84740201Skarels 				break;
84840201Skarels 			case 011:	/* tab ^I */
84940201Skarels 				if (pagepending)
85040201Skarels 					InitPage ();
851*45863Skarels 				dX += TabWidth - ((dX - lX) % TabWidth);
85240201Skarels 				break;
85340201Skarels 			default:	/* other control character, take your
85440201Skarels 					 * chances */
85540201Skarels 				if (pagepending)
85640201Skarels 					InitPage ();
85740201Skarels 				ShowChar (c);
85840201Skarels 			}
85940201Skarels 	ClosePage ();
86033295Skarels }
86133295Skarels 
86233295Skarels 
86333295Skarels /*
86440201Skarels  * close the PS file
86533295Skarels  */
86640201Skarels private VOID
ClosePS()86740201Skarels ClosePS ()
86840201Skarels {
86940201Skarels 	fprintf (OutFile, "%%%%Trailer\n");
87040201Skarels 	if (PreFeed) {
87140201Skarels 		fprintf (OutFile, "false DoPreFeed\n");
87240201Skarels 	}
87340201Skarels 	fprintf (OutFile, "EndEnscriptDoc\nEnscriptJob restore\n");
87433295Skarels }
87533295Skarels 
87633295Skarels 
87740201Skarels private VOID
SetTime(tval)87840201Skarels SetTime (tval)
87940201Skarels 	long    tval;
88040201Skarels {
88140201Skarels 	struct tm *tp;
88233295Skarels 
88340201Skarels 	if (Gaudy) {
88440201Skarels 		tp = localtime (&tval);
88540201Skarels 		VOIDC   sprintf (DateStr, "(%02d/%02d/%02d)(%02d:%02d:%02d)",
88640201Skarels 			           tp->tm_year, tp->tm_mon + 1, tp->tm_mday,
88740201Skarels 			               tp->tm_hour, tp->tm_min, tp->tm_sec);
88840201Skarels 	} else {
88940201Skarels 		VOIDC   strcpy (DateStr, ctime (&tval));
89033295Skarels 
89140201Skarels 		DateStr[24] = '\0';	/* get rid of newline */
89240201Skarels 	}
89340201Skarels 
89440201Skarels 	FileDate = DateStr;
89533295Skarels }
89633295Skarels 
89733295Skarels 
89833295Skarels 
89933295Skarels 
90040521Skarels #define ARGS "12gGBlL:oqrRkKf:F:b:p:J:C:P:#:mhO:s:v"
90133295Skarels 
ParseArgs(ac,av)90240201Skarels private VOID ParseArgs (ac, av)
90340201Skarels 	int     ac;
90440201Skarels 	char  **av;
90540201Skarels {
90640201Skarels 	int     argp;
90740201Skarels 
90840201Skarels 	while ((argp = getopt (ac, av, ARGS)) != EOF) {
90940201Skarels 		debugp ((stderr, "option: %c\n", argp));
91040201Skarels 		switch (argp) {
91140201Skarels 		case '1':
91240201Skarels 			TwoColumn = FALSE;
91340201Skarels 			break;
91440201Skarels 		case '2':
91540201Skarels 			TwoColumn = TRUE;
91640201Skarels 			break;
91740201Skarels 		case 'G':
91840201Skarels 			Gaudy = TRUE;
91940201Skarels 			if (UsersHeader == NULL)
92040201Skarels 				UsersHeader = "";
92140201Skarels 			if (Header == NULL)
92240201Skarels 				Header = "";
92340538Skarels 			/* warning: fonts must be defined in this order! */
92440538Skarels 			ResetFont(HeaderFont, GHEADFONT, GHEADSZ);
92540538Skarels 			if (SHeaderFont == -1)
92640538Skarels 				SHeaderFont = DefineFont(SHEADFONT, SHEADSZ);
92740521Skarels 			DateFont = DefineFont(DATEFONT, DATESZ);
92840521Skarels 			PgNumFont = DefineFont(PGNUMFONT, PGNUMSZ);
92940201Skarels 			break;
93040201Skarels 		case 'g':
93140201Skarels 			IgnoreGarbage = TRUE;
93240201Skarels 			break;
93340201Skarels 		case 'B':
93440201Skarels 			NoTitle = TRUE;
93540201Skarels 			break;
93640201Skarels 		case 'l':
93740201Skarels 			LPTsimulate = TRUE;
93840201Skarels 			NoTitle = TRUE;
93940201Skarels 			Lines = 66;
94040201Skarels 			break;
94140201Skarels 		case 'L':
94240201Skarels 			Lines = atoi (optarg);
94340201Skarels 			break;
94440201Skarels 		case 'o':
94540201Skarels 			ListOmitted = TRUE;
94640201Skarels 			break;
94740201Skarels 		case 'q':
94840201Skarels 			BeQuiet = TRUE;
94940201Skarels 			break;
95040201Skarels 		case 'r':
95140201Skarels 			Rotated = TRUE;
95240201Skarels 			break;
95340201Skarels 		case 'R':
95440201Skarels 			Rotated = FALSE;
95540201Skarels 			break;
95640201Skarels 		case 'k':
95740201Skarels 			PreFeed = TRUE;
95840201Skarels 			break;
95940201Skarels 		case 'K':
96040201Skarels 			PreFeed = FALSE;
96140201Skarels 			break;
96240201Skarels 		case 'f':{
96340201Skarels 				register char font = 'r';
96440201Skarels 				int    *whichfont;
96540201Skarels 
96640201Skarels 				if (*optarg == '-') {
96740201Skarels 					font = *++optarg;
96840201Skarels 					optarg++;
96940201Skarels 				}
97040201Skarels 				if ((font < 'a') || ('z' < font)) {
97140201Skarels 					fprintf (stderr,
97240201Skarels 						 "%s: '%c' isn't a valid font designator.\n",
97340201Skarels 						 prog, font);
97440201Skarels 					exit (1);
97540201Skarels 				}
97640201Skarels 				whichfont = &fontindex[font - 'a'];
97740201Skarels 				if (*whichfont < 0)
97840201Skarels 					*whichfont = nf++;
97940201Skarels 				decodefont (optarg, &fonts[*whichfont]);
98040521Skarels 				if (font == 'r')
98140521Skarels 					SeenFont++;
98240201Skarels 			}
98340201Skarels 			break;
98440201Skarels 		case 'F':
98540521Skarels 			if (HeaderFont == -1)
98640521Skarels 				HeaderFont = nf++;
98740201Skarels 			decodefont (optarg, &fonts[HeaderFont]);
98840201Skarels 			break;
98940201Skarels 		case 'b':
99040201Skarels 			UsersHeader = optarg;
99140201Skarels 			break;
99240521Skarels 		case 's':
99340521Skarels 			Header2 = optarg;
99440521Skarels 			break;
99540201Skarels 		case 'p':
99640201Skarels 			OutOnly = TRUE;
99740201Skarels 			VOIDC   strcpy (OutName, optarg);
99840201Skarels 
99940201Skarels 			if (strcmp (OutName, "-") == 0)
100040201Skarels 				PipeOut = TRUE;
100140201Skarels 			break;
100240201Skarels 		case 'h':
100340201Skarels 			spoolNoBurst = TRUE;
100440201Skarels 			break;
100540201Skarels 			/* BSD lpr options processing */
100640201Skarels 		case 'm':
100740201Skarels 			spoolNotify = argp;
100840201Skarels 			break;
100940201Skarels 		case '#':
101040201Skarels 			spoolCopies = optarg;
101140201Skarels 			break;
101240201Skarels 		case 'C':
101340201Skarels 			spoolJobClass = optarg;
101440201Skarels 			break;
101540201Skarels 		case 'J':
101640201Skarels 			spoolJobName = optarg;
101740201Skarels 			break;
101840201Skarels 		case 'P':
101940201Skarels 			PrinterName = optarg;
102040201Skarels 			break;
102140201Skarels 		case '?':
102240201Skarels 			/* bad option */
102340201Skarels 			break;
102440201Skarels 		case 'O':
102540201Skarels 			Xoffset = atof(optarg) * (double)UperInch;
102640201Skarels 			if (Xoffset < 0)
102740201Skarels 				Xoffset = 0;
102840201Skarels 			break;
102940521Skarels 		case 'v':
103040521Skarels 			Verbose = TRUE;
103140521Skarels 			break;
103240201Skarels 		default:
103340201Skarels 			break;
103433295Skarels 		}
103533295Skarels 	}
103633295Skarels }
103733295Skarels 
103833295Skarels 
103933295Skarels /* addarg is used to construct an argv for the spooler */
104040201Skarels private VOID
addarg(argv,argstr,argc)104140201Skarels addarg (argv, argstr, argc)
104240201Skarels 	char  **argv;
104340201Skarels 	char   *argstr;
104440201Skarels 	register int *argc;
104540201Skarels {
104640201Skarels 	register char *p = (char *) malloc ((unsigned) (strlen (argstr) + 1));
104740201Skarels 	VOIDC   strcpy (p, argstr);
104840201Skarels 
104940201Skarels 	argv[(*argc)++] = p;
105040201Skarels 	argv[*argc] = '\0';
105133295Skarels }
105233295Skarels 
105333295Skarels 
105440201Skarels private VOID
SpoolIt()105540201Skarels SpoolIt ()
105640201Skarels {
105740201Skarels 	char    temparg[200];
105840201Skarels 	char   *argstr[200];
105940201Skarels 	int     nargs = 0;
106033295Skarels 
106133295Skarels 
106240201Skarels 	addarg (argstr, LPR, &nargs);
106340201Skarels 	/* BSD spooler */
106440201Skarels 	if (atoi (spoolCopies) > 1) {
106540201Skarels 		VOIDC   sprintf (temparg, "-#%s", spoolCopies);
106633295Skarels 
106740201Skarels 		addarg (argstr, temparg, &nargs);
106840201Skarels 	}
106940201Skarels 	if ((PrinterName == NULL) && ((PrinterName = envget ("PRINTER")) == NULL)) {
107040201Skarels 		PrinterName = POSTSCRIPTPRINTER;
107140201Skarels 	}
107240201Skarels 	VOIDC   sprintf (temparg, "-P%s", PrinterName);
107333295Skarels 
107440201Skarels 	addarg (argstr, temparg, &nargs);
107533295Skarels 
107640201Skarels 	if (spoolJobClass) {
107740201Skarels 		addarg (argstr, "-C", &nargs);
107840201Skarels 		addarg (argstr, spoolJobClass, &nargs);
107940201Skarels 	}
108040201Skarels 	addarg (argstr, "-J", &nargs);
108140201Skarels 	if (spoolJobName) {
108240201Skarels 		addarg (argstr, spoolJobName, &nargs);
108340201Skarels 	} else {
108440201Skarels 		if (!FileName)
108540201Skarels 			addarg (argstr, "stdin", &nargs);
108640201Skarels 		else
108740201Skarels 			addarg (argstr, FileName, &nargs);
108840201Skarels 	}
108940201Skarels 	if (spoolNotify) {
109040201Skarels 		addarg (argstr, "-m", &nargs);
109140201Skarels 	}
109240201Skarels 	if (spoolNoBurst) {
109340201Skarels 		addarg (argstr, "-h", &nargs);
109440201Skarels 	}
109540201Skarels 	/* remove the temporary file after spooling */
109640201Skarels 	addarg (argstr, "-r", &nargs);	/* should we use a symbolic link too? */
109740201Skarels 	addarg (argstr, TempName, &nargs);
109833295Skarels 
109933295Skarels #ifdef DEBUG
110040201Skarels 	{
110140201Skarels 		int     i;
110240201Skarels 
110340201Skarels 		fprintf (stderr, "called spooler with: ");
110440201Skarels 		for (i = 0; i < nargs; i++)
110540201Skarels 			fprintf (stderr, "(%s)", argstr[i]);
110640201Skarels 		fprintf (stderr, "\n");
110740201Skarels 	}
110833295Skarels #endif
110933295Skarels 
111040201Skarels 	execvp (LPR, argstr);
111140201Skarels 	pexit2 (prog, "can't exec spooler", 1);
111233295Skarels }
111333295Skarels 
111433295Skarels 
111533295Skarels private char *eargv[60];
111633295Skarels private int eargc = 1;
111733295Skarels 
111833295Skarels 
main(argc,argv)111940201Skarels main (argc, argv)
112040201Skarels 	int     argc;
112140201Skarels 	char  **argv;
112240201Skarels {
112340201Skarels 	register char *p;	/* pointer to "ENSCRIPT" in env */
112433295Skarels 
112540201Skarels 	prog = *argv;		/* argv[0] is program name */
112633295Skarels 
112740201Skarels 	debugp ((stderr, "PL %ld PW %ld TPL %ld TPW %ld\n", PageLength, PageWidth, TruePageLength, TruePageWidth));
112833295Skarels 
112940201Skarels 	if (signal (SIGINT, int1) == SIG_IGN) {
113040201Skarels 		VOIDC   signal (SIGINT, SIG_IGN);
113140201Skarels 		VOIDC   signal (SIGQUIT, SIG_IGN);
113240201Skarels 		VOIDC   signal (SIGHUP, SIG_IGN);
113340201Skarels 		VOIDC   signal (SIGTERM, SIG_IGN);
113440201Skarels 	} else {
113540201Skarels 		VOIDC   signal (SIGQUIT, int1);
113640201Skarels 		VOIDC   signal (SIGHUP, int1);
113740201Skarels 		VOIDC   signal (SIGTERM, int1);
113840201Skarels 	}
113933295Skarels 
114040201Skarels 	{
114140201Skarels 		register int i;
114233295Skarels 
114340201Skarels 		for (i = 0; i < 26; i++)
114440201Skarels 			fontindex[i] = -1;
114540201Skarels 	}
114633295Skarels 
114740201Skarels 	if ((libdir = envget ("PSLIBDIR")) == NULL)
114840201Skarels 		libdir = LibDir;
114940201Skarels 	if ((tempdir = envget ("PSTEMPDIR")) == NULL)
115040201Skarels 		tempdir = TempDir;
115133295Skarels 
115240521Skarels 	Roman = CurFont = DefineFont (BODYROMAN, BODYSZ);
115340538Skarels 	HeaderFont = DefineFont (HEADFONT, HEADSZ);
115440201Skarels 
115540201Skarels 	/* process args in environment variable ENSCRIPT */
115640201Skarels 	if (p = envget ("ENSCRIPT")) {
115740201Skarels 		while (1) {
115840201Skarels 			register char quote = ' ';
115940201Skarels 
116040201Skarels 			while (*p == ' ')
116140201Skarels 				p++;
116240201Skarels 			if ((*p == '"') || (*p == '\''))
116340201Skarels 				quote = *p++;
116440201Skarels 			eargv[eargc++] = p;
116540201Skarels 			while ((*p != quote) && (*p != '\0'))
116640201Skarels 				p++;
116740201Skarels 			if (*p == '\0')
116840201Skarels 				break;
116940201Skarels 			*p++ = '\0';
117040201Skarels 		}
117140201Skarels 		ParseArgs (eargc, eargv);
117240201Skarels 		if (eargc != optind) {
117340201Skarels 			fprintf (stderr, "%s: bad environment variable ENSCRIPT \"%s\"\n",
117440201Skarels 				 prog, envget ("ENSCRIPT"));
117540201Skarels 			exit (1);
117640201Skarels 		}
117733295Skarels 	}
117840201Skarels 	/* process the command line arguments */
117940201Skarels 	optind = 1;		/* reset getopt global */
118040201Skarels 	ParseArgs (argc, argv);
118133295Skarels 
118240201Skarels 	/* process non-option args */
118340201Skarels 	for (; optind < argc; optind++) {
118440201Skarels 		FileName = Header = argv[optind];
118540201Skarels 		if (freopen (FileName, "r", stdin) == NULL) {
118640201Skarels 			fprintf (stderr, "%s: can't open %s\n", prog, FileName);
118740201Skarels 			exit (1);
118840201Skarels 		}
118940201Skarels 		VOIDC   fstat (fileno (stdin), &S);
119033295Skarels 
119140201Skarels 		SetTime (S.st_mtime);
119240201Skarels 		CopyFile ();
119340201Skarels 		VOIDC   fclose (stdin);
119440201Skarels 
119540201Skarels 		SeenFile = TRUE;
119633295Skarels 	}
119740201Skarels 	if (!SeenFile) {
119840201Skarels 		FileName = Header = Gaudy ? "" : 0;
119940201Skarels 		VOIDC   fstat (fileno (stdin), &S);
120033295Skarels 
120140201Skarels 		if ((S.st_mode & S_IFMT) == S_IFREG)
120240201Skarels 			SetTime (S.st_mtime);
120340201Skarels 		else
120440201Skarels 			SetTime (time ((long *) 0));
120540201Skarels 		CopyFile ();
120640201Skarels 	}
120740201Skarels 	if (Cvted) {
120840201Skarels 		ClosePS ();
120940201Skarels 		VOIDC   fclose (OutFile);
121033295Skarels 
121140201Skarels 		OutFile = 0;
121233295Skarels 	}
121340201Skarels 	if (TruncChars && !BeQuiet)
121440201Skarels 		fprintf (stderr, "%s: %d characters omitted because of long lines.\n",
121540201Skarels 			 prog, TruncChars);
121640201Skarels 	if (UndefChars && !BeQuiet)
121740201Skarels 		fprintf (stderr, "%s: %d characters omitted because of incomplete fonts.\n",
121840201Skarels 			 prog, UndefChars);
121940521Skarels 	if (Verbose && (TotalPages > 0)) {
122040521Skarels 	    fprintf(stderr,"[ %d page%s * %s cop%s ]\n",
122140521Skarels 		    TotalPages, TotalPages > 1 ? "s" : "",
122240521Skarels 		    spoolCopies, atoi(spoolCopies) > 1 ? "ies" : "y" );
122333295Skarels 	}
122440521Skarels 	if (Cvted && !OutOnly) {
122540521Skarels 		SpoolIt ();	/* does an exec */
122640201Skarels 	}
122733295Skarels }
122833295Skarels 
122933295Skarels 
123033295Skarels /* signal catcher */
123140201Skarels private VOID
int1()123240201Skarels int1 ()
123340201Skarels {
123440201Skarels 	if ((!PipeOut) && (OutName != NULL) && (*OutName != '\0')) {
123540201Skarels 		VOIDC   unlink (OutName);
123640201Skarels 	}
123740201Skarels 	exit (1);
123833295Skarels }
1239