xref: /original-bsd/local/transcript/src/ps4014.c (revision b907ef3c)
1 #ifndef lint
2 static char Notice[] = "Copyright (c) 1985 Adobe Systems Incorporated";
3 static char *RCSID = "$Header: ps4014.c,v 2.1 85/11/24 11:49:18 shore Rel $";
4 #endif
5 /* ps4014.c
6  *
7  * Copyright (c) 1985 Adobe Systems Incorporated
8  *
9  * tektronics 4014 to PostScript filter
10  *
11  * Edit History:
12  * Original Version: Tom Malloy
13  * Andrew Shore: Mon Nov  4 13:46:08 1985
14  * End Edit History.
15  *
16  * RCSLOG:
17  * $Log:	ps4014.c,v $
18  * Revision 2.1  85/11/24  11:49:18  shore
19  * Product Release 2.0
20  *
21  * Revision 1.1  85/11/20  00:16:33  shore
22  * Initial revision
23  *
24  *
25  */
26 
27 #include <stdio.h>
28 #include <pwd.h>
29 #ifdef SYSV
30 extern struct passwd *getpwuid();
31 #include <string.h>
32 #else
33 #include <strings.h>
34 #endif
35 #include <setjmp.h>
36 #include "transcript.h"
37 
38 /* move this to transcript.h some day */
39 private char scProlog[512];
40 
41 struct Params {
42     char   *scSrcFile;		/* string name of 4014 source file */
43     char   *scDstFile;		/* string name of PS destination file */
44     char   *scDbgFile;		/* string name of debug output file */
45     short   fCrGenLf;		/* true if carriage return generates line
46     				   feed */
47     short   fLfGenCr;		/* true if line feed generates carriage
48 				   return  */
49     short   fMarg2;		/* true if there are two left margins for
50 				   text, one a left and one in the middle
51 				   of the page */
52     short   fDbg;		/* true if debug output should be
53 				   generated */
54     float   xRtInch;		/* top, left location of output on page */
55     float   yBotInch;
56     float   dxWidInch;		/* width, height of output */
57     float   dyHtInch;
58     int     fLandscape;		/* do landscape page */
59 };
60 
61 
62 struct Real4110 {
63     long    mantissa, exp;
64 };				/* 4110-format real number */
65 struct Sts {
66     short   md;			/* current mode */
67     int     xh;			/* current x-position (in 4096ths) */
68     int     yh;			/* current y-position (in 4096ths) */
69     char    chHiY, chHiX, chExtra, chLoY;
70  /* current values for the vector-mode address bytes that may be omitted
71     when sending an address - see GetXhYh */
72     short   syline;		/* current line style from 4014 input
73 				   viewpoint */
74     short   sychar;		/* current character style */
75     short   charset;		/* normal or alternate character set */
76     short   sylinePrt;		/* current line style from printers
77 				   viewpoint */
78     short   sycharPrt;		/* current character style from printers
79 				   viewpoint */
80     short   charsetPrt;		/* normal or alternate characters from
81 				   printers viewpoint */
82     short   fPenDown;		/* true implies vector command draws false
83 				   implies vector command moves */
84     short   fMovePending;	/* true implies 4014 position and
85 				   PostScript position are different */
86     short   fVectorDrawn;	/* true implies Stroke command is pending
87 				   on current PostScript path */
88     short   dir;		/* current incremental point plot
89 				   direction */
90     int     cincr;		/* count of increments tom move/draw in
91 				   current incremental point plot
92 				   direction */
93     int     xhLeftMarg;		/* current left margin */
94 };
95 
96 #define mdAlpha 0		/* Alpha mode */
97 #define mdVector 1		/* Vector graphics mode */
98 #define mdPtPlot 2		/* Point plot mode */
99 #define mdSpecPtPlot 3		/* Special point plot mode */
100 #define mdIncrPtPlot 4		/* Incremental point plot mode */
101 #define mdBypass 5		/* Bypass mode */
102 
103 #define chFstSyline	'`'	/* first valid line style command
104 				   character */
105 #define chLstSyline	'w'	/* last valid line style command character */
106 
107 #define sylineNormal	0	/* normal line style */
108 #define sylineDot	1	/* dotted line style */
109 #define sylineDotDashed 2	/* dot-dashed line style */
110 #define sylineShortDash 3	/* short dash line style */
111 #define sylineLongDash	4	/* long dash line style */
112 #define sylineMax	5	/* number of valid line styles */
113 #define mskSyline	7	/* mask for extracting line style indexes
114 				   from line style command characters. */
115 
116 #define chFstSychar	'8'	/* first valid character style command
117 				   character */
118 #define chLstSychar	';'	/* last valid character style command
119 				   character */
120 
121 #define sycharLarge	0	/* character style: large character */
122 #define sychar2		1	/* character style 2 */
123 #define sychar3		2	/* charactr style 3 */
124 #define sycharSmall	3	/* charactr style: small characters */
125 #define sycharMax	4	/* number of valid character styles */
126 
127 #define charsetStd	0	/* normal character set */
128 #define charsetAlt	1	/* Alternate character set */
129 
130 #define chFstShow	' '	/* first valid printable character */
131 #define chLstShow	126	/* last valid printable character */
132 #define chFstCoord	' '	/* first valid graphics address byte */
133 #define chLstCoord	127	/* last valid graphcs address byte */
134 #define chFstLoX	'@'	/* first valid low x byte */
135 #define chFstLoY	'`'	/* last valid low x byte */
136 #define mskLoBits	3	/* mask for extracting low order address
137 				   bits from extra byte */
138 #define mskBit4		16	/* mask for extracting margin bit from
139 				   extra byte */
140 #define shiftHiByte	7	/* number of bits to shift high-byte
141 				   address bits in composed address */
142 #define shiftLoByte	2	/* number of bits to shift low-byte
143 				   address bits in composed address */
144 #define shiftYExtra	2	/* number of bits to shift extra byte to
145 				   right align the low order y bits */
146 
147 /* Some 4110 command code definitions */
148 #define chFst4110	'I'	/* first valid 4110 command code character
149 				   */
150 #define chLst4110	'Z'	/* last valid 4110 command code character
151 				*/
152 #define chFstEsc2	'A'	/* first valid character for the second
153 				   character of a 2-byte 4110 command code
154 				   sequence */
155 #define chLstEsc2	'Z'	/* last valid character for the second
156 				   character of a 2-byte 4110 command code
157 				   sequence */
158 #define chFstHiInt	'@'	/* first valid character for non-low-order
159 				   portion of integer parameter */
160 #define chLstHiInt	127	/* last valid character for non-low-order
161 				   portion of integer parameter */
162 #define chFstLoPosInt	'0'	/* first valid character for low-order
163 				   portion of positive integer */
164 #define chLstLoPosInt	'?'	/* last valid character for low-order
165 				   portion of positive integer */
166 #define chFstLoNegInt	32	/* first valid character for low-order
167 				   portion of negative integer */
168 #define chLstLoNegInt	'/'	/* last valid character for low-order
169 				   portion of positive integer */
170 
171 /* Some useful ASCII command character defintions */
172 #define chNull		0x0
173 #define chEnq		0x5
174 #define chBell		0x7
175 #define chBs		0x8
176 #define chTab		0x9
177 #define chLf		0xA
178 #define chVTab		0xB
179 #define chFf		0xC
180 #define chCr		0xD
181 #define chSo		0xE
182 #define chSi		0xF
183 #define chEtb		0x17
184 #define chCan		0x18
185 #define chSub		0x1A
186 #define chEsc		0x1B
187 #define chFs		0x1C
188 #define chGs		0x1D
189 #define chRs		0x1E
190 #define chUs		0x1F
191 #define chSp		0x20
192 #define chDel		0x7F
193 
194 /* Types of 4014 postion movement commands */
195 #define tymoveNil	0
196 #define tymoveLeft	1
197 #define tymoveRt	2
198 #define tymoveUp	3
199 #define tymoveDown	4
200 #define tymoveGDown	5
201 #define tymoveXMarg	6
202 #define tymoveMax	7
203 
204 /* masks for extracting movement direction
205 from incremental point plot commands */
206 #define mskDir		0xF
207 #define mskDirUp	4
208 #define mskDirRt	1
209 #define mskDirDown	8
210 #define mskDirLeft	2
211 #define dirNil	0
212 
213 /* Some x and y coordinates (in 4096ths) */
214 #define xhHome		0
215 #define xhMarg1		0
216 #define xhMarg2		2048
217 #define yhHome		3071
218 #define xhMax		4096
219 #define yhMax		3120
220 
221 /* Constants and parser tables for 4110 parser */
222 
223 /* parameter types */
224 #define typrmNil	0
225 #define typrmLong	1	/* 32-bit integer parameter */
226 #define typrmAryLong	2	/* array of 32-bit integers */
227 #define typrmXhYh	3	/* vector mode xy-coordinate */
228 #define typrmString	4	/* 4110 format string */
229 #define typrmCh		5	/* character */
230 #define typrmReal4110	6	/* 4110 format real number */
231 #define typrmAryXhYh	7	/* array of vector mode corrdinates */
232 #define typrmMax	8	/* number of valid parameter types */
233 
234 #define iprmMax		4	/* maximum number of parameters to a 4110
235 				   command */
236 /* Identifiers for some, but not all, commonly used
237    parameter sequences for 4110 commands */
238 #define ifmtNil		0
239 #define ifmtL		1
240 #define ifmtLL		2
241 #define ifmtLLL		3
242 #define ifmtLLLL	4
243 #define ifmtXhYh	9
244 #define ifmtMax		31	/* total number of distinct parameter
245 				   seqeunces */
246 
247 #define cchEsc1		18	/* number of valid 4110 command character
248 				   that can follow an <Esc> */
249 #define chEsc1Fst	'I'	/* first valid 4110 command character */
250 #define chEsc1Lst	'Z'	/* last valid 4110 command character */
251 #define cchEsc2		26	/* number of valid command characters for
252 				   the second character in two character
253 				   4110 command sequences */
254 #define chEsc2Fst	'A'	/* first valid character for second
255 				   character in a 4110 command sequence */
256 #define chEsc2Lst	'Z'	/* last valid character for second
257 				   character in a 4110 command sequence */
258 
259 /* Parser table 1.  Indexed by ifmt, a parameter sequence id.  Yields
260    an array of four elements each of which identifies the type of
261    the i-th parameter in the sequence. */
262 private char    aryfmt[ifmtMax][iprmMax] =
263 {
264     {typrmNil, typrmNil, typrmNil, typrmNil},
265     {typrmLong, typrmNil, typrmNil, typrmNil},
266     {typrmLong, typrmLong, typrmNil, typrmNil},
267     {typrmLong, typrmLong, typrmLong, typrmNil},
268     {typrmLong, typrmLong, typrmLong, typrmLong}, /*[5]*/
269     {typrmAryLong, typrmNil, typrmNil, typrmNil},
270     {typrmAryLong, typrmAryLong, typrmNil, typrmNil},
271     {typrmLong, typrmAryLong, typrmNil, typrmNil},
272     {typrmLong, typrmAryLong, typrmAryLong, typrmNil},
273     {typrmXhYh, typrmNil, typrmNil, typrmNil}, /*[10]*/
274     {typrmXhYh, typrmXhYh, typrmNil, typrmNil},
275     {typrmLong, typrmXhYh, typrmNil, typrmNil},
276     {typrmXhYh, typrmLong, typrmNil, typrmNil},
277     {typrmLong, typrmLong, typrmXhYh, typrmXhYh},
278     {typrmXhYh, typrmXhYh, typrmLong, typrmNil}, /*[15]*/
279     {typrmLong, typrmXhYh, typrmXhYh, typrmXhYh},
280     {typrmAryXhYh, typrmNil, typrmNil, typrmNil},
281     {typrmString, typrmNil, typrmNil, typrmNil},
282     {typrmString, typrmString, typrmNil, typrmNil},
283     {typrmString, typrmString, typrmString, typrmNil},
284      /*[20]*/ {typrmString, typrmLong, typrmNil, typrmNil},
285     {typrmString, typrmString, typrmLong, typrmNil},
286     {typrmString, typrmLong, typrmLong, typrmNil},
287     {typrmString, typrmLong, typrmString, typrmLong},
288     {typrmCh, typrmNil, typrmNil, typrmNil}, /*[25]*/
289     {typrmCh, typrmCh, typrmNil, typrmNil},
290     {typrmLong, typrmString, typrmNil, typrmNil},
291     {typrmReal4110, typrmNil, typrmNil, typrmNil},
292     {typrmString, typrmLong, typrmString, typrmString},
293     {typrmString, typrmAryLong, typrmNil, typrmNil},
294     {typrmString, typrmLong, typrmLong, typrmLong}
295 };
296 
297 /* Parser table 2.  Indexed by the two characters of a 4110 command
298    sequence.  Yields a parameter sequence index, which can be used to
299    retreive the parameter types from aryfmt. */
300 private char    aryaryifmt[cchEsc1][cchEsc2] =
301 {
302      /*['I']*/ {
303 	ifmtL, ifmtNil, ifmtLL, ifmtL, ifmtLL, ifmtLLL, ifmtLLL,
304 	ifmtL, ifmtLL, ifmtNil, ifmtNil, ifmtL, ifmtL, ifmtL,
305 	ifmtNil, ifmtL, 25, ifmtLL, ifmtLLL, ifmtL, ifmtL,
306 	13, 10, 11, ifmtNil, ifmtNil
307     },
308      /*['J']*/ {
309 	ifmtNil, 17, 19, 19, ifmtNil, 17, ifmtNil,
310 	ifmtL, ifmtNil, 17, 17, 17, ifmtNil, ifmtNil,
311 	ifmtNil, 20, 17, 19, 19, ifmtNil, ifmtL,
312 	28, ifmtNil, ifmtNil, ifmtNil, ifmtNil
313     },
314      /*['K']*/ {
315 	ifmtL, ifmtNil, ifmtNil, 7, ifmtL, ifmtL, ifmtNil,
316 	ifmtL, ifmtL, ifmtNil, ifmtNil, ifmtL, ifmtL, ifmtL, ifmtNil,
317 	ifmtL, ifmtNil, ifmtL, ifmtL, ifmtL, ifmtNil, ifmtNil,
318 	ifmtNil, ifmtL, ifmtNil, ifmtNil
319     },
320      /*['L']*/ {
321 	ifmtNil, ifmtL, ifmtL, ifmtNil, ifmtNil, ifmtXhYh, ifmtXhYh,
322 	ifmtXhYh, ifmtLLL, ifmtL, ifmtL, ifmtL, ifmtL, ifmtNil,
323 	ifmtNil, 12, ifmtNil, ifmtNil, ifmtL, 17, ifmtNil,
324 	ifmtL, ifmtNil, ifmtXhYh, ifmtNil, ifmtNil
325     },
326      /*['M']*/ {
327 	27, ifmtLL, ifmtLLL, ifmtLLLL, ifmtNil, ifmtL, ifmtL,
328 	ifmtNil, ifmtL, ifmtNil, ifmtNil, ifmtL, ifmtL, ifmtNil,
329 	ifmtNil, ifmtL, ifmtL, 27, ifmtLLL, ifmtL, ifmtNil,
330 	ifmtL, ifmtL, ifmtNil, ifmtL, ifmtLLL
331     },
332      /*['N']*/ {
333 	ifmtNil, ifmtL, ifmtLL, ifmtL, 5, ifmtL, ifmtNil,
334 	ifmtNil, ifmtNil, ifmtNil, ifmtL, ifmtL, ifmtL, ifmtNil,
335 	ifmtNil, ifmtL, ifmtL, ifmtLL, 5, 5, ifmtL,
336 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil
337     },
338      /*['O']*/ {
339 	ifmtNil, ifmtL, ifmtLL, ifmtL, ifmtLL, ifmtNil, ifmtNil,
340 	6, ifmtNil, ifmtNil, ifmtNil, ifmtL, ifmtLL, 6,
341 	ifmtNil, ifmtLLLL, ifmtNil, ifmtNil, ifmtLL, ifmtL, ifmtNil,
342 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil
343     },
344      /*['P']*/ {
345 	21, 22, 19, ifmtNil, 29, 30, ifmtNil,
346 	ifmtNil, 22, ifmtNil, ifmtNil, 18, 29, ifmtNil,
347 	ifmtNil, 20, 17, 20, ifmtNil, ifmtNil, ifmtNil,
348 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil
349     },
350      /*['Q']*/ {
351 	ifmtNil, ifmtL, ifmtNil, ifmtL, ifmtNil, ifmtL, ifmtNil,
352 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtLLL, ifmtL, ifmtL,
353 	ifmtL, ifmtNil, ifmtNil, ifmtL, ifmtNil, ifmtNil, ifmtL,
354 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil
355     },
356      /*['R']*/ {
357 	ifmtLLL, ifmtL, ifmtL, 5, ifmtL, ifmtL, 7,
358 	ifmtXhYh, 5, ifmtL, ifmtL, 5, ifmtNil, 5,
359 	ifmtNil, 26, 5, 14, 10, ifmtLLL, ifmtLLL,
360 	10, 10, 15, ifmtNil, ifmtNil
361     },
362      /*['S']*/ {
363 	8, ifmtNil, ifmtNil, ifmtLL, ifmtL, ifmtNil, ifmtLLL,
364 	ifmtLL, 31, ifmtNil, ifmtL, 6, ifmtLL, ifmtNil,
365 	ifmtL, ifmtXhYh, 26, ifmtLL, ifmtLL, ifmtLL, ifmtNil,
366 	ifmtLL, ifmtNil, 11, ifmtNil, ifmtLL
367     },
368      /*['T']*/ {
369 	ifmtNil, ifmtLLL, ifmtNil, ifmtNil, ifmtNil, ifmtNil, 7,
370 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtLLL,
371 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil,
372 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil
373     },
374      /*['U']*/ {
375 	ifmtNil, ifmtL, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil,
376 	ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil, ifmtNil,
377 	ifmtNil, ifmtNil, ifmtNil, 16, ifmtNil, ifmtNil, ifmtNil,
378 	ifmtNil, 10, ifmtL, ifmtNil, ifmtNil
379     }
380 };
381 
382 private jmp_buf env;
383 
384 /* these strange numbers were arrived at by the following observations: */
385 /* Table 3-2 in spec gives the spacing values in mils */
386 /* Using "Point Spacing" section on page 3-26 we compute that there are */
387 /* approximately 286 points/inch on a 10.9 x 14.5 inch image area
388 /* I rounded to "reasonable" 4096th's of an inch */
389 private int     rgdxhSpace[sycharMax] = {
390     56, 51, 34, 31
391 };
392 private int     rgdyhSpace[sycharMax] = {
393     90, 81, 53, 48
394 };
395 
396 private FILE * fpSrc, *fpPsDst, *fpDbg;
397 private struct Params   params;
398 
399 private char *prog;
400 
401 /* Outputs a conforming PostScript header to destination file */
CommentHeader(pparams)402 private CommentHeader(pparams)
403 struct Params  *pparams;
404 {
405     long    clock;
406     struct passwd  *pswd;
407     char    hostname[40];
408     fprintf(fpPsDst, "%%!\n"); /* no reversal */
409     fprintf(fpPsDst, "%%%%Creator: ");
410     pswd = getpwuid(getuid ());
411     VOIDC gethostname(hostname, sizeof hostname);
412     fprintf(fpPsDst,"%s:%s (%s)\n",hostname,pswd->pw_name,pswd->pw_gecos);
413 
414     fprintf(fpPsDst, "%%%%Title: %s\n",
415 	    ((pparams->scSrcFile == NULL) ? "stdin" : pparams->scSrcFile));
416 
417     fprintf(fpPsDst, "%%%%CreationDate: %s",
418     	(VOIDC time(&clock), ctime(&clock)));
419 }
420 
421 /* Filter some input characters that are ignored under all(?) circumstances */
ChGet(psts)422 private ChGet(psts)
423 struct Sts *psts;
424 {
425     int ch;
426 
427     while (TRUE) {
428 	ch = getc (fpSrc);
429 	switch (ch) {
430 	    case chEsc:
431 		ch = ChEscapeAction (psts);
432 		if (ch = chDel)
433 		    return (chDel);
434 		else
435 		    longjmp (env, 1);
436 		break;
437 	    case chFs:
438 		FsAction (psts);
439 		longjmp (env, 1);
440 		break;
441 	    case chGs:
442 		GsAction (psts);
443 		longjmp (env, 1);
444 		break;
445 	}
446 	if ((ch >= chEsc) || (ch == EOF) || ((ch >= chBell) && (ch < chSo)))
447 	    break;
448     }
449     return (ch);
450 }
451 
452 /* Parse a 4110 31-bit integer parameter */
LongGet(psts)453 private long    LongGet(psts)
454 struct Sts *psts;
455 {
456     char    ch;
457     long    longT;
458 
459     longT = 0;
460     while (TRUE) {
461 	ch = ChGet (psts);
462 	if (params.fDbg)
463 	    PrintLongByte (ch);
464 	if ((ch >= chFstHiInt) && (ch <= chLstHiInt))
465 	    longT = longT * 64 + (ch - chFstHiInt);
466 	else
467 	    break;
468     }
469     if ((ch >= chFstLoPosInt) && (ch <= chLstLoPosInt))
470 	longT = longT * 16 + (ch - chFstLoPosInt);
471     else if ((ch >= chFstLoNegInt) && (ch <= chLstLoNegInt))
472 	longT = -(longT * 16 + (ch - chFstLoNegInt));
473     else {
474 	fprintf(stderr,
475 	"%s: Error while parsing int, expecting low int char. ch = %d\n",
476 	prog, ch);
477 	longT = 0;
478     }
479     if (params.fDbg)
480 	fprintf(fpDbg, "long: %ld\n", longT);
481     return (longT);
482 }
483 
484 /* Parse an array of 32-bit integers */
GetAryLong(psts,arylong,ilongMax,pilongMac)485 private GetAryLong (psts, arylong, ilongMax, pilongMac)
486 struct Sts *psts;
487 long    arylong[];
488 int     ilongMax, *pilongMac;
489 {
490     int     ilong, ilongMac;
491 
492     if (params.fDbg)
493 	fprintf(fpDbg, "AryLong - ilongMac = ");
494     ilongMac = LongGet (psts);
495     *pilongMac = (ilongMac < ilongMax) ? ilongMac : ilongMax;
496     for (ilong = 0; ilong < *pilongMac; ilong++)
497 	arylong[ilong] = LongGet (psts);
498     for (ilong = *pilongMac; ilong < ilongMac; ilong++) VOIDC LongGet(psts);
499 }
500 
501 /* Parse a 4100-format string parameter */
GetString(psts,sc,ichMax)502 private GetString (psts, sc, ichMax)
503 struct Sts *psts;
504 char   *sc;
505 int     ichMax;
506 {
507     int     ich, ichMac;
508     char    chT;
509     long    longT;
510 
511     if (params.fDbg)
512 	fprintf(fpDbg, "String - length = ");
513     longT = LongGet (psts);
514     ichMac = (longT < ichMax - 1) ? longT : ichMax - 1;
515     for (ich = 0; ich < ichMac; ich++) {
516 	sc[ich] = ChGet (psts);
517 	if (params.fDbg)
518 	    PrintCmd (sc[ich]);
519     }
520     sc[ichMac] = '\0';
521     for (ich = ichMac; ich < longT; ich++) {
522 	chT = ChGet (psts);
523 	if (params.fDbg)
524 	    PrintCmd (chT);
525     }
526 }
527 
528 /* parse a 4110-format real parameter */
GetReal4110(psts,preal4110)529 private GetReal4110 (psts, preal4110)
530 struct Sts *psts;
531 struct Real4110 *preal4110;
532 {
533     if (params.fDbg)
534 	fprintf(fpDbg, "Real4110: \n");
535     preal4110->mantissa = LongGet (psts);
536     preal4110->exp = LongGet (psts);
537 }
538 
539 /* parse a 4014 xy-coordinate */
GetXhYh(ch,psts,pxh,pyh)540 private GetXhYh (ch, psts, pxh, pyh)
541 char    ch;
542 struct Sts *psts;
543 int    *pxh, *pyh;
544 {
545     char    chNxt;
546 
547     if ((ch >= chFstCoord) && (ch < chFstLoX)) {/* it is a High Y */
548 	if (params.fDbg)
549 	    PrintAdrByte (ch, TRUE, FALSE);
550 	psts->chHiY = ch;
551 	ch = ChGet (psts);
552     }
553 
554     if (ch >= chFstLoY) {
555 	chNxt = ChGet (psts);
556 	if ( /* psts->fHiRes && */ (chNxt >= chFstLoY)) {
557 	    if (params.fDbg)
558 		PrintAdrByte (ch, FALSE, TRUE);
559 	    psts->chExtra = ch;
560 	    ch = chNxt;
561 	    chNxt = ChGet (psts);
562 	}
563 	if (params.fDbg)
564 	    PrintAdrByte (ch, FALSE, FALSE);
565 	psts->chLoY = ch;
566 	ch = chNxt;
567     }
568     if ((ch >= chFstCoord) && (ch < chFstLoX)) {/* it is a High X */
569 	if (params.fDbg)
570 	    PrintAdrByte (ch, FALSE, FALSE);
571 	psts->chHiX = ch;
572 	ch = ChGet (psts);
573     }
574     if ((ch < chFstLoX) || (ch >= chFstLoY)) {
575 	fprintf(stderr,
576 		"%s: Expecting Lo X Coordinate.  ch = %d\n", prog, ch);
577 	if (params.fDbg)
578 	    fprintf(fpDbg,
579 		    "Error: Expecting Lo X Coordinate.  ch = %d\n", ch);
580 	ch = chFstLoX;
581     }
582     if (params.fDbg)
583 	PrintAdrByte (ch, FALSE, FALSE);
584 
585     *pyh = ((psts->chHiY - chFstCoord) << shiftHiByte)
586 	| ((psts->chExtra >> shiftYExtra) & mskLoBits)
587 	| ((psts->chLoY - chFstLoY) << shiftLoByte);
588     *pxh = ((psts->chHiX - chFstCoord) << shiftHiByte)
589 	| (psts->chExtra & mskLoBits)
590 	| ((ch - chFstLoX) << shiftLoByte);
591     if (params.fDbg)
592 	fprintf(fpDbg, "*pxh: %d or 0X%x, *pyh: %d or 0X%x\n",
593 		*pxh, *pxh, *pyh, *pyh);
594 }
595 
596 /* parse an array of xy-coordinates */
GetAryXhYh(psts,aryxh,aryyh,iMax,piMac)597 private GetAryXhYh (psts, aryxh, aryyh, iMax, piMac)
598 struct Sts *psts;
599 int    *aryxh, *aryyh;
600 int     iMax, *piMac;
601 {
602     int     i, iMac, xhT, yhT;
603 
604     if (params.fDbg)
605 	fprintf(fpDbg, "AryXyYh - length = ");
606     iMac = LongGet (psts);
607     *piMac = (iMac < iMax) ? iMac : iMax;
608     for (i = 0; i < *piMac; i++)
609 	GetXhYh (ChGet (psts), psts, &aryxh[i], &aryyh[i]);
610     for (i = *piMac; i < iMac; i++)
611 	GetXhYh (ChGet (psts), psts, &xhT, &yhT);
612 }
613 
614 #define scMoveTo "%d %d m\n"
615 /* char	*rgscMoveCmd[tymoveMax] =
616 	    { "",
617 	    "%d ml\n",
618 	    "%d mr\n",
619 	    "%d mu\n",
620 	    "%d md\n",
621 	    "%d md\n",
622 	    ""
623 	    };
624 */
625 
626 /* Process a line-feed from the 4014 file:
627    Update the current position in the Sts - do NOT output any PostScript.
628    All PostScript marking commands move issue moveto commands
629    whenever necessary */
MoveDown(psts)630 private MoveDown (psts)
631 struct Sts *psts;
632 {
633     int     xhLeftNew;
634 
635     psts->yh -= rgdyhSpace[psts->sychar];
636     if (psts->yh < 0) {
637 	psts->yh = yhHome;
638 	if (params.fMarg2) {
639 	    xhLeftNew = (psts->xhLeftMarg == xhMarg1) ? xhMarg2 : xhMarg1;
640 	    psts->xh = xhLeftNew + (psts->xh - psts->xhLeftMarg);
641 	    psts->xhLeftMarg = xhLeftNew;
642 	}
643     }
644 }
645 
646 /* Move the current position.  No PostScript move commands are emitted.
647    PostScript marking commands (i.e. stroke) issue moveto's when needed */
MovePos(psts,tymove)648 private MovePos (psts, tymove)
649 struct Sts *psts;
650 short   tymove;
651 {
652 /* char *scMoveCmd;
653 #define scXMarg1 "%d cr1\n"
654 #define scXMarg2 "cr2\n"
655 
656 if (psts->fMovePending)
657     fprintf(fpPsDst, scMoveTo, psts->xh, psts->yh);
658 psts->fMovePending = FALSE;
659 */
660     switch (tymove) {
661 	case tymoveNil:
662 	    return;
663 	case tymoveLeft:
664 	    psts->xh -= rgdxhSpace[psts->sychar];
665 	    if (psts->xh < psts->xhLeftMarg)
666 		psts->xh = psts->xhLeftMarg;
667 /*        fprintf(fpPsDst, rgscMoveCmd[tymove], psts->sychar); */
668 	    break;
669 	case tymoveRt:
670 	    psts->xh += rgdxhSpace[psts->sychar];
671 	    if (psts->xh > xhMax) {
672 		MoveDown (psts);
673 		psts->xh = psts->xhLeftMarg;
674 	    }
675 /*        fprintf(fpPsDst, rgscMoveCmd[tymove], psts->sychar); */
676 	    break;
677 	case tymoveUp:
678 	    psts->yh += rgdyhSpace[psts->sychar];
679 /*        fprintf(fpPsDst, rgscMoveCmd[tymove], psts->sychar); */
680 	    break;
681 	case tymoveGDown:
682 	case tymoveDown:
683 	    MoveDown (psts);
684 	    if (params.fLfGenCr)
685 		psts->xh = psts->xhLeftMarg;
686 /*         if (params.fLfGenCr)
687              { fprintf(fpPsDst, scXMarg1, psts->sychar);
688              psts->xh = xhLeftMarg;
689 	     }
690         else fprintf(fpPsDst, rgscMoveCmd[tymove], psts->sychar);
691 */
692 	    break;
693 	case tymoveXMarg:
694 	    if (params.fCrGenLf)
695 		MoveDown (psts);
696 	    psts->xh = psts->xhLeftMarg;
697 /*         if (params.fCrGenLf)
698              { fprintf(fpPsDst, scXMarg1, psts->sychar);
699              psts->yh -= rgdyhSpace[psts->sychar];
700 	     }
701         else fprintf(fpPsDst, scXMarg2);
702 */
703 	    break;
704     }
705     psts->fMovePending = TRUE;
706 }
707 
708 
709 /* Process form feed */
EraseAndHome()710 private EraseAndHome ()
711 {
712 #define scEraseAndHome "erasepage\nxHome yHome m\n"
713 
714     fprintf(fpPsDst, scEraseAndHome);
715 }
716 
717 /* Process Etb character */
MakeCopy()718 private MakeCopy ()
719 {
720 #define scMakeCopy "showpage\n"
721 
722     fprintf(fpPsDst, scMakeCopy);
723 }
724 
725 /* Process a movement/drawing command in on of the graphics modes */
VectorGoTo(psts,xhNew,yhNew)726 private VectorGoTo (psts, xhNew, yhNew)
727 struct Sts *psts;
728 int     xhNew, yhNew;
729 {
730 #define scLineTo "%d %d rl\n"
731 
732     if (psts->fPenDown) {
733 	if (psts->syline != psts->sylinePrt) {
734 	    fprintf(fpPsDst, "%d SetLineStyle\n", psts->syline);
735 	    psts->sylinePrt = psts->syline;
736 	}
737 	if (psts->md == mdVector) {
738 	    if (psts->fMovePending)
739 		fprintf(fpPsDst, scMoveTo, psts->xh, psts->yh);
740 	    fprintf(fpPsDst, scLineTo, xhNew - psts->xh, yhNew - psts->yh);
741 	}
742 	else {			/* md = mdPtPlot */
743 	    fprintf(fpPsDst, scMoveTo, xhNew, yhNew);
744 	    fprintf(fpPsDst, scLineTo, 0, 0);
745 	}
746 	psts->fVectorDrawn = TRUE;
747     }
748     psts->fMovePending = (!psts->fPenDown);
749     psts->xh = xhNew;
750     psts->yh = yhNew;
751 }
752 
753 /* Emit a stoke command if there are any vector's pending */
Stroke(psts)754 private Stroke (psts)
755 struct Sts *psts;
756 {
757     if (psts->fVectorDrawn && psts->fPenDown) {
758 	fprintf(fpPsDst, "s\n");
759 	psts->fVectorDrawn = FALSE;
760     }
761 }
762 
763 /* Emit a show command */
EmitShow(psts,scShow,ichFst,ichLim)764 private EmitShow (psts, scShow, ichFst, ichLim)
765 struct Sts *psts;
766 char    scShow[];
767 int     ichFst, ichLim;
768 {
769     int     ich;
770 
771     if (psts->fMovePending)
772 	fprintf(fpPsDst, scMoveTo, psts->xh, psts->yh);
773     psts->fMovePending = FALSE;
774     if (psts->sychar != psts->sycharPrt) {
775 	fprintf(fpPsDst, "%d SetCharStyle\n", psts->sychar);
776 	psts->sycharPrt = psts->sychar;
777     }
778 
779     if (ichFst < ichLim) {
780 	putc('\(', fpPsDst);
781 	for (ich = ichFst; ich < ichLim; ich++)
782 	    putc(scShow[ich], fpPsDst);
783 	fprintf(fpPsDst, ")sh\n");
784     }
785 }
786 
787 /* Output a string of characters to PostScript file.  Deal with
788    line overflow and special character '\' */
Show(psts,scShow,cchShow)789 private Show (psts, scShow, cchShow)
790 struct Sts *psts;
791 char    scShow[];
792 int     cchShow;
793 {
794     int     ichFst, ich;
795     int     xh, dxhSpace;
796 
797     scShow[cchShow] = '\0';
798 
799     dxhSpace = rgdxhSpace[psts->sychar];
800     ichFst = ich = 0;
801     xh = psts->xh;
802     while (ich < cchShow) {
803 	if (scShow[ich] == '\\')
804 	    ich++;
805 	xh += dxhSpace;
806 	if (xh >= xhMax) {
807 	    EmitShow (psts, scShow, ichFst, ich);
808 	    ichFst = ich;
809 	    MoveDown (psts);
810 	    xh = psts->xh = psts->xhLeftMarg;
811 	    psts->fMovePending = TRUE;
812 	}
813 	ich++;
814     }
815 
816     if (params.fDbg)
817 	fprintf(fpDbg, "Show(%s)\n", scShow);
818 
819     EmitShow (psts, scShow, ichFst, cchShow);
820     psts->xh = xh;
821 }
822 
823 /* Process the <Fs> character */
FsAction(psts)824 private FsAction (psts)
825 struct Sts *psts;
826 {
827     if (params.fDbg)
828 	PrintCmd (chFs);
829     Stroke (psts);
830     psts->md = mdPtPlot;
831 }
832 
833 /* Process the Graphic Shift character */
GsAction(psts)834 private GsAction (psts)
835 struct Sts *psts;
836 {
837     if (params.fDbg)
838 	PrintCmd (chGs);
839     Stroke (psts);
840     psts->fPenDown = FALSE;
841     psts->md = mdVector;
842     psts->syline = sylineNormal;
843 }
844 
845 /* Process a sequence beginning with an Escape character.  Return
846    the character following the Escape or the Del character if the
847    escape sequence is <Esc>? */
ChEscapeAction(psts)848 private ChEscapeAction (psts)
849 struct Sts *psts;
850 {
851     int ch;
852     short   sylineT;
853 
854     ch = getc (fpSrc);
855     if (params.fDbg)
856 	PrintEscCmd (ch);
857     while (ch != EOF) {
858 	switch (ch) {
859 	    case chEnq:
860 		Stroke (psts);
861 		psts->md = mdBypass;
862 		goto Done;
863 	    case chBell:
864 		psts->fPenDown = TRUE;
865 		goto Done;
866 	    case chBs:
867 		MovePos (psts, tymoveLeft);
868 		goto Done;
869 	    case chTab:
870 		MovePos (psts, tymoveRt);
871 		goto Done;
872 	    case chVTab:
873 		MovePos (psts, tymoveUp);
874 		goto Done;
875 	    case chFf:
876 		EraseAndHome ();
877 		goto Done;
878 	    case chSo:
879 		psts->charset = charsetAlt;
880 		goto Done;
881 	    case chSi:
882 		psts->charset = charsetStd;
883 		goto Done;
884 	    case chEtb:
885 		Stroke (psts);
886 		MakeCopy ();
887 		goto Done;
888 	    case chCan:
889 		Stroke (psts);
890 		psts->md = mdBypass;
891 		goto Done;
892 	    case chSub:
893 		Stroke (psts);
894 		psts->md = mdBypass;
895 		goto Done;
896 	    case chFs:
897 		Stroke (psts);
898 		psts->md = mdSpecPtPlot;
899 		goto Done;
900 	    case chGs:
901 		GsAction (psts);
902 		goto Done;
903 	    case chRs:
904 		Stroke (psts);
905 		psts->md = mdIncrPtPlot;
906 		psts->dir = dirNil;
907 		goto Done;
908 	    case chUs:
909 		Stroke (psts);
910 		psts->md = mdAlpha;
911 		goto Done;
912 	    case '?':
913 		ch = chDel;
914 		goto Done;
915 	    default:
916 		if ((ch >= chFstSychar) && (ch <= chLstSychar)) {
917 		    psts->sychar = (ch - chFstSychar);
918 		    goto Done;
919 		}
920 		else if ((ch >= chFstSyline) && (ch <= chLstSyline)) {
921 		    sylineT = ((ch - chFstSyline) & mskSyline);
922 		    if (sylineT < sylineMax)
923 			psts->syline = sylineT;
924 		    else
925 			psts->syline = sylineNormal;
926 /* What about Defocused? */
927 		    goto Done;
928 		}
929 		else if ((ch >= chFst4110) && (ch <= chLst4110)) {
930 		    Skip4110 (ch, psts);
931 		    goto Done;
932 		}
933 		break;
934 	}
935 	ch = getc (fpSrc);
936 	if (params.fDbg)
937 	    PrintCmd (ch);
938     }
939 Done:
940     if (params.fDbg)
941 	PrintCr ();
942     return (ch);
943 }
944 
945 /* Process some characters in one of the vector modes */
VectorAction(ch,psts)946 private VectorAction (ch, psts)
947 char    ch;
948 struct Sts *psts;
949 {
950     int     xhNew, yhNew;
951 
952     if ((ch >= chFstCoord) && (ch <= chLstCoord)) {
953 	if (psts->md == mdIncrPtPlot)
954 	    IncrPtPlotAction (ch, psts);
955 	else {
956 	    if ((psts->md != mdVector) && (psts->md != mdPtPlot))
957 		fprintf(stderr, "%s: Unimplemented vector mode: %d\n",
958 			prog, psts->md);
959 
960 	    GetXhYh (ch, psts, &xhNew, &yhNew);
961 	    VectorGoTo (psts, xhNew, yhNew);
962 	    psts->fPenDown = TRUE;
963 	}
964     }
965     else {
966 	if (params.fDbg)
967 	    PrintCmd (ch);
968 	switch (ch) {
969 	    case chLf:
970 		MovePos (psts, tymoveGDown);
971 		break;
972 	    case chCr:
973 		if (psts->fVectorDrawn)
974 		    MovePos (psts, tymoveXMarg);
975 		psts->md = mdAlpha;
976 		break;
977 	    case chUs:
978 		psts->md = mdAlpha;
979 		break;
980 	}
981     }
982 }
983 
984 /* Finish processing a sequence of characters in Incremental
985    Point Plot Mode by issuing an appropriate VectorGoTo */
DoIncrPtPlot(psts)986 private DoIncrPtPlot (psts)
987 struct Sts *psts;
988 {
989     int     xhNew;
990     int     yhNew;
991 
992     xhNew = psts->xh;
993     yhNew = psts->yh;
994     if (psts->dir & mskDirUp)
995 	yhNew += psts->cincr;
996     else if (psts->dir & mskDirDown)
997 	yhNew -= psts->cincr;
998     if (psts->dir & mskDirLeft)
999 	xhNew -= psts->cincr;
1000     else if (psts->dir & mskDirRt)
1001 	xhNew += psts->cincr;
1002     VectorGoTo (psts, xhNew, yhNew);
1003     psts->cincr = 0;
1004 }
1005 
1006 /* Process a character in Incremental Point Plot Mode */
IncrPtPlotAction(ch,psts)1007 private IncrPtPlotAction (ch, psts)
1008 char    ch;
1009 struct Sts *psts;
1010 {
1011     short   fPenDown;
1012     short   dir;
1013 
1014     if (params.fDbg)
1015 	PrintCmd (ch);
1016     fPenDown = psts->fPenDown;
1017     dir = psts->dir;
1018     if (ch == chSp)
1019 	fPenDown = FALSE;
1020     else if (ch == 'P')
1021 	fPenDown = TRUE;
1022     else
1023 	dir = (ch & mskDir);
1024     if ((psts->dir == dir) && (psts->fPenDown == fPenDown)
1025 	    && (psts->dir != dirNil))
1026 	psts->cincr++;
1027     else {
1028 	if (psts->dir != dirNil)
1029 	    DoIncrPtPlot (psts);
1030 	psts->dir = dir;
1031 	psts->cincr = 1;
1032 	psts->fPenDown = fPenDown;
1033     }
1034 }
1035 
1036 /* Process a character in bypass mode */
BypassAction(ch,psts)1037 private BypassAction (ch, psts)
1038 char    ch;
1039 struct Sts *psts;
1040 {
1041     if (params.fDbg)
1042 	PrintCmd (ch);
1043     switch (ch) {
1044 	case chLf:
1045 	    MovePos (psts, tymoveGDown);
1046 	    break;
1047 	case chCr:
1048 	    MovePos (psts, tymoveXMarg);
1049 	    psts->md = mdAlpha;
1050 	    break;
1051 	case chUs:
1052 	    psts->md = mdAlpha;
1053 	    break;
1054     }
1055 }
1056 
1057 /* Some debug print routines and data */
1058 private char   *rgsc[0x21] =
1059 {
1060     "<Null>", "<Soh>", "<Stx>", "<Etx>",
1061     "<Eot>", "<Enq>", "<Ack>", "<Bell>",
1062     "<Bs>", "<Tab>", "<Lf>", "<VTab>",
1063     "<Ff>", "<Cr>", "<So>", "<Si>",
1064     "<Dle>", "<Dcl>", "<Dc2>", "<Dc3>",
1065     "<Dc4>", "<Nak>", "<Syn>", "<Etb>",
1066     "<Can>", "<Em>", "<Sub>", "<Esc>",
1067     "<Fs>", "<Gs>", "<Rs>", "<Us>",
1068     "<Sp>"
1069 };
1070 
1071 /* Concatenate a human-readable form of a character code to
1072    the supplied string */
CatChName(ch,scDst)1073 private CatChName (ch, scDst)
1074 char    ch;
1075 char    scDst[];
1076 {
1077     char   *sc;
1078     char    scT[3];
1079 
1080     if (ch < 0x21)
1081 	sc = rgsc[ch];
1082     else if (ch == chDel)
1083 	sc = "<Del>";
1084     else {
1085 	scT[0] = ch;
1086 	scT[1] = '\0';
1087 	sc = scT;
1088     }
1089     VOIDC strcat(scDst, sc);
1090 }
1091 
1092 /* Output a line of test output for the given command character */
PrintCmd(ch)1093 private PrintCmd (ch)
1094 char    ch;
1095 {
1096     char    scPrint[100];
1097 
1098     scPrint[0] = '\0';
1099     CatChName (ch, scPrint);
1100     VOIDC strcat(scPrint, "\n");
1101     fprintf(fpDbg, scPrint);
1102 }
1103 
1104 /* Print a line of test output for and Escape command */
PrintEscCmd(ch)1105 private PrintEscCmd (ch)
1106 char    ch;
1107 {
1108     char    scPrint[100];
1109 
1110     VOIDC strcpy(scPrint, "<Esc> ");
1111     CatChName(ch, scPrint);
1112     fprintf(fpDbg, scPrint);
1113 }
1114 
1115 /* Print some diagnostic info on a vector-mode address byte */
PrintAdrByte(ch,fHiY,fExtra)1116 private PrintAdrByte (ch, fHiY, fExtra)
1117 char    ch;
1118 char    fHiY, fExtra;
1119 {
1120     if (ch < chFstCoord) {
1121 	fprintf(fpDbg, "Bad Vector Command");
1122 	PrintCmd (ch);
1123     }
1124     else if (ch < chFstLoX) {
1125 	if (fHiY)
1126 	    fprintf(fpDbg, "yHi: %x    ", ch - chFstCoord);
1127 	else
1128 	    fprintf(fpDbg, "xHi: %x    ", ch - chFstCoord);
1129     }
1130     else if (ch < chFstLoY)
1131 	fprintf(fpDbg, "xLo: %x\n", ch - chFstLoX);
1132     else if (ch <= chLstCoord) {
1133 	if (fExtra)
1134 	    fprintf(fpDbg, "x12: %x    y12: %x   margin bit: %s ",
1135 		    ch & mskLoBits,
1136 		    (ch >> shiftYExtra) & mskLoBits,
1137 		    (ch & mskBit4) ? "TRUE" : "FALSE");
1138 	else
1139 	    fprintf(fpDbg, "yLo: %x    ", ch - chFstLoY);
1140     }
1141     else {
1142 	fprintf(fpDbg, "Bad Vector Command");
1143 	PrintCmd (ch);
1144     }
1145 }
1146 
1147 /* Print some diagnostic info on a 32-bit integer parameter byte */
PrintLongByte(ch)1148 private PrintLongByte (ch)
1149 char    ch;
1150 {
1151     if (ch < chFstLoNegInt) {
1152 	fprintf(fpDbg, "Bad Integer Command");
1153 	PrintCmd (ch);
1154     }
1155     else if (ch < chFstLoPosInt)
1156 	fprintf(fpDbg, "iLoNeg: (-) %x, ", ch - chFstLoNegInt);
1157     else if (ch < chFstHiInt)
1158 	fprintf(fpDbg, "iLoPos: %x, ", ch - chFstLoPosInt);
1159     else if (ch <= chLstHiInt)
1160 	fprintf(fpDbg, "iHi: %x, ", ch - chFstHiInt);
1161     else {
1162 	fprintf(fpDbg, "Bad Vector Command");
1163 	PrintCmd (ch);
1164     }
1165 }
1166 
PrintCr()1167 private PrintCr () {
1168     putc('\n', fpDbg);
1169 }
1170 
1171 /* 4110 Command Scanner */
Skip4110(ch,psts)1172 private Skip4110 (ch, psts)
1173 struct Sts *psts;
1174 char    ch;
1175 {
1176     char    chNxt;
1177     int     ifmt, i, iprm, xh, yh;
1178     char   *pfmt;
1179     long    longT;
1180 #define ichScMax 32
1181     char    sc[ichScMax];
1182     struct Real4110 realT;
1183 
1184     chNxt = ChGet (psts);
1185     if (params.fDbg) {
1186 	PrintCmd (chNxt);
1187 	fprintf(fpDbg, "    ");
1188     }
1189     if ((ch < chFst4110) || (ch > chLst4110) || (chNxt < chFstEsc2)
1190 	    || (chNxt > chLstEsc2)) {
1191 	if (params.fDbg)
1192 	    fprintf(fpDbg, "Bad 4110 command: %c%c\n", ch, chNxt);
1193 	fprintf(stderr, "%s: Bad 4110 command: %c%c\n", prog, ch, chNxt);
1194 	return;
1195     }
1196     if ((ch == 'S') && (chNxt == 'I')) {
1197 				/* this one command takes five parameters
1198 				*/
1199 	longT = LongGet (psts);
1200 	GetReal4110 (psts, &realT);
1201 	GetReal4110 (psts, &realT);
1202 	GetReal4110 (psts, &realT);
1203 	GetXhYh (ChGet (psts), psts, &xh, &yh);
1204 	return;
1205     }
1206     ifmt = aryaryifmt[ch - chFst4110][chNxt - chFstEsc2];
1207     pfmt = aryfmt[ifmt];
1208     for (iprm = 0; iprm < iprmMax; iprm++) {
1209 	switch (pfmt[iprm]) {
1210 	    case typrmNil:
1211 		goto Exit;
1212 	    case typrmLong:
1213 		longT = LongGet (psts);
1214 		break;
1215 	    case typrmAryLong:
1216 		GetAryLong (psts, &longT, 1, &i);
1217 		break;
1218 	    case typrmXhYh:
1219 		GetXhYh (ChGet (psts), psts, &xh, &yh);
1220 		break;
1221 	    case typrmAryXhYh:
1222 		GetAryXhYh (psts, &xh, &yh, 1, &i);
1223 		break;
1224 	    case typrmString:
1225 		GetString (psts, sc, ichScMax);
1226 		break;
1227 	    case typrmReal4110:
1228 		GetReal4110 (psts, &realT);
1229 		break;
1230 	    case typrmCh:
1231 		VOIDC ChGet (psts);
1232 		break;
1233 	}
1234     }
1235 Exit:
1236     return;
1237 }
1238 
1239 /* 4104 Parser */
Convert4014()1240 private Convert4014 () {
1241     struct Sts  stsCur;
1242 #define chLim	0x80
1243     short   rgtymove[chLim];
1244     short   tymoveT;
1245     int    ch;
1246 #define ichShowMax 500
1247     char    scShow[ichShowMax];
1248     int     ichShowCur;
1249     int     chT;
1250 
1251     ichShowCur = 0;
1252     stsCur.md = mdAlpha;
1253     stsCur.xh = xhHome;
1254     stsCur.xhLeftMarg = xhHome;
1255     stsCur.yh = yhHome;
1256     stsCur.syline = stsCur.sylinePrt = sylineNormal;
1257     stsCur.sychar = stsCur.sycharPrt = sycharLarge;
1258     stsCur.charset = stsCur.charsetPrt = charsetStd;
1259     stsCur.fPenDown = FALSE;
1260     stsCur.fMovePending = FALSE;
1261     stsCur.fVectorDrawn = FALSE;
1262     stsCur.cincr = 0;
1263 
1264     for (chT = 0; chT < chLim; chT++)
1265 	rgtymove[chT] = tymoveNil;
1266     rgtymove[chBs] = tymoveLeft;
1267     rgtymove[chTab] = tymoveRt;
1268     rgtymove[chLf] = tymoveDown;
1269     rgtymove[chVTab] = tymoveUp;
1270     rgtymove[chCr] = tymoveXMarg;
1271     rgtymove[chSp] = tymoveRt;
1272 
1273     VOIDC setjmp(env);
1274 
1275     ch = getc(fpSrc);
1276     while (ch != EOF) {
1277 	if ((stsCur.md != mdIncrPtPlot) && (stsCur.cincr != 0))
1278 	    DoIncrPtPlot (&stsCur);
1279 	if ((stsCur.md == mdAlpha) &&
1280 		(ch >= chFstShow) && (ch <= chLstShow)) {
1281 	    if (ichShowCur >= ichShowMax - 2) {
1282 		Show (&stsCur, scShow, ichShowCur);
1283 		ichShowCur = 0;
1284 	    }
1285 	    if ((ch == '(') || (ch == ')') || (ch == '\\'))
1286 		scShow[ichShowCur++] = '\\';
1287 	    scShow[ichShowCur++] = ch;
1288 	}
1289 	else {
1290 	    if (ichShowCur > 0) {
1291 		Show (&stsCur, scShow, ichShowCur);
1292 		ichShowCur = 0;
1293 	    }
1294 	    switch (ch) {
1295 		case chEsc:
1296 		    ch = ChEscapeAction (&stsCur);
1297 		    if (ch == chDel)
1298 			continue;
1299 		    break;
1300 		case chBell:
1301 		    if (params.fDbg)
1302 			PrintCmd (ch);
1303 		    stsCur.fPenDown = TRUE;
1304 		    break;
1305 		case chFs:
1306 		    FsAction (&stsCur);
1307 		    break;
1308 		case chGs:
1309 		    GsAction (&stsCur);
1310 		    break;
1311 		case chRs:
1312 		    if (params.fDbg)
1313 			PrintCmd (ch);
1314 		    Stroke (&stsCur);
1315 		    stsCur.md = mdIncrPtPlot;
1316 		    stsCur.dir = dirNil;
1317 		    break;
1318 		default:
1319 		    switch (stsCur.md) {
1320 			case mdAlpha:
1321 			    Stroke (&stsCur);
1322 			    if ((tymoveT = rgtymove[ch]) != tymoveNil)
1323 				MovePos (&stsCur, tymoveT);
1324 			    if (params.fDbg)
1325 				PrintCmd (ch);
1326 			    break;
1327 			case mdVector:
1328 			case mdPtPlot:
1329 			case mdSpecPtPlot:
1330 			case mdIncrPtPlot:
1331 			    VectorAction (ch, &stsCur);
1332 			    break;
1333 			case mdBypass:
1334 			    BypassAction (ch, &stsCur);
1335 			    break;
1336 			default:
1337 			    fprintf(stderr, "%s: Illegal mode\n",prog);
1338 			    exit (2);
1339 			    break;
1340 		    }
1341 		    break;
1342 	    }
1343 	}
1344 	ch = getc (fpSrc);
1345     }
1346     MakeCopy ();
1347 }
1348 
1349 #define ARGS "RCNmp:d:l:s:S:"
1350 #define USAGE "ps4014 [-RCNm] [-p outfile] [-l left,bottom] [-s width,height] [-S width] [file]"
1351 
main(argc,argv)1352 main(argc, argv)
1353 int     argc;
1354 char   *argv[];
1355 {
1356     register int argp;
1357     extern int optind;
1358     extern char *optarg;
1359     char *libdir;
1360 
1361     params.scSrcFile = NULL;
1362     params.scDstFile = NULL;
1363     params.scDbgFile = NULL;
1364     params.fDbg = FALSE;
1365     params.fLfGenCr = TRUE;
1366     params.fCrGenLf = TRUE;
1367     params.fMarg2 = FALSE;
1368 /* these numbers make the image occupy almost the whole page
1369    with the correct proportions */
1370     params.xRtInch = 0.38;
1371     params.yBotInch = 0.35;
1372     params.dxWidInch = 10.24;
1373     params.dyHtInch = 7.8;
1374     params.fLandscape = TRUE;
1375 
1376     prog = *argv;
1377 
1378     while ((argp = getopt(argc, argv, ARGS)) != EOF) {
1379 	switch (argp) {
1380 	    case 'R':
1381 		params.fLandscape = FALSE;
1382 		break;
1383 	    case 'C':
1384 		params.fCrGenLf = FALSE;
1385 		break;
1386 	    case 'N':
1387 		params.fLfGenCr = FALSE;
1388 		break;
1389 	    case 'm':
1390 		params.fMarg2 = TRUE;
1391 		break;
1392 	    case 'p':
1393 		params.scDstFile = optarg;
1394 		break;
1395 	    case 'd':
1396 		params.scDbgFile = optarg;
1397 		break;
1398 	    case 'l':
1399 	    	if (sscanf(optarg, " %f,%f",
1400 			&params.xRtInch,&params.yBotInch) != 2) {
1401 		    fprintf(stderr,"%s: bad parameter -l%s\n",prog,optarg);
1402 		    exit(2);
1403 		}
1404 		break;
1405 	    case 's':
1406 	    	if (sscanf(optarg, " %f,%f",
1407 			&params.dxWidInch,&params.dyHtInch) != 2) {
1408 		    fprintf(stderr,"%s: bad parameter -s%s\n",prog,optarg);
1409 		    exit(2);
1410 		}
1411 		break;
1412 	    case 'S':
1413 	    	if (sscanf(optarg, " %f",
1414 			&params.dxWidInch) != 1) {
1415 		    fprintf(stderr,"%s: bad parameter -S%s\n",prog,optarg);
1416 		    exit(2);
1417 		}
1418 		params.dyHtInch = 0;
1419 		break;
1420 	    case '?':
1421 	    default:
1422 		fprintf(stderr,"%s: bad option -%c\n",prog,argp);
1423 		exit(2);
1424 	}
1425     }
1426     if ((optind + 1) < argc) {
1427 	fprintf(stderr,"%s: %s\n", USAGE);
1428 	exit(2);
1429     }
1430     if (optind < argc) {
1431 	params.scSrcFile = argv[optind];
1432 	if ((fpSrc = fopen(params.scSrcFile, "r")) == NULL) {
1433 	    fprintf(stderr,"%s: can't open %s\n",prog,params.scSrcFile);
1434 	    exit(2);
1435 	}
1436     }
1437     else fpSrc = stdin;
1438 
1439     if (params.scDstFile == NULL)
1440 	fpPsDst = stdout;
1441     else {
1442 	if ((fpPsDst = fopen(params.scDstFile, "w")) == NULL) {
1443 	    fprintf(stderr,"%s: can't open output file %s\n",
1444 	    	prog,params.scDstFile);
1445 	    exit(2);
1446 	}
1447     }
1448     if (params.scDbgFile != NULL) {
1449 	if ((fpDbg = fopen(params.scDbgFile, "w")) == NULL) {
1450 	    fprintf(stderr,"%s: can't open debug file %s\n",
1451 	    	prog, params.scDbgFile);
1452 	    exit(2);
1453 	}
1454         params.fDbg = TRUE;
1455     }
1456     if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir;
1457     VOIDC mstrcat(scProlog,libdir,PS4014PRO,sizeof scProlog);
1458     CommentHeader (&params);
1459     putc('\n', fpPsDst);
1460 
1461     if (copyfile(scProlog,fpPsDst) != 0) {
1462 	fprintf(stderr,"%s: trouble copying prolog file %s\n",prog,scProlog);
1463 	exit(2);
1464     }
1465 /* rotate and translate before we scale */
1466     if (params.fLandscape)
1467 	fprintf(fpPsDst, "90 rotate 0 -8.5 inch translate\n");
1468     fprintf(fpPsDst, "%g inch %g inch translate\n",
1469 	    params.xRtInch, params.yBotInch);
1470     if (params.dyHtInch == 0) {	/* we got a dxWidInch but not a dyHtInch */
1471     /* -> we are scaling y axis proportional to x axis */
1472 	params.dyHtInch = (params.dxWidInch * yhMax) / xhMax;
1473     }
1474     fprintf(fpPsDst, "/dxWidInch %g def\n", params.dxWidInch);
1475     fprintf(fpPsDst, "/dyHtInch %g def\n", params.dyHtInch);
1476     fprintf(fpPsDst,
1477      "ScaleCoords\n0 SetCharStyle\n0 SetLineStyle\nxHome yHome moveto\n");
1478 
1479     Convert4014 ();
1480 
1481     fprintf(fpPsDst, "\n%%%%Trailer\ngrestore\n");
1482     fprintf(fpPsDst, "ps4014sav restore\n");
1483 
1484     VOIDC fclose(fpPsDst);
1485     VOIDC fclose(fpSrc);
1486     if (fpDbg != NULL) VOIDC fclose(fpDbg);
1487     exit(0);
1488 
1489 }
1490