1 /*
2    Copyright (c) 1991 - 1994 Heinz W. Werntges.  All rights reserved.
3    Distributed by Free Software Foundation, Inc.
4 
5 This file is part of HP2xx.
6 
7 HP2xx is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
9 to anyone for the consequences of using it or for whether it serves any
10 particular purpose or works at all, unless he says so in writing.  Refer
11 to the GNU General Public License, Version 2 or later, for full details.
12 
13 Everyone is granted permission to copy, modify and redistribute
14 HP2xx, but only under the conditions described in the GNU General Public
15 License.  A copy of this license is supposed to have been
16 given to you along with HP2xx so you can know your rights and
17 responsibilities.  It should be in a file named COPYING.  Among other
18 things, the copyright notice and this notice must be preserved on all
19 copies.
20 
21 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 */
23 
24 /** std_main.c: Traditional user interface for hp2xx
25  **
26  ** 94/02/14  V 1.00  HWW  Derived from hp2xx.c
27  **/
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #ifdef WIN32
34 #include <fcntl.h>
35 #include <io.h>
36 #endif				/* WIN32 */
37 #include "bresnham.h"
38 #include "pendef.h"
39 #include "hp2xx.h"
40 #include "getopt.h"
41 
42 
43 extern mode_list ModeList[];
44 
45 static short Logfile_flag = FALSE;
46 
47 
48 
49 
Eprintf(const char * fmt,...)50 void Eprintf(const char *fmt, ...)
51 {
52 	va_list ap;
53 
54 	va_start(ap, fmt);
55 	vfprintf(stderr, fmt, ap);
56 	va_end(ap);
57 }
58 
59 
60 
PError(const char * msg)61 void PError(const char *msg)
62 {
63 	perror(msg);
64 }
65 
66 
67 
68 
SilentWait(void)69 void SilentWait(void)
70 {
71 	char dummy[80];
72 #ifdef UNIX
73 	FILE *tty;
74 #endif
75 /**
76  ** Get anything typed including '\n' if stderr does NOT go to a file
77  ** or else the user may be invisibly prompted.
78  **
79  ** According to a suggestion from A. Bagge, in UNIX pipe mode stdin
80  ** will be replaced by /dev/tty.
81  **/
82 	if (!Logfile_flag) {
83 #ifdef UNIX
84 		if ((tty = fopen("/dev/tty", "r")) != NULL) {
85 			(void) fgets(dummy, 80, tty);
86 			fclose(tty);
87 		} else
88 #endif
89 			(void) fgets(dummy, 80, stdin);
90 	}
91 }
92 
93 
94 
95 
NormalWait(void)96 void NormalWait(void)
97 {
98 #ifdef	UNIX
99 	if (getenv("TERM") == (char *) NULL)
100 		return;
101 #endif
102 	Eprintf("\nPress <Return> to continue ...\n");
103 	SilentWait();
104 }
105 
106 
107 
108 
action_oldstyle(GEN_PAR * pg,IN_PAR * pi,OUT_PAR * po)109 void action_oldstyle(GEN_PAR * pg, IN_PAR * pi, OUT_PAR * po)
110 {
111 	int err;
112 	char savedname[100];
113 /*int counter=-1;*/
114 	char thepage[4];
115 
116 
117 	if (!pg->quiet)
118 		Send_version();
119 
120 	strcpy(savedname, po->outfile);
121 	for (;;) {
122   /**
123    ** Phase 1: HP-GL --> TMP file data
124    **/
125 		err = HPGL_to_TMP(pg, pi);
126 		if (err) {
127 /*	po->outfile=realloc(po->outfile,2*sizeof(char));*/
128 			strcpy(po->outfile, "");
129 			cleanup_i(pi);
130 			cleanup_g(pg);
131 			cleanup_o(po);
132 			return;
133 		}
134 		if (strcmp(pg->mode, "pre")) {
135 			po->pagecount++;
136 			if (po->outfile != "-" && po->pagecount > 0) {
137 				sprintf(thepage, "%d", po->pagecount);
138 				strcpy(po->outfile, savedname);
139 				if (strstr(po->outfile, pg->mode))
140 					strcpy(strstr
141 					       (po->outfile, pg->mode),
142 					       thepage);
143 				else
144 					strcat(po->outfile, thepage);
145 				strcat(po->outfile, ".");
146 				strcat(po->outfile, pg->mode);
147 			}
148 		}
149   /**
150    ** Phase 2: TMP file re-scaling
151    **/
152 		adjust_input_transform(pg, pi, po);
153 
154   /**
155    ** Phase 3: (a) TMP file --> Vector formats
156    **/
157 		err = TMP_to_VEC(pg, po);
158 		if (err == 0)
159 			continue;
160 		if (err == ERROR) {
161 			cleanup(pg, pi, po);
162 			return;
163 		}
164 
165   /**
166    ** Phase 3: (b) TMP file --> Raster image
167    **/
168 		if (TMP_to_BUF(pg, po)) {
169 			cleanup(pg, pi, po);
170 			return;
171 		}
172 
173   /**
174    ** Phase 3: (c) Raster image --> output formats
175    **/
176 		err = BUF_to_RAS(pg, po);
177 
178 		if (err == 1)
179 			Eprintf("%s: Not implemented!\n", pg->mode);
180 		cleanup_g(pg);
181 		cleanup_o(po);
182 	}
183 
184 }
185 
186 
187 static void
process_opts(int argc,char * argv[],const char * shortopts,struct option longopts[],GEN_PAR * pg,IN_PAR * pi,OUT_PAR * po)188 process_opts(int argc, char *argv[],
189 	     const char *shortopts, struct option longopts[],
190 	     GEN_PAR * pg, IN_PAR * pi, OUT_PAR * po)
191 {
192 	int c, i, j, longind;
193 	char *p, cdummy;
194 
195 	while ((c =
196 		getopt_long(argc, argv, shortopts, longopts,
197 			    &longind)) != EOF)
198 		switch (c) {	/* Easy addition of options ... */
199 		case 'a':
200 			pi->aspectfactor = atof(optarg);
201 			if (pi->aspectfactor <= 0.0) {
202 				Eprintf("Aspect factor: %g illegal\n",
203 					pi->aspectfactor);
204 				exit(ERROR);
205 			}
206 			break;
207 
208 		case 'c':
209 			i = (int) strlen(optarg);
210 			if ((i < 1) || (i > 8)) {
211 				Eprintf("Invalid pencolor string: %s\n",
212 					optarg);
213 				exit(ERROR);
214 			}
215 			for (j = 1, p = optarg; j <= i; j++, p++) {
216 				switch (*p - '0') {
217 				case xxBackground:
218 					pt.color[j] = xxBackground;
219 					break;
220 				case xxForeground:
221 					pt.color[j] = xxForeground;
222 					break;
223 				case xxRed:
224 					pt.color[j] = xxRed;
225 					break;
226 				case xxGreen:
227 					pt.color[j] = xxGreen;
228 					break;
229 				case xxBlue:
230 					pt.color[j] = xxBlue;
231 					break;
232 				case xxCyan:
233 					pt.color[j] = xxCyan;
234 					break;
235 				case xxMagenta:
236 					pt.color[j] = xxMagenta;
237 					break;
238 				case xxYellow:
239 					pt.color[j] = xxYellow;
240 					break;
241 				default:
242 					Eprintf
243 					    ("Invalid color of pen %d: %c\n",
244 					     j, *p);
245 					exit(ERROR);
246 				}
247 				if (pt.color[j] != xxBackground &&
248 				    pt.color[j] != xxForeground)
249 					pg->is_color = TRUE;
250 			}
251 			pi->hwcolor = TRUE;
252 			break;
253 
254 		case 'C':
255 			pi->center_mode = TRUE;
256 			break;
257 
258 		case 'd':
259 			switch (po->dpi_x = atoi(optarg)) {
260 			case 75:
261 				break;
262 			case 100:
263 			case 150:
264 			case 300:
265 			case 600:
266 				if ((!pg->quiet)
267 				    && (strcmp(pg->mode, "pcl") == 0)
268 				    && po->specials == 0)
269 					Eprintf
270 					    ("Warning: DPI setting is no PCL level 3 feature!\n");
271 				break;
272 			default:
273 				if ((!pg->quiet)
274 				    && (strcmp(pg->mode, "pcl") == 0))
275 					Eprintf
276 					    ("Warning: DPI value %d is invalid for PCL mode\n",
277 					     po->dpi_x);
278 				break;
279 			}
280 			break;
281 
282 		case 'D':
283 			po->dpi_y = atoi(optarg);
284 			if ((!pg->quiet) && strcmp(pg->mode, "pcl") == 0
285 			    && po->specials == 0)
286 				Eprintf("Warning: %s\n",
287 					"Different DPI for x & y is invalid for PCL mode");
288 			break;
289 
290 		case 'e':
291 			pg->extraclip = atoi(optarg);
292 			break;
293 
294 		case 'F':
295 			po->formfeed = TRUE;
296 			break;
297 
298 		case 'f':
299 			po->outfile = optarg;
300 			break;
301 
302 		case 'h':
303 			if (!strncmp(optarg, "elp", 3)) {
304 				usage_msg(pg, pi, po);
305 				exit(ERROR);
306 			}
307 			pi->height = atof(optarg);
308 			if (pi->height < 0.1)
309 				Eprintf("Warning: Small height: %g mm\n",
310 					pi->height);
311 			if (pi->height > 300.0)
312 				Eprintf("Warning: Huge  height: %g mm\n",
313 					pi->height);
314 			break;
315 
316 		case 'i':
317 			po->init_p = TRUE;
318 			break;
319 
320 		case 'I':
321 			po->init_p = TRUE;
322 			po->init_p3gui = TRUE;
323 			break;
324 
325 		case 'l':
326 			pg->logfile = optarg;
327 			if (freopen(pg->logfile, "w", stderr) == NULL) {
328 				PError("Cannot open log file");
329 				Eprintf("Error redirecting stderr\n");
330 				Eprintf
331 				    ("Continuing with output to stderr\n");
332 			} else
333 				Logfile_flag = TRUE;
334 			break;
335 /*MJR These are NOT sanity checked, GIGO*/
336 		case 'z':
337 			po->zengage = atof(optarg);
338 			break;
339 		case 'Z':
340 			po->zretract = atof(optarg);
341 			break;
342 
343 		case 'M':
344 			pg->mapzero = atof(optarg);
345 			if (pg->mapzero < 0 || pg->mapzero > 255)
346 				pg->mapzero = -1;
347 			break;
348 
349 		case 'm':
350 			pg->mode = optarg;
351 			for (i = 0; ModeList[i].mode != XX_TERM; i++)
352 				if (strcmp(ModeList[i].modestr, pg->mode)
353 				    == 0)
354 					break;
355 			if (ModeList[i].mode == XX_TERM) {
356 				Eprintf("'%s': unknown mode!\n", pg->mode);
357 				Eprintf("Supported are:\n\t");
358 				print_supported_modes();
359 				Send_Copyright();
360 			}
361 			break;
362 
363 		case 'n':
364 			pg->nofill = TRUE;
365 			break;
366 
367 		case 'N':
368 			pg->no_ps = TRUE;
369 			break;
370 
371 		case 'o':
372 			pi->xoff = atof(optarg);
373 			break;
374 
375 		case 'O':
376 			pi->yoff = atof(optarg);
377 			break;
378 
379 		case 'p':
380 			i = (int) strlen(optarg);
381 			if ((i < 1) || (i > 8)) {
382 				Eprintf("Invalid pensize string: %s\n",
383 					optarg);
384 				exit(ERROR);
385 			}
386 			for (j = 1, p = optarg; j <= i; j++, p++) {
387 				if ((*p < '0') || (*p > '9')) {
388 					if ((*p < 'A') || (*p > 'Z')) {
389 						Eprintf
390 						    ("Invalid size of pen %d: %c\n",
391 						     j, *p);
392 						exit(ERROR);
393 					} else {
394 						pt.width[j] =
395 						    1 + (*p - 'A') / 10.0;
396 						if (pg->maxpensize <
397 						    pt.width[j])
398 							pg->maxpensize =
399 							    pt.width[j];
400 					}
401 				} else {
402 					pt.width[j] = (*p - '0') / 10.0;
403 					if (pg->maxpensize < pt.width[j])
404 						pg->maxpensize =
405 						    pt.width[j];
406 				}
407 			}
408 			pi->hwsize = TRUE;
409 			break;
410 
411 		case 'P':
412 			if (*optarg == ':') {
413 				pi->first_page = 0;
414 				optarg++;
415 				if (sscanf(optarg, "%d", &pi->last_page) !=
416 				    1)
417 					pi->last_page = 0;
418 			} else
419 				switch (sscanf(optarg, "%d%c%d",
420 					       &pi->first_page, &cdummy,
421 					       &pi->last_page)) {
422 				case 1:
423 					pi->last_page = pi->first_page;
424 					break;
425 
426 				case 2:
427 					if (cdummy == ':') {
428 						pi->last_page = 0;
429 						break;
430 					}
431 					/* not ':' Syntax error -- drop through */
432 				case 3:
433 					if (cdummy == ':')
434 						break;
435 					/* not ':' Syntax error -- drop through */
436 				default:
437 					Eprintf("Illegal page range.\n");
438 					usage_msg(pg, pi, po);
439 					exit(ERROR);
440 				}
441 			break;
442 
443 		case 'q':
444 			pg->quiet = TRUE;
445 			break;
446 
447 		case 'r':
448 			pi->rotation = atof(optarg);
449 			break;
450 
451 		case 'S':
452 			po->specials = atoi(optarg);
453 			break;
454 
455 		case 's':
456 			pg->swapfile = optarg;
457 			break;
458 
459 		case 't':
460 			pi->truesize = TRUE;
461 			break;
462 
463 		case 'V':
464 			po->vga_mode = (Byte) atoi(optarg);
465 			break;
466 
467 		case 'w':
468 			pi->width = atof(optarg);
469 			if (pi->width < 0.1)
470 				Eprintf("Warning: Small width: %g mm\n",
471 					pi->width);
472 			if (pi->width > 300.0)
473 				Eprintf("Warning: Huge  width: %g mm\n",
474 					pi->width);
475 			break;
476 
477 		case 'v':
478 			Send_version();
479 			exit(NOERROR);
480 
481 		case 'x':
482 			pi->x0 = atof(optarg);
483 			break;
484 
485 		case 'X':
486 			pi->x1 = atof(optarg);
487 			break;
488 
489 		case 'y':
490 			pi->y0 = atof(optarg);
491 			break;
492 
493 		case 'Y':
494 			pi->y1 = atof(optarg);
495 			break;
496 		case 'H':
497 			pi->hwlimit.y = atof(optarg);
498 			break;
499 		case 'W':
500 			pi->hwlimit.x = atof(optarg);
501 			break;
502 		case '?':
503 		default:
504 			usage_msg(pg, pi, po);
505 			exit(ERROR);
506 		}
507 }
508 
509 
510 
511 /**
512  ** main(): Process command line & call action routine
513  **/
514 
main(int argc,char * argv[])515 int main(int argc, char *argv[])
516 {
517 	GEN_PAR Pg;
518 	IN_PAR Pi;
519 	OUT_PAR Po;
520 	int i;
521 	char outname[128] = "";
522 
523 	char *shortopts =
524 	    "a:c:d:D:e:f:h:l:m:M:o:O:p:P:r:s:S:V:w:x:X:y:Y:z:Z:CFH:W:inqtvNI?";
525 	struct option longopts[] = {
526 		{"mode", 1, NULL, 'm'},
527 		{"pencolors", 1, NULL, 'c'},
528 		{"pensizes", 1, NULL, 'p'},
529 		{"pages", 1, NULL, 'P'},
530 		{"quiet", 0, NULL, 'q'},
531 		{"nofill", 0, NULL, 'n'},
532 		{"no_ps", 0, NULL, 'N'},
533 		{"mapzero", 1, NULL, 'M'},
534 
535 		{"DPI", 1, NULL, 'd'},
536 		{"DPI_x", 1, NULL, 'd'},
537 		{"DPI_y", 1, NULL, 'D'},
538 		{"extraclip", 1, NULL, 'e'},
539 
540 		{"PCL_formfeed", 0, NULL, 'F'},
541 		{"PCL_init", 0, NULL, 'i'},
542 		{"PCL_Deskjet", 1, NULL, 'S'},
543 		{"PCL_PCL3GUI", 0, NULL, 'I'},
544 
545 		{"outfile", 1, NULL, 'f'},
546 		{"logfile", 1, NULL, 'l'},
547 		{"swapfile", 1, NULL, 's'},
548 
549 		{"aspectfactor", 1, NULL, 'a'},
550 		{"height", 1, NULL, 'h'},
551 		{"width", 1, NULL, 'w'},
552 		{"truesize", 0, NULL, 't'},
553 
554 		{"x0", 1, NULL, 'x'},
555 		{"x1", 1, NULL, 'X'},
556 		{"y0", 1, NULL, 'y'},
557 		{"y1", 1, NULL, 'Y'},
558 		{"zengage", 1, NULL, 'z'},
559 		{"zretract", 1, NULL, 'Z'},
560 
561 		{"xoffset", 1, NULL, 'o'},
562 		{"yoffset", 1, NULL, 'O'},
563 		{"center", 0, NULL, 'C'},
564 
565 #ifdef DOS
566 		{"VGAmodebyte", 1, NULL, 'V'},
567 #endif
568 		{"help", 0, NULL, '?'},
569 		{"version", 0, NULL, 'v'},
570 		{NULL, 0, NULL, '\0'}
571 	};
572 
573 
574 	preset_par(&Pg, &Pi, &Po);
575 	if (argc == 1) {
576 		usage_msg(&Pg, &Pi, &Po);
577 		exit(ERROR);
578 	}
579 #ifdef WIN32
580 	/* set stdin and stdout to binary mode: */
581 	_setmode(_fileno(stdin), _O_BINARY);
582 	_setmode(_fileno(stdout), _O_BINARY);
583 #endif				/* WIN32 */
584 	process_opts(argc, argv, shortopts, longopts, &Pg, &Pi, &Po);
585 
586 /**
587  ** Determine internal mode code
588  **/
589 
590 	for (i = 0; ModeList[i].mode != XX_TERM; i++)
591 /*	if (strncmp(Pg.mode, ModeList[i].modestr,
592 		strlen(ModeList[i].modestr)) == 0)*/
593 		if (strcmp(Pg.mode, ModeList[i].modestr) == 0) {
594 			Pg.xx_mode = ModeList[i].mode;
595 			break;
596 		}
597 /**
598  ** Place consistency checks & adjustments here if you like
599  **/
600 
601 	if (Po.dpi_y == 0)
602 		Po.dpi_y = Po.dpi_x;
603 
604 	Po.pagecount = -1;
605 	if (strlen(Po.outfile) > 0)
606 		strcpy(outname, Po.outfile);	/* store fixed outfile name if present */
607 	else {
608 		Po.outfile = malloc(1 * sizeof(char));
609 		strcpy(Po.outfile, "");
610 	}
611 /**
612  ** Action loop over all input files
613  **/
614 
615 	if (optind == argc) {	/* No  filename: use stdin        */
616 		Pi.in_file = "-";
617 		autoset_outfile_name(Pg.mode, Pi.in_file, &Po.outfile);
618 		action_oldstyle(&Pg, &Pi, &Po);
619 	} else
620 		for (; optind < argc; optind++) {	/* Multiple-input file handling: */
621 			Pi.in_file = argv[optind];
622 			/* if output file name given on commandline, use it for all files */
623 			if (strlen(outname) > 0) {
624 				strcpy(Po.outfile, outname);
625 			} else {
626 				Po.pagecount = -1;	/* reset page counter for new file */
627 			}
628 			autoset_outfile_name(Pg.mode, Pi.in_file,
629 					     &Po.outfile);
630 			action_oldstyle(&Pg, &Pi, &Po);
631 			reset_par(&Pi);
632 		}
633 
634 	cleanup(&Pg, &Pi, &Po);
635 	if (!strcmp(Pg.mode, "pre"))
636 		free(Po.outfile);
637 	if (*Pg.logfile)
638 		fclose(stderr);
639 	return NOERROR;
640 }
641