xref: /plan9/sys/src/cmd/postscript/postprint/postprint.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier  *
3*219b2ee8SDavid du Colombier  * postprint - PostScript translator for ASCII files.
4*219b2ee8SDavid du Colombier  *
5*219b2ee8SDavid du Colombier  * A simple program that translates ASCII files into PostScript. All it really
6*219b2ee8SDavid du Colombier  * does is expand tabs and backspaces, handle character quoting, print text lines,
7*219b2ee8SDavid du Colombier  * and control when pages are started based on the requested number of lines per
8*219b2ee8SDavid du Colombier  * page.
9*219b2ee8SDavid du Colombier  *
10*219b2ee8SDavid du Colombier  * The PostScript prologue is copied from *prologue before any of the input files
11*219b2ee8SDavid du Colombier  * are translated. The program expects that the following procedures are defined
12*219b2ee8SDavid du Colombier  * in that file:
13*219b2ee8SDavid du Colombier  *
14*219b2ee8SDavid du Colombier  *	setup
15*219b2ee8SDavid du Colombier  *
16*219b2ee8SDavid du Colombier  *	  mark ... setup -
17*219b2ee8SDavid du Colombier  *
18*219b2ee8SDavid du Colombier  *	    Handles special initialization stuff that depends on how the program
19*219b2ee8SDavid du Colombier  *	    was called. Expects to find a mark followed by key/value pairs on the
20*219b2ee8SDavid du Colombier  *	    stack. The def operator is applied to each pair up to the mark, then
21*219b2ee8SDavid du Colombier  *	    the default state is set up.
22*219b2ee8SDavid du Colombier  *
23*219b2ee8SDavid du Colombier  *	pagesetup
24*219b2ee8SDavid du Colombier  *
25*219b2ee8SDavid du Colombier  *	  page pagesetup -
26*219b2ee8SDavid du Colombier  *
27*219b2ee8SDavid du Colombier  *	    Does whatever is needed to set things up for the next page. Expects
28*219b2ee8SDavid du Colombier  *	    to find the current page number on the stack.
29*219b2ee8SDavid du Colombier  *
30*219b2ee8SDavid du Colombier  *	l
31*219b2ee8SDavid du Colombier  *
32*219b2ee8SDavid du Colombier  *	  string l -
33*219b2ee8SDavid du Colombier  *
34*219b2ee8SDavid du Colombier  *	    Prints string starting in the first column and then goes to the next
35*219b2ee8SDavid du Colombier  *	    line.
36*219b2ee8SDavid du Colombier  *
37*219b2ee8SDavid du Colombier  *	L
38*219b2ee8SDavid du Colombier  *
39*219b2ee8SDavid du Colombier  *	  mark string column string column ... L mark
40*219b2ee8SDavid du Colombier  *
41*219b2ee8SDavid du Colombier  *	    Prints each string on the stack starting at the horizontal position
42*219b2ee8SDavid du Colombier  *	    selected by column. Used when tabs and spaces can be sufficiently well
43*219b2ee8SDavid du Colombier  *	    compressed to make the printer overhead worthwhile. Always used when
44*219b2ee8SDavid du Colombier  *	    we have to back up.
45*219b2ee8SDavid du Colombier  *
46*219b2ee8SDavid du Colombier  *	LL
47*219b2ee8SDavid du Colombier  *
48*219b2ee8SDavid du Colombier  *	  mark string column string column ... LL mark
49*219b2ee8SDavid du Colombier  *
50*219b2ee8SDavid du Colombier  *	    Like L, but only used to prevent potential PostScript stack overflow
51*219b2ee8SDavid du Colombier  *	    from too many string/column pairs. Stays on the current line. It will
52*219b2ee8SDavid du Colombier  *	    not be needed often!!
53*219b2ee8SDavid du Colombier  *
54*219b2ee8SDavid du Colombier  *	done
55*219b2ee8SDavid du Colombier  *
56*219b2ee8SDavid du Colombier  *	  done
57*219b2ee8SDavid du Colombier  *
58*219b2ee8SDavid du Colombier  *	    Makes sure the last page is printed. Only needed when we're printing
59*219b2ee8SDavid du Colombier  *	    more than one page on each sheet of paper.
60*219b2ee8SDavid du Colombier  *
61*219b2ee8SDavid du Colombier  * Almost everything has been changed in this version of postprint. The program
62*219b2ee8SDavid du Colombier  * is more intelligent, especially about tabs, spaces, and backspacing, and as a
63*219b2ee8SDavid du Colombier  * result output files usually print faster. Output files also now conform to
64*219b2ee8SDavid du Colombier  * Adobe's file structuring conventions, which is undoubtedly something I should
65*219b2ee8SDavid du Colombier  * have done in the first version of the program. If the number of lines per page
66*219b2ee8SDavid du Colombier  * is set to 0, which can be done using the -l option, pointsize will be used to
67*219b2ee8SDavid du Colombier  * guess a reasonable value. The estimate is based on the values of LINESPP,
68*219b2ee8SDavid du Colombier  * POINTSIZE, and pointsize, and assumes LINESPP lines would fit on a page if
69*219b2ee8SDavid du Colombier  * we printed in size POINTSIZE. Selecting a point size using the -s option and
70*219b2ee8SDavid du Colombier  * adding -l0 to the command line forces the guess to be made.
71*219b2ee8SDavid du Colombier  *
72*219b2ee8SDavid du Colombier  * Many default values, like the magnification and orientation, are defined in
73*219b2ee8SDavid du Colombier  * the prologue, which is where they belong. If they're changed (by options), an
74*219b2ee8SDavid du Colombier  * appropriate definition is made after the prologue is added to the output file.
75*219b2ee8SDavid du Colombier  * The -P option passes arbitrary PostScript through to the output file. Among
76*219b2ee8SDavid du Colombier  * other things it can be used to set (or change) values that can't be accessed by
77*219b2ee8SDavid du Colombier  * other options.
78*219b2ee8SDavid du Colombier  *
79*219b2ee8SDavid du Colombier  */
80*219b2ee8SDavid du Colombier 
81*219b2ee8SDavid du Colombier #include <stdio.h>
82*219b2ee8SDavid du Colombier #include <signal.h>
83*219b2ee8SDavid du Colombier #include <ctype.h>
84*219b2ee8SDavid du Colombier #ifdef plan9
85*219b2ee8SDavid du Colombier #define	isascii(c)	((unsigned char)(c)<=0177)
86*219b2ee8SDavid du Colombier #endif
87*219b2ee8SDavid du Colombier #include <sys/types.h>
88*219b2ee8SDavid du Colombier #include <fcntl.h>
89*219b2ee8SDavid du Colombier 
90*219b2ee8SDavid du Colombier #include "comments.h"			/* PostScript file structuring comments */
91*219b2ee8SDavid du Colombier #include "gen.h"			/* general purpose definitions */
92*219b2ee8SDavid du Colombier #include "path.h"			/* for the prologue */
93*219b2ee8SDavid du Colombier #include "ext.h"			/* external variable declarations */
94*219b2ee8SDavid du Colombier #include "postprint.h"			/* a few special definitions */
95*219b2ee8SDavid du Colombier 
96*219b2ee8SDavid du Colombier char	*optnames = "a:c:ef:l:m:n:o:p:r:s:t:x:y:A:C:E:J:L:P:R:DI";
97*219b2ee8SDavid du Colombier 
98*219b2ee8SDavid du Colombier char	*prologue = POSTPRINT;		/* default PostScript prologue */
99*219b2ee8SDavid du Colombier char	*formfile = FORMFILE;		/* stuff for multiple pages per sheet */
100*219b2ee8SDavid du Colombier 
101*219b2ee8SDavid du Colombier int	formsperpage = 1;		/* page images on each piece of paper */
102*219b2ee8SDavid du Colombier int	copies = 1;			/* and this many copies of each sheet */
103*219b2ee8SDavid du Colombier 
104*219b2ee8SDavid du Colombier int	linespp = LINESPP;		/* number of lines per page */
105*219b2ee8SDavid du Colombier int	pointsize = POINTSIZE;		/* in this point size */
106*219b2ee8SDavid du Colombier int	tabstops = TABSTOPS;		/* tabs set at these columns */
107*219b2ee8SDavid du Colombier int	crmode = 0;			/* carriage return mode - 0, 1, or 2 */
108*219b2ee8SDavid du Colombier int	extended = TRUE;		/* use escapes for unprintable chars */
109*219b2ee8SDavid du Colombier 
110*219b2ee8SDavid du Colombier int	col = 1;			/* next character goes in this column */
111*219b2ee8SDavid du Colombier int	line = 1;			/* on this line */
112*219b2ee8SDavid du Colombier 
113*219b2ee8SDavid du Colombier int	stringcount = 0;		/* number of strings on the stack */
114*219b2ee8SDavid du Colombier int	stringstart = 1;		/* column where current one starts */
115*219b2ee8SDavid du Colombier 
116*219b2ee8SDavid du Colombier Fontmap	fontmap[] = FONTMAP;		/* for translating font names */
117*219b2ee8SDavid du Colombier char	*fontname = "Courier";		/* use this PostScript font */
118*219b2ee8SDavid du Colombier 
119*219b2ee8SDavid du Colombier int	page = 0;			/* page we're working on */
120*219b2ee8SDavid du Colombier int	printed = 0;			/* printed this many pages */
121*219b2ee8SDavid du Colombier 
122*219b2ee8SDavid du Colombier FILE	*fp_in = stdin;			/* read from this file */
123*219b2ee8SDavid du Colombier FILE	*fp_out = stdout;		/* and write stuff here */
124*219b2ee8SDavid du Colombier FILE	*fp_acct = NULL;		/* for accounting data */
125*219b2ee8SDavid du Colombier 
126*219b2ee8SDavid du Colombier /*****************************************************************************/
127*219b2ee8SDavid du Colombier 
128*219b2ee8SDavid du Colombier main(agc, agv)
129*219b2ee8SDavid du Colombier 
130*219b2ee8SDavid du Colombier     int		agc;
131*219b2ee8SDavid du Colombier     char	*agv[];
132*219b2ee8SDavid du Colombier 
133*219b2ee8SDavid du Colombier {
134*219b2ee8SDavid du Colombier 
135*219b2ee8SDavid du Colombier /*
136*219b2ee8SDavid du Colombier  *
137*219b2ee8SDavid du Colombier  * A simple program that translates ASCII files into PostScript. If there's more
138*219b2ee8SDavid du Colombier  * than one input file, each begins on a new page.
139*219b2ee8SDavid du Colombier  *
140*219b2ee8SDavid du Colombier  */
141*219b2ee8SDavid du Colombier 
142*219b2ee8SDavid du Colombier     argc = agc;				/* other routines may want them */
143*219b2ee8SDavid du Colombier     argv = agv;
144*219b2ee8SDavid du Colombier 
145*219b2ee8SDavid du Colombier     prog_name = argv[0];		/* really just for error messages */
146*219b2ee8SDavid du Colombier 
147*219b2ee8SDavid du Colombier     init_signals();			/* sets up interrupt handling */
148*219b2ee8SDavid du Colombier     header();				/* PostScript header and prologue */
149*219b2ee8SDavid du Colombier     options();				/* handle the command line options */
150*219b2ee8SDavid du Colombier     setup();				/* for PostScript */
151*219b2ee8SDavid du Colombier     arguments();			/* followed by each input file */
152*219b2ee8SDavid du Colombier     done();				/* print the last page etc. */
153*219b2ee8SDavid du Colombier     account();				/* job accounting data */
154*219b2ee8SDavid du Colombier 
155*219b2ee8SDavid du Colombier     exit(x_stat);			/* not much could be wrong */
156*219b2ee8SDavid du Colombier 
157*219b2ee8SDavid du Colombier }   /* End of main */
158*219b2ee8SDavid du Colombier 
159*219b2ee8SDavid du Colombier /*****************************************************************************/
160*219b2ee8SDavid du Colombier 
161*219b2ee8SDavid du Colombier init_signals()
162*219b2ee8SDavid du Colombier 
163*219b2ee8SDavid du Colombier {
164*219b2ee8SDavid du Colombier 
165*219b2ee8SDavid du Colombier /*
166*219b2ee8SDavid du Colombier  *
167*219b2ee8SDavid du Colombier  * Makes sure we handle interrupts.
168*219b2ee8SDavid du Colombier  *
169*219b2ee8SDavid du Colombier  */
170*219b2ee8SDavid du Colombier 
171*219b2ee8SDavid du Colombier     if ( signal(SIGINT, interrupt) == SIG_IGN ) {
172*219b2ee8SDavid du Colombier 	signal(SIGINT, SIG_IGN);
173*219b2ee8SDavid du Colombier 	signal(SIGQUIT, SIG_IGN);
174*219b2ee8SDavid du Colombier 	signal(SIGHUP, SIG_IGN);
175*219b2ee8SDavid du Colombier     } else {
176*219b2ee8SDavid du Colombier 	signal(SIGHUP, interrupt);
177*219b2ee8SDavid du Colombier 	signal(SIGQUIT, interrupt);
178*219b2ee8SDavid du Colombier     }   /* End else */
179*219b2ee8SDavid du Colombier 
180*219b2ee8SDavid du Colombier     signal(SIGTERM, interrupt);
181*219b2ee8SDavid du Colombier 
182*219b2ee8SDavid du Colombier }   /* End of init_signals */
183*219b2ee8SDavid du Colombier 
184*219b2ee8SDavid du Colombier /*****************************************************************************/
185*219b2ee8SDavid du Colombier 
186*219b2ee8SDavid du Colombier header()
187*219b2ee8SDavid du Colombier 
188*219b2ee8SDavid du Colombier {
189*219b2ee8SDavid du Colombier 
190*219b2ee8SDavid du Colombier     int		ch;			/* return value from getopt() */
191*219b2ee8SDavid du Colombier     int		old_optind = optind;	/* for restoring optind - should be 1 */
192*219b2ee8SDavid du Colombier 
193*219b2ee8SDavid du Colombier /*
194*219b2ee8SDavid du Colombier  *
195*219b2ee8SDavid du Colombier  * Scans the option list looking for things, like the prologue file, that we need
196*219b2ee8SDavid du Colombier  * right away but could be changed from the default. Doing things this way is an
197*219b2ee8SDavid du Colombier  * attempt to conform to Adobe's latest file structuring conventions. In particular
198*219b2ee8SDavid du Colombier  * they now say there should be nothing executed in the prologue, and they have
199*219b2ee8SDavid du Colombier  * added two new comments that delimit global initialization calls. Once we know
200*219b2ee8SDavid du Colombier  * where things really are we write out the job header, follow it by the prologue,
201*219b2ee8SDavid du Colombier  * and then add the ENDPROLOG and BEGINSETUP comments.
202*219b2ee8SDavid du Colombier  *
203*219b2ee8SDavid du Colombier  */
204*219b2ee8SDavid du Colombier 
205*219b2ee8SDavid du Colombier     while ( (ch = getopt(argc, argv, optnames)) != EOF )
206*219b2ee8SDavid du Colombier 	if ( ch == 'L' )
207*219b2ee8SDavid du Colombier 	    prologue = optarg;
208*219b2ee8SDavid du Colombier 	else if ( ch == '?' )
209*219b2ee8SDavid du Colombier 	    error(FATAL, "");
210*219b2ee8SDavid du Colombier 
211*219b2ee8SDavid du Colombier     optind = old_optind;		/* get ready for option scanning */
212*219b2ee8SDavid du Colombier 
213*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", CONFORMING);
214*219b2ee8SDavid du Colombier     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
215*219b2ee8SDavid du Colombier     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
216*219b2ee8SDavid du Colombier     fprintf(stdout, "%s %s\n", PAGES, ATEND);
217*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", ENDCOMMENTS);
218*219b2ee8SDavid du Colombier 
219*219b2ee8SDavid du Colombier     if ( cat(prologue) == FALSE )
220*219b2ee8SDavid du Colombier 	error(FATAL, "can't read %s", prologue);
221*219b2ee8SDavid du Colombier 
222*219b2ee8SDavid du Colombier     if ( DOROUND )
223*219b2ee8SDavid du Colombier 	cat(ROUNDPAGE);
224*219b2ee8SDavid du Colombier 
225*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", ENDPROLOG);
226*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", BEGINSETUP);
227*219b2ee8SDavid du Colombier     fprintf(stdout, "mark\n");
228*219b2ee8SDavid du Colombier 
229*219b2ee8SDavid du Colombier }   /* End of header */
230*219b2ee8SDavid du Colombier 
231*219b2ee8SDavid du Colombier /*****************************************************************************/
232*219b2ee8SDavid du Colombier 
233*219b2ee8SDavid du Colombier options()
234*219b2ee8SDavid du Colombier 
235*219b2ee8SDavid du Colombier {
236*219b2ee8SDavid du Colombier 
237*219b2ee8SDavid du Colombier     int		ch;			/* return value from getopt() */
238*219b2ee8SDavid du Colombier 
239*219b2ee8SDavid du Colombier /*
240*219b2ee8SDavid du Colombier  *
241*219b2ee8SDavid du Colombier  * Reads and processes the command line options. Added the -P option so arbitrary
242*219b2ee8SDavid du Colombier  * PostScript code can be passed through. Expect it could be useful for changing
243*219b2ee8SDavid du Colombier  * definitions in the prologue for which options have not been defined.
244*219b2ee8SDavid du Colombier  *
245*219b2ee8SDavid du Colombier  * Although any PostScript font can be used, things will only work well for
246*219b2ee8SDavid du Colombier  * constant width fonts.
247*219b2ee8SDavid du Colombier  *
248*219b2ee8SDavid du Colombier  */
249*219b2ee8SDavid du Colombier 
250*219b2ee8SDavid du Colombier     while ( (ch = getopt(argc, argv, optnames)) != EOF ) {
251*219b2ee8SDavid du Colombier 	switch ( ch ) {
252*219b2ee8SDavid du Colombier 
253*219b2ee8SDavid du Colombier 	    case 'a':			/* aspect ratio */
254*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/aspectratio %s def\n", optarg);
255*219b2ee8SDavid du Colombier 		    break;
256*219b2ee8SDavid du Colombier 
257*219b2ee8SDavid du Colombier 	    case 'c':			/* copies */
258*219b2ee8SDavid du Colombier 		    copies = atoi(optarg);
259*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/#copies %s store\n", optarg);
260*219b2ee8SDavid du Colombier 		    break;
261*219b2ee8SDavid du Colombier 
262*219b2ee8SDavid du Colombier 	    case 'e':			/* obsolete - it's now always on */
263*219b2ee8SDavid du Colombier 		    extended = TRUE;
264*219b2ee8SDavid du Colombier 		    break;
265*219b2ee8SDavid du Colombier 
266*219b2ee8SDavid du Colombier 	    case 'f':			/* use this PostScript font */
267*219b2ee8SDavid du Colombier 		    fontname = get_font(optarg);
268*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/font /%s def\n", fontname);
269*219b2ee8SDavid du Colombier 		    break;
270*219b2ee8SDavid du Colombier 
271*219b2ee8SDavid du Colombier 	    case 'l':			/* lines per page */
272*219b2ee8SDavid du Colombier 		    linespp = atoi(optarg);
273*219b2ee8SDavid du Colombier 		    break;
274*219b2ee8SDavid du Colombier 
275*219b2ee8SDavid du Colombier 	    case 'm':			/* magnification */
276*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/magnification %s def\n", optarg);
277*219b2ee8SDavid du Colombier 		    break;
278*219b2ee8SDavid du Colombier 
279*219b2ee8SDavid du Colombier 	    case 'n':			/* forms per page */
280*219b2ee8SDavid du Colombier 		    formsperpage = atoi(optarg);
281*219b2ee8SDavid du Colombier 		    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
282*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/formsperpage %s def\n", optarg);
283*219b2ee8SDavid du Colombier 		    break;
284*219b2ee8SDavid du Colombier 
285*219b2ee8SDavid du Colombier 	    case 'o':			/* output page list */
286*219b2ee8SDavid du Colombier 		    out_list(optarg);
287*219b2ee8SDavid du Colombier 		    break;
288*219b2ee8SDavid du Colombier 
289*219b2ee8SDavid du Colombier 	    case 'p':			/* landscape or portrait mode */
290*219b2ee8SDavid du Colombier 		    if ( *optarg == 'l' )
291*219b2ee8SDavid du Colombier 			fprintf(stdout, "/landscape true def\n");
292*219b2ee8SDavid du Colombier 		    else fprintf(stdout, "/landscape false def\n");
293*219b2ee8SDavid du Colombier 		    break;
294*219b2ee8SDavid du Colombier 
295*219b2ee8SDavid du Colombier 	    case 'r':			/* carriage return mode */
296*219b2ee8SDavid du Colombier 		    crmode = atoi(optarg);
297*219b2ee8SDavid du Colombier 		    break;
298*219b2ee8SDavid du Colombier 
299*219b2ee8SDavid du Colombier 	    case 's':			/* point size */
300*219b2ee8SDavid du Colombier 		    pointsize = atoi(optarg);
301*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/pointsize %s def\n", optarg);
302*219b2ee8SDavid du Colombier 		    break;
303*219b2ee8SDavid du Colombier 
304*219b2ee8SDavid du Colombier 	    case 't':			/* tabstops */
305*219b2ee8SDavid du Colombier 		    tabstops = atoi(optarg);
306*219b2ee8SDavid du Colombier 		    break;
307*219b2ee8SDavid du Colombier 
308*219b2ee8SDavid du Colombier 	    case 'x':			/* shift things horizontally */
309*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/xoffset %s def\n", optarg);
310*219b2ee8SDavid du Colombier 		    break;
311*219b2ee8SDavid du Colombier 
312*219b2ee8SDavid du Colombier 	    case 'y':			/* and vertically on the page */
313*219b2ee8SDavid du Colombier 		    fprintf(stdout, "/yoffset %s def\n", optarg);
314*219b2ee8SDavid du Colombier 		    break;
315*219b2ee8SDavid du Colombier 
316*219b2ee8SDavid du Colombier 	    case 'A':			/* force job accounting */
317*219b2ee8SDavid du Colombier 	    case 'J':
318*219b2ee8SDavid du Colombier 		    if ( (fp_acct = fopen(optarg, "a")) == NULL )
319*219b2ee8SDavid du Colombier 			error(FATAL, "can't open accounting file %s", optarg);
320*219b2ee8SDavid du Colombier 		    break;
321*219b2ee8SDavid du Colombier 
322*219b2ee8SDavid du Colombier 	    case 'C':			/* copy file straight to output */
323*219b2ee8SDavid du Colombier 		    if ( cat(optarg) == FALSE )
324*219b2ee8SDavid du Colombier 			error(FATAL, "can't read %s", optarg);
325*219b2ee8SDavid du Colombier 		    break;
326*219b2ee8SDavid du Colombier 
327*219b2ee8SDavid du Colombier 	    case 'E':			/* text font encoding */
328*219b2ee8SDavid du Colombier 		    fontencoding = optarg;
329*219b2ee8SDavid du Colombier 		    break;
330*219b2ee8SDavid du Colombier 
331*219b2ee8SDavid du Colombier 	    case 'L':			/* PostScript prologue file */
332*219b2ee8SDavid du Colombier 		    prologue = optarg;
333*219b2ee8SDavid du Colombier 		    break;
334*219b2ee8SDavid du Colombier 
335*219b2ee8SDavid du Colombier 	    case 'P':			/* PostScript pass through */
336*219b2ee8SDavid du Colombier 		    fprintf(stdout, "%s\n", optarg);
337*219b2ee8SDavid du Colombier 		    break;
338*219b2ee8SDavid du Colombier 
339*219b2ee8SDavid du Colombier 	    case 'R':			/* special global or page level request */
340*219b2ee8SDavid du Colombier 		    saverequest(optarg);
341*219b2ee8SDavid du Colombier 		    break;
342*219b2ee8SDavid du Colombier 
343*219b2ee8SDavid du Colombier 	    case 'D':			/* debug flag */
344*219b2ee8SDavid du Colombier 		    debug = ON;
345*219b2ee8SDavid du Colombier 		    break;
346*219b2ee8SDavid du Colombier 
347*219b2ee8SDavid du Colombier 	    case 'I':			/* ignore FATAL errors */
348*219b2ee8SDavid du Colombier 		    ignore = ON;
349*219b2ee8SDavid du Colombier 		    break;
350*219b2ee8SDavid du Colombier 
351*219b2ee8SDavid du Colombier 	    case '?':			/* don't understand the option */
352*219b2ee8SDavid du Colombier 		    error(FATAL, "");
353*219b2ee8SDavid du Colombier 		    break;
354*219b2ee8SDavid du Colombier 
355*219b2ee8SDavid du Colombier 	    default:			/* don't know what to do for ch */
356*219b2ee8SDavid du Colombier 		    error(FATAL, "missing case for option %c\n", ch);
357*219b2ee8SDavid du Colombier 		    break;
358*219b2ee8SDavid du Colombier 	}   /* End switch */
359*219b2ee8SDavid du Colombier     }   /* End while */
360*219b2ee8SDavid du Colombier 
361*219b2ee8SDavid du Colombier     argc -= optind;			/* get ready for non-option args */
362*219b2ee8SDavid du Colombier     argv += optind;
363*219b2ee8SDavid du Colombier 
364*219b2ee8SDavid du Colombier }   /* End of options */
365*219b2ee8SDavid du Colombier 
366*219b2ee8SDavid du Colombier /*****************************************************************************/
367*219b2ee8SDavid du Colombier 
368*219b2ee8SDavid du Colombier char *get_font(name)
369*219b2ee8SDavid du Colombier 
370*219b2ee8SDavid du Colombier     char	*name;			/* name the user asked for */
371*219b2ee8SDavid du Colombier 
372*219b2ee8SDavid du Colombier {
373*219b2ee8SDavid du Colombier 
374*219b2ee8SDavid du Colombier     int		i;			/* for looking through fontmap[] */
375*219b2ee8SDavid du Colombier 
376*219b2ee8SDavid du Colombier /*
377*219b2ee8SDavid du Colombier  *
378*219b2ee8SDavid du Colombier  * Called from options() to map a user's font name into a legal PostScript name.
379*219b2ee8SDavid du Colombier  * If the lookup fails *name is returned to the caller. That should let you choose
380*219b2ee8SDavid du Colombier  * any PostScript font, although things will only work well for constant width
381*219b2ee8SDavid du Colombier  * fonts.
382*219b2ee8SDavid du Colombier  *
383*219b2ee8SDavid du Colombier  */
384*219b2ee8SDavid du Colombier 
385*219b2ee8SDavid du Colombier     for ( i = 0; fontmap[i].name != NULL; i++ )
386*219b2ee8SDavid du Colombier 	if ( strcmp(name, fontmap[i].name) == 0 )
387*219b2ee8SDavid du Colombier 	    return(fontmap[i].val);
388*219b2ee8SDavid du Colombier 
389*219b2ee8SDavid du Colombier     return(name);
390*219b2ee8SDavid du Colombier 
391*219b2ee8SDavid du Colombier }   /* End of get_font */
392*219b2ee8SDavid du Colombier 
393*219b2ee8SDavid du Colombier /*****************************************************************************/
394*219b2ee8SDavid du Colombier 
395*219b2ee8SDavid du Colombier setup()
396*219b2ee8SDavid du Colombier 
397*219b2ee8SDavid du Colombier {
398*219b2ee8SDavid du Colombier 
399*219b2ee8SDavid du Colombier /*
400*219b2ee8SDavid du Colombier  *
401*219b2ee8SDavid du Colombier  * Handles things that must be done after the options are read but before the
402*219b2ee8SDavid du Colombier  * input files are processed. linespp (lines per page) can be set using the -l
403*219b2ee8SDavid du Colombier  * option. If it's not positive we calculate a reasonable value using the
404*219b2ee8SDavid du Colombier  * requested point size - assuming LINESPP lines fit on a page in point size
405*219b2ee8SDavid du Colombier  * POINTSIZE.
406*219b2ee8SDavid du Colombier  *
407*219b2ee8SDavid du Colombier  */
408*219b2ee8SDavid du Colombier 
409*219b2ee8SDavid du Colombier     writerequest(0, stdout);		/* global requests eg. manual feed */
410*219b2ee8SDavid du Colombier     setencoding(fontencoding);
411*219b2ee8SDavid du Colombier     fprintf(stdout, "setup\n");
412*219b2ee8SDavid du Colombier 
413*219b2ee8SDavid du Colombier     if ( formsperpage > 1 ) {
414*219b2ee8SDavid du Colombier 	if ( cat(formfile) == FALSE )
415*219b2ee8SDavid du Colombier 	    error(FATAL, "can't read %s", formfile);
416*219b2ee8SDavid du Colombier 	fprintf(stdout, "%d setupforms\n", formsperpage);
417*219b2ee8SDavid du Colombier     }	/* End if */
418*219b2ee8SDavid du Colombier 
419*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", ENDSETUP);
420*219b2ee8SDavid du Colombier 
421*219b2ee8SDavid du Colombier     if ( linespp <= 0 )
422*219b2ee8SDavid du Colombier 	linespp = LINESPP * POINTSIZE / pointsize;
423*219b2ee8SDavid du Colombier 
424*219b2ee8SDavid du Colombier }   /* End of setup */
425*219b2ee8SDavid du Colombier 
426*219b2ee8SDavid du Colombier /*****************************************************************************/
427*219b2ee8SDavid du Colombier 
428*219b2ee8SDavid du Colombier arguments()
429*219b2ee8SDavid du Colombier 
430*219b2ee8SDavid du Colombier {
431*219b2ee8SDavid du Colombier 
432*219b2ee8SDavid du Colombier /*
433*219b2ee8SDavid du Colombier  *
434*219b2ee8SDavid du Colombier  * Makes sure all the non-option command line arguments are processed. If we get
435*219b2ee8SDavid du Colombier  * here and there aren't any arguments left, or if '-' is one of the input files
436*219b2ee8SDavid du Colombier  * we'll translate stdin.
437*219b2ee8SDavid du Colombier  *
438*219b2ee8SDavid du Colombier  */
439*219b2ee8SDavid du Colombier 
440*219b2ee8SDavid du Colombier     if ( argc < 1 )
441*219b2ee8SDavid du Colombier 	text();
442*219b2ee8SDavid du Colombier     else {				/* at least one argument is left */
443*219b2ee8SDavid du Colombier 	while ( argc > 0 ) {
444*219b2ee8SDavid du Colombier 	    if ( strcmp(*argv, "-") == 0 )
445*219b2ee8SDavid du Colombier 		fp_in = stdin;
446*219b2ee8SDavid du Colombier 	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
447*219b2ee8SDavid du Colombier 		error(FATAL, "can't open %s", *argv);
448*219b2ee8SDavid du Colombier 	    text();
449*219b2ee8SDavid du Colombier 	    if ( fp_in != stdin )
450*219b2ee8SDavid du Colombier 		fclose(fp_in);
451*219b2ee8SDavid du Colombier 	    argc--;
452*219b2ee8SDavid du Colombier 	    argv++;
453*219b2ee8SDavid du Colombier 	}   /* End while */
454*219b2ee8SDavid du Colombier     }   /* End else */
455*219b2ee8SDavid du Colombier 
456*219b2ee8SDavid du Colombier }   /* End of arguments */
457*219b2ee8SDavid du Colombier 
458*219b2ee8SDavid du Colombier /*****************************************************************************/
459*219b2ee8SDavid du Colombier 
460*219b2ee8SDavid du Colombier done()
461*219b2ee8SDavid du Colombier 
462*219b2ee8SDavid du Colombier {
463*219b2ee8SDavid du Colombier 
464*219b2ee8SDavid du Colombier /*
465*219b2ee8SDavid du Colombier  *
466*219b2ee8SDavid du Colombier  * Finished with all the input files, so mark the end of the pages with a TRAILER
467*219b2ee8SDavid du Colombier  * comment, make sure the last page prints, and add things like the PAGES comment
468*219b2ee8SDavid du Colombier  * that can only be determined after all the input files have been read.
469*219b2ee8SDavid du Colombier  *
470*219b2ee8SDavid du Colombier  */
471*219b2ee8SDavid du Colombier 
472*219b2ee8SDavid du Colombier     fprintf(stdout, "%s", TRAILER);
473*219b2ee8SDavid du Colombier     fprintf(stdout, "done\n");
474*219b2ee8SDavid du Colombier     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname);
475*219b2ee8SDavid du Colombier     fprintf(stdout, "%s %d\n", PAGES, printed);
476*219b2ee8SDavid du Colombier 
477*219b2ee8SDavid du Colombier }   /* End of done */
478*219b2ee8SDavid du Colombier 
479*219b2ee8SDavid du Colombier /*****************************************************************************/
480*219b2ee8SDavid du Colombier 
481*219b2ee8SDavid du Colombier account()
482*219b2ee8SDavid du Colombier 
483*219b2ee8SDavid du Colombier {
484*219b2ee8SDavid du Colombier 
485*219b2ee8SDavid du Colombier /*
486*219b2ee8SDavid du Colombier  *
487*219b2ee8SDavid du Colombier  * Writes an accounting record to *fp_acct provided it's not NULL. Accounting is
488*219b2ee8SDavid du Colombier  * requested using the -A or -J options.
489*219b2ee8SDavid du Colombier  *
490*219b2ee8SDavid du Colombier  */
491*219b2ee8SDavid du Colombier 
492*219b2ee8SDavid du Colombier     if ( fp_acct != NULL )
493*219b2ee8SDavid du Colombier 	fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
494*219b2ee8SDavid du Colombier 
495*219b2ee8SDavid du Colombier }   /* End of account */
496*219b2ee8SDavid du Colombier 
497*219b2ee8SDavid du Colombier /*****************************************************************************/
498*219b2ee8SDavid du Colombier 
499*219b2ee8SDavid du Colombier text()
500*219b2ee8SDavid du Colombier 
501*219b2ee8SDavid du Colombier {
502*219b2ee8SDavid du Colombier 
503*219b2ee8SDavid du Colombier     int		ch;			/* next input character */
504*219b2ee8SDavid du Colombier 
505*219b2ee8SDavid du Colombier /*
506*219b2ee8SDavid du Colombier  *
507*219b2ee8SDavid du Colombier  * Translates *fp_in into PostScript. Intercepts space, tab, backspace, newline,
508*219b2ee8SDavid du Colombier  * return, and formfeed. Everything else goes to oput(), which handles quoting
509*219b2ee8SDavid du Colombier  * (if needed) and escapes for nonascii characters if extended is TRUE. The
510*219b2ee8SDavid du Colombier  * redirect(-1) call forces the initial output to go to /dev/null - so stuff
511*219b2ee8SDavid du Colombier  * that formfeed() does at the end of each page goes to /dev/null rather than
512*219b2ee8SDavid du Colombier  * the real output file.
513*219b2ee8SDavid du Colombier  *
514*219b2ee8SDavid du Colombier  */
515*219b2ee8SDavid du Colombier 
516*219b2ee8SDavid du Colombier     redirect(-1);			/* get ready for the first page */
517*219b2ee8SDavid du Colombier     formfeed();				/* force PAGE comment etc. */
518*219b2ee8SDavid du Colombier 
519*219b2ee8SDavid du Colombier     while ( (ch = getc(fp_in)) != EOF )
520*219b2ee8SDavid du Colombier 	switch ( ch ) {
521*219b2ee8SDavid du Colombier 	    case '\n':
522*219b2ee8SDavid du Colombier 		    newline();
523*219b2ee8SDavid du Colombier 		    break;
524*219b2ee8SDavid du Colombier 
525*219b2ee8SDavid du Colombier 	    case '\t':
526*219b2ee8SDavid du Colombier 	    case '\b':
527*219b2ee8SDavid du Colombier 	    case ' ':
528*219b2ee8SDavid du Colombier 		    spaces(ch);
529*219b2ee8SDavid du Colombier 		    break;
530*219b2ee8SDavid du Colombier 
531*219b2ee8SDavid du Colombier 	    case '\014':
532*219b2ee8SDavid du Colombier 		    formfeed();
533*219b2ee8SDavid du Colombier 		    break;
534*219b2ee8SDavid du Colombier 
535*219b2ee8SDavid du Colombier 	    case '\r':
536*219b2ee8SDavid du Colombier 		    if ( crmode == 1 )
537*219b2ee8SDavid du Colombier 			spaces(ch);
538*219b2ee8SDavid du Colombier 		    else if ( crmode == 2 )
539*219b2ee8SDavid du Colombier 			newline();
540*219b2ee8SDavid du Colombier 		    break;
541*219b2ee8SDavid du Colombier 
542*219b2ee8SDavid du Colombier 	    default:
543*219b2ee8SDavid du Colombier 		    oput(ch);
544*219b2ee8SDavid du Colombier 		    break;
545*219b2ee8SDavid du Colombier 	}   /* End switch */
546*219b2ee8SDavid du Colombier 
547*219b2ee8SDavid du Colombier     formfeed();				/* next file starts on a new page? */
548*219b2ee8SDavid du Colombier 
549*219b2ee8SDavid du Colombier }   /* End of text */
550*219b2ee8SDavid du Colombier 
551*219b2ee8SDavid du Colombier /*****************************************************************************/
552*219b2ee8SDavid du Colombier 
553*219b2ee8SDavid du Colombier formfeed()
554*219b2ee8SDavid du Colombier 
555*219b2ee8SDavid du Colombier {
556*219b2ee8SDavid du Colombier 
557*219b2ee8SDavid du Colombier /*
558*219b2ee8SDavid du Colombier  *
559*219b2ee8SDavid du Colombier  * Called whenever we've finished with the last page and want to get ready for the
560*219b2ee8SDavid du Colombier  * next one. Also used at the beginning and end of each input file, so we have to
561*219b2ee8SDavid du Colombier  * be careful about what's done. The first time through (up to the redirect() call)
562*219b2ee8SDavid du Colombier  * output goes to /dev/null.
563*219b2ee8SDavid du Colombier  *
564*219b2ee8SDavid du Colombier  * Adobe now recommends that the showpage operator occur after the page level
565*219b2ee8SDavid du Colombier  * restore so it can be easily redefined to have side-effects in the printer's VM.
566*219b2ee8SDavid du Colombier  * Although it seems reasonable I haven't implemented it, because it makes other
567*219b2ee8SDavid du Colombier  * things, like selectively setting manual feed or choosing an alternate paper
568*219b2ee8SDavid du Colombier  * tray, clumsy - at least on a per page basis.
569*219b2ee8SDavid du Colombier  *
570*219b2ee8SDavid du Colombier  */
571*219b2ee8SDavid du Colombier 
572*219b2ee8SDavid du Colombier     if ( fp_out == stdout )		/* count the last page */
573*219b2ee8SDavid du Colombier 	printed++;
574*219b2ee8SDavid du Colombier 
575*219b2ee8SDavid du Colombier     endline();				/* print the last line */
576*219b2ee8SDavid du Colombier 
577*219b2ee8SDavid du Colombier     fprintf(fp_out, "cleartomark\n");
578*219b2ee8SDavid du Colombier     fprintf(fp_out, "showpage\n");
579*219b2ee8SDavid du Colombier     fprintf(fp_out, "saveobj restore\n");
580*219b2ee8SDavid du Colombier     fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);
581*219b2ee8SDavid du Colombier 
582*219b2ee8SDavid du Colombier     if ( ungetc(getc(fp_in), fp_in) == EOF )
583*219b2ee8SDavid du Colombier 	redirect(-1);
584*219b2ee8SDavid du Colombier     else redirect(++page);
585*219b2ee8SDavid du Colombier 
586*219b2ee8SDavid du Colombier     fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
587*219b2ee8SDavid du Colombier     fprintf(fp_out, "/saveobj save def\n");
588*219b2ee8SDavid du Colombier     fprintf(fp_out, "mark\n");
589*219b2ee8SDavid du Colombier     writerequest(printed+1, fp_out);
590*219b2ee8SDavid du Colombier     fprintf(fp_out, "%d pagesetup\n", printed+1);
591*219b2ee8SDavid du Colombier 
592*219b2ee8SDavid du Colombier     line = 1;
593*219b2ee8SDavid du Colombier 
594*219b2ee8SDavid du Colombier }   /* End of formfeed */
595*219b2ee8SDavid du Colombier 
596*219b2ee8SDavid du Colombier /*****************************************************************************/
597*219b2ee8SDavid du Colombier 
598*219b2ee8SDavid du Colombier newline()
599*219b2ee8SDavid du Colombier 
600*219b2ee8SDavid du Colombier {
601*219b2ee8SDavid du Colombier 
602*219b2ee8SDavid du Colombier /*
603*219b2ee8SDavid du Colombier  *
604*219b2ee8SDavid du Colombier  * Called when we've read a newline character. The call to startline() ensures
605*219b2ee8SDavid du Colombier  * that at least an empty string is on the stack.
606*219b2ee8SDavid du Colombier  *
607*219b2ee8SDavid du Colombier  */
608*219b2ee8SDavid du Colombier 
609*219b2ee8SDavid du Colombier     startline();
610*219b2ee8SDavid du Colombier     endline();				/* print the current line */
611*219b2ee8SDavid du Colombier 
612*219b2ee8SDavid du Colombier     if ( ++line > linespp )		/* done with this page */
613*219b2ee8SDavid du Colombier 	formfeed();
614*219b2ee8SDavid du Colombier 
615*219b2ee8SDavid du Colombier }   /* End of newline */
616*219b2ee8SDavid du Colombier 
617*219b2ee8SDavid du Colombier /*****************************************************************************/
618*219b2ee8SDavid du Colombier 
619*219b2ee8SDavid du Colombier spaces(ch)
620*219b2ee8SDavid du Colombier 
621*219b2ee8SDavid du Colombier     int		ch;			/* next input character */
622*219b2ee8SDavid du Colombier 
623*219b2ee8SDavid du Colombier {
624*219b2ee8SDavid du Colombier 
625*219b2ee8SDavid du Colombier     int		endcol;			/* ending column */
626*219b2ee8SDavid du Colombier     int		i;			/* final distance - in spaces */
627*219b2ee8SDavid du Colombier 
628*219b2ee8SDavid du Colombier /*
629*219b2ee8SDavid du Colombier  *
630*219b2ee8SDavid du Colombier  * Counts consecutive spaces, tabs, and backspaces and figures out where the next
631*219b2ee8SDavid du Colombier  * string should start. Once that's been done we try to choose an efficient way
632*219b2ee8SDavid du Colombier  * to output the required number of spaces. The choice is between using procedure
633*219b2ee8SDavid du Colombier  * l with a single string on the stack and L with several string and column pairs.
634*219b2ee8SDavid du Colombier  * We usually break even, in terms of the size of the output file, if we need four
635*219b2ee8SDavid du Colombier  * consecutive spaces. More means using L decreases the size of the file. For now
636*219b2ee8SDavid du Colombier  * if there are less than 6 consecutive spaces we just add them to the current
637*219b2ee8SDavid du Colombier  * string, otherwise we end that string, follow it by its starting position, and
638*219b2ee8SDavid du Colombier  * begin a new one that starts at endcol. Backspacing is always handled this way.
639*219b2ee8SDavid du Colombier  *
640*219b2ee8SDavid du Colombier  */
641*219b2ee8SDavid du Colombier 
642*219b2ee8SDavid du Colombier     startline();			/* so col makes sense */
643*219b2ee8SDavid du Colombier     endcol = col;
644*219b2ee8SDavid du Colombier 
645*219b2ee8SDavid du Colombier     do {
646*219b2ee8SDavid du Colombier 	if ( ch == ' ' )
647*219b2ee8SDavid du Colombier 	    endcol++;
648*219b2ee8SDavid du Colombier 	else if ( ch == '\t' )
649*219b2ee8SDavid du Colombier 	    endcol += tabstops - ((endcol - 1) % tabstops);
650*219b2ee8SDavid du Colombier 	else if ( ch == '\b' )
651*219b2ee8SDavid du Colombier 	    endcol--;
652*219b2ee8SDavid du Colombier 	else if ( ch == '\r' )
653*219b2ee8SDavid du Colombier 	    endcol = 1;
654*219b2ee8SDavid du Colombier 	else break;
655*219b2ee8SDavid du Colombier     } while ( ch = getc(fp_in) );	/* if ch is 0 we'd quit anyway */
656*219b2ee8SDavid du Colombier 
657*219b2ee8SDavid du Colombier     ungetc(ch, fp_in);			/* wasn't a space, tab, or backspace */
658*219b2ee8SDavid du Colombier 
659*219b2ee8SDavid du Colombier     if ( endcol < 1 )			/* can't move past left edge */
660*219b2ee8SDavid du Colombier 	endcol = 1;
661*219b2ee8SDavid du Colombier 
662*219b2ee8SDavid du Colombier     if ( (i = endcol - col) >= 0 && i < 6 )
663*219b2ee8SDavid du Colombier 	for ( ; i > 0; i-- )
664*219b2ee8SDavid du Colombier 	    oput((int)' ');
665*219b2ee8SDavid du Colombier     else {
666*219b2ee8SDavid du Colombier 	endstring();
667*219b2ee8SDavid du Colombier 	col = stringstart = endcol;
668*219b2ee8SDavid du Colombier     }	/* End else */
669*219b2ee8SDavid du Colombier 
670*219b2ee8SDavid du Colombier }   /* End of spaces */
671*219b2ee8SDavid du Colombier 
672*219b2ee8SDavid du Colombier /*****************************************************************************/
673*219b2ee8SDavid du Colombier 
674*219b2ee8SDavid du Colombier startline()
675*219b2ee8SDavid du Colombier 
676*219b2ee8SDavid du Colombier {
677*219b2ee8SDavid du Colombier 
678*219b2ee8SDavid du Colombier /*
679*219b2ee8SDavid du Colombier  *
680*219b2ee8SDavid du Colombier  * Called whenever we want to be certain we're ready to start pushing characters
681*219b2ee8SDavid du Colombier  * into an open string on the stack. If stringcount is positive we've already
682*219b2ee8SDavid du Colombier  * started, so there's nothing to do. The first string starts in column 1.
683*219b2ee8SDavid du Colombier  *
684*219b2ee8SDavid du Colombier  */
685*219b2ee8SDavid du Colombier 
686*219b2ee8SDavid du Colombier     if ( stringcount < 1 ) {
687*219b2ee8SDavid du Colombier 	putc('(', fp_out);
688*219b2ee8SDavid du Colombier 	stringstart = col = 1;
689*219b2ee8SDavid du Colombier 	stringcount = 1;
690*219b2ee8SDavid du Colombier     }	/* End if */
691*219b2ee8SDavid du Colombier 
692*219b2ee8SDavid du Colombier }   /* End of startline */
693*219b2ee8SDavid du Colombier 
694*219b2ee8SDavid du Colombier /*****************************************************************************/
695*219b2ee8SDavid du Colombier 
696*219b2ee8SDavid du Colombier endstring()
697*219b2ee8SDavid du Colombier 
698*219b2ee8SDavid du Colombier {
699*219b2ee8SDavid du Colombier 
700*219b2ee8SDavid du Colombier /*
701*219b2ee8SDavid du Colombier  *
702*219b2ee8SDavid du Colombier  * End the current string and start a new one.
703*219b2ee8SDavid du Colombier  *
704*219b2ee8SDavid du Colombier  */
705*219b2ee8SDavid du Colombier 
706*219b2ee8SDavid du Colombier     if ( stringcount > 100 ) {		/* don't put too much on the stack */
707*219b2ee8SDavid du Colombier 	fprintf(fp_out, ")%d LL\n(", stringstart-1);
708*219b2ee8SDavid du Colombier 	stringcount = 2;		/* kludge - don't let endline() use l */
709*219b2ee8SDavid du Colombier     } else {
710*219b2ee8SDavid du Colombier 	fprintf(fp_out, ")%d(", stringstart-1);
711*219b2ee8SDavid du Colombier 	stringcount++;
712*219b2ee8SDavid du Colombier     }   /* End else */
713*219b2ee8SDavid du Colombier 
714*219b2ee8SDavid du Colombier }   /* End of endstring */
715*219b2ee8SDavid du Colombier 
716*219b2ee8SDavid du Colombier /*****************************************************************************/
717*219b2ee8SDavid du Colombier 
718*219b2ee8SDavid du Colombier endline()
719*219b2ee8SDavid du Colombier 
720*219b2ee8SDavid du Colombier {
721*219b2ee8SDavid du Colombier 
722*219b2ee8SDavid du Colombier /*
723*219b2ee8SDavid du Colombier  *
724*219b2ee8SDavid du Colombier  * Generates a call to the PostScript procedure that processes all the text on
725*219b2ee8SDavid du Colombier  * the stack - provided stringcount is positive. If one string is on the stack
726*219b2ee8SDavid du Colombier  * the fast procedure (ie. l) is used to print the line, otherwise the slower
727*219b2ee8SDavid du Colombier  * one that processes string and column pairs is used.
728*219b2ee8SDavid du Colombier  *
729*219b2ee8SDavid du Colombier  */
730*219b2ee8SDavid du Colombier 
731*219b2ee8SDavid du Colombier     if ( stringcount == 1 )
732*219b2ee8SDavid du Colombier 	fprintf(fp_out, ")l\n");
733*219b2ee8SDavid du Colombier     else if ( stringcount > 1 )
734*219b2ee8SDavid du Colombier 	fprintf(fp_out, ")%d L\n", stringstart-1);
735*219b2ee8SDavid du Colombier 
736*219b2ee8SDavid du Colombier     stringcount = 0;
737*219b2ee8SDavid du Colombier 
738*219b2ee8SDavid du Colombier }   /* End of endline */
739*219b2ee8SDavid du Colombier 
740*219b2ee8SDavid du Colombier /*****************************************************************************/
741*219b2ee8SDavid du Colombier 
742*219b2ee8SDavid du Colombier oput(ch)
743*219b2ee8SDavid du Colombier 
744*219b2ee8SDavid du Colombier     int		ch;			/* next output character */
745*219b2ee8SDavid du Colombier 
746*219b2ee8SDavid du Colombier {
747*219b2ee8SDavid du Colombier 
748*219b2ee8SDavid du Colombier /*
749*219b2ee8SDavid du Colombier  *
750*219b2ee8SDavid du Colombier  * Responsible for adding all printing characters from the input file to the
751*219b2ee8SDavid du Colombier  * open string on top of the stack.
752*219b2ee8SDavid du Colombier  *
753*219b2ee8SDavid du Colombier  */
754*219b2ee8SDavid du Colombier 
755*219b2ee8SDavid du Colombier     if ( isascii(ch) && isprint(ch) ) {
756*219b2ee8SDavid du Colombier 	startline();
757*219b2ee8SDavid du Colombier 	if ( ch == '(' || ch == ')' || ch == '\\' )
758*219b2ee8SDavid du Colombier 	    putc('\\', fp_out);
759*219b2ee8SDavid du Colombier 	putc(ch, fp_out);
760*219b2ee8SDavid du Colombier 	col++;
761*219b2ee8SDavid du Colombier     } else if ( extended == TRUE ) {
762*219b2ee8SDavid du Colombier 	startline();
763*219b2ee8SDavid du Colombier 	fprintf(fp_out, "\\%.3o", ch & 0377);
764*219b2ee8SDavid du Colombier 	col++;
765*219b2ee8SDavid du Colombier     }	/* End if */
766*219b2ee8SDavid du Colombier 
767*219b2ee8SDavid du Colombier }   /* End of oput */
768*219b2ee8SDavid du Colombier 
769*219b2ee8SDavid du Colombier /*****************************************************************************/
770*219b2ee8SDavid du Colombier 
771*219b2ee8SDavid du Colombier redirect(pg)
772*219b2ee8SDavid du Colombier 
773*219b2ee8SDavid du Colombier     int		pg;			/* next page we're printing */
774*219b2ee8SDavid du Colombier 
775*219b2ee8SDavid du Colombier {
776*219b2ee8SDavid du Colombier 
777*219b2ee8SDavid du Colombier     static FILE	*fp_null = NULL;	/* if output is turned off */
778*219b2ee8SDavid du Colombier 
779*219b2ee8SDavid du Colombier /*
780*219b2ee8SDavid du Colombier  *
781*219b2ee8SDavid du Colombier  * If we're not supposed to print page pg, fp_out will be directed to /dev/null,
782*219b2ee8SDavid du Colombier  * otherwise output goes to stdout.
783*219b2ee8SDavid du Colombier  *
784*219b2ee8SDavid du Colombier  */
785*219b2ee8SDavid du Colombier 
786*219b2ee8SDavid du Colombier     if ( pg >= 0 && in_olist(pg) == ON )
787*219b2ee8SDavid du Colombier 	fp_out = stdout;
788*219b2ee8SDavid du Colombier     else if ( (fp_out = fp_null) == NULL )
789*219b2ee8SDavid du Colombier 	fp_out = fp_null = fopen("/dev/null", "w");
790*219b2ee8SDavid du Colombier 
791*219b2ee8SDavid du Colombier }   /* End of redirect */
792*219b2ee8SDavid du Colombier 
793*219b2ee8SDavid du Colombier /*****************************************************************************/
794*219b2ee8SDavid du Colombier 
795