1 /*
2 * Main entry for HTMLDOC, a HTML document processing program.
3 *
4 * Copyright 2011-2020 by Michael R Sweet.
5 * Copyright 1997-2010 by Easy Software Products. All rights reserved.
6 *
7 * This program is free software. Distribution and use rights are outlined in
8 * the file "COPYING".
9 */
10
11 /*
12 * Include necessary headers.
13 */
14
15 #define _HTMLDOC_CXX_
16 #include "htmldoc.h"
17 #include "markdown.h"
18 #include "http.h"
19 #include <ctype.h>
20 #include <fcntl.h>
21
22 #ifdef HAVE_LOCALE_H
23 # include <locale.h>
24 #endif // HAVE_LOCALE_H
25
26 #ifdef WIN32
27 # include <direct.h>
28 # include <io.h>
29 #else
30 # include <signal.h>
31 # include <unistd.h>
32 # include <sys/time.h>
33 #endif // WIN32
34
35 #ifdef __APPLE__
36 # include <libproc.h>
37 #endif // __APPLE__
38
39 #ifdef __EMX__
40 extern "C" {
41 const char *__XOS2RedirRoot(const char *);
42 }
43 #endif
44
45
46 /*
47 * Local types...
48 */
49
50 typedef int (*exportfunc_t)(tree_t *, tree_t *);
51
52
53 /*
54 * Local functions...
55 */
56
57 static int compare_strings(const char *s, const char *t, int tmin);
58 static double get_seconds(void);
59 static int load_book(const char *filename, tree_t **document,
60 exportfunc_t *exportfunc, int set_nolocal = 0);
61 static void parse_options(const char *line, exportfunc_t *exportfunc);
62 static const char *prefs_getrc(void);
63 static int read_file(const char *filename, tree_t **document,
64 const char *path);
65 static void set_permissions(const char *p);
66 #ifndef WIN32
67 extern "C" {
68 static void term_handler(int signum);
69 }
70 #endif // !WIN32
71 static void usage(const char *arg = NULL);
72
73
74 /*
75 * 'main()' - Main entry for HTMLDOC.
76 */
77
78 int
main(int argc,char * argv[])79 main(int argc, /* I - Number of command-line arguments */
80 char *argv[]) /* I - Command-line arguments */
81 {
82 int i, j; /* Looping vars */
83 tree_t *document, /* Master HTML document */
84 *file, /* HTML document file */
85 *toc; /* Table of contents */
86 exportfunc_t exportfunc; /* Export function */
87 const char *extension; /* Extension of output filename */
88 double fontsize, /* Base font size */
89 fontspacing; /* Base font spacing */
90 int num_files; /* Number of files provided on the command-line */
91 double start_time, /* Start time */
92 load_time, /* Load time */
93 end_time; /* End time */
94 const char *debug; /* HTMLDOC_DEBUG environment variable */
95
96
97 start_time = get_seconds();
98
99 #ifdef __APPLE__
100 /*
101 * OSX passes an extra command-line option when run from the Finder.
102 * If the first command-line argument is "-psn..." then skip it...
103 */
104
105 if (argc > 1 && strncmp(argv[1], "-psn", 4) == 0)
106 {
107 argv ++;
108 argc --;
109 }
110 #endif // __APPLE__
111
112 /*
113 * Localize as needed...
114 */
115
116 #ifdef HAVE_LOCALE_H
117 setlocale(LC_TIME, "");
118 #endif // HAVE_LOCALE_H
119
120 /*
121 * Catch CTRL-C and term signals...
122 */
123
124 #ifdef WIN32
125 #else
126 signal(SIGTERM, term_handler);
127 #endif // WIN32
128
129 /*
130 * Set the location of data and help files...
131 */
132
133 prefs_set_paths();
134
135 /*
136 * Check if we are being executed as a CGI program...
137 *
138 * Note: We can't short-circuit this test to include a check for
139 * PATH_INFO since that could lead to a remote execution hole.
140 * Instead, we'll display an error message later if we can't find
141 * a PATH_INFO variable and advise the administrator on how to
142 * correct the problem...
143 */
144
145 if (!getenv("HTMLDOC_NOCGI") && getenv("GATEWAY_INTERFACE") &&
146 getenv("SERVER_NAME") && getenv("SERVER_SOFTWARE"))
147 {
148 const char *path_translated; // PATH_TRANSLATED env var
149 char bookfile[1024]; // Book filename
150
151
152 // CGI mode implies the following options:
153 //
154 // --no-localfiles
155 // --webpage
156 // -t pdf
157 // -f -
158 //
159 // Additional args cannot be provided on the command-line, however
160 // we load directory-specific options from the ".book" file in the
161 // current web server directory...
162
163 CGIMode = 1;
164 TocLevels = 0;
165 TitlePage = 0;
166 OutputPath[0] = '\0';
167 OutputType = OUTPUT_WEBPAGES;
168 document = NULL;
169 exportfunc = (exportfunc_t)pspdf_export;
170 PSLevel = 0;
171 PDFVersion = 14;
172 PDFPageMode = PDF_DOCUMENT;
173 PDFFirstPage = PDF_PAGE_1;
174
175 file_cookies(getenv("HTTP_COOKIE"));
176 file_referer(getenv("HTTP_REFERER"));
177
178 progress_error(HD_ERROR_NONE, "INFO: HTMLDOC " SVERSION " starting in CGI mode.");
179 #ifdef WIN32
180 progress_error(HD_ERROR_NONE, "INFO: TEMP is \"%s\"", getenv("TEMP"));
181 #else
182 progress_error(HD_ERROR_NONE, "INFO: TMPDIR is \"%s\"", getenv("TMPDIR"));
183 #endif // WIN32
184
185 argc = 1;
186
187 // Look for a book file in the following order:
188 //
189 // $PATH_TRANSLATED.book
190 // `dirname $PATH_TRANSLATED`/.book
191 // .book
192 //
193 // If we find one, use it...
194 if ((path_translated = getenv("PATH_TRANSLATED")) != NULL)
195 {
196 // Try $PATH_TRANSLATED.book...
197 snprintf(bookfile, sizeof(bookfile), "%s.book", path_translated);
198 if (access(bookfile, 0))
199 {
200 // Not found, try `dirname $PATH_TRANSLATED`/.book
201 snprintf(bookfile, sizeof(bookfile), "%s/.book",
202 file_directory(path_translated));
203 if (access(bookfile, 0))
204 strlcpy(bookfile, ".book", sizeof(bookfile));
205 }
206 }
207 else
208 strlcpy(bookfile, ".book", sizeof(bookfile));
209
210 if (!access(bookfile, 0))
211 load_book(bookfile, &document, &exportfunc, 1);
212 else
213 file_nolocal();
214 }
215 else
216 {
217 /*
218 * Default to producing HTML files.
219 */
220
221 document = NULL;
222 exportfunc = (exportfunc_t)html_export;
223
224 /*
225 * Load preferences...
226 */
227
228 prefs_load();
229 }
230
231 /*
232 * Parse command-line options...
233 */
234
235 fontsize = 11.0f;
236 fontspacing = 1.2f;
237 num_files = 0;
238 Errors = 0;
239
240 for (i = 1; i < argc; i ++)
241 {
242 #ifdef DEBUG
243 printf("argv[%d] = \"%s\"\n", i, argv[i]);
244 #endif // DEBUG
245
246 if (compare_strings(argv[i], "--batch", 4) == 0)
247 {
248 i ++;
249 if (i < argc)
250 {
251 num_files ++;
252 load_book(argv[i], &document, &exportfunc);
253 }
254 else
255 usage(argv[i - 1]);
256 }
257 else if (compare_strings(argv[i], "--bodycolor", 7) == 0)
258 {
259 i ++;
260 if (i < argc)
261 strlcpy((char *)BodyColor, argv[i], sizeof(BodyColor));
262 else
263 usage(argv[i - 1]);
264 }
265 else if (compare_strings(argv[i], "--bodyfont", 7) == 0 ||
266 compare_strings(argv[i], "--textfont", 7) == 0)
267 {
268 i ++;
269 if (i < argc)
270 {
271 if (!strcasecmp(argv[i], "monospace"))
272 _htmlBodyFont = TYPE_MONOSPACE;
273 else if (!strcasecmp(argv[i], "serif"))
274 _htmlBodyFont = TYPE_SERIF;
275 else if (!strcasecmp(argv[i], "sans-serif") ||
276 !strcasecmp(argv[i], "sans"))
277 _htmlBodyFont = TYPE_SANS_SERIF;
278 else if (!strcasecmp(argv[i], "courier"))
279 _htmlBodyFont = TYPE_COURIER;
280 else if (!strcasecmp(argv[i], "times"))
281 _htmlBodyFont = TYPE_TIMES;
282 else if (!strcasecmp(argv[i], "helvetica") ||
283 !strcasecmp(argv[i], "arial"))
284 _htmlBodyFont = TYPE_HELVETICA;
285 }
286 else
287 usage(argv[i - 1]);
288 }
289 else if (compare_strings(argv[i], "--bodyimage", 7) == 0)
290 {
291 i ++;
292 if (i < argc)
293 strlcpy((char *)BodyImage, argv[i], sizeof(BodyImage));
294 else
295 usage(argv[i - 1]);
296 }
297 else if (compare_strings(argv[i], "--book", 5) == 0)
298 OutputType = OUTPUT_BOOK;
299 else if (compare_strings(argv[i], "--bottom", 5) == 0)
300 {
301 i ++;
302 if (i < argc)
303 PageBottom = get_measurement(argv[i]);
304 else
305 usage(argv[i - 1]);
306 }
307 else if (compare_strings(argv[i], "--browserwidth", 4) == 0)
308 {
309 i ++;
310 if (i < argc)
311 {
312 _htmlBrowserWidth = atof(argv[i]);
313
314 if (_htmlBrowserWidth < 1.0f)
315 {
316 progress_error(HD_ERROR_INTERNAL_ERROR, "Bad browser width \"%s\"!",
317 argv[i]);
318 usage();
319 }
320 }
321 else
322 usage(argv[i - 1]);
323 }
324 else if (compare_strings(argv[i], "--charset", 4) == 0)
325 {
326 i ++;
327 if (i < argc)
328 htmlSetCharSet(argv[i]);
329 else
330 usage(argv[i - 1]);
331 }
332 else if (compare_strings(argv[i], "--color", 5) == 0)
333 {
334 OutputColor = 1;
335 _htmlGrayscale = 0;
336 }
337 else if (compare_strings(argv[i], "--compression", 5) == 0 ||
338 strncmp(argv[i], "--compression=", 14) == 0)
339 {
340 if (strlen(argv[i]) > 14 && PDFVersion >= 12)
341 Compression = atoi(argv[i] + 14);
342 else if (PDFVersion >= 12)
343 Compression = 1;
344 }
345 else if (compare_strings(argv[i], "--continuous", 5) == 0)
346 {
347 TocLevels = 0;
348 TitlePage = 0;
349 OutputType = OUTPUT_CONTINUOUS;
350 PDFPageMode = PDF_DOCUMENT;
351 PDFFirstPage = PDF_PAGE_1;
352 }
353 else if (compare_strings(argv[i], "--cookies", 5) == 0)
354 {
355 i ++;
356 if (i < argc)
357 file_cookies(argv[i]);
358 else
359 usage(argv[i - 1]);
360 }
361 else if (compare_strings(argv[i], "--datadir", 4) == 0)
362 {
363 i ++;
364 if (i < argc)
365 _htmlData = argv[i];
366 else
367 usage(argv[i - 1]);
368 }
369 #if defined(HAVE_LIBFLTK) && !WIN32
370 else if (compare_strings(argv[i], "-display", 3) == 0 ||
371 compare_strings(argv[i], "--display", 4) == 0)
372 {
373 // The X standard requires support for the -display option, but
374 // we also support the GNU standard --display...
375 i ++;
376 if (i < argc)
377 Fl::display(argv[i]);
378 else
379 usage(argv[i - 1]);
380 }
381 #endif // HAVE_LIBFLTK && !WIN32
382 else if (compare_strings(argv[i], "--duplex", 4) == 0)
383 PageDuplex = 1;
384 else if (compare_strings(argv[i], "--effectduration", 4) == 0)
385 {
386 i ++;
387 if (i < argc)
388 {
389 PDFEffectDuration = atof(argv[i]);
390
391 if (PDFEffectDuration < 0.0f)
392 {
393 progress_error(HD_ERROR_INTERNAL_ERROR, "Bad effect duration \"%s\"!",
394 argv[i]);
395 usage();
396 }
397 }
398 else
399 usage(argv[i - 1]);
400 }
401 else if (compare_strings(argv[i], "--embedfonts", 4) == 0)
402 EmbedFonts = 1;
403 else if (compare_strings(argv[i], "--encryption", 4) == 0)
404 Encryption = 1;
405 else if (compare_strings(argv[i], "--firstpage", 4) == 0)
406 {
407 i ++;
408 if (i >= argc)
409 usage(argv[i - 1]);
410
411 for (j = 0; j < (int)(sizeof(PDFPages) / sizeof(PDFPages[0])); j ++)
412 if (strcasecmp(argv[i], PDFPages[j]) == 0)
413 {
414 PDFFirstPage = j;
415 break;
416 }
417 }
418 else if (compare_strings(argv[i], "--fontsize", 8) == 0)
419 {
420 i ++;
421 if (i < argc)
422 {
423 fontsize = atof(argv[i]);
424
425 if (fontsize < 4.0f)
426 fontsize = 4.0f;
427 else if (fontsize > 24.0f)
428 fontsize = 24.0f;
429
430 htmlSetBaseSize(fontsize, fontspacing);
431 }
432 else
433 usage(argv[i - 1]);
434 }
435 else if (compare_strings(argv[i], "--fontspacing", 8) == 0)
436 {
437 i ++;
438 if (i < argc)
439 {
440 fontspacing = atof(argv[i]);
441
442 if (fontspacing < 1.0f)
443 fontspacing = 1.0f;
444 else if (fontspacing > 3.0f)
445 fontspacing = 3.0f;
446
447 htmlSetBaseSize(fontsize, fontspacing);
448 }
449 else
450 usage(argv[i - 1]);
451 }
452 else if (compare_strings(argv[i], "--footer", 5) == 0)
453 {
454 i ++;
455 if (i < argc)
456 get_format(argv[i], Footer);
457 else
458 usage(argv[i - 1]);
459 }
460 else if (compare_strings(argv[i], "--format", 5) == 0 ||
461 strcmp(argv[i], "-t") == 0)
462 {
463 i ++;
464 if (i < argc)
465 {
466 if (strcasecmp(argv[i], "epub") == 0)
467 exportfunc = (exportfunc_t)epub_export;
468 else if (strcasecmp(argv[i], "html") == 0)
469 exportfunc = (exportfunc_t)html_export;
470 else if (strcasecmp(argv[i], "htmlsep") == 0)
471 exportfunc = (exportfunc_t)htmlsep_export;
472 else if (strcasecmp(argv[i], "pdf14") == 0 ||
473 strcasecmp(argv[i], "pdf") == 0)
474 {
475 exportfunc = (exportfunc_t)pspdf_export;
476 PSLevel = 0;
477 PDFVersion = 14;
478 }
479 else if (strcasecmp(argv[i], "pdf13") == 0)
480 {
481 exportfunc = (exportfunc_t)pspdf_export;
482 PSLevel = 0;
483 PDFVersion = 13;
484 }
485 else if (strcasecmp(argv[i], "pdf12") == 0)
486 {
487 exportfunc = (exportfunc_t)pspdf_export;
488 PSLevel = 0;
489 PDFVersion = 12;
490 }
491 else if (strcasecmp(argv[i], "pdf11") == 0)
492 {
493 exportfunc = (exportfunc_t)pspdf_export;
494 PSLevel = 0;
495 PDFVersion = 11;
496 Compression = 0;
497 }
498 else if (strcasecmp(argv[i], "ps1") == 0)
499 {
500 exportfunc = (exportfunc_t)pspdf_export;
501 PSLevel = 1;
502 }
503 else if (strcasecmp(argv[i], "ps2") == 0 ||
504 strcasecmp(argv[i], "ps") == 0)
505 {
506 exportfunc = (exportfunc_t)pspdf_export;
507 PSLevel = 2;
508 }
509 else if (strcasecmp(argv[i], "ps3") == 0)
510 {
511 exportfunc = (exportfunc_t)pspdf_export;
512 PSLevel = 3;
513 }
514 else
515 usage(argv[i - 1]);
516 }
517 else
518 usage(argv[i - 1]);
519 }
520 else if (compare_strings(argv[i], "--grayscale", 3) == 0)
521 {
522 OutputColor = 0;
523 _htmlGrayscale = 1;
524 }
525 else if (!strcmp(argv[i], "--header"))
526 {
527 i ++;
528 if (i < argc)
529 get_format(argv[i], Header);
530 else
531 usage(argv[i - 1]);
532 }
533 else if (!strcmp(argv[i], "--header1"))
534 {
535 i ++;
536 if (i < argc)
537 get_format(argv[i], Header1);
538 else
539 usage(argv[i - 1]);
540 }
541 else if (!compare_strings(argv[i], "--headfootfont", 11))
542 {
543 i ++;
544 if (i < argc)
545 {
546 if (!strcasecmp(argv[i], "courier"))
547 {
548 HeadFootType = TYPE_COURIER;
549 HeadFootStyle = STYLE_NORMAL;
550 }
551 else if (!strcasecmp(argv[i], "courier-bold"))
552 {
553 HeadFootType = TYPE_COURIER;
554 HeadFootStyle = STYLE_BOLD;
555 }
556 else if (!strcasecmp(argv[i], "courier-oblique"))
557 {
558 HeadFootType = TYPE_COURIER;
559 HeadFootStyle = STYLE_ITALIC;
560 }
561 else if (!strcasecmp(argv[i], "courier-boldoblique"))
562 {
563 HeadFootType = TYPE_COURIER;
564 HeadFootStyle = STYLE_BOLD_ITALIC;
565 }
566 else if (!strcasecmp(argv[i], "times") ||
567 !strcasecmp(argv[i], "times-roman"))
568 {
569 HeadFootType = TYPE_TIMES;
570 HeadFootStyle = STYLE_NORMAL;
571 }
572 else if (!strcasecmp(argv[i], "times-bold"))
573 {
574 HeadFootType = TYPE_TIMES;
575 HeadFootStyle = STYLE_BOLD;
576 }
577 else if (!strcasecmp(argv[i], "times-italic"))
578 {
579 HeadFootType = TYPE_TIMES;
580 HeadFootStyle = STYLE_ITALIC;
581 }
582 else if (!strcasecmp(argv[i], "times-bolditalic"))
583 {
584 HeadFootType = TYPE_TIMES;
585 HeadFootStyle = STYLE_BOLD_ITALIC;
586 }
587 else if (!strcasecmp(argv[i], "helvetica"))
588 {
589 HeadFootType = TYPE_HELVETICA;
590 HeadFootStyle = STYLE_NORMAL;
591 }
592 else if (!strcasecmp(argv[i], "helvetica-bold"))
593 {
594 HeadFootType = TYPE_HELVETICA;
595 HeadFootStyle = STYLE_BOLD;
596 }
597 else if (!strcasecmp(argv[i], "helvetica-oblique"))
598 {
599 HeadFootType = TYPE_HELVETICA;
600 HeadFootStyle = STYLE_ITALIC;
601 }
602 else if (!strcasecmp(argv[i], "helvetica-boldoblique"))
603 {
604 HeadFootType = TYPE_HELVETICA;
605 HeadFootStyle = STYLE_BOLD_ITALIC;
606 }
607 else if (!strcasecmp(argv[i], "monospace"))
608 {
609 HeadFootType = TYPE_MONOSPACE;
610 HeadFootStyle = STYLE_NORMAL;
611 }
612 else if (!strcasecmp(argv[i], "monospace-bold"))
613 {
614 HeadFootType = TYPE_MONOSPACE;
615 HeadFootStyle = STYLE_BOLD;
616 }
617 else if (!strcasecmp(argv[i], "monospace-oblique"))
618 {
619 HeadFootType = TYPE_MONOSPACE;
620 HeadFootStyle = STYLE_ITALIC;
621 }
622 else if (!strcasecmp(argv[i], "monospace-boldoblique"))
623 {
624 HeadFootType = TYPE_MONOSPACE;
625 HeadFootStyle = STYLE_BOLD_ITALIC;
626 }
627 else if (!strcasecmp(argv[i], "serif") ||
628 !strcasecmp(argv[i], "serif-roman"))
629 {
630 HeadFootType = TYPE_SERIF;
631 HeadFootStyle = STYLE_NORMAL;
632 }
633 else if (!strcasecmp(argv[i], "serif-bold"))
634 {
635 HeadFootType = TYPE_SERIF;
636 HeadFootStyle = STYLE_BOLD;
637 }
638 else if (!strcasecmp(argv[i], "serif-italic"))
639 {
640 HeadFootType = TYPE_SERIF;
641 HeadFootStyle = STYLE_ITALIC;
642 }
643 else if (!strcasecmp(argv[i], "serif-bolditalic"))
644 {
645 HeadFootType = TYPE_SERIF;
646 HeadFootStyle = STYLE_BOLD_ITALIC;
647 }
648 else if (!strcasecmp(argv[i], "sans-serif") ||
649 !strcasecmp(argv[i], "sans"))
650 {
651 HeadFootType = TYPE_SANS_SERIF;
652 HeadFootStyle = STYLE_NORMAL;
653 }
654 else if (!strcasecmp(argv[i], "sans-serif-bold") ||
655 !strcasecmp(argv[i], "sans-bold"))
656 {
657 HeadFootType = TYPE_SANS_SERIF;
658 HeadFootStyle = STYLE_BOLD;
659 }
660 else if (!strcasecmp(argv[i], "sans-serif-oblique") ||
661 !strcasecmp(argv[i], "sans-oblique"))
662 {
663 HeadFootType = TYPE_SANS_SERIF;
664 HeadFootStyle = STYLE_ITALIC;
665 }
666 else if (!strcasecmp(argv[i], "sans-serif-boldoblique") ||
667 !strcasecmp(argv[i], "sans-boldoblique"))
668 {
669 HeadFootType = TYPE_SANS_SERIF;
670 HeadFootStyle = STYLE_BOLD_ITALIC;
671 }
672 }
673 else
674 usage(argv[i - 1]);
675 }
676 else if (compare_strings(argv[i], "--headfootsize", 11) == 0)
677 {
678 i ++;
679 if (i < argc)
680 {
681 HeadFootSize = atof(argv[i]);
682
683 if (HeadFootSize < 6.0f)
684 HeadFootSize = 6.0f;
685 else if (HeadFootSize > 24.0f)
686 HeadFootSize = 24.0f;
687 }
688 else
689 usage(argv[i - 1]);
690 }
691 else if (!compare_strings(argv[i], "--headingfont", 7))
692 {
693 i ++;
694 if (i < argc)
695 {
696 if (!strcasecmp(argv[i], "courier"))
697 _htmlHeadingFont = TYPE_COURIER;
698 else if (!strcasecmp(argv[i], "times"))
699 _htmlHeadingFont = TYPE_TIMES;
700 else if (!strcasecmp(argv[i], "helvetica") ||
701 !strcasecmp(argv[i], "arial"))
702 _htmlHeadingFont = TYPE_HELVETICA;
703 else if (!strcasecmp(argv[i], "monospace"))
704 _htmlHeadingFont = TYPE_MONOSPACE;
705 else if (!strcasecmp(argv[i], "serif"))
706 _htmlHeadingFont = TYPE_SERIF;
707 else if (!strcasecmp(argv[i], "sans-serif") ||
708 !strcasecmp(argv[i], "sans"))
709 _htmlHeadingFont = TYPE_SANS_SERIF;
710 }
711 else
712 usage(argv[i - 1]);
713 }
714 else if (compare_strings(argv[i], "--help", 6) == 0)
715 usage(argv[i - 1]);
716 #ifdef HAVE_LIBFLTK
717 else if (compare_strings(argv[i], "--helpdir", 7) == 0)
718 {
719 i ++;
720 if (i < argc)
721 GUI::help_dir = argv[i];
722 else
723 usage(argv[i - 1]);
724 }
725 #endif // HAVE_LIBFLTK
726 else if (strncmp(argv[i], "--hfimage", 9) == 0)
727 {
728 int hfimgnum; // Image number
729 char *hfptr; // Pointer into option
730
731
732 if (strlen(argv[i]) > 9)
733 {
734 hfimgnum = strtol(argv[i] + 9, &hfptr, 10);
735
736 if (hfimgnum < 0 || hfimgnum >= MAX_HF_IMAGES || *hfptr)
737 usage(argv[i]);
738 }
739 else
740 hfimgnum = 0;
741
742 i ++;
743
744 if (i >= argc)
745 usage(argv[i - 1]);
746
747 strlcpy(HFImage[hfimgnum], argv[i], sizeof(HFImage[0]));
748 }
749 else if (compare_strings(argv[i], "--jpeg", 3) == 0 ||
750 strncmp(argv[i], "--jpeg=", 7) == 0)
751 {
752 if (strlen(argv[i]) > 7)
753 OutputJPEG = atoi(argv[i] + 7);
754 else
755 OutputJPEG = 90;
756 }
757 else if (compare_strings(argv[i], "--landscape", 4) == 0)
758 Landscape = 1;
759 else if (compare_strings(argv[i], "--left", 5) == 0)
760 {
761 i ++;
762 if (i < argc)
763 PageLeft = get_measurement(argv[i]);
764 else
765 usage(argv[i - 1]);
766 }
767 else if (compare_strings(argv[i], "--letterhead", 5) == 0)
768 {
769 i ++;
770 if (i < argc)
771 strlcpy(Letterhead, argv[i], sizeof(Letterhead));
772 else
773 usage(argv[i - 1]);
774 }
775 else if (compare_strings(argv[i], "--linkcolor", 7) == 0)
776 {
777 i ++;
778 if (i < argc)
779 strlcpy(LinkColor, argv[i], sizeof(LinkColor));
780 else
781 usage(argv[i - 1]);
782 }
783 else if (strcmp(argv[i], "--links") == 0)
784 Links = 1;
785 else if (compare_strings(argv[i], "--linkstyle", 8) == 0)
786 {
787 i ++;
788 if (i < argc)
789 {
790 if (strcmp(argv[i], "plain") == 0)
791 LinkStyle = 0;
792 else if (strcmp(argv[i], "underline") == 0)
793 LinkStyle = 1;
794 else
795 usage(argv[i - 1]);
796 }
797 else
798 usage(argv[i - 1]);
799 }
800 else if (compare_strings(argv[i], "--logoimage", 5) == 0)
801 {
802 i ++;
803 if (i < argc)
804 strlcpy(LogoImage, argv[i], sizeof(LogoImage));
805 else
806 usage(argv[i - 1]);
807 }
808 else if (compare_strings(argv[i], "--no-compression", 6) == 0)
809 Compression = 0;
810 else if (compare_strings(argv[i], "--no-duplex", 4) == 0)
811 PageDuplex = 0;
812 else if (compare_strings(argv[i], "--no-embedfonts", 7) == 0)
813 EmbedFonts = 0;
814 else if (compare_strings(argv[i], "--no-encryption", 7) == 0)
815 Encryption = 0;
816 else if (compare_strings(argv[i], "--no-jpeg", 6) == 0)
817 OutputJPEG = 0;
818 else if (compare_strings(argv[i], "--no-links", 7) == 0)
819 Links = 0;
820 else if (compare_strings(argv[i], "--no-localfiles", 7) == 0)
821 file_nolocal();
822 else if (compare_strings(argv[i], "--no-numbered", 6) == 0)
823 TocNumbers = 0;
824 else if (compare_strings(argv[i], "--no-overflow", 6) == 0)
825 OverflowErrors = 0;
826 else if (compare_strings(argv[i], "--no-pscommands", 6) == 0)
827 PSCommands = 0;
828 else if (compare_strings(argv[i], "--no-strict", 6) == 0)
829 StrictHTML = 0;
830 else if (compare_strings(argv[i], "--no-title", 7) == 0)
831 TitlePage = 0;
832 else if (compare_strings(argv[i], "--no-toc", 7) == 0)
833 TocLevels = 0;
834 else if (compare_strings(argv[i], "--no-truetype", 7) == 0)
835 {
836 fputs("htmldoc: Warning, --no-truetype option superseded by --no-embedfonts!\n", stderr);
837 EmbedFonts = 0;
838 }
839 else if (compare_strings(argv[i], "--no-xrxcomments", 6) == 0)
840 XRXComments = 0;
841 else if (compare_strings(argv[i], "--numbered", 5) == 0)
842 TocNumbers = 1;
843 else if (compare_strings(argv[i], "--nup", 5) == 0)
844 {
845 i ++;
846 if (i >= argc)
847 usage(argv[i - 1]);
848
849 NumberUp = atoi(argv[i]);
850
851 if (NumberUp != 1 && NumberUp != 2 && NumberUp != 4 &&
852 NumberUp != 6 && NumberUp != 9 && NumberUp != 16)
853 usage(argv[i - 1]);
854 }
855 else if (compare_strings(argv[i], "--outdir", 6) == 0 ||
856 strcmp(argv[i], "-d") == 0)
857 {
858 i ++;
859 if (i < argc)
860 {
861 strlcpy(OutputPath, argv[i], sizeof(OutputPath));
862 OutputFiles = 1;
863 }
864 else
865 usage(argv[i - 1]);
866 }
867 else if (compare_strings(argv[i], "--outfile", 6) == 0 ||
868 strcmp(argv[i], "-f") == 0)
869 {
870 i ++;
871 if (i < argc)
872 {
873 strlcpy(OutputPath, argv[i], sizeof(OutputPath));
874 OutputFiles = 0;
875
876 if ((extension = file_extension(argv[i])) != NULL)
877 {
878 if (strcasecmp(extension, "epub") == 0)
879 exportfunc = (exportfunc_t)epub_export;
880 else if (strcasecmp(extension, "html") == 0)
881 exportfunc = (exportfunc_t)html_export;
882 else if (strcasecmp(extension, "pdf") == 0)
883 {
884 exportfunc = (exportfunc_t)pspdf_export;
885 PSLevel = 0;
886 }
887 else if (strcasecmp(extension, "ps") == 0)
888 {
889 exportfunc = (exportfunc_t)pspdf_export;
890
891 if (PSLevel == 0)
892 PSLevel = 2;
893 }
894 }
895 }
896 else
897 usage(argv[i - 1]);
898 }
899 else if (compare_strings(argv[i], "--overflow", 4) == 0)
900 OverflowErrors = 1;
901 else if (compare_strings(argv[i], "--owner-password", 4) == 0)
902 {
903 i ++;
904 if (i < argc)
905 strlcpy(OwnerPassword, argv[i], sizeof(OwnerPassword));
906 else
907 usage(argv[i - 1]);
908 }
909 else if (compare_strings(argv[i], "--pageduration", 7) == 0)
910 {
911 i ++;
912 if (i < argc)
913 {
914 PDFPageDuration = atof(argv[i]);
915
916 if (PDFPageDuration < 1.0f)
917 {
918 progress_error(HD_ERROR_INTERNAL_ERROR, "Bad page duration \"%s\"!",
919 argv[i]);
920 usage();
921 }
922 }
923 else
924 usage(argv[i - 1]);
925 }
926 else if (compare_strings(argv[i], "--pageeffect", 7) == 0)
927 {
928 i ++;
929 if (i >= argc)
930 usage(argv[i - 1]);
931
932 for (j = 0; j < (int)(sizeof(PDFEffects) / sizeof(PDFEffects[0])); j ++)
933 if (strcasecmp(argv[i], PDFEffects[j]) == 0)
934 {
935 PDFEffect = j;
936 break;
937 }
938 }
939 else if (compare_strings(argv[i], "--pagelayout", 7) == 0)
940 {
941 i ++;
942 if (i >= argc)
943 usage(argv[i - 1]);
944
945 for (j = 0; j < (int)(sizeof(PDFLayouts) / sizeof(PDFLayouts[0])); j ++)
946 if (strcasecmp(argv[i], PDFLayouts[j]) == 0)
947 {
948 PDFPageLayout = j;
949 break;
950 }
951 }
952 else if (compare_strings(argv[i], "--pagemode", 7) == 0)
953 {
954 i ++;
955 if (i >= argc)
956 usage(argv[i - 1]);
957
958 for (j = 0; j < (int)(sizeof(PDFModes) / sizeof(PDFModes[0])); j ++)
959 if (strcasecmp(argv[i], PDFModes[j]) == 0)
960 {
961 PDFPageMode = j;
962 break;
963 }
964 }
965 else if (compare_strings(argv[i], "--path", 5) == 0)
966 {
967 i ++;
968 if (i < argc)
969 strlcpy(Path, argv[i], sizeof(Path));
970 else
971 usage(argv[i - 1]);
972 }
973 else if (compare_strings(argv[i], "--permissions", 4) == 0)
974 {
975 i ++;
976 if (i >= argc)
977 usage(argv[i - 1]);
978
979 set_permissions(argv[i]);
980 }
981 else if (compare_strings(argv[i], "--portrait", 4) == 0)
982 Landscape = 0;
983 else if (compare_strings(argv[i], "--proxy", 4) == 0)
984 {
985 i ++;
986 if (i < argc)
987 {
988 strlcpy(Proxy, argv[i], sizeof(Proxy));
989 file_proxy(Proxy);
990 }
991 else
992 usage(argv[i - 1]);
993 }
994 else if (compare_strings(argv[i], "--pscommands", 3) == 0)
995 PSCommands = 1;
996 else if (compare_strings(argv[i], "--quiet", 3) == 0)
997 Verbosity = -1;
998 else if (!compare_strings(argv[i], "--referer", 4))
999 {
1000 i ++;
1001 if (i < argc)
1002 file_referer(argv[i]);
1003 else
1004 usage(argv[i - 1]);
1005 }
1006 else if (compare_strings(argv[i], "--right", 4) == 0)
1007 {
1008 i ++;
1009 if (i < argc)
1010 PageRight = get_measurement(argv[i]);
1011 else
1012 usage(argv[i - 1]);
1013 }
1014 else if (compare_strings(argv[i], "--size", 4) == 0)
1015 {
1016 i ++;
1017 if (i < argc)
1018 set_page_size(argv[i]);
1019 else
1020 usage(argv[i - 1]);
1021 }
1022 else if (compare_strings(argv[i], "--strict", 4) == 0)
1023 StrictHTML = 1;
1024 else if (compare_strings(argv[i], "--textcolor", 7) == 0)
1025 {
1026 i ++;
1027 if (i < argc)
1028 htmlSetTextColor((uchar *)argv[i]);
1029 else
1030 usage(argv[i - 1]);
1031 }
1032 else if (compare_strings(argv[i], "--title", 7) == 0)
1033 TitlePage = 1;
1034 else if (compare_strings(argv[i], "--titlefile", 8) == 0 ||
1035 compare_strings(argv[i], "--titleimage", 8) == 0)
1036 {
1037 i ++;
1038 if (i < argc)
1039 strlcpy(TitleImage, argv[i], sizeof(TitleImage));
1040 else
1041 usage(argv[i - 1]);
1042
1043 TitlePage = 1;
1044 }
1045 else if (compare_strings(argv[i], "--tocfooter", 6) == 0)
1046 {
1047 i ++;
1048 if (i < argc)
1049 get_format(argv[i], TocFooter);
1050 else
1051 usage(argv[i - 1]);
1052 }
1053 else if (compare_strings(argv[i], "--tocheader", 6) == 0)
1054 {
1055 i ++;
1056 if (i < argc)
1057 get_format(argv[i], TocHeader);
1058 else
1059 usage(argv[i - 1]);
1060 }
1061 else if (compare_strings(argv[i], "--toclevels", 6) == 0)
1062 {
1063 i ++;
1064 if (i < argc)
1065 TocLevels = atoi(argv[i]);
1066 else
1067 usage(argv[i - 1]);
1068 }
1069 else if (compare_strings(argv[i], "--toctitle", 6) == 0)
1070 {
1071 i ++;
1072 if (i < argc)
1073 strlcpy(TocTitle, argv[i], sizeof(TocTitle));
1074 else
1075 usage(argv[i - 1]);
1076 }
1077 else if (compare_strings(argv[i], "--top", 5) == 0)
1078 {
1079 i ++;
1080 if (i < argc)
1081 PageTop = get_measurement(argv[i]);
1082 else
1083 usage(argv[i - 1]);
1084 }
1085 else if (compare_strings(argv[i], "--user-password", 4) == 0)
1086 {
1087 i ++;
1088 if (i < argc)
1089 strlcpy(UserPassword, argv[i], sizeof(UserPassword));
1090 else
1091 usage(argv[i - 1]);
1092 }
1093 else if (compare_strings(argv[i], "--truetype", 4) == 0)
1094 {
1095 fputs("htmldoc: Warning, --truetype option superseded by --embedfonts!\n", stderr);
1096
1097 EmbedFonts = 1;
1098 }
1099 else if (compare_strings(argv[i], "--verbose", 6) == 0 ||
1100 strcmp(argv[i], "-v") == 0)
1101 {
1102 Verbosity ++;
1103 }
1104 else if (compare_strings(argv[i], "--version", 6) == 0)
1105 {
1106 puts(SVERSION);
1107 return (0);
1108 }
1109 else if (compare_strings(argv[i], "--webpage", 3) == 0)
1110 {
1111 TocLevels = 0;
1112 TitlePage = 0;
1113 OutputType = OUTPUT_WEBPAGES;
1114 PDFPageMode = PDF_DOCUMENT;
1115 PDFFirstPage = PDF_PAGE_1;
1116 }
1117 else if (compare_strings(argv[i], "--xrxcomments", 3) == 0)
1118 XRXComments = 1;
1119 else if (strcmp(argv[i], "-") == 0)
1120 {
1121 /*
1122 * Read from stdin...
1123 */
1124
1125 num_files ++;
1126
1127 _htmlPPI = 72.0f * _htmlBrowserWidth / (PageWidth - PageLeft - PageRight);
1128
1129 file = htmlAddTree(NULL, MARKUP_FILE, NULL);
1130 htmlSetVariable(file, (uchar *)"_HD_FILENAME", (uchar *)"");
1131 htmlSetVariable(file, (uchar *)"_HD_BASE", (uchar *)".");
1132
1133 #ifdef WIN32
1134 // Make sure stdin is in binary mode.
1135 // (I hate Microsoft... I hate Microsoft... Everybody join in!)
1136 setmode(0, O_BINARY);
1137 #elif defined(__EMX__)
1138 // OS/2 has a setmode for FILE's...
1139 fflush(stdin);
1140 _fsetmode(stdin, "b");
1141 #endif // WIN32 || __EMX__
1142
1143 _htmlCurrentFile = "(stdin)";
1144 htmlReadFile(file, stdin, ".");
1145
1146 if (document == NULL)
1147 document = file;
1148 else
1149 {
1150 while (document->next != NULL)
1151 document = document->next;
1152
1153 document->next = file;
1154 file->prev = document;
1155 }
1156 }
1157 else if (argv[i][0] == '-')
1158 usage(argv[i]);
1159 #ifdef HAVE_LIBFLTK
1160 else if (strlen(argv[i]) > 5 &&
1161 strcmp(argv[i] + strlen(argv[i]) - 5, ".book") == 0)
1162 {
1163 /*
1164 * GUI mode...
1165 */
1166
1167 if (BookGUI == NULL)
1168 BookGUI = new GUI(argv[i]);
1169 else
1170 BookGUI->loadBook(argv[i]);
1171 }
1172 #endif /* HAVE_LIBFLTK */
1173 else
1174 {
1175 num_files ++;
1176
1177 read_file(argv[i], &document, Path);
1178 }
1179 }
1180
1181 if (CGIMode)
1182 {
1183 char url[1024]; // URL
1184 const char *https, // HTTPS env var, if any
1185 *path_info, // Path info, if any
1186 *query, // Query string, if any
1187 *server_name, // Server name
1188 *server_port; // Server port
1189
1190
1191 https = getenv("HTTPS");
1192 path_info = getenv("PATH_INFO");
1193 query = getenv("QUERY_STRING");
1194 server_name = getenv("SERVER_NAME");
1195 server_port = getenv("SERVER_PORT");
1196
1197 if (server_port && path_info && *path_info)
1198 {
1199 // Read the referenced file from the local server...
1200 if (https && strcmp(https, "off"))
1201 httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "https",
1202 NULL, server_name, atoi(server_port), path_info);
1203 else
1204 httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "http",
1205 NULL, server_name, atoi(server_port), path_info);
1206
1207 if (query && *query && *query != '-')
1208 {
1209 // Include query string on end of URL, which is already URI encoded...
1210 strlcat(url, "?", sizeof(url));
1211 strlcat(url, query, sizeof(url));
1212 }
1213
1214 progress_error(HD_ERROR_NONE, "INFO: HTMLDOC converting \"%s\".", url);
1215
1216 num_files ++;
1217
1218 read_file(url, &document, Path);
1219 }
1220 else
1221 progress_error(HD_ERROR_FILE_NOT_FOUND,
1222 "PATH_INFO is not set in the environment!");
1223 }
1224
1225 /*
1226 * Display the GUI if necessary...
1227 */
1228
1229 #ifdef HAVE_LIBFLTK
1230 if (num_files == 0 && BookGUI == NULL)
1231 BookGUI = new GUI();
1232
1233 if (BookGUI != NULL)
1234 {
1235 Fl_File_Icon::load_system_icons();
1236
1237 BookGUI->show();
1238
1239 i = Fl::run();
1240
1241 delete BookGUI;
1242
1243 return (i);
1244 }
1245 #endif /* HAVE_LIBFLTK */
1246
1247 /*
1248 * We *must* have a document to process...
1249 */
1250
1251 if (num_files == 0 || document == NULL)
1252 usage("No HTML files!");
1253
1254 /*
1255 * Find the first one in the list...
1256 */
1257
1258 while (document && document->prev != NULL)
1259 document = document->prev;
1260
1261 // Fix links...
1262 htmlFixLinks(document, document);
1263
1264 load_time = get_seconds();
1265
1266 // Show debug info...
1267 htmlDebugStats("Document Tree", document);
1268
1269 /*
1270 * Build a table of contents for the documents if necessary...
1271 */
1272
1273 if (OutputType == OUTPUT_BOOK && TocLevels > 0)
1274 {
1275 toc = toc_build(document);
1276 }
1277 else
1278 {
1279 if (TocNumbers)
1280 htmlDeleteTree(toc_build(document));
1281
1282 toc = NULL;
1283 }
1284
1285 htmlDebugStats("Table of Contents Tree", toc);
1286
1287 /*
1288 * Generate the output file(s).
1289 */
1290
1291 (*exportfunc)(document, toc);
1292
1293 end_time = get_seconds();
1294
1295 /*
1296 * Report running time statistics as needed...
1297 */
1298
1299 if ((debug = getenv("HTMLDOC_DEBUG")) != NULL &&
1300 (strstr(debug, "all") != NULL || strstr(debug, "timing") != NULL))
1301 progress_error(HD_ERROR_NONE, "TIMING: %.3f %.3f %.3f",
1302 load_time - start_time, end_time - load_time,
1303 end_time - start_time);
1304
1305 /*
1306 * Cleanup...
1307 */
1308
1309 htmlDeleteTree(document);
1310 htmlDeleteTree(toc);
1311
1312 file_cleanup();
1313 image_flush_cache();
1314
1315 return (Errors);
1316 }
1317
1318
1319 /*
1320 * 'prefs_getrc()' - Get the rc file for preferences...
1321 */
1322
1323 static const char *
prefs_getrc(void)1324 prefs_getrc(void)
1325 {
1326 #ifdef WIN32
1327 HKEY key; // Registry key
1328 DWORD size; // Size of string
1329 char home[1024]; // Home (profile) directory
1330 #else
1331 const char *home; // Home directory
1332 #endif // WIN32
1333 static char htmldocrc[1024];// HTMLDOC RC file
1334
1335
1336 // Find the home directory...
1337 #ifdef WIN32
1338 // Open the registry...
1339 if (RegOpenKeyEx(HKEY_CURRENT_USER,
1340 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0,
1341 KEY_READ, &key))
1342 {
1343 // Use the install directory...
1344 strlcpy(home, _htmlData, sizeof(home));
1345 }
1346 else
1347 {
1348 // Grab the current user's AppData directory...
1349 size = sizeof(home);
1350 if (RegQueryValueEx(key, "AppData", NULL, NULL, (unsigned char *)home, &size))
1351 strlcpy(home, _htmlData, sizeof(home));
1352
1353 RegCloseKey(key);
1354 }
1355 #else
1356 if ((home = getenv("HOME")) == NULL)
1357 home = _htmlData;
1358 #endif // WIN32
1359
1360 // Format the rc filename and return...
1361 snprintf(htmldocrc, sizeof(htmldocrc), "%s/.htmldocrc", home);
1362
1363 return (htmldocrc);
1364 }
1365
1366
1367 /*
1368 * 'prefs_load()' - Load HTMLDOC preferences...
1369 */
1370
1371 void
prefs_load(void)1372 prefs_load(void)
1373 {
1374 int pos; // Header/footer position
1375 char line[2048]; // Line from RC file
1376 FILE *fp; // File pointer
1377
1378
1379 //
1380 // Read the preferences file...
1381 //
1382
1383 if ((fp = fopen(prefs_getrc(), "r")) != NULL)
1384 {
1385 while (fgets(line, sizeof(line), fp) != NULL)
1386 {
1387 if (line[strlen(line) - 1] == '\n')
1388 line[strlen(line) - 1] = '\0';
1389
1390 if (strncasecmp(line, "TEXTCOLOR=", 10) == 0)
1391 htmlSetTextColor((uchar *)(line + 10));
1392 else if (strncasecmp(line, "BODYCOLOR=", 10) == 0)
1393 strlcpy(BodyColor, line + 10, sizeof(BodyColor));
1394 else if (strncasecmp(line, "BODYIMAGE=", 10) == 0)
1395 strlcpy(BodyImage, line + 10, sizeof(BodyImage));
1396 else if (strncasecmp(line, "LINKCOLOR=", 10) == 0)
1397 strlcpy(LinkColor, line + 10, sizeof(LinkColor));
1398 else if (strncasecmp(line, "LINKSTYLE=", 10) == 0)
1399 LinkStyle = atoi(line + 10);
1400 else if (strncasecmp(line, "BROWSERWIDTH=", 13) == 0)
1401 _htmlBrowserWidth = atof(line + 13);
1402 else if (strncasecmp(line, "PAGEWIDTH=", 10) == 0)
1403 PageWidth = atoi(line + 10);
1404 else if (strncasecmp(line, "PAGELENGTH=", 11) == 0)
1405 PageLength = atoi(line + 11);
1406 else if (strncasecmp(line, "PAGELEFT=", 9) == 0)
1407 PageLeft = atoi(line + 9);
1408 else if (strncasecmp(line, "PAGERIGHT=", 10) == 0)
1409 PageRight = atoi(line + 10);
1410 else if (strncasecmp(line, "PAGETOP=", 8) == 0)
1411 PageTop = atoi(line + 8);
1412 else if (strncasecmp(line, "PAGEBOTTOM=", 11) == 0)
1413 PageBottom = atoi(line + 11);
1414 else if (strncasecmp(line, "PAGEDUPLEX=", 11) == 0)
1415 PageDuplex = atoi(line + 11);
1416 else if (strncasecmp(line, "LANDSCAPE=", 10) == 0)
1417 Landscape = atoi(line + 10);
1418 else if (strncasecmp(line, "COMPRESSION=", 12) == 0)
1419 Compression = atoi(line + 12);
1420 else if (strncasecmp(line, "OUTPUTCOLOR=", 12) == 0)
1421 {
1422 OutputColor = atoi(line + 12);
1423 _htmlGrayscale = !OutputColor;
1424 }
1425 else if (strncasecmp(line, "TOCNUMBERS=", 11) == 0)
1426 TocNumbers = atoi(line + 11);
1427 else if (strncasecmp(line, "TOCLEVELS=", 10) == 0)
1428 TocLevels = atoi(line + 10);
1429 else if (strncasecmp(line, "JPEG=", 5) == 0)
1430 OutputJPEG = atoi(line + 1);
1431 else if (strncasecmp(line, "PAGEHEADER=", 11) == 0)
1432 get_format(line + 11, Header);
1433 else if (strncasecmp(line, "PAGEFOOTER=", 11) == 0)
1434 get_format(line + 11, Footer);
1435 else if (strncasecmp(line, "NUMBERUP=", 9) == 0)
1436 NumberUp = atoi(line + 9);
1437 else if (strncasecmp(line, "TOCHEADER=", 10) == 0)
1438 get_format(line + 10, TocHeader);
1439 else if (strncasecmp(line, "TOCFOOTER=", 10) == 0)
1440 get_format(line + 10, TocFooter);
1441 else if (strncasecmp(line, "TOCTITLE=", 9) == 0)
1442 strlcpy(TocTitle, line + 9, sizeof(TocTitle));
1443 else if (strncasecmp(line, "BODYFONT=", 9) == 0)
1444 _htmlBodyFont = (typeface_t)atoi(line + 9);
1445 else if (strncasecmp(line, "HEADINGFONT=", 12) == 0)
1446 _htmlHeadingFont = (typeface_t)atoi(line + 12);
1447 else if (strncasecmp(line, "FONTSIZE=", 9) == 0)
1448 htmlSetBaseSize(atof(line + 9),
1449 _htmlSpacings[SIZE_P] / _htmlSizes[SIZE_P]);
1450 else if (strncasecmp(line, "FONTSPACING=", 12) == 0)
1451 htmlSetBaseSize(_htmlSizes[SIZE_P], atof(line + 12));
1452 else if (strncasecmp(line, "HEADFOOTTYPE=", 13) == 0)
1453 HeadFootType = (typeface_t)atoi(line + 13);
1454 else if (strncasecmp(line, "HEADFOOTSTYLE=", 14) == 0)
1455 HeadFootStyle = (style_t)atoi(line + 14);
1456 else if (strncasecmp(line, "HEADFOOTSIZE=", 13) == 0)
1457 HeadFootSize = atof(line + 13);
1458 else if (strncasecmp(line, "PDFVERSION=", 11) == 0)
1459 {
1460 if (strchr(line + 11, '.') != NULL)
1461 PDFVersion = (int)(atof(line + 11) * 10.0 + 0.5);
1462 else
1463 PDFVersion = atoi(line + 11);
1464 }
1465 else if (strncasecmp(line, "PSLEVEL=", 8) == 0)
1466 PSLevel = atoi(line + 8);
1467 else if (strncasecmp(line, "PSCOMMANDS=", 11) == 0)
1468 PSCommands = atoi(line + 11);
1469 else if (strncasecmp(line, "XRXCOMMENTS=", 12) == 0)
1470 XRXComments = atoi(line + 12);
1471 else if (strncasecmp(line, "CHARSET=", 8) == 0)
1472 htmlSetCharSet(line + 8);
1473 else if (strncasecmp(line, "PAGEMODE=", 9) == 0)
1474 PDFPageMode = atoi(line + 9);
1475 else if (strncasecmp(line, "PAGELAYOUT=", 11) == 0)
1476 PDFPageLayout = atoi(line + 11);
1477 else if (strncasecmp(line, "FIRSTPAGE=", 10) == 0)
1478 PDFFirstPage = atoi(line + 10);
1479 else if (strncasecmp(line, "PAGEEFFECT=", 11) == 0)
1480 PDFEffect = atoi(line + 11);
1481 else if (strncasecmp(line, "PAGEDURATION=", 14) == 0)
1482 PDFPageDuration = atof(line + 14);
1483 else if (strncasecmp(line, "EFFECTDURATION=", 16) == 0)
1484 PDFEffectDuration = atof(line + 16);
1485 else if (strncasecmp(line, "ENCRYPTION=", 11) == 0)
1486 Encryption = atoi(line + 11);
1487 else if (strncasecmp(line, "PERMISSIONS=", 12) == 0)
1488 Permissions = atoi(line + 12);
1489 else if (strncasecmp(line, "OWNERPASSWORD=", 14) == 0)
1490 strlcpy(OwnerPassword, line + 14, sizeof(OwnerPassword));
1491 else if (strncasecmp(line, "USERPASSWORD=", 13) == 0)
1492 strlcpy(UserPassword, line + 13, sizeof(UserPassword));
1493 else if (strncasecmp(line, "LINKS=", 6) == 0)
1494 Links = atoi(line + 6);
1495 else if (strncasecmp(line, "TRUETYPE=", 9) == 0)
1496 EmbedFonts = atoi(line + 9);
1497 else if (strncasecmp(line, "EMBEDFONTS=", 11) == 0)
1498 EmbedFonts = atoi(line + 11);
1499 else if (strncasecmp(line, "PATH=", 5) == 0)
1500 strlcpy(Path, line + 5, sizeof(Path));
1501 else if (strncasecmp(line, "PROXY=", 6) == 0)
1502 strlcpy(Proxy, line + 6, sizeof(Proxy));
1503 else if (strncasecmp(line, "STRICTHTML=", 11) == 0)
1504 StrictHTML = atoi(line + 11);
1505
1506 # ifdef HAVE_LIBFLTK
1507 else if (strncasecmp(line, "EDITOR=", 7) == 0)
1508 strlcpy(HTMLEditor, line + 7, sizeof(HTMLEditor));
1509 else if (strncasecmp(line, "TOOLTIPS=", 9) == 0)
1510 Tooltips = atoi(line + 9);
1511 # endif // HAVE_LIBFLTK
1512 }
1513
1514 fclose(fp);
1515 }
1516
1517 // Check header/footer formats...
1518 for (pos = 0; pos < 3; pos ++)
1519 if (Header[pos])
1520 break;
1521
1522 if (pos == 3)
1523 get_format(".t.", Header);
1524
1525 for (pos = 0; pos < 3; pos ++)
1526 if (Footer[pos])
1527 break;
1528
1529 if (pos == 3)
1530 get_format("h.1", Footer);
1531
1532 for (pos = 0; pos < 3; pos ++)
1533 if (TocHeader[pos])
1534 break;
1535
1536 if (pos == 3)
1537 get_format(".t.", TocHeader);
1538
1539 for (pos = 0; pos < 3; pos ++)
1540 if (TocFooter[pos])
1541 break;
1542
1543 if (pos == 3)
1544 get_format("..i", TocFooter);
1545 }
1546
1547
1548 /*
1549 * 'prefs_save()' - Save HTMLDOC preferences...
1550 */
1551
1552 void
prefs_save(void)1553 prefs_save(void)
1554 {
1555 FILE *fp; // File pointer
1556
1557
1558 if ((fp = fopen(prefs_getrc(), "w")) != NULL)
1559 {
1560 fputs("#HTMLDOCRC " SVERSION "\n", fp);
1561
1562 fprintf(fp, "TEXTCOLOR=%s\n", _htmlTextColor);
1563 fprintf(fp, "BODYCOLOR=%s\n", BodyColor);
1564 fprintf(fp, "BODYIMAGE=%s\n", BodyImage);
1565 fprintf(fp, "LINKCOLOR=%s\n", LinkColor);
1566 fprintf(fp, "LINKSTYLE=%d\n", LinkStyle);
1567 fprintf(fp, "BROWSERWIDTH=%.0f\n", _htmlBrowserWidth);
1568 fprintf(fp, "PAGEWIDTH=%d\n", PageWidth);
1569 fprintf(fp, "PAGELENGTH=%d\n", PageLength);
1570 fprintf(fp, "PAGELEFT=%d\n", PageLeft);
1571 fprintf(fp, "PAGERIGHT=%d\n", PageRight);
1572 fprintf(fp, "PAGETOP=%d\n", PageTop);
1573 fprintf(fp, "PAGEBOTTOM=%d\n", PageBottom);
1574 fprintf(fp, "PAGEDUPLEX=%d\n", PageDuplex);
1575 fprintf(fp, "LANDSCAPE=%d\n", Landscape);
1576 fprintf(fp, "COMPRESSION=%d\n", Compression);
1577 fprintf(fp, "OUTPUTCOLOR=%d\n", OutputColor);
1578 fprintf(fp, "TOCNUMBERS=%d\n", TocNumbers);
1579 fprintf(fp, "TOCLEVELS=%d\n", TocLevels);
1580 fprintf(fp, "JPEG=%d\n", OutputJPEG);
1581 fprintf(fp, "PAGEHEADER=%s\n", get_fmt(Header));
1582 fprintf(fp, "PAGEFOOTER=%s\n", get_fmt(Footer));
1583 fprintf(fp, "NUMBERUP=%d\n", NumberUp);
1584 fprintf(fp, "TOCHEADER=%s\n", get_fmt(TocHeader));
1585 fprintf(fp, "TOCFOOTER=%s\n", get_fmt(TocFooter));
1586 fprintf(fp, "TOCTITLE=%s\n", TocTitle);
1587 fprintf(fp, "BODYFONT=%d\n", _htmlBodyFont);
1588 fprintf(fp, "HEADINGFONT=%d\n", _htmlHeadingFont);
1589 fprintf(fp, "FONTSIZE=%.2f\n", _htmlSizes[SIZE_P]);
1590 fprintf(fp, "FONTSPACING=%.2f\n",
1591 _htmlSpacings[SIZE_P] / _htmlSizes[SIZE_P]);
1592 fprintf(fp, "HEADFOOTTYPE=%d\n", HeadFootType);
1593 fprintf(fp, "HEADFOOTSTYLE=%d\n", HeadFootStyle);
1594 fprintf(fp, "HEADFOOTSIZE=%.2f\n", HeadFootSize);
1595 fprintf(fp, "PDFVERSION=%d\n", PDFVersion);
1596 fprintf(fp, "PSLEVEL=%d\n", PSLevel);
1597 fprintf(fp, "PSCOMMANDS=%d\n", PSCommands);
1598 fprintf(fp, "XRXCOMMENTS=%d\n", XRXComments);
1599 fprintf(fp, "CHARSET=%s\n", _htmlCharSet);
1600 fprintf(fp, "PAGEMODE=%d\n", PDFPageMode);
1601 fprintf(fp, "PAGELAYOUT=%d\n", PDFPageLayout);
1602 fprintf(fp, "FIRSTPAGE=%d\n", PDFFirstPage);
1603 fprintf(fp, "PAGEEFFECT=%d\n", PDFEffect);
1604 fprintf(fp, "PAGEDURATION=%.0f\n", PDFPageDuration);
1605 fprintf(fp, "EFFECTDURATION=%.1f\n", PDFEffectDuration);
1606 fprintf(fp, "ENCRYPTION=%d\n", Encryption);
1607 fprintf(fp, "PERMISSIONS=%d\n", Permissions);
1608 fprintf(fp, "OWNERPASSWORD=%s\n", OwnerPassword);
1609 fprintf(fp, "USERPASSWORD=%s\n", UserPassword);
1610 fprintf(fp, "LINKS=%d\n", Links);
1611 fprintf(fp, "EMBEDFONTS=%d\n", EmbedFonts);
1612 fprintf(fp, "PATH=%s\n", Path);
1613 fprintf(fp, "PROXY=%s\n", Proxy);
1614 fprintf(fp, "STRICTHTML=%d\n", StrictHTML);
1615
1616 #ifdef HAVE_LIBFLTK
1617 fprintf(fp, "EDITOR=%s\n", HTMLEditor);
1618 fprintf(fp, "TOOLTIPS=%d\n", Tooltips);
1619 #endif // HAVE_LIBFLTK
1620
1621 fclose(fp);
1622 }
1623 }
1624
1625
1626 /*
1627 * 'prefs_set_paths()' - Set HTMLDOC data/help paths...
1628 */
1629
1630 void
prefs_set_paths(void)1631 prefs_set_paths(void)
1632 {
1633 //
1634 // Get the installed directories...
1635 //
1636
1637 #ifdef WIN32 //// Do registry magic...
1638 HKEY key; // Registry key
1639 DWORD size; // Size of string
1640 static char data[1024]; // Data directory
1641 static char doc[1024]; // Documentation directory
1642 static char path[4096]; // PATH environment variable
1643
1644 // Open the registry...
1645 if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\HTMLDOC", 0, KEY_READ, &key))
1646 {
1647 // Grab the installed directories...
1648 size = sizeof(data);
1649 if (!RegQueryValueEx(key, "data", NULL, NULL, (unsigned char *)data, &size))
1650 _htmlData = data;
1651 else
1652 progress_error(HD_ERROR_FILE_NOT_FOUND, "Unable to read \"data\" value from registry!");
1653
1654 # ifdef HAVE_LIBFLTK
1655 size = sizeof(doc);
1656 if (!RegQueryValueEx(key, "doc", NULL, NULL, (unsigned char *)doc, &size))
1657 GUI::help_dir = doc;
1658 # endif // HAVE_LIBFLTK
1659
1660 RegCloseKey(key);
1661 }
1662 else
1663 progress_error(HD_ERROR_FILE_NOT_FOUND, "Unable to read HTMLDOC installation from registry!");
1664
1665 // See if the HTMLDOC program folder is in the system execution path...
1666 if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1667 "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
1668 0, KEY_READ | KEY_WRITE, &key))
1669 {
1670 // Grab the current path...
1671 size = sizeof(path);
1672 if (!RegQueryValueEx(key, "Path", NULL, NULL, (unsigned char *)path, &size))
1673 if (strstr(path, _htmlData) == NULL)
1674 {
1675 // The data directory is not in the path, so add it...
1676 strlcat(path, ";", sizeof(path));
1677 strlcat(path, _htmlData, sizeof(path));
1678 RegSetValueEx(key, "Path", 0, REG_EXPAND_SZ, (unsigned char *)path, strlen(path) + 1);
1679 }
1680 }
1681
1682 #elif defined(__EMX__) && defined(HAVE_LIBFLTK)
1683 // If being installed within XFree86 OS/2 Environment
1684 // we can use those values which are overwritten by
1685 // the according environment variables.
1686 _htmlData = strdup(__XOS2RedirRoot("/XFree86/lib/X11/htmldoc"));
1687 GUI::help_dir = strdup(__XOS2RedirRoot("/XFree86/lib/X11/htmldoc/doc"));
1688
1689 #elif defined(__APPLE__) && defined(HAVE_LIBFLTK)
1690 char path[PROC_PIDPATHINFO_MAXSIZE + 1];
1691 // Process path
1692 int pathlen; // Length of path string
1693 static char resources[1024]; // Resources directory
1694
1695 if ((pathlen = proc_pidpath(getpid(), path, sizeof(path) - 1)) >= 0)
1696 {
1697 char *ptr; // Pointer into path
1698
1699 path[pathlen] = '\0';
1700 // printf("proc_pidpath returned \"%s\"\n", path);
1701
1702 if ((ptr = strstr(path, "/Contents/MacOS")) != NULL)
1703 {
1704 *ptr = '\0';
1705 // printf("Bundle path is \"%s\"\n", path);
1706
1707 snprintf(resources, sizeof(resources), "%s/Contents/Resources", path);
1708 _htmlData = resources;
1709 GUI::help_dir = resources;
1710 }
1711 }
1712 // else
1713 // perror("proc_pidpath failed");
1714
1715 #elif defined(__linux)
1716 const char *snap; // SNAP environment variable
1717
1718 // Support HTMLDOC as a snap package...
1719 if ((snap = getenv("SNAP")) != NULL)
1720 {
1721 static char datadir[1024]; // Data directory
1722
1723 snprintf(datadir, sizeof(datadir), "%s/share/htmldoc", snap);
1724 _htmlData = datadir;
1725
1726 # ifdef HAVE_LIBFLTK
1727 static char docdir[1024]; // Documentation directory
1728
1729 snprintf(docdir, sizeof(docdir), "%s/share/doc/htmldoc", snap);
1730 GUI::help_dir = docdir;
1731 # endif // HAVE_LIBFLTK
1732 }
1733 #endif // WIN32
1734
1735 //
1736 // See if the installed directories have been overridden by
1737 // environment variables...
1738 //
1739
1740 if (getenv("HTMLDOC_DATA") != NULL)
1741 _htmlData = getenv("HTMLDOC_DATA");
1742
1743 #ifdef HAVE_LIBFLTK
1744 if (getenv("HTMLDOC_HELP") != NULL)
1745 GUI::help_dir = getenv("HTMLDOC_HELP");
1746 #endif // HAVE_LIBFLTK
1747 }
1748
1749
1750 /*
1751 * 'compare_strings()' - Compare two command-line strings.
1752 */
1753
1754 static int /* O - -1 or 1 = no match, 0 = match */
compare_strings(const char * s,const char * t,int tmin)1755 compare_strings(const char *s, /* I - Command-line string */
1756 const char *t, /* I - Option string */
1757 int tmin) /* I - Minimum number of unique chars in option */
1758 {
1759 size_t slen; /* Length of command-line string */
1760
1761
1762 slen = strlen(s);
1763 if (slen < (size_t)tmin)
1764 return (-1);
1765 else
1766 return (strncmp(s, t, slen));
1767 }
1768
1769
1770 /*
1771 * 'get_seconds()' - Get the current fractional time in seconds.
1772 */
1773
1774 static double /* O - Number of seconds */
get_seconds(void)1775 get_seconds(void)
1776 {
1777 #ifdef WIN32
1778 return (GetTickCount() * 0.001);
1779 #else
1780 struct timeval curtime; /* Current time */
1781
1782 gettimeofday(&curtime, NULL);
1783
1784 return (curtime.tv_sec + curtime.tv_usec * 0.000001);
1785 #endif /* WIN32 */
1786 }
1787
1788
1789 //
1790 // 'load_book()' - Load a book file...
1791 //
1792
1793 static int // O - 1 = success, 0 = failure
load_book(const char * filename,tree_t ** document,exportfunc_t * exportfunc,int set_nolocal)1794 load_book(const char *filename, // I - Book file
1795 tree_t **document, // IO - Document tree
1796 exportfunc_t *exportfunc, // O - Export function
1797 int set_nolocal) // I - Set file_nolocal() after lookup?
1798 {
1799 FILE *fp; // File to read from
1800 char line[10240]; // Line from file
1801 const char *dir; // Directory
1802 const char *local; // Local filename
1803 char path[2048]; // Current path
1804
1805
1806 // See if the filename contains a path...
1807 dir = file_directory(filename);
1808
1809 if (dir != NULL)
1810 snprintf(path, sizeof(path), "%s;%s", dir, Path);
1811 else
1812 strlcpy(path, Path, sizeof(path));
1813
1814 // Open the file...
1815 local = file_find(Path, filename);
1816
1817 if (set_nolocal)
1818 file_nolocal();
1819
1820 if (!local)
1821 return (0);
1822
1823 if ((fp = fopen(local, "rb")) == NULL)
1824 {
1825 progress_error(HD_ERROR_READ_ERROR, "Unable to open book file \"%s\": %s",
1826 local, strerror(errno));
1827 return (0);
1828 }
1829
1830 // Get the header...
1831 file_gets(line, sizeof(line), fp);
1832 if (strncmp(line, "#HTMLDOC", 8) != 0)
1833 {
1834 fclose(fp);
1835 progress_error(HD_ERROR_BAD_FORMAT,
1836 "Bad or missing #HTMLDOC header in \"%s\".", filename);
1837 return (0);
1838 }
1839
1840 // Read the second line from the book file; for older book files, this will
1841 // be the file count; for new files this will be the options...
1842 do
1843 {
1844 file_gets(line, sizeof(line), fp);
1845
1846 if (line[0] == '-')
1847 {
1848 parse_options(line, exportfunc);
1849
1850 if (dir != NULL)
1851 snprintf(path, sizeof(path), "%s;%s", dir, Path);
1852 else
1853 strlcpy(path, Path, sizeof(path));
1854 }
1855 }
1856 while (!line[0]); // Skip blank lines
1857
1858 // Get input files/options...
1859 while (file_gets(line, sizeof(line), fp) != NULL)
1860 {
1861 if (!line[0])
1862 continue; // Skip blank lines
1863 else if (line[0] == '-')
1864 {
1865 parse_options(line, exportfunc);
1866
1867 if (dir != NULL)
1868 snprintf(path, sizeof(path), "%s;%s", dir, Path);
1869 else
1870 strlcpy(path, Path, sizeof(path));
1871 }
1872 else if (line[0] == '\\')
1873 read_file(line + 1, document, path);
1874 else
1875 read_file(line, document, path);
1876 }
1877
1878 // Close the book file and return...
1879 fclose(fp);
1880
1881 return (1);
1882 }
1883
1884
1885 //
1886 // 'parse_options()' - Parse options from a book file...
1887 //
1888
1889 static void
parse_options(const char * line,exportfunc_t * exportfunc)1890 parse_options(const char *line, // I - Options from book file
1891 exportfunc_t *exportfunc) // O - Export function
1892 {
1893 int i; // Looping var
1894 const char *lineptr; // Pointer into line
1895 char temp[1024], // Option name
1896 temp2[1024], // Option value
1897 *tempptr; // Pointer into option
1898 double fontsize, // Size of body text
1899 fontspacing; // Spacing between lines
1900
1901
1902 // Parse the input line...
1903 for (lineptr = line; *lineptr != '\0';)
1904 {
1905 while (*lineptr == ' ')
1906 lineptr ++;
1907
1908 for (tempptr = temp; *lineptr != '\0' && *lineptr != ' '; lineptr ++)
1909 if (tempptr < (temp + sizeof(temp) - 1))
1910 *tempptr++ = *lineptr;
1911
1912 *tempptr = '\0';
1913
1914 while (*lineptr == ' ')
1915 lineptr ++;
1916
1917 if (strcmp(temp, "--duplex") == 0)
1918 {
1919 PageDuplex = 1;
1920 continue;
1921 }
1922 else if (strcmp(temp, "--landscape") == 0)
1923 {
1924 Landscape = 1;
1925 continue;
1926 }
1927 else if (strcmp(temp, "--portrait") == 0)
1928 {
1929 Landscape = 0;
1930 continue;
1931 }
1932 else if (strncmp(temp, "--jpeg", 6) == 0)
1933 {
1934 if (strlen(temp) > 7)
1935 OutputJPEG = atoi(temp + 7);
1936 else
1937 OutputJPEG = 90;
1938 continue;
1939 }
1940 else if (strcmp(temp, "--grayscale") == 0)
1941 {
1942 OutputColor = 0;
1943 continue;
1944 }
1945 else if (strcmp(temp, "--color") == 0)
1946 {
1947 OutputColor = 1;
1948 continue;
1949 }
1950 else if (strcmp(temp, "--links") == 0)
1951 {
1952 Links = 1;
1953 continue;
1954 }
1955 else if (strcmp(temp, "--no-links") == 0)
1956 {
1957 Links = 0;
1958 continue;
1959 }
1960 else if (strcmp(temp, "--embedfonts") == 0 ||
1961 strcmp(temp, "--truetype") == 0)
1962 {
1963 EmbedFonts = 1;
1964 continue;
1965 }
1966 else if (strcmp(temp, "--no-embedfonts") == 0 ||
1967 strcmp(temp, "--no-truetype") == 0)
1968 {
1969 EmbedFonts = 0;
1970 continue;
1971 }
1972 else if (strcmp(temp, "--pscommands") == 0)
1973 {
1974 PSCommands = 1;
1975 continue;
1976 }
1977 else if (strcmp(temp, "--no-pscommands") == 0)
1978 {
1979 PSCommands = 0;
1980 continue;
1981 }
1982 else if (strcmp(temp, "--xrxcomments") == 0)
1983 {
1984 XRXComments = 1;
1985 continue;
1986 }
1987 else if (strcmp(temp, "--no-xrxcomments") == 0)
1988 {
1989 XRXComments = 0;
1990 continue;
1991 }
1992 else if (strncmp(temp, "--compression", 13) == 0)
1993 {
1994 if (strlen(temp) > 14)
1995 Compression = atoi(temp + 14);
1996 else
1997 Compression = 1;
1998 continue;
1999 }
2000 else if (strcmp(temp, "--no-compression") == 0)
2001 {
2002 Compression = 0;
2003 continue;
2004 }
2005 else if (strcmp(temp, "--no-jpeg") == 0)
2006 {
2007 OutputJPEG = 0;
2008 continue;
2009 }
2010 else if (strcmp(temp, "--numbered") == 0)
2011 {
2012 TocNumbers = 1;
2013 continue;
2014 }
2015 else if (strcmp(temp, "--no-numbered") == 0)
2016 {
2017 TocNumbers = 0;
2018 continue;
2019 }
2020 else if (strcmp(temp, "--no-toc") == 0)
2021 {
2022 TocLevels = 0;
2023 continue;
2024 }
2025 else if (strcmp(temp, "--title") == 0)
2026 {
2027 TitlePage = 1;
2028 continue;
2029 }
2030 else if (strcmp(temp, "--no-title") == 0)
2031 {
2032 TitlePage = 0;
2033 continue;
2034 }
2035 else if (strcmp(temp, "--book") == 0)
2036 {
2037 OutputType = OUTPUT_BOOK;
2038 continue;
2039 }
2040 else if (strcmp(temp, "--continuous") == 0)
2041 {
2042 OutputType = OUTPUT_CONTINUOUS;
2043 continue;
2044 }
2045 else if (strcmp(temp, "--webpage") == 0)
2046 {
2047 OutputType = OUTPUT_WEBPAGES;
2048 continue;
2049 }
2050 else if (strcmp(temp, "--encryption") == 0)
2051 {
2052 Encryption = 1;
2053 continue;
2054 }
2055 else if (strcmp(temp, "--no-encryption") == 0)
2056 {
2057 Encryption = 0;
2058 continue;
2059 }
2060 else if (strcmp(temp, "--strict") == 0)
2061 StrictHTML = 1;
2062 else if (strcmp(temp, "--no-strict") == 0)
2063 StrictHTML = 0;
2064 else if (strcmp(temp, "--overflow") == 0)
2065 OverflowErrors = 1;
2066 else if (strcmp(temp, "--no-overflow") == 0)
2067 OverflowErrors = 0;
2068
2069 if (*lineptr == '\"')
2070 {
2071 lineptr ++;
2072
2073 for (tempptr = temp2; *lineptr != '\0' && *lineptr != '\"'; lineptr ++)
2074 if (tempptr < (temp2 + sizeof(temp2) - 1))
2075 *tempptr++ = *lineptr;
2076
2077 if (*lineptr == '\"')
2078 lineptr ++;
2079 }
2080 else
2081 {
2082 for (tempptr = temp2; *lineptr != '\0' && *lineptr != ' '; lineptr ++)
2083 if (tempptr < (temp2 + sizeof(temp2) - 1))
2084 *tempptr++ = *lineptr;
2085 }
2086
2087 *tempptr = '\0';
2088
2089 if (strcmp(temp, "-t") == 0 && !CGIMode)
2090 {
2091 if (strcmp(temp2, "epub") == 0)
2092 *exportfunc = (exportfunc_t)epub_export;
2093 else if (strcmp(temp2, "html") == 0)
2094 *exportfunc = (exportfunc_t)html_export;
2095 else if (strcmp(temp2, "htmlsep") == 0)
2096 *exportfunc = (exportfunc_t)htmlsep_export;
2097 else if (strcmp(temp2, "pdf11") == 0)
2098 {
2099 *exportfunc = (exportfunc_t)pspdf_export;
2100 PSLevel = 0;
2101 PDFVersion = 11;
2102 }
2103 else if (strcmp(temp2, "pdf12") == 0)
2104 {
2105 *exportfunc = (exportfunc_t)pspdf_export;
2106 PSLevel = 0;
2107 PDFVersion = 12;
2108 }
2109 else if (strcmp(temp2, "pdf13") == 0)
2110 {
2111 *exportfunc = (exportfunc_t)pspdf_export;
2112 PSLevel = 0;
2113 PDFVersion = 13;
2114 }
2115 else if (strcmp(temp2, "pdf") == 0 ||
2116 strcmp(temp2, "pdf14") == 0)
2117 {
2118 *exportfunc = (exportfunc_t)pspdf_export;
2119 PSLevel = 0;
2120 PDFVersion = 14;
2121 }
2122 else if (strcmp(temp2, "ps1") == 0)
2123 {
2124 *exportfunc = (exportfunc_t)pspdf_export;
2125 PSLevel = 1;
2126 }
2127 else if (strcmp(temp2, "ps") == 0 ||
2128 strcmp(temp2, "ps2") == 0)
2129 {
2130 *exportfunc = (exportfunc_t)pspdf_export;
2131 PSLevel = 2;
2132 }
2133 else if (strcmp(temp2, "ps3") == 0)
2134 {
2135 *exportfunc = (exportfunc_t)pspdf_export;
2136 PSLevel = 3;
2137 }
2138 }
2139 else if (strcmp(temp, "--letterhead") == 0)
2140 strlcpy(Letterhead, temp2, sizeof(Letterhead));
2141 else if (strcmp(temp, "--logo") == 0 ||
2142 strcmp(temp, "--logoimage") == 0)
2143 strlcpy(LogoImage, temp2, sizeof(LogoImage));
2144 else if (strcmp(temp, "--titlefile") == 0 ||
2145 strcmp(temp, "--titleimage") == 0)
2146 {
2147 TitlePage = 1;
2148 strlcpy(TitleImage, temp2, sizeof(TitleImage));
2149 }
2150 else if (strcmp(temp, "-f") == 0 && !CGIMode)
2151 {
2152 OutputFiles = 0;
2153 strlcpy(OutputPath, temp2, sizeof(OutputPath));
2154 }
2155 else if (strcmp(temp, "-d") == 0 && !CGIMode)
2156 {
2157 OutputFiles = 1;
2158 strlcpy(OutputPath, temp2, sizeof(OutputPath));
2159 }
2160 else if (strcmp(temp, "--browserwidth") == 0)
2161 _htmlBrowserWidth = atof(temp2);
2162 else if (strcmp(temp, "--nup") == 0)
2163 NumberUp = atoi(temp2);
2164 else if (strcmp(temp, "--size") == 0)
2165 set_page_size(temp2);
2166 else if (strcmp(temp, "--left") == 0)
2167 PageLeft = get_measurement(temp2);
2168 else if (strcmp(temp, "--right") == 0)
2169 PageRight = get_measurement(temp2);
2170 else if (strcmp(temp, "--top") == 0)
2171 PageTop = get_measurement(temp2);
2172 else if (strcmp(temp, "--bottom") == 0)
2173 PageBottom = get_measurement(temp2);
2174 else if (strcmp(temp, "--header") == 0)
2175 get_format(temp2, Header);
2176 else if (strcmp(temp, "--header1") == 0)
2177 get_format(temp2, Header1);
2178 else if (strcmp(temp, "--footer") == 0)
2179 get_format(temp2, Footer);
2180 else if (strcmp(temp, "--bodycolor") == 0)
2181 strlcpy(BodyColor, temp2, sizeof(BodyColor));
2182 else if (strcmp(temp, "--bodyimage") == 0)
2183 strlcpy(BodyImage, temp2, sizeof(BodyImage));
2184 else if (strcmp(temp, "--textcolor") == 0)
2185 htmlSetTextColor((uchar *)temp2);
2186 else if (strcmp(temp, "--linkcolor") == 0)
2187 strlcpy(LinkColor, temp2, sizeof(LinkColor));
2188 else if (strcmp(temp, "--linkstyle") == 0)
2189 {
2190 if (strcmp(temp2, "plain") == 0)
2191 LinkStyle = 0;
2192 else
2193 LinkStyle = 1;
2194 }
2195 else if (strcmp(temp, "--toclevels") == 0)
2196 TocLevels = atoi(temp2);
2197 else if (strcmp(temp, "--tocheader") == 0)
2198 get_format(temp2, TocHeader);
2199 else if (strcmp(temp, "--tocfooter") == 0)
2200 get_format(temp2, TocFooter);
2201 else if (strcmp(temp, "--toctitle") == 0)
2202 strlcpy(TocTitle, temp2, sizeof(TocTitle));
2203 else if (strcmp(temp, "--fontsize") == 0)
2204 {
2205 fontsize = atof(temp2);
2206 fontspacing = _htmlSpacings[SIZE_P] / _htmlSizes[SIZE_P];
2207
2208 if (fontsize < 4.0f)
2209 fontsize = 4.0f;
2210 else if (fontsize > 24.0f)
2211 fontsize = 24.0f;
2212
2213 htmlSetBaseSize(fontsize, fontspacing);
2214 }
2215 else if (strcmp(temp, "--fontspacing") == 0)
2216 {
2217 fontsize = _htmlSizes[SIZE_P];
2218 fontspacing = atof(temp2);
2219
2220 if (fontspacing < 1.0f)
2221 fontspacing = 1.0f;
2222 else if (fontspacing > 3.0f)
2223 fontspacing = 3.0f;
2224
2225 htmlSetBaseSize(fontsize, fontspacing);
2226 }
2227 else if (!strcmp(temp, "--headingfont"))
2228 {
2229 if (!strcasecmp(temp2, "courier"))
2230 _htmlHeadingFont = TYPE_COURIER;
2231 else if (!strcasecmp(temp2, "times"))
2232 _htmlHeadingFont = TYPE_TIMES;
2233 else if (!strcasecmp(temp2, "helvetica") ||
2234 !strcasecmp(temp2, "arial"))
2235 _htmlHeadingFont = TYPE_HELVETICA;
2236 else if (!strcasecmp(temp2, "monospace"))
2237 _htmlHeadingFont = TYPE_MONOSPACE;
2238 else if (!strcasecmp(temp2, "serif"))
2239 _htmlHeadingFont = TYPE_SERIF;
2240 else if (!strcasecmp(temp2, "sans"))
2241 _htmlHeadingFont = TYPE_SANS_SERIF;
2242 }
2243 else if (!strcmp(temp, "--bodyfont"))
2244 {
2245 if (!strcasecmp(temp2, "monospace"))
2246 _htmlBodyFont = TYPE_MONOSPACE;
2247 else if (!strcasecmp(temp2, "serif"))
2248 _htmlBodyFont = TYPE_SERIF;
2249 else if (!strcasecmp(temp2, "sans"))
2250 _htmlBodyFont = TYPE_SANS_SERIF;
2251 else if (!strcasecmp(temp2, "courier"))
2252 _htmlBodyFont = TYPE_COURIER;
2253 else if (!strcasecmp(temp2, "times"))
2254 _htmlBodyFont = TYPE_TIMES;
2255 else if (!strcasecmp(temp2, "helvetica") ||
2256 !strcasecmp(temp2, "arial"))
2257 _htmlBodyFont = TYPE_HELVETICA;
2258 }
2259 else if (strcmp(temp, "--headfootsize") == 0)
2260 HeadFootSize = atof(temp2);
2261 else if (!strcmp(temp, "--headfootfont"))
2262 {
2263 if (!strcasecmp(temp2, "courier"))
2264 {
2265 HeadFootType = TYPE_COURIER;
2266 HeadFootStyle = STYLE_NORMAL;
2267 }
2268 else if (!strcasecmp(temp2, "courier-bold"))
2269 {
2270 HeadFootType = TYPE_COURIER;
2271 HeadFootStyle = STYLE_BOLD;
2272 }
2273 else if (!strcasecmp(temp2, "courier-oblique"))
2274 {
2275 HeadFootType = TYPE_COURIER;
2276 HeadFootStyle = STYLE_ITALIC;
2277 }
2278 else if (!strcasecmp(temp2, "courier-boldoblique"))
2279 {
2280 HeadFootType = TYPE_COURIER;
2281 HeadFootStyle = STYLE_BOLD_ITALIC;
2282 }
2283 else if (!strcasecmp(temp2, "times") ||
2284 !strcasecmp(temp2, "times-roman"))
2285 {
2286 HeadFootType = TYPE_TIMES;
2287 HeadFootStyle = STYLE_NORMAL;
2288 }
2289 else if (!strcasecmp(temp2, "times-bold"))
2290 {
2291 HeadFootType = TYPE_TIMES;
2292 HeadFootStyle = STYLE_BOLD;
2293 }
2294 else if (!strcasecmp(temp2, "times-italic"))
2295 {
2296 HeadFootType = TYPE_TIMES;
2297 HeadFootStyle = STYLE_ITALIC;
2298 }
2299 else if (!strcasecmp(temp2, "times-bolditalic"))
2300 {
2301 HeadFootType = TYPE_TIMES;
2302 HeadFootStyle = STYLE_BOLD_ITALIC;
2303 }
2304 else if (!strcasecmp(temp2, "helvetica"))
2305 {
2306 HeadFootType = TYPE_HELVETICA;
2307 HeadFootStyle = STYLE_NORMAL;
2308 }
2309 else if (!strcasecmp(temp2, "helvetica-bold"))
2310 {
2311 HeadFootType = TYPE_HELVETICA;
2312 HeadFootStyle = STYLE_BOLD;
2313 }
2314 else if (!strcasecmp(temp2, "helvetica-oblique"))
2315 {
2316 HeadFootType = TYPE_HELVETICA;
2317 HeadFootStyle = STYLE_ITALIC;
2318 }
2319 else if (!strcasecmp(temp2, "helvetica-boldoblique"))
2320 {
2321 HeadFootType = TYPE_HELVETICA;
2322 HeadFootStyle = STYLE_BOLD_ITALIC;
2323 }
2324 else if (!strcasecmp(temp2, "monospace"))
2325 {
2326 HeadFootType = TYPE_MONOSPACE;
2327 HeadFootStyle = STYLE_NORMAL;
2328 }
2329 else if (!strcasecmp(temp2, "monospace-bold"))
2330 {
2331 HeadFootType = TYPE_MONOSPACE;
2332 HeadFootStyle = STYLE_BOLD;
2333 }
2334 else if (!strcasecmp(temp2, "monospace-oblique"))
2335 {
2336 HeadFootType = TYPE_MONOSPACE;
2337 HeadFootStyle = STYLE_ITALIC;
2338 }
2339 else if (!strcasecmp(temp2, "monospace-boldoblique"))
2340 {
2341 HeadFootType = TYPE_MONOSPACE;
2342 HeadFootStyle = STYLE_BOLD_ITALIC;
2343 }
2344 else if (!strcasecmp(temp2, "serif") ||
2345 !strcasecmp(temp2, "serif-roman"))
2346 {
2347 HeadFootType = TYPE_SERIF;
2348 HeadFootStyle = STYLE_NORMAL;
2349 }
2350 else if (!strcasecmp(temp2, "serif-bold"))
2351 {
2352 HeadFootType = TYPE_SERIF;
2353 HeadFootStyle = STYLE_BOLD;
2354 }
2355 else if (!strcasecmp(temp2, "serif-italic"))
2356 {
2357 HeadFootType = TYPE_SERIF;
2358 HeadFootStyle = STYLE_ITALIC;
2359 }
2360 else if (!strcasecmp(temp2, "serif-bolditalic"))
2361 {
2362 HeadFootType = TYPE_SERIF;
2363 HeadFootStyle = STYLE_BOLD_ITALIC;
2364 }
2365 else if (!strcasecmp(temp2, "sans"))
2366 {
2367 HeadFootType = TYPE_SANS_SERIF;
2368 HeadFootStyle = STYLE_NORMAL;
2369 }
2370 else if (!strcasecmp(temp2, "sans-bold"))
2371 {
2372 HeadFootType = TYPE_SANS_SERIF;
2373 HeadFootStyle = STYLE_BOLD;
2374 }
2375 else if (!strcasecmp(temp2, "sans-oblique"))
2376 {
2377 HeadFootType = TYPE_SANS_SERIF;
2378 HeadFootStyle = STYLE_ITALIC;
2379 }
2380 else if (!strcasecmp(temp2, "sans-boldoblique"))
2381 {
2382 HeadFootType = TYPE_SANS_SERIF;
2383 HeadFootStyle = STYLE_BOLD_ITALIC;
2384 }
2385 }
2386 else if (strcmp(temp, "--charset") == 0)
2387 htmlSetCharSet(temp2);
2388 else if (strcmp(temp, "--pagemode") == 0)
2389 {
2390 for (i = 0; i < (int)(sizeof(PDFModes) / sizeof(PDFModes[0])); i ++)
2391 if (strcasecmp(temp2, PDFModes[i]) == 0)
2392 {
2393 PDFPageMode = i;
2394 break;
2395 }
2396 }
2397 else if (strcmp(temp, "--pagelayout") == 0)
2398 {
2399 for (i = 0; i < (int)(sizeof(PDFLayouts) / sizeof(PDFLayouts[0])); i ++)
2400 if (strcasecmp(temp2, PDFLayouts[i]) == 0)
2401 {
2402 PDFPageLayout = i;
2403 break;
2404 }
2405 }
2406 else if (strcmp(temp, "--firstpage") == 0)
2407 {
2408 for (i = 0; i < (int)(sizeof(PDFPages) / sizeof(PDFPages[0])); i ++)
2409 if (strcasecmp(temp2, PDFPages[i]) == 0)
2410 {
2411 PDFFirstPage = i;
2412 break;
2413 }
2414 }
2415 else if (strcmp(temp, "--pageeffect") == 0)
2416 {
2417 for (i = 0; i < (int)(sizeof(PDFEffects) / sizeof(PDFEffects[0])); i ++)
2418 if (strcasecmp(temp2, PDFEffects[i]) == 0)
2419 {
2420 PDFEffect = i;
2421 break;
2422 }
2423 }
2424 else if (strcmp(temp, "--pageduration") == 0)
2425 PDFPageDuration = atof(temp2);
2426 else if (strcmp(temp, "--effectduration") == 0)
2427 PDFEffectDuration = atof(temp2);
2428 else if (strcmp(temp, "--permissions") == 0)
2429 set_permissions(temp2);
2430 else if (strcmp(temp, "--user-password") == 0)
2431 strlcpy(UserPassword, temp2, sizeof(UserPassword));
2432 else if (strcmp(temp, "--owner-password") == 0)
2433 strlcpy(OwnerPassword, temp2, sizeof(OwnerPassword));
2434 else if (strcmp(temp, "--path") == 0)
2435 strlcpy(Path, temp2, sizeof(Path) - 1);
2436 else if (strcmp(temp, "--proxy") == 0)
2437 {
2438 strlcpy(Proxy, temp2, sizeof(Proxy));
2439 file_proxy(Proxy);
2440 }
2441 else if (strcmp(temp, "--cookies") == 0)
2442 file_cookies(temp2);
2443 }
2444 }
2445
2446
2447 //
2448 // 'read_file()' - Read a file into the current document.
2449 //
2450
2451 static int // O - 1 on success, 0 on failure
read_file(const char * filename,tree_t ** document,const char * path)2452 read_file(const char *filename, // I - File/URL to read
2453 tree_t **document, // IO - Current document
2454 const char *path) // I - Search path
2455 {
2456 FILE *docfile; // Document file
2457 tree_t *file; // HTML document file
2458 const char *realname, // Real name of file
2459 *ext; // Extension of filename
2460 char base[1024]; // Base directory name of file
2461
2462
2463 DEBUG_printf(("read_file(filename=\"%s\", document=%p, path=\"%s\")\n", filename, (void *)document, path));
2464
2465 if ((realname = file_find(path, filename)) != NULL)
2466 {
2467 if ((docfile = fopen(realname, "rb")) != NULL)
2468 {
2469 // Prepare to read the file...
2470 if (Verbosity > 0)
2471 progress_error(HD_ERROR_NONE, "INFO: Reading %s...", filename);
2472
2473 _htmlPPI = 72.0f * _htmlBrowserWidth / (PageWidth - PageLeft - PageRight);
2474
2475 strlcpy(base, file_directory(filename), sizeof(base));
2476 ext = file_extension(filename);
2477
2478 file = htmlAddTree(NULL, MARKUP_FILE, NULL);
2479 htmlSetVariable(file, (uchar *)"_HD_URL", (uchar *)filename);
2480 htmlSetVariable(file, (uchar *)"_HD_FILENAME", (uchar *)file_basename(filename));
2481 htmlSetVariable(file, (uchar *)"_HD_BASE", (uchar *)base);
2482
2483 if (ext && !strcmp(ext, "md"))
2484 {
2485 // Read markdown from a file...
2486 mdReadFile(file, docfile, base);
2487 }
2488 else
2489 {
2490 // Read HTML from a file...
2491 _htmlCurrentFile = filename;
2492 htmlReadFile(file, docfile, base);
2493 }
2494
2495 fclose(docfile);
2496
2497 if (*document == NULL)
2498 *document = file;
2499 else
2500 {
2501 while ((*document)->next != NULL)
2502 *document = (*document)->next;
2503
2504 (*document)->next = file;
2505 file->prev = *document;
2506 }
2507 }
2508 else
2509 {
2510 file = NULL;
2511 progress_error(HD_ERROR_FILE_NOT_FOUND, "Unable to open \"%s\" for reading...", filename);
2512 }
2513 }
2514 else
2515 {
2516 file = NULL;
2517 progress_error(HD_ERROR_FILE_NOT_FOUND, "Unable to find \"%s\"...", filename);
2518 }
2519
2520 return (file != NULL);
2521 }
2522
2523
2524 //
2525 // 'set_permissions()' - Set the PDF permission bits.
2526 //
2527
2528 void
set_permissions(const char * p)2529 set_permissions(const char *p) // I - Permission string
2530 {
2531 char *copyp, // Copy of string
2532 *start, // Start of current keyword
2533 *ptr; // Pointer into string
2534
2535
2536 // Range check input...
2537 if (!p || !*p)
2538 return;
2539
2540 // Make a copy of the string and parse it...
2541 copyp = strdup(p);
2542 if (!copyp)
2543 return;
2544
2545 for (start = copyp; *start; start = ptr)
2546 {
2547 for (ptr = start; *ptr; ptr ++)
2548 if (*ptr == ',')
2549 {
2550 *ptr++ = '\0';
2551 break;
2552 }
2553
2554 if (!strcasecmp(start, "all"))
2555 Permissions = -4;
2556 else if (!strcasecmp(start, "none"))
2557 Permissions = -64;
2558 else if (!strcasecmp(start, "print"))
2559 Permissions |= PDF_PERM_PRINT;
2560 else if (!strcasecmp(start, "no-print"))
2561 Permissions &= ~PDF_PERM_PRINT;
2562 else if (!strcasecmp(start, "modify"))
2563 Permissions |= PDF_PERM_MODIFY;
2564 else if (!strcasecmp(start, "no-modify"))
2565 Permissions &= ~PDF_PERM_MODIFY;
2566 else if (!strcasecmp(start, "copy"))
2567 Permissions |= PDF_PERM_COPY;
2568 else if (!strcasecmp(start, "no-copy"))
2569 Permissions &= ~PDF_PERM_COPY;
2570 else if (!strcasecmp(start, "annotate"))
2571 Permissions |= PDF_PERM_ANNOTATE;
2572 else if (!strcasecmp(start, "no-annotate"))
2573 Permissions &= ~PDF_PERM_ANNOTATE;
2574 }
2575
2576 if (Permissions != -4)
2577 Encryption = 1;
2578
2579 free(copyp);
2580 }
2581
2582
2583 #ifndef WIN32
2584 //
2585 // 'term_handler()' - Handle CTRL-C or kill signals...
2586 //
2587
2588 static void
term_handler(int signum)2589 term_handler(int signum) // I - Signal number
2590 {
2591 REF(signum);
2592
2593 file_cleanup();
2594 image_flush_cache();
2595 exit(1);
2596 }
2597 #endif // !WIN32
2598
2599
2600 /*
2601 * 'usage()' - Show program version and command-line options.
2602 */
2603
2604 static void
usage(const char * arg)2605 usage(const char *arg) // I - Bad argument string
2606 {
2607 if (CGIMode)
2608 puts("Content-Type: text/plain\r\n\r");
2609
2610 puts("HTMLDOC Version " SVERSION " Copyright 2011-2020 by Michael R Sweet.");
2611 puts("HTMLDOC is provided under the terms of the GNU General Public License and");
2612 puts("comes with absolutely no warranty. This software is based in part on the work");
2613 puts("of the Independent JPEG Group.");
2614 puts("");
2615
2616 #ifdef HAVE_SSL
2617 puts("This copy of HTMLDOC has been built to support both http: and https: URLs.");
2618 #else
2619 puts("This copy of HTMLDOC has been built to support http: URLs only.");
2620 #endif /* HAVE_SSL */
2621 puts("");
2622
2623 if (CGIMode)
2624 {
2625 puts("HTMLDOC is running in CGI mode. To disable CGI mode when running");
2626 puts("from a server-side script/page, set the HTMLDOC_NOCGI environment");
2627 puts("variable prior to running HTMLDOC.");
2628 puts("");
2629 puts("If you are trying to use CGI mode, make sure that the ServerName");
2630 puts("for the web server is accessible from the local system. If you");
2631 puts("are using Apache 2.0.30 or later, make sure you set 'AcceptPathInfo'");
2632 puts("to 'On' for the HTMLDOC/cgi-bin directory.");
2633 }
2634 else
2635 {
2636 if (arg && arg[0] == '-')
2637 printf("ERROR: Bad option argument \"%s\"!\n\n", arg);
2638 else
2639 printf("ERROR: %s\n", arg);
2640
2641 puts("");
2642 puts("Usage:");
2643 puts(" htmldoc [options] filename1.html [ ... filenameN.html ]");
2644 #ifdef HAVE_LIBFLTK
2645 puts(" htmldoc filename.book");
2646 #endif // HAVE_LIBFLTK
2647 puts("");
2648 puts("Options:");
2649 puts("");
2650 puts(" --batch filename.book");
2651 puts(" --bodycolor color");
2652 puts(" --bodyfont {courier,helvetica,monospace,sans,serif,times}");
2653 puts(" --bodyimage filename.{bmp,gif,jpg,png}");
2654 puts(" --book");
2655 puts(" --bottom margin{in,cm,mm}");
2656 puts(" --browserwidth pixels");
2657 puts(" --charset {cp-874...1258,iso-8859-1...-15,koi8-r,utf-8}");
2658 puts(" --color");
2659 puts(" --compression[=level]");
2660 puts(" --continuous");
2661 puts(" --cookies 'name=\"value with space\"; name=value'");
2662 puts(" --datadir directory");
2663 puts(" --duplex");
2664 puts(" --effectduration {0.1..10.0}");
2665 puts(" --embedfonts");
2666 puts(" --encryption");
2667 puts(" --firstpage {p1,toc,c1}");
2668 puts(" --fontsize {4.0..24.0}");
2669 puts(" --fontspacing {1.0..3.0}");
2670 puts(" --footer fff");
2671 puts(" {--format, -t} {epub,html,htmlsep,pdf11,pdf12,pdf13,pdf14,ps1,ps2,ps3}");
2672 puts(" --gray");
2673 puts(" --header fff");
2674 puts(" --header1 fff");
2675 puts(" --headfootfont {courier{-bold,-oblique,-boldoblique},\n"
2676 " helvetica{-bold,-oblique,-boldoblique},\n"
2677 " monospace{-bold,-oblique,-boldoblique},\n"
2678 " sans{-bold,-oblique,-boldoblique},\n"
2679 " serif{-bold,-italic,-bolditalic},\n"
2680 " times{-roman,-bold,-italic,-bolditalic}}\n");
2681 puts(" --headfootsize {6.0..24.0}");
2682 puts(" --headingfont {courier,helvetica,monospace,sans,serif,times}");
2683 puts(" --help");
2684 #ifdef HAVE_LIBFLTK
2685 puts(" --helpdir directory");
2686 #endif // HAVE_LIBFLTK
2687 for (int i = 0; i < MAX_HF_IMAGES; i ++)
2688 printf(" --hfimage%d filename.{bmp,gif,jpg,png}\n", i);
2689 puts(" --jpeg[=quality]");
2690 puts(" --landscape");
2691 puts(" --left margin{in,cm,mm}");
2692 puts(" --letterhead filename.{bmp,gif,jpg,png}");
2693 puts(" --linkcolor color");
2694 puts(" --links");
2695 puts(" --linkstyle {plain,underline}");
2696 puts(" --logoimage filename.{bmp,gif,jpg,png}");
2697 puts(" --no-compression");
2698 puts(" --no-duplex");
2699 puts(" --no-embedfonts");
2700 puts(" --no-encryption");
2701 puts(" --no-links");
2702 puts(" --no-localfiles");
2703 puts(" --no-numbered");
2704 puts(" --no-overflow");
2705 puts(" --no-pscommands");
2706 puts(" --no-strict");
2707 puts(" --no-title");
2708 puts(" --no-toc");
2709 puts(" --numbered");
2710 puts(" --nup {1,2,4,6,9,16}");
2711 puts(" {--outdir, -d} dirname");
2712 puts(" {--outfile, -f} filename.{epub,html,pdf,ps}");
2713 puts(" --overflow");
2714 puts(" --owner-password password");
2715 puts(" --pageduration {1.0..60.0}");
2716 puts(" --pageeffect {none,bi,bo,d,gd,gdr,gr,hb,hsi,hso,vb,vsi,vso,wd,wl,wr,wu}");
2717 puts(" --pagelayout {single,one,twoleft,tworight}");
2718 puts(" --pagemode {document,outline,fullscreen}");
2719 puts(" --path \"dir1;dir2;dir3;...;dirN\"");
2720 puts(" --permissions {all,annotate,copy,modify,print,no-annotate,no-copy,no-modify,no-print,none}");
2721 puts(" --portrait");
2722 puts(" --proxy http://host:port");
2723 puts(" --pscommands");
2724 puts(" --quiet");
2725 puts(" --referer url");
2726 puts(" --right margin{in,cm,mm}");
2727 puts(" --size {letter,a4,WxH{in,cm,mm},etc}");
2728 puts(" --strict");
2729 puts(" --textcolor color");
2730 puts(" --textfont {courier,times,helvetica}");
2731 puts(" --title");
2732 puts(" --titlefile filename.{htm,html,shtml}");
2733 puts(" --titleimage filename.{bmp,gif,jpg,png}");
2734 puts(" --tocfooter fff");
2735 puts(" --tocheader fff");
2736 puts(" --toclevels levels");
2737 puts(" --toctitle string");
2738 puts(" --top margin{in,cm,mm}");
2739 puts(" --user-password password");
2740 puts(" {--verbose, -v}");
2741 puts(" --version");
2742 puts(" --webpage");
2743 puts("");
2744 puts(" fff = heading format string; each \'f\' can be one of:");
2745 puts("");
2746 puts(" . = blank");
2747 puts(" / = n/N arabic page numbers (1/3, 2/3, 3/3)");
2748 puts(" : = c/C arabic chapter page numbers (1/2, 2/2, 1/4, 2/4, ...)");
2749 puts(" 1 = arabic numbers (1, 2, 3, ...)");
2750 puts(" a = lowercase letters");
2751 puts(" A = uppercase letters");
2752 puts(" c = current chapter heading");
2753 puts(" C = current chapter page number (arabic)");
2754 puts(" d = current date");
2755 puts(" D = current date and time");
2756 puts(" h = current heading");
2757 puts(" i = lowercase roman numerals");
2758 puts(" I = uppercase roman numerals");
2759 puts(" l = logo image");
2760 puts(" L = letterhead image");
2761 puts(" t = title text");
2762 puts(" T = current time");
2763 puts(" u = current file/URL");
2764 }
2765
2766 exit(1);
2767 }
2768