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