1 rizwank 1.1 /*
2 * Argument handling and main.
3 * Copyright (c) 1995-2000, 2002 Markku Rossi.
4 *
5 * Author: Markku Rossi <mtr@iki.fi>
6 */
7
8 /*
9 * This file is part of GNU enscript.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 rizwank 1.1 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
25 */
26
27 #include "gsint.h"
28 #include "getopt.h"
29
30 /*
31 * Prototypes for static functions.
32 */
33
34 /*
35 * Open output file according to user options. Void if output file
36 * has already been opened.
37 */
38 static void open_output_file ();
39
40 /* Close output file. */
41 static void close_output_file ();
42
43 rizwank 1.1 /* Handle options from environment variable <var> */
44 static void handle_env_options ___P ((char *var));
45
46 /* Handle options from <argv> array. */
47 static void handle_options ___P ((int argc, char *argv[]));
48
49 /* Print usage info. */
50 static void usage ();
51
52 /* Print version info. */
53 static void version ();
54
55
56 /*
57 * Global variables.
58 */
59
60 char *program; /* Program's name, used for messages. */
61 FILE *ofp = NULL; /* Output file. */
62 void *printer_context; /* Context for the printer. */
63 char *version_string = NULL; /* Enscript's version string. */
64 rizwank 1.1 char *ps_version_string = NULL; /* Version string for PS procsets. */
65 char *date_string = NULL; /* Preformatted time string. */
66 struct tm run_tm; /* Time when program is run. */
67 struct tm mod_tm; /* Last modification time for current file. */
68 struct passwd *passwd; /* Passwd entry for the user running this
69 program. */
70
71 /* Path to our library. */
72 char *enscript_library = LIBRARY;
73
74 /* Library lookup path. */
75 char *libpath = NULL;
76
77 /* AFM library lookup path. */
78 char *afm_path = NULL;
79
80 MediaEntry *media_names = NULL; /* List of known media. */
81 MediaEntry *media = NULL; /* Entry for used media. */
82 int bs = 8; /* The backspace character. */
83
84 /* Statistics. */
85 rizwank 1.1 int total_pages = 0; /* Total number of pages printed. */
86 int num_truncated_lines = 0; /* Number of lines truncated. */
87 int num_missing_chars = 0; /* Number of unknown characters. */
88 int missing_chars[256] = {0}; /* Table of unknown characters. */
89 int num_non_printable_chars = 0; /* Number of non-printable characters. */
90 int non_printable_chars[256] = {0}; /* Table of non-printable characters. */
91
92 /* Output media dimensions that are used during PostScript emission. */
93 int d_page_w = 0; /* page's width */
94 int d_page_h = 0; /* page's height */
95 int d_header_w = 0; /* fancy header's width */
96 int d_header_h = 0; /* fancy header's height */
97 int d_footer_h = 0; /* fancy footer's height */
98 int d_output_w = 0; /* output area's width */
99 int d_output_h = 0; /* output area's height */
100 int d_output_x_margin = 5; /* output area's x marginal */
101 int d_output_y_margin = 2; /* output area's y marginal */
102
103 /* Document needed resources. */
104 StringHashPtr res_fonts; /* fonts */
105
106 rizwank 1.1 /* Fonts to download. */
107 StringHashPtr download_fonts;
108
109 /* Additional key-value pairs, passed to the generated PostScript code. */
110 StringHashPtr pagedevice; /* for setpagedevice */
111 StringHashPtr statusdict; /* for statusdict */
112
113 /* User defined strings. */
114 StringHashPtr user_strings;
115
116 /* Cache for AFM files. */
117 StringHashPtr afm_cache = NULL;
118 StringHashPtr afm_info_cache = NULL;
119
120 /* AFM library handle. */
121 AFMHandle afm = NULL;
122
123
124 /* Options. */
125
126 /*
127 rizwank 1.1 * Free single-letter options are: Q, x, y, Y
128 */
129
130 /*
131 * -#
132 *
133 * An alias for -n, --copies.
134 */
135
136 /*
137 * -1, -2, -3, -4, -5, -6, -7, -8, -9, --columns=NUM
138 *
139 * Number of columns per page. The default is 1 column.
140 */
141 int num_columns = 1;
142
143 /*
144 * -a PAGES, --pages=PAGES
145 *
146 * Specify which pages are printed.
147 */
148 rizwank 1.1 PageRange *page_ranges = NULL;
149
150 /*
151 * -A ALIGN, --file-align=ALIGN
152 *
153 * Align input files to start from ALIGN page count. This is handy
154 * for two-side printings.
155 */
156 unsigned int file_align = 1;
157
158 /*
159 * -b STRING, --header=STRING
160 *
161 * Set the string that is used as the page header. As a default, page
162 * header is constructed from filename, date and page number.
163 */
164 char *page_header = NULL;
165
166 /*
167 * -B, --no-header
168 *
169 rizwank 1.1 * Do not print page headers.
170 */
171
172 /*
173 * -c, --truncate-lines
174 *
175 * Truncate lines that are longer than the page width. Default is character
176 * wrap.
177 */
178 LineEndType line_end = LE_CHAR_WRAP;
179
180 /*
181 * -C [START], --line-numbers[=START]
182 *
183 * Precede each line with its line number. As a default, do not mark
184 * line numbers. If the optional argument START is given, it
185 * specifies the number from which the line numbers are assumed to
186 * start in the file. This is useful if the file contains a region
187 * of a bigger file.
188 */
189 int line_numbers = 0;
190 rizwank 1.1 unsigned int start_line_number = 1;
191
192 /*
193 * -d, -P, --printer
194 *
195 * Name of the printer to which output is send. Defaults to system's
196 * default printer.
197 */
198 char *printer = NULL;
199
200 /*
201 * -e [CHAR], --escapes[=CHAR]
202 *
203 * Enable special escape ('\000') interpretation. If option CHAR is given
204 * it is assumed to specify the escape character.
205 */
206 int special_escapes = 0;
207 int escape_char = '\0';
208 int default_escape_char;
209
210 /*
211 rizwank 1.1 * -E [LANG], --highlight=[LANG] (deprecated --pretty-print[=LANG])
212 *
213 * Highlight program source code. Highlighting is handled by creating
214 * an input filter with the states-program. States makes an educated
215 * guess about the start state but sometimes it fails, so the start
216 * state can also be specified to be LANG. This option overwrites
217 * input filter and enables special escapes.
218 */
219
220 int highlight = 0;
221 char *hl_start_state = NULL;
222
223 /*
224 * -f, --font
225 *
226 * Select body font.
227 */
228 char *Fname = "Courier";
229 FontPoint Fpt = {10.0, 10.0};
230 FontPoint default_Fpt; /* Point size of the original font. */
231 char *default_Fname; /* Name of the original font. */
232 rizwank 1.1 InputEncoding default_Fencoding; /* The encoding of the original font. */
233 int user_body_font_defined = 0; /* Has user defined new body font? */
234
235 double font_widths[256]; /* Width array for body font. */
236 char font_ctype[256]; /* Font character types. */
237 int font_is_fixed; /* Is body font a fixed pitch font? */
238 double font_bbox_lly; /* Font's bounding box's lly-coordinate. */
239
240 /*
241 * -F, --header-font
242 *
243 * Select font to be used to print the standard simple header.
244 */
245 char *HFname = "Courier-Bold";
246 FontPoint HFpt = {10.0, 10.0};
247
248 /*
249 * -g, --print-anyway
250 *
251 * Print document even it contains binary data. This does nothing
252 * since enscript prints files anyway.
253 rizwank 1.1 */
254
255 /*
256 * -G, --fancy-header
257 *
258 * Add a fancy header to top of every page. There are several header styles
259 * but the default is 'no fancy header'.
260 */
261 HeaderType header = HDR_SIMPLE;
262 char *fancy_header_name = NULL;
263 char *fancy_header_default = NULL;
264
265 /*
266 * -h, --no-job-header
267 *
268 * Supress the job header page.
269 */
270 static int no_job_header = 0;
271
272 /*
273 * -H num, --highlight-bars=num
274 rizwank 1.1 *
275 * Print highlight bars under text. Bars will be <num> lines high.
276 * As a default, do not print bars.
277 */
278 unsigned int highlight_bars = 0;
279
280 /*
281 * -i, --indent
282 *
283 * Indent every line this many characters.
284 */
285 double line_indent = 0.0;
286 char *line_indent_spec = "0";
287
288 /*
289 * -I CMD, --filter=CMD
290 *
291 * Read input files through input filter CMD.
292 */
293 char *input_filter = NULL;
294
295 rizwank 1.1 /*
296 * -j, --borders
297 *
298 * Print borders around columns.
299 */
300 int borders = 0;
301
302 /*
303 * -J
304 *
305 * An alias for -t, --title.
306 */
307
308 /*
309 * -k, --page-prefeed
310 * -K, --no-page-prefeed
311 *
312 * Control page prefeed.
313 */
314 int page_prefeed = 0;
315
316 rizwank 1.1 /*
317 * -l, --lineprinter
318 *
319 * Emulate lineprinter - make pages 66 lines long and omit headers.
320 */
321
322 /*
323 * -L, --lines-per-page
324 *
325 * Specify how many lines should be printed on a single page. Normally
326 * enscript counts it from font point sizes.
327 */
328 unsigned int lines_per_page = (unsigned int) -1;
329
330 /*
331 * -m, --mail
332 *
333 * Send mail notification to user after print job has been completed.
334 */
335 int mail = 0;
336
337 rizwank 1.1 /*
338 * -M, --media
339 *
340 * Name of the output media. Default is A4.
341 */
342 char *media_name = NULL;
343
344 /*
345 * -n, --copies
346 *
347 * Number of copies to print.
348 */
349 int num_copies = 1;
350
351 /*
352 * -N, --newline
353 *
354 * Set the newline character: '\n' or '\r'. As a default, the newline
355 * character is specified by the input encoding.
356 */
357 int nl = -1;
358 rizwank 1.1
359 /*
360 * -o, -p, --output
361 *
362 * Leave output to the specified file. As a default result is spooled to
363 * printer.
364 */
365 char *output_file = OUTPUT_FILE_NONE;
366
367 /*
368 * -O, --missing-characters
369 *
370 * List all missing characters. Default is no listing.
371 */
372 int list_missing_characters = 0;
373
374 /*
375 * -q, --quiet
376 *
377 * Do not tell what we are doing. Default is to tell something but
378 * not --verbose.
379 rizwank 1.1 */
380 int quiet = 0;
381
382 /*
383 * -r, --landscape
384 * -R, --portrait
385 *
386 * Print with page rotated 90 degrees (landscape mode). Default is
387 * portrait.
388 */
389 int landscape = 0;
390
391 /*
392 * -s, --baselineskip
393 *
394 * Specify baselineskip value that is used when enscript moves to
395 * a new line. Current point movement is font_point_size + baselineskip.
396 */
397 double baselineskip = 1.0;
398
399 /*
400 rizwank 1.1 * -t, --title
401 *
402 * Title which is printed to the banner page. If this option is given
403 * from the command line, this sets also the name of the stdin which
404 * is by the default "".
405 */
406 char *title = "Enscript Output";
407 int title_given = 0;
408
409 /*
410 * -T, --tabsize
411 *
412 * Specify tabulator size.
413 */
414 int tabsize = 8;
415
416 /*
417 * -u, --underlay
418 *
419 * Place text under every page. Default is no underlay.
420 */
421 rizwank 1.1 double ul_gray = .8;
422 FontPoint ul_ptsize = {200.0, 200.0};
423 char *ul_font = "Times-Roman";
424 char *underlay = NULL;
425 char *ul_position = NULL; /* Position info as a string. */
426 double ul_x; /* Position x-coordinate. */
427 double ul_y; /* Position y-coordinate. */
428 double ul_angle;
429 unsigned int ul_style = UL_STYLE_OUTLINE;
430 char *ul_style_str = NULL;
431 int ul_position_p = 0; /* Is ul-position given? */
432 int ul_angle_p = 0; /* Is ul-angle given? */
433
434 /*
435 * -U NUM, --nup=NUM
436 *
437 * Print NUM PostScript pages on each output page (n-up printing).
438 */
439 unsigned int nup = 1;
440 unsigned int nup_exp = 0;
441 unsigned int nup_rows = 1;
442 rizwank 1.1 unsigned int nup_columns = 1;
443 int nup_landscape = 0;
444 unsigned int nup_width;
445 unsigned int nup_height;
446 double nup_scale;
447
448 /*
449 * -v, --verbose
450 *
451 * Tell what we are doing. Default is no verbose outputs.
452 */
453 int verbose = 0;
454
455 /*
456 * -V, --version
457 *
458 * Print version information.
459 */
460
461 /*
462 * -w LANGUAGE, --language=LANGUAGE
463 rizwank 1.1 *
464 * Generate output for language LANGUAGE. The default is PostScript.
465 */
466 char *output_language = "PostScript";
467 int output_language_pass_through = 0;
468
469 /*
470 * -W APP,option, --options=APP,OPTION
471 *
472 * Pass additional option to enscript's helper applications. The
473 * first part of the option's argument (APP) specifies the
474 * helper application to which the options are added. Currently the
475 * following helper application are defined:
476 *
477 * s states
478 */
479 Buffer *helper_options[256] = {0};
480
481 /*
482 * -X, --encoding
483 *
484 rizwank 1.1 * Specifies input encoding. Default is ISO-8859.1.
485 */
486 InputEncoding encoding = ENC_ISO_8859_1;
487 char *encoding_name = NULL;
488
489 /*
490 * -z, --no-formfeed
491 *
492 * Do not interpret form feed characters. As a default, form feed
493 * characters are interpreted.
494 */
495 int interpret_formfeed = 1;
496
497 /*
498 * -Z, --pass-through
499 *
500 * Pass through all PostScript and PCL files without any modifications.
501 * As a default, don't.
502 */
503 int pass_through = 0;
504
505 rizwank 1.1 /*
506 * --color[=bool]
507 *
508 * Create color output with states?
509 */
510
511 /*
512 * --continuous-page-numbers
513 *
514 * Count page numbers across input files. Don't restart numbering
515 * at beginning of each file.
516 */
517 int continuous_page_numbers = 0;
518
519 /*
520 * --download-font=FONT
521 *
522 * Download font FONT to printer.
523 */
524
525 /*
526 rizwank 1.1 * --extended-return-values
527 *
528 * Enable extended return values.
529 */
530 int extended_return_values = 0;
531
532 /*
533 * --filter-stdin=STR
534 *
535 * How stdin is shown to the filter command. The default is "" but
536 * some utilities might want it as "-".
537 */
538 char *input_filter_stdin = "";
539
540 /*
541 * --footer=STRING
542 *
543 * Set the string that is used as the page footer. As a default, the
544 * page has no footer. Setting this option does not necessary show
545 * any footer strings in the output. It depends on the selected
546 * header (`.hdr' file) whether it supports footer strings or not.
547 rizwank 1.1 */
548 char *page_footer = NULL;
549
550 /*
551 * --h-column-height=HEIGHT
552 *
553 * Set the horizontal column (channel) height to be HEIGHT. This option
554 * also sets the FormFeedType to `hcolumn'. The default value is set to be
555 * big enough to cause a jump to the next vertical column (100m).
556 */
557 double horizontal_column_height = 283465.0;
558
559 /*
560 * --help-highlight (deprecated --help-pretty-print)
561 *
562 * Descript all supported -E, --highlight languages and file formats.
563 */
564 int help_highlight = 0;
565
566 /*
567 * --highlight-bar-gray=val
568 rizwank 1.1 *
569 * Specify the gray level for highlight bars.
570 */
571 double highlight_bar_gray = .97;
572
573 /*
574 * --list-media
575 *
576 * List all known media. As a default do not list media names.
577 */
578 int list_media = 0;
579
580 /*
581 * --margins=LEFT:RIGHT:TOP:BOTTOM
582 *
583 * Adjust page marginals.
584 */
585 char *margins_spec = NULL;
586
587 /*
588 * --mark-wrapped-lines[=STYLE]
589 rizwank 1.1 *
590 * Mark wrapped lines so that they can be easily detected from the printout.
591 * Optional parameter STYLE specifies the marking style, the system default
592 * is black box.
593 */
594 char *mark_wrapped_lines_style_name = NULL;
595 MarkWrappedLinesStyle mark_wrapped_lines_style = MWLS_NONE;
596
597 /*
598 * --non-printable-format=FORMAT
599 *
600 * Format in which non-printable characters are printed.
601 */
602 char *npf_name = NULL;
603 NonPrintableFormat non_printable_format = NPF_OCTAL;
604
605 /*
606 * --nup-columnwise
607 *
608 * Layout N-up pages colunwise instead of row-wise.
609 */
610 rizwank 1.1 int nup_columnwise = 0;
611
612 /*
613 * --nup-xpad=NUM
614 *
615 * The x-padding between N-up subpages.
616 */
617 unsigned int nup_xpad = 10;
618
619 /*
620 * --nup-ypad=NUM
621 *
622 * The y-padding between N-up subpages.
623 */
624 unsigned int nup_ypad = 10;
625
626 /*
627 * --page-label-format=FORMAT
628 *
629 * Format in which page labels are printed; the default is "short".
630 */
631 rizwank 1.1 char *page_label_format = NULL;
632 PageLabelFormat page_label;
633
634 /*
635 * --ps-level=LEVEL
636 *
637 * The PostScript language level that enscript should use; the default is 2.
638 */
639 unsigned int pslevel = 2;
640
641 /*
642 * --printer-options=OPTIONS
643 *
644 * Pass extra options OPTIONS to the printer spooler.
645 */
646 char *printer_options = NULL;
647
648 /*
649 * --rotate-even-pages
650 *
651 * Rotate each even-numbered page 180 degrees. This might be handy in
652 rizwank 1.1 * two-side printing when the resulting pages are bind from some side.
653 * Greetings to Jussi-Pekka Sairanen.
654 */
655 int rotate_even_pages = 0;
656
657 /*
658 * --slice=NUM
659 *
660 * Horizontal input slicing. Print only NUMth wrapped input pages.
661 */
662 int slicing = 0;
663 unsigned int slice = 1;
664
665 /*
666 * --swap-even-page-margins
667 *
668 * Swap left and right side margins for each even numbered page. This
669 * might be handy in two-side printing.
670 */
671 int swap_even_page_margins = 0;
672
673 rizwank 1.1 /*
674 * --toc
675 *
676 * Print Table of Contents page.
677 */
678 int toc = 0;
679 FILE *toc_fp;
680 char *toc_fmt_string;
681
682 /*
683 * --word-wrap
684 *
685 * Wrap long lines from word boundaries. The default is character wrap.
686 */
687
688 /*
689 * AcceptCompositeCharacters: bool
690 *
691 * Specify whatever we accept composite characters or should them be
692 * considered as non-existent. As a default, do not accept them.
693 */
694 rizwank 1.1 int accept_composites = 0;
695
696 /*
697 * AppendCtrlD: bool
698 *
699 * Append ^D character to the end of the output. Some printers require this
700 * but the default is false.
701 */
702 int append_ctrl_D = 0;
703
704 /*
705 * Clean7Bit: bool
706 *
707 * Specify how characters greater than 127 are printed.
708 */
709 int clean_7bit = 1;
710
711 /*
712 * FormFeedType: type
713 *
714 * Specify what to do when a formfeed character is encountered from the
715 rizwank 1.1 * input stream. The default action is to jump to the beginning of the
716 * next column.
717 */
718 FormFeedType formfeed_type = FORMFEED_COLUMN;
719
720 /*
721 * GeneratePageSize: bool
722 *
723 * Specify whether the `PageSize' pagedevice definitions should be
724 * generated to the output.
725 */
726 int generate_PageSize = 1;
727
728 /*
729 * NoJobHeaderSwitch: switch
730 *
731 * Spooler switch to suppress the job header (-h).
732 */
733 char *no_job_header_switch = NULL;
734
735 /*
736 rizwank 1.1 * OutputFirstLine: line
737 *
738 * Set the PostScript output's first line to something your system can handle.
739 * The default is "%!PS-Adobe-3.0"
740 */
741 char *output_first_line = NULL;
742
743 /*
744 * QueueParam: param
745 *
746 * The spooler command switch to select the printer queue (-P).
747 */
748 char *queue_param = NULL;
749
750 /*
751 * Spooler: command
752 *
753 * The spooler command name (lpr).
754 */
755 char *spooler_command = NULL;
756
757 rizwank 1.1 /*
758 * StatesBinary: path
759 *
760 * An absolute path to the `states' binary.
761 */
762
763 char *states_binary = NULL;
764
765 /*
766 * StatesColor: bool
767 *
768 * Should the States program generate color outputs.
769 */
770 int states_color = 0;
771
772 /*
773 * StatesConfigFile: file
774 *
775 * The name of the states' configuration file.
776 */
777 char *states_config_file = NULL;
778 rizwank 1.1
779 /*
780 * StatesHighlightStyle: style
781 *
782 * The highlight style.
783 */
784 char *states_highlight_style = NULL;
785
786 /*
787 * StatesPath: path
788 *
789 * Define the path for the states program. The states program will
790 * lookup its state definition files from this path.
791 */
792 char *states_path = NULL;
793
794 /* ^@shade{GRAY}, set the line highlight gray. */
795 double line_highlight_gray = 1.0;
796
797 /* ^@bggray{GRAY}, set the text background gray. */
798 double bggray = 1.0;
799 rizwank 1.1
800 EncodingRegistry encodings[] =
801 {
802 {{"88591", "latin1", NULL}, ENC_ISO_8859_1, '\n', 8},
803 {{"88592", "latin2", NULL}, ENC_ISO_8859_2, '\n', 8},
804 {{"88593", "latin3", NULL}, ENC_ISO_8859_3, '\n', 8},
805 {{"88594", "latin4", NULL}, ENC_ISO_8859_4, '\n', 8},
806 {{"88595", "cyrillic", NULL}, ENC_ISO_8859_5, '\n', 8},
807 {{"88597", "greek", NULL}, ENC_ISO_8859_7, '\n', 8},
808 {{"88599", "latin5", NULL}, ENC_ISO_8859_9, '\n', 8},
809 {{"885910", "latin6", NULL}, ENC_ISO_8859_10, '\n', 8},
810 {{"ascii", NULL, NULL}, ENC_ASCII, '\n', 8},
811 {{"asciifise", "asciifi", "asciise"}, ENC_ASCII_FISE, '\n', 8},
812 {{"asciidkno", "asciidk", "asciino"}, ENC_ASCII_DKNO, '\n', 8},
813 {{"ibmpc", "pc", "dos"}, ENC_IBMPC, '\n', 8},
814 {{"mac", NULL, NULL}, ENC_MAC, '\r', 8},
815 {{"vms", NULL, NULL}, ENC_VMS, '\n', 8},
816 {{"hp8", NULL, NULL}, ENC_HP8, '\n', 8},
817 {{"koi8", NULL, NULL}, ENC_KOI8, '\n', 8},
818 {{"ps", "PS", NULL}, ENC_PS, '\n', 8},
819 {{"pslatin1", "ISOLatin1Encoding", NULL}, ENC_ISO_8859_1, '\n', 8},
820 rizwank 1.1
821 {{NULL, NULL, NULL}, 0, 0, 0},
822 };
823
824
825 /*
826 * Static variables.
827 */
828
829 static struct option long_options[] =
830 {
831 {"columns", required_argument, 0, 0},
832 {"pages", required_argument, 0, 'a'},
833 {"file-align", required_argument, 0, 'A'},
834 {"header", required_argument, 0, 'b'},
835 {"no-header", no_argument, 0, 'B'},
836 {"truncate-lines", no_argument, 0, 'c'},
837 {"line-numbers", optional_argument, 0, 'C'},
838 {"printer", required_argument, 0, 'd'},
839 {"setpagedevice", required_argument, 0, 'D'},
840 {"escapes", optional_argument, 0, 'e'},
841 rizwank 1.1 {"highlight", optional_argument, 0, 'E'},
842 {"font", required_argument, 0, 'f'},
843 {"header-font", required_argument, 0, 'F'},
844 {"print-anyway", no_argument, 0, 'g'},
845 {"fancy-header", optional_argument, 0, 'G'},
846 {"no-job-header", no_argument, 0, 'h'},
847 {"highlight-bars", optional_argument, 0, 'H'},
848 {"indent", required_argument, 0, 'i'},
849 {"filter", required_argument, 0, 'I'},
850 {"borders", no_argument, 0, 'j'},
851 {"page-prefeed", no_argument, 0, 'k'},
852 {"no-page-prefeed", no_argument, 0, 'K'},
853 {"lineprinter", no_argument, 0, 'l'},
854 {"lines-per-page", required_argument, 0, 'L'},
855 {"mail", no_argument, 0, 'm'},
856 {"media", required_argument, 0, 'M'},
857 {"copies", required_argument, 0, 'n'},
858 {"newline", required_argument, 0, 'N'},
859 {"output", required_argument, 0, 'p'},
860 {"missing-characters", no_argument, 0, 'O'},
861 {"quiet", no_argument, 0, 'q'},
862 rizwank 1.1 {"silent", no_argument, 0, 'q'},
863 {"landscape", no_argument, 0, 'r'},
864 {"portrait", no_argument, 0, 'R'},
865 {"baselineskip", required_argument, 0, 's'},
866 {"statusdict", required_argument, 0, 'S'},
867 {"title", required_argument, 0, 't'},
868 {"tabsize", required_argument, 0, 'T'},
869 {"underlay", optional_argument, 0, 'u'},
870 {"nup", required_argument, 0, 'U'},
871 {"verbose", optional_argument, 0, 'v'},
872 {"version", no_argument, 0, 'V'},
873 {"language", required_argument, 0, 'w'},
874 {"option", required_argument, 0, 'W'},
875 {"encoding", required_argument, 0, 'X'},
876 {"no-formfeed", no_argument, 0, 'z'},
877 {"pass-through", no_argument, 0, 'Z'},
878
879 /* Long options without short counterparts. Next free is 157. */
880 {"color", optional_argument, 0, 142},
881 {"continuous-page-numbers", no_argument, 0, 156},
882 {"download-font", required_argument, 0, 131},
883 rizwank 1.1 {"extended-return-values", no_argument, 0, 154},
884 {"filter-stdin", required_argument, 0, 138},
885 {"footer", required_argument, 0, 155},
886 {"h-column-height", required_argument, 0, 148},
887 {"help", no_argument, 0, 135},
888 {"help-highlight", no_argument, 0, 141},
889 {"highlight-bar-gray", required_argument, 0, 136},
890 {"list-media", no_argument, &list_media, 1},
891 {"margins", required_argument, 0, 144},
892 {"mark-wrapped-lines", optional_argument, 0, 143},
893 {"non-printable-format", required_argument, 0, 134},
894 {"nup-columnwise", no_argument, 0, 152},
895 {"nup-xpad", required_argument, 0, 145},
896 {"nup-ypad", required_argument, 0, 146},
897 {"page-label-format", required_argument, 0, 130},
898 {"ps-level", required_argument, 0, 149},
899 {"printer-options", required_argument, 0, 139},
900 {"rotate-even-pages", no_argument, 0, 150},
901 {"slice", required_argument, 0, 140},
902 {"style", required_argument, 0, 151},
903 {"swap-even-page-margins", no_argument, 0, 153},
904 rizwank 1.1 {"toc", no_argument, &toc, 1},
905 {"word-wrap", no_argument, 0, 147},
906 {"ul-angle", required_argument, 0, 132},
907 {"ul-font", required_argument, 0, 128},
908 {"ul-gray", required_argument, 0, 129},
909 {"ul-position", required_argument, 0, 133},
910 {"ul-style", required_argument, 0, 137},
911
912 /* Backwards compatiblity options. */
913 {"pretty-print", optional_argument, 0, 'E'},
914 {"help-pretty-print", no_argument, 0, 141},
915
916 {NULL, 0, 0, 0},
917 };
918
919
920 /*
921 * Global functions.
922 */
923
924 int
925 rizwank 1.1 main (int argc, char *argv[])
926 {
927 InputStream is;
928 time_t tim;
929 struct tm *tm;
930 int i, j, found;
931 unsigned int ui;
932 MediaEntry *mentry;
933 AFMError afm_error;
934 char *cp, *cp2;
935 int retval = 0;
936 Buffer buffer;
937
938 /* Init our dynamic memory buffer. */
939 buffer_init (&buffer);
940
941 /* Get program's name. */
942 program = strrchr (argv[0], '/');
943 if (program == NULL)
944 program = argv[0];
945 else
946 rizwank 1.1 program++;
947
948 /* Make getopt_long() to use our modified programname. */
949 argv[0] = program;
950
951 /* Create version strings. */
952
953 buffer_clear (&buffer);
954 buffer_append (&buffer, "GNU ");
955 buffer_append (&buffer, PACKAGE);
956 buffer_append (&buffer, " ");
957 buffer_append (&buffer, VERSION);
958 version_string = buffer_copy (&buffer);
959
960 ps_version_string = xstrdup (VERSION);
961 cp = strrchr (ps_version_string, '.');
962 *cp = ' ';
963
964 /* Create the default TOC format string. Wow, this is cool! */
965 /* xgettext:no-c-format */
966 toc_fmt_string = _("$3v $-40N $3% pages $4L lines $E $C");
967 rizwank 1.1
968 /* Internationalization. */
969 #if HAVE_SETLOCALE
970 /*
971 * We want to change only messages (gs do not like decimals in 0,1
972 * format ;)
973 */
974 #if HAVE_LC_MESSAGES
975 setlocale (LC_MESSAGES, "");
976 #endif
977 #endif
978 #if ENABLE_NLS
979 bindtextdomain (PACKAGE, LOCALEDIR);
980 textdomain (PACKAGE);
981 #endif
982
983 /* Create date string. */
984
985 tim = time (NULL);
986 tm = localtime (&tim);
987 memcpy (&run_tm, tm, sizeof (*tm));
988 rizwank 1.1
989 date_string = xstrdup (asctime (&run_tm));
990 i = strlen (date_string);
991 date_string[i - 1] = '\0';
992
993 /* Get user's passwd entry. */
994 passwd = getpwuid (getuid ());
995 if (passwd == NULL)
996 FATAL ((stderr, _("couldn't get passwd entry for uid=%d: %s"), getuid (),
997 strerror (errno)));
998
999 /* Defaults for some options. */
1000 media_name = xstrdup ("A4");
1001 encoding_name = xstrdup ("88591");
1002 npf_name = xstrdup ("octal");
1003 page_label_format = xstrdup ("short");
1004 ul_style_str = xstrdup ("outline");
1005 ul_position = xstrdup ("+0-0");
1006 spooler_command = xstrdup ("lpr");
1007 queue_param = xstrdup ("-P");
1008 no_job_header_switch = xstrdup ("-h");
1009 rizwank 1.1 fancy_header_default = xstrdup ("enscript");
1010 output_first_line = xstrdup ("%!PS-Adobe-3.0");
1011
1012 /* Check ENSCRIPT_LIBRARY for custom library location. */
1013 cp = getenv ("ENSCRIPT_LIBRARY");
1014 if (cp)
1015 enscript_library = cp;
1016
1017 /* Fill up build-in libpath. */
1018
1019 cp = getenv ("HOME");
1020 if (cp == NULL)
1021 cp = passwd->pw_dir;
1022
1023 buffer_clear (&buffer);
1024 buffer_append (&buffer, enscript_library);
1025 buffer_append (&buffer, PATH_SEPARATOR_STR);
1026 buffer_append (&buffer, cp);
1027 buffer_append (&buffer, "/.enscript");
1028 libpath = buffer_copy (&buffer);
1029
1030 rizwank 1.1 /* Defaults for the states filter. */
1031
1032 states_binary = xstrdup ("states"); /* Take it from the user path. */
1033
1034 buffer_clear (&buffer);
1035 buffer_append (&buffer, enscript_library);
1036 buffer_append (&buffer, "/hl/enscript.st");
1037 states_config_file = buffer_copy (&buffer);
1038
1039 states_highlight_style = xstrdup ("emacs");
1040
1041 /* The <cp> holds the user's home directory. */
1042 buffer_clear (&buffer);
1043 buffer_append (&buffer, cp);
1044 buffer_append (&buffer, "/.enscript");
1045 buffer_append (&buffer, PATH_SEPARATOR_STR);
1046 buffer_append (&buffer, enscript_library);
1047 buffer_append (&buffer, "/hl");
1048 states_path = buffer_copy (&buffer);
1049
1050 /* Initialize resource sets. */
1051 rizwank 1.1 res_fonts = strhash_init ();
1052 download_fonts = strhash_init ();
1053 pagedevice = strhash_init ();
1054 statusdict = strhash_init ();
1055 user_strings = strhash_init ();
1056
1057
1058 /*
1059 * Read configuration files.
1060 */
1061
1062 /* Global config. */
1063 #define CFG_FILE_NAME "enscript.cfg"
1064 if (!read_config (SYSCONFDIR, CFG_FILE_NAME))
1065 {
1066 int saved_errno = errno;
1067
1068 /* Try to read it from our library directory. This is mostly
1069 the case for the micro ports. */
1070 if (!read_config (enscript_library, CFG_FILE_NAME))
1071 {
1072 rizwank 1.1 /* Try `enscript_library/../../etc/'. This is the case for
1073 installations which set the prefix after the compilation
1074 and our SYSCONFDIR points to wrong directory. */
1075
1076 buffer_clear (&buffer);
1077 buffer_append (&buffer, enscript_library);
1078 buffer_append (&buffer, "/../../etc");
1079
1080 if (!read_config (buffer_ptr (&buffer), CFG_FILE_NAME))
1081 {
1082 /* Maybe we are not installed yet, let's try `../lib'
1083 and `../../lib'. */
1084 if (!read_config ("../lib", CFG_FILE_NAME)
1085 && !read_config ("../../lib", CFG_FILE_NAME))
1086 {
1087 /* No luck, report error from the original config file. */
1088 ERROR ((stderr, _("couldn't read config file \"%s/%s\": %s"),
1089 enscript_library, CFG_FILE_NAME,
1090 strerror (saved_errno)));
1091 ERROR ((stderr,
1092 _("I did also try the following directories:")));
1093 rizwank 1.1 ERROR ((stderr, _("\t%s"), SYSCONFDIR));
1094 ERROR ((stderr, _("\t%s"), enscript_library));
1095 ERROR ((stderr, _("\t%s"), buffer_ptr (&buffer)));
1096 ERROR ((stderr, _("\t../lib")));
1097 ERROR ((stderr, _("\t../../lib")));
1098 ERROR ((stderr,
1099 _("This is probably an installation error. Please, try to rebuild:")));
1100 ERROR ((stderr, _("\tmake distclean")));
1101 ERROR ((stderr, _("\t./configure --prefix=PREFIX")));
1102 ERROR ((stderr, _("\tmake")));
1103 ERROR ((stderr, _("\tmake check")));
1104 ERROR ((stderr, _("\tmake install")));
1105 ERROR ((stderr,
1106 _("or set the environment variable `ENSCRIPT_LIBRARY' to point to your")));
1107 ERROR ((stderr,
1108 _("library directory.")));
1109 exit (1);
1110 }
1111
1112 /* Ok, we are not installed yet. Here is a small kludge
1113 to conform the GNU coding standards: we must be able
1114 rizwank 1.1 to run without being installed, so we must append the
1115 `../lib' and `../../lib' directories to the libpath.
1116 The later allows us to be run form the `src/tests'
1117 directory. */
1118 buffer_clear (&buffer);
1119 buffer_append (&buffer, libpath);
1120 buffer_append (&buffer, PATH_SEPARATOR_STR);
1121 buffer_append (&buffer, "../lib");
1122 buffer_append (&buffer, PATH_SEPARATOR_STR);
1123 buffer_append (&buffer, "../../lib");
1124
1125 xfree (libpath);
1126 libpath = buffer_copy (&buffer);
1127 }
1128 }
1129 }
1130
1131 /* Site config. */
1132 (void) read_config (SYSCONFDIR, "enscriptsite.cfg");
1133
1134 /* Personal config. */
1135 rizwank 1.1 (void) read_config (passwd->pw_dir, ".enscriptrc");
1136
1137 /*
1138 * Options.
1139 */
1140
1141 /* Environment variables. */
1142 handle_env_options ("ENSCRIPT");
1143 handle_env_options ("GENSCRIPT");
1144
1145 /* Command line arguments. */
1146 handle_options (argc, argv);
1147
1148 /*
1149 * Check options which have some validity conditions.
1150 */
1151
1152 /*
1153 * Save the user-specified escape char so ^@escape{default} knows
1154 * what to set.
1155 */
1156 rizwank 1.1 default_escape_char = escape_char;
1157
1158 /* Input encoding. */
1159
1160 found = 0;
1161 for (i = 0; !found && encodings[i].names[0]; i++)
1162 for (j = 0; j < 3; j++)
1163 if (encodings[i].names[j] != NULL && MATCH (encodings[i].names[j],
1164 encoding_name))
1165 {
1166 /* Found a match for this encoding. Use the first
1167 "official" name. */
1168
1169 encoding = encodings[i].encoding;
1170 xfree (encoding_name);
1171 encoding_name = xstrdup (encodings[i].names[0]);
1172
1173 if (nl < 0)
1174 nl = encodings[i].nl;
1175 bs = encodings[i].bs;
1176 found = 1;
1177 rizwank 1.1 break;
1178 }
1179 if (!found)
1180 FATAL ((stderr, _("unknown encoding: %s"), encoding_name));
1181
1182 /* Fonts. */
1183
1184 /* Default font for landscape, 2 column printing is Courier 7. */
1185 if (!user_body_font_defined && landscape && num_columns > 1)
1186 Fpt.w = Fpt.h = 7.0;
1187
1188 /* Cache for font AFM information. */
1189 afm_cache = strhash_init ();
1190 afm_info_cache = strhash_init ();
1191
1192 /* Open AFM library. */
1193 afm_error = afm_create (afm_path, verbose, &afm);
1194 if (afm_error != AFM_SUCCESS)
1195 {
1196 char buf[256];
1197
1198 rizwank 1.1 afm_error_to_string (afm_error, buf);
1199 FATAL ((stderr, _("couldn't open AFM library: %s"), buf));
1200 }
1201
1202 /*
1203 * Save default Fpt and Fname since special escape 'font' can change
1204 * it and later we might want to switch back to the "default" font.
1205 */
1206 default_Fpt.w = Fpt.w;
1207 default_Fpt.h = Fpt.h;
1208 default_Fname = Fname;
1209 default_Fencoding = encoding;
1210
1211 /* Register that document uses at least these fonts. */
1212 strhash_put (res_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
1213 strhash_put (res_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
1214
1215 /* As a default, download both named fonts. */
1216 strhash_put (download_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
1217 strhash_put (download_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
1218
1219 rizwank 1.1 /* Read font's character widths and character types. */
1220 read_font_info ();
1221
1222 /* Count the line indentation. */
1223 line_indent = parse_float (line_indent_spec, 1, 1);
1224
1225 /* List media names. */
1226 if (list_media)
1227 {
1228 printf (_("known media:\n\
1229 name width\theight\tllx\tlly\turx\tury\n\
1230 ------------------------------------------------------------\n"));
1231 for (mentry = media_names; mentry; mentry = mentry->next)
1232 printf ("%-16s %d\t%d\t%d\t%d\t%d\t%d\n",
1233 mentry->name, mentry->w, mentry->h,
1234 mentry->llx, mentry->lly, mentry->urx, mentry->ury);
1235 /* Exit after listing. */
1236 exit (0);
1237 }
1238
1239 /* Output media. */
1240 rizwank 1.1 for (mentry = media_names; mentry; mentry = mentry->next)
1241 if (strcmp (media_name, mentry->name) == 0)
1242 {
1243 media = mentry;
1244 break;
1245 }
1246 if (media == NULL)
1247 FATAL ((stderr, _("do not know anything about media \"%s\""), media_name));
1248
1249 if (margins_spec)
1250 {
1251 /* Adjust marginals. */
1252 for (i = 0; i < 4; i++)
1253 {
1254 if (*margins_spec == '\0')
1255 /* All done. */
1256 break;
1257
1258 if (*margins_spec == ':')
1259 {
1260 margins_spec++;
1261 rizwank 1.1 continue;
1262 }
1263
1264 j = atoi (margins_spec);
1265 for (; *margins_spec != ':' && *margins_spec != '\0'; margins_spec++)
1266 ;
1267 if (*margins_spec == ':')
1268 margins_spec++;
1269
1270 switch (i)
1271 {
1272 case 0: /* left */
1273 media->llx = j;
1274 break;
1275
1276 case 1: /* right */
1277 media->urx = media->w - j;
1278 break;
1279
1280 case 2: /* top */
1281 media->ury = media->h - j;
1282 rizwank 1.1 break;
1283
1284 case 3: /* bottom */
1285 media->lly = j;
1286 break;
1287 }
1288 }
1289 MESSAGE (1,
1290 (stderr,
1291 _("set new marginals for media `%s' (%dx%d): llx=%d, lly=%d, urx=%d, ury=%d\n"),
1292 media->name, media->w, media->h, media->llx, media->lly,
1293 media->urx, media->ury));
1294 }
1295
1296 /* Page label format. */
1297 if (MATCH (page_label_format, "short"))
1298 page_label = LABEL_SHORT;
1299 else if (MATCH (page_label_format, "long"))
1300 page_label = LABEL_LONG;
1301 else
1302 FATAL ((stderr, _("illegal page label format \"%s\""), page_label_format));
1303 rizwank 1.1
1304 /* Non-printable format. */
1305 if (MATCH (npf_name, "space"))
1306 non_printable_format = NPF_SPACE;
1307 else if (MATCH (npf_name, "questionmark"))
1308 non_printable_format = NPF_QUESTIONMARK;
1309 else if (MATCH (npf_name, "caret"))
1310 non_printable_format = NPF_CARET;
1311 else if (MATCH (npf_name, "octal"))
1312 non_printable_format = NPF_OCTAL;
1313 else
1314 FATAL ((stderr, _("illegal non-printable format \"%s\""), npf_name));
1315
1316 /* Mark wrapped lines style. */
1317 if (mark_wrapped_lines_style_name)
1318 {
1319 if (MATCH (mark_wrapped_lines_style_name, "none"))
1320 mark_wrapped_lines_style = MWLS_NONE;
1321 else if (MATCH (mark_wrapped_lines_style_name, "plus"))
1322 mark_wrapped_lines_style = MWLS_PLUS;
1323 else if (MATCH (mark_wrapped_lines_style_name, "box"))
1324 rizwank 1.1 mark_wrapped_lines_style = MWLS_BOX;
1325 else if (MATCH (mark_wrapped_lines_style_name, "arrow"))
1326 mark_wrapped_lines_style = MWLS_ARROW;
1327 else
1328 FATAL ((stderr, _("illegal style for wrapped line marker: \"%s\""),
1329 mark_wrapped_lines_style_name));
1330 }
1331
1332 /* Count N-up stuffs. */
1333 for (i = 0; ; i++)
1334 {
1335 ui = nup >> i;
1336
1337 if (ui == 0)
1338 FATAL ((stderr, _("illegal N-up argument: %d"), nup));
1339
1340 if (ui & 0x1)
1341 {
1342 if (ui != 1)
1343 FATAL ((stderr, _("N-up argument must be power of 2: %d"), nup));
1344
1345 rizwank 1.1 nup_exp = i;
1346 break;
1347 }
1348 }
1349
1350 nup_rows = nup_exp / 2 * 2;
1351 if (nup_rows == 0)
1352 nup_rows = 1;
1353 nup_columns = (nup_exp + 1) / 2 * 2;
1354 if (nup_columns == 0)
1355 nup_columns = 1;
1356
1357 nup_landscape = nup_exp & 0x1;
1358
1359
1360 /*
1361 * Count output media dimensions.
1362 */
1363
1364 if (landscape)
1365 {
1366 rizwank 1.1 d_page_w = media->ury - media->lly;
1367 d_page_h = media->urx - media->llx;
1368 }
1369 else
1370 {
1371 d_page_w = media->urx - media->llx;
1372 d_page_h = media->ury - media->lly;
1373 }
1374
1375 /*
1376 * Count N-up page width, height and scale.
1377 */
1378
1379 if (nup_landscape)
1380 {
1381 nup_width = media->ury - media->lly;
1382 nup_height = media->urx - media->llx;
1383 }
1384 else
1385 {
1386 nup_width = media->urx - media->llx;
1387 rizwank 1.1 nup_height = media->ury - media->lly;
1388 }
1389
1390 {
1391 double w, h;
1392
1393 w = ((double) nup_width - (nup_columns - 1) * nup_xpad) / nup_columns;
1394 h = ((double) nup_height - (nup_rows - 1) * nup_ypad) / nup_rows;
1395
1396 nup_width = w;
1397 nup_height = h;
1398
1399 w = w / (media->urx - media->llx);
1400 h = h / (media->ury - media->lly);
1401
1402 nup_scale = w < h ? w : h;
1403 }
1404
1405 /*
1406 * Underlay (this must come after output media dimensions, because
1407 * `underlay position' needs them).
1408 rizwank 1.1 */
1409 if (underlay != NULL)
1410 {
1411 strhash_put (res_fonts, ul_font, strlen (ul_font) + 1, NULL, NULL);
1412 underlay = escape_string (underlay);
1413 }
1414
1415 /* Underlay X-coordinate. */
1416 ul_x = strtod (ul_position, &cp);
1417 if (cp == ul_position)
1418 {
1419 malformed_position:
1420 FATAL ((stderr, _("malformed underlay position: %s"), ul_position));
1421 }
1422 if (ul_position[0] == '-')
1423 ul_x += d_page_w;
1424
1425 /* Underlay Y-coordinate. */
1426 ul_y = strtod (cp, &cp2);
1427 if (cp2 == cp)
1428 goto malformed_position;
1429 rizwank 1.1 if (cp[0] == '-')
1430 ul_y += d_page_h;
1431
1432 /* Underlay Angle. */
1433 if (!ul_angle_p)
1434 /* No angle given, count the default. */
1435 ul_angle = (atan2 (-d_page_h, d_page_w) / 3.14159265 * 180);
1436
1437 /* Underlay style. */
1438 if (strcmp (ul_style_str, "outline") == 0)
1439 ul_style = UL_STYLE_OUTLINE;
1440 else if (strcmp (ul_style_str, "filled") == 0)
1441 ul_style = UL_STYLE_FILLED;
1442 else
1443 FATAL ((stderr, _("illegal underlay style: %s"), ul_style_str));
1444
1445 /*
1446 * Header. Note! The header attributes can be changed from
1447 * the `.hdr' files, these are only the defaults.
1448 */
1449
1450 rizwank 1.1 d_header_w = d_page_w;
1451 switch (header)
1452 {
1453 case HDR_NONE:
1454 d_header_h = 0;
1455 break;
1456
1457 case HDR_SIMPLE:
1458 d_header_h = HFpt.h * 1.5;
1459 break;
1460
1461 case HDR_FANCY:
1462 d_header_h = 36;
1463 break;
1464 }
1465
1466 /* Help highlight. */
1467 if (help_highlight)
1468 {
1469 /* Create description with states. */
1470 printf (_("Highlighting is supported for the following languages and file formats:\n\n"));
1471 rizwank 1.1 fflush (stdout);
1472
1473 buffer_clear (&buffer);
1474 buffer_append (&buffer, states_binary);
1475 buffer_append (&buffer, " -f \"");
1476 buffer_append (&buffer, states_config_file);
1477 buffer_append (&buffer, "\" -p \"");
1478 buffer_append (&buffer, states_path);
1479 buffer_append (&buffer, "\" -s describe_languages ");
1480 buffer_append (&buffer, enscript_library);
1481 buffer_append (&buffer, "/hl/*.st");
1482
1483 system (buffer_ptr (&buffer));
1484 exit (0);
1485 }
1486
1487 /*
1488 * And now to the main business. The actual input file processing
1489 * is divided to two parts: PostScript generation and everything else.
1490 * The PostScript generation is handled in the conventional way, we
1491 * process the input and generate PostScript. However all other input
1492 rizwank 1.1 * languages will be handled with States, we only pass enscript's
1493 * options to the states pre-filter and dump output.
1494 */
1495 if (output_language_pass_through)
1496 {
1497 char *start_state;
1498 Buffer cmd;
1499 char intbuf[256];
1500
1501 /* The States output generation. */
1502
1503 /* Resolve the start state. */
1504 if (hl_start_state)
1505 start_state = hl_start_state;
1506 else if (highlight)
1507 start_state = NULL;
1508 else
1509 start_state = "passthrough";
1510
1511 /* Create the states command. */
1512
1513 rizwank 1.1 buffer_init (&cmd);
1514
1515 buffer_append (&cmd, states_binary);
1516 buffer_append (&cmd, " -f \"");
1517 buffer_append (&cmd, states_config_file);
1518 buffer_append (&cmd, "\" -p \"");
1519 buffer_append (&cmd, states_path);
1520 buffer_append (&cmd, "\" ");
1521
1522 if (verbose > 0)
1523 buffer_append (&cmd, "-v ");
1524
1525 if (start_state)
1526 {
1527 buffer_append (&cmd, "-s");
1528 buffer_append (&cmd, start_state);
1529 buffer_append (&cmd, " ");
1530 }
1531
1532 buffer_append (&cmd, "-Dcolor=");
1533 buffer_append (&cmd, states_color ? "1" : "0");
1534 rizwank 1.1 buffer_append (&cmd, " ");
1535
1536 buffer_append (&cmd, "-Dstyle=");
1537 buffer_append (&cmd, states_highlight_style);
1538 buffer_append (&cmd, " ");
1539
1540 buffer_append (&cmd, "-Dlanguage=");
1541 buffer_append (&cmd, output_language);
1542 buffer_append (&cmd, " ");
1543
1544 buffer_append (&cmd, "-Dnum_input_files=");
1545 sprintf (intbuf, "%d", optind == argc ? 1 : argc - optind);
1546 buffer_append (&cmd, intbuf);
1547 buffer_append (&cmd, " ");
1548
1549 buffer_append (&cmd, "-Ddocument_title=\"");
1550 buffer_append (&cmd, title);
1551 buffer_append (&cmd, "\" ");
1552
1553 buffer_append (&cmd, "-Dtoc=");
1554 buffer_append (&cmd, toc ? "1" : "0");
1555 rizwank 1.1
1556 /* Additional options for states? */
1557 if (helper_options['s'])
1558 {
1559 Buffer *opts = helper_options['s'];
1560
1561 buffer_append (&cmd, " ");
1562 buffer_append_len (&cmd, buffer_ptr (opts), buffer_len (opts));
1563 }
1564
1565 /* Append input files. */
1566 for (i = optind; i < argc; i++)
1567 {
1568 buffer_append (&cmd, " ");
1569 buffer_append (&cmd, argv[i]);
1570 }
1571
1572 /* And do the job. */
1573 if (is_open (&is, stdin, NULL, buffer_ptr (&cmd)))
1574 {
1575 open_output_file ();
1576 rizwank 1.1 process_file ("unused", &is, 0);
1577 is_close (&is);
1578 }
1579
1580 buffer_uninit (&cmd);
1581 }
1582 else
1583 {
1584 /* The conventional way. */
1585
1586 /* Highlighting. */
1587 if (highlight)
1588 {
1589 char fbuf[256];
1590
1591 /* Create a highlight input filter. */
1592 buffer_clear (&buffer);
1593 buffer_append (&buffer, states_binary);
1594 buffer_append (&buffer, " -f \"");
1595 buffer_append (&buffer, states_config_file);
1596 buffer_append (&buffer, "\" -p \"");
1597 rizwank 1.1 buffer_append (&buffer, states_path);
1598 buffer_append (&buffer, "\"");
1599
1600 if (verbose > 0)
1601 buffer_append (&buffer, " -v");
1602
1603 if (hl_start_state)
1604 {
1605 buffer_append (&buffer, " -s ");
1606 buffer_append (&buffer, hl_start_state);
1607 }
1608
1609 buffer_append (&buffer, " -Dcolor=");
1610 buffer_append (&buffer, states_color ? "1" : "0");
1611
1612 buffer_append (&buffer, " -Dstyle=");
1613 buffer_append (&buffer, states_highlight_style);
1614
1615 buffer_append (&buffer, " -Dfont_spec=");
1616 buffer_append (&buffer, Fname);
1617 sprintf (fbuf, "@%g/%g", Fpt.w, Fpt.h);
1618 rizwank 1.1 buffer_append (&buffer, fbuf);
1619
1620 /* Additional options for states? */
1621 if (helper_options['s'])
1622 {
1623 Buffer *opts = helper_options['s'];
1624
1625 buffer_append (&buffer, " ");
1626 buffer_append_len (&buffer,
1627 buffer_ptr (opts), buffer_len (opts));
1628 }
1629
1630 buffer_append (&buffer, " \"%s\"");
1631
1632 input_filter = buffer_copy (&buffer);
1633 input_filter_stdin = "-";
1634 }
1635
1636 /* Table of Contents. */
1637 if (toc)
1638 {
1639 rizwank 1.1 toc_fp = tmpfile ();
1640 if (toc_fp == NULL)
1641 FATAL ((stderr, _("couldn't create temporary toc file: %s"),
1642 strerror (errno)));
1643 }
1644
1645
1646 /*
1647 * Process files.
1648 */
1649
1650 if (optind == argc)
1651 {
1652 /* stdin's modification time is the current time. */
1653 memcpy (&mod_tm, &run_tm, sizeof (run_tm));
1654
1655 if (is_open (&is, stdin, NULL, input_filter))
1656 {
1657 /* Open output file. */
1658 open_output_file ();
1659 process_file (title_given ? title : "", &is, 0);
1660 rizwank 1.1 is_close (&is);
1661 }
1662 }
1663 else
1664 {
1665 for (; optind < argc; optind++)
1666 {
1667 if (is_open (&is, NULL, argv[optind], input_filter))
1668 {
1669 struct stat stat_st;
1670
1671 /* Get modification time. */
1672 if (stat (argv[optind], &stat_st) == 0)
1673 {
1674 tim = stat_st.st_mtime;
1675 tm = localtime (&tim);
1676 memcpy (&mod_tm, tm, sizeof (*tm));
1677
1678 /*
1679 * Open output file. Output file opening is delayed to
1680 * this point so we can optimize the case when a
1681 rizwank 1.1 * non-existing input file is printed => we do nothing.
1682 */
1683 open_output_file ();
1684
1685 process_file (argv[optind], &is, 0);
1686 }
1687 else
1688 ERROR ((stderr, _("couldn't stat input file \"%s\": %s"),
1689 argv[optind],
1690 strerror (errno)));
1691
1692 is_close (&is);
1693 }
1694 }
1695 }
1696
1697 /* Table of Contents. */
1698 if (toc)
1699 {
1700 /* This is really cool... */
1701
1702 rizwank 1.1 /* Set the printing options for toc. */
1703 toc = 0;
1704 special_escapes = 1;
1705 line_numbers = 0;
1706
1707 if (fseek (toc_fp, 0, SEEK_SET) != 0)
1708 FATAL ((stderr, _("couldn't rewind toc file: %s"),
1709 strerror (errno)));
1710
1711 memcpy (&mod_tm, &run_tm, sizeof (run_tm));
1712 if (is_open (&is, toc_fp, NULL, NULL))
1713 {
1714 process_file (_("Table of Contents"), &is, 1);
1715 is_close (&is);
1716 }
1717
1718 /* Clean up toc file. */
1719 fclose (toc_fp);
1720 }
1721
1722 /* Give trailer a chance to dump itself. */
1723 rizwank 1.1 dump_ps_trailer ();
1724
1725 /*
1726 * Append ^D to the end of the output? Note! It must be ^D followed
1727 * by a newline.
1728 */
1729 if (ofp != NULL && append_ctrl_D)
1730 fprintf (ofp, "\004\n");
1731 }
1732
1733 /* Close output file. */
1734 close_output_file ();
1735
1736 /* Tell how things went. */
1737 if (ofp == NULL)
1738 {
1739 /*
1740 * The value of <ofp> is not reset in close_output_file(),
1741 * this is ugly but it saves one flag.
1742 */
1743 MESSAGE (0, (stderr, _("no output generated\n")));
1744 rizwank 1.1 }
1745 else if (output_language_pass_through)
1746 {
1747 if (output_file == OUTPUT_FILE_NONE)
1748 MESSAGE (0, (stderr, _("output sent to %s\n"),
1749 printer ? printer : _("printer")));
1750 else
1751 MESSAGE (0, (stderr, _("output left in %s\n"),
1752 output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
1753 }
1754 else
1755 {
1756 unsigned int real_total_pages;
1757
1758 if (nup > 1)
1759 {
1760 if (total_pages > 0)
1761 real_total_pages = (total_pages - 1) / nup + 1;
1762 else
1763 real_total_pages = 0;
1764 }
1765 rizwank 1.1 else
1766 real_total_pages = total_pages;
1767
1768 /* We did something, tell what. */
1769 MESSAGE (0, (stderr, _("[ %d pages * %d copy ]"), real_total_pages,
1770 num_copies));
1771 if (output_file == OUTPUT_FILE_NONE)
1772 MESSAGE (0, (stderr, _(" sent to %s\n"),
1773 printer ? printer : _("printer")));
1774 else
1775 MESSAGE (0, (stderr, _(" left in %s\n"),
1776 output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
1777 if (num_truncated_lines)
1778 {
1779 retval |= 2;
1780 MESSAGE (0, (stderr, _("%d lines were %s\n"), num_truncated_lines,
1781 line_end == LE_TRUNCATE
1782 ? _("truncated") : _("wrapped")));
1783 }
1784
1785 if (num_missing_chars)
1786 rizwank 1.1 {
1787 retval |= 4;
1788 MESSAGE (0, (stderr, _("%d characters were missing\n"),
1789 num_missing_chars));
1790 if (list_missing_characters)
1791 {
1792 MESSAGE (0, (stderr, _("missing character codes (decimal):\n")));
1793 do_list_missing_characters (missing_chars);
1794 }
1795 }
1796
1797 if (num_non_printable_chars)
1798 {
1799 retval |= 8;
1800 MESSAGE (0, (stderr, _("%d non-printable characters\n"),
1801 num_non_printable_chars));
1802 if (list_missing_characters)
1803 {
1804 MESSAGE (0, (stderr,
1805 _("non-printable character codes (decimal):\n")));
1806 do_list_missing_characters (non_printable_chars);
1807 rizwank 1.1 }
1808 }
1809 }
1810
1811 /* Uninit our dynamic memory buffer. */
1812 buffer_uninit (&buffer);
1813
1814 /* Return the extended return values only if requested. */
1815 if (!extended_return_values)
1816 retval = 0;
1817
1818 /* This is the end. */
1819 return retval;
1820 }
1821
1822
1823 /*
1824 * Static functions.
1825 */
1826
1827 static void
1828 rizwank 1.1 open_output_file ()
1829 {
1830 if (ofp)
1831 /* Output file has already been opened, do nothing. */
1832 return;
1833
1834 if (output_file == OUTPUT_FILE_NONE)
1835 {
1836 char spooler_options[512];
1837
1838 /* Format spooler options. */
1839 spooler_options[0] = '\0';
1840 if (mail)
1841 strcat (spooler_options, "-m ");
1842 if (no_job_header)
1843 {
1844 strcat (spooler_options, no_job_header_switch);
1845 strcat (spooler_options, " ");
1846 }
1847 if (printer_options)
1848 strcat (spooler_options, printer_options);
1849 rizwank 1.1
1850 /* Open printer. */
1851 ofp = printer_open (spooler_command, spooler_options, queue_param,
1852 printer, &printer_context);
1853 if (ofp == NULL)
1854 FATAL ((stderr, _("couldn't open printer `%s': %s"), printer,
1855 strerror (errno)));
1856 }
1857 else if (output_file == OUTPUT_FILE_STDOUT)
1858 ofp = stdout;
1859 else
1860 {
1861 ofp = fopen (output_file, "w");
1862 if (ofp == NULL)
1863 FATAL ((stderr, _("couldn't create output file \"%s\": %s"),
1864 output_file, strerror (errno)));
1865 }
1866 }
1867
1868
1869 static void
1870 rizwank 1.1 close_output_file ()
1871 {
1872 if (ofp == NULL)
1873 /* Output file hasn't been opened, we are done. */
1874 return;
1875
1876 if (output_file == OUTPUT_FILE_NONE)
1877 printer_close (printer_context);
1878 else if (output_file != OUTPUT_FILE_STDOUT)
1879 if (fclose (ofp))
1880 FATAL ((stderr, _("couldn't close output file \"%s\": %s"),
1881 output_file, strerror (errno)));
1882
1883 /* We do not reset <ofp> since its value is needed in diagnostigs. */
1884 }
1885
1886
1887 static void
1888 handle_env_options (char *var)
1889 {
1890 int argc;
1891 rizwank 1.1 char **argv;
1892 char *string;
1893 char *str;
1894 int i;
1895
1896 string = getenv (var);
1897 if (string == NULL)
1898 return;
1899
1900 MESSAGE (2, (stderr, "handle_env_options(): %s=\"%s\"\n", var, string));
1901
1902 /* Copy string so we can modify it in place. */
1903 str = xstrdup (string);
1904
1905 /*
1906 * We can count this, each option takes at least 1 character and one
1907 * space. We also need one for program's name and one for the
1908 * trailing NULL.
1909 */
1910 argc = (strlen (str) + 1) / 2 + 2;
1911 argv = xcalloc (argc, sizeof (char *));
1912 rizwank 1.1
1913 /* Set program name. */
1914 argc = 0;
1915 argv[argc++] = program;
1916
1917 /* Split string and set arguments to argv array. */
1918 i = 0;
1919 while (str[i])
1920 {
1921 /* Skip leading whitespace. */
1922 for (; str[i] && isspace (str[i]); i++)
1923 ;
1924 if (!str[i])
1925 break;
1926
1927 /* Check for quoted arguments. */
1928 if (str[i] == '"' || str[i] == '\'')
1929 {
1930 int endch = str[i++];
1931
1932 argv[argc++] = str + i;
1933 rizwank 1.1
1934 /* Skip until we found the end of the quotation. */
1935 for (; str[i] && str[i] != endch; i++)
1936 ;
1937 if (!str[i])
1938 FATAL ((stderr, _("syntax error in option string %s=\"%s\":\n\
1939 missing end of quotation: %c"), var, string, endch));
1940
1941 str[i++] = '\0';
1942 }
1943 else
1944 {
1945 argv[argc++] = str + i;
1946
1947 /* Skip until whitespace if found. */
1948 for (; str[i] && !isspace (str[i]); i++)
1949 ;
1950 if (str[i])
1951 str[i++] = '\0';
1952 }
1953 }
1954 rizwank 1.1
1955 /* argv[argc] must be NULL. */
1956 argv[argc] = NULL;
1957
1958 MESSAGE (2, (stderr, "found following options (argc=%d):\n", argc));
1959 for (i = 0; i < argc; i++)
1960 MESSAGE (2, (stderr, "%3d = \"%s\"\n", i, argv[i]));
1961
1962 /* Process options. */
1963 handle_options (argc, argv);
1964
1965 /* Check that all got processed. */
1966 if (optind != argc)
1967 {
1968 MESSAGE (0,
1969 (stderr,
1970 _("warning: didn't process following options from \
1971 environment variable %s:\n"),
1972 var));
1973 for (; optind < argc; optind++)
1974 MESSAGE (0, (stderr, _(" option %d = \"%s\"\n"), optind,
1975 rizwank 1.1 argv[optind]));
1976 }
1977
1978 /* Cleanup. */
1979 xfree (argv);
1980
1981 /*
1982 * <str> must not be freed, since some global variables can point to
1983 * its elements
1984 */
1985 }
1986
1987
1988 static void
1989 handle_options (int argc, char *argv[])
1990 {
1991 int c;
1992 PageRange *prange;
1993
1994 /* Reset optind. */
1995 optind = 0;
1996 rizwank 1.1
1997 while (1)
1998 {
1999 int option_index = 0;
2000 const char *cp;
2001 int i;
2002
2003 c = getopt_long (argc, argv,
2004 "#:123456789a:A:b:BcC::d:D:e::E::f:F:gGhH::i:I:jJ:kKlL:mM:n:N:o:Op:P:qrRs:S:t:T:u::U:vVW:X:zZ",
2005 long_options, &option_index);
2006
2007 if (c == -1)
2008 break;
2009
2010 switch (c)
2011 {
2012 case 0: /* Long option found. */
2013 cp = long_options[option_index].name;
2014
2015 if (strcmp (cp, "columns") == 0)
2016 {
2017 rizwank 1.1 num_columns = atoi (optarg);
2018 if (num_columns < 1)
2019 FATAL ((stderr,
2020 _("number of columns must be larger than zero")));
2021 }
2022 break;
2023
2024 /* Short options. */
2025
2026 case '1': /* 1 column */
2027 case '2': /* 2 columns */
2028 case '3': /* 3 columns */
2029 case '4': /* 4 columns */
2030 case '5': /* 5 columns */
2031 case '6': /* 6 columns */
2032 case '7': /* 7 columns */
2033 case '8': /* 8 columns */
2034 case '9': /* 9 columns */
2035 num_columns = c - '0';
2036 break;
2037
2038 rizwank 1.1 case 'a': /* pages */
2039 prange = (PageRange *) xcalloc (1, sizeof (PageRange));
2040
2041 if (strcmp (optarg, "odd") == 0)
2042 prange->odd = 1;
2043 else if (strcmp (optarg, "even") == 0)
2044 prange->even = 1;
2045 else
2046 {
2047 cp = strchr (optarg, '-');
2048 if (cp)
2049 {
2050 if (optarg[0] == '-')
2051 /* -end */
2052 prange->end = atoi (optarg + 1);
2053 else if (cp[1] == '\0')
2054 {
2055 /* begin- */
2056 prange->start = atoi (optarg);
2057 prange->end = (unsigned int) -1;
2058 }
2059 rizwank 1.1 else
2060 {
2061 /* begin-end */
2062 prange->start = atoi (optarg);
2063 prange->end = atoi (cp + 1);
2064 }
2065 }
2066 else
2067 /* pagenumber */
2068 prange->start = prange->end = atoi (optarg);
2069 }
2070
2071 prange->next = page_ranges;
2072 page_ranges = prange;
2073 break;
2074
2075 case 'A': /* file alignment */
2076 file_align = atoi (optarg);
2077 if (file_align == 0)
2078 FATAL ((stderr, _("file alignment must be larger than zero")));
2079 break;
2080 rizwank 1.1
2081 case 'b': /* page header */
2082 page_header = optarg;
2083 break;
2084
2085 case 'B': /* no page headers */
2086 header = HDR_NONE;
2087 break;
2088
2089 case 'c': /* truncate (cut) long lines */
2090 line_end = LE_TRUNCATE;
2091 break;
2092
2093 case 'C': /* line numbers */
2094 line_numbers = 1;
2095 if (optarg)
2096 start_line_number = atoi (optarg);
2097 break;
2098
2099 case 'd': /* specify printer */
2100 case 'P':
2101 rizwank 1.1 xfree (printer);
2102 printer = xstrdup (optarg);
2103 output_file = OUTPUT_FILE_NONE;
2104 break;
2105
2106 case 'D': /* setpagedevice */
2107 parse_key_value_pair (pagedevice, optarg);
2108 break;
2109
2110 case 'e': /* special escapes */
2111 special_escapes = 1;
2112 if (optarg)
2113 {
2114 /* Specify the escape character. */
2115 if (isdigit (optarg[0]))
2116 /* As decimal, octal, or hexadicimal number. */
2117 escape_char = (int) strtoul (optarg, NULL, 0);
2118 else
2119 /* As character directly. */
2120 escape_char = ((unsigned char *) optarg)[0];
2121 }
2122 rizwank 1.1 break;
2123
2124 case 'E': /* highlight */
2125 highlight = 1;
2126 special_escapes = 1;
2127 escape_char = '\0';
2128 hl_start_state = optarg;
2129 break;
2130
2131 case 'f': /* font */
2132 if (!parse_font_spec (optarg, &Fname, &Fpt, NULL))
2133 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2134 user_body_font_defined = 1;
2135 break;
2136
2137 case 'F': /* header font */
2138 if (!parse_font_spec (optarg, &HFname, &HFpt, NULL))
2139 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2140 break;
2141
2142 case 'g': /* print anyway */
2143 rizwank 1.1 /* nothing. */
2144 break;
2145
2146 case 'G': /* fancy header */
2147 header = HDR_FANCY;
2148 if (optarg)
2149 fancy_header_name = optarg;
2150 else
2151 fancy_header_name = fancy_header_default;
2152
2153 if (!file_existsp (fancy_header_name, ".hdr"))
2154 FATAL ((stderr,
2155 _("couldn't find header definition file \"%s.hdr\""),
2156 fancy_header_name));
2157 break;
2158
2159 case 'h': /* no job header */
2160 no_job_header = 1;
2161 break;
2162
2163 case 'H': /* highlight bars */
2164 rizwank 1.1 if (optarg)
2165 highlight_bars = atoi (optarg);
2166 else
2167 highlight_bars = 2;
2168 break;
2169
2170 case 'i': /* line indent */
2171 line_indent_spec = optarg;
2172 break;
2173
2174 case 'I': /* input filter */
2175 input_filter = optarg;
2176 break;
2177
2178 case 'j': /* borders */
2179 borders = 1;
2180 break;
2181
2182 case 'k': /* enable page prefeed */
2183 page_prefeed = 1;
2184 break;
2185 rizwank 1.1
2186 case 'K': /* disable page prefeed */
2187 page_prefeed = 0;
2188 break;
2189
2190 case 'l': /* emulate lineprinter */
2191 lines_per_page = 66;
2192 header = HDR_NONE;
2193 break;
2194
2195 case 'L': /* lines per page */
2196 lines_per_page = atoi (optarg);
2197 if (lines_per_page <= 0)
2198 FATAL ((stderr,
2199 _("must print at least one line per each page: %s"),
2200 argv[optind]));
2201 break;
2202
2203 case 'm': /* send mail upon completion */
2204 mail = 1;
2205 break;
2206 rizwank 1.1
2207 case 'M': /* select output media */
2208 media_name = xstrdup (optarg);
2209 break;
2210
2211 case 'n': /* num copies */
2212 case '#':
2213 num_copies = atoi (optarg);
2214 break;
2215
2216 case 'N': /* newline character */
2217 if (!(optarg[0] == 'n' || optarg[0] == 'r') || optarg[1] != '\0')
2218 {
2219 fprintf (stderr, _("%s: illegal newline character specifier: \
2220 '%s': expected 'n' or 'r'\n"),
2221 program, optarg);
2222 goto option_error;
2223 }
2224 if (optarg[0] == 'n')
2225 nl = '\n';
2226 else
2227 rizwank 1.1 nl = '\r';
2228 break;
2229
2230 case 'o':
2231 case 'p': /* output file */
2232 /* Check output file "-". */
2233 if (strcmp (optarg, "-") == 0)
2234 output_file = OUTPUT_FILE_STDOUT;
2235 else
2236 output_file = optarg;
2237 break;
2238
2239 case 'O': /* list missing characters */
2240 list_missing_characters = 1;
2241 break;
2242
2243 case 'q': /* quiet */
2244 quiet = 1;
2245 verbose = 0;
2246 break;
2247
2248 rizwank 1.1 case 'r': /* landscape */
2249 landscape = 1;
2250 break;
2251
2252 case 'R': /* portrait */
2253 landscape = 0;
2254 break;
2255
2256 case 's': /* baselineskip */
2257 baselineskip = atof (optarg);
2258 break;
2259
2260 case 'S': /* statusdict */
2261 parse_key_value_pair (statusdict, optarg);
2262 break;
2263
2264 case 't': /* title */
2265 case 'J':
2266 title = optarg;
2267 title_given = 1;
2268 break;
2269 rizwank 1.1
2270 case 'T': /* tabulator size */
2271 tabsize = atoi (optarg);
2272 if (tabsize <= 0)
2273 tabsize = 1;
2274 break;
2275
2276 case 'u': /* underlay */
2277 underlay = optarg;
2278 break;
2279
2280 case 'U': /* nup */
2281 nup = atoi (optarg);
2282 break;
2283
2284 case 'v': /* verbose */
2285 if (optarg)
2286 verbose = atoi (optarg);
2287 else
2288 verbose++;
2289 quiet = 0;
2290 rizwank 1.1 break;
2291
2292 case 'V': /* version */
2293 version ();
2294 exit (0);
2295 break;
2296
2297 case 'w': /* output language */
2298 output_language = optarg;
2299 if (strcmp (output_language, "PostScript") != 0)
2300 /* Other output languages are handled with states. */
2301 output_language_pass_through = 1;
2302 break;
2303
2304 case 'W': /* a helper application option */
2305 cp = strchr (optarg, ',');
2306 if (cp == NULL)
2307 FATAL ((stderr,
2308 _("malformed argument `%s' for option -W, --option: \
2309 no comma found"),
2310 optarg));
2311 rizwank 1.1
2312 if (cp - optarg != 1)
2313 FATAL ((stderr, _("helper application specification must be \
2314 single character: %s"),
2315 optarg));
2316
2317 /* Take the index of the helper application and update `cp'
2318 to point to the beginning of the option. */
2319 i = *optarg;
2320 cp++;
2321
2322 if (helper_options[i] == NULL)
2323 helper_options[i] = buffer_alloc ();
2324 else
2325 {
2326 /* We already had some options for this helper
2327 application. Let's separate these arguments. */
2328 buffer_append (helper_options[i], " ");
2329 }
2330
2331 /* Add this new option. */
2332 rizwank 1.1 buffer_append (helper_options[i], cp);
2333 break;
2334
2335 case 'X': /* input encoding */
2336 xfree (encoding_name);
2337 encoding_name = xstrdup (optarg);
2338 break;
2339
2340 case 'z': /* no form feeds */
2341 interpret_formfeed = 0;
2342 break;
2343
2344 case 'Z': /* pass through */
2345 pass_through = 1;
2346 break;
2347
2348 case 128: /* underlay font */
2349 if (!parse_font_spec (optarg, &ul_font, &ul_ptsize, NULL))
2350 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2351 break;
2352
2353 rizwank 1.1 case 129: /* underlay gray */
2354 ul_gray = atof (optarg);
2355 break;
2356
2357 case 130: /* page label format */
2358 xfree (page_label_format);
2359 page_label_format = xstrdup (optarg);
2360 break;
2361
2362 case 131: /* download font */
2363 strhash_put (download_fonts, optarg, strlen (optarg) + 1, NULL,
2364 NULL);
2365 break;
2366
2367 case 132: /* underlay angle */
2368 ul_angle = atof (optarg);
2369 ul_angle_p = 1;
2370 break;
2371
2372 case 133: /* underlay position */
2373 xfree (ul_position);
2374 rizwank 1.1 ul_position = xstrdup (optarg);
2375 ul_position_p = 1;
2376 break;
2377
2378 case 134: /* non-printable format */
2379 xfree (npf_name);
2380 npf_name = xstrdup (optarg);
2381 break;
2382
2383 case 135: /* help */
2384 usage ();
2385 exit (0);
2386 break;
2387
2388 case 136: /* highlight bar gray */
2389 highlight_bar_gray = atof (optarg);
2390 break;
2391
2392 case 137: /* underlay style */
2393 xfree (ul_style_str);
2394 ul_style_str = xstrdup (optarg);
2395 rizwank 1.1 break;
2396
2397 case 138: /* filter stdin */
2398 input_filter_stdin = optarg;
2399 break;
2400
2401 case 139: /* extra options for the printer spooler */
2402 printer_options = optarg;
2403 break;
2404
2405 case 140: /* slicing */
2406 slicing = 1;
2407 slice = atoi (optarg);
2408 if (slice <= 0)
2409 FATAL ((stderr, _("slice must be greater than zero")));
2410 break;
2411
2412 case 141: /* help-highlight */
2413 help_highlight = 1;
2414 break;
2415
2416 rizwank 1.1 case 142: /* States color? */
2417 if (optarg == NULL)
2418 states_color = 1;
2419 else
2420 states_color = atoi (optarg);
2421 break;
2422
2423 case 143: /* mark-wrapped-lines */
2424 if (optarg)
2425 {
2426 xfree (mark_wrapped_lines_style_name);
2427 mark_wrapped_lines_style_name = xstrdup (optarg);
2428 }
2429 else
2430 /* Set the system default. */
2431 mark_wrapped_lines_style = MWLS_BOX;
2432 break;
2433
2434 case 144: /* adjust margins */
2435 margins_spec = optarg;
2436 break;
2437 rizwank 1.1
2438 case 145: /* N-up x-pad */
2439 nup_xpad = atoi (optarg);
2440 break;
2441
2442 case 146: /* N-up y-pad */
2443 nup_ypad = atoi (optarg);
2444 break;
2445
2446 case 147: /* word wrap */
2447 line_end = LE_WORD_WRAP;
2448 break;
2449
2450 case 148: /* horizontal column height */
2451 horizontal_column_height = atof (optarg);
2452 formfeed_type = FORMFEED_HCOLUMN;
2453 break;
2454
2455 case 149: /* PostScript language level */
2456 pslevel = atoi (optarg);
2457 break;
2458 rizwank 1.1
2459 case 150: /* rotate even-numbered pages */
2460 rotate_even_pages = 1;
2461 break;
2462
2463 case 151: /* highlight style */
2464 xfree (states_highlight_style);
2465 states_highlight_style = xstrdup (optarg);
2466 break;
2467
2468 case 152: /* N-up colunwise */
2469 nup_columnwise = 1;
2470 break;
2471
2472 case 153: /* swap even page margins */
2473 swap_even_page_margins = 1;
2474 break;
2475
2476 case 154: /* extended return values */
2477 extended_return_values = 1;
2478 break;
2479 rizwank 1.1
2480 case 155: /* footer */
2481 page_footer = optarg;
2482 break;
2483
2484 case 156: /* continuous page numbers */
2485 continuous_page_numbers = 1;
2486 break;
2487
2488 case '?': /* Errors found during getopt_long(). */
2489 option_error:
2490 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2491 program);
2492 exit (1);
2493 break;
2494
2495 default:
2496 printf ("Hey! main() didn't handle option \"%c\" (%d)", c, c);
2497 if (optarg)
2498 printf (" with arg %s", optarg);
2499 printf ("\n");
2500 rizwank 1.1 FATAL ((stderr, "This is a bug!"));
2501 break;
2502 }
2503 }
2504 }
2505
2506
2507 static void
2508 usage ()
2509 {
2510 printf (_("\
2511 Usage: %s [OPTION]... [FILE]...\n\
2512 Mandatory arguments to long options are mandatory for short options too.\n\
2513 -# an alias for option -n, --copies\n\
2514 -1 same as --columns=1\n\
2515 -2 same as --columns=2\n\
2516 --columns=NUM specify the number of columns per page\n\
2517 -a, --pages=PAGES specify which pages are printed\n\
2518 -A, --file-align=ALIGN align separate input files to ALIGN\n\
2519 -b, --header=HEADER set page header\n\
2520 -B, --no-header no page headers\n\
2521 rizwank 1.1 -c, --truncate-lines cut long lines (default is to wrap)\n\
2522 -C, --line-numbers[=START]\n\
2523 precede each line with its line number\n\
2524 -d an alias for option --printer\n\
2525 -D, --setpagedevice=KEY[:VALUE]\n\
2526 pass a page device definition to output\n\
2527 -e, --escapes[=CHAR] enable special escape interpretation\n"),
2528 program);
2529
2530 printf (_("\
2531 -E, --highlight[=LANG] highlight source code\n"));
2532
2533 printf (_("\
2534 -f, --font=NAME use font NAME for body text\n\
2535 -F, --header-font=NAME use font NAME for header texts\n\
2536 -g, --print-anyway nothing (compatibility option)\n\
2537 -G same as --fancy-header\n\
2538 --fancy-header[=NAME] select fancy page header\n\
2539 -h, --no-job-header suppress the job header page\n\
2540 -H, --highlight-bars=NUM specify how high highlight bars are\n\
2541 -i, --indent=NUM set line indent to NUM characters\n\
2542 rizwank 1.1 -I, --filter=CMD read input files through input filter CMD\n\
2543 -j, --borders print borders around columns\n\
2544 -J, an alias for option --title\n\
2545 -k, --page-prefeed enable page prefeed\n\
2546 -K, --no-page-prefeed disable page prefeed\n\
2547 -l, --lineprinter simulate lineprinter, this is an alias for:\n\
2548 --lines-per-page=66, --no-header, --portrait,\n\
2549 --columns=1\n"));
2550
2551 printf (_("\
2552 -L, --lines-per-page=NUM specify how many lines are printed on each page\n\
2553 -m, --mail send mail upon completion\n\
2554 -M, --media=NAME use output media NAME\n\
2555 -n, --copies=NUM print NUM copies of each page\n\
2556 -N, --newline=NL select the newline character. Possible\n\
2557 values for NL are: n (`\\n') and r (`\\r').\n\
2558 -o an alias for option --output\n\
2559 -O, --missing-characters list missing characters\n\
2560 -p, --output=FILE leave output to file FILE. If FILE is `-',\n\
2561 leave output to stdout.\n\
2562 -P, --printer=NAME print output to printer NAME\n\
2563 rizwank 1.1 -q, --quiet, --silent be really quiet\n\
2564 -r, --landscape print in landscape mode\n\
2565 -R, --portrait print in portrait mode\n"));
2566
2567 printf (_("\
2568 -s, --baselineskip=NUM set baselineskip to NUM\n\
2569 -S, --statusdict=KEY[:VALUE]\n\
2570 pass a statusdict definition to the output\n\
2571 -t, --title=TITLE set banner page's job title to TITLE. Option\n\
2572 sets also the name of the input file stdin.\n\
2573 -T, --tabsize=NUM set tabulator size to NUM\n\
2574 -u, --underlay[=TEXT] print TEXT under every page\n\
2575 -U, --nup=NUM print NUM logical pages on each output page\n\
2576 -v, --verbose tell what we are doing\n\
2577 -V, --version print version number\n\
2578 -w, --language=LANG set output language to LANG\n\
2579 -W, --options=APP,OPTION pass option OPTION to helper application APP\n\
2580 -X, --encoding=NAME use input encoding NAME\n\
2581 -z, --no-formfeed do not interpret form feed characters\n\
2582 -Z, --pass-through pass through PostScript and PCL files\n\
2583 without any modifications\n"));
2584 rizwank 1.1
2585 printf (_("Long-only options:\n\
2586 --color[=bool] create color outputs with states\n\
2587 --continuous-page-numbers count page numbers across input files. Don't\n\
2588 restart numbering at beginning of each file.\n\
2589 --download-font=NAME download font NAME\n\
2590 --extended-return-values enable extended return values\n\
2591 --filter-stdin=NAME specify how stdin is shown to the input filter\n\
2592 --footer=FOOTER set page footer\n\
2593 --h-column-height=HEIGHT set the horizontal column height to HEIGHT\n\
2594 --help print this help and exit\n"));
2595
2596 printf (_("\
2597 --help-highlight describe all supported --highlight languages\n\
2598 and file formats\n\
2599 --highlight-bar-gray=NUM print highlight bars with gray NUM (0 - 1)\n\
2600 --list-media list names of all known media\n\
2601 --margins=LEFT:RIGHT:TOP:BOTTOM\n\
2602 adjust page marginals\n\
2603 --mark-wrapped-lines[STYLE]\n\
2604 mark wrapped lines in the output with STYLE\n\
2605 rizwank 1.1 --non-printable-format=FMT specify how non-printable chars are printed\n"));
2606
2607 printf (_("\
2608 --nup-columnwise layout pages in the N-up printing columnwise\n\
2609 --nup-xpad=NUM set the page x-padding of N-up printing to NUM\n\
2610 --nup-ypad=NUM set the page y-padding of N-up printing to NUM\n\
2611 --page-label-format=FMT set page label format to FMT\n\
2612 --ps-level=LEVEL set the PostScript language level that enscript\n\
2613 should use\n\
2614 --printer-options=OPTIONS pass extra options to the printer command\n\
2615 --rotate-even-pages rotate even-numbered pages 180 degrees\n"));
2616
2617 printf (_("\
2618 --slice=NUM print vertical slice NUM\n\
2619 --style=STYLE use highlight style STYLE\n\
2620 --swap-even-page-margins swap left and right side margins for each even\n\
2621 numbered page\n\
2622 --toc print table of contents\n\
2623 --ul-angle=ANGLE set underlay text's angle to ANGLE\n\
2624 --ul-font=NAME print underlays with font NAME\n\
2625 --ul-gray=NUM print underlays with gray value NUM\n\
2626 rizwank 1.1 --ul-position=POS set underlay's starting position to POS\n\
2627 --ul-style=STYLE print underlays with style STYLE\n\
2628 --word-wrap wrap long lines from word boundaries\n\
2629 "));
2630
2631 printf (_("\nReport bugs to mtr@iki.fi.\n"));
2632 }
2633
2634
2635 static void
2636 version ()
2637 {
2638 printf ("%s\n\
2639 Copyright (C) 1999 Markku Rossi.\n\
2640 GNU enscript comes with NO WARRANTY, to the extent permitted by law.\n\
2641 You may redistribute copies of GNU enscript under the terms of the GNU\n\
2642 General Public License. For more information about these matters, see\n\
2643 the files named COPYING.\n",
2644 version_string);
2645 }
|