From 7f2f4b7e145540ab700daaa58912be883f23e46a Mon Sep 17 00:00:00 2001 From: janw Date: Tue, 6 Jun 2006 13:50:14 +0000 Subject: [PATCH] Need to use a patched version of latex2html. Included this in contrib and change gen_online_help script to make use of this. Added ogroups online help. git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@3661 594d385d-05f5-0310-b6e9-bd551577e9d8 --- contrib/latex2html | 17413 ++++++++++++++++ doc/guide/user/de/html/applications/WARNINGS | 3 +- .../de/html/applications/applications.css | 18 +- .../de/html/applications/applications.html | 11 +- .../user/de/html/applications/index.html | 11 +- .../user/de/html/applications/node1.html | 36 +- .../user/de/html/applications/node2.html | 9 +- .../user/de/html/applications/node3.html | 29 +- .../user/de/html/applications/node4.html | 8 +- .../user/de/html/applications/node5.html | 8 +- .../user/de/html/applications/node6.html | 11 +- .../user/de/html/applications/node7.html | 4 +- .../user/de/html/applications/node8.html | 10 +- doc/guide/user/de/html/departments/WARNINGS | 2 - .../user/de/html/departments/departments.css | 8 +- .../user/de/html/departments/departments.html | 11 +- doc/guide/user/de/html/departments/index.html | 11 +- .../user/de/html/departments/list_back.png | Bin 0 -> 862 bytes doc/guide/user/de/html/departments/node1.html | 41 +- doc/guide/user/de/html/departments/node2.html | 4 +- doc/guide/user/de/html/departments/node3.html | 6 +- doc/guide/user/de/html/departments/node4.html | 4 +- doc/guide/user/de/html/departments/node5.html | 21 +- doc/guide/user/de/html/departments/node6.html | 20 +- doc/guide/user/de/html/departments/node7.html | 8 +- doc/guide/user/de/html/departments/node8.html | 4 +- doc/guide/user/de/html/departments/node9.html | 10 +- doc/guide/user/de/html/groups/WARNINGS | 3 - doc/guide/user/de/html/groups/groups.css | 12 +- doc/guide/user/de/html/groups/groups.html | 11 +- doc/guide/user/de/html/groups/index.html | 11 +- doc/guide/user/de/html/groups/node1.html | 9 +- doc/guide/user/de/html/groups/node10.html | 6 +- doc/guide/user/de/html/groups/node11.html | 6 +- doc/guide/user/de/html/groups/node12.html | 6 +- doc/guide/user/de/html/groups/node13.html | 4 +- doc/guide/user/de/html/groups/node14.html | 8 +- doc/guide/user/de/html/groups/node15.html | 6 +- doc/guide/user/de/html/groups/node16.html | 6 +- doc/guide/user/de/html/groups/node17.html | 6 +- doc/guide/user/de/html/groups/node18.html | 6 +- doc/guide/user/de/html/groups/node19.html | 4 +- doc/guide/user/de/html/groups/node2.html | 4 +- doc/guide/user/de/html/groups/node20.html | 10 +- doc/guide/user/de/html/groups/node3.html | 4 +- doc/guide/user/de/html/groups/node4.html | 8 +- doc/guide/user/de/html/groups/node5.html | 14 +- doc/guide/user/de/html/groups/node6.html | 4 +- doc/guide/user/de/html/groups/node7.html | 4 +- doc/guide/user/de/html/groups/node8.html | 6 +- doc/guide/user/de/html/groups/node9.html | 6 +- doc/guide/user/de/html/ogroups/WARNINGS | 4 + doc/guide/user/de/html/ogroups/index.html | 59 + doc/guide/user/de/html/ogroups/labels.pl | 13 + doc/guide/user/de/html/ogroups/list_back.png | Bin 0 -> 862 bytes doc/guide/user/de/html/ogroups/list_home.png | Bin 0 -> 865 bytes .../user/de/html/ogroups/list_new_ogroup.png | Bin 0 -> 754 bytes .../user/de/html/ogroups/list_reload.png | Bin 0 -> 910 bytes doc/guide/user/de/html/ogroups/list_root.png | Bin 0 -> 852 bytes doc/guide/user/de/html/ogroups/node1.html | 179 + doc/guide/user/de/html/ogroups/node2.html | 61 + doc/guide/user/de/html/ogroups/node3.html | 39 + doc/guide/user/de/html/ogroups/node4.html | 51 + doc/guide/user/de/html/ogroups/ogroups.css | 38 + doc/guide/user/de/html/ogroups/ogroups.html | 59 + doc/guide/user/de/html/ogroups/rocket.png | Bin 0 -> 828 bytes doc/guide/user/de/html/ogroups/search.png | Bin 0 -> 1023 bytes doc/guide/user/de/html/systems/WARNINGS | 3 - doc/guide/user/de/html/systems/index.html | 17 +- doc/guide/user/de/html/systems/list_back.png | Bin 0 -> 862 bytes doc/guide/user/de/html/systems/node1.html | 37 +- doc/guide/user/de/html/systems/node10.html | 2 +- doc/guide/user/de/html/systems/node11.html | 12 +- doc/guide/user/de/html/systems/node12.html | 12 +- doc/guide/user/de/html/systems/node13.html | 13 +- doc/guide/user/de/html/systems/node14.html | 9 +- doc/guide/user/de/html/systems/node15.html | 9 +- doc/guide/user/de/html/systems/node16.html | 2 +- doc/guide/user/de/html/systems/node17.html | 13 +- doc/guide/user/de/html/systems/node18.html | 2 +- doc/guide/user/de/html/systems/node19.html | 2 +- doc/guide/user/de/html/systems/node2.html | 2 +- doc/guide/user/de/html/systems/node20.html | 2 +- doc/guide/user/de/html/systems/node21.html | 15 +- doc/guide/user/de/html/systems/node22.html | 13 +- doc/guide/user/de/html/systems/node23.html | 2 +- doc/guide/user/de/html/systems/node24.html | 9 +- doc/guide/user/de/html/systems/node25.html | 2 +- doc/guide/user/de/html/systems/node26.html | 10 +- doc/guide/user/de/html/systems/node27.html | 2 +- doc/guide/user/de/html/systems/node28.html | 27 +- doc/guide/user/de/html/systems/node29.html | 9 +- doc/guide/user/de/html/systems/node3.html | 2 +- doc/guide/user/de/html/systems/node30.html | 2 +- doc/guide/user/de/html/systems/node31.html | 12 +- doc/guide/user/de/html/systems/node32.html | 2 +- doc/guide/user/de/html/systems/node33.html | 18 +- doc/guide/user/de/html/systems/node34.html | 2 +- doc/guide/user/de/html/systems/node35.html | 12 +- doc/guide/user/de/html/systems/node36.html | 16 +- doc/guide/user/de/html/systems/node37.html | 5 +- doc/guide/user/de/html/systems/node38.html | 2 +- doc/guide/user/de/html/systems/node39.html | 13 +- doc/guide/user/de/html/systems/node4.html | 32 +- doc/guide/user/de/html/systems/node40.html | 2 +- doc/guide/user/de/html/systems/node41.html | 2 +- doc/guide/user/de/html/systems/node42.html | 2 +- doc/guide/user/de/html/systems/node43.html | 4 +- doc/guide/user/de/html/systems/node44.html | 4 +- doc/guide/user/de/html/systems/node45.html | 13 +- doc/guide/user/de/html/systems/node46.html | 2 +- doc/guide/user/de/html/systems/node47.html | 9 +- doc/guide/user/de/html/systems/node48.html | 2 +- doc/guide/user/de/html/systems/node49.html | 2 +- doc/guide/user/de/html/systems/node5.html | 9 +- doc/guide/user/de/html/systems/node50.html | 2 +- doc/guide/user/de/html/systems/node51.html | 15 +- doc/guide/user/de/html/systems/node52.html | 9 +- doc/guide/user/de/html/systems/node53.html | 4 +- doc/guide/user/de/html/systems/node54.html | 55 +- doc/guide/user/de/html/systems/node55.html | 19 +- doc/guide/user/de/html/systems/node56.html | 2 +- doc/guide/user/de/html/systems/node57.html | 4 +- doc/guide/user/de/html/systems/node58.html | 2 +- doc/guide/user/de/html/systems/node59.html | 2 +- doc/guide/user/de/html/systems/node6.html | 2 +- doc/guide/user/de/html/systems/node60.html | 15 +- doc/guide/user/de/html/systems/node61.html | 13 +- doc/guide/user/de/html/systems/node62.html | 2 +- doc/guide/user/de/html/systems/node63.html | 9 +- doc/guide/user/de/html/systems/node64.html | 2 +- doc/guide/user/de/html/systems/node65.html | 2 +- doc/guide/user/de/html/systems/node66.html | 15 +- doc/guide/user/de/html/systems/node67.html | 62 +- doc/guide/user/de/html/systems/node68.html | 11 +- doc/guide/user/de/html/systems/node69.html | 2 +- doc/guide/user/de/html/systems/node7.html | 2 +- doc/guide/user/de/html/systems/node70.html | 2 +- doc/guide/user/de/html/systems/node71.html | 15 +- doc/guide/user/de/html/systems/node72.html | 11 +- doc/guide/user/de/html/systems/node73.html | 2 +- doc/guide/user/de/html/systems/node74.html | 6 +- doc/guide/user/de/html/systems/node8.html | 12 +- doc/guide/user/de/html/systems/node9.html | 10 +- doc/guide/user/de/html/systems/systems.css | 80 +- doc/guide/user/de/html/systems/systems.html | 17 +- doc/guide/user/de/html/users/WARNINGS | 3 +- doc/guide/user/de/html/users/index.html | 6 +- doc/guide/user/de/html/users/node1.html | 41 +- doc/guide/user/de/html/users/node10.html | 6 +- doc/guide/user/de/html/users/node11.html | 18 +- doc/guide/user/de/html/users/node12.html | 8 +- doc/guide/user/de/html/users/node13.html | 7 +- doc/guide/user/de/html/users/node14.html | 6 +- doc/guide/user/de/html/users/node15.html | 6 +- doc/guide/user/de/html/users/node16.html | 6 +- doc/guide/user/de/html/users/node17.html | 6 +- doc/guide/user/de/html/users/node18.html | 6 +- doc/guide/user/de/html/users/node19.html | 6 +- doc/guide/user/de/html/users/node2.html | 4 +- doc/guide/user/de/html/users/node20.html | 4 +- doc/guide/user/de/html/users/node21.html | 8 +- doc/guide/user/de/html/users/node22.html | 6 +- doc/guide/user/de/html/users/node23.html | 8 +- doc/guide/user/de/html/users/node24.html | 8 +- doc/guide/user/de/html/users/node25.html | 4 +- doc/guide/user/de/html/users/node26.html | 6 +- doc/guide/user/de/html/users/node27.html | 8 +- doc/guide/user/de/html/users/node28.html | 8 +- doc/guide/user/de/html/users/node29.html | 4 +- doc/guide/user/de/html/users/node3.html | 4 +- doc/guide/user/de/html/users/node30.html | 8 +- doc/guide/user/de/html/users/node31.html | 8 +- doc/guide/user/de/html/users/node32.html | 6 +- doc/guide/user/de/html/users/node33.html | 6 +- doc/guide/user/de/html/users/node34.html | 9 +- doc/guide/user/de/html/users/node35.html | 4 +- doc/guide/user/de/html/users/node36.html | 6 +- doc/guide/user/de/html/users/node37.html | 8 +- doc/guide/user/de/html/users/node38.html | 8 +- doc/guide/user/de/html/users/node39.html | 4 +- doc/guide/user/de/html/users/node4.html | 6 +- doc/guide/user/de/html/users/node40.html | 6 +- doc/guide/user/de/html/users/node41.html | 4 +- doc/guide/user/de/html/users/node42.html | 8 +- doc/guide/user/de/html/users/node43.html | 6 +- doc/guide/user/de/html/users/node44.html | 6 +- doc/guide/user/de/html/users/node45.html | 4 +- doc/guide/user/de/html/users/node46.html | 10 +- doc/guide/user/de/html/users/node5.html | 4 +- doc/guide/user/de/html/users/node6.html | 20 +- doc/guide/user/de/html/users/node7.html | 6 +- doc/guide/user/de/html/users/node8.html | 4 +- doc/guide/user/de/html/users/node9.html | 8 +- doc/guide/user/de/html/users/users.css | 22 +- doc/guide/user/de/html/users/users.html | 6 +- gen_online_help.sh | 2 +- 197 files changed, 18828 insertions(+), 747 deletions(-) create mode 100755 contrib/latex2html create mode 100644 doc/guide/user/de/html/departments/list_back.png create mode 100644 doc/guide/user/de/html/ogroups/WARNINGS create mode 100644 doc/guide/user/de/html/ogroups/index.html create mode 100644 doc/guide/user/de/html/ogroups/labels.pl create mode 100644 doc/guide/user/de/html/ogroups/list_back.png create mode 100644 doc/guide/user/de/html/ogroups/list_home.png create mode 100644 doc/guide/user/de/html/ogroups/list_new_ogroup.png create mode 100644 doc/guide/user/de/html/ogroups/list_reload.png create mode 100644 doc/guide/user/de/html/ogroups/list_root.png create mode 100644 doc/guide/user/de/html/ogroups/node1.html create mode 100644 doc/guide/user/de/html/ogroups/node2.html create mode 100644 doc/guide/user/de/html/ogroups/node3.html create mode 100644 doc/guide/user/de/html/ogroups/node4.html create mode 100644 doc/guide/user/de/html/ogroups/ogroups.css create mode 100644 doc/guide/user/de/html/ogroups/ogroups.html create mode 100644 doc/guide/user/de/html/ogroups/rocket.png create mode 100644 doc/guide/user/de/html/ogroups/search.png create mode 100644 doc/guide/user/de/html/systems/list_back.png diff --git a/contrib/latex2html b/contrib/latex2html new file mode 100755 index 000000000..5b4e3f7f5 --- /dev/null +++ b/contrib/latex2html @@ -0,0 +1,17413 @@ +#! /usr/bin/perl +# +# $Id: latex2html.pin,v 1.71 2004/01/06 23:49:54 RRM Exp $ +# +# Comprises patches and revisions by various authors: +# See Changes, the log file of LaTeX2HTML. +# +# Original Copyright notice: +# +# LaTeX2HTML by Nikos Drakos + +# **************************************************************** +# LaTeX To HTML Translation ************************************** +# **************************************************************** +# LaTeX2HTML is a Perl program that translates LaTeX source +# files into HTML (HyperText Markup Language). For each source +# file given as an argument the translator will create a +# directory containing the corresponding HTML files. +# +# The man page for this program is included at the end of this file +# and can be viewed using "perldoc latex2html" +# +# For more information on this program and some examples of its +# capabilities visit +# +# http://www.latex2html.org/ +# +# or see the accompanying documentation in the docs/ directory +# +# or +# +# http://www-texdev.ics.mq.edu.au/l2h/docs/manual/ +# +# or +# +# http://www.cbl.leeds.ac.uk/nikos/tex2html/doc/latex2html/ +# +# Original code written by Nikos Drakos, July 1993. +# +# Address: Computer Based Learning Unit +# University of Leeds +# Leeds, LS2 9JT +# +# Copyright (c) 1993-95. All rights reserved. +# +# +# Extensively modified by Ross Moore, Herb Swan and others +# +# Address: Mathematics Department +# Macquarie University +# Sydney, Australia, 2109 +# +# Copyright (c) 1996-2001. All rights reserved. +# +# See general license in the LICENSE file. +# +########################################################################## + +use 5.003; # refuse to work with old and buggy perl version +#use strict; +#use diagnostics; + +# include some perl packages; these come with the standard distribution +use Getopt::Long; +use Fcntl; +use AnyDBM_File; + +# The following are global variables that also appear in some modules +use vars qw($LATEX2HTMLDIR $LATEX2HTMLPLATDIR $SCRIPT + %Month %used_icons $inside_tabbing $TABLE_attribs + %mathentities $date_name $outer_math $TABLE__CELLPADDING_rx); + +BEGIN { + # print "scanning for l2hdir\n"; + if($ENV{'LATEX2HTMLDIR'}) { + $LATEX2HTMLDIR = $ENV{'LATEX2HTMLDIR'}; + } else { + $ENV{'LATEX2HTMLDIR'} = $LATEX2HTMLDIR = '/usr/share/latex2html'; + } + + if($ENV{'LATEX2HTMLPLATDIR'}) { + $LATEX2HTMLPLATDIR = $ENV{'LATEX2HTMLPLATDIR'}; + } else { + $LATEX2HTMLPLATDIR = '/usr/share/latex2html'||$LATEX2HTMLDIR; + $ENV{'LATEX2HTMLPLATDIR'} = $LATEX2HTMLPLATDIR; + } + if(-d $LATEX2HTMLPLATDIR) { + push(@INC,$LATEX2HTMLPLATDIR); + } + + if(-d $LATEX2HTMLDIR) { + push(@INC,$LATEX2HTMLDIR); + } else { + die qq{Fatal: Directory "$LATEX2HTMLDIR" does not exist.\n}; + } +} + +use L2hos; # Operating system dependent routines + +# $^W = 1; # turn on warnings + +my $RELEASE = '2002-2-1'; +my ($REVISION) = q$Revision: 1.71 $ =~ /:\s*(\S+)/; + +# The key, which delimts expressions defined in the environment +# depends on the operating system. +$envkey = L2hos->pathd(); + +# $dd is the directory delimiter character +$dd = L2hos->dd(); + +# make sure the $LATEX2HTMLDIR is on the search-path for forked processes +if($ENV{'PERL5LIB'}) { + $ENV{'PERL5LIB'} .= "$envkey$LATEX2HTMLDIR" + unless($ENV{'PERL5LIB'} =~ m|\Q$LATEX2HTMLDIR\E|o); +} else { + $ENV{'PERL5LIB'} = $LATEX2HTMLDIR; +} + +# Local configuration, read at runtime +# Read the $CONFIG_FILE (usually l2hconf.pm ) +if($ENV{'L2HCONFIG'}) { + require $ENV{'L2HCONFIG'} || + die "Fatal (require $ENV{'L2HCONFIG'}): $!"; +} else { + eval 'use l2hconf'; + if($@) { + die "Fatal (use l2hconf): $@\n"; + } +} + +# MRO: Changed this to global value in config/config.pl +# change these whenever you do a patch to this program and then +# name the resulting patch file accordingly +# $TVERSION = "2002-2-1"; +#$TPATCHLEVEL = " beta"; +#$TPATCHLEVEL = " release"; +#$RELDATE = "(March 30, 1999)"; +#$TEX2HTMLV_SHORT = $TVERSION . $TPATCHLEVEL; + +$TEX2HTMLV_SHORT = $RELEASE; +$TEX2HTMLVERSION = "$TEX2HTMLV_SHORT ($REVISION)"; +$TEX2HTMLADDRESS = "http://www.latex2html.org/"; +$AUTHORADDRESS = "http://cbl.leeds.ac.uk/nikos/personal.html"; +#$AUTHORADDRESS2 = "http://www-math.mpce.mq.edu.au/%7Eross/"; +$AUTHORADDRESS2 = "http://www.maths.mq.edu.au/~ross/"; + +# Set $HOME to what the system considers the home directory +$HOME = L2hos->home(); +push(@INC,$HOME); + +# flush stdout with every print -- gives better feedback during +# long computations +$| = 1; + +# set Perl's subscript separator to LaTeX's illegal character. +# (quite defensive but why not) +$; = "\000"; + +# No arguments!! +unless(@ARGV) { + die "Error: No files to process!\n"; +} + +# Image prefix +$IMAGE_PREFIX = '_image'; + +# Partition prefix +$PARTITION_PREFIX = 'part_' unless $PARTITION_PREFIX; + +# Author address +@address_data = &address_data('ISO'); +$ADDRESS = "$address_data[0]\n$address_data[1]"; + +# ensure non-zero defaults +$MAX_SPLIT_DEPTH = 4 unless ($MAX_SPLIT_DEPTH); +$MAX_LINK_DEPTH = 4 unless ($MAX_LINK_DEPTH); +$TOC_DEPTH = 4 unless ($TOC_DEPTH); + +# A global value may already be set in the $CONFIG_FILE +$INIT_FILE_NAME = $ENV{'L2HINIT_NAME'} || '.latex2html-init' + unless $INIT_FILE_NAME; + +# Read the $HOME/$INIT_FILE_NAME if one is found +if (-f "$HOME$dd$INIT_FILE_NAME" && -r _) { + print "Note: Loading $HOME$dd$INIT_FILE_NAME\n"; + require("$HOME$dd$INIT_FILE_NAME"); + $INIT_FILE = "$HOME$dd$INIT_FILE_NAME"; + # _MRO_TODO_: Introduce a version to be checked? + die "Error: You have an out-of-date " . $HOME . + "$dd$INIT_FILE_NAME file.\nPlease update or delete it.\n" + if ($DESTDIR eq '.'); +} + +# Read the $INIT_FILE_NAME file if one is found in current directory +if ( L2hos->Cwd() ne $HOME && -f ".$dd$INIT_FILE_NAME" && -r _) { + print "Note: Loading .$dd$INIT_FILE_NAME\n"; + require(".$dd$INIT_FILE_NAME"); + $INIT_FILE = "$INIT_FILE_NAME"; +} +die "Error: '.' is an incorrect setting for DESTDIR.\n" . + "Please check your $INIT_FILE_NAME file.\n" + if ($DESTDIR eq '.'); + +# User home substitutions +$LATEX2HTMLSTYLES =~ s/~([$dd$dd$envkey]|$)/$HOME$1/go; +# the next line fails utterly on non-UNIX systems +$LATEX2HTMLSTYLES =~ s/~([^$dd$dd$envkey]+)/L2hos->home($1)/geo; + +#absolutise the paths +$LATEX2HTMLSTYLES = join($envkey, + map(L2hos->Make_directory_absolute($_), + split(/$envkey/o, $LATEX2HTMLSTYLES))); + +#HWS: That was the last reference to HOME. Now set HOME to $LATEX2HTMLDIR, +# to enable dvips to see that version of .dvipsrc! But only if we +# have DVIPS_MODE not set - yes - this is a horrible nasty kludge +# MRO: The file has to be updated by configure _MRO_TODO_ + +if ($PK_GENERATION && ! $DVIPS_MODE) { + $ENV{HOME} = $LATEX2HTMLDIR; + delete $ENV{PRINTER}; # Overrides .dvipsrc +} + +# language of the DTD specified in the tag +$ISO_LANGUAGE = 'EN' unless $ISO_LANGUAGE; + +# Save the command line arguments, quote where necessary +$argv = join(' ', map {/[\s#*!\$%]/ ? "'$_'" : $_ } @ARGV); + +# Pre-process the command line for backward compatibility +foreach(@ARGV) { + s/^--?no_/-no/; # replace e.g. no_fork by nofork + # s/^[+](\d+)$/$1/; # remove + in front of integers +} + +# Process command line options +my %opt; +unless(GetOptions(\%opt, # all non-linked options go into %opt + # option linkage (optional) + 'help|h', + 'version|V', + 'split=s', + 'link=s', + 'toc_depth=i', \$TOC_DEPTH, + 'toc_stars!', \$TOC_STARS, + 'short_extn!', \$SHORTEXTN, + 'iso_language=s', \$ISO_LANGUAGE, + 'validate!', \$HTML_VALIDATE, + 'latex!', + 'djgpp!', \$DJGPP, + 'fork!', \$CAN_FORK, + 'external_images!', \$EXTERNAL_IMAGES, + 'ascii_mode!', \$ASCII_MODE, + 'lcase_tags!', \$LOWER_CASE_TAGS, + 'ps_images!', \$PS_IMAGES, + 'font_size=s', \$FONT_SIZE, + 'tex_defs!', \$TEXDEFS, + 'navigation!', + 'top_navigation!', \$TOP_NAVIGATION, + 'bottom_navigation!', \$BOTTOM_NAVIGATION, + 'auto_navigation!', \$AUTO_NAVIGATION, + 'index_in_navigation!', \$INDEX_IN_NAVIGATION, + 'contents_in_navigation!', \$CONTENTS_IN_NAVIGATION, + 'next_page_in_navigation!', \$NEXT_PAGE_IN_NAVIGATION, + 'previous_page_in_navigation!', \$PREVIOUS_PAGE_IN_NAVIGATION, + 'footnode!', + 'numbered_footnotes!', \$NUMBERED_FOOTNOTES, + 'prefix=s', \$PREFIX, + 'auto_prefix!', \$AUTO_PREFIX, + 'long_titles=i', \$LONG_TITLES, + 'custom_titles!', \$CUSTOM_TITLES, + 'title|t=s', \$TITLE, + 'rooted!', \$ROOTED, + 'rootdir=s', + 'dir=s', \$FIXEDDIR, + 'mkdir', \$MKDIR, + 'address=s', \$ADDRESS, + 'noaddress', + 'subdir!', + 'info=s', \$INFO, + 'noinfo', + 'auto_link!', + 'reuse=i', \$REUSE, + 'noreuse', + 'antialias_text!', \$ANTI_ALIAS_TEXT, + 'antialias!', \$ANTI_ALIAS, + 'transparent!', \$TRANSPARENT_FIGURES, + 'white!', \$WHITE_BACKGROUND, + 'discard!', \$DISCARD_PS, + 'image_type=s', \$IMAGE_TYPE, + 'images!', + 'accent_images=s', \$ACCENT_IMAGES, + 'noaccent_images', + 'style=s', \$STYLESHEET, + 'parbox_images!', + 'math!', + 'math_parsing!', + 'latin!', + 'entities!', \$USE_ENTITY_NAMES, + 'local_icons!', \$LOCAL_ICONS, + 'scalable_fonts!', \$SCALABLE_FONTS, + 'images_only!', \$IMAGES_ONLY, + 'show_section_numbers!',\$SHOW_SECTION_NUMBERS, + 'show_init!', \$SHOW_INIT_FILE, + 'init_file=s', \$INIT_FILE, + 'up_url=s', \$EXTERNAL_UP_LINK, + 'up_title=s', \$EXTERNAL_UP_TITLE, + 'down_url=s', \$EXTERNAL_DOWN_LINK, + 'down_title=s', \$EXTERNAL_DOWN_TITLE, + 'prev_url=s', \$EXTERNAL_PREV_LINK, + 'prev_title=s', \$EXTERNAL_PREV_TITLE, + 'index=s', \$EXTERNAL_INDEX, + 'biblio=s', \$EXTERNAL_BIBLIO, + 'contents=s', \$EXTERNAL_CONTENTS, + 'external_file=s', \$EXTERNAL_FILE, + 'short_index!', \$SHORT_INDEX, + 'unsegment!', \$UNSEGMENT, + 'debug!', \$DEBUG, + 'tmp=s', \$TMP, + 'ldump!', \$LATEX_DUMP, + 'timing!', \$TIMING, + 'verbosity=i', \$VERBOSITY, + 'html_version=s', \$HTML_VERSION, + 'strict!', \$STRICT_HTML, + 'xbit!', \$XBIT_HACK, + 'ssi!', \$ALLOW_SSI, + 'php!', \$ALLOW_PHP, + 'test_mode!' # undocumented switch + )) { + &usage(); + exit 1; +} + +# interpret options, check option consistency +if(defined $opt{'split'}) { + if ($opt{'split'} =~ /^(\+?)(\d+)$/) { + $MAX_SPLIT_DEPTH = $2; + if ($1) { $MAX_SPLIT_DEPTH *= -1; $REL_DEPTH = 1; } + } else { + &usage; + die "Error: Unrecognised value for -split: $opt{'split'}\n"; + } +} +if(defined $opt{'link'}) { + if ($opt{'link'} =~ /^(\+?)(\d+)$/) { + $MAX_LINK_DEPTH = $2; + if ($1) { $MAX_LINK_DEPTH *= -1 } + } else { + &usage; + die "Error: Unrecognised value for -link: $opt{'link'}\n"; + } +} +unless ($ISO_LANGUAGE =~ /^[A-Z.]+$/) { + die "Error: Language (-iso_language) must be uppercase and dots only: $ISO_LANGUAGE\n"; +} +if ($HTML_VALIDATE && !$HTML_VALIDATOR) { + die "Error: Need a HTML_VALIDATOR when -validate is specified.\n"; +} +&set_if_false($NOLATEX,$opt{latex}); # negate the option... +if ($ASCII_MODE || $PS_IMAGES) { + $EXTERNAL_IMAGES = 1; +} +if ($FONT_SIZE && $FONT_SIZE !~ /^\d+pt$/) { + die "Error: Font size (-font_size) must end with 'pt': $FONT_SIZE\n" +} +&set_if_false($NO_NAVIGATION,$opt{navigation}); +&set_if_false($NO_FOOTNODE,$opt{footnode}); +if (defined $TITLE && !length($TITLE)) { + die "Error: Empty title (-title).\n"; +} +if ($opt{rootdir}) { + $ROOTED = 1; + $FIXEDDIR = $opt{rootdir}; +} +if ($FIXEDDIR && !-d $FIXEDDIR) { + if ($MKDIR) { + print "\n *** creating directory: $FIXEDDIR "; + die "Failed: $!\n" unless (mkdir($FIXEDDIR, 0755)); + # _TODO_ use File::Path to create a series of directories + } else { + &usage; + die "Error: Specified directory (-rootdir, -dir) does not exist.\n"; + } +} +&set_if_false($NO_SUBDIR, $opt{subdir}); +&set_if_false($NO_AUTO_LINK, $opt{auto_link}); +if ($opt{noreuse}) { + $REUSE = 0; +} +unless(grep(/^\Q$IMAGE_TYPE\E$/o, @IMAGE_TYPES)) { + die <<"EOF"; +Error: No such image type '$IMAGE_TYPE'. + This installation supports (first is default): @IMAGE_TYPES +EOF +} +&set_if_false($NO_IMAGES, $opt{images}); +if ($opt{noaccent_images}) { + $ACCENT_IMAGES = ''; +} +if($opt{noaddress}) { + $ADDRESS = ''; +} +if($opt{noinfo}) { + $INFO = 0; +} +if($ACCENT_IMAGES && $ACCENT_IMAGES !~ /^[a-zA-Z,]+$/) { + die "Error: Single word or comma-list of style words needed for -accent_images, not: $_\n"; +} +&set_if_false($NO_PARBOX_IMAGES, $opt{parbox_images}); +&set_if_false($NO_SIMPLE_MATH, $opt{math}); +if (defined $opt{math_parsing}) { + $NO_MATH_PARSING = !$opt{math_parsing}; + $NO_SIMPLE_MATH = !$opt{math_parsing} unless(defined $opt{math}); +} +&set_if_false($NO_ISOLATIN, $opt{latin}); +if ($INIT_FILE) { + if (-f $INIT_FILE && -r _) { + print "Note: Initialising with file: $INIT_FILE\n" + if ($DEBUG || $VERBOSITY); + require($INIT_FILE); + } else { + die "Error: Could not find file (-init_file): $INIT_FILE\n"; + } +} +foreach($EXTERNAL_UP_LINK, $EXTERNAL_DOWN_LINK, $EXTERNAL_PREV_LINK, + $EXTERNAL_INDEX, $EXTERNAL_BIBLIO, $EXTERNAL_CONTENTS) { + $_ ||= ''; # initialize + s/~/~/g; # protect `~' +} +if($TMP && !(-d $TMP && -w _)) { + die "Error: '$TMP' not usable as temporary directory.\n"; +} +if ($opt{help}) { + L2hos->perldoc($SCRIPT); + exit 0; +} +if ($opt{version}) { + &banner(); + exit 0; +} +if ($opt{test_mode}) { + return; # make /usr/bin/latex2html non-exploitable + $TITLE = 'LaTeX2HTML Test Document'; + $TEXEXPAND = "$PERL /build/buildd/latex2html-2002-2-1-20050114${dd}texexpand"; + $PSTOIMG = "$PERL /build/buildd/latex2html-2002-2-1-20050114${dd}pstoimg"; + $ICONSERVER = L2hos->path2URL("/build/buildd/latex2html-2002-2-1-20050114${dd}icons"); + $TEST_MODE = 1; + $RGBCOLORFILE = "/build/buildd/latex2html-2002-2-1-20050114${dd}styles${dd}rgb.txt"; + $CRAYOLAFILE = "/build/buildd/latex2html-2002-2-1-20050114${dd}styles${dd}crayola.txt"; +} +if($DEBUG) { + # make the OS-dependent functions more chatty, too + $L2hos::Verbose = 1; +} + +undef %opt; # not needed any more + + +$FIXEDDIR = $FIXEDDIR || $DESTDIR || ''; # for backward compatibility + +if ($EXTERNAL_UP_TITLE xor $EXTERNAL_UP_LINK) { + warn "Warning (-up_url, -up_title): Need to specify both a parent URL and a parent title!\n"; + $EXTERNAL_UP_TITLE = $EXTERNAL_UP_LINK = ""; +} + +if ($EXTERNAL_DOWN_TITLE xor $EXTERNAL_DOWN_LINK) { + warn "Warning (-down_url, -down_title): Need to specify both a parent URL and a parent title!\n"; + $EXTERNAL_DOWN_TITLE = $EXTERNAL_DOWN_LINK = ""; +} + +# $NO_NAVIGATION = 1 unless $MAX_SPLIT_DEPTH; # Martin Wilck + +if ($MAX_SPLIT_DEPTH && $MAX_SPLIT_DEPTH < 0) { + $MAX_SPLIT_DEPTH *= -1; $REL_DEPTH = 1; +} +if ($MAX_LINK_DEPTH && $MAX_LINK_DEPTH < 0) { + $MAX_LINK_DEPTH *= -1; $LEAF_LINKS = 1; +} + +$FOOT_FILENAME = 'footnode' unless ($FOOT_FILENAME); +$NO_FOOTNODE = 1 unless ($MAX_SPLIT_DEPTH || $NO_FOOTNODE); +$NO_SPLIT = 1 unless $MAX_SPLIT_DEPTH; # _MRO_TODO_: is this needed at all? +$SEGMENT = $SEGMENTED = 0; +$NO_MATH_MARKUP = 1; + +# specify the filename extension to use with the generated HTML files +if ($SHORTEXTN) { $EXTN = ".htm"; } # for HTML files on CDROM +elsif ($ALLOW_PHP) { $EXTN = ".php"; } # has PHP dynamic includes + # with server-side includes (SSI) : +elsif ($ALLOW_SSI && !$XBIT_HACK) { $EXTN = ".shtml"; } + # ordinary names, valid also for SSI with XBit hack : +else { $EXTN = ".html"; } + +$NODE_NAME = 'node' unless (defined $NODE_NAME); + +# space for temporary files +# different to the $TMPDIR for image-generation +# MRO: No directory should end with $dd! +$TMP_ = "TMP"; + +$TMP_PREFIX = "l2h" unless ($TMP_PREFIX); + +# This can be set to 1 when using a version of dvips that is safe +# from the "dot-in-name" bug. +# _TODO_ this should be determined by configure +$DVIPS_SAFE = 1; + +$CHARSET = $charset || 'iso-8859-1'; + +#################################################################### +# +# If possible, use icons of the same type as generated images +# +if ($IMAGE_TYPE && defined %{"icons_$IMAGE_TYPE"}) { + %icons = %{"icons_$IMAGE_TYPE"}; +} + +#################################################################### +# +# Figure out what options we need to pass to DVIPS and store that in +# the $DVIPSOPT variable. Also, scaling is taken care of at the +# dvips level if PK_GENERATION is set to 1, so adjust SCALE_FACTORs +# accordingly. +# +if ($SCALABLE_FONTS) { + $PK_GENERATION = 0; + $DVIPS_MODE = ''; +} + +if ($PK_GENERATION) { + if ($MATH_SCALE_FACTOR <= 0) { $MATH_SCALE_FACTOR = 2; } + if ($FIGURE_SCALE_FACTOR <= 0) { $FIGURE_SCALE_FACTOR = 2; } + my $saveMSF = $MATH_SCALE_FACTOR; + my $saveFSF = $FIGURE_SCALE_FACTOR; + my $desired_dpi = int($MATH_SCALE_FACTOR*75); + $FIGURE_SCALE_FACTOR = ($METAFONT_DPI / 72) * + ($FIGURE_SCALE_FACTOR / $MATH_SCALE_FACTOR) ; + $MATH_SCALE_FACTOR = $METAFONT_DPI / 72; + $dvi_mag = int(1000 * $desired_dpi / $METAFONT_DPI); + if ($dvi_mag > 1000) { + &write_warnings( + "WARNING: Your SCALE FACTOR is too large for PK_GENERATION.\n" . + " See $CONFIG_FILE for more information.\n"); + } + + # RRM: over-sized scaling, using dvi-magnification + if ($EXTRA_IMAGE_SCALE) { + print "\n *** Images at $EXTRA_IMAGE_SCALE times resolution of displayed size ***\n"; + $desired_dpi = int($EXTRA_IMAGE_SCALE * $desired_dpi+.5); + print " desired_dpi = $desired_dpi METAFONT_DPI = $METAFONT_DPI\n" + if $DEBUG; + $dvi_mag = int(1000 * $desired_dpi / $METAFONT_DPI); + $MATH_SCALE_FACTOR = $saveMSF; + $FIGURE_SCALE_FACTOR = $saveFSF; + } + # no space after "-y", "-D", "-e" --- required by DVIPS under DOS ! + my $mode_switch = "-mode $DVIPS_MODE" if $DVIPS_MODE; + $DVIPSOPT .= " -y$dvi_mag -D$METAFONT_DPI $mode_switch -e5 "; +} else { # no PK_GENERATION +# if ($EXTRA_IMAGE_SCALE) { +# &write_warnings( +# "the \$EXTRA_IMAGE_SCALE feature requires either \$PK_GENERATION=1" +# . " or the '-scalable_fonts' option"); +# $EXTRA_IMAGE_SCALE = ''; +# } + # MRO: shifted to l2hconf + #$DVIPSOPT .= ' -M'; +} # end PK_GENERATION + +# The mapping from numbers to accents. +# These are required to process the \accent command, which is found in +# tables of contents whenever there is an accented character in a +# caption or section title. Processing the \accent command makes +# $encoded_*_number work properly (see &extract_captions) with +# captions that contain accented characters. +# I got the numbers from the plain.tex file, version 3.141. + +# Missing entries should be looked up by a native speaker. +# Have a look at generate_accent_commands and $iso_8859_1_character_map. + +# MEH: added more accent types +# MRO: only uppercase needed! +%accent_type = ( + '18' => 'grave', # \` + '19' => 'acute', # `' + '20' => 'caron', # \v + '21' => 'breve', # \u + '22' => 'macr', # \= + '23' => 'ring', # + '24' => 'cedil', # \c + '94' => 'circ', # \^ + '95' => 'dot', # \. + '7D' => 'dblac', # \H + '7E' => 'tilde', # \~ + '7F' => 'uml', # \" +); + +&driver; + +exit 0; # clean exit, no errors + +############################ Subroutines ################################## + +#check that $TMP is writable, if so create a subdirectory +sub make_tmp_dir { + &close_dbm_database if $DJGPP; # to save file-handles + + # determine a suitable temporary path + # + $TMPDIR = ''; + my @tmp_try = (); + push(@tmp_try, $TMP) if($TMP); + push(@tmp_try, "$DESTDIR$dd$TMP_") if($TMP_); + push(@tmp_try, $DESTDIR) if($DESTDIR); + push(@tmp_try, L2hos->Cwd()); + + my $try; + TempTry: foreach $try (@tmp_try) { + next unless(-d $try && -w _); + my $tmp = "$try$dd$TMP_PREFIX$$"; + if(mkdir($tmp,0755)) { + $TMPDIR=$tmp; + last TempTry; + } else { + warn "Warning: Cannot create temporary directory '$tmp': $!\n"; + } + } + + $dvips_warning = <<"EOF"; + +Warning: There is a '.' in \$TMPDIR, $DVIPS will probably fail. +Set \$TMP to use a /tmp directory, or rename the working directory. +EOF + die ($dvips_warning . "\n\$TMPDIR=$TMPDIR ***\n\n") + if ($TMPDIR =~ /\./ && $DVIPS =~ /dvips/ && !$DVIPS_SAFE); + + &open_dbm_database if $DJGPP; +} + +# MRO: set first parameter to the opposite of the second if second parameter is defined +sub set_if_false { + $_[0] = !$_[1] if(defined $_[1]); +} + +sub check_for_dots { + local($file) = @_; + if ($file =~ /\.[^.]*\./ && !$DVIPS_SAFE) { + die "\n\n\n *** Fatal Error --- but easy to fix ***\n" + . "\nCannot have '.' in file-name prefix, else dvips fails on images" + . "\nChange the name from $file and try again.\n\n"; + } +} + +# Process each file ... +sub driver { + local($FILE, $orig_cwd, %unknown_commands, %dependent, %depends_on + , %styleID, %env_style, $bbl_cnt, $dbg, %numbered_section); + # MRO: $texfilepath has to be global! + local(%styles_loaded); + $orig_cwd = L2hos->Cwd(); + + print "\n *** initialise *** " if ($VERBOSITY > 1); + &initialise; # Initialise some global variables + + print "\n *** check modes *** " if ($VERBOSITY > 1); + &ascii_mode if $ASCII_MODE; # Must come after initialization + &titles_language($TITLES_LANGUAGE); + &make_numbered_footnotes if ($NUMBERED_FOOTNOTES); + $dbg = $DEBUG ? "-debug" : ""; + $dbg .= (($VERBOSITY>2) ? " -verbose" : ""); + + #use the same hashes for all files in a batch + local(%cached_env_img, %id_map, %symbolic_labels, %latex_labels) + if ($FIXEDDIR && $NO_SUBDIR); + + local($MULTIPLE_FILES,$THIS_FILE); + $MULTIPLE_FILES = 1+$#ARGV if $ROOTED; + print "\n *** $MULTIPLE_FILES file".($MULTIPLE_FILES ? 's: ' : ': ') + . join(',',@ARGV) . " *** " if ($VERBOSITY > 1); + + local(%section_info, %toc_section_info, %cite_info, %ref_files); + + foreach $FILE (@ARGV) { + &check_for_dots($FILE) unless $DVIPS_SAFE; + ++$THIS_FILE if $MULTIPLE_FILES; + do { + %section_info = (); + %toc_section_info = (); + %cite_info = (); + %ref_files = (); + } unless $MULTIPLE_FILES; + local($bbl_nr) = 1; + + # The number of reused images and those in images.tex + local($global_page_num) = (0) unless($FIXEDDIR && $NO_SUBDIR); + # The number of images in images.tex + local($new_page_num) = (0); # unless($FIXEDDIR && $NO_SUBDIR); + local($pid, $sections_rx, + , $outermost_level, %latex_body, $latex_body + , %encoded_section_number + , %verbatim, %new_command, %new_environment + , %provide_command, %renew_command, %new_theorem + , $preamble, $aux_preamble, $prelatex, @preamble); + + # must retain these when all files are in the same directory + # else the images.pl and labels.pl files get clobbered + unless ($FIXEDDIR && $NO_SUBDIR) { + print "\nResetting image-cache" if ($#ARGV); + local(%cached_env_img, %id_map, %symbolic_labels, %latex_labels) + } + +## AYS: Allow extension other than .tex and make it optional + ($EXT = $FILE) =~ s/.*\.([^\.]*)$/$1/; + if ( $EXT eq $FILE ) { + $EXT = "tex"; + $FILE =~ s/$/.tex/; + } + + #RRM: allow user-customisation, dependent on file-name + # e.g. add directories to $TEXINPUTS named for the file + # --- idea due to Fred Drake + &custom_driver_hook($FILE) if (defined &custom_driver_hook); + +# JCL(jcl-dir) +# We need absolute paths for TEXINPUTS here, because +# we change the directory + if ($orig_cwd eq $texfilepath) { + &deal_with_texinputs($orig_cwd); + } else { + &deal_with_texinputs($orig_cwd, $texfilepath); + } + + ($texfilepath, $FILE) = &get_full_path($FILE); + $texfilepath = '.' unless($texfilepath); + + die "Cannot read $texfilepath$dd$FILE \n" + unless (-f "$texfilepath$dd$FILE"); + + +# Tell texexpand which files we *don't* want to look at. + $ENV{'TEXE_DONT_INCLUDE'} = $DONT_INCLUDE if $DONT_INCLUDE; +# Tell texexpand which files we *do* want to look at, e.g. +# home-brew style files + $ENV{'TEXE_DO_INCLUDE'} = $DO_INCLUDE if $DO_INCLUDE; + + $FILE =~ s/\.[^\.]*$//; ## AYS + $DESTDIR = ''; # start at empty + if ($FIXEDDIR) { + $DESTDIR = $FIXEDDIR unless ($FIXEDDIR eq '.'); + if (($ROOTED)&&!($texfilepath eq $orig_cwd)) { + $DESTDIR .= $dd . $FILE unless $NO_SUBDIR; + }; + } elsif ($texfilepath eq $orig_cwd) { + $DESTDIR = ($NO_SUBDIR ? '.' : $FILE); + } else { + $DESTDIR = $ROOTED ? '.' : $texfilepath; + $DESTDIR .= $dd . $FILE unless $NO_SUBDIR; + } + $PREFIX = "$FILE-" if $AUTO_PREFIX; + + print "\nOPENING $texfilepath$dd$FILE.$EXT \n"; ## AYS + + next unless (&new_dir($DESTDIR,'')); + # establish absolute path to $DESTDIR + $DESTDIR = L2hos->Make_directory_absolute($DESTDIR); + &make_tmp_dir; + print "\nNote: Working directory is $DESTDIR\n"; + print "Note: Images will be generated in $TMPDIR\n\n"; + +# Need to clean up a bit in case there's garbage left +# from former runs. + if ($DESTDIR) { chdir($DESTDIR) || die "$!\n"; } + if (opendir (TMP,$TMP_)) { + foreach (readdir TMP) { + L2hos->Unlink("TMP_$dd$_") unless (/^\.\.?$/); + } + closedir TMP; + } + &cleanup(1); + unless(-d $TMP_) { + mkdir($TMP_, 0755) || + die "Cannot create directory '$TMP_': $!\n"; + } + chdir($orig_cwd); + +# RRM 14/5/98 moved this to occur earlier +## JCL(jcl-dir) +## We need absolute paths for TEXINPUTS here, because +## we change the directory +# if ($orig_cwd eq $texfilepath) { +# &deal_with_texinputs($orig_cwd); +# } else { +# &deal_with_texinputs($orig_cwd, $texfilepath); +# } + + +# This needs $DESTDIR to have been created ... + print " *** calling `texexpand' ***" if ($VERBOSITY > 1); + local($unseg) = ($UNSEGMENT ? "-unsegment " : ""); + +# does DOS need to check these here ? +# die "File $TEXEXPAND does not exist or is not executable\n" +# unless (-x $TEXEXPAND); + L2hos->syswait("$TEXEXPAND $dbg -auto_exclude $unseg" + . "-save_styles $DESTDIR$dd$TMP_${dd}styles " + . ($TEXINPUTS ? "-texinputs $TEXINPUTS " : '' ) + . (($VERBOSITY >2) ? "-verbose " : '' ) + . "-out $DESTDIR$dd$TMP_$dd$FILE " + . "$texfilepath$dd$FILE.$EXT") + && die " texexpand failed: $!\n"; + print STDOUT "\n *** `texexpand' done ***\n" if ($VERBOSITY > 1); + + chdir($DESTDIR) if $DESTDIR; + $SIG{'INT'} = 'handler'; + + &open_dbm_database; + &initialise_sections; + print STDOUT "\n *** database open ***\n" if ($VERBOSITY > 1); + + if ($IMAGES_ONLY) { + &make_off_line_images; + } else { + &rename_image_files; + &load_style_file_translations; + &make_language_rx; + &make_raw_arg_cmd_rx; +# &make_isolatin1_rx unless ($NO_ISOLATIN); + &translate_titles; + &make_sections_rx; + print "\nReading ..."; + if ($SHORT_FILENAME) { + L2hos->Rename ("$TMP_$dd$FILE" ,"$TMP_$dd$SHORT_FILENAME" ); + &slurp_input_and_partition_and_pre_process( + "$TMP_$dd$SHORT_FILENAME"); + } else { + &slurp_input_and_partition_and_pre_process("$TMP_$dd$FILE"); + } + &add_preamble_head; + # Create a regular expressions + &set_depth_levels; + &make_sections_rx; + &make_order_sensitive_rx; + &add_document_info_page if ($INFO && !(/\\htmlinfo/)); + &add_bbl_and_idx_dummy_commands; + &translate; # Destructive! + } + &style_sheet; + &close_dbm_database; + &cleanup(); + +#JCL: read warnings from file to $warnings + local($warnings) = &get_warnings; + print "\n\n*********** WARNINGS *********** \n$warnings" + if ($warnings || $NO_IMAGES || $IMAGES_ONLY); + &image_cache_message if ($NO_IMAGES || $IMAGES_ONLY); + &image_message if ($warnings =~ /Failed to convert/io); + undef $warnings; + +# JCL - generate directory index entry. +# Yet, a hard link, cause Perl lacks symlink() on some systems. + do { + local($EXTN) = $EXTN; + $EXTN =~ s/_\w+(\.html?)/$1/ if ($frame_main_name); + local($from,$to) = (eval($LINKPOINT),eval($LINKNAME)); + if (length($from) && length($to) && ($from ne $to)) { + #frames may have altered $EXTN + $from =~ s/$frame_main_name(\.html?)/$1/ if ($frame_main_name); + $to =~ s/$frame_main_name(\.html?)/$1/ if ($frame_main_name); + L2hos->Unlink($to); + L2hos->Link($from,$to); + } + } unless ($NO_AUTO_LINK || !($LINKPOINT) || !($LINKNAME)); + + &html_validate if ($HTML_VALIDATE && $HTML_VALIDATOR); + +# Go back to the source directory + chdir($orig_cwd); + $TEST_MODE = $DESTDIR if($TEST_MODE); # save path + $DESTDIR = ''; + $OUT_NODE = 0 unless $FIXEDDIR; + $STYLESHEET = '' if ($STYLESHEET =~ /^\Q$FILE./); + } + print "\nUnknown commands: ". join(" ",keys %unknown_commands) + if %unknown_commands; +###MEH -- math support + print "\nMath commands outside math: " . + join(" ",keys %commands_outside_math) . + "\n Output may look weird or may be faulty!\n" + if %commands_outside_math; + print "\nDone.\n"; + if($TEST_MODE) { + $TEST_MODE =~ s:[$dd$dd]+$::; + print "\nTo view the results, point your browser at:\n", + L2hos->path2URL(L2hos->Make_directory_absolute($TEST_MODE).$dd. + "index$EXTN"),"\n"; + } + $end_time = time; + $total_time = $end_time - $start_time; + print STDOUT join(' ',"Timing:",$total_time,"seconds\n") + if ($TIMING||$DEBUG||($VERBOSITY > 2)); + $_; +} + +sub open_dbm_database { + # These are DBM (unix DataBase Management) arrays which are actually + # stored in external files. They are used for communication between + # the main process and forked child processes; + print STDOUT "\n"; # this mysteriously prevents a core dump ! + + dbmopen(%verb, "$TMP_${dd}verb",0755); +# dbmopen(%verbatim, "$TMP_${dd}verbatim",0755); + dbmopen(%verb_delim, "$TMP_${dd}verb_delim",0755); + dbmopen(%expanded,"$TMP_${dd}expanded",0755); +# Holds max_id, verb_counter, verbatim_counter, eqn_number + dbmopen(%global, "$TMP_${dd}global",0755); +# Hold style sheet information + dbmopen(%env_style, "$TMP_${dd}envstyles",0755); + dbmopen(%txt_style, "$TMP_${dd}txtstyles",0755); + dbmopen(%styleID, "$TMP_${dd}styleIDs",0755); + +# These next two are used during off-line image conversion +# %new_id_map maps image id's to page_numbers of the images in images.tex +# %image_params maps image_ids to conversion parameters for that image + dbmopen(%new_id_map, "$TMP_${dd}ID_MAP",0755); + dbmopen(%img_params, "$TMP_${dd}IMG_PARAMS",0755); + dbmopen(%orig_name_map, "$TMP_${dd}ORIG_MAP",0755); + + $global{'max_id'} = ($global{'max_id'} | 0); + &read_mydb(\%verbatim, "verbatim"); + $global{'verb_counter'} = ($global{'verb_counter'} | 0); + $global{'verbatim_counter'} = ($global{'verbatim_counter'} | 0); + + &read_mydb(\%new_command, "new_command"); + &read_mydb(\%renew_command, "renew_command"); + &read_mydb(\%provide_command, "provide_command"); + &read_mydb(\%new_theorem, "new_theorem"); + &read_mydb(\%new_environment, "new_environment"); + &read_mydb(\%dependent, "dependent"); +# &read_mydb(\%env_style, "env_style"); +# &read_mydb(\%styleID, "styleID"); + # MRO: Why should we use read_mydb instead of catfile? + $preamble = &catfile(&_dbname("preamble"),1) || ''; + $prelatex = &catfile(&_dbname("prelatex"),1) || ''; + $aux_preamble = &catfile(&_dbname("aux_preamble"),1) || ''; + &restore_critical_variables; +} + +sub close_dbm_database { + &save_critical_variables; + dbmclose(%verb); undef %verb; +# dbmclose(%verbatim); undef %verbatim; + dbmclose(%verb_delim); undef %verb_delim; + dbmclose(%expanded); undef %expanded; + dbmclose(%global); undef %global; + dbmclose(%env_style); undef %env_style; + dbmclose(%style_id); undef %style_id; + dbmclose(%new_id_map); undef %new_id_map; + dbmclose(%img_params); undef %img_params; + dbmclose(%orig_name_map); undef %orig_name_map; + dbmclose(%txt_style); undef %txt_style; + dbmclose(%styleID); undef %styleID; +} + +sub clear_images_dbm_database { + # + # %new_id_map will be used by the off-line image conversion process + # + dbmclose(%new_id_map); + dbmclose(%img_params); + dbmclose(%orig_name_map); + undef %new_id_map; + undef %img_params; + undef %orig_name_map; + dbmopen(%new_id_map, "$TMP_${dd}ID_MAP",0755); + dbmopen(%img_params, "$TMP_${dd}IMG_PARAMS",0755); + dbmopen(%orig_name_map, "$TMP_${dd}ORIG_MAP",0755); +} + +sub initialise_sections { + local($key); + foreach $key (keys %numbered_section) { + $global{$key} = $numbered_section{$key}} +} + +sub save_critical_variables { + $global{'math_markup'} = $NO_MATH_MARKUP; + $global{'charset'} = $CHARSET; + $global{'charenc'} = $charset; + $global{'language'} = $default_language; + $global{'isolatin'} = $ISOLATIN_CHARS; + $global{'unicode'} = $UNICODE_CHARS; + if ($UNFINISHED_ENV) { + $global{'unfinished_env'} = $UNFINISHED_ENV; + $global{'replace_end_env'} = $REPLACE_END_ENV; + } + $global{'unfinished_comment'} = $UNFINISHED_COMMENT; + if (@UNMATCHED_OPENING) { + $global{'unmatched'} = join(',',@UNMATCHED_OPENING); + } +} + +sub restore_critical_variables { + $NO_MATH_MARKUP = ($global{'math_markup'}| + (defined $NO_MATH_MARKUP ? $NO_MATH_MARKUP:1)); + $CHARSET = ($global{'charset'}| $CHARSET); + $charset = ($global{'charenc'}| $charset); + $default_language = ($global{'language'}| + (defined $default_language ? $default_language:'english')); + $ISOLATIN_CHARS = ($global{'isolatin'}| + (defined $ISOLATIN_CHARS ? $ISOLATIN_CHARS:0)); + $UNICODE_CHARS = ($global{'unicode'}| + (defined $UNICODE_CHARS ? $UNICODE_CHARS:0)); + if ($global{'unfinished_env'}) { + $UNFINISHED_ENV = $global{'unfinished_env'}; + $REPLACE_END_ENV = $global{'replace_end_env'}; + } + $UNFINISHED_COMMENT = $global{'unfinished_comment'}; + if ($global{'unmatched'}) { + @UNMATCHED_OPENING = split(',',$global{'unmatched'}); + } + + # undef any renewed-commands... + # so the new defs are read from %new_command + local($cmd,$key,$code); + foreach $key (keys %renew_command) { + $cmd = "do_cmd_$key"; + $code = "undef \&$cmd"; eval($code) if (defined &$cmd); + if ($@) { print "\nundef \&do_cmd_$cmd failed"} + } +} + +#JCL: The warnings should have been handled within the DBM database. +# Unfortunately if the contents of an array are more than ~900 (system +# dependent) chars long then dbm cannot handle it and gives error messages. +sub write_warnings { #clean + my ($str) = @_; + $str .= "\n" unless($str =~ /\n$/); + print STDOUT "\n *** Warning: $str" if ($VERBOSITY > 1); + my $warnings = ''; + if(-f 'WARNINGS') { + $warnings = &catfile('WARNINGS') || ''; + } + return () if ($warnings =~ /\Q$str\E/); + if(open(OUT,">>WARNINGS")) { + print OUT $str; + close OUT; + } else { + print "\nError: Cannot append to 'WARNINGS': $!\n"; + } +} + +sub get_warnings { + return &catfile('WARNINGS',1) || ''; +} + +# MRO: Standardizing +sub catfile { + my ($file,$ignore) = @_; + unless(open(CATFILE,"<$file")) { + print "\nError: Cannot read '$file': $!\n" + unless($ignore); + return undef; + } + local($/) = undef; # slurp in whole file + my $contents = ; + close(CATFILE); + $contents; +} + + +sub html_validate { + my ($extn) = $EXTN; + if ($EXTN !~ /^\.html?$/i) { + $extn =~ s/^[^\.]*(\.html?)$/$1/; + } + print "\n *** Validating ***\n"; + my @htmls = glob("*$extn"); + my $file; + foreach $file (@htmls) { + system("$HTML_VALIDATOR $file"); + } +} + +sub lost_argument { + local($cmd) = @_; + &write_warnings("\nincomplete argument to command: \\$cmd"); +} + + +# These subroutines should have been handled within the DBM database. +# Unfortunately if the contents of an array are more than ~900 (system +# dependent) chars long then dbm cannot handle it and gives error messages. +# So here we save and then read the contents explicitly. +sub write_mydb { + my ($db, $key, $str) = @_; + &write_mydb_simple($db, "\n$mydb_mark#$key#$str"); +} + +# generate the DB file name from the DB name +sub _dbname { + "$TMP_$dd$_[0]"; +} + +sub write_mydb_simple { + my ($db, $str) = @_; + my $file = &_dbname($db); + if(open(DB,">>$file")) { + print DB $str; + close DB; + } else { + print "\nError: Cannot append to '$file': $!\n"; + } +} + +sub clear_mydb { + my ($db) = @_; + my $file = &_dbname($db); + if(open(DB,">$file")) { + close DB; + } else { + print "\nError: Cannot clear '$file': $!\n"; + } +} + +# Assumes the existence of a DB file which contains +# sequences of e.g. verbatim counters and verbatim contents. +sub read_mydb { + my ($dbref,$name) = @_; + my $contents = &catfile(&_dbname($name),1); + return '' unless(defined $contents); + my @tmp = split(/\n$mydb_mark#([^#]*)#/, $contents); + my $i = 1; # Ignore the first element at 0 + print "\nDBM: $name open..." if ($VERBOSITY > 2); + while ($i < scalar(@tmp)) { + my $tmp1 = $tmp[$i]; + my $tmp2 = $tmp[++$i]; + $$dbref{$tmp1} = defined $tmp2 ? $tmp2 : ''; + ++$i; + }; + $contents; +} + + +# Reads in a latex generated file (e.g. .bbl or .aux) +# It returns success or failure +# ****** and binds $_ in the caller as a side-effect ****** +sub process_ext_file { + local($ext) = @_; + local($found, $extfile,$dum,$texpath); + $extfile = $EXTERNAL_FILE||$FILE; + local($file) = &fulltexpath("$extfile.$ext"); + $found = 0; + &write_warnings( + "\n$extfile.$EXT is newer than $extfile.$ext: Please rerun latex" . ## AYS + (($ext =~ /bbl/) ? " and bibtex.\n" : ".\n")) + if ( ($found = (-f $file)) && + &newer(&fulltexpath("$extfile.$EXT"), $file)); ## AYS + if ((!$found)&&($extfile =~ /\.$EXT$/)) { + $file = &fulltexpath("$extfile"); + &write_warnings( + "\n$extfile is newer than $extfile: Please rerun latex" . ## AYS + (($ext =~ /bbl/) ? " and bibtex.\n" : ".\n")) + if ( ($found = (-f $file)) && + &newer(&fulltexpath("$extfile"), $file)); ## AYS + } + + # check in other directories on the $TEXINPUTS paths + if (!$found) { + foreach $texpath (split /$envkey/, $TEXINPUTS ) { + $file = "$texpath$dd$extfile.$ext"; + last if ($found = (-f $file)); + } + } + if ( $found ) { + print "\nReading $ext file: $file ..."; + # must allow @ within control-sequence names + $dum = &do_cmd_makeatletter(); + &slurp_input($file); + if ($ext =~ /bbl/) { + # remove the \newcommand{\etalchar}{...} since not needed + s/^\\newcommand{\\etalchar}[^\n\r]*[\n\r]+//s; + } + &pre_process; + &substitute_meta_cmds if (%new_command || %new_environment); + if ($ext eq "aux") { + my $latex_pathname = L2hos->path2latex($file); + $aux_preamble .= + "\\AtBeginDocument{\\makeatletter\n\\input $latex_pathname\n\\makeatother\n}\n"; + local(@extlines) = split ("\n", $_); + print " translating ".(0+@extlines). " lines " if ($VERBOSITY >1); + local($eline,$skip_to); #$_ = ''; + foreach $eline (@extlines) { + if ($skip_to) { next unless ($eline =~ s/$O$skip_to$C//) } + $skip_to = ''; + # skip lines added for pdfTeX/hyperref compatibility + next if ($eline =~ /^\\(ifx|else|fi|global \\let|gdef|AtEndDocument|let )/); + # remove \index and \label commands, else invalid links may result + $eline =~ s/\\(index|label)\s*($O\d+$C).*\2//g; + if ($eline =~ /\\(old)?contentsline/) { + do { local($_,$save_AUX) = ($eline,$AUX_FILE); + $AUX_FILE = 0; + &wrap_shorthand_environments; + #footnote markers upset the numbering + s/\\footnote(mark|text)?//g; + $eline = &translate_environments($_); + $AUX_FILE = $save_AUX; + undef $_ }; + } elsif ($eline =~ s/^\\\@input//) { + &do_cmd__at_input($eline); + $eline = ''; + } elsif ($eline =~ s/^\\\@setckpt$O(\d+)$C//) { + $skip_to = $1; next; + } +# $eline =~ s/$image_mark#([^#]+)#/print "\nIMAGE:",$img_params{$1},"\n";''/e; +# $_ .= &translate_commands(&translate_environments($eline)); + $_ .= &translate_commands($eline) if $eline; + } + undef @extlines; + } elsif ($ext =~ /$caption_suffixes/) { + local(@extlines) = split ("\n", $_); + print " translating ".(0+@extlines). " lines "if ($VERBOSITY >1); + local($eline); $_ = ''; + foreach $eline (@extlines) { + # remove \index and \label commands, else invalid links may result + $eline =~ s/\\(index|label)\s*($O\d+$C).*\2//gso; + if ($eline =~ /\\(old)?contentsline/) { + do { local($_,$save_PREAMBLE) = ($eline,$PREAMBLE); + $PREAMBLE = 0; + &wrap_shorthand_environments; + $eline = &translate_environments($_); + $PREAMBLE = $save_PREAMBLE; + undef $_ }; + } + $_ .= &translate_commands($eline); + } + undef @extlines; + } else { + print " wrapping " if ($VERBOSITY >1); + &wrap_shorthand_environments; + $_ = &translate_commands(&translate_environments($_)); + print " translating " if ($VERBOSITY >1); + } + print "\n processed size: ".length($_)."\n" if($VERBOSITY>1); + $dum = &do_cmd_makeatother(); + } else { + print "\n*** Could not find file: $file ***\n" if ($DEBUG) + }; + $found; +} + +sub deal_with_texinputs { +# The dot precedes all, this let's local files override always. +# The dirs we want are given as parameter list. + if(!$TEXINPUTS) { $TEXINPUTS = '.' } + elsif ($TEXINPUTS =~ /^$envkey/) { + $TEXINPUTS = '.'.$TEXINPUTS + }; + if ($ROOTED) {$TEXINPUTS .= "$envkey$FIXEDDIR"} + $TEXINPUTS = &absolutize_path($TEXINPUTS); + $ENV{'TEXINPUTS'} = join($envkey,".",@_,$TEXINPUTS,$ENV{'TEXINPUTS'}); +} + +# provided by Fred Drake +sub absolutize_path { + my ($path) = @_; + my $npath = ''; + foreach $dir (split /$envkey/o, $path) { + $npath .= L2hos->Make_directory_absolute($dir) . $envkey; + } + $npath =~ s/$envkey$//; + $npath; +} + +sub add_document_info_page { + # Uses $outermost_level + # Nasty race conditions if the next two are done in parallel + local($X) = ++$global{'max_id'}; + local($Y) = ++$global{'max_id'}; + ###MEH -- changed for math support: no underscores in commandnames + $_ = join('', $_ + , (($MAX_SPLIT_DEPTH <= $section_commands{$outermost_level})? + "\n
\n" : '') + , "\\$outermost_level", "*" + , "$O$X$C$O$Y$C\\infopagename$O$Y$C$O$X$C\n", + , " \\textohtmlinfopage"); +} + + +# For each style file name in TMP_styles (generated by texexpand) look for a +# perl file in $LATEX2HTMLDIR/styles and load it. +sub load_style_file_translations { + local($_, $style, $options, $dir); + print "\n"; + if ($TEXDEFS) { + foreach $dir (split(/$envkey/,$LATEX2HTMLSTYLES)) { + if (-f ($_ = "$dir${dd}texdefs.perl")) { + print "\nLoading $_..."; + require ($_); + $styles_loaded{'texdefs'} = 1; + last; + } + } + } + + # packages automatically implemented + local($auto_styles) = $AUTO_STYLES; + $auto_styles .= 'array|' if ($HTML_VERSION > 3.1); + $auto_styles .= 'tabularx|' if ($HTML_VERSION > 3.1); + $auto_styles .= 'theorem|'; + + # these are not packages, but can appear as if class-options + $auto_styles .= 'psamsfonts|'; + $auto_styles .= 'noamsfonts|'; + + $auto_styles =~ s/\|$//; + + if(open(STYLES, "<$TMP_${dd}styles")) { + while() { + if(s/^\s*(\S+)\s*(.*)$/$style = $1; $options = $2;/eo) { + &do_require_package($style); + $_ = $DONT_INCLUDE; + s/:/|/g; + &write_warnings("No implementation found for style \`$style\'\n") + unless ($styles_loaded{$style} || $style =~ /^($_)$/ + || $style =~ /$auto_styles/); + + # MRO: Process options for packages + &do_package_options($style,$options) if($options); + } + } + close(STYLES); + } else { + print "\nError: Cannot read '$TMP_${dd}styles': $!\n"; + } +} + +################## Weird Special case ################## + +# The new texexpand can be told to leave in \input and \include +# commands which contain code that the translator should simply pass +# to latex, such as the psfig stuff. These should still be seen by +# TeX, so we add them to the preamble ... + +sub do_include_lines { + while (s/$include_line_rx//o) { + local($include_line) = &revert_to_raw_tex($&); + &add_to_preamble ('include', $include_line); + } +} + +########################## Preprocessing ############################ + +# JCL(jcl-verb) +# The \verb declaration and the verbatim environment contain simulated +# typed text and should not be processed. Characters such as $,\,{,and } +# loose their special meanings and should not be considered when marking +# brackets etc. To achieve this \verb declarations and the contents of +# verbatim environments are replaced by markers. At the end the original +# text is put back into the document. +# The markers for verb and verbatim are different so that these commands +# can be restored to what the raw input was just in case they need to +# be passed to latex. + +sub pre_process { + # Modifies $_; + #JKR: We need support for some special environments. + # This has to be here, because they might contain + # structuring commands like \section etc. + local(%comments); + &pre_pre_process if (defined &pre_pre_process); + s/\\\\/\\\\ /go; # Makes it unnecessary to look for escaped cmds + &replace_html_special_chars; + # Remove fake environment which should be invisible to LaTeX2HTML. + s/\001//m; + s/[%]end\s*{latexonly}/\001/gom; + s/[%]begin\s*{latexonly}([^\001]*)\001/%/gos; + s/\001//m; + + &preprocess_alltt if defined(&preprocess_alltt); + + $KEEP_FILE_MARKERS = 1; + if ($KEEP_FILE_MARKERS) { +# if (s/%%% TEXEXPAND: \w+ FILE( MARKER)? (\S*).*/ +# ''.qq|#$2#|."\n"/em) { +# $_ = "#$2#\n". $_ }; + #RRM: ignore \n at end of included file, else \par may result + if (s/(\n{1,2})?%%% TEXEXPAND: \w+ FILE( MARKER)? (\S*).*\n?/ + ($2?$1:"\n").''.qq|#$3#|."\n"/em) { + $_ = "#$3#\n". $_ }; + } else { + s/%%% TEXEXPAND[^\n]*\n//gm; + } + + # Move all LaTeX comments into a local list + s/([ \t]*(^|\G|[^\\]))(%.*(\n[ \t]*|$))/print "%"; + $comments{++$global{'verbatim_counter'}} = "$3"; + &write_mydb("verbatim", $global{'verbatim_counter'}, $3); + "$1$comment_mark".$global{'verbatim_counter'}."\n"/mge; + # Remove the htmlonly-environment + s/\\begin\s*{htmlonly}\s*\n?//gom; + s/\\end\s*{htmlonly}\s*\n?//gom; + # Remove enviroments which should be invisible to LaTeX2HTML. + s/\n[^%\n]*\\end\s*{latexonly}\s*\n?/\001/gom; + s/((^|\n)[^%\n]*)\\begin\s*{latexonly}([^\001]*)\001/$1/gom; + s/\\end\s*{comment}\s*\n?/\001/gom; + s/\\begin\s*{comment}([^\001]*)\001//gom; + + # this used to be earlier, but that can create problems with comments + &wrap_other_environments if (%other_environments); + +# s/\\\\/\\\\ /go; # Makes it unnecessary to look for escaped cmds + local($next, $esc_del); + &normalize_language_changes; + # Patches by #JKR, #EI#, #JCL(jcl-verb) + + #protect \verb|\begin/end....| parts, for LaTeX documentation + s/(\\verb\*?(.))\\(begin|end)/$1\003$3/g; + + local(@processedV); + local($opt, $style_info,$before, $contents, $after, $env); + while (($UNFINISHED_COMMENT)|| + (/\\begin\s*($opt_arg_rx)?\s*\{($verbatim_env_rx|$keepcomments_rx)\}/o)) { + ($opt, $style_info) = ($1,$2); + $before=$contents=$after=$env=''; + if ($UNFINISHED_COMMENT) { + $UNFINISHED_COMMENT =~ s/([^:]*)::(\d+)/$env=$1;$after=$_; + $before = join("",$unfinished_mark,$env,$2,"#");''/e; + print "\nfound the lost \\end{$env}\n"; + } + #RRM: can we avoid copying long strings here ? + # maybe this loop can be an s/.../../s with (.*?) + # + ($before, $after, $env) = ($`, $', $3) unless ($env); + if (!($before =~ + /\\begin(\s*\[[^\]]*\]\s*)?\{($verbatim_env_rx|$keepcomments_rx)\}/)) { + push(@processedV,$before); + print "'";$before = ''; + } + if ($after =~ /\s*\\end{$env[*]?}/) { # Must NOT use the s///o option!!! + ($contents, $after) = ($`, $'); + $contents =~ s/^\n+/\n/s; +# $contents =~ s/\n+$//s; + + # re-insert comments + $contents =~ s/$comment_mark(\d+)\n?/$comments{$1}/g; +# $contents =~ s/$comment_mark(\d+)/$verbatim{$1}/g; + + # revert '\\ ' -> '\\' only once + if ($env =~ /rawhtml|$keepcomments_rx/i) { + $contents = &revert_to_raw_tex($contents); + } else { + $contents =~ s/([^\\](?:\\\\)*\\)([$html_escape_chars])/$1.&special($2)/geos; + $contents =~ s/\\\\ /\\\\/go; + } + + if ($env =~/$keepcomments_rx/) { + $verbatim{++$global{'verbatim_counter'}} = "$contents"; + } else { + &write_mydb("verbatim", ++$global{'verbatim_counter'}, $contents); + } +# $verbatim{$global{'verbatim_counter'}} = "$contents" if ($env =~/$keepcomments_rx/); +# $verbatim{$global{'verbatim_counter'}} = "$contents"; + + if ($env =~ /rawhtml|$keepcomments_rx/i) { + if ($before) { + $after = join("",$verbatim_mark,$env + ,$global{'verbatim_counter'},"#",$after); + } else { + push (@processedV, join("",$verbatim_mark,$env + ,$global{'verbatim_counter'},"#")); + } + } elsif ($env =~ /tex2html_code/) { + if ($before) { + $after = join("","\\begin", $opt, "\{verbatim_code\}" + , $verbatim_mark,$env + , $global{'verbatim_counter'},"#" + , "\\end\{verbatim_code\}",$after); + } else { + push (@processedV + , join("","\\begin", $opt, "\{verbatim_code\}" + , $verbatim_mark,$env + , $global{'verbatim_counter'},"#" + , "\\end\{verbatim_code\}")); + } + } else { + if ($before) { + $after = join("","\\begin", $opt, "\{tex2html_preform\}" + , $verbatim_mark,$env + , $global{'verbatim_counter'},"#" + , "\\end\{tex2html_preform\}",$after); + } else { + push (@processedV + , join("","\\begin", $opt, "\{tex2html_preform\}" + , $verbatim_mark,$env + , $global{'verbatim_counter'},"#" + , "\\end\{tex2html_preform\}" )); + } + } + } else { + print "Cannot find \\end{$env}\n"; + $after =~ s/$comment_mark(\d+)\n?/$comments{$1}/g; +# $after =~ s/$comment_mark(\d+)/$verbatim{$1}/g; + if ($env =~ /rawhtml|$keepcomments_rx/i) { + $after = &revert_to_raw_tex($contents); + } else { + $after =~ s/([^\\](?:\\\\)*\\)([$html_escape_chars])/$1.&special($2)/geos; + $after =~ s/\\\\ /\\\\/go; + } + if ($env =~/$keepcomments_rx/) { + $verbatim{++$global{'verbatim_counter'}} = "$after"; + } else { + &write_mydb("verbatim", ++$global{'verbatim_counter'}, $after ); + } + $after = join("",$unfinished_mark,$env + ,$global{'verbatim_counter'},"#"); + } + $_ = join("",$before,$after); + } + print STDOUT "\nsensitive environments found: ".(int(0+@processedV/2))." " + if((@processedV)&&($VERBOSITY > 1)); + $_ = join('',@processedV, $_); undef @processedV; + + #restore \verb|\begin/end....| parts, for LaTeX documentation +# $_ =~ s/(\\verb\W*?)\003(begin|end)/$1\\$2/g; + $_ =~ s/(\\verb(;SPM\w+;|\W*?))\003(begin|end)/$1\\$3/g; + + # Now do the \verb declarations + # Patches by: #JKR, #EI#, #JCL(jcl-verb) + # Tag \verb command and legal opening delimiter with unique number. + # Replace tagged ones and its contents with $verb_mark & id number if the + # closing delimiter can be found. After no more \verb's are to tag, revert + # tagged one's to the original pattern. + local($del,$contents,$verb_rerun); + local($id) = $global{'verb_counter'}; + # must tag only one alternation per loop + ##RRM: can this be speeded up using a list ?? + my $vbmark = $verb_mark; + while (s/\\verb(\t*\*\t*)(\S)/"$2"/e || + s/\\verb()(\;SPM\w+\;|[^a-zA-Z*\s])/"$2"/e || + s/\\verb(\t\t*)([^*\s])/"$2"/e) { + + $del = $2; + #RRM: retain knowledge of whether \verb* or \verb + $vb_mark = ($1 =~/^\s*\*/? $verbstar_mark : $verb_mark); + $esc_del = &escape_rx_chars($del); + $esc_del = '' if (length($del) > 2); + + # try to find closing delimiter and substitute the complete + # statement with $verb_mark or $verbstar_mark +# s/(]*$id>[\Q$del\E])([^$esc_del\n]*)([\Q$del\E]|$comment_mark(\d+)\n?)/ + s/(]*$id>\Q$del\E)([^$esc_del\n]*?)(\Q$del\E|$comment_mark(\d+)\n?)/ + $contents=$2; + if ($4) { $verb_rerun = 1; + join('', "\\verb$del", $contents, $comments{$4}) + } else { + $contents =~ s|\\\\ |\\\\|g; + $contents =~ s|\n| |g; + $verb{$id}=$contents; + $verb_delim{$id}=$del; + join('',$vb_mark,$id,$verb_mark) + } + /e; + } + $global{'verb_counter'} = $id; + # revert changes to fake verb statements + s/]*)\d+>/\\verb$1/g; + + #JKR: the comments include the linebreak and the following whitespace +# s/([^\\]|^)(%.*\n[ \t]*)+/$1/gom; # Remove Comments but not % which may be meaningful + s/((^|\n)$comment_mark(\d+))+//gom; # Remove comment markers on new lines, but *not* the trailing \n + s/(\\\w+|(\W?))($comment_mark\d*\n?)/($2)? $2.$3:($1? $1.' ':'')/egm; # Remove comment markers, not after braces +# s/(\W?)($comment_mark\d*\n?)/($1)? $1.$2:''/egm; # Remove comment markers, not after braces + # Remove comment markers, but *not* the trailing \n +# HWS: Correctly remove multiple %%'s. +# + s/\\%/\002/gm; +# s/(%.*\n[ \t]*)//gm; + s/(%[^\n]*\n)[ \t]*/$comment_mark\n/gm; + + s/\002/\\%/gm; + + local($tmp1,$tmp2); + s/^$unfinished_mark$keepcomments_rx(\d+)#\n?$verbatim_mark$keepcomments_rx(\d+)#/ + $verbatim{$4}."\n\\end{$1}"/egm; # Raw TeX + s/$verbatim_mark$keepcomments_rx(\d+)#/ + $tmp1 = $1; + $tmp2 = &protect_after_comments($verbatim{$2}); + $tmp2 =~ s!\n$!!s; + join ('', "\\begin{$tmp1}" + , $tmp2 + , "\n\\end{$tmp1}" + )/egm; # Raw TeX + s/$unfinished_mark$keepcomments_rx(\d+)#/$UNFINISHED_COMMENT="$1::$2"; + "\\begin{$1}\n".$verbatim{$2}/egm; # Raw TeX + + $KEEP_FILE_MARKERS = 1; + if ($KEEP_FILE_MARKERS) { + s/%%% TEXEXPAND: \w+ FILE( MARKER) (\S*).*\n/ + ''.qq|#.$2#\n|/gem; + } else { + s/%%% TEXEXPAND[^\n]*\n//gm; + } + + &mark_string($_); + + + # attempt to remove the \html \latex and \latexhtml commands + s/\\latex\s*($O\d+$C)(.*)\1//gm; + s/\\latexhtml\s*($O\d+$C)(.*)\1\s*($O\d+$C)(.*)\3/$4/sg; + s/\\html\s*($O\d+$C)(.*)\1/$2/sg; + s/\\html\s*($O\d+$C)//gm; + +# &make_unique($_); +} + +# RRM: When comments are retained, then ensure that they are benign +# by removing \s and escaping braces, +# so that environments/bracing cannot become unbalanced. +sub protect_after_comments { + my ($verb_text) = @_; +# $verb_text =~ s/\%(.*)/'%'.&protect_helper($1)/eg; + $verb_text =~ s/(^|[^\\])(\\\\)*\%(.*)/$1.$2.'%'.&protect_helper($3)/emg; + $verb_text; +} + +sub protect_helper { + my ($text) = @_; + $text =~ s/\\/ /g; + $text =~ s/(\{|\})/\\$1/g; + $text; +} + +sub make_comment { + local($type,$_) = @_; + $_ =~ s/\\(index|label)\s*(($O|$OP)\d+($C|$CP)).*\2//sg; + $_ = &revert_to_raw_tex($_); s/^\n+//m; + $_ =~ s/\\(index|label)\s*\{.*\}//sg; + s/\-\-/- -/g; s/\-\-/- -/g; # cannot have -- inside a comment + $_ = join('', '" ); + $verbatim{++$global{'verbatim_counter'}} = $_; + &write_mydb('verbatim', $global{'verbatim_counter'}, $_ ); + join('', $verbatim_mark, 'verbatim' , $global{'verbatim_counter'},'#') +} + +sub wrap_other_environments { + local($key, $env, $start, $end, $opt_env, $opt_start); + foreach $key (keys %other_environments) { + # skip bogus entries + next unless ($env = $other_environments{$key}); + $key =~ s/:/($start,$end)=($`,$');':'/e; + + if (($end =~ /^\#$/m) && ($start =~ /^\#/m)) { + # catch Indica pre-processor language switches + $opt_start = $'; + if ($env =~ s/\[(\w*)\]//o) { + $opt_env = join('','[', ($1 ? $1 : $opt_start ), ']'); + } + local($next); + while ($_ =~ /$start\b/) { + push(@pre_wrapped, $`, "\\begin\{pre_$env\}", $opt_env ); + $_=$'; + if (/(\n*)$end/) { + push(@pre_wrapped, $`.$1,"\\end\{pre_$env\}$1"); + $_ = $'; + if (!(s/^N(IL)?//o)) {$_ = '#'.$_ } + } else { + print "\n *** unclosed $start...$end chunk ***\n"; + last; + } + } + $_ = join('', @pre_wrapped, $_); + undef @pre_wrapped; + + } elsif (($end=~/^\n$/) && ($start =~ /^\#/)) { + # catch ITRANS pre-processor language info; $env = 'nowrap'; + local($ilang) = $start; $ilang =~ s/^\#//m; + s/$start\s*\=([^<\n%]*)\s*($comment_mark\d*|\n|%)/\\begin\{tex2html_$env\}\\ITRANSinfo\{$ilang\}\{$1\}\n\\end\{tex2html_$env\}$2/g; + + } elsif (!$end &&($start =~ /^\#/m)) { + # catch Indica pre-processor input-mode switches + s/$start(.*)\n/\\begin\{tex2html_$env\}$&\\end\{tex2html_$env\}\n/g; + + } elsif (($start eq $end)&&(length($start) == 1)) { + $start =~ s/(\W)/\\$1/; $end = $start; + s/([^$end])$start([^$end]+)$end/$1\\begin\{pre_$env\}$2\\end\{pre_$env\}/mg; + } elsif ($start eq $end) { + if (!($start =~ /\#\#/)) { + $start =~ s/(\W)/\\$1/g; $end = $start; } + local (@pre_wrapped); + local($opt); $opt = '[indian]' if ($start =~ /^\#\#$/m); + while ($_ =~ /$start/s) { + push(@pre_wrapped, $` , "\\begin\{pre_$env\}$opt"); + $_=$'; + if (/$end/s) { + push(@pre_wrapped, $`, "\\end\{pre_$env\}"); + $_ = $'; + } else { + print "\n *** unclosed $start...$end chunk ***\n"; + last; + } + } + $_ = join('', @pre_wrapped, $_); + undef @pre_wrapped; + } elsif ($start && ($env =~ /itrans/)) { + # ITRANS is of this form + local($indic); if($start =~ /\#(\w+)$/m) {$indic = $1} + #include the language-name as an optional parameter + s/$start\b/\\begin\{pre_$env\}\[$indic\]/sg; + s/$end\b/\\end\{pre_$env\}/sg; + } elsif (($start)&&($end)) { + s/$start\b/\\begin\{pre_$env\}/sg; + s/$end\b/\\end\{pre_$env\}/sg; + } + } + $_; +} + +#################### Marking Matching Brackets ###################### + +# Reads the entire input file and performs pre_processing operations +# on it before returning it as a single string. The pre_processing is +# done on separate chunks of the input file by separate Unix processes +# as determined by LaTeX \input commands, in order to reduce the memory +# requirements of LaTeX2HTML. +sub slurp_input_and_partition_and_pre_process { + local($file) = @_; + local(%string, @files, $pos); + local ($count) = 1; + + unless(open(SINPUT,"<$file")) { + die "\nError: Cannot read '$file': $!\n"; + } + local(@file_string); + print STDOUT "$file" if ($VERBOSITY >1); + while () { + if (/TEXEXPAND: INCLUDED FILE MARKER (\S*)/) { + # Forking seems to screw up the rest of the input stream + # We save the current position ... + $pos = tell SINPUT; + print STDOUT " fork at offset $pos " if ($VERBOSITY >1); + $string{'STRING'} = join('',@file_string); @file_string = (); + &write_string_out($count); + delete $string{'STRING'}; + # ... so that we can return to it + seek(SINPUT, $pos, 0); + print STDOUT "\nDoing $1 "; + ++$count} + else { +# $string{'STRING'} .= $_ + push(@file_string,$_); + } + } + $string{'STRING'} = join('',@file_string); @file_string = (); + &write_string_out($count); + delete $string{'STRING'}; + close SINPUT; + @files = (); + if(opendir(DIR, $TMP_)) { + @files = sort grep(/^\Q$PARTITION_PREFIX\E\d+/, readdir(DIR)); + closedir(DIR); + } + + unless(@files) { + die "\nFailed to read in document parts.\n". + "Look up section Globbing in the troubleshooting manual.\n"; + } + + $count = 0; + foreach $file (@files) { + print STDOUT "\nappending file: $TMP_$dd$file " if ($VERBOSITY > 1); + $_ .= (&catfile("$TMP_$dd$file") || ''); + print STDOUT "\ntotal length: ".length($_)." characters\n" if ($VERBOSITY > 1); + } + die "\nFailed to read in document parts (out of memory?).\n" + unless length($_); + print STDOUT "\ntotal length: ".length($_)." characters\n" if ($VERBOSITY > 1); +} + +sub write_string_out { + local($count) = @_; + if ($count < 10) {$count = '00'.$count} + elsif ($count < 100) {$count = '0'.$count} + local($pid); + # All open unflushed streams are inherited by the child. If this is + # not set then the parent will *not* wait + $| = 1; + # fork returns 0 to the child and PID to the parent + &write_mydb_simple("prelatex", $prelatex); + &close_dbm_database; + unless ($CAN_FORK) { + &do_write_string_out; + } else { + unless ($pid = fork) { + &do_write_string_out; + exit 0; + }; + waitpid($pid,0); + } + &open_dbm_database; +} + +sub do_write_string_out { + local($_); + close (SINPUT) if($CAN_FORK); + &open_dbm_database; + $_ = delete $string{'STRING'}; + # locate blank-lines, for paragraphs. + # Replace verbatim environments etc. + &pre_process; + # locate the blank lines for \par s + &substitute_pars; + # Handle newcommand, newenvironment, newcounter ... + &substitute_meta_cmds; + &wrap_shorthand_environments; + print STDOUT "\n *** End-of-partition ***" if ($VERBOSITY > 1); + if(open(OUT, ">$TMP_$dd$PARTITION_PREFIX$count")) { + print OUT $_; + close(OUT); + } else { + print "\nError: Cannot write '$TMP_$dd$PARTITION_PREFIX$count': $!\n"; + } + print STDOUT $_ if ($VERBOSITY > 9); + $preamble = join("\n",$preamble,@preamble); # undef @preamble; + &write_mydb_simple("preamble", $preamble); + # this was done earlier; it should not be repeated + #&write_mydb_simple("prelatex", $prelatex); + &write_mydb_simple("aux_preamble", $aux_preamble); + &close_dbm_database; +} + +# Reads the entire input file into a +# single string. +sub slurp_input { + local($file) = @_; + local(%string); + if(open(INPUT,"<$file")) { + local(@file_string); + while () { + push(@file_string, $_ ); + } + $string{'STRING'} = join('',@file_string); + close INPUT; + undef @file_string; + } else { + print "\nError: Cannot read '$file': $!\n"; + } + $_ = delete $string{'STRING'}; # Blow it away and return the result +} + +# MRO: make them more efficient +sub special { + $html_specials{$_[0]} || $_[0]; +} + +sub special_inv { + $html_specials_inv{$_[0]} || $_[0]; +} + +sub special_html { + $html_special_entities{$_[0]} || $_[0]; +} + +sub special_html_inv { + $html_spec_entities_inv{$_[0]} || $_[0]; +} + +# Mark each matching opening and closing bracket with a unique id. +sub mark_string { + # local (*_) = @_; # Modifies $_ in the caller; + # -> MRO: changed to $_[0] (same effect) + # MRO: removed deprecated $*, replaced by option /m + $_[0] =~ s/(^|[^\\])\\{/$1tex2html_escaped_opening_bracket/gom; + $_[0] =~ s/(^|[^\\])\\{/$1tex2html_escaped_opening_bracket/gom; # repeat this + $_[0] =~ s/(^|[^\\])\\}/$1tex2html_escaped_closing_bracket/gom; + $_[0] =~ s/(^|[^\\])\\}/$1tex2html_escaped_closing_bracket/gom; # repeat this + my $id = $global{'max_id'}; + my $prev_id = $id; + # mark all balanced braces + # MRO: This should in fact mark all of them as the hierarchy is + # processed inside-out. + 1 while($_[0] =~ s/{([^{}]*)}/join("",$O,++$id,$C,$1,$O,$id,$C)/geo); + # What follows seems esoteric... + my @processedB = (); + # Take one opening brace at a time + while ($_[0] =~ /\{/) { + my ($before,$after) = ($`,$'); + my $change = 0; + while (@UNMATCHED_OPENING && $before =~ /\}/) { + my $this = pop(@UNMATCHED_OPENING); + print "\n *** matching brace \#$this found ***\n"; + $before =~ s/\}/join("",$O,$this,$C)/eo; + $change = 1; + } + $_[0] = join('',$before,"\{",$after) if($change); + # MRO: mark one opening brace + if($_[0] =~ s/^([^{]*){/push(@processedB,$1);join('',$O,++$id,$C)/eos) { + $before=''; $after=$'; + } + if ($after =~ /\}/) { + $after =~ s/\}/join("",$O,$id,$C)/eo; + $_[0] = join('',$before,$O,$id,$C,$after); + } else { + print "\n *** opening brace \#$id is unmatched ***\n"; + $after =~ /^(.+\n)(.+\n)?/; + print " preceding: $after \n"; + push (@UNMATCHED_OPENING,$id); + } + } + $_[0] = join('',@processedB,$_[0]); undef(@processedB); + print STDOUT "\nInfo: bracketings found: ", $id - $prev_id,"\n" + if ($VERBOSITY > 1); + # process remaining closing braces + while (@UNMATCHED_OPENING && $_[0] =~ /\}/) { + my $this = pop(@UNMATCHED_OPENING); + print "\n *** matching brace \#$this found ***\n"; + $_[0] =~ s/\}/join("",$O,$this,$C)/eo; + } + + while ($_[0] =~ /\}/) { + print "\n *** there was an unmatched closing \} "; + my ($beforeline,$prevline,$afterline) = ($`, $`.$& , $'); + $prevline =~ /\n([^\n]+)\}$/m; + if ($1) { + print "at the end of:\n" . $1 . "\}\n\n"; + } else { + $afterline =~ /^([^\n]+)\n/m; + if ($1) { + print "at the start of:\n\}" . $1 ."\n\n"; + } else { + $prevline =~ /\n([^\n]+)\n\}$/m; + print "on a line by itself after:\n" . $1 . "\n\}\n\n"; + } + } + $_[0] = $beforeline . $afterline; + } + $global{'max_id'} = $id; + + # restore escaped braces + $_[0] =~ s/tex2html_escaped_opening_bracket/\\{/go; + $_[0] =~ s/tex2html_escaped_closing_bracket/\\}/go; +} + +sub replace_html_special_chars { + # Replaces html special characters with markers unless preceded by "\" + s/([^\\])(<|>|&|\"|``|'')/&special($1).&special($2)/geom; + # MUST DO IT AGAIN JUST IN CASE THERE ARE CONSECUTIVE HTML SPECIALS + s/([^\\])(<|>|&|\"|``|'')/&special($1).&special($2)/geom; + s/^(<|>|&|\"|``|'')/&special($1)/geom; +} + +# used in \verbatiminput only: $html_escape_chars = '<>&'; +sub replace_all_html_special_chars { s/([$html_escape_chars])/&special($1)/geom; } + +# The bibliography and the index should be treated as separate sections +# in their own HTML files. The \bibliography{} command acts as a sectioning command +# that has the desired effect. But when the bibliography is constructed +# manually using the thebibliography environment, or when using the +# theindex environment it is not possible to use the normal sectioning +# mechanism. This subroutine inserts a \bibliography{} or a dummy +# \textohtmlindex command just before the appropriate environments +# to force sectioning. +sub add_bbl_and_idx_dummy_commands { + local($id) = $global{'max_id'}; + + s/([\\]begin\s*$O\d+$C\s*thebibliography)/$bbl_cnt++; $1/eg; + ## if ($bbl_cnt == 1) { + s/([\\]begin\s*$O\d+$C\s*thebibliography)/$id++; "\\bibliography$O$id$C$O$id$C $1"/geo; + #} + $global{'max_id'} = $id; + s/([\\]begin\s*$O\d+$C\s*theindex)/\\textohtmlindex $1/o; + s/[\\]printindex/\\textohtmlindex /o; + &lib_add_bbl_and_idx_dummy_commands() if defined(&lib_add_bbl_and_idx_dummy_commands); +} + + +# Uses and modifies $default_language +# This would be straight-forward except when there are +# \MakeUppercase, \MakeLowercase or \uppercase , \lowercase commands +# present in the source. The cases have to be adjusted before the +# ISO-character code is set; e.g. with "z --> "Z in german.perl +# +sub convert_iso_latin_chars { + local($_) = @_; + local($next_language, $pattern); + local($xafter, $before, $after, $funct, $level, $delim); + local(@case_processed); + while (/$case_change_rx/) { + $xafter = $2; +# $before .= $`; + push(@case_processed, $`); + $funct = $3; + $after = ''; + $_ = $'; + if ($xafter =~ /noexpand/) { $before .= "\\$funct"; next; } + + s/^[\s%]*(.)/$delim=$1;''/eo; + if ($delim =~ /{/ ) { + # brackets not yet numbered... +# $before .= $funct . $delim; + push(@case_processed, $funct . $delim); + $level = 1; + $after = $delim; + while (($level)&&($_)&&(/[\{\}]/)) { + $after .= $` . $&; + $_ = $'; + if ( "$&" eq "\{" ) {$level++} + elsif ( "$&" eq "\}" ) { $level-- } + else { print $_ } + print "$level"; + } +# $before .= $after; + push(@case_processed, $after); + } elsif ($delim eq "<") { + # brackets numbered, but maybe not processed... + s/((<|#)(\d+)(>|#)>).*\1//; + $after .= $delim . $&; + $_ = $'; + print STDOUT "\n<$2$funct$4>" if ($VERBOSITY > 2); + $funct =~ s/^\\//o; + local($cmd) = "do_cmd_$funct"; + $after = &$cmd($after); +# $before .= $after; + push(@case_processed, $after); + } elsif (($xafter)&&($delim eq "\\")) { + # preceded by \expandafter ... + # ...so expand the following macro first + $funct =~ s/^\\//o; + local($case_change) = $funct; + s/^(\w+|\W)/$funct=$1;''/eo; + local($cmd) = $funct; + local($thiscmd) = "do_cmd_$funct"; + if (defined &$thiscmd) { $_ = &$thiscmd($_) } + elsif ($new_command{$funct}) { + local($argn, $body, $opt) = split(/:!:/, $new_command{$funct}); + do { ### local($_) = $body; + &make_unique($body); + } if ($body =~ /$O/); + if ($argn) { + do { + local($before) = ''; + local($after) = "\\$funct ".$_; + $after = &substitute_newcmd; # may change $after + $after =~ s/\\\@#\@\@/\\/o ; + } + } else { $_ = $body . $_; } + } else { print "\nUNKNOWN COMMAND: $cmd "; } + + $cmd = $case_change; + $case_change = "do_cmd_$cmd"; + if (defined &$case_change) { $_ = &$case_change($_) } + } else { + # this should not happen, but just in case... + $funct =~ s/^\\//o; + local($cmd) = "do_cmd_$funct"; + print STDOUT "\n\n<$delim$funct>" if ($VERBOSITY > 2); + $_ = join('', $delim , $_ ); + if (defined &$cmd) { $_ = &$cmd($_) } + } + } +# $_ = join('', $before, $_) if ($before); + $_ = join('', @case_processed, $_) if (@case_processed); + + # ...now do the conversions + ($before, $after, $funct) = ('','',''); + @case_processed = (); + if (/$language_rx/o) { + ($next_language, $pattern, $before, $after) = (($2||$1), $&, $`, $'); + $before = &convert_iso_latin_chars($before) if ($before); +# push(@case_processed, $pattern, $before); + local($br_id) = ++$global{'max_id'}; + $pattern = join('' , '\selectlanguage', $O.$br_id.$C + , (($pattern =~ /original/) ? $TITLES_LANGUAGE : $next_language ) + , $O.$br_id.$C ); + push(@case_processed, $before, $pattern); + push(@language_stack, $default_language); + $default_language = $next_language; + $_ = &convert_iso_latin_chars($after); + $default_language = pop @language_stack; + } else { + $funct = $language_translations{$default_language}; + (defined(&$funct) ? $_ = &$funct($_) : + do { &write_warnings( + "\nCould not find translation function for $default_language.\n\n") + } + ); + if ($USE_UTF ||(!$NO_UTF &&(defined %unicode_table)&&length(%unicode_table)>2)) { + &convert_to_unicode($_)}; + } + $_ = join('', @case_processed, $_); undef(@case_processed); + $_; +} + +# May need to add something here later +sub english_translation { $_[0] } + +# This replaces \setlanguage{\language} with \languageTeX +# This makes the identification of language chunks easier. +sub normalize_language_changes { + s/$setlanguage_rx/\\$2TeX/gs; +} + +sub get_current_language { + return () if ($default_language eq $TITLES_LANGUAGE); + local($lang,$lstyle) = ' LANG="'; + $lang_code = $iso_languages{$default_language}; + if (%styled_languages) { + $lstyle = $styled_languages{$default_language}; + $lstyle = '" CLASS="'.$lstyle if $lstyle; + } + ($lang_code ? $lang.$lang_code.$lstyle.'"' : ''); +} + +%styled_languages = (); + +sub do_cmd_htmllanguagestyle { + local($_) = @_; + local($class) = &get_next_optional_argument; + local($lang) = &missing_braces unless ( + (s/$next_pair_pr_rx/$lang=$2;''/e) + ||(s/$next_pair_rx/$lang=$2;''/e)); + return ($_) unless $lang; + local($class) = $iso_languages{$lang} unless $class; + if ($USING_STYLES && $class) { + print "\nStyling language: $lang = \"$class\" "; + $styled_languages{"$lang"} = $class; + } + $_; +} + +# General translation mechanism: +# +# +# The main program latex2html calls texexpand with the document name +# in order to expand some of its \input and \include statements, here +# also called 'merging', and to write a list of sensitized style, class, +# input, or include file names. +# When texexpand has finished, all is contained in one file, TMP_foo. +# (assumed foo.tex is the name of the document to translate). +# +# In this version, texexpand cares for following environments +# that may span include files / section boundaries: +# (For a more technical description, see texexpand.) +# a) \begin{comment} +# b) %begin{comment} +# c) \begin{any} introduced with \excludecomment +# d) %begin{any} +# e) \begin{verbatim} +# f) \begin{latexonly} +# g) %begin{latexonly} +# +# a)-d) cause texexpand to drop its contents, it will not show up in the +# output file. You can use this to 'comment out' a bunch of files, say. +# +# e)-g) prevent texexpand from expanding input files, but the environment +# content goes fully into the output file. +# +# Together with each merging of \input etc. there are so-called %%%texexpand +# markers accompanying the boundary. +# +# When latex2html reads in the output file, it uses these markers to write +# each part to a separate file, and process them further. +# +# +# If you have, for example: +# +# a) preample +# b) \begin{document} +# c) text +# d) \input{chapter} +# e) more text +# f) \end{document} +# +# you end up in two parts, part 1 is a)-c), part 2 is the rest. +# Regardless of environments spanning input files or sections. +# +# +# What now starts is meta command substitution: +# Therefore, latex2html forks a child process on the first part and waits +# until it finished, then forks another on the next part and so forth +# (see also &slurp_input_and_partition_and_preprocess). +# +# Here's what each child is doing: +# Each child process reads the new commands translated so far by the previous +# child from the TMP_global DBM database. +# After &pre_processing, it substitutes the meta commands (\newcommand, \def, +# and the like) it finds, and adds the freshly retrieved new commands to the +# list so far. +# This is done *only on its part* of the document; this saves upwards of memory. +# Finally, it writes its list of new commands (synopsis and bodies) to the +# DBM database, and exits. +# After the last child finished, latex2html reads in all parts and +# concatenates them. +# +# +# So, at this point in time (start of &translate), it again has the complete +# document, but now preprocessed and with new commands substituted. +# This has several disadvantages: an amount of commands is substituted (in +# TeX lingo, expanded) earlier than the rest. +# This causes trouble if commands really must get expanded at the point +# in time they show up. +# +# +# Then, still in &translate, latex2html uses the list of section commands to +# split the complete document into chunks. +# The chunks are not written to files yet. They are retained in the @sections +# list, but each chunk is handled separately. +# latex2html puts the current chunk to $_ and processes it with +# &translate_environments etc., then fetches the next chunk, and so on. +# This prevents environments that span section boundaries from getting +# translated, because \begin and \end cannot find one another, to say it this +# way. +# +# +# After the chunk is translated to HTML, it is written to a file. +# When all chunks are done, latex2html rereads each file to get cross +# references right, replace image markers with the image file names, and +# writes index and bibliography. +# +# +sub translate { + &normalize_sections; # Deal with the *-form of sectioning commands + + # Split the input into sections, keeping the preamble together + # Due to the regular expression, each split will create 5 more entries. + # Entry 1 and 2: non-letter/letter sectioning command, + # entry 4: the delimiter (may be empty) + # entry 5: the text. + local($pre_section, @sections); + if (/\\(startdocument|begin\s*($O\d+$C)\s*document\s*\2)/) { + $pre_section = $`.$&; $_ = $'; + } + @sections = split(/$sections_rx/, $_); + $sections[0] = $pre_section.$sections[0] if ($pre_section); + undef $pre_section; + local($sections) = int(scalar(@sections) / 5); + + # Initialises $curr_sec_id to a list of 0's equal to + # the number of sectioning commands. + local(@curr_sec_id) = split(' ', &make_first_key); + local(@segment_sec_id) = @curr_sec_id; + local($i, $j, $current_depth) = (0,0,0); + local($curr_sec) = $SHORT_FILENAME||$FILE; + local($top_sec) = ($SEGMENT ? '' : 'top of '); +# local(%section_info, %toc_section_info, $CURRENT_FILE, %cite_info, %ref_files); + local($CURRENT_FILE); + # These filenames may be set when translating the corresponding commands. + local($tocfile, $loffile, $lotfile, $footfile, $citefile, $idxfile, + $figure_captions, $table_captions, $footnotes, $citations, %font_size, %index, + %done, $t_title, $t_author, $t_date, $t_address, $t_affil, $changed); + local(@authors,@affils,@addresses,@emails,@authorURLs); + local(%index_labels, %index_segment, $preindex, %footnotes, %citefiles); + local($segment_table_captions, $segment_figure_captions); + local($dir,$nosave) = ('',''); + local($del,$close_all,$open_all,$toc_sec_title,$multiple_toc); + local($open_tags_R) = []; + local(@save_open_tags)= (); + local(@language_stack) = (); + push (@language_stack, $default_language); + +# $LATEX_FONT_SIZE = '10pt' unless ($LATEX_FONT_SIZE); + &process_aux_file + if $SHOW_SECTION_NUMBERS || /\\(caption|(html|hyper)?((eq)?ref|cite))/; + + require ("${PREFIX}internals.pl") if (-f "${PREFIX}internals.pl"); +#JCL(jcl-del) + &make_single_cmd_rx; +# + $tocfile = $EXTERNAL_CONTENTS; + $idxfile = $EXTERNAL_INDEX; + $citefile = $EXTERNAL_BIBLIO; $citefile =~ s/#.*$//; + $citefiles{1} = $citefile if ($citefile); + print "\nTranslating ..."; + + while ($i <= @sections) { + undef $_; + $_ = $sections[$i]; + s/^[\s]*//; # Remove initial blank lines + + # The section command was removed when splitting ... + s/^/\\$curr_sec$del/ if ($i > 0); # ... so put it back + if ($current_depth < $MAX_SPLIT_DEPTH) { + if (($footnotes)&&($NO_FOOTNODE)&&( $current_depth < $MAX_SPLIT_DEPTH)) { + local($thesenotes) = &make_footnotes ; + print OUTPUT $thesenotes; + } + $CURRENT_FILE = &make_name($curr_sec, join('_',@curr_sec_id)); + + open(OUTPUT, ">$CURRENT_FILE") + || die "Cannot write '$CURRENT_FILE': $!\n"; + if ($XBIT_HACK) { # use Apache's XBit hack + chmod 0744, $CURRENT_FILE; + &check_htaccess; + } else { + chmod 0644, $CURRENT_FILE; + } + + if ($MULTIPLE_FILES && $ROOTED) { + if ($DESTDIR =~ /^\Q$FIXEDDIR\E[$dd$dd]?([^$dd$dd]+)/) + { $CURRENT_FILE = "$1$dd$CURRENT_FILE" }; + } + } + &remove_document_env; +# &wrap_shorthand_environments; #RRM Is this needed ? + print STDOUT "\n" if ($VERBOSITY); + print STDOUT "\n" if ($VERBOSITY > 2); + print $i/5,"/$sections"; + print ":$top_sec$curr_sec:" if ($VERBOSITY); + + # Must do this early ... It also sets $TITLE + &process_command($sections_rx, $_) if (/^$sections_rx/); + # reset tags saved from the previous section + $open_tags_R = [ @save_open_tags ]; + @save_open_tags = (); + + local($curr_sec_tex); + if ((! $TITLE) || ($TITLE eq $default_title)) { + eval '$TITLE = '.$default_title; + $TITLE = $default_title if $@; + $curr_sec_tex = ($top_sec ? '' : + join('', '"', &revert_to_raw_tex($curr_sec), '"')); + print STDOUT "$curr_sec_tex for $CURRENT_FILE\n" if ($VERBOSITY); + } else { + local($tmp) = &purify($TITLE,1); + $tmp = &revert_to_raw_tex($tmp); + print STDOUT "\"$tmp\" for $CURRENT_FILE\n" if ($VERBOSITY); + } + + if (/\\(latextohtmlditchpreceding|startdocument)/m) { + local($after) = $'; + local($before) = $`.$&; + $SEGMENT = 1 if ($1 =~ /startdocument/); + print STDOUT "\n *** translating preamble ***\n" if ($VERBOSITY); + $_ = &translate_preamble($before); + s/\n\n//g; s/
//g; # remove redundant blank lines and breaks +# +# &process_aux_file if $AUX_FILE_NEEDED; +# + print STDOUT "\n *** preamble done ***\n" if ($VERBOSITY); + $PREAMBLE = 0; + $NESTING_LEVEL=0; + &do_AtBeginDocument; + $after =~ s/^\s*//m; + print STDOUT (($VERBOSITY >2)? "\n*** Translating environments ***" : ";"); + $after = &translate_environments($after); + print STDOUT (($VERBOSITY >2)? "\n*** Translating commands ***" : ";"); + $_ .= &translate_commands($after); +# $_ = &translate_commands($after); + } else { + &do_AtBeginDocument; + $PREAMBLE = 0; + $NESTING_LEVEL=0; + print STDOUT (($VERBOSITY >2)? "\n*** Translating environments ***" : ";"); + $_ = &translate_environments($_); + print STDOUT (($VERBOSITY >2)? "\n*** Translating commands ***" : ";"); + $_ = &translate_commands($_); + } + + # close any tags that remain open + if (@$open_tags_R) { + ($close_all,$open_all) = &preserve_open_tags(); + $_ .= $close_all; + @save_open_tags = @$open_tags_R; $open_tags_R = []; + } else { ($close_all,$open_all) = ('','') } + + print STDOUT (($VERBOSITY >2)? "\n*** Translations done ***" : "\n"); +# if (($footnotes)&&($NO_FOOTNODE)&&( $current_depth < $MAX_SPLIT_DEPTH)) { +# $_ .= &make_footnotes +# } + print OUTPUT $_; + + # Associate each id with the depth, the filename and the title + ###MEH -- starred sections don't show up in TOC ... + # RRM: ...unless $TOC_STARS is set +# $toc_sec_title = &simplify($toc_sec_title); + $toc_sec_title = &purify($toc_sec_title);# if $SEGMENT; + $toc_sec_title = &purify($TITLE) unless ($toc_sec_title); + + if ($TOC_STARS) { + $toc_section_info{join(' ',@curr_sec_id)} = + "$current_depth$delim$CURRENT_FILE$delim$toc_sec_title" +# if ($current_depth <= $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH); + if ($current_depth <= $TOC_DEPTH); + } else { + $toc_section_info{join(' ',@curr_sec_id)} = + "$current_depth$delim$CURRENT_FILE$delim$toc_sec_title" + . ($curr_sec =~ /star$/ ? "$delim" : "") +# if ($current_depth <= $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH); + if ($current_depth <= $TOC_DEPTH); + } + + # include $BODYTEXT in the section_info, when starting a new page + $section_info{join(' ',@curr_sec_id)} = + "$current_depth$delim$CURRENT_FILE$delim$TITLE$delim" + . (($current_depth < $MAX_SPLIT_DEPTH)? $BODYTEXT: ""); + + # Get type of section (see also the split above) + $curr_sec = $sections[$i+1].$sections[$i+2]; + $del = $sections[$i+4]; + + # Get the depth of the current section; +# $curr_sec = $outermost_level unless $curr_sec; + $current_depth = $section_commands{$curr_sec}; + if ($after_segment) { + $current_depth = $after_segment; + $curr_sec_id[$after_segment] += $after_seg_num; + ($after_segment,$after_seg_num) = ('',''); + for($j=1+$current_depth; $j <= $#curr_sec_id; $j++) { + $curr_sec_id[$j] = 0; + } + } + if ($SEGMENT||$SEGMENTED) { + for($j=1; $j <= $#curr_sec_id; $j++) { + $curr_sec_id[$j] += $segment_sec_id[$j]; + $segment_sec_id[$j] = 0; + } + }; + + + # this may alter the section-keys + $multiple_toc = 1 if ($MULTIPLE_FILES && $ROOTED && (/$toc_mark/)); + + + #RRM : Should this be done here, or in \stepcounter ? + @curr_sec_id = &new_level($current_depth, @curr_sec_id); + + $toc_sec_title = $TITLE = $top_sec = ''; + $i+=5; #skip to next text section + } + $open_tags_R = []; + $open_all = ''; + + $_ = undef; + $_ = &make_footnotes if ($footnotes); + $CURRENT_FILE = ''; + print OUTPUT; + close OUTPUT; + + +# # this may alter the section-keys +# &adjust_root_keys if $multiple_toc; + + if ($PREPROCESS_IMAGES) { &preprocess_images } + else { &make_image_file } + print STDOUT "\n *** making images ***" if ($VERBOSITY > 1); + &make_images; + + # Link sections, add head/body/address do cross-refs etc + print STDOUT "\n *** post-process ***" if ($VERBOSITY > 1); + &post_process; + + if (defined &document_post_post_process) { + #BRM: extra document-wide post-processing + print STDOUT "\n *** post-processing Document ***" if ($VERBOSITY > 1); + &document_post_post_process(); + } + + print STDOUT "\n *** post-processed ***" if ($VERBOSITY > 1); + ©_icons if $LOCAL_ICONS; + if ($SEGMENT || $DEBUG || $SEGMENTED) { + &save_captions_in_file("figure", $figure_captions) if $figure_captions; + &save_captions_in_file("table", $table_captions) if $table_captions; +# &save_array_in_file ("captions", "figure_captions", 0, %figure_captions) if %figure_captions; +# &save_array_in_file ("captions", "table_captions", 0, %table_captions) if %table_captions; + &save_array_in_file ("index", "index", 0, %index); + &save_array_in_file ("sections", "section_info", 0, %section_info); + &save_array_in_file ("contents", "toc_section_info", 0,%toc_section_info); + &save_array_in_file ("index", "sub_index", 1, %sub_index) if %sub_index; + &save_array_in_file ("index", "index_labels", 1, %index_labels) if %index_labels; + &save_array_in_file ("index", "index_segment", 1, %index_segment) if %index_segment; + &save_array_in_file ("index", "printable_key", 1, %printable_key) + if (%printable_key || %index_segment); + } + elsif ($MULTIPLE_FILES && $ROOTED) { + &save_array_in_file ("sections", "section_info", 0, %section_info); + &save_array_in_file ("contents", "toc_section_info", 0, %toc_section_info); + } + &save_array_in_file ("internals", "ref_files", 0, %ref_files) if $changed; + &save_array_in_file ("labels", "external_labels", 0, %ref_files); + &save_array_in_file ("labels", "external_latex_labels", 1, %latex_labels); + &save_array_in_file ("images", "cached_env_img", 0, %cached_env_img); +} + +# RRM: +sub translate_preamble { + local($_) = @_; + $PREAMBLE = 1; + $NESTING_LEVEL=0; #counter for TeX group nesting level + # remove some artificially inserted constructions + s/\n${tex2html_deferred_rx}\\par\s*${tex2html_deferred_rx2}\n/\n/gm; + s/\\newedcommand(<<\d+>>)([A-Za-z]+|[^A-Za-z])\1(\[\d+\])?(\[[^]]*\])?(<<\d+>>)[\w\W\n]*\5($comment_mark\d*)?//gm; + s/\n{2,}/\n/ogm; + + if (/\\htmlhead/) { + print STDOUT "\nPREAMBLE: discarding...\n$`" if ($VERBOSITY > 4); + local($after) = $&.$'; + # translate segment preamble preceding \htmlhead + &translate_commands(&translate_environments($`)); + # translate \htmlhead and rest of preamble + $_=&translate_commands(&translate_environments($after)); + print STDOUT "\nPREAMBLE: retaining...\n$_" if ($VERBOSITY > 4); + } else { + # translate only preamble here (metacommands etc.) + # there should be no textual results, if so, discard them + &translate_commands(&translate_environments($_)); + print STDOUT "\nPREAMBLE: discarding...\n$_" if ($VERBOSITY > 4); + $_=""; + }; + $_ = &do_AtBeginDocument($_); + if (! $SEGMENT) { $_ = ''} # segmented documents have a heading already + $_; +} + +############################ Processing Environments ########################## + +sub wrap_shorthand_environments { + # This wraps a dummy environment around environments that do not use + # the begin-end convention. The wrapper will force them to be + # evaluated by Latex rather than them being translated. + # Wrap a dummy environment around matching TMPs. + # s/^\$\$|([^\\])\$\$/{$1.&next_wrapper('tex2html_double_dollar')}/ge; + # Wrap a dummy environment around matching $s. + # s/^\$|([^\\])\$/{$1.&next_wrapper('$')}/ge; + # s/tex2html_double_dollar/\$\$/go; + # Do \(s and \[s + # + local($wrapper) = "tex2html_wrap_inline"; # \ensuremath wrapper + print STDOUT "\n *** wrapping environments ***\n" if ($VERBOSITY > 3); + + # MRO: replaced $* with /m + print STDOUT "\\(" if ($VERBOSITY > 3); + s/(^\\[(])|([^\\])(\\[(])/{$2.&make_any_wrapper(1,'',$wrapper).$1.$3}/geom; + print STDOUT "\\)" if ($VERBOSITY > 3); + s/(^\\[)]|[^\\]\\[)])/{$1.&make_any_wrapper(0,'',$wrapper)}/geom; + + print STDOUT "\\[" if ($VERBOSITY > 3); + s/(^\\[[])|([^\\])(\\[[])/{$2.&make_any_wrapper(1,1,"displaymath")}/geom; + print STDOUT "\\]" if ($VERBOSITY > 3); + s/(^\\[\]])|([^\\])(\\[\]])/{$2.&make_any_wrapper(0,1,"displaymath")}/geom; + + print STDOUT "\$" if ($VERBOSITY > 3); + s/$enspair/print "\$"; + {&make_any_wrapper(1,'',$wrapper).$&.&make_any_wrapper(0,'',$wrapper)}/geom; + + $double_dol_rx = '(^|[^\\\\])\\$\\$'; + $single_dol_rx = '(^|[^\\\\])\\$'; + print STDOUT "\$" if ($VERBOSITY > 3); + + local($dollars_remain) = 0; + $_ = &wrap_math_environment; + $_ = &wrap_raw_arg_cmds; +} + +sub wrap_math_environment { + + # This wraps math-type environments + # The trick here is that the opening brace is the same as the close, + # but they *can* still nest, in cases like this: + # + # $ outer stuff ... \hbox{ ... $ inner stuff $ ... } ... $ + # + # Note that the inner pair of $'s is nested within a group. So, to + # handle these cases correctly, we need to make sure that the outer + # brace-level is the same as the inner. --- rst + #tex2html_wrap + # And yet another problem: there is a scungy local idiom to do + # this: $\_$ for a boldfaced underscore. xmosaic can't display the + # resulting itty-bitty bitmap, for some reason; even if it could, it + # would probably come out as an overbar because of the floating- + # baseline problem. So, we have to special case this. --- rst again. + + local ($processed_text, @processed_text, $before, $end_rx, $delim, $ifclosed); + local ($underscore_match_rx) = "^\\s*\\\\\\_\\s*\\\$"; + local ($wrapper); + print STDOUT "\nwrap math:" if ($VERBOSITY > 3); + + #find braced dollars, in tabular-specs + while (/((($O|$OP)\d+($C|$CP))\s*)\$(\s*\2)/) { + push (@processed_text, $`, $1.$dol_mark.$5); + $_ = $'; + } + $_ = join('',@processed_text, $_) if (@processed_text); + undef @processed_text; + + $dollars_remain = 0; + while (/$single_dol_rx/) { + $processed_text .= $`.$1; + $_ = $'; + $wrapper = "tex2html_wrap_inline"; + $end_rx = $single_dol_rx; # Default, unless we begin with $$. + $delim = "\$"; + + if (/^\$/ && (! $`)) { + s/^\$//; + $end_rx = $double_dol_rx; + $delim = ""; # Cannot say "\$\$" inside displaymath + $wrapper = "displaymath"; + + } elsif (/$underscore_match_rx/ && (! $`)) { + + # Special case for $\_$ ... + + s/$underscore_match_rx//; + $processed_text .= '\\_'; + next; + } + + # Have an opening $ or $$. Find matching close, at same bracket level +# $processed_text .= &make_any_wrapper(1,'',$wrapper).$delim; + + print STDOUT "\$" if ($VERBOSITY > 3); + $ifclosed = 0; + local($thismath); + while (/$end_rx/) { + # Forget the $$ if we are going to replace it with "displaymath" + $before = $` . (($wrapper eq "displaymath")? "$1" : $&); + last if ($before =~ /\\(sub)*(item|section|chapter|part|paragraph)(star)?\b/); + $thismath .= $before; + $_ = $'; + s/^( [^\n])/\\space$1/s; #make sure a trailing space doesn't get lost. + + # Found dollar sign inside open subgroup ... now see if it's + # at the same brace-level ... + + local ($losing, $br_rx) = (0, ''); + print STDOUT "\$" if ($VERBOSITY > 3); + while ($before =~ /$begin_cmd_rx/) { + $br_rx = &make_end_cmd_rx($1); $before = $'; + + if ($before =~ /$br_rx/) { $before = $'; } + else { $losing = 1; last; } + } + do { $ifclosed = 1; last } unless $losing; + + # It wasn't ... find the matching close brace farther on; then + # keep going. + + /$br_rx/; + + $thismath .= $`.$&; + + #RRM: may now contain unprocessed $s e.g. $\mbox{...$...$...}$ + # the &do_cmd_mbox uses this specially to force an image + # ...but there may be other situations; e.g. \hbox + # so set a flag: + $dollars_remain = 1; + + $_ = $'; + } + + # Got to the end. Whew! + if ($ifclosed) { + # also process any nested math + while (($dollars_remain)&&($delim eq "\$")) { + local($saved) = $_; + $thismath =~ s/\$$//; + $_ = $thismath; + $thismath = &wrap_math_environment; + $thismath .= "\$"; + $_ = $saved; + } + $processed_text .= &make_any_wrapper(1,'',$wrapper) . $delim + . $thismath . &make_any_wrapper(0,'',$wrapper); + } else { + print STDERR "\n\n *** Error: unclosed math or extra `\$', before:\n$thismath\n\n"; +# # remove a $ to try to recover as much as possible. +# $thismath =~ s/([^\\]\\\\|[^\\])\$/$1\%\%/; +# $_ = $thismath . $_; $thismath = ""; + print "\n$thismath\n\n\n$_\n\n\n"; die; + + } + } + $processed_text . $_; +} + +sub translate_environments { + local ($_) = @_; + local($tmp, $capenv); +# print "\nTranslating environments ..."; + local($after, @processedE); + local ($contents, $before, $br_id, $env, $pattern); + for (;;) { +# last unless (/$begin_env_rx/o); + last unless (/$begin_env_rx|$begin_cmd_rx|\\(selectlanguage)/o); +# local ($contents, $before, $br_id, $env, $pattern); + local($this_env, $opt_arg, $style_info); + $contents = ''; + # $1,$2 : optional argument/text --- stylesheet info + # $3 : br_id (at the beginning of an environment name) + # $4 : environment name + # $5 : br_id of open-brace, when $3 == $4 == ''; + # $6 : \selectlanguage{...} + if ($7) { + push(@processedE,$`); + $_ = $'; + if (defined &do_cmd_selectlanguage) { + $_ = &do_cmd_selectlanguage($_); + } else { + local($cmd) = $7; + $pattern = &missing_braces unless ( + s/$next_pair_rx/$pattern = $2;''/e); + local($trans) = $pattern.'_translation'; + if (defined &$trans) { + &set_default_language($pattern,$_); + } + undef $cmd; undef $trans; + } + next; + } elsif ($4) { + ($before, $opt_arg, $style_info, $br_id + , $env, $after, $pattern) = ($`, $2, $3, $4, $5, $', $&); + if (($before)&& (!($before =~ /$begin_env_rx|$begin_cmd_rx/))) { + push(@processedE,$before); + $_ = $pattern . $after; $before = ''; + } + } else { + ($before, $br_id, $env, $after, $pattern) = ($`, $6, 'group', $', $&); + if (($before)&& (!($before =~ /$begin_env_rx|$begin_cmd_rx/))) { + push(@processedE,$before); + $_ = $pattern . $after; $before = ''; + } + local($end_cmd_rx) = &make_end_cmd_rx($br_id); + if ($after =~ /$end_cmd_rx/) { + # ... find the the matching closing one + $NESTING_LEVEL++; + ($contents, $after) = ($`, $'); + $contents = &process_group_env($contents); + print STDOUT "\nOUT: {$br_id} ".length($contents) if ($VERBOSITY > 3); + print STDOUT "\n:$contents\n" if ($VERBOSITY > 7); + # THIS MARKS THE OPEN-CLOSE DELIMITERS AS PROCESSED + $_ = join("", $before,"$OP$br_id$CP", $contents,"$OP$br_id$CP", $after); + $NESTING_LEVEL--; + } else { + $pattern = &escape_rx_chars($pattern); + s/$pattern//; + print "\nCannot find matching bracket for $br_id"; + $_ = join("", $before,"$OP$br_id$CP", $after); + } + next; + } + $contents = undef; + local($defenv) = $env =~ /deferred/; +# local($color_env); + local($color_env) + unless ($env =~ /tabular|longtable|in(line|display)|math/); + local($closures,$reopens); + local(@save_open_tags) = @$open_tags_R unless ($defenv); + local($open_tags_R) = [ @save_open_tags ] unless ($defenv); + local(@saved_tags) if ($env =~ /tabular|longtable/); + if ($env =~ /tabular|longtable|makeimage|in(line|display)/) { + @save_open_tags = @$open_tags_R; + $open_tags_R = [ @save_open_tags ]; + # check for color + local($color_test) = join(',',@$open_tags_R); + if ($color_test =~ /(color{[^}]*})/g ) { + $color_env = $1; + } # else { $color_env = '' } + + if ($env =~ /tabular|longtable|makeimage/) { + # close to the surrounding block-type tag + ($closures,$reopens,@saved_tags) = &preserve_open_block_tags(); + @save_open_tags = @$open_tags_R; + $open_tags_R = [ @save_open_tags ]; + if ($color_env) { + $color_test = join(',',@saved_tags); + if ($color_test =~ /(color{[^}]*})/g ) { + $color_env = $1; + } + } + } elsif ($env =~ /in(line|display)/) { + $closures = &close_all_tags() if ((&defined_env($env)) + &&!($defenv)&&!($env=~/inline/)&&(!$declarations{$env})); + if ($color_env) { + $color_test = $declarations{$color_env}; + $color_test =~ s/<\/.*$//; + $closures .= "\n$color_test"; + push (@$open_tags_R , $color_env); + } + } + } elsif ($env =~ /alltt|tex2html_wrap/) { + # alltt is constructed as paragraphs, not with
+	    #  tex2html_wrap  creates an image, which is at text-level
+	} else {
+	    $closures = &close_all_tags() if ((&defined_env($env))
+		&&!($defenv)&&(!$declarations{$env}) );
+	}
+	# Sets $contents and modifies $after
+	if (&find_end_env($env,$contents,$after)) {
+	    print STDOUT "\nIN-A {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    &process_command($counters_rx, $before)
+		if ($before =~ /$counters_rx/);
+	    # This may modify $before and $after
+	    # Modifies $contents
+#RRM: the do_env_... subroutines handle when to translate sub-environments
+#	    $contents = &translate_environments($contents) if
+##		((!$defenv) && (&defined_env($env)) && (! $raw_arg_cmds{$env})
+##		&& (!$declarations{$env})
+#		((&defined_env($env)) && (! $raw_arg_cmds{$env})
+#		&& (!($env =~ /latexonly|enumerate|figure|table|makeimage|wrap_inline/))
+#		&& ((! $NO_SIMPLE_MATH)||(!($env =~ /wrap/)))
+#		&& (!($env =~ /(math|wrap|equation|eqnarray|makeimage|minipage|tabular)/) )
+#		);
+	    if ($opt_arg) { 
+		&process_environment(1, $env, $br_id, $style_info); # alters $contents
+	    } else {
+		&process_environment(0, $env, $br_id, '');
+	    }
+	    undef $_;
+	    print STDOUT "\nOUT-A {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    #JCL(jcl-env) - insert the $O$br_id$C stuff to handle environment grouping
+	    if (!($contents eq '')) {
+		$after =~ s/^\n//o if ($defenv);
+		$this_env = join("", $before, $closures
+			  , $contents
+			  , ($defenv ? '': &balance_tags())
+			  , $reopens ); $_ = $after;
+	    } else { 
+		$this_env = join("", $before , $closures
+			  , ($defenv ? '': &balance_tags())
+			  , $reopens ); $_ = $after;
+	    };
+	### Evan Welsh  added the next 24 lines ##
+	} elsif (&defined_env($env)) {
+	    print STDOUT "\nIN-B {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    # If I specify a function for the environment then it
+	    # calls it with the contents truncated at the next section.
+	    # It assumes I know what I'm doing and doesn't give a
+	    # deferred warning.
+	    $contents = $after;
+	    if ($opt_arg) { 
+		$contents = &process_environment(1, $env, $br_id, $style_info);
+	    } else {
+		$contents = &process_environment(0, $env, $br_id, '');
+	    }
+	    print STDOUT "\nOUT-B {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    $this_env = join("", $before, $closures ,$contents, $reopens);
+
+	    # there should not be anything left over 
+#	    $_ = $after;
+	    $_ = '';
+	} elsif ($ignore{$env}) {
+	    print STDOUT "\nIGNORED {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    # If I specify that the environment should be ignored then
+	    # it is but I get a deferred warning.
+	    $this_env = join("", $before , $closures , &balance_tags()
+		      , $contents, $reopens );
+	    $_ = $after;
+	    &write_warnings("\n\\end{$env} not found (ignored).\n");
+	} elsif ($raw_arg_cmds{$env}) {
+	    print "\nIN-C {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    # If I specify that the environment should be passed to tex
+	    # then it is with the environment truncated at the next
+	    # section and I get a deferred warning.
+
+	    $contents = $after;
+	    if ($opt_arg) { 
+		$contents = &process_environment(1, $env, $br_id, $style_info);
+	    } else {
+		$contents = &process_environment(0, $env, $br_id, '');
+	    }
+	    print STDOUT "\nOUT-C {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
+	    $this_env = join("", $before, $closures
+			     , $contents, &balance_tags(), $reopens );
+	    $_='';
+	    &write_warnings(
+	        "\n\\end{$env $br_id} not found (truncated at next section boundary).\n");
+	} else {
+	    $pattern = &escape_rx_chars($pattern);
+	    s/$pattern/$closures/;
+	    print "\nCannot find \\end{$env $br_id}\n";
+	    $_ .= join('', &balance_tags(), $reopens) unless ($defenv);
+	}
+	if ($this_env =~ /$begin_env_rx|$begin_cmd_rx/) {
+	    $_ = $this_env . $_;
+	} else { push (@processedE, $this_env) }
+    }
+    $_ = join('',@processedE) . $_;
+    $tmp = $_; undef $_;
+    &process_command($counters_rx, $tmp) if ($tmp =~ /$counters_rx/);
+    $_ = $tmp; undef $tmp;
+    $_
+}
+
+sub find_end_env {
+    # MRO: find_end_env($env,$contents,$rest)
+    #local ($env, *ref_contents, *rest) = @_;
+    my $env = $_[0];
+    my $be_rx = &make_begin_end_env_rx($env);
+    my $count = 1;
+
+    while ($_[2] =~ /($be_rx)(\n?)/s) { # $rest
+	$_[1] .= $`; # $contents
+
+	if ($2 eq "begin") { ++$count }
+	else { --$count };
+
+	#include any final \n at an {end} only
+	$_[2] = (($2 eq 'end')? $5 : '') . $'; # $rest
+	last if $count == 0;
+
+	$_[1] .= $1; # $contents
+    }
+
+    if ($count != 0) {
+	$_[2] = join('', $_[1], $_[2]); # $rest = join('', $contents, $rest);
+	$_[1] = ''; # $contents
+	return(0)
+    } else { return(1) }
+}
+
+
+sub process_group_env {
+    local($contents) = @_;
+    local(@save_open_tags) = @$open_tags_R;
+    local($open_tags_R) = [ @save_open_tags ];
+    print STDOUT "\nIN::{group $br_id}" if ($VERBOSITY > 4);
+    print STDOUT "\n:$contents\n" if ($VERBOSITY > 6);
+
+    # need to catch explicit local font-changes
+    local(%font_size) = %font_size if (/\\font\b/);
+
+    # record class/id info for a style-sheet entry
+    local($env_id, $tmp, $etmp);
+    if (($USING_STYLES) && !$PREAMBLE ) { $env_id = $br_id; }
+#	$env_id = "grp$br_id";
+#	$styleID{$env_id} = " ";
+#        $env_id = " ID=\"$env_id\"";
+#    }
+
+    undef $_;
+    $contents =~ s/^\s*$par_rx\s*//s; # don't start with a \par 
+    if ($contents =~ /^\s*\\($image_switch_rx)\b\s*/s) {
+	# catch TeX-like environments: {\fontcmd ... }
+	local($image_style) = $1;
+	if ($USING_STYLES) {
+	    $env_style{$image_style} = " " unless ($env_style{$image_style});
+	}
+	local($switch_cmd) = "do_cmd_${image_style}";
+	if (defined &$switch_cmd ) {
+	    eval "\$contents = \&${switch_cmd}(\$')";
+	    print "\n*** &$switch_cmd didn't work: $@\n$contents\n\n" if ($@);
+	} elsif ($contents =~ /$par_rx/) {
+	    # split into separate image for each paragraph
+	    local($par_style,$this_par_img) = '';
+	    local(@par_pieces) = split($par_rx, $contents);
+	    local($this_par,$par_style,$par_comment);
+	    $contents = '';
+	    while (@par_pieces) {
+		$this_par = shift @par_pieces;
+		if ($this_par =~ /^\s*\\($image_switch_rx)\b/s) {
+		    $image_style = $1;
+		    $par_style = 'P.'.$1;
+		    $env_style{$par_style} = " " unless ($env_style{$par_style});
+		}
+#	no comment: source is usually too highly encoded to be meaningful
+#	$par_comment = &make_comment($image_style,$this_par);
+		$this_par_img = &process_in_latex("\{".$this_par."\}");
+		$contents .=  join(''  #,"\n", $par_comment
+			, "\n", $this_par_img
+			, "

\n"); + if (@par_pieces) { + # discard the pieces from matching $par_rx + $dum = shift @par_pieces; + $dum = shift @par_pieces; + $dum = shift @par_pieces; + $dum = shift @par_pieces; + $dum = shift @par_pieces; + $dum = shift @par_pieces; +# $contents .= "\n

\n

"; + } + } + } else { + $contents = &process_undefined_environment("tex2html_accent_inline" + , ++$global{'max_id'},"\{".$contents."\}"); + } + } elsif ($contents =~ /^\s*\\(html)?url\b($O\d+$C)[^<]*\2\s*/) { + # do nothing + $contents = &translate_environments($contents); + $contents = &translate_commands($contents); + } elsif (($env_switch_rx)&&($contents =~ s/^(\s*)\\($env_switch_rx)\b//s)) { + # write directly into images.tex, protected by \begingroup...\endgroup + local($prespace, $cmd, $tmp) = ($1,$2,"do_cmd_$2"); + $latex_body .= "\n\\begingroup "; + if (defined &$tmp) { + eval("\$contents = &do_cmd_$cmd(\$contents)"); + } + $contents = &translate_environments($contents); + $contents = &translate_commands($contents); + undef $tmp; undef $cmd; + $contents .= "\n\\endgroup "; + } elsif ($contents =~ /^\s*\\([a-zA-Z]+)\b/s) { + local($after_cmd) = $'; + local($cmd) = $1; $tmp = "do_cmd_$cmd"; $etmp = "do_env_$cmd"; + if (($cmd =~/^(rm(family)?|normalsize)$/) + ||($declarations{$cmd}&&(defined &$tmp))) { + do{ + local(@save_open_tags) = @$open_tags_R; + eval "\$contents = \&$tmp(\$after_cmd);"; + print "\n*** eval &$tmp failed: $@\n$contents\n\n" if ($@); + $contents .= &balance_tags(); + }; + } elsif ($declarations{$cmd}&&(defined &$etmp)) { + eval "\$contents = \&$etmp(\$after_cmd);"; + } else { + $contents = &translate_environments($contents); + $contents = &translate_commands($contents) + if ($contents =~ /$match_br_rx/o); + # Modifies $contents + &process_command($single_cmd_rx,$contents) if ($contents =~ /\\/o); + } + undef $cmd; undef $tmp; undef $etmp; + } else { + $contents = &translate_environments($contents); + $contents = &translate_commands($contents) + if ($contents =~ /$match_br_rx/o); + # Modifies $contents + &process_command($single_cmd_rx,$contents) + if ($contents =~ /\\/o); + } + $contents . &balance_tags(); +} + +# MODIFIES $contents +sub process_environment { + local($opt, $env, $id, $styles) = @_; + + local($envS) = $env; $envS =~ s/\*\s*$/star/; + local($env_sub,$border,$attribs,$env_id) = ("do_env_$envS",'','',''); + local($original) = $contents; + + if ($env =~ /tex2html_deferred/ ) { + $contents = &do_env_tex2html_deferred($contents); + return ($contents); + } + $env_id = &read_style_info($opt, $env, $id, $styles) + if (($USING_STYLES)&&($opt)); + + if (&defined_env($env)) { + print STDOUT ","; + print STDOUT "{$env $id}" if ($VERBOSITY > 1); +# $env_sub =~ s/\*$/star/; + $contents = &$env_sub($contents); + + } elsif ($env =~ /tex2html_nowrap/) { + #pass it on directly for LaTeX, via images.tex + $contents = &process_undefined_environment($env, $id, $contents); + return ($contents); + +# elsif (&special_env) { # &special_env modifies $contents + } else { + local($no_special_chars) = 0; + local($failed) = 0; + local($has_special_chars) = 0; + &special_env; # modifies $contents + print STDOUT "\n" if ($VERBOSITY > 3); + if ($failed || $has_special_chars) { + $contents = $original; + $failed = 1; + print STDOUT " !failed!\n" if ($VERBOSITY > 3); + } + } + if (($contents) && ($contents eq $original)) { + if ($ignore{$env}) { return(''); } + # Generate picture + if ($contents =~ s/$htmlborder_rx//o) { + $attribs = $2; $border = (($4)? "$4" : 1) + } elsif ($contents =~ s/$htmlborder_pr_rx//o) { + $attribs = $2; $border = (($4)? "$4" : 1) + } + $contents = &process_undefined_environment($env, $id, $contents); + $env_sub = "post_latex_$env_sub"; # i.e. post_latex_do_env_ENV + if ( defined &$env_sub) { + $contents = &$env_sub($contents); + } elsif (($border||($attributes))&&($HTML_VERSION > 2.1)) { + $contents = &make_table($border,$attribs,'','','',$contents); + } else { + $contents = join('',"
\n",$contents,"\n
") + unless (!($contents)||($inner_math)||($env =~ + /^(tex2html_wrap|tex2html_nowrap|\w*math|eq\w*n)/o )); + } + } + $contents; +} + + +#RRM: This reads the style information contained in the optional argument +# to the \begin command. It is stored to be recovered later as an entry +# within the automatically-generated style-sheet, if $USING_STYLES is set. +# Syntax for this info is: +#