summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwlemb <wlemb>2002-01-05 21:53:10 +0000
committerwlemb <wlemb>2002-01-05 21:53:10 +0000
commit21354b4829b79ceea3a9e88eb64ffc3c3bf20bbf (patch)
tree6a80311325bcd14b3edefe426e1d2b74e8fc7012
parent8847026dc2642b3b55c35b0dca04ce244afd3aad (diff)
downloadgroff-21354b4829b79ceea3a9e88eb64ffc3c3bf20bbf.tar.gz
Initial revision
-rw-r--r--contrib/groffer/ChangeLog61
-rw-r--r--contrib/groffer/Makefile.sub19
-rw-r--r--contrib/groffer/groffer.man829
-rw-r--r--contrib/groffer/groffer.sh1417
4 files changed, 2326 insertions, 0 deletions
diff --git a/contrib/groffer/ChangeLog b/contrib/groffer/ChangeLog
new file mode 100644
index 00000000..edfc3b37
--- /dev/null
+++ b/contrib/groffer/ChangeLog
@@ -0,0 +1,61 @@
+2002-01-05 Werner LEMBERG <wl@gnu.org>
+
+ Integrate groffer into groff's `contrib' tree.
+
+ * Makefile: Replaced by...
+ * Makefile.sub: New file.
+ * groffer: Replaced by...
+ * groffer.sh: New file.
+
+ * groffer.man (OptDef): Add missing backslashes.
+ Update copyright.
+
+2001-12-15 Bernd Warken <bwarken@mayn.de>
+
+ * groffer 0.3 (alpha) released (still stand-alone package).
+
+ * GNU and POSIX are supported (POSIX without long options).
+
+ * New options : --man, --mandb, --title, --xrdb
+
+ * Support for command line arguments with embedded single space
+ characters (GNU only) .
+
+ * Several search methods for man-pages when no `man -w' is
+ available.
+
+2001-12-03 Bernd Warken <bwarken@mayn.de>
+
+ * Stand-alone package for groffer 0.2 (alpha) created
+ Files: groffer, groffer.man, Makefile, TODO, ChangeLog
+
+2001-12-02 Bernd Warken <bwarken@mayn.de>
+
+ * groffer 0.2 (alpha) program released.
+
+ * Name changed from `groffview' to `groffer'.
+
+ * Comments added.
+
+ * Name changed from `groffview' to `groffer'.
+
+ * Options harmonized with groff.
+ New options : -Q --source, -T --device, -X .
+ Other options known from groff are passed unchanged.
+
+ * 100 dpi as default, 75 dpi only in emergency situations.
+
+ * Bugs with temporary files fixed.
+
+ * Code restructured and comments added.
+
+2001-11-28 Bernd Warken <bwarken@mayn.de>
+
+ * groffview 0.1 (experimental) and groffview.man released
+ (predecessor of groffer, shell script)
+
+ * Options : -h --help, -v --version
+
+ * Search for man-pages based on $MANPATH
+
+ * development of `groffview' shell script started
diff --git a/contrib/groffer/Makefile.sub b/contrib/groffer/Makefile.sub
new file mode 100644
index 00000000..45f57b01
--- /dev/null
+++ b/contrib/groffer/Makefile.sub
@@ -0,0 +1,19 @@
+MAN1=groffer.n
+CLEANADD=groffer
+
+all: groffer
+
+groffer: groffer.sh
+ rm -f $@; \
+ sed -e "s|@g@|$(g)|g" \
+ -e "s|@VERSION@|$(version)$(revision)|" \
+ -e $(SH_SCRIPT_SED_CMD) $(srcdir)/groffer.sh >$@; \
+ chmod +x $@
+
+install_data: groffer
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/groffer
+ $(INSTALL_SCRIPT) groffer $(bindir)/groffer
+
+uninstall_sub:
+ -rm -f $(bindir)/groffer
diff --git a/contrib/groffer/groffer.man b/contrib/groffer/groffer.man
new file mode 100644
index 00000000..3e9dfe56
--- /dev/null
+++ b/contrib/groffer/groffer.man
@@ -0,0 +1,829 @@
+.ig
+groffer.man
+
+Version : groffer 0.3 (alpha)
+Last update : 05 Jan 2002
+
+This file is part of groff, the GNU roff type-setting system.
+
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+Written by Bernd Warken <bwarken@mayn.de>
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being this .ig-section and AUTHORS, with no
+Front-Cover Texts, and with no Back-Cover Texts.
+
+A copy of the Free Documentation License is included as a file called
+FDL in the main directory of the groff source package.
+..
+.
+.\" --------------------------------------------------------------------
+.\" Setup
+.\" --------------------------------------------------------------------
+.
+.mso www.tmac
+.
+.if n \{\
+. mso tty-char.tmac
+. ftr CR R
+. ftr CI I
+. ftr CB B
+.\}
+.if '\*[.T]'dvi' \{\
+. ftr CB CW
+.\}
+.
+.ie t \{\
+. ds @- "\-\"
+. ds @-- "\-\-\"
+.\}
+.el \{\
+. ds @- "-\"
+. ds @-- "--\"
+.\}
+.
+.ds Ellipsis .\|.\|.\"
+.
+.ad b
+.
+.\" --------------------------------------------------------------------
+.\" Start macro definitions
+.eo
+.
+.\" --------------------------------------------------------------------
+.de TP+
+.br
+.ns
+.TP \$1
+..
+.\" --------------------------------------------------------------------
+.de Text
+. nop \)\$*
+..
+.\" --------------------------------------------------------------------
+.\" Topic
+.\"
+.\" a bulleted paragraph
+.\"
+.de Topic
+. TP 2m
+. Text \(bu
+..
+.\" --------------------------------------------------------------------
+.\" LongOpt ([name [punct]])
+.\"
+.\" `--name' somwhere in the text
+.\" second arg is punctuation
+.\"
+.de LongOpt
+. ds @opt \$1\"
+. shift
+. Text \f(CB\*[@--]\fP\fB\*[@opt]\fP\/\$*
+. rm @opt
+..
+.\" --------------------------------------------------------------------
+.\" ShortOpt ([char [punct]])
+.\"
+.\" `-c' somwhere in the text
+.\" second arg is punctuation
+.\"
+.de ShortOpt
+. ds @opt \$1\"
+. shift
+. Text \f(CB\*[@-]\*[@opt]\fP\/\$*
+. rm @opt
+..
+.\" --------------------------------------------------------------------
+.\" [LongOpt] (name [arg])
+.\"
+.\" long option in synopsis
+.\"
+.de [LongOpt]
+. if \n[.$]=0 .return
+. ds @opt \$1\"
+. shift
+. ie \n[.$]=0 \
+. Text \fR[\fP\f(CB\*[@--]\fP\fB\*[@opt]\fP\fR]\fP
+. el \
+. Text \fR[\fP\f(CB\*[@--]\fP\fB\*[@opt] \fP\fI\/\$*\fP\fR]\fP
+. rm @opt
+..
+.\" --------------------------------------------------------------------
+.\" [ShortOpt] (name [arg])
+.\"
+.\" short option in synopsis
+.\"
+.de [ShortOpt]
+. if \n[.$]=0 .return
+. ds @opt \$1\"
+. shift
+. ie \n[.$]=0 \
+. Text \fR[\fP\f(CB\*[@-]\*[@opt]\fP\fR]\fP
+. el \
+. Text \fR[\fP\f(CB\*[@-]\*[@opt] \fP\fI\/\$*\fP\fR]\fP
+. rm @opt
+..
+.\" --------------------------------------------------------------------
+.\" OptDef (shortopt [longopt [argument]])
+.\"
+.\" option documentation
+.\" args : `shortopt', `longopt' can be ""
+.\"
+.de OptDef
+. rm @short
+. rm @long
+. rm @arg
+. if \n[.$]>=1 \{\
+. ds @arg1 "\$1\"
+. if !'\*[@arg1]'' .ds @short "\f(CB\*[@-]\*[@arg1]\fP\"
+. if \n[.$]>=2 \{\
+. if !'\*[@short]'' \
+. as @short \f(CW\0\fP
+. ds @arg2 "\$2\"
+. if !'\*[@arg2]'' \
+. ds @long "\f(CB\*[@--]\fP\fB\*[@arg2]\fP\"
+. if \n[.$]>=3 \{\
+. if !'\*[@long]'' \
+. as @long \|=\|\"
+. shift 2
+. ds @arg \fI\$*\"
+. \}
+. \}
+. \}
+. IP "\fR\*[@short]\*[@long]\*[@arg]\fP"
+. rm @arg
+. rm @arg1
+. rm @arg2
+. rm @short
+. rm @long
+..
+.\" --------------------------------------------------------------------
+.\" environment variable
+.de EnvVar
+. SM
+. BR \$1 \$2
+..
+.\" --------------------------------------------------------------------
+.\" a shell command line
+.de ShellCommand
+. br
+. IR "shell>" "\h'1m'\f(CB\$*\fP\/"
+..
+.\" --------------------------------------------------------------------
+.de Synopsis
+. ds @arg1 \$1\"
+. nr @old_indent \n(.i
+. ad l
+. in +\w'\fB\*[@arg1]\0'u
+. ti \n[@old_indent]u
+. B \*[@arg1]\0\c
+. rr @old_indent
+. rm @arg1
+..
+.de EndSynopsis
+. br
+. ad
+. in
+..
+.ec
+.\" End of macro definitions
+.
+.
+.\" --------------------------------------------------------------------
+.\" Title
+.\" --------------------------------------------------------------------
+.
+.TH GROFFER @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groffer \- display groff files and man-pages on X and tty
+.
+.
+.\" --------------------------------------------------------------------
+.SH "SYNOPSIS"
+.\" --------------------------------------------------------------------
+.
+.ad l
+.Synopsis groffer
+.[ShortOpt] Q
+.[ShortOpt] X
+.[ShortOpt] T device
+.[LongOpt] man
+.[LongOpt] manpath man_page_dirs
+.[LongOpt] title title_in_X_mode
+.[LongOpt] xrdb X_resouce_options
+.RI [ groff_options ]
+.RI [ filespec
+.Text \*[Ellipsis]]
+.EndSynopsis
+.
+.Synopsis groffer
+.ShortOpt h
+|
+.LongOpt help
+.EndSynopsis
+.
+.Synopsis groffer
+.ShortOpt v
+|
+.LongOpt version
+.EndSynopsis
+.
+.P
+where each element of the
+.I filespec
+sequence has one of the following forms, where testing is done in the
+specified sequence.
+.
+.TP 10m
+.I filename
+the path name of an existing file.
+.
+.TP
+.ShortOpt
+stands for standard input (can occur several times).
+.
+.TP
+.IB name . section
+the manual page (man-page)
+.I name
+in
+.IR section ,
+see
+.BR man (1).
+.
+.TP
+.BI man: name ( section )
+search the man-page
+.I name
+in
+.IR section ,
+the same as
+.IB name . section
+above
+.
+.TP
+.BI man: name
+search the man-page
+.I name
+in the lowest section.
+.
+.TP
+.BI other_name
+if not an existing file search the man-page
+.I other_name
+in the lowest section.
+.
+.P
+No
+.I filespec
+parameters means standard input.
+.
+.
+.\" --------------------------------------------------------------------
+.SH DESCRIPTION
+.\" --------------------------------------------------------------------
+.
+The
+.I groffer
+program is able to display files written in the
+.IR "roff formatting language" ,
+see
+.BR groff (@MAN7EXT@).
+When it is called within the X window system the graphical
+.BR gxditview (@MAN1EXT@)
+display program is started, otherwise text output is displayed in a
+pager on the terminal.
+.
+.P
+The program always concatenates all input specified by the non-option
+parameters of the calling command line, or standard input if none are
+given.
+.
+Compressed standard input or files are decompressed on-the-fly.
+.
+In the following, this concatenation of all input sources with
+decompression is called
+.I the input
+for the program.
+.
+.P
+Besides processing groff files and standard input, groffer provides a
+search facility for manual pages (man-pages).
+.
+This makes the groffer program a graphical extension of the
+.BR man (1)
+program.
+.
+.P
+Normally, the input is run thru the
+.BR groff (@MAN1EXT@)
+text processor before being displayed.
+.
+By using the option
+.ShortOpt Q ,
+the roff source code is displayed without being processed.
+.
+.P
+The
+.ShortOpt T
+option allows to produce output for all output devices provided by
+groff.
+.
+This is like groff, but additionally with the search and decompression
+facilities.
+.
+.P
+Internally, the program uses the
+.BR grog (@MAN1EXT@)
+program to determine from the source which preprocessors should be run
+and which macro files should be included.
+.
+This can be enhanced manually by the corresponding options that are
+known from
+.BR groff (@MAN1EXT@).
+.
+.
+.\" --------------------------------------------------------------------
+.SH OPTIONS
+.\" --------------------------------------------------------------------
+.
+The following options are caught be groffer and have a special
+meaning.
+.
+.OptDef h help
+print usage message to standard error and exit.
+.
+.OptDef Q source
+output the roff source code of the input files unprocessed.
+.
+.OptDef T device devname
+use
+.I devname
+as the output device, just like in plain groff;
+if this is
+.B X75
+the X output with 75 dpi is selected, with
+.B X100
+X output will have 100 dpi, which is the default anyway; all other
+devices generate output that was processed for the specified device;
+this is printed onto standard output without a pager.
+.
+.OptDef v version
+print version information onto standard error.
+.
+.OptDef X
+display in X window with a resolution of 75 dpi.
+.
+.OptDef "" man
+check the non-option command line arguments (filespecs) first on being
+man-pages, then if they represent an existing file.
+.
+By default, a filespec is first tested if it is an existing file.
+.
+.OptDef "" manpath "'dir1 dir2 \*[Ellipsis]'"
+.br
+.ns
+.OptDef "" manpath "'dir1:dir2:\*[Ellipsis]'"
+use the specified search path for retrieving man-pages instead of the
+program defaults.
+.
+If the argument is set to the empty string "" the search for man-page
+is disabled.
+.
+.OptDef "" title "'some title of your own'"
+set the title for the diplay window.
+.
+This effects only the X mode.
+.
+.OptDef "" xrdb "'\*[@-]\fIopt1 arg1\fP \*[@-]\fIopt2 arg2 ...\fP'"
+pass the argument unchanged to the X display program gxditview of
+groffer.
+.
+All options of
+.BR gxditview (@MAN1EXT@)
+are allowed; this inludes
+.ShortOpt bg
+(background color),
+.ShortOpt display
+(the X display to be used),
+.ShortOpt geometry
+(size and position of the window),
+.ShortOpt fg
+(foreground color),
+.ShortOpt fn
+(font),
+.ShortOpt xrm
+(set general X resource),
+and many more, see
+.BR X (1).
+Note that the arguments for the gxditview options are not allowed to
+have embedded space characters; so it is safer to use the normal
+option
+.LongOpt title
+instead of the
+.ShortOpt -title
+resource option to set the title of the display window..
+.
+.TP
+.LongOpt \" just `--'
+signals the end of option processing; all remaining arguments are
+interpreted as filespec parameters.
+.
+.P
+Besides these, groffer accepts all arguments that are valid for the
+.BR groff (@MAN1EXT@)
+program.
+.
+All non-groffer options are sent unmodified via grog to groff.
+.
+Postprocessors, macro packages, compatibility with classical troff,
+and much more can be manually specified.
+.
+.
+.\" --------------------------------------------------------------------
+.SH FEATURES
+.\" --------------------------------------------------------------------
+.
+This chapter describes the details of the features of the groffer
+program in detail.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Output modes"
+.\" --------------------------------------------------------------------
+.
+The groffer program provides 4 different operation modes,
+.Topic
+graphical display in X,
+.Topic
+text display in a pager,
+.Topic
+output for a given device streamed onto standard output.
+.Topic
+source code streamed onto standard output.
+.
+.P
+Normally, the input is processed by groff and then displayed in a
+viewer, either in X or on a text terminal.
+.
+If the environment variable
+.EnvVar $DISPLAY
+is set or one of the options
+.ShortOpt X ,
+.ShortOpt TX100 ,
+or
+.ShortOpt TX75
+is set the
+.B gxditview
+program will be started on the X terminal that is specified by the
+.EnvVar $DISPLAY
+variable.
+.
+.P
+X provides two resolutions, the old value
+.B 75 dpi
+and the more modern value of
+.BR "100 dpi" ,
+which should be available on almost all modern computers.
+.
+By default, the X resolution of 100 dpi is used if there are
+corresponding fonts available; this is checked by questioning the X
+font path using the shell command
+.ShellCommand xset q
+.
+.P
+The lower resolution can be explicitly specified by the option
+.ShortOpt TX75 ;
+the option
+.ShortOpt X
+is inherited from groff, actually it chooses 75 dpi as well.
+.
+.P
+If the variable
+.EnvVar $DISPLAY
+is not set or empty groffer assumes that it should produce output on a
+text terminal.
+.
+In the actual implementation, the groff output device
+.I latin1
+is chosen and the processed output is piped into a pager program.
+.
+The pager (together with options) can be specified by the environment
+variable
+.EnvVar $PAGER .
+If this is not set or empty the
+.BR less (1)
+program is used as the default pager.
+.
+.P
+Besides the two display modes above, for X and text pager, there are
+two more operating modes.
+.
+These are streaming modes, that means both of them print to standard
+output without using a pager.
+.
+.P
+If a device other than the
+.B X
+devices is specified with the
+.ShortOpt T
+option groffer assumes that the user wants to pipe the output into
+some kind of postprocessor.
+.
+The reason for this is that the output of many devices, such as
+.BR ps ,
+or
+.B dvi
+is not directly displayable.
+.
+.P
+The user may also choose to read the source code of the input by
+specifying the
+.ShortOpt Q
+option.
+.
+Again, no output pager is used to allow piping.
+.
+.
+.\" --------------------------------------------------------------------
+.SS Decompression
+.\" --------------------------------------------------------------------
+.
+The program has a decompression facility.
+.
+If standard input or a file that is specified as a command line
+parameter was compressed by a format that is understood by
+.BR zcat (1)
+it is decompressed on-the-fly.
+.
+This includes the GNU
+.B .gz
+compression format of
+.BR gzip (1)
+and the traditional
+.B .Z
+compression.
+.
+The program displays the concatenation of all decompressed input in
+the sequence that was specified on the command line.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Man-pages"
+.\" --------------------------------------------------------------------
+.
+The groffer program provides a search facility for system manual pages
+(man-pages).
+.
+So it can be used as a replacement or a grapical extension for the
+.BR man (1)
+program.
+.
+.P
+Preformatted man-pages (cat-pages) are intentionally not supported,
+because groffer is a roff program, not a text pager.
+.
+With the excellent performance of the actual computers, the
+preformatted man-pages aren't necessary any longer.
+.
+Due to their inflexible nature, they provoke some trouble with
+changing line lengths.
+.
+These cat-pages should be disabled with the man program, or be
+circumvented by using groffer instead.
+.
+.P
+The groffer program determines if the user wanted to diplay a man-page
+by the following methods.
+.
+If a non-option command line parameter does not represent a valid file
+name groffer suspects whether this could be a system manual page
+(man-page).
+.
+The following parameter formats are recognized to represent a wanted
+man-page.
+.
+.TP
+.IB name . section
+the man-page
+.I name
+in
+.IR section .
+The corresponding command with the man program would be
+.ShellCommand man \f(CIsection name\fP
+.
+.TP
+.BI man: name ( section )
+the quasi-URL notation used in many Desktop systems to
+represent the man-page
+.I name
+in
+.IR section .
+.
+.TP
+.BI man: name
+search the man-page
+.I name
+in the lowest section.
+The corresponding command with the man program would be
+.ShellCommand man \f(CIname\fP
+.
+.TP
+.I name
+if
+.I name
+is not an existing file search for the man-page
+.I name
+in the lowest section just like
+.ShellCommand man \f(CIname\fP
+.
+.P
+The algorithm for retrieving man-pages uses five search methods.
+.
+They are successively tried until a method works.
+.
+.Topic
+The search path can be manually specified by using the option
+.LongOpt manpath .
+An empty argument disables the man-page searching.
+.
+This overwrites the other methods.
+.
+.Topic
+The best results are obtained when the
+.BR man (1)
+program has the command line option
+.ShortOpt w
+to determine the path of a man-page.
+.
+This is available in the GNU version of
+.IR man .
+.
+.Topic
+If this isn't available the environment variable
+.EnvVar $MANPATH
+is searched.
+.
+.Topic
+If this is empty the
+.BR manpath (1)
+program for determining a path of man directories is tried.
+.
+.Topic
+If this does not work a reasonable default path is searched for
+man-pages.
+.
+.P
+In all cases, language-specific man-pages are searched first if the
+environment variable
+.EnvVar $LANG
+is set.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Source Code"
+.\" --------------------------------------------------------------------
+.
+Usually, groffer displays the input in formatted form.
+.
+When, however, the option
+.ShortOpt Q
+is specified on the command line the source code of the input is
+displayed instead; more exactly, it is printed onto standard output
+as is, without any pager or other formatter.
+.
+.P
+In this source code displaying mode, the decompression and man-page
+search features are still active.
+.
+As no formatter or X window program is run in this mode all opotions
+different from
+.ShortOpt Q
+are silently ignored.
+.
+.\" --------------------------------------------------------------------
+.SH "ENVIRONMENT"
+.\" --------------------------------------------------------------------
+.
+.TP
+.EnvVar $DISPLAY
+If this variable is set this indicates that the X window system is
+running.
+.
+Testing this variable decides on whether graphical or text output is
+generated.
+.
+This variable should not be changed by the user carelessly, but it can
+be used to start the graphical groffer on a remote X terminal.
+.
+For example, depending on your system, groffer can be started on the
+second monitor by the command
+.ShellCommand DISPLAY=:0.1 groffer what.ever &
+.
+.TP
+.EnvVar $PAGER
+This variable can be used to set the pager for the tty output.
+.
+For example, to disable the use of a pager completely set this
+variable to the
+.BR cat (1)
+program
+.ShellCommand PAGER=cat groffer anything
+.
+.TP
+.EnvVar $MANPATH
+if set, this variable contains the directories in which the man-page
+trees are stored.
+.
+.TP
+.EnvVar $LANG
+
+if set, this variable contains the directories in which the man-page
+trees are stored.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COMPATIBILITY"
+.\" --------------------------------------------------------------------
+.
+The
+.B groffer
+shell script should be compatible to both POSIX and GNU.
+.
+.P
+This document describes the behavior on GNU systems.
+.
+Due to the limitations of POSIX as compared to GNU, not all features
+of groffer are available on non-GNU systems.
+.
+This includes long options, arguments with embedded space characters,
+and the search capabilities of man-pages.
+.
+.P
+The groffer program can handle option arguments and file names that
+contain space characters, but mutliple space characters are flattened
+to a single space character.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "SEE ALSO"
+.\" --------------------------------------------------------------------
+.
+.TP
+.BR groff (@MAN1EXT@)
+the GNU roff program.
+.
+.TP
+.BR grog (@MAN1EXT@)
+tries to guess the groff command line options for given input files.
+.
+.TP
+.BR gxditview (@MAN1EXT@)
+the GNU version of the roff viewer
+.BR xditview (@MAN1EXT@)
+of the X window system.
+.
+.TP
+.BR gzip (1)
+.TP+
+.BR gunzip (1)
+.TP+
+.BR zcat (1)
+.
+.TP
+.BR man (1)
+the standard way to diplay man-pages.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "AUTHORS"
+.\" --------------------------------------------------------------------
+.
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+.
+.P
+This document is distributed under the terms of the FDL (GNU Free
+Documentation License) version 1.1 or later.
+.
+You should have received a copy of the FDL on your system, it is also
+available on-line at the
+.URL "GNU copyleft site" http://www.gnu.org/copyleft/fdl.html .
+.
+.P
+This document is part of
+.IR groff ,
+the GNU roff distribution.
+.
+It was written by
+.MAILTO bwarken@mayn.de "Bernd Warken" .
+.
+.
+\" --------------------------------------------------------------------
+.\" Emacs settings
+.\" --------------------------------------------------------------------
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/contrib/groffer/groffer.sh b/contrib/groffer/groffer.sh
new file mode 100644
index 00000000..a889d9c4
--- /dev/null
+++ b/contrib/groffer/groffer.sh
@@ -0,0 +1,1417 @@
+#!/bin/sh
+
+PROGRAM_NAME=groffer
+PROGRAM_VERSION="0.3 (alpha)"
+LAST_UPDATE="15 Dec 2001"
+
+# Copyright (C) 2001 Free Software Foundation, Inc.
+# Written by Bernd Warken <bwarken@mayn.de>
+
+# This file is part of groff.
+
+# groff is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# groff is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with groff; see the file COPYING. If not, write to the Free
+# Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+########################################################################
+# Description
+########################################################################
+
+# Display groff files on X or tty, even when zipped.
+
+# This script tries to avoid features of special shells, so some
+# elements are programmed in a more complicated way than necessary.
+
+########################################################################
+# Debugging
+########################################################################
+# Error handling and exit behavior is complicated by the fact that
+# `exit' can only escape from the current shell. This leads to trouble
+# in `$()' subshells.
+#
+
+
+# for debugging only
+#set -x
+#set -v
+function diag ()
+{
+ echo '>>>>>' "$@" >&2;
+}
+function abort ()
+{
+ [ $# -gt 0 ] && diag "$@";
+ error 2>/dev/null || exit 1;
+}
+
+########################################################################
+# Setup
+########################################################################
+
+set -a
+
+########################################################################
+# Environment Variables
+########################################################################
+
+# Environment variables that are regarded as global to this file are
+# written in upper case letters and can use the underline character
+# inside, e.g. $GLOBAL_VARIABLE; local variables start with an
+# underline and use only lower case letters and underlines, e.g.
+# $_local_variable .
+
+# [A-Z]* system variables, e.g. $MANPATH
+# [A-Z][A_Z_]* global file variables, e.g. $MAN_PATH
+# _[a-z_]* local variables, e.g. $_manpath
+# _[a-z_] local loop variables, e.g. $_i
+
+# global variables
+FILE_ARGS="" # the non-option command line parameters
+HAS_COMPRESSION="" # `yes' if compression is available
+HAS_MANW="" # `yes' if `man -w' is available
+HAS_MKTEMP="" # `yes' if `mktemp' program is available
+HAS_OPTS_GNU="" # `yes' if GNU `getopt' is available
+HAS_OPTS_POSIX="" # `yes' if POSIX `getopts' is available
+MAN_PATH="" # search path for man-pages
+OTHER_OPTIONS="" # given non-native command line options
+OPT_SOURCE="" # source code option (`Quellcode')
+OPT_DEVICE="" # device option
+OPT_DPI="" # groff -X option
+OPT_MAN="" # interpret file params as man-pages
+OPT_MANPATH="" # manual setting of path for man-pages
+OPT_TITLE="" # title for gxditview window
+OPT_XRDB="" # X resource arguments to gxditview
+TEMP_DIR="" # directory for temporary files
+TMP_CAT="" # stores concatenation of everything
+TMP_INPUT="" # stores stdin, if any
+TMP_DONE="" # stores the names of processed args
+
+# command line arguments
+GROFFER_LONGOPTS="device: help man manpath: source title: version \
+ xrdb:";
+GROFFER_SHORTOPTS="hQT:vX";
+GROFF_ARG_SHORTS="d:f:F:I:L:m:M:n:o:P:r:w:W:"; # inhereted from groff
+GROFF_SHORTOPTS="abcegilpstzCEGNRSUVZ"; # inhereted from groff
+ALL_SHORTOPTS=\
+"${GROFFER_SHORTOPTS}${GROFF_SHORTOPTS}${GROFF_ARG_SHORTS}";
+ALL_LONGOPTS="${GROFFER_LONGOPTS}";
+
+PROCESS_ID="$$" # for shutting down the program
+
+ENABLE_MANPAGES=yes # enable search for man-pages
+
+########################################################################
+# System Test
+########################################################################
+
+# Test the availability of the system utilities used in this script.
+
+########################################################################
+# Test of function "test".
+#
+[ "a" = "a" ] || exit 1;
+
+########################################################################
+# Test of function "echo".
+#
+if [ "$(echo -n 'te' && echo -n && echo 'st')" != "test" ]; then
+ echo 'Test of "echo" command failed.' >&2;
+ exit 1;
+fi;
+
+########################################################################
+# Test of function "sed".
+#
+if [ "$(echo teeest | sed -e '\|^teeest$|s|\(e\)\+|\1|')" != "test" ];
+then
+ echo 'Test of "sed" command failed.' >&2;
+ exit 1;
+fi;
+
+########################################################################
+# Test of function "grep".
+#
+if [ "$( (echo no; echo test) | grep -e '^.e..$')" != "test" ]; then
+ echo 'Test of "grep" command failed.' >&2;
+ exit 1;
+fi;
+
+########################################################################
+# Test of function "cat".
+#
+if [ "$(echo test | cat)" != "test" ]; then
+ echo 'Test of "cat" command failed.' >&2;
+ exit 1;
+fi;
+
+########################################################################
+# Test for compression.
+#
+if [ "$(echo test | zcat -f -)" = "test" ]; then
+ HAS_COMPRESSION="yes";
+else
+ HAS_COMPRESSION="no";
+fi;
+
+########################################################################
+# Test for temporary directory and file generating utility
+#
+
+# determine temporary directory into `$TEMP_DIR'
+for _i in "$GROFF_TMPDIR $TMPDIR" "$TMP" "$TEMP" "$TEMPDIR" \
+ "$HOME"/tmp /tmp "$HOME" .;
+do
+ if [ "$_i" != "" ]; then
+ if [ -d "$_i" -a -r "$_i" -a -w "$_i" ]; then
+ TEMP_DIR="$_i";
+ break;
+ fi;
+ fi;
+done
+unset _i
+if [ "$TEMP_DIR" = "" ]; then
+ echo "Couldn't find a directory for storing temorary files." >&2;
+ exit 1;
+fi;
+
+# test whether function `mktemp' is available
+_tmp="$(mktemp "${TEMP_DIR}/.${PROGRAM_NAME}".XXXXXX)" 2>/dev/null;
+if [ "$_tmp" != "" ]; then
+ HAS_MKTEMP="yes";
+ rm -f "$_tmp";
+else
+ HAS_MKTEMP="no";
+fi;
+unset _tmp;
+
+########################################################################
+# Test option parsing programs.
+#
+
+# GNU getopt
+if _res="$(getopt -l GNU: ab: --GNU getopt test 2>/dev/null |
+ sed -e '\|^ *\(.*\) *$|s||\1|')"; then
+ if [ "$_res" = "--GNU 'getopt' -- 'test'" ]; then
+ HAS_OPTS_GNU="yes";
+ fi;
+fi;
+
+# POSIX getopts
+OPTIND=1;
+OPTARG="";
+getopts "t:" _opt -test 2>/dev/null;
+if [ "$?" -eq 0 -a "$_opt" = "t" -a \
+ "$OPTARG" = "est" -a "$OPTIND" -eq 2 ]; then
+ HAS_OPTS_POSIX="yes";
+fi;
+
+if [ "$HAS_OPTS_GNU" = "" -a "$HAS_OPTS_POSIX" = "" ]; then
+ error "No argument parser program available (`getopt' or `getopts').";
+fi;
+
+unset _opt;
+unset _res;
+OPTIND=1;
+OPTARG="";
+
+########################################################################
+# Determine search method for man-pages
+#
+unset HAS_MANW # `yes' if `man -w' is available
+if _files="$(man -w man 2>/dev/null)"; then
+ if [ "$_files" = "" ]; then
+ HAS_MANW="no";
+ else
+ for _i in $_files; do
+ if [ -f "$_i" ]; then
+ HAS_MANW="yes";
+ break;
+ fi;
+ done;
+ fi;
+ if [ "$HAS_MANW" != "yes" ]; then
+ HAS_MANW="no";
+ fi;
+fi;
+if [ "$HAS_MANW" != "yes" ]; then
+ if [ "$MANPATH" = "" ]; then
+ _dirs="$(manpath 2>/dev/null | tr : ' ')";
+ if [ "$?" != 0 -o "$_dirs" = "" ]; then
+ MANPATH="$_dirs";
+ fi
+ fi
+ if [ "$MANPATH" = "" ]; then # set some default path
+ _manpath="/usr/local/share/man /usr/local/man \
+ /usr/share/man /usr/man \
+ /usr/X11R6/man /usr/openwin/man \
+ /opt/man /opt/gnome/man /opt/kde/man";
+ else
+ _manpath="$(echo -n $MANPATH | tr : ' ')";
+ fi;
+ _dirs="";
+ for _p in $_manpath; do
+ if [ -d "$_p" -a -r "$_p" -a -x "$_p" ]; then
+ if [ "$_dirs" = "" ]; then
+ _dirs="$_p";
+ else
+ _dirs="$_dirs $_p";
+ fi;
+ fi;
+ done;
+ _manpath="$_dirs";
+ if [ "$LANG" = "" ]; then
+ MAN_PATH="$_manpath";
+ else # language-specific directories
+ MAN_PATH="";
+ # two-letter version of $LANG
+ _lang_short="$(echo $LANG | sed -e '\|^\(..\).*$|s||\1|')";
+ for _p in $_manpath; do
+ _dirs="${_p}/${_lang_short}*"; # all dirs for 2-letter lang code
+ if [ "$_dirs" != "" ]; then
+ if [ -d "${_p}/${LANG}" ]; then
+ _dirs="$_dirs ${_p}/${LANG}";
+ fi;
+ fi;
+ if [ "$MAN_PATH" = "" ]; then
+ MAN_PATH="$_dirs $_p";
+ else
+ MAN_PATH="$MAN_PATH $_dirs $_p";
+ fi;
+ done;
+ fi;
+fi;
+unset _files;
+unset _dirs;
+unset _i;
+unset _p;
+unset _manpath;
+
+########################################################################
+# Shell Funtions
+########################################################################
+
+# Survey of functions defined here
+
+# The elements specified within paranthesis `(<>)' give hints to what
+# the arguments are meant to be; the argument names are irrelevant.
+# <>? 0 or 1
+# <>* arbitrarily many incl. none
+# <> exactly 1
+
+# append_args (<arg>*)
+# base_name (path)
+# catz (<file>*)
+# check_dpi ()
+# clean_up ()
+# count_next_quoted (<arg>*)
+# del_all_leading_from (<regexp> <string>)
+# del_ext_from (<extension> <filename>)
+# echo2 (<text>*)
+# error (<err_no> <text>*)
+# get_manpath ()
+# get_next_quoted (<arg>*)
+# get_title ()
+# is_substring_of (<part> <string>)
+# leave ()
+# manpage_from_path (<name> <section>?)
+# manpage_search_filespec (<filespec>)
+# manpage_search_name (<name> <section>?)
+# normalize_args (<arg>*)
+# output (<text>*)
+# register_done_file (<filespec>*)
+# save_stdin_if_any ()
+# shift_quoted (<arg>*)
+# supercat (<filearg>*)
+# tmp_cat ()
+# tmp_create ()
+# unquote (<arg>*)
+# usage ()
+# version ()
+
+########################################################################
+# append_args (<arg>*)
+#
+# Append args to `string' separated by a space, omitting empty args.
+#
+# Arguments : >=2
+# Output : the generated string
+#
+append_args()
+{
+ local _res;
+ while [ "$1" = "" ]; do
+ if [ "$#" -eq 0 ]; then
+ return;
+ fi;
+ shift;
+ done;
+ _res="$1";
+ shift;
+ while [ "$#" -ge 1 ]; do
+ if [ "$1" != "" ]; then
+ _res="$_res $1";
+ fi;
+ shift;
+ done;
+ output "$_res";
+}
+
+########################################################################
+# base_name (path)
+#
+# Delete the directory part of `path', i.e. everything up to last `/'
+# at the beginning of `path'.
+#
+# Arguments : 1
+# Output : the corrected string
+#
+base_name()
+{
+ if [ "$#" != 1 ]; then
+ error 1 "Function base_name needs 1 argument.";
+ fi
+ output "$1" | sed -e '\|^\(.*/\)\+|s|||';
+}
+
+########################################################################
+# catz (<file>*)
+#
+# If compression is available decompress standard input and write it to
+# standard output; otherwise copy standard input to standard output.
+#
+catz()
+{
+ if [ "$HAS_COMPRESSION" = "yes" ]; then
+ if [ "$#" = 0 ]; then
+ set -- -;
+ fi;
+ zcat -f "$@";
+ else
+ cat "$@";
+ fi;
+}
+
+########################################################################
+# check_dpi ()
+#
+# Sanity check for having default X resolution 100 dpi (very defensive)
+#
+# Output : generated title
+#
+check_dpi()
+{
+ local _res=100;
+ local _fp;
+ if _fp="$(xset q | grep '/font' 2>/dev/null)"; then
+ case "$_fp" in
+ *100*) : ; ;;
+ *75*) _res=75; ;; # no 100 found in X font path, but 75
+ esac;
+ fi;
+ output "$_res";
+}
+
+########################################################################
+# clean_up () :
+#
+# Clean exit without an error.
+#
+clean_up()
+{
+ rm -f "$TMP_CAT" "$TMP_INPUT" "$TMP_DONE";
+}
+
+########################################################################
+# count_next_quoted (<arg>*)
+#
+# Expects single-quoted arguments, returns the first quoted argument.
+#
+# Arguments : single-quoted, evt. with included spaces.
+# Output : number of arguments within the single-quote.
+# Return : `1' if arguments are not single-quoted, `0' otherwise.
+#
+count_next_quoted()
+{
+ local _args;
+ local _number;
+ local _quoted_block="";
+ if [ "$#" -eq 0 ]; then
+ return 1;
+ fi;
+ if output $1 | grep -e "^'" >/dev/null 2>&1; then
+ # starts with a single quote
+ while ! (output $1 | grep -e \'\$ >/dev/null 2>&1); do
+ # doesn't end with a single quote
+ _quoted_block="$(append_args $_quoted_block $1)";
+ shift;
+ if [ "$#" = 0 ]; then
+ error "count_next_quoted : no closing quote found"
+ return 1;
+ fi;
+ done;
+ # actual $1 has closing quote
+ _quoted_block="$(append_args $_quoted_block $1)";
+ set -- $_quoted_block;
+ _number="$#";
+ else
+ _number=1;
+ fi;
+ output $_number;
+}
+
+########################################################################
+# del_all_leading_from (<regexp> <string>)
+#
+# Delete every occurence of `regexp' at the beginning of `string'.
+#
+# Arguments : 2
+# Output : the corrected string
+#
+del_all_leading_from()
+{
+ if [ "$#" != 2 ]; then
+ error 1 'Function "del_all_leading_from" needs 2 args.';
+ fi
+ output "$2" | sed -e '\|^\('"$1"'\)\+|s|||';
+}
+
+########################################################################
+# del_ext_from (<extension> <filename>)
+#
+# Delete `extension' from the end of `filename'.
+#
+# Arguments : 2
+# Output : the corrected string
+#
+del_ext_from()
+{
+ if [ "$#" != 2 ]; then
+ error 1 'Function "del_ext_from" needs 2 args.';
+ fi
+ output "$2" | sed -e "\|^ *\('\?.*\)$1\('\?\) *"'$|s||\1\2|';
+}
+
+########################################################################
+# echo2 (<text>*)
+#
+# Output to stderr.
+#
+# Arguments : arbitrary text.
+#
+echo2()
+{
+ echo "$*" >&2;
+}
+
+########################################################################
+# error (<err_no> <text>*)
+#
+# Output argurments to stderr and abort.
+#
+# Arguments : arbitrary text
+#
+error()
+{
+ local _errno;
+ case "$#" in
+ 0) set -- 'unknown error'; ;;
+ esac;
+ echo2 "groffer error : $*";
+ clean_up;
+ kill "$PROCESS_ID" >/dev/null 2>&1;
+ kill -9 "$PROCESS_ID" >/dev/null 2>&1;
+ exit 1;
+}
+
+########################################################################
+# get_manpath ()
+#
+# Determine search path for man-pages (only needed when no `man -w').
+#
+# Return : `0' if a valid path was retrieved.
+# Output : path as space-separated list (intended for $MAN_PATH).
+# Globals : system : $MANPATH $LANG
+# file : $OPT_MANPATH $MAN_PATH
+#
+get_manpath()
+{
+ local _files;
+ local _dirs;
+ local _i;
+ local _d;
+ local _p;
+ local _all;
+ local _manpath;
+ if [ "$OPT_MANPATH" != "" ]; then # --manpath was set
+ MANPATH="$OPT_MANPATH";
+ fi;
+ if [ "$MANPATH" = "" ]; then # try `manpath' program
+ _dirs="$(manpath 2>/dev/null)";
+ if [ "$?" = 0 -a "$_dirs" != "" ]; then
+ MANPATH="$_dirs";
+ fi
+ fi
+ if [ "$MANPATH" = "" ]; then # set some default path
+ _manpath="/usr/local/share/man /usr/local/man \
+ /usr/share/man /usr/man \
+ /usr/X11R6/man /usr/openwin/man \
+ /opt/man /opt/gnome/man /opt/kde/man";
+ else
+ _manpath="$(echo -n $MANPATH | tr : ' ')";
+ fi;
+ if [ "$_manpath" = "" ]; then
+ return 1;
+ fi;
+ _dirs="";
+ for _p in $_manpath; do # remove non-existing directories
+ if [ -d "$_p" -a -r "$_p" -a -x "$_p" ]; then
+ _dirs="$(append_args $_dirs $_p)";
+ fi;
+ done;
+ _manpath="$_dirs";
+ if [ "$_manpath" = "" ]; then
+ return 1;
+ fi;
+ if [ "$LANG" = "" ]; then
+ MAN_PATH="$_manpath";
+ else # language-specific directories
+ MAN_PATH="";
+ # two-letter version of $LANG
+ _short_code="$(echo $LANG | sed -e '\|^\(..\).*$|s||\1|')";
+ for _p in $_manpath; do
+ _langdir="${_p}/${LANG}";
+ _all="$(ls -d "${_p}/${_short_code}"* 2>/dev/null)";
+ # all dirs with this 2-letter lang code
+ _langs="";
+ if [ "$_all" != "" ]; then
+ for _d in $_all; do
+ if [ "$_d" != "$_langdir" -a -d "$_d" ]; then
+ _langs="$(append_args "$_langs" "$_d")";
+ fi;
+ done;
+ if [ -d "$_langdir" ]; then
+ _langs="$(append_args "$_langdir" $_langs)";
+ fi;
+ fi;
+ MAN_PATH="$(append_args "$_langs" $_p)";
+ done;
+ fi;
+ if [ "$MAN_PATH" = "" ]; then
+ return 1;
+ fi;
+ output "$MAN_PATH";
+}
+
+
+########################################################################
+# get_next_quoted (<arg>*)
+#
+# Expects single-quoted arguments, returns the first quoted argument.
+#
+# Arguments : single-quoted, evt. with included spaces.
+# Output : everything up to the next arg terminated by a quote;
+# the enclosing quotes are removed.
+# Return : `1' if arguments are not single-quoted, `0' otherwise.
+#
+get_next_quoted()
+{
+ local _args="$*";
+ local _number="$(count_next_quoted $_args)";
+ shift $_number;
+ output $_args | sed -e '\|^\(.*\)'"$*"'$|s||\1|' |
+ sed -e "\|^ *'\(.*\)' *"'$|s||\1|';
+}
+
+########################################################################
+# get_title ()
+#
+# create title for X from the $TMP_DONE file
+#
+# Globals : $TMP_DONE $OPT_XRDB $OPT_TITLE
+# Output : generated title
+#
+get_title()
+{
+ if [ "$OPT_TITLE" != "" ]; then
+ # title was set by option --title
+ output "$OPT_TITLE";
+ return 0;
+ fi;
+ if is_substring_of "-title" "$OPT_XRDB"; then
+ # $OPT_XRDB is handled anyway, so no extra output from here
+ return 0;
+ fi;
+ # no title was supplied on the command line, take the default title
+ # constisting of the processed filespecs, stored in file $TMP_DONE.
+ cat "$TMP_DONE";
+}
+
+########################################################################
+# is_substring_of (<part> <string>)
+#
+# Test whether `part' is contained in `string'.
+#
+# Arguments : 2 text arguments.
+# Return : `0' if arg1 is substring of arg2, `1' otherwise.
+#
+is_substring_of()
+{
+ if [ "$#" != 2 ]; then
+ false;
+ error "is_substring_of needs 2 arguments.";
+ fi;
+ if output "$2" | grep -e "$1" >/dev/null 2>&1; then
+ return 0;
+ else
+ return 1;
+ fi;
+}
+
+########################################################################
+# leave ()
+#
+# Clean exit without an error.
+#
+leave()
+{
+ clean_up;
+ exit 0;
+}
+
+########################################################################
+# manpage_from_path (<name> <section>?)
+#
+# Get position of man-page using the $MAN_PATH variable.
+#
+# Globals : $MAN_PATH must be preset as space-separated list of dirs.
+# $LANG system language preset.
+# Arguments : either 2 (`name' `section') or 1 (`name').
+# Output : the file position for the man-page
+# Return : `0'
+#
+manpage_from_path()
+{
+ local _i;
+ local _p;
+ local _dirs;
+ local _args;
+ local _name="$1";
+ local _section="$2";
+ case "$#" in
+ 1) _args="$1"; ;;
+ 2) _args="$2 $1"; ;;
+ *)
+ false;
+ error 1 "man_from_path : needs 1 or 2 arguments.";
+ ;;
+ esac;
+ if [ "$HAS_MANW" = "yes" ]; then
+ error manpage_from_path : "man -w" is available.
+ fi;
+ if [ "$MAN_PATH" = "" ]; then
+ return 0;
+ fi;
+ for _p in $MAN_PATH; do
+ set -- "$(ls -d "${_p}/man${_section}"*"/${_name}.${_section}"* \
+ 2>/dev/null)";
+ while [ "$#" -gt 0 ]; do
+ if [ -f "$1" -a -r "$1" ]; then
+ output "$1";
+ return 0;
+ fi;
+ shift;
+ done;
+ done;
+ return 1;
+}
+
+########################################################################
+# manpage_search_filespec (<filespec>)
+#
+# check argument with `man -w'
+#
+# Arguments : exactly 1 argument of the form `name.section',
+# `man:name', or `man:name(section)'.
+# Several args indicate an embedded space character.
+#
+# Output : filename of man page, if any.
+# Return : `0' if man page was found, `1' else.
+#
+manpage_search_filespec()
+{
+ local _file="";
+ local _arg;
+ local _name;
+ local _section;
+ if [ "$#" -ne 1 ]; then
+ return 1;
+ fi;
+ _arg="$1";
+# _arg="$(output "$1" | sed -e "\|'\(.*\)'|s||\1|")";
+ case "$_arg" in
+ */*) # contains directory part, not handled
+ return 1;
+ ;;
+ man:?*\(?*\)) # `man:' URL with section
+ _name="$(output "$_arg" |
+ sed -e '\|^man:\([^(]\+\)(\(.*\))$|s||\1|')";
+ _section="$(output $_arg |
+ sed -e '\|^man:\([^(]\+\)(\(.*\))$|s||\2|')";
+ if _file="$(manpage_search_name "$_name" "$_section")" &&
+ [ "$_file" != "" ]; then
+ output "$_file";
+ return 0;
+ fi;
+ return 1;
+ ;;
+ man:?*) # `man:' URL without section
+ _name="$(output "$_arg" | sed -e '\|^man:|s|||')";
+ if _file="$(manpage_search_name "$_name")"; then
+ output "$_file";
+ return 0;
+ else
+ return 1;
+ fi;
+ ;;
+ ?*.?*) # name.section
+ _name="$(output "$_arg" |
+ sed -e '\|^\([^.]\+\)\.\([^.]\+\)$|s||\1|')";
+ _section="$(output "$_arg" |
+ sed -e '\|^\([^.]\+\)\.\([^.]\+\)$|s||\2|')";
+ _file="$(manpage_search_name "$_name" "$_section")";
+ if [ "$?" -eq 0 -a "$_file" != "" ]; then
+ output "$_file";
+ return 0;
+ fi;
+ _file="$(manpage_search_name "$_arg")"
+ if [ "$?" -eq 0 -a "$_file" != "" ]; then
+ output "$_file";
+ return 0;
+ fi;
+ return 1;
+ ;;
+ ?*)
+ _file="$(manpage_search_name "$_arg")";
+ if [ "$?" -eq 0 -a "$_file" != "" ]; then
+ output "$_file";
+ return 0;
+ fi;
+ return 1;
+ ;;
+ esac;
+ return 1;
+}
+
+########################################################################
+# manpage_search_name (<name> <section>?)
+#
+# Get position of man-page `name(section)', or just `name' in the
+# lowest section using `man -w'.
+#
+# Arguments : either 2 (`name' `section') or 1 (`name').
+# Output : the file position for the man-page
+#
+manpage_search_name()
+{
+ local _i;
+ local _name;
+ local _section;
+ case "$#" in
+ 1)
+ _name="$1";
+ _section="";
+ ;;
+ 2)
+ _name="$1";
+ _section="$2";
+ ;;
+ *)
+ error "man_search_name : needs 1 or 2 arguments.";
+ ;;
+ esac;
+ if [ "$HAS_MANW" = "yes" ]; then
+ for _i in $(man -w $_section "$_name" 2>/dev/null); do
+ if [ -f "$_i" -a -r "$_i" ] &&
+ (catz "$_i" | grog | grep -e '-man') >/dev/null 2>&1;
+ then
+ output "$_i";
+ return 0;
+ fi
+ done;
+ else
+ manpage_from_path $_section "$_name";
+ return 0;
+ fi;
+ return 1;
+}
+
+########################################################################
+# normalize_args (<arg>+)
+#
+# Display arguments in the normalized form of GNU `getopt'.
+#
+# Arguments : if no arguments are given, $* is parsed instead
+# Globals : $ALL_LONGOPTS $ALL_SHORTOPTS
+# Output : arguments in normalized form
+#
+normalize_args()
+{
+ local _args;
+ local _long_opts="";
+ local _i;
+ local _res;
+ local _opt;
+ if [ "$#" -eq 0 ]; then
+ set -- -;
+ fi;
+ if [ "$HAS_OPTS_GNU" = "yes" ]; then
+ _long_opts="";
+ for _i in ${ALL_LONGOPTS}; do
+ _long_opts="$(append_args $_long_opts -l "$_i")";
+ done;
+ if _res="$(getopt -l "$_long_opts" "$ALL_SHORTOPTS" "$@")"; then
+ output "$_res";
+ return 0;
+ else
+ error 'wrong option';
+ fi;
+ elif [ "$HAS_OPTS_POSIX" = "yes" ]; then # POSIX getopts
+ case "--[^ ]" in
+ "$_args") error "long options are only available in GNU."; ;;
+ esac;
+ OPTIND=1;
+ OPTARG="";
+ _res="";
+ while getopts ":$ALL_SHORTOPTS" _opt $_args; do
+ if [ "$_opt" = ":" ]; then
+ if [ "$OPTARG" = "-" ]; then
+ error "your system does not allow GNU long options.";
+ else
+ error "unknown option.";
+ fi;
+ fi;
+ _res="$(append_args $_res -"$_opt")";
+ if [ "$OPTARG" != "" ]; then
+ _res="$(append_args $_res "'$OPTARG'")";
+ # option args are quoted;
+ OPTARG="";
+ fi;
+ done;
+ if [ "$_opt" == '?' ]; then # end of options
+ # non-option parameters are quoted in the output
+ _param="";
+ set -- $_args;
+ if [ "$OPTIND" -le "$#" ]; then
+ _res="$(append_args $_res "--")";
+ eval _param=${"$OPTIND"};
+ if [ "$_param" != "--" ]; then
+ _res="$(append_args $_res "'$_param'")";
+ fi;
+ shift "$OPTIND";
+ while [ "$#" -gt 0 ]; do
+ _res="$(append_args $_res "'$1'")";
+ done;
+ fi;
+ output $_res;
+ return 0;
+ else
+ error 'error in option parsing';
+ fi;
+ fi;
+}
+
+########################################################################
+# output (<text>*)
+#
+# Print arguments to standard output, if there are any.
+# Handle `echo' programs that can have only 1 arg.
+#
+# Arguments : any.
+# Output : the list of the arguments without a line break.
+#
+output()
+{
+ if [ "$#" -ge 1 ]; then
+ echo -n "$*";
+ fi;
+}
+
+########################################################################
+# register_done_file (<filespec>)
+#
+# Transform argument into a title element and append to $TMP_DONE file.
+#
+register_done_file() {
+ set -- $(base_name "$*"); # remove directory part
+ set -- $(del_ext_from .gz "$*"); # remove .hz
+ set -- $(del_ext_from .Z "$*"); # remove .Z
+ case "$#" in
+ 0) return; ;;
+ 1) _res="$1"; ;;
+ *) _res="'$*'"; ;;
+ esac;
+ output " $_res" >> "$TMP_DONE";
+}
+
+########################################################################
+# save_stdin_if_any ()
+#
+# Check if stdin is needed; if so, store to temporary file.
+# Globals : $FILE_ARGS
+#
+save_stdin_if_any()
+{
+ local _a
+ set -- $FILE_ARGS
+ for _a in "$@"; do
+ if [ "$_a" = "'-'" ]; then
+ cat | catz - >"$TMP_INPUT"; # using `cat' first is safer
+ break;
+ fi;
+ done;
+}
+
+########################################################################
+# shift_quoted (<arg>*)
+#
+# Expects single-quoted arguments, strips the first quoted argument.
+#
+# Arguments : single-quoted, evt. with included spaces.
+# Output : delete everything up to the next arg terminated by a
+# quote and the following space, output the rest.
+# Return : `1' if arguments are not single-quoted, `0' otherwise.
+#
+shift_quoted()
+{
+ local _args="$*";
+ shift "$(count_next_quoted $_args)";
+ output $*;
+}
+
+########################################################################
+# supercat (<filearg>*)
+#
+# Output the concatenation of files, man-pages, or standard input to
+# standard output. All parts that are stored in the gzip or Z
+# compression format are decompressed. No other modifications.
+# All processed arguments are added to the global variable
+# $ARGS_DONE.
+#
+# Arguments :
+# All arguments are expected to be surrounded by single quotes.
+# - names of existing files.
+# - '-' to represent standard input (several times allowed).
+# - 'man:name.(section)' the man-page for `name' in `section'.
+# - 'man:name' the man-page for `name' in the lowest `section'.
+# - 'name.section' the man-page for `name' in `section'.
+# - 'name' the man-page for `name' in the lowest `section'.
+# Globals :
+# $TMP_INPUT : (read-only)
+# $ARGS_DONE : (read-write) arguments with a corresponding file
+# are added to variable ARGS_DONE.
+# Output : the decompressed files corresponding to the arguments
+# Return : 0 always, all errors are tolerated or fatal.
+#
+supercat()
+{
+ local _file;
+ local _filespec;
+ local _args;
+ local _mode;
+ local _sequence;
+ if [ "$#" -eq 0 ]; then
+ error 1 "supercat needs at least 1 arg";
+ fi;
+ # remove enclosing quotes and space characters
+ _args="$(output $* | grep -e "^ *'.\+'"'$' |
+ sed -e '\|^ *\(.*\) *$|s||\1|')";
+ if [ "$_args" = "" ]; then
+ error 1 "supercat : arguments are not quoted.";
+ fi;
+ while [ "$_args" != "" ]; do
+ _filespec="$(get_next_quoted $_args)";
+ _args="$(shift_quoted $_args)";
+ if [ "$_filespec" = "" ]; then
+ continue;
+ fi;
+ if [ "$_filespec" = "-" ]; then
+ catz "$TMP_INPUT";
+ register_done_file "-";
+ continue;
+ fi
+ if [ "$ENABLE_MANPAGES" = "yes" ]; then
+ if [ "$OPT_MAN" = "yes" ]; then
+ _sequence="Manpage File";
+ else
+ _sequence="File Manpage";
+ fi;
+ else
+ _sequence="File";
+ fi;
+ _done="no";
+ for _mode in $_sequence; do
+ case "$_mode" in
+ File)
+ if [ -f "$_filespec" -a -r "$_filespec" ]; then
+ catz "$_filespec";
+ register_done_file "$_filespec";
+ _done="yes";
+ break;
+ fi;
+ ;;
+ Manpage)
+ _manfile="$(manpage_search_filespec "$_filespec")";
+ if [ "$?" -eq 0 ]; then
+ catz "$_manfile";
+ register_done_file "$_manfile";
+ _done="yes";
+ break;
+ fi;
+ ;;
+ esac;
+ done;
+ if [ "$_done" != "yes" ]; then
+ echo2 \"$_filespec\" is neither a file nor a man-page.;
+ fi;
+ done;
+}
+
+########################################################################
+# tmp_cat ()
+#
+# output the temporary cat file (the concatenation of all input)
+#
+tmp_cat()
+{
+ cat "$TMP_CAT";
+}
+
+########################################################################
+# tmp_create ()
+#
+# create temporary file
+#
+# Output : file generated title
+#
+tmp_create()
+{
+ local _i;
+ local _tmp="";
+ local _prefix="${TEMP_DIR}/.${PROGRAM_NAME}.";
+ if [ "$TEMP_DIR" = "" ]; then
+ error 1 "Temporary directory must be determined first.";
+ fi;
+ if [ "$HAS_MKTEMP" = "yes" ]; then
+ # unquoted is ok, because mktemp output has no space chars
+ _tmp="$(mktemp "${_prefix}.XXXXXX" 2>/dev/null)"; # automatic
+ if [ "$_tmp" = "" ]; then
+ HAS_MKTEMP="no"; # try manually
+ else
+ if [ ! -e "$_tmp" ]; then
+ echo -n >"$_tmp";
+ fi;
+ output "$_tmp";
+ return 0;
+ fi;
+ fi;
+ if [ "$HAS_MKTEMP" != "yes" ]; then
+ _tmp=""; # manual determination
+ for _i in a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z; do
+ _tmp="${_prefix}$$${_i}";
+ if [ -e "$_tmp" ]; then
+ _tmp="";
+ continue;
+ else
+ break;
+ fi;
+ done;
+ fi;
+ if [ "$_tmp" = "" ]; then
+ error 1 "Could not manually create temporary file.";
+ fi
+ echo -n >"$_tmp";
+ output "$_tmp";
+}
+
+########################################################################
+# unquote (<arg>*)
+#
+# Remove quotes around each argument and escape all space characters
+# by a backslash `\'.
+#
+# Output : the same number of arguments, but each processed.
+#
+unquote()
+{
+ local _res;
+ local _a;
+ local _args;
+ [ "$#" = 0 ] && return;
+ _res="";
+ for _a in "$@"; do
+ _unq="$(eval output $_a | sed -e '\| |s||\\ |g')";
+ if [ "$_res" = "" ]; then
+ _res="$_unq";
+ else
+ _res="$_res $_unq";
+ fi;
+ done;
+ output "$_res";
+}
+
+########################################################################
+# usage ()
+#
+# print usage information to stderr
+#
+usage()
+{
+ echo2;
+ version;
+ cat >&2 <<EOF
+Copyright (C) 2001 Free Software Foundation, Inc.
+This is free software licensed under the GNU General Public License.
+
+Usage : $PROGRAM_NAME [options] [file] [-]
+ [manpage.x] [man:manpage] [man:manpage(x)] ...
+
+Display groff files, standard input, and/or Unix manual pages with
+gxditview in X window or in a text pager.
+"-" stands for including standard input.
+"manpage" is the name of a man-page, "x" its section.
+All parameters and standard input are decompressed on-the-fly (by zcat).
+
+-c --stdout tty output without a pager
+-h --help print this usage message.
+-Q --source output as roff source.
+-T --device set device for X or tty output.
+-v --version print version information.
+-X --dpi=res set resolution to "res" ("75" or "100" (default)).
+--man check file arguments first on being man-pages.
+--manpath=path preset path for searching man-pages, "" means disable.
+--xrdb=opt pass "opt" as option to gxditview (several allowed).
+All other options are interpreted as "groff" parameters and tranferred
+unmodified to "grog".
+EOF
+
+ if [ "$HAS_OPTS_GNU" != "yes" ]; then
+ cat >&2 <<EOF
+
+Your system does not support GNU long options. All options starting
+with double-minus are not available.
+EOF
+ echo2;
+ fi;
+}
+
+########################################################################
+# version ()
+#
+# print version information to stderr
+#
+version()
+{
+ echo2 "$PROGRAM_NAME $PROGRAM_VERSION of $LAST_UPDATE";
+}
+
+########################################################################
+# main
+########################################################################
+
+# The main area contains the following parts:
+# - argument parsing
+# - temporary files
+# - display
+
+########################################################################
+# main : argument parsing
+#
+set -- $(normalize_args "$@");
+
+# $* is garanteed to have a "--" argument, separating opts and params.
+# Note that all arguments to options and all non-option parameters are
+# enclosed in single quotes, while options are not quoted. The quotes
+# must be removed before being used, see function `unqote'. For example,
+# -X -m 'man' -- 'file1' '-' 'file2'
+
+# parse options
+until [ "$1" = "--" -o "$1" = "'--'" ]; do
+ # Note: arguments to options are quoted; these quotes must be handled.
+ #
+ _opt="$1";
+ shift;
+ case "$_opt" in
+ -h|--help)
+ usage;
+ leave;
+ ;;
+ -Q|--source) # output source code (`Quellcode').
+ OPT_SOURCE="yes";
+ ;;
+ -T|--device) # device, non-X* go to stdout, arg
+ _arg="$(get_next_quoted $*)";
+ set -- $(shift_quoted $*);
+ case "$_arg" in
+ X75)
+ OPT_DEVICE="";
+ OPT_DPI=75;
+ ;;
+ X100)
+ OPT_DEVICE="";
+ OPT_DPI=100;
+ ;;
+ *)
+ OPT_DEVICE="$_arg";
+ OPT_DPI="";
+ ;;
+ esac;
+ ;;
+ -v|--version)
+ version;
+ leave;
+ ;;
+ -X) # set X resolution 75 dpi (default 100).
+ OPT_DEVICE="";
+ OPT_DPI=75;
+ ;;
+ --man) # interpret all file params as man-pages
+ OPT_MAN="yes";
+ if [ "$ENABLE_MANPAGES" != "yes" ] ; then
+ error "confilicting options --man and --manpath.";
+ fi;
+ ;;
+ --manpath) # specify search path for man-pages, arg
+ OPT_MANPATH="$(get_next_quoted $*)";
+ set -- $(shift_quoted $*);
+ if [ "$OPT_MANPATH" = "" ]; then
+ ENABLE_MANPAGES="no";
+ if [ "$OPT_MAN" = "yes" ] ; then
+ error "confilicting options --man and --manpath.";
+ fi;
+ else
+ ENABLE_MANPAGES="yes";
+ fi;
+ HAS_MANW="";
+ ;;
+ --title)
+ OPT_TITLE="$(get_next_quoted $*)";
+ set -- $(shift_quoted $*);
+ ;;
+ --xrdb) # add X resource for gxditview, arg
+ _arg="$(get_next_quoted $*)";
+ set -- $(shift_quoted $*);
+ OPT_XRDB="$(append_args "$OPT_XRDB" "$_arg")";
+ ;;
+ -?)
+ _opt_char="$(output $_opt | sed -e '\|-.|s|-||')";
+ if is_substring_of "$_opt_char" "${GROFF_SHORTOPTS}"; then
+ OTHER_OPTIONS="$(append_args "$OTHER_OPTIONS" "$_opt")";
+ elif is_substring_of "$_opt_char" "${GROFF_ARG_SHORTS}"; then
+ OTHER_OPTIONS="$(\
+ append_args $OTHER_OPTIONS "${1}$(unquote ${2})")";
+ shift; # argument
+ else
+ error 1 "Unknown option : $1";
+ fi;
+ ;;
+ *) error 1 "main : error on argument parsing : $*"; ;;
+ esac;
+done;
+shift; # remove `--' argument
+
+unset _arg
+unset _opt
+
+# Remaining arguments are file names, each enclosed in single quotes.
+# Function supercat expects such arguments.
+
+if [ "$#" -eq 0 ]; then # use "-" for standard input
+ set -- "'-'";
+fi;
+FILE_ARGS="$*"; # all file parameters; do not change
+
+# setup for man-pages
+
+if [ "$ENABLE_MANPAGES" = "yes" -a "$HAS_MANW" != "yes" ]; then
+ MAN_PATH="$(get_manpath)";
+ if [ "$MAN_PATH" = "" ]; then
+ ENABLE_MANPAGES="no";
+ fi;
+fi;
+
+########################################################################
+# main : temporary files
+#
+# save standard input
+TMP_INPUT="$(tmp_create)";
+save_stdin_if_any;
+
+# built up title consisting of processed filespecs
+TMP_DONE="$(tmp_create)";
+output "$PROGRAM_NAME :" > $TMP_DONE;
+
+# output parameter files (and stdin) decompressed into temporary file
+TMP_CAT="$(tmp_create)";
+supercat $FILE_ARGS >"$TMP_CAT"; # this does the main work
+set -- $(ls -l -L "$TMP_CAT"); # check on empty
+if [ "$5" -eq 0 ]; then
+ echo2 "input is empty, nothing to display.";
+ leave;
+fi;
+
+########################################################################
+# main : display
+#
+_mode="";
+if [ "$OPT_SOURCE" = "yes" ]; then # output source code
+ _mode="source";
+elif [ "$OPT_DEVICE" != "" ]; then # non-X device, cat to stdout
+ _mode="device";
+elif [ "$DISPLAY" != "" ]; then # within X window
+ _mode="X";
+else # tty
+ _mode="tty";
+fi;
+
+case "$_mode" in
+ source)
+ tmp_cat;
+ ;;
+ device)
+ _groggy="$(tmp_cat | grog $OTHER_OPTIONS -T"${OPT_DEVICE}")";
+ tmp_cat | eval $_groggy;
+ ;;
+ X)
+ if [ "$OPT_DPI" = "" ]; then
+ OPT_DPI="$(check_dpi)"; # sanity check for using 100 dpi default
+ fi;
+ _groggy="$(tmp_cat | grog $OTHER_OPTIONS -TX"${OPT_DPI}" -Z )";
+ tmp_cat | eval $_groggy | \
+ gxditview $OPT_XRDB -title "$(get_title)" -;
+ ;;
+ tty)
+ if [ "$OPT_DPI" = "" ]; then
+ error 1 "Not in X window, no X device available.";
+ fi;
+ _groggy="$(tmp_cat | grog $OTHER_OPTIONS -Tlatin1)";
+ if [ "$PAGER" = "" ]; then
+ _pager=less;
+ else
+ _pager=$PAGER;
+ fi;
+ tmp_cat | eval $_groggy | $_pager;
+ ;;
+esac;
+clean_up;