source: trunk/third/enscript/src/main.c @ 17631

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