1 #ifndef lint
2 static char sccsid[] = "@(#)driver.c	1.1 (CWI) 85/07/19";
3 #endif lint
4 
5 #include <stdio.h>
6 #include <ctype.h>
7 
8 #define	DEV202	1
9 #define	DEVAPS	2
10 #define	DEVCAT	3
11 #define	DEV450	4
12 #define DEVHAR	6
13 int	devtype	= DEVHAR;
14 
15 float	deltx;	/* max x value in output, for scaling */
16 float	delty;	/* max y value in output, for scaling */
17 int	dbg	= 0;
18 int	res	= 1445;	/* harris is default */
19 FILE	*fin;	/* input file pointer */
20 char	*cmdname;
21 int	crop	= 1;	/* trim off exterior white space if non-zero */
22 float	hshift	= 0.3;	/* move this far left for text (in em's) */
23 float	vshift	= 0.3;	/* this far down */
24 			/* these values are suitable for circuit diagrams */
25 int	linetype	= 's';	/* solid is normal */
26 
27 char	buf[20000];
28 char	*bp	= buf;
29 
30 int	sxmin;		/* lower limit from s command */
31 int	symin;
32 int	sxmax	= 4096;	/* upper */
33 int	symax	= 4096;
34 int	xmin	= 30000;	/* min values found in actual data */
35 int	ymin	= 30000;
36 int	xmax	= -30000;	/* max */
37 int	ymax	= -30000;
38 
39 main(argc,argv)
40 char **argv;
41 {
42 	float atof();
43 	int c;
44 
45 	cmdname = argv[0];
46 	while (argc > 1 && *argv[1] == '-') {
47 		switch (c = argv[1][1]) {
48 		case 'T':
49 			if (strcmp(&argv[1][2], "aps") == 0) {
50 				res = 723;
51 				devtype = DEVAPS;
52 			} else if (strcmp(&argv[1][2], "cat") == 0) {
53 				res = 432;
54 				devtype = DEVCAT;
55 			} else if (strcmp(&argv[1][2], "202") == 0) {
56 				res = 972;
57 				devtype = DEV202;
58 			}
59 			break;
60 		case 'c':
61 			crop = 0;
62 			break;
63 		case 'l':
64 			delty = atof(&argv[1][2]);
65 			break;
66 		case 'w':
67 		case 's':	/* set size */
68 			if (argv[1][2] == 0) {
69 				argv++;
70 				argc--;
71 				deltx = atof(&argv[1][0]);
72 			} else
73 				deltx = atof(&argv[1][2]);
74 			if (c == 's')
75 				delty = deltx;
76 			break;
77 		case 'd':
78 			dbg = 1;
79 			break;
80 		}
81 		argc--;
82 		argv++;
83 	}
84 	if (argc <= 1) {
85 		fin = stdin;
86 		getdata();
87 	} else
88 		while (argc-- > 1) {
89 			if ((fin = fopen(*++argv, "r")) == NULL) {
90 				fprintf(stderr, "%s: can't open %s\n", cmdname, *argv);
91 				exit(1);
92 			}
93 			getdata();
94 			fclose(fin);
95 		}
96 	print();
97 	exit(0);
98 }
99 
100 getdata()	/* read the file, collect max, min sizes, etc. */
101 {
102 	char s[100], s1[20], *p;
103 	int x, y, x1, y1, x2, y2, r, c;
104 
105 	while ((c = getc(fin)) != EOF) {
106 		switch (c) {
107 		case 'M':
108 		case 'N':
109 		case 'P':
110 			fscanf(fin, "%d %d", &x, &y);
111 			extreme(x, y);
112 			ctobuf(tolower(c));
113 			xytobuf(x, y);
114 			break;
115 		case 'm':
116 		case 'n':
117 		case 'p':
118 			x = getsi(fin);
119 			y = getsi(fin);
120 			extreme(x, y);
121 			ctobuf(c);
122 			xytobuf(x, y);
123 			break;
124 		case 'L':
125 		case 'B':
126 			fscanf(fin, "%d %d %d %d", &x, &y, &x1, &y1);
127 			extreme(x, y);
128 			extreme(x1, y1);
129 			ctobuf(tolower(c));
130 			xytobuf(x, y);
131 			xytobuf(x1, y1);
132 			break;
133 		case 'l':
134 		case 'b':
135 			x = getsi(fin);
136 			y = getsi(fin);
137 			x1 = getsi(fin);
138 			y1 = getsi(fin);
139 			extreme(x, y);
140 			extreme(x1, y1);
141 			ctobuf(c);
142 			xytobuf(x, y);
143 			xytobuf(x1, y1);
144 			break;
145 		case 'S':
146 			fscanf(fin, "%d %d %d %d", &sxmin, &symin, &sxmax, &symax);
147 			break;	/* BUG -- ignoring this because it overrides -c */
148 			ctobuf('s');
149 			xytobuf(sxmin, symin);
150 			xytobuf(sxmax, symax);
151 			break;
152 		case 's':
153 			sxmin = getsi(fin);
154 			symin = getsi(fin);
155 			sxmax = getsi(fin);
156 			symax = getsi(fin);
157 			break;	/* BUG -- ignoring this because it overrides -c */
158 			ctobuf(c);
159 			xytobuf(sxmin, symin);
160 			xytobuf(sxmax, symax);
161 			break;
162 		case 'T':
163 		case 't':
164 			fgets(s, sizeof s, fin);
165 			for (p = s; *p != '\n'; p++)
166 				;
167 			*p = 0;	/* zap newline */
168 			ctobuf('t');
169 			stobuf(s);
170 			break;
171 		case 'E':
172 		case 'e':
173 			ctobuf('e');
174 			break;
175 		case 'A':
176 			fscanf(fin, "%d %d %d %d %d %d", &x, &y, &x1, &y1, &x2, &y2);
177 			extreme(x, y);	/* should use radius */
178 			ctobuf('a');
179 			xytobuf(x, y);
180 			xytobuf(x1, y1);
181 			xytobuf(x2, y2);
182 			break;
183 		case 'a':
184 			x = getsi(fin);
185 			y = getsi(fin);
186 			x1 = getsi(fin);
187 			y1 = getsi(fin);
188 			x2 = getsi(fin);
189 			y2 = getsi(fin);
190 			extreme(x, y);	/* should use radius */
191 			ctobuf('a');
192 			xytobuf(x, y);
193 			xytobuf(x1, y1);
194 			xytobuf(x2, y2);
195 			break;
196 		case 'C':
197 			fscanf(fin, "%d %d %d", &x, &y, &r);
198 			extreme(x+r, y+r);
199 			extreme(x-r, y-r);
200 			ctobuf('c');
201 			xytobuf(x, y);
202 			xtobuf(r);
203 			break;
204 		case 'c':
205 			x = getsi(fin);
206 			y = getsi(fin);
207 			r = getsi(fin);
208 			extreme(x+r, y+r);
209 			extreme(x-r, y-r);
210 			ctobuf('c');
211 			xytobuf(x, y);
212 			xtobuf(r);
213 			break;
214 		case 'F':
215 		case 'f':
216 			fgets(s, sizeof s, fin);
217 			ctobuf('f');
218 			sscanf(s, "%s", s1);
219 			if (strcmp(s1, "solid") == 0)
220 				c = 's';
221 			else if (strcmp(s1, "dotted") == 0)
222 				c = '.';
223 			else if (strcmp(s1, "longdashed") == 0)
224 				c = '_';
225 			else if (strcmp(s1, "shortdashed") == 0)
226 				c = '-';
227 			else
228 				c = '!';	/* would you believe dotdashed? */
229 			ctobuf(c);
230 			break;
231 		case 'd':
232 		case 'D':
233 			fgets(s, 100, fin);
234 			/* ignore */
235 			break;
236 		default:
237 			break;
238 		}
239 		if (bp >= buf + sizeof buf) {
240 			fprintf(stderr, "pltroff: input too big to handle\n");
241 			exit(1);
242 		}
243 	}
244 	*bp = 0;
245 }
246 
247 extreme(x, y)	/* record max and min x and y values */
248 {
249 	if (x > xmax)
250 		xmax = x;
251 	if (y > ymax)
252 		ymax = y;
253 	if (x < xmin)
254 		xmin = x;
255 	if (y < ymin)
256 		ymin = y;
257 }
258 
259 ctobuf(c)
260 {
261 	*bp++ = c;
262 }
263 
264 stobuf(s)
265 char *s;
266 {
267 	while (*bp++ = *s++)
268 		;
269 }
270 
271 xytobuf(x, y)
272 {
273 	*bp++ = x >> 8;
274 	*bp++ = x & 0377;
275 	*bp++ = y >> 8;
276 	*bp++ = y & 0377;
277 }
278 
279 xtobuf(x)
280 {
281 	*bp++ = x >> 8;
282 	*bp++ = x & 0377;
283 }
284 
285 print()
286 {
287 	char s[100], *p;
288 	int x, y, x1, y1, x2, y2, r, c;
289 
290 	openpl("\n");	/* outputs .PS\n */
291 	for (bp = buf; *bp; ) {
292 		switch (c = *bp++) {
293 		case 'm':
294 			x = getbuf();
295 			y = getbuf();
296 			move(x, y);
297 			break;
298 		case 'f':	/* line mode */
299 			linetype = *bp++;
300 			break;
301 		case 'l':
302 			x = getbuf();
303 			y = getbuf();
304 			x1 = getbuf();
305 			y1 = getbuf();
306 			if (linetype == 's')
307 				line(x, y, x1, y1);
308 			else
309 				dotline(x, y, x1, y1, linetype);
310 			break;
311 		case 't':
312 			for (p = s; *p++ = *bp++; )
313 				;
314 			label(s, 'L', 0);
315 			break;
316 		case 'e':
317 			erase();
318 			break;
319 		case 'p':
320 			x = getbuf();
321 			y = getbuf();
322 			point(x, y);
323 			break;
324 		case 'n':
325 			x = getbuf();
326 			y = getbuf();
327 			cont(x, y);
328 			break;
329 		case 's':
330 			x = getbuf();
331 			y = getbuf();
332 			x1 = getbuf();
333 			y1 = getbuf();
334 			space(x, y, x1, y1);
335 			break;
336 		case 'a':
337 			x = getbuf();
338 			y = getbuf();
339 			x1 = getbuf();
340 			y1 = getbuf();
341 			x2 = getbuf();
342 			y2 = getbuf();
343 			arc(x, y, x1, y1, x2, y2);
344 			break;
345 		case 'c':
346 			x = getbuf();
347 			y = getbuf();
348 			r = getbuf();
349 			circle(x, y, r);
350 			break;
351 		case 'b':
352 			x = getbuf();
353 			y = getbuf();
354 			x1 = getbuf();
355 			y1 = getbuf();
356 			box(x, y, x1, y1);
357 			break;
358 		default:
359 			break;
360 		}
361 	}
362 	closepl();
363 }
364 
365 dotline(x0, y0, x1, y1, type) /* dotted or dashed line */
366 int x0, y0, x1, y1;
367 int type;
368 {
369 	int prevval = 10;
370 	int i, numdots;
371 	double a, b, sqrt(), dx, dy;
372 
373 	dx = x1 - x0;
374 	dy = y1 - y0;
375 	if (type == '.') {
376 		numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
377 		for (i = 0; i <= numdots; i++) {
378 			a = (float) i / (float) numdots;
379 			move(x0 + (int)(a * dx), y0 + (int)(a * dy));
380 			dot();
381 		}
382 	} else {	/* all others */
383 		double d, dashsize, spacesize;
384 		d = sqrt(dx*dx + dy*dy) + 0.5;
385 		if (d <= 2 * prevval) {
386 			line(x0, y0, x1, y1);
387 			return;
388 		}
389 		numdots = d / (2 * prevval - 1) + 1;	/* ceiling */
390 		dashsize = prevval;
391 		spacesize = (d - numdots * dashsize) / (numdots - 1);
392 		for (i = 0; i < numdots-1; i++) {
393 			a = i * (dashsize + spacesize) / d;
394 			b = a + dashsize / d;
395 			line(x0 + (int)(a*dx), y0 + (int)(a*dy), x0 + (int)(b*dx), y0 + (int)(b*dy));
396 			a = b;
397 			b = a + spacesize / d;
398 			move(x0 + (int)(a*dx), y0 + (int)(a*dy));
399 		}
400 		line(x0 + (int)(b * dx), y0 + (int)(b * dy), x1, y1);
401 	}
402 }
403 
404 getbuf()
405 {
406 	int n;
407 
408 	n = *bp++ << 8;
409 	n |= (*bp++ & 0377);
410 	return(n);
411 }
412 
413 getsi(fin)  FILE *fin; {	/* get an integer stored in 2 ascii bytes. */
414 	short a, b;
415 	if((b = getc(fin)) == EOF)
416 		return(EOF);
417 	if((a = getc(fin)) == EOF)
418 		return(EOF);
419 	a = a<<8;
420 	return(a|b);
421 }
422