xref: /plan9/sys/src/cmd/postscript/postbgi/postbgi.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier /*
2*7dd7cddfSDavid du Colombier  *
3*7dd7cddfSDavid du Colombier  * postbgi - BGI (Basic Graphical Instructions) to PostScript translator.
4*7dd7cddfSDavid du Colombier  *
5*7dd7cddfSDavid du Colombier  * A simple program that translates BGI files into PostScript. Probably only
6*7dd7cddfSDavid du Colombier  * useful in Computer Centers that support STARE or PRISM plotters. Most of the
7*7dd7cddfSDavid du Colombier  * code was borrowed from the corresponding program that was written for printers
8*7dd7cddfSDavid du Colombier  * that understand Impress.
9*7dd7cddfSDavid du Colombier  *
10*7dd7cddfSDavid du Colombier  * Extending the original program to handle PRISM jobs was not trivial. Graphics
11*7dd7cddfSDavid du Colombier  * packages that support PRISM occasionally use BGI commands that I ignored in the
12*7dd7cddfSDavid du Colombier  * STARE implementation. Subroutines, color requests, patterns (for filling), and
13*7dd7cddfSDavid du Colombier  * filled trapeziods were the most important omissions. All are now implemented,
14*7dd7cddfSDavid du Colombier  * and at present only repeats, filled slices, and raster rectangles are missing.
15*7dd7cddfSDavid du Colombier  *
16*7dd7cddfSDavid du Colombier  * Pattern filling results were not always predictable or even good, unless the
17*7dd7cddfSDavid du Colombier  * halftone screen definitions were changed and scaling was adjusted so one pixel
18*7dd7cddfSDavid du Colombier  * in user space mapped into an integral number of device space pixels. Doing that
19*7dd7cddfSDavid du Colombier  * makes the resulting PostScript output device dependent, but was often necessary.
20*7dd7cddfSDavid du Colombier  * I've added two booleans to the PostScript prologue (fixscreen and scaletodevice)
21*7dd7cddfSDavid du Colombier  * that control what's done. By default both are false (check postbgi.ps) but can
22*7dd7cddfSDavid du Colombier  * be set to true on the command line using the -P option or by hand by changing
23*7dd7cddfSDavid du Colombier  * the definitions in the prologue. A command line that would set fixscreen and
24*7dd7cddfSDavid du Colombier  * scaletodevice true would look like,
25*7dd7cddfSDavid du Colombier  *
26*7dd7cddfSDavid du Colombier  *	postbgi -P"/fixscreen true" -P"/scaletodevice true" file >file.ps
27*7dd7cddfSDavid du Colombier  *
28*7dd7cddfSDavid du Colombier  * Several other approaches are available if you want to have your spooler handle
29*7dd7cddfSDavid du Colombier  * STARE and PRISM jobs differently. A boolean called prism is defined in the
30*7dd7cddfSDavid du Colombier  * prologue (postbgi.ps) and if it's set to true PostScript procedure setup will
31*7dd7cddfSDavid du Colombier  * set fixscreen and scaletodevice to true before anything important is done. That
32*7dd7cddfSDavid du Colombier  * means the following command line,
33*7dd7cddfSDavid du Colombier  *
34*7dd7cddfSDavid du Colombier  *	postbgi -P"/prism true" file >file.ps
35*7dd7cddfSDavid du Colombier  *
36*7dd7cddfSDavid du Colombier  * accomplishes the same things as the last example. Two different prologue files,
37*7dd7cddfSDavid du Colombier  * one for STARE jobs and the other for PRISM, could be used and the spooler could
38*7dd7cddfSDavid du Colombier  * point postbgi to the appropriate one using the -L option. In that case the only
39*7dd7cddfSDavid du Colombier  * important difference in the two prologues would be the definition of prism. The
40*7dd7cddfSDavid du Colombier  * prologue used for PRISM jobs would have prism set to true, while the STARE
41*7dd7cddfSDavid du Colombier  * prologue would have it set to false.
42*7dd7cddfSDavid du Colombier  *
43*7dd7cddfSDavid du Colombier  * Also included is code that ties lines to device space coordinates. What you get
44*7dd7cddfSDavid du Colombier  * is a consistent line thickness, but placement of lines won't be exact. It's a
45*7dd7cddfSDavid du Colombier  * trade-off that should be right for most jobs. Everything is implemented in the
46*7dd7cddfSDavid du Colombier  * prologue (postbgi.ps) and nothing will be done if the linewidth is zero or if
47*7dd7cddfSDavid du Colombier  * the boolean fixlinewidth (again in postbgi.ps) is false. Once again the -P
48*7dd7cddfSDavid du Colombier  * option can be used to set fixlinewidth to whatever you choose.
49*7dd7cddfSDavid du Colombier  *
50*7dd7cddfSDavid du Colombier  * BGI supports color mixing but PostScript doesn't. BGI files that expect to mix
51*7dd7cddfSDavid du Colombier  * colors won't print properly. PostScript's fill operator overlays whatever has
52*7dd7cddfSDavid du Colombier  * already been put down. Implementing color mixing would have been a terribly
53*7dd7cddfSDavid du Colombier  * difficult job - not worth the effort!
54*7dd7cddfSDavid du Colombier  *
55*7dd7cddfSDavid du Colombier  * The PostScript prologue is copied from *prologue before any of the input files
56*7dd7cddfSDavid du Colombier  * are translated. The program expects that the following PostScript procedures
57*7dd7cddfSDavid du Colombier  * are defined in that file:
58*7dd7cddfSDavid du Colombier  *
59*7dd7cddfSDavid du Colombier  *	setup
60*7dd7cddfSDavid du Colombier  *
61*7dd7cddfSDavid du Colombier  *	  mark ... setup -
62*7dd7cddfSDavid du Colombier  *
63*7dd7cddfSDavid du Colombier  *	    Handles special initialization stuff that depends on how the program
64*7dd7cddfSDavid du Colombier  *	    was called. Expects to find a mark followed by key/value pairs on the
65*7dd7cddfSDavid du Colombier  *	    stack. The def operator is applied to each pair up to the mark, then
66*7dd7cddfSDavid du Colombier  *	    the default state is set up.
67*7dd7cddfSDavid du Colombier  *
68*7dd7cddfSDavid du Colombier  *	pagesetup
69*7dd7cddfSDavid du Colombier  *
70*7dd7cddfSDavid du Colombier  *	  page pagesetup -
71*7dd7cddfSDavid du Colombier  *
72*7dd7cddfSDavid du Colombier  *	    Does whatever is needed to set things up for the next page. Expects
73*7dd7cddfSDavid du Colombier  *	    to find the current page number on the stack.
74*7dd7cddfSDavid du Colombier  *
75*7dd7cddfSDavid du Colombier  *	v
76*7dd7cddfSDavid du Colombier  *
77*7dd7cddfSDavid du Colombier  *	  dx1 dy1 ... dxn dyn x y v -
78*7dd7cddfSDavid du Colombier  *
79*7dd7cddfSDavid du Colombier  *	    Draws the vector described by the numbers on the stack. The top two
80*7dd7cddfSDavid du Colombier  *	    numbers are the coordinates of the starting point. The rest of the
81*7dd7cddfSDavid du Colombier  *	    numbers are relative displacements from the preceeding point.
82*7dd7cddfSDavid du Colombier  *
83*7dd7cddfSDavid du Colombier  *	pp
84*7dd7cddfSDavid du Colombier  *
85*7dd7cddfSDavid du Colombier  *	  x1 y1 ... xn yn string pp -
86*7dd7cddfSDavid du Colombier  *
87*7dd7cddfSDavid du Colombier  *	    Prints string, which is always a single character, at the points
88*7dd7cddfSDavid du Colombier  *	    represented by the rest of the numbers on the stack.
89*7dd7cddfSDavid du Colombier  *
90*7dd7cddfSDavid du Colombier  *	R
91*7dd7cddfSDavid du Colombier  *
92*7dd7cddfSDavid du Colombier  *	  n deltax deltay x y R -
93*7dd7cddfSDavid du Colombier  *
94*7dd7cddfSDavid du Colombier  *	    Creates a rectangular path with its lower left corner at (x, y) and
95*7dd7cddfSDavid du Colombier  *	    sides of length deltax and deltay. The resulting path is stroked if
96*7dd7cddfSDavid du Colombier  *	    n is 0 and filled otherwise.
97*7dd7cddfSDavid du Colombier  *
98*7dd7cddfSDavid du Colombier  *	T
99*7dd7cddfSDavid du Colombier  *
100*7dd7cddfSDavid du Colombier  *	  dx3 dy3 dx2 dy2 dx1 dy1 x y T -
101*7dd7cddfSDavid du Colombier  *
102*7dd7cddfSDavid du Colombier  *	    Fills a trapezoid starting at (x, y) and having relative displacements
103*7dd7cddfSDavid du Colombier  *	    given by the (dx, dy) pairs.
104*7dd7cddfSDavid du Colombier  *
105*7dd7cddfSDavid du Colombier  *	t
106*7dd7cddfSDavid du Colombier  *
107*7dd7cddfSDavid du Colombier  *	  angle x y string t -
108*7dd7cddfSDavid du Colombier  *
109*7dd7cddfSDavid du Colombier  *	    Prints string starting at (x, y) using an orientation of angle degrees.
110*7dd7cddfSDavid du Colombier  *	    The PostScript procedure can handle any angle, but BGI files will only
111*7dd7cddfSDavid du Colombier  *	    request 0 or 90 degrees. Text printed at any other orientation will be
112*7dd7cddfSDavid du Colombier  *	    vector generated.
113*7dd7cddfSDavid du Colombier  *
114*7dd7cddfSDavid du Colombier  *	p
115*7dd7cddfSDavid du Colombier  *
116*7dd7cddfSDavid du Colombier  *	  x y p -
117*7dd7cddfSDavid du Colombier  *
118*7dd7cddfSDavid du Colombier  *	    Called to mark the point (x, y). It fills a small circle, that right
119*7dd7cddfSDavid du Colombier  *	    now has a constant radius. This stuff could probably be much more
120*7dd7cddfSDavid du Colombier  *	    efficient?
121*7dd7cddfSDavid du Colombier  *
122*7dd7cddfSDavid du Colombier  *	l
123*7dd7cddfSDavid du Colombier  *
124*7dd7cddfSDavid du Colombier  *	  array l -
125*7dd7cddfSDavid du Colombier  *
126*7dd7cddfSDavid du Colombier  *	    Sets the line drawing mode according to the description given in
127*7dd7cddfSDavid du Colombier  *	    array. The arrays that describe the different line styles are declared
128*7dd7cddfSDavid du Colombier  *	    in STYLES (file posttek.h), although it would be better to have them
129*7dd7cddfSDavid du Colombier  *	    defined in the prologue.
130*7dd7cddfSDavid du Colombier  *
131*7dd7cddfSDavid du Colombier  *	c
132*7dd7cddfSDavid du Colombier  *
133*7dd7cddfSDavid du Colombier  *	  red green blue c -
134*7dd7cddfSDavid du Colombier  *
135*7dd7cddfSDavid du Colombier  *	    Sets the current PostScript RGB color using setrgbcolor. Also used for
136*7dd7cddfSDavid du Colombier  *	    selecting appropriate patterns as colors.
137*7dd7cddfSDavid du Colombier  *
138*7dd7cddfSDavid du Colombier  *	f
139*7dd7cddfSDavid du Colombier  *
140*7dd7cddfSDavid du Colombier  *	  bgisize f -
141*7dd7cddfSDavid du Colombier  *
142*7dd7cddfSDavid du Colombier  *	    Changes the size of the font that's used to print text. bgisize is a
143*7dd7cddfSDavid du Colombier  *	    grid separation in a 5 by 7 array in which characters are assumed to
144*7dd7cddfSDavid du Colombier  *	    be built.
145*7dd7cddfSDavid du Colombier  *
146*7dd7cddfSDavid du Colombier  *	done
147*7dd7cddfSDavid du Colombier  *
148*7dd7cddfSDavid du Colombier  *	  done
149*7dd7cddfSDavid du Colombier  *
150*7dd7cddfSDavid du Colombier  *	    Makes sure the last page is printed. Only needed when we're printing
151*7dd7cddfSDavid du Colombier  *	    more than one page on each sheet of paper.
152*7dd7cddfSDavid du Colombier  *
153*7dd7cddfSDavid du Colombier  * The default line width is zero, which forces lines to be one pixel wide. That
154*7dd7cddfSDavid du Colombier  * works well for 'write to black' engines but won't be right for 'write to white'
155*7dd7cddfSDavid du Colombier  * engines. The line width can be changed using the -w option, or you can change
156*7dd7cddfSDavid du Colombier  * the initialization of linewidth in the prologue. Code in the prologue supports
157*7dd7cddfSDavid du Colombier  * the generation of uniform width lines when linewidth is non-zero and boolean
158*7dd7cddfSDavid du Colombier  * fixlinewidth is true.
159*7dd7cddfSDavid du Colombier  *
160*7dd7cddfSDavid du Colombier  * Many default values, like the magnification and orientation, are defined in
161*7dd7cddfSDavid du Colombier  * the prologue, which is where they belong. If they're changed (by options), an
162*7dd7cddfSDavid du Colombier  * appropriate definition is made after the prologue is added to the output file.
163*7dd7cddfSDavid du Colombier  * The -P option passes arbitrary PostScript through to the output file. Among
164*7dd7cddfSDavid du Colombier  * other things it can be used to set (or change) values that can't be accessed by
165*7dd7cddfSDavid du Colombier  * other options.
166*7dd7cddfSDavid du Colombier  *
167*7dd7cddfSDavid du Colombier  */
168*7dd7cddfSDavid du Colombier 
169*7dd7cddfSDavid du Colombier #include <stdio.h>
170*7dd7cddfSDavid du Colombier #include <sys/types.h>
171*7dd7cddfSDavid du Colombier #include <fcntl.h>
172*7dd7cddfSDavid du Colombier #include <signal.h>
173*7dd7cddfSDavid du Colombier #include <math.h>
174*7dd7cddfSDavid du Colombier #include <ctype.h>
175*7dd7cddfSDavid du Colombier #ifdef plan9
176*7dd7cddfSDavid du Colombier #define	isascii(c)	((unsigned char)(c)<=0177)
177*7dd7cddfSDavid du Colombier #endif
178*7dd7cddfSDavid du Colombier 
179*7dd7cddfSDavid du Colombier #include "comments.h"			/* PostScript file structuring comments */
180*7dd7cddfSDavid du Colombier #include "gen.h"			/* general purpose definitions */
181*7dd7cddfSDavid du Colombier #include "path.h"			/* for the prologue */
182*7dd7cddfSDavid du Colombier #include "ext.h"			/* external variable declarations */
183*7dd7cddfSDavid du Colombier #include "postbgi.h"			/* a few definitions just used here */
184*7dd7cddfSDavid du Colombier 
185*7dd7cddfSDavid du Colombier char	*optnames = "a:c:f:m:n:o:p:w:x:y:A:C:E:J:L:P:R:DI";
186*7dd7cddfSDavid du Colombier 
187*7dd7cddfSDavid du Colombier char	*prologue = POSTBGI;		/* default PostScript prologue */
188*7dd7cddfSDavid du Colombier char	*formfile = FORMFILE;		/* stuff for multiple pages per sheet */
189*7dd7cddfSDavid du Colombier 
190*7dd7cddfSDavid du Colombier int	formsperpage = 1;		/* page images on each piece of paper */
191*7dd7cddfSDavid du Colombier int	copies = 1;			/* and this many copies of each sheet */
192*7dd7cddfSDavid du Colombier 
193*7dd7cddfSDavid du Colombier char	*styles[] = STYLES;		/* descriptions of line styles */
194*7dd7cddfSDavid du Colombier 
195*7dd7cddfSDavid du Colombier int	hpos = 0;			/* current horizontal */
196*7dd7cddfSDavid du Colombier int	vpos = 0;			/* and vertical position */
197*7dd7cddfSDavid du Colombier 
198*7dd7cddfSDavid du Colombier int	bgisize = BGISIZE;		/* just the character grid spacing */
199*7dd7cddfSDavid du Colombier int	linespace;			/* distance between lines of text */
200*7dd7cddfSDavid du Colombier 
201*7dd7cddfSDavid du Colombier int	bgimode;			/* character or graph mode */
202*7dd7cddfSDavid du Colombier 
203*7dd7cddfSDavid du Colombier int	in_subr = FALSE;		/* currently defining a subroutine */
204*7dd7cddfSDavid du Colombier int	in_global = FALSE;		/* to save space with subroutine defs */
205*7dd7cddfSDavid du Colombier int	subr_id = 0;			/* defining this subroutine */
206*7dd7cddfSDavid du Colombier int	shpos = 0;			/* starting horizontal */
207*7dd7cddfSDavid du Colombier int	svpos = 0;			/* and vertical positions - subroutines */
208*7dd7cddfSDavid du Colombier Disp	displacement[64];		/* dx and dy after a subroutine call */
209*7dd7cddfSDavid du Colombier 
210*7dd7cddfSDavid du Colombier Fontmap	fontmap[] = FONTMAP;		/* for translating font names */
211*7dd7cddfSDavid du Colombier char	*fontname = "Courier";		/* use this PostScript font */
212*7dd7cddfSDavid du Colombier 
213*7dd7cddfSDavid du Colombier int	page = 0;			/* page we're working on */
214*7dd7cddfSDavid du Colombier int	printed = 0;			/* printed this many pages */
215*7dd7cddfSDavid du Colombier 
216*7dd7cddfSDavid du Colombier FILE	*fp_in = stdin;			/* read from this file */
217*7dd7cddfSDavid du Colombier FILE	*fp_out = NULL;			/* and write stuff here */
218*7dd7cddfSDavid du Colombier FILE	*fp_acct = NULL;		/* for accounting data */
219*7dd7cddfSDavid du Colombier 
220*7dd7cddfSDavid du Colombier /*****************************************************************************/
221*7dd7cddfSDavid du Colombier 
main(agc,agv)222*7dd7cddfSDavid du Colombier main(agc, agv)
223*7dd7cddfSDavid du Colombier 
224*7dd7cddfSDavid du Colombier     int		agc;
225*7dd7cddfSDavid du Colombier     char	*agv[];
226*7dd7cddfSDavid du Colombier 
227*7dd7cddfSDavid du Colombier {
228*7dd7cddfSDavid du Colombier 
229*7dd7cddfSDavid du Colombier /*
230*7dd7cddfSDavid du Colombier  *
231*7dd7cddfSDavid du Colombier  * A program that converts BGI (Basic Graphical Instructions) files generated by
232*7dd7cddfSDavid du Colombier  * packages like GRAFPAC and DISSPLA into PostScript. It does an adequate job but
233*7dd7cddfSDavid du Colombier  * is far from perfect. A few things still haven't been implemented (eg. repeats
234*7dd7cddfSDavid du Colombier  * and raster rectangles), but what's here should be good enough for most of our
235*7dd7cddfSDavid du Colombier  * STARE and PRISM jobs. Color mixing (in PRISM jobs) won't work on PostScript
236*7dd7cddfSDavid du Colombier  * printers, and there's no chance I'll implement it!
237*7dd7cddfSDavid du Colombier  *
238*7dd7cddfSDavid du Colombier  */
239*7dd7cddfSDavid du Colombier 
240*7dd7cddfSDavid du Colombier     argc = agc;				/* global so everyone can use them */
241*7dd7cddfSDavid du Colombier     argv = agv;
242*7dd7cddfSDavid du Colombier 
243*7dd7cddfSDavid du Colombier     prog_name = argv[0];		/* just for error messages */
244*7dd7cddfSDavid du Colombier 
245*7dd7cddfSDavid du Colombier     init_signals();			/* set up interrupt handling */
246*7dd7cddfSDavid du Colombier     header();				/* PostScript header comments */
247*7dd7cddfSDavid du Colombier     options();				/* command line options */
248*7dd7cddfSDavid du Colombier     setup();				/* for PostScript */
249*7dd7cddfSDavid du Colombier     arguments();			/* followed by each input file */
250*7dd7cddfSDavid du Colombier     done();				/* print the last page etc. */
251*7dd7cddfSDavid du Colombier     account();				/* job accounting data */
252*7dd7cddfSDavid du Colombier 
253*7dd7cddfSDavid du Colombier     exit(x_stat);			/* everything probably went OK */
254*7dd7cddfSDavid du Colombier 
255*7dd7cddfSDavid du Colombier }   /* End of main */
256*7dd7cddfSDavid du Colombier 
257*7dd7cddfSDavid du Colombier /*****************************************************************************/
258*7dd7cddfSDavid du Colombier 
init_signals()259*7dd7cddfSDavid du Colombier init_signals()
260*7dd7cddfSDavid du Colombier 
261*7dd7cddfSDavid du Colombier {
262*7dd7cddfSDavid du Colombier 
263*7dd7cddfSDavid du Colombier /*
264*7dd7cddfSDavid du Colombier  *
265*7dd7cddfSDavid du Colombier  * Make sure we handle interrupts.
266*7dd7cddfSDavid du Colombier  *
267*7dd7cddfSDavid du Colombier  */
268*7dd7cddfSDavid du Colombier 
269*7dd7cddfSDavid du Colombier     if ( signal(SIGINT, interrupt) == SIG_IGN )  {
270*7dd7cddfSDavid du Colombier 	signal(SIGINT, SIG_IGN);
271*7dd7cddfSDavid du Colombier 	signal(SIGQUIT, SIG_IGN);
272*7dd7cddfSDavid du Colombier 	signal(SIGHUP, SIG_IGN);
273*7dd7cddfSDavid du Colombier     } else {
274*7dd7cddfSDavid du Colombier 	signal(SIGHUP, interrupt);
275*7dd7cddfSDavid du Colombier 	signal(SIGQUIT, interrupt);
276*7dd7cddfSDavid du Colombier     }   /* End else */
277*7dd7cddfSDavid du Colombier 
278*7dd7cddfSDavid du Colombier     signal(SIGTERM, interrupt);
279*7dd7cddfSDavid du Colombier 
280*7dd7cddfSDavid du Colombier }   /* End of init_signals */
281*7dd7cddfSDavid du Colombier 
282*7dd7cddfSDavid du Colombier /*****************************************************************************/
283*7dd7cddfSDavid du Colombier 
header()284*7dd7cddfSDavid du Colombier header()
285*7dd7cddfSDavid du Colombier 
286*7dd7cddfSDavid du Colombier {
287*7dd7cddfSDavid du Colombier 
288*7dd7cddfSDavid du Colombier     int		ch;			/* return value from getopt() */
289*7dd7cddfSDavid du Colombier     int		old_optind = optind;	/* for restoring optind - should be 1 */
290*7dd7cddfSDavid du Colombier 
291*7dd7cddfSDavid du Colombier /*
292*7dd7cddfSDavid du Colombier  *
293*7dd7cddfSDavid du Colombier  * Scans the option list looking for things, like the prologue file, that we need
294*7dd7cddfSDavid du Colombier  * right away but could be changed from the default. Doing things this way is an
295*7dd7cddfSDavid du Colombier  * attempt to conform to Adobe's latest file structuring conventions. In particular
296*7dd7cddfSDavid du Colombier  * they now say there should be nothing executed in the prologue, and they have
297*7dd7cddfSDavid du Colombier  * added two new comments that delimit global initialization calls. Once we know
298*7dd7cddfSDavid du Colombier  * where things really are we write out the job header, follow it by the prologue,
299*7dd7cddfSDavid du Colombier  * and then add the ENDPROLOG and BEGINSETUP comments.
300*7dd7cddfSDavid du Colombier  *
301*7dd7cddfSDavid du Colombier  */
302*7dd7cddfSDavid du Colombier 
303*7dd7cddfSDavid du Colombier     while ( (ch = getopt(argc, argv, optnames)) != EOF )
304*7dd7cddfSDavid du Colombier 	if ( ch == 'L' )
305*7dd7cddfSDavid du Colombier 	    prologue = optarg;
306*7dd7cddfSDavid du Colombier 	else if ( ch == '?' )
307*7dd7cddfSDavid du Colombier 	    error(FATAL, "");
308*7dd7cddfSDavid du Colombier 
309*7dd7cddfSDavid du Colombier     optind = old_optind;		/* get ready for option scanning */
310*7dd7cddfSDavid du Colombier 
311*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", CONFORMING);
312*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
313*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
314*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s %s\n", PAGES, ATEND);
315*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", ENDCOMMENTS);
316*7dd7cddfSDavid du Colombier 
317*7dd7cddfSDavid du Colombier     if ( cat(prologue) == FALSE )
318*7dd7cddfSDavid du Colombier 	error(FATAL, "can't read %s", prologue);
319*7dd7cddfSDavid du Colombier 
320*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", ENDPROLOG);
321*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", BEGINSETUP);
322*7dd7cddfSDavid du Colombier     fprintf(stdout, "mark\n");
323*7dd7cddfSDavid du Colombier 
324*7dd7cddfSDavid du Colombier }   /* End of header */
325*7dd7cddfSDavid du Colombier 
326*7dd7cddfSDavid du Colombier /*****************************************************************************/
327*7dd7cddfSDavid du Colombier 
options()328*7dd7cddfSDavid du Colombier options()
329*7dd7cddfSDavid du Colombier 
330*7dd7cddfSDavid du Colombier {
331*7dd7cddfSDavid du Colombier 
332*7dd7cddfSDavid du Colombier     int		ch;			/* option name - from getopt() */
333*7dd7cddfSDavid du Colombier 
334*7dd7cddfSDavid du Colombier /*
335*7dd7cddfSDavid du Colombier  *
336*7dd7cddfSDavid du Colombier  * Reads and processes the command line options.
337*7dd7cddfSDavid du Colombier  *
338*7dd7cddfSDavid du Colombier  */
339*7dd7cddfSDavid du Colombier 
340*7dd7cddfSDavid du Colombier     while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
341*7dd7cddfSDavid du Colombier 	switch ( ch )  {
342*7dd7cddfSDavid du Colombier 	    case 'a':			/* aspect ratio */
343*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/aspectratio %s def\n", optarg);
344*7dd7cddfSDavid du Colombier 		    break;
345*7dd7cddfSDavid du Colombier 
346*7dd7cddfSDavid du Colombier 	    case 'c':			/* copies */
347*7dd7cddfSDavid du Colombier 		    copies = atoi(optarg);
348*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/#copies %s def\n", optarg);
349*7dd7cddfSDavid du Colombier 		    break;
350*7dd7cddfSDavid du Colombier 
351*7dd7cddfSDavid du Colombier 	    case 'f':			/* new font */
352*7dd7cddfSDavid du Colombier 		    fontname = get_font(optarg);
353*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/font /%s def\n", fontname);
354*7dd7cddfSDavid du Colombier 		    break;
355*7dd7cddfSDavid du Colombier 
356*7dd7cddfSDavid du Colombier 	    case 'm':			/* magnification */
357*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/magnification %s def\n", optarg);
358*7dd7cddfSDavid du Colombier 		    break;
359*7dd7cddfSDavid du Colombier 
360*7dd7cddfSDavid du Colombier 	    case 'n':			/* forms per page */
361*7dd7cddfSDavid du Colombier 		    formsperpage = atoi(optarg);
362*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
363*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/formsperpage %s def\n", optarg);
364*7dd7cddfSDavid du Colombier 		    break;
365*7dd7cddfSDavid du Colombier 
366*7dd7cddfSDavid du Colombier 	    case 'o':			/* output page list */
367*7dd7cddfSDavid du Colombier 		    out_list(optarg);
368*7dd7cddfSDavid du Colombier 		    break;
369*7dd7cddfSDavid du Colombier 
370*7dd7cddfSDavid du Colombier 	    case 'p':			/* landscape or portrait mode */
371*7dd7cddfSDavid du Colombier 		    if ( *optarg == 'l' )
372*7dd7cddfSDavid du Colombier 			fprintf(stdout, "/landscape true def\n");
373*7dd7cddfSDavid du Colombier 		    else fprintf(stdout, "/landscape false def\n");
374*7dd7cddfSDavid du Colombier 		    break;
375*7dd7cddfSDavid du Colombier 
376*7dd7cddfSDavid du Colombier 	    case 'w':			/* line width */
377*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/linewidth %s def\n", optarg);
378*7dd7cddfSDavid du Colombier 		    break;
379*7dd7cddfSDavid du Colombier 
380*7dd7cddfSDavid du Colombier 	    case 'x':			/* shift horizontally */
381*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/xoffset %s def\n", optarg);
382*7dd7cddfSDavid du Colombier 		    break;
383*7dd7cddfSDavid du Colombier 
384*7dd7cddfSDavid du Colombier 	    case 'y':			/* and vertically on the page */
385*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "/yoffset %s def\n", optarg);
386*7dd7cddfSDavid du Colombier 		    break;
387*7dd7cddfSDavid du Colombier 
388*7dd7cddfSDavid du Colombier 	    case 'A':			/* force job accounting */
389*7dd7cddfSDavid du Colombier 	    case 'J':
390*7dd7cddfSDavid du Colombier 		    if ( (fp_acct = fopen(optarg, "a")) == NULL )
391*7dd7cddfSDavid du Colombier 		    	error(FATAL, "can't open accounting file %s", optarg);
392*7dd7cddfSDavid du Colombier 		    break;
393*7dd7cddfSDavid du Colombier 
394*7dd7cddfSDavid du Colombier 	    case 'C':			/* copy file straight to output */
395*7dd7cddfSDavid du Colombier 		    if ( cat(optarg) == FALSE )
396*7dd7cddfSDavid du Colombier 			error(FATAL, "can't read %s", optarg);
397*7dd7cddfSDavid du Colombier 		    break;
398*7dd7cddfSDavid du Colombier 
399*7dd7cddfSDavid du Colombier 	    case 'E':			/* text font encoding */
400*7dd7cddfSDavid du Colombier 		    fontencoding = optarg;
401*7dd7cddfSDavid du Colombier 		    break;
402*7dd7cddfSDavid du Colombier 
403*7dd7cddfSDavid du Colombier 	    case 'L':			/* Postscript prologue file */
404*7dd7cddfSDavid du Colombier 		    prologue = optarg;
405*7dd7cddfSDavid du Colombier 		    break;
406*7dd7cddfSDavid du Colombier 
407*7dd7cddfSDavid du Colombier 	    case 'P':			/* PostScript pass through */
408*7dd7cddfSDavid du Colombier 		    fprintf(stdout, "%s\n", optarg);
409*7dd7cddfSDavid du Colombier 		    break;
410*7dd7cddfSDavid du Colombier 
411*7dd7cddfSDavid du Colombier 	    case 'R':			/* special global or page level request */
412*7dd7cddfSDavid du Colombier 		    saverequest(optarg);
413*7dd7cddfSDavid du Colombier 		    break;
414*7dd7cddfSDavid du Colombier 
415*7dd7cddfSDavid du Colombier 	    case 'D':			/* debug flag */
416*7dd7cddfSDavid du Colombier 		    debug = ON;
417*7dd7cddfSDavid du Colombier 		    break;
418*7dd7cddfSDavid du Colombier 
419*7dd7cddfSDavid du Colombier 	    case 'I':			/* ignore FATAL errors */
420*7dd7cddfSDavid du Colombier 		    ignore = ON;
421*7dd7cddfSDavid du Colombier 		    break;
422*7dd7cddfSDavid du Colombier 
423*7dd7cddfSDavid du Colombier 	    case '?':			/* don't know the option */
424*7dd7cddfSDavid du Colombier 		    error(FATAL, "");
425*7dd7cddfSDavid du Colombier 		    break;
426*7dd7cddfSDavid du Colombier 
427*7dd7cddfSDavid du Colombier 	    default:			/* don't know what to do for ch */
428*7dd7cddfSDavid du Colombier 		    error(FATAL, "missing case for option %c", ch);
429*7dd7cddfSDavid du Colombier 		    break;
430*7dd7cddfSDavid du Colombier 	}   /* End switch */
431*7dd7cddfSDavid du Colombier     }	/* End while */
432*7dd7cddfSDavid du Colombier 
433*7dd7cddfSDavid du Colombier     argc -= optind;			/* get ready for non-option args */
434*7dd7cddfSDavid du Colombier     argv += optind;
435*7dd7cddfSDavid du Colombier 
436*7dd7cddfSDavid du Colombier }   /* End of options */
437*7dd7cddfSDavid du Colombier 
438*7dd7cddfSDavid du Colombier /*****************************************************************************/
439*7dd7cddfSDavid du Colombier 
get_font(name)440*7dd7cddfSDavid du Colombier char *get_font(name)
441*7dd7cddfSDavid du Colombier 
442*7dd7cddfSDavid du Colombier     char	*name;			/* name the user asked for */
443*7dd7cddfSDavid du Colombier 
444*7dd7cddfSDavid du Colombier {
445*7dd7cddfSDavid du Colombier 
446*7dd7cddfSDavid du Colombier     int		i;			/* for looking through fontmap[] */
447*7dd7cddfSDavid du Colombier 
448*7dd7cddfSDavid du Colombier /*
449*7dd7cddfSDavid du Colombier  *
450*7dd7cddfSDavid du Colombier  * Called from options() to map a user's font name into a legal PostScript name.
451*7dd7cddfSDavid du Colombier  * If the lookup fails *name is returned to the caller. That should let you choose
452*7dd7cddfSDavid du Colombier  * any PostScript font.
453*7dd7cddfSDavid du Colombier  *
454*7dd7cddfSDavid du Colombier  */
455*7dd7cddfSDavid du Colombier 
456*7dd7cddfSDavid du Colombier     for ( i = 0; fontmap[i].name != NULL; i++ )
457*7dd7cddfSDavid du Colombier 	if ( strcmp(name, fontmap[i].name) == 0 )
458*7dd7cddfSDavid du Colombier 	    return(fontmap[i].val);
459*7dd7cddfSDavid du Colombier 
460*7dd7cddfSDavid du Colombier     return(name);
461*7dd7cddfSDavid du Colombier 
462*7dd7cddfSDavid du Colombier }   /* End of get_font */
463*7dd7cddfSDavid du Colombier 
464*7dd7cddfSDavid du Colombier /*****************************************************************************/
465*7dd7cddfSDavid du Colombier 
setup()466*7dd7cddfSDavid du Colombier setup()
467*7dd7cddfSDavid du Colombier 
468*7dd7cddfSDavid du Colombier {
469*7dd7cddfSDavid du Colombier 
470*7dd7cddfSDavid du Colombier /*
471*7dd7cddfSDavid du Colombier  *
472*7dd7cddfSDavid du Colombier  * Handles things that must be done after the options are read but before the
473*7dd7cddfSDavid du Colombier  * input files are processed.
474*7dd7cddfSDavid du Colombier  *
475*7dd7cddfSDavid du Colombier  */
476*7dd7cddfSDavid du Colombier 
477*7dd7cddfSDavid du Colombier     writerequest(0, stdout);		/* global requests eg. manual feed */
478*7dd7cddfSDavid du Colombier     setencoding(fontencoding);
479*7dd7cddfSDavid du Colombier     fprintf(stdout, "setup\n");
480*7dd7cddfSDavid du Colombier 
481*7dd7cddfSDavid du Colombier     if ( formsperpage > 1 )  {
482*7dd7cddfSDavid du Colombier 	if ( cat(formfile) == FALSE )
483*7dd7cddfSDavid du Colombier 	    error(FATAL, "can't read %s", formfile);
484*7dd7cddfSDavid du Colombier 	fprintf(stdout, "%d setupforms\n", formsperpage);
485*7dd7cddfSDavid du Colombier     }	/* End if */
486*7dd7cddfSDavid du Colombier 
487*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", ENDSETUP);
488*7dd7cddfSDavid du Colombier 
489*7dd7cddfSDavid du Colombier }   /* End of setup */
490*7dd7cddfSDavid du Colombier 
491*7dd7cddfSDavid du Colombier /*****************************************************************************/
492*7dd7cddfSDavid du Colombier 
arguments()493*7dd7cddfSDavid du Colombier arguments()
494*7dd7cddfSDavid du Colombier 
495*7dd7cddfSDavid du Colombier {
496*7dd7cddfSDavid du Colombier 
497*7dd7cddfSDavid du Colombier /*
498*7dd7cddfSDavid du Colombier  *
499*7dd7cddfSDavid du Colombier  * Makes sure all the non-option command line options are processed. If we get
500*7dd7cddfSDavid du Colombier  * here and there aren't any arguments left, or if '-' is one of the input files
501*7dd7cddfSDavid du Colombier  * we'll process stdin.
502*7dd7cddfSDavid du Colombier  *
503*7dd7cddfSDavid du Colombier  */
504*7dd7cddfSDavid du Colombier 
505*7dd7cddfSDavid du Colombier     if ( argc < 1 )
506*7dd7cddfSDavid du Colombier 	conv();
507*7dd7cddfSDavid du Colombier     else
508*7dd7cddfSDavid du Colombier 	while ( argc > 0 )  {
509*7dd7cddfSDavid du Colombier 	    if ( strcmp(*argv, "-") == 0 )
510*7dd7cddfSDavid du Colombier 		fp_in = stdin;
511*7dd7cddfSDavid du Colombier 	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
512*7dd7cddfSDavid du Colombier 		error(FATAL, "can't open %s", *argv);
513*7dd7cddfSDavid du Colombier 	    conv();
514*7dd7cddfSDavid du Colombier 	    if ( fp_in != stdin )
515*7dd7cddfSDavid du Colombier 		fclose(fp_in);
516*7dd7cddfSDavid du Colombier 	    argc--;
517*7dd7cddfSDavid du Colombier 	    argv++;
518*7dd7cddfSDavid du Colombier 	}   /* End while */
519*7dd7cddfSDavid du Colombier 
520*7dd7cddfSDavid du Colombier }   /* End of arguments */
521*7dd7cddfSDavid du Colombier 
522*7dd7cddfSDavid du Colombier /*****************************************************************************/
523*7dd7cddfSDavid du Colombier 
done()524*7dd7cddfSDavid du Colombier done()
525*7dd7cddfSDavid du Colombier 
526*7dd7cddfSDavid du Colombier {
527*7dd7cddfSDavid du Colombier 
528*7dd7cddfSDavid du Colombier /*
529*7dd7cddfSDavid du Colombier  *
530*7dd7cddfSDavid du Colombier  * Finished with the last input file, so mark the end of the pages, make sure the
531*7dd7cddfSDavid du Colombier  * last page is printed, and restore the initial environment.
532*7dd7cddfSDavid du Colombier  *
533*7dd7cddfSDavid du Colombier  */
534*7dd7cddfSDavid du Colombier 
535*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s", TRAILER);
536*7dd7cddfSDavid du Colombier     fprintf(stdout, "done\n");
537*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname);
538*7dd7cddfSDavid du Colombier     fprintf(stdout, "%s %d\n", PAGES, printed);
539*7dd7cddfSDavid du Colombier 
540*7dd7cddfSDavid du Colombier }   /* End of done */
541*7dd7cddfSDavid du Colombier 
542*7dd7cddfSDavid du Colombier /*****************************************************************************/
543*7dd7cddfSDavid du Colombier 
account()544*7dd7cddfSDavid du Colombier account()
545*7dd7cddfSDavid du Colombier 
546*7dd7cddfSDavid du Colombier {
547*7dd7cddfSDavid du Colombier 
548*7dd7cddfSDavid du Colombier /*
549*7dd7cddfSDavid du Colombier  *
550*7dd7cddfSDavid du Colombier  * Writes an accounting record to *fp_acct, provided it's not NULL.
551*7dd7cddfSDavid du Colombier  *
552*7dd7cddfSDavid du Colombier  */
553*7dd7cddfSDavid du Colombier 
554*7dd7cddfSDavid du Colombier     if ( fp_acct != NULL )
555*7dd7cddfSDavid du Colombier 	fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
556*7dd7cddfSDavid du Colombier 
557*7dd7cddfSDavid du Colombier }   /* End of account */
558*7dd7cddfSDavid du Colombier 
559*7dd7cddfSDavid du Colombier /*****************************************************************************/
560*7dd7cddfSDavid du Colombier 
conv()561*7dd7cddfSDavid du Colombier conv()
562*7dd7cddfSDavid du Colombier 
563*7dd7cddfSDavid du Colombier {
564*7dd7cddfSDavid du Colombier 
565*7dd7cddfSDavid du Colombier     int		ch;			/* next input character */
566*7dd7cddfSDavid du Colombier 
567*7dd7cddfSDavid du Colombier /*
568*7dd7cddfSDavid du Colombier  *
569*7dd7cddfSDavid du Colombier  * Controls the conversion of BGI files into PostScript. Not everything has been
570*7dd7cddfSDavid du Colombier  * implemented, but what's been done should be good enough for our purposes.
571*7dd7cddfSDavid du Colombier  *
572*7dd7cddfSDavid du Colombier  */
573*7dd7cddfSDavid du Colombier 
574*7dd7cddfSDavid du Colombier     redirect(-1);			/* get ready for the first page */
575*7dd7cddfSDavid du Colombier     bgimode = 0;
576*7dd7cddfSDavid du Colombier     formfeed();
577*7dd7cddfSDavid du Colombier 
578*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) != EOF )  {
579*7dd7cddfSDavid du Colombier 	switch ( ch )  {
580*7dd7cddfSDavid du Colombier 		case BRCHAR:			/* rotated character mode */
581*7dd7cddfSDavid du Colombier 			    bgimode = ch;
582*7dd7cddfSDavid du Colombier 			    text(90);
583*7dd7cddfSDavid du Colombier 			    break;
584*7dd7cddfSDavid du Colombier 
585*7dd7cddfSDavid du Colombier 		case BCHAR:			/* graphical character mode */
586*7dd7cddfSDavid du Colombier 			    bgimode = ch;
587*7dd7cddfSDavid du Colombier 			    text(0);
588*7dd7cddfSDavid du Colombier 			    break;
589*7dd7cddfSDavid du Colombier 
590*7dd7cddfSDavid du Colombier 		case BGRAPH:			/* graphical master mode */
591*7dd7cddfSDavid du Colombier 			    bgimode = ch;
592*7dd7cddfSDavid du Colombier 			    break;
593*7dd7cddfSDavid du Colombier 
594*7dd7cddfSDavid du Colombier 		case BSUB:			/* subroutine definition */
595*7dd7cddfSDavid du Colombier 			    subr_def();
596*7dd7cddfSDavid du Colombier 			    break;
597*7dd7cddfSDavid du Colombier 
598*7dd7cddfSDavid du Colombier 		case BRET:			/* end of subroutine */
599*7dd7cddfSDavid du Colombier 			    subr_end();
600*7dd7cddfSDavid du Colombier 			    break;
601*7dd7cddfSDavid du Colombier 
602*7dd7cddfSDavid du Colombier 		case BCALL:			/* subroutine call */
603*7dd7cddfSDavid du Colombier 			    subr_call();
604*7dd7cddfSDavid du Colombier 			    break;
605*7dd7cddfSDavid du Colombier 
606*7dd7cddfSDavid du Colombier 		case BEND:			/* end display - page */
607*7dd7cddfSDavid du Colombier 			    formfeed();
608*7dd7cddfSDavid du Colombier 			    break;
609*7dd7cddfSDavid du Colombier 
610*7dd7cddfSDavid du Colombier 		case BERASE:			/* erase - shouldn't be used */
611*7dd7cddfSDavid du Colombier 			    error(FATAL, "BGI erase opcode obsolete");
612*7dd7cddfSDavid du Colombier 			    break;
613*7dd7cddfSDavid du Colombier 
614*7dd7cddfSDavid du Colombier 		case BREP:			/* repeat */
615*7dd7cddfSDavid du Colombier 			    error(FATAL, "Repeat not implemented");
616*7dd7cddfSDavid du Colombier 			    repeat();
617*7dd7cddfSDavid du Colombier 			    break;
618*7dd7cddfSDavid du Colombier 
619*7dd7cddfSDavid du Colombier 		case BSETX:			/* new x coordinate */
620*7dd7cddfSDavid du Colombier 			    hgoto(get_int(0));
621*7dd7cddfSDavid du Colombier 			    break;
622*7dd7cddfSDavid du Colombier 
623*7dd7cddfSDavid du Colombier 		case BSETY:			/* new y coordinate */
624*7dd7cddfSDavid du Colombier 			    vgoto(get_int(0));
625*7dd7cddfSDavid du Colombier 			    break;
626*7dd7cddfSDavid du Colombier 
627*7dd7cddfSDavid du Colombier 		case BSETXY:			/* new x and y coordinates */
628*7dd7cddfSDavid du Colombier 			    hgoto(get_int(0));
629*7dd7cddfSDavid du Colombier 			    vgoto(get_int(0));
630*7dd7cddfSDavid du Colombier 			    break;
631*7dd7cddfSDavid du Colombier 
632*7dd7cddfSDavid du Colombier 		case BINTEN:			/* mark the current point */
633*7dd7cddfSDavid du Colombier 			    fprintf(fp_out, "%d %d p\n", hpos, vpos);
634*7dd7cddfSDavid du Colombier 			    break;
635*7dd7cddfSDavid du Colombier 
636*7dd7cddfSDavid du Colombier 		case BVISX:			/* visible x */
637*7dd7cddfSDavid du Colombier 			    vector(X_COORD, VISIBLE);
638*7dd7cddfSDavid du Colombier 			    break;
639*7dd7cddfSDavid du Colombier 
640*7dd7cddfSDavid du Colombier 		case BINVISX:			/* invisible x */
641*7dd7cddfSDavid du Colombier 			    vector(X_COORD, INVISIBLE);
642*7dd7cddfSDavid du Colombier 			    break;
643*7dd7cddfSDavid du Colombier 
644*7dd7cddfSDavid du Colombier 		case BVISY:			/* visible y */
645*7dd7cddfSDavid du Colombier 			    vector(Y_COORD, VISIBLE);
646*7dd7cddfSDavid du Colombier 			    break;
647*7dd7cddfSDavid du Colombier 
648*7dd7cddfSDavid du Colombier 		case BINVISY:			/* invisible y */
649*7dd7cddfSDavid du Colombier 			    vector(Y_COORD, INVISIBLE);
650*7dd7cddfSDavid du Colombier 			    break;
651*7dd7cddfSDavid du Colombier 
652*7dd7cddfSDavid du Colombier 		case BVEC:			/* arbitrary vector */
653*7dd7cddfSDavid du Colombier 			    vector(LONGVECTOR, VISIBLE);
654*7dd7cddfSDavid du Colombier 			    break;
655*7dd7cddfSDavid du Colombier 
656*7dd7cddfSDavid du Colombier 		case BSVEC:			/* short vector */
657*7dd7cddfSDavid du Colombier 			    vector(SHORTVECTOR, VISIBLE);
658*7dd7cddfSDavid du Colombier 			    break;
659*7dd7cddfSDavid du Colombier 
660*7dd7cddfSDavid du Colombier 		case BRECT:			/* draw rectangle */
661*7dd7cddfSDavid du Colombier 			    rectangle(OUTLINE);
662*7dd7cddfSDavid du Colombier 			    break;
663*7dd7cddfSDavid du Colombier 
664*7dd7cddfSDavid du Colombier 		case BPOINT1:			/* point plot 1 */
665*7dd7cddfSDavid du Colombier 		case BPOINT:			/* point plot 2 */
666*7dd7cddfSDavid du Colombier 			    point_plot(ch, get_char());
667*7dd7cddfSDavid du Colombier 			    break;
668*7dd7cddfSDavid du Colombier 
669*7dd7cddfSDavid du Colombier 		case BLINE:			/* line plot */
670*7dd7cddfSDavid du Colombier 			    line_plot();
671*7dd7cddfSDavid du Colombier 			    break;
672*7dd7cddfSDavid du Colombier 
673*7dd7cddfSDavid du Colombier 		case BLTY:			/* line type */
674*7dd7cddfSDavid du Colombier 			    fprintf(fp_out, "%s l\n", styles[get_data()]);
675*7dd7cddfSDavid du Colombier 			    break;
676*7dd7cddfSDavid du Colombier 
677*7dd7cddfSDavid du Colombier 		case BARC:			/* circular arc */
678*7dd7cddfSDavid du Colombier 			    arc(OUTLINE);
679*7dd7cddfSDavid du Colombier 			    break;
680*7dd7cddfSDavid du Colombier 
681*7dd7cddfSDavid du Colombier 		case BFARC:			/* filled circle */
682*7dd7cddfSDavid du Colombier 			    arc(FILL);
683*7dd7cddfSDavid du Colombier 			    break;
684*7dd7cddfSDavid du Colombier 
685*7dd7cddfSDavid du Colombier 		case BFRECT:			/* filled rectangle */
686*7dd7cddfSDavid du Colombier 			    rectangle(FILL);
687*7dd7cddfSDavid du Colombier 			    break;
688*7dd7cddfSDavid du Colombier 
689*7dd7cddfSDavid du Colombier 		case BRASRECT:			/* raster rectangle */
690*7dd7cddfSDavid du Colombier 			    error(FATAL, "Raster Rectangle not implemented");
691*7dd7cddfSDavid du Colombier 			    break;
692*7dd7cddfSDavid du Colombier 
693*7dd7cddfSDavid du Colombier 		case BCOL:			/* select color */
694*7dd7cddfSDavid du Colombier 			    set_color(get_data());
695*7dd7cddfSDavid du Colombier 			    break;
696*7dd7cddfSDavid du Colombier 
697*7dd7cddfSDavid du Colombier 		case BFTRAPH:			/* filled trapezoid */
698*7dd7cddfSDavid du Colombier 			    trapezoid();
699*7dd7cddfSDavid du Colombier 			    break;
700*7dd7cddfSDavid du Colombier 
701*7dd7cddfSDavid du Colombier 		case BPAT:			/* pattern for area filling */
702*7dd7cddfSDavid du Colombier 			    pattern();
703*7dd7cddfSDavid du Colombier 			    break;
704*7dd7cddfSDavid du Colombier 
705*7dd7cddfSDavid du Colombier 		case BCSZ:			/* change BGI character 'size' */
706*7dd7cddfSDavid du Colombier 			    setsize(get_data());
707*7dd7cddfSDavid du Colombier 			    break;
708*7dd7cddfSDavid du Colombier 
709*7dd7cddfSDavid du Colombier 		case BNOISE:			/* from bad file format */
710*7dd7cddfSDavid du Colombier 			    break;
711*7dd7cddfSDavid du Colombier 
712*7dd7cddfSDavid du Colombier 		default:			/* don't recognize the code */
713*7dd7cddfSDavid du Colombier 			    error(FATAL, "bad BGI command %d (0%o)", ch, ch);
714*7dd7cddfSDavid du Colombier 			    break;
715*7dd7cddfSDavid du Colombier 	}   /* End switch */
716*7dd7cddfSDavid du Colombier 
717*7dd7cddfSDavid du Colombier 	if ( debug == ON )
718*7dd7cddfSDavid du Colombier 	    fprintf(stderr, "\n");
719*7dd7cddfSDavid du Colombier     }	/* End while */
720*7dd7cddfSDavid du Colombier 
721*7dd7cddfSDavid du Colombier     formfeed();					/* in case BEND was missing */
722*7dd7cddfSDavid du Colombier 
723*7dd7cddfSDavid du Colombier }   /* End of conv */
724*7dd7cddfSDavid du Colombier 
725*7dd7cddfSDavid du Colombier /*****************************************************************************/
726*7dd7cddfSDavid du Colombier 
hgoto(n)727*7dd7cddfSDavid du Colombier hgoto(n)
728*7dd7cddfSDavid du Colombier 
729*7dd7cddfSDavid du Colombier     int		n;			/* new horizontal position */
730*7dd7cddfSDavid du Colombier 
731*7dd7cddfSDavid du Colombier {
732*7dd7cddfSDavid du Colombier 
733*7dd7cddfSDavid du Colombier /*
734*7dd7cddfSDavid du Colombier  *
735*7dd7cddfSDavid du Colombier  * Sets the current BGI horizontal position to n.
736*7dd7cddfSDavid du Colombier  *
737*7dd7cddfSDavid du Colombier  */
738*7dd7cddfSDavid du Colombier 
739*7dd7cddfSDavid du Colombier     hpos = n;
740*7dd7cddfSDavid du Colombier 
741*7dd7cddfSDavid du Colombier }   /* End of hgoto */
742*7dd7cddfSDavid du Colombier 
743*7dd7cddfSDavid du Colombier /*****************************************************************************/
744*7dd7cddfSDavid du Colombier 
vgoto(n)745*7dd7cddfSDavid du Colombier vgoto(n)
746*7dd7cddfSDavid du Colombier 
747*7dd7cddfSDavid du Colombier     int		n;			/* move to this vertical position */
748*7dd7cddfSDavid du Colombier 
749*7dd7cddfSDavid du Colombier {
750*7dd7cddfSDavid du Colombier 
751*7dd7cddfSDavid du Colombier /*
752*7dd7cddfSDavid du Colombier  *
753*7dd7cddfSDavid du Colombier  * Sets the absolute vertical position to n.
754*7dd7cddfSDavid du Colombier  *
755*7dd7cddfSDavid du Colombier  */
756*7dd7cddfSDavid du Colombier 
757*7dd7cddfSDavid du Colombier     vpos = n;
758*7dd7cddfSDavid du Colombier 
759*7dd7cddfSDavid du Colombier }   /* End of vgoto */
760*7dd7cddfSDavid du Colombier 
761*7dd7cddfSDavid du Colombier /*****************************************************************************/
762*7dd7cddfSDavid du Colombier 
setsize(n)763*7dd7cddfSDavid du Colombier setsize(n)
764*7dd7cddfSDavid du Colombier 
765*7dd7cddfSDavid du Colombier     int		n;			/* BGI size - just a grid separation */
766*7dd7cddfSDavid du Colombier 
767*7dd7cddfSDavid du Colombier {
768*7dd7cddfSDavid du Colombier 
769*7dd7cddfSDavid du Colombier /*
770*7dd7cddfSDavid du Colombier  *
771*7dd7cddfSDavid du Colombier  * Called when we're supposed to change the BGI character size to n. The BGI
772*7dd7cddfSDavid du Colombier  * size is the grid separation in a 5 by 7 array in which characters are assumed
773*7dd7cddfSDavid du Colombier  * to be built.
774*7dd7cddfSDavid du Colombier  *
775*7dd7cddfSDavid du Colombier  */
776*7dd7cddfSDavid du Colombier 
777*7dd7cddfSDavid du Colombier     bgisize = n;
778*7dd7cddfSDavid du Colombier     linespace = LINESPACE(bgisize);
779*7dd7cddfSDavid du Colombier 
780*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d f\n", bgisize);
781*7dd7cddfSDavid du Colombier 
782*7dd7cddfSDavid du Colombier     if ( debug == ON )
783*7dd7cddfSDavid du Colombier 	fprintf(stderr, "BGI size = %d\n", n);
784*7dd7cddfSDavid du Colombier 
785*7dd7cddfSDavid du Colombier }   /* End of setsize */
786*7dd7cddfSDavid du Colombier 
787*7dd7cddfSDavid du Colombier /*****************************************************************************/
788*7dd7cddfSDavid du Colombier 
repeat()789*7dd7cddfSDavid du Colombier repeat()
790*7dd7cddfSDavid du Colombier 
791*7dd7cddfSDavid du Colombier {
792*7dd7cddfSDavid du Colombier 
793*7dd7cddfSDavid du Colombier     int		count;			/* repeat this many times */
794*7dd7cddfSDavid du Colombier     int		ch;			/* next input character */
795*7dd7cddfSDavid du Colombier 
796*7dd7cddfSDavid du Colombier /*
797*7dd7cddfSDavid du Colombier  *
798*7dd7cddfSDavid du Colombier  * Haven't implemented repeats, although it wouldn't be difficult. Apparently it's
799*7dd7cddfSDavid du Colombier  * not used by any graphics packages that generate BGI.
800*7dd7cddfSDavid du Colombier  *
801*7dd7cddfSDavid du Colombier  */
802*7dd7cddfSDavid du Colombier 
803*7dd7cddfSDavid du Colombier     count = get_int();			/* get the repeat count */
804*7dd7cddfSDavid du Colombier 
805*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) != EOF  &&  ch != BENDR ) ;
806*7dd7cddfSDavid du Colombier 
807*7dd7cddfSDavid du Colombier }   /* End of repeat */
808*7dd7cddfSDavid du Colombier 
809*7dd7cddfSDavid du Colombier /*****************************************************************************/
810*7dd7cddfSDavid du Colombier 
text(angle)811*7dd7cddfSDavid du Colombier text(angle)
812*7dd7cddfSDavid du Colombier 
813*7dd7cddfSDavid du Colombier     int		angle;			/* either 0 or 90 degrees */
814*7dd7cddfSDavid du Colombier 
815*7dd7cddfSDavid du Colombier {
816*7dd7cddfSDavid du Colombier 
817*7dd7cddfSDavid du Colombier     int		ch;			/* next character from file *fp_in */
818*7dd7cddfSDavid du Colombier 
819*7dd7cddfSDavid du Colombier /*
820*7dd7cddfSDavid du Colombier  *
821*7dd7cddfSDavid du Colombier  * Called from conv() after we've entered one of the graphical character modes.
822*7dd7cddfSDavid du Colombier  * Characters are read from the input file and printed until the next mode change
823*7dd7cddfSDavid du Colombier  * opcode is found (or until EOF). angle will be 90 for rotated character mode
824*7dd7cddfSDavid du Colombier  * and 0 otherwise.
825*7dd7cddfSDavid du Colombier  *
826*7dd7cddfSDavid du Colombier  *
827*7dd7cddfSDavid du Colombier  */
828*7dd7cddfSDavid du Colombier 
829*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d %d %d(", angle, hpos, vpos);
830*7dd7cddfSDavid du Colombier 
831*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) != EOF )  {
832*7dd7cddfSDavid du Colombier 	if ( ch == BGRAPH || ch == BCHAR || ch == BRCHAR )  {
833*7dd7cddfSDavid du Colombier 	    ungetc(ch, fp_in);
834*7dd7cddfSDavid du Colombier 	    position--;
835*7dd7cddfSDavid du Colombier 	    break;
836*7dd7cddfSDavid du Colombier 	}   /* End if */
837*7dd7cddfSDavid du Colombier 
838*7dd7cddfSDavid du Colombier 	switch ( ch )  {
839*7dd7cddfSDavid du Colombier 	    case '\012':
840*7dd7cddfSDavid du Colombier 		vgoto(vpos - linespace);
841*7dd7cddfSDavid du Colombier 
842*7dd7cddfSDavid du Colombier 	    case '\015':
843*7dd7cddfSDavid du Colombier 		hgoto(0);
844*7dd7cddfSDavid du Colombier 		fprintf(fp_out, ")t\n%d %d %d(", angle, hpos, vpos);
845*7dd7cddfSDavid du Colombier 		break;
846*7dd7cddfSDavid du Colombier 
847*7dd7cddfSDavid du Colombier 	    case '(':
848*7dd7cddfSDavid du Colombier 	    case ')':
849*7dd7cddfSDavid du Colombier 	    case '\\':
850*7dd7cddfSDavid du Colombier 		putc('\\', fp_out);
851*7dd7cddfSDavid du Colombier 
852*7dd7cddfSDavid du Colombier 	    default:
853*7dd7cddfSDavid du Colombier 		if ( isascii(ch) && isprint(ch) )
854*7dd7cddfSDavid du Colombier 		    putc(ch, fp_out);
855*7dd7cddfSDavid du Colombier 		else fprintf(fp_out, "\\%.3o", ch & 0377);
856*7dd7cddfSDavid du Colombier 		break;
857*7dd7cddfSDavid du Colombier 	}   /* End switch */
858*7dd7cddfSDavid du Colombier     }	/* End while */
859*7dd7cddfSDavid du Colombier 
860*7dd7cddfSDavid du Colombier     fprintf(fp_out, ") t\n");
861*7dd7cddfSDavid du Colombier 
862*7dd7cddfSDavid du Colombier }   /* End of text */
863*7dd7cddfSDavid du Colombier 
864*7dd7cddfSDavid du Colombier /*****************************************************************************/
865*7dd7cddfSDavid du Colombier 
formfeed()866*7dd7cddfSDavid du Colombier formfeed()
867*7dd7cddfSDavid du Colombier 
868*7dd7cddfSDavid du Colombier {
869*7dd7cddfSDavid du Colombier 
870*7dd7cddfSDavid du Colombier     int		ch;			/* repeat count for this page */
871*7dd7cddfSDavid du Colombier 
872*7dd7cddfSDavid du Colombier /*
873*7dd7cddfSDavid du Colombier  *
874*7dd7cddfSDavid du Colombier  * Does whatever is needed to print the last page and get ready for the next one.
875*7dd7cddfSDavid du Colombier  * It's called, from conv(), after a BEND code is processed. I'm ignoring the
876*7dd7cddfSDavid du Colombier  * copy count that's expected to follow each page.
877*7dd7cddfSDavid du Colombier  *
878*7dd7cddfSDavid du Colombier  */
879*7dd7cddfSDavid du Colombier 
880*7dd7cddfSDavid du Colombier     if ( bgimode == BGRAPH && (ch = get_char()) != EOF  &&  ! (ch & MSB) )  {
881*7dd7cddfSDavid du Colombier 	ungetc(ch, fp_in);
882*7dd7cddfSDavid du Colombier 	position--;
883*7dd7cddfSDavid du Colombier     }	/* End if */
884*7dd7cddfSDavid du Colombier 
885*7dd7cddfSDavid du Colombier     if ( fp_out == stdout )		/* count the last page */
886*7dd7cddfSDavid du Colombier 	printed++;
887*7dd7cddfSDavid du Colombier 
888*7dd7cddfSDavid du Colombier     fprintf(fp_out, "cleartomark\n");
889*7dd7cddfSDavid du Colombier     fprintf(fp_out, "showpage\n");
890*7dd7cddfSDavid du Colombier     fprintf(fp_out, "saveobj restore\n");
891*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);
892*7dd7cddfSDavid du Colombier 
893*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) == 0 ) ;	/* skip any NULL characters */
894*7dd7cddfSDavid du Colombier     ungetc(ch, fp_in);
895*7dd7cddfSDavid du Colombier     position--;
896*7dd7cddfSDavid du Colombier 
897*7dd7cddfSDavid du Colombier     if ( ungetc(getc(fp_in), fp_in) == EOF )
898*7dd7cddfSDavid du Colombier 	redirect(-1);
899*7dd7cddfSDavid du Colombier     else redirect(++page);
900*7dd7cddfSDavid du Colombier 
901*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
902*7dd7cddfSDavid du Colombier     fprintf(fp_out, "/saveobj save def\n");
903*7dd7cddfSDavid du Colombier     fprintf(fp_out, "mark\n");
904*7dd7cddfSDavid du Colombier     writerequest(printed+1, fp_out);
905*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d pagesetup\n", printed+1);
906*7dd7cddfSDavid du Colombier 
907*7dd7cddfSDavid du Colombier     setsize(bgisize);
908*7dd7cddfSDavid du Colombier     hpos = vpos = 0;
909*7dd7cddfSDavid du Colombier 
910*7dd7cddfSDavid du Colombier }    /* End of formfeed */
911*7dd7cddfSDavid du Colombier 
912*7dd7cddfSDavid du Colombier /*****************************************************************************/
913*7dd7cddfSDavid du Colombier 
subr_def()914*7dd7cddfSDavid du Colombier subr_def()
915*7dd7cddfSDavid du Colombier 
916*7dd7cddfSDavid du Colombier {
917*7dd7cddfSDavid du Colombier 
918*7dd7cddfSDavid du Colombier /*
919*7dd7cddfSDavid du Colombier  *
920*7dd7cddfSDavid du Colombier  * Starts a subroutine definition. All subroutines are defined as PostScript
921*7dd7cddfSDavid du Colombier  * procedures that begin with the character S and end with the subroutine's id
922*7dd7cddfSDavid du Colombier  * (a number between 0 and 63 - I guess). The primary, and perhaps only use of
923*7dd7cddfSDavid du Colombier  * subroutines is in special color plots produced by several graphics libraries,
924*7dd7cddfSDavid du Colombier  * and even there it's not all that common. I've also chosen not to worry about
925*7dd7cddfSDavid du Colombier  * nested subroutine definitions - that would certainly be overkill!
926*7dd7cddfSDavid du Colombier  *
927*7dd7cddfSDavid du Colombier  * All subroutines set up their own (translated) coordinate system, do their work
928*7dd7cddfSDavid du Colombier  * in that system, and restore things when they exit. To make everything work
929*7dd7cddfSDavid du Colombier  * properly we save the current point (in shpos and svpos), set our position to
930*7dd7cddfSDavid du Colombier  * (0, 0), and restore things at the end of the subroutine definition. That means
931*7dd7cddfSDavid du Colombier  * hpos and vpos measure the relative displacement after a subroutine returns, and
932*7dd7cddfSDavid du Colombier  * we save those values in the displacement[] array. The displacements are used
933*7dd7cddfSDavid du Colombier  * (in subr_call()) to properly adjust our position after each subroutine call,
934*7dd7cddfSDavid du Colombier  * and all subroutines are called with the current x and y coordinates on top of
935*7dd7cddfSDavid du Colombier  * the stack.
936*7dd7cddfSDavid du Colombier  *
937*7dd7cddfSDavid du Colombier  */
938*7dd7cddfSDavid du Colombier 
939*7dd7cddfSDavid du Colombier     if ( in_subr == TRUE )		/* a nested subroutine definition?? */
940*7dd7cddfSDavid du Colombier 	error(FATAL, "can't handle nested subroutine definitions");
941*7dd7cddfSDavid du Colombier 
942*7dd7cddfSDavid du Colombier     if ( (subr_id = get_data()) == EOF )
943*7dd7cddfSDavid du Colombier 	error(FATAL, "missing subroutine identifier");
944*7dd7cddfSDavid du Colombier 
945*7dd7cddfSDavid du Colombier     if ( in_global == FALSE )  {	/* just used to reduce file size some */
946*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "cleartomark\n");
947*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "saveobj restore\n");
948*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%s", BEGINGLOBAL);
949*7dd7cddfSDavid du Colombier 	in_global = TRUE;
950*7dd7cddfSDavid du Colombier     }	/* End if */
951*7dd7cddfSDavid du Colombier 
952*7dd7cddfSDavid du Colombier     fprintf(fp_out, "/S%d {\n", subr_id);
953*7dd7cddfSDavid du Colombier     fprintf(fp_out, "gsave translate\n");
954*7dd7cddfSDavid du Colombier 
955*7dd7cddfSDavid du Colombier     shpos = hpos;			/* save our current position */
956*7dd7cddfSDavid du Colombier     svpos = vpos;
957*7dd7cddfSDavid du Colombier 
958*7dd7cddfSDavid du Colombier     hgoto(0);				/* start at the origin */
959*7dd7cddfSDavid du Colombier     vgoto(0);
960*7dd7cddfSDavid du Colombier 
961*7dd7cddfSDavid du Colombier     in_subr = TRUE;			/* in a subroutine definition */
962*7dd7cddfSDavid du Colombier 
963*7dd7cddfSDavid du Colombier }   /* End of subr_def */
964*7dd7cddfSDavid du Colombier 
965*7dd7cddfSDavid du Colombier /*****************************************************************************/
966*7dd7cddfSDavid du Colombier 
subr_end()967*7dd7cddfSDavid du Colombier subr_end()
968*7dd7cddfSDavid du Colombier 
969*7dd7cddfSDavid du Colombier {
970*7dd7cddfSDavid du Colombier 
971*7dd7cddfSDavid du Colombier     int		ch;			/* for looking at next opcode */
972*7dd7cddfSDavid du Colombier 
973*7dd7cddfSDavid du Colombier /*
974*7dd7cddfSDavid du Colombier  *
975*7dd7cddfSDavid du Colombier  * Handles stuff needed at the end of each subroutine. Want to remember the change
976*7dd7cddfSDavid du Colombier  * in horizontal and vertical positions for each subroutine so we can adjust our
977*7dd7cddfSDavid du Colombier  * position after each call - just in case. The current position was set to (0, 0)
978*7dd7cddfSDavid du Colombier  * before we started the subroutine definition, so when we get here hpos and vpos
979*7dd7cddfSDavid du Colombier  * are the relative displacements after the subroutine is called. They're saved in
980*7dd7cddfSDavid du Colombier  * the displacement[] array and used to adjust the current position when we return
981*7dd7cddfSDavid du Colombier  * from a subroutine.
982*7dd7cddfSDavid du Colombier  *
983*7dd7cddfSDavid du Colombier  */
984*7dd7cddfSDavid du Colombier 
985*7dd7cddfSDavid du Colombier     if ( in_subr == FALSE )		/* not in a subroutine definition?? */
986*7dd7cddfSDavid du Colombier 	error(FATAL, "subroutine end without corresponding start");
987*7dd7cddfSDavid du Colombier 
988*7dd7cddfSDavid du Colombier     fprintf(fp_out, "grestore\n");
989*7dd7cddfSDavid du Colombier     fprintf(fp_out, "} def\n");
990*7dd7cddfSDavid du Colombier 
991*7dd7cddfSDavid du Colombier     if ( in_global == TRUE && (ch = get_char()) != BSUB )  {
992*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%s", ENDGLOBAL);
993*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "/saveobj save def\n");
994*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "mark\n");
995*7dd7cddfSDavid du Colombier 	in_global = FALSE;
996*7dd7cddfSDavid du Colombier     }	/* End if */
997*7dd7cddfSDavid du Colombier 
998*7dd7cddfSDavid du Colombier     ungetc(ch, fp_in);			/* put back the next opcode */
999*7dd7cddfSDavid du Colombier 
1000*7dd7cddfSDavid du Colombier     displacement[subr_id].dx = hpos;
1001*7dd7cddfSDavid du Colombier     displacement[subr_id].dy = vpos;
1002*7dd7cddfSDavid du Colombier 
1003*7dd7cddfSDavid du Colombier     hgoto(shpos);			/* back to where we started */
1004*7dd7cddfSDavid du Colombier     vgoto(svpos);
1005*7dd7cddfSDavid du Colombier 
1006*7dd7cddfSDavid du Colombier     in_subr = FALSE;			/* done with the definition */
1007*7dd7cddfSDavid du Colombier 
1008*7dd7cddfSDavid du Colombier }   /* End of subr_end */
1009*7dd7cddfSDavid du Colombier 
1010*7dd7cddfSDavid du Colombier /*****************************************************************************/
1011*7dd7cddfSDavid du Colombier 
subr_call()1012*7dd7cddfSDavid du Colombier subr_call()
1013*7dd7cddfSDavid du Colombier 
1014*7dd7cddfSDavid du Colombier {
1015*7dd7cddfSDavid du Colombier 
1016*7dd7cddfSDavid du Colombier     int		ch;			/* next byte from *fp_in */
1017*7dd7cddfSDavid du Colombier     int		id;			/* subroutine id if ch wasn't an opcode */
1018*7dd7cddfSDavid du Colombier 
1019*7dd7cddfSDavid du Colombier /*
1020*7dd7cddfSDavid du Colombier  *
1021*7dd7cddfSDavid du Colombier  * Handles subroutine calls. Everything that follows the BCALL opcode (up to the
1022*7dd7cddfSDavid du Colombier  * next opcode) is taken as a subroutine identifier - thus the loop that generates
1023*7dd7cddfSDavid du Colombier  * the subroutine calls.
1024*7dd7cddfSDavid du Colombier  *
1025*7dd7cddfSDavid du Colombier  */
1026*7dd7cddfSDavid du Colombier 
1027*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) != EOF && (ch & MSB) )  {
1028*7dd7cddfSDavid du Colombier 	id = ch & DMASK;
1029*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%d %d S%d\n", hpos, vpos, id);
1030*7dd7cddfSDavid du Colombier 
1031*7dd7cddfSDavid du Colombier 	hgoto(hpos + displacement[id].dx);	/* adjust our position */
1032*7dd7cddfSDavid du Colombier 	vgoto(vpos + displacement[id].dy);
1033*7dd7cddfSDavid du Colombier     }	/* End while */
1034*7dd7cddfSDavid du Colombier 
1035*7dd7cddfSDavid du Colombier     ungetc(ch, fp_in);
1036*7dd7cddfSDavid du Colombier 
1037*7dd7cddfSDavid du Colombier }   /* End of subr_call */
1038*7dd7cddfSDavid du Colombier 
1039*7dd7cddfSDavid du Colombier /*****************************************************************************/
1040*7dd7cddfSDavid du Colombier 
vector(var,mode)1041*7dd7cddfSDavid du Colombier vector(var, mode)
1042*7dd7cddfSDavid du Colombier 
1043*7dd7cddfSDavid du Colombier     int		var;			/* coordinate that varies next? */
1044*7dd7cddfSDavid du Colombier     int		mode;			/* VISIBLE or INVISIBLE vectors */
1045*7dd7cddfSDavid du Colombier 
1046*7dd7cddfSDavid du Colombier {
1047*7dd7cddfSDavid du Colombier 
1048*7dd7cddfSDavid du Colombier     int		ch;			/* next character from *fp_in */
1049*7dd7cddfSDavid du Colombier     int		x, y;			/* line drawn to this point */
1050*7dd7cddfSDavid du Colombier     int		count = 0;		/* number of points so far */
1051*7dd7cddfSDavid du Colombier 
1052*7dd7cddfSDavid du Colombier /*
1053*7dd7cddfSDavid du Colombier  *
1054*7dd7cddfSDavid du Colombier  * Handles plotting of all types of BGI vectors. If it's a manhattan vector var
1055*7dd7cddfSDavid du Colombier  * specifies which coordinate will be changed by the next number in the input
1056*7dd7cddfSDavid du Colombier  * file.
1057*7dd7cddfSDavid du Colombier  *
1058*7dd7cddfSDavid du Colombier  */
1059*7dd7cddfSDavid du Colombier 
1060*7dd7cddfSDavid du Colombier     x = hpos;				/* set up the first point */
1061*7dd7cddfSDavid du Colombier     y = vpos;
1062*7dd7cddfSDavid du Colombier 
1063*7dd7cddfSDavid du Colombier     while ( (ch = get_char()) != EOF  &&  ch & MSB )  {
1064*7dd7cddfSDavid du Colombier 	if ( var == X_COORD )		/* next length is change in x */
1065*7dd7cddfSDavid du Colombier 	    x += get_int(ch);
1066*7dd7cddfSDavid du Colombier 	else if ( var == Y_COORD )	/* it's the change in y */
1067*7dd7cddfSDavid du Colombier 	    y += get_int(ch);
1068*7dd7cddfSDavid du Colombier 	else if ( var == LONGVECTOR )  {	/* long vector */
1069*7dd7cddfSDavid du Colombier 	    x += get_int(ch);
1070*7dd7cddfSDavid du Colombier 	    y += get_int(0);
1071*7dd7cddfSDavid du Colombier 	} else {			/* must be a short vector */
1072*7dd7cddfSDavid du Colombier 	    x += ((ch & MSBMAG) * ((ch & SGNB) ? -1 : 1));
1073*7dd7cddfSDavid du Colombier 	    y += (((ch = get_data()) & MSBMAG) * ((ch & SGNB) ? -1 : 1));
1074*7dd7cddfSDavid du Colombier 	}   /* End else */
1075*7dd7cddfSDavid du Colombier 
1076*7dd7cddfSDavid du Colombier 	if ( mode == VISIBLE )  {	/* draw the line segment */
1077*7dd7cddfSDavid du Colombier 	    fprintf(fp_out, "%d %d\n", hpos - x, vpos - y);
1078*7dd7cddfSDavid du Colombier 	    count++;
1079*7dd7cddfSDavid du Colombier 	}   /* End if */
1080*7dd7cddfSDavid du Colombier 
1081*7dd7cddfSDavid du Colombier 	hgoto(x);			/* adjust the current BGI position */
1082*7dd7cddfSDavid du Colombier 	vgoto(y);
1083*7dd7cddfSDavid du Colombier 
1084*7dd7cddfSDavid du Colombier 	if ( var == X_COORD )		/* vertical length comes next */
1085*7dd7cddfSDavid du Colombier 	    var = Y_COORD;
1086*7dd7cddfSDavid du Colombier 	else if ( var == Y_COORD )	/* change horizontal next */
1087*7dd7cddfSDavid du Colombier 	    var = X_COORD;
1088*7dd7cddfSDavid du Colombier     }	/* End while */
1089*7dd7cddfSDavid du Colombier 
1090*7dd7cddfSDavid du Colombier     if ( count > 0 )
1091*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%d %d v\n", hpos, vpos);
1092*7dd7cddfSDavid du Colombier 
1093*7dd7cddfSDavid du Colombier     ungetc(ch, fp_in);			/* it wasn't part of the vector */
1094*7dd7cddfSDavid du Colombier     position--;
1095*7dd7cddfSDavid du Colombier 
1096*7dd7cddfSDavid du Colombier }   /* End of vector */
1097*7dd7cddfSDavid du Colombier 
1098*7dd7cddfSDavid du Colombier /*****************************************************************************/
1099*7dd7cddfSDavid du Colombier 
rectangle(mode)1100*7dd7cddfSDavid du Colombier rectangle(mode)
1101*7dd7cddfSDavid du Colombier 
1102*7dd7cddfSDavid du Colombier     int		mode;			/* FILL or OUTLINE the rectangle */
1103*7dd7cddfSDavid du Colombier 
1104*7dd7cddfSDavid du Colombier {
1105*7dd7cddfSDavid du Colombier 
1106*7dd7cddfSDavid du Colombier     int		deltax;			/* displacement for horizontal side */
1107*7dd7cddfSDavid du Colombier     int		deltay;			/* same but for vertical sides */
1108*7dd7cddfSDavid du Colombier 
1109*7dd7cddfSDavid du Colombier /*
1110*7dd7cddfSDavid du Colombier  *
1111*7dd7cddfSDavid du Colombier  * Draws a rectangle and either outlines or fills it, depending on the value of
1112*7dd7cddfSDavid du Colombier  * mode. Would be clearer, and perhaps better, if {stroke} or {fill} were put on
1113*7dd7cddfSDavid du Colombier  * the stack instead of 0 or 1. R could then define the path and just do an exec
1114*7dd7cddfSDavid du Colombier  * to fill or stroke it.
1115*7dd7cddfSDavid du Colombier  *
1116*7dd7cddfSDavid du Colombier  */
1117*7dd7cddfSDavid du Colombier 
1118*7dd7cddfSDavid du Colombier     deltax = get_int(0);		/* get the height and width */
1119*7dd7cddfSDavid du Colombier     deltay = get_int(0);
1120*7dd7cddfSDavid du Colombier 
1121*7dd7cddfSDavid du Colombier     if ( mode == OUTLINE )
1122*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "0 %d %d %d %d R\n", deltax, deltay, hpos, vpos);
1123*7dd7cddfSDavid du Colombier     else fprintf(fp_out, "1 %d %d %d %d R\n", deltax, deltay, hpos, vpos);
1124*7dd7cddfSDavid du Colombier 
1125*7dd7cddfSDavid du Colombier }   /* End of rectangle */
1126*7dd7cddfSDavid du Colombier 
1127*7dd7cddfSDavid du Colombier /*****************************************************************************/
1128*7dd7cddfSDavid du Colombier 
trapezoid()1129*7dd7cddfSDavid du Colombier trapezoid()
1130*7dd7cddfSDavid du Colombier 
1131*7dd7cddfSDavid du Colombier {
1132*7dd7cddfSDavid du Colombier 
1133*7dd7cddfSDavid du Colombier     int		kind;			/* which sides are parallel */
1134*7dd7cddfSDavid du Colombier     int		d[6];			/* true displacements - depends on kind */
1135*7dd7cddfSDavid du Colombier 
1136*7dd7cddfSDavid du Colombier /*
1137*7dd7cddfSDavid du Colombier  *
1138*7dd7cddfSDavid du Colombier  * Handles filled trapeziods. A data byte of 0101 following the opcode means the
1139*7dd7cddfSDavid du Colombier  * horizontal sides are parallel, 0102 means the vertical sides are parallel.
1140*7dd7cddfSDavid du Colombier  * Filling is handled by eofill so we don't need to get things in the right order.
1141*7dd7cddfSDavid du Colombier  *
1142*7dd7cddfSDavid du Colombier  */
1143*7dd7cddfSDavid du Colombier 
1144*7dd7cddfSDavid du Colombier     kind = get_data();
1145*7dd7cddfSDavid du Colombier 
1146*7dd7cddfSDavid du Colombier     d[0] = get_int(0);
1147*7dd7cddfSDavid du Colombier     d[1] = 0;
1148*7dd7cddfSDavid du Colombier     d[2] = get_int(0);
1149*7dd7cddfSDavid du Colombier     d[3] = get_int(0);
1150*7dd7cddfSDavid du Colombier     d[4] = get_int(0);
1151*7dd7cddfSDavid du Colombier     d[5] = 0;
1152*7dd7cddfSDavid du Colombier 
1153*7dd7cddfSDavid du Colombier     if ( kind == 2 )  {			/* parallel sides are vertical */
1154*7dd7cddfSDavid du Colombier 	d[1] = d[0];
1155*7dd7cddfSDavid du Colombier 	d[0] = 0;
1156*7dd7cddfSDavid du Colombier 	d[5] = d[4];
1157*7dd7cddfSDavid du Colombier 	d[4] = 0;
1158*7dd7cddfSDavid du Colombier     }	/* End if */
1159*7dd7cddfSDavid du Colombier 
1160*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d %d %d %d %d %d %d %d T\n", d[4], d[5], d[2], d[3], d[0], d[1], hpos, vpos);
1161*7dd7cddfSDavid du Colombier 
1162*7dd7cddfSDavid du Colombier }   /* End of trapezoid */
1163*7dd7cddfSDavid du Colombier 
1164*7dd7cddfSDavid du Colombier /*****************************************************************************/
1165*7dd7cddfSDavid du Colombier 
point_plot(mode,ch)1166*7dd7cddfSDavid du Colombier point_plot(mode, ch)
1167*7dd7cddfSDavid du Colombier 
1168*7dd7cddfSDavid du Colombier     int		mode;			/* plotting mode BPOINT or BPOINT1 */
1169*7dd7cddfSDavid du Colombier     int		ch;			/* will be placed at the points */
1170*7dd7cddfSDavid du Colombier 
1171*7dd7cddfSDavid du Colombier {
1172*7dd7cddfSDavid du Colombier 
1173*7dd7cddfSDavid du Colombier     int		c;			/* next character from input file */
1174*7dd7cddfSDavid du Colombier     int		x, y;			/* ch gets put here next */
1175*7dd7cddfSDavid du Colombier     int		deltax;			/* x increment for BPOINT1 mode */
1176*7dd7cddfSDavid du Colombier 
1177*7dd7cddfSDavid du Colombier /*
1178*7dd7cddfSDavid du Colombier  *
1179*7dd7cddfSDavid du Colombier  * The two point plot modes are used to place a character at selected points. The
1180*7dd7cddfSDavid du Colombier  * difference in the two modes, namely BPOINT and BPOINT1, is the way we get the
1181*7dd7cddfSDavid du Colombier  * coordinates of the next point. In BPOINT1 the two bytes immediately following
1182*7dd7cddfSDavid du Colombier  * ch select a constant horizontal change, while both coordinates are given for
1183*7dd7cddfSDavid du Colombier  * all points in BPOINT mode.
1184*7dd7cddfSDavid du Colombier  *
1185*7dd7cddfSDavid du Colombier  */
1186*7dd7cddfSDavid du Colombier 
1187*7dd7cddfSDavid du Colombier     if ( mode == BPOINT1 )  {		/* first integer is change in x */
1188*7dd7cddfSDavid du Colombier 	deltax = get_int(0);
1189*7dd7cddfSDavid du Colombier 	x = hpos - deltax;
1190*7dd7cddfSDavid du Colombier     }	/* End if */
1191*7dd7cddfSDavid du Colombier 
1192*7dd7cddfSDavid du Colombier     while ( (c = get_char()) != EOF  &&  (c & MSB) )  {
1193*7dd7cddfSDavid du Colombier 	if ( mode == BPOINT1 )  {	/* only read y coordinate */
1194*7dd7cddfSDavid du Colombier 	    y = get_int(c);
1195*7dd7cddfSDavid du Colombier 	    x += deltax;
1196*7dd7cddfSDavid du Colombier 	} else {			/* get new x and y from input file */
1197*7dd7cddfSDavid du Colombier 	    x = get_int(c);
1198*7dd7cddfSDavid du Colombier 	    y = get_int(0);
1199*7dd7cddfSDavid du Colombier 	}   /* End else */
1200*7dd7cddfSDavid du Colombier 
1201*7dd7cddfSDavid du Colombier 	hgoto(x);			/* adjust BGI position */
1202*7dd7cddfSDavid du Colombier 	vgoto(y);
1203*7dd7cddfSDavid du Colombier 
1204*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%d %d\n", hpos, vpos);
1205*7dd7cddfSDavid du Colombier     }	/* End while */
1206*7dd7cddfSDavid du Colombier 
1207*7dd7cddfSDavid du Colombier     putc('(', fp_out);
1208*7dd7cddfSDavid du Colombier 
1209*7dd7cddfSDavid du Colombier     switch ( ch )  {
1210*7dd7cddfSDavid du Colombier 	case '(':
1211*7dd7cddfSDavid du Colombier 	case ')':
1212*7dd7cddfSDavid du Colombier 	case '\\':
1213*7dd7cddfSDavid du Colombier 		putc('\\', fp_out);
1214*7dd7cddfSDavid du Colombier 
1215*7dd7cddfSDavid du Colombier 	default:
1216*7dd7cddfSDavid du Colombier 		putc(ch, fp_out);
1217*7dd7cddfSDavid du Colombier     }	/* End switch */
1218*7dd7cddfSDavid du Colombier 
1219*7dd7cddfSDavid du Colombier     fprintf(fp_out, ")pp\n");
1220*7dd7cddfSDavid du Colombier 
1221*7dd7cddfSDavid du Colombier     ungetc(c, fp_in);			/* it wasn't part of the point plot */
1222*7dd7cddfSDavid du Colombier     position--;
1223*7dd7cddfSDavid du Colombier 
1224*7dd7cddfSDavid du Colombier }   /* End of point_plot */
1225*7dd7cddfSDavid du Colombier 
1226*7dd7cddfSDavid du Colombier /*****************************************************************************/
1227*7dd7cddfSDavid du Colombier 
line_plot()1228*7dd7cddfSDavid du Colombier line_plot()
1229*7dd7cddfSDavid du Colombier 
1230*7dd7cddfSDavid du Colombier {
1231*7dd7cddfSDavid du Colombier 
1232*7dd7cddfSDavid du Colombier     int		c;			/* next input character from fp_in */
1233*7dd7cddfSDavid du Colombier     int		deltax;			/* change in x coordinate */
1234*7dd7cddfSDavid du Colombier     int		x0, y0;			/* starting point for next segment */
1235*7dd7cddfSDavid du Colombier     int		x1, y1;			/* endpoint of the line */
1236*7dd7cddfSDavid du Colombier     int		count = 0;		/* number of points so far */
1237*7dd7cddfSDavid du Colombier 
1238*7dd7cddfSDavid du Colombier /*
1239*7dd7cddfSDavid du Colombier  *
1240*7dd7cddfSDavid du Colombier  * Essentially the same format as BPOINT1, except that in this case we connect
1241*7dd7cddfSDavid du Colombier  * pairs of points by line segments.
1242*7dd7cddfSDavid du Colombier  *
1243*7dd7cddfSDavid du Colombier  */
1244*7dd7cddfSDavid du Colombier 
1245*7dd7cddfSDavid du Colombier     deltax = get_int(0);		/* again the change in x is first */
1246*7dd7cddfSDavid du Colombier 
1247*7dd7cddfSDavid du Colombier     x1 = hpos;				/* so it works first time through */
1248*7dd7cddfSDavid du Colombier     y1 = get_int(0);
1249*7dd7cddfSDavid du Colombier 
1250*7dd7cddfSDavid du Colombier     while ( (c = get_char()) != EOF  &&  (c & MSB) )  {
1251*7dd7cddfSDavid du Colombier 	x0 = x1;			/* line starts here */
1252*7dd7cddfSDavid du Colombier 	y0 = y1;
1253*7dd7cddfSDavid du Colombier 
1254*7dd7cddfSDavid du Colombier 	x1 += deltax;			/* and ends at this point */
1255*7dd7cddfSDavid du Colombier     	y1 = get_int(c);
1256*7dd7cddfSDavid du Colombier 
1257*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%d %d\n", -deltax, y0 - y1);
1258*7dd7cddfSDavid du Colombier 	count++;
1259*7dd7cddfSDavid du Colombier     }	/* End while */
1260*7dd7cddfSDavid du Colombier 
1261*7dd7cddfSDavid du Colombier     hgoto(x1);				/* adjust current BGI position */
1262*7dd7cddfSDavid du Colombier     vgoto(y1);
1263*7dd7cddfSDavid du Colombier 
1264*7dd7cddfSDavid du Colombier     if ( count > 0 )
1265*7dd7cddfSDavid du Colombier 	fprintf(fp_out, "%d %d v\n", hpos, vpos);
1266*7dd7cddfSDavid du Colombier 
1267*7dd7cddfSDavid du Colombier     ungetc(c, fp_in);			/* wasn't part of the line */
1268*7dd7cddfSDavid du Colombier     position--;
1269*7dd7cddfSDavid du Colombier 
1270*7dd7cddfSDavid du Colombier }   /* End of line_plot */
1271*7dd7cddfSDavid du Colombier 
1272*7dd7cddfSDavid du Colombier /*****************************************************************************/
1273*7dd7cddfSDavid du Colombier 
arc(mode)1274*7dd7cddfSDavid du Colombier arc(mode)
1275*7dd7cddfSDavid du Colombier 
1276*7dd7cddfSDavid du Colombier     int		mode;			/* FILL or OUTLINE the path */
1277*7dd7cddfSDavid du Colombier 
1278*7dd7cddfSDavid du Colombier {
1279*7dd7cddfSDavid du Colombier 
1280*7dd7cddfSDavid du Colombier     int		dx1, dy1;		/* displacements for first point */
1281*7dd7cddfSDavid du Colombier     int		dx2, dy2;		/* same for the second point */
1282*7dd7cddfSDavid du Colombier     int		radius;			/* of the arc */
1283*7dd7cddfSDavid du Colombier     int		angle1, angle2;		/* starting and ending angles */
1284*7dd7cddfSDavid du Colombier 
1285*7dd7cddfSDavid du Colombier /*
1286*7dd7cddfSDavid du Colombier  *
1287*7dd7cddfSDavid du Colombier  * Called whenever we need to draw an arc. I'm ignoring filled slices for now.
1288*7dd7cddfSDavid du Colombier  *
1289*7dd7cddfSDavid du Colombier  */
1290*7dd7cddfSDavid du Colombier 
1291*7dd7cddfSDavid du Colombier     dx1 = get_int(0);			/* displacements relative to center */
1292*7dd7cddfSDavid du Colombier     dy1 = get_int(0);
1293*7dd7cddfSDavid du Colombier     dx2 = get_int(0);
1294*7dd7cddfSDavid du Colombier     dy2 = get_int(0);
1295*7dd7cddfSDavid du Colombier 
1296*7dd7cddfSDavid du Colombier     radius = get_int(0);		/* and the radius */
1297*7dd7cddfSDavid du Colombier 
1298*7dd7cddfSDavid du Colombier     if ( radius == 0 )			/* nothing to do */
1299*7dd7cddfSDavid du Colombier 	return;
1300*7dd7cddfSDavid du Colombier 
1301*7dd7cddfSDavid du Colombier     angle1 = (atan2((double) dy1, (double) dx1) * 360) / (2 * PI) + .5;
1302*7dd7cddfSDavid du Colombier     angle2 = (atan2((double) dy2, (double) dx2) * 360) / (2 * PI) + .5;
1303*7dd7cddfSDavid du Colombier 
1304*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d %d %d %d %d arcn stroke\n", hpos, vpos, radius, angle1, angle2);
1305*7dd7cddfSDavid du Colombier 
1306*7dd7cddfSDavid du Colombier }   /* End of arc */
1307*7dd7cddfSDavid du Colombier 
1308*7dd7cddfSDavid du Colombier /*****************************************************************************/
1309*7dd7cddfSDavid du Colombier 
pattern()1310*7dd7cddfSDavid du Colombier pattern()
1311*7dd7cddfSDavid du Colombier 
1312*7dd7cddfSDavid du Colombier {
1313*7dd7cddfSDavid du Colombier 
1314*7dd7cddfSDavid du Colombier     double	red = 0;		/* color components */
1315*7dd7cddfSDavid du Colombier     double	green = 0;
1316*7dd7cddfSDavid du Colombier     double	blue = 0;
1317*7dd7cddfSDavid du Colombier     int		kind;			/* corse or fine pattern */
1318*7dd7cddfSDavid du Colombier     int		val;			/* next color data byte */
1319*7dd7cddfSDavid du Colombier     int		i;			/* loop index */
1320*7dd7cddfSDavid du Colombier 
1321*7dd7cddfSDavid du Colombier /*
1322*7dd7cddfSDavid du Colombier  *
1323*7dd7cddfSDavid du Colombier  * Handles patterns by setting the current color based of the values assigned to
1324*7dd7cddfSDavid du Colombier  * the next four data bytes. BGI supports two kinds of patterns (fine or coarse)
1325*7dd7cddfSDavid du Colombier  * but I'm handling each in the same way - for now. In a fine pattern the four
1326*7dd7cddfSDavid du Colombier  * data bytes assign a color to four individual pixels (upperleft first) while
1327*7dd7cddfSDavid du Colombier  * in a coarse pattern the four colors are assigned to groups of four pixels,
1328*7dd7cddfSDavid du Colombier  * for a total of 16. Again the first color goes to the group in the upper left
1329*7dd7cddfSDavid du Colombier  * corner. The byte immediately following the BPAT opcode selects fine (040) or
1330*7dd7cddfSDavid du Colombier  * coarse (041) patterns. The PostScript RGB color is assigned by averaging the
1331*7dd7cddfSDavid du Colombier  * RED, GREEN, and BLUE components assigned to the four pixels (or groups of
1332*7dd7cddfSDavid du Colombier  * pixels). Acceptable results, but there's no distinction between fine and
1333*7dd7cddfSDavid du Colombier  * coarse patterns.
1334*7dd7cddfSDavid du Colombier  *
1335*7dd7cddfSDavid du Colombier  */
1336*7dd7cddfSDavid du Colombier 
1337*7dd7cddfSDavid du Colombier     if ( (kind = get_char()) == EOF )
1338*7dd7cddfSDavid du Colombier 	error(FATAL, "bad pattern command");
1339*7dd7cddfSDavid du Colombier 
1340*7dd7cddfSDavid du Colombier     for ( i = 0; i < 4; i++ )  {
1341*7dd7cddfSDavid du Colombier 	val = get_data();
1342*7dd7cddfSDavid du Colombier 	red += get_color(val, RED);
1343*7dd7cddfSDavid du Colombier 	green += get_color(val, GREEN);
1344*7dd7cddfSDavid du Colombier 	blue += get_color(val, BLUE);
1345*7dd7cddfSDavid du Colombier     }	/* End for */
1346*7dd7cddfSDavid du Colombier 
1347*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%g %g %g c\n", red/4, green/4, blue/4);
1348*7dd7cddfSDavid du Colombier 
1349*7dd7cddfSDavid du Colombier }   /* End of pattern */
1350*7dd7cddfSDavid du Colombier 
1351*7dd7cddfSDavid du Colombier /*****************************************************************************/
1352*7dd7cddfSDavid du Colombier 
get_color(val,component)1353*7dd7cddfSDavid du Colombier get_color(val, component)
1354*7dd7cddfSDavid du Colombier 
1355*7dd7cddfSDavid du Colombier     int		val;			/* color data byte */
1356*7dd7cddfSDavid du Colombier     int		component;		/* RED, GREEN, or BLUE component */
1357*7dd7cddfSDavid du Colombier 
1358*7dd7cddfSDavid du Colombier {
1359*7dd7cddfSDavid du Colombier 
1360*7dd7cddfSDavid du Colombier 
1361*7dd7cddfSDavid du Colombier     int		primary;		/* color mixing mode - bits 2 to 4 */
1362*7dd7cddfSDavid du Colombier     int		plane;			/* primary color plane - bits 5 to 7 */
1363*7dd7cddfSDavid du Colombier     unsigned	rgbcolor;		/* PostScript expects an RGB triple */
1364*7dd7cddfSDavid du Colombier 
1365*7dd7cddfSDavid du Colombier /*
1366*7dd7cddfSDavid du Colombier  *
1367*7dd7cddfSDavid du Colombier  * Picks the requested color component (RED, GREEN, or BLUE) from val and returns
1368*7dd7cddfSDavid du Colombier  * the result to the caller. BGI works with Cyan, Yellow, and Magenta so the one's
1369*7dd7cddfSDavid du Colombier  * complement stuff (following the exclusive or'ing) recovers the RED, BLUE, and
1370*7dd7cddfSDavid du Colombier  * GREEN components that PostScript's setrgbcolor operator needs. The PostScript
1371*7dd7cddfSDavid du Colombier  * interpreter in the ColorScript 100 has a setcmycolor operator, but it's not
1372*7dd7cddfSDavid du Colombier  * generally available so I've decided to stick with setrgbcolor.
1373*7dd7cddfSDavid du Colombier  *
1374*7dd7cddfSDavid du Colombier  */
1375*7dd7cddfSDavid du Colombier 
1376*7dd7cddfSDavid du Colombier     primary = (val >> 3) & 07;
1377*7dd7cddfSDavid du Colombier     plane = val & 07;
1378*7dd7cddfSDavid du Colombier     rgbcolor = (~(primary ^ plane)) & 07;
1379*7dd7cddfSDavid du Colombier 
1380*7dd7cddfSDavid du Colombier     if ( debug == ON )
1381*7dd7cddfSDavid du Colombier 	fprintf(stderr, "val = %o, primary = %o, plane = %o, rgbcolor = %o\n",
1382*7dd7cddfSDavid du Colombier 		val, primary, plane, rgbcolor);
1383*7dd7cddfSDavid du Colombier 
1384*7dd7cddfSDavid du Colombier     switch ( component )  {
1385*7dd7cddfSDavid du Colombier 	case RED:
1386*7dd7cddfSDavid du Colombier 		return(rgbcolor>>2);
1387*7dd7cddfSDavid du Colombier 
1388*7dd7cddfSDavid du Colombier 	case GREEN:
1389*7dd7cddfSDavid du Colombier 		return(rgbcolor&01);
1390*7dd7cddfSDavid du Colombier 
1391*7dd7cddfSDavid du Colombier 	case BLUE:
1392*7dd7cddfSDavid du Colombier 		return((rgbcolor>>1)&01);
1393*7dd7cddfSDavid du Colombier 
1394*7dd7cddfSDavid du Colombier 	default:
1395*7dd7cddfSDavid du Colombier 		error(FATAL, "unknown color component");
1396*7dd7cddfSDavid du Colombier 		return(0);
1397*7dd7cddfSDavid du Colombier     }	/* End switch */
1398*7dd7cddfSDavid du Colombier 
1399*7dd7cddfSDavid du Colombier }   /* End of get_color */
1400*7dd7cddfSDavid du Colombier 
1401*7dd7cddfSDavid du Colombier /*****************************************************************************/
1402*7dd7cddfSDavid du Colombier 
set_color(val)1403*7dd7cddfSDavid du Colombier set_color(val)
1404*7dd7cddfSDavid du Colombier 
1405*7dd7cddfSDavid du Colombier     int		val;			/* color data byte */
1406*7dd7cddfSDavid du Colombier 
1407*7dd7cddfSDavid du Colombier {
1408*7dd7cddfSDavid du Colombier 
1409*7dd7cddfSDavid du Colombier /*
1410*7dd7cddfSDavid du Colombier  *
1411*7dd7cddfSDavid du Colombier  * Arranges to have the color set to the value requested in the BGI data byte val.
1412*7dd7cddfSDavid du Colombier  *
1413*7dd7cddfSDavid du Colombier  */
1414*7dd7cddfSDavid du Colombier 
1415*7dd7cddfSDavid du Colombier     fprintf(fp_out, "%d %d %d c\n", get_color(val, RED), get_color(val, GREEN), get_color(val, BLUE));
1416*7dd7cddfSDavid du Colombier 
1417*7dd7cddfSDavid du Colombier }   /* End of set_color */
1418*7dd7cddfSDavid du Colombier 
1419*7dd7cddfSDavid du Colombier /*****************************************************************************/
1420*7dd7cddfSDavid du Colombier 
get_int(highbyte)1421*7dd7cddfSDavid du Colombier get_int(highbyte)
1422*7dd7cddfSDavid du Colombier 
1423*7dd7cddfSDavid du Colombier     int		highbyte;		/* already read this byte */
1424*7dd7cddfSDavid du Colombier 
1425*7dd7cddfSDavid du Colombier {
1426*7dd7cddfSDavid du Colombier 
1427*7dd7cddfSDavid du Colombier     int		lowbyte;		/* this and highbyte make the int */
1428*7dd7cddfSDavid du Colombier 
1429*7dd7cddfSDavid du Colombier /*
1430*7dd7cddfSDavid du Colombier  *
1431*7dd7cddfSDavid du Colombier  * Figures out the value on the integer (sign magnitude form) that's next in the
1432*7dd7cddfSDavid du Colombier  * input file. If highbyte is nonzero we'll use it and the next byte to build the
1433*7dd7cddfSDavid du Colombier  * integer, otherwise two bytes are read from fp_in.
1434*7dd7cddfSDavid du Colombier  *
1435*7dd7cddfSDavid du Colombier  */
1436*7dd7cddfSDavid du Colombier 
1437*7dd7cddfSDavid du Colombier 
1438*7dd7cddfSDavid du Colombier     if ( highbyte == 0 )		/* need to read the first byte */
1439*7dd7cddfSDavid du Colombier 	highbyte = get_data();
1440*7dd7cddfSDavid du Colombier 
1441*7dd7cddfSDavid du Colombier     lowbyte = get_data();		/* always need the second byte */
1442*7dd7cddfSDavid du Colombier 
1443*7dd7cddfSDavid du Colombier     return(highbyte & SGNB ? -MAG(highbyte, lowbyte) : MAG(highbyte, lowbyte));
1444*7dd7cddfSDavid du Colombier 
1445*7dd7cddfSDavid du Colombier }   /* End of get_int */
1446*7dd7cddfSDavid du Colombier 
1447*7dd7cddfSDavid du Colombier /*****************************************************************************/
1448*7dd7cddfSDavid du Colombier 
get_data()1449*7dd7cddfSDavid du Colombier get_data()
1450*7dd7cddfSDavid du Colombier 
1451*7dd7cddfSDavid du Colombier {
1452*7dd7cddfSDavid du Colombier 
1453*7dd7cddfSDavid du Colombier     int		val;			/* data value returned to caller */
1454*7dd7cddfSDavid du Colombier 
1455*7dd7cddfSDavid du Colombier /*
1456*7dd7cddfSDavid du Colombier  *
1457*7dd7cddfSDavid du Colombier  * Called when we expect to find a single data character in the input file. The
1458*7dd7cddfSDavid du Colombier  * data bit is turned off and the resulting value is returned to the caller.
1459*7dd7cddfSDavid du Colombier  *
1460*7dd7cddfSDavid du Colombier  */
1461*7dd7cddfSDavid du Colombier 
1462*7dd7cddfSDavid du Colombier     if ( (val = get_char()) == EOF  ||  ! (val & MSB) )
1463*7dd7cddfSDavid du Colombier 	error(FATAL, "missing data value");
1464*7dd7cddfSDavid du Colombier 
1465*7dd7cddfSDavid du Colombier     return(val & DMASK);
1466*7dd7cddfSDavid du Colombier 
1467*7dd7cddfSDavid du Colombier }   /* End of get_data */
1468*7dd7cddfSDavid du Colombier 
1469*7dd7cddfSDavid du Colombier /*****************************************************************************/
1470*7dd7cddfSDavid du Colombier 
get_char()1471*7dd7cddfSDavid du Colombier get_char()
1472*7dd7cddfSDavid du Colombier 
1473*7dd7cddfSDavid du Colombier {
1474*7dd7cddfSDavid du Colombier 
1475*7dd7cddfSDavid du Colombier     int		ch;			/* character we just read */
1476*7dd7cddfSDavid du Colombier 
1477*7dd7cddfSDavid du Colombier /*
1478*7dd7cddfSDavid du Colombier  *
1479*7dd7cddfSDavid du Colombier  * Reads the next character from file *fp_in and returns the value to the caller.
1480*7dd7cddfSDavid du Colombier  * This routine isn't really needed, but we may want to deal directly with some
1481*7dd7cddfSDavid du Colombier  * screwball file formats so I thought it would probably be a good idea to isolate
1482*7dd7cddfSDavid du Colombier  * all the input in one routine that could be easily changed.
1483*7dd7cddfSDavid du Colombier  *
1484*7dd7cddfSDavid du Colombier  */
1485*7dd7cddfSDavid du Colombier 
1486*7dd7cddfSDavid du Colombier     if ( (ch = getc(fp_in)) != EOF )  {
1487*7dd7cddfSDavid du Colombier 	position++;
1488*7dd7cddfSDavid du Colombier 	ch &= CHMASK;
1489*7dd7cddfSDavid du Colombier     }	/* End if */
1490*7dd7cddfSDavid du Colombier 
1491*7dd7cddfSDavid du Colombier     if ( debug == ON )
1492*7dd7cddfSDavid du Colombier 	fprintf(stderr, "%o ", ch);
1493*7dd7cddfSDavid du Colombier 
1494*7dd7cddfSDavid du Colombier     return(ch);
1495*7dd7cddfSDavid du Colombier 
1496*7dd7cddfSDavid du Colombier }   /* End of get_char */
1497*7dd7cddfSDavid du Colombier 
1498*7dd7cddfSDavid du Colombier /*****************************************************************************/
1499*7dd7cddfSDavid du Colombier 
redirect(pg)1500*7dd7cddfSDavid du Colombier redirect(pg)
1501*7dd7cddfSDavid du Colombier 
1502*7dd7cddfSDavid du Colombier     int		pg;			/* next page we're printing */
1503*7dd7cddfSDavid du Colombier 
1504*7dd7cddfSDavid du Colombier {
1505*7dd7cddfSDavid du Colombier 
1506*7dd7cddfSDavid du Colombier     static FILE	*fp_null = NULL;	/* if output is turned off */
1507*7dd7cddfSDavid du Colombier 
1508*7dd7cddfSDavid du Colombier /*
1509*7dd7cddfSDavid du Colombier  *
1510*7dd7cddfSDavid du Colombier  * If we're not supposed to print page pg, fp_out will be directed to /dev/null,
1511*7dd7cddfSDavid du Colombier  * otherwise output goes to stdout.
1512*7dd7cddfSDavid du Colombier  *
1513*7dd7cddfSDavid du Colombier  */
1514*7dd7cddfSDavid du Colombier 
1515*7dd7cddfSDavid du Colombier     if ( pg >= 0 && in_olist(pg) == ON )
1516*7dd7cddfSDavid du Colombier 	fp_out = stdout;
1517*7dd7cddfSDavid du Colombier     else if ( (fp_out = fp_null) == NULL )
1518*7dd7cddfSDavid du Colombier 	fp_out = fp_null = fopen("/dev/null", "w");
1519*7dd7cddfSDavid du Colombier 
1520*7dd7cddfSDavid du Colombier }   /* End of redirect */
1521*7dd7cddfSDavid du Colombier 
1522*7dd7cddfSDavid du Colombier /*****************************************************************************/
1523*7dd7cddfSDavid du Colombier 
1524