3 # groffer - display groff files
5 # Source file position: <groff-source>/contrib/groffer/subs.pl
6 # Installed position: <prefix>/lib/groff/groffer/subs.pl
8 # Copyright (C) 2006-2014 Free Software Foundation, Inc.
9 # Written by Bernd Warken <groff-bernd.warken-72@web.de>.
11 # This file is part of `groffer', which is part of `groff'.
13 # `groff' is free software; you can redistribute it and/or modify it
14 # under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 2 of the License, or
16 # (at your option) any later version.
18 # `groff' is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see
25 # <http://www.gnu.org/licenses/gpl-2.0.html>.
27 ########################################################################
28 # This file contains the main functions formerly in `groff.pl'
34 ########################################################################
36 ########################################################################
38 sub main_set_options {
39 our %Opts_Cmdline_Short;
40 our %Opts_Cmdline_Long;
41 our $Opts_Cmdline_Long_Str;
42 our %Opts_Cmdline_Double;
43 our %Opts_Groff_Short;
45 # the following options are ignored in groffer.pl, but are kept from
46 # groffer.sh: --shell arg, --debug-shell
48 my @opts_ignored_short_na = ();
49 my @opts_ignored_short_arg = ();
51 my @opts_ignored_long_na = ('debug-shell');
53 my @opts_ignored_long_arg = ('shell');
56 ###### groffer native options
58 my @opts_groffer_short_na = ('h', 'Q', 'v', 'V', 'X', 'Z');
59 my @opts_groffer_short_arg = ('T');
61 my @opts_groffer_long_na = ('auto', 'apropos', 'apropos-data',
62 'apropos-devel', 'apropos-progs', 'debug', 'debug-all',
63 'debug-filenames', 'debug-func', 'debug-grog', 'debug-not-func',
64 'debug-keep', 'debug-lm', 'debug-params', 'debug-stacks',
65 'debug-tmpdir', 'debug-user', 'default', 'do-nothing', 'dvi',
66 'groff', 'help', 'intermediate-output', 'html', 'latin1', 'man',
67 'no-location', 'no-man', 'no-special', 'pdf', 'pdf2', 'ps', 'rv',
68 'source', 'text', 'to-stdout', 'text-device', 'tty', 'tty-device',
69 'utf8', 'version', 'whatis', 'where', 'www', 'x', 'X');
71 ### main_set_options()
72 my @opts_groffer_long_arg =
73 ('default-modes', 'device', 'extension', 'fg', 'fn', 'font',
74 'foreground', 'mode', 'print', 'title', 'viewer',
75 # tty viewers are ignored
76 'dvi-viewer-tty', 'html-viewer-tty', 'pdf-viewer-tty',
77 'ps-viewer-tty', 'tty-viewer-tty', 'www-viewer-tty',
78 'X-viewer-tty', 'x-viewer-tty',
79 # viewers for modes are ignored
80 'dvi-viewer', 'html-viewer', 'pdf-viewer', 'ps-viewer', 'tty-viewer',
81 'www-viewer', 'X-viewer', 'x-viewer',
84 ##### groffer options inhereted from groff
86 my @opts_groff_short_na = ('a', 'b', 'c', 'C', 'e', 'E', 'g', 'G',
87 'i', 'j', 'J', 'k', 'l', 'N', 'p', 'R', 's', 'S', 't', 'U', 'z');
89 my @opts_groff_short_arg = ('d', 'f', 'F', 'I', 'K', 'L', 'm', 'M', 'n',
90 'o', 'P', 'r', 'w', 'W');
92 my @opts_groff_long_na = ();
93 my @opts_groff_long_arg = ();
95 ##### groffer options inhereted from the X Window toolkit
97 my @opts_x_short_na = ();
98 my @opts_x_short_arg = ();
100 my @opts_x_long_na = ('iconic', 'rv');
102 my @opts_x_long_arg = ('background', 'bd', 'bg', 'bordercolor',
103 'borderwidth', 'bw', 'display', 'fg', 'fn', 'font', 'foreground',
104 'ft', 'geometry', 'resolution', 'title', 'xrm');
106 ### main_set_options()
107 ###### groffer options inherited from man
109 my @opts_man_short_na = ();
110 my @opts_man_short_arg = ();
112 my @opts_man_long_na = ('all', 'ascii', 'catman', 'ditroff',
113 'local-file', 'location', 'troff', 'update');
115 my @opts_man_long_arg = ('locale', 'manpath', 'pager',
116 'preprocessor', 'prompt', 'sections', 'systems', 'troff-device');
118 ###### additional options for parsing evironment variable $MANOPT only
120 my @opts_manopt_short_na = ('7', 'a', 'c', 'd', 'D', 'f', 'h', 'k',
121 'l', 't', 'u', 'V', 'w', 'Z');
123 my @opts_manopt_short_arg = ('e', 'L', 'm', 'M', 'p', 'P', 'r', 'S',
126 my @opts_manopt_long_na = (@opts_man_long_na, 'apropos', 'debug',
127 'default', 'help', 'html', 'ignore-case', 'location-cat',
128 'match-case', 'troff', 'update', 'version', 'whatis', 'where',
131 my @opts_manopt_long_arg = (@opts_man_long_na, 'config_file',
132 'encoding', 'extension', 'locale');
134 ### main_set_options()
135 ###### collections of command line options
137 # There are two hashes that control the whole of the command line
138 # options, one for short and one for long options. Options without
139 # and with arguments are mixed by advicing a value of 0 for an option
140 # without argument and a value of 1 for an option with argument.
141 # The options are with leading minus.
143 foreach (@opts_groffer_short_na, @opts_groff_short_na,
144 @opts_x_short_na, @opts_man_short_na, @opts_ignored_short_na) {
145 $Opts_Cmdline_Short{"-$_"} = 0 if $_;
147 foreach (@opts_groffer_short_arg, @opts_groff_short_arg,
148 @opts_x_short_arg, @opts_man_short_arg, @opts_ignored_short_arg) {
149 $Opts_Cmdline_Short{"-$_"} = 1 if $_;
152 foreach (@opts_groffer_long_na, @opts_groff_long_na,
153 @opts_x_long_na, @opts_man_long_na, @opts_ignored_long_na) {
154 $Opts_Cmdline_Long{"--$_"} = 0 if $_;
156 foreach (@opts_groffer_long_arg, @opts_groff_long_arg,
157 @opts_x_long_arg, @opts_man_long_arg, @opts_ignored_long_arg) {
158 $Opts_Cmdline_Long{"--$_"} = 1 if $_;
161 # For determining abbreviations of an option take two spaces as join
163 # The options are without leading minus.
164 $Opts_Cmdline_Long_Str = join ' ', keys %Opts_Cmdline_Long;
165 if ($Opts_Cmdline_Long_Str) {
166 $Opts_Cmdline_Long_Str = " $Opts_Cmdline_Long_Str ";
167 $Opts_Cmdline_Long_Str =~ s/--//g;
170 ### main_set_options()
171 # options with equal meaning are mapped to a single option name
172 # all of these have leading minus characters
173 %Opts_Cmdline_Double = ('-h' => '--help',
177 '-Z' => '--intermediate-output',
178 '--bd' => '--bordercolor',
179 '--bg' => '--background',
180 '--bw' => '--borderwidth',
181 '--debug-all' => '--debug',
182 '--ditroff' => '--intermediate-output',
183 '--fg' => '--foreground',
186 '--latin1' => '--tty',
187 '--troff-device' => '--device',
188 '--tty-device' => '--text-device',
189 '--viewer' => '--viewer',
190 '--where' => '--location',
193 # '--dvi-viewer' => '--viewer',
194 '--dvi-viewer-tty' => '--viewer',
195 '--html-viewer-tty' => '--viewer',
196 '--pdf-viewer-tty' => '--viewer',
197 '--ps-viewer-tty' => '--viewer',
198 '--tty-viewer' => '--pager',
199 '--tty-viewer-tty' => '--pager',
200 '--www-viewer' => '--viewer',
201 '--www-viewer-tty' => '--pager',
202 '--X-viewer' => '--viewer', '--X-viewer-tty'
203 => '--pager', '--x-viewer' => '--viewer',
204 '--x-viewer-tty' => '--pager', );
206 # groff short options with leading minus
207 foreach (@opts_groff_short_na) {
208 $Opts_Groff_Short{"-$_"} = 0;
210 foreach (@opts_groff_short_arg) {
211 $Opts_Groff_Short{"-$_"} = 1;
214 } # main_set_options()
217 ########################################################################
219 ########################################################################
221 sub main_parse_MANOPT {
223 our $File_split_env_sh;
225 if ( $ENV{'MANOPT'} ) {
226 @Manopt = `sh $File_split_env_sh MANOPT`;
230 # %opts stores options that are used by groffer for $MANOPT
231 # All options not in %opts are ignored.
232 # Check options used with %Opts_Cmdline_Double.
233 # 0: option used ('' for ignore), 1: has argument or not
234 ### main_parse_MANOPT()
235 my %opts = ('-7' => ['--ascii', 0],
236 '-L' => ['--locale', 1],
237 '-M' => ['--manpath', 1],
238 '-P' => ['--pager', 1],
239 '-S' => ['--sections', 1],
241 '-w' => ['--location', 0],
242 '-a' => ['--all', 0],
244 '-e' => ['--extension', 1],
245 '-f' => ['--whatis', 1],
246 '-m' => ['--systems', 1],
249 '-manpath' => ['--manpath', 1],
250 '-pager' => ['--pager', 1],
251 '-prompt' => ['', 1],
252 '-sections' => ['--sections', 1],
253 '--all' => ['--all', 0],
254 '--ascii' => ['--ascii', 0],
255 '--catman' => ['', 1],
256 '--device' => ['-T', 1],
257 '--extension' => ['--extension', 1],
258 '--locale' => ['--locale', 1],
259 '--location' => ['--location', 0],
260 '--manpath' => ['--manpath', 1],
261 '--preprocessor' => ['', 1],
262 '--systems' => ['--systems', 1],
263 '--whatis' => ['--whatis', 1],
264 '--where' => ['--location', 0],
267 ### main_parse_MANOPT()
274 # ignore, when not in %opts
275 next unless (exists $opts{$o});
276 if (($o eq '-D') or ($o eq '--default')) {
281 $has_arg = $opts{$o}[1];
282 # ignore, when empty in %opts
284 # ignore without argument
285 next unless ($has_arg);
286 # ignore the argument as well
292 push @manopt, $opt, $Manopt[$i];
302 } # main_parse_MANOPT()
305 ########################################################################
306 # configuration files, $GROFFER_OPT, and command line, main_config_params()
307 ########################################################################
309 sub main_config_params { # handle configuration files
313 our @Starting_ARGV = @ARGV;
315 our %Opts_Cmdline_Short;
316 our %Opts_Cmdline_Long;
317 our $Opts_Cmdline_Long_Str;
318 our %Opts_Cmdline_Double;
319 our %Opts_Groff_Short;
321 our $File_split_env_sh;
325 # options may not be abbreviated, but must be exact
327 foreach my $f ( @Conf_Files ) {
330 open $fh, "<$f" || next;
332 LINE: foreach my $line (<$fh>) {
335 # remove starting and ending whitespace
336 $line =~ s/^\s+|\s+$//g;
337 # replace whitespace by single space
339 # ignore all lines that do not start with minus
340 next unless $line =~ /^-/;
342 if ($line =~ /^---/) {
343 warn "Wrong option $line in configuration file $f.\n";
346 if ( $line =~ /^--[ =]/ ) {
347 warn "No option name in `$line' in configuration " .
351 push @Starting_Conf, $line;
353 if ($line =~ /^--?$/) {
354 warn "`$line' is not allowed in configuration files.\n";
356 ### main_config_params()
357 if ($line =~ /^--/) { # line is long option
359 if ($line =~ /[ =]/) { # has arg on line $line =~
360 /^(--[^ =]+)[ =] ?(.*)$/;
361 ($name, $arg) = ($1, $2);
363 } else { # does not have an argument on line
365 } $name =~ s/[\'\"]//g;
366 unless (exists $Opts_Cmdline_Long{$name}) {
367 # option does not exist
368 warn "Option `$name' does not exist.\n";
372 if ( $Opts_Cmdline_Long{$name} ) { # option has arg
374 push @conf_args, $name, $arg;
376 } else { warn "Option `$name' needs an argument in " .
377 "configuration file $f\n";
380 } else { # option has no arg
382 warn "Option `$name' may not have an argument " .
383 "in configuration file $f\n";
386 push @conf_args, $name; next LINE;
389 ### main_config_params()
390 } else { # line is short option or cluster
395 next if ($opt =~ /\'\"/);
397 warn "Option `$conf_args[$#conf_args]' does not " .
398 "have an argument.\n";
401 if ( exists $Opts_Cmdline_Short{$opt} ) {
403 push @conf_args, $opt;
404 if ( $Opts_Cmdline_Short{$opt} ) { # with arg
408 push @conf_args, "$arg";
413 } else { # short option does not exist
414 warn "Wrong short option `-$opt' from " .
415 "configuration. Rest of line ignored.\n";
425 ### main_config_params()
426 #handle environment variable $GROFFER_OPT
428 if ( $ENV{'GROFFER_OPT'} ) {
429 @GROFFER_OPT = `sh $File_split_env_sh GROFFER_OPT`;
433 # Handle command line parameters together with $GROFFER_OPT.
434 # Options can be abbreviated, with each - as abbreviation place.
436 my @argv0 = (@GROFFER_OPT, @ARGV);
439 my $n = $#argv0; # last element
440 my $n1 = scalar @GROFFER_OPT; # first element of @ARGV
441 my $i = 0; # number of the element
442 my @s = ('the environment variable $GROFFER_OPT', 'the command line');
443 my $j = 0; # index in @s, 0 before $n1, 1 then
444 ELT: while ($i <= $n) {
445 my $elt = $argv0[$i];
448 # remove starting and ending whitespace
449 $elt =~ s/^\s+|\s+$//g;
450 # replace whitespace by single space
454 push @Filespecs, $elt;
458 ### main_config_params()
459 if ( $elt =~ /^-$/ ) { # -
460 push @Filespecs, $elt;
463 if ($elt =~ /^--$/) { # --
468 if ($elt =~ /^--[ =]/) { # no option name
469 warn "No option name in `$elt' at $s[$j].\n";
472 if ($elt =~ /^---/) { # wrong with three minus
473 warn "Wrong option `$elt' at $s[$j].\n";
477 if ($elt =~ /^--[^-]/) { # long option
478 my ($name, $opt, $abbrev, $arg);
479 if ($elt =~ /[ =]/) { # has arg on elt
480 $elt =~ /^--([^ =]+)[ =] ?(.*)$/;
481 ($name, $arg) = ($1, $2);
485 } else { # does not have an argument in the element
490 ### main_config_params()
491 # remove quotes in name
492 $name =~ s/[\'\"]//g;
494 $match =~ s/-/[^- ]*-/g;
495 if ( exists $Opts_Cmdline_Long{$opt} ) {
496 # option exists exactly
497 } elsif ( $Opts_Cmdline_Long_Str =~ / (${match}[^- ]*?) / ) {
498 # option is an abbreviation without further -
500 if ( $Opts_Cmdline_Long_Str =~
501 /\s(${match}[^-\s]*)\s.*\s(${match}[^-\s]*) / ) {
502 warn "Option name `--$abbrev' is not unique: " .
508 } elsif ( $Opts_Cmdline_Long_Str =~ /\s(${match}[^\s]*)\s/ ) {
509 # option is an abbreviation with further -
511 if ( $Opts_Cmdline_Long_Str =~
512 /\s(${match}[^\s]*)\s.*\s(${match}[^\s]*)\s/ ) {
513 warn "Option name `--$abbrev' is not unique: " .
520 warn "Option `--$abbrev' does not exist.\n";
523 ### main_config_params()
524 if ( $Opts_Cmdline_Long{$opt} ) { # option has arg
526 push @argv, "--$name", $arg;
528 } else { # $arg not defined, argument at next element
529 if (($i == $n1) || ($i > $n)) {
530 warn "No argument left for option " .
531 "`$elt' at $s[$j].\n";
533 # add argument as next element
534 push @argv, "--$name", $argv0[$i];
537 } # if (defined $arg)
538 } else { # option has no arg
540 warn "Option `$abbrev' may not have an argument " .
544 push @argv, "--$name";
547 } # if ($Opts_Cmdline_Long{$opt})
548 ### main_config_params()
549 } elsif ( $elt =~ /^-[^-]/ ) { # short option or cluster
553 $cluster =~ s/^(.)//;
555 if ( exists $Opts_Cmdline_Short{$opt} ) { # opt exists
556 if ( $Opts_Cmdline_Short{$opt} ) { # with arg
557 if ($cluster) { # has argument in this element
559 $cluster =~ s/\'\"//g;
560 # add argument as rest of this element
561 push @argv, $opt, $cluster;
563 } else { # argument at next element
564 if (($i == $n1) || ($i > $n)) {
565 warn "No argument left for option " .
566 "`$opt' at $s[$j].\n";
568 ### main_config_params()
569 # add argument as next element
570 push @argv, $opt, $argv0[$i];
575 push @argv, $opt; next;
577 } else { # short option does not exist
578 warn "Wrong short option `$opt' at $s[$j].\n";
580 } # if (exists $Opts_Cmdline_Short{$opt})
582 } else { # not an option, file name
583 push @Filespecs, $elt;
587 ### main_config_params()
588 @Options = (@Manopt, @conf_args, @argv);
589 foreach my $i ( 0..$#Options ) {
590 if ( exists $Opts_Cmdline_Double{$Options[$i]} ) {
591 $Options[$i] = $Opts_Cmdline_Double{ $Options[$i] };
593 } @Filespecs = ('-') unless (@Filespecs);
594 @ARGV = (@Options, '--', @Filespecs);
596 } # main_config_params()
599 ########################################################################
600 # main_parse_params()
601 ########################################################################
603 sub main_parse_params {
604 # options that are ignored in this part
605 # shell version of groffer: --debug*, --shell
606 # man options: --catman (only special in man),
607 # --preprocessor (force groff preproc., handled by grog),
608 # --prompt (prompt for less, ignored),
609 # --troff (-mandoc, handled by grog),
610 # --update (inode check, ignored)
614 our %Opts_Cmdline_Short;
615 our %Opts_Cmdline_Double;
616 our %Opts_Cmdline_Long;
617 our %Opts_Groff_Short;
629 '--debug-not-func' => 0,
631 '--debug-shell' => 0,
632 '--debug-stacks' => 0,
634 '--preprocessor' => 1,
641 ### main_parse_params()
645 sub { $Debug{$_} = 1 foreach (qw/FILENAMES GROG KEEP PARAMS TMPDIR/); },
646 '--debug-filenames' => sub { $Debug{'FILENAMES'} = 1; },
647 '--debug-grog' => sub { $Debug{'GROG'} = 1; },
648 '--debug-keep' => sub { $Debug{'KEEP'} = 1; $Debug{'PARAMS'} = 1; },
649 '--debug-params' => sub { $Debug{'PARAMS'} = 1; },
650 '--debug-tmpdir' => sub { $Debug{'TMPDIR'} = 1; },
651 '--help' => sub { &usage(); $Opt{'DO_NOTHING'} = 1; },
652 '--source' => sub { $Opt{'MODE'} = 'source'; },
654 sub { $Opt{'DEVICE'} = &_get_arg();
668 if ($Opt{'DEVICE'} =~ /^X.*/) {
670 } elsif ( exists $modes{ $Opt{'DEVICE'} } ) {
671 if ( $modes{ $Opt{'DEVICE'} } eq 'tty' ) {
673 unless ($Opt{'MODE'} eq 'text');
675 $Opt{'MODE'} = $modes{ $Opt{'DEVICE'} };
678 # for all elements not in %modes
679 $Opt{'MODE'} = 'groff';
682 ### main_parse_params()
683 '--version' => sub { &version(); $Opt{'DO_NOTHING'} = 1; },
684 '--intermediate-output' => sub { $Opt{'Z'} = 1; },
685 '--all' => sub { $Opt{'ALL'} = 1; },
686 '--apropos' => # run apropos
687 sub { $Opt{'APROPOS'} = 1;
688 delete $Opt{'APROPOS_SECTIONS'};
689 delete $Opt{'WHATIS'}; },
690 '--apropos-data' => # run apropos for data sections
691 sub { $Opt{'APROPOS'} = 1;
692 $Opt{'APROPOS_SECTIONS'} = '457';
693 delete $Opt{'WHATIS'}; },
694 '--apropos-devel' => # run apropos for devel sections
695 sub { $Opt{'APROPOS'} = 1;
696 $Opt{'APROPOS_SECTIONS'} = '239';
697 delete $Opt{'WHATIS'}; },
698 '--apropos-progs' => # run apropos for prog sections
699 sub { $Opt{'APROPOS'} = 1;
700 $Opt{'APROPOS_SECTIONS'} = '168';
701 delete $Opt{'WHATIS'}; },
703 sub { push @Addopts_Groff, '-mtty-char';
704 $Opt{'MODE'} = 'text' unless $Opt{'MODE'}; },
705 '--auto' => # the default automatic mode
706 sub { delete $Opt{'MODE'}; },
707 '--bordercolor' => # border color for viewers, arg
708 sub { $Opt{'BD'} = &_get_arg(); },
709 '--background' => # background color for viewers, arg
710 sub { $Opt{'BG'} = &_get_arg(); },
711 ### main_parse_params()
712 '--borderwidth' => # border width for viewers, arg
713 sub { $Opt{'BW'} = &_get_arg(); },
714 '--default' => # reset variables to default
716 '--default-modes' => # sequence of modes in auto mode; arg
717 sub { $Opt{'DEFAULT_MODES'} = &_get_arg(); },
718 '--display' => # set X display, arg
719 sub { $Opt{'DISPLAY'} = &_get_arg(); },
720 '--do-nothing' => sub { $Opt{'DO_NOTHING'} = 1; },
721 '--dvi' => sub { $Opt{'MODE'} = 'dvi'; },
722 '--extension' => # the extension for man pages, arg
723 sub { $Opt{'EXTENSION'} = &_get_arg(); },
724 '--foreground' => # foreground color for viewers, arg
725 sub { $Opt{'FG'} = &_get_arg(); },
726 '--font' => # set font for viewers, arg
727 sub { $Opt{'FN'} = &_get_arg(); },
728 '--geometry' => # window geometry for viewers, arg
729 sub { $Opt{'GEOMETRY'} = &_get_arg(); },
730 '--groff' => sub { $Opt{'MODE'} = 'groff'; },
731 '--html' => sub { $Opt{'MODE'} = 'html'; },
732 '--iconic' => # start viewers as icons
733 sub { $Opt{'ICONIC'} = 1; },
734 '--locale' => # set language for man pages, arg
735 # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
736 sub { $Opt{'LANG'} = &_get_arg(); },
737 '--local-file' => # force local files; same as `--no-man'
738 sub { delete $Man{'ENABLE'}; delete $Man{'FORCE'}; },
739 '--location' => # print file locations to stderr
740 sub { $Opt{'LOCATION'} = 1; },
741 ### main_parse_params()
742 '--man' => # force all file params to be man pages
743 sub { $Man{'ENABLE'} = 1; $Man{'FORCE'} = 1; },
744 '--manpath' => # specify search path for man pages, arg
745 # arg is colon-separated list of directories
746 sub { $Opt{'MANPATH'} = &_get_arg(); },
747 '--mode' => # display mode
748 sub { my $arg = &_get_arg();
749 my %modes = ( '' => '',
763 'source' => 'source',
765 if ( exists $modes{$arg} ) {
766 if ( $modes{$arg} ) {
767 $Opt{'MODE'} = $modes{$arg};
772 warn "Unknown mode in `$arg' for --mode\n";
775 ### main_parse_params()
776 '--no-location' => # disable former call to `--location'
777 sub { delete $Opt{'LOCATION'}; },
778 '--no-man' => # disable search for man pages
779 sub { delete $Man{'ENABLE'}; delete $Man{'FORCE'}; },
780 '--no-special' => # disable some special former calls
781 sub { delete $Opt{'ALL'}; delete $Opt{'APROPOS'};
782 delete $Opt{'WHATIS'}; },
783 '--pager' => # set paging program for tty mode, arg
784 sub { $Opt{'PAGER'} = &_get_arg(); },
785 '--pdf' => sub { $Opt{'MODE'} = 'pdf'; },
786 '--pdf2' => sub { $Opt{'MODE'} = 'pdf2'; },
787 '--print' => # print argument, for argument test
788 sub { my $arg = &_get_arg; print STDERR $arg . "\n"; },
789 '--ps' => sub { $Opt{'MODE'} = 'ps'; },
790 '--resolution' => # set resolution for X devices, arg
791 sub { my $arg = &_get_arg();
792 my %res = ( '75' => 75,
797 if (exists $res{$arg}) {
798 $Opt{'RESOLUTION'} = $res{$arg};
800 warn "--resolution allows only 75, 75dpi, " .
801 "100, 100dpi as argument.\n";
804 ### main_parse_params()
805 '--rv' => sub { $Opt{'RV'} = 1; },
806 '--sections' => # specify sections for man pages, arg
807 # arg is a `:'-separated (colon) list of section names
808 sub { my $arg = &_get_arg();
809 my @arg = split /:/, $arg;
814 if ($Man{'AUTO_SEC_CHARS'} =~ /$c/) {
817 warn "main_parse_params(): not a man section `$c';";
820 $Opt{'SECTIONS'} = $s; },
821 '--systems' => # man pages for different OS's, arg
822 # argument is a comma-separated list
823 sub { $Opt{'SYSTEMS'} = &_get_arg(); },
824 '--text' => # text mode without pager
825 sub { $Opt{'MODE'} = 'text'; },
826 '--title' => # title for X viewers; arg
827 sub { my $arg = &_get_arg();
829 if ( $Opt{'TITLE'} ) {
830 $Opt{'TITLE'} = "$Opt{'TITLE'} $arg";
832 $Opt{'TITLE'} = $arg;
836 '--text-device' => # device for tty mode; arg
837 sub { $Opt{'TEXT_DEVICE'} = &_get_arg(); },
838 '--to-stdout' => # print mode file without display
839 sub { $Opt{'STDOUT'} = 1; },
840 '--tty' => # tty mode, text with pager
841 sub { $Opt{'MODE'} = 'tty'; },
842 '--viewer' => # viewer for actiual mode
843 sub { $Opt{'VIEWER'} = &_get_arg(); },
844 '--whatis' => sub { delete $Opt{'APROPOS'}; $Opt{'WHATIS'} = 1; },
845 '--x' => sub { $Opt{'MODE'} = 'x'; },
846 ### main_parse_params()
847 '--xrm' => # pass X resource string, arg
848 sub { my $arg = &_get_arg(); push @{$Opt{'XRM'}}, $arg if $arg; },
851 # '--dvi-viewer' => # viewer program for dvi mode; arg
852 # sub { $Opt{'VIEWER_DVI'} = &_get_arg(); },
853 # '--html-viewer' => # viewer program for html mode; arg
854 # sub { $Opt{'VIEWER_HTML'} = &_get_arg(); },
855 # '--pdf-viewer' => # viewer program for pdf and pdf2 mode; arg
856 # sub { $Opt{'VIEWER_PDF'} = &_get_arg(); },
857 # '--ps-viewer' => # viewer program for ps mode; arg
858 # sub { $Opt{'VIEWER_PS'} = &_get_arg(); },
859 # '--x-viewer' => # viewer program for x mode; arg
860 # sub { $Opt{'VIEWER_X'} = &_get_arg(); },
863 '-V' => sub { $Opt{'V'} = 1; },
864 '-X' => sub { $Opt{'X'} = 1; },
868 # check if all options are handled in parse parameters
871 my %these_opts = (%ignored_opts, %short_opts, %Opts_Groff_Short,
872 %Opts_Cmdline_Double);
873 foreach my $key (keys %Opts_Cmdline_Short) {
874 warn "unused option: $key" unless exists $these_opts{$key};
878 %these_opts = (%ignored_opts, %long_opts, %Opts_Cmdline_Double);
879 foreach my $key (keys %Opts_Cmdline_Long) {
880 warn "unused option: $key" unless exists $these_opts{$key};
884 ### main_parse_params()
885 OPTION: while ($i <= $n) {
886 my $opt = $Options[$i];
888 if ($opt =~ /^-([^-])$/) { # single minus for short option
889 if (exists $short_opts{$opt}) { # short option handled by hash
890 $short_opts{$opt}->();
892 } else { # $short_opts{$opt} does not exist
893 my $c = $1; # the option character
894 next OPTION unless $c;
895 if ( exists $Opts_Groff_Short{ $opt } ) { # groff short option
896 if ( $Opts_Groff_Short{ $opt } ) { # option has argument
897 my $arg = $Options[$i];
899 push @Addopts_Groff, $opt, $arg;
901 } else { # no argument for this option
902 push @Addopts_Groff, $opt;
905 } elsif ( exists $Opts_Cmdline_Short{ $opt } ) {
906 # is a groffer short option
907 warn "Groffer option $opt not handled " .
908 "in parameter parsing";
910 warn "$opt is not a groffer option.\n";
912 } # if (exists $short_opts{$opt})
913 } # if ($opt =~ /^-([^-])$/)
914 # now it is a long option
916 # handle ignored options
917 if ( exists $ignored_opts{ $opt } ) {
918 ++$i if ( $ignored_opts{ $opt } );
921 ### main_parse_params()
923 # handle normal long options
924 if (exists $long_opts{$opt}) {
925 $long_opts{$opt}->();
927 warn "Unknown option $opt.\n";
932 if ($Debug{'PARAMS'}) {
933 print STDERR '$MANOPT: ' . $ENV{'MANOPT'} . "\n" if $ENV{'MANOPT'};
934 foreach (@Starting_Conf) {
935 print STDERR "configuration: " . $_ . "\n";
937 print STDERR '$GROFFER_OPT: ' . $ENV{'GROFFER_OPT'} . "\n"
938 if $ENV{'GROFFER_OPT'};
939 print STDERR "command line: @Starting_ARGV\n";
940 print STDERR "parameters: @ARGV\n";
943 if ( $Opt{'WHATIS'} ) {
944 die "main_parse_params(): cannot handle both `whatis' and `apropos';"
947 delete $Opt{'APROPOS_SECTIONS'};
950 if ( $Opt{'DO_NOTHING'} ) {
954 if ( $Opt{'DEFAULT_MODES'} ) {
955 @Default_Modes = split /,/, $Opt{'DEFAULT_MODES'};
957 } # main_parse_params()
965 die '_get_arg(): No argument left for last option;';
967 my $arg = $Options[$i];
970 } # _get_arg() of main_parse_params()
973 ########################################################################
975 ########################################################################
983 our $Viewer_Background;
984 our $PDF_Did_Not_Work;
987 our %Display = ('MODE' => '',
995 $ENV{'DISPLAY'} = $Opt{'DISPLAY'} if $Opt{'DISPLAY'};
997 push @Addopts_Groff, '-V' if $Opt{'V'};
1000 $Display{'MODE'} = 'groff';
1001 push @Addopts_Groff, '-X';
1005 $Display{'MODE'} = 'groff';
1006 push @Addopts_Groff, '-Z';
1009 $Display{'MODE'} = 'groff' if $Opt{'MODE'} and $Opt{'MODE'} eq 'groff';
1011 return 1 if $Display{'MODE'} and $Display{'MODE'} eq 'groff';
1015 if ($Opt{'MODE'} =~ /^(source|text|tty)$/) {
1016 $Display{'MODE'} = $Opt{'MODE'};
1019 $Display{'MODE'} = $Opt{'MODE'} if $Opt{'MODE'} =~ /^html$/;
1020 @modes = ($Opt{'MODE'});
1021 } else { # empty mode
1022 if ($Opt{'DEVICE'}) {
1023 if ($Opt{'DEVICE'} =~ /^X/) {
1024 &is_X() || die "no X display found for device $Opt{'DEVICE'}";
1025 $Display{'MODE'} = 'x';
1029 if ($Opt{'DEVICE'} =~ /^(ascii|cp1047|latin1|utf8)$/) {
1030 $Display{'MODE'} ne 'text' and $Display{'MODE'} = 'tty';
1035 $Display{'MODE'} = 'tty';
1039 @modes = @Default_Modes;
1043 LOOP: foreach my $m (@modes) {
1044 $Viewer_Background = 0;
1045 if ($m =~ /^(test|tty|X)$/) {
1046 $Display{'MODE'} = $m;
1048 } elsif ($m eq 'pdf') {
1049 &_get_prog_args($m) ? return 1: next LOOP;
1050 } elsif ($m eq 'pdf2') {
1051 next LOOP if $PDF_Did_Not_Work;
1052 $PDF_Has_gs = &where_is_prog('gs') ? 1 : 0
1053 unless (defined $PDF_Has_gs);
1054 $PDF_Has_ps2pdf = &where_is_prog('ps2pdf') ? 1 : 0
1055 unless (defined $PDF_Has_ps2pdf);
1056 if ( (! $PDF_Has_gs) and (! $PDF_Has_ps2pdf) ) {
1057 $PDF_Did_Not_Work = 1;
1061 if (&_get_prog_args($m)) {
1064 $PDF_Did_Not_Work = 1;
1067 } else { # other modes
1068 &_get_prog_args($m) ? return 1 : next LOOP;
1071 die 'set mode: no suitable display mode found under ' .
1072 join(', ', @modes) . ';' unless $Display{'MODE'};
1073 die 'set mode: no viewer available for mode ' . $Display{'MODE'} . ';'
1074 unless $Display{'PROG'};
1079 ########################################################################
1080 # functions to main_set_mode()
1081 ########################################################################
1084 # _get_prog_args(<MODE>)
1086 # Simplification for loop in set mode.
1088 # Globals in/out: $Viewer_Background
1089 # globals in : $Opt{VIEWER}, $VIEWER_X{<MODE>},
1090 # $Viewer_tty{<MODE>}
1092 ## globals in : $Opt{VIEWER_<MODE>}, $VIEWER_X{<MODE>},
1093 ## $Viewer_tty{<MODE>}
1095 sub _get_prog_args {
1101 our $Viewer_Background;
1103 die "_get_prog_args(): one argument is needed; you used $n;"
1106 my $mode = lc($_[0]);
1107 my $MODE = uc($mode);
1108 $MODE = 'PDF' if ( $MODE =~ /^PDF2$/ );
1110 my $xlist = $Viewer_X{$MODE};
1111 my $ttylist = $Viewer_tty{$MODE};
1113 # my $vm = "VIEWER_${MODE";
1115 my $opt = $Opt{$vm};
1118 my %prog = &where_is_prog($opt);
1119 my $prog_ref = \%prog;
1121 warn "_get_prog_args(): `$opt' is not an existing program;";
1125 # $prog from $opt is an existing program
1127 ### _get_prog_args() of main_set_mode()
1129 if ( &_check_prog_on_list($prog_ref, $xlist) ) {
1130 $Viewer_Background = 1;
1132 $Viewer_Background = 0;
1133 &_check_prog_on_list($prog_ref, $ttylist);
1136 $Viewer_Background = 0;
1137 &_check_prog_on_list($prog_ref, $ttylist);
1139 } else { # $opt is empty
1140 $Viewer_Background = 0;
1143 $x = &_get_first_prog($xlist);
1144 $Viewer_Background = 1 if $x;
1146 $x = &_get_first_prog($ttylist);
1148 $Display{'MODE'} = $mode if $x;
1151 $Display{'MODE'} = $mode;
1153 } # _get_prog_args() of main_set_mode()
1157 # _get_first_prog(<prog_list_ref>)
1159 # Retrieve from the elements of the list in the argument the first
1160 # existing program in $PATH.
1162 # Local function of main_set_mode().
1164 # Return : `0' if not a part of the list, `1' if found in the list.
1166 sub _get_first_prog {
1169 die "_get_first_prog(): one argument is needed; you used $n;"
1172 foreach my $i (@{$_[0]}) {
1174 my %prog = &where_is_prog($i);
1176 $Display{'PROG'} = $prog{'fullname'};
1177 $Display{'ARGS'} = $prog{'args'};
1182 } # _get_first_prog() of main_set_mode()
1186 # _check_prog_on_list (<prog-hash-ref> <prog_list_ref>)
1188 # Check whether the content of <prog-hash-ref> is in the list
1190 # The globals are set correspondingly.
1192 # Local function for main_set_mode().
1196 # Return : `0' if not a part of the list, `1' if found in the list.
1199 # Globals in : $Viewer_X{<MODE>}, $Viewer_tty{<MODE>}
1200 # Globals in/out: $Display{'PROG'}, $Display{'ARGS'}
1202 sub _check_prog_on_list {
1205 die "_get_first_prog(): 2 arguments are needed; you used $n;"
1208 my %prog = %{$_[0]};
1210 $Display{'PROG'} = $prog{'fullname'};
1211 $Display{'ARGS'} = $prog{'args'};
1213 foreach my $i (@{$_[1]}) {
1214 my %p = &where_is_prog($i);
1216 next unless $Display{'PROG'} eq $p{'fullname'};
1218 if ($Display{'ARGS'}) {
1219 $Display{'ARGS'} = $p{'args'};
1221 $Display{'ARGS'} = "$p{'args'} $Display{'ARGS'}";
1226 # prog was not in the list
1228 } # _check_prog_on_list() of main_set_mode()
1231 ########################################################################
1232 # groffer temporary directory, main_temp()
1233 ########################################################################
1242 my $template = 'groffer_' . "$$" . '_XXXX';
1243 foreach ($ENV{'GROFF_TMPDIR'}, $ENV{'TMPDIR'}, $ENV{'TMP'}, $ENV{'TEMP'},
1244 $ENV{'TEMPDIR'}, File::Spec->catfile($ENV{'HOME'}, 'tmp')) {
1245 if ($_ && -d $_ && -w $_) {
1246 if ($Debug{'KEEP'}) {
1247 eval { $tmpdir = tempdir( $template, DIR => "$_" ); };
1249 eval { $tmpdir = tempdir( $template,
1250 CLEANUP => 1, DIR => "$_" ); };
1255 $tmpdir = tempdir( $template, CLEANUP => 1, DIR => File::Spec->tmpdir )
1258 # see Lerning Perl, page 205, or Programming Perl, page 413
1259 # $SIG{'INT'} is for Ctrl-C interruption
1260 $SIG{'INT'} = sub { &clean_up(); die "interrupted..."; };
1261 $SIG{'QUIT'} = sub { &clean_up(); die "quit..."; };
1263 if ($Debug{'TMPDIR'}) {
1264 if ( $Debug{'KEEP'}) {
1265 print STDERR "temporary directory is kept: " . $tmpdir . "\n";
1267 print STDERR "temporary directory will be cleaned: " .
1272 # further argument: SUFFIX => '.sh'
1273 if ($Debug{'KEEP'}) {
1274 ($fh_cat, $tmp_cat) = tempfile(',cat_XXXX', DIR => $tmpdir);
1275 ($fh_stdin, $tmp_stdin) = tempfile(',stdin_XXXX', DIR => $tmpdir);
1277 ($fh_cat, $tmp_cat) = tempfile(',cat_XXXX', UNLINK => 1,
1279 ($fh_stdin, $tmp_stdin) = tempfile(',stdin_XXXX', UNLINK => 1,
1285 ########################################################################
1286 # subs needed for main_do_fileargs()
1287 ########################################################################
1290 # register_file(<filename>)
1292 # Write a found file and register the title element.
1294 # Arguments: 1: a file name
1300 die "register_file(): one argument is needed; you used $n;"
1302 die 'register_file(): file name is empty;' unless $_[0];
1305 &to_tmp($tmp_stdin) && ®ister_title('stdin');
1307 &to_tmp($_[0]) && ®ister_title($_[0]);
1314 # register_title(<filespec>)
1316 # Create title element from <filespec> and append to $_REG_TITLE_LIST.
1317 # Basename is created.
1319 # Globals in/out: @REG_TITLE
1321 # Variable prefix: rt
1323 sub register_title {
1327 die "register_title(): one argument is needed; you used $n;"
1329 return 1 unless $_[0];
1331 return 1 if scalar @REG_TITLE > 3;
1333 my $title = &get_filename($_[0]);
1335 $title =~ s/\.bz2$//g;
1336 $title =~ s/\.gz$//g;
1337 $title =~ s/\.Z$//g;
1339 if ($Debug{'FILENAMES'}) {
1340 if ($_[0] eq 'stdin') {
1341 print STDERR "register_title(): file title is stdin\n";
1343 print STDERR "register_title(): file title is $title\n";
1345 } # if ($Debug{'FILENAMES'})
1347 return 1 unless $title;
1348 push @REG_TITLE, $title;
1350 } # register_title()
1356 # Store standard input to temporary file (with decompression).
1365 my ($fh_input, $tmp_input);
1366 $tmp_input = File::Spec->catfile($tmpdir, ',input');
1367 open $fh_input, ">$tmp_input" or
1368 die "save_stdin(): could not open $tmp_input";
1373 open $fh_stdin, ">$tmp_stdin" or
1374 die "save_stdin(): could not open $tmp_stdin";
1375 foreach ( &cat_z("$tmp_input") ) {
1379 unlink $tmp_input unless $Debug{'KEEP'};
1383 ########################################################################
1384 # main_do_fileargs()
1385 ########################################################################
1387 sub main_do_fileargs {
1394 our $Filespec_Is_Man;
1395 our $Special_Filespec;
1401 if ($Opt{'APROPOS'}) {
1402 if ($No_Filespecs) {
1403 &apropos_filespec();
1407 foreach (@Filespecs) {
1412 } # foreach (@Filespecs)
1413 } # if ($Opt{'APROPOS'})
1421 FILESPEC: foreach (@Filespecs) {
1424 $Filespec_Is_Man = 0;
1426 $Special_Filespec = 0;
1428 next FILESPEC unless $filespec;
1430 ### main_do_fileargs()
1431 if ($twoargs) { # second run
1433 # $section and $ext are kept from earlier run
1434 my $h = { 'name' => $filespec, 'sec' => $section, 'ext' => $ext };
1436 if ( &is_man($h) ) {
1437 $Filespec_Arg = "$former_arg $Filespec_Arg";
1438 &special_filespec();
1439 $Filespec_Is_Man = 1;
1443 warn "main_do_fileargs(): $former_arg is neither a file nor a " .
1444 "man page nor a section argument for $filespec;";
1449 if ( $Opt{'APROPOS'} ) {
1450 &apropos_filespec();
1454 if ($filespec eq '-') {
1455 ®ister_file('-');
1456 &special_filespec();
1458 } elsif ( &get_filename($filespec) ne $filespec ) { # path with dir
1459 &special_filespec();
1460 if (-f $filespec && -r $filespec) {
1461 ®ister_file($filespec)
1463 warn "main_do_fileargs: the argument $filespec is not a file;";
1466 } else { # neither `-' nor has dir
1467 # check whether filespec is an existing file
1468 unless ( $Man{'FORCE'} ) {
1469 if (-f $filespec && -r $filespec) {
1470 &special_filespec();
1471 ®ister_file($filespec);
1475 } # if ($filespec eq '-')
1477 ### main_do_fileargs()
1478 # now it must be a man page pattern
1480 if ($Macro_Pkg and $Macro_Pkg ne '-man') {
1481 warn "main_do_fileargs(): $filespec is not a file, " .
1482 "man pages are ignored due to $Macro_Pkg;";
1486 # check for man page
1488 unless ( $Man{'ENABLE'} ) {
1489 warn "main_do_fileargs(): the argument $filespec is not a file;";
1493 if ( $Man{'FORCE'} ) {
1494 $errmsg = 'is not a man page';
1496 $errmsg = 'is neither a file nor a man page';
1499 $Filespec_Is_Man = 1;
1501 ### main_do_fileargs()
1502 # test filespec with `man:...' or `...(...)' on man page
1504 my @names = ($filespec);
1505 if ($filespec =~ /^man:(.*)$/) {
1509 foreach my $i (@names) {
1511 my $h = { 'name' => $i };
1512 if ( &is_man($h) ) {
1513 &special_filespec();
1517 if ( $i =~ /^(.*)\(([$Man{'AUTO_SEC_CHARS'}])(.*)\)$/ ) {
1518 $h = { 'name' => $1, 'sec' => $2, 'ext' => $3 };
1519 if ( &is_man($h) ) {
1520 &special_filespec();
1525 if ( $i =~ /^(.*)\.([$Man{'AUTO_SEC_CHARS'}])(.*)$/ ) {
1526 $h = { 'name' => $1, 'sec' => $2, 'ext' => $3 };
1527 if ( &is_man($h) ) {
1528 &special_filespec();
1533 } # foreach (@names)
1535 ### main_do_fileargs()
1536 # check on "s name", where "s" is a section with or without an extension
1537 if ($filespec =~ /^([$Man{'AUTO_SEC_CHARS'}])(.*)$/) {
1538 unless ( $Man{'ENABLE'} ) {
1539 warn "main_do_fileargs(): $filespec $errmsg;";
1545 $former_arg = $filespec;
1548 warn "main_do_fileargs(): $filespec $errmsg;";
1551 } # foreach (@Filespecs)
1554 warn "main_do_fileargs(): no filespec arguments left for second run;";
1558 } # main_do_fileargs()
1561 ########################################################################
1562 # main_set_resources()
1563 ########################################################################
1566 # main_set_resources ()
1568 # Determine options for setting X resources with $_DISPLAY_PROG.
1570 # Globals: $Display{PROG}, $Output_File_Name
1572 sub main_set_resources {
1579 our $Default_Resolution;
1582 our $Output_File_Name;
1584 # $prog viewer program
1586 unlink $tmp_stdin unless $Debug{'KEEP'};
1587 $Output_File_Name = '';
1589 my @title = @REG_TITLE;
1590 @title = ($Opt{'TITLE'}) unless @title;
1591 @title = () unless @title;
1593 foreach my $n (@title) {
1595 $n =~ s/^,+// if $n =~ /^,/;
1597 $Output_File_Name = $Output_File_Name . ',' if $Output_File_Name;
1598 $Output_File_Name = "$Output_File_Name$n";
1599 } # foreach (@title)
1601 $Output_File_Name =~ s/^,+//;
1602 $Output_File_Name = '-' unless $Output_File_Name;
1603 $Output_File_Name = File::Spec->catfile($tmpdir, $Output_File_Name);
1605 ### main_set_resources()
1606 unless ($Display{'PROG'}) { # for example, for groff mode
1607 $Display{'ARGS'} = '';
1611 my %h = &where_is_prog($Display{'PROG'});
1612 my $prog = $h{'file'};
1613 if ($Display{'ARGS'}) {
1614 $Display{'ARGS'} = "$h{'args'} $Display{'ARGS'}";
1616 $Display{'ARGS'} = $h{'args'};
1622 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1623 push @rl, '-bd', $Opt{'BD'};
1628 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1629 push @rl, '-bg', $Opt{'BG'};
1630 } elsif ($prog eq 'kghostview') {
1631 push @rl, '--bg', $Opt{'BG'};
1632 } elsif ($prog eq 'xpdf') {
1633 push @rl, '-papercolor', $Opt{'BG'};
1637 ### main_set_resources()
1639 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1640 push @rl, '-bw', $Opt{'BW'};
1645 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1646 push @rl, '-fg', $Opt{'FG'};
1647 } elsif ($prog eq 'kghostview') {
1648 push @rl, '--fg', $Opt{'FG'};
1653 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1654 push @rl, '-fn', $Opt{'FN'};
1655 } elsif ($prog eq 'kghostview') {
1656 push @rl, '--fn', $Opt{'FN'};
1660 if ($Opt{'GEOMETRY'}) {
1661 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1662 push @rl, '-geometry', $Opt{'GEOMETRY'};
1663 } elsif ($prog eq 'kghostview') {
1664 push @rl, '--geometry', $Opt{'GEOMETRY'};
1668 ### main_set_resources()
1669 if ($Opt{'RESOLUTION'}) {
1670 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1671 push @rl, '-resolution', $Opt{'RESOLUTION'};
1672 } elsif ($prog eq 'xpdf') {
1673 if ($Display{'PROG'} !~ / -z/) { # if xpdf does not have option -z
1674 if ($Default_Resolution == 75) {
1675 push @rl, '-z', 104;
1676 } elsif ($Default_Resolution == 100) { # 72dpi is '100'
1677 push @rl, '-z', 139;
1681 } else { # empty $Opt{RESOLUTION}
1682 $Opt{'RESOLUTION'} = $Default_Resolution;
1683 if ($prog =~ /^(gxditview|xditview)$/) {
1684 push @rl, '-resolution', $Default_Resolution;
1685 } elsif ($prog eq 'xpdf') {
1686 if ($Display{'PROG'} !~ / -z/) { # if xpdf does not have option -z
1687 if ($Default_Resolution == 75) {
1688 push @rl, '-z', 104;
1689 } elsif ($Default_Resolution == 100) { # 72dpi is '100'
1690 push @rl, '-z', 139;
1694 } # if $Opt{RESOLUTION}
1696 if ($Opt{'ICONIC'}) {
1697 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1698 push @rl, '-iconic';
1702 ### main_set_resources()
1704 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi)$/) {
1709 if (@{$Opt{'XRM'}}) {
1710 if ($prog =~ /^(ghostview|gv|gxditview|xditview|xdvi|xpdf)$/) {
1711 foreach (@{$Opt{'XRM'}}) {
1712 push @rl, '-xrm', $_;
1718 if ($prog =~ /^(gxditview|xditview)$/) {
1719 push @rl, '-title', $Output_File_Name;
1723 my $args = join ' ', @rl;
1724 if ($Display{'ARGS'}) {
1725 $Display{'ARGS'} = "$args $Display{'ARGS'}";
1727 $Display{'ARGS'} = $args;
1731 } # main_set_resources()
1734 ########################################################################
1736 ########################################################################
1741 # Do the actual display of the whole thing.
1744 # in: $Display{MODE}, $Opt{DEVICE}, @Addopts_Groff,
1745 # $fh_cat, $tmp_cat, $Opt{PAGER}, $Output_File_Name
1748 our ( %Display, %Opt, %Debug, %Viewer_tty, %Viewer_X );
1752 our ( $groggy, $modefile, $addopts, $fh_cat, $tmp_cat, $tmpdir );
1753 our ( $Output_File_Name, $Default_tty_Device );
1755 $addopts = join ' ', @Addopts_Groff;
1758 warn "groffer: empty input\n";
1763 $modefile = $Output_File_Name;
1765 # go to the temporary directory to be able to access internal data files
1769 SWITCH: foreach ($Display{'MODE'}) {
1771 push @Addopts_Groff, "-T$Opt{'DEVICE'}" if $Opt{'DEVICE'};
1772 $addopts = join ' ', @Addopts_Groff;
1773 $groggy = `cat $tmp_cat | grog`;
1774 die "main_display(): grog error;" if $?;
1776 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1779 rename $tmp_cat, $modefile;
1780 system("cat $modefile | $groggy $addopts");
1785 /^(text|tty)$/ and do {
1787 if (! $Opt{'DEVICE'}) {
1788 $device = $Opt{'TEXT_DEVICE'};
1789 $device = $Default_tty_Device unless $device;
1790 } elsif ($Opt{'DEVICE'} =~ /^(ascii||cp1047|latin1|utf8)$/) {
1791 $device = $Opt{'DEVICE'};
1793 warn "main_display(): wrong device for $Display{'MODE'} mode: " .
1796 $groggy = `cat $tmp_cat | grog -T$device`;
1797 die "main_display(): grog error;" if $?;
1799 print STDERR "grog output: " . $groggy . "\n" if $Debug{'GROG'};
1800 if ($Display{'MODE'} eq 'text') {
1802 system("cat $tmp_cat | $groggy $addopts");
1808 # mode is not 'text', but `tty'
1811 push @p, $Opt{'PAGER'} if $Opt{'PAGER'};
1812 push @p, $ENV{'PAGER'} if $ENV{'PAGER'};
1814 %pager = &where_is_prog($_);
1816 if ($pager{'file'} eq 'less') {
1817 if ($pager{'args'}) {
1818 $pager{'args'} = "-r -R $pager{'args'}";
1820 $pager{'args'} = '-r -R';
1823 last if $pager{'file'};
1826 foreach (@{$Viewer_tty{'TTY'}}, @{$Viewer_X{'TTY'}}, 'cat') {
1828 %pager = &where_is_prog($_);
1832 die "main_display(): no pager program found for tty mode;"
1835 system("cat $tmp_cat | $groggy $addopts | " .
1836 "$pager{'fullname'} $pager{'args'}");
1842 open $fh_cat, "<$tmp_cat";
1843 foreach (<$fh_cat>) {
1852 if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'dvi') {
1853 warn "main_display(): " .
1854 "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
1856 $modefile .= '.dvi';
1857 $groggy = `cat $tmp_cat | grog -Tdvi`;
1858 die "main_display(): grog error;" if $?;
1860 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1866 if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'html') {
1867 warn "main_display(): " .
1868 "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
1870 $modefile .= '.html';
1871 $groggy = `cat $tmp_cat | grog -Thtml`;
1872 die "main_display(): grog error;" if $?;
1874 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1880 $modefile .= '.pdf';
1881 $groggy = `cat $tmp_cat | grog -Tpdf --ligatures`;
1882 die "main_display(): grog error;" if $?;
1884 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1891 if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'ps') {
1892 warn "main_display(): " .
1893 "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
1896 $groggy = `cat $tmp_cat | grog -Tps`;
1897 die "main_display(): grog error;" if $?;
1899 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1900 &_do_display(\&_make_pdf2);
1906 if ($Opt{'DEVICE'} && $Opt{'DEVICE'} ne 'ps') {
1907 warn "main_display(): " .
1908 "wrong device for $Display{'MODE'} mode: $Opt{'DEVICE'};"
1911 $groggy = `cat $tmp_cat | grog -Tps`;
1912 die "main_display(): grog error;" if $?;
1914 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1921 if ($Opt{'DEVICE'} && $Opt{'DEVICE'} =~ /^X/) {
1922 $device = $Opt{'DEVICE'};
1924 if ($Opt{'RESOLUTION'} == 100) {
1925 if ( $Display{'PROG'} =~ /^(g|)xditview$/ ) {
1926 # add width of 800dpi for resolution of 100dpi to the args
1927 $Display{'ARGS'} .= ' -geometry 800';
1928 $Display{'ARGS'} =~ s/^ //;
1930 } else { # RESOLUTIOM != 100
1934 $groggy = `cat $tmp_cat | grog -T$device -Z`;
1935 die "main_display(): grog error;" if $?;
1937 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1944 if (! $Opt{'DEVICE'}) {
1945 $groggy = `cat $tmp_cat | grog -X`;
1946 die "main_display(): grog error;" if $?;
1948 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1949 } elsif ($Opt{'DEVICE'} =~ /^(X.*|dvi|html|lbp|lj4|ps)$/) {
1950 # these devices work with
1951 $groggy = `cat $tmp_cat | grog -T$Opt{'DEVICE'} -X`;
1952 die "main_display(): grog error;" if $?;
1954 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1956 warn "main_display(): wrong device for " .
1957 "$Display{'MODE'} mode: $Opt{'DEVICE'};";
1958 $groggy = `cat $tmp_cat | grog -Z`;
1959 die "main_display(): grog error;" if $?;
1961 print STDERR "grog output: $groggy\n" if $Debug{'GROG'};
1968 die "main_display(): unknown mode `$Display{'MODE'}';";
1976 ########################
1977 # _do_display ([<prog>])
1979 # Perform the generation of the output and view the result. If an
1980 # argument is given interpret it as a function name that is called in
1981 # the midst (actually only for `pdf').
1984 our ( %Display, %Debug, %Opt );
1986 our ( $modefile, $tmpdir, $tmp_cat, $addopts, $groggy );
1987 our ( $Viewer_Background );
1990 unless ($Display{'PROG'}) {
1991 system("$groggy $addopts $tmp_cat");
1996 die "_do_display(): empty output;" if -z $tmp_cat;
1997 system("cat $tmp_cat | $groggy $addopts >$modefile");
1998 die "_do_display(): empty output;" if -z $modefile;
1999 &print_times("before display");
2000 if ($_[0] && ref($_[0]) eq 'CODE') {
2003 unlink $tmp_cat unless $Debug{'KEEP'};
2005 if ( $Opt{'STDOUT'} ) {
2007 open $fh, "<$modefile";
2015 if ( $Viewer_Background ) {
2016 if ($Debug{'KEEP'}) {
2017 exec "$Display{'PROG'} $Display{'ARGS'} $modefile &";
2019 exec "{ $Display{'PROG'} $Display{'ARGS'} $modefile; " .
2020 "rm -rf $tmpdir; } &";
2023 system("$Display{'PROG'} $Display{'ARGS'} $modefile");
2026 } # _do_display() of main_display()
2032 # Check on option `-V'; if set print the corresponding output and leave.
2034 # Globals: @ARGV, $Display{MODE}, $Display{PROG},
2035 # $Display{ARGS}, $groggy, $modefile, $addopts
2042 our ($groggy, $modefile, $addopts);
2046 print "Parameters: @ARGV\n";
2047 print "Display Mode: $Display{'MODE'}\n";
2048 print "Output file: $modefile\n";
2049 print "Display prog: $Display{'PROG'} $Display{'ARGS'}\n";
2050 print "Output of grog: $groggy $addopts\n";
2051 my $res = `$groggy $addopts\n`;
2053 print "groff -V: $res\n";
2057 } # _do_opt_V() of main_display()
2063 # Transform to ps/pdf format; for pdf2 mode in _do_display().
2065 # Globals: $md_modefile (from main_display())
2071 our $PDF_Did_Not_Work;
2073 our $PDF_Has_ps2pdf;
2077 die "_make_pdf2(): pdf2 mode did not work;" if $PDF_Did_Not_Work;
2078 my $psfile = $modefile;
2079 die "_make_pdf2(): empty output;" if -z $modefile;
2080 $modefile =~ s/\.ps$/.pdf/;
2083 if ($PDF_Has_ps2pdf) {
2084 system("ps2pdf $psfile $modefile 2>$Dev_Null");
2087 if (! $done && $PDF_Has_gs) {
2088 system("gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite " .
2089 "-sOutputFile=$modefile -c save pop -f $psfile 2>$Dev_Null");
2093 $PDF_Did_Not_Work = 1;
2094 warn '_make_pdf2(): Could not transform into pdf format, ' .
2095 'the Postscript mode (ps) is used instead;';
2096 $Opt{'MODE'} = 'ps';
2098 &main_set_resources();
2102 unlink $psfile unless $Debug{'KEEP'};
2104 } # _make_pdf2() of main_display()
2108 ########################################################################