133295Skarels #ifndef lint
233295Skarels static char Notice[] = "Copyright (c) 1985 Adobe Systems Incorporated";
3*40564Skarels static char sccsid[] = "@(#)enscript.c	1.6 (Berkeley) 03/22/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 */
12033295Skarels private 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 
12933295Skarels private int TabWidth = TruePageWidth / 10;	/* 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 col;		/* column number on current line */
15033295Skarels private int SeenText = TRUE;	/* true if seen some text on this page */
15133295Skarels private int OutOnly = FALSE;	/* PS file only wanted */
15233295Skarels private int Rotated = FALSE;	/* pages to be rotated landscape */
15333295Skarels private int PreFeed = FALSE;	/* prefeed should be enabled */
15433295Skarels private int TwoColumn = FALSE;	/* two-column mode */
15533295Skarels private int FirstCol = TRUE;	/* we're printing column 1 */
15633295Skarels private int NoTitle = FALSE;	/* title line is suppressed */
15733295Skarels private int Cvted = FALSE;	/* converted a file to PS format */
15833295Skarels 
15940201Skarels private int IgnoreGarbage = FALSE;	/* garbage should be ignored */
16040521Skarels private int SeenFont = FALSE;	/* we've seen a font request */
16133295Skarels private int SeenFile = FALSE;	/* a file has been processed */
16240201Skarels private int ScannedFonts = FALSE;	/* we've scanned the font file */
16333295Skarels private char *FileName = 0;	/* name of file currently being PSed */
16433295Skarels private char *FileDate = 0;	/* last mod date of file being PSed */
16533295Skarels private char DateStr[27];	/* thanks, but no thanks ctime! */
16640201Skarels private int spoolNoBurst = FALSE;	/* no break page flag for spooler */
16733295Skarels 
16833295Skarels #ifdef BSD
16933295Skarels private char *spoolJobClass = NULL;
17033295Skarels private char *spoolJobName = NULL;
17140201Skarels 
17233295Skarels #endif
17333295Skarels private char *PrinterName = NULL;
17433295Skarels private int spoolNotify = 0;
17533295Skarels private char *spoolCopies = "1";
17633295Skarels 
17733295Skarels private char tempstr[256];	/* various path names */
17833295Skarels 
17933295Skarels private int CurFont;		/* current Font */
18040201Skarels private int fontindex[26];	/* table of fonts, indexed by font designator
18140201Skarels 				 * ('a' to 'z') */
18240201Skarels 
18333295Skarels /* indexes for default fonts */
18433295Skarels 
18533295Skarels #define Roman fontindex['r'-'a']
18633295Skarels #define HeaderFont fontindex['h'-'a']
18740201Skarels #define SHeaderFont fontindex['i'-'a']
18840201Skarels #define DateFont fontindex['j'-'a']
18940201Skarels #define PgNumFont fontindex['k'-'a']
19033295Skarels 
19133295Skarels private long cX, cY;		/* current page positions */
19233295Skarels private long dX, dY;		/* desired page positions */
19333295Skarels private long lX, lY;		/* page positions of the start of the line */
19433295Skarels private long crX, crY;		/* X and Y increments to apply to CR's */
19533295Skarels private long maxX;		/* maximum x coord on line */
19633295Skarels private long minY;		/* minimum y coord on page */
19740201Skarels private long Xoffset;		/* amount to offset left margin */
19833295Skarels 
19933295Skarels #define None	0
20033295Skarels #define RelX	1
20133295Skarels #define	RelY	2
20233295Skarels #define RelXY	3
20333295Skarels #define AbsX	4
20433295Skarels #define AbsY	8
20533295Skarels #define AbsXY	12
20633295Skarels 
20733295Skarels private int movepending;	/* moveto pending coords on stack */
20833295Skarels private int showpending;	/* number of characters waiting to be shown */
20940201Skarels private int pagepending;	/* start on next page when have something to
21040201Skarels 				 * print */
21140201Skarels private char *UsersHeader = NULL;	/* user specified heading */
21233295Skarels private char *Header = NULL;	/* generated header (usually FileName) */
21340521Skarels private char *Header2 = NULL;	/* second header line for Gaudy */
21433295Skarels private int Page = 0;		/* current page number */
21533295Skarels private int TotalPages = 0;	/* total number of pages printed */
21633295Skarels private int TruncChars = 0;	/* number of characters truncated */
21740201Skarels private int UndefChars = 0;	/* number of characters skipped because they
21840201Skarels 				 * weren't defined in some font */
21940201Skarels private int BadChars = 0;	/* number of bad characters seen so far */
22033295Skarels private FILE *OutFile = NULL;	/* output ps file */
22133295Skarels 
22233295Skarels 
22333295Skarels /* decode a fontname string - e.g. Courier10 Helvetica-Bold12 */
22440201Skarels private
22540201Skarels decodefont (name, f)
22640201Skarels 	register char *name;
22740201Skarels 	register struct font *f;
22840201Skarels {
22940201Skarels 	register char *d, *p;
23033295Skarels 
23140201Skarels 	p = name;
23240201Skarels 	d = f->name;
23340201Skarels 	f->dsize = 0;
23440201Skarels 	while (isascii (*p) && (isalpha (*p) || (*p == '-'))) {
23540201Skarels 		*d++ = *p++;
23640201Skarels 	}
23740201Skarels 	*d++ = '\0';
23840201Skarels 	while (isascii (*p) && isdigit (*p)) {
23940201Skarels 		f->dsize = f->dsize * 10 + *p++ - '0';
24040201Skarels 	}
24140201Skarels 	if (*p || !f->dsize || !f->name[0]) {
24240201Skarels 		fprintf (stderr, "%s: poorly formed font name & size: \"%s\"\n",
24340201Skarels 			 prog, name);
24440201Skarels 		exit (1);
24540201Skarels 	}
24633295Skarels }
24740201Skarels 
24840201Skarels 
24933295Skarels #define NOTDEF 0x8000
25033295Skarels #define ForAllFonts(p) for(p = &fonts[nf-1]; p >= &fonts[0]; p--)
25133295Skarels 
25233295Skarels 
25340201Skarels /*
25440201Skarels  * Scan the font metrics directory looking for entries that match the entries
25540201Skarels  * in ``fonts''.  For entries that are found the data in the font description
25640201Skarels  * is filled in, if any are missing, it dies horribly.
25733295Skarels  */
25840201Skarels private VOID ScanFont ()
25940201Skarels {
26040201Skarels 	register struct font *f;
26140201Skarels 	register FILE *FontData;/* afm file */
26240201Skarels 	char   *c;
26340201Skarels 	int     ccode, cwidth, inChars;
26440201Skarels 	char    FontFile[512];	/* afm file name */
26540201Skarels 	char    afmbuf[BUFSIZ];
26633295Skarels 
26733295Skarels 
26840201Skarels 	if (!SeenFont) {
26940201Skarels 		if (Lines == 0)
27040201Skarels 			Lines = 64;
27140201Skarels 		if (Rotated && TwoColumn)
27240201Skarels 			fonts[Roman].dsize = 7;
27333295Skarels 	}
27440201Skarels 	/* loop through fonts, find and read metric entry in dir */
27540201Skarels 	ForAllFonts (f) {
27640201Skarels 		VOIDC   mstrcat (FontFile, libdir, "/", sizeof FontFile);
27733295Skarels 
27840201Skarels 		VOIDC   mstrcat (FontFile, FontFile, f->name, sizeof FontFile);
27940201Skarels 
28040201Skarels 		VOIDC   mstrcat (FontFile, FontFile, ".afm", sizeof FontFile);
28140201Skarels 
28240201Skarels 		if ((FontData = fopen (FontFile, "r")) == NULL) {
28340201Skarels 			fprintf (stderr, "%s: can't open font metrics file %s\n",
28440201Skarels 				 prog, FontFile);
28540201Skarels 			exit (1);
28633295Skarels 		}
28740201Skarels 		/* read the .afm file to get the widths */
28840201Skarels 		for (ccode = 0; ccode < FSIZEMAX; ccode++)
28940201Skarels 			f->Xwid[ccode] = NOTDEF;
29040201Skarels 
29140201Skarels 		inChars = 0;
29240201Skarels 		while (fgets (afmbuf, sizeof afmbuf, FontData) != NULL) {
29340201Skarels 			/* strip off newline */
29440201Skarels 			if ((c = INDEX (afmbuf, '\n')) == 0) {
29540201Skarels 				fprintf (stderr, "%s: AFM file %s line too long %s\n",
29640201Skarels 					 prog, FontFile, afmbuf);
29740201Skarels 				exit (1);
29840201Skarels 			}
29940201Skarels 			*c = '\0';
30040201Skarels 			if (*afmbuf == '\0')
30140201Skarels 				continue;
30240201Skarels 			if (strcmp (afmbuf, "StartCharMetrics") == 0) {
30340201Skarels 				inChars++;
30440201Skarels 				continue;
30540201Skarels 			}
30640201Skarels 			if (strcmp (afmbuf, "EndCharMetrics") == 0)
30740201Skarels 				break;
30840201Skarels 			if (inChars == 1) {
30940201Skarels 				if (sscanf (afmbuf, "C %d ; WX %d ;", &ccode, &cwidth) != 2) {
31040201Skarels 					fprintf (stderr, "%s: trouble with AFM file %s\n",
31140201Skarels 						 prog, FontFile);
31240201Skarels 					exit (1);
31340201Skarels 				}
31440201Skarels 				/* get out once we see an unencoded char */
31540201Skarels 				if (ccode == -1)
31640201Skarels 					break;
31740201Skarels 				if (ccode > 255)
31840201Skarels 					continue;
31940201Skarels 				f->Xwid[ccode] =
32040201Skarels 					(short) (((long) cwidth * (long) f->dsize * (long) UperPt)
32140201Skarels 						 / 1000L);
32240201Skarels 				continue;
32340201Skarels 			}
32440201Skarels 		}
32540201Skarels 		VOIDC   fclose (FontData);
32633295Skarels 	}
32733295Skarels 
32840201Skarels 	TabWidth = fonts[Roman].Xwid['0'] * 8;	/* 8 * figure width */
32940201Skarels 	BSWidth = fonts[Roman].Xwid[' '];	/* space width */
33033295Skarels 
33140201Skarels 	UperLine = (fonts[Roman].dsize + 1) * UperPt;
33233295Skarels 
33340201Skarels 	if (LPTsimulate) {
33440201Skarels 		UperHLine = UperLine;
33540201Skarels 		Lines = LineMax = 66;
33640201Skarels 	} else {
33740201Skarels 		UperHLine = (fonts[HeaderFont].dsize + 1) * UperPt;
33840201Skarels 	}
33933295Skarels 
34040201Skarels 	crX = 0;
34140201Skarels 	crY = -UperLine;
34233295Skarels 
34333295Skarels }
34433295Skarels 
34533295Skarels 
34640201Skarels /*
34740201Skarels  * Return a font number for the font with the indicated name and size.  Adds
34840201Skarels  * info to the font list for the eventual search.
34933295Skarels  */
35040201Skarels private int
35140201Skarels DefineFont (name, size)
35240201Skarels 	char   *name;
35340201Skarels {
35440201Skarels 	register struct font *p;
35540201Skarels 
35640201Skarels 	p = &fonts[nf];
35740201Skarels 	VOIDC   strcpy (p->name, name);
35840201Skarels 
35940201Skarels 	p->dsize = size;
36040201Skarels 	return (nf++);
36133295Skarels }
36233295Skarels 
36340538Skarels ResetFont(indx, name, size)
36440538Skarels 	char   *name;
36540538Skarels {
36640538Skarels 	register struct font *p;
36733295Skarels 
36840538Skarels 	p = &fonts[indx];
36940538Skarels 	VOIDC   strcpy (p->name, name);
37040538Skarels 	p->dsize = size;
37140538Skarels }
37240538Skarels 
37333295Skarels /* dump the fonts to the PS file for setup */
37440201Skarels private VOID
37540201Skarels DumpFonts ()
37640201Skarels {
37740201Skarels 	register struct font *f;
37833295Skarels 
37940201Skarels 	ForAllFonts (f) {
38040201Skarels 		fprintf (OutFile, "%d %d /%s\n", f - &fonts[0], f->dsize * UperPt, f->name);
38140201Skarels 	}
38240201Skarels 	fprintf (OutFile, "%d SetUpFonts\n", nf);
38333295Skarels }
38433295Skarels 
38533295Skarels /* add a shown character to the PS file */
38640201Skarels private VOID
38740201Skarels OUTputc (c)
38840201Skarels 	register int c;
38940201Skarels {
39040201Skarels 	if (!showpending) {
39140201Skarels 		putc ('(', OutFile);
39240201Skarels 		showpending = TRUE;
39340201Skarels 	}
39440201Skarels 	if (c == '\\' || c == '(' || c == ')')
39540201Skarels 		putc ('\\', OutFile);
39640201Skarels 	if ((c > 0176) || (c < 040)) {
39740201Skarels 		putc ('\\', OutFile);
39840201Skarels 		putc ((c >> 6) + '0', OutFile);
39940201Skarels 		putc (((c >> 3) & 07) + '0', OutFile);
40040201Skarels 		putc ((c & 07) + '0', OutFile);
40140201Skarels 	} else
40240201Skarels 		putc (c, OutFile);
40333295Skarels }
40433295Skarels 
40540201Skarels /* put a correctly escaped string to the PS file */
40640201Skarels private VOID
40740201Skarels OUTstr(s)
40840201Skarels 	register char *s;
40940201Skarels {
41040201Skarels 	if (!showpending) {
41140201Skarels 		putc ('(', OutFile);
41240201Skarels 		showpending = TRUE;
41340201Skarels 	}
41440201Skarels 	while (*s)
41540201Skarels 		OUTputc(*s++);
41640201Skarels 
41740201Skarels 	putc(')', OutFile);
41840201Skarels 	showpending = FALSE;
41940201Skarels }
42040201Skarels 
42133295Skarels /* Set the current font */
42240201Skarels private VOID
42340201Skarels SetFont (f)
42440201Skarels 	int     f;
42540201Skarels {
42640201Skarels 	FlushShow ();
42740201Skarels 	CurFont = f;
42840201Skarels 	fprintf (OutFile, "%d F\n", f);
42933295Skarels }
43033295Skarels 
43140201Skarels /*
43240201Skarels  * put a character onto the page at the desired X and Y positions. If the
43340201Skarels  * current position doesn't agree with the desired position, put out movement
43440201Skarels  * directives.  Leave the current position updated to account for the
43540201Skarels  * character.
43633295Skarels  */
43740201Skarels private VOID
43840201Skarels ShowChar (c)
43940201Skarels 	register int c;
44040201Skarels {
44140201Skarels 	register struct font *f;
44240201Skarels 	register long nX, nY;
44340201Skarels 	static  level = 0;
444*40564Skarels 	VOID PageEject(), InitPage();
44533295Skarels 
44640201Skarels 	level++;
44740201Skarels 	f = &fonts[CurFont];
44833295Skarels 
44940201Skarels 	if (f->Xwid[c] == NOTDEF) {
45040201Skarels 		UndefChars++;
45140201Skarels 		if (ListOmitted)
45240201Skarels 			fprintf (stderr, "%s: \\%03o not found in font %s\n",
45340201Skarels 				 prog, c, f->name);
45440201Skarels 		if (level <= 1) {
45540201Skarels 			ShowChar ('\\');
45640201Skarels 			ShowChar ((c >> 6) + '0');
45740201Skarels 			ShowChar (((c >> 3) & 07) + '0');
45840201Skarels 			ShowChar ((c & 07) + '0');
45940201Skarels 			col += 3;
46040201Skarels 		}
46140201Skarels 		level--;
46240201Skarels 		return;
46333295Skarels 	}
46440201Skarels 	nX = dX + f->Xwid[c];	/* resulting position after showing this char */
46540201Skarels 	nY = dY;
46633295Skarels 
46740201Skarels 	if (c != ' ' || ((cX == dX) && (cY == dY))) {
46840521Skarels 		/*
46940521Skarels 		 * If character doesn't fit on this line
47040521Skarels 		 * (and we're not at left margin), simulate newline
47140521Skarels 		 * and then call ourselves recursively.
47240521Skarels 		 */
47340521Skarels 		if (nX > maxX && dX > lX) {
47440521Skarels 			SeenText = TRUE;
47540521Skarels 			dY = lY = lY + crY;
47640521Skarels 			dX = lX = lX + crX;
477*40564Skarels 			if ((dY < minY) || (--LinesLeft <= 0)) {
47840521Skarels 				PageEject ();
479*40564Skarels 				if (pagepending)
480*40564Skarels 					InitPage ();
481*40564Skarels 			}
48240521Skarels 			col = 1;
48340521Skarels 			ShowChar(c);
484*40564Skarels 			col++;
48540521Skarels 			level--;
48640521Skarels 			return;
48740521Skarels 		}
48840521Skarels 		if (cX != dX) {
48940521Skarels 			if (cY != dY) {
49040201Skarels 				FlushShow ();
49140521Skarels 				/* absolute x, relative y */
49240521Skarels 				fprintf (OutFile, "%ld %ld", dX, dY);
49340521Skarels 				movepending = AbsXY;
49440521Skarels 			} else {
49540521Skarels 				FlushShow ();
49640521Skarels 				fprintf (OutFile, "%ld", dX - cX);	/* relative x */
49740521Skarels 				movepending = RelX;
49840201Skarels 			}
49940521Skarels 		} else if (cY != dY) {
50040521Skarels 			FlushShow ();
50140521Skarels 			fprintf (OutFile, "%ld", dY - cY);	/* relative y */
50240521Skarels 			movepending = RelY;
50340521Skarels 		}
50440521Skarels 		OUTputc (c);
50540521Skarels 		showpending = TRUE;
50640521Skarels 		cX = nX;
50740521Skarels 		cY = nY;
50833295Skarels 	}
50940201Skarels 	dX = nX;
51040201Skarels 	dY = nY;
51133295Skarels 
51240201Skarels 	level--;
51333295Skarels }
51433295Skarels 
51533295Skarels /* put out a shown string to the PS file */
51640201Skarels private VOID
51740201Skarels ShowStr (s)
51840201Skarels 	register char *s;
51940201Skarels {
52040201Skarels 	while (*s) {
52140201Skarels 		if (*s >= 040)
52240201Skarels 			ShowChar (*s);
52340201Skarels 		s++;
52440201Skarels 	}
52533295Skarels }
52633295Skarels 
52733295Skarels /* flush pending show */
52840201Skarels private
52940201Skarels FlushShow ()
53040201Skarels {
53140201Skarels 	if (showpending) {
53240201Skarels 		putc (')', OutFile);
53340201Skarels 		switch (movepending) {
53440201Skarels 		case RelX:
53540201Skarels 			putc ('X', OutFile);
53640201Skarels 			break;
53740201Skarels 		case RelY:
53840201Skarels 			putc ('Y', OutFile);
53940201Skarels 			break;
54040201Skarels 		case AbsXY:
54140201Skarels 			putc ('B', OutFile);
54240201Skarels 			break;
54340201Skarels 		case None:
54440201Skarels 			putc ('S', OutFile);
54540201Skarels 			break;
54640201Skarels 		}
54740201Skarels 		putc ('\n', OutFile);
54840201Skarels 		movepending = None;
54940201Skarels 		showpending = FALSE;
55033295Skarels 	}
55133295Skarels }
55233295Skarels 
55333295Skarels /* put out a page heading to the PS file */
55440201Skarels private VOID
55540201Skarels InitPage ()
55640201Skarels {
55740201Skarels 	char    header[200];
55840201Skarels 	register int OldFont = CurFont;
55933295Skarels 
56040201Skarels 	TotalPages++;
56140201Skarels 	fprintf (OutFile, "%%%%Page: ? %d\n", TotalPages);
56240201Skarels 	fprintf (OutFile, "StartPage\n");
56340201Skarels 	SeenText = FALSE;
56440201Skarels 	cX = cY = -1;
56540201Skarels 	showpending = pagepending = FALSE;
56640201Skarels 	FirstCol = TRUE;
56740201Skarels 	if (Rotated) {
56840201Skarels 		fprintf (OutFile, "Landscape\n");
56940201Skarels 		lX = dX = UperInch / 4 + Xoffset;
57040201Skarels 		lY = dY = PageLength - (UperHLine * 3) / 2;
57140201Skarels 		maxX = TruePageLength;
57240201Skarels 		/* minY = (PageLength - TruePageWidth) + 3*UperLine+480; */
57340201Skarels 		minY = (TruePageLength - TruePageWidth) + (TruePageWidth - PageWidth) / 2;
57440201Skarels 	} else {
57540201Skarels 		lX = dX = Xoffset +
57640201Skarels 			   (TwoColumn? (UperInch * 0.3) : ((UperInch * 5) / 8));
57740201Skarels 		lY = dY = PageLength - UperHLine;
57840201Skarels 		maxX = TruePageWidth;
57940201Skarels 		minY = (UperInch / 4);	/* 0.25 inches */
58040201Skarels 	}
58140201Skarels 	movepending = None;
58240201Skarels 	cX = dX;
58340201Skarels 	cY = dY;
58433295Skarels 
58540201Skarels 	if (!NoTitle) {
58640201Skarels 		if (Gaudy) {
58740201Skarels 			OUTstr(UsersHeader);
58840521Skarels 			if (Header2)
58940521Skarels 			    OUTstr(Header2);
59040521Skarels 			else
59140521Skarels 			    OUTstr(Header);
59240201Skarels 			fprintf (OutFile, "[%s](%d)Gaudy\n", FileDate, ++Page);
59340201Skarels 			cX = cY = 0;	/* force moveto here */
59440201Skarels 		} else {
59540201Skarels 			SetFont (HeaderFont);
59640201Skarels 			fprintf (OutFile, "%ld %ld ", cX, cY);
59740201Skarels 			movepending = AbsXY;
59840201Skarels 			if (UsersHeader) {
59940201Skarels 				if (*UsersHeader == 0) {
60040201Skarels 					fprintf (OutFile, "()B\n");
60140201Skarels 					movepending = None;
60240201Skarels 					showpending = FALSE;
60340201Skarels 				} else
60440201Skarels 					ShowStr (UsersHeader);
60540201Skarels 			} else {
60640201Skarels 				VOIDC sprintf (header, "%s        %s        %d",
60740201Skarels 					       Header? Header : "              ", FileDate, ++Page);
60840201Skarels 
60940201Skarels 				ShowStr (header);
61040201Skarels 			}
61140201Skarels 			FlushShow ();
61233295Skarels 		}
61340201Skarels 		dX = lX = lX + crX * 2;
61440201Skarels 		dY = lY = lY + crY * 2;
61540201Skarels 	} else {
61640201Skarels 		/* fake it to force a moveto */
61740201Skarels 		cX = cY = 0;
61833295Skarels 	}
61940201Skarels 	if (TwoColumn)
62040201Skarels 		maxX = maxX / 2 - BSWidth;
62140201Skarels 	else
62240201Skarels 		maxX -= ((long) (UperInch * 0.3));
62340201Skarels 	LineMax = (lY - minY) / (-crY);
62440201Skarels 	if ((Lines <= 0) || (Lines > LineMax))
62540201Skarels 		Lines = LinesLeft = LineMax;
62640201Skarels 	else
62740201Skarels 		LinesLeft = Lines;
62840201Skarels 	SetFont (OldFont);
62933295Skarels }
63033295Skarels 
63140201Skarels private VOID
63240201Skarels ClosePage ()
63340201Skarels {
63440201Skarels 	FlushShow ();
63540201Skarels 	if (!pagepending)
63640201Skarels 		fprintf (OutFile, "EndPage\n");
63740201Skarels 	pagepending = TRUE;
63833295Skarels }
63933295Skarels 
64033295Skarels /* skip to a new page */
64140201Skarels private VOID
64240201Skarels PageEject ()
64340201Skarels {
64440201Skarels 	if (TwoColumn && FirstCol) {
64540201Skarels 		FirstCol = FALSE;
64640201Skarels 		if (Rotated) {
64740201Skarels 			lY = dY = PageLength - (UperHLine * 3) / 2;
64840201Skarels 			lX = dX = Xoffset + TruePageLength / 2;
64940201Skarels 			maxX = TruePageLength - UperInch * 0.3;
65040201Skarels 		} else {
65140201Skarels 			lY = dY = PageLength - UperHLine;
65240201Skarels 			lX = dX = Xoffset + TruePageWidth / 2;
65340201Skarels 			maxX = TruePageWidth - UperInch * 0.3;
65440201Skarels 		}
65540201Skarels 		if (!NoTitle) {
65640201Skarels 			dX = lX = lX + crX * 2;
65740201Skarels 			dY = lY = lY + crY * 2;
65840201Skarels 		}
65940201Skarels 	} else
66040201Skarels 		ClosePage ();
66140201Skarels 	LinesLeft = Lines;
66240201Skarels 	SeenText = FALSE;
66333295Skarels }
66433295Skarels 
66540201Skarels private VOID
66640201Skarels CommentHeader ()
66740201Skarels {
66840201Skarels 	long    clock;
66940201Skarels 	struct passwd *pswd;
67040201Skarels 	char    hostname[40];
67140201Skarels 
67240201Skarels 	/* copy the file, prepending a new comment header */
67340201Skarels 	fprintf (OutFile, "%%!%s\n", COMMENTVERSION);
67440201Skarels 	fprintf (OutFile, "%%%%Creator: ");
67540201Skarels 	pswd = getpwuid ((int) getuid ());
67640201Skarels 	VOIDC   gethostname (hostname, (int) sizeof hostname);
67740201Skarels 
67840201Skarels 	fprintf (OutFile, "%s:%s (%s)\n", hostname, pswd->pw_name, pswd->pw_gecos);
67940201Skarels 	fprintf (OutFile, "%%%%Title: %s\n", (FileName ? FileName : "stdin"));
68040201Skarels 	fprintf (OutFile, "%%%%CreationDate: %s", (VOIDC time (&clock), ctime (&clock)));
68133295Skarels }
68233295Skarels 
68333295Skarels /* Copy the standard input file to the PS file */
68440201Skarels private VOID
68540201Skarels CopyFile ()
68640201Skarels {
68740201Skarels 	register int c;
68833295Skarels 
68940201Skarels 	col = 1;
69040201Skarels 	if (OutFile == 0) {
69140201Skarels 		if (OutOnly) {
69240201Skarels 			OutFile = PipeOut ? stdout : fopen (OutName, "w");
69340201Skarels 		} else {
69440201Skarels 			VOIDC   mktemp (mstrcat (TempName, tempdir,
69540201Skarels 				            ENSCRIPTTEMP, sizeof TempName));
69640201Skarels 			VOIDC   strcpy (OutName, TempName);
69740201Skarels 
69840201Skarels 			VOIDC   umask (077);
69940201Skarels 
70040201Skarels 			OutFile = fopen (TempName, "w");
70140201Skarels 		}
70233295Skarels 	}
70340201Skarels 	if (OutFile == NULL) {
70440201Skarels 		fprintf (stderr, "%s: can't create PS file %s\n", prog, TempName);
70540201Skarels 		exit (1);
70633295Skarels 	}
70740201Skarels 	if (!ScannedFonts) {
70840201Skarels 		ScannedFonts = TRUE;
70940201Skarels 		ScanFont ();
71033295Skarels 	}
71140201Skarels 	if (!Cvted) {
71240201Skarels 		CommentHeader ();
71340201Skarels 		if (nf) {
71440201Skarels 			register struct font *f;
71540201Skarels 
71640201Skarels 			fprintf (OutFile, "%%%%DocumentFonts:");
71740201Skarels 			ForAllFonts (f) {
71840201Skarels 				fprintf (OutFile, " %s", f->name);
71940201Skarels 			}
72040201Skarels 			fprintf (OutFile, "\n");
72140201Skarels 		}
72240201Skarels 		/* copy in fixed prolog */
72340201Skarels 		if (copyfile (mstrcat (tempstr, libdir, ENSCRIPTPRO, sizeof tempstr),
72440201Skarels 			      OutFile)) {
72540201Skarels 			fprintf (stderr, "%s: trouble copying prolog file\n", prog);
72640201Skarels 			exit (1);
72740201Skarels 		}
72840201Skarels 		fprintf (OutFile, "StartEnscriptDoc %% end fixed prolog\n");
72940201Skarels 		DumpFonts ();
73040201Skarels 		if (Gaudy)
73140201Skarels 			fprintf (OutFile, "%s %s InitGaudy\n",
73240201Skarels 				 Rotated ? "10.55" : "8.0", TwoColumn ? "true" : "false");
73340201Skarels 		if (PreFeed) {
73440201Skarels 			fprintf (OutFile, "true DoPreFeed\n");
73540201Skarels 		}
73640201Skarels 		fprintf (OutFile, "%%%%EndProlog\n");
73733295Skarels 	}
73840201Skarels 	Cvted = TRUE;
73933295Skarels 
74040201Skarels 	Page = 0;
74140201Skarels 	BadChars = 0;		/* give each file a clean slate */
74240201Skarels 	pagepending = TRUE;
74340201Skarels 	while ((c = getchar ()) != EOF)
74440201Skarels 		if ((c > 0177 || c < 0) && (!IgnoreGarbage)) {
74540201Skarels 			if (BadChars++ > MAXBAD) {	/* allow some kruft but
74640201Skarels 							 * not much */
74740201Skarels 				fprintf (stderr, "%s: \"%s\" not a text file? Try -g.\n",
74840201Skarels 				     prog, FileName ? FileName : "(stdin)");
74940201Skarels 				if (!PipeOut)
75040201Skarels 					VOIDC   unlink (OutName);
75140201Skarels 
75240201Skarels 				exit (1);
75340201Skarels 			}
75440201Skarels 		} else if (c >= ' ') {
75540201Skarels 			if (pagepending)
75640201Skarels 				InitPage ();
75740201Skarels 			ShowChar (c);
75840201Skarels 			col++;
75940201Skarels 		} else
76040201Skarels 			switch (c) {
76140201Skarels 			case 010:	/* backspace */
76240201Skarels 				dX -= BSWidth;
76333295Skarels 				break;
76440201Skarels 			case 015:	/* carriage return ^M */
76540201Skarels 				dY = lY;
76640201Skarels 				dX = lX;
76733295Skarels 				break;
76840201Skarels 			case 012:	/* linefeed ^J */
76940201Skarels 				if (pagepending)
77040201Skarels 					InitPage ();
77140201Skarels 				if (dX != lX || dY != lY || !LPTsimulate || SeenText) {
77240201Skarels 					SeenText = TRUE;
77340201Skarels 					dY = lY = lY + crY;
77440201Skarels 					dX = lX = lX + crX;
77540201Skarels 				} else
77640201Skarels 					LinesLeft = LineMax;
77740201Skarels 				if ((dY < minY) || (--LinesLeft <= 0))
77840201Skarels 					PageEject ();
77940201Skarels 				col = 1;
78040201Skarels 				break;
78140201Skarels 			case 033:	/* escape */
78240201Skarels 				switch (c = getchar ()) {
78340201Skarels 				case '7':	/* backup one line */
78440201Skarels 					dY = lY = lY - crY;
78540201Skarels 					dX = lX = lX - crX;
78640201Skarels 					break;
78740201Skarels 				case '8':	/* backup 1/2 line */
78840201Skarels 					dY -= crY / 2;
78940201Skarels 					dX -= crX / 2;
79040201Skarels 					break;
79140201Skarels 				case '9':	/* forward 1/2 linefeed */
79240201Skarels 					dY += crY / 2;
79340201Skarels 					dX += crX / 2;
79440201Skarels 					break;
79540201Skarels 				case 'F':	/* font setting */
79640201Skarels 					c = getchar ();
79740201Skarels 					if ('a' <= c && c <= 'z')
79840201Skarels 						if (fontindex[c - 'a'] >= 0)
79940201Skarels 							SetFont (fontindex[c - 'a']);
80040201Skarels 						else {
80140201Skarels 							fprintf (stderr, "%s: font '%c' not defined\n",
80240201Skarels 								 prog, c);
80340201Skarels 							exit (1);
80440201Skarels 						}
80540201Skarels 					else {
80640201Skarels 						fprintf (stderr, "%s: bad font code in file: '%c'\n",
80740201Skarels 							 prog, c);
80840201Skarels 						exit (1);
80940201Skarels 					}
81040201Skarels 					break;
81140201Skarels 				case 'D':	/* date string */
81240201Skarels 					VOIDC fgets (DateStr, sizeof(DateStr), stdin);
81340201Skarels 					FileDate = DateStr;
81440201Skarels 					break;
81540201Skarels 				case 'U':	/* new "user's" heading */
81640201Skarels 					{
81740201Skarels 						static char header[100];
81840201Skarels 						VOIDC   fgets (header, sizeof(header), stdin);
81933295Skarels 
82040201Skarels 						UsersHeader = header;
82140201Skarels 						break;
82240201Skarels 					}
82340201Skarels 				case 'H':	/* new heading */
82440201Skarels 					{
82540201Skarels 						static char header[100];
82640201Skarels 
82740201Skarels 						VOIDC   fgets (header, sizeof(header), stdin);
82840201Skarels 
82940201Skarels 						ClosePage ();
83040521Skarels 						Header2 = header;
83140201Skarels 						Page = 0;
83240201Skarels 						break;
83340201Skarels 					}
83440201Skarels 				}
83533295Skarels 				break;
83640201Skarels 			case '%':	/* included PostScript line */
83740201Skarels 				{
83840201Skarels 					char    psline[200];
83940201Skarels 					VOIDC   fgets (psline, sizeof(psline), stdin);
84040201Skarels 
84140201Skarels 					fprintf (OutFile, "%s\n", psline);
84240201Skarels 					break;
84340201Skarels 				}
84440201Skarels 			case 014:	/* form feed ^L */
84540201Skarels 				PageEject ();
84640201Skarels 				col = 1;
84740201Skarels 				break;
84840201Skarels 			case 011:	/* tab ^I */
84940201Skarels 				if (pagepending)
85040201Skarels 					InitPage ();
85140201Skarels 				col = (col - 1) / 8 * 8 + 9;
85240201Skarels 				dX = lX + (col - 1) / 8 * TabWidth;
85340201Skarels 				break;
85440201Skarels 			default:	/* other control character, take your
85540201Skarels 					 * chances */
85640201Skarels 				if (pagepending)
85740201Skarels 					InitPage ();
85840201Skarels 				ShowChar (c);
85940201Skarels 				col++;
86040201Skarels 			}
86140201Skarels 	ClosePage ();
86233295Skarels }
86333295Skarels 
86433295Skarels 
86533295Skarels /*
86640201Skarels  * close the PS file
86733295Skarels  */
86840201Skarels private VOID
86940201Skarels ClosePS ()
87040201Skarels {
87140201Skarels 	fprintf (OutFile, "%%%%Trailer\n");
87240201Skarels 	if (PreFeed) {
87340201Skarels 		fprintf (OutFile, "false DoPreFeed\n");
87440201Skarels 	}
87540201Skarels 	fprintf (OutFile, "EndEnscriptDoc\nEnscriptJob restore\n");
87633295Skarels }
87733295Skarels 
87833295Skarels 
87940201Skarels private VOID
88040201Skarels SetTime (tval)
88140201Skarels 	long    tval;
88240201Skarels {
88340201Skarels 	struct tm *tp;
88433295Skarels 
88540201Skarels 	if (Gaudy) {
88640201Skarels 		tp = localtime (&tval);
88740201Skarels 		VOIDC   sprintf (DateStr, "(%02d/%02d/%02d)(%02d:%02d:%02d)",
88840201Skarels 			           tp->tm_year, tp->tm_mon + 1, tp->tm_mday,
88940201Skarels 			               tp->tm_hour, tp->tm_min, tp->tm_sec);
89040201Skarels 	} else {
89140201Skarels 		VOIDC   strcpy (DateStr, ctime (&tval));
89233295Skarels 
89340201Skarels 		DateStr[24] = '\0';	/* get rid of newline */
89440201Skarels 	}
89540201Skarels 
89640201Skarels 	FileDate = DateStr;
89733295Skarels }
89833295Skarels 
89933295Skarels 
90033295Skarels 
90133295Skarels 
90240521Skarels #define ARGS "12gGBlL:oqrRkKf:F:b:p:J:C:P:#:mhO:s:v"
90333295Skarels 
90440201Skarels private VOID ParseArgs (ac, av)
90540201Skarels 	int     ac;
90640201Skarels 	char  **av;
90740201Skarels {
90840201Skarels 	int     argp;
90940201Skarels 
91040201Skarels 	while ((argp = getopt (ac, av, ARGS)) != EOF) {
91140201Skarels 		debugp ((stderr, "option: %c\n", argp));
91240201Skarels 		switch (argp) {
91340201Skarels 		case '1':
91440201Skarels 			TwoColumn = FALSE;
91540201Skarels 			break;
91640201Skarels 		case '2':
91740201Skarels 			TwoColumn = TRUE;
91840201Skarels 			break;
91940201Skarels 		case 'G':
92040201Skarels 			Gaudy = TRUE;
92140201Skarels 			if (UsersHeader == NULL)
92240201Skarels 				UsersHeader = "";
92340201Skarels 			if (Header == NULL)
92440201Skarels 				Header = "";
92540538Skarels 			/* warning: fonts must be defined in this order! */
92640538Skarels 			ResetFont(HeaderFont, GHEADFONT, GHEADSZ);
92740538Skarels 			if (SHeaderFont == -1)
92840538Skarels 				SHeaderFont = DefineFont(SHEADFONT, SHEADSZ);
92940521Skarels 			DateFont = DefineFont(DATEFONT, DATESZ);
93040521Skarels 			PgNumFont = DefineFont(PGNUMFONT, PGNUMSZ);
93140201Skarels 			break;
93240201Skarels 		case 'g':
93340201Skarels 			IgnoreGarbage = TRUE;
93440201Skarels 			break;
93540201Skarels 		case 'B':
93640201Skarels 			NoTitle = TRUE;
93740201Skarels 			break;
93840201Skarels 		case 'l':
93940201Skarels 			LPTsimulate = TRUE;
94040201Skarels 			NoTitle = TRUE;
94140201Skarels 			Lines = 66;
94240201Skarels 			break;
94340201Skarels 		case 'L':
94440201Skarels 			Lines = atoi (optarg);
94540201Skarels 			break;
94640201Skarels 		case 'o':
94740201Skarels 			ListOmitted = TRUE;
94840201Skarels 			break;
94940201Skarels 		case 'q':
95040201Skarels 			BeQuiet = TRUE;
95140201Skarels 			break;
95240201Skarels 		case 'r':
95340201Skarels 			Rotated = TRUE;
95440201Skarels 			break;
95540201Skarels 		case 'R':
95640201Skarels 			Rotated = FALSE;
95740201Skarels 			break;
95840201Skarels 		case 'k':
95940201Skarels 			PreFeed = TRUE;
96040201Skarels 			break;
96140201Skarels 		case 'K':
96240201Skarels 			PreFeed = FALSE;
96340201Skarels 			break;
96440201Skarels 		case 'f':{
96540201Skarels 				register char font = 'r';
96640201Skarels 				int    *whichfont;
96740201Skarels 
96840201Skarels 				if (*optarg == '-') {
96940201Skarels 					font = *++optarg;
97040201Skarels 					optarg++;
97140201Skarels 				}
97240201Skarels 				if ((font < 'a') || ('z' < font)) {
97340201Skarels 					fprintf (stderr,
97440201Skarels 						 "%s: '%c' isn't a valid font designator.\n",
97540201Skarels 						 prog, font);
97640201Skarels 					exit (1);
97740201Skarels 				}
97840201Skarels 				whichfont = &fontindex[font - 'a'];
97940201Skarels 				if (*whichfont < 0)
98040201Skarels 					*whichfont = nf++;
98140201Skarels 				decodefont (optarg, &fonts[*whichfont]);
98240521Skarels 				if (font == 'r')
98340521Skarels 					SeenFont++;
98440201Skarels 			}
98540201Skarels 			break;
98640201Skarels 		case 'F':
98740521Skarels 			if (HeaderFont == -1)
98840521Skarels 				HeaderFont = nf++;
98940201Skarels 			decodefont (optarg, &fonts[HeaderFont]);
99040201Skarels 			break;
99140201Skarels 		case 'b':
99240201Skarels 			UsersHeader = optarg;
99340201Skarels 			break;
99440521Skarels 		case 's':
99540521Skarels 			Header2 = optarg;
99640521Skarels 			break;
99740201Skarels 		case 'p':
99840201Skarels 			OutOnly = TRUE;
99940201Skarels 			VOIDC   strcpy (OutName, optarg);
100040201Skarels 
100140201Skarels 			if (strcmp (OutName, "-") == 0)
100240201Skarels 				PipeOut = TRUE;
100340201Skarels 			break;
100440201Skarels 		case 'h':
100540201Skarels 			spoolNoBurst = TRUE;
100640201Skarels 			break;
100740201Skarels 			/* BSD lpr options processing */
100840201Skarels 		case 'm':
100940201Skarels 			spoolNotify = argp;
101040201Skarels 			break;
101140201Skarels 		case '#':
101240201Skarels 			spoolCopies = optarg;
101340201Skarels 			break;
101440201Skarels 		case 'C':
101540201Skarels 			spoolJobClass = optarg;
101640201Skarels 			break;
101740201Skarels 		case 'J':
101840201Skarels 			spoolJobName = optarg;
101940201Skarels 			break;
102040201Skarels 		case 'P':
102140201Skarels 			PrinterName = optarg;
102240201Skarels 			break;
102340201Skarels 		case '?':
102440201Skarels 			/* bad option */
102540201Skarels 			break;
102640201Skarels 		case 'O':
102740201Skarels 			Xoffset = atof(optarg) * (double)UperInch;
102840201Skarels 			if (Xoffset < 0)
102940201Skarels 				Xoffset = 0;
103040201Skarels 			break;
103140521Skarels 		case 'v':
103240521Skarels 			Verbose = TRUE;
103340521Skarels 			break;
103440201Skarels 		default:
103540201Skarels 			break;
103633295Skarels 		}
103733295Skarels 	}
103833295Skarels }
103933295Skarels 
104033295Skarels 
104133295Skarels /* addarg is used to construct an argv for the spooler */
104240201Skarels private VOID
104340201Skarels addarg (argv, argstr, argc)
104440201Skarels 	char  **argv;
104540201Skarels 	char   *argstr;
104640201Skarels 	register int *argc;
104740201Skarels {
104840201Skarels 	register char *p = (char *) malloc ((unsigned) (strlen (argstr) + 1));
104940201Skarels 	VOIDC   strcpy (p, argstr);
105040201Skarels 
105140201Skarels 	argv[(*argc)++] = p;
105240201Skarels 	argv[*argc] = '\0';
105333295Skarels }
105433295Skarels 
105533295Skarels 
105640201Skarels private VOID
105740201Skarels SpoolIt ()
105840201Skarels {
105940201Skarels 	char    temparg[200];
106040201Skarels 	char   *argstr[200];
106140201Skarels 	int     nargs = 0;
106233295Skarels 
106333295Skarels 
106440201Skarels 	addarg (argstr, LPR, &nargs);
106540201Skarels 	/* BSD spooler */
106640201Skarels 	if (atoi (spoolCopies) > 1) {
106740201Skarels 		VOIDC   sprintf (temparg, "-#%s", spoolCopies);
106833295Skarels 
106940201Skarels 		addarg (argstr, temparg, &nargs);
107040201Skarels 	}
107140201Skarels 	if ((PrinterName == NULL) && ((PrinterName = envget ("PRINTER")) == NULL)) {
107240201Skarels 		PrinterName = POSTSCRIPTPRINTER;
107340201Skarels 	}
107440201Skarels 	VOIDC   sprintf (temparg, "-P%s", PrinterName);
107533295Skarels 
107640201Skarels 	addarg (argstr, temparg, &nargs);
107733295Skarels 
107840201Skarels 	if (spoolJobClass) {
107940201Skarels 		addarg (argstr, "-C", &nargs);
108040201Skarels 		addarg (argstr, spoolJobClass, &nargs);
108140201Skarels 	}
108240201Skarels 	addarg (argstr, "-J", &nargs);
108340201Skarels 	if (spoolJobName) {
108440201Skarels 		addarg (argstr, spoolJobName, &nargs);
108540201Skarels 	} else {
108640201Skarels 		if (!FileName)
108740201Skarels 			addarg (argstr, "stdin", &nargs);
108840201Skarels 		else
108940201Skarels 			addarg (argstr, FileName, &nargs);
109040201Skarels 	}
109140201Skarels 	if (spoolNotify) {
109240201Skarels 		addarg (argstr, "-m", &nargs);
109340201Skarels 	}
109440201Skarels 	if (spoolNoBurst) {
109540201Skarels 		addarg (argstr, "-h", &nargs);
109640201Skarels 	}
109740201Skarels 	/* remove the temporary file after spooling */
109840201Skarels 	addarg (argstr, "-r", &nargs);	/* should we use a symbolic link too? */
109940201Skarels 	addarg (argstr, TempName, &nargs);
110033295Skarels 
110133295Skarels #ifdef DEBUG
110240201Skarels 	{
110340201Skarels 		int     i;
110440201Skarels 
110540201Skarels 		fprintf (stderr, "called spooler with: ");
110640201Skarels 		for (i = 0; i < nargs; i++)
110740201Skarels 			fprintf (stderr, "(%s)", argstr[i]);
110840201Skarels 		fprintf (stderr, "\n");
110940201Skarels 	}
111033295Skarels #endif
111133295Skarels 
111240201Skarels 	execvp (LPR, argstr);
111340201Skarels 	pexit2 (prog, "can't exec spooler", 1);
111433295Skarels }
111533295Skarels 
111633295Skarels 
111733295Skarels private char *eargv[60];
111833295Skarels private int eargc = 1;
111933295Skarels 
112033295Skarels 
112140201Skarels main (argc, argv)
112240201Skarels 	int     argc;
112340201Skarels 	char  **argv;
112440201Skarels {
112540201Skarels 	register char *p;	/* pointer to "ENSCRIPT" in env */
112633295Skarels 
112740201Skarels 	prog = *argv;		/* argv[0] is program name */
112833295Skarels 
112940201Skarels 	debugp ((stderr, "PL %ld PW %ld TPL %ld TPW %ld\n", PageLength, PageWidth, TruePageLength, TruePageWidth));
113033295Skarels 
113140201Skarels 	if (signal (SIGINT, int1) == SIG_IGN) {
113240201Skarels 		VOIDC   signal (SIGINT, SIG_IGN);
113340201Skarels 		VOIDC   signal (SIGQUIT, SIG_IGN);
113440201Skarels 		VOIDC   signal (SIGHUP, SIG_IGN);
113540201Skarels 		VOIDC   signal (SIGTERM, SIG_IGN);
113640201Skarels 	} else {
113740201Skarels 		VOIDC   signal (SIGQUIT, int1);
113840201Skarels 		VOIDC   signal (SIGHUP, int1);
113940201Skarels 		VOIDC   signal (SIGTERM, int1);
114040201Skarels 	}
114133295Skarels 
114240201Skarels 	{
114340201Skarels 		register int i;
114433295Skarels 
114540201Skarels 		for (i = 0; i < 26; i++)
114640201Skarels 			fontindex[i] = -1;
114740201Skarels 	}
114833295Skarels 
114940201Skarels 	if ((libdir = envget ("PSLIBDIR")) == NULL)
115040201Skarels 		libdir = LibDir;
115140201Skarels 	if ((tempdir = envget ("PSTEMPDIR")) == NULL)
115240201Skarels 		tempdir = TempDir;
115333295Skarels 
115440521Skarels 	Roman = CurFont = DefineFont (BODYROMAN, BODYSZ);
115540538Skarels 	HeaderFont = DefineFont (HEADFONT, HEADSZ);
115640201Skarels 
115740201Skarels 	/* process args in environment variable ENSCRIPT */
115840201Skarels 	if (p = envget ("ENSCRIPT")) {
115940201Skarels 		while (1) {
116040201Skarels 			register char quote = ' ';
116140201Skarels 
116240201Skarels 			while (*p == ' ')
116340201Skarels 				p++;
116440201Skarels 			if ((*p == '"') || (*p == '\''))
116540201Skarels 				quote = *p++;
116640201Skarels 			eargv[eargc++] = p;
116740201Skarels 			while ((*p != quote) && (*p != '\0'))
116840201Skarels 				p++;
116940201Skarels 			if (*p == '\0')
117040201Skarels 				break;
117140201Skarels 			*p++ = '\0';
117240201Skarels 		}
117340201Skarels 		ParseArgs (eargc, eargv);
117440201Skarels 		if (eargc != optind) {
117540201Skarels 			fprintf (stderr, "%s: bad environment variable ENSCRIPT \"%s\"\n",
117640201Skarels 				 prog, envget ("ENSCRIPT"));
117740201Skarels 			exit (1);
117840201Skarels 		}
117933295Skarels 	}
118040201Skarels 	/* process the command line arguments */
118140201Skarels 	optind = 1;		/* reset getopt global */
118240201Skarels 	ParseArgs (argc, argv);
118333295Skarels 
118440201Skarels 	/* process non-option args */
118540201Skarels 	for (; optind < argc; optind++) {
118640201Skarels 		FileName = Header = argv[optind];
118740201Skarels 		if (freopen (FileName, "r", stdin) == NULL) {
118840201Skarels 			fprintf (stderr, "%s: can't open %s\n", prog, FileName);
118940201Skarels 			exit (1);
119040201Skarels 		}
119140201Skarels 		VOIDC   fstat (fileno (stdin), &S);
119233295Skarels 
119340201Skarels 		SetTime (S.st_mtime);
119440201Skarels 		CopyFile ();
119540201Skarels 		VOIDC   fclose (stdin);
119640201Skarels 
119740201Skarels 		SeenFile = TRUE;
119833295Skarels 	}
119940201Skarels 	if (!SeenFile) {
120040201Skarels 		FileName = Header = Gaudy ? "" : 0;
120140201Skarels 		VOIDC   fstat (fileno (stdin), &S);
120233295Skarels 
120340201Skarels 		if ((S.st_mode & S_IFMT) == S_IFREG)
120440201Skarels 			SetTime (S.st_mtime);
120540201Skarels 		else
120640201Skarels 			SetTime (time ((long *) 0));
120740201Skarels 		CopyFile ();
120840201Skarels 	}
120940201Skarels 	if (Cvted) {
121040201Skarels 		ClosePS ();
121140201Skarels 		VOIDC   fclose (OutFile);
121233295Skarels 
121340201Skarels 		OutFile = 0;
121433295Skarels 	}
121540201Skarels 	if (TruncChars && !BeQuiet)
121640201Skarels 		fprintf (stderr, "%s: %d characters omitted because of long lines.\n",
121740201Skarels 			 prog, TruncChars);
121840201Skarels 	if (UndefChars && !BeQuiet)
121940201Skarels 		fprintf (stderr, "%s: %d characters omitted because of incomplete fonts.\n",
122040201Skarels 			 prog, UndefChars);
122140521Skarels 	if (Verbose && (TotalPages > 0)) {
122240521Skarels 	    fprintf(stderr,"[ %d page%s * %s cop%s ]\n",
122340521Skarels 		    TotalPages, TotalPages > 1 ? "s" : "",
122440521Skarels 		    spoolCopies, atoi(spoolCopies) > 1 ? "ies" : "y" );
122533295Skarels 	}
122640521Skarels 	if (Cvted && !OutOnly) {
122740521Skarels 		SpoolIt ();	/* does an exec */
122840201Skarels 	}
122933295Skarels }
123033295Skarels 
123133295Skarels 
123233295Skarels /* signal catcher */
123340201Skarels private VOID
123440201Skarels int1 ()
123540201Skarels {
123640201Skarels 	if ((!PipeOut) && (OutName != NULL) && (*OutName != '\0')) {
123740201Skarels 		VOIDC   unlink (OutName);
123840201Skarels 	}
123940201Skarels 	exit (1);
124033295Skarels }
1241