summaryrefslogtreecommitdiff
path: root/Build/source/utils/texdoctk
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-12-16 00:59:24 +0000
committerKarl Berry <karl@freefriends.org>2012-12-16 00:59:24 +0000
commit78b57f12e537918f0e6f9f9a1d8d0017cb6c86ba (patch)
treeab61d31e41fc4a884b118c2713657a31da0eea3c /Build/source/utils/texdoctk
parent53c4b8c53ed95a842aac0efbedd7dc0a55ffa511 (diff)
consolidate texdoctk files in new directory (uninstalled just for the moment)
git-svn-id: svn://tug.org/texlive/trunk@28542 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/texdoctk')
-rw-r--r--Build/source/utils/texdoctk/README.texdoctk298
-rw-r--r--Build/source/utils/texdoctk/texdoctk.1217
-rwxr-xr-xBuild/source/utils/texdoctk/texdoctk.pl1857
3 files changed, 2372 insertions, 0 deletions
diff --git a/Build/source/utils/texdoctk/README.texdoctk b/Build/source/utils/texdoctk/README.texdoctk
new file mode 100644
index 00000000000..54217cb61ce
--- /dev/null
+++ b/Build/source/utils/texdoctk/README.texdoctk
@@ -0,0 +1,298 @@
+ texdoctk v.0.5.3
+
+texdoctk is a Perl/Tk-based frontend for easy access of package documentation
+for the TeX typesetting system on Unix platforms. It includes the following
+files:
+
+ texdoctk - the program source
+ texdoctk.dat - the database containing the information about the
+ accessible documentation files for teTeX-texmf
+ texdocrc.defaults - the system-wide default specification for viewer
+ and printer settings
+ texdoctk.1 - manpage
+ README.texdoctk - this file
+The current version is 0.6.0.
+
+REQUIREMENTS
+The program is written in Perl/Tk; it requires Perl 5 and Perl/Tk 8.x. It is
+known to run with Perl 5.004_04 or higher and PerlTk 800.015.
+The database file texdoctk.dat is made for the teTeX distribution.
+Note that the program is *not* a viewer, but an interface to access a document
+with the appropriate viewer. Thus, you need to have appropriate viewers for
+the different formats to actually read the files. Documentations are available
+as .dvi, .ps, .pdf, .html or plain text; some packages are only documented in
+the .sty files. For plain text files (.txt, .sty etc.), texdoctk's own text
+viewer can be used (default). If a document format is not known, texdoctk
+will by default assume that it is plain text and use the text file viewer;
+this behaviour can be switched off in the Settings menu.
+If you want to print the documentations, you will need converters to turn
+non-PS files into PostScript. Here are some suggestions:
+dvi->ps: dvips (is part of teTeX)
+ http://www.radicaleye.com/dvips.html
+pdf->ps: pdf2ps
+ http://www.cs.wisc.edu/~ghost
+ Acrobat Reader
+ http://www.adobe.com
+html->ps: html2ps
+ http://user.it.uu.se/~jan/html2ps.html
+plain text->ps: a2ps
+ http://www-inf.enst.fr/~demaille/a2ps/
+To increase the font size automatically for high-resolution screen, the program
+xwininfo is used; texdoctk will work without as well, though.
+
+INSTALLATION
+The program texdoctk can be copied into any directory where programs are stored
+on your system, e.g. into /usr/local/bin or, probably more adequate, into
+/usr/local/teTeX/bin. It assumes that you have the env command in /usr/bin/
+available to determine the location of the Perl executable; therefore, you may
+need to change the first line of the code if this is not the case for your
+system or if for some reason your Perl executable is not called "perl"; you
+will also have to change the perl call in the sub viewslc as well.
+The database file texdoctk.dat and the configuration file texdocrc.defaults
+must then be put into a subdirectory of the main texmf directory called
+texdoctk. If you want to include information for your local system,
+generate a file texdoctk-local.dat. Make sure to run texhash after
+installation. See the manpage for more info.
+Set the defaults in texdocrc.defaults according to your system; you can
+replace the settings which are specified in the shipped file, but do not
+uncomment variables for items which are not available or applicable for you,
+but just leave the value empty by specifying nothing.
+The individual users can define their own preferences by copying the system
+texdocrc.defaults to ~/.texdocrc and assign new values to the items to be
+changed. They can also establish an additional personal database for packages
+they might have installed in their respective $HOME; this database must be
+called texdoctk-pers.dat and reside in $HOMETEXMF/texdoctk/.
+If you meet the requirements concerning the teTeX distribution, I assume that
+the texdoctk.dat file should work without failures; if you have another
+distribution or if your texmf/doc tree is somehow modified, it may happen that
+a file is not found in spite of the program trying to find it elsewhere. You
+will have to edit the file then, but make sure to keep the right format for
+the entries:
+<package-label>;Short description for listbox (opt. <package-name>);path in doc directory;optional keywords
+(without breaking the line!). If the documentation is included in the .sty file
+instead of a proper documentation file, the optional keywords should start with
+-?- directly after the semicolon, where ? is 0, 1, 2 or 3; these are flags
+which indicate in which part of the .sty the instructions are placed. See the
+database file and/or the manpage for more details if necessary.
+The documentation is grouped into 17 categories; the 18th button of the main
+panel is inactive by default. If you have special documents which do not fit
+into any of the categories, you can create a block with a new name in
+texdoctk-local.dat or texdoctk-pers.dat with the respective entries.
+In the settings window you see a checkbox in the html->ps and text->ps
+converter menus for switching on/off output redirect. This is due to the fact
+that some converters do not write their output into a file but to stdout by
+default, so a redirect is needed, e.g.
+a2ps myfile.txt >myfile.ps
+
+DISCLAIMER
+texdoctk v.0.6.0 (Sep 23, 2004) - GUI for TeX documentation access
+Copyright (C) 2000-2004 Thomas Ruedas
+This program 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 of the License, or
+(at your option) any later version.
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ACKNOWLEDGEMENTS
+Thomas Esser included the program in the teTeX distribution of TeX and Friends.
+He provided me with informations about changes in the texmf tree and made a
+number of very useful suggestions. He also has coordinated and kept track of
+several additions from other contributors, who fixed bugs and added extensions
+e.g. for use under Win32 systems.
+Reinhard Kotucha and Andreas Werner made very valuable comments and suggestions
+to enhance v.0.3.0, especially about the special treatment of Netscape.
+Reinhard Kotucha also made many useful suggestions and provided patches for
+v.0.4.0; unfortunately, I could not implement all these ideas yet.
+Hans Fredrik Nordhaug made some suggestions, e.g. concerning local and
+personal texmf trees, and reported several bugs in different releases; he also
+contributed fixes/patches.
+Adrian Bunk also has reported a bug and contributed a small manpage for the
+program. He made a Debian GNU/Linux package of texdoctk.
+Michael Sanders reminded me to set the permissions right in the tarball.
+As this is my first application written in PerlTk, it happened that I could
+not solve every problem with my book and the other documentation, but had to
+ask for help on comp.lang.perl.tk. Paul R. Andersen and Stephen O. Lidie have
+given helpful replies and examples for me to try out.
+Fabrice Popineau, and possibly others who I don't know, have provided
+portability to Win32 platforms for use with fpTeX. Staszek Wawrykiewicz helped
+making it ready for use with new TeXLive editions.
+Paul Szabo pointed out a potential security risk related to the way names of
+temporary files are generated.
+
+TO DO LIST
+Unfortunately, I didn't have time to implement all suggestions made by the
+aforementioned people; I hope that I can do that at some later time:
+- widget placement in topic toplevels becomes ugly when the toplevel is
+ stretched or shrunk; should be made more elegant
+- raise existing texdoctk window instead of possibly running texdoctk twice;
+ (this seems to be difficult, because it requires interprocess communication
+ which is kind of unsafe and requires the use of perl -T)
+Possible further long-term enhancements:
+- maybe use Williams Catalogue for automatically building database during
+ installation
+- refined printing facility
+
+BUGS
+Netscape error output will be written to stderr even if the quiet mode was set,
+because I didn't manage to start it with the "inline" perl script.
+Widget placement in topic toplevels becomes ugly when the toplevel is stretched
+or shrunk.
+The font in the frame labels of the Settings menu are not forced to the default
+font; this will become visible e.g. at hi-res screens, where the label font is
+not scaled up.
+Please let me know if you find bugs or have suggestions for improvements.
+
+HISTORY/CHANGES
+v.0.6.0 Sep 23, 2004
+ - Unknown document formats will be opened as plain text with the text
+ file viewer by default; the Settings menu was given a new button to
+ toggle this behaviour.
+ - Allow for texmf-dist and texmf-doc trees for compliance with teTeX 3
+ and TeXLive.
+ - Made an attempt to allow for additional personal user's databases to
+ be located in $HOMETEXMF, following a long-standing suggestion of
+ H.F.Nordhaug. Additional local and personal databases do not need
+ to be copies of the system database; instead their contents will be
+ appended to the entries of the default list.
+ - Fixed a bug with the handling of the local texmf tree reported by
+ Sebastian Luque.
+ - Updated this README and the manpage.
+v.0.5.2 May 20, 2004
+ - Changed the name generation of temporary files to something random
+ in order to address a potential security risk pointed out by Paul
+ Szabo.
+ - Replaced -q option for enabling "quiet" behaviour by -v option for
+ enabling "verbose" behaviour; quiet behaviour is now the default and
+ was extended to suppress the popup of Warning windows (popmsg level
+ 1).
+ - Added a possibility to have the Settings menu write the user's
+ ~/.texdocrc (older suggestion by R.Kotucha). NB: It is not intended
+ to write the system-wide texdocrc.defaults, because it does not set
+ $TEXDOCPATH and $LOCALDOCPATH.
+ - Button colours are made configurable through the texdocrc files or
+ the Settings menu. This is intended to fix a problem H.F.Nordhaug
+ reported with users of newer versions of the KDE, where some button
+ colours suddenly where messed up. - Validity of entered colours
+ is checked if X11's showrgb program is available.
+ - DVIPS_OPTS, PDFPS_OPTS and PRINT_OPTS in texdocrc.defaults are now
+ obsolete, but still supported. It seemed more reasonable to treat
+ the contents of DVIPS_CONV, PDFPS_CONV and PRINT_CMD as command lines
+ (which actually would have already been possible all the time). The
+ same is true for the viewer variables.
+ - Command line options can now be grouped (i.e. -av instead of -a -v).
+ - Cursor changes from arrow to watch in some tasks, to indicate a
+ process which takes a bit of time.
+ - fixed some glitches in databases: semicolons at the end of the
+ pdfTeX-related entries; corrected description of ltxtable (hint by
+ Rolf Niepraschk) and changed its position; corrected description of
+ AMSguide (AMS TeX instead of AMS LaTeX) (hint by H.F.Nordhaug)
+ - several additions by other contributors, for instance support for
+ Win32 systems
+v.0.5.1 April 21, 2001
+ - Enhanced right-button search function so that compressed doc files
+ are also found.
+ - Fixed a bug in the documentation finding subroutine reported by H.F.
+ Nordhaug: the compression determination block in sub finddoc was
+ broken.
+ - Improved treatment of entering an empty string in the search:
+ this is now explicitly treated as demand for display of the whole
+ database, instead of search for a null string.
+ - Automatic selection of list item in listbox if it contains only one
+ element; this will frequently happen in search results. In this
+ context, the autoview flag (option -a) has been introduced in the
+ texdocrc.defaults and the Settings menu: if it is chosen, the
+ appropriate viewer will be started automatically in the case of
+ one-item listboxes.
+ - Made <Ctrl-q>, <Ctrl-s>, <Ctrl-t> and <Ctrl-h> definitions active in
+ all widgets; thus, you don't need to type <Ctrl-q> in the main window
+ to quit, for example. Introduced new global key binding for raising
+ the main window (<Ctrl-m>).
+ - Fixed a braindead typo in the texdoc-*.dat files (too dumb to tell).
+ - Some small changes/updates in the Help text; the button and window
+ are now named "Help/About".
+ - Added an emacs perl-mode directive at the end, mostly for my
+ convenience.
+v.0.5.0a April 19, 2001
+ - Fixed bug in texdoc-102.dat reported by H.F.Nordhaug: correct path
+ for multirow is latex/multirow/multirow.sty (instead of
+ latex/misc/multirow.sty, as in texdoc-100.dat)
+v.0.5.0 April 18, 2001
+ - For some packages, the only documentation is included in the .sty
+ file itself. This documentation is now made accessible by extracting
+ the comments/instructions, writing them into a temporary text file
+ and calling the text file viewer on it. Thus 38 additional
+ documentation files are made accessible now.
+ - implementation of a suggestion by Hans Fredrik Nordhaug: contents of
+ the local texmf tree ($TEXMFLOCAL) can be included now. Arbitrary
+ inclusion of additional private texmf trees is not yet possible,
+ though.
+ - Two fixes/improvements in the databases by R.Kotucha were made
+ (concerning epslatex and the MetaPost tutorial)
+ - R.Kotucha suggested the use of the program xwininfo to determine
+ screen resolution and switch to a larger font size at hi-res screens.
+ He provided a patch for this, which I added after a slight
+ adaptation.
+ - auto-determination of Perl's path (stolen from some script by Thomas
+ Esser, IIRC)
+ - If a beta release of teTeX is used, the teTeX-1.0.2 database will be
+ used as a default instead of the 1.0.0 database
+ - introduced new message type with transient windows
+ - fatal error messages if essential config/database files are not found
+ - some syntax cosmetics
+v.0.4.0 June 11, 2000
+ - implementation of several suggestions by Reinhard Kotucha and
+ Andreas Werner:
+ * More than 1 document can now be viewed at one time, because the
+ viewers now run as background processes. They are not killed when
+ texdoctk itself is quit.
+ If Netscape is your browser, HTML documents are now loaded into
+ an existing Netscape window; no new Netscape will be started. This
+ is to be a bit economic with system resources.
+ * The Search button resp. <Ctrl-s> now switches on/off the search
+ entry widget; this is to avoid that multiple entry widgets come up,
+ because that doesn't make much sense.
+ * If no TXT_VIEWER is defined, the environment variable $PAGER will
+ be used, if defined (but see below).
+ - bugs/fixes and suggestions reported by Hans Fredrik Nordhaug:
+ * $j for loop in sub srchstr was too short:
+ $j<$maxind[$i] --> $j<$maxind[$i]+1
+ * misplaced last SRCH in keywords branch of sub srchstr: last SRCH
+ had to be put into inner if block
+ * added support of zip compression format
+ - bug/fix reported by Adrian Bunk:
+ * ambiguous use of redirection flag/sign hor html and text->ps
+ conversion
+ - own text viewer for plain text documentation files; this is now the
+ default in the original texdocrc.defaults
+ - kpsewhich instead of find is used for rescue file search
+ - temporary files generated when printing or possibly decompressing (as
+ in Debian) now get different names to prevent overwriting files which
+ are still in use
+ - main, settings, and help windows made non-resizable
+ - suppressed availability of listbox selection to X selection
+ - document selection toplevel windows will be raised now instead of
+ being opened twice or more times if they are already open
+ - uniform font for all text-containing widgets explicitly set; I had
+ some weird font configuration when running texdoctk under a CDE
+ - environment
+v.0.3.0 March 11, 2000
+ - first full public release
+ - implementation of some suggestions by Thomas Esser:
+ use of kpsewhich, changes in directory and database configuration
+ implemented cd to file directory to ensure rendering of graphics
+ made viewer message output suppression really quiet
+ better layout of help window
+v.0.2 March 7, 2000
+ - first public release (preliminary)
+v.0.1 - private trial version, does not exist anymore
+
+AUTHOR
+Thomas Ruedas
+tr@geol.ku.dk
+http://www.geophysik.uni-frankfurt.de/~ruedas/progs.html
diff --git a/Build/source/utils/texdoctk/texdoctk.1 b/Build/source/utils/texdoctk/texdoctk.1
new file mode 100644
index 00000000000..e7aebb7098a
--- /dev/null
+++ b/Build/source/utils/texdoctk/texdoctk.1
@@ -0,0 +1,217 @@
+.TH TEXDOCTK 1
+.SH NAME
+texdoctk \- GUI for easier access of TeX package and program documentations
+.SH SYNOPSIS
+.B texdoctk
+-[aq]
+.SH "DESCRIPTION"
+.B texdoctk
+is a GUI for easier access to a large part of the vast amount
+of package and program documentations and tutorials for TeX and its
+different derivatives (mainly LaTeX). It is optimized and included in
+the teTeX and fpTeX distributions and also available with TeXLive.
+.PP
+The documentation is grouped into 17 categories; the 18th button of the main
+panel is inactive by default and intended for use with local additions (see
+section
+.B CONFIGURATION
+below).
+.PP
+In the settings window you see a checkbox in the html->ps and text->ps
+converter menus for switching on/off output redirect. This is due to the fact
+that some converters do not write their output into a file but to stdout by
+default, so a redirect is needed, e.g.
+.PP
+a2ps myfile.txt >myfile.ps
+.SH "OPTIONS"
+.TP
+.I "\-v"
+verbose: enable some viewer messages which are otherwise sent to stderr,
+as well as some warning popup windows. This can also be set in a
+configuration file.
+.TP
+.I "\-a"
+autoview: autostart viewer if a listbox contains only one item (this will
+frequently happen in search results). This can also be set in a configuration
+file.
+.SH "CONFIGURATION"
+.PP
+The configuration is controlled by the system default configuration file
+($TEXMFMAIN)/texdoctk/texdocrc.defaults, most of whose entries can though be
+overridden by the users' own optional ~/.texdocrc files and/or command line
+options.
+.SS The Settings menu and configuration files
+.PP
+The Settings menu is used to change the user-definable settings of \fBtexdoctk\fP
+for the duration of the program call or as new defaults. The latter case is
+the purpose of the Save button, which generates or rewrites the user's own
+~/.texdocrc file. The system defaults cannot be edited with the Settings
+menu.
+.TP
+Paths
+The TEXMF-type paths on the system are reported, and the user can specify the
+name of the subdirectory of $HOMETEXMF, where the personal documentation is
+stored.
+.TP
+General viewer behaviour
+
+.I Suppress error messages
+toggle verbose mode (see option -v); default is off.
+
+.I Autostart viewer for one-item listboxes
+if a listbox contains only one item (see option -a)
+
+.I Use text viewer for unknown file format
+i.e. treat the file as plain text. \fBtexdoctk\fP should recognize the usual file
+formats and also relate names like README to plain text, but some docs may have
+freely invented names. Default is on; if switched off, trying to view such
+files will raise an error. The switch does not influence printing: unrecognized
+formats cannot be printed.
+
+.I Change viewer colours
+using either RGB triplets in the format #rrggbb or the standardized names.
+.TP
+DVI/PostScript/PDF/HTML/Plain text
+For text files, \fBtexdoctk\fP provides an own viewer. If this viewer is disabled,
+but no alternative viewer is specified, \fBtexdoctk\fP tries to read the content
+of the environment variable $PAGER.
+
+If you want to print the documentations, you will need converters to turn
+non-PS files into PostScript. Here are some suggestions:
+
+\& dvi->ps:
+dvips (is part of teTeX) (http://www.radicaleye.com/dvips.html)
+
+\& pdf->ps:
+pdf2ps (http://www.cs.wisc.edu/~ghost) or
+Acrobat Reader (http://www.adobe.com)
+
+\& html->ps: html2ps (http://user.it.uu.se/~jan/html2ps.html)
+
+\& plain text->ps: a2ps (http://www-inf.enst.fr/~demaille/a2ps/)
+
+The html->ps and text->ps converter menus for switching on/off output redirect.
+This is due to the fact that some converters do not write their output into a
+file but to stdout by default, so a redirect is needed, e.g.
+.B a2ps myfile.txt >myfile.ps
+.PP
+The system-wide configuration file is ($TEXMFMAIN)/texdoctk/texdocrc.defaults
+and should only be writable by the administrator of the installation using any
+text editor. The optional user configuration file is ~/.texdocrc and can
+override all but those system settings which affect the installation as a
+whole. The preferred way of changing it is through the Settings menu.
+.SS The databases
+\fBtexdoctk\fP comes with a default database file ($TEXMFMAIN)/texdoctk/texdoctk.dat
+with a special format. It is divided into 17 sections corresponding to the
+17 buttons that are active by default. Each section begins with a line
+
+@\fIsection_name\fP
+
+where
+.I section_name
+is the text as it appears in the button. This title is
+followed by the descriptive entries for each documentation, which have this
+format:
+
+\fIpackage-label\fP;Short description for listbox (opt. \fIpackage-name\fP);path in doc directory;optional keywords
+
+(without breaking the line!). Comments (initiated with a #) and empty lines
+are ignored by the program. The second field is the text displayed in the
+selection listboxes of \fBtexdoctk\fP, and you will usually want to mention the name
+of the package in parens along with it; the first field is a \fBunique\fP label
+for the package for internal use of the program which will usually be chosen
+identical to the package name, but can be different if there is more than one
+documentation file coming with a package.
+.PP
+The administrator will probably install additional packages in the local texmf
+tree. The corresponding documentation can be made accessible by an additional
+database $TEXMFLOCAL/texdoctk/texdoctk-local.dat. Furthermore, individual
+users possibly install additional packages in an texmf subdirectory of their
+$HOME, for which they can make an individual database themselves as
+$TEXMFHOME/texdoctk/texdoctk-pers.dat. After creating such files, texhash
+must be executed.
+.PP
+Both types of databases must have the same structure as the system database,
+although they need (and should) not include all its sections if there are no
+additional entries. For example, if the the package
+.I foo
+is added to the local tree such that its documentation file is
+($TEXMFLOCAL)/doc/latex/foo/foo.dvi and it is decided that it fits best into
+the existing category Graphics, texdoctk-local.dat would look like this:
+
+@Graphics
+.br
+foo;Create bells and whistles (foo);latex/foo/foo.dvi;decoration
+
+The entry for
+.I foo
+will then be appended to the list of entries in the Graphics category. The 18th
+button can be activated in the same way, but using a new category name;
+possible entries at the beginning of the database which have not been assigned
+to a category will be assigned to the default Miscellaneous, making the 18th
+button active with that label. Note that you cannot have more than 18
+categories; if there are more, only the one defined last will appear and be
+used.
+.PP
+If the documentation is included in the .sty file instead of a proper
+documentation file, the optional keywords should start with
+-?- directly after the semicolon, where ? is 0, 1, 2 or 3; these are flags
+which indicate in which part of the .sty the instructions are placed and
+should help \fBtexdoctk\fP to extract the documentation from the style and present
+it without the code, which would normally be of little use.
+.TP
+0
+no specific place, scattered between the code
+.TP
+1
+at end, behind \\endinput; some .sty files have well-organized documentation
+behind the end of the actual code, where TeX doesn't see it upon compilation
+.TP
+2
+at beginning, terminated by %%%%%%; in some other cases, some usage information
+is at the beginning of the .sty as a comment terminated by a line full of %
+.TP
+3
+as 2, but with a blank line as termination
+.PP
+See the system database for plenty of examples.
+
+.SH "FILES"
+.PP
+\& $TEXMFMAIN/texdoctk/texdocrc.defaults
+system-wide configuration file
+.PP
+\& ~/.texdocrc
+(optional) personal configuration file; can also be created with the Settings menu
+.PP
+\& $TEXMFMAIN/texdoctk/texdoctk.dat
+default database file for documentation files of the distribution
+.PP
+\& $TEXMFLOCAL/texdoctk/texdoctk-local.dat
+(optional) local database file for documentation files
+.PP
+\& $TEXMFHOME/texdoctk/texdoctk-pers.dat
+(optional) personal database file of individual users for documentation files
+.SH BUGS
+Widget placement in topic toplevels becomes ugly when the toplevel is stretched
+or shrunk.
+.PP
+The font in the frame labels of the Settings menu are not forced to the default
+font; this will become visible e.g. at hi-res screens, where the label font is
+not scaled up.
+.PP
+Netscape and Mozilla error output will be written to stderr even if the quiet
+mode was set.
+.SH AUTHOR
+.B texdoctk
+was written by Thomas Ruedas <tr@geol.ku.dk>.
+.PP
+This manual page was originally written by Adrian Bunk <bunk@fs.tum.de> for
+the Debian GNU/Linux system (but may be used by others). It is now maintained
+by Thomas Ruedas.
+
+.SH COPYRIGHT
+Copyright (C) 2000-2004 Thomas Ruedas
+.br
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/Build/source/utils/texdoctk/texdoctk.pl b/Build/source/utils/texdoctk/texdoctk.pl
new file mode 100755
index 00000000000..36497183e3b
--- /dev/null
+++ b/Build/source/utils/texdoctk/texdoctk.pl
@@ -0,0 +1,1857 @@
+#! /usr/bin/env perl
+###############################################################################
+# texdoctk - GUI for TeX documentation access
+# Copyright (C) 2000-2004 Thomas Ruedas
+# Updated in 2010 by Manuel Pegourie-Gonnard
+# This program is provided under the GNU Public License; see the file
+# README.texdoctk for details about requirements, installation, configuration,
+# and the full disclaimer.
+###############################################################################
+my ($version, $date) = ("0.6.1", "2004-11-05");
+use strict;
+use Tk;
+use Getopt::Long;
+Getopt::Long::config('bundling');
+use File::Basename;
+
+BEGIN {
+ Win32::SetChildShowWindow(0) if defined &Win32::SetChildShowWindow;
+}
+
+my $IsWin32 = ($^O =~ /MSWin32/i);
+
+if ($IsWin32) {
+ require Win32::API;
+# Win32::API->import( qw(
+# &something
+# ));
+}
+
+# initialization of some internal variables
+$|=1;
+my $quiet=1;
+my $autoview;
+my $xfmt_viewer=1,
+my @tdcolors;
+my %butcol;
+my $srchentry;
+my $srchflag=0;
+my $srchtype; # 0 = database, 1 = texdoc
+my $tmpfno;
+# system variables
+my ($texmfmain,$texmfdist,$texmfdoc,$texmflocal,$texmfhome,
+ $texdocpath,$distdocpath,$docdocpath,$localdocpath,$homedocpath,
+ $datadir,
+ $dvi_viewer,$dvips_conv,$ps_viewer,$pdf_viewer,
+ $pdfps_conv,$html_viewer,$htmlps_conv,$htmlps_redir,
+ $txt_viewer,$txtps_conv,$txtps_redir,$print_cmd);
+
+# defaults: unix values
+my $qq="'";
+my $HomeEnv=$ENV{HOME};
+my $TeXDocRcDefaults="texdocrc.defaults";
+my $TempDir; $TempDir=$ENV{TMPDIR} or $TempDir="/tmp";
+my $CmdConsole="xterm -e ";
+
+if ($IsWin32) {
+ $qq = "\"";
+ $HomeEnv = $ENV{'USERPROFILE'};
+ chomp $HomeEnv;
+ $TeXDocRcDefaults = "texdocrc-win32.defaults";
+ $TempDir = &GetTempPath;
+ $CmdConsole = "cmd /c ";
+}
+
+my $myrc="${HomeEnv}/.texdocrc"; # optional personal settings file
+
+my ($line,@dummy);
+my @tmpfiles;
+# read system-wide defaults from texdocrc.defaults
+my $sysrc=`kpsewhich --progname=texdoctk --format=${qq}other text files${qq} ${TeXDocRcDefaults}`;
+my $database=`kpsewhich --progname=texdoctk --format=${qq}other text files${qq} texdoctk.dat`;
+my $locdatabase=`kpsewhich --progname=texdoctk --format=${qq}other text files${qq} texdoctk-local.dat`;
+my $homedatabase=`kpsewhich --progname=texdoctk --format=${qq}other text files${qq} texdoctk-pers.dat`;
+chomp $locdatabase;
+chomp $homedatabase;
+chomp $sysrc;
+&readrc($sysrc,1);
+@dummy=split("/",$sysrc);
+pop @dummy;
+$datadir=join('/',@dummy);
+# possibly use personal settings instead of defaults
+if (-e $myrc) { &readrc($myrc,2); }
+# command line options
+GetOptions('v'=>\$quiet,'a'=>\$autoview);
+my $special=0;
+my @button;
+$button[17]="Miscellaneous";
+my (@packname,@topic,@doc,@keywords,@maxind,%stydoc);
+# read database file
+my $i=-1;
+my $j;
+open(DATABASE,"$database") || &fatalmsg("Couldn't open database $database.\n");
+while ($line = <DATABASE>) {
+ LINETYPE: {
+ ($line =~ /^\@/) && do { # category
+ ++$i;
+ if ($i == $#button) {
+ pop @button;
+ push @button,(substr($line,1,-1));
+ $special=1;
+ } else {
+ $button[$i]=substr($line,1,-1);
+ }
+ $j=0;
+ last LINETYPE;
+ };
+ ($line =~ /^(#|$)/) && do { # comment or empty line
+ last LINETYPE;
+ };
+# list item
+ @dummy=split(";",$line);
+ $packname[$i][$j]=$dummy[0];
+ $topic[$i][$j]=$dummy[1];
+ $doc[$i][$j]=$dummy[2];
+ $keywords[$i][$j]=$dummy[3];
+ if ($doc[$i][$j] =~ /sty$/ && $keywords[$i][$j]) {
+ $stydoc{"$doc[$i][$j]"}=substr($keywords[$i][$j],1,1);
+ unless ($stydoc{"$doc[$i][$j]"} =~ /^\d$/) {
+ $stydoc{"$doc[$i][$j]"}=0;
+ }
+ }
+ $maxind[$i]=$j;
+ ++$j;
+ };
+}
+close(DATABASE);
+# Read site-local and user's database(s) if it/they exist(s)
+foreach my $dbfile ($locdatabase,$homedatabase) {
+ if (-e "$dbfile") {
+ open(DATABASE,"$dbfile") ||
+ print "Couldn't open additional database $dbfile.\n";
+ $i=17; # local/user: if no category is specified in database, add to "Misc"
+ while ($line = <DATABASE>) {
+ LINETYPE: {
+ ($line =~ /^\@/) && do { # category
+ $i=&arrindex(@button,substr($line,1,-1));
+ if ($i >= $#button) {
+ $i=$#button;
+ pop @button;
+ push @button,(substr($line,1,-1));
+ $special=1;
+ }
+ last LINETYPE;
+ };
+ ($line =~ /^(#|$)/) && do { # comment or empty line
+ last LINETYPE;
+ };
+# list item
+ @dummy=split(";",$line);
+ $j=&arrindex(@{$packname[$i]},$dummy[0]);
+ if ($j > $#{$packname[$i]}) {
+ $packname[$i][$j]=$dummy[0];
+ $topic[$i][$j]=$dummy[1];
+ $doc[$i][$j]=$dummy[2];
+ $keywords[$i][$j]=$dummy[3];
+ if ($doc[$i][$j] =~ /sty$/ && $keywords[$i][$j]) {
+ $stydoc{"$doc[$i][$j]"}=substr($keywords[$i][$j],1,1);
+ unless ($stydoc{"$doc[$i][$j]"} =~ /^\d$/) {
+ $stydoc{"$doc[$i][$j]"}=0;
+ }
+ }
+ $maxind[$i]=$j;
+ ++$j;
+ }
+ };
+ }
+ close(DATABASE);
+ $special=1 if ($i == 17 && $j > 0);
+ }
+}
+
+# Tk
+# hash table for toplevel windows; used to avoid multiple calls of same window
+my %tlwins;
+my %buttonlist;
+# create frames for main window: commands on top, frame for buttons below
+my $main=new MainWindow;
+$tlwins{'mainwindow'}{'addr'}=$main;
+$main->resizable(0,0);
+$main->title("TeX Documentation Browser");
+$main->bind('all','<Control-q>'=>\&clean_exit);
+$main->bind('all','<Control-m>'=>sub { $main->raise(); });
+$main->bind('all','<Control-h>'=>\&helptext);
+$main->bind('all','<Control-s>'=>sub { $main->raise(); &mksrch; });
+$main->bind('all','<Control-t>'=>\&settings);
+my $cmdframe=$main->Frame(-background=>"#ffcc99");
+my $buttonframe=$main->Frame;
+$cmdframe->pack(-side=>'top',-fill=>'x');
+$buttonframe->pack(-side=>'bottom');
+# normal cursor
+my $defcursor=$main->cget(-cursor);
+# make buttons for command frame
+my $Qbut=$cmdframe->Button(-text=>'Quit',%butcol,
+ -command=>\&clean_exit)->pack(-side=>'left');
+$tlwins{'mainwindow'}{'buttons'}[0]=$Qbut;
+# define common default font for labels and text explicitly
+my $deffont=$Qbut->cget(-font);
+# ensure readability on high-res screens (suggested by R.Kotucha)
+$deffont='Helvetica -16 bold' if &x_resolution > 1200;
+$Qbut->configure(-font=>$deffont);
+$tlwins{'mainwindow'}{'buttons'}[1]=$cmdframe->Button(
+ -text=>'Database search',
+ -font=>$deffont,%butcol,
+ -command=>[\&mksrch, 0]
+ )->pack(-side=>'left');
+$tlwins{'mainwindow'}{'buttons'}[2]=$cmdframe->Button(
+ -text=>'File search',
+ -font=>$deffont,%butcol,
+ -command=>[\&mksrch, 1]
+ )->pack(-side=>'left');
+$tlwins{'mainwindow'}{'buttons'}[3]=$cmdframe->Button(-text=>'Help/About',
+ -font=>$deffont,%butcol,
+ -command=>\&helptext
+ )->pack(-side=>'right');
+$tlwins{'mainwindow'}{'buttons'}[4]=$cmdframe->Button(-text=>'Settings',
+ -font=>$deffont,%butcol,
+ -command=>\&settings
+ )->pack(-side=>'right');
+# make buttons for category button frame
+my $lbut=0;
+my $l;
+foreach (@button) { $l=length $_; $lbut=$l if ( $l > $lbut) }
+my @catg;
+my ($i2,$i3);
+my $nbutt=scalar @button;
+my $ncols=$nbutt/3-1;
+foreach (0..$ncols) {
+ $i=$_;
+ $i2=$i+$nbutt/3;
+ $i3=$i+2*$nbutt/3;
+ $catg[$i]=$buttonframe->Button(-text=>$button[$i],
+ -font=>$deffont,%butcol,
+ -width=>$lbut,
+ -command=>[\&tpslct,$i,\@dummy])->grid
+ ($catg[$i2]=$buttonframe->Button(-text=>$button[$i2],
+ -font=>$deffont,%butcol,
+ -width=>$lbut,
+ -command=>[\&tpslct,$i2,\@dummy]),
+ $catg[$i3]=$buttonframe->Button(-text=>$button[$i3],
+ -font=>$deffont,%butcol,
+ -width=>$lbut,
+ -command=>[\&tpslct,$i3,\@dummy]));
+}
+# disable last button (lower right) if no local specials are found in list
+my $ncat;
+if ($special == 0) {
+ $catg[$#button]->configure(-state=>'disabled');
+ $ncat=$nbutt-1;
+} else {
+ $ncat=$nbutt;
+}
+for ($i=0,$j=5; $i<@catg; ++$i,++$j) {
+ $tlwins{'mainwindow'}{'buttons'}[$j]=$catg[$i];
+}
+MainLoop;
+
+########## SUBROUTINES ########################################################
+# toplevel for selecting a topic of a category for viewing or printing
+sub tpslct {
+ my($opt,@srchitems)=@_;
+ my (@lbitems,@lbdocs,$dspselect,$docselect,$wtitle);
+ if ($opt >= 0) {
+# main window buttons
+# see if toplevel window is already there
+ if (Exists($tlwins{$opt}{'addr'})) {
+ $tlwins{$opt}{'addr'}->deiconify();
+ $tlwins{$opt}{'addr'}->raise();
+ return;
+ }
+ for ($j=0; $j <= $maxind[$opt]; ++$j) {
+ push @lbitems,$topic[$opt][$j];
+ push @lbdocs,$doc[$opt][$j];
+ }
+ $wtitle=$button[$opt];
+ } else {
+# search results
+ my $spec_wtitle=shift @srchitems;
+ for ($j=0; $j < $#srchitems; $j+=2) {
+ my $k=$j+1;
+ push @lbitems,$topic[$srchitems[$j]][$srchitems[$k]];
+ push @lbdocs,$doc[$srchitems[$j]][$srchitems[$k]];
+ }
+ $wtitle = ($srchtype ? "File" : "Database")
+ . " search results for $spec_wtitle";
+ }
+# toplevel window of category $opt with two frames
+ my $tpwin=$main->Toplevel(-title=>$wtitle);
+ $tlwins{$opt}{'addr'}=$tpwin;
+ my $tpdsp=$tpwin->Frame(-relief=>'groove')->pack(-side=>'top');
+ my $tpslc=$tpwin->Frame()->pack(-side=>'top');
+# selection frame with listbox and buttons
+# label for listbox
+ my $tplabel=$tpslc->Label(-text=>($srchtype ? "Files" : "Topics"),
+ -font=>$deffont)->pack(-anchor=>'w',
+ -side=>'top');
+# listbox with optional scrollbar
+ my $tplist=$tpslc->Scrolled("Listbox",
+ -font=>$deffont,
+ -scrollbars=>'osoe',
+# -height=>0,
+ -width=>0,
+ -selectmode=>'single',
+ -exportselection=>0,
+ -cursor=>'hand2')->pack(-side=>'left',
+ -fill=>'y',
+ -expand=>1);
+ $tplist->insert('end',@lbitems); # fill topics into listbox
+# buttons frame
+ my $tpbframe=$tpslc->Frame(-borderwidth=>8);
+ $tpbframe->pack(-side=>'right');
+# make buttons for command frame
+ my $n_buttons = 0;
+ $tlwins{$opt}{'buttons'}[$n_buttons++]=
+ $tpbframe->Button(-text=>'View',
+ -font=>$deffont,%butcol,
+ -command=>sub{ &viewslc($docselect,$tpbframe);},
+ -width=>6)->pack(-side=>'top');
+ if (! $IsWin32) {
+ $tlwins{$opt}{'buttons'}[$n_buttons++]=
+ $tpbframe->Button(-text=>'Print',
+ -font=>$deffont,%butcol,
+ -command=>sub{ &prtslc($docselect,$tpbframe);},
+ -width=>6)->pack(-side=>'top');
+ }
+ $tlwins{$opt}{'buttons'}[$n_buttons++]=
+ $tpbframe->Button(-text=>'Cancel',
+ -font=>$deffont,%butcol,
+ -command=>sub{ destroy $tpwin; undef $tlwins{$opt};},
+ -width=>6)->pack(-side=>'bottom');
+# if only 1 item is in the list (most likely in search results), select it
+ if (scalar @lbitems == 1) {
+ $tplist->selectionSet(0);
+ $dspselect=$lbitems[0];
+ $docselect=$lbdocs[0];
+ &viewslc($docselect,$tpbframe)
+ if ($autoview && $wtitle =~ /^Search results/);
+ }
+# display frame
+ my $dsplabel=$tpdsp->Label(-text=>'Selection:',
+ -font=>$deffont)->pack(-anchor=>'w',,
+ -fill=>'x',
+ -side=>'left');
+ my $dspslc=$tpdsp->Label(-textvariable=>\$dspselect,
+ -font=>$deffont,
+ -borderwidth=>2)->pack(-anchor=>'w',
+ -fill=>'x',
+ -side=>'right');
+# handle selection; only one selection possible
+ $tplist->bind('<Button-1>'=>sub{my ($slctind)=$tplist->curselection();
+ $dspselect=$lbitems[$slctind];
+ $docselect=$lbdocs[$slctind];});
+# key bindings
+ $tplist->bind('<Double-Button-1>'=>sub{
+ &viewslc($docselect,$tpbframe);});
+ $tpwin->bind('<Control-v>'=>sub{
+ &viewslc($docselect,$tpbframe);});
+ $tpwin->bind('<Control-p>'=>sub{
+ &prtslc($docselect,$tpbframe);});
+ $tpwin->bind('<Control-c>'=>sub{destroy $tpwin; undef $tlwins{$opt};});
+ $tplist->bind('<Button-3>'=>sub{
+ if ($docselect) {
+ &showpath($docselect,$tpbframe);
+ } else {
+ &popmsg(2,"No selection;\nuse left mouse button.",$tpbframe);
+ }});
+}
+
+# view document selected in listbox
+sub viewslc {
+ my($slc,$parframe)=@_;
+ my $viewer;
+ my $itype=-1;
+ my $browser=0;
+ my $styflag=0;
+ unless (defined $slc) {
+ &popmsg(2,"No selection was made.",$parframe);
+ return;
+ }
+ $parframe->configure(-cursor=>'watch');
+ chomp $slc;
+ my @dummy=split('\.',$slc);
+ DOC_FORMAT: { # determine document type
+ ($dummy[-1] =~ /dvi/) && do { $viewer=$dvi_viewer; last DOC_FORMAT; };
+ ($dummy[-1] =~ /ps/) && do { $viewer=$ps_viewer; last DOC_FORMAT; };
+ ($dummy[-1] =~ /pdf/) && do { $viewer=$pdf_viewer; last DOC_FORMAT; };
+ ($dummy[-1] =~ /txt/ || $dummy[-1] =~ /faq$/) && do {
+ $viewer=($txt_viewer eq "TDK_OWN" ||
+ $txt_viewer =~ /xterm/) ?
+ $txt_viewer : "${CmdConsole} $txt_viewer";
+ last DOC_FORMAT;
+ };
+ ($dummy[-1] =~ /README/i || $dummy[-2] =~ /\/README$/i) && do {
+ $viewer=($txt_viewer eq "TDK_OWN" ||
+ $txt_viewer =~ /xterm/) ?
+ $txt_viewer : "${CmdConsole} $txt_viewer";
+ last DOC_FORMAT;
+ };
+ ($dummy[-1] =~ /htm/) && do {
+ $viewer=$html_viewer;
+ if ($html_viewer =~ /netscape/i) { # check if Netscape is open
+ my $lockfile="${HomeEnv}/.netscape/lock";
+ $browser=1 if (-e $lockfile || -l $lockfile);
+ } elsif ($html_viewer =~ /mozilla/i) { # check if Mozilla is open
+ my $mozcheck=
+ `mozilla -remote 'openFile($texmfmain/doc/index.html)'`;
+ $browser=1 unless ($?);
+ }
+ last DOC_FORMAT;
+ };
+# some packages have no normal documentation but useful info in the .sty
+ ($dummy[-1] =~ /sty$/) && do {
+ $viewer=($txt_viewer eq "TDK_OWN" ||
+ $txt_viewer =~ /xterm/) ?
+ $txt_viewer : "${CmdConsole} $txt_viewer";
+ $slc="../tex/$slc"; # .sty files are in ${tex,local}docpath/../tex/
+ $styflag=1;
+ last DOC_FORMAT;
+ };
+ $parframe->configure(-cursor=>$defcursor);
+ if ($xfmt_viewer != 1) {
+ &popmsg(2,"$dummy[-1]: not a known document format",$parframe);
+ return;
+ }
+ };
+ if ($viewer eq "") {
+ if ($xfmt_viewer == 1) {
+ &popmsg(-1,'Unknown format; assuming plain text.',$parframe);
+ $viewer=($txt_viewer eq "TDK_OWN" ||
+ $txt_viewer =~ /xterm/) ?
+ $txt_viewer : "${CmdConsole} $txt_viewer";
+ } else {
+ &popmsg(2,"$dummy[-1]: no viewer available/specified for this format",
+ $parframe);
+ $parframe->configure(-cursor=>$defcursor);
+ return;
+ }
+ }
+# build complete path and start viewer if file exists
+ my $slcdoc;
+ $slcdoc=&finddoc($slcdoc,$slc,$parframe);
+ if ($slcdoc ne "") {
+# change to doc directory in case there are pictures
+ my $docpath=substr($slcdoc,0,(rindex($slcdoc,'/',(length $slcdoc))));
+ chomp $slcdoc;
+ chdir ($docpath);
+# try to get doc out of .sty file
+ if ($styflag) {
+ &popmsg(-1,'Trying to extract documentation out of .sty file;
+might be cluttered with program comments.',
+ $parframe);
+ $slcdoc=&stripsty($slcdoc,substr($slc,7));
+ }
+# for text files use built-in text viewer if set
+ if ($IsWin32) {
+ if ($viewer eq "TDK_OWN") {
+ &ShellExecute('open', $slcdoc);
+ $parframe->configure(-cursor=>$defcursor);
+ return;
+ }
+ else {
+ system("$viewer $slcdoc");
+ }
+ }
+ else {
+ if ($viewer eq "TDK_OWN") {
+ &textview($slcdoc);
+ $parframe->configure(-cursor=>$defcursor);
+ return;
+ }
+ if ($quiet == 0) { # show messages
+ if ($browser == 0) { # normal viewers or new Netscape/Mozilla
+ system("$viewer $slcdoc &");
+ } else { # open doc in existing Netscape/Mozilla window
+ system("$viewer -remote 'openFile($slcdoc)' &");
+ &popmsg(-1,"Opening document in existing $viewer window.",
+ $parframe);
+ }
+ } else { # viewer messages written to /dev/null instead of terminal
+ if ($browser == 0) { # normal viewers or new Netscape/Mozilla
+ system("perl -we 'use strict; \
+my \$dump=\"\"; \
+open(NULL,\">/dev/null\"); \
+open (VIEWQ,\"$viewer $slcdoc |\"); \
+while (\$dump=<VIEWQ>) { print NULL \$dump; } \
+close(VIEWQ); \
+close(NULL);' &");
+ } else { # open doc in existing window (Netscape or Mozilla)
+ # not quiet; I didn't get an inline perl call like in
+ # the other branch working
+ system("$viewer -remote 'openFile($slcdoc)' &");
+ &popmsg(-1,"Opening document in existing $viewer window.",
+ $parframe);
+ }
+ }
+ }
+ }
+ $parframe->configure(-cursor=>$defcursor);
+}
+
+# Tk widget for text document
+sub textview {
+ my($txtfile)=@_;
+# see if toplevel window with this file is already there
+ if (Exists($tlwins{$txtfile}{'addr'})) {
+ $tlwins{$txtfile}{'addr'}->deiconify();
+ $tlwins{$txtfile}{'addr'}->raise();
+ return;
+ }
+ my $tfv_tk=$main->Toplevel(-title=>"Text file viewer");
+ $tfv_tk->resizable(0,1);
+ $tlwins{$txtfile}{'addr'}=$tfv_tk;
+ $tfv_tk->Label(-text=>"File: $txtfile",
+ -font=>$deffont,
+ -relief=>'ridge',
+ -borderwidth=>3)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>10,
+ -anchor=>'s');
+ my $txtbody=$tfv_tk->Scrolled("Text",
+ -relief=>'flat',
+ -font=>$deffont,
+ -height=>20,
+ -width=>80,
+ -scrollbars=>"e")->pack(-side=>'top',
+ -fill=>'y',
+ -expand=>1);
+ open(TXTFILE,"$txtfile");
+ while (<TXTFILE>) { $txtbody->insert('end',$_); }
+ close(TXTFILE);
+ $txtbody->configure(-state=>'disabled');
+ $tlwins{$txtfile}{'buttons'}[0]=
+ $tfv_tk->Button(-text=>'Close',
+ -font=>$deffont,%butcol,
+ -command=>sub{ destroy $tfv_tk;
+ undef $tlwins{$txtfile};
+ })->pack(-side=>'bottom',
+ -fill=>'x');
+ $tfv_tk->bind('<Control-c>'=>sub{destroy $tfv_tk;
+ undef $tlwins{$txtfile};
+ });
+}
+
+# print document selected in listbox
+sub prtslc {
+ my($slc,$parframe)=@_;
+ $tmpfno=&randname;
+ my $pstmpfile="${TempDir}/texdoc_$tmpfno.ps";
+ push @tmpfiles,$pstmpfile;
+ my $status;
+ chomp $slc;
+ unless (defined $slc) {
+ &popmsg(2,"No selection was made.",$parframe);
+ return;
+ }
+ if ($print_cmd eq "") {
+ &popmsg(2,"No printer specified.",$parframe);
+ return;
+ }
+# build complete path and check existence of file
+ my @dummy=split('\.',$slc);
+ if ($dummy[-1] =~ /sty$/) {
+ $slc="../tex/$slc"; # .sty files are in ${tex,local,home}docpath/../tex
+ }
+ my $slcdoc;
+ $slcdoc=&finddoc($slcdoc,$slc,$parframe);
+ return if ($slcdoc eq "");
+# change to doc directory in case there are pictures
+ my $docpath=substr($slcdoc,0,(rindex($slcdoc,'/',(length $slcdoc))));
+ chdir ($docpath);
+ DOC_FORMAT: { # determine document type
+# convert dvi files to ps before printing
+ ($dummy[-1] =~ /dvi/) && do {
+ if ($dvips_conv eq "") {
+ &popmsg(2,"No converter available for dvi->ps conversion.",
+ $parframe);
+ return;
+ }
+ &popmsg(-1,"Converting dvi to ps for printing and sending file to print...",$parframe);
+ $status=system("$dvips_conv $slcdoc -o $pstmpfile");
+ if ($status != 0) {
+ &popmsg(2,"Error: Conversion dvi->ps failed!",$parframe);
+ }
+ last DOC_FORMAT;
+ };
+# PostScript is printed directly
+ ($dummy[-1] =~ /ps/) && do {
+ &popmsg(-1,"Sending file to $print_cmd...",$parframe);
+ $pstmpfile=$slcdoc;
+ last DOC_FORMAT;
+ };
+# convert pdf files to ps before printing
+ ($dummy[-1] =~ /pdf/) && do {
+ if ($pdfps_conv eq "") {
+ &popmsg(2,"No converter available for pdf->ps conversion.",
+ $parframe);
+ return;
+ }
+ &popmsg(-1,"Converting pdf to ps for printing and sending file to print...",$parframe);
+ system("$pdfps_conv $slcdoc $pstmpfile");
+ last DOC_FORMAT;
+ };
+# convert html files to ps before printing
+ ($dummy[-1] =~ /htm/) && do {
+ if ($htmlps_conv eq "") {
+ &popmsg(2,"No converter available for html->ps conversion.",
+ $parframe);
+ return;
+ }
+ &popmsg(-1,"Converting html to ps for printing and sending file to print...",$parframe);
+ my $htmlps_redir_sign=($htmlps_redir == 1) ? ">" :"";
+ system("$htmlps_conv $slcdoc $htmlps_redir_sign $pstmpfile");
+ last DOC_FORMAT;
+ };
+# convert txt files to ps before printing
+ ($dummy[-1] =~ /txt/ || $dummy[-1] =~ /faq$/
+ || $dummy[-1] =~ /README/i) && do {
+ if ($txtps_conv eq "") {
+ &popmsg(2,"No converter available for txt->ps conversion.",
+ $parframe);
+ return;
+ }
+ &popmsg(-1,"Converting txt to ps for printing and sending file to print...",$parframe);
+ my $txtps_redir_sign=($txtps_redir == 1) ? ">" :"";
+ system("$txtps_conv $slcdoc $txtps_redir_sign $pstmpfile");
+ last DOC_FORMAT;
+ };
+# convert extracted comments from sty files to ps before printing
+ ($dummy[-1] =~ /sty$/) && do {
+ if ($txtps_conv eq "") {
+ &popmsg(2,"No converter available for sty(txt)->ps conversion.",
+ $parframe);
+ return;
+ }
+ &popmsg(-1,"Converting sty(txt) to ps for printing and sending file to print...",$parframe);
+# try to get doc out of .sty file
+ &popmsg(-1,'Trying to extract documentation out of .sty file;
+might be cluttered with program comments.',
+ $parframe);
+ $slcdoc=&stripsty($slcdoc,substr($slc,7));
+ my $txtps_redir_sign=($txtps_redir == 1) ? ">" :"";
+ system("$txtps_conv $slcdoc $txtps_redir_sign $pstmpfile");
+ last DOC_FORMAT;
+ };
+ &popmsg(2,"$dummy[-1]: cannot print document format",$parframe);
+ return;
+ };
+ system("$print_cmd $pstmpfile");
+}
+
+# test existence and search a documentation which is not in specified place
+sub finddoc {
+ my($slcdoc,$slc,$parframe)=@_;
+ my ($dummy,$status);
+ SLCDOCFIND: foreach ($texdocpath,$distdocpath,$docdocpath) {
+ $slcdoc="$_/$slc";
+ if (-e $slcdoc) {
+# found where it should be
+ return $slcdoc;
+ } else {
+# see if the documentation file is in the local doc tree...
+ my @srchslcdoc=($slcdoc);
+ if ($localdocpath) {
+ push @srchslcdoc,"$localdocpath/$slc";
+ return $srchslcdoc[-1] if (-e $srchslcdoc[-1]);
+ }
+# ... or the user's doc tree...
+ if ($homedocpath) {
+ push @srchslcdoc,"$homedocpath/$slc";
+ return $srchslcdoc[-1] if (-e $srchslcdoc[-1]);
+ }
+# ... otherwise proceed with searching
+ $status=-1;
+# see if the documentation file is compressed
+ CMPREND: foreach my $cmprtype ("gz","bz2","zip") {
+ foreach (@srchslcdoc) {
+ $dummy="$_.$cmprtype";
+ if (-e $dummy) { # yes, it is compressed
+ $tmpfno=&randname;
+ my $rawname=basename($slc,"");
+ $slcdoc="${TempDir}/texdoc_$tmpfno$rawname";
+ push @tmpfiles,$slcdoc;
+ my ($dcmp,$dcmp_opt);
+ COMPRESS: { # determine compression type
+ ($cmprtype eq "gz") && do {
+ $dcmp="gzip";
+ $dcmp_opt="-cd";
+ last COMPRESS;
+ };
+ ($cmprtype eq "bz2") && do {
+ $dcmp="bzip2";
+ $dcmp_opt="-cd";
+ last COMPRESS;
+ };
+ ($cmprtype eq "zip") && do {
+ $dcmp="zip";
+ $dcmp_opt="-p";
+ last COMPRESS;
+ };
+ };
+# try to decompress
+ $status=system("$dcmp $dcmp_opt $dummy > $slcdoc");
+ if ($status != 0) { # failure
+ &popmsg(2,
+ "$dcmp: Couldn't decompress file, cancelling.",
+ $parframe);
+ $slcdoc="";
+ return $slcdoc;
+ }
+# last CMPREND; does not work, what we need is:
+ return $slcdoc;
+ }
+ }
+ }
+ }
+ }
+ if ($status != 0) {
+ $parframe->configure(-cursor=>'watch');
+# try to find it elsewhere with kpsewhich
+ my $rawname=basename($slc,"");
+ $slcdoc=($slcdoc =~ /\.sty$/) ?
+ `kpsewhich $rawname` :
+ `kpsewhich --format=${qq}TeX system documentation${qq} $rawname`;
+ if ($slcdoc eq "") { # nothing found; cancel
+ &popmsg(2,"$rawname not found, cancelling.",$parframe);
+ $slcdoc="";
+ }
+ $parframe->configure(-cursor=>$defcursor);
+ }
+ return $slcdoc;
+}
+
+# determine existence and show paths of files (Button-3)
+sub showpath {
+ my ($docselect,$tpbframe)=@_;
+ my $found=0;
+ if ($docselect =~ /\.sty$/) {
+ STYPATH: foreach my $fullpath ("$texmfmain/tex/$docselect",
+ "$texmfdist/tex/$docselect",
+ "$texmflocal/tex/$docselect",
+ "$texmfhome/tex/$docselect") {
+ if (-e $fullpath) {
+ &popmsg(0,"Selected file:\n$fullpath",$tpbframe);
+ $found=1;
+ last STYPATH;
+ }
+ }
+ if (!$found) {
+ &popmsg(2,"Selected file:\n$docselect\ndoes not exist.",$tpbframe) }
+ } else {
+ DOCPATH: foreach my $fullpath ("$texdocpath/$docselect",
+ "$distdocpath/$docselect",
+ "$docdocpath/$docselect",
+ "$localdocpath/$docselect",
+ "$homedocpath/$docselect") {
+ foreach ('','.gz','.bz2','.zip') {
+ my $fullpathext="$fullpath$_";
+ if (-e $fullpathext) {
+ &popmsg(0,"Selected file:\n$fullpathext",$tpbframe);
+ $found=1;
+ last DOCPATH;
+ }
+ }
+ }
+ if (!$found) {
+ &popmsg(2,"Selected file:\n$docselect\ndoes not exist (neither in normal form nor compressed).",$tpbframe) }
+ }
+}
+
+# make or destroy search entry widget
+sub mksrch {
+ my ($type) = @_;
+ if ($srchflag == 1) {
+ if ($type == $srchtype) {
+ destroy $srchentry;
+ $srchflag=0;
+ } else {
+ $srchtype = $type;
+ }
+ } else {
+ $srchtype = $type;
+# get the search string
+ $srchentry=$cmdframe->Entry(-cursor=>'xterm',
+ -font=>$deffont,
+ -width=>20,
+ -takefocus=>1)->pack(-side=>'left');
+ $srchentry->focus();
+ $srchentry->bind('<Return>'=>[\&srchstr, $srchentry]);
+ $srchflag=1;
+# key binding
+ $srchentry->bind('<Control-c>'=>sub{destroy $srchentry; $srchflag=0;});
+ $srchentry->bind('<Escape>'=>sub{destroy $srchentry; $srchflag=0;});
+ }
+}
+
+# call search routine and display results
+sub srchstr {
+ my $string;
+ my @reslist;
+ $string=$srchentry->get();
+# search
+ $main->Busy(-recurse => 1);
+ if ($srchtype == 0) {
+ @reslist = &srchdb($string);
+ } else {
+ @reslist = &srchtd($string);
+ }
+ $main->Unbusy();
+# destroy entry widget and show results
+ destroy $srchentry;
+ $srchflag=0;
+ if (scalar @reslist == 0) {
+ &popmsg(0, ($srchtype == 0 ? 'Database' : 'File').
+ " search for $string: no matches found.\n".
+ "You may want to try a ".
+ ($srchtype == 0 ? 'File' : 'Databse') . " search.\n\n".
+ "If nothing else works, CTAN offers an online search form:\n".
+ "http://ctan.org/search.html\n",
+ $cmdframe);
+ } else {
+ &tpslct(-1, $string, @reslist);
+ }
+}
+
+# search using texdoc
+sub srchtd {
+ my ($string) = @_;
+ my @res;
+ my $tdout = `texdoc -M -l $string`;
+ if ($?) {
+ &popmsg(0,"texdoc failed, sorry: $!\n".
+ "Please report this problem on the texlive mailing list.\n");
+ return;
+ } else {
+ my $i = 0;
+ for my $line (split /\n/, $tdout) {
+ my @fields = split /\t/, $line;
+ $doc[$ncat][$i] = $fields[2];
+ $topic[$ncat][$i] = basename($fields[2]);
+ $packname[$ncat][$i] = "no package name";
+ push @res, ($ncat, $i++);
+ }
+ return @res;
+ }
+}
+
+# search a string in @packname, @topic and @keywords
+sub srchdb {
+ my ($string) = @_;
+ my (@results, @reslist);
+ if ($string) {
+ for ($i=0; $i<$ncat; ++$i) {
+ for ($j=0; $j<$maxind[$i]+1; ++$j) {
+ SRCH: {
+ ($topic[$i][$j] =~ /$string/i) && do {
+ push @results,($i,$j);
+ last SRCH;
+ };
+ (defined $keywords[$i][$j]) && do {
+ if ($keywords[$i][$j] =~ /$string/i) {
+ push @results,($i,$j);
+ last SRCH;
+ }
+ };
+ ($packname[$i][$j] =~ /$string/i) && do {
+ push @results,($i,$j);
+ last SRCH;
+ };
+ };
+ }
+ }
+ } else { # return full database
+ $string='all database entries';
+ for ($i=0; $i<$ncat; ++$i) {
+ for ($j=0; $j<$maxind[$i]+1; ++$j) { push @results,($i,$j); }
+ }
+ }
+ unless (scalar @results == 0) {
+# cancel multiple entries
+ my ($omit,$pack1,$pack2);
+ @reslist=($results[0],$results[1]);
+ for ($i=0; $i<$#results; $i+=2) {
+ $omit=0;
+ $pack1=$packname[$results[$i]][$results[$i+1]];
+ for ($j=0; $j<$#reslist; $j+=2) {
+ $pack2=$packname[$reslist[$j]][$reslist[$j+1]];
+ if ($pack1 eq $pack2) { $omit=1; last; }
+ }
+ if ($omit == 0) { push @reslist,($results[$i],$results[$i+1]); }
+ }
+ }
+ return @reslist;
+}
+
+# extract documentation of .sty files; a flag in the @keywords array shows
+# where the doc is located:
+# -0-: no specific place; -1-: at end, behind \endinput; -2-: at beginning,
+# terminated by %%%%%%; -3-: at beginning, terminated with blank line
+sub stripsty {
+ my ($slcdoc,$slc)=@_;
+ my @stydoc;
+ $tmpfno=&randname;
+ my $tmpslcdoc="${TempDir}/texdoc_$tmpfno.txt";
+ push @tmpfiles,$tmpslcdoc;
+ open (STY,"$slcdoc");
+ LOC: {
+ ($stydoc{$slc} == 0) && do { # no specific place, suck in everything :-(
+ while ($line = <STY>) { push @stydoc,$line if ($line =~ /^%/); }
+ last LOC;
+ };
+ ($stydoc{$slc} == 1) && do { # at end, behind \endinput
+ while ($line = <STY>) {
+ last if ($line =~ /^\s*\\endinput/ && !($line =~ /^%/));
+ }
+ while ($line = <STY>) { push @stydoc,$line; }
+ last LOC;
+ };
+ ($stydoc{$slc} == 2) && do { # up to a certain %%%%%%%, hopefully the 1st
+ for (my $i=0; $i<9; ++$i) { $stydoc[$i]=<STY>; } # after the 8th line
+ while ($line = <STY>) {
+ last if ($line =~ /^%{4,}/);
+ push @stydoc,$line;
+ }
+ last LOC;
+ };
+ ($stydoc{$slc} == 3) && do { # up to 1st blank/apparently empty line
+ while ($line = <STY>) {
+ last if ($line =~ /^\s*$/);
+ push @stydoc,$line;
+ }
+ last LOC;
+ };
+ };
+ close(STY);
+ open(TMPSTY,">$tmpslcdoc");
+ foreach (@stydoc) { print TMPSTY $_; }
+ close(TMPSTY);
+ return $tmpslcdoc;
+}
+
+# pop up a note or an error or warning message toplevel window
+sub popmsg {
+ my($level,$msg,$parframe)=@_;
+ my $degree;
+ LEVEL: {
+ ($level == -1) && do { $degree="Info"; last LEVEL; };
+ ($level == 0) && do { $degree="Note"; last LEVEL; };
+ ($level == 1) && do {
+ return if ($quiet == 1);
+ $degree="Warning";
+ last LEVEL
+ };
+ ($level == 2) && do { $degree="Error"; last LEVEL; };
+ };
+ my $msgwin=$parframe->Toplevel(-title=>$degree);
+ my $lbl=$msgwin->Label(-text=>uc($degree),
+ -font=>$deffont)->pack(-side=>'top', -fill=>'x');
+# get size of message text
+ my @dummy=split("\n",$msg);
+ my $nline=scalar @dummy;
+ my $msgwidth=0;
+ my $lline;
+ foreach (@dummy) {
+ $lline=length $_;
+ if ($lline > $msgwidth) { $msgwidth=$lline; }
+ }
+ my $message=$msgwin->Text(-relief=>'flat',
+ -font=>$deffont,
+ -height=>$nline,
+ -width=>$msgwidth)->pack(-side=>'top');
+ $message->insert('end',$msg);
+ $message->configure(-state=>'disabled');
+ if ($level < 0) { # transient message window
+ $msgwin->after(3000,sub{destroy $msgwin});
+ } else { # persistent message window
+ $msgwin->Button(-text=>'Close',
+ -font=>$deffont,%butcol,
+ -command=>sub{destroy $msgwin})->pack(-side=>'bottom',
+ -fill=>'x');
+ $msgwin->bind('<Control-c>'=>sub{destroy $msgwin});
+ }
+}
+
+# show/change settings (don't show this to an expert :-/ )
+sub settings {
+ my ($homedocpath_tmp,$quiet_tmp,$autoview_tmp,$xfmt_viewer_tmp,
+ $dvi_viewer_tmp,$dvips_conv_tmp,
+ $ps_viewer_tmp,$pdf_viewer_tmp,$pdfps_conv_tmp,
+ $html_viewer_tmp,$htmlps_conv_tmp,$htmlps_redir_tmp,
+ $txt_viewer_tmp,$txtps_conv_tmp,$txtps_redir_tmp,$print_cmd_tmp)=
+ ($homedocpath,$quiet,$autoview,$xfmt_viewer,
+ $dvi_viewer,$dvips_conv,$ps_viewer,
+ $pdf_viewer,$pdfps_conv,$html_viewer,
+ $htmlps_conv,$htmlps_redir,$txt_viewer,
+ $txtps_conv,$txtps_redir,$print_cmd);
+ my @tdcolors_tmp=@tdcolors;
+# see if toplevel window is already there
+ if (Exists($tlwins{"setmenu"}{'addr'})) {
+ $tlwins{"setmenu"}{'addr'}->deiconify();
+ $tlwins{"setmenu"}{'addr'}->raise();
+ return;
+ }
+ my $setmenu=$main->Toplevel(-title=>'Settings');
+ $setmenu->resizable(0,0);
+ $tlwins{"setmenu"}{'addr'}=$setmenu;
+# documentation path
+ my $datlabel;
+ $datlabel="Database file(s) used: teTeX";
+ $datlabel.=", local database" if (-e $locdatabase);
+ $datlabel.=", user database" if (-e $homedatabase);
+ my $docframe=$setmenu->Frame(-relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -expand=>1);
+ my $docframestring="\nDistribution documentation root path(s):\n$texdocpath";
+ $docframestring.=", $distdocpath" if (-e $distdocpath);
+ $docframestring.=", $docdocpath" if (length $docdocpath);
+ if ($localdocpath && $localdocpath ne $texdocpath) {
+ $docframestring.="\nLocal documentation root path: $localdocpath\n";
+ }
+ $docframe->Label(-text=>"$docframestring",
+ -font=>$deffont)->pack(-side=>'top',
+ -anchor=>'w',
+ -fill=>'x',
+ -expand=>1);
+ if (defined $texmfhome && -d $texmfhome) {
+ $homedocpath_tmp=basename($homedocpath_tmp,"");
+ my $usrdocframe=$docframe->Frame(-relief=>'flat')->pack(-side=>'top',
+ -fill=>'x');
+ my $usrdoclabel=$usrdocframe->Label(-text=>"User's documentation root path: $texmfhome/",
+ -font=>$deffont)->pack(-side=>'left');
+ my $usrdocentry=$usrdocframe->Entry(-textvariable=>\$homedocpath_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+ }
+ $docframe->Label(-text=>"$datlabel.",
+ -font=>$deffont)->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>2,
+ -fill=>'x',
+ -expand=>1);
+# General viewer behaviour
+ my $genvframe=$setmenu->Frame(-label=>'General viewer behaviour',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>6,
+ -expand=>1);
+ my $genvframe1=$genvframe->Frame()->pack(-side=>'left');
+ my $genvsub1=$genvframe1->Frame()->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>3);
+ my $genvecbut=$genvsub1->
+ Checkbutton(-variable=>\$quiet_tmp)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $genvelabel=$genvsub1->Label(-text=>'Suppress error messages',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $genvsub2=$genvframe1->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $genvscbut=$genvsub2->
+ Checkbutton(-variable=>\$autoview_tmp)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $genvslabel=$genvsub2->Label(-text=>'Autostart viewer for one-item listboxes',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $genvsub3=$genvframe1->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $genvxcbut=$genvsub3->
+ Checkbutton(-variable=>\$xfmt_viewer_tmp)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $genvxlabel=$genvsub3->Label(-text=>'Use text viewer for unknown file format',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+# colours of GUI
+ my @tdcolors_d=@tdcolors_tmp;
+ $tlwins{'setmenu'}{'buttons'}[0]=
+ $genvframe->Button(-text=>'Change viewer colours',
+ -command=>sub {
+ @tdcolors_tmp=&popcolor($setmenu,@tdcolors_tmp);
+ @tdcolors_d=@tdcolors_tmp;
+ },
+ -font=>$deffont,%butcol)->pack(-side=>'right');
+# DVI
+ my $dviframe=$setmenu->Frame(-label=>'DVI',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>6,
+ -expand=>1);
+ my $dvisub1=$dviframe->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $dvisub2=$dviframe->Frame()->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>6);
+ my $dvivlabel=$dvisub1->Label(-text=>'Viewer command',
+ -anchor=>'w',
+ -font=>$deffont)->pack(-side=>'left');
+ my $dviventry=$dvisub1->Entry(-textvariable=>\$dvi_viewer_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+ my $dviclabel=$dvisub2->Label(-text=>'DVI->PS converter command',
+ -anchor=>'w',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $dvilbwidth=length 'DVI->PS converter command';
+ $dvivlabel->configure(-width=>1.1*$dvilbwidth);
+ $dviclabel->configure(-width=>1.1*$dvilbwidth);
+ my $dvicentry=$dvisub2->Entry(-textvariable=>\$dvips_conv_tmp,
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+# PostScript
+ my $psframe=$setmenu->Frame(-label=>'PostScript',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>10,
+ -expand=>1);
+ my $psvlabel=$psframe->Label(-text=>'Viewer command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'w');
+ my $psventry=$psframe->Entry(-textvariable=>\$ps_viewer_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+# PDF
+ my $pdfframe=$setmenu->Frame(-label=>'PDF',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>6,
+ -expand=>1);
+ my $pdfsub1=$pdfframe->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $pdfsub2=$pdfframe->Frame()->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>6);
+ my $pdfvlabel=$pdfsub1->Label(-text=>'Viewer command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'w');
+ my $pdfventry=$pdfsub1->Entry(-textvariable=>\$pdf_viewer_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+ my $pdfclabel=$pdfsub2->Label(-text=>'PDF->PS converter command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $pdfcentry=$pdfsub2->Entry(-textvariable=>\$pdfps_conv_tmp,
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+# HTML
+ my $htmlframe=$setmenu->Frame(-label=>'HTML',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>6,
+ -expand=>1);
+ my $htmlsub1=$htmlframe->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $htmlsub2=$htmlframe->Frame()->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>6);
+ my $htmlvlabel=$htmlsub1->Label(-text=>'Viewer command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'w');
+ my $htmlventry=$htmlsub1->Entry(-textvariable=>\$html_viewer_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+ my $htmlclabel=$htmlsub2->Label(-text=>'HTML->PS converter command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $htmlcentry=$htmlsub2->Entry(-textvariable=>\$htmlps_conv_tmp,
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $htmlrlabel=$htmlsub2->Label(-text=>'Output redirect needed',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $htmlrcbut=$htmlsub2->
+ Checkbutton(-variable=>\$htmlps_redir_tmp)->pack(-side=>'left',
+ -anchor=>'sw');
+# plain text
+ my $txtframe=$setmenu->Frame(-label=>'Plain text',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>6,
+ -expand=>1);
+ my $txtsub1=$txtframe->Frame()->pack(-side=>'top',
+ -anchor=>'w');
+ my $txtsub2=$txtframe->Frame()->pack(-side=>'top',
+ -anchor=>'w',
+ -ipady=>6);
+ my $txtvlabel=$txtsub1->Label(-text=>'Viewer command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'w');
+ my $txtventry=$txtsub1->Entry(-textvariable=>\$txt_viewer_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+ my $txt_view_flag;
+ if ($txt_viewer_tmp eq "TDK_OWN") {
+ $txt_view_flag=1;
+ $txtventry->configure(-state=>'disabled');
+ } else {
+ $txt_view_flag=0;
+ $txtventry->configure(-state=>'normal');
+ }
+ my $txtvilabel=$txtsub1->Label(-text=>"\tUse texdoctk\'s own viewer",
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $txtvcbut=$txtsub1->
+ Checkbutton(-variable=>\$txt_view_flag,
+ -command=>sub {
+ if ($txt_view_flag == 1) {
+ $txt_viewer_tmp="TDK_OWN";
+ $txtventry->configure(-state=>'disabled');
+ } else {
+ $txt_viewer_tmp=$txt_viewer;
+ $txtventry->configure(-state=>'normal');
+ $txtventry->focus();
+ }
+ })->pack(-side=>'left',
+ -anchor=>'sw');
+ my $txtclabel=$txtsub2->Label(-text=>'Text->PS converter command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $txtcentry=$txtsub2->Entry(-textvariable=>\$txtps_conv_tmp,
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $txtrlabel=$txtsub2->Label(-text=>'Output redirect needed',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'sw');
+ my $txtrcbut=$txtsub2->
+ Checkbutton(-variable=>\$txtps_redir_tmp)->pack(-side=>'left',
+ -anchor=>'sw');
+# printer
+ my $prtframe=$setmenu->Frame(-label=>'Printer',
+ -relief=>'groove',
+ -borderwidth=>2)->pack(-side=>'top',
+ -fill=>'x',
+ -ipady=>10,
+ -expand=>1);
+ my $prtclabel=$prtframe->Label(-text=>'Command',
+ -font=>$deffont)->pack(-side=>'left',
+ -anchor=>'w');
+ my $prtcentry=$prtframe->Entry(-textvariable=>\$print_cmd_tmp,
+ -font=>$deffont)->pack(-side=>'left');
+# buttons and key bindings
+ my $setbfr=$setmenu->Frame()->pack(-side=>'bottom');
+ $tlwins{'setmenu'}{'buttons'}[1]=
+ $setbfr->Button(-text=>'OK',
+ -font=>$deffont,%butcol,
+ -command=>sub{
+ $homedocpath="$texmfhome/$homedocpath_tmp";
+ ($quiet,$autoview,$xfmt_viewer,
+ $dvi_viewer,$dvips_conv,
+ $ps_viewer,$pdf_viewer,
+ $pdfps_conv,$html_viewer,
+ $htmlps_conv,$htmlps_redir,
+ $txt_viewer,$txtps_conv,$txtps_redir,$print_cmd)=
+ ($quiet_tmp,$autoview_tmp,$xfmt_viewer_tmp,
+ $dvi_viewer_tmp,$dvips_conv_tmp,
+ $ps_viewer_tmp,
+ $pdf_viewer_tmp,$pdfps_conv_tmp,
+ $html_viewer_tmp,
+ $htmlps_conv_tmp,$htmlps_redir_tmp,
+ $txt_viewer_tmp,$txtps_conv_tmp,
+ $txtps_redir_tmp,$print_cmd_tmp);
+ @tdcolors=@tdcolors_tmp;
+ %butcol=('-background'=>$tdcolors[0],
+ '-foreground'=>$tdcolors[1],
+ '-activebackground'=>$tdcolors[2],
+ '-activeforeground'=>$tdcolors[3]);
+ foreach my $tlkey (keys %tlwins) {
+ foreach (@{$tlwins{$tlkey}{'buttons'}}) {
+ $_->configure(%butcol);
+ }
+ }
+ if ($txt_viewer eq "" &&
+ defined $ENV{PAGER}) {
+ $txt_viewer=$ENV{PAGER};
+ }
+ destroy $setmenu},
+ -width=>6)->pack(-side=>'left',
+ -padx=>10,
+ -pady=>10);
+ $tlwins{'setmenu'}{'buttons'}[2]=
+ $setbfr->Button(-text=>'Save',
+ -font=>$deffont,%butcol,
+ -command=>sub{
+ $setmenu->configure(-cursor=>'watch');
+ &popmsg(-1,"Writing settings to $myrc",$setmenu);
+ my $tdcolors_tmp=join(' ',@tdcolors_tmp);
+ &writerc($homedocpath_tmp,
+ $quiet_tmp,$autoview_tmp,$xfmt_viewer_tmp,
+ $tdcolors_tmp,
+ $dvi_viewer_tmp,$dvips_conv_tmp,
+ $ps_viewer_tmp,
+ $pdf_viewer_tmp,$pdfps_conv_tmp,
+ $html_viewer_tmp,
+ $htmlps_conv_tmp,$htmlps_redir_tmp,
+ $txt_viewer_tmp,$txtps_conv_tmp,
+ $txtps_redir_tmp,$print_cmd_tmp,$setmenu);
+ $setmenu->configure(-cursor=>$defcursor);
+ })->pack(-side=>'left',
+ -padx=>10);
+ $tlwins{'setmenu'}{'buttons'}[3]=
+ $setbfr->Button(-text=>'Cancel',
+ -font=>$deffont,%butcol,
+ -command=>sub{destroy $setmenu;
+ undef $tlwins{"setmenu"};
+ })->pack(-side=>'left',
+ -padx=>10);
+ $setmenu->bind('<Control-c>'=>sub{destroy $setmenu;
+ undef $tlwins{"setmenu"};});
+}
+
+# dialog toplevel for color settings
+sub popcolor {
+ my ($parframe,@entryvar)=@_;
+# see if toplevel window is already there
+ if (Exists($tlwins{'chngcol'}{'addr'})) {
+ $tlwins{'chngcol'}{'addr'}->deiconify();
+ $tlwins{'chngcol'}{'addr'}->raise();
+ return;
+ }
+ my $dlgwin=$parframe->Toplevel(-title=>'Change colours');
+ $dlgwin->resizable(0,0);
+ $tlwins{'chngcol'}{'addr'}=$dlgwin;
+# entry widgets for default/active back/foreground
+ $dlgwin->Label(-text=>'Enter colours as names or RGB #xxxxxx values',
+ -font=>$deffont)->pack(-side=>'top');
+ my $dlgdef=$dlgwin->Frame()->pack(-side=>'top');
+ my $dlgact=$dlgwin->Frame()->pack(-side=>'top');
+ my $dlgdef1=$dlgdef->Frame()->pack(-side=>'left');
+ my $dlgtfr0=$dlgdef1->Frame()->pack(-side=>'top');
+ my $dlgtfr1=$dlgdef1->Frame()->pack(-side=>'top');
+ my $dlgact1=$dlgact->Frame()->pack(-side=>'left');
+ my $dlgtfr2=$dlgact1->Frame()->pack(-side=>'top');
+ my $dlgtfr3=$dlgact1->Frame()->pack(-side=>'top');
+ $dlgtfr0->Label(-text=>"Default background",
+ -anchor=>'w',
+ -width=>18,
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr0->Entry(-textvariable=>\$entryvar[0],
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr1->Label(-text=>"Default foreground",
+ -anchor=>'w',
+ -width=>18,
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr1->Entry(-textvariable=>\$entryvar[1],
+ -font=>$deffont)->pack(-side=>'left');
+ my $deflabel=$dlgdef->Label(-text=>'Default',
+ -relief=>'ridge',
+ -width=>10,
+ -height=>2)->pack(-side=>'right',
+ -padx=>7);
+ $dlgtfr2->Label(-text=>"Active background",
+ -anchor=>'w',
+ -width=>18,
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr2->Entry(-textvariable=>\$entryvar[2],
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr3->Label(-text=>"Active foreground",
+ -anchor=>'w',
+ -width=>18,
+ -font=>$deffont)->pack(-side=>'left');
+ $dlgtfr3->Entry(-textvariable=>\$entryvar[3],
+ -font=>$deffont)->pack(-side=>'left');
+ my $actlabel=$dlgact->Label(-text=>'Active',
+ -background=>$entryvar[2],
+ -foreground=>$entryvar[3],
+ -relief=>'ridge',
+ -width=>10,
+ -height=>2)->pack(-side=>'right',
+ -padx=>7);
+# buttons
+ my $setbfr=$dlgwin->Frame()->pack(-side=>'bottom');
+ my $chngflag=0;
+ $tlwins{'chngcol'}{'buttons'}[0]=
+ $setbfr->Button(-text=>'OK',
+ -font=>$deffont,%butcol,
+ -command=>sub {
+ foreach (@entryvar) { # RGB form with leading #
+ $_="#$_" if (/^[A-Fa-f0-9]{6}$/);
+ }
+ $chngflag=1 if (&colcheck($dlgwin,@entryvar));
+ },
+ -width=>6)->pack(-side=>'left',
+ -padx=>5,
+ -pady=>10);
+ $tlwins{'chngcol'}{'buttons'}[1]=
+ $setbfr->Button(-text=>'Preview',
+ -font=>$deffont,%butcol,
+ -command=>sub {
+ foreach (@entryvar) { # RGB form with leading #
+ $_="#$_" if (/^[A-Fa-f0-9]{6}$/);
+ }
+ if (&colcheck($dlgwin,@entryvar)) {
+ $deflabel->
+ configure(-background=>$entryvar[0],
+ -foreground=>$entryvar[1]);
+ $actlabel->
+ configure(-background=>$entryvar[2],
+ -foreground=>$entryvar[3]);
+ }
+ },
+ -width=>6)->pack(-side=>'left',
+ -padx=>5,
+ -pady=>10);
+ $tlwins{'chngcol'}{'buttons'}[2]=
+ $setbfr->Button(-text=>'Cancel',
+ -font=>$deffont,%butcol,
+ -command=>sub{destroy $dlgwin;
+ undef $tlwins{'chngcol'};
+ })->pack(-side=>'right',
+ -padx=>5,
+ -pady=>10);
+ $dlgwin->bind('<Control-c>'=>sub{destroy $dlgwin;
+ undef $tlwins{'chngcol'}; });
+ $dlgwin->waitVariable(\$chngflag);
+ destroy $dlgwin;
+ undef $tlwins{'chngcol'};
+ return @entryvar;
+}
+
+# check colours set in popcolor; relies on the existence of X11's showrgb
+sub colcheck {
+ my ($dlgwin,@entryvar)=@_;
+ my $ecnt=0;
+ foreach (@entryvar) { # all colours defined?
+ last unless ($_);
+ ++$ecnt;
+ }
+ &popmsg(2,'Some colours undefined.',$dlgwin) if ($ecnt != 4);
+ my $defcol=0;
+ if (`which showrgb`) { # test for proper name
+ my @rgb=`showrgb`;
+ my @norgb;
+ foreach my $colour (@entryvar) {
+ if ($colour =~ /^#[A-Fa-f0-9]{6}$/ || grep /\b$colour\b/i,@rgb) {
+ ++$defcol;
+ } else {
+ push @norgb,$colour;
+ }
+ }
+ if ($defcol != 4) {
+ my $norgb=join("\n",@norgb);
+ &popmsg(2,"Some colours invalid:\n$norgb",$dlgwin);
+ }
+ } else { $defcol=4; }
+ return ($ecnt == 4 && $defcol == 4) ? 1 : 0;
+}
+
+# write user's ~/.texdocrc
+sub writerc {
+ use File::Copy qw/cp mv/;
+ my ($homedocpath_tmp,$quiet_tmp,$autoview_tmp,$xfmt_viewer_tmp,
+ $tdcolors_tmp,
+ $dvi_viewer_tmp,$dvips_conv_tmp,
+ $ps_viewer_tmp,
+ $pdf_viewer_tmp,$pdfps_conv_tmp,
+ $html_viewer_tmp,
+ $htmlps_conv_tmp,$htmlps_redir_tmp,
+ $txt_viewer_tmp,$txtps_conv_tmp,
+ $txtps_redir_tmp,$print_cmd_tmp,$parframe)=@_;
+ my $err=0;
+ mv $myrc,"$myrc.save" if (-e $myrc);
+ open(MYRC,">$myrc");
+ print MYRC "# user's .texdocrc, generated by program\n
+# root of user's doc directory (from \$HOMETEXMF)
+# can be left empty if \$TEXMFHOME is undefined
+HOMEDOCPATH=$homedocpath_tmp
+# general viewer behaviour (y or yes to make active)
+QUIET=$quiet_tmp
+AUTOVIEW=$autoview_tmp
+XFMT_VIEWER=$xfmt_viewer_tmp
+# button colours: default and active back-/foreground
+# names and RGB values are both allowed; use the form #xxxxxx for RGB
+TDCOLORS=$tdcolors_tmp
+# the following variables contain whole commands, i.e. options can be given
+# DVI settings
+DVI_VIEWER=$dvi_viewer_tmp
+DVIPS_CONV=$dvips_conv_tmp
+# PostScript handling
+PS_VIEWER=$ps_viewer_tmp
+# PDF handling
+PDF_VIEWER=$pdf_viewer_tmp
+PDFPS_CONV=$pdfps_conv_tmp
+# HTML handling
+HTML_VIEWER=$html_viewer_tmp
+HTMLPS_CONV=$htmlps_conv_tmp
+# HTMLPS_REDIR must be on, if the html->ps converter normally writes its output
+# to stdout instead of a file (e.g. as html2ps) (y or yes to make active)
+HTMLPS_REDIR=$htmlps_redir_tmp
+# Plain text handling
+# TDK_OWN is texdoctk's own text file viewer
+TXT_VIEWER=$txt_viewer_tmp
+TXTPS_CONV=$txtps_conv_tmp
+# TXTPS_REDIR must be on, if the txt->ps converter normally writes its output
+# to stdout instead of a file (e.g. as a2ps) (y or yes to make active)
+TXTPS_REDIR=$txtps_redir_tmp
+# printer
+PRINT_CMD=$print_cmd_tmp
+\n# end of config\n";
+ close(MYRC);
+}
+
+# help window (toplevel)
+sub helptext {
+# see if toplevel window is already there
+ if (Exists($tlwins{"helptext"}{'addr'})) {
+ $tlwins{"helptext"}{'addr'}->deiconify();
+ $tlwins{"helptext"}{'addr'}->raise();
+ return;
+ }
+ my $help=$main->Toplevel(-title=>'Help/About');
+ $help->resizable(0,1);
+ $tlwins{'helptext'}{'addr'}=$help;
+ $help->Label(-text=>"texdoctk
+TeX documentation browser
+v$version ($date)",
+ -font=>$deffont)->pack(-side=>'top',
+ -ipady=>10,
+ -anchor=>'s');
+ my $helpbody=$help->Scrolled("Text",
+ -relief=>'flat',
+ -font=>$deffont,
+ -height=>20,
+ -width=>60,
+ -scrollbars=>"e")->pack(-side=>'top',
+ -fill=>'y',
+ -expand=>1);
+ my $pos=tell DATA;
+ while (<DATA>) {
+ $_ =~ s/\$sysrc/$sysrc/;
+ last if (/^#/);
+ $helpbody->insert('end',$_);
+ }
+ seek(DATA,$pos,0);
+ $helpbody->configure(-state=>'disabled');
+ $tlwins{'helptext'}{'buttons'}[0]=
+ $help->Button(-text=>'Close',
+ -font=>$deffont,%butcol,
+ -command=>sub{destroy $help;
+ undef $tlwins{"helptext"};
+ })->pack(-side=>'bottom',
+ -fill=>'x');
+ $help->bind('<Control-c>'=>sub{destroy $help; undef $tlwins{"helptext"};});
+}
+
+# read config file; personal settings override the default settings
+sub readrc {
+ my($rcfile,$icall)=@_;
+ my ($var,$val);
+ my $pathflag=0;
+ my $pathflagl=0;
+ my $pathflagh=0;
+ my $tdcolors='';
+# for backward compatibility of converter/printer options
+ my ($dvips_opts,$pdfps_opts,$print_opts);
+# read defaults resp. local/personal settings
+ CALL: {
+ ($icall == 1) && do {
+ open (RC,"$rcfile") ||
+ &fatalmsg("Couldn't open system-wide default config file ${TeXDocRcDefaults}.\n");
+ last CALL;
+ };
+ ($icall == 2) && do {
+ open (RC,"$rcfile") ||
+ &fatalmsg("Couldn't open personal config file ~/.texdocrc.\n");
+ last CALL;
+ };
+ };
+ while ($line = <RC>) {
+ next if ($line =~ /^($|#)/);
+ chomp $line;
+ ($var,$val)=split("=",$line,2);
+ RCVARS: {
+ ($var =~ /texdocpath/i) && do { # TEXDOCPATH
+ if (length $val > 0) {
+ $pathflag=1;
+ eval(join("",("\$",lc($var),"=\$val")));
+ }
+ last RCVARS;
+ };
+ ($var =~ /localdocpath/i) && do { # LOCALDOCPATH
+ if (length $val > 0) {
+ $pathflagl=1;
+ eval(join("",("\$",lc($var),"=\$val")));
+ }
+ last RCVARS;
+ };
+ ($var =~ /homedocpath/i) && do { # HOMEDOCPATH
+ if ($icall == 2 && length $val > 0) { # set only in ~/.texdocrc
+ $pathflagh=1;
+ eval(join("",("\$",lc($var),"=\$val")));
+ }
+ last RCVARS;
+ };
+ # other variables
+ eval(join("",("\$",lc($var),"=\$val")));
+ };
+ }
+ close(RC);
+# find texmf/doc, and possibly other distribution texmf trees
+ if ($rcfile eq $sysrc || $pathflag == 1) {
+ $texmfmain=`kpsewhich --expand-path=${qq}\$TEXMFMAIN${qq}`;
+ chomp $texmfmain;
+ $texdocpath="$texmfmain/$texdocpath";
+ $texmfdist=`kpsewhich --expand-path=${qq}\$TEXMFDIST${qq}`;
+ chomp $texmfdist;
+ $distdocpath=join('/',"$texmfdist",basename($texdocpath,""))
+ if (length $texmfdist);
+ # TeXLive has this texmf-doc
+ $texmfdoc=join('/',"$texmfmain-doc",basename($texdocpath,""));
+ if (-e $texmfdoc) {
+ chomp $texmfdoc;
+ $docdocpath="$texmfdoc/$docdocpath";
+ }
+ }
+# find texmf-local/doc, if there is one
+ if ($rcfile eq $sysrc || $pathflagl == 1) {
+ $texmflocal=`kpsewhich --expand-path=${qq}\$TEXMFLOCAL${qq}`;
+ chomp $texmflocal;
+ if (length $texmflocal) {
+ # if LOCALDOCPATH is not explicitly defined, it equals TEXDOCPATH
+ unless (defined $localdocpath) {
+ $localdocpath=basename($texdocpath,"");
+ }
+ $localdocpath="$texmflocal/$localdocpath";
+ }
+ }
+# find user's $HOMETEXMF/doc, if there is one
+ if ($icall == 2 || $pathflagh == 1) {
+ $texmfhome=`kpsewhich --expand-path=${qq}\$HOMETEXMF${qq}`;
+ chomp $texmfhome;
+ if (length $texmfhome) {
+ # if HOMEDOCPATH is not explicitly defined, it equals TEXDOCPATH
+ unless (defined $homedocpath) {
+ $homedocpath=basename($texdocpath,"");
+ }
+ $homedocpath="$texmfhome/$homedocpath";
+ }
+ }
+# colours: create array
+ @tdcolors=split(' ',$tdcolors);
+ if (scalar @tdcolors != 4) { # if old texdocrc file is used
+ if (!(-e $myrc) || (-e $myrc && $icall == 2)) {
+ print "NOTE: Button colours not set in $rcfile; using defaults.\n";
+ @tdcolors=('#d9d9d9','Black','#ececec','red');
+ }
+ }
+ %butcol=('-background'=>$tdcolors[0],
+ '-foreground'=>$tdcolors[1],
+ '-activebackground'=>$tdcolors[2],
+ '-activeforeground'=>$tdcolors[3]);
+# viewer: suppress viewer warnings/use $PAGER if no $txt_viewer is defined
+ $quiet=($quiet =~ /y/i || $quiet eq "1") ? 1 : 0;
+ if (!(defined $txt_viewer) && defined $ENV{PAGER}) {
+ $txt_viewer=$ENV{PAGER};
+ }
+# viewer: autostart viewer if listbox of search results contains only 1 item
+ $autoview=($autoview =~ /y/i || $autoview eq "1") ? 1 : 0;
+# viewer: use text viewer to open files with unrecognized format
+ $xfmt_viewer=($xfmt_viewer =~ /y/i || $xfmt_viewer eq "1") ? 1 : 0;
+# converter: output redirection flags for HTML/Text->PS converters
+ $htmlps_redir=($htmlps_redir =~ /(y|1)/i) ? 1 : 0;
+ $txtps_redir=($txtps_redir =~ /(y|1)/i) ? 1 : 0;
+# for backward compatibility of converter/printer options
+ $dvips_conv.=" $dvips_opts" if ($dvips_opts);
+ $pdfps_conv.=" $pdfps_opts" if ($pdfps_opts);
+ $print_cmd.=" $print_opts" if ($print_opts);
+}
+
+# determine resolution if xwininfo is available
+# slightly modified from a patch contributed by Reinhard Kotucha
+sub x_resolution {
+ my $x_res;
+ if ($IsWin32) {
+ $x_res = &GetScreenWidth;
+ }
+ else {
+ open(XINF,"xwininfo -root|") or return 1200;
+ while (<XINF>) {
+ chop;
+ if (/Width:/) { ($x_res=$_)=/Width:\s+(\d+)/; last; }
+ }
+ close(XINF);
+ }
+ return $x_res;
+}
+
+# generate a random name for temporary files
+sub randname {
+ my $namestr;
+ my @chars=("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");
+ my $time=time;
+ my $maxcnt=3+substr($time,-1);
+ for (my $i=0; $i<=$maxcnt; $i++) { $namestr.=$chars[rand(51)] }
+ my @tmp=split(/./,$time/$$);
+ $namestr.=$tmp[1];
+ until (length($namestr) > 16) { $namestr.=int(rand(1000000)) }
+ return $namestr;
+}
+
+# find index of an array entry
+sub arrindex {
+ my @array=@_;
+ my $item=pop @array;
+ my $i=0;
+ foreach (@array) {
+ last if ($_ eq $item);
+ ++$i;
+ }
+ return $i;
+}
+
+# clean up and exit
+sub clean_exit {
+ foreach (@tmpfiles) { if (-e $_) { unlink $_; } }
+ exit;
+}
+
+# alternative main window, launched for fatal error messages on startup
+sub fatalmsg {
+ my($msg)=@_;
+ print STDERR $msg; # also print to stderr
+# create frame for main window
+ my $main=new MainWindow;
+ $main->resizable(0,0);
+ $main->title("TeX Documentation Browser");
+ $main->bind('<Control-q>'=>sub { exit });
+ $main->bind('<Control-k>'=>sub { exit });
+ my $msgframe=$main->Frame(-background=>"#ffcc99");
+ my $cmdframe=$main->Frame;
+ $msgframe->pack(-side=>'top');
+ $cmdframe->pack(-side=>'bottom',-fill=>'x');
+# make buttons for command frame
+ my $Qbut=$cmdframe->Button(-text=>'Kill',%butcol,
+ -command=>sub { exit })->pack(-fill=>'x');
+# define common default font for labels and text explicitly
+ my @deffont=$Qbut->configure(-font);
+# ensure readability on high-res screens (suggested by R.Kotucha)
+ $deffont='Helvetica -16 bold' if &x_resolution > 1200;
+ $Qbut->configure(-font=>$deffont);
+ $msgframe->Label(-text=>'FATAL ERROR',
+ -font=>$deffont)->pack(-side=>'top', -fill=>'x');
+# get size of message text
+ my @dummy=split("\n",$msg);
+ my $nline=scalar @dummy;
+ my $msgwidth=0;
+ my $lline;
+ foreach (@dummy) {
+ $lline=length $_;
+ if ($lline > $msgwidth) { $msgwidth=$lline; }
+ }
+ my $message=$msgframe->Text(-relief=>'flat',
+ -font=>$deffont,
+ -height=>$nline,
+ -width=>$msgwidth)->pack(-side=>'top');
+ $message->insert('end',$msg);
+ $message->configure(-state=>'disabled');
+ MainLoop;
+}
+
+if ($IsWin32) {
+ sub GetScreenWidth {
+ my $GetDeviceCaps = new Win32::API('gdi32', 'GetDeviceCaps', 'NN', 'N');
+ my $HORZRES = 8; # from WinGDI.h
+ if(not defined $GetDeviceCaps) {
+ die "Can't import API GetDeviceCaps: $!\n";
+ }
+ return $GetDeviceCaps->Call(0, $HORZRES);
+ }
+
+ sub GetTempPath {
+ my $GetTempPath = new Win32::API('kernel32', 'GetTempPath', 'NP', 'N');
+ if(not defined $GetTempPath) {
+ die "Can't import API GetTempPath: $!\n";
+ }
+ my $lpBuffer = " " x 260;
+
+ $GetTempPath->Call(80, $lpBuffer);
+ }
+
+ sub ShellExecute {
+ my ($command, $file) = @_;
+ my $ShellExecute = new Win32::API('shell32', 'ShellExecute', 'NPPPPN', 'N');
+ if(not defined $ShellExecute) {
+ die "Can't import API ShellExecute: $!\n";
+ }
+ $ShellExecute->Call(0, $command, $file, '', '', 0);
+ }
+
+ sub GetHomeDir {
+ my $home = $ENV{'HOME'};
+ # Should check for CSIDL_...
+ return $home;
+ }
+}
+__END__
+Many TeX programmers provide more or less detailed manuals for
+their programs or packages. They are usually available as .dvi,
+.ps, .pdf, .html or plain text files (sometimes included in the
+.sty files instead of a separate documentation file) and can be
+accessed with this browser, which is simply an interface to find a
+documentation more easily. It starts the respective viewer for
+reading the selected documentation making use of a database file
+which contains the path entries according to the current teTeX
+texmf/doc structure; additional usage of a system-wide local and
+of individual user texmf trees with corresponding databases is also
+possible.
+The documentations are grouped in several categories shown in the
+main window; pressing one of its buttons lists all documentations
+belonging to this topic.
+The topic window lets you select one documentation file, view or
+send it to the default printer. By right-clicking on the selected
+item you get the complete path of the file.
+The search button of the main window allows you to search the
+database for a string; it does not search file names. Enter the
+string and hit <Return> to start the search or <Control-c> to
+cancel. Just hitting <Return> without typing something in will
+show the full list of files in the database.
+Defaults for the documentation root directory, the viewers, the
+converters, certain options and the printer are set in the global
+configuration file $sysrc.
+However, each user can put a copy of it as .texdocrc into his home
+directory to modify them according to his needs; modification or
+generation of ~/.texdocrc can also be done with the Settings menu.
+Additionally, the settings can be changed temporarily with this
+menu.
+
+The following key shortcuts are defined for use with the browser:
+ <Ctrl-q> Quit browser
+ <Ctrl-m> Raise the Main window to the foreground
+ <Ctrl-s> Search a keyword in database (case insensitive)
+ <Ctrl-c> Cancel/close subwindow or search entry widget
+ <Ctrl-v> View selected document (topic windows)
+ <Ctrl-p> Print selected document (topic windows)
+ <Ctrl-t> Open settings menu
+ <Ctrl-k> Kill fatal error message window (same as
+ <Ctrl-q>)
+ <Ctrl-h> Open this help
+ <Return> Equivalent to button press;
+ OK in selection menu and search
+ <Tab> Next/previous widget
+
+There are the following command line options:
+ -a autostart viewer if a listbox of search results
+ contains only one item; can also be set in a
+ configuration file
+ -v disable suppression of viewer messages sent to
+ stderr and of certain permanent message popup
+ windows, in case this was not set in a
+ configuration file; default: off
+
+Some more information is available in the manpage of texdoctk.
+
+Comments and suggestions to:
+Thomas Ruedas
+tr@dlc.ku.dk or tex-k@tug.org
+# Local Variables:
+# mode: perl
+# auto-fill-hook: do-auto-fill
+# End:
+# vim: ts=8 sw=4 noexpandtab