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