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