1 #! /usr/bin/perl
2 #
3 # $Id: latex2html.pin,v 1.71 2004/01/06 23:49:54 RRM Exp $
4 #
5 # Comprises patches and revisions by various authors:
6 # See Changes, the log file of LaTeX2HTML.
7 #
8 # Original Copyright notice:
9 #
10 # LaTeX2HTML by Nikos Drakos <nikos@cbl.leeds.ac.uk>
12 # ****************************************************************
13 # LaTeX To HTML Translation **************************************
14 # ****************************************************************
15 # LaTeX2HTML is a Perl program that translates LaTeX source
16 # files into HTML (HyperText Markup Language). For each source
17 # file given as an argument the translator will create a
18 # directory containing the corresponding HTML files.
19 #
20 # The man page for this program is included at the end of this file
21 # and can be viewed using "perldoc latex2html"
22 #
23 # For more information on this program and some examples of its
24 # capabilities visit
25 #
26 # http://www.latex2html.org/
27 #
28 # or see the accompanying documentation in the docs/ directory
29 #
30 # or
31 #
32 # http://www-texdev.ics.mq.edu.au/l2h/docs/manual/
33 #
34 # or
35 #
36 # http://www.cbl.leeds.ac.uk/nikos/tex2html/doc/latex2html/
37 #
38 # Original code written by Nikos Drakos, July 1993.
39 #
40 # Address: Computer Based Learning Unit
41 # University of Leeds
42 # Leeds, LS2 9JT
43 #
44 # Copyright (c) 1993-95. All rights reserved.
45 #
46 #
47 # Extensively modified by Ross Moore, Herb Swan and others
48 #
49 # Address: Mathematics Department
50 # Macquarie University
51 # Sydney, Australia, 2109
52 #
53 # Copyright (c) 1996-2001. All rights reserved.
54 #
55 # See general license in the LICENSE file.
56 #
57 ##########################################################################
59 use 5.003; # refuse to work with old and buggy perl version
60 #use strict;
61 #use diagnostics;
63 # include some perl packages; these come with the standard distribution
64 use Getopt::Long;
65 use Fcntl;
66 use AnyDBM_File;
68 # The following are global variables that also appear in some modules
69 use vars qw($LATEX2HTMLDIR $LATEX2HTMLPLATDIR $SCRIPT
70 %Month %used_icons $inside_tabbing $TABLE_attribs
71 %mathentities $date_name $outer_math $TABLE__CELLPADDING_rx);
73 BEGIN {
74 # print "scanning for l2hdir\n";
75 if($ENV{'LATEX2HTMLDIR'}) {
76 $LATEX2HTMLDIR = $ENV{'LATEX2HTMLDIR'};
77 } else {
78 $ENV{'LATEX2HTMLDIR'} = $LATEX2HTMLDIR = '/usr/share/latex2html';
79 }
81 if($ENV{'LATEX2HTMLPLATDIR'}) {
82 $LATEX2HTMLPLATDIR = $ENV{'LATEX2HTMLPLATDIR'};
83 } else {
84 $LATEX2HTMLPLATDIR = '/usr/share/latex2html'||$LATEX2HTMLDIR;
85 $ENV{'LATEX2HTMLPLATDIR'} = $LATEX2HTMLPLATDIR;
86 }
87 if(-d $LATEX2HTMLPLATDIR) {
88 push(@INC,$LATEX2HTMLPLATDIR);
89 }
91 if(-d $LATEX2HTMLDIR) {
92 push(@INC,$LATEX2HTMLDIR);
93 } else {
94 die qq{Fatal: Directory "$LATEX2HTMLDIR" does not exist.\n};
95 }
96 }
98 use L2hos; # Operating system dependent routines
100 # $^W = 1; # turn on warnings
102 my $RELEASE = '2002-2-1';
103 my ($REVISION) = q$Revision: 1.71 $ =~ /:\s*(\S+)/;
105 # The key, which delimts expressions defined in the environment
106 # depends on the operating system.
107 $envkey = L2hos->pathd();
109 # $dd is the directory delimiter character
110 $dd = L2hos->dd();
112 # make sure the $LATEX2HTMLDIR is on the search-path for forked processes
113 if($ENV{'PERL5LIB'}) {
114 $ENV{'PERL5LIB'} .= "$envkey$LATEX2HTMLDIR"
115 unless($ENV{'PERL5LIB'} =~ m|\Q$LATEX2HTMLDIR\E|o);
116 } else {
117 $ENV{'PERL5LIB'} = $LATEX2HTMLDIR;
118 }
120 # Local configuration, read at runtime
121 # Read the $CONFIG_FILE (usually l2hconf.pm )
122 if($ENV{'L2HCONFIG'}) {
123 require $ENV{'L2HCONFIG'} ||
124 die "Fatal (require $ENV{'L2HCONFIG'}): $!";
125 } else {
126 eval 'use l2hconf';
127 if($@) {
128 die "Fatal (use l2hconf): $@\n";
129 }
130 }
132 # MRO: Changed this to global value in config/config.pl
133 # change these whenever you do a patch to this program and then
134 # name the resulting patch file accordingly
135 # $TVERSION = "2002-2-1";
136 #$TPATCHLEVEL = " beta";
137 #$TPATCHLEVEL = " release";
138 #$RELDATE = "(March 30, 1999)";
139 #$TEX2HTMLV_SHORT = $TVERSION . $TPATCHLEVEL;
141 $TEX2HTMLV_SHORT = $RELEASE;
142 $TEX2HTMLVERSION = "$TEX2HTMLV_SHORT ($REVISION)";
143 $TEX2HTMLADDRESS = "http://www.latex2html.org/";
144 $AUTHORADDRESS = "http://cbl.leeds.ac.uk/nikos/personal.html";
145 #$AUTHORADDRESS2 = "http://www-math.mpce.mq.edu.au/%7Eross/";
146 $AUTHORADDRESS2 = "http://www.maths.mq.edu.au/~ross/";
148 # Set $HOME to what the system considers the home directory
149 $HOME = L2hos->home();
150 push(@INC,$HOME);
152 # flush stdout with every print -- gives better feedback during
153 # long computations
154 $| = 1;
156 # set Perl's subscript separator to LaTeX's illegal character.
157 # (quite defensive but why not)
158 $; = "\000";
160 # No arguments!!
161 unless(@ARGV) {
162 die "Error: No files to process!\n";
163 }
165 # Image prefix
166 $IMAGE_PREFIX = '_image';
168 # Partition prefix
169 $PARTITION_PREFIX = 'part_' unless $PARTITION_PREFIX;
171 # Author address
172 @address_data = &address_data('ISO');
173 $ADDRESS = "$address_data[0]\n$address_data[1]";
175 # ensure non-zero defaults
176 $MAX_SPLIT_DEPTH = 4 unless ($MAX_SPLIT_DEPTH);
177 $MAX_LINK_DEPTH = 4 unless ($MAX_LINK_DEPTH);
178 $TOC_DEPTH = 4 unless ($TOC_DEPTH);
180 # A global value may already be set in the $CONFIG_FILE
181 $INIT_FILE_NAME = $ENV{'L2HINIT_NAME'} || '.latex2html-init'
182 unless $INIT_FILE_NAME;
184 # Read the $HOME/$INIT_FILE_NAME if one is found
185 if (-f "$HOME$dd$INIT_FILE_NAME" && -r _) {
186 print "Note: Loading $HOME$dd$INIT_FILE_NAME\n";
187 require("$HOME$dd$INIT_FILE_NAME");
188 $INIT_FILE = "$HOME$dd$INIT_FILE_NAME";
189 # _MRO_TODO_: Introduce a version to be checked?
190 die "Error: You have an out-of-date " . $HOME .
191 "$dd$INIT_FILE_NAME file.\nPlease update or delete it.\n"
192 if ($DESTDIR eq '.');
193 }
195 # Read the $INIT_FILE_NAME file if one is found in current directory
196 if ( L2hos->Cwd() ne $HOME && -f ".$dd$INIT_FILE_NAME" && -r _) {
197 print "Note: Loading .$dd$INIT_FILE_NAME\n";
198 require(".$dd$INIT_FILE_NAME");
199 $INIT_FILE = "$INIT_FILE_NAME";
200 }
201 die "Error: '.' is an incorrect setting for DESTDIR.\n" .
202 "Please check your $INIT_FILE_NAME file.\n"
203 if ($DESTDIR eq '.');
205 # User home substitutions
206 $LATEX2HTMLSTYLES =~ s/~([$dd$dd$envkey]|$)/$HOME$1/go;
207 # the next line fails utterly on non-UNIX systems
208 $LATEX2HTMLSTYLES =~ s/~([^$dd$dd$envkey]+)/L2hos->home($1)/geo;
210 #absolutise the paths
211 $LATEX2HTMLSTYLES = join($envkey,
212 map(L2hos->Make_directory_absolute($_),
213 split(/$envkey/o, $LATEX2HTMLSTYLES)));
215 #HWS: That was the last reference to HOME. Now set HOME to $LATEX2HTMLDIR,
216 # to enable dvips to see that version of .dvipsrc! But only if we
217 # have DVIPS_MODE not set - yes - this is a horrible nasty kludge
218 # MRO: The file has to be updated by configure _MRO_TODO_
220 if ($PK_GENERATION && ! $DVIPS_MODE) {
221 $ENV{HOME} = $LATEX2HTMLDIR;
222 delete $ENV{PRINTER}; # Overrides .dvipsrc
223 }
225 # language of the DTD specified in the <DOCTYPE...> tag
226 $ISO_LANGUAGE = 'EN' unless $ISO_LANGUAGE;
228 # Save the command line arguments, quote where necessary
229 $argv = join(' ', map {/[\s#*!\$%]/ ? "'$_'" : $_ } @ARGV);
231 # Pre-process the command line for backward compatibility
232 foreach(@ARGV) {
233 s/^--?no_/-no/; # replace e.g. no_fork by nofork
234 # s/^[+](\d+)$/$1/; # remove + in front of integers
235 }
237 # Process command line options
238 my %opt;
239 unless(GetOptions(\%opt, # all non-linked options go into %opt
240 # option linkage (optional)
241 'help|h',
242 'version|V',
243 'split=s',
244 'link=s',
245 'toc_depth=i', \$TOC_DEPTH,
246 'toc_stars!', \$TOC_STARS,
247 'short_extn!', \$SHORTEXTN,
248 'iso_language=s', \$ISO_LANGUAGE,
249 'validate!', \$HTML_VALIDATE,
250 'latex!',
251 'djgpp!', \$DJGPP,
252 'fork!', \$CAN_FORK,
253 'external_images!', \$EXTERNAL_IMAGES,
254 'ascii_mode!', \$ASCII_MODE,
255 'lcase_tags!', \$LOWER_CASE_TAGS,
256 'ps_images!', \$PS_IMAGES,
257 'font_size=s', \$FONT_SIZE,
258 'tex_defs!', \$TEXDEFS,
259 'navigation!',
260 'top_navigation!', \$TOP_NAVIGATION,
261 'bottom_navigation!', \$BOTTOM_NAVIGATION,
262 'auto_navigation!', \$AUTO_NAVIGATION,
263 'index_in_navigation!', \$INDEX_IN_NAVIGATION,
264 'contents_in_navigation!', \$CONTENTS_IN_NAVIGATION,
265 'next_page_in_navigation!', \$NEXT_PAGE_IN_NAVIGATION,
266 'previous_page_in_navigation!', \$PREVIOUS_PAGE_IN_NAVIGATION,
267 'footnode!',
268 'numbered_footnotes!', \$NUMBERED_FOOTNOTES,
269 'prefix=s', \$PREFIX,
270 'auto_prefix!', \$AUTO_PREFIX,
271 'long_titles=i', \$LONG_TITLES,
272 'custom_titles!', \$CUSTOM_TITLES,
273 'title|t=s', \$TITLE,
274 'rooted!', \$ROOTED,
275 'rootdir=s',
276 'dir=s', \$FIXEDDIR,
277 'mkdir', \$MKDIR,
278 'address=s', \$ADDRESS,
279 'noaddress',
280 'subdir!',
281 'info=s', \$INFO,
282 'noinfo',
283 'auto_link!',
284 'reuse=i', \$REUSE,
285 'noreuse',
286 'antialias_text!', \$ANTI_ALIAS_TEXT,
287 'antialias!', \$ANTI_ALIAS,
288 'transparent!', \$TRANSPARENT_FIGURES,
289 'white!', \$WHITE_BACKGROUND,
290 'discard!', \$DISCARD_PS,
291 'image_type=s', \$IMAGE_TYPE,
292 'images!',
293 'accent_images=s', \$ACCENT_IMAGES,
294 'noaccent_images',
295 'style=s', \$STYLESHEET,
296 'parbox_images!',
297 'math!',
298 'math_parsing!',
299 'latin!',
300 'entities!', \$USE_ENTITY_NAMES,
301 'local_icons!', \$LOCAL_ICONS,
302 'scalable_fonts!', \$SCALABLE_FONTS,
303 'images_only!', \$IMAGES_ONLY,
304 'show_section_numbers!',\$SHOW_SECTION_NUMBERS,
305 'show_init!', \$SHOW_INIT_FILE,
306 'init_file=s', \$INIT_FILE,
307 'up_url=s', \$EXTERNAL_UP_LINK,
308 'up_title=s', \$EXTERNAL_UP_TITLE,
309 'down_url=s', \$EXTERNAL_DOWN_LINK,
310 'down_title=s', \$EXTERNAL_DOWN_TITLE,
311 'prev_url=s', \$EXTERNAL_PREV_LINK,
312 'prev_title=s', \$EXTERNAL_PREV_TITLE,
313 'index=s', \$EXTERNAL_INDEX,
314 'biblio=s', \$EXTERNAL_BIBLIO,
315 'contents=s', \$EXTERNAL_CONTENTS,
316 'external_file=s', \$EXTERNAL_FILE,
317 'short_index!', \$SHORT_INDEX,
318 'unsegment!', \$UNSEGMENT,
319 'debug!', \$DEBUG,
320 'tmp=s', \$TMP,
321 'ldump!', \$LATEX_DUMP,
322 'timing!', \$TIMING,
323 'verbosity=i', \$VERBOSITY,
324 'html_version=s', \$HTML_VERSION,
325 'strict!', \$STRICT_HTML,
326 'xbit!', \$XBIT_HACK,
327 'ssi!', \$ALLOW_SSI,
328 'php!', \$ALLOW_PHP,
329 'test_mode!' # undocumented switch
330 )) {
331 &usage();
332 exit 1;
333 }
335 # interpret options, check option consistency
336 if(defined $opt{'split'}) {
337 if ($opt{'split'} =~ /^(\+?)(\d+)$/) {
338 $MAX_SPLIT_DEPTH = $2;
339 if ($1) { $MAX_SPLIT_DEPTH *= -1; $REL_DEPTH = 1; }
340 } else {
341 &usage;
342 die "Error: Unrecognised value for -split: $opt{'split'}\n";
343 }
344 }
345 if(defined $opt{'link'}) {
346 if ($opt{'link'} =~ /^(\+?)(\d+)$/) {
347 $MAX_LINK_DEPTH = $2;
348 if ($1) { $MAX_LINK_DEPTH *= -1 }
349 } else {
350 &usage;
351 die "Error: Unrecognised value for -link: $opt{'link'}\n";
352 }
353 }
354 unless ($ISO_LANGUAGE =~ /^[A-Z.]+$/) {
355 die "Error: Language (-iso_language) must be uppercase and dots only: $ISO_LANGUAGE\n";
356 }
357 if ($HTML_VALIDATE && !$HTML_VALIDATOR) {
358 die "Error: Need a HTML_VALIDATOR when -validate is specified.\n";
359 }
360 &set_if_false($NOLATEX,$opt{latex}); # negate the option...
361 if ($ASCII_MODE || $PS_IMAGES) {
362 $EXTERNAL_IMAGES = 1;
363 }
364 if ($FONT_SIZE && $FONT_SIZE !~ /^\d+pt$/) {
365 die "Error: Font size (-font_size) must end with 'pt': $FONT_SIZE\n"
366 }
367 &set_if_false($NO_NAVIGATION,$opt{navigation});
368 &set_if_false($NO_FOOTNODE,$opt{footnode});
369 if (defined $TITLE && !length($TITLE)) {
370 die "Error: Empty title (-title).\n";
371 }
372 if ($opt{rootdir}) {
373 $ROOTED = 1;
374 $FIXEDDIR = $opt{rootdir};
375 }
376 if ($FIXEDDIR && !-d $FIXEDDIR) {
377 if ($MKDIR) {
378 print "\n *** creating directory: $FIXEDDIR ";
379 die "Failed: $!\n" unless (mkdir($FIXEDDIR, 0755));
380 # _TODO_ use File::Path to create a series of directories
381 } else {
382 &usage;
383 die "Error: Specified directory (-rootdir, -dir) does not exist.\n";
384 }
385 }
386 &set_if_false($NO_SUBDIR, $opt{subdir});
387 &set_if_false($NO_AUTO_LINK, $opt{auto_link});
388 if ($opt{noreuse}) {
389 $REUSE = 0;
390 }
391 unless(grep(/^\Q$IMAGE_TYPE\E$/o, @IMAGE_TYPES)) {
392 die <<"EOF";
393 Error: No such image type '$IMAGE_TYPE'.
394 This installation supports (first is default): @IMAGE_TYPES
395 EOF
396 }
397 &set_if_false($NO_IMAGES, $opt{images});
398 if ($opt{noaccent_images}) {
399 $ACCENT_IMAGES = '';
400 }
401 if($opt{noaddress}) {
402 $ADDRESS = '';
403 }
404 if($opt{noinfo}) {
405 $INFO = 0;
406 }
407 if($ACCENT_IMAGES && $ACCENT_IMAGES !~ /^[a-zA-Z,]+$/) {
408 die "Error: Single word or comma-list of style words needed for -accent_images, not: $_\n";
409 }
410 &set_if_false($NO_PARBOX_IMAGES, $opt{parbox_images});
411 &set_if_false($NO_SIMPLE_MATH, $opt{math});
412 if (defined $opt{math_parsing}) {
413 $NO_MATH_PARSING = !$opt{math_parsing};
414 $NO_SIMPLE_MATH = !$opt{math_parsing} unless(defined $opt{math});
415 }
416 &set_if_false($NO_ISOLATIN, $opt{latin});
417 if ($INIT_FILE) {
418 if (-f $INIT_FILE && -r _) {
419 print "Note: Initialising with file: $INIT_FILE\n"
420 if ($DEBUG || $VERBOSITY);
421 require($INIT_FILE);
422 } else {
423 die "Error: Could not find file (-init_file): $INIT_FILE\n";
424 }
425 }
426 foreach($EXTERNAL_UP_LINK, $EXTERNAL_DOWN_LINK, $EXTERNAL_PREV_LINK,
427 $EXTERNAL_INDEX, $EXTERNAL_BIBLIO, $EXTERNAL_CONTENTS) {
428 $_ ||= ''; # initialize
429 s/~/~/g; # protect `~'
430 }
431 if($TMP && !(-d $TMP && -w _)) {
432 die "Error: '$TMP' not usable as temporary directory.\n";
433 }
434 if ($opt{help}) {
435 L2hos->perldoc($SCRIPT);
436 exit 0;
437 }
438 if ($opt{version}) {
439 &banner();
440 exit 0;
441 }
442 if ($opt{test_mode}) {
443 return; # make /usr/bin/latex2html non-exploitable
444 $TITLE = 'LaTeX2HTML Test Document';
445 $TEXEXPAND = "$PERL /build/buildd/latex2html-2002-2-1-20050114${dd}texexpand";
446 $PSTOIMG = "$PERL /build/buildd/latex2html-2002-2-1-20050114${dd}pstoimg";
447 $ICONSERVER = L2hos->path2URL("/build/buildd/latex2html-2002-2-1-20050114${dd}icons");
448 $TEST_MODE = 1;
449 $RGBCOLORFILE = "/build/buildd/latex2html-2002-2-1-20050114${dd}styles${dd}rgb.txt";
450 $CRAYOLAFILE = "/build/buildd/latex2html-2002-2-1-20050114${dd}styles${dd}crayola.txt";
451 }
452 if($DEBUG) {
453 # make the OS-dependent functions more chatty, too
454 $L2hos::Verbose = 1;
455 }
457 undef %opt; # not needed any more
460 $FIXEDDIR = $FIXEDDIR || $DESTDIR || ''; # for backward compatibility
462 if ($EXTERNAL_UP_TITLE xor $EXTERNAL_UP_LINK) {
463 warn "Warning (-up_url, -up_title): Need to specify both a parent URL and a parent title!\n";
464 $EXTERNAL_UP_TITLE = $EXTERNAL_UP_LINK = "";
465 }
467 if ($EXTERNAL_DOWN_TITLE xor $EXTERNAL_DOWN_LINK) {
468 warn "Warning (-down_url, -down_title): Need to specify both a parent URL and a parent title!\n";
469 $EXTERNAL_DOWN_TITLE = $EXTERNAL_DOWN_LINK = "";
470 }
472 # $NO_NAVIGATION = 1 unless $MAX_SPLIT_DEPTH; # Martin Wilck
474 if ($MAX_SPLIT_DEPTH && $MAX_SPLIT_DEPTH < 0) {
475 $MAX_SPLIT_DEPTH *= -1; $REL_DEPTH = 1;
476 }
477 if ($MAX_LINK_DEPTH && $MAX_LINK_DEPTH < 0) {
478 $MAX_LINK_DEPTH *= -1; $LEAF_LINKS = 1;
479 }
481 $FOOT_FILENAME = 'footnode' unless ($FOOT_FILENAME);
482 $NO_FOOTNODE = 1 unless ($MAX_SPLIT_DEPTH || $NO_FOOTNODE);
483 $NO_SPLIT = 1 unless $MAX_SPLIT_DEPTH; # _MRO_TODO_: is this needed at all?
484 $SEGMENT = $SEGMENTED = 0;
485 $NO_MATH_MARKUP = 1;
487 # specify the filename extension to use with the generated HTML files
488 if ($SHORTEXTN) { $EXTN = ".htm"; } # for HTML files on CDROM
489 elsif ($ALLOW_PHP) { $EXTN = ".php"; } # has PHP dynamic includes
490 # with server-side includes (SSI) :
491 elsif ($ALLOW_SSI && !$XBIT_HACK) { $EXTN = ".shtml"; }
492 # ordinary names, valid also for SSI with XBit hack :
493 else { $EXTN = ".html"; }
495 $NODE_NAME = 'node' unless (defined $NODE_NAME);
497 # space for temporary files
498 # different to the $TMPDIR for image-generation
499 # MRO: No directory should end with $dd!
500 $TMP_ = "TMP";
502 $TMP_PREFIX = "l2h" unless ($TMP_PREFIX);
504 # This can be set to 1 when using a version of dvips that is safe
505 # from the "dot-in-name" bug.
506 # _TODO_ this should be determined by configure
507 $DVIPS_SAFE = 1;
509 $CHARSET = $charset || 'iso-8859-1';
511 ####################################################################
512 #
513 # If possible, use icons of the same type as generated images
514 #
515 if ($IMAGE_TYPE && defined %{"icons_$IMAGE_TYPE"}) {
516 %icons = %{"icons_$IMAGE_TYPE"};
517 }
519 ####################################################################
520 #
521 # Figure out what options we need to pass to DVIPS and store that in
522 # the $DVIPSOPT variable. Also, scaling is taken care of at the
523 # dvips level if PK_GENERATION is set to 1, so adjust SCALE_FACTORs
524 # accordingly.
525 #
526 if ($SCALABLE_FONTS) {
527 $PK_GENERATION = 0;
528 $DVIPS_MODE = '';
529 }
531 if ($PK_GENERATION) {
532 if ($MATH_SCALE_FACTOR <= 0) { $MATH_SCALE_FACTOR = 2; }
533 if ($FIGURE_SCALE_FACTOR <= 0) { $FIGURE_SCALE_FACTOR = 2; }
534 my $saveMSF = $MATH_SCALE_FACTOR;
535 my $saveFSF = $FIGURE_SCALE_FACTOR;
536 my $desired_dpi = int($MATH_SCALE_FACTOR*75);
537 $FIGURE_SCALE_FACTOR = ($METAFONT_DPI / 72) *
538 ($FIGURE_SCALE_FACTOR / $MATH_SCALE_FACTOR) ;
539 $MATH_SCALE_FACTOR = $METAFONT_DPI / 72;
540 $dvi_mag = int(1000 * $desired_dpi / $METAFONT_DPI);
541 if ($dvi_mag > 1000) {
542 &write_warnings(
543 "WARNING: Your SCALE FACTOR is too large for PK_GENERATION.\n" .
544 " See $CONFIG_FILE for more information.\n");
545 }
547 # RRM: over-sized scaling, using dvi-magnification
548 if ($EXTRA_IMAGE_SCALE) {
549 print "\n *** Images at $EXTRA_IMAGE_SCALE times resolution of displayed size ***\n";
550 $desired_dpi = int($EXTRA_IMAGE_SCALE * $desired_dpi+.5);
551 print " desired_dpi = $desired_dpi METAFONT_DPI = $METAFONT_DPI\n"
552 if $DEBUG;
553 $dvi_mag = int(1000 * $desired_dpi / $METAFONT_DPI);
554 $MATH_SCALE_FACTOR = $saveMSF;
555 $FIGURE_SCALE_FACTOR = $saveFSF;
556 }
557 # no space after "-y", "-D", "-e" --- required by DVIPS under DOS !
558 my $mode_switch = "-mode $DVIPS_MODE" if $DVIPS_MODE;
559 $DVIPSOPT .= " -y$dvi_mag -D$METAFONT_DPI $mode_switch -e5 ";
560 } else { # no PK_GENERATION
561 # if ($EXTRA_IMAGE_SCALE) {
562 # &write_warnings(
563 # "the \$EXTRA_IMAGE_SCALE feature requires either \$PK_GENERATION=1"
564 # . " or the '-scalable_fonts' option");
565 # $EXTRA_IMAGE_SCALE = '';
566 # }
567 # MRO: shifted to l2hconf
568 #$DVIPSOPT .= ' -M';
569 } # end PK_GENERATION
571 # The mapping from numbers to accents.
572 # These are required to process the \accent command, which is found in
573 # tables of contents whenever there is an accented character in a
574 # caption or section title. Processing the \accent command makes
575 # $encoded_*_number work properly (see &extract_captions) with
576 # captions that contain accented characters.
577 # I got the numbers from the plain.tex file, version 3.141.
579 # Missing entries should be looked up by a native speaker.
580 # Have a look at generate_accent_commands and $iso_8859_1_character_map.
582 # MEH: added more accent types
583 # MRO: only uppercase needed!
584 %accent_type = (
585 '18' => 'grave', # \`
586 '19' => 'acute', # `'
587 '20' => 'caron', # \v
588 '21' => 'breve', # \u
589 '22' => 'macr', # \=
590 '23' => 'ring', #
591 '24' => 'cedil', # \c
592 '94' => 'circ', # \^
593 '95' => 'dot', # \.
594 '7D' => 'dblac', # \H
595 '7E' => 'tilde', # \~
596 '7F' => 'uml', # \"
597 );
599 &driver;
601 exit 0; # clean exit, no errors
603 ############################ Subroutines ##################################
605 #check that $TMP is writable, if so create a subdirectory
606 sub make_tmp_dir {
607 &close_dbm_database if $DJGPP; # to save file-handles
609 # determine a suitable temporary path
610 #
611 $TMPDIR = '';
612 my @tmp_try = ();
613 push(@tmp_try, $TMP) if($TMP);
614 push(@tmp_try, "$DESTDIR$dd$TMP_") if($TMP_);
615 push(@tmp_try, $DESTDIR) if($DESTDIR);
616 push(@tmp_try, L2hos->Cwd());
618 my $try;
619 TempTry: foreach $try (@tmp_try) {
620 next unless(-d $try && -w _);
621 my $tmp = "$try$dd$TMP_PREFIX$$";
622 if(mkdir($tmp,0755)) {
623 $TMPDIR=$tmp;
624 last TempTry;
625 } else {
626 warn "Warning: Cannot create temporary directory '$tmp': $!\n";
627 }
628 }
630 $dvips_warning = <<"EOF";
632 Warning: There is a '.' in \$TMPDIR, $DVIPS will probably fail.
633 Set \$TMP to use a /tmp directory, or rename the working directory.
634 EOF
635 die ($dvips_warning . "\n\$TMPDIR=$TMPDIR ***\n\n")
636 if ($TMPDIR =~ /\./ && $DVIPS =~ /dvips/ && !$DVIPS_SAFE);
638 &open_dbm_database if $DJGPP;
639 }
641 # MRO: set first parameter to the opposite of the second if second parameter is defined
642 sub set_if_false {
643 $_[0] = !$_[1] if(defined $_[1]);
644 }
646 sub check_for_dots {
647 local($file) = @_;
648 if ($file =~ /\.[^.]*\./ && !$DVIPS_SAFE) {
649 die "\n\n\n *** Fatal Error --- but easy to fix ***\n"
650 . "\nCannot have '.' in file-name prefix, else dvips fails on images"
651 . "\nChange the name from $file and try again.\n\n";
652 }
653 }
655 # Process each file ...
656 sub driver {
657 local($FILE, $orig_cwd, %unknown_commands, %dependent, %depends_on
658 , %styleID, %env_style, $bbl_cnt, $dbg, %numbered_section);
659 # MRO: $texfilepath has to be global!
660 local(%styles_loaded);
661 $orig_cwd = L2hos->Cwd();
663 print "\n *** initialise *** " if ($VERBOSITY > 1);
664 &initialise; # Initialise some global variables
666 print "\n *** check modes *** " if ($VERBOSITY > 1);
667 &ascii_mode if $ASCII_MODE; # Must come after initialization
668 &titles_language($TITLES_LANGUAGE);
669 &make_numbered_footnotes if ($NUMBERED_FOOTNOTES);
670 $dbg = $DEBUG ? "-debug" : "";
671 $dbg .= (($VERBOSITY>2) ? " -verbose" : "");
673 #use the same hashes for all files in a batch
674 local(%cached_env_img, %id_map, %symbolic_labels, %latex_labels)
675 if ($FIXEDDIR && $NO_SUBDIR);
677 local($MULTIPLE_FILES,$THIS_FILE);
678 $MULTIPLE_FILES = 1+$#ARGV if $ROOTED;
679 print "\n *** $MULTIPLE_FILES file".($MULTIPLE_FILES ? 's: ' : ': ')
680 . join(',',@ARGV) . " *** " if ($VERBOSITY > 1);
682 local(%section_info, %toc_section_info, %cite_info, %ref_files);
684 foreach $FILE (@ARGV) {
685 &check_for_dots($FILE) unless $DVIPS_SAFE;
686 ++$THIS_FILE if $MULTIPLE_FILES;
687 do {
688 %section_info = ();
689 %toc_section_info = ();
690 %cite_info = ();
691 %ref_files = ();
692 } unless $MULTIPLE_FILES;
693 local($bbl_nr) = 1;
695 # The number of reused images and those in images.tex
696 local($global_page_num) = (0) unless($FIXEDDIR && $NO_SUBDIR);
697 # The number of images in images.tex
698 local($new_page_num) = (0); # unless($FIXEDDIR && $NO_SUBDIR);
699 local($pid, $sections_rx,
700 , $outermost_level, %latex_body, $latex_body
701 , %encoded_section_number
702 , %verbatim, %new_command, %new_environment
703 , %provide_command, %renew_command, %new_theorem
704 , $preamble, $aux_preamble, $prelatex, @preamble);
706 # must retain these when all files are in the same directory
707 # else the images.pl and labels.pl files get clobbered
708 unless ($FIXEDDIR && $NO_SUBDIR) {
709 print "\nResetting image-cache" if ($#ARGV);
710 local(%cached_env_img, %id_map, %symbolic_labels, %latex_labels)
711 }
713 ## AYS: Allow extension other than .tex and make it optional
714 ($EXT = $FILE) =~ s/.*\.([^\.]*)$/$1/;
715 if ( $EXT eq $FILE ) {
716 $EXT = "tex";
717 $FILE =~ s/$/.tex/;
718 }
720 #RRM: allow user-customisation, dependent on file-name
721 # e.g. add directories to $TEXINPUTS named for the file
722 # --- idea due to Fred Drake <fdrake@acm.org>
723 &custom_driver_hook($FILE) if (defined &custom_driver_hook);
725 # JCL(jcl-dir)
726 # We need absolute paths for TEXINPUTS here, because
727 # we change the directory
728 if ($orig_cwd eq $texfilepath) {
729 &deal_with_texinputs($orig_cwd);
730 } else {
731 &deal_with_texinputs($orig_cwd, $texfilepath);
732 }
734 ($texfilepath, $FILE) = &get_full_path($FILE);
735 $texfilepath = '.' unless($texfilepath);
737 die "Cannot read $texfilepath$dd$FILE \n"
738 unless (-f "$texfilepath$dd$FILE");
741 # Tell texexpand which files we *don't* want to look at.
742 $ENV{'TEXE_DONT_INCLUDE'} = $DONT_INCLUDE if $DONT_INCLUDE;
743 # Tell texexpand which files we *do* want to look at, e.g.
744 # home-brew style files
745 $ENV{'TEXE_DO_INCLUDE'} = $DO_INCLUDE if $DO_INCLUDE;
747 $FILE =~ s/\.[^\.]*$//; ## AYS
748 $DESTDIR = ''; # start at empty
749 if ($FIXEDDIR) {
750 $DESTDIR = $FIXEDDIR unless ($FIXEDDIR eq '.');
751 if (($ROOTED)&&!($texfilepath eq $orig_cwd)) {
752 $DESTDIR .= $dd . $FILE unless $NO_SUBDIR;
753 };
754 } elsif ($texfilepath eq $orig_cwd) {
755 $DESTDIR = ($NO_SUBDIR ? '.' : $FILE);
756 } else {
757 $DESTDIR = $ROOTED ? '.' : $texfilepath;
758 $DESTDIR .= $dd . $FILE unless $NO_SUBDIR;
759 }
760 $PREFIX = "$FILE-" if $AUTO_PREFIX;
762 print "\nOPENING $texfilepath$dd$FILE.$EXT \n"; ## AYS
764 next unless (&new_dir($DESTDIR,''));
765 # establish absolute path to $DESTDIR
766 $DESTDIR = L2hos->Make_directory_absolute($DESTDIR);
767 &make_tmp_dir;
768 print "\nNote: Working directory is $DESTDIR\n";
769 print "Note: Images will be generated in $TMPDIR\n\n";
771 # Need to clean up a bit in case there's garbage left
772 # from former runs.
773 if ($DESTDIR) { chdir($DESTDIR) || die "$!\n"; }
774 if (opendir (TMP,$TMP_)) {
775 foreach (readdir TMP) {
776 L2hos->Unlink("TMP_$dd$_") unless (/^\.\.?$/);
777 }
778 closedir TMP;
779 }
780 &cleanup(1);
781 unless(-d $TMP_) {
782 mkdir($TMP_, 0755) ||
783 die "Cannot create directory '$TMP_': $!\n";
784 }
785 chdir($orig_cwd);
787 # RRM 14/5/98 moved this to occur earlier
788 ## JCL(jcl-dir)
789 ## We need absolute paths for TEXINPUTS here, because
790 ## we change the directory
791 # if ($orig_cwd eq $texfilepath) {
792 # &deal_with_texinputs($orig_cwd);
793 # } else {
794 # &deal_with_texinputs($orig_cwd, $texfilepath);
795 # }
798 # This needs $DESTDIR to have been created ...
799 print " *** calling `texexpand' ***" if ($VERBOSITY > 1);
800 local($unseg) = ($UNSEGMENT ? "-unsegment " : "");
802 # does DOS need to check these here ?
803 # die "File $TEXEXPAND does not exist or is not executable\n"
804 # unless (-x $TEXEXPAND);
805 L2hos->syswait("$TEXEXPAND $dbg -auto_exclude $unseg"
806 . "-save_styles $DESTDIR$dd$TMP_${dd}styles "
807 . ($TEXINPUTS ? "-texinputs $TEXINPUTS " : '' )
808 . (($VERBOSITY >2) ? "-verbose " : '' )
809 . "-out $DESTDIR$dd$TMP_$dd$FILE "
810 . "$texfilepath$dd$FILE.$EXT")
811 && die " texexpand failed: $!\n";
812 print STDOUT "\n *** `texexpand' done ***\n" if ($VERBOSITY > 1);
814 chdir($DESTDIR) if $DESTDIR;
815 $SIG{'INT'} = 'handler';
817 &open_dbm_database;
818 &initialise_sections;
819 print STDOUT "\n *** database open ***\n" if ($VERBOSITY > 1);
821 if ($IMAGES_ONLY) {
822 &make_off_line_images;
823 } else {
824 &rename_image_files;
825 &load_style_file_translations;
826 &make_language_rx;
827 &make_raw_arg_cmd_rx;
828 # &make_isolatin1_rx unless ($NO_ISOLATIN);
829 &translate_titles;
830 &make_sections_rx;
831 print "\nReading ...";
832 if ($SHORT_FILENAME) {
833 L2hos->Rename ("$TMP_$dd$FILE" ,"$TMP_$dd$SHORT_FILENAME" );
834 &slurp_input_and_partition_and_pre_process(
835 "$TMP_$dd$SHORT_FILENAME");
836 } else {
837 &slurp_input_and_partition_and_pre_process("$TMP_$dd$FILE");
838 }
839 &add_preamble_head;
840 # Create a regular expressions
841 &set_depth_levels;
842 &make_sections_rx;
843 &make_order_sensitive_rx;
844 &add_document_info_page if ($INFO && !(/\\htmlinfo/));
845 &add_bbl_and_idx_dummy_commands;
846 &translate; # Destructive!
847 }
848 &style_sheet;
849 &close_dbm_database;
850 &cleanup();
852 #JCL: read warnings from file to $warnings
853 local($warnings) = &get_warnings;
854 print "\n\n*********** WARNINGS *********** \n$warnings"
855 if ($warnings || $NO_IMAGES || $IMAGES_ONLY);
856 &image_cache_message if ($NO_IMAGES || $IMAGES_ONLY);
857 &image_message if ($warnings =~ /Failed to convert/io);
858 undef $warnings;
860 # JCL - generate directory index entry.
861 # Yet, a hard link, cause Perl lacks symlink() on some systems.
862 do {
863 local($EXTN) = $EXTN;
864 $EXTN =~ s/_\w+(\.html?)/$1/ if ($frame_main_name);
865 local($from,$to) = (eval($LINKPOINT),eval($LINKNAME));
866 if (length($from) && length($to) && ($from ne $to)) {
867 #frames may have altered $EXTN
868 $from =~ s/$frame_main_name(\.html?)/$1/ if ($frame_main_name);
869 $to =~ s/$frame_main_name(\.html?)/$1/ if ($frame_main_name);
870 L2hos->Unlink($to);
871 L2hos->Link($from,$to);
872 }
873 } unless ($NO_AUTO_LINK || !($LINKPOINT) || !($LINKNAME));
875 &html_validate if ($HTML_VALIDATE && $HTML_VALIDATOR);
877 # Go back to the source directory
878 chdir($orig_cwd);
879 $TEST_MODE = $DESTDIR if($TEST_MODE); # save path
880 $DESTDIR = '';
881 $OUT_NODE = 0 unless $FIXEDDIR;
882 $STYLESHEET = '' if ($STYLESHEET =~ /^\Q$FILE./);
883 }
884 print "\nUnknown commands: ". join(" ",keys %unknown_commands)
885 if %unknown_commands;
886 ###MEH -- math support
887 print "\nMath commands outside math: " .
888 join(" ",keys %commands_outside_math) .
889 "\n Output may look weird or may be faulty!\n"
890 if %commands_outside_math;
891 print "\nDone.\n";
892 if($TEST_MODE) {
893 $TEST_MODE =~ s:[$dd$dd]+$::;
894 print "\nTo view the results, point your browser at:\n",
895 L2hos->path2URL(L2hos->Make_directory_absolute($TEST_MODE).$dd.
896 "index$EXTN"),"\n";
897 }
898 $end_time = time;
899 $total_time = $end_time - $start_time;
900 print STDOUT join(' ',"Timing:",$total_time,"seconds\n")
901 if ($TIMING||$DEBUG||($VERBOSITY > 2));
902 $_;
903 }
905 sub open_dbm_database {
906 # These are DBM (unix DataBase Management) arrays which are actually
907 # stored in external files. They are used for communication between
908 # the main process and forked child processes;
909 print STDOUT "\n"; # this mysteriously prevents a core dump !
911 dbmopen(%verb, "$TMP_${dd}verb",0755);
912 # dbmopen(%verbatim, "$TMP_${dd}verbatim",0755);
913 dbmopen(%verb_delim, "$TMP_${dd}verb_delim",0755);
914 dbmopen(%expanded,"$TMP_${dd}expanded",0755);
915 # Holds max_id, verb_counter, verbatim_counter, eqn_number
916 dbmopen(%global, "$TMP_${dd}global",0755);
917 # Hold style sheet information
918 dbmopen(%env_style, "$TMP_${dd}envstyles",0755);
919 dbmopen(%txt_style, "$TMP_${dd}txtstyles",0755);
920 dbmopen(%styleID, "$TMP_${dd}styleIDs",0755);
922 # These next two are used during off-line image conversion
923 # %new_id_map maps image id's to page_numbers of the images in images.tex
924 # %image_params maps image_ids to conversion parameters for that image
925 dbmopen(%new_id_map, "$TMP_${dd}ID_MAP",0755);
926 dbmopen(%img_params, "$TMP_${dd}IMG_PARAMS",0755);
927 dbmopen(%orig_name_map, "$TMP_${dd}ORIG_MAP",0755);
929 $global{'max_id'} = ($global{'max_id'} | 0);
930 &read_mydb(\%verbatim, "verbatim");
931 $global{'verb_counter'} = ($global{'verb_counter'} | 0);
932 $global{'verbatim_counter'} = ($global{'verbatim_counter'} | 0);
934 &read_mydb(\%new_command, "new_command");
935 &read_mydb(\%renew_command, "renew_command");
936 &read_mydb(\%provide_command, "provide_command");
937 &read_mydb(\%new_theorem, "new_theorem");
938 &read_mydb(\%new_environment, "new_environment");
939 &read_mydb(\%dependent, "dependent");
940 # &read_mydb(\%env_style, "env_style");
941 # &read_mydb(\%styleID, "styleID");
942 # MRO: Why should we use read_mydb instead of catfile?
943 $preamble = &catfile(&_dbname("preamble"),1) || '';
944 $prelatex = &catfile(&_dbname("prelatex"),1) || '';
945 $aux_preamble = &catfile(&_dbname("aux_preamble"),1) || '';
946 &restore_critical_variables;
947 }
949 sub close_dbm_database {
950 &save_critical_variables;
951 dbmclose(%verb); undef %verb;
952 # dbmclose(%verbatim); undef %verbatim;
953 dbmclose(%verb_delim); undef %verb_delim;
954 dbmclose(%expanded); undef %expanded;
955 dbmclose(%global); undef %global;
956 dbmclose(%env_style); undef %env_style;
957 dbmclose(%style_id); undef %style_id;
958 dbmclose(%new_id_map); undef %new_id_map;
959 dbmclose(%img_params); undef %img_params;
960 dbmclose(%orig_name_map); undef %orig_name_map;
961 dbmclose(%txt_style); undef %txt_style;
962 dbmclose(%styleID); undef %styleID;
963 }
965 sub clear_images_dbm_database {
966 # <Added calls to dbmclose dprhws>
967 # %new_id_map will be used by the off-line image conversion process
968 #
969 dbmclose(%new_id_map);
970 dbmclose(%img_params);
971 dbmclose(%orig_name_map);
972 undef %new_id_map;
973 undef %img_params;
974 undef %orig_name_map;
975 dbmopen(%new_id_map, "$TMP_${dd}ID_MAP",0755);
976 dbmopen(%img_params, "$TMP_${dd}IMG_PARAMS",0755);
977 dbmopen(%orig_name_map, "$TMP_${dd}ORIG_MAP",0755);
978 }
980 sub initialise_sections {
981 local($key);
982 foreach $key (keys %numbered_section) {
983 $global{$key} = $numbered_section{$key}}
984 }
986 sub save_critical_variables {
987 $global{'math_markup'} = $NO_MATH_MARKUP;
988 $global{'charset'} = $CHARSET;
989 $global{'charenc'} = $charset;
990 $global{'language'} = $default_language;
991 $global{'isolatin'} = $ISOLATIN_CHARS;
992 $global{'unicode'} = $UNICODE_CHARS;
993 if ($UNFINISHED_ENV) {
994 $global{'unfinished_env'} = $UNFINISHED_ENV;
995 $global{'replace_end_env'} = $REPLACE_END_ENV;
996 }
997 $global{'unfinished_comment'} = $UNFINISHED_COMMENT;
998 if (@UNMATCHED_OPENING) {
999 $global{'unmatched'} = join(',',@UNMATCHED_OPENING);
1000 }
1001 }
1003 sub restore_critical_variables {
1004 $NO_MATH_MARKUP = ($global{'math_markup'}|
1005 (defined $NO_MATH_MARKUP ? $NO_MATH_MARKUP:1));
1006 $CHARSET = ($global{'charset'}| $CHARSET);
1007 $charset = ($global{'charenc'}| $charset);
1008 $default_language = ($global{'language'}|
1009 (defined $default_language ? $default_language:'english'));
1010 $ISOLATIN_CHARS = ($global{'isolatin'}|
1011 (defined $ISOLATIN_CHARS ? $ISOLATIN_CHARS:0));
1012 $UNICODE_CHARS = ($global{'unicode'}|
1013 (defined $UNICODE_CHARS ? $UNICODE_CHARS:0));
1014 if ($global{'unfinished_env'}) {
1015 $UNFINISHED_ENV = $global{'unfinished_env'};
1016 $REPLACE_END_ENV = $global{'replace_end_env'};
1017 }
1018 $UNFINISHED_COMMENT = $global{'unfinished_comment'};
1019 if ($global{'unmatched'}) {
1020 @UNMATCHED_OPENING = split(',',$global{'unmatched'});
1021 }
1023 # undef any renewed-commands...
1024 # so the new defs are read from %new_command
1025 local($cmd,$key,$code);
1026 foreach $key (keys %renew_command) {
1027 $cmd = "do_cmd_$key";
1028 $code = "undef \&$cmd"; eval($code) if (defined &$cmd);
1029 if ($@) { print "\nundef \&do_cmd_$cmd failed"}
1030 }
1031 }
1033 #JCL: The warnings should have been handled within the DBM database.
1034 # Unfortunately if the contents of an array are more than ~900 (system
1035 # dependent) chars long then dbm cannot handle it and gives error messages.
1036 sub write_warnings { #clean
1037 my ($str) = @_;
1038 $str .= "\n" unless($str =~ /\n$/);
1039 print STDOUT "\n *** Warning: $str" if ($VERBOSITY > 1);
1040 my $warnings = '';
1041 if(-f 'WARNINGS') {
1042 $warnings = &catfile('WARNINGS') || '';
1043 }
1044 return () if ($warnings =~ /\Q$str\E/);
1045 if(open(OUT,">>WARNINGS")) {
1046 print OUT $str;
1047 close OUT;
1048 } else {
1049 print "\nError: Cannot append to 'WARNINGS': $!\n";
1050 }
1051 }
1053 sub get_warnings {
1054 return &catfile('WARNINGS',1) || '';
1055 }
1057 # MRO: Standardizing
1058 sub catfile {
1059 my ($file,$ignore) = @_;
1060 unless(open(CATFILE,"<$file")) {
1061 print "\nError: Cannot read '$file': $!\n"
1062 unless($ignore);
1063 return undef;
1064 }
1065 local($/) = undef; # slurp in whole file
1066 my $contents = <CATFILE>;
1067 close(CATFILE);
1068 $contents;
1069 }
1072 sub html_validate {
1073 my ($extn) = $EXTN;
1074 if ($EXTN !~ /^\.html?$/i) {
1075 $extn =~ s/^[^\.]*(\.html?)$/$1/;
1076 }
1077 print "\n *** Validating ***\n";
1078 my @htmls = glob("*$extn");
1079 my $file;
1080 foreach $file (@htmls) {
1081 system("$HTML_VALIDATOR $file");
1082 }
1083 }
1085 sub lost_argument {
1086 local($cmd) = @_;
1087 &write_warnings("\nincomplete argument to command: \\$cmd");
1088 }
1091 # These subroutines should have been handled within the DBM database.
1092 # Unfortunately if the contents of an array are more than ~900 (system
1093 # dependent) chars long then dbm cannot handle it and gives error messages.
1094 # So here we save and then read the contents explicitly.
1095 sub write_mydb {
1096 my ($db, $key, $str) = @_;
1097 &write_mydb_simple($db, "\n$mydb_mark#$key#$str");
1098 }
1100 # generate the DB file name from the DB name
1101 sub _dbname {
1102 "$TMP_$dd$_[0]";
1103 }
1105 sub write_mydb_simple {
1106 my ($db, $str) = @_;
1107 my $file = &_dbname($db);
1108 if(open(DB,">>$file")) {
1109 print DB $str;
1110 close DB;
1111 } else {
1112 print "\nError: Cannot append to '$file': $!\n";
1113 }
1114 }
1116 sub clear_mydb {
1117 my ($db) = @_;
1118 my $file = &_dbname($db);
1119 if(open(DB,">$file")) {
1120 close DB;
1121 } else {
1122 print "\nError: Cannot clear '$file': $!\n";
1123 }
1124 }
1126 # Assumes the existence of a DB file which contains
1127 # sequences of e.g. verbatim counters and verbatim contents.
1128 sub read_mydb {
1129 my ($dbref,$name) = @_;
1130 my $contents = &catfile(&_dbname($name),1);
1131 return '' unless(defined $contents);
1132 my @tmp = split(/\n$mydb_mark#([^#]*)#/, $contents);
1133 my $i = 1; # Ignore the first element at 0
1134 print "\nDBM: $name open..." if ($VERBOSITY > 2);
1135 while ($i < scalar(@tmp)) {
1136 my $tmp1 = $tmp[$i];
1137 my $tmp2 = $tmp[++$i];
1138 $$dbref{$tmp1} = defined $tmp2 ? $tmp2 : '';
1139 ++$i;
1140 };
1141 $contents;
1142 }
1145 # Reads in a latex generated file (e.g. .bbl or .aux)
1146 # It returns success or failure
1147 # ****** and binds $_ in the caller as a side-effect ******
1148 sub process_ext_file {
1149 local($ext) = @_;
1150 local($found, $extfile,$dum,$texpath);
1151 $extfile = $EXTERNAL_FILE||$FILE;
1152 local($file) = &fulltexpath("$extfile.$ext");
1153 $found = 0;
1154 &write_warnings(
1155 "\n$extfile.$EXT is newer than $extfile.$ext: Please rerun latex" . ## AYS
1156 (($ext =~ /bbl/) ? " and bibtex.\n" : ".\n"))
1157 if ( ($found = (-f $file)) &&
1158 &newer(&fulltexpath("$extfile.$EXT"), $file)); ## AYS
1159 if ((!$found)&&($extfile =~ /\.$EXT$/)) {
1160 $file = &fulltexpath("$extfile");
1161 &write_warnings(
1162 "\n$extfile is newer than $extfile: Please rerun latex" . ## AYS
1163 (($ext =~ /bbl/) ? " and bibtex.\n" : ".\n"))
1164 if ( ($found = (-f $file)) &&
1165 &newer(&fulltexpath("$extfile"), $file)); ## AYS
1166 }
1168 # check in other directories on the $TEXINPUTS paths
1169 if (!$found) {
1170 foreach $texpath (split /$envkey/, $TEXINPUTS ) {
1171 $file = "$texpath$dd$extfile.$ext";
1172 last if ($found = (-f $file));
1173 }
1174 }
1175 if ( $found ) {
1176 print "\nReading $ext file: $file ...";
1177 # must allow @ within control-sequence names
1178 $dum = &do_cmd_makeatletter();
1179 &slurp_input($file);
1180 if ($ext =~ /bbl/) {
1181 # remove the \newcommand{\etalchar}{...} since not needed
1182 s/^\\newcommand{\\etalchar}[^\n\r]*[\n\r]+//s;
1183 }
1184 &pre_process;
1185 &substitute_meta_cmds if (%new_command || %new_environment);
1186 if ($ext eq "aux") {
1187 my $latex_pathname = L2hos->path2latex($file);
1188 $aux_preamble .=
1189 "\\AtBeginDocument{\\makeatletter\n\\input $latex_pathname\n\\makeatother\n}\n";
1190 local(@extlines) = split ("\n", $_);
1191 print " translating ".(0+@extlines). " lines " if ($VERBOSITY >1);
1192 local($eline,$skip_to); #$_ = '';
1193 foreach $eline (@extlines) {
1194 if ($skip_to) { next unless ($eline =~ s/$O$skip_to$C//) }
1195 $skip_to = '';
1196 # skip lines added for pdfTeX/hyperref compatibility
1197 next if ($eline =~ /^\\(ifx|else|fi|global \\let|gdef|AtEndDocument|let )/);
1198 # remove \index and \label commands, else invalid links may result
1199 $eline =~ s/\\(index|label)\s*($O\d+$C).*\2//g;
1200 if ($eline =~ /\\(old)?contentsline/) {
1201 do { local($_,$save_AUX) = ($eline,$AUX_FILE);
1202 $AUX_FILE = 0;
1203 &wrap_shorthand_environments;
1204 #footnote markers upset the numbering
1205 s/\\footnote(mark|text)?//g;
1206 $eline = &translate_environments($_);
1207 $AUX_FILE = $save_AUX;
1208 undef $_ };
1209 } elsif ($eline =~ s/^\\\@input//) {
1210 &do_cmd__at_input($eline);
1211 $eline = '';
1212 } elsif ($eline =~ s/^\\\@setckpt$O(\d+)$C//) {
1213 $skip_to = $1; next;
1214 }
1215 # $eline =~ s/$image_mark#([^#]+)#/print "\nIMAGE:",$img_params{$1},"\n";''/e;
1216 # $_ .= &translate_commands(&translate_environments($eline));
1217 $_ .= &translate_commands($eline) if $eline;
1218 }
1219 undef @extlines;
1220 } elsif ($ext =~ /$caption_suffixes/) {
1221 local(@extlines) = split ("\n", $_);
1222 print " translating ".(0+@extlines). " lines "if ($VERBOSITY >1);
1223 local($eline); $_ = '';
1224 foreach $eline (@extlines) {
1225 # remove \index and \label commands, else invalid links may result
1226 $eline =~ s/\\(index|label)\s*($O\d+$C).*\2//gso;
1227 if ($eline =~ /\\(old)?contentsline/) {
1228 do { local($_,$save_PREAMBLE) = ($eline,$PREAMBLE);
1229 $PREAMBLE = 0;
1230 &wrap_shorthand_environments;
1231 $eline = &translate_environments($_);
1232 $PREAMBLE = $save_PREAMBLE;
1233 undef $_ };
1234 }
1235 $_ .= &translate_commands($eline);
1236 }
1237 undef @extlines;
1238 } else {
1239 print " wrapping " if ($VERBOSITY >1);
1240 &wrap_shorthand_environments;
1241 $_ = &translate_commands(&translate_environments($_));
1242 print " translating " if ($VERBOSITY >1);
1243 }
1244 print "\n processed size: ".length($_)."\n" if($VERBOSITY>1);
1245 $dum = &do_cmd_makeatother();
1246 } else {
1247 print "\n*** Could not find file: $file ***\n" if ($DEBUG)
1248 };
1249 $found;
1250 }
1252 sub deal_with_texinputs {
1253 # The dot precedes all, this let's local files override always.
1254 # The dirs we want are given as parameter list.
1255 if(!$TEXINPUTS) { $TEXINPUTS = '.' }
1256 elsif ($TEXINPUTS =~ /^$envkey/) {
1257 $TEXINPUTS = '.'.$TEXINPUTS
1258 };
1259 if ($ROOTED) {$TEXINPUTS .= "$envkey$FIXEDDIR"}
1260 $TEXINPUTS = &absolutize_path($TEXINPUTS);
1261 $ENV{'TEXINPUTS'} = join($envkey,".",@_,$TEXINPUTS,$ENV{'TEXINPUTS'});
1262 }
1264 # provided by Fred Drake
1265 sub absolutize_path {
1266 my ($path) = @_;
1267 my $npath = '';
1268 foreach $dir (split /$envkey/o, $path) {
1269 $npath .= L2hos->Make_directory_absolute($dir) . $envkey;
1270 }
1271 $npath =~ s/$envkey$//;
1272 $npath;
1273 }
1275 sub add_document_info_page {
1276 # Uses $outermost_level
1277 # Nasty race conditions if the next two are done in parallel
1278 local($X) = ++$global{'max_id'};
1279 local($Y) = ++$global{'max_id'};
1280 ###MEH -- changed for math support: no underscores in commandnames
1281 $_ = join('', $_
1282 , (($MAX_SPLIT_DEPTH <= $section_commands{$outermost_level})?
1283 "\n<HR>\n" : '')
1284 , "\\$outermost_level", "*"
1285 , "$O$X$C$O$Y$C\\infopagename$O$Y$C$O$X$C\n",
1286 , " \\textohtmlinfopage");
1287 }
1290 # For each style file name in TMP_styles (generated by texexpand) look for a
1291 # perl file in $LATEX2HTMLDIR/styles and load it.
1292 sub load_style_file_translations {
1293 local($_, $style, $options, $dir);
1294 print "\n";
1295 if ($TEXDEFS) {
1296 foreach $dir (split(/$envkey/,$LATEX2HTMLSTYLES)) {
1297 if (-f ($_ = "$dir${dd}texdefs.perl")) {
1298 print "\nLoading $_...";
1299 require ($_);
1300 $styles_loaded{'texdefs'} = 1;
1301 last;
1302 }
1303 }
1304 }
1306 # packages automatically implemented
1307 local($auto_styles) = $AUTO_STYLES;
1308 $auto_styles .= 'array|' if ($HTML_VERSION > 3.1);
1309 $auto_styles .= 'tabularx|' if ($HTML_VERSION > 3.1);
1310 $auto_styles .= 'theorem|';
1312 # these are not packages, but can appear as if class-options
1313 $auto_styles .= 'psamsfonts|';
1314 $auto_styles .= 'noamsfonts|';
1316 $auto_styles =~ s/\|$//;
1318 if(open(STYLES, "<$TMP_${dd}styles")) {
1319 while(<STYLES>) {
1320 if(s/^\s*(\S+)\s*(.*)$/$style = $1; $options = $2;/eo) {
1321 &do_require_package($style);
1322 $_ = $DONT_INCLUDE;
1323 s/:/|/g;
1324 &write_warnings("No implementation found for style \`$style\'\n")
1325 unless ($styles_loaded{$style} || $style =~ /^($_)$/
1326 || $style =~ /$auto_styles/);
1328 # MRO: Process options for packages
1329 &do_package_options($style,$options) if($options);
1330 }
1331 }
1332 close(STYLES);
1333 } else {
1334 print "\nError: Cannot read '$TMP_${dd}styles': $!\n";
1335 }
1336 }
1338 ################## Weird Special case ##################
1340 # The new texexpand can be told to leave in \input and \include
1341 # commands which contain code that the translator should simply pass
1342 # to latex, such as the psfig stuff. These should still be seen by
1343 # TeX, so we add them to the preamble ...
1345 sub do_include_lines {
1346 while (s/$include_line_rx//o) {
1347 local($include_line) = &revert_to_raw_tex($&);
1348 &add_to_preamble ('include', $include_line);
1349 }
1350 }
1352 ########################## Preprocessing ############################
1354 # JCL(jcl-verb)
1355 # The \verb declaration and the verbatim environment contain simulated
1356 # typed text and should not be processed. Characters such as $,\,{,and }
1357 # loose their special meanings and should not be considered when marking
1358 # brackets etc. To achieve this \verb declarations and the contents of
1359 # verbatim environments are replaced by markers. At the end the original
1360 # text is put back into the document.
1361 # The markers for verb and verbatim are different so that these commands
1362 # can be restored to what the raw input was just in case they need to
1363 # be passed to latex.
1365 sub pre_process {
1366 # Modifies $_;
1367 #JKR: We need support for some special environments.
1368 # This has to be here, because they might contain
1369 # structuring commands like \section etc.
1370 local(%comments);
1371 &pre_pre_process if (defined &pre_pre_process);
1372 s/\\\\/\\\\ /go; # Makes it unnecessary to look for escaped cmds
1373 &replace_html_special_chars;
1374 # Remove fake environment which should be invisible to LaTeX2HTML.
1375 s/\001//m;
1376 s/[%]end\s*{latexonly}/\001/gom;
1377 s/[%]begin\s*{latexonly}([^\001]*)\001/%/gos;
1378 s/\001//m;
1380 &preprocess_alltt if defined(&preprocess_alltt);
1382 $KEEP_FILE_MARKERS = 1;
1383 if ($KEEP_FILE_MARKERS) {
1384 # if (s/%%% TEXEXPAND: \w+ FILE( MARKER)? (\S*).*/
1385 # '<tex2html_'.($1?'':'end').'file>'.qq|#$2#|."\n"/em) {
1386 # $_ = "<tex2html_file>#$2#\n". $_ };
1387 #RRM: ignore \n at end of included file, else \par may result
1388 if (s/(\n{1,2})?%%% TEXEXPAND: \w+ FILE( MARKER)? (\S*).*\n?/
1389 ($2?$1:"\n").'<tex2html_'.($2?'':'end').'file>'.qq|#$3#|."\n"/em) {
1390 $_ = "<tex2html_file>#$3#\n". $_ };
1391 } else {
1392 s/%%% TEXEXPAND[^\n]*\n//gm;
1393 }
1395 # Move all LaTeX comments into a local list
1396 s/([ \t]*(^|\G|[^\\]))(%.*(\n[ \t]*|$))/print "%";
1397 $comments{++$global{'verbatim_counter'}} = "$3";
1398 &write_mydb("verbatim", $global{'verbatim_counter'}, $3);
1399 "$1$comment_mark".$global{'verbatim_counter'}."\n"/mge;
1400 # Remove the htmlonly-environment
1401 s/\\begin\s*{htmlonly}\s*\n?//gom;
1402 s/\\end\s*{htmlonly}\s*\n?//gom;
1403 # Remove enviroments which should be invisible to LaTeX2HTML.
1404 s/\n[^%\n]*\\end\s*{latexonly}\s*\n?/\001/gom;
1405 s/((^|\n)[^%\n]*)\\begin\s*{latexonly}([^\001]*)\001/$1/gom;
1406 s/\\end\s*{comment}\s*\n?/\001/gom;
1407 s/\\begin\s*{comment}([^\001]*)\001//gom;
1409 # this used to be earlier, but that can create problems with comments
1410 &wrap_other_environments if (%other_environments);
1412 # s/\\\\/\\\\ /go; # Makes it unnecessary to look for escaped cmds
1413 local($next, $esc_del);
1414 &normalize_language_changes;
1415 # Patches by #JKR, #EI#, #JCL(jcl-verb)
1417 #protect \verb|\begin/end....| parts, for LaTeX documentation
1418 s/(\\verb\*?(.))\\(begin|end)/$1\003$3/g;
1420 local(@processedV);
1421 local($opt, $style_info,$before, $contents, $after, $env);
1422 while (($UNFINISHED_COMMENT)||
1423 (/\\begin\s*($opt_arg_rx)?\s*\{($verbatim_env_rx|$keepcomments_rx)\}/o)) {
1424 ($opt, $style_info) = ($1,$2);
1425 $before=$contents=$after=$env='';
1426 if ($UNFINISHED_COMMENT) {
1427 $UNFINISHED_COMMENT =~ s/([^:]*)::(\d+)/$env=$1;$after=$_;
1428 $before = join("",$unfinished_mark,$env,$2,"#");''/e;
1429 print "\nfound the lost \\end{$env}\n";
1430 }
1431 #RRM: can we avoid copying long strings here ?
1432 # maybe this loop can be an s/.../../s with (.*?)
1433 #
1434 ($before, $after, $env) = ($`, $', $3) unless ($env);
1435 if (!($before =~
1436 /\\begin(\s*\[[^\]]*\]\s*)?\{($verbatim_env_rx|$keepcomments_rx)\}/)) {
1437 push(@processedV,$before);
1438 print "'";$before = '';
1439 }
1440 if ($after =~ /\s*\\end{$env[*]?}/) { # Must NOT use the s///o option!!!
1441 ($contents, $after) = ($`, $');
1442 $contents =~ s/^\n+/\n/s;
1443 # $contents =~ s/\n+$//s;
1445 # re-insert comments
1446 $contents =~ s/$comment_mark(\d+)\n?/$comments{$1}/g;
1447 # $contents =~ s/$comment_mark(\d+)/$verbatim{$1}/g;
1449 # revert '\\ ' -> '\\' only once
1450 if ($env =~ /rawhtml|$keepcomments_rx/i) {
1451 $contents = &revert_to_raw_tex($contents);
1452 } else {
1453 $contents =~ s/([^\\](?:\\\\)*\\)([$html_escape_chars])/$1.&special($2)/geos;
1454 $contents =~ s/\\\\ /\\\\/go;
1455 }
1457 if ($env =~/$keepcomments_rx/) {
1458 $verbatim{++$global{'verbatim_counter'}} = "$contents";
1459 } else {
1460 &write_mydb("verbatim", ++$global{'verbatim_counter'}, $contents);
1461 }
1462 # $verbatim{$global{'verbatim_counter'}} = "$contents" if ($env =~/$keepcomments_rx/);
1463 # $verbatim{$global{'verbatim_counter'}} = "$contents";
1465 if ($env =~ /rawhtml|$keepcomments_rx/i) {
1466 if ($before) {
1467 $after = join("",$verbatim_mark,$env
1468 ,$global{'verbatim_counter'},"#",$after);
1469 } else {
1470 push (@processedV, join("",$verbatim_mark,$env
1471 ,$global{'verbatim_counter'},"#"));
1472 }
1473 } elsif ($env =~ /tex2html_code/) {
1474 if ($before) {
1475 $after = join("","\\begin", $opt, "\{verbatim_code\}"
1476 , $verbatim_mark,$env
1477 , $global{'verbatim_counter'},"#"
1478 , "\\end\{verbatim_code\}",$after);
1479 } else {
1480 push (@processedV
1481 , join("","\\begin", $opt, "\{verbatim_code\}"
1482 , $verbatim_mark,$env
1483 , $global{'verbatim_counter'},"#"
1484 , "\\end\{verbatim_code\}"));
1485 }
1486 } else {
1487 if ($before) {
1488 $after = join("","\\begin", $opt, "\{tex2html_preform\}"
1489 , $verbatim_mark,$env
1490 , $global{'verbatim_counter'},"#"
1491 , "\\end\{tex2html_preform\}",$after);
1492 } else {
1493 push (@processedV
1494 , join("","\\begin", $opt, "\{tex2html_preform\}"
1495 , $verbatim_mark,$env
1496 , $global{'verbatim_counter'},"#"
1497 , "\\end\{tex2html_preform\}" ));
1498 }
1499 }
1500 } else {
1501 print "Cannot find \\end{$env}\n";
1502 $after =~ s/$comment_mark(\d+)\n?/$comments{$1}/g;
1503 # $after =~ s/$comment_mark(\d+)/$verbatim{$1}/g;
1504 if ($env =~ /rawhtml|$keepcomments_rx/i) {
1505 $after = &revert_to_raw_tex($contents);
1506 } else {
1507 $after =~ s/([^\\](?:\\\\)*\\)([$html_escape_chars])/$1.&special($2)/geos;
1508 $after =~ s/\\\\ /\\\\/go;
1509 }
1510 if ($env =~/$keepcomments_rx/) {
1511 $verbatim{++$global{'verbatim_counter'}} = "$after";
1512 } else {
1513 &write_mydb("verbatim", ++$global{'verbatim_counter'}, $after );
1514 }
1515 $after = join("",$unfinished_mark,$env
1516 ,$global{'verbatim_counter'},"#");
1517 }
1518 $_ = join("",$before,$after);
1519 }
1520 print STDOUT "\nsensitive environments found: ".(int(0+@processedV/2))." "
1521 if((@processedV)&&($VERBOSITY > 1));
1522 $_ = join('',@processedV, $_); undef @processedV;
1524 #restore \verb|\begin/end....| parts, for LaTeX documentation
1525 # $_ =~ s/(\\verb\W*?)\003(begin|end)/$1\\$2/g;
1526 $_ =~ s/(\\verb(;SPM\w+;|\W*?))\003(begin|end)/$1\\$3/g;
1528 # Now do the \verb declarations
1529 # Patches by: #JKR, #EI#, #JCL(jcl-verb)
1530 # Tag \verb command and legal opening delimiter with unique number.
1531 # Replace tagged ones and its contents with $verb_mark & id number if the
1532 # closing delimiter can be found. After no more \verb's are to tag, revert
1533 # tagged one's to the original pattern.
1534 local($del,$contents,$verb_rerun);
1535 local($id) = $global{'verb_counter'};
1536 # must tag only one alternation per loop
1537 ##RRM: can this be speeded up using a list ??
1538 my $vbmark = $verb_mark;
1539 while (s/\\verb(\t*\*\t*)(\S)/"<verb$1".++$id.">$2"/e ||
1540 s/\\verb()(\;SPM\w+\;|[^a-zA-Z*\s])/"<verb$1".++$id.">$2"/e ||
1541 s/\\verb(\t\t*)([^*\s])/"<verb$1".++$id.">$2"/e) {
1543 $del = $2;
1544 #RRM: retain knowledge of whether \verb* or \verb
1545 $vb_mark = ($1 =~/^\s*\*/? $verbstar_mark : $verb_mark);
1546 $esc_del = &escape_rx_chars($del);
1547 $esc_del = '' if (length($del) > 2);
1549 # try to find closing delimiter and substitute the complete
1550 # statement with $verb_mark or $verbstar_mark
1551 # s/(<verb[^\d>]*$id>[\Q$del\E])([^$esc_del\n]*)([\Q$del\E]|$comment_mark(\d+)\n?)/
1552 s/(<verb[^\d>]*$id>\Q$del\E)([^$esc_del\n]*?)(\Q$del\E|$comment_mark(\d+)\n?)/
1553 $contents=$2;
1554 if ($4) { $verb_rerun = 1;
1555 join('', "\\verb$del", $contents, $comments{$4})
1556 } else {
1557 $contents =~ s|\\\\ |\\\\|g;
1558 $contents =~ s|\n| |g;
1559 $verb{$id}=$contents;
1560 $verb_delim{$id}=$del;
1561 join('',$vb_mark,$id,$verb_mark)
1562 }
1563 /e;
1564 }
1565 $global{'verb_counter'} = $id;
1566 # revert changes to fake verb statements
1567 s/<verb([^\d>]*)\d+>/\\verb$1/g;
1569 #JKR: the comments include the linebreak and the following whitespace
1570 # s/([^\\]|^)(%.*\n[ \t]*)+/$1/gom; # Remove Comments but not % which may be meaningful
1571 s/((^|\n)$comment_mark(\d+))+//gom; # Remove comment markers on new lines, but *not* the trailing \n
1572 s/(\\\w+|(\W?))($comment_mark\d*\n?)/($2)? $2.$3:($1? $1.' ':'')/egm; # Remove comment markers, not after braces
1573 # s/(\W?)($comment_mark\d*\n?)/($1)? $1.$2:''/egm; # Remove comment markers, not after braces
1574 # Remove comment markers, but *not* the trailing \n
1575 # HWS: Correctly remove multiple %%'s.
1576 #
1577 s/\\%/\002/gm;
1578 # s/(%.*\n[ \t]*)//gm;
1579 s/(%[^\n]*\n)[ \t]*/$comment_mark\n/gm;
1581 s/\002/\\%/gm;
1583 local($tmp1,$tmp2);
1584 s/^$unfinished_mark$keepcomments_rx(\d+)#\n?$verbatim_mark$keepcomments_rx(\d+)#/
1585 $verbatim{$4}."\n\\end{$1}"/egm; # Raw TeX
1586 s/$verbatim_mark$keepcomments_rx(\d+)#/
1587 $tmp1 = $1;
1588 $tmp2 = &protect_after_comments($verbatim{$2});
1589 $tmp2 =~ s!\n$!!s;
1590 join ('', "\\begin{$tmp1}"
1591 , $tmp2
1592 , "\n\\end{$tmp1}"
1593 )/egm; # Raw TeX
1594 s/$unfinished_mark$keepcomments_rx(\d+)#/$UNFINISHED_COMMENT="$1::$2";
1595 "\\begin{$1}\n".$verbatim{$2}/egm; # Raw TeX
1597 $KEEP_FILE_MARKERS = 1;
1598 if ($KEEP_FILE_MARKERS) {
1599 s/%%% TEXEXPAND: \w+ FILE( MARKER) (\S*).*\n/
1600 '<tex2html_'.($1?'':'end').'file>'.qq|#.$2#\n|/gem;
1601 } else {
1602 s/%%% TEXEXPAND[^\n]*\n//gm;
1603 }
1605 &mark_string($_);
1608 # attempt to remove the \html \latex and \latexhtml commands
1609 s/\\latex\s*($O\d+$C)(.*)\1//gm;
1610 s/\\latexhtml\s*($O\d+$C)(.*)\1\s*($O\d+$C)(.*)\3/$4/sg;
1611 s/\\html\s*($O\d+$C)(.*)\1/$2/sg;
1612 s/\\html\s*($O\d+$C)//gm;
1614 # &make_unique($_);
1615 }
1617 # RRM: When comments are retained, then ensure that they are benign
1618 # by removing \s and escaping braces,
1619 # so that environments/bracing cannot become unbalanced.
1620 sub protect_after_comments {
1621 my ($verb_text) = @_;
1622 # $verb_text =~ s/\%(.*)/'%'.&protect_helper($1)/eg;
1623 $verb_text =~ s/(^|[^\\])(\\\\)*\%(.*)/$1.$2.'%'.&protect_helper($3)/emg;
1624 $verb_text;
1625 }
1627 sub protect_helper {
1628 my ($text) = @_;
1629 $text =~ s/\\/ /g;
1630 $text =~ s/(\{|\})/\\$1/g;
1631 $text;
1632 }
1634 sub make_comment {
1635 local($type,$_) = @_;
1636 $_ =~ s/\\(index|label)\s*(($O|$OP)\d+($C|$CP)).*\2//sg;
1637 $_ = &revert_to_raw_tex($_); s/^\n+//m;
1638 $_ =~ s/\\(index|label)\s*\{.*\}//sg;
1639 s/\-\-/- -/g; s/\-\-/- -/g; # cannot have -- inside a comment
1640 $_ = join('', '<!-- ', $type , "\n ", $_ , "\n -->" );
1641 $verbatim{++$global{'verbatim_counter'}} = $_;
1642 &write_mydb('verbatim', $global{'verbatim_counter'}, $_ );
1643 join('', $verbatim_mark, 'verbatim' , $global{'verbatim_counter'},'#')
1644 }
1646 sub wrap_other_environments {
1647 local($key, $env, $start, $end, $opt_env, $opt_start);
1648 foreach $key (keys %other_environments) {
1649 # skip bogus entries
1650 next unless ($env = $other_environments{$key});
1651 $key =~ s/:/($start,$end)=($`,$');':'/e;
1653 if (($end =~ /^\#$/m) && ($start =~ /^\#/m)) {
1654 # catch Indica pre-processor language switches
1655 $opt_start = $';
1656 if ($env =~ s/\[(\w*)\]//o) {
1657 $opt_env = join('','[', ($1 ? $1 : $opt_start ), ']');
1658 }
1659 local($next);
1660 while ($_ =~ /$start\b/) {
1661 push(@pre_wrapped, $`, "\\begin\{pre_$env\}", $opt_env );
1662 $_=$';
1663 if (/(\n*)$end/) {
1664 push(@pre_wrapped, $`.$1,"\\end\{pre_$env\}$1");
1665 $_ = $';
1666 if (!(s/^N(IL)?//o)) {$_ = '#'.$_ }
1667 } else {
1668 print "\n *** unclosed $start...$end chunk ***\n";
1669 last;
1670 }
1671 }
1672 $_ = join('', @pre_wrapped, $_);
1673 undef @pre_wrapped;
1675 } elsif (($end=~/^\n$/) && ($start =~ /^\#/)) {
1676 # catch ITRANS pre-processor language info; $env = 'nowrap';
1677 local($ilang) = $start; $ilang =~ s/^\#//m;
1678 s/$start\s*\=([^<\n%]*)\s*($comment_mark\d*|\n|%)/\\begin\{tex2html_$env\}\\ITRANSinfo\{$ilang\}\{$1\}\n\\end\{tex2html_$env\}$2/g;
1680 } elsif (!$end &&($start =~ /^\#/m)) {
1681 # catch Indica pre-processor input-mode switches
1682 s/$start(.*)\n/\\begin\{tex2html_$env\}$&\\end\{tex2html_$env\}\n/g;
1684 } elsif (($start eq $end)&&(length($start) == 1)) {
1685 $start =~ s/(\W)/\\$1/; $end = $start;
1686 s/([^$end])$start([^$end]+)$end/$1\\begin\{pre_$env\}$2\\end\{pre_$env\}/mg;
1687 } elsif ($start eq $end) {
1688 if (!($start =~ /\#\#/)) {
1689 $start =~ s/(\W)/\\$1/g; $end = $start; }
1690 local (@pre_wrapped);
1691 local($opt); $opt = '[indian]' if ($start =~ /^\#\#$/m);
1692 while ($_ =~ /$start/s) {
1693 push(@pre_wrapped, $` , "\\begin\{pre_$env\}$opt");
1694 $_=$';
1695 if (/$end/s) {
1696 push(@pre_wrapped, $`, "\\end\{pre_$env\}");
1697 $_ = $';
1698 } else {
1699 print "\n *** unclosed $start...$end chunk ***\n";
1700 last;
1701 }
1702 }
1703 $_ = join('', @pre_wrapped, $_);
1704 undef @pre_wrapped;
1705 } elsif ($start && ($env =~ /itrans/)) {
1706 # ITRANS is of this form
1707 local($indic); if($start =~ /\#(\w+)$/m) {$indic = $1}
1708 #include the language-name as an optional parameter
1709 s/$start\b/\\begin\{pre_$env\}\[$indic\]/sg;
1710 s/$end\b/\\end\{pre_$env\}/sg;
1711 } elsif (($start)&&($end)) {
1712 s/$start\b/\\begin\{pre_$env\}/sg;
1713 s/$end\b/\\end\{pre_$env\}/sg;
1714 }
1715 }
1716 $_;
1717 }
1719 #################### Marking Matching Brackets ######################
1721 # Reads the entire input file and performs pre_processing operations
1722 # on it before returning it as a single string. The pre_processing is
1723 # done on separate chunks of the input file by separate Unix processes
1724 # as determined by LaTeX \input commands, in order to reduce the memory
1725 # requirements of LaTeX2HTML.
1726 sub slurp_input_and_partition_and_pre_process {
1727 local($file) = @_;
1728 local(%string, @files, $pos);
1729 local ($count) = 1;
1731 unless(open(SINPUT,"<$file")) {
1732 die "\nError: Cannot read '$file': $!\n";
1733 }
1734 local(@file_string);
1735 print STDOUT "$file" if ($VERBOSITY >1);
1736 while (<SINPUT>) {
1737 if (/TEXEXPAND: INCLUDED FILE MARKER (\S*)/) {
1738 # Forking seems to screw up the rest of the input stream
1739 # We save the current position ...
1740 $pos = tell SINPUT;
1741 print STDOUT " fork at offset $pos " if ($VERBOSITY >1);
1742 $string{'STRING'} = join('',@file_string); @file_string = ();
1743 &write_string_out($count);
1744 delete $string{'STRING'};
1745 # ... so that we can return to it
1746 seek(SINPUT, $pos, 0);
1747 print STDOUT "\nDoing $1 ";
1748 ++$count}
1749 else {
1750 # $string{'STRING'} .= $_
1751 push(@file_string,$_);
1752 }
1753 }
1754 $string{'STRING'} = join('',@file_string); @file_string = ();
1755 &write_string_out($count);
1756 delete $string{'STRING'};
1757 close SINPUT;
1758 @files = ();
1759 if(opendir(DIR, $TMP_)) {
1760 @files = sort grep(/^\Q$PARTITION_PREFIX\E\d+/, readdir(DIR));
1761 closedir(DIR);
1762 }
1764 unless(@files) {
1765 die "\nFailed to read in document parts.\n".
1766 "Look up section Globbing in the troubleshooting manual.\n";
1767 }
1769 $count = 0;
1770 foreach $file (@files) {
1771 print STDOUT "\nappending file: $TMP_$dd$file " if ($VERBOSITY > 1);
1772 $_ .= (&catfile("$TMP_$dd$file") || '');
1773 print STDOUT "\ntotal length: ".length($_)." characters\n" if ($VERBOSITY > 1);
1774 }
1775 die "\nFailed to read in document parts (out of memory?).\n"
1776 unless length($_);
1777 print STDOUT "\ntotal length: ".length($_)." characters\n" if ($VERBOSITY > 1);
1778 }
1780 sub write_string_out {
1781 local($count) = @_;
1782 if ($count < 10) {$count = '00'.$count}
1783 elsif ($count < 100) {$count = '0'.$count}
1784 local($pid);
1785 # All open unflushed streams are inherited by the child. If this is
1786 # not set then the parent will *not* wait
1787 $| = 1;
1788 # fork returns 0 to the child and PID to the parent
1789 &write_mydb_simple("prelatex", $prelatex);
1790 &close_dbm_database;
1791 unless ($CAN_FORK) {
1792 &do_write_string_out;
1793 } else {
1794 unless ($pid = fork) {
1795 &do_write_string_out;
1796 exit 0;
1797 };
1798 waitpid($pid,0);
1799 }
1800 &open_dbm_database;
1801 }
1803 sub do_write_string_out {
1804 local($_);
1805 close (SINPUT) if($CAN_FORK);
1806 &open_dbm_database;
1807 $_ = delete $string{'STRING'};
1808 # locate blank-lines, for paragraphs.
1809 # Replace verbatim environments etc.
1810 &pre_process;
1811 # locate the blank lines for \par s
1812 &substitute_pars;
1813 # Handle newcommand, newenvironment, newcounter ...
1814 &substitute_meta_cmds;
1815 &wrap_shorthand_environments;
1816 print STDOUT "\n *** End-of-partition ***" if ($VERBOSITY > 1);
1817 if(open(OUT, ">$TMP_$dd$PARTITION_PREFIX$count")) {
1818 print OUT $_;
1819 close(OUT);
1820 } else {
1821 print "\nError: Cannot write '$TMP_$dd$PARTITION_PREFIX$count': $!\n";
1822 }
1823 print STDOUT $_ if ($VERBOSITY > 9);
1824 $preamble = join("\n",$preamble,@preamble); # undef @preamble;
1825 &write_mydb_simple("preamble", $preamble);
1826 # this was done earlier; it should not be repeated
1827 #&write_mydb_simple("prelatex", $prelatex);
1828 &write_mydb_simple("aux_preamble", $aux_preamble);
1829 &close_dbm_database;
1830 }
1832 # Reads the entire input file into a
1833 # single string.
1834 sub slurp_input {
1835 local($file) = @_;
1836 local(%string);
1837 if(open(INPUT,"<$file")) {
1838 local(@file_string);
1839 while (<INPUT>) {
1840 push(@file_string, $_ );
1841 }
1842 $string{'STRING'} = join('',@file_string);
1843 close INPUT;
1844 undef @file_string;
1845 } else {
1846 print "\nError: Cannot read '$file': $!\n";
1847 }
1848 $_ = delete $string{'STRING'}; # Blow it away and return the result
1849 }
1851 # MRO: make them more efficient
1852 sub special {
1853 $html_specials{$_[0]} || $_[0];
1854 }
1856 sub special_inv {
1857 $html_specials_inv{$_[0]} || $_[0];
1858 }
1860 sub special_html {
1861 $html_special_entities{$_[0]} || $_[0];
1862 }
1864 sub special_html_inv {
1865 $html_spec_entities_inv{$_[0]} || $_[0];
1866 }
1868 # Mark each matching opening and closing bracket with a unique id.
1869 sub mark_string {
1870 # local (*_) = @_; # Modifies $_ in the caller;
1871 # -> MRO: changed to $_[0] (same effect)
1872 # MRO: removed deprecated $*, replaced by option /m
1873 $_[0] =~ s/(^|[^\\])\\{/$1tex2html_escaped_opening_bracket/gom;
1874 $_[0] =~ s/(^|[^\\])\\{/$1tex2html_escaped_opening_bracket/gom; # repeat this
1875 $_[0] =~ s/(^|[^\\])\\}/$1tex2html_escaped_closing_bracket/gom;
1876 $_[0] =~ s/(^|[^\\])\\}/$1tex2html_escaped_closing_bracket/gom; # repeat this
1877 my $id = $global{'max_id'};
1878 my $prev_id = $id;
1879 # mark all balanced braces
1880 # MRO: This should in fact mark all of them as the hierarchy is
1881 # processed inside-out.
1882 1 while($_[0] =~ s/{([^{}]*)}/join("",$O,++$id,$C,$1,$O,$id,$C)/geo);
1883 # What follows seems esoteric...
1884 my @processedB = ();
1885 # Take one opening brace at a time
1886 while ($_[0] =~ /\{/) {
1887 my ($before,$after) = ($`,$');
1888 my $change = 0;
1889 while (@UNMATCHED_OPENING && $before =~ /\}/) {
1890 my $this = pop(@UNMATCHED_OPENING);
1891 print "\n *** matching brace \#$this found ***\n";
1892 $before =~ s/\}/join("",$O,$this,$C)/eo;
1893 $change = 1;
1894 }
1895 $_[0] = join('',$before,"\{",$after) if($change);
1896 # MRO: mark one opening brace
1897 if($_[0] =~ s/^([^{]*){/push(@processedB,$1);join('',$O,++$id,$C)/eos) {
1898 $before=''; $after=$';
1899 }
1900 if ($after =~ /\}/) {
1901 $after =~ s/\}/join("",$O,$id,$C)/eo;
1902 $_[0] = join('',$before,$O,$id,$C,$after);
1903 } else {
1904 print "\n *** opening brace \#$id is unmatched ***\n";
1905 $after =~ /^(.+\n)(.+\n)?/;
1906 print " preceding: $after \n";
1907 push (@UNMATCHED_OPENING,$id);
1908 }
1909 }
1910 $_[0] = join('',@processedB,$_[0]); undef(@processedB);
1911 print STDOUT "\nInfo: bracketings found: ", $id - $prev_id,"\n"
1912 if ($VERBOSITY > 1);
1913 # process remaining closing braces
1914 while (@UNMATCHED_OPENING && $_[0] =~ /\}/) {
1915 my $this = pop(@UNMATCHED_OPENING);
1916 print "\n *** matching brace \#$this found ***\n";
1917 $_[0] =~ s/\}/join("",$O,$this,$C)/eo;
1918 }
1920 while ($_[0] =~ /\}/) {
1921 print "\n *** there was an unmatched closing \} ";
1922 my ($beforeline,$prevline,$afterline) = ($`, $`.$& , $');
1923 $prevline =~ /\n([^\n]+)\}$/m;
1924 if ($1) {
1925 print "at the end of:\n" . $1 . "\}\n\n";
1926 } else {
1927 $afterline =~ /^([^\n]+)\n/m;
1928 if ($1) {
1929 print "at the start of:\n\}" . $1 ."\n\n";
1930 } else {
1931 $prevline =~ /\n([^\n]+)\n\}$/m;
1932 print "on a line by itself after:\n" . $1 . "\n\}\n\n";
1933 }
1934 }
1935 $_[0] = $beforeline . $afterline;
1936 }
1937 $global{'max_id'} = $id;
1939 # restore escaped braces
1940 $_[0] =~ s/tex2html_escaped_opening_bracket/\\{/go;
1941 $_[0] =~ s/tex2html_escaped_closing_bracket/\\}/go;
1942 }
1944 sub replace_html_special_chars {
1945 # Replaces html special characters with markers unless preceded by "\"
1946 s/([^\\])(<|>|&|\"|``|'')/&special($1).&special($2)/geom;
1947 # MUST DO IT AGAIN JUST IN CASE THERE ARE CONSECUTIVE HTML SPECIALS
1948 s/([^\\])(<|>|&|\"|``|'')/&special($1).&special($2)/geom;
1949 s/^(<|>|&|\"|``|'')/&special($1)/geom;
1950 }
1952 # used in \verbatiminput only: $html_escape_chars = '<>&';
1953 sub replace_all_html_special_chars { s/([$html_escape_chars])/&special($1)/geom; }
1955 # The bibliography and the index should be treated as separate sections
1956 # in their own HTML files. The \bibliography{} command acts as a sectioning command
1957 # that has the desired effect. But when the bibliography is constructed
1958 # manually using the thebibliography environment, or when using the
1959 # theindex environment it is not possible to use the normal sectioning
1960 # mechanism. This subroutine inserts a \bibliography{} or a dummy
1961 # \textohtmlindex command just before the appropriate environments
1962 # to force sectioning.
1963 sub add_bbl_and_idx_dummy_commands {
1964 local($id) = $global{'max_id'};
1966 s/([\\]begin\s*$O\d+$C\s*thebibliography)/$bbl_cnt++; $1/eg;
1967 ## if ($bbl_cnt == 1) {
1968 s/([\\]begin\s*$O\d+$C\s*thebibliography)/$id++; "\\bibliography$O$id$C$O$id$C $1"/geo;
1969 #}
1970 $global{'max_id'} = $id;
1971 s/([\\]begin\s*$O\d+$C\s*theindex)/\\textohtmlindex $1/o;
1972 s/[\\]printindex/\\textohtmlindex /o;
1973 &lib_add_bbl_and_idx_dummy_commands() if defined(&lib_add_bbl_and_idx_dummy_commands);
1974 }
1977 # Uses and modifies $default_language
1978 # This would be straight-forward except when there are
1979 # \MakeUppercase, \MakeLowercase or \uppercase , \lowercase commands
1980 # present in the source. The cases have to be adjusted before the
1981 # ISO-character code is set; e.g. with "z --> "Z in german.perl
1982 #
1983 sub convert_iso_latin_chars {
1984 local($_) = @_;
1985 local($next_language, $pattern);
1986 local($xafter, $before, $after, $funct, $level, $delim);
1987 local(@case_processed);
1988 while (/$case_change_rx/) {
1989 $xafter = $2;
1990 # $before .= $`;
1991 push(@case_processed, $`);
1992 $funct = $3;
1993 $after = '';
1994 $_ = $';
1995 if ($xafter =~ /noexpand/) { $before .= "\\$funct"; next; }
1997 s/^[\s%]*(.)/$delim=$1;''/eo;
1998 if ($delim =~ /{/ ) {
1999 # brackets not yet numbered...
2000 # $before .= $funct . $delim;
2001 push(@case_processed, $funct . $delim);
2002 $level = 1;
2003 $after = $delim;
2004 while (($level)&&($_)&&(/[\{\}]/)) {
2005 $after .= $` . $&;
2006 $_ = $';
2007 if ( "$&" eq "\{" ) {$level++}
2008 elsif ( "$&" eq "\}" ) { $level-- }
2009 else { print $_ }
2010 print "$level";
2011 }
2012 # $before .= $after;
2013 push(@case_processed, $after);
2014 } elsif ($delim eq "<") {
2015 # brackets numbered, but maybe not processed...
2016 s/((<|#)(\d+)(>|#)>).*\1//;
2017 $after .= $delim . $&;
2018 $_ = $';
2019 print STDOUT "\n<$2$funct$4>" if ($VERBOSITY > 2);
2020 $funct =~ s/^\\//o;
2021 local($cmd) = "do_cmd_$funct";
2022 $after = &$cmd($after);
2023 # $before .= $after;
2024 push(@case_processed, $after);
2025 } elsif (($xafter)&&($delim eq "\\")) {
2026 # preceded by \expandafter ...
2027 # ...so expand the following macro first
2028 $funct =~ s/^\\//o;
2029 local($case_change) = $funct;
2030 s/^(\w+|\W)/$funct=$1;''/eo;
2031 local($cmd) = $funct;
2032 local($thiscmd) = "do_cmd_$funct";
2033 if (defined &$thiscmd) { $_ = &$thiscmd($_) }
2034 elsif ($new_command{$funct}) {
2035 local($argn, $body, $opt) = split(/:!:/, $new_command{$funct});
2036 do { ### local($_) = $body;
2037 &make_unique($body);
2038 } if ($body =~ /$O/);
2039 if ($argn) {
2040 do {
2041 local($before) = '';
2042 local($after) = "\\$funct ".$_;
2043 $after = &substitute_newcmd; # may change $after
2044 $after =~ s/\\\@#\@\@/\\/o ;
2045 }
2046 } else { $_ = $body . $_; }
2047 } else { print "\nUNKNOWN COMMAND: $cmd "; }
2049 $cmd = $case_change;
2050 $case_change = "do_cmd_$cmd";
2051 if (defined &$case_change) { $_ = &$case_change($_) }
2052 } else {
2053 # this should not happen, but just in case...
2054 $funct =~ s/^\\//o;
2055 local($cmd) = "do_cmd_$funct";
2056 print STDOUT "\n\n<$delim$funct>" if ($VERBOSITY > 2);
2057 $_ = join('', $delim , $_ );
2058 if (defined &$cmd) { $_ = &$cmd($_) }
2059 }
2060 }
2061 # $_ = join('', $before, $_) if ($before);
2062 $_ = join('', @case_processed, $_) if (@case_processed);
2064 # ...now do the conversions
2065 ($before, $after, $funct) = ('','','');
2066 @case_processed = ();
2067 if (/$language_rx/o) {
2068 ($next_language, $pattern, $before, $after) = (($2||$1), $&, $`, $');
2069 $before = &convert_iso_latin_chars($before) if ($before);
2070 # push(@case_processed, $pattern, $before);
2071 local($br_id) = ++$global{'max_id'};
2072 $pattern = join('' , '\selectlanguage', $O.$br_id.$C
2073 , (($pattern =~ /original/) ? $TITLES_LANGUAGE : $next_language )
2074 , $O.$br_id.$C );
2075 push(@case_processed, $before, $pattern);
2076 push(@language_stack, $default_language);
2077 $default_language = $next_language;
2078 $_ = &convert_iso_latin_chars($after);
2079 $default_language = pop @language_stack;
2080 } else {
2081 $funct = $language_translations{$default_language};
2082 (defined(&$funct) ? $_ = &$funct($_) :
2083 do { &write_warnings(
2084 "\nCould not find translation function for $default_language.\n\n")
2085 }
2086 );
2087 if ($USE_UTF ||(!$NO_UTF &&(defined %unicode_table)&&length(%unicode_table)>2)) {
2088 &convert_to_unicode($_)};
2089 }
2090 $_ = join('', @case_processed, $_); undef(@case_processed);
2091 $_;
2092 }
2094 # May need to add something here later
2095 sub english_translation { $_[0] }
2097 # This replaces \setlanguage{\language} with \languageTeX
2098 # This makes the identification of language chunks easier.
2099 sub normalize_language_changes {
2100 s/$setlanguage_rx/\\$2TeX/gs;
2101 }
2103 sub get_current_language {
2104 return () if ($default_language eq $TITLES_LANGUAGE);
2105 local($lang,$lstyle) = ' LANG="';
2106 $lang_code = $iso_languages{$default_language};
2107 if (%styled_languages) {
2108 $lstyle = $styled_languages{$default_language};
2109 $lstyle = '" CLASS="'.$lstyle if $lstyle;
2110 }
2111 ($lang_code ? $lang.$lang_code.$lstyle.'"' : '');
2112 }
2114 %styled_languages = ();
2116 sub do_cmd_htmllanguagestyle {
2117 local($_) = @_;
2118 local($class) = &get_next_optional_argument;
2119 local($lang) = &missing_braces unless (
2120 (s/$next_pair_pr_rx/$lang=$2;''/e)
2121 ||(s/$next_pair_rx/$lang=$2;''/e));
2122 return ($_) unless $lang;
2123 local($class) = $iso_languages{$lang} unless $class;
2124 if ($USING_STYLES && $class) {
2125 print "\nStyling language: $lang = \"$class\" ";
2126 $styled_languages{"$lang"} = $class;
2127 }
2128 $_;
2129 }
2131 # General translation mechanism:
2132 #
2133 #
2134 # The main program latex2html calls texexpand with the document name
2135 # in order to expand some of its \input and \include statements, here
2136 # also called 'merging', and to write a list of sensitized style, class,
2137 # input, or include file names.
2138 # When texexpand has finished, all is contained in one file, TMP_foo.
2139 # (assumed foo.tex is the name of the document to translate).
2140 #
2141 # In this version, texexpand cares for following environments
2142 # that may span include files / section boundaries:
2143 # (For a more technical description, see texexpand.)
2144 # a) \begin{comment}
2145 # b) %begin{comment}
2146 # c) \begin{any} introduced with \excludecomment
2147 # d) %begin{any}
2148 # e) \begin{verbatim}
2149 # f) \begin{latexonly}
2150 # g) %begin{latexonly}
2151 #
2152 # a)-d) cause texexpand to drop its contents, it will not show up in the
2153 # output file. You can use this to 'comment out' a bunch of files, say.
2154 #
2155 # e)-g) prevent texexpand from expanding input files, but the environment
2156 # content goes fully into the output file.
2157 #
2158 # Together with each merging of \input etc. there are so-called %%%texexpand
2159 # markers accompanying the boundary.
2160 #
2161 # When latex2html reads in the output file, it uses these markers to write
2162 # each part to a separate file, and process them further.
2163 #
2164 #
2165 # If you have, for example:
2166 #
2167 # a) preample
2168 # b) \begin{document}
2169 # c) text
2170 # d) \input{chapter}
2171 # e) more text
2172 # f) \end{document}
2173 #
2174 # you end up in two parts, part 1 is a)-c), part 2 is the rest.
2175 # Regardless of environments spanning input files or sections.
2176 #
2177 #
2178 # What now starts is meta command substitution:
2179 # Therefore, latex2html forks a child process on the first part and waits
2180 # until it finished, then forks another on the next part and so forth
2181 # (see also &slurp_input_and_partition_and_preprocess).
2182 #
2183 # Here's what each child is doing:
2184 # Each child process reads the new commands translated so far by the previous
2185 # child from the TMP_global DBM database.
2186 # After &pre_processing, it substitutes the meta commands (\newcommand, \def,
2187 # and the like) it finds, and adds the freshly retrieved new commands to the
2188 # list so far.
2189 # This is done *only on its part* of the document; this saves upwards of memory.
2190 # Finally, it writes its list of new commands (synopsis and bodies) to the
2191 # DBM database, and exits.
2192 # After the last child finished, latex2html reads in all parts and
2193 # concatenates them.
2194 #
2195 #
2196 # So, at this point in time (start of &translate), it again has the complete
2197 # document, but now preprocessed and with new commands substituted.
2198 # This has several disadvantages: an amount of commands is substituted (in
2199 # TeX lingo, expanded) earlier than the rest.
2200 # This causes trouble if commands really must get expanded at the point
2201 # in time they show up.
2202 #
2203 #
2204 # Then, still in &translate, latex2html uses the list of section commands to
2205 # split the complete document into chunks.
2206 # The chunks are not written to files yet. They are retained in the @sections
2207 # list, but each chunk is handled separately.
2208 # latex2html puts the current chunk to $_ and processes it with
2209 # &translate_environments etc., then fetches the next chunk, and so on.
2210 # This prevents environments that span section boundaries from getting
2211 # translated, because \begin and \end cannot find one another, to say it this
2212 # way.
2213 #
2214 #
2215 # After the chunk is translated to HTML, it is written to a file.
2216 # When all chunks are done, latex2html rereads each file to get cross
2217 # references right, replace image markers with the image file names, and
2218 # writes index and bibliography.
2219 #
2220 #
2221 sub translate {
2222 &normalize_sections; # Deal with the *-form of sectioning commands
2224 # Split the input into sections, keeping the preamble together
2225 # Due to the regular expression, each split will create 5 more entries.
2226 # Entry 1 and 2: non-letter/letter sectioning command,
2227 # entry 4: the delimiter (may be empty)
2228 # entry 5: the text.
2229 local($pre_section, @sections);
2230 if (/\\(startdocument|begin\s*($O\d+$C)\s*document\s*\2)/) {
2231 $pre_section = $`.$&; $_ = $';
2232 }
2233 @sections = split(/$sections_rx/, $_);
2234 $sections[0] = $pre_section.$sections[0] if ($pre_section);
2235 undef $pre_section;
2236 local($sections) = int(scalar(@sections) / 5);
2238 # Initialises $curr_sec_id to a list of 0's equal to
2239 # the number of sectioning commands.
2240 local(@curr_sec_id) = split(' ', &make_first_key);
2241 local(@segment_sec_id) = @curr_sec_id;
2242 local($i, $j, $current_depth) = (0,0,0);
2243 local($curr_sec) = $SHORT_FILENAME||$FILE;
2244 local($top_sec) = ($SEGMENT ? '' : 'top of ');
2245 # local(%section_info, %toc_section_info, $CURRENT_FILE, %cite_info, %ref_files);
2246 local($CURRENT_FILE);
2247 # These filenames may be set when translating the corresponding commands.
2248 local($tocfile, $loffile, $lotfile, $footfile, $citefile, $idxfile,
2249 $figure_captions, $table_captions, $footnotes, $citations, %font_size, %index,
2250 %done, $t_title, $t_author, $t_date, $t_address, $t_affil, $changed);
2251 local(@authors,@affils,@addresses,@emails,@authorURLs);
2252 local(%index_labels, %index_segment, $preindex, %footnotes, %citefiles);
2253 local($segment_table_captions, $segment_figure_captions);
2254 local($dir,$nosave) = ('','');
2255 local($del,$close_all,$open_all,$toc_sec_title,$multiple_toc);
2256 local($open_tags_R) = [];
2257 local(@save_open_tags)= ();
2258 local(@language_stack) = ();
2259 push (@language_stack, $default_language);
2261 # $LATEX_FONT_SIZE = '10pt' unless ($LATEX_FONT_SIZE);
2262 &process_aux_file
2263 if $SHOW_SECTION_NUMBERS || /\\(caption|(html|hyper)?((eq)?ref|cite))/;
2265 require ("${PREFIX}internals.pl") if (-f "${PREFIX}internals.pl");
2266 #JCL(jcl-del)
2267 &make_single_cmd_rx;
2268 #
2269 $tocfile = $EXTERNAL_CONTENTS;
2270 $idxfile = $EXTERNAL_INDEX;
2271 $citefile = $EXTERNAL_BIBLIO; $citefile =~ s/#.*$//;
2272 $citefiles{1} = $citefile if ($citefile);
2273 print "\nTranslating ...";
2275 while ($i <= @sections) {
2276 undef $_;
2277 $_ = $sections[$i];
2278 s/^[\s]*//; # Remove initial blank lines
2280 # The section command was removed when splitting ...
2281 s/^/\\$curr_sec$del/ if ($i > 0); # ... so put it back
2282 if ($current_depth < $MAX_SPLIT_DEPTH) {
2283 if (($footnotes)&&($NO_FOOTNODE)&&( $current_depth < $MAX_SPLIT_DEPTH)) {
2284 local($thesenotes) = &make_footnotes ;
2285 print OUTPUT $thesenotes;
2286 }
2287 $CURRENT_FILE = &make_name($curr_sec, join('_',@curr_sec_id));
2289 open(OUTPUT, ">$CURRENT_FILE")
2290 || die "Cannot write '$CURRENT_FILE': $!\n";
2291 if ($XBIT_HACK) { # use Apache's XBit hack
2292 chmod 0744, $CURRENT_FILE;
2293 &check_htaccess;
2294 } else {
2295 chmod 0644, $CURRENT_FILE;
2296 }
2298 if ($MULTIPLE_FILES && $ROOTED) {
2299 if ($DESTDIR =~ /^\Q$FIXEDDIR\E[$dd$dd]?([^$dd$dd]+)/)
2300 { $CURRENT_FILE = "$1$dd$CURRENT_FILE" };
2301 }
2302 }
2303 &remove_document_env;
2304 # &wrap_shorthand_environments; #RRM Is this needed ?
2305 print STDOUT "\n" if ($VERBOSITY);
2306 print STDOUT "\n" if ($VERBOSITY > 2);
2307 print $i/5,"/$sections";
2308 print ":$top_sec$curr_sec:" if ($VERBOSITY);
2310 # Must do this early ... It also sets $TITLE
2311 &process_command($sections_rx, $_) if (/^$sections_rx/);
2312 # reset tags saved from the previous section
2313 $open_tags_R = [ @save_open_tags ];
2314 @save_open_tags = ();
2316 local($curr_sec_tex);
2317 if ((! $TITLE) || ($TITLE eq $default_title)) {
2318 eval '$TITLE = '.$default_title;
2319 $TITLE = $default_title if $@;
2320 $curr_sec_tex = ($top_sec ? '' :
2321 join('', '"', &revert_to_raw_tex($curr_sec), '"'));
2322 print STDOUT "$curr_sec_tex for $CURRENT_FILE\n" if ($VERBOSITY);
2323 } else {
2324 local($tmp) = &purify($TITLE,1);
2325 $tmp = &revert_to_raw_tex($tmp);
2326 print STDOUT "\"$tmp\" for $CURRENT_FILE\n" if ($VERBOSITY);
2327 }
2329 if (/\\(latextohtmlditchpreceding|startdocument)/m) {
2330 local($after) = $';
2331 local($before) = $`.$&;
2332 $SEGMENT = 1 if ($1 =~ /startdocument/);
2333 print STDOUT "\n *** translating preamble ***\n" if ($VERBOSITY);
2334 $_ = &translate_preamble($before);
2335 s/\n\n//g; s/<BR>//g; # remove redundant blank lines and breaks
2336 #
2337 # &process_aux_file if $AUX_FILE_NEEDED;
2338 #
2339 print STDOUT "\n *** preamble done ***\n" if ($VERBOSITY);
2340 $PREAMBLE = 0;
2341 $NESTING_LEVEL=0;
2342 &do_AtBeginDocument;
2343 $after =~ s/^\s*//m;
2344 print STDOUT (($VERBOSITY >2)? "\n*** Translating environments ***" : ";");
2345 $after = &translate_environments($after);
2346 print STDOUT (($VERBOSITY >2)? "\n*** Translating commands ***" : ";");
2347 $_ .= &translate_commands($after);
2348 # $_ = &translate_commands($after);
2349 } else {
2350 &do_AtBeginDocument;
2351 $PREAMBLE = 0;
2352 $NESTING_LEVEL=0;
2353 print STDOUT (($VERBOSITY >2)? "\n*** Translating environments ***" : ";");
2354 $_ = &translate_environments($_);
2355 print STDOUT (($VERBOSITY >2)? "\n*** Translating commands ***" : ";");
2356 $_ = &translate_commands($_);
2357 }
2359 # close any tags that remain open
2360 if (@$open_tags_R) {
2361 ($close_all,$open_all) = &preserve_open_tags();
2362 $_ .= $close_all;
2363 @save_open_tags = @$open_tags_R; $open_tags_R = [];
2364 } else { ($close_all,$open_all) = ('','') }
2366 print STDOUT (($VERBOSITY >2)? "\n*** Translations done ***" : "\n");
2367 # if (($footnotes)&&($NO_FOOTNODE)&&( $current_depth < $MAX_SPLIT_DEPTH)) {
2368 # $_ .= &make_footnotes
2369 # }
2370 print OUTPUT $_;
2372 # Associate each id with the depth, the filename and the title
2373 ###MEH -- starred sections don't show up in TOC ...
2374 # RRM: ...unless $TOC_STARS is set
2375 # $toc_sec_title = &simplify($toc_sec_title);
2376 $toc_sec_title = &purify($toc_sec_title);# if $SEGMENT;
2377 $toc_sec_title = &purify($TITLE) unless ($toc_sec_title);
2379 if ($TOC_STARS) {
2380 $toc_section_info{join(' ',@curr_sec_id)} =
2381 "$current_depth$delim$CURRENT_FILE$delim$toc_sec_title"
2382 # if ($current_depth <= $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH);
2383 if ($current_depth <= $TOC_DEPTH);
2384 } else {
2385 $toc_section_info{join(' ',@curr_sec_id)} =
2386 "$current_depth$delim$CURRENT_FILE$delim$toc_sec_title"
2387 . ($curr_sec =~ /star$/ ? "$delim<tex2html_star_mark>" : "")
2388 # if ($current_depth <= $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH);
2389 if ($current_depth <= $TOC_DEPTH);
2390 }
2392 # include $BODYTEXT in the section_info, when starting a new page
2393 $section_info{join(' ',@curr_sec_id)} =
2394 "$current_depth$delim$CURRENT_FILE$delim$TITLE$delim"
2395 . (($current_depth < $MAX_SPLIT_DEPTH)? $BODYTEXT: "");
2397 # Get type of section (see also the split above)
2398 $curr_sec = $sections[$i+1].$sections[$i+2];
2399 $del = $sections[$i+4];
2401 # Get the depth of the current section;
2402 # $curr_sec = $outermost_level unless $curr_sec;
2403 $current_depth = $section_commands{$curr_sec};
2404 if ($after_segment) {
2405 $current_depth = $after_segment;
2406 $curr_sec_id[$after_segment] += $after_seg_num;
2407 ($after_segment,$after_seg_num) = ('','');
2408 for($j=1+$current_depth; $j <= $#curr_sec_id; $j++) {
2409 $curr_sec_id[$j] = 0;
2410 }
2411 }
2412 if ($SEGMENT||$SEGMENTED) {
2413 for($j=1; $j <= $#curr_sec_id; $j++) {
2414 $curr_sec_id[$j] += $segment_sec_id[$j];
2415 $segment_sec_id[$j] = 0;
2416 }
2417 };
2420 # this may alter the section-keys
2421 $multiple_toc = 1 if ($MULTIPLE_FILES && $ROOTED && (/$toc_mark/));
2424 #RRM : Should this be done here, or in \stepcounter ?
2425 @curr_sec_id = &new_level($current_depth, @curr_sec_id);
2427 $toc_sec_title = $TITLE = $top_sec = '';
2428 $i+=5; #skip to next text section
2429 }
2430 $open_tags_R = [];
2431 $open_all = '';
2433 $_ = undef;
2434 $_ = &make_footnotes if ($footnotes);
2435 $CURRENT_FILE = '';
2436 print OUTPUT;
2437 close OUTPUT;
2440 # # this may alter the section-keys
2441 # &adjust_root_keys if $multiple_toc;
2443 if ($PREPROCESS_IMAGES) { &preprocess_images }
2444 else { &make_image_file }
2445 print STDOUT "\n *** making images ***" if ($VERBOSITY > 1);
2446 &make_images;
2448 # Link sections, add head/body/address do cross-refs etc
2449 print STDOUT "\n *** post-process ***" if ($VERBOSITY > 1);
2450 &post_process;
2452 if (defined &document_post_post_process) {
2453 #BRM: extra document-wide post-processing
2454 print STDOUT "\n *** post-processing Document ***" if ($VERBOSITY > 1);
2455 &document_post_post_process();
2456 }
2458 print STDOUT "\n *** post-processed ***" if ($VERBOSITY > 1);
2459 ©_icons if $LOCAL_ICONS;
2460 if ($SEGMENT || $DEBUG || $SEGMENTED) {
2461 &save_captions_in_file("figure", $figure_captions) if $figure_captions;
2462 &save_captions_in_file("table", $table_captions) if $table_captions;
2463 # &save_array_in_file ("captions", "figure_captions", 0, %figure_captions) if %figure_captions;
2464 # &save_array_in_file ("captions", "table_captions", 0, %table_captions) if %table_captions;
2465 &save_array_in_file ("index", "index", 0, %index);
2466 &save_array_in_file ("sections", "section_info", 0, %section_info);
2467 &save_array_in_file ("contents", "toc_section_info", 0,%toc_section_info);
2468 &save_array_in_file ("index", "sub_index", 1, %sub_index) if %sub_index;
2469 &save_array_in_file ("index", "index_labels", 1, %index_labels) if %index_labels;
2470 &save_array_in_file ("index", "index_segment", 1, %index_segment) if %index_segment;
2471 &save_array_in_file ("index", "printable_key", 1, %printable_key)
2472 if (%printable_key || %index_segment);
2473 }
2474 elsif ($MULTIPLE_FILES && $ROOTED) {
2475 &save_array_in_file ("sections", "section_info", 0, %section_info);
2476 &save_array_in_file ("contents", "toc_section_info", 0, %toc_section_info);
2477 }
2478 &save_array_in_file ("internals", "ref_files", 0, %ref_files) if $changed;
2479 &save_array_in_file ("labels", "external_labels", 0, %ref_files);
2480 &save_array_in_file ("labels", "external_latex_labels", 1, %latex_labels);
2481 &save_array_in_file ("images", "cached_env_img", 0, %cached_env_img);
2482 }
2484 # RRM:
2485 sub translate_preamble {
2486 local($_) = @_;
2487 $PREAMBLE = 1;
2488 $NESTING_LEVEL=0; #counter for TeX group nesting level
2489 # remove some artificially inserted constructions
2490 s/\n${tex2html_deferred_rx}\\par\s*${tex2html_deferred_rx2}\n/\n/gm;
2491 s/\\newedcommand(<<\d+>>)([A-Za-z]+|[^A-Za-z])\1(\[\d+\])?(\[[^]]*\])?(<<\d+>>)[\w\W\n]*\5($comment_mark\d*)?//gm;
2492 s/\n{2,}/\n/ogm;
2494 if (/\\htmlhead/) {
2495 print STDOUT "\nPREAMBLE: discarding...\n$`" if ($VERBOSITY > 4);
2496 local($after) = $&.$';
2497 # translate segment preamble preceding \htmlhead
2498 &translate_commands(&translate_environments($`));
2499 # translate \htmlhead and rest of preamble
2500 $_=&translate_commands(&translate_environments($after));
2501 print STDOUT "\nPREAMBLE: retaining...\n$_" if ($VERBOSITY > 4);
2502 } else {
2503 # translate only preamble here (metacommands etc.)
2504 # there should be no textual results, if so, discard them
2505 &translate_commands(&translate_environments($_));
2506 print STDOUT "\nPREAMBLE: discarding...\n$_" if ($VERBOSITY > 4);
2507 $_="";
2508 };
2509 $_ = &do_AtBeginDocument($_);
2510 if (! $SEGMENT) { $_ = ''} # segmented documents have a heading already
2511 $_;
2512 }
2514 ############################ Processing Environments ##########################
2516 sub wrap_shorthand_environments {
2517 # This wraps a dummy environment around environments that do not use
2518 # the begin-end convention. The wrapper will force them to be
2519 # evaluated by Latex rather than them being translated.
2520 # Wrap a dummy environment around matching TMPs.
2521 # s/^\$\$|([^\\])\$\$/{$1.&next_wrapper('tex2html_double_dollar')}/ge;
2522 # Wrap a dummy environment around matching $s.
2523 # s/^\$|([^\\])\$/{$1.&next_wrapper('$')}/ge;
2524 # s/tex2html_double_dollar/\$\$/go;
2525 # Do \(s and \[s
2526 #
2527 local($wrapper) = "tex2html_wrap_inline"; # \ensuremath wrapper
2528 print STDOUT "\n *** wrapping environments ***\n" if ($VERBOSITY > 3);
2530 # MRO: replaced $* with /m
2531 print STDOUT "\\(" if ($VERBOSITY > 3);
2532 s/(^\\[(])|([^\\])(\\[(])/{$2.&make_any_wrapper(1,'',$wrapper).$1.$3}/geom;
2533 print STDOUT "\\)" if ($VERBOSITY > 3);
2534 s/(^\\[)]|[^\\]\\[)])/{$1.&make_any_wrapper(0,'',$wrapper)}/geom;
2536 print STDOUT "\\[" if ($VERBOSITY > 3);
2537 s/(^\\[[])|([^\\])(\\[[])/{$2.&make_any_wrapper(1,1,"displaymath")}/geom;
2538 print STDOUT "\\]" if ($VERBOSITY > 3);
2539 s/(^\\[\]])|([^\\])(\\[\]])/{$2.&make_any_wrapper(0,1,"displaymath")}/geom;
2541 print STDOUT "\$" if ($VERBOSITY > 3);
2542 s/$enspair/print "\$";
2543 {&make_any_wrapper(1,'',$wrapper).$&.&make_any_wrapper(0,'',$wrapper)}/geom;
2545 $double_dol_rx = '(^|[^\\\\])\\$\\$';
2546 $single_dol_rx = '(^|[^\\\\])\\$';
2547 print STDOUT "\$" if ($VERBOSITY > 3);
2549 local($dollars_remain) = 0;
2550 $_ = &wrap_math_environment;
2551 $_ = &wrap_raw_arg_cmds;
2552 }
2554 sub wrap_math_environment {
2556 # This wraps math-type environments
2557 # The trick here is that the opening brace is the same as the close,
2558 # but they *can* still nest, in cases like this:
2559 #
2560 # $ outer stuff ... \hbox{ ... $ inner stuff $ ... } ... $
2561 #
2562 # Note that the inner pair of $'s is nested within a group. So, to
2563 # handle these cases correctly, we need to make sure that the outer
2564 # brace-level is the same as the inner. --- rst
2565 #tex2html_wrap
2566 # And yet another problem: there is a scungy local idiom to do
2567 # this: $\_$ for a boldfaced underscore. xmosaic can't display the
2568 # resulting itty-bitty bitmap, for some reason; even if it could, it
2569 # would probably come out as an overbar because of the floating-
2570 # baseline problem. So, we have to special case this. --- rst again.
2572 local ($processed_text, @processed_text, $before, $end_rx, $delim, $ifclosed);
2573 local ($underscore_match_rx) = "^\\s*\\\\\\_\\s*\\\$";
2574 local ($wrapper);
2575 print STDOUT "\nwrap math:" if ($VERBOSITY > 3);
2577 #find braced dollars, in tabular-specs
2578 while (/((($O|$OP)\d+($C|$CP))\s*)\$(\s*\2)/) {
2579 push (@processed_text, $`, $1.$dol_mark.$5);
2580 $_ = $';
2581 }
2582 $_ = join('',@processed_text, $_) if (@processed_text);
2583 undef @processed_text;
2585 $dollars_remain = 0;
2586 while (/$single_dol_rx/) {
2587 $processed_text .= $`.$1;
2588 $_ = $';
2589 $wrapper = "tex2html_wrap_inline";
2590 $end_rx = $single_dol_rx; # Default, unless we begin with $$.
2591 $delim = "\$";
2593 if (/^\$/ && (! $`)) {
2594 s/^\$//;
2595 $end_rx = $double_dol_rx;
2596 $delim = ""; # Cannot say "\$\$" inside displaymath
2597 $wrapper = "displaymath";
2599 } elsif (/$underscore_match_rx/ && (! $`)) {
2601 # Special case for $\_$ ...
2603 s/$underscore_match_rx//;
2604 $processed_text .= '\\_';
2605 next;
2606 }
2608 # Have an opening $ or $$. Find matching close, at same bracket level
2609 # $processed_text .= &make_any_wrapper(1,'',$wrapper).$delim;
2611 print STDOUT "\$" if ($VERBOSITY > 3);
2612 $ifclosed = 0;
2613 local($thismath);
2614 while (/$end_rx/) {
2615 # Forget the $$ if we are going to replace it with "displaymath"
2616 $before = $` . (($wrapper eq "displaymath")? "$1" : $&);
2617 last if ($before =~ /\\(sub)*(item|section|chapter|part|paragraph)(star)?\b/);
2618 $thismath .= $before;
2619 $_ = $';
2620 s/^( [^\n])/\\space$1/s; #make sure a trailing space doesn't get lost.
2622 # Found dollar sign inside open subgroup ... now see if it's
2623 # at the same brace-level ...
2625 local ($losing, $br_rx) = (0, '');
2626 print STDOUT "\$" if ($VERBOSITY > 3);
2627 while ($before =~ /$begin_cmd_rx/) {
2628 $br_rx = &make_end_cmd_rx($1); $before = $';
2630 if ($before =~ /$br_rx/) { $before = $'; }
2631 else { $losing = 1; last; }
2632 }
2633 do { $ifclosed = 1; last } unless $losing;
2635 # It wasn't ... find the matching close brace farther on; then
2636 # keep going.
2638 /$br_rx/;
2640 $thismath .= $`.$&;
2642 #RRM: may now contain unprocessed $s e.g. $\mbox{...$...$...}$
2643 # the &do_cmd_mbox uses this specially to force an image
2644 # ...but there may be other situations; e.g. \hbox
2645 # so set a flag:
2646 $dollars_remain = 1;
2648 $_ = $';
2649 }
2651 # Got to the end. Whew!
2652 if ($ifclosed) {
2653 # also process any nested math
2654 while (($dollars_remain)&&($delim eq "\$")) {
2655 local($saved) = $_;
2656 $thismath =~ s/\$$//;
2657 $_ = $thismath;
2658 $thismath = &wrap_math_environment;
2659 $thismath .= "\$";
2660 $_ = $saved;
2661 }
2662 $processed_text .= &make_any_wrapper(1,'',$wrapper) . $delim
2663 . $thismath . &make_any_wrapper(0,'',$wrapper);
2664 } else {
2665 print STDERR "\n\n *** Error: unclosed math or extra `\$', before:\n$thismath\n\n";
2666 # # remove a $ to try to recover as much as possible.
2667 # $thismath =~ s/([^\\]\\\\|[^\\])\$/$1\%\%/;
2668 # $_ = $thismath . $_; $thismath = "";
2669 print "\n$thismath\n\n\n$_\n\n\n"; die;
2671 }
2672 }
2673 $processed_text . $_;
2674 }
2676 sub translate_environments {
2677 local ($_) = @_;
2678 local($tmp, $capenv);
2679 # print "\nTranslating environments ...";
2680 local($after, @processedE);
2681 local ($contents, $before, $br_id, $env, $pattern);
2682 for (;;) {
2683 # last unless (/$begin_env_rx/o);
2684 last unless (/$begin_env_rx|$begin_cmd_rx|\\(selectlanguage)/o);
2685 # local ($contents, $before, $br_id, $env, $pattern);
2686 local($this_env, $opt_arg, $style_info);
2687 $contents = '';
2688 # $1,$2 : optional argument/text --- stylesheet info
2689 # $3 : br_id (at the beginning of an environment name)
2690 # $4 : environment name
2691 # $5 : br_id of open-brace, when $3 == $4 == '';
2692 # $6 : \selectlanguage{...}
2693 if ($7) {
2694 push(@processedE,$`);
2695 $_ = $';
2696 if (defined &do_cmd_selectlanguage) {
2697 $_ = &do_cmd_selectlanguage($_);
2698 } else {
2699 local($cmd) = $7;
2700 $pattern = &missing_braces unless (
2701 s/$next_pair_rx/$pattern = $2;''/e);
2702 local($trans) = $pattern.'_translation';
2703 if (defined &$trans) {
2704 &set_default_language($pattern,$_);
2705 }
2706 undef $cmd; undef $trans;
2707 }
2708 next;
2709 } elsif ($4) {
2710 ($before, $opt_arg, $style_info, $br_id
2711 , $env, $after, $pattern) = ($`, $2, $3, $4, $5, $', $&);
2712 if (($before)&& (!($before =~ /$begin_env_rx|$begin_cmd_rx/))) {
2713 push(@processedE,$before);
2714 $_ = $pattern . $after; $before = '';
2715 }
2716 } else {
2717 ($before, $br_id, $env, $after, $pattern) = ($`, $6, 'group', $', $&);
2718 if (($before)&& (!($before =~ /$begin_env_rx|$begin_cmd_rx/))) {
2719 push(@processedE,$before);
2720 $_ = $pattern . $after; $before = '';
2721 }
2722 local($end_cmd_rx) = &make_end_cmd_rx($br_id);
2723 if ($after =~ /$end_cmd_rx/) {
2724 # ... find the the matching closing one
2725 $NESTING_LEVEL++;
2726 ($contents, $after) = ($`, $');
2727 $contents = &process_group_env($contents);
2728 print STDOUT "\nOUT: {$br_id} ".length($contents) if ($VERBOSITY > 3);
2729 print STDOUT "\n:$contents\n" if ($VERBOSITY > 7);
2730 # THIS MARKS THE OPEN-CLOSE DELIMITERS AS PROCESSED
2731 $_ = join("", $before,"$OP$br_id$CP", $contents,"$OP$br_id$CP", $after);
2732 $NESTING_LEVEL--;
2733 } else {
2734 $pattern = &escape_rx_chars($pattern);
2735 s/$pattern//;
2736 print "\nCannot find matching bracket for $br_id";
2737 $_ = join("", $before,"$OP$br_id$CP", $after);
2738 }
2739 next;
2740 }
2741 $contents = undef;
2742 local($defenv) = $env =~ /deferred/;
2743 # local($color_env);
2744 local($color_env)
2745 unless ($env =~ /tabular|longtable|in(line|display)|math/);
2746 local($closures,$reopens);
2747 local(@save_open_tags) = @$open_tags_R unless ($defenv);
2748 local($open_tags_R) = [ @save_open_tags ] unless ($defenv);
2749 local(@saved_tags) if ($env =~ /tabular|longtable/);
2750 if ($env =~ /tabular|longtable|makeimage|in(line|display)/) {
2751 @save_open_tags = @$open_tags_R;
2752 $open_tags_R = [ @save_open_tags ];
2753 # check for color
2754 local($color_test) = join(',',@$open_tags_R);
2755 if ($color_test =~ /(color{[^}]*})/g ) {
2756 $color_env = $1;
2757 } # else { $color_env = '' }
2759 if ($env =~ /tabular|longtable|makeimage/) {
2760 # close to the surrounding block-type tag
2761 ($closures,$reopens,@saved_tags) = &preserve_open_block_tags();
2762 @save_open_tags = @$open_tags_R;
2763 $open_tags_R = [ @save_open_tags ];
2764 if ($color_env) {
2765 $color_test = join(',',@saved_tags);
2766 if ($color_test =~ /(color{[^}]*})/g ) {
2767 $color_env = $1;
2768 }
2769 }
2770 } elsif ($env =~ /in(line|display)/) {
2771 $closures = &close_all_tags() if ((&defined_env($env))
2772 &&!($defenv)&&!($env=~/inline/)&&(!$declarations{$env}));
2773 if ($color_env) {
2774 $color_test = $declarations{$color_env};
2775 $color_test =~ s/<\/.*$//;
2776 $closures .= "\n$color_test";
2777 push (@$open_tags_R , $color_env);
2778 }
2779 }
2780 } elsif ($env =~ /alltt|tex2html_wrap/) {
2781 # alltt is constructed as paragraphs, not with <PRE>
2782 # tex2html_wrap creates an image, which is at text-level
2783 } else {
2784 $closures = &close_all_tags() if ((&defined_env($env))
2785 &&!($defenv)&&(!$declarations{$env}) );
2786 }
2787 # Sets $contents and modifies $after
2788 if (&find_end_env($env,$contents,$after)) {
2789 print STDOUT "\nIN-A {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2790 &process_command($counters_rx, $before)
2791 if ($before =~ /$counters_rx/);
2792 # This may modify $before and $after
2793 # Modifies $contents
2794 #RRM: the do_env_... subroutines handle when to translate sub-environments
2795 # $contents = &translate_environments($contents) if
2796 ## ((!$defenv) && (&defined_env($env)) && (! $raw_arg_cmds{$env})
2797 ## && (!$declarations{$env})
2798 # ((&defined_env($env)) && (! $raw_arg_cmds{$env})
2799 # && (!($env =~ /latexonly|enumerate|figure|table|makeimage|wrap_inline/))
2800 # && ((! $NO_SIMPLE_MATH)||(!($env =~ /wrap/)))
2801 # && (!($env =~ /(math|wrap|equation|eqnarray|makeimage|minipage|tabular)/) )
2802 # );
2803 if ($opt_arg) {
2804 &process_environment(1, $env, $br_id, $style_info); # alters $contents
2805 } else {
2806 &process_environment(0, $env, $br_id, '');
2807 }
2808 undef $_;
2809 print STDOUT "\nOUT-A {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2810 #JCL(jcl-env) - insert the $O$br_id$C stuff to handle environment grouping
2811 if (!($contents eq '')) {
2812 $after =~ s/^\n//o if ($defenv);
2813 $this_env = join("", $before, $closures
2814 , $contents
2815 , ($defenv ? '': &balance_tags())
2816 , $reopens ); $_ = $after;
2817 } else {
2818 $this_env = join("", $before , $closures
2819 , ($defenv ? '': &balance_tags())
2820 , $reopens ); $_ = $after;
2821 };
2822 ### Evan Welsh <welsh@epcc.ed.ac.uk> added the next 24 lines ##
2823 } elsif (&defined_env($env)) {
2824 print STDOUT "\nIN-B {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2825 # If I specify a function for the environment then it
2826 # calls it with the contents truncated at the next section.
2827 # It assumes I know what I'm doing and doesn't give a
2828 # deferred warning.
2829 $contents = $after;
2830 if ($opt_arg) {
2831 $contents = &process_environment(1, $env, $br_id, $style_info);
2832 } else {
2833 $contents = &process_environment(0, $env, $br_id, '');
2834 }
2835 print STDOUT "\nOUT-B {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2836 $this_env = join("", $before, $closures ,$contents, $reopens);
2838 # there should not be anything left over
2839 # $_ = $after;
2840 $_ = '';
2841 } elsif ($ignore{$env}) {
2842 print STDOUT "\nIGNORED {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2843 # If I specify that the environment should be ignored then
2844 # it is but I get a deferred warning.
2845 $this_env = join("", $before , $closures , &balance_tags()
2846 , $contents, $reopens );
2847 $_ = $after;
2848 &write_warnings("\n\\end{$env} not found (ignored).\n");
2849 } elsif ($raw_arg_cmds{$env}) {
2850 print "\nIN-C {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2851 # If I specify that the environment should be passed to tex
2852 # then it is with the environment truncated at the next
2853 # section and I get a deferred warning.
2855 $contents = $after;
2856 if ($opt_arg) {
2857 $contents = &process_environment(1, $env, $br_id, $style_info);
2858 } else {
2859 $contents = &process_environment(0, $env, $br_id, '');
2860 }
2861 print STDOUT "\nOUT-C {$env $br_id}\n$contents\n" if ($VERBOSITY > 4);
2862 $this_env = join("", $before, $closures
2863 , $contents, &balance_tags(), $reopens );
2864 $_='';
2865 &write_warnings(
2866 "\n\\end{$env $br_id} not found (truncated at next section boundary).\n");
2867 } else {
2868 $pattern = &escape_rx_chars($pattern);
2869 s/$pattern/$closures/;
2870 print "\nCannot find \\end{$env $br_id}\n";
2871 $_ .= join('', &balance_tags(), $reopens) unless ($defenv);
2872 }
2873 if ($this_env =~ /$begin_env_rx|$begin_cmd_rx/) {
2874 $_ = $this_env . $_;
2875 } else { push (@processedE, $this_env) }
2876 }
2877 $_ = join('',@processedE) . $_;
2878 $tmp = $_; undef $_;
2879 &process_command($counters_rx, $tmp) if ($tmp =~ /$counters_rx/);
2880 $_ = $tmp; undef $tmp;
2881 $_
2882 }
2884 sub find_end_env {
2885 # MRO: find_end_env($env,$contents,$rest)
2886 #local ($env, *ref_contents, *rest) = @_;
2887 my $env = $_[0];
2888 my $be_rx = &make_begin_end_env_rx($env);
2889 my $count = 1;
2891 while ($_[2] =~ /($be_rx)(\n?)/s) { # $rest
2892 $_[1] .= $`; # $contents
2894 if ($2 eq "begin") { ++$count }
2895 else { --$count };
2897 #include any final \n at an {end} only
2898 $_[2] = (($2 eq 'end')? $5 : '') . $'; # $rest
2899 last if $count == 0;
2901 $_[1] .= $1; # $contents
2902 }
2904 if ($count != 0) {
2905 $_[2] = join('', $_[1], $_[2]); # $rest = join('', $contents, $rest);
2906 $_[1] = ''; # $contents
2907 return(0)
2908 } else { return(1) }
2909 }
2912 sub process_group_env {
2913 local($contents) = @_;
2914 local(@save_open_tags) = @$open_tags_R;
2915 local($open_tags_R) = [ @save_open_tags ];
2916 print STDOUT "\nIN::{group $br_id}" if ($VERBOSITY > 4);
2917 print STDOUT "\n:$contents\n" if ($VERBOSITY > 6);
2919 # need to catch explicit local font-changes
2920 local(%font_size) = %font_size if (/\\font\b/);
2922 # record class/id info for a style-sheet entry
2923 local($env_id, $tmp, $etmp);
2924 if (($USING_STYLES) && !$PREAMBLE ) { $env_id = $br_id; }
2925 # $env_id = "grp$br_id";
2926 # $styleID{$env_id} = " ";
2927 # $env_id = " ID=\"$env_id\"";
2928 # }
2930 undef $_;
2931 $contents =~ s/^\s*$par_rx\s*//s; # don't start with a \par
2932 if ($contents =~ /^\s*\\($image_switch_rx)\b\s*/s) {
2933 # catch TeX-like environments: {\fontcmd ... }
2934 local($image_style) = $1;
2935 if ($USING_STYLES) {
2936 $env_style{$image_style} = " " unless ($env_style{$image_style});
2937 }
2938 local($switch_cmd) = "do_cmd_${image_style}";
2939 if (defined &$switch_cmd ) {
2940 eval "\$contents = \&${switch_cmd}(\$')";
2941 print "\n*** &$switch_cmd didn't work: $@\n$contents\n\n" if ($@);
2942 } elsif ($contents =~ /$par_rx/) {
2943 # split into separate image for each paragraph
2944 local($par_style,$this_par_img) = '';
2945 local(@par_pieces) = split($par_rx, $contents);
2946 local($this_par,$par_style,$par_comment);
2947 $contents = '';
2948 while (@par_pieces) {
2949 $this_par = shift @par_pieces;
2950 if ($this_par =~ /^\s*\\($image_switch_rx)\b/s) {
2951 $image_style = $1;
2952 $par_style = 'P.'.$1;
2953 $env_style{$par_style} = " " unless ($env_style{$par_style});
2954 }
2955 # no comment: source is usually too highly encoded to be meaningful
2956 # $par_comment = &make_comment($image_style,$this_par);
2957 $this_par_img = &process_in_latex("\{".$this_par."\}");
2958 $contents .= join('' #,"\n", $par_comment
2959 , "\n<P"
2960 , (($USING_STYLES && $image_style)? " CLASS=\"$image_style\"" :'')
2961 ,">", $this_par_img
2962 , "</P>\n");
2963 if (@par_pieces) {
2964 # discard the pieces from matching $par_rx
2965 $dum = shift @par_pieces;
2966 $dum = shift @par_pieces;
2967 $dum = shift @par_pieces;
2968 $dum = shift @par_pieces;
2969 $dum = shift @par_pieces;
2970 $dum = shift @par_pieces;
2971 # $contents .= "\n</P>\n<P>";
2972 }
2973 }
2974 } else {
2975 $contents = &process_undefined_environment("tex2html_accent_inline"
2976 , ++$global{'max_id'},"\{".$contents."\}");
2977 }
2978 } elsif ($contents =~ /^\s*\\(html)?url\b($O\d+$C)[^<]*\2\s*/) {
2979 # do nothing
2980 $contents = &translate_environments($contents);
2981 $contents = &translate_commands($contents);
2982 } elsif (($env_switch_rx)&&($contents =~ s/^(\s*)\\($env_switch_rx)\b//s)) {
2983 # write directly into images.tex, protected by \begingroup...\endgroup
2984 local($prespace, $cmd, $tmp) = ($1,$2,"do_cmd_$2");
2985 $latex_body .= "\n\\begingroup ";
2986 if (defined &$tmp) {
2987 eval("\$contents = &do_cmd_$cmd(\$contents)");
2988 }
2989 $contents = &translate_environments($contents);
2990 $contents = &translate_commands($contents);
2991 undef $tmp; undef $cmd;
2992 $contents .= "\n\\endgroup ";
2993 } elsif ($contents =~ /^\s*\\([a-zA-Z]+)\b/s) {
2994 local($after_cmd) = $';
2995 local($cmd) = $1; $tmp = "do_cmd_$cmd"; $etmp = "do_env_$cmd";
2996 if (($cmd =~/^(rm(family)?|normalsize)$/)
2997 ||($declarations{$cmd}&&(defined &$tmp))) {
2998 do{
2999 local(@save_open_tags) = @$open_tags_R;
3000 eval "\$contents = \&$tmp(\$after_cmd);";
3001 print "\n*** eval &$tmp failed: $@\n$contents\n\n" if ($@);
3002 $contents .= &balance_tags();
3003 };
3004 } elsif ($declarations{$cmd}&&(defined &$etmp)) {
3005 eval "\$contents = \&$etmp(\$after_cmd);";
3006 } else {
3007 $contents = &translate_environments($contents);
3008 $contents = &translate_commands($contents)
3009 if ($contents =~ /$match_br_rx/o);
3010 # Modifies $contents
3011 &process_command($single_cmd_rx,$contents) if ($contents =~ /\\/o);
3012 }
3013 undef $cmd; undef $tmp; undef $etmp;
3014 } else {
3015 $contents = &translate_environments($contents);
3016 $contents = &translate_commands($contents)
3017 if ($contents =~ /$match_br_rx/o);
3018 # Modifies $contents
3019 &process_command($single_cmd_rx,$contents)
3020 if ($contents =~ /\\/o);
3021 }
3022 $contents . &balance_tags();
3023 }
3025 # MODIFIES $contents
3026 sub process_environment {
3027 local($opt, $env, $id, $styles) = @_;
3029 local($envS) = $env; $envS =~ s/\*\s*$/star/;
3030 local($env_sub,$border,$attribs,$env_id) = ("do_env_$envS",'','','');
3031 local($original) = $contents;
3033 if ($env =~ /tex2html_deferred/ ) {
3034 $contents = &do_env_tex2html_deferred($contents);
3035 return ($contents);
3036 }
3037 $env_id = &read_style_info($opt, $env, $id, $styles)
3038 if (($USING_STYLES)&&($opt));
3040 if (&defined_env($env)) {
3041 print STDOUT ",";
3042 print STDOUT "{$env $id}" if ($VERBOSITY > 1);
3043 # $env_sub =~ s/\*$/star/;
3044 $contents = &$env_sub($contents);
3046 } elsif ($env =~ /tex2html_nowrap/) {
3047 #pass it on directly for LaTeX, via images.tex
3048 $contents = &process_undefined_environment($env, $id, $contents);
3049 return ($contents);
3051 # elsif (&special_env) { # &special_env modifies $contents
3052 } else {
3053 local($no_special_chars) = 0;
3054 local($failed) = 0;
3055 local($has_special_chars) = 0;
3056 &special_env; # modifies $contents
3057 print STDOUT "\n<MATH $env$id $contents>" if ($VERBOSITY > 3);
3058 if ($failed || $has_special_chars) {
3059 $contents = $original;
3060 $failed = 1;
3061 print STDOUT " !failed!\n" if ($VERBOSITY > 3);
3062 }
3063 }
3064 if (($contents) && ($contents eq $original)) {
3065 if ($ignore{$env}) { return(''); }
3066 # Generate picture
3067 if ($contents =~ s/$htmlborder_rx//o) {
3068 $attribs = $2; $border = (($4)? "$4" : 1)
3069 } elsif ($contents =~ s/$htmlborder_pr_rx//o) {
3070 $attribs = $2; $border = (($4)? "$4" : 1)
3071 }
3072 $contents = &process_undefined_environment($env, $id, $contents);
3073 $env_sub = "post_latex_$env_sub"; # i.e. post_latex_do_env_ENV
3074 if ( defined &$env_sub) {
3075 $contents = &$env_sub($contents);
3076 } elsif (($border||($attributes))&&($HTML_VERSION > 2.1)) {
3077 $contents = &make_table($border,$attribs,'','','',$contents);
3078 } else {
3079 $contents = join('',"<BR>\n",$contents,"\n<BR>")
3080 unless (!($contents)||($inner_math)||($env =~
3081 /^(tex2html_wrap|tex2html_nowrap|\w*math|eq\w*n)/o ));
3082 }
3083 }
3084 $contents;
3085 }
3088 #RRM: This reads the style information contained in the optional argument
3089 # to the \begin command. It is stored to be recovered later as an entry
3090 # within the automatically-generated style-sheet, if $USING_STYLES is set.
3091 # Syntax for this info is:
3092 # <style names> ; <extra style-info>
3094 sub read_style_info {
3095 local($opt, $envS, $id, $styles) = @_;
3096 return() unless (($opt)&&($USING_STYLES));
3097 # allow macro-expansion within the style-info
3098 $opt = &translate_commands($opt) if ($opt =~ /\\/);
3100 # record class/id info for a style-sheet entry
3101 local($style_names, $style_extra, $env_id)=(''," ",'');
3102 if ($opt) {
3103 # if there is a `;' then <names> ; <extra>
3104 if ($styles =~ /^\s*([^\|]*)\|\s*(.*)$/) {
3105 $style_names = $1; $style_extra = $2;
3106 if ($style_names =~ /[=:;]/) {
3107 # cannot be <names>, so is <extra>
3108 $style_extra = $style_names.$style_extra;
3109 $style_names = '';
3110 }
3111 } elsif ($styles =~ /[\=\:]/) {
3112 # cannot be <names>, so is <extras>
3113 $style_extra = $styles;
3114 } else { $style_names = $styles }
3115 $style_extra =~ s/\s*[=:]\s*/ : /go;
3116 $style_extra =~ s/([\w,\-]+)\s+([\w,\-]+)/$1 ; $2/go;
3117 $style_extra =~ s/\s*,\s*/ /go;
3119 if ($style_names) {
3120 local($sname);
3121 local(@names) = split ( /\s+/ , $style_names );
3122 # ensure a style-sheet entry for each new name
3123 foreach $sname (@names) {
3124 $env_style{$sname} = " "
3125 unless (($env_style{$sname})||($sname =~ /^\s*$/));
3126 }
3127 }
3128 }
3129 # remove uninformative part of internally-defined env names
3130 $envS =~ s/tex2html_(\w+_)?(\w+)/$2/; $envS =~ s/preform/pre/;
3131 $env_id = $envS.$id;
3132 $styleID{$env_id} = $style_extra unless ($PREAMBLE);
3134 if ($style_names) { $envS = "$style_names" }
3135 elsif (($envS =~ /^pre$/)&&
3136 (/^\\begin.*preform($O|$OP)\d+($C|$CP)$verbatim_mark(\w*[vV]erbatim)(\*?)/))
3137 { $envS = $3.($4 ? 'star' : '') };
3138 $env_style{$envS} = " " unless (($style_names)||($env_style{$envS}));
3139 $env_id = " ID=\"$env_id\"".(($envS) ? " CLASS=\"$envS\"" : '');
3140 return($env_id);
3141 }
3143 # RRM: This provides the mechanism to save style information in %env_style
3144 # using LaTeX macros \htmlsetstyle and \htmladdtostyle
3145 #
3146 sub process_htmlstyles {
3147 local($mode, $_) = @_;
3148 local($pre_tags) = &get_next_optional_argument;
3149 local($class) = &missing_braces unless (
3150 (s/$next_pair_pr_rx/$class = $2;''/e)
3151 ||(s/$next_pair_rx/$class = $2;''/e));
3152 local($sinfo) = &missing_braces unless (
3153 (s/$next_pair_pr_rx/$sinfo = $2;''/e)
3154 ||(s/$next_pair_rx/$sinfo = $2;''/e));
3155 return ($_) unless ($class||$pre_tags);
3157 $class = $pre_tags.($class ?'.':'').$class;
3158 $sinfo =~ s/\s*[:=]\s*/ : /g;
3159 $sinfo =~ s/\s*,\s*/ /g;
3160 if ($mode =~ /add/) {
3161 $sinfo = '; '.$sinfo if ($env_style{$class});
3162 $env_style{$class} .= $sinfo;
3163 } else { $env_style{$class} = $sinfo }
3164 $_;
3165 }
3166 sub do_cmd_htmlsetstyle { &process_htmlstyles('set',@_) }
3167 sub do_cmd_htmladdtostyle { &process_htmlstyles('add',@_) }
3170 # The $<$, $>$, $|$ and $=>$, etc strings are replaced with their textual
3171 # equivalents instead of passing them on to latex for processing in math-mode.
3172 # This will not be necessary when the mechanism for passing environments
3173 # to Latex is improved.
3174 # RETURNS SUCCESS OR FAILURE
3175 sub special_env {
3176 # Modifies $contents in its caller
3177 local($next)='';
3178 local ($allow) = $HTML_VERSION ge '3.0' ?
3179 "[^#\$%&~\\\\{}]|\\limits" : "[^^#\$%&~_\\\\{}]";
3180 #JKR: Use italics instead of bold #HWS: Generalize to include more symbols.
3181 # $contents =~ s/^\$(\s*($html_specials_inv_rx|$allow)*\s*)\$(.)?/
3182 # $next=$3;&simple_math_env($1).(($next =~ m|\w|)? " ":'').$next/ige;
3183 $contents =~ s/^\$(\s*($html_specials_inv_rx|$allow)*\s*)\$$/
3184 &simple_math_env($1)." "/ige;
3185 if ($contents =~ /\&\w*;/) { $has_math_chars=1 }
3186 if ($contents =~ /;SPM([a-zA-Z]+);/) { $has_special_chars=1 };
3187 }
3189 # Translate simple math environments into italic.
3190 # Only letters should become italic; symbols should stay non-italic.
3191 sub simple_math_env {
3192 local($mathcontents) = @_;
3193 if ($mathcontents eq '') { return("$mathcontents"); }
3194 elsif ($NO_SIMPLE_MATH) { # always make an image
3195 $failed = 1; return($mathcontents);
3196 } elsif ($mathcontents =~ /\\/) { # any macro kills "simple-math"
3197 local($save_math) = $mathcontents;
3198 local(@text_only) = ();
3199 while ((!$failed)&&($mathcontents =~
3200 /\\((boldsymbol|bm)|(math|text)(bf|rm|it|tt)|times|[{}@#^_])(\b|[^A-Za-z]|$)/)) {
3201 # ...except when only simple styles
3202 push (@text_only, $`, ("$2$4" ? "\\simplemath".($4 ? $4 :"bf") :"\\$1") );
3203 $mathcontents = $5.$';
3204 $failed = 1 if ($` =~ /\\/);
3205 }
3206 $failed = 1 if ($mathcontents =~ /\\/);
3207 return($save_math) if $failed;
3208 $mathcontents = join('',@text_only,$mathcontents);
3209 }
3210 # Is there a problem here, with nested super/subscripts ?
3211 # Yes, so do each pattern-match for bracketings within a while-loop
3212 while ($mathcontents =~ s/\^$any_next_pair_rx/<SUP>$2<\/SUP>/go){};
3213 while ($mathcontents =~ s/\^$any_next_pair_pr_rx/<SUP>$2<\/SUP>/go){};
3214 while ($mathcontents =~ s/_$any_next_pair_rx/<SUB>$2<\/SUB>/g){};
3215 while ($mathcontents =~ s/_$any_next_pair_pr_rx/<SUB>$2<\/SUB>/g){};
3217 $mathcontents =~ s/\^(\\[a-zA-Z]+|.)/<SUP>$1<\/SUP>/g;
3218 $mathcontents =~ s/_(\\[a-zA-Z]+|.)/<SUB>$1<\/SUB>/g;
3219 $mathcontents =~ s/(^|\s|[,;:'\?\.\[\]\(\)\+\-\=\!>]|[^\\<]\/|\d)(<(I|TT|B)>)?([a-zA-Z]([a-zA-Z ]*[a-zA-Z])?)(<\/\3>)?/
3220 $1.(($2)? $2 :'<I>').$4.(($6)? $6 : '<\/I>')/eig;
3222 $mathcontents =~ s/\\times($|\b|[^A-Za-z])/ x $1/g;
3223 $mathcontents =~ s/\\times($|\b|[^A-Za-z])/ x $1/g;
3224 $mathcontents =~ s/\\\\/<BR>\n/g;
3225 $mathcontents =~ s/\\\\/<BR>\n/g;
3226 $mathcontents =~ s/\\([,;])/ /g;
3227 $mathcontents =~ s/\\(\W)/$1/g;
3228 $mathcontents =~ s/ {2,}/ /g;
3230 # any simple style changes remove enclosed <I> tags
3231 $mathcontents = &translate_commands($mathcontents)
3232 if ($mathcontents =~ /\\/);
3234 $mathcontents =~ s/<I><\/(SUB|SUP)>/<\/$1><I>/g;
3235 $mathcontents =~ s/<(SUB|SUP)><\/I>/<\/I><$1>/g;
3236 $mathcontents =~ s/;<I>SPM([a-zA-Z]+)<\/I>;/;SPM$1;/go;
3237 $mathcontents =~ s/<(\/?)<I>(SUB|SUP|I|B|TT)<\/I>>/<$1$2>/g;
3238 $mathcontents =~ s/<\/(B|I|TT)><\1>//g;
3239 $mathcontents;
3240 }
3242 sub do_cmd_simplemathrm {
3243 local ($_) = @_;
3244 local($text);
3245 $text = &missing_braces unless (
3246 (s/$next_pair_pr_rx/$text = $2;''/e)
3247 ||(s/$next_pair_rx/$text = $2;''/e));
3248 $text =~ s/<\/?I>//g;
3249 join('', $text, $_)
3250 }
3251 sub do_cmd_simplemathbf {
3252 local ($_) = @_;
3253 local($text);
3254 $text = &missing_braces unless (
3255 (s/$next_pair_pr_rx/$text = $2;''/e)
3256 ||(s/$next_pair_rx/$text = $2;''/e));
3257 $text =~ s/<\/?I>//g;
3258 join('','<B>', $text, '</B>', $_)
3259 }
3260 sub do_cmd_simplemathtt {
3261 local ($_) = @_;
3262 local($text);
3263 $text = &missing_braces unless (
3264 (s/$next_pair_pr_rx/$text = $2;''/e)
3265 ||(s/$next_pair_rx/$text = $2;''/e));
3266 $text =~ s/<\/?I>//g;
3267 join('','<TT>', $text, '</TT>', $_)
3268 }
3270 sub process_math_in_latex {
3271 local($mode,$style,$level,$math) = @_;
3272 local(@anchors);
3273 if ($level) {
3274 $style = (($level > 1) ? "script" : "") . "script";
3275 } elsif (! $style) {
3276 $style = (($mode =~/display|equation/)? "display" : "")
3277 }
3278 $style = "\\${style}style" if ($style);
3280 # &process_undefined_environment changes $_ , so save it.
3281 local($after) = $_;
3283 # the 'unless' catches nested AMS-aligned environments
3284 $mode = "tex2html_wrap_" .
3285 (($mode =~/display|equation|eqnarray/) ? 'indisplay' : 'inline')
3286 unless ($mode =~ /^equationstar/ && $outer_math =~ /^equationstar/);
3288 $global{'max_id'}++;
3289 $math =~ s/\\(\n|$)/\\ $1/g; # catch \ at end of line or string
3290 $math =~ s/^\s*((\\!|;SPMnegsp;)\s*)*//g; # remove neg-space at start of string
3291 if ($mode =~ /tex2html_wrap_/ ) {
3292 $math = &process_undefined_environment( $mode
3293 , $global{'max_id'}, join('', "\$$style ", $math, "\$"));
3294 } else {
3295 # some AMS environments must be within {equation} not {displaymath}
3296 $math =~ s/displaymath/equation*/
3297 if ($math =~ /\\begin\{(x+|fl)*align/);
3298 $math = &process_undefined_environment($mode, $global{'max_id'}, $math);
3299 }
3300 $math .= "\n" if ($math =~ /$comment_mark\s*\d+$/s);
3301 $_ = $after;
3302 # the delimiter \001 inhibits an unwanted \n at image-replacement
3303 $math . ($math =~ /$image_mark/? "\001" : '');
3304 }
3306 #RRM: Explicit font switches need images. Use the image_switch mechanism.
3307 sub do_cmd_font {
3308 local($_) = @_;
3309 local($fontinfo,$fontname,$size) = ('','','10pt');
3310 s/\s*\\(\w+)\s*=?\s*(.*)(\n|$)/$fontname=$1;$fontinfo=$2;''/eo;
3311 $image_switch_rx .= "|$fontname";
3313 if ($fontinfo =~ /([.\d]+\s*(true)?(pt|mm|cm))/ ) { $size = $1 }
3314 elsif ( $fontinfo =~ /[a-zA-Z]+(\d+)\b/ ) { $size = $1.'pt' }
3315 if ( $fontinfo =~ /(scaled|at)\s*\\?(.+)/) { $size .= " scaled $1" }
3316 $font_size{$fontname} = $size;
3317 $_;
3318 }
3319 sub wrap_cmd_font {
3320 local($cmd, $_) = @_;
3321 local ($args, $dummy, $pat) = "";
3322 if (/\n/) { $args .= $`.$& ; $_ = $' } else {$args = $_; $_ = ''};
3323 (&make_deferred_wrapper(1).$cmd.$padding.$args.&make_deferred_wrapper(0),$_)
3324 }
3326 sub do_cmd_newfont {
3327 local($_) = @_;
3328 local($fontinfo,$fontname,$size) = ('','','10pt');
3329 $fontname = &missing_braces unless (
3330 (s/$next_pair_pr_rx/$fontname=$2;''/eo)
3331 ||(s/$next_pair_rx/$fontname=$2;''/eo));
3332 $fontname=~ s/^\s*\\|\s*$//g;
3333 $image_switch_rx .= "|$fontname";
3335 $fontinfo = &missing_braces unless (
3336 (s/$next_pair_pr_rx/$fontinfo=$2;''/eo)
3337 ||(s/$next_pair_rx/$fontinfo=$2;''/eo));
3338 if ($fontinfo =~ /([.\d]+\s*(true)?(pt|mm|cm))/ ) { $size = $1 }
3339 elsif ( $fontinfo =~ /[a-zA-Z]+(\d+)\b/ ) { $size = $1.'pt' }
3340 if ( $fontinfo =~ /(scaled|at)\s*\\?(.+)/) { $size .= " scaled $1" }
3341 $font_size{$fontname} = $size;
3342 $_;
3343 }
3345 sub defined_env {
3346 local($env) = @_;
3347 $env =~ s/\*$/star/;
3348 local($env_sub) = ("do_env_$env");
3349 # The test using declarations should not be necessary but 'defined'
3350 # doesn't seem to recognise subroutines generated dynamically using 'eval'.
3351 # Remember that each entry in $declarations generates a dynamic prodedure ...
3352 ((defined &$env_sub) || ($declarations{$env}));
3353 }
3355 # RRM: utility to add style information to stored image-parameters
3356 # currently only (math) scaling info is included;
3357 # current color, etc. could also be added here.
3358 sub addto_encoding {
3359 local($env, $contents) = @_;
3360 # $contents =~ s/(\\(begin|end)\s*)?<<\d*>>|\n//g; # RRM: remove env delimiters
3361 $contents =~ s/(\\(begin|end)\s*(<<\d*>>))|\n//g; # RRM: remove env delimiters
3362 # append scaling information for environments using it
3363 if (($MATH_SCALE_FACTOR)
3364 &&(($contents =~ /makeimage|inline|indisplay|entity|displaymath|eqnarray|equation|xy|diagram/)
3365 ||($env =~ /makeimage|inline|indisplay|entity|displaymath|eqnarray|equation|xy|diagram/))
3366 ) { $contents .= ";MSF=$MATH_SCALE_FACTOR" }
3368 if ($LATEX_FONT_SIZE =~ /([\d\.]+)pt/) {
3369 local($fsize) = $1;
3370 $contents .= ";LFS=$fsize" unless ($fsize ==10);
3371 }
3373 if (($EXTRA_IMAGE_SCALE)
3374 &&(($contents =~ /makeimage|inline|indisplay|entity|displaymath|eqnarray|equation|xy|diagram/)
3375 ||($env =~ /makeimage|inline|indisplay|entity|displaymath|eqnarray|equation|xy|diagram/))
3376 ) { $contents .= ";EIS=$EXTRA_IMAGE_SCALE" }
3378 if (($DISP_SCALE_FACTOR)
3379 &&(($contents =~ /indisplay|displaymath|eqnarray|equation/)
3380 ||($env =~ /indisplay|displaymath|eqnarray|equation/))
3381 &&!(($contents =~ /makeimage/)||($env =~ /makeimage/))
3382 ) { $contents .= ";DSF=$DISP_SCALE_FACTOR" }
3384 if (($EQN_TAGS)
3385 &&(($env =~ /eqnarray($|[^_\*])|equation/)
3386 ||($contents =~ /eqnarray($|[^_\*])|equation/))
3387 &&!(($contents =~ /makeimage/)||($env =~ /makeimage/))
3388 ) { $contents .= ";TAGS=$EQN_TAGS" }
3390 if (($FIGURE_SCALE_FACTOR)
3391 &&!(($contents =~ /makeimage/)||($env =~ /makeimage/))
3392 &&(($contents =~ /figure/)||($env =~ /figure/))
3393 ) { $contents .= ";FSF=$FIGURE_SCALE_FACTOR"}
3395 if (($ANTI_ALIAS)
3396 &&(($contents =~ /figure/)||($env =~ /figure/))
3397 &&!(($contents =~ /makeimage/)||($env =~ /makeimage/))
3398 ) { $contents .= ";AAF" }
3399 elsif ($ANTI_ALIAS_TEXT) { $contents .= ";AAT" }
3400 if (!$TRANSPARENT_FIGURES) { $contents .= ";NTR" }
3402 $contents;
3403 }
3405 sub process_undefined_environment {
3406 local($env, $id, $contents) = @_;
3407 if ($env =~ s/\*{2,}/*/) { print "\n*** $_[0] has too many \*s ***"};
3409 local($name,$cached,$raw_contents,$uucontents) = ("$env$id");
3410 $name =~ s/\*/star/;
3411 local($oldimg,$size,$fullcontents,$imgID);
3412 return if ($AUX_FILE);
3414 # catch \footnotemark within an image, especially if in math
3415 local(@foot_anchors,$foot_anchor);
3416 local($im_footnote,$im_mpfootnote) = ($global{'footnote'},$global{'mpfootnote'});
3417 @foot_anchors = &process_image_footnote($contents)
3418 if ($contents =~ /\\footnote(mark)?\b/s);
3419 if ((@foot_anchors)&&($eqno)) {
3420 # append the markers to the equation-numbers
3421 $eqno .= join(' ', ' ', @foot_anchors);
3422 @foot_anchors = ();
3423 }
3425 print STDOUT "\nUNDEF-IN {$env $id}:\n$contents\n" if ($VERBOSITY > 4);
3426 #RRM - LaTeX commands wrapped with this environment go directly into images.tex.
3427 if ($env =~ /tex2html_nowrap|^lrbox$/){ # leave off the wrapper, do not cache
3428 # totally ignore if in preamble...
3429 # ...since it will be put into images.tex anyway!!
3430 if (!($PREAMBLE)) {
3431 $contents =~ s/^\n+|\n+$/\n/g;
3432 local($lcontents) = join('', "\\begin{$env}", $contents , "\\end{$env}" );
3433 $lcontents =~ s/\\(index|label)\s*(($O|$OP)\d+($C|$CP)).*\2//sg;
3434 print STDOUT "pre-LATEX {$env}:\n$lcontents\n" if ($VERBOSITY > 3);
3435 $raw_contents = &revert_to_raw_tex($lcontents);
3436 print STDOUT "LATEX {$env}:\n$raw_contents\n" if ($VERBOSITY > 3);
3437 $latex_body .= "\n$raw_contents"."%\n\n" ;
3438 }
3439 return("") if ($env =~ /^lrbox/);
3440 # ignore enclosed environments; e.g. in \settolength commands
3441 # $contents = &translate_environments($contents); # ignore environments
3442 # $contents = &translate_commands($contents);
3443 # ...but apply any Perl settings that may be defined
3444 $contents = &process_command($single_cmd_rx,$contents);
3445 print STDOUT "\nOUT {$env $id}:\n$contents\n" if ($VERBOSITY > 4);
3446 return("");
3447 }
3448 # catch pre-processor environments
3449 if ($PREPROCESS_IMAGES) {
3450 local($pre_env,$which, $done, $indic);
3451 while ($contents =~ /$pre_processor_env_rx/) {
3452 $done .= $`; $pre_env = $5; $which =$1; $contents = $';
3453 if (($which =~ /begin/)&&($pre_env =~ /indica/)) {
3454 if ($contents =~ s/^\[(\w+)]//o) { $done .= '#'.$1 }
3455 } elsif (($which =~ /end/)&&($pre_env =~ /indica/)) {
3456 $done .= '#NIL';
3457 } elsif (($which =~ /begin/)&&($pre_env =~ /itrans/)) {
3458 if ($contents =~ s/^\[(\w+)]/$indic=$1;''/e)
3459 { $done .= "\#$indic" }
3460 } elsif (($which =~ /end/)&&($pre_env =~ /itrans/)) {
3461 $done .= "\#end$indic";
3462 } elsif ($which =~ /begin/) {
3463 $done .= (($which =~ /end/)? $end_preprocessor{$pre_env}
3464 : $begin_preprocessor{$pre_env} )
3465 }
3466 }
3467 $contents = $done . $contents;
3468 }
3469 $fullcontents = $contents; # save for later \label search.
3470 # MRO: replaced $* with /m
3471 $contents =~ s/\n?$labels_rx(\%([^\n]+$|$EOL))?/\n/gm;
3473 local($tmp) = $contents;
3474 $tmp =~ s/^((\\par|\%)?\s*\n)+$//g;
3475 return( &do_labels($fullcontents, "\ ") ) unless $tmp;
3477 # just a comment as the contents of a cell in a math-display
3478 if ($tmp =~ /\$\\(display|text|(script)+)style\s*$comment_mark\d+\s*\$$/)
3479 { return ( &do_labels($fullcontents, "\ ") ) };
3481 $contents = "\n% latex2html id marker $id\n$contents" if
3482 (!$PREAMBLE &&($contents =~ /$order_sensitive_rx/)
3483 &&(!($env =~ /makeimage/)));
3485 $env =~ s/displaymath/equation*/
3486 if ($contents =~ /\\begin\{(x+|fl)*align/);
3487 #RRM: include the inline-color, when applicable
3488 $contents = join(''
3489 , (($inner_math =~ /in(display|line)/) ? '$' : '')
3490 , "\\begin{$env}"
3491 , ($color_env ? "\\bgroup\\$color_env" : '')
3492 , $contents , ($color_env ? "\\egroup" : '')
3493 , "\\end{$env}"
3494 , (($inner_math =~ /in(display|line)/) ? '$' : '')
3495 ) if ($contents);
3497 # append to the name of special environments found within math
3498 if ($inner_math) {
3499 local($ext) = $inner_math;
3500 if ($inner_math =~ /(display|line)/){ $ext = 'in'.$1;};
3501 $name =~ s/(\d+)$/_$ext$1/;
3502 }
3504 if (!($latex_body{$name} = $contents)) {
3505 print "\n *** code for $name is too long ***\n"}
3506 if ($contents =~ /$htmlimage_rx/) {
3507 $uucontents = &special_encoding($env,$2,$contents);
3508 } elsif ($contents =~ /$htmlimage_pr_rx/) {
3509 $uucontents = &special_encoding($env,$2,$contents);
3510 } else {
3511 $uucontents = &encode(&addto_encoding($env,$contents));
3512 }
3513 $cached = $cached_env_img{$uucontents};
3514 print STDOUT "\nCACHED: $uucontents:\n$cached\n" if ($VERBOSITY > 4);
3515 if ($NOLATEX) {
3516 $id_map{$name} = "[$name]";
3517 } elsif (defined ($_ = $cached)) { # Is it in our cache?
3518 # Have we already used it?
3519 if (($oldimg) = /SRC="$PREFIX$img_rx\.$IMAGE_TYPE"/o) {
3520 # No, check its size
3521 local($eis) = 1;
3522 # Does it have extra scaling ?
3523 if ($uucontents =~ /EIS=(.*);/) { $eis = $1 }
3524 ($size, $imgID) = &get_image_size("$PREFIX$oldimg.old", $eis);
3525 # Does it have extra scaling ?
3526 # if ($uucontents =~ /EIS=(.*);/) {
3527 # local($eis) = $1; local($w,$h);
3528 # # quotes will not be there with HTML 2.0
3529 # $size =~ s/(WIDTH=\")(\d*)(\".*HEIGHT=\")(\d*)\"/
3530 # $w = int($2\/$eis + .5); $h=int($4\/$eis + .5);
3531 # "$1$w$3$h\""/e ; # insert the re-scaled size
3532 # }
3533 # quotes will not be there with HTML 2.0
3534 $size =~ s/\"//g if ($HTML_VERSION < 2.2);
3535 if ($size && /\s$size\s/) {
3536 # Size is OK; recycle it!
3537 ++$global_page_num;
3538 $_ = $cached ; # ...perhaps restoring the desired size.
3539 s/(${PREFIX}T?img)\d+\.($IMAGE_TYPE|html)/
3540 &rename_html($&,"$1$global_page_num.$2")/geo;
3541 } else {
3542 if ($env =~ /equation/) { &extract_eqno($name,$cached) }
3543 $_ = ""; # The old Image has wrong size!
3544 undef($cached); # (or it doesn't exist)
3545 }
3546 }
3547 s/(IMG\n)/$1$imgID/ if $imgID;
3549 s/$PREFIX$img_rx\.new/$PREFIX$1.$IMAGE_TYPE/go; # Point to the actual image file(s)
3550 $id_map{$name} = $_;
3551 s/$PREFIX$img_rx\.$IMAGE_TYPE/$PREFIX$1.new/go; # But remember them as used.
3552 $cached_env_img{$uucontents} = $_;
3553 }
3555 if (! defined($cached)) { # Must generate it anew.
3556 &clear_images_dbm_database
3557 unless ($new_page_num ||($NO_SUBDIR && $FIXEDDIR));
3558 $new_id_map{$name} = $id_map{$name} = ++$global_page_num . "#" .
3559 ++$new_page_num;
3560 $orig_name_map{$id_map{$name}} = $name;
3561 $cached_env_img{$uucontents} = $id_map{$name} if ($REUSE == 2);
3563 #RRM: this (old) code frequently crashes NDBM, so do it in 2 steps
3564 # $img_params{$name} = join('#', &extract_parameters($contents));
3565 local(@params) = &extract_parameters($contents);
3566 $img_params{$name} = join('#',@params); undef $params;
3567 print "\nIMAGE_PARAMS $name: ".$img_params{$name} if ($VERBOSITY > 3);
3569 $contents =~ s/\\(index|label)\s*(($O|$OP)\d+($C|$CP)).*\2//sg;
3570 print STDOUT "\nLATEX {$env}:\n$contents" if ($VERBOSITY > 3);
3571 $raw_contents = &revert_to_raw_tex($contents) unless ($contents =~ /^\s*$/) ;
3572 $raw_contents =~ s/\\pagebreak|\\newpage|\\clearpage/\\\\/go;
3573 print STDOUT "\nLATEX {$env}:\n$raw_contents\n" if ($VERBOSITY > 3);
3574 local($box_type) = '';
3575 if ($raw_contents =~ /\\special\s*\{/) {
3576 $tex_specials{$name} = "1";
3577 &write_warnings("\nenvironment $name contains \\special commands");
3578 print STDOUT "\n *** environment $name contains \\special commands ***\n"
3579 if ($VERBOSITY);
3580 } elsif (($env =~ /$inline_env_rx/)||($inner_math =~ /in(line|display)/)) {
3581 # crop to the marks only... or shave a bit off the bottom
3582 if (($env =~ /tex2html_[^w]/)||$inner_math) {
3583 # e.g. accents, indic but not wrap
3584 $crop{$name} = "bl";
3585 $box_type = "i";
3586 } else {
3587 # ...or shave a bit off the bottom as well
3588 $crop{$name} = "bls";
3589 $box_type = "h";
3590 }
3591 } elsif (($env =~ /(eqnarray|equation)(\*|star)/)||($inner_math)) {
3592 # crop to minimum size...
3593 $crop{$name} = "blrl";
3594 $box_type = "v";
3595 } elsif ($env =~ /(picture|tex2html_wrap)(\*|star)?/) {
3596 # crop hbox to minimum size...
3597 $crop{$name} = "";
3598 $box_type = "p";
3599 } elsif ($env =~ /$display_env_rx/) {
3600 # crop vbox to minimum size...
3601 $crop{$name} = "blrl" ;
3602 if ($env =~ /(equation|eqnarray)((s)?$|\d)/) {
3603 # ... unless equation numbers are included ...
3604 if ($3) { # AMS {subequations}
3605 $global{'eqn_number'}=$prev_eqn_number if $prev_eqn_number;
3606 --$global{'eqn_number'};
3607 }
3608 $raw_contents = join('' ,
3609 (($eqno{$name}||$global{'eqn_number'})?
3610 &set_equation_counter($eqno{$name}) : '')
3611 , $raw_contents);
3612 $crop{$name} = "bl" ;
3613 } elsif ($HTML_VERSION < 2.2) {
3614 # ... HTML 2.0 cannot align images, so keep the full typeset width
3615 $crop{$name} = "bl" ;
3616 }
3617 $box_type = "v";
3618 }
3620 #RRM: include the TeX-code for the appropriate type of box.
3621 eval "\$raw_contents = \&make_$box_type"."box($name, \$raw_contents);";
3623 # JCL(jcl-pag) - remember html text if debug is set.
3624 local($_);
3625 if ($DEBUG) {
3626 $_ = $contents;
3627 s/\n/ /g;
3628 $_ = &revert_to_raw_tex($_);
3629 # incomplete or long commented code can break pre-processors
3630 if ($PREPROCESS_IMAGES) {
3631 $_ = ((/^(\\\w+)?\{[^\\\}\<]*\}?/)? $& : '').'...' ;
3632 $_ = '{ ... }' if ( length($_) > 100);
3633 } elsif ( length($_) > 200) {
3634 $_ = join('',substr($_,0,200),"...\}");
3635 }
3636 s/\\(begin|end)/$1/g; s/[\000-\020]//g;
3637 $_ = join('',"% contents=",$_,"\n");
3638 }
3639 $raw_contents = '\setcounter{equation}{'.$prev_eqn_number."}\n".$raw_contents
3640 if ($env =~ /subequations/);
3642 # JCL(jcl-pag) - build the page entries for images.tex: Each page is embraced to
3643 # let most statements have only local effect. Each page must compile into a
3644 # single dvi page to get proper image translation. Hence the invisible glue to
3645 # get *at least* one page (raw_contents alone might not wield glue), and
3646 # sufficing page length to get *exactly* one page.
3647 #
3648 $latex_body .= "{\\newpage\\clearpage\n$_" .
3649 # "$raw_contents\\hfill\\vglue1pt\\vfill}\n\n";
3650 # "$raw_contents\\hfill\\vss}\n\n" if ($raw_contents);
3651 # "$raw_contents\\hfill\\lthtmlcheckvsize\\clearpage}\n\n" if ($raw_contents);
3652 "$raw_contents\\lthtmlcheckvsize\\clearpage}\n\n" if ($raw_contents);
3653 }
3654 print STDOUT "\nIMAGE_CODE:{$env $id}:\n$raw_contents\n" if ($VERBOSITY > 4);
3656 # Anchor the labels and put a marker in the text;
3657 local($img) = &do_labels($fullcontents,"$image_mark#$name#");
3658 print STDOUT "\nUNDEF_OUT {$env $id}:\n$img\n" if ($VERBOSITY > 4);
3659 return($img) unless (@foot_anchors);
3661 # use the image as source to the 1st footnote, unless it is already an anchor.
3662 if ($img =~ /<\/?A>/) {
3663 join(' ', $img, @foot_anchors);
3664 } elsif ($#foot_anchors ==0) {
3665 $foot_anchor = shift @foot_anchors;
3666 $foot_anchor =~ s/<SUP>.*<\/SUP>/$img/;
3667 # join(' ', $foot_anchor, @foot_anchors);
3668 $foot_anchor;
3669 } else {
3670 join(' ', $img, @foot_anchors);
3671 }
3672 }
3674 sub special_encoding { # locally sets $EXTRA_IMAGE_SCALE
3675 local($env,$_,$contents) = @_;
3676 local($exscale) = /extrascale=([\.\d]*)/;
3677 local($EXTRA_IMAGE_SCALE) = $exscale if ($exscale);
3678 &encode(&addto_encoding($env,$contents));
3679 }
3682 sub extract_eqno{
3683 local($name,$contents) = @_;
3684 if ($contents =~ /<P ALIGN="\w+">\(([^<>])\)<\/P>$/) {
3685 if (($eqno{$name})&&!($eqno{$name} eq $1)) {
3686 &write_warnings("\nequation number for $name may be wrong.")};
3687 $eqno{$name}="$1";
3688 }
3689 }
3690 sub set_equation_counter{
3691 if ( $global{'eqn_number'}) {
3692 "\\setcounter{equation}{". $global{'eqn_number'} ."}\n"
3693 } else { "\\setcounter{equation}{0}\n" }
3694 }
3696 # RRM: 3 different types of boxing, for image environments.
3698 # general environments --- crops to width & height
3699 sub make_box {
3700 local($id,$contents) = @_;
3701 "\\lthtmlfigureA{". $id ."}%\n". $contents ."%\n\\lthtmlfigureZ\n";
3702 }
3704 # inline math --- horizontal mode, captures height/depth + \mathsurround
3705 sub make_hbox {
3706 local($id,$contents) = @_;
3707 if ($id =~ /indisplay/) {
3708 "\\lthtmlinlinemathA{". $id ."}%\n". $contents ."%\n\\lthtmlindisplaymathZ\n";
3709 } else {
3710 "\\lthtmlinlinemathA{". $id ."}%\n". $contents ."%\n\\lthtmlinlinemathZ\n";
3711 }
3712 }
3714 # inline text-image (e.g. accents) --- horizontal mode, captures height/depth
3715 sub make_ibox {
3716 local($id,$contents) = @_;
3717 "\\lthtmlinlineA{". $id ."}%\n". $contents ."%\n\\lthtmlinlineZ\n";
3718 }
3720 # centered images (e.g. picture environments) --- horizontal mode
3721 sub make_pbox {
3722 local($id,$contents) = @_;
3723 "\\lthtmlpictureA{". $id ."}%\n". $contents ."%\n\\lthtmlpictureZ\n";
3724 }
3726 # displayed math --- vertical mode, captures height/depth + page-width
3727 sub make_vbox {
3728 local($id,$contents) = @_;
3729 if (($HTML_VERSION >=3.2)&&($id =~/(equation|eqnarray)($|\d)/) &&! $failed ) {
3730 if ($contents =~ s/^\\setcounter\{equation\}\{\d+\}/$&%\n\\lthtmldisplayB\{$id\}%/)
3731 { $contents ."%\n\\lthtmldisplayZ\n" }
3732 else { "\\lthtmldisplayB{$id}%\n". $contents ."%\n\\lthtmldisplayZ\n" }
3733 } else { "\\lthtmldisplayA{$id}%\n". $contents ."%\n\\lthtmldisplayZ\n"}
3734 }
3736 sub preprocess_images {
3737 do {
3738 print "\nWriting image.pre file ...\n";
3739 open(ENV,">.$dd${PREFIX}images.pre")
3740 || die "\nCannot write '${PREFIX}images.pre': $!\n";
3741 print ENV &make_latex($latex_body);
3742 print ENV "\n";
3743 close ENV;
3744 ©_file($FILE, "bbl");
3745 ©_file($FILE, "aux");
3746 local($num_cmds, $cnt, $this, @cmds);
3747 @cmds = (split ('\n', $preprocessor_cmds));
3748 $this_cmd = $num_cmds = 1+$#cmds;
3749 $cnt = $num_cmds; $preprocessor_cmds = '';
3750 while (@cmds) {
3751 $this_cmd = shift @cmds; last unless ($this_cmd);
3752 $this_cmd =~ s/.pre /.tex$cnt / if(($cnt)&&($cnt < $num_cmds));
3753 $cnt--; $this_cmd .= $cnt if ($cnt);
3754 $preprocessor_cmds .= $this_cmd."\n";
3755 L2hos->syswait($this_cmd);
3756 }
3757 # save pre-processor commands in a file: preproc
3758 open(CMDS,">.$dd${PREFIX}preproc")
3759 || die "\nCannot write '${PREFIX}preproc': $!\n";
3760 print CMDS $preprocessor_cmds ;
3761 close CMDS;
3763 } if ((%latex_body) && ($latex_body =~ /newpage/));
3764 }
3765 sub make_image_file {
3766 do {
3767 print "\nWriting image file ...\n";
3768 open(ENV,">.$dd${PREFIX}images.tex")
3769 || die "\nCannot write '${PREFIX}images.tex': $!\n";
3770 print ENV &make_latex($latex_body);
3771 print ENV "\n";
3772 close ENV;
3773 ©_file($FILE, "bbl");
3774 ©_file($FILE, "aux");
3775 } if ((%latex_body) && ($latex_body =~ /newpage/));
3776 }
3778 sub make_latex_images{
3779 &close_dbm_database if $DJGPP;
3780 local($dd) = $dd; $dd = '/' if ($dd eq "\\");
3781 local($latex_call) = "$LATEX .$dd${PREFIX}images.tex";
3782 print "$latex_call\n" if (($DEBUG)||($VERBOSITY > 1));
3783 L2hos->syswait($latex_call);
3784 &open_dbm_database if $DJGPP;
3785 }
3787 sub make_off_line_images {
3788 local($name, $page_num);
3789 if (!$NOLATEX && -f ".${dd}${PREFIX}images.tex") {
3790 &make_tmp_dir; # sets $TMPDIR and $DESTDIR
3791 $IMAGE_PREFIX =~ s/^_//o if ($TMPDIR);
3793 &make_latex_images();
3795 print "\nGenerating postscript images using dvips ...\n";
3796 &process_log_file(".$dd${PREFIX}images.log"); # Get eqn size info
3797 unless ($LaTeXERROR) {
3798 local($dvips_call) =
3799 "$DVIPS -S1 -i $DVIPSOPT -o$TMPDIR$dd${IMAGE_PREFIX} .${dd}${PREFIX}images.dvi";
3800 print "$dvips_call\n" if (($DEBUG)||($VERBOSITY > 1));
3802 &close_dbm_database if $DJGPP;
3803 L2hos->syswait($dvips_call) && print "Error: $!\n";
3804 undef $dvips_call;
3805 &open_dbm_database if $DJGPP;
3807 # add suffix .ps to the file-names for each image
3808 if(opendir(DIR, $TMPDIR || '.')) {
3809 # use list-context instead; thanks De-Wei Yin <yin@asc.on.ca>
3810 my (@ALL_IMAGE_FILES) = grep /^$IMAGE_PREFIX\d+$/o, readdir(DIR);
3811 foreach (@ALL_IMAGE_FILES) {
3812 L2hos->Rename("$TMPDIR$dd$_", "$TMPDIR$dd$_.ps");
3813 }
3814 closedir(DIR);
3815 } else {
3816 print "\nError: Cannot read dir '$TMPDIR': $!\n";
3817 }
3818 }
3819 }
3820 if ($LaTeXERROR) {
3821 print "\n\n*** LaTeXERROR\n"; return();
3822 }
3824 while ( ($name, $page_num) = each %new_id_map) {
3825 # Extract the page, convert and save it
3826 &extract_image($page_num,$orig_name_map{$page_num});
3827 }
3828 }
3830 # Generate images for unknown environments, equations etc, and replace
3831 # the markers in the main text with them.
3832 # - $cached_env_img maps encoded contents to image URL's
3833 # - $id_map maps $env$id to page numbers in the generated latex file and after
3834 # the images are generated, maps page numbers to image URL's
3835 # - $page_map maps page_numbers to image URL's (temporary map);
3836 # Uses global variables $id_map and $cached_env_img,
3837 # $new_page_num and $latex_body
3840 sub make_images {
3841 local($name, $contents, $raw_contents, $uucontents, $page_num,
3842 $uucontents, %page_map, $img);
3843 # It is necessary to run LaTeX this early because we need the log file
3844 # which contains information used to determine equation alignment
3845 if ( $latex_body =~ /newpage/) {
3846 print "\n";
3847 if ($LATEX_DUMP) {
3848 # dump a pre-compiled format
3849 if (!(-f "${PREFIX}images.fmt")) {
3850 print "$INILATEX ./${PREFIX}images.tex\n"
3851 if (($DEBUG)||($VERBOSITY > 1));
3852 print "dumping ${PREFIX}images.fmt\n"
3853 unless ( L2hos->syswait("$INILATEX ./${PREFIX}images.tex"));
3854 }
3855 local ($img_fmt) = (-f "${PREFIX}images.fmt");
3856 if ($img_fmt) {
3857 # use the pre-compiled format
3858 print "$TEX \"&./${PREFIX}images\" ./${PREFIX}images.tex\n"
3859 if (($DEBUG)||($VERBOSITY > 1));
3860 L2hos->syswait("$TEX \"&./${PREFIX}images\" ./${PREFIX}images.tex");
3861 } elsif (-f "${PREFIX}images.dvi") {
3862 print "${PREFIX}images.fmt failed, proceeding anyway\n";
3863 } else {
3864 print "${PREFIX}images.fmt failed, trying without it\n";
3865 print "$LATEX ./${PREFIX}images.tex\n"
3866 if (($DEBUG)||($VERBOSITY > 1));
3867 L2hos->syswait("$LATEX ./${PREFIX}images.tex");
3868 }
3869 } else { &make_latex_images() }
3870 # local($latex_call) = "$LATEX .$dd${PREFIX}images.tex";
3871 # print "$latex_call\n" if (($DEBUG)||($VERBOSITY > 1));
3872 # L2hos->syswait("$latex_call");
3873 ## print "$LATEX ./${PREFIX}images.tex\n" if (($DEBUG)||($VERBOSITY > 1));
3874 ## L2hos->syswait("$LATEX ./${PREFIX}images.tex");
3875 ## }
3876 $LaTeXERROR = 0;
3877 &process_log_file("./${PREFIX}images.log"); # Get image size info
3878 }
3879 if ($NO_IMAGES) {
3880 my $img = "image.$IMAGE_TYPE";
3881 my $img_path = "$LATEX2HTMLDIR${dd}icons$dd$img";
3882 L2hos->Copy($img_path, ".$dd$img")
3883 if(-e $img_path && !-e $img);
3884 }
3885 elsif ((!$NOLATEX) && ($latex_body =~ /newpage/) && !($LaTeXERROR)) {
3886 print "\nGenerating postscript images using dvips ...\n";
3887 &make_tmp_dir; # sets $TMPDIR and $DESTDIR
3888 $IMAGE_PREFIX =~ s/^_//o if ($TMPDIR);
3890 local($dvips_call) =
3891 "$DVIPS -S1 -i $DVIPSOPT -o$TMPDIR$dd$IMAGE_PREFIX .${dd}${PREFIX}images.dvi\n";
3892 print $dvips_call if (($DEBUG)||($VERBOSITY > 1));
3894 if ((($PREFIX=~/\./)||($TMPDIR=~/\./)) && not($DVIPS_SAFE)) {
3895 print " *** There is a '.' in $TMPDIR or $PREFIX filename;\n"
3896 . " dvips will fail, so image-generation is aborted ***\n";
3897 } else {
3898 &close_dbm_database if $DJGPP;
3899 L2hos->syswait($dvips_call) && print "Error: $!\n";
3900 &open_dbm_database if $DJGPP;
3901 }
3903 # append .ps suffix to the filenames
3904 if(opendir(DIR, $TMPDIR || '.')) {
3905 # use list-context instead; thanks De-Wei Yin <yin@asc.on.ca>
3906 my @ALL_IMAGE_FILES = grep /^$IMAGE_PREFIX\d+$/o, readdir(DIR);
3907 foreach (@ALL_IMAGE_FILES) {
3908 L2hos->Rename("$TMPDIR$dd$_", "$TMPDIR$dd$_.ps");
3909 }
3910 closedir(DIR);
3911 } else {
3912 print "\nError: Cannot read dir '$TMPDIR': $!\n";
3913 }
3914 }
3915 do {print "\n\n*** LaTeXERROR"; return()} if ($LaTeXERROR);
3916 return() if ($LaTeXERROR); # empty .dvi file
3917 L2hos->Unlink(".$dd${PREFIX}images.dvi") unless $DEBUG;
3919 print "\n *** updating image cache\n" if ($VERBOSITY > 1);
3920 while ( ($uucontents, $_) = each %cached_env_img) {
3921 delete $cached_env_img{$uucontents}
3922 if ((/$PREFIX$img_rx\.$IMAGE_TYPE/o)&&!($DESTDIR&&$NO_SUBDIR));
3923 $cached_env_img{$uucontents} = $_
3924 if (s/$PREFIX$img_rx\.new/$PREFIX$1.$IMAGE_TYPE/go);
3925 }
3926 print "\n *** removing unnecessary images ***\n" if ($VERBOSITY > 1);
3927 while ( ($name, $page_num) = each %id_map) {
3928 $contents = $latex_body{$name};
3929 if ($page_num =~ /^\d+\#\d+$/) { # If it is a page number
3930 do { # Extract the page, convert and save it
3931 $img = &extract_image($page_num,$orig_name_map{$page_num});
3932 if ($contents =~ /$htmlimage_rx/) {
3933 $uucontents = &special_encoding($env,$2,$contents);
3934 } elsif ($contents =~ /$htmlimage_pr_rx/) {
3935 $uucontents = &special_encoding($env,$2,$contents);
3936 } else {
3937 $uucontents = &encode(&addto_encoding($contents,$contents));
3938 }
3939 if (($HTML_VERSION >=3.2)||!($contents=~/$order_sensitive_rx/)){
3940 $cached_env_img{$uucontents} = $img;
3941 } else {
3942 # Blow it away so it is not saved for next time
3943 delete $cached_env_img{$uucontents};
3944 print "\nimage $name not recycled, contents may change (e.g. numbering)";
3945 }
3946 $page_map{$page_num} = $img;
3947 } unless ($img = $page_map{$page_num}); # unless we've just done it
3948 $id_map{$name} = $img;
3949 } else {
3950 $img = $page_num; # it is already available from previous runs
3951 }
3952 print STDOUT " *** image done ***\n" if ($VERBOSITY > 2);
3953 }
3954 &write_warnings(
3955 "\nOne of the images is more than one page long.\n".
3956 "This may cause the rest of the images to get out of sync.\n\n")
3957 if (-f sprintf("%s%.3d%s", $IMAGE_PREFIX, ++$new_page_num, ".ps"));
3958 print "\n *** no more images ***\n" if ($VERBOSITY > 1);
3959 # MRO: The following cleanup seems to be incorrect: The DBM is
3960 # still open at this stage, this causes a lot of unlink errors
3961 #
3962 #do { &cleanup; print "\n *** clean ***\n" if ($VERBOSITY > 1);}
3963 # unless $DJGPP;
3964 }
3966 # MRO: This copies the navigation icons from the distribution directory
3967 # or an alternative specified in $ALTERNATIVE_ICONS
3968 # to the document directory.
3970 sub copy_icons {
3971 local($icon,$_);
3972 print "\nCopying navigation icons ...";
3973 foreach (keys %used_icons) {
3974 # each entry ends in gif or png
3975 if ($ALTERNATIVE_ICONS) {
3976 L2hos->Copy("$ALTERNATIVE_ICONS$dd$_", ".$dd$_")
3977 if (-e "$ALTERNATIVE_ICONS$dd$_" && !-e $_);
3978 } elsif (/(gif|png)$/) {
3979 L2hos->Copy("$LATEX2HTMLDIR${dd}icons$dd$_", ".$dd$_")
3980 if (-e "$LATEX2HTMLDIR${dd}icons$dd$_" && !-e $_);
3981 }
3982 }
3983 }
3985 sub process_log_file {
3986 local($logfile) = @_;
3987 local($name,$before,$lengthsfound);
3988 local($TeXpt)= 72/72.27;
3989 local($image_counter);
3990 open(LOG, "<$logfile") || die "\nCannot read logfile '$logfile': $!\n";
3991 while (<LOG>) {
3992 if (/Overfull/) { $before .= $_ }
3993 elsif (/latex2htmlLength ([a-zA-Z]+)=(\-?[\d\.]+)pt/) {
3994 ${$1} = 0.0+$2; $lengthsfound = 1;
3995 } elsif (/latex2htmlSize|l2hSize/) {
3996 /:([^:]*):/;
3997 $name = $1; $name =~ s/\*//g;
3998 ++$image_counter;
3999 s/:([0-9.]*)pt/$height{$name} = $1*$TeXpt;''/e;
4000 s/::([0-9.]*)pt/$depth{$name} = $1*$TeXpt;''/e;
4001 s/::([0-9.]*)pt/$width{$name} = $1*$TeXpt;''/e;
4002 s/\((.*)\)/$eqno{$name} = 1+$1;''/e;
4003 if ($before) {
4004 local($tmp);
4005 if ($before =~ /hbox\s*\((\d+\.?\d*)pt/) {
4006 $width{$name} = $width{$name}+$1*$TeXpt;
4007 }
4008 if ($before =~ /vbox\s*\((\d+\.?\d*)pt/) {
4009 $height{$name} = $height{$name}+$1*$TeXpt;
4010 }
4011 $before = '';
4012 }
4013 }
4014 $LaTeXERROR = 1 if (/^No pages of output./);
4015 }
4017 if ($LaTeXERROR) {
4018 print STDERR "\n\n *** LaTeX produced no output ***\n"
4019 . " *** no new images can be created\n"
4020 . " *** Examine the images.log file.\n\n";
4021 return;
4022 }
4023 print STDOUT "\n *** processing $image_counter images ***\n";
4024 print STDOUT "\n *** LATEX LOG OK. ***\n" if ($VERBOSITY > 1);
4026 if ($lengthsfound) {
4027 $ODD_HMARGIN = $hoffset + $oddsidemargin;
4028 $EVEN_HMARGIN = $hoffset + $evensidemargin;
4029 $VMARGIN = $voffset + $topmargin + $headheight + $headsep;
4030 if ($dvi_mag >0 && $dvi_mag != 1000) {
4031 $ODD_HMARGIN = int($dvi_mag /1000 * $ODD_HMARGIN);
4032 $EVEN_HMARGIN = int($dvi_mag /1000 * $EVEN_HMARGIN);
4033 $VMARGIN = int($dvi_mag /1000 * $VMARGIN);
4034 }
4035 } else {
4036 $ODD_HMARGIN = 0;
4037 $EVEN_HMARGIN = 0;
4038 $VMARGIN = 0;
4039 }
4040 $ODD_HMARGIN = int($ODD_HMARGIN*$TeXpt + 72.5);
4041 $EVEN_HMARGIN = int($EVEN_HMARGIN*$TeXpt + 72.5);
4042 $VMARGIN = int($VMARGIN*$TeXpt + 72.5);
4043 close(LOG);
4044 }
4046 sub extract_image { # clean
4047 my ($page_num,$name) = @_;
4049 # The followin come out of %img_params
4050 my ($scale, $external, $thumbnail, $map, $psimage, $align, $usemap,
4051 $flip, $aalias, $trans, $exscale, $alt, $exstr);
4053 my ($lwidth, $val) = (0, '');
4054 my ($custom_size,$color_depth,$height,$width,$croparg);
4056 print STDOUT "\nextracting $name as $page_num\n" if ($VERBOSITY > 1);
4057 # $global_num identifies this image in the original source file
4058 # $new_num identifies this image in images.tex
4059 my ($global_num, $new_num) = split(/#/, $page_num);
4060 $name =~ s/\*/star/;
4061 my ($env,$basename,$img) = ($name,"img$global_num",'');
4062 $env =~ s/\d+$//;
4063 $psname = sprintf("%s%.3d", "$TMPDIR$dd$IMAGE_PREFIX", $new_num);
4064 if ( $EXTERNAL_IMAGES && $PS_IMAGES ) {
4065 $img = "$basename.ps";
4066 L2hos->Copy("$psname.ps", "${PREFIX}$img");
4067 } else {
4068 $img = "$basename.$IMAGE_TYPE";
4069 ($scale, $external, $thumbnail, $map, $psimage, $align, $usemap,
4070 $flip, $aalias, $trans, $exscale, $alt, $exstr) =
4071 split('#', $img_params{$name});
4072 $lwidth = ($align =~ s/nojustify/middle/) ? 0 : $LINE_WIDTH;
4073 $alt = "ALT=\"$name\"" unless $alt;
4074 $exscale = $EXTRA_IMAGE_SCALE unless($exscale);
4075 if ($NO_IMAGES) {
4076 L2hos->Symlink("image.$IMAGE_TYPE", "${PREFIX}$img");
4077 if ($thumbnail) {
4078 L2hos->Symlink("image.$IMAGE_TYPE", "${PREFIX}T$img");
4079 $thumbnail = "${PREFIX}T$img";
4080 }
4081 } else {
4082 # RRM: deal with size data
4083 if ($width{$name} < 0) {
4084 if ($exscale && $PK_GENERATION) {
4085 $height = int(
4086 $exscale*$height{$name}+
4087 $exscale*$depth{$name} +.5);
4088 $width = int($exscale*$width{$name}-.5);
4089 } else {
4090 $height = int($height{$name}+$depth{$name}+.5);
4091 $width = int($width{$name}-.5);
4092 }
4093 $custom_size = "${width}x$height";
4094 } elsif ($width{$name}) {
4095 if ($exscale && $PK_GENERATION) {
4096 $height = int( $height{$name} * $exscale +
4097 $depth{$name} * $exscale +.5);
4098 $width = int($width{$name} * $exscale +.5);
4099 } else {
4100 $height = int($height{$name}+$depth{$name}+.5);
4101 $width = int($width{$name}+.5);
4102 }
4103 $custom_size = "${width}x$height";
4104 } else {
4105 $custom_size = '';
4106 }
4107 # MRO: add first overall crop
4108 $croparg = '-crop a' . ($crop{$name} || '') . ' ';
4109 $page_num =~ s/^\d+#//o;
4110 $custom_size .= " -margins "
4111 . (($page_num % 2) ? $ODD_HMARGIN:$EVEN_HMARGIN)
4112 . ",$VMARGIN" if ($custom_size);
4114 #RRM: \special commands may place ink outside the expected bounds:
4115 $custom_size = '' if ($tex_specials{$name});
4117 # MRO: Patches for image conversion with pstoimg
4118 # RRM: ...with modifications and fixes
4119 L2hos->Unlink("${PREFIX}$img");
4120 &close_dbm_database if $DJGPP;
4121 print "Converting image #$new_num\n";
4123 if ( ($name =~ /figure/) || $psimage || $scale || $thumbnail) {
4124 $scale = $FIGURE_SCALE_FACTOR unless ($scale);
4125 print "\nFIGURE: $name scaled $scale $aalias\n" if ($VERBOSITY > 2);
4126 (L2hos->syswait( "$PSTOIMG -type $IMAGE_TYPE "
4127 . ($DEBUG ? '-debug ' : '-quiet ' )
4128 . ($TMPDIR ? "-tmp $TMPDIR " : '' )
4129 . (($DISCARD_PS && !$thumbnail && !$psimage)? "-discard " :'')
4130 . (($INTERLACE) ? "-interlace " : '' )
4131 . (((($ANTI_ALIAS)||($aalias))&&($aalias !~ /no|text/))? "-antialias ":'')
4132 . (($ANTI_ALIAS_TEXT||(($aalias =~/text/)&&($aalias !~/no/)))?
4133 "-aaliastext ":'')
4134 . (($custom_size) ? "-geometry $custom_size ": '' )
4135 . $croparg
4136 . ($color_depth || '')
4137 . (($flip) ? "-flip $flip " : '' )
4138 . (($scale > 0) ? "-scale $scale " : '' )
4139 . (((($TRANSPARENT_FIGURES && ($env =~ /figure/o))||($trans))
4140 &&(!($trans =~ /no/))) ? "-transparent " : '')
4141 . (($WHITE_BACKGROUND) ? "-white " : '' )
4142 . "-out ${PREFIX}$img $psname.ps"
4143 ) ) # ||!(print "\nWriting image: ${PREFIX}$img"))
4144 && print "\nError while converting image: $!\n";
4146 if ($thumbnail) { # $thumbnail contains the reduction factor
4147 L2hos->Unlink("${PREFIX}T$img");
4148 print "\nIMAGE thumbnail: $name" if ($VERBOSITY > 2);
4149 (L2hos->syswait( "$PSTOIMG -type $IMAGE_TYPE "
4150 . ($DEBUG ? '-debug ' : '-quiet ' )
4151 . ($TMPDIR ? "-tmp $TMPDIR " : '' )
4152 . (($DISCARD_PS && !$psimage) ? "-discard " : '' )
4153 . (($INTERLACE) ? "-interlace " : '' )
4154 . ((($ANTI_ALIAS||($aalias))&&(!($aalias =~/no/)))? "-antialias " :'')
4155 . (($ANTI_ALIAS_TEXT||(($aalias =~/text/)&&($aalias !~/no/)))?
4156 "-aaliastext ":'')
4157 . (($custom_size) ? "-geometry $custom_size " : '' )
4158 . ($color_depth || '')
4159 . (($flip) ? "-flip $flip " : '' )
4160 . (($thumbnail > 0) ? "-scale $thumbnail " : '' )
4161 . ((($trans)&&(!($trans =~ /no/))) ? "-transparent " : '')
4162 . (($WHITE_BACKGROUND) ? "-white " : '' )
4163 . "-out ${PREFIX}T$img $psname.ps"
4164 ) ) # ||!(print "\nWriting image: ${PREFIX}T$img"))
4165 && print "\nError while converting thumbnail: $!\n";
4166 $thumbnail = "${PREFIX}T$img";
4167 }
4168 } elsif (($exscale &&(!$PK_GENERATION))&&($width{$name})) {
4169 my $under = '';
4170 my $mathscale = ($MATH_SCALE_FACTOR > 0) ? $MATH_SCALE_FACTOR : 1;
4171 if (($DISP_SCALE_FACTOR > 0) &&
4172 ( $name =~ /equation|eqnarray|display/))
4173 { $mathscale *= $DISP_SCALE_FACTOR; };
4174 if ($scale) {
4175 $scale *= $exscale if ($name =~ /makeimage|tab/);
4176 } else {
4177 $scale = $mathscale*$exscale;
4178 $under = "d" if (($name =~/inline|indisplay/)&&($depth{$name}));
4179 }
4180 print "\nIMAGE: $name scaled by $scale \n" if ($VERBOSITY > 2);
4181 (L2hos->syswait( "$PSTOIMG -type $IMAGE_TYPE "
4182 . ($DEBUG ? '-debug ' : '-quiet ' )
4183 . ($TMPDIR ? "-tmp $TMPDIR " : '' )
4184 . (($DISCARD_PS)? "-discard " : '' )
4185 . (($INTERLACE)? "-interlace " : '' )
4186 . ((($ANTI_ALIAS_TEXT||($aalias))&&($aalias !=~/no/))?
4187 "-antialias -depth 1 " :'')
4188 . (($custom_size)? "-geometry $custom_size " : '' )
4189 . $croparg
4190 . (($scale != 1)? "-scale $scale " : '' )
4191 . ((($exscale)&&($exscale != 1)&&
4192 !($ANTI_ALIAS_TEXT &&($LATEX_COLOR)))?
4193 "-shoreup $exscale$under " :'')
4194 . ((($TRANSPARENT_FIGURES ||($trans))
4195 &&(!($trans =~ /no/)))? "-transparent " : '')
4196 . (($WHITE_BACKGROUND && !$TRANSPARENT_FIGURES) ? "-white " : '' )
4197 . "-out ${PREFIX}$img $psname.ps"
4198 ) ) # ||!(print "\nWriting image: ${PREFIX}$img"))
4199 && print "\nError while converting image: $!\n";
4200 } else {
4201 print "\nIMAGE: $name\n" if ($VERBOSITY > 2);
4202 my $under = '';
4203 my $mathscale = ($MATH_SCALE_FACTOR > 0) ? $MATH_SCALE_FACTOR : 1;
4204 if (($DISP_SCALE_FACTOR > 0) &&
4205 ( $name =~ /equation|eqnarray|display/))
4206 { $mathscale *= $DISP_SCALE_FACTOR; };
4207 if (($scale)&&($exscale)) {
4208 $scale *= $exscale if ($name =~ /makeimage|tab/);
4209 } elsif ($scale) {
4210 } elsif (($mathscale)&&($exscale)) {
4211 $scale = $mathscale*$exscale;
4212 $under = "d" if (($name =~/inline|indisplay/)&&($depth{$name}));
4213 } elsif ($mathscale) { $scale = $mathscale; }
4215 (L2hos->syswait("$PSTOIMG -type $IMAGE_TYPE "
4216 . ($DEBUG ? '-debug ' : '-quiet ' )
4217 . ($TMPDIR ? "-tmp $TMPDIR " : '' )
4218 . (($DISCARD_PS) ? "-discard " : '' )
4219 . (($INTERLACE) ? "-interlace " : '' )
4220 . ((($ANTI_ALIAS_TEXT||($aalias))&&(!($aalias =~ /no/)))?
4221 "-antialias -depth 1 " :'')
4222 . ((($exscale)&&($exscale != 1)&&
4223 !($ANTI_ALIAS_TEXT &&($LATEX_COLOR)))?
4224 "-shoreup $exscale " :'')
4225 . (($scale ne 1) ? "-scale $scale " : '' )
4226 . (($custom_size) ? "-geometry $custom_size " : '' )
4227 . $croparg
4228 # . (($name =~ /(equation|eqnarray)/) ? "-rightjustify $lwidth " : '')
4229 # . (($name =~ /displaymath/) ? "-center $lwidth " : '')
4230 . (($name =~ /inline|indisplay/ && (!($custom_size))&&$depth{$name}!= 0) ?
4231 do {$val=($height{$name}-$depth{$name})/($height{$name}+$depth{$name});
4232 "-topjustify x$val "} : '')
4233 . ((($TRANSPARENT_FIGURES||($trans))
4234 &&(!($trans =~ /no/))) ? "-transparent " : '')
4235 . (($WHITE_BACKGROUND && !$TRANSPARENT_FIGURES) ? "-white " : '' )
4236 . "-out ${PREFIX}$img $psname.ps")
4237 ) #|| !(print "\nWriting image: ${PREFIX}$img"))
4238 && print "\nError while converting image\n";
4239 }
4240 if (! -r "${PREFIX}$img") {
4241 &write_warnings("\nFailed to convert image $psname.ps")
4242 } else { } #L2hos->Unlink("$psname.ps") unless $DEBUG }
4243 &open_dbm_database if $DJGPP;
4244 }
4245 }
4246 print "\nextracted $name as $page_num\n" if ($VERBOSITY > 1);
4247 &embed_image("${PREFIX}$img", $name, $external, $alt, $thumbnail, $map,
4248 $align, $usemap, $exscale, $exstr);
4249 }
4251 sub extract_parameters {
4252 local($contents) = @_;
4253 local($_, $scale, $external, $thumbnail, $map, $psimage, $align,
4254 $usemap, $flip, $aalias, $trans, $pagecolor, $alt, $exscale,
4255 $cdepth, $htmlparams);
4257 #remove the \htmlimage commands and arguments before...
4258 $contents =~ s/$htmlimage_rx/$_ = $2;''/ego;
4259 $contents =~ s/$htmlimage_pr_rx/$_ .= $2;''/ego;
4261 # code adapted from original idea by Stephen Gildea:
4262 # If the document specifies the ALT tag explicitly
4263 # with \htmlimage{alt=some text} then use it.
4264 s!alt=([^,]+)!$alt = $1;
4265 $alt =~ s/^\s+|\s+$//g; $alt =~ s/"//g;
4266 $alt="ALT=\"$alt\"";
4267 ''!ie;
4269 if (!$alt) {
4270 #...catching all the code for the ALT text.
4271 local($keep_gt)=1;
4272 $alt = &flatten_math($contents); undef $keep_gt;
4273 #RRM: too long strings upset the DBM. Truncate to <= 165 chars.
4274 if ( length($alt) > 163 ) {
4275 local($start,$end);
4276 $start = substr($alt,0,80);
4277 $end = substr($alt,length($alt)-80,80);
4278 $alt = join('',$start,"...\n ...",$end);
4279 }
4280 s/ALT\s*=\"([\w\W]*)\"/$alt=$1;''/ie;
4281 if ($alt) {
4282 if ($alt =~ /\#/) {
4283 $alt =~ s/^(\\vbox\{)?\#[A-Za-z]*\s*//;
4284 $alt =~ s/\n?\#[A-Za-z]*\s*\}?$//s;
4285 if ($alt =~ /\#/) { $alt = $` . " ... " };
4286 }
4287 $alt =~ s/\`\`/\\lq\\lq /g; $alt =~ s/\`/\\lq /g;
4288 $alt =~ s/(^\s*|\s*$)//mg;
4289 $alt = "ALT=\"$alt\"" if ($alt);
4290 } else { $alt = 'ALT="image"' }
4291 }
4293 $psimage++ if ($contents =~ /\.ps/);
4294 # $contents =~ s/\s//g; # Remove spaces Why ?
4295 s/extrascale=([\.\d]*)/$exscale=$1;''/ie;
4296 s/\bscale=([\.\d]*)/$scale=$1;''/ie;
4297 s/(^|,\s*)external/$external=1;''/ie;
4298 s/(^|,\s*)((no)?_?anti)alias(_?(text))?/$aalias = $2.$4;''/ie;
4299 s/(^|,\s*)((no)?_?trans)parent/$trans = $2;''/ie;
4300 s/thumbnail=([\.\d]*)/$thumbnail=$1;''/ie;
4301 s/usemap=([^\s,]+)/$usemap=$1;''/ie;
4302 s/map=([^\s,]+)/;$map=$1;''/ie;
4303 s/align=([^\s,]+)/$align=$1;''/ie;
4304 s/flip=([^\s,]+)/$flip=$1;''/ie;
4305 s/color_?(depth)?=([^\s,]+)/$cdepth=$2;''/ie;
4306 ($scale,$external,$thumbnail,$map,$psimage,$align
4307 ,$usemap,$flip,$aalias,$trans,$exscale,$alt,$_);
4308 }
4311 # RRM: Put the raw \TeX code into the ALT tag
4312 # replacing artificial environments and awkward characters
4313 sub flatten_math {
4314 local ($_) = @_;
4315 $_ = &revert_to_raw_tex($_);
4316 s/[ \t]+/ /g;
4317 # MRO: replaced $* with /m
4318 s/$tex2html_wrap_rx//gm;
4319 s/(\\begin\s*\{[^\}]*\})(\s*(\[[^]]*\]))?[ \t]*/$1$3/gm;
4320 s/(\\end\{[^\}]*\})\n?/$1/gm;
4321 s/>(\w)?/($1)?"\\gt $1":"\\gt"/eg unless ($keep_gt); # replace > by \gt
4322 s/\\\|(\w)?/($1)?"\\Vert $1":"\\Vert"/eg; # replace \| by \Vert
4323 s/\|(\w)?/($1)?"\\vert $1":"\\vert"/eg; # replace | by \vert
4324 s/\\\\/\\\\ /g; # insert space after \\
4325 s/\\"/\\uml /g; # screen umlaut accents...
4326 s/"/\'\'/g; # replace " by ''
4327 s/\\\#/\\char93 /g; # replace \# by \char93 else caching fails
4328 # s/"(\w)?/($1)?"\\rq\\rq $1":"\'\'"/eg; # replace " by \rq\rq
4329 # s/\&\\uml /\\\"/g; # ...reinstate umlauts
4330 $_;
4331 }
4333 sub scaled_image_size {
4334 local($exscale,$_) = @_;
4335 local($width,$height) = ('','');
4336 /WIDTH=\"?(\d*)\"?\s*HEIGHT=\"?(\d*)\"?$/o;
4337 $width=int($1/$exscale + .5);
4338 $height=int($2/$exscale + .5);
4339 "WIDTH=\"$width\" HEIGHT=\"$height\""
4340 }
4342 sub process_in_latex {
4343 # This is just a wrapper for process_undefined_environment.
4344 # @[0] = contents
4345 $global{'max_id'}++;
4346 &process_undefined_environment('tex2html_wrap',$global{'max_id'},$_[0]);
4347 }
4349 # MRO: cp deprecated, replaced by L2hos->Copy
4351 # Marcus Hennecke 6/3/96
4352 # MRO: test for existance
4353 sub copy_file {
4354 local($file, $ext) = @_;
4355 $file = &fulltexpath("$FILE.$ext");
4356 if(-r $file) {
4357 print "\nNote: Copying '$file' for image generation\n"
4358 if($VERBOSITY > 2);
4359 L2hos->Copy($file, ".$dd${PREFIX}images.$ext");
4360 }
4361 }
4363 sub rename_image_files {
4364 local($_, $old_name, $prefix);
4365 if ($PREFIX) {
4366 foreach (<${PREFIX}*img*.$IMAGE_TYPE>) {
4367 $old_name = $_;
4368 s/\.$IMAGE_TYPE$/\.old/o;
4369 L2hos->Rename($old_name, $_);
4370 }
4371 }
4372 else {
4373 foreach (<img*.$IMAGE_TYPE>) {
4374 $old_name = $_;
4375 s/\.$IMAGE_TYPE$/\.old/o;
4376 L2hos->Rename($old_name, $_);
4377 }
4378 foreach (<Timg*.$IMAGE_TYPE>) {
4379 $old_name = $_;
4380 s/\.$IMAGE_TYPE$/\.old/o;
4381 L2hos->Rename($old_name, $_);
4382 }
4383 }
4384 }
4387 ############################ Processing Commands ##########################
4389 sub ignore_translate_commands {
4390 local ($_) = @_;
4391 # print "\nTranslating commands ...";
4393 local(@processedC);
4394 &replace_strange_accents;
4395 local($before, $contents, $br_id, $after, $pattern, $end_cmd_rx);
4396 s/$begin_cmd_rx/&replace_macro_expansion($`, $1, $&, $')/eg;
4397 }
4399 sub replace_macro_expansion {
4400 push(@processedC,$_[1]);
4401 $end_cmd_rx = &make_end_cmd_rx($_[2]);
4402 $pattern = $_[3];
4403 $_ = join('',$_[3],$_[4]);
4404 $after = $_[4];
4405 if (($before)&&(!($before =~ /$begin_cmd_rx/))) {
4406 push(@processedC,$before);
4407 $_ = join('',$pattern,$after); $before = '';
4408 }
4409 local($end_cmd_rx) = &make_end_cmd_rx($br_id);
4411 }
4413 sub translate_aux_commands {
4414 s/^(.*)$/&translate_commands($1)/s;
4415 }
4417 sub translate_commands {
4418 local ($_) = @_;
4419 # print "\nTranslating commands ...";
4421 local(@processedC);
4422 &replace_strange_accents;
4423 for (;;) { # For each opening bracket ...
4424 last unless ($_ =~ /$begin_cmd_rx/);
4425 local($before, $contents, $br_id, $after, $pattern);
4426 ($before, $br_id, $after, $pattern) = ($`, $1, $', $&);
4427 if (($before)&&(!($before =~ /$begin_cmd_rx/))) {
4428 push(@processedC,$before);
4429 $_ = join('',$pattern,$after); $before = '';
4430 }
4431 local($end_cmd_rx) = &make_end_cmd_rx($br_id);
4432 if ($after =~ /$end_cmd_rx/) { # ... find the the matching closing one
4433 $NESTING_LEVEL++;
4434 ($contents, $after) = ($`, $');
4435 do {
4436 local(@save_open_tags) = @$open_tags_R;
4437 local($open_tags_R) = [ @save_open_tags ];
4438 print STDOUT "\nIN::{$br_id}" if ($VERBOSITY > 4);
4439 print STDOUT "\n:$contents\n" if ($VERBOSITY > 7);
4440 undef $_;
4441 $contents = &translate_commands($contents)
4442 if ($contents =~ /$match_br_rx/o);
4443 # Modifies $contents
4444 &process_command($single_cmd_rx,$contents)
4445 if ($contents =~ /\\/o);
4447 $contents .= &balance_tags();
4448 };
4450 print STDOUT "\nOUT: {$br_id}" if ($VERBOSITY > 4);
4451 print STDOUT "\n:$contents\n" if ($VERBOSITY > 7);
4452 # THIS MARKS THE OPEN-CLOSE DELIMITERS AS PROCESSED
4453 $_ = join("", $before,"$OP$br_id$CP", $contents,"$OP$br_id$CP", $after);
4454 $NESTING_LEVEL--;
4455 }
4456 else {
4457 $pattern = &escape_rx_chars($pattern);
4458 s/$pattern//;
4459 print "\nCannot find matching bracket for $br_id" unless $AUX_FILE;
4460 }
4461 last unless ($_ =~ /$begin_cmd_rx/o);
4462 }
4463 $_ = join('',@processedC) . $_;
4464 # Now do any top level commands that are not inside any brackets
4465 # MODIFIES $_
4466 print $_ if ($VERBOSITY > 8);
4467 &process_command($single_cmd_rx,$_);
4468 }
4470 #RRM: based on earlier work of Marcus Hennecke
4471 # makes sure the $open_tags_R at the end of an environment
4472 # is the same as @save_open_tags from the start,
4473 # ensuring that the HTML page indeed has balanced tags
4474 sub balance_tags {
4475 local($tag_cmd, $tags, $save_tags, $open_tags, @reopen_tags);
4476 $save_tags = join(',',@save_open_tags) if (@save_open_tags);
4477 $open_tags = join(',',@$open_tags_R) if (@$open_tags_R);
4478 if ($open_tags eq $save_tags) { return(); }
4479 if ($save_tags =~ s/^$open_tags//) {
4480 @reopen_tags = split (',',$');
4481 } else {
4482 @reopen_tags = @save_open_tags;
4483 while (@$open_tags_R) {
4484 $tag_cmd = pop (@$open_tags_R);
4485 print STDOUT "\n</$tag_cmd>" if $VERBOSITY > 2;
4486 $declarations{$tag_cmd} =~ m|</.*$|;
4487 $tags .= $& unless ($` =~ /^<>$/);
4488 $open_tags = join(',',@$open_tags_R) if (@$open_tags_R);
4489 last if ( $save_tags =~ s/^$open_tags/
4490 @reopen_tags = split (',',$');''/e);
4491 }
4492 }
4493 while (@reopen_tags) {
4494 $tag_cmd = shift @reopen_tags;
4495 if ($tag_cmd) {
4496 push (@$open_tags_R, $tag_cmd) if ($tag_cmd);
4497 print STDOUT "\n<$tag_cmd>" if $VERBOSITY > 2;
4498 $declarations{$tag_cmd} =~ m|</.*$|;
4499 $tags .= $` unless ($` =~ /^<>$/);
4500 }
4501 }
4502 $tags;
4503 }
4505 sub close_all_tags {
4506 return() if (!@$open_tags_R);
4507 local($tags,$tag_cmd);
4508 while (@$open_tags_R) {
4509 $tag_cmd = pop (@$open_tags_R);
4510 print STDOUT "\n</$tag_cmd>" if $VERBOSITY > 2;
4511 $declarations{$tag_cmd} =~ m|</.*$|;
4512 $tags .= $& unless ($` =~ /^<>$/);
4513 }
4514 $tags;
4515 }
4517 sub preserve_open_tags {
4518 local(@save_open_tags) = @$open_tags_R;
4519 local($open_tags_R) = [ @save_open_tags ];
4520 # provides the markup to close and reopen the current tags
4521 (&close_all_tags(), &balance_tags());
4522 }
4524 sub preserve_open_block_tags {
4525 local($tag_cmd,$tags_open,$tags_close,$pre,$post,@tags);
4526 while (@$open_tags_R) {
4527 $tag_cmd = pop (@$open_tags_R);
4528 print STDOUT "\n</$tag_cmd>" if $VERBOSITY > 2;
4529 $declarations{$tag_cmd} =~ m|</.*$|;
4530 ($pre,$post) = ($`,$&);
4531 if ($post =~ /$block_close_rx/) {
4532 # put it back and exit
4533 push(@$open_tags_R,$tag_cmd);
4534 last;
4535 } else {
4536 # leave it closed, collecting tags for it
4537 $tags_close .= $post;
4538 $tags_open = $pre . $tags_open;
4539 unshift(@tags,$tag_cmd);
4540 }
4541 }
4542 ($tags_close , $tags_open, @tags);
4543 }
4545 sub minimize_open_tags {
4546 local($this_tag, $close_only) = @_;
4547 local($pre,$post,$decl);
4548 $decl = $declarations{$this_tag};
4549 if ($decl) {
4550 # if it is a declaration, get the corresponding tags...
4551 $decl =~ m|</.*$|;
4552 ($pre,$post) = ($`,$&) unless ($` =~ /^<>$/);
4553 if (!@$open_tags_R) { # when nothing else is open...
4554 # pushing the style, when appropriate
4555 push (@$open_tags_R, $this_tag)
4556 unless ($close_only ||($post =~ /$block_close_rx/));
4557 print STDOUT "\n<$this_tag>" if $VERBOSITY > 2;
4558 # and return the tags
4559 return($pre,$post) unless ($USING_STYLES);
4560 local($env_id) = '' if ($env_id =~/^\w+$/);
4561 $pre =~ s/>$/ $env_id>/ if ($env_id);
4562 return($pre,$post);
4563 }
4564 } else { # ...else record the argument as $pre
4565 $pre = $this_tag unless $close_only;
4566 }
4567 local($env_id) = '' if ($env_id =~/^\w+$/);
4568 $pre =~ s/>$/ ID="$env_id">/ if ($USING_STYLES &&($env_id));
4570 # return the tags, if nothing is already open
4571 if (!@$open_tags_R) {
4572 return($pre,$post);
4573 }
4574 # elsif ($close_only) { push (@$open_tags_R, $this_tag) }
4576 local($tags,$tag_cmd,$tag_open);
4577 local($closures,$reopens,@tags);
4578 local($tag_close,$tag_open);
4579 local($size_cmd,$size_open);
4580 local($font_cmd,$font_open);
4581 local($fontwt_cmd,$fontwt_open);
4582 local($color_cmd,$color_open);
4583 if ($decl) {
4584 if ($this_tag =~ /$sizechange_rx/) {
4585 $size_cmd = $this_tag;
4586 } else {
4587 if ($this_tag =~ /$fontchange_rx/) {
4588 $font_cmd = $this_tag }
4589 if ($this_tag =~ /$fontweight_rx/) {
4590 $fontwt_cmd = $this_tag }
4591 }
4592 }
4593 while (@$open_tags_R) {
4594 ($tag_close,$tag_open) = ('','');
4595 $tag_cmd = pop (@$open_tags_R);
4596 print STDOUT "\n</$tag_cmd>" if $VERBOSITY > 2;
4597 $declarations{$tag_cmd} =~ m|</.*$|;
4598 ($tag_close,$tag_open) = ($&,$`) unless ($` =~ /<>/);
4599 $closures .= $tag_close;
4601 if ((!$size_cmd)&&($tag_cmd =~ /$sizechange_rx/)) {
4602 $size_cmd = $tag_cmd;
4603 $size_open = $tag_open;
4604 }
4605 elsif ((!$font_cmd)&&($tag_cmd =~ /$fontchange_rx/)) {
4606 $font_cmd = $tag_cmd;
4607 $font_open = $tag_open;
4608 }
4609 elsif ((!$fontwt_cmd)&&($tag_cmd =~ /$fontweight_rx/)) {
4610 $fontwt_cmd = $tag_cmd;
4611 $fontwt_open = $tag_open;
4612 }
4613 elsif ((!$color_cmd)&&($tag_cmd =~ /$colorchange_rx/)) {
4614 $color_cmd = $tag_cmd;
4615 $color_open = $tag_open;
4616 }
4617 elsif ($tag_cmd =~
4618 /$sizechange_rx|$fontchange_rx|$fontweight_rx|$colorchange_rx/) {
4619 } else {
4620 unshift (@tags, $tag_cmd);
4621 print STDOUT "\n<<$tag_cmd>" if $VERBOSITY > 2;
4622 $reopens = $tag_open . $reopens;
4623 }
4624 }
4625 if ($USING_STYLES) {
4626 local($TAG) = "DIV";
4627 if ($pre =~ /^<(DIV|SPAN|PRE)/) { $TAG = $1 };
4628 if (($pre =~ /^<$TAG/)&&($env_id =~ /^\s+(CLASS|ID)/)) {
4629 $pre =~ s/<$TAG/<$TAG$env_id/;
4630 } elsif ($pre =~ /<P>/) {
4631 $TAG = 'P';
4632 } else {
4633 }
4634 # $post .= "</$TAG>";
4635 }
4636 push (@$open_tags_R, @tags);
4637 $tags .= $pre if ($pre && $post =~ /$block_close_rx/);
4638 if ($font_cmd && !($font_cmd eq $this_tag)) {
4639 push (@$open_tags_R,$font_cmd);
4640 print STDOUT "\n<$font_cmd>" if $VERBOSITY > 2;
4641 $tags .= $font_open;
4642 }
4643 if ($fontwt_cmd && !($fontwt_cmd eq $this_tag)) {
4644 push (@$open_tags_R,$fontwt_cmd);
4645 print STDOUT "\n<$fontwt_cmd>" if $VERBOSITY > 2;
4646 $tags .= $fontwt_open;
4647 }
4648 if ($size_cmd && !($size_cmd eq $this_tag)) {
4649 push (@$open_tags_R,$size_cmd);
4650 print STDOUT "\n<$size_cmd>" if $VERBOSITY > 2;
4651 $tags .= $size_open;
4652 }
4653 if ($color_cmd && !($color_cmd eq $this_tag)) {
4654 push (@$open_tags_R,$color_cmd);
4655 print STDOUT "\n<$color_cmd>" if $VERBOSITY > 2;
4656 $tags .= $color_open;
4657 }
4658 $tags .= $pre unless ($pre && $post =~ /$block_close_rx/);
4659 push (@$open_tags_R, $this_tag)
4660 if ($decl &&!($post =~ /$block_close_rx|$all_close_rx/));
4661 print STDOUT "\n<$this_tag>" if $VERBOSITY > 2;
4662 ($closures.$reopens.$tags , $post );
4663 }
4666 sub declared_env {
4667 local($decl, $_, $deferred) = @_;
4668 local($after_cell,$pre,$post);
4669 local($decls) = $declarations{$decl};
4670 $decls =~ m|</.*$|;
4671 ($pre,$post) = ($`,$&);
4672 if ($USING_STYLES) {
4673 $env_style{$decl} = " " unless ($env_style{$decl});
4674 $pre =~ s/>$/$env_id>/ if ($env_id);
4675 }
4676 local($closing_tag) = 1 if ($pre =~ /^<>$/);
4677 $pre = $post = '' if $closing_tag;
4678 local($closures,$reopens);
4680 local(@save_open_tags) = @$open_tags_R
4681 unless ($closing_tag || $deferred);
4682 local($open_tags_R) = [ @save_open_tags ]
4683 unless ($closing_tag || $deferred );
4685 if ($post =~ /$block_close_rx/) {
4686 local($last_tag) = pop (@$open_tags_R);
4687 local($ldecl) = $declarations{$last_tag};
4688 if ($ldecl =~ m|</.*$|) { $ldecl = $& }
4689 if (($last_tag)&&!($ldecl =~ /$block_close_rx/)) {
4690 # need to close tags, for re-opening inside
4691 push (@$open_tags_R, $last_tag);
4692 ($closures,$reopens) = &preserve_open_tags();
4693 $pre = join('', $closures, "\n", $pre, $reopens);
4694 $post = join('', $closures, $post, $reopens);
4695 } elsif ($last_tag) {
4696 $pre = "\n".$pre;
4697 push (@$open_tags_R, $last_tag);
4698 undef $ldecl;
4699 } else {
4700 }
4702 if ($deferred) {
4703 if (defined $ldecl) {
4704 print STDOUT "\n<<$decl>" if $VERBOSITY > 2;
4705 unshift(@$open_tags_R, $decl);
4706 } else {
4707 print STDOUT "\n<$decl>" if $VERBOSITY > 2;
4708 push(@$open_tags_R, $decl);
4709 }
4710 return ( $pre . $_ );
4711 } else {
4712 if (defined $ldecl) {
4713 print STDOUT "\n<<$decl>" if $VERBOSITY > 2;
4714 unshift(@$open_tags_R, $decl);
4715 } else {
4716 print STDOUT "\n<$decl>" if $VERBOSITY > 2;
4717 push(@$open_tags_R, $decl);
4718 }
4719 }
4720 } elsif ($post =~/$all_close_rx/) {
4721 ($closures,$reopens) = &preserve_open_tags();
4722 ($pre,$post) = &minimize_open_tags($decl,1);
4723 $pre = join('', $closures, $pre);
4724 } elsif ($closing_tag) {
4725 $prev_open = $pre;
4726 ($pre,$post) = &minimize_open_tags($decl,1);
4727 $pre =~ s/<\/?>//g; $post =~ s/<\/?>//;
4728 } else {
4729 ($pre,$post) = &minimize_open_tags($decl);
4730 }
4731 $_ =~ s/^\s+//s; #RRM:28/4/99 remove spaces at the beginning
4732 $_ = &translate_environments($_);
4733 $_ = &translate_commands($_) if (/\\/);
4734 if ($post =~ /$block_close_rx/) {
4735 s/^\n?/\n/o;
4736 if (defined $ldecl) {
4737 $post = &close_all_tags();
4738 } else {
4739 $post = "\n";
4740 }
4741 } elsif ($post =~/$all_close_rx/) {
4742 } else { $post = '' };
4744 join('', $pre, $_, $post
4745 , ($closing_tag ? '' : &balance_tags()) );
4746 }
4748 sub do_cmd_centering{&declared_env('center',$_[0],$tex2html_deferred)}
4749 sub do_cmd_raggedright{&declared_env('flushleft',$_[0],$tex2html_deferred)}
4750 sub do_cmd_raggedleft{&declared_env('flushright',$_[0],$tex2html_deferred)}
4752 sub do_env_verse { &declared_env('verse',@_) }
4753 sub do_env_quote { &declared_env('quote', @_) }
4754 sub do_env_quotation { &declared_env('quote', @_) }
4755 sub do_env_tex2html_preform { &declared_env('preform', @_) }
4756 sub do_env_tex2html_ord { &declared_env('ord', @_) }
4757 sub do_env_tex2html_unord { &declared_env('unord', @_) }
4758 sub do_env_tex2html_desc { &declared_env('desc', @_) }
4761 # Modifies $contents
4762 sub process_command {
4763 # MRO: modified to use $_[1]
4764 # local ($cmd_rx, *ref_contents) = @_;
4765 local ($cmd_rx) = @_;
4766 local($ref_before, $cmd , $pc_after);
4767 local($cmd_sub, $cmd_msub, $cmd_trans, $mathentity);
4768 local (@open_font_tags,@open_size_tags);
4769 $_[1] = &convert_iso_latin_chars($_[1])
4770 unless (($cmd =~ /(Make)?([Uu]pp|[Ll]ow)ercase/)||
4771 ((!$cmd)&&($_[1] =~ /^\\(Make)?([Uu]pp|[Ll]ow)ercase/s)));
4773 local(@ref_processed);
4774 for (;;) { # Do NOT use the o option
4775 last unless ($_[1] =~ /$cmd_rx/ );
4776 print ".";
4777 #JCL(jcl-del) - use new regexp form which handles white space
4778 ($ref_before, $cmd, $pc_after) = ($`, $1.$2, $4.$');
4779 push(@ref_processed,$ref_before);
4780 #print "\nAFTER:$1.$2:".$4."\n" if ($cmd_rx eq $single_cmd_rx);
4781 print STDOUT "$cmd" if ($VERBOSITY > 2);
4782 print STDOUT "\nIN: $_[1]\n" if ($VERBOSITY > 6);
4783 #
4784 if ( $cmd = &normalize($cmd,$pc_after) ) {
4785 ($cmd_sub, $cmd_msub, $cmd_trans, $mathentity) =
4786 ("do_cmd_$cmd", "do_math_cmd_$cmd"
4787 , $declarations{$cmd}, $mathentities{$cmd});
4788 if ($new_command{$cmd}||$renew_command{$cmd}) {
4789 # e.g. some \the$counter
4790 local($argn, $body, $opt) = split(/:!:/, $new_command{$cmd});
4791 &make_unique($body) if ($body =~ /$O/);
4792 if ($argn) {
4793 do {
4794 local($before) = '';
4795 local($_) = "\\$cmd ".$pc_after;
4796 # &substitute_newcmd may need what comes after the $cmd
4797 # from the value of $after
4798 #RRM: maybe best to pass it as a parameter ?
4799 my $keep_after = $after;
4800 $after = $pc_after;
4801 $pc_after = &substitute_newcmd; # may change $after
4802 $pc_after =~ s/\\\@#\@\@/\\/o ;
4803 $pc_after .= $after;
4804 $after = $keep_after;
4805 }
4806 } else {
4807 $pc_after = $body . $pc_after;
4808 }
4809 } elsif (defined &$cmd_sub) {
4810 # $ref_before may also be modified ...
4811 if ($cmd =~ /$sizechange_rx/o) {
4812 $pc_after = &$cmd_sub($pc_after, $open_tags_R);
4813 } else {
4814 $pc_after = &$cmd_sub($pc_after, $open_tags_R);
4815 };
4816 } elsif ((defined &$cmd_msub)&&!$NO_SIMPLE_MATH) {
4817 #print "\nMCMD:$cmd_msub : ";
4818 # $ref_before may also be modified ...
4819 $pc_after = &$cmd_msub($pc_after, $open_tags_R);
4820 if ( !$math_mode ) {
4821 $pc_after = "<MATH>" . $pc_after . "</MATH>";
4822 ++$commands_outside_math{$cmd};
4823 };
4824 } elsif ($cmd_trans) { # One to one transform
4825 #print "\nCMD-DECL: $inside_tabular : $cmd_trans". join(',',@$open_tags_R);
4826 if ($inside_tabular) {
4827 push (@ref_processed , "\\$cmd ")
4828 } else {
4829 $cmd_trans =~ m|</.*$|;
4830 $pc_after = $` . $pc_after unless ($` =~ /^<>/);
4831 push(@$open_tags_R, $cmd)
4832 if ($cmd =~ /$fontchange_rx|$fontweight_rx|$sizechange_rx/o);
4833 }
4834 } elsif ($mathentity) {
4835 #print "\nM-ENT:$mathentity : ";
4836 if ( $math_mode ) {
4837 $pc_after = "&$mathentity#$cmd;" . $pc_after;
4838 } elsif ($NO_SIMPLE_MATH) {
4839 $pc_after = "&$mathentity#$cmd;" . $pc_after;
4840 # ++$commands_outside_math{$cmd};
4841 } else {
4842 $pc_after = "<MATH>&$mathentity#$cmd;</MATH>" . $pc_after;
4843 ++$commands_outside_math{$cmd};
4844 }
4845 } elsif ($ignore{$cmd}) { # Ignored command
4846 print "\nignoring \\$cmd" if $VERBOSITY > 5;
4847 $pc_after = join('', " ", $pc_after) if ($cmd eq " "); # catches `\ '
4848 $pc_after = join(''," ", $pc_after)
4849 if (($cmd eq ',')&&($pc_after =~ /^\-/s)&&($ref_before =~/\-$/s));
4850 } elsif ($cmd =~ /^the(.+)$/){
4851 $counter = $1;
4852 local($tmp)="do_cmd_$cmd";
4853 if (defined &$tmp) { # Counter
4854 $pc_after = &do_cmd_thecounter($pc_after);
4855 } else {
4856 if (defined $failed) {
4857 $failed = 1;
4858 # $ref_before .= "$cmd";
4859 push(@ref_processed,$cmd); # $ref_before .= "$cmd";
4860 } else { &declare_unknown_cmd($cmd) }
4861 # $ref_before .= "$cmd" if ($failed);
4862 }
4863 } elsif ($cmd eq "\n") { push(@ref_processed," "); # $ref_before .= " ";
4864 } else {
4865 # Do not add if reading an auxiliary file
4866 if (defined $failed) {
4867 $failed = 1;
4868 } else { &declare_unknown_cmd($cmd) }
4869 }
4870 } else {
4871 # &normalize should have already handled it adequately
4872 # '\ ' (space) gets thru to here. Perhaps some others too ?
4873 # print "\n ?? This should not happen: \\$cmd ??\n";
4874 }
4875 # $_[1] = join('', $ref_before, $pc_after);
4876 $_[1] = $pc_after;
4877 print STDOUT "\n-> $ref_before\n" if ($VERBOSITY > 6);
4878 }
4879 $_[1] = join('',@ref_processed).$_[1];
4880 }
4882 sub declare_unknown_cmd {
4883 local($this_cmd) = @_;
4884 local($tmp) = "wrap_cmd_$cmd";
4885 do { ++$unknown_commands{$cmd};
4886 print STDOUT "\n*** Unknown command[1]: \\$cmd *** \n"
4887 if ($VERBOSITY > 2);
4888 } unless ($AUX_FILE||(defined &$tmp)||($image_switch_rx=~/\b\Q$cmd\E\b/));
4889 }
4892 # This makes images from the code for math-entities,
4893 # when $NO_SIMPLE_MATH is set and the math extension is loaded.
4894 #
4895 sub replace_math_constructions {
4896 local($math_mode) = @_;
4897 &make_math_box_images($math_mode) if (/<BOX>/);
4898 &make_math_entity_images($math_mode) if (/\&\w+#\w+;/);
4899 }
4901 sub make_math_box_images {
4902 local($math_mode) = @_;
4903 local($pre,$this,$post,$tmp) = ('','','');
4904 local($slevel,$blevel) = 0;
4906 while (/<BOX>/) {
4907 $pre .= $`; $tmp = $`; $this = ''; $post = $';
4908 # compute the super/sub-scripting level for each entity
4909 $tmp =~ s/<(\/?)SU[BP]>/
4910 if ($1) { $slevel--} else { $slevel++};''/eog;
4912 $tmp = $post;
4913 if ($tmp =~ /<(\/?)BOX>/o ) {
4914 if ($1) { $this = $`; $post = $' }
4915 else { $failed = 1 } # nested box, too complicated !
4916 } else {
4917 &write_warnings("\nLost end of a <BOX> ?");
4918 $failed = 1;
4919 }
4920 last if ($failed);
4922 ($this,$_) = &process_box_in_latex(
4923 $math_mode, $slevel, $this, $post);
4924 $_ =~ s/^\s*//; # remove any leading spaces
4925 $pre .= $this ."\001";
4926 }
4927 return if ($failed);
4928 $_ = $pre . $_;
4929 }
4931 sub make_math_entity_images {
4932 local($math_mode) = @_;
4933 local($pre,$this,$post,$tmp) = ('','','');
4934 local($slevel) = 0;
4935 # compute the super/sub-scripting level for each entity
4936 while (/\&\w+#(\w+);/) {
4937 $pre .= $`; $tmp = $`; $this = $1; $post = $';
4938 $tmp =~ s/<(\/?)SU[BP]>/
4939 if ($1) { $slevel--} else { $slevel++};''/eog;
4940 ($this,$_) = &process_entity_in_latex(
4941 $math_mode, $slevel, $this, $post);
4942 $_ =~ s/^\s*//; # remove any leading spaces
4943 $pre .= $this ."\001";
4944 }
4945 $_ = $pre . $_;
4946 }
4949 #RRM: Revert a math-entity to create image using LaTeX, together with
4950 # any super/sub-scripts (possibly nested or with \limits ).
4951 # Must also get the correct \display/text/(script)script style.
4952 #
4953 sub process_entity_in_latex {
4954 local($mode,$level,$entity,$after) = @_;
4955 local($math_style,$supsub,$rest) = ('','','');
4956 $level++ if ($mode =~/box/); # for top/bottom of inline fractions, etc.
4958 if ($level) {
4959 $math_style = "\\". (($level > 1) ? "script" : "")."scriptstyle"
4960 } else {
4961 $math_style = "\\displaystyle" unless ($mode =~ /inline/);
4962 }
4963 while ($after =~ s/^\s*((\\limits|\&limits;)?\s*<SU(P|B)>)\s*/$supsub .= $1;''/eo) {
4964 local($slevel) = 1;
4965 local($aftersupb) = '';
4966 while ($slevel) {
4967 $after =~ s/(<(\/)SU(B|P)>)/($2)? $slevel-- : $slevel++;''/oe;
4968 $supsub .= $`.$&;
4969 $aftersupb = $';
4970 }
4971 $after = $aftersupb;
4972 }
4974 local($latex_code) = "\$$math_style\\$entity$supsub\$";
4976 $global{'max_id'}++;
4977 ( &process_undefined_environment('tex2html_wrap_inline'
4978 ,$global{'max_id'}, $latex_code ) , $after);
4979 }
4981 sub process_box_in_latex {
4982 local($mode,$level,$inside,$after) = @_;
4983 local($math_style,$which,$pre,$post,$tmp) = ('','',"\{","\}");
4985 if ($level) {
4986 $math_style = "\\". (($level > 1) ? "script" : "")."scriptstyle"
4987 } else {
4988 $math_style = "\\displaystyle" unless ($mode =~ /inline/);
4989 }
4991 if ($inside =~ /<((LEFT)|(RIGHT))>/ ) {
4992 $pre = "\\left"; $post = "\\right";
4993 if ($2) {
4994 $tmp = $`; $inside = $';
4995 $pre .= (($tmp) ? $tmp : ".") . "\{";
4996 if ( $inside =~ /<RIGHT>/ ) {
4997 $tmp = $';
4998 $inside = $`;
4999 $post = "\}". (($tmp) ? $tmp : ".");
5000 }
5001 } else {
5002 $pre .= ".\{"; $tmp = $'; $inside = $`;
5003 $post = "\}". (($tmp) ? $tmp : ".");
5004 }
5005 }
5006 if ( $inside =~ /<((OVER)|(ATOP)|(CHOOSE))>/ ) {
5007 $pre .= $`;
5008 $post = $' . $post ;
5009 if ($2) { $which = "over " }
5010 elsif ($3) { $which = "atop " }
5011 elsif ($4) { $which = "atopwithdelims\(\)" }
5012 }
5014 local($latex_code) = join('', "\$" , $math_style , " ", $pre
5015 , (($which)? "\\$which" : "") , $post , "\$" );
5017 if ($after =~ s/<SUP ALIGN=\"CENTER\">([^<]*)<\/SUP>/
5018 $tmp =$1;''/eo ) {
5019 $latex_code = join('', "\\stackrel" , $latex_code
5020 , "\{" , $tmp , "\}" );
5021 }
5023 $global{'max_id'}++;
5024 ( &process_undefined_environment('tex2html_wrap_inline'
5025 ,$global{'max_id'}, $latex_code ) , $after);
5026 }
5028 ####################### Processing Meta Commands ############################
5029 # This is a specialised version of process_command above.
5030 # The special commands (newcommand, newenvironment etc.)
5031 # must be processed before translating their arguments,
5032 # and before we cut up the document into sections
5033 # (there might be sectioning commands in the new definitions etc.).
5034 # \newtheorem commands are treated during normal processing by
5035 # generating code for the environments they define.
5037 sub substitute_meta_cmds {
5038 local ($next_def);
5039 local ($cmd, $arg, $argn, $opt, $body, $before, $xafter);
5040 local ($new_cmd_no_delim_rx, $new_cmd_rx, $new_env_rx, $new_cmd_or_env_rx);
5041 local ($new_end_env_rx);
5042 &tokenize($meta_cmd_rx); #JCL(jcl-del) - put delimiter after meta command
5043 print "\nProcessing macros ..." if (%new_command || %new_environment);
5044 # First complete any replacement left-over from the previous part.
5045 if ($UNFINISHED_ENV) {
5046 s/$UNFINISHED_ENV/$REPLACE_END_ENV/;
5047 $UNFINISHED_ENV = '';
5048 $REPLACE_END_ENV = '';
5049 }
5051 local(@processed);
5052 local($processed, $before, $after)=('', '', $_);
5053 while ($after =~ /$meta_cmd_rx$EOL/o) { # ... and uses the delimiter
5054 ($cmd, $after) = ($1.$2, $');
5055 $before .= $`;
5056 # $next_def = '';
5057 if (!($before =~ /$meta_cmd_rx$EOL/)) {
5058 push(@processed, $before); $before = '';
5059 }
5061 print ",";
5062 # $next_def = "\\$cmd" unless (($cmd =~ /renewcommand/));
5063 local($cmd_sub) = "get_body_$cmd";
5064 if (defined &$cmd_sub) {
5065 # $processed = &$cmd_sub(*after);
5066 $processed = &$cmd_sub(\$after);
5067 # if ($processed) { $after = $before . $processed; }
5068 # $next_def = ''
5069 # if (($PREAMBLE > 1)&&($cmd =~ /(re)?newcommand/));
5070 # &add_to_preamble($cmd, $next_def)
5071 # unless ($next_def =~ /^\s*$/);
5072 ### new style of handling meta-commands
5073 if ($processed) { push(@processed, "\\".$processed) }
5074 }
5075 elsif ($before) {
5076 # this shouldn't happen !!
5077 print STDERR "\nCannot handle \\$cmd , since there is no $cmd_sub ";
5078 $after = $before . $cmd . $after;
5079 $before = '';
5080 } else {
5081 push(@processed, "\\$cmd ") if $cmd;
5082 }
5083 }
5084 print "\nmeta-commands: ". (0+@processed) ." found "
5085 if ((@processed)&&($VERBOSITY > 1));
5086 $_ = join('',@processed, $after); undef @processed;
5087 if ($PREAMBLE) {
5088 # MRO: replaced $* with /m
5089 s/((\n$comment_mark\d*)+\n)//gm;
5090 s/(\\par\b\s*\n?)+/\\par\n/gm;
5091 s/(\\par\b\n?)+/\\par\n/gm;
5092 }
5094 # hard-code the new-command replacements for these
5095 $new_command{'begingroup'} = "0:!:\\begin<<0>>tex2html_begingroup<<0>>:!:}";
5096 $new_command{'endgroup'} = "0:!:\\end<<0>>tex2html_begingroup<<0>>:!:}";
5097 $new_command{'bgroup'} = "0:!:\\begin<<0>>tex2html_bgroup<<0>>:!:}";
5098 $new_command{'egroup'} = "0:!:\\end<<0>>tex2html_bgroup<<0>>:!:}";
5100 # All the definitions have now moved to the $preamble and their bodies
5101 # are stored in %new_command and %new_environment
5102 #
5103 # Now substitute the new commands and environments:
5104 # (must do them all together because of cross definitions)
5105 $new_cmd_rx = &make_new_cmd_rx(keys %new_command);
5106 $new_cmd_no_delim_rx = &make_new_cmd_no_delim_rx(keys %new_command);
5107 $new_env_rx = &make_new_env_rx;
5108 $new_end_env_rx = &make_new_end_env_rx;
5109 # $new_cnt_rx = &make_new_cnt_rx(keys %new_counter);
5110 $new_cmd_or_env_rx = join("|", $new_cmd_no_delim_rx." ", $new_env_rx);
5111 # $new_cmd_or_env_rx = join("|", $new_cmd_no_delim_rx." ", $new_env_rx, " ".$new_cnt_rx);
5112 $new_cmd_or_env_rx =~ s/^ \||\|$//;
5114 print STDOUT "\nnew commands:\n" if ($VERBOSITY > 2);
5115 while (($cmd, $body) = each %new_command) {
5116 unless ($expanded{"CMD$cmd"}++) {
5117 print STDOUT ".$cmd " if ($VERBOSITY > 2);
5118 $new_command{$cmd} = &expand_body;
5119 print STDOUT " ".$new_command{$cmd}."\n" if ($VERBOSITY > 4);
5120 &write_mydb("new_command", $cmd, $new_command{$cmd});
5121 }
5122 }
5124 print STDOUT "\nnew environments:\n" if ($VERBOSITY > 2);
5125 while (($cmd, $body) = each %new_environment) {
5126 unless ($expanded{"ENV$cmd"}++) {
5127 print STDOUT ".$cmd" if ($VERBOSITY > 2);
5128 $new_environment{$cmd} = &expand_body;
5129 &write_mydb("new_environment", $cmd, $new_environment{$cmd});
5130 }
5131 }
5133 print STDOUT "\nnew counters and dependencies:\n" if ($VERBOSITY > 2);
5134 &clear_mydb("dependent") if ($DEBUG); #avoids appending to a previous version
5135 while (($cmd, $body) = each %dependent) {
5136 print STDOUT ".($cmd,$body)" if ($VERBOSITY > 2);
5137 &write_mydb("dependent", $cmd, $dependent{$cmd});
5138 }
5139 &clear_mydb("img_style") if ($DEBUG); #avoids appending to a previous version
5140 while (($cmd, $body) = each %img_style) {
5141 &write_mydb("img_style", $cmd, $img_style{$cmd});
5142 }
5144 &clear_mydb("depends_on") if ($DEBUG); #avoids appending to a previous version
5145 while (($cmd, $body) = each %depends_on) {
5146 print STDOUT ".($cmd,$body)" if ($VERBOSITY > 2);
5147 &write_mydb("depends_on", $cmd, $depends_on{$cmd});
5148 }
5151 &clear_mydb("styleID") if ($DEBUG); #avoids appending to a previous version
5152 while (($cmd, $body) = each %styleID) {
5153 &write_mydb("styleID", $cmd, $styleID{$cmd});
5154 }
5156 &clear_mydb("env_style") if ($DEBUG); #avoids appending to a previous version
5157 while (($cmd, $body) = each %env_style) {
5158 &write_mydb("env_style", $cmd, $env_style{$cmd});
5159 }
5160 &clear_mydb("txt_style") if ($DEBUG); #avoids appending to a previous version
5161 while (($cmd, $body) = each %txt_style) {
5162 &write_mydb("txt_style", $cmd, $txt_style{$cmd});
5163 }
5165 print STDOUT "\ntheorem counters:\n" if ($VERBOSITY > 2);
5166 &clear_mydb("new_theorem") if ($DEBUG); #avoids appending to a previous version
5167 while (($cmd, $body) = each %new_theorem) {
5168 print STDOUT ".($cmd,$body)" if ($VERBOSITY > 2);
5169 &write_mydb("new_theorem", $cmd, $new_theorem{$cmd});
5170 }
5173 print "+";
5174 if (length($new_env_rx)) {
5175 local(@pieces);
5176 print STDOUT "\nsubstituting new environments: $new_env_rx\n" if ($VERBOSITY > 3);
5177 # while (/\n?$new_env_rx/ && (($before, $cmd, $after) = ($`, $2, $'))) {
5178 while (/$new_env_rx/ && (($before, $cmd, $after) = ($`, $2, $'))) {
5179 print STDOUT ",";
5180 print STDOUT "{$cmd}" if ($VERBOSITY > 1);
5181 if (!($before =~ /$new_env_rx/)) {
5182 push (@pieces, $before); $before = ''; print "{}";
5183 }
5184 $_ = join('',$before, &substitute_newenv);
5185 }
5186 print "\n ".(0+@pieces). " new environments replaced\n" if (@pieces);
5187 $_ = join('', @pieces, $_); undef @pieces;
5188 }
5191 print "+";
5192 if (length($new_cmd_rx)) {
5193 print STDOUT "\ntokenizing: $new_cmd_rx\n" if ($VERBOSITY > 2);
5194 &tokenize($new_cmd_rx); # Put delimiter after the new commands
5196 # and use the delimiter.
5197 print STDOUT "\nsubstituting new commands: $new_cmd_rx\n" if ($VERBOSITY > 2);
5198 print STDOUT "\ninitial size: ".length($after) if ($VERBOSITY > 1);
5199 # store processed pieces in an array
5200 local($this_cmd, @pieces);
5201 # speed-up processing of long files by splitting into smaller segments
5202 # but don't split within the preamble, else \newenvironment may break
5203 local($pre_segment,@segments); &make_sections_rx;
5204 local($within_preamble,$this_section) = 1 if ($PREAMBLE>1);
5205 while (/$sections_rx/) {
5206 $pre_segment .= $`; $_ = $'; $this_section = $&;
5207 do {
5208 push(@segments,$pre_segment);
5209 $pre_segment = '';
5210 } unless ($within_preamble);
5211 $within_preamble = 0 if ($within_preamble && ($pre_segment =~
5212 /\\(startdocument|begin\s*($O\d+${C})\s*document\s*\2)/));
5213 $pre_segment .= $this_section;
5214 }
5215 push(@segments,$pre_segment.$_);
5216 local($replacements,$seg) ; $before = ''; # count the segments
5217 local($within_preamble) = 1 if ($PREAMBLE>1);
5218 foreach $after (@segments) {
5219 while ($after =~ /(\\(expandafter|noexpand)\b\s*)?$new_cmd_no_delim_rx\b\s?/) {
5220 ($before, $xafter, $cmd, $after) = ($`, $2, $3, $');
5221 $within_preamble = 0
5222 if ($before =~ /\\(startdocument|begin\s*($O\d+${C})\s*document\s*\2)/);
5223 push(@pieces, $before);
5224 print "."; ++$replacements;
5225 print STDOUT "$cmd" if ($VERBOSITY > 2);
5226 if ($xafter =~ /no/) { $this_cmd = "\\\@#\@\@".$cmd }
5227 elsif (($xafter =~ /after/)&&($after =~ /^\s*\\/)) {
5228 local($delayed) = $cmd;
5229 local($nextcmd);
5230 $after =~ s/^\s*\\([a-zA-Z]+|.)/$nextcmd = $1;''/eo;
5231 ($cmd,$nextcmd) = ($nextcmd, "do_cmd_$nextcmd");
5232 if (defined &$nextcmd) { $after = &$nextcmd($after); }
5233 elsif ($new_command{$cmd}) {
5234 local($argn, $body, $opt) = split(/:!:/, $new_command{$cmd});
5235 &make_unique($body) if ($body =~ /$O/);
5236 if ($argn) {
5237 do {
5238 local($before) = '';
5239 $after = join('',&substitute_newcmd, $after);
5240 $after =~ s/\\\@#\@\@/\\/o ;
5241 };
5242 } else { $after = $body . $after; }
5243 } else { print "\nUNKNOWN COMMAND: $cmd "; }
5244 $cmd = $delayed;
5245 if ($new_command{$cmd}) {
5246 if ($renew_command{$cmd}) {
5247 # # must wrap it in a deferred environment
5248 # $this_cmd = join('', &make_deferred_wrapper(1)
5249 # ,"\\$cmd".(($cmd =~ /\w$/)? " ":'')
5250 # , &make_deferred_wrapper(0));
5251 # push(@pieces, $this_cmd); $this_cmd = '';
5252 push(@pieces, "\\$cmd".(($cmd =~ /\w$/)? " ":''));
5253 $this_cmd = '';
5254 } elsif ($provide_command{$cmd}&&$within_preamble) {
5255 # leave it alone
5256 push(@pieces, "\\$cmd".(($cmd =~ /\w$/)? " ":''));
5257 $this_cmd = '';
5258 } else {
5259 # do the substitution
5260 $this_cmd = &substitute_newcmd;
5261 }
5262 }
5263 } elsif ($renew_command{$cmd}) {
5264 # leave it alone
5265 push(@pieces, "\\$cmd".(($cmd =~ /\w$/)? " ":''));
5266 $this_cmd = '';
5267 } elsif (($provide_command{$cmd})&&($within_preamble)) {
5268 # leave it alone
5269 push(@pieces, "\\$cmd".(($cmd =~ /\w$/)? " ":''));
5270 $this_cmd = '';
5271 } else {
5272 # do the substitution
5273 $this_cmd = &substitute_newcmd if ($new_command{$cmd});
5274 }
5275 if ($this_cmd =~ /(\\(expandafter|noexpand)\s*)?$new_cmd_no_delim_rx\b\s?/)
5276 { $after = $this_cmd . $after }
5277 elsif ($this_cmd) { push(@pieces, $this_cmd) }
5278 }
5279 push(@pieces, $after);
5280 # after the first segment we should no longer be in the preamble
5281 $within_preamble = 0;
5282 }
5283 print " $replacements new-command replacements\n"
5284 if (($VERBOSITY>1) && $replacements);
5285 # recombine the processed pieces
5286 $_ = join('', @pieces); undef @pieces;
5287 print STDOUT ", resulting size: ".length($_)." " if ($VERBOSITY > 1);
5288 $_ =~ s/\\\@#\@\@/\\/go;
5289 }
5291 print STDOUT "\n *** substituting metacommands done ***\n" if ($VERBOSITY > 3);
5292 }
5294 sub insert_command_expansion {
5295 ($xafter, $cmd) = @_;
5296 # push(@pieces, $_[1]);
5297 print ".$cmd";
5298 print STDOUT "$_[3]" if ($VERBOSITY > 2);
5299 # $xafter = $_[2];
5300 # $cmd = $_[3];
5301 if ($xafter =~ /no/) { $this_cmd = "\\\@#\@\@".$cmd }
5302 elsif (($xafter =~ /after/)&&($after =~ /^\s*\\/)) {
5303 local($delayed,$nextcmd) = ($_[3],'');
5305 $after =~ s/^\s*\\([a-zA-Z]+|.)/$nextcmd = $1;''/eo;
5306 ($cmd,$nextcmd) = ($nextcmd, "do_cmd_$nextcmd");
5307 if (defined &$nextcmd) { $after = &$nextcmd($after); }
5308 elsif ($new_command{$cmd}) {
5309 local($argn, $body, $opt) = split(/:!:/, $new_command{$cmd});
5310 &make_unique($body) if ($body =~ /$O/);
5311 if ($argn) {
5312 do {
5313 local($before) = '';
5314 $after = join('',&substitute_newcmd, $after);
5315 $after =~ s/\\\@#\@\@/\\/o ;
5316 };
5317 } else { $after = $body . $after; }
5318 } else { print "\nUNKNOWN COMMAND: $cmd "; }
5319 $cmd = $delayed;
5320 $this_cmd = &substitute_newcmd if ($new_command{$cmd});
5321 } else {
5322 $this_cmd = &substitute_newcmd if ($new_command{$cmd});
5323 }
5324 # if ($this_cmd =~ /(\\(expandafter|noexpand)\s*)?$new_cmd_no_delim_rx\s?/){
5325 # $after = $this_cmd . $after
5326 # } else { push(@pieces, $this_cmd); }
5327 $this_cmd;
5328 }
5331 sub expand_body {
5332 return unless length($new_cmd_or_env_rx);
5333 local($_) = $body;
5334 local($cmd,$saveafter,$avoid_looping);
5335 # Uses $before, $body, $arg, etc. of the caller, but not $cmd.
5336 # Uses $new_cmd_rx (resp. $new_cmd_no_delim_rx) and $new_env_rx
5337 # set in the caller, of which one might be empty.
5339 # Puts delimiter after the new commands ...
5340 &tokenize($new_cmd_rx) if length($new_cmd_rx);
5342 while (/$new_cmd_or_env_rx/) {
5343 # $new_cmd_rx binds $1, and $new_env_rx binds $3.
5344 ($before,$cmd,$after,$saveafter) = ($`,$1.$3,$',$');
5345 if (length($new_command{$cmd})) { # We have a command
5346 # this tokenizes again
5347 local($replace) = &substitute_newcmd; # sets $_, changes $after
5348 if (!($replace)) {
5349 # protect name of unexpanded macro
5350 $_ = join('', $before ,"\\@#@@", $cmd, $saveafter );
5351 } else {
5352 $_ = join('', $before , $replace, $after );
5353 }
5354 } elsif (length($new_environment{$cmd})) {
5355 $_ = join('',$before, &substitute_newenv);
5356 }
5357 last if $avoid_looping;
5358 }
5359 # remove protection from unreplaced macro names
5360 s/\\\@#\@\@/\\/go;
5362 # remove trivial comments
5363 s/(\\\w+)$comment_mark\d*\n[ \t]*/$1 /go;
5364 s/$comment_mark\d*\n[ \t]*//go;
5365 # s/($O\d+$C)?($comment_mark\n)[ \t]*/($1 ? $1.$2 : '')/eg;
5367 $_;
5368 }
5371 sub substitute_newcmd {
5372 # Modifies $after in the caller
5373 # Get the body from the new_command array
5374 local($tmp,$cnt,$saved, $arg, $isword) = ('',0,$cmd);
5375 local($argn, $_, $opt) = split(/:!:/, $new_command{$cmd});
5376 $avoid_looping = 1 if ($new_command{$cmd} =~ /\\$cmd\b/);
5378 &tokenize($new_cmd_rx); # must do it again for newly inserted cmd bodies
5379 print STDOUT "\nNEW:$cmd:$_" if ($VERBOSITY > 5);
5380 foreach $i (1..$argn) {
5381 $arg = $isword = '';
5382 if ($i == 1 && $opt ne '}') {
5383 $arg = ($after =~ s/$optional_arg_rx//o) ? $1 : $opt;
5384 }
5385 else {
5386 # Get the next argument, if not in braces, get next character
5387 #RRM: allow also for processed braces, in case substitution
5388 # was delayed; e.g. by \renewcommand
5389 if (!(($after =~ s/$next_pair_rx/$arg = $2;''/e)
5390 ||($after =~ s/$next_pair_pr_rx/$arg = $2;''/e))) {
5391 $after =~ s/^\s*(\\[a-zA-Z]+|.)/$arg = $1;''/e;
5392 }
5393 if ($arg eq '#') {
5394 &write_warnings("\nSubstitution of arg to $cmd delayed.");
5395 $_ = "\\\@#\@\@$saved";
5396 return ();
5397 };
5398 }
5399 $arg =~ s/(^|\G|[^\\])\\\#/$1$hash_mark/gs;
5400 $arg =~ s/\#/$param_mark/gs;
5402 #RRM: Substitute the arguments in the body one at a time
5403 # else multiple instances would fail in &make_unique
5405 # First protect ## parameters in TeX-like substitutions
5406 # suggested by Dirk Pleiter (Berlin)
5407 s/((^|[^\\])(\\\\)*)\#\#$i/$1$protected_hash/gs;
5408 $tmp = $_;
5409 $cnt = $tmp =~ s/\#$i//g ;
5410 $isword = 1 if ($arg =~ /^\w/);
5411 if ($cnt > 1 ) {
5412 $tmp = $_;
5413 while ($cnt > 1) {
5414 if ( s/(\\\w+)?\#$i/(($1&&$isword)? $1.' ': '').$arg/e) {
5415 &make_unique($_) if ($arg =~ /$O/ );
5416 &make_unique_p($_) if ($arg =~ /$OP/ );
5417 }
5418 $cnt--;
5419 }
5420 $tmp = $_;
5421 }
5422 # s/(\\\w+)?\#$i/(($1&&$isword)? $1.' ': '').$arg/e ;
5423 s/(\\\w+)?\#$i/$1.(($1&&$isword)? ' ': '').$arg/e ;
5424 print "\n *** substitution: $arg \nfor \#$i in \\$cmd did not take ***\n"
5425 if (/\#$i/);
5426 &write_warnings("incomplete substitution in a \\$cmd command:\n$_") if (/\#$i/);
5427 s/$protected_hash/\#$i/g;
5428 }
5429 s/$param_mark/\#/g;
5430 s/$hash_mark/\\\#/g;
5431 s/(\\\w+)$/$1 /s;
5433 # Make the body unique (give unique id's to the brackets),
5434 # translate, and return it
5435 &make_unique($_);
5436 if ($avoid_looping) {
5437 s/\\$cmd\b/\\csname $cmd\\endcsname/g;
5438 print STDERR "\n *** possible looping with new-command \\$cmd ***\n";
5439 &write_warnings("\npossible looping with new-command \\$cmd ");
5440 }
5441 print STDOUT "\nOUT:$cmd:$_" if ($VERBOSITY > 5);
5443 # Insert a space to prevent letters from clashing together with a
5444 # letter command. Consider this:
5445 # New command substitution is restricted to commands introduced by
5446 # \newcommand etc. (so-called meta commands), but it is not done
5447 # for already defined commands, eg. \large.
5448 # But new command, as well as new environment, substitution is done
5449 # prior to any other substitution.
5450 # So \newcommand{\this}{...} {\large\this b} will get expanded the
5451 # following way:
5452 # 1. \newcommand{\this}{...}
5453 # is handled by &substitute_meta_cmds, it gets the definition
5454 # of \this and stores it within a table, %new_command.
5455 # After all new commands are recognized, &expand_body is called
5456 # to expand one command body from each other. That's O(n*n)!
5457 # 2. A regular expression $new_cmd_rx is built containing a pattern
5458 # that matches all occurrences of a properly delimited \this
5459 # macro. When matching, ensuing white space gets lost.
5460 # (But only for letter commands, see also &make_new_cmd_rx.)
5461 # Another regular expression called $new_cmd_no_delim_rx is built
5462 # which matches exact the \this, and would also match the prefix
5463 # of \thisx.
5464 # 3. The *whole* text is tokenized using $new_cmd_rx, with separates
5465 # \this from the ensuing text by one white space.
5466 # 4. Then $new_cmd_no_delim_rx together with the delimiting space
5467 # is used to substitute \this with its body.
5468 # 5. The following situations may occur:
5469 # a) ... is some text (no macros) => {\large<text>yyy}
5470 # Then we must prevent that the text clashes into \large.
5471 # This is only dangerous when <text> begins with a letter.
5472 # b) ... contains another, not expanded new command.
5473 # This happens during &expand_body.
5474 # In this case, make sure to &tokenize the body before giving
5475 # the result to the caller. Also take care that leading letters
5476 # of the body cannot clash into \large.
5477 # e) ... contains a macro not known as new command:
5478 # Make sure that the macro cannot clash with the ensuing yyy.
5479 # f) ... is empty:
5480 # Make sure that \large cannot clash with yyy.
5481 # 6. We prevent clashing by inserting a delimiting blank.
5482 # Out of the scetched situation, there are three conditions to
5483 # take care of:
5484 # a) empty body, left a letter command, right a letter => blank
5485 # b) body starts with letter, left a letter command => blank
5486 # c) body ends with letter command, right a letter => blank
5487 # d) else => no blank, clash all together, it will work.
5488 # 7. With this rules, the expansion should work quite well,
5489 # concerning letter/non-letter commands and white space
5490 # handling.
5491 # 8. Deficiencies:
5492 # 8.1 Consider \this<CR>that. It's handled this way:
5493 # a) The \this swallows the <CR> in LaTeX, but what LaTeX2HTML does
5494 # is to &tokenize the expression into \this <CR>that.
5495 # b) If ... is some text, it results in <text><CR>that.
5496 # c) If ... is a macro (or command, or control sequence, these
5497 # terms are often mixed up, but effectively mean the same),
5498 # then if the macro later takes at least one argument, the <CR>
5499 # might get swallowed, this depends on the grace of $next_pair_rx
5500 # resp. $next_pair_pr_rx.
5501 # If the macro takes no arguments, the <CR> remains in the text.
5502 # d) If ... ends in another new command, the problem repeats.
5503 # 8.2 The new commands are substituted in a very insensitive way.
5504 # If \this occurs within an environment which sees \this
5505 # totally different, there's no chance to substitute \this in
5506 # a different way.
5507 # 8.3 In relation to 8.2 a similar problem arises when the meta
5508 # command, or several meta commands redefining \this, occur
5509 # amongst several \this macros.
5510 # 8.4 In raw TeX like environments it is not possible to revert the
5511 # expansion of \this, but \this probably *must* occur in its
5512 # raw form.
5514 # Handle the cases as depicted in the description of new command
5515 # substitution.
5516 local($befdel,$aftdel);
5517 $befdel = ' '
5518 if ($before=~/(^|[^\\])\\[a-zA-Z]+$/ && /^$/ && $after=~/^[a-zA-Z]/) ||
5519 ($before=~/(^|[^\\])\\[a-zA-Z]+$/ && /^[a-zA-Z]/);
5520 $aftdel = ' '
5521 if /(^|[^\\])\\[a-zA-Z]+$/s && $after=~/^[a-zA-Z]/;
5522 join('', $befdel, $_, $aftdel);
5523 }
5525 #RRM: use this to test whether a specific command is substituting correctly
5526 sub trace_cmd {
5527 local($this) = @_;
5528 if ($cmd eq $this) { print "\n$1=>$id:$2::"}
5529 }
5531 # Make the text unique (give unique id's to the brackets).
5532 # The text shouldn't contain processed brackets.
5533 sub make_unique {
5534 # MRO: Change to references $_[0]
5535 # local(*_) = @_;
5536 my $id = $global{'max_id'};
5537 # MRO: replaced $* by /m
5538 # this looks quite funny but is optimized
5539 1 while($_[0] =~ s/$O(\d+)$C([\w\W]*)$O\1$C/$id++;"\000$id $2\000$id "/geom);
5540 $_[0] =~ s/\000(\d+) /$O$1$C/gom;
5541 $global{'max_id'} = $id;
5542 }
5544 #RRM: this shouldn't be needed, but just in case...
5545 sub make_unique_p {
5546 # MRO: Change to references $_[0]
5547 my $id = $global{'max_id'};
5548 # MRO: replaced $* by /m
5549 # this looks quite funny but is optimized
5550 1 while($_[0] =~ s/$OP(\d+)$CP([\w\W]*)$OP\1$CP/$id++;"\000$id $2\000$id "/geom);
5551 $_[0] =~ s/\000(\d+) /$OP$1$CP/gom;
5552 $global{'max_id'} = $id;
5553 }
5556 sub substitute_newenv {
5557 # Modifies $cmd and $after in the caller
5558 # Get the body from the new_environment array
5559 local($argn, $begdef, $enddef, $opt) = split(/:!:/, $new_environment{$cmd});
5560 local($arg,$new_def_rx,$tmp,$cnt);
5562 # Note that latex allows argument substitution only in the
5563 # \begin part of the new definition
5564 foreach $i (1..$argn) { # Process the arguments
5565 if (($i == 1) && ($opt ne '}')) {
5566 $after =~ s/$optional_arg_rx/$arg = $1;''/eo;
5567 $arg = $opt unless $arg;
5568 }
5569 else {
5570 $after =~ s/$next_pair_rx/$arg = $2;''/eo;
5571 }
5572 $arg =~ s/(^|[^\\])\\\#/$1$hash_mark/g;
5573 $arg =~ s/\#/$param_mark/g;
5575 #RRM: multiple instances can fail later in &make_unique
5576 # s/\#$i/$arg/g; # Substitute the arguments in the body
5577 #RRM: ...so do one at a time and &make_unique_p
5578 $tmp = $begdef;
5579 $cnt = $tmp =~ s/\#$i//g ;
5580 if ($cnt > 1) {
5581 $tmp = $begdef;
5582 while ($cnt > 1) {
5583 if ( $begdef =~ s/\#$i/$arg/) {
5584 &make_unique($begdef) if ($arg =~ /$O/ );
5585 &make_unique_p($begdef) if ($arg =~ /$OP/ );
5586 }
5587 $cnt--;
5588 }
5589 $tmp = $_;
5590 }
5591 $begdef =~ s/\#$i/$arg/ ;
5592 print "\n *** substitution: $arg \nfor \#$i in {$cmd} did not take ***\n"
5593 if ($begdef =~ /\#$i/);
5594 &write_warnings("incomplete substitution in a {$cmd} environment:\n$begdef")
5595 if ($begdef =~ /\#$i/);
5596 }
5597 $begdef =~ s/$param_mark/\#/g;
5598 $begdef =~ s/$hash_mark/\\\#/g;
5599 $begdef =~ s/(\\\w+)$/$1 /s;
5601 # Make the body unique (Give unique id's to the brackets),
5602 # translate, and return it
5603 #RRM: when are these needed ?
5604 # $_ = &revert_to_raw_tex($_);
5605 # &pre_process;
5607 &make_unique($begdef); # Make bracket IDs unique
5608 print STDOUT "\nBEGIN:$cmd:$begdef" if ($VERBOSITY > 4);
5610 # Now substitute the \end part:
5611 #RRM: when are these needed ?
5612 # $_ = &revert_to_raw_tex($enddef);
5613 # &pre_process;
5615 &make_unique($enddef); # Make bracket IDs unique
5616 print STDOUT "\nEND:$cmd:$enddef" if (($enddef)&&($VERBOSITY > 4));
5617 $enddef =~ s/(\\\w+)$/$1 /s;
5619 local($new_end_def_rx) = &make_end_env_rx($cmd);
5620 if (($enddef)&&!($after =~ s/\n?$new_end_def_rx/$enddef/ )) {
5621 $UNFINISHED_ENV = $new_end_def_rx;
5622 $REPLACE_END_ENV = $enddef;
5623 };
5624 join('',$begdef,$after);
5625 }
5627 sub substitute_pars {
5628 s/((\%|$comment_mark\d*)|.)(\r*\n[ \t]*){2,}[ \t]*/$1\n\\par \n/og;
5629 # s/((\%|$comment_mark\d*)|\d|.)[\r\n\015]{2,}/print "\nPAR:".$`.$&;"$1\n\\par \n"/egs;
5630 }
5632 sub do_cmd_end { #RRM: catches the end of any unclosed environments
5633 local($_) = @_;
5634 &missing_braces unless (
5635 (s/$next_pair_pr_rx//o)||(s/$next_pair_rx//o));
5636 s/^\n//;
5637 $_;
5638 }
5640 # Removes the definition from the input string,
5641 # adds to the preamble unless it is part of the preamble already
5642 # and stores the body in %new_command;
5643 sub get_body_newcommand {
5644 local($newed, $n_after) = &process_body_newcommand(0,@_);
5645 (($PREAMBLE)? "newed".$newed : '');
5646 }
5648 sub process_body_newcommand {
5649 # local($renewed,*_) = @_;
5650 local($renewed,$after_R) = @_;
5651 local($_) = $$after_R;
5652 local($no_change) = $_;
5653 local($argn,$newcmd,$cmd_br,$body,$body_br,$tmp,$tmp1,$opt,$pat);
5654 local($new_cmd) = 'command';
5655 if ($renewed =~ /provide/||$renewed == 2) {
5656 # $newcmd = &missing_braces unless (
5657 ($newcmd,$pat) = &get_next(1) unless (
5658 (s/$next_pair_pr_rx/$pat=$&;$newcmd=$2;''/e)
5659 ||(s/$next_pair_rx/$pat=$&;$newcmd=$2;''/e));
5660 if (!$pat) {
5661 local($br_id) = ++$global{'max_id'};
5662 $pat = "$O$br_id$C".$newcmd."$O$br_id$C";
5663 }
5664 } else {
5665 ($newcmd,$pat) = &get_next(1); # Get command name
5666 }
5667 $pat =~ s/\\//; $new_cmd .= $pat;
5668 $newcmd =~ s/^\s*\\//;
5669 ($argn,$pat) = &get_next(0); # Get optional no. of args
5670 $argn = 0 unless $argn; $new_cmd .= $pat if $argn;
5671 local($cmd) = $newcmd;
5673 # Get the body of the code and store it with the name and number of args
5674 # UNLESS THE COMMAND IS ALREADY DEFINED
5675 # ...in which case $ALLOW_REDEFINE must also have been set. # RRM
5676 # (This is the mechanism with which raw html can be ignored in a Latex document
5677 # but be recognised as such by the translator).
5678 $opt = '}'; # Flag for no optional arg
5679 local($bodyA) = '';
5680 if (/^\[/) {
5681 ($opt,$pat) = &get_next(0);
5682 $new_cmd .= $pat;
5683 $bodyA .= "\n".'($dummy, $pat) = &get_next_optional_argument;' .
5684 "\n". '$args .= $pat;';
5685 }
5686 local($nargs) = $argn;
5687 while ($nargs > 0) { $nargs--;
5688 $bodyA .=
5689 "\n".'$args .= $`.$& if ((s/$next_pair_pr_rx//o)||(s/$next_pair_rx//o));';
5690 }
5691 if ($renewed =~ /provide/||$renewed == 2 ) {
5692 $body = &missing_braces unless (
5693 (s/$next_pair_pr_rx/$pat=$&;$body=$2;''/e)
5694 ||(s/$next_pair_rx/$pat=$&;$body=$2;''/e));
5695 $new_cmd .= $pat;
5696 } else {
5697 ($body,$pat) = &get_next(4); #get the body
5698 $new_cmd .= $pat;
5699 }
5701 local($thisone);
5702 # $thisone = 1 if ($cmd =~ /div|vec/); # for debugging
5704 $tmp = "do_cmd_$cmd";
5705 local($wtmp) = "wrap_cmd_$cmd";
5706 if ((defined &$tmp)||(defined &$wtmp)){
5707 # command already exists, so \providecommand does nothing
5708 # but may still be needed in images.tex
5709 $$after_R = $_;
5710 return ($new_cmd) if ($renewed =~ /provide/);
5712 print "\n*** redefining \\$cmd ***\n";
5713 &write_warnings("\nredefining command \\$cmd ");
5714 if (!$ALLOW_REDEFINE) {
5715 print "*** overriding previous meaning ***\n";
5716 &write_warnings("\nprevious meaning of \\$cmd will be lost");
5717 }
5718 # local($code) = "undef \&$tmp"; eval ($code);
5719 # if ($@) {print "\n*** undef \&$cmd failed \n"}
5720 if ((!$PREAMBLE)||($renewed>1)) {
5721 $new_command{$cmd} = join(':!:',$argn,$body,$opt);
5722 # local($code) = "sub $tmp\{\&replace_new_command(\"$cmd\");\}";
5723 # eval $code;
5724 # print STDERR "\n*** sub do_cmd_$cmd failed:\nPERL: $@\n" if ($@);
5725 # &replace_new_command($cmd);
5726 }
5728 $renew_command{$cmd} = 1;
5729 &write_mydb("renew_command", $cmd, $renew_command{$cmd});
5730 local($padding) = " ";
5731 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
5732 # Generate a new subroutine
5733 local($codeA) = "sub wrap_cmd_$cmd {" . "\n"
5734 .'local($cmd, $_) = @_; local ($args, $dummy, $pat) = "";'
5735 . $bodyA
5736 . (($thisone)? "\nprint \"\\nwrap $cmd:\".\$args.\"\\n\";" : '')
5737 . "\n".'(&make_deferred_wrapper(1).$cmd.'
5738 . "\"$padding\"".'.$args.&make_deferred_wrapper(0),$_)}'
5739 . "\n";
5740 print "\nWRAP_CMD: $codeA " if ($thisone); # for debugging
5741 eval $codeA;
5742 print STDERR "\n\n*** sub wrap_cmd_$cmd failed: $@\n" if ($@);
5743 $raw_arg_cmds{$cmd} = 1;
5745 } elsif (($ALLOW_REDEFINE)&&($PREAMBLE < 2)) {
5746 print "\n*** redefining \\$cmd ***\n";
5747 &write_warnings("\ncommand \\$cmd had no previous definition")
5748 if (!($new_command{$cmd}));
5749 }
5750 if ($renewed && ($PREAMBLE > 1) &&($new_command{$cmd})) {
5751 $raw_arg_cmds{$cmd} = 1 ;
5752 $renew_command{$cmd} = 1;
5753 local($padding) = " ";
5754 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
5755 # Generate a new subroutine
5756 local($codeA) = "sub wrap_cmd_$cmd {" . "\n"
5757 .'local($cmd, $_) = @_; local ($args, $dummy, $pat) = "";'
5758 . $bodyA
5759 . (($thisone)? "\nprint \"\\nwrap $cmd:\".\$args.\"\\n\";" : '')
5760 . "\n".'(&make_deferred_wrapper(1).$cmd.'
5761 . "\"$padding\"".'.$args.&make_deferred_wrapper(0),$_)}'
5762 . "\n";
5763 print "\nWRAP_CMD: $codeA " if ($thisone); # for debugging
5764 eval $codeA;
5765 print STDERR "\n\n*** sub wrap_cmd_$cmd failed: $@\n" if ($@);
5767 &write_mydb("renew_command", $cmd, $renew_command{$cmd});
5768 } elsif ($renewed) {
5769 $new_command{$cmd} = join(':!:',$argn,$body,$opt);
5770 } else {
5771 $new_command{$cmd} = join(':!:',$argn,$body,$opt)
5772 unless (($PREAMBLE > 1)&&($renew_command{$cmd}));
5773 }
5775 local($this_cmd);
5776 $this_cmd = join(''
5777 , "command{\\$cmd}"
5778 , ($argn ? "[$argn]" :'')
5779 , (($opt =~ /^}$/) ? '' : "[$opt]" )
5780 , "{", $body , "}" );
5781 $this_cmd = &revert_to_raw_tex($this_cmd);
5782 if ($renewed) {
5783 if ($renewed=~/provide/){
5784 $provide_command{$cmd} = 1;
5785 &write_mydb("provide_command", $cmd, $provide_command{$cmd});
5786 # } else {
5787 # print "\n ** marking $cmd as renewed **";
5788 # $renew_command{$cmd} = 1;
5789 };
5790 if ((!$PREAMBLE)&&($renewed>1)) {
5791 # local($this_cmd) = join(''
5792 # , "\n\\renewcommand{\\$cmd}"
5793 # , ($argn ? "[$argn]" :'')
5794 # , (($opt =~ /^}$/) ? '' : "[$opt]" )
5795 # , "{", $body , "}\n" );
5796 # $latex_body .= &revert_to_raw_tex($this_cmd);
5797 $latex_body .= "\n\\renew". $this_cmd."\n";
5798 } else {
5799 ## &add_to_preamble('command',"\\" . $this_cmd);
5800 }
5801 } else {
5802 &add_to_preamble('command',"\\new" . $this_cmd)
5803 unless ($PREAMBLE);
5804 }
5805 undef $body;
5806 if ($renewed == 2) {
5807 # there is no output to return
5808 $$after_R = $_;
5809 return();
5810 }
5812 if (!$PREAMBLE) {
5813 $$after_R = $_;
5814 return ($new_cmd) if ($renewed);
5815 # $cmd_br =~ s/\\//;
5816 # ( join ('', &make_deferred_wrapper(1)
5817 # , "\\". ($renewed ? (($renewed =~ /provide/)? 'provid' : 'renew')
5818 # : 'new')."edcommand"
5819 # , $cmd_br , ($argn ? "[$argn]" :'')
5820 # , ( ($opt =~ /^\}$/ ) ? '' : "[$opt]" ) , $body_br
5821 # , &make_deferred_wrapper(0)) , $_ );
5822 $new_cmd = join('', "command{\\$cmd}"
5823 , ($argn ? "[$argn]" :'')
5824 , (($opt =~ /^\}$/) ? '' : "[$opt]" )
5825 , "{", $body , "}" );
5826 $new_cmd = &revert_to_raw_tex($new_cmd);
5827 &add_to_preamble('command', "\\provide".$new_cmd );
5828 $$after_R = $_;
5829 return();
5830 }
5831 $new_cmd =~ s/\\$cmd([\d\W]|$)/$cmd$1/s;
5832 $$after_R = $_;
5833 $new_cmd;
5834 }
5836 sub replace_new_command {
5837 local($cmd) = @_;
5838 local($argn, $body, $opt) = split(/:!:/, $new_command{$cmd});
5839 do { ### local($_) = $body;
5840 &make_unique($body);
5841 } if ($body =~ /$O/);
5842 $body =~ s/(^|[^\\])\~/$1\\nobreakspace /g;
5843 if ($argn) {
5844 do {
5845 local($before) = '';
5846 local($after) = "\\$cmd ".$_;
5847 $after = &substitute_newcmd; # may change $after
5848 $after =~ s/\\\@#\@\@/\\/o ;
5849 };
5850 } elsif ($body =~ /\\/) {
5851 $body = &translate_commands($body); # ???
5852 $_ = $body . $_;
5853 } else { $_ = $body . $_; }
5854 $_;
5855 }
5857 sub get_body_let {
5858 # local(*_) = @_;
5859 local($_) = @_;
5860 local($cmd,$body,$replace,$tmp,$pat);
5861 ($cmd,$body) = &get_next_tex_cmd;
5862 s/^\s*=?\s*/$body .= $&;''/e;
5863 ($replace,$pat) = &get_next_tex_cmd;
5864 # return() if ($replace eq $cmd);
5865 $body .= $pat;
5866 $body = &revert_to_raw_tex($body);
5867 &add_to_preamble('', "\\let ".$body );
5868 $_[0] = $_;
5869 if (($replace eq $cmd)||($cmd="\\")||($cmd =~/(style|size)$/)) {
5870 "let ".$body
5871 } else {
5872 $new_command{$cmd} = join(':!:','',"\\$replace ",'}');
5873 '';
5874 }
5875 }
5878 # do not remove the \renewcommand code, since it may be needed
5879 # within images. Instead replace it with \renewedcommand;
5880 # This will be reverted in &revert_to_raw_tex
5881 sub get_body_renewcommand {
5882 local($ALLOW_REDEFINE) = 1;
5883 local($renew, $n_after) = &process_body_newcommand(1,@_);
5884 ($renew ? 'renewed' . $renew : '');
5885 }
5887 sub do_cmd_renewedcommand {
5888 local($_) = @_;
5889 local($ALLOW_REDEFINE) = 1;
5890 &process_body_newcommand(2,\$_);
5891 $_ ;
5892 }
5894 sub get_body_providecommand {
5895 local($provide, $n_after) = &process_body_newcommand('provide',@_);
5896 (($PREAMBLE && $provide) ? 'provided'.$provide : '');
5897 }
5899 sub do_cmd_providedcommand{ &do_cmd_renewedcommand(@_) }
5901 sub get_body_DeclareRobustCommand {
5902 local($provide, $n_after) = &process_body_newcommand('provide',@_);
5903 (($PREAMBLE && $provide) ? 'provided'.$provide : '');
5904 }
5906 sub get_body_DeclareMathOperator {
5907 local($after_R) = @_;
5908 local($_) = $$after_R;
5909 my $star;
5910 s/^\\DeclareMathOperator\s*(\*|star)/$star = $1;''/s;
5911 my ($mcmd,$patA) = &get_next(1);
5912 my ($mop,$patB) = &get_next(1);
5913 if ($star) {
5914 $patA .= "${O}0$C\\mathop${O}1$C\\mathrm${patB}${O}1$C${O}0$C".$_;
5915 } else {
5916 $patA .= "${O}0$C${O}1$C\\mathrm${patB}${O}1$C${O}0$C".$_;
5917 }
5918 local($provide, $n_after) = &process_body_newcommand('provide',\$patA);
5919 $$after_R = $patA;
5920 (($PREAMBLE && $provide) ? 'provided'.$provide : '');
5921 }
5923 sub get_body_DeclareMathOperatorstar {
5924 local($after_R) = @_;
5925 local($_) = $$after_R;
5926 my $star;
5927 s/^\\DeclareMathOperator\s*(\*|star)/$star = $1;''/s;
5928 my ($mcmd,$patA) = &get_next(1);
5929 my ($mop,$patB) = &get_next(1);
5930 $patA .= "${O}0$C\\mathop${O}1$C\\mathrm${patB}${O}1$C${O}0$C".$_;
5931 local($provide, $n_after) = &process_body_newcommand('provide',\$patA);
5932 $$after_R = $patA;
5933 (($PREAMBLE && $provide) ? 'provided'.$provide : '');
5934 }
5937 # Removes the definition from the input string, adds to the preamble
5938 # and stores the body in %new_environment;
5939 sub get_body_newenvironment {
5940 local($newed,$after) = &process_body_newenvironment(0,@_);
5941 ( $PREAMBLE ? "newed".$newed : '');
5942 }
5944 sub process_body_newenvironment {
5945 # local($renew,*_) = @_;
5946 local($renew,$after_R) = @_;
5947 local($_) = $$after_R;
5948 local($no_change) = $_;
5949 local($argn,$env,$begin,$end,$tmp,$opt,$pat);
5950 local($new_env) = 'environment';
5951 if ($renew == 2) {
5952 $env = &missing_braces unless (
5953 (s/$next_pair_pr_rx/$pat=$&;$env=$2;''/e)
5954 ||(s/$next_pair_rx/$pat=$&;$env=$2;''/e));
5955 $new_env .= $pat;
5956 } else {
5957 ($env,$pat) = &get_next(1); # Get the environment name
5958 $env =~ s/^\s*\\//; $new_env .= $pat;
5959 }
5960 ($argn,$pat) = &get_next(0); # Get optional no. of args
5961 $argn = 0 unless $argn; $new_env .= $pat if $argn;
5963 # Get the body of the code and store it with the name and number of args
5964 # UNLESS THE COMMAND IS ALREADY DEFINED (see get_body_newcommand)
5965 # ...in which case $ALLOW_REDEFINE must also have been set. # RRM
5966 $opt = '}'; # Flag for no optional arg
5967 if (/^\[/) {
5968 ($opt,$pat) = &get_next(0);
5969 $new_env .= $pat;
5970 }
5971 $tmp = "do_env_$env";
5973 if ($renewed == 2 ) {
5974 $begin = &missing_braces unless (
5975 (s/$next_pair_pr_rx/$pat=$&;$begin=$2;''/e)
5976 ||(s/$next_pair_rx/$pat=$&;$begin=$2;''/e));
5977 $new_env .= $pat;
5978 $end = &missing_braces unless (
5979 (s/$next_pair_pr_rx/$pat=$&;$end=$2;''/e)
5980 ||(s/$next_pair_rx/$pat=$&;$end=$2;''/e));
5981 $new_env .= $pat;
5982 } else {
5983 ($begin,$pat) = &get_next(1); $new_env .= $pat;
5984 ($end,$pat) = &get_next(1); $new_env .= $pat;
5985 }
5986 if ((defined &$tmp)&&($ALLOW_REDEFINE)) {
5987 print STDOUT "\n*** redefining environment {$env} ***\n";
5988 &write_warnings("\nredefined environment {$env} ");
5989 }
5990 $new_environment{$env} = join(':!:', $argn, $begin, $end, $opt)
5991 unless ((defined &$tmp)&&(! $ALLOW_REDEFINE));
5993 if (!$PREAMBLE) {
5994 $new_env = join ('',
5995 , "environment{$env}"
5996 , ($argn ? "[$argn]" : '')
5997 , (($opt ne '}')? "[$opt]" : '')
5998 , "{$begin}{$end}"
5999 );
6000 &revert_to_raw_tex($new_env);
6001 if ($renew == 2) {
6002 $latex_body .= "\n\\".($renew ? 're':'').'new'.$new_env."\n";
6003 } else {
6004 &add_to_preamble ('environment'
6005 , "\\".($renew ? 're':'').'new'.$new_env );
6006 }
6007 $$after_R = $_;
6008 return();
6009 }
6010 if ($new_env =~ /$sections_rx/) {
6011 $new_env = join('', $`,'\csname ',$2,'\endcsname',$3,$');
6012 }
6013 $new_env =~ s/$par_rx/\\par /g;
6014 $$after_R = $_;
6015 $new_env;
6016 }
6018 sub get_body_renewenvironment {
6019 local($ALLOW_REDEFINE) = 1;
6020 local($renewed, $after) = &process_body_newenvironment(1,@_);
6021 'renewed'.$renewed;
6022 }
6024 sub do_cmd_renewedenvironment {
6025 local($ALLOW_REDEFINE) = 1;
6026 local($_) = @_;
6027 &process_body_newenvironment(2,\$_);
6028 $_;
6029 }
6031 # Instead of substituting as with newcommand and newenvironment,
6032 # or generating code to handle each new theorem environment,
6033 # it now does nothing. This forces theorem environments to be passed
6034 # to latex. Although it would be possible to handle theorem
6035 # formatting in HTML as it was done previously it is impossible
6036 # to keep the theorem counters in step with other counters (e.g. equations)
6037 # to which only latex has access to. Sad...
6038 sub get_body_newtheorem {
6039 # local(*_) = @_;
6040 local($after_R) = @_;
6041 local($_) = $$after_R;
6042 my ($orig, $body) = ($_, '');
6043 my ($title, $env, $ctr, $within, $cmd, $tmp, $begin, $end, $pat);
6044 my ($new_thm) = 'theorem';
6045 # Just chop off the arguments and append to $next_def
6046 ($env,$pat) = &get_next(1); $new_thm .= $pat;
6047 ($ctr,$pat) = &get_next(0); $new_thm .= $pat;
6048 ($title,$pat) = &get_next(1); $new_thm .= $pat;
6049 ($within,$pat) = &get_next(0); $new_thm .= $pat;
6051 #check the style parameters
6052 my ($hfont,$bfont,$thm_style);
6053 my ($before_thm) = join('',@processed);
6054 my ($which,$cmds);
6055 while ($before_thm =~ /$theorem_cmd_rx/) {
6056 $which = $1;
6057 $before_thm = $';
6058 $before_thm =~ s/$next_pair_rx/$cmds = $2;''/e;
6059 $cmds =~ s/\\/\|/g; # escape any backslash
6060 if ($which =~ /style/) { $thm_style = $cmds }
6061 elsif ($which =~ /header/) { $hfont = $cmds }
6062 elsif ($which =~ /body/) { $bfont = $cmds }
6063 }
6064 $hfont = '['.$hfont.']';
6065 $bfont = '['.$bfont.']';
6066 $thm_style = '['.$thm_style.']';
6067 undef $before_thm;
6069 if (!($ctr)) {
6070 # define the new counter
6071 $ctr = $env;
6072 do {
6073 ### local($_) = "\\arabic<<1>>$ctr<<1>>";
6074 ### $_ = join('',"\\the$within", "." , $_) if ($within);
6075 $body = "\\arabic<<1>>$ctr<<1>>";
6076 $body = join('',"\\the$within", "." , $body) if ($within);
6077 &make_unique($body);
6078 $cmd = "the$ctr";
6079 $tmp = "do_cmd_$cmd";
6080 do {
6081 $new_command{$cmd} = join(':!:',0,$body,'}')
6082 } unless (defined &$tmp);
6083 &write_mydb("new_command", $cmd, $new_command{$cmd});
6084 eval "sub do_cmd_$cmd {\n"
6085 . 'local($_,$ot) = @_;'."\n"
6086 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'."\n"
6087 . '&translate_commands(' . "\"$body\"" . ");\n}\n";
6088 print STDERR "\n*** sub $tmp failed:\n$@\n" if ($@);
6089 $raw_arg_cmds{$cmd} = 1;
6090 undef $body;
6091 };
6092 &do_body_newcounter($ctr);
6093 } else {
6094 do {
6095 ### local($_) = "\\arabic<<1>>$ctr<<1>>";
6096 $body = "\\arabic<<1>>$ctr<<1>>";
6097 &make_unique($body);
6098 $cmd = "the$env";
6099 $tmp = "do_cmd_$cmd";
6100 do {
6101 $new_command{$cmd} = join(':!:',0,$body,'}')
6102 } unless (defined &$tmp);
6103 &write_mydb("new_command", $cmd, $new_command{$cmd});
6104 eval "sub do_cmd_$cmd {\n"
6105 . 'local($_,$ot) = @_;'
6106 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'
6107 . '&translate_commands(' . "\"$body\"" . ");\n}\n";
6108 print STDERR "\n*** sub $tmp failed:\n$@\n" if ($@);
6109 $raw_arg_cmds{$cmd} = 1;
6110 undef $body;
6111 };
6112 }
6114 # record the counter dependency
6115 &addto_dependents($within,$ctr) if ($within);
6117 # save the text-label in the %new_theorem hash
6118 $new_theorem{$env} = $title;
6120 # define a new environment
6121 my ($id) = ++$global{'max_id'};
6122 $begin = "\\begin<<$id>>theorem_type<<$id>>"
6123 . "[$env][$ctr][$within]$thm_style$hfont$bfont\n";
6124 $id = ++$global{'max_id'};
6125 $end = "\\end<<$id>>theorem_type<<$id>>\n";
6126 $tmp = "do_env_$env";
6127 if ((defined &$tmp)&&($ALLOW_REDEFINE)) {
6128 print STDOUT "\n*** redefining theorem environment {$env} ***\n";
6129 }
6130 $new_environment{$env} = join(':!:', '', $begin, $end, '')
6131 unless ((defined &$tmp)&&(! $ALLOW_REDEFINE));
6133 if (!$PREAMBLE) {
6134 my ($new_cmd) = join(''
6135 , 'theorem{}' );
6136 &add_to_preamble('theorem', "\\new".$new_cmd );
6137 $$after_R = $_;
6138 return();
6139 }
6140 $$after_R = $_;
6141 'newed'.$new_thm;
6142 }
6144 sub do_cmd_theoremstyle {
6145 local($_) = @_;
6146 local($thm_type);
6147 $thm_type = &missing_braces unless (
6148 (s/$next_pair_pr_rx/$thm_type=$2;''/e)
6149 ||(s/$next_pair_rx/$thm_type=$2;''/e));
6150 # $THM_STYLE = $thm_type;
6151 $_;
6152 }
6153 sub do_cmd_theoremheaderfont {
6154 local($_) = @_;
6155 local($thm_type);
6156 $thm_type = &missing_braces unless (
6157 (s/$next_pair_pr_rx/$thm_type=$2;''/e)
6158 ||(s/$next_pair_rx/$thm_type=$2;''/e));
6159 # $THM_HFONT = $thm_type;
6160 $_;
6161 }
6162 sub do_cmd_theorembodyfont {
6163 local($_) = @_;
6164 local($thm_type);
6165 $thm_type = &missing_braces unless (
6166 (s/$next_pair_pr_rx/$thm_type=$2;''/e)
6167 ||(s/$next_pair_rx/$thm_type=$2;''/e));
6168 # $THM_BFONT = $thm_type;
6169 $_;
6170 }
6172 sub do_env_theorem_type {
6173 local($_) = @_;
6174 local($dum,$env,$ctr,$within, $label, $name, $title, $text, $index);
6175 ($env, $dum) = &get_next_optional_argument;
6176 ($ctr, $dum) = &get_next_optional_argument;
6177 ($within, $dum) = &get_next_optional_argument;
6179 local($thm_num, $thm_style);
6180 # defaults for plain theorem-style
6181 my ($hfont,$bfont) = ('','');
6183 ($thm_style, $dum) = &get_next_optional_argument;
6184 ($hfont, $dum) = &get_next_optional_argument;
6185 $hfont =~ s/\|/\\/og;
6186 ($bfont, $dum) = &get_next_optional_argument;
6187 $bfont =~ s/\|/\\/og;
6189 # the pre-defined alternative theorem-styles
6190 if ($thm_style =~ /definition/) {
6191 $bfont = '\normalfont' unless $bfont;
6192 } elsif ($thm_style =~ /remark/) {
6193 $hfont = '\itshape' unless $hfont;
6194 $bfont = '\normalfont' unless $bfont;
6195 }
6197 # defaults for plain theorem-style
6198 $hfont = '\bfseries' unless $hfont;
6199 $bfont = '\itshape' unless $bfont;
6201 ($name, $dum) = &get_next_optional_argument;
6202 $name = &translate_environments("${O}0$C".$name."${O}0$C") if $name;
6203 $name = &translate_commands($name) if ($name =~ /\\/);
6205 $index = $section_commands{$ctr};
6206 if ($index) {
6207 # environment actually starts a new (sub-)section
6208 $curr_sec_id[$index]++;
6209 local($this) = &translate_commands("\\the$ctr");
6210 local($hash) = &sanitize($name." $this");
6211 local($section_tag) = join('', @curr_sec_id);
6212 $encoded_section_number{$hash} = join($;, $section_tag);
6213 &reset_dependents($ctr) if ($dependent{$ctr});
6214 $thm_num = &translate_commands("\\the$ctr");
6215 $thm_num =~ s/(\w)\.(\.\w)/$1$2/g;
6217 # construct the sectioning title from the counter values
6218 $title = join( '', $new_theorem{$env}, " "
6219 , &translate_commands("\\the$ctr") );
6220 $toc_section_info{join(' ',@curr_sec_id)} = \
6221 "$current_depth$delim$CURRENT_FILE$delim$title"
6222 if ($current_depth <= $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH);
6223 $section_info{join(' ',@curr_sec_id)} = \
6224 "$current_depth$delim$CURRENT_FILE$delim$title$delim";
6225 $title = join('',"<A NAME=\"SECTION$section_tag\"><B>"
6226 , $title , "</B></A>" );
6227 } else {
6228 if ($ctr) {
6229 print STDOUT "\nSTP:$ctr:+1" if ($VERBOSITY > 3);
6230 $global{$ctr}++;
6231 print STDOUT "=".$global{$ctr}." " if ($VERBOSITY > 3);
6232 &reset_dependents($ctr) if ($dependent{$ctr});
6233 $thm_num = "\\the$ctr ";
6234 } else { $thm_num = ''; }
6236 # construct the full title from the counter values
6237 $title = $new_theorem{$env};
6238 if (($thm_style =~ /margin/)&&($HTML_VERSION > 2.1)) {
6239 # don't use the number yet
6240 } elsif ($thm_style =~ /change/) {
6241 $title = join(' ', $thm_num, "\\space", $title)
6242 } else {
6243 $title = join(' ', $title, "\\space", $thm_num);
6244 }
6246 if ($hfont) {
6247 $title = join('',$O,++$global{'max_id'},$C,$hfont," "
6248 , $title, $O,++$global{'max_id'},$C);
6249 $title = &translate_environments($title);
6250 $title = &translate_commands($title);
6251 } else {
6252 $title = join('',"<B>",&translate_commands($title),"</B>");
6253 }
6254 $title =~ s/(\w)\.(\.\w)/$1$2/g;
6255 }
6256 # extract any name or label that may occur at the start
6257 s/^\s*(\\label(($O|$OP)\d+($C|$CP))([^<]*)\2)?\s*(\(([^\)]*)\))?/
6258 $label=$1; $text=$5; $name=$7 if ($7); ''/eo;
6259 if ($label) {
6260 $label = &anchor_label($text,$CURRENT_FILE,'');
6261 $label =~ s/$anchor_mark/$title/;
6262 $title = $label;
6263 }
6264 if ($name) {
6265 $name =~ s/^\s*|\s*$//g;
6266 $name = join('', " (", $name, ") ") if $name;
6267 }
6268 local($attribs, $border);
6269 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
6270 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
6272 $_ = join('', $O,++$global{'max_id'},$C, $bfont
6273 , " ", $_ ,$O,++$global{'max_id'},$C) if ($bfont);
6275 my($cmd) = 'do_thm_'.$env;
6276 if (defined &$cmd) {
6277 $_ = &$cmd($ctr, $title, $_);
6278 } else {
6279 $_ = &translate_environments($_);
6280 $_ = &translate_commands($_);
6281 }
6283 if ($thm_style =~ /margin/) {
6284 local($valign);
6285 $valign = ($NETSCAPE_HTML ? ' VALIGN="BASELINE"':'');
6286 if ($hfont) {
6287 $thm_num = join('',$O,++$global{'max_id'},$C,$hfont," "
6288 , $thm_num, $O,++$global{'max_id'},$C);
6289 $thm_num = &translate_environments($thm_num);
6290 $thm_num = &translate_commands($thm_num);
6291 } else {
6292 $thm_num = join('',"<B>",&translate_commands($thm_num),"</B>");
6293 }
6294 $thm_num =~ s/(\w)\.(\.\w)/$1$2/g;
6296 # code copied from &make_table
6297 local($Tattribs);
6298 if ($attribs) {
6299 if (!($attribs =~ /=/)) {
6300 $Tattribs = &parse_valuesonly($attribs,"TABLE");
6301 } else {
6302 $Tattribs = &parse_keyvalues($attribs,"TABLE");
6303 }
6304 $Tattribs = ' '.$Tattribs if ($Tattribs);
6305 }
6306 $_ = join ('', "\n<P><DIV$env_id><TABLE"
6307 , (($border) ? " BORDER=\"$border\"" : '')
6308 , $Tattribs , ">\n<TR VALIGN=\"TOP\">"
6309 , "<TD$valign>", &translate_commands($thm_num)
6310 , "</TD>\n<TD>", $title, $name
6311 , (($thm_style =~ /break/)? "\n<BR>":" \ \n")
6312 , $_ , "\n</TD></TR></TABLE></DIV>");
6313 } else {
6314 $_ = join('', "<P><DIV$env_id>"
6315 , $title, $name
6316 , (($thm_style =~ /break/)? "\n<BR>":" \ \n")
6317 , $_
6318 ,"</DIV><P></P>\n");
6319 if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
6320 &make_table( $border, $attribs, '', '', '', $_ )
6321 } else { $_ }
6322 }
6323 }
6325 # Modifies $_ in the caller and as a side-effect it modifies $next_def
6326 # which is local to substitute_meta_cmds
6327 sub get_next {
6328 local($what) = @_;
6329 local($next, $pat, $tmp);
6330 if ($what == 1) {
6331 ($next, $tmp, $pat) = &get_next_argument;
6332 }
6333 elsif ($what == 2) {
6334 ($next, $pat) = &get_next_tex_cmd;
6335 }
6336 elsif ($what == 3) {
6337 ($next, $pat) = &get_next_def_arg;
6338 }
6339 elsif ($what == 4) {
6340 ($next, $tmp, $pat) = &get_next_argument;
6341 }
6342 else {
6343 ($next, $pat) = &get_next_optional_argument;
6344 }
6345 do {
6346 $next_def .= &revert_to_raw_tex($pat) if $pat;
6347 } unless ($renewed); # don't add \renewcommand to preamble
6348 # $next =~ s/(^\s*)|(\s*$)//g unless ($what == 4); #don't lose white space on body
6349 $next =~ s/(^\s*)|(\s*$)//g unless ($what =~ /[14]/); #retain white space in body
6350 ($next, $pat);
6351 }
6353 # The following get_next_<something> ARE ALL DESTRUCTIVE.
6354 sub get_next_argument {
6355 local($next, $br_id, $pat);
6356 if (!(s/$next_pair_rx/$br_id=$1;$next=$2;$pat=$&;''/seo)) {
6357 print " *** Could not find argument for command \\$cmd ***\n";
6358 print "$_\n";
6359 };
6360 ($next, $br_id, $pat);
6361 }
6363 sub get_next_pair_or_char_pr {
6364 local($next, $br_id, $pat, $epat);
6365 if ( /^\{([^\}]*)\}/o && (! $`)) {
6366 ($next, $pat) = ($1, $&);
6367 } elsif ( (/^\s*([^\s\\<])/o && (! $`))) {
6368 ($next, $pat) = ($1, $&);
6369 } elsif ( /$next_pair_pr_rx/o && (! $`)) {
6370 ($next, $br_id, $pat) = ($2, $1, $&);
6371 };
6372 $epat = &escape_rx_chars($pat);
6373 s/$epat// if $pat;
6374 ($next, $br_id, $pat);
6375 }
6377 sub get_next_optional_argument {
6378 local($next, $pat);
6379 s/$optional_arg_rx/$next=$1;$pat=$&;''/eo
6380 if (/\s*[[]/ && (! $`)); # if the first character is a [
6381 #remove trailing spaces and/or comments
6382 s/^($comment_mark(\d+\n?)?|$EOL)//gos;
6384 # if nested inside {}s we need to get more tokens
6385 if ($pat) {
6386 # check for \item, indicating something has gone wrong
6387 if ($pat =~ /\\item\b/ ) {
6388 print "\n*** optional argument badly formed:\n" . $pat . "\n\n";
6389 $_ = $pat . $_;
6390 return('','');
6391 }
6392 # check for being nested inside {}s
6393 local($found) = $pat;
6394 while ($found =~ s/$O(\d+)$C[\s\S]*$O\1$C//g) {
6395 if ($found =~ /$O(\d+)$C/) {
6396 local($br_id) = $1;
6397 if (s/$O$br_id$C//) {
6398 $found .= $`.$&;
6399 $pat .= "]".$`.$&;
6400 $next .= "]".$`.$&;
6401 $_ = $';
6402 s/^([^]]*)\]/$next.=$1;$pat.=$&;''/e;
6403 $found .= $&;
6404 } else { last } # give up if no closing brace
6405 }
6406 }
6407 } else {
6408 s/^\s*\[\]/$pat=$&;''/e; # This is not picked by $optional_arg_rx
6409 }
6410 ($next, $pat);
6411 }
6413 #JCL(jcl-del) - use new form of $single_cmd_rx.
6414 sub get_next_tex_cmd {
6415 local($next, $pat);
6416 s/^\s*\=?\s*$single_cmd_rx/$4/;
6417 ($next, $pat) = ($1.$2,"\\".$1.$2);
6418 }
6420 sub get_next_def_arg {
6421 local($next, $pat);
6423 # Sets is_simple_def for caller. Start by turning it off, then
6424 # turn it on if we find one of the "simple" patterns.
6426 # This has got to be hit-or-miss to an extent, given the
6427 # thoroughly incestuous relationship between the TeX macroprocessor
6428 # ('mouth') and typesetting back-end ('stomach'). Anything which
6429 # even does catcode hacking is going to lose BAD.
6431 s/^\s*//so; # Remove whitespace
6433 $is_simple_def = 0;
6435 # no arguments
6437 if (/^$O/ && (! $`)) { $next=0; $pat=''; $is_simple_def=1; }
6439 # 'simple' arguments
6441 if (! $is_simple_def && /$tex_def_arg_rx/o && (! $`)) {
6442 s/$tex_def_arg_rx/$next=$1; $pat=$&; $is_simple_def=1; $2/seo; }
6444 # MESSY arguments
6446 if (! $is_simple_def) {
6447 print "Arguments to $cmd are too complex ...\n";
6448 print "It will not be processed unless used in another environment\n";
6449 print "which is passed to LaTeX whole for processing.\n";
6451 s/^[^<]*(<[^<]+)*<</$next=''; $pat=$&; $O/seo;
6452 }
6454 $pat =~ s/$O$//so;
6456 ($next, $pat);
6457 }
6459 #### Key-value parsing added by RRM
6460 #
6461 # This cleans-up the key-value pairs for a given tag,
6462 # by removing unnecessary spaces and commas, inserting quotes
6463 # around the value and puts a preceding space.
6464 # The key becomes upper-case, while the value becomes lower-case.
6465 # If specific `tags' are provided, then checking is done to verify
6466 # that the keys and values are valid for these tags, eliminating
6467 # any that are not; unmatched keys or values are handled as well.
6468 # If no tags are provided, then just a list of pairs is returned.
6469 #
6470 sub parse_keyvalues {
6471 local($_,@tags) = @_;
6472 local($key,$KEY,$attribs,$atts,%attributes)=('','','','');
6474 # beware active " in german
6475 local($is_german);
6476 if (s/\"/'/g) {
6477 $is_german=1;
6478 s/(^|[\s,=])(\&\#\d\d\d;)/$1'$2/g
6479 }
6480 local($saved) = &revert_to_raw_tex(&translate_commands($_));
6481 print "\nATTRIBS: $saved\n" if ($VERBOSITY > 6);
6483 $saved =~ s/$percent_mark/%/g;
6484 $saved =~ s/((^|[\s,=])')\\\W{(\w)}/$1$3/g
6485 if $is_german; #unwanted accents, from active "
6486 if (@tags) {
6487 foreach $tag (@tags) {
6488 $_ = $saved;
6489 local($name)= $tag."_attribs";
6490 $taglist = $$name;
6491 $name .= "_rx_list";
6492 $taglist .= $$name;
6493 $taglist =~ s/,,/,/;
6494 # s/(^|,)\s*([a-zA-Z]+)\s*\=\s*"?([\#\%\w\d]+)"?\s*/$attributes{$2}="$3";''/eg;
6495 # s/(^|,)\s*([a-zA-Z]+)\s*\=\s*(\"([^"]*)\"|\'([^\']*)\'|([#%\w\d]*))\s*/
6496 # s/(^|,)\s*([a-zA-Z]+)\s*\=\s*(\"([^"]*)\"|\'([^\']*)\'|([#%&@;:+-\/\w\d]*))\s*/
6497 s/(^|,)\s*([a-zA-Z]+)\s*\=\s*(\"([^"]*)\"|\'([^\']*)\'|([^<>,=\s]*))\s*/
6498 $attributes{$2}=($4?$4:($5?$5:$6));' '/eg;
6499 foreach $key (keys %attributes){
6500 $KEY = $key;
6501 $KEY =~ tr/a-z/A-Z/;
6502 if ($taglist =~ /,$KEY,/i) {
6503 local($keyname) = $tag."__".$KEY;
6504 local($keyvalues) = '';
6505 if ($$keyname) {
6506 $keyvalues = $$keyname;
6507 $atts = $attributes{$key};
6508 if ($keyvalues =~ /\,$atts\,/i ) {
6509 # $atts =~ tr/A-Z/a-z/;
6510 $attribs .= " $KEY=\"$atts\"";
6511 print "\n$KEY=$atts " if ($VERBOSITY > 3);
6512 } else { &invalid_tag($tag,$KEY,$atts); }
6513 } else { # test for a regular expression
6514 $keyname = $keyname."_rx";
6515 if ($$keyname) {
6516 $keyvalues = $$keyname;
6517 $atts = $attributes{$key};
6518 if ($atts =~ /$keyvalues/) {
6519 # $atts =~ tr/A-Z/a-z/;
6520 $attribs .= " $KEY=\"$atts\"";
6521 print "\n$KEY=$atts " if ($VERBOSITY > 3);
6522 } else { &invalid_tag($tag,$KEY,$atts) }
6523 } else {
6524 $atts = $attributes{$key};
6525 # $atts =~ tr/A-Z/a-z/;
6526 $attribs .= " $KEY=\"$atts\"";
6527 print "\n$KEY=$atts " if ($VERBOSITY > 3);
6528 }
6529 }
6530 } else {
6531 print "\n$key not in $taglist for $tag" if ($VERBOSITY > 3);
6532 }
6533 }
6534 }
6535 s/(^|\s,)\'([^\s,]*)\'(\s|$)/$1$2 /g if $is_german;
6536 $attribs .= &parse_valuesonly($_,@tags);
6537 } else {
6538 # with no tags provided, just list the key-value pairs
6539 $_ = $saved;
6540 s/\s*(\w+)\s*=\s*\"?(\w+)\"?\s*,?/$attributes{$1}=$2;''/eg;
6541 foreach $key (keys %attributes){
6542 $KEY = $key;
6543 $KEY =~ tr/a-z/A-Z/;
6544 $atts = $attributes{$key};
6545 $atts =~ tr/A-Z/a-z/;
6546 $attribs .= " $KEY=\"$atts\"";
6547 }
6548 }
6549 $attribs;
6550 }
6552 sub invalid_tag {
6553 local($tag,$key,$value) = @_;
6554 &write_warnings("$key=$value is an invalid value in the <$tag> tag\n");
6555 }
6557 # RRM
6558 # This creates key-value pairs from values only,
6559 # by checking whether the data matches any key to the provided tags.
6560 # Only the first match found is retained.
6561 # Attributes with no values are also recognised here.
6562 #
6563 sub parse_valuesonly {
6564 local($values,@tags) = @_;
6565 local($i,$tag,$key,$KEY,$attribs,$atts)=(0,'','','','','');
6566 local($saved) = &revert_to_raw_tex(&translate_commands($values));
6567 $saved =~ s/$percent_mark/%/g;
6568 foreach $tag (@tags) {
6569 local($name)= $tag."_attribs";
6570 $taglist = $$name;
6571 $values = $saved;
6572 $values =~ s/\s*\"?([^,\s\"]+)\"?\s*,?/$i++;$attributes{$i}=$1;''/eg;
6573 local($j) = 0;
6574 while ($j < $i) {
6575 $j++;
6576 $key = $attributes{$j};
6577 if ($taglist =~ /,$key,/i) {
6578 $KEY = $key;
6579 $KEY =~ tr/a-z/A-Z/;
6580 $attribs .= " $KEY";
6581 print " $KEY" if ($VERBOSITY > 3);
6582 } else {
6583 $atts = $attributes{$j};
6584 $key = &find_attribute($key,$tag);
6585 if ($key) {
6586 $KEY = $key;
6587 $KEY =~ tr/a-z/A-Z/;
6588 $atts =~ tr/A-Z/a-z/;
6589 $attribs .= " $KEY=\"$atts\"";
6590 print " $KEY = $atts" if ($VERBOSITY > 3);
6591 } else { }
6592 }
6593 }
6594 }
6595 $attribs;
6596 }
6598 # RRM
6599 # Extracts key-value pairs using a supplied (comma-separated) list.
6600 # When no list is given, it checks for a pre-defined list for the tag.
6601 #
6602 sub extract_attributes {
6603 local($tag,$taglist,$_) = @_;
6604 local($key,$attribs,$unused,%attributes);
6605 if (! ($taglist)) {
6606 local($name) = "$tag"."_attribs";
6607 if ($$name) { $taglist = $$name }
6608 }
6609 s/\s*(\w+)\s*=\s*\"?(\w+)\"?\s*,?/$attributes{$1}=$2;''/eg;
6610 foreach $key (keys %attributes){
6611 if ($taglist =~ /\,$key\,/) {
6612 $attribs .= " $key=\"$attributes{$key}\"";
6613 &write_warnings("valid attribute $key for $tag\n");
6614 } else {
6615 &write_warnings("unknown attribute $key for $tag\n");
6616 $unused .= " $key=\"$attributes{$key}\"";
6617 }
6618 }
6619 ($attribs,$unused);
6620 }
6622 # RRM
6623 # Finds the attribute of a given tag, for which a given value is valid.
6624 # Requires variables: <tag>_<key> to be a comma-separated list of keys.
6625 # So far it cannot recognise data-types, only names.
6626 #
6627 sub find_attribute {
6628 local($key,$attrib,$tag) = ('',@_);
6629 local($name) = $tag."_attribs";
6630 local($attrib_list)=$$name;
6631 if ($attrib_list) {
6632 $attrib_list =~ s/^\,//o;
6633 $attrib_list =~ s/\,$//o;
6634 local(@keys) = split(',',$attrib_list);
6635 local($attrib_vals) = '';
6636 foreach $key (@keys) {
6637 $name = $tag."__".$key;
6638 $attrib_vals = $$name;
6639 return ($key) if ($attrib_vals =~ /\,$attrib\,/i );
6640 }
6641 }
6642 $name = $tag."_attribs_rx_list";
6643 $attrib_list=$$name;
6644 if (!($attrib_list)) { return(); }
6645 $attrib_list =~ s/^\,//o;
6646 $attrib_list =~ s/\,$//o;
6647 @keys = split(',',$attrib_list);
6648 foreach $key (@keys) {
6649 next if ($attribs =~ / $key=/);
6650 $name = $tag."__".$key."_rx";
6651 $attrib_vals = $$name;
6652 if ( $attrib =~ /^$attrib_vals$/ ) {
6653 return ($key);
6654 }
6655 }
6656 0;
6657 }
6659 # in case \HTML is defined differently in packages
6660 sub do_cmd_HTML { &do_cmd_HTMLcode(@_) }
6662 sub do_cmd_HTMLcode {
6663 local($_) = @_;
6664 local($tag,$attribs,$dum);
6665 local($attribs, $dum) = &get_next_optional_argument;
6666 $tag = &missing_braces unless (
6667 (s/$next_pair_pr_rx/$tag = $2;''/eo)
6668 ||(s/$next_pair_rx/$tag = $2;''/eo));
6669 $tag = &translate_commands($tag) if ($tag =~ /\\/);
6670 if (! $tag) {
6671 print "*** no tag given with \\HTML command, ignoring it";
6672 return($_);
6673 }
6674 local($afterHTML) = $_;
6675 local($value,$TAGattribs,$etag);
6676 if (defined $unclosed_tags_list{$tag}) {
6677 } elsif (defined $closed_tags_list{$tag}) {
6678 $value = &missing_braces unless (
6679 (s/$next_pair_pr_rx/$value = $2;''/eo)
6680 ||(s/$next_pair_rx/$value = $2;''/eo));
6681 $etag = "</$tag>";
6682 $afterHTML = $_;
6683 } else {
6684 print "\n*** <$tag> is not a valid tag for HTML $HTML_VERSION";
6685 print "\n rejecting: \\HTML".(($attribs)? "[$attribs]" : '')."{$tag}";
6686 return $_ ;
6687 }
6688 if ($dum) {
6689 $attribs = &translate_commands($attribs) if ($attribs=~/\\/);
6690 if ($attribs) {
6691 if (!($attribs =~ /=/)) {
6692 $TAGattribs = &parse_valuesonly($attribs,$tag);
6693 } else {
6694 $TAGattribs = &parse_keyvalues($attribs,$tag);
6695 }
6696 }
6697 } else { } # default if no [...]
6698 local($needed) = join(','
6699 , $closed_tags_list{$tag},$unclosed_tags_list{$tag});
6700 $needed =~ s/,,/,/g; $needed =~ s/^,|,$//g;
6701 if ($TAGattribs) {
6702 if ($needed) {
6703 $needed =~ s/,,/,/g;
6704 local($this, @needed);
6705 (@needed) = split(',',$needed);
6706 foreach $this (@needed) {
6707 next unless ($this);
6708 next if ($TAGattribs =~ /\b$this\b/);
6709 print "\n*** attribute $this required for <$tag> ***";
6710 print "\n rejecting: \\HTML".(($attribs)? "[$attribs]" : '')."{$tag}";
6711 return($value.$afterHTML);
6712 }
6713 }
6714 $value = &translate_environments($value);
6715 $value = &translate_commands($value) if ($value =~ /\\/);
6716 $_ = join('', "<$tag", $TAGattribs, ">", $value, $etag);
6717 } elsif ($needed) {
6718 print STDOUT "\n*** attributes $needed are required for <$tag> ***";
6719 return($value.$after);
6720 } elsif ($value) {
6721 $value = &translate_environments($value);
6722 $value = &translate_commands($value) if ($value =~ /\\/);
6723 $_ = join('', "<$tag>", $value, $etag);
6724 } else {
6725 $_ = join('', "<$tag>", $etag);
6726 }
6727 $_.$afterHTML;
6728 }
6730 sub do_cmd_HTMLget {
6731 local($_) = @_;
6732 local($which,$value,$hash,$dummy);
6733 local($hash, $dummy) = &get_next_optional_argument;
6734 $which = &missing_braces unless (
6735 (s/$next_pair_pr_rx/$which = $2;''/eo)
6736 ||(s/$next_pair_rx/$which = $2;''/eo));
6737 if ($hash) {
6738 local($tmp) = "\%$hash";
6739 if (eval "defined \%{$hash}") { $! = '';
6740 $value = ${$hash}{'$which'};
6741 } else { print "\nhash: \%$hash not defined" }
6742 } elsif ($which) {
6743 $value = ${$which};
6744 }
6745 $value.$_;
6746 }
6748 sub do_cmd_HTMLset {
6749 local($_) = @_;
6750 local($which,$value,$hash,$dummy);
6751 local($hash, $dummy) = &get_next_optional_argument;
6752 $which = &missing_braces unless (
6753 (s/$next_pair_pr_rx/$which = $2;''/eo)
6754 ||(s/$next_pair_rx/$which = $2;''/eo));
6755 $value = &missing_braces unless (
6756 (s/$next_pair_pr_rx/$value = $2;''/eo)
6757 ||(s/$next_pair_rx/$value = $2;''/eo));
6758 if ($hash) {
6759 local($tmp) = "\%$hash";
6760 if (eval "defined \%{$hash}") { $! = '';
6761 # eval "\$$hash{'$which'} = \"$value\";";
6762 ${$hash}{'$which'} = $value;
6763 print "\nHTMLset failed: $! " if ($!);
6764 } else { print "\nhash: \%$hash not defined" }
6765 } elsif ($which) { $! = '';
6766 eval "\${$which} = \"$value\";";
6767 print "\nHTMLset failed: $! " if ($!);
6768 }
6769 $_;
6770 }
6772 sub do_cmd_HTMLsetenv { &do_cmd_HTMLset(@_) }
6774 ####
6777 # Appends $next_def to the preamble if it is not already there.
6778 sub add_to_preamble {
6779 local($type, $next_def) = @_;
6780 local($name);
6781 if ($type =~ /def|include|special|graphicspath/) {
6782 local($pat) = &escape_rx_chars ($next_def);
6783 # $preamble .= $next_def . "\n" unless ($preamble =~ /$pat/);
6784 push(@preamble, $pat);
6785 }
6786 elsif ($type =~ /command|environment|theorem|counter/) {
6787 push(@preamble, $next_def );
6788 }
6789 else {
6790 ($name) = $next_def =~ /$marker\s*({[^}]+})/; # matches type{name}
6791 $name = &escape_rx_chars($name);
6792 # $preamble .= $next_def . "\n" unless ($preamble =~ /$marker\s*$name/);
6793 push(@preamble, $name );
6794 }
6795 }
6797 sub make_latex{
6798 # This is the environment in which to process constructs that cannot be
6799 # translated to HTML.
6800 # The environment tex2html_wrap will be wrapped around any shorthand
6801 # environments (e.g. $, \(, \[).
6802 # The tex2html_wrap environment will be treated as an unrecognised
6803 # evironment by the translator and its contents (i.e. the 'shorthand'
6804 # environment) will be passed to latex for processing as usual.
6805 local($contents) = @_;
6806 local($preamble) = $preamble;
6807 local($aux_preamble) = $aux_preamble;
6808 while ($preamble =~ s/^(\@.*\n)/$prelatex .= $1;''/e) {}
6809 print "\nPRE-LATEX: $prelatex" if (($prelatex)&&($VERBOSITY > 1));
6811 %newed_commands =
6812 ( 'newedcommand' , 'newcommand'
6813 , 'renewedcommand' , 'renewcommand'
6814 , 'providedcommand' , 'providecommand'
6815 , 'newedenvironment' , 'newenvironment'
6816 , 'newedboolean' , 'newboolean'
6817 , 'newedcounter' , 'newcounter'
6818 , 'newedtheorem' , 'newtheorem'
6819 , 'newedfont' , 'newfont' , 'newedif', 'newif'
6820 );
6823 # Make the @ character a normal letter ...
6824 $preamble =~ s/\\par([^A-Za-z]|$)/\n$1/g;
6825 $preamble =~ s/(\\document(class|style)(\[[^\]]+\])?\{\w+\})/$1\n/;
6826 $preamble =~ s/(\\document(class|style)(\[[^\]]+\])?\{\w+\})/$1\n\\RequirePackage{ifthen}\n/
6827 unless ($preamble =~/\{ifthen\}/);
6828 # $preamble =~ s/(\\document(class|style)(\[[^\]]+\])?\{\w+\})/$1\n\\makeatletter/;
6829 # ... and make it special again after the preamble
6830 # remove the \begin/\end for tex2html_nowrap and tex2html_deferred environments
6831 $preamble =~s/\\(begin|end)\s*\{(tex2html_(nowrap|deferred|nomath|preform)[_a-z]*|imagesonly)\}//g;
6832 $preamble =~s/\n?\s?<tex2html_(end)?file>\#[^#]*\#//mg;
6834 $preamble = "\\documentclass\{article\}%\n\\usepackage{html}\n\\usepackage[dvips]{color}\n"
6835 unless ($preamble);
6836 if (($LATEX_DUMP)&&(!($preamble =~ /\\usepackage\{ldump\}/))) {
6837 # MRO: replaced $* with /m
6838 $preamble =~ s/(\\document(class|style)[^\n]*\n)/$1\\usepackage\{ldump\}\n/m;
6839 }
6840 if ($preamble =~ /pstricks/) {
6841 if ($LOAD_LATEX_COLOR) {
6842 $LOAD_LATEX_COLOR =~ s/\{color\}/\{pstcol\}/ ;
6843 } else {
6844 $LOAD_LATEX_COLOR = "\n\\usepackage[dvips]{pstcol}\n";
6845 }
6846 } else {
6847 $LOAD_LATEX_COLOR = "\n\\usepackage[dvips]{color}";
6848 }
6849 $LATEX_COLOR = "\\pagecolor[gray]{.85}\\nobreak " unless $LATEX_COLOR;
6850 if ($preamble =~ /(^|\s*[^%])\s*\\documentstyle/) {
6851 # \usepackage is invalid in LaTeX 2.09 and LaTeX-2e compatibility mode
6852 $LATEX_COLOR = ''; $LOAD_LATEX_COLOR = '';
6853 # ... so is \providecommand
6854 $preamble =~ s/\\documentstyle[^{]*{[^}]*}\n?/
6855 $&."\n\\let\\providecommand\\newcommand\n"/eo;
6856 }
6858 $preamble .= $LOAD_LATEX_COLOR."\n" unless ($preamble =~ /[,\{]color[,\}]/);
6859 $preamble .= "\n\n".$LATEX_COLOR."\n" unless ($preamble =~ /\\pagecolor/);
6860 do {
6861 if ($ISOLATIN_CHARS) { $INPUTENC = $INPUTENC || 'latin1' };
6862 $preamble .= "\n\\usepackage[".$INPUTENC."]\{inputenc\}\n";
6863 } unless ($preamble =~ /\\inputenc/);
6865 $aux_preamble = '' unless (($aux_preamble)&&($contents =~ /\\(hyper)?(ref|cite)/));
6867 $preamble =~ s/\\((provide|(re)?new)ed(command|counter|if|theorem|environment|font))\b/
6868 "%\n\\".$newed_commands{$1}/eg;
6869 $preamble =~ s/(\\(re)?newcommand)\s*(\{(\\?)(\}|[^\}]+)\})/
6870 $1.(($4)? $3 : "{\\".$5.'}' )/eg;
6872 $preamble =~s/$verbatim_mark(imagesonly)(\d+)#/$verbatim{$2}/eg; # for images.tex only
6874 # local($key);
6875 # foreach $key (keys %newed_commands) {
6876 # $preamble .= "\n\\let\\$key\\".$newed_commands{$key}
6877 # }
6878 $preamble .= "\n";
6880 local($paperwidth) = '';
6881 if ($PAPERSIZE) { $paperwidth = &adjust_textwidth($PAPERSIZE); }
6882 else { $paperwidth = &adjust_textwidth("a5"); }
6883 local($kern) = ($EXTRA_IMAGE_SCALE ? $EXTRA_IMAGE_SCALE/2 : ".5" );
6884 $kern = $kern * $MATH_SCALE_FACTOR;
6885 $prelatex . ($DEBUG ? "\\nonstopmode" : "\\batchmode") .
6886 "\n$preamble\n\n\\makeatletter\n$aux_preamble\n" .
6887 "\\makeatletter\n\\count\@=\\the\\catcode`\\_ \\catcode`\\_=8 \n" .
6888 "\\newenvironment{tex2html_wrap}{}{}%\n" .
6889 "\\catcode`\\<=12\\catcode`\\_=\\count\@\n" .
6890 "\\newcommand{\\providedcommand}[1]{\\expandafter\\providecommand\\csname #1\\endcsname}%\n" .
6891 "\\newcommand{\\renewedcommand}[1]{\\expandafter\\providecommand\\csname #1\\endcsname{}%\n" .
6892 " \\expandafter\\renewcommand\\csname #1\\endcsname}%\n" .
6893 "\\newcommand{\\newedenvironment}[1]{\\newenvironment{#1}{}{}\\renewenvironment{#1}}%\n" .
6894 "\\let\\newedcommand\\renewedcommand\n" .
6895 "\\let\\renewedenvironment\\newedenvironment\n" .
6896 "\\makeatother\n" .
6897 "\\let\\mathon=\$\n\\let\\mathoff=\$\n" .
6898 "\\ifx\\AtBeginDocument\\undefined \\newcommand{\\AtBeginDocument}[1]{}\\fi\n" .
6899 "\\newbox\\sizebox\n" . "$paperwidth" .
6900 "\\newwrite\\lthtmlwrite\n" . "\\makeatletter\n" .
6901 "\\let\\realnormalsize=\\normalsize\n\\global\\topskip=2sp\n\\def\\preveqno{}" .
6902 "\\let\\real\@float=\\\@float \\let\\realend\@float=\\end\@float\n" .
6903 "\\def\\\@float{\\let\\\@savefreelist\\\@freelist\\real\@float}\n" .
6904 # "\\def\\\@float{\\\@dbflt}\n" .
6905 "\\def\\liih\@math{\\ifmmode\$\\else\\bad\@math\\fi}\n" .
6906 "\\def\\end\@float{\\realend\@float\\global\\let\\\@freelist\\\@savefreelist}\n" .
6907 "\\let\\real\@dbflt=\\\@dbflt \\let\\end\@dblfloat=\\end\@float\n" .
6908 "\\let\\\@largefloatcheck=\\relax\n" .
6909 "\\let\\if\@boxedmulticols=\\iftrue\n" .
6910 "\\def\\\@dbflt{\\let\\\@savefreelist\\\@freelist\\real\@dbflt}\n" .
6911 "\\def\\adjustnormalsize{\\def\\normalsize{\\mathsurround=0pt \\realnormalsize\n" .
6912 " \\parindent=0pt\\abovedisplayskip=0pt\\belowdisplayskip=0pt}%\n" .
6913 " \\def\\phantompar{\\csname par\\endcsname}\\normalsize}%\n" .
6914 "\\def\\lthtmltypeout#1{{\\let\\protect\\string \\immediate\\write\\lthtmlwrite{#1}}}%\n" .
6915 "\\newcommand\\lthtmlhboxmathA{\\adjustnormalsize\\setbox\\sizebox=\\hbox\\bgroup\\kern.05em }%\n" .
6916 "\\newcommand\\lthtmlhboxmathB{\\adjustnormalsize\\setbox\\sizebox=\\hbox to\\hsize\\bgroup\\hfill }%\n" .
6917 "\\newcommand\\lthtmlvboxmathA{\\adjustnormalsize\\setbox\\sizebox=\\vbox\\bgroup %\n".
6918 " \\let\\ifinner=\\iffalse \\let\\)\\liih\@math }%\n" .
6919 "\\newcommand\\lthtmlboxmathZ{\\\@next\\next\\\@currlist{}{\\def\\next{\\voidb\@x}}%\n" .
6920 # " \\expandafter\\box\\next\\edef\\next{\\egroup\\def\\noexpand\\thiseqn{\\theequation}}\\next}%\n" .
6921 " \\expandafter\\box\\next\\egroup}%\n" .
6922 "\\newcommand\\lthtmlmathtype[1]{\\gdef\\lthtmlmathenv{#1}}%\n" .
6923 "\\newcommand\\lthtmllogmath{\\dimen0\\ht\\sizebox \\advance\\dimen0\\dp\\sizebox\n" .
6924 " \\ifdim\\dimen0>.95\\vsize\n" . " \\lthtmltypeout{%\n" .
6925 "*** image for \\lthtmlmathenv\\space is too tall at \\the\\dimen0, reducing to .95 vsize ***}%\n" .
6926 " \\ht\\sizebox.95\\vsize \\dp\\sizebox\\z\@ \\fi\n" . " \\lthtmltypeout{l2hSize %\n" .
6927 ":\\lthtmlmathenv:\\the\\ht\\sizebox::\\the\\dp\\sizebox::\\the\\wd\\sizebox.\\preveqno}}%\n" .
6928 "\\newcommand\\lthtmlfigureA[1]{\\let\\\@savefreelist\\\@freelist
6929 \\lthtmlmathtype{#1}\\lthtmlvboxmathA}%\n" .
6930 "\\newcommand\\lthtmlpictureA{\\bgroup\\catcode`\\_=8 \\lthtmlpictureB}%\n" .
6931 "\\newcommand\\lthtmlpictureB[1]{\\lthtmlmathtype{#1}\\egroup
6932 \\let\\\@savefreelist\\\@freelist \\lthtmlhboxmathB}%\n" .
6933 "\\newcommand\\lthtmlpictureZ[1]{\\hfill\\lthtmlfigureZ}%\n" .
6934 "\\newcommand\\lthtmlfigureZ{\\lthtmlboxmathZ\\lthtmllogmath\\copy\\sizebox
6935 \\global\\let\\\@freelist\\\@savefreelist}%\n" .
6936 "\\newcommand\\lthtmldisplayA{\\bgroup\\catcode`\\_=8 \\lthtmldisplayAi}%\n" .
6937 "\\newcommand\\lthtmldisplayAi[1]{\\lthtmlmathtype{#1}\\egroup\\lthtmlvboxmathA}%\n" .
6938 "\\newcommand\\lthtmldisplayB[1]{\\edef\\preveqno{(\\theequation)}%\n" .
6939 " \\lthtmldisplayA{#1}\\let\\\@eqnnum\\relax}%\n" .
6940 "\\newcommand\\lthtmldisplayZ{\\lthtmlboxmathZ\\lthtmllogmath\\lthtmlsetmath}%\n" .
6941 "\\newcommand\\lthtmlinlinemathA{\\bgroup\\catcode`\\_=8 \\lthtmlinlinemathB}\n" .
6942 "\\newcommand\\lthtmlinlinemathB[1]{\\lthtmlmathtype{#1}\\egroup\\lthtmlhboxmathA\n" .
6943 " \\vrule height1.5ex width0pt }%\n" .
6944 "\\newcommand\\lthtmlinlineA{\\bgroup\\catcode`\\_=8 \\lthtmlinlineB}%\n" .
6945 "\\newcommand\\lthtmlinlineB[1]{\\lthtmlmathtype{#1}\\egroup\\lthtmlhboxmathA}%\n" .
6946 "\\newcommand\\lthtmlinlineZ{\\egroup\\expandafter\\ifdim\\dp\\sizebox>0pt %\n" .
6947 " \\expandafter\\centerinlinemath\\fi\\lthtmllogmath\\lthtmlsetinline}\n" .
6948 "\\newcommand\\lthtmlinlinemathZ{\\egroup\\expandafter\\ifdim\\dp\\sizebox>0pt %\n" .
6949 " \\expandafter\\centerinlinemath\\fi\\lthtmllogmath\\lthtmlsetmath}\n" .
6950 "\\newcommand\\lthtmlindisplaymathZ{\\egroup %\n" .
6951 " \\centerinlinemath\\lthtmllogmath\\lthtmlsetmath}\n" .
6952 "\\def\\lthtmlsetinline{\\hbox{\\vrule width.1em \\vtop{\\vbox{%\n" .
6953 " \\kern.1em\\copy\\sizebox}\\ifdim\\dp\\sizebox>0pt\\kern.1em\\else\\kern.3pt\\fi\n" .
6954 " \\ifdim\\hsize>\\wd\\sizebox \\hrule depth1pt\\fi}}}\n" .
6955 "\\def\\lthtmlsetmath{\\hbox{\\vrule width.1em\\kern-.05em\\vtop{\\vbox{%\n" .
6956 " \\kern.1em\\kern$kern pt\\hbox{\\hglue.17em\\copy\\sizebox\\hglue$kern pt}}\\kern.3pt%\n" .
6957 " \\ifdim\\dp\\sizebox>0pt\\kern.1em\\fi \\kern$kern pt%\n" .
6958 " \\ifdim\\hsize>\\wd\\sizebox \\hrule depth1pt\\fi}}}\n" .
6959 "\\def\\centerinlinemath{%\n" .
6960 " \\dimen1=\\ifdim\\ht\\sizebox<\\dp\\sizebox \\dp\\sizebox\\else\\ht\\sizebox\\fi\n" .
6961 " \\advance\\dimen1by.5pt \\vrule width0pt height\\dimen1 depth\\dimen1 \n".
6962 " \\dp\\sizebox=\\dimen1\\ht\\sizebox=\\dimen1\\relax}\n\n" .
6963 "\\def\\lthtmlcheckvsize{\\ifdim\\ht\\sizebox<\\vsize \n" .
6964 " \\ifdim\\wd\\sizebox<\\hsize\\expandafter\\hfill\\fi \\expandafter\\vfill\n" .
6965 " \\else\\expandafter\\vss\\fi}%\n" .
6966 "\\providecommand{\\selectlanguage}[1]{}%\n" .
6967 # "\\def\\\@enddocumenthook{\\ifnum\\count0>1 \\ifvoid\\\@cclv\\penalty-\\\@MM\\fi\\fi}\n" .
6968 "\\makeatletter \\tracingstats = 1 \n"
6969 . ($itrans_loaded ? $itrans_tex_mod : '')
6970 . $LaTeXmacros . "\n" # macros defined in extension files
6971 # "\\usepackage{lthimages}\n" .
6972 . (($LATEX_DUMP)? "\\latexdump\n" : '')
6973 . "\n\\begin{document}\n" .
6974 "\\pagestyle{empty}\\thispagestyle{empty}\\lthtmltypeout{}%\n" .
6975 "\\lthtmltypeout{latex2htmlLength hsize=\\the\\hsize}\\lthtmltypeout{}%\n" .
6976 "\\lthtmltypeout{latex2htmlLength vsize=\\the\\vsize}\\lthtmltypeout{}%\n" .
6977 "\\lthtmltypeout{latex2htmlLength hoffset=\\the\\hoffset}\\lthtmltypeout{}%\n" .
6978 "\\lthtmltypeout{latex2htmlLength voffset=\\the\\voffset}\\lthtmltypeout{}%\n" .
6979 "\\lthtmltypeout{latex2htmlLength topmargin=\\the\\topmargin}\\lthtmltypeout{}%\n" .
6980 "\\lthtmltypeout{latex2htmlLength topskip=\\the\\topskip}\\lthtmltypeout{}%\n" .
6981 "\\lthtmltypeout{latex2htmlLength headheight=\\the\\headheight}\\lthtmltypeout{}%\n" .
6982 "\\lthtmltypeout{latex2htmlLength headsep=\\the\\headsep}\\lthtmltypeout{}%\n" .
6983 "\\lthtmltypeout{latex2htmlLength parskip=\\the\\parskip}\\lthtmltypeout{}%\n" .
6984 "\\lthtmltypeout{latex2htmlLength oddsidemargin=\\the\\oddsidemargin}\\lthtmltypeout{}%\n" .
6985 "\\makeatletter\n" .
6986 "\\if\@twoside\\lthtmltypeout{latex2htmlLength evensidemargin=\\the\\evensidemargin}%\n" .
6987 "\\else\\lthtmltypeout{latex2htmlLength evensidemargin=\\the\\oddsidemargin}\\fi%\n" .
6988 "\\lthtmltypeout{}%\n" .
6989 "\\makeatother\n\\setcounter{page}{1}\n\\onecolumn\n\n% !!! IMAGES START HERE !!!\n\n"
6990 . "$contents\n"
6991 # "\\clearpage\n" .
6992 . "\\end{document}";
6993 }
6995 sub adjust_textwidth {
6996 local($_) = @_;
6997 local($width,$length) = ('','');
6998 if (/a4/) {$width = 595; $length= 842; }
6999 elsif (/letter/) {$width = 612; $length= 792; }
7000 elsif (/legal/) {$width = 612; $length= 1008; }
7001 elsif (/note/) {$width = 540; $length= 720; }
7002 elsif (/b5/) {$width = 501; $length= 709; }
7003 elsif (/a5/) {$width = 421; $length= 595; }
7004 elsif (/a6/) {$width = 297; $length= 421; }
7005 elsif (/a7/) {$width = 210; $length= 297; }
7006 elsif (/a8/) {$width = 148; $length= 210; }
7007 elsif (/a9/) {$width = 105; $length= 148; }
7008 elsif (/a10/) {$width = 74; $length= 105; }
7009 elsif (/b4/) {$width = 709; $length= 1002; }
7010 elsif (/a3/) {$width = 842; $length= 1190; }
7011 elsif (/b3/) {$width = 1002; $length= 1418; }
7012 elsif (/a2/) {$width = 1190; $length= 1684; }
7013 elsif (/b2/) {$width = 1418; $length= 2004; }
7014 elsif (/a1/) {$width = 1684; $length= 2380; }
7015 elsif (/b1/) {$width = 2004; $length= 2836; }
7016 elsif (/a0/) {$width = 2380; $length= 3368; }
7017 elsif (/b0/) {$width = 2836; $length= 4013; }
7018 else {
7019 &write_warnings("\nPAPERSIZE: $_ unknown, using LaTeX's size.");
7020 return();
7021 }
7022 if ($width > 500) { $width = $width - 144; $length = $length - 288; }
7023 elsif ($width > 250) { $width = $width - 72; $length = $length - 144; }
7024 elsif ($width > 125) { $width = $width - 36; $length = $length - 72; }
7025 # "\\setlength{\\oddsidemargin}{0pt}\n" .
7026 # "\\setlength{\\evensidemargin}{0pt}\n" .
7027 # "\\setlength{\\parskip}{0pt}\\setlength{\\topskip}{0pt}\n" .
7028 "\\setlength{\\hoffset}{0pt}\\setlength{\\voffset}{0pt}\n" .
7029 "\\addtolength{\\textheight}{\\footskip}\\setlength{\\footskip}{0pt}\n" .
7030 "\\addtolength{\\textheight}{\\topmargin}\\setlength{\\topmargin}{0pt}\n" .
7031 "\\addtolength{\\textheight}{\\headheight}\\setlength{\\headheight}{0pt}\n" .
7032 "\\addtolength{\\textheight}{\\headsep}\\setlength{\\headsep}{0pt}\n" .
7033 "\\setlength{\\textwidth}{${width}pt}\n"
7034 . (($length > 500) ? "\\setlength{\\textheight}{${length}pt}\n" : '')
7035 }
7037 # Given the depth of the current sectioning declaration and the current
7038 # section numbers it returns the new section numbers.
7039 # It increments the $depth-ieth element of the @curr_sec_id list and
7040 # 0's the elements after the $depth-ieth element.
7041 sub new_level {
7042 local($depth, @curr_sec_id) = @_;
7043 $depth = $section_commands{$outermost_level} unless $depth;
7044 local($i) = 0;
7045 grep( do { if ($i == $depth) {$_++ ;}
7046 elsif ($i > $depth) {$_ = 0 ;};
7047 $i++;
7048 0;
7049 },
7050 @curr_sec_id);
7051 @curr_sec_id;
7052 }
7054 sub make_head_and_body {
7055 local($title,$body,$before_body) = @_;
7056 local($DTDcomment) = '';
7057 local($version,$isolanguage) = ($HTML_VERSION, 'EN');
7058 local(%isolanguages) = ( 'english', 'EN' , 'USenglish', 'EN-US'
7059 , 'original', 'EN' , 'german' , 'DE'
7060 , 'austrian', 'DE-AT', 'french' , 'FR'
7061 , 'spanish', 'ES'
7062 , %isolanguages );
7063 # $isolanguage = $isolanguages{$default_language}; # DTD is in EN
7064 $isolanguage = 'EN' unless $isolanguage;
7065 #JCL(jcl-tcl)
7066 # clean title as necessary
7067 # the first words ... is a kludge, but reasonable (or not?)
7068 #RRM: why bother? --- as long as it is pure text.
7069 $title = &purify($title,1);
7070 eval("\$title = ". $default_title ) unless ($title);
7071 # $title = &get_first_words($title, $WORDS_IN_NAVIGATION_PANEL_TITLES);
7073 # allow user-modification of the <TITLE> tag; thanks Dan Young
7074 if (defined &custom_TITLE_hook) {
7075 $title = &custom_TITLE_hook($title, $toc_sec_title);
7076 }
7078 if ($DOCTYPE =~ /\/\/[\w\.]+\s*$/) { # language spec included
7079 $DTDcomment = '<!DOCTYPE HTML PUBLIC "'. $DOCTYPE .'"';
7080 } else {
7081 $DTDcomment = '<!DOCTYPE HTML PUBLIC "'. $DOCTYPE .'//'
7082 . ($ISO_LANGUAGE ? $ISO_LANGUAGE : $isolanguage) . '"'
7083 }
7084 $DTDcomment .= ($PUBLIC_REF ? "\n \"".$PUBLIC_REF.'"' : '' ) . '>'."\n";
7086 $STYLESHEET = $FILE.".css" unless defined($STYLESHEET);
7088 my ($this_charset) = $charset;
7089 if ($USE_UTF) { $charset = $utf8_str; $NO_UTF = ''; }
7090 if (!$charset && $CHARSET) {
7091 $this_charset = $CHARSET;
7092 $this_charset =~ s/_/\-/go;
7093 }
7094 if ($NO_UTF && $charset =~/utf/) {
7095 $this_charset = $PREV_CHARSET||$CHARSET;
7096 $this_charset =~ s/_/\-/go;
7097 }
7099 join("\n", (($DOCTYPE)? $DTDcomment : '' )
7100 ,"<!--Converted with LaTeX2HTML $TEX2HTMLVERSION"
7101 , "original version by: Nikos Drakos, CBLU, University of Leeds"
7102 , "* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan"
7103 , "* with significant contributions from:"
7104 , " Jens Lippmann, Marek Rouchal, Martin Wilck and others"
7105 . " -->\n<HTML>\n<HEAD>\n<TITLE>".$title."</TITLE>"
7106 , &meta_information($title)
7107 , ($CHARSET && $HTML_VERSION ge "2.1" ?
7108 "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=$this_charset\">"
7109 : "" )
7110 , $LATEX2HTML_META
7111 , ($BASE ? "<BASE HREF=\"$BASE\">" : "" )
7112 , $STYLESHEET_CASCADE
7113 , ($STYLESHEET ? "<LINK REL=\"STYLESHEET\" HREF=\"$STYLESHEET\">" : '' )
7114 , $more_links_mark
7115 , "</HEAD>" , ($before_body? $before_body : '')
7116 , "<BODY $body>", '');
7117 }
7120 sub style_sheet {
7121 local($env,$id,$style);
7122 #AXR: don't overwrite existing .css
7123 #MRO: This is supposed to be $FILE.css, no?
7124 #RRM: only by default, others can be specified as well, via $EXTERNAL_STYLESHEET
7125 #return if (-f $EXTERNAL_STYLESHEET);
7126 return if (-r "$FILE.css" && -s _ && !$REFRESH_STYLES );
7128 unless(open(STYLESHEET, ">$FILE.css")) {
7129 print "\nError: Cannot write '$FILE.css': $!\n";
7130 return;
7131 }
7132 if ( -f $EXTERNAL_STYLESHEET ) {
7133 if(open(EXT_STYLES, "<$EXTERNAL_STYLESHEET")) {
7134 while (<EXT_STYLES>) { print STYLESHEET $_; }
7135 close(EXT_STYLES);
7136 } else {
7137 print "\nError: Cannot read '$EXTERNAL_STYLESHEET': $!\n";
7138 }
7139 } else {
7140 print STYLESHEET <<"EOF"
7141 /* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
7142 .MATH { font-family: \"Century Schoolbook\", serif; }
7143 .MATH I { font-family: \"Century Schoolbook\", serif; font-style: italic }
7144 .BOLDMATH { font-family: \"Century Schoolbook\", serif; font-weight: bold }
7146 /* implement both fixed-size and relative sizes */
7147 SMALL.XTINY { font-size : xx-small }
7148 SMALL.TINY { font-size : x-small }
7149 SMALL.SCRIPTSIZE { font-size : smaller }
7150 SMALL.FOOTNOTESIZE { font-size : small }
7151 SMALL.SMALL { }
7152 BIG.LARGE { }
7153 BIG.XLARGE { font-size : large }
7154 BIG.XXLARGE { font-size : x-large }
7155 BIG.HUGE { font-size : larger }
7156 BIG.XHUGE { font-size : xx-large }
7158 /* heading styles */
7159 H1 { }
7160 H2 { }
7161 H3 { }
7162 H4 { }
7163 H5 { }
7165 /* mathematics styles */
7166 DIV.displaymath { } /* math displays */
7167 TD.eqno { } /* equation-number cells */
7170 /* document-specific styles come next */
7171 EOF
7172 }
7173 print "\n *** Adding document-specific styles *** ";
7174 while (($env,$style) = each %env_style) {
7175 if ($env =~ /\./) {
7176 $env =~ s/\.$//;
7177 print STYLESHEET "$env\t\t{ $style }\n";
7178 } elsif ($env =~ /inline|^(text|math)?((tt|rm|sf)(family)?|(up|it|sl|sc)(shape)?|(bf|md)(series)?|normal(font)?)$/) {
7179 print STYLESHEET "SPAN.$env\t\t{ $style }\n";
7180 } elsif ($env =~ /\./) {
7181 print STYLESHEET "$env\t\t{ $style }\n";
7182 } elsif ($env =~ /^(preform|\w*[Vv]erbatim(star)?)$/) {
7183 print STYLESHEET "PRE.$env\t\t{ $style }\n";
7184 } elsif ($env =~ /figure|table|tabular|equation|$array_env_rx/) {
7185 print STYLESHEET "TABLE.$env\t\t{ $style }\n";
7186 } else {
7187 print STYLESHEET "DIV.$env\t\t{ $style }\n";
7188 }
7189 }
7190 while (($env,$style) = each %txt_style) {
7191 print STYLESHEET "SPAN.$env\t\t{ $style }\n";
7192 }
7193 while (($env,$style) = each %img_style) {
7194 print STYLESHEET "IMG.$env\t\t{ $style }\n";
7195 }
7197 my ($style);
7198 foreach $id (sort(keys %styleID)) {
7199 $style = $styleID{$id};
7200 $style =~ s/font-(color)/$1/;
7201 print STYLESHEET "\#$id\t\t{ $style }\n"
7202 if ($styleID{$id} ne '');
7203 }
7204 close(STYLESHEET);
7205 }
7207 sub clear_styleID {
7208 return unless ($USING_STYLES);
7209 local($env_id,$id) = ("grp", @_);
7210 undef $styleID{$env_id} if ($id =~ /^\d+$/);
7211 }
7213 sub make_address {
7214 local($addr) = &make_real_address(@_);
7215 $addr .= "\n</BODY>\n</HTML>\n";
7216 &lowercase_tags($addr) if $LOWER_CASE_TAGS;
7217 $addr;
7218 }
7220 sub make_real_address {
7221 local($addr) = $ADDRESS;
7222 if ((defined &custom_address)&&($addr)) {
7223 &custom_address($addr)
7224 } elsif ($addr) {
7225 "<ADDRESS>\n$addr\n</ADDRESS>";
7226 } else { '' }
7227 }
7229 sub purify_caption {
7230 local($_) = @_;
7231 local($text) = &recover_image_code($_);
7232 $text =~ s/\\protect|ALT\=|%EQNO:\d+//g;
7233 $text =~ s/[\\\#\'\"\`]//g;
7234 $text;
7235 }
7237 sub recover_image_code {
7238 local($key) = @_;
7239 local($text) = $img_params{$key};
7240 if (!$text) {
7241 if ($text = $id_map{$key}) {
7242 if ($orig_name_map{$text}) {
7243 $text = $img_params{$orig_name_map{$text}}
7244 }
7245 } elsif ($cached_env_img{$key}) {
7246 $text = $img_params{$cached_env_img{$key}};
7247 }
7248 if ($text =~ /\#*ALT="([^"]+)"(>|#)/s) { $text = $1 }
7249 }
7250 $text =~ s/\\protect|%EQNO:\d+//g;
7251 $text =~ s/&(gt|lt|amp|quot);/&special_html_inv($1)/eg;
7252 $text;
7253 }
7255 sub encode_title {
7256 local($_) = @_;
7257 $_ = &encode($_);
7258 while (/(<[^<>]*>)/o) {s/$1//g}; # Remove HTML tags
7259 s/#[^#]*#//g; # Remove #-delimited markers
7260 $_;
7261 }
7263 # Encodes the contents of enviroments that are passed to latex. The code
7264 # is then used as key to a hash table pointing to the URL of the resulting
7265 # picture.
7266 sub encode {
7267 local($_) = @_;
7268 # Remove invocation-specific stuff
7269 1 while(s/\\(begin|end)\s*(($O|$OP)\d+($C|$CP))?|{?tex2html_(wrap|nowrap|deferred|)(_\w+)?}?(\2)?//go);
7270 $_ = &revert_to_raw_tex($_);
7271 s/\\protect//g; # remove redundant \protect macros
7272 #$_ = pack("u*", $_); # uuencode
7273 s/\\\$/dollar/g; # replace funnies, may cause problems in a hash key
7274 s/\//slash/g; # replace funnies, may cause problems in a hash key
7275 s/\$|\/|\\//g; # remove funnies, may cause problems in a hash key
7276 s/\s*|\n//g; # Remove spaces and newlines
7277 s/^(.{80}).*(.{80})$/$1$2/; # truncate to avoid DBM problems
7278 $_;
7279 }
7282 ##################### Hypertext Section Links ########################
7283 sub post_process {
7284 # Put hyperlinks between sections, add HTML headers and addresses,
7285 # do cross references and citations.
7286 # Uses the %section_info array created in sub translate.
7287 # Binds the global variables
7288 # $PREVIOUS, $PREVIOUS_TITLE
7289 # $NEXT, $NEXT_TITLE
7290 # $UP, $UP_TITLE
7291 # $CONTENTS, $CONTENTS_TITLE
7292 # $INDEX, $INDEX_TITLE
7293 # $NEXT_GROUP, $NEXT_GROUP_TITLE
7294 # $PREVIOUS_GROUP, $PREVIOUS_GROUP_TITLE
7295 # Converting to and from lists and strings is very inefficient.
7296 # Maybe proper lists of lists should be used (or wait for Perl5?)
7297 # JKR: Now using top_navigation and bot_navigation instead of navigation
7298 local($_, $key, $depth, $file, $title, $header, @link, @old_link,
7299 $top_navigation, $bot_navigation, @keys,
7300 @tmp_keys, $flag, $child_links, $body, $more_links);
7302 @tmp_keys = @keys = sort numerically keys %section_info;
7303 print "\nDoing section links ...";
7304 while (@tmp_keys) {
7305 $key = shift @tmp_keys;
7306 next if ($MULTIPLE_FILES &&!($key =~ /^$THIS_FILE/));
7307 print ".";
7308 $more_links = "";
7309 ($depth, $file, $title, $body) = split($delim,$section_info{$key});
7310 print STDOUT "\n$key $file $title $body" if ($VERBOSITY > 3);
7311 next if ($body =~ /external/);
7312 $PREVIOUS = $PREVIOUS_TITLE = $NEXT = $NEXT_TITLE = $UP = $UP_TITLE
7313 = $CONTENTS = $CONTENTS_TITLE = $INDEX = $INDEX_TITLE
7314 = $NEXT_GROUP = $NEXT_GROUP_TITLE
7315 = $PREVIOUS_GROUP = $PREVIOUS_GROUP_TITLE
7316 = $_ = $top_navigation = $bot_navigation = undef;
7317 &add_link_tag('previous',$file);
7318 @link = split(' ',$key);
7319 ($PREVIOUS, $PREVIOUS_TITLE) =
7320 &add_link($previous_page_visible_mark,$file,@old_link);
7321 @old_link = @link;
7322 unless ($done{$file}) {
7323 ++$link[$depth];
7324 # if ($MULTIPLE_FILES && !$depth && $multiple_toc ) {
7325 # local($save_depth) = $link[$depth];
7326 # $link[$depth] = 1;
7327 # ($NEXT_GROUP, $NEXT_GROUP_TITLE) =
7328 # &add_link($next_visible_mark, $file, @link);
7329 # &add_link_tag('next', $file, @link);
7330 # $link[$depth] = $save_depth;
7331 # } else {
7332 ($NEXT_GROUP, $NEXT_GROUP_TITLE) =
7333 &add_link($next_visible_mark, $file, @link);
7334 &add_link_tag('next', $file, @link);
7335 # }
7337 $link[$depth]--;$link[$depth]--;
7338 if ($MULTIPLE_FILES && !$depth ) {
7339 } else {
7340 ($PREVIOUS_GROUP, $PREVIOUS_GROUP_TITLE) =
7341 &add_link($previous_visible_mark, $file,@link);
7342 &add_link_tag('previous', $file,@link);
7343 }
7345 $link[$depth] = 0;
7346 ($UP, $UP_TITLE) =
7347 &add_link($up_visible_mark, $file, @link);
7348 &add_link_tag('up', $file, @link);
7350 if ($CONTENTS_IN_NAVIGATION) {
7351 ($CONTENTS, $CONTENTS_LINK) =
7352 &add_special_link($contents_visible_mark, $tocfile, $file);
7353 &add_link_tag('contents', $file, $delim.$tocfile);
7354 }
7356 if ($INDEX_IN_NAVIGATION) {
7357 ($INDEX, $INDEX_LINK) =
7358 &add_special_link($index_visible_mark, $idxfile, $file);
7359 &add_link_tag('index', $file, $delim.$idxfile,);
7360 }
7362 @link = split(' ',$tmp_keys[0]);
7363 # the required `next' link may be several sub-sections along
7364 local($nextdepth,$nextfile,$nextkey,$nexttitle,$nextbody)=
7365 ($depth,$file,$key,'','');
7366 $nextkey = shift @tmp_keys;
7367 ($nextdepth, $nextfile,$nexttitle,$nextbody) = split($delim,$section_info{$nextkey});
7368 if (($nextdepth<$MAX_SPLIT_DEPTH)&&(!($nextbody=~/external/))) {
7369 ($NEXT, $NEXT_TITLE) =
7370 &add_link($next_page_visible_mark, $file, @link);
7371 &add_link_tag('next', $file, @link);
7372 } else {
7373 ($NEXT, $NEXT_TITLE) = ('','');
7374 $nextfile = $file;
7375 }
7376 if ((!$NEXT || $NEXT =~ /next_page_inactive_visible_mark/)&&(@tmp_keys)) {
7377 # the required `next' link may be several sub-sections along
7378 while ((@tmp_keys)&&(($MAX_SPLIT_DEPTH < $nextdepth+1)||($nextfile eq $file))) {
7379 $nextkey = shift @tmp_keys;
7380 ($nextdepth, $nextfile,$nexttitle,$nextbody) = split($delim,$section_info{$nextkey});
7381 if ($nextbody =~ /external/) {
7382 $nextfile = $file;
7383 next;
7384 };
7385 print ",";
7386 print STDOUT "\n $nextkey" if ($VERBOSITY > 3);
7387 }
7388 @link = split(' ',$nextkey);
7389 if (($nextkey)&&($nextdepth<$MAX_SPLIT_DEPTH)) {
7390 ($NEXT, $NEXT_TITLE) =
7391 &add_link($next_page_visible_mark, $file, @link);
7392 &add_link_tag('next', $file, @link);
7393 } else {
7394 ($NEXT, $NEXT_TITLE) = ($NEXT_GROUP, $NEXT_GROUP_TITLE);
7395 $NEXT =~ s/next_page_(inactive_)?visible_mark/next_page_$1visible_mark/;
7396 ($PREVIOUS, $PREVIOUS_TITLE) = ($PREVIOUS_GROUP, $PREVIOUS_GROUP_TITLE);
7397 $PREVIOUS =~ s/previous_(inactive_)?visible_mark/previous_page_$1visible_mark/;
7398 }
7399 }
7400 unshift (@tmp_keys,$nextkey) if ($nextkey);
7401 #
7402 $top_navigation = (defined(&top_navigation_panel) ?
7403 &top_navigation_panel : &navigation_panel)
7404 unless $NO_NAVIGATION;
7405 $bot_navigation = (defined(&bot_navigation_panel) ?
7406 &bot_navigation_panel : &navigation_panel)
7407 unless $NO_NAVIGATION;
7408 local($end_navigation) = "\n<!--End of Navigation Panel-->\n";
7409 if ($USING_STYLES) {
7410 $top_navigation = "\n".'<DIV CLASS="navigation">' . $top_navigation
7411 if $top_navigation;
7412 $bot_navigation = "\n".'<DIV CLASS="navigation">' . $bot_navigation
7413 if $bot_navigation;
7414 $end_navigation = '</DIV>' . $end_navigation;
7415 $env_style{'navigation'} = " ";
7416 }
7418 $header = &make_head_and_body($title, $body);
7419 $header = join('', $header, $top_navigation, $end_navigation) if ($top_navigation);
7421 local($this_file) = $file;
7422 if ($MULTIPLE_FILES && $ROOTED) {
7423 if ($this_file =~ /\Q$dd\E([^$dd$dd]+)$/) { $this_file = $1 }
7424 }
7425 &slurp_input($this_file);
7426 open(OUTFILE, ">$this_file")
7427 || die "\nError: Cannot write file '$this_file': $!\n";
7429 if (($INDEX) && ($SHORT_INDEX) && ($SEGMENT eq 1)) {
7430 &make_index_segment($title,$file); }
7432 local($child_star,$child_links);
7433 local($CURRENT_FILE) = $this_file; # ensure $CURRENT_FILE is set correctly
7434 if (/$childlinks_on_mark\#(\d)\#/) { $child_star = $1 }
7435 $child_links = &add_child_links('',$file, $depth, $child_star,$key, @keys)
7436 unless (/$childlinks_null_mark\#(\d)\#/);
7437 if (($child_links)&&(!/$childlinks_mark/)&&($MAX_SPLIT_DEPTH > 1)) {
7438 if ($depth < $MAX_SPLIT_DEPTH -1) {
7439 $_ = join('', $header, $_, &child_line(), $childlinks_mark, "\#0\#" );
7440 } else {
7441 $_ = join('', $header, "\n$childlinks_mark\#0\#", &upper_child_line(), $_ );
7442 }
7443 } else {
7444 $_ = join('', $header, $_ );
7445 }
7446 $flag = (($BOTTOM_NAVIGATION || &auto_navigation) && $bot_navigation);
7447 $_ .= $bot_navigation . $end_navigation if ($flag &&($bot_navigation));
7448 $_ .= &child_line() unless $flag;
7449 print STDOUT "\n *** replace markers *** " if ($VERBOSITY > 1);
7450 &replace_markers;
7451 print STDOUT "\n *** post-post-process *** " if ($VERBOSITY > 1);
7452 &post_post_process if (defined &post_post_process);
7453 &adjust_encoding;
7454 print OUTFILE $_;
7455 print OUTFILE &make_address;
7456 close OUTFILE;
7457 $done{$file}++;
7458 }
7459 }
7460 &post_process_footnotes if ($footfile);
7461 }
7463 sub adjust_encoding {
7464 &convert_to_utf8($_) if ($USE_UTF);
7465 &lowercase_tags($_) if $LOWER_CASE_TAGS;
7466 }
7468 sub post_replace_markers {
7469 # MRO: replaced $* with /m
7470 # clean up starts and ends of P, BR and DIV tags
7471 s/(<\/?(P|BR|DIV)>)\s*(\w)/$1\n$3/gom unless ($file eq $citefile);
7472 s/([^\s])(<(BR|DIV))/$1\n$2/gom unless ($file eq $citefile);
7473 local($keep,$after);
7475 # anchor images when otherwise there is an invisible-anchor
7476 # s/(<A[^>]*>)\&\#160;<\/A>\s?(<(P|DIV)[^>]*>)\s*(<IMG[^>]*>)\s*(<\/(P|DIV)>)/
7477 s/(<A[^>]*>)($anchor_mark|$anchor_invisible_mark)<\/A>\s?(<(P|DIV)[^>]*>)\s*(<IMG[^>]*>)\s*(<\/(P|DIV)>)/
7478 do{ $keep="$3$1$5<\/A>";
7479 $after = $6;
7480 join('',$keep, &after_punct_break($after), $after);
7481 } /egom;
7483 # absorb named anchor (e.g. from index-entry) into preceding or following anchor
7484 # s/(<A NAME=\"[^\"]+\")>\ <\/A>\s*\b?<A( HREF=\"[^\"]+\">)/$1$2/gom;
7485 # s/(<A HREF=\"[^\"]+\")(>\s*\b?([^<]+|<([^>\/]+|\/[^>A]+)>\s*)*<\/A>)\s*\b?<A( NAME=\"[^\"]+\")>\ <\/A>/$1$5$2/gom;
7487 # clean up empty table cells
7488 s/(<TD[^>]*>)\s*(<\/TD>)/<TD>$2/gom;
7490 # clean up list items (only desirable in the bibliography ?)
7491 # s/\n<P>(<DT[^>]*>)/\n<P><\/P>\n$1/gom;
7493 # remove blank lines and comment-markers
7494 # s/\n\n/\n/g; # no, cause this kills intended ones in verbatims
7495 s/$comment_mark(\d+\n?)?//gm;
7496 s/\"/"/gm; # replace " entities
7498 # italic \LaTeX looks bad
7499 s:<(I|EM)>(($Laname|$AmSname)?$TeXname)</\1>:$2:gm;
7500 }
7502 sub lowercase_tags {
7503 # MRO: modified to use $_[0]
7504 # local(*stream) = @_;
7505 my ($tags,$attribs);
7506 $_[0] =~ s!<(/?\w+)( [^>]*)?>!
7507 $tags = $1; $attribs = $2;
7508 $attribs =~ s/ ([\w\d-]+)(=| |$)/' '.lc($1).$2/eg;
7509 join('', '<', lc($tags) , $attribs , '>')!eg;
7510 }
7512 sub after_punct_break {
7513 # MRO: modified to use $_[0]
7514 # local(*stream) = @_;
7515 # $stream =~ s/^([ \t]*)([,;\.\)\!\"\'\?])[ \t]*(\n)?/(($2)? "$2" : "$1")."\n"/em;
7516 # $stream;
7517 $_[0] =~ s/^([ \t]*)([,;\.\)\!\"\'\?\>]|\>)[ \t]*(\n)?//em;
7518 ($2 ? $2 : $1)."\n";
7519 }
7521 sub make_index_segment {
7522 local($title,$file)= @_ ;
7523 #JCL(jcl-tcl)
7524 # s/<[^>]*>//g;
7525 #
7526 $index_segment{$PREFIX} = "$title";
7527 if (!($ref_files{"segment"."$PREFIX"} eq "$file")) {
7528 $ref_files{"segment"."$PREFIX"} = "$file";
7529 $changed = 1
7530 }
7531 $SEGMENT = 2;
7532 }
7535 sub add_link {
7536 # Returns a pair (iconic link, textual link)
7537 local($icon, $current_file, @link) = @_;
7538 local($dummy, $file, $title, $lbody) = split($delim,$section_info{join(' ',@link)});
7539 if ($lbody =~ /external/) { return ('','') };
7541 # local($dummy, $file, $title) = split($delim,$toc_section_info{join(' ',@link)});
7543 if ($MULTIPLE_FILES && $ROOTED && $file) {
7544 if (!($DESTDIR =~ /\Q$FIXEDDIR\E[$dd$dd]?$/)) { $file = "..$dd$file" }
7545 }
7546 # if ($title && ($file ne $current_file || $icon ne $up_visible_mark)) {
7547 if ($title && ($file ne $current_file)) {
7548 #RRM: allow user-customisation of the link-text; thanks Dan Young
7549 if (defined &custom_link_hook ) {
7550 $title = &custom_link_hook($title,$toc_section_info{join(' ',@link)});
7551 } else {
7552 $title = &purify($title);
7553 $title = &get_first_words($title, $WORDS_IN_NAVIGATION_PANEL_TITLES);
7554 }
7555 return ("\n".&make_href($file, $icon), &make_href($file, "$title"))
7556 }
7557 # elsif ($icon eq $up_visible_mark && $file eq $current_file && $EXTERNAL_UP_LINK) {
7558 elsif ($icon eq $up_visible_mark && $EXTERNAL_UP_LINK) {
7559 return ("\n".&make_href($EXTERNAL_UP_LINK, $icon),
7560 &make_href($EXTERNAL_UP_LINK, "$EXTERNAL_UP_TITLE"))
7561 }
7562 elsif (($icon eq $previous_visible_mark || $icon eq $previous_page_visible_mark)
7563 && $EXTERNAL_PREV_LINK && $EXTERNAL_PREV_TITLE) {
7564 return ("\n".&make_href($EXTERNAL_PREV_LINK, $icon),
7565 &make_href($EXTERNAL_PREV_LINK, "$EXTERNAL_PREV_TITLE"))
7566 }
7567 elsif (($icon eq $next_visible_mark || $icon eq $next_page_visible_mark)
7568 && $EXTERNAL_DOWN_LINK && $EXTERNAL_DOWN_TITLE) {
7569 return ("\n".&make_href($EXTERNAL_DOWN_LINK, $icon),
7570 &make_href($EXTERNAL_DOWN_LINK, "$EXTERNAL_DOWN_TITLE"))
7571 }
7572 (&inactive_img($icon), "");
7573 }
7575 sub add_special_link { &add_real_special_link(@_) }
7576 sub add_real_special_link {
7577 local($icon, $file, $current_file) = @_;
7578 local($text);
7579 if ($icon eq $contents_visible_mark) { $text = $toc_title }
7580 elsif ($icon eq $index_visible_mark) { $text = $idx_title }
7581 elsif ($icon eq $biblio_visible_mark) { $text = $bib_title }
7582 (($file && ($file ne $current_file)) ?
7583 ("\n" . &make_href($file, $icon),
7584 ($text ? " ". &make_href($file, $text) : undef))
7585 : ( undef, undef ))
7586 }
7588 #RRM: add <LINK ...> tag to the HTML head.
7589 # suggested by Marcus Hennecke
7590 #
7591 sub add_link_tag {
7592 local($rel, $currentfile, @link ) = @_;
7593 # local($dummy, $file, $title) = split($delim,$toc_section_info{join(' ',@link)});
7594 local($dummy, $file, $title) = split($delim,$section_info{join(' ',@link)});
7595 ($dummy, $file, $title) = split($delim,$toc_section_info{join(' ',@link)})
7596 unless ($title);
7598 if ($MULTIPLE_FILES && $ROOTED && $file) {
7599 if (!($DESTDIR =~ /\Q$FIXEDDIR\E[$dd$dd]?$/)) { $file = "..$dd$file" }
7600 }
7601 if ($file && !($file eq $currentfile) && (!$NO_NAVIGATION)) {
7602 #RRM: allow user-customisation of the REL attribute
7603 if (defined &custom_REL_hook ) {
7604 $rel = &custom_REL_hook($rel,$toc_section_info{join(' ',@link)});
7605 }
7606 $more_links .= "\n<LINK REL=\"$rel\" HREF=\"$file\">";
7607 }
7608 }
7610 sub remove_markers {
7611 # modifies $_
7612 s/$lof_mark//go;
7613 s/$lot_mark//go;
7614 &remove_bbl_marks;
7615 s/$toc_mark//go;
7616 s/$idx_mark//go;
7617 &remove_cross_ref_marks;
7618 &remove_external_ref_marks;
7619 &remove_cite_marks;
7620 &remove_file_marks;
7621 # sensitive markers
7622 &remove_image_marks;
7623 &remove_icon_marks;
7624 &remove_verbatim_marks;
7625 &remove_verb_marks;
7626 &remove_child_marks;
7627 # uncaught markers
7628 s/$percent_mark/%/go;
7629 s/$ampersand_mark/\&/go;
7630 s/$comment_mark\s*(\d+\n?)?//sgo;
7631 s/$caption_mark//go;
7632 s/<tex2html[^>]*>//g;
7633 s/$OP\d+\$CP//g;
7634 $_;
7635 }
7637 sub replace_markers {
7638 &find_quote_ligatures;
7639 &replace_general_markers;
7640 &text_cleanup;
7641 # Must NOT clean the ~'s out of the navigation icons (in panel or text),
7642 # and must not interfere with verbatim-like environments
7643 &replace_sensitive_markers;
7644 &replace_init_file_mark if (/$init_file_mark/);
7645 &replace_file_marks;
7646 &post_replace_markers;
7647 }
7649 sub replace_general_markers {
7650 if (defined &replace_infopage_hook) {&replace_infopage_hook if (/$info_page_mark/);}
7651 else { &replace_infopage if (/$info_page_mark/); }
7652 if (defined &add_idx_hook) {&add_idx_hook if (/$idx_mark/);}
7653 else {&add_idx if (/$idx_mark/);}
7655 if ($segment_figure_captions) {
7656 # s/$lof_mark/<UL>$segment_figure_captions<\/UL>/o
7657 # } else { s/$lof_mark/<UL>$figure_captions<\/UL>/o }
7658 s/$lof_mark/$segment_figure_captions/o
7659 } else { s/$lof_mark/$figure_captions/o }
7660 if ($segment_table_captions) {
7661 # s/$lot_mark/<UL>$segment_table_captions<\/UL>/o
7662 # } else { s/$lot_mark/<UL>$table_captions<\/UL>/o }
7663 s/$lot_mark/$segment_table_captions/o
7664 } else { s/$lot_mark/$table_captions/o }
7665 &replace_morelinks();
7666 if (defined &replace_citations_hook) {&replace_citations_hook if /$bbl_mark/;}
7667 else {&replace_bbl_marks if /$bbl_mark/;}
7668 if (defined &add_toc_hook) {&add_toc_hook if (/$toc_mark/);}
7669 else {&add_toc if (/$toc_mark/);}
7670 if (defined &add_childs_hook) {&add_childs_hook if (/$childlinks_on_mark/);}
7671 else {&add_childlinks if (/$childlinks_on_mark/);}
7672 &remove_child_marks;
7674 if (defined &replace_cross_references_hook) {&replace_cross_references_hook;}
7675 else {&replace_cross_ref_marks if /$cross_ref_mark||$cross_ref_visible_mark/;}
7676 if (defined &replace_external_references_hook) {&replace_external_references_hook;}
7677 else {&replace_external_ref_marks if /$external_ref_mark/;}
7678 if (defined &replace_cite_references_hook) {&replace_cite_references_hook;}
7679 else { &replace_cite_marks if /$cite_mark/; }
7680 if (defined &replace_user_references) {
7681 &replace_user_references if /$user_ref_mark/; }
7682 }
7684 sub replace_sensitive_markers {
7685 if (defined &replace_images_hook) {&replace_images_hook;}
7686 else {&replace_image_marks if /$image_mark/;}
7687 if (defined &replace_icons_hook) {&replace_icons_hook;}
7688 else {&replace_icon_marks if /$icon_mark_rx/;}
7689 if (defined &replace_verbatim_hook) {&replace_verbatim_hook;}
7690 else {&replace_verbatim_marks if /$verbatim_mark/;}
7691 if (defined &replace_verb_hook) {&replace_verb_hook;}
7692 else {&replace_verb_marks if /$verb_mark|$verbstar_mark/;}
7693 s/;SPMdollar;/\$/g; s/;SPMtilde;/\~/g; s/;SPMpct;/\%/g;
7694 s/;SPM/\&/go;
7695 s/$percent_mark/%/go;
7696 s/$ampersand_mark/\&/go;
7697 #JKR: Turn encoded ~ back to normal
7698 s/~/~/go;
7699 }
7701 sub find_quote_ligatures {
7702 my $ent;
7704 # guillemets, governed by $NO_FRENCH_QUOTES
7705 do {
7706 $ent = &iso_map('laquo', "", 1);
7707 if ($NO_UTF && !$USE_UTF && $ent=~/\&\#(\d+);/) {
7708 $ent='' if ($1 > 255);
7709 }
7710 s/((\&|;SPM)lt;){2}/$ent/ogs if $ent;
7711 $ent = &iso_map('raquo', "", 1) if ($ent);
7712 s/((\&|;SPM)gt;){2}/$ent/ogs if $ent;
7713 # single guillemot chars cannot be easily implemented this way
7714 # finding an approp regexp is work for the future
7715 } unless ($NO_FRENCH_QUOTES);
7717 $ent = &iso_map("gg", "", 1);
7718 s/;SPMgg;/($ent ? $ent : '>>')/eg unless ($USE_NAMED_ENTITIES);
7719 $ent = &iso_map("ll", "", 1);
7720 s/;SPMll;/($ent ? $ent : '<<')/eg unless ($USE_NAMED_ENTITIES);
7722 my $ldquo, $rdquo;
7723 # "curly" quotes, governed by $USE_CURLY_QUOTES.
7724 do {
7725 $ldquo = &iso_map("ldquo", "", 1);
7726 if ($NO_UTF && !$USE_UTF && $ldquo =~ /\&\#(\d+);/) {
7727 $ldquo = '' if ($1 > 255);
7728 }
7729 s/``/$ldquo/ogs if ($ldquo);
7730 $rdquo = &iso_map("rdquo", "", 1) if ($ldquo);
7731 s/''/$rdquo/ogs if ($rdquo);
7733 # single curly quotes cannot be easily implemented this way
7734 # finding an approp regexp is work for the future
7735 } if ($USE_CURLY_QUOTES);
7737 # "german" quotes, governed by $NO_GERMAN_QUOTES.
7738 do {
7739 $ent = &iso_map('bdquo', "", 1);
7740 if ($NO_UTF && !$USE_UTF && $ent =~ /\&\#(\d+);/) {
7741 $ent = '' if ($1 > 255);
7742 }
7743 s/,,/$ent/eg if $ent;
7745 # closing upper quotes are not properly displayed in browsers
7746 s/($ent[\w\s\&\#;']+)$ldquo/$1``/og
7747 if ($USE_CURLY_QUOTES && $ldquo && $ent);
7748 } unless ($NO_GERMAN_QUOTES);
7749 }
7751 sub add_childlinks {
7752 local($before, $after, $star);
7753 while (/$childlinks_on_mark\#(\d)\#/) {
7754 $star = $1;
7755 $before = $`;
7756 $after = $';
7757 $before =~ s/\n\s*$//;
7758 $_ = join('', $before, "\n", $child_links, $after);
7759 }
7760 }
7762 sub replace_infopage {
7763 local($INFO)=1 if !(defined $INFO);
7764 if ($INFO == 1) {
7765 local($title);
7766 if ((defined &do_cmd_infopagename)||$new_command{'infopagename'}) {
7767 local($br_id)=++$global{'max_id'};
7768 $title = &translate_environments("$O$br_id$C\\infopagename$O$br_id$C");
7769 } else { $title = $info_title }
7770 if ($MAX_SPLIT_DEPTH <= $section_commands{$outermost_level}) {
7771 $_ =~ s/(<HR[^>]*>\s*)?$info_title_mark/
7772 ($1? $1 : "\n<HR>")."\n<H2>$title<\/H2>"/eog;
7773 } else {
7774 $_ =~ s/$info_title_mark/"\n<H2>$title<\/H2>"/eog;
7775 }
7776 }
7777 while (/$info_page_mark/o) {
7778 $_ = join('', $`, &do_cmd_textohtmlinfopage, $');
7779 }
7780 }
7782 sub replace_init_file_mark {
7783 local($init_file, $init_contents, $info_line)=($INIT_FILE,'','');
7784 if (-f $init_file) {
7785 } elsif (-f "$orig_cwd$dd$init_file") {
7786 $init_file = $orig_cwd.$dd.$init_file;
7787 } else {
7788 s/$init_file_mark//g;
7789 return();
7790 }
7791 if(open(INIT, "<$init_file")) {
7792 foreach $info_line (<INIT>) {
7793 $info_line =~ s/[<>"&]/'&'.$html_special_entities{$&}.';'/eg;
7794 $init_contents .= $info_line;
7795 }
7796 close INIT;
7797 } else {
7798 print "\nError: Cannot read '$init_file': $!\n";
7799 }
7800 s/$init_file_mark/\n<BLOCKQUOTE><PRE>\n$init_contents\n<\/PRE><\/BLOCKQUOTE>\n/g;
7801 }
7803 sub replace_morelinks {
7804 $_ =~ s/$more_links_mark/$more_links/e;
7805 }
7807 # This code is extremely inefficient. At least the subtrees should be
7808 # filtered according to $MAX_LINK_DEPTH before going into the
7809 # inner loops.
7810 # RRM: revamped parts, for $TOC_STARS, fixing some errors.
7811 #
7812 sub add_child_links { &add_real_child_links(@_) }
7813 sub add_real_child_links {
7814 local($exclude, $base_file, $depth, $star, $current_key, @keys) = @_;
7815 local $min_depth = $section_commands{$outermost_level} - 1;
7816 return ('') if ((!$exclude)&&(!$LEAF_LINKS)&&($depth >= $MAX_SPLIT_DEPTH));
7817 if ((!$depth)&&($outermost_level)) { $depth = $min_depth }
7819 local($_, $child_rx, @subtree, $next, %open, @roottree);
7820 local($first, $what, $pre, $change_key, $list_class);
7821 $childlinks_start = "<!--Table of Child-Links-->";
7822 $childlinks_end = "<!--End of Table of Child-Links-->\n";
7823 $child_rx = $current_key;
7824 $child_rx =~ s/( 0)*$//; # Remove trailing 0's
7825 if ((!$exclude)&&($depth < $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH -1 )
7826 # &&($depth >= $MAX_SPLIT_DEPTH-1)) {
7827 &&($depth > $min_depth)) {
7828 if ((defined &do_cmd_childlinksname)||$new_command{'childlinksname'}) {
7829 local($br_id)=++$global{'max_id'};
7830 $what = &translate_environments("$O$br_id$C\\childlinksname$O$br_id$C");
7831 } else {
7832 $what = "<strong>$child_name</strong>";
7833 }
7834 $list_class = ' CLASS="ChildLinks"' if ($USING_STYLES);
7835 $first = "$childlinks_start\n<A NAME=\"CHILD_LINKS\">$what<\/A>\n";
7836 } elsif ($exclude) {
7837 # remove any surrounding braces
7838 $exclude =~ s/^($O|$OP)\d+($C|$CP)|($O|$OP)\d+($C|$CP)$//g;
7839 # Table-of-Contents
7840 $list_class = ' CLASS="TofC"' if ($USING_STYLES);
7841 $childlinks_start = "\n<!--Table of Contents-->\n";
7842 $childlinks_end = "<!--End of Table of Contents-->";
7843 $first = "$childlinks_start";
7844 } else {
7845 $list_class = ' CLASS="ChildLinks"' if ($USING_STYLES);
7846 $first = "$childlinks_start\n"
7847 . ($star ? '':"<A NAME=\"CHILD_LINKS\">$anchor_mark<\/A>\n");
7848 }
7849 my $startlist, $endlist;
7850 $startlist = "<UL$list_class>" unless $CHILD_NOLIST;
7851 $endlist = '</UL>' unless $CHILD_NOLIST;
7852 my $alt_item = '<BR> <BR>'."\n";
7853 my $outer_item = ($CHILD_NOLIST ? $alt_item : '<LI>');
7854 my $inner_item = '<LI>';
7855 my $inner_end = '</UL><BR>';
7857 # collect the relevant keys...
7858 foreach $next (@keys) {
7859 if ($MULTIPLE_FILES && $exclude) {
7860 # ...all but with this document as the root
7861 if ($next =~ /^$THIS_FILE /) {
7862 # # make current document the root
7863 # $change_key = '0 '.$';
7864 push(@roottree,$next);
7865 print "\n$next : m-root" if ($VERBOSITY > 3);
7866 } else {
7867 push(@subtree,$next);
7868 print "\n$next : m-sub" if ($VERBOSITY > 3);
7869 }
7870 } elsif (($next =~ /^$child_rx /)&&($next ne $current_key)) {
7871 # ...which start as $current_key
7872 push(@subtree,$next);
7873 print "\n$next : sub $child_rx" if ($VERBOSITY > 3);
7874 } else {
7875 print "\n$next : out $current_key" if ($VERBOSITY > 3);
7876 }
7877 }
7878 if (@subtree) { @subtree = sort numerically @subtree; }
7879 if (@roottree) {
7880 @roottree = sort numerically @roottree;
7881 @subtree = ( @roottree, @subtree );
7882 }
7883 # @subtree now contains the subtree rooted at the current node
7885 local($countUL); #counter to ensure correct tag matching
7886 my $root_file, $href;
7887 if (@subtree) {
7888 local($next_depth, $file, $title, $sec_title, $star, $ldepth,$this_file, $prev_file);
7889 $ldepth = $depth;
7890 $prev_file = $base_file;
7891 # @subtree = sort numerically @subtree;
7892 foreach $next (@subtree) {
7893 $title = '';
7894 if ($exclude) {
7895 # making TOC
7896 ($next_depth, $file, $sec_title) =
7897 split($delim,$section_info{$next});
7898 ($next_depth, $file, $title, $star) =
7899 split($delim,$toc_section_info{$next});
7900 # use the %section_info title, in case there are images
7901 $title = $sec_title if ($sec_title =~ /image_mark>\#/);
7902 } else {
7903 # making mini-TOC i.e. the child-links tables
7904 $star = '';
7905 ($next_depth, $file, $title) =
7906 split($delim,$section_info{$next});
7907 }
7908 $root_file = $file unless $root_file;
7909 if ($root_file && $root_file =~ /_mn\./) { $root_file=$` };
7910 # remove any surrounding braces
7911 $title =~ s/^($O|$OP)\d+($C|$CP)|($O|$OP)\d+($C|$CP)$//g;
7912 next if ($exclude && $title =~ /^$exclude$/);
7913 if (!$title) {
7914 ($next_depth, $file, $title, $star) =
7915 split($delim,$toc_section_info{$next});
7916 }
7917 $this_file = $file;
7918 $title = "\n".$title if !($title =~/^\n/);
7919 next if ( $exclude &&( # doing Table-of-Contents
7920 ( $TOC_DEPTH &&($next_depth > $TOC_DEPTH)) # and too deep
7921 ||($star && !$TOC_STARS ) )); # or no starred sections
7922 $file = "" if (!$MAX_SPLIT_DEPTH); # Martin Wilck
7923 next if ($exclude && !$MULTIPLE_FILES &&($title =~ /^\s*$exclude\s*$/));
7924 next if (!$exclude && $next_depth > $MAX_LINK_DEPTH + $depth);
7925 print "\n$next :" if ($VERBOSITY > 3);
7926 if ($this_file =~ /^(\Q$prev_file\E|\Q$base_file\E)$/) {
7927 $file .= join('', "#SECTION", split(' ', $next));
7928 } else { $prev_file = $file }
7930 if (!$next_depth && $MULTIPLE_FILES) { ++$next_depth }
7931 local($num_open) = (split('/',%open))[0];
7932 if ((($next_depth > $ldepth)||$first)
7933 && ((split('/',%open))[0] < $MAX_LINK_DEPTH + $depth )
7934 ) {
7935 # start a new <UL> list
7936 if ($first) {
7937 $_ = "$first\n$startlist\n"; $countUL++;
7938 local $i = 1;
7939 while ($i <= $ldepth) {
7940 $open{$i}=0; $i++
7941 }
7942 $first = ''; # include NAME tag first time only
7943 while ($i < $next_depth) {
7944 $open{$i}=1; $i++;
7945 $_ .= ($countUL >1 ? $inner_item : $outer_item)."<UL>\n";
7946 $countUL++;
7947 }
7948 } else {
7949 $_ .= "<UL>\n"; $countUL++;
7950 }
7951 $ldepth = $next_depth;
7952 $open{$ldepth}++;
7953 # append item to this list
7954 print " yes " if ($VERBOSITY > 3);
7955 if (defined &add_frame_child_links) {
7956 $href = &make_href($file,$title);
7957 if ($href =~ s/($root_file)_mn/$1_ct/) {
7958 $href =~ s/(target=")main(")/$1contents$2/i;
7959 };
7960 $_ .= ($countUL >1 ? $inner_item : $outer_item)
7961 . $href . "\n";
7962 } else {
7963 $_ .= ($countUL >1 ? $inner_item : $outer_item)
7964 . &make_href($file,$title) . "\n";
7965 }
7966 }
7967 elsif (($next_depth)&&($next_depth <= $ldepth)
7968 &&((split('/',%open))[0] <= $MAX_LINK_DEPTH + $depth )
7969 ) {
7970 # append item to existing <UL> list
7971 while (($next_depth < $ldepth) && %open ) {
7972 # ...closing-off any nested <UL> lists
7973 if ($open{$ldepth}) {
7974 if (!(defined $open{$next_depth})) {
7975 $open{$next_depth}++;
7976 } else {
7977 $_ .= ($countUL==2 ? $inner_end : '</UL>')."\n";
7978 $countUL--;
7979 }
7980 delete $open{$ldepth};
7981 };
7982 $ldepth--;
7983 }
7984 $ldepth = $next_depth;
7985 print " yes" if ($VERBOSITY > 3);
7986 if (defined &add_frame_child_links) {
7987 $href = &make_href($file,$title);
7988 if ($href =~ s/($root_file)_mn/$1_ct/) {
7989 $href =~ s/(target=")main(")/$1contents$2/i;
7990 };
7991 $_ .= ($countUL >1 ? $inner_item : $outer_item)
7992 . $href . "\n";
7993 } else {
7994 $_ .= ($countUL >1 ? $inner_item : $outer_item)
7995 . &make_href($file,$title) . "\n";
7996 }
7997 } else {
7998 # ignore items that are deeper than $MAX_LINK_DEPTH
7999 print " no" if ($VERBOSITY > 3);
8000 }
8001 }
8003 if (%open) {
8004 # close-off any remaining <UL> lists
8005 $countUL-- if $CHILD_NOLIST;
8006 local $cnt = (split('/',%open))[0];
8007 local $i = $cnt;
8008 while ($i > $depth) {
8009 if ($open{$i}) {
8010 $_ .= '</UL>' if $countUL;
8011 $countUL--;
8012 delete $open{$i};
8013 }
8014 $i--;
8015 }
8016 }
8017 }
8018 # just in case the count is wrong
8019 $countUL-- if ($CHILD_NOLIST && $countUL > 0);
8020 $countUL = '' if ($countUL < 0);
8021 while ($countUL) { $_ .= '</UL>'; $countUL-- }
8022 ($_ ? join('', $_, "\n$childlinks_end") : '');
8023 }
8025 sub child_line {($CHILDLINE) ? "$CHILDLINE" : "<BR>\n<HR>";}
8026 sub upper_child_line { "<HR>\n"; }
8028 sub adjust_root_keys {
8029 return() unless ($MULTIPLE_FILES && $ROOTED);
8030 local($next,$change_key,$current_rx);
8031 local(@keys) = (keys %toc_section_info);
8033 local($current_key) = join(' ',@curr_sec_id);
8034 $current_key =~ /^(\d+ )/;
8035 $current_rx = $1;
8036 return() unless $current_rx;
8038 # alter the keys which start as $current_key
8039 foreach $next (@keys) {
8040 if ($next =~ /^$current_rx/) {
8041 # make current document the root
8042 $change_key = '0 '.$';
8043 $toc_section_info{$change_key} = $toc_section_info{$next};
8044 $section_info{$change_key} = $section_info{$next};
8045 # if (!($next eq $current_key)) {
8046 # $toc_section_info{$next} = $section_info{$next} = '';
8047 # }
8048 }
8049 }
8050 }
8052 sub top_page {
8053 local($file, @navigation_panel) = @_;
8054 # It is the top page if there is a link to itself
8055 join('', @navigation_panel) =~ /$file/;
8056 }
8058 # Sets global variable $AUX_FILE
8059 sub process_aux_file {
8060 local(@exts) = ('aux');
8061 push(@exts, 'lof') if (/\\listoffigures/s);
8062 push(@exts, 'lot') if (/\\listoftables/s);
8063 local($_, $status); # To protect caller from &process_ext_file
8064 $AUX_FILE = 1;
8065 foreach $auxfile (@exts) {
8066 $status = &process_ext_file($auxfile);
8067 if ($auxfile eq "aux" && ! $status) {
8068 print "\nCannot open $FILE.aux $!\n";
8069 &write_warnings("\nThe $FILE.aux file was not found," .
8070 " so sections will not be numbered \nand cross-references "
8071 . "will be shown as icons.\n");
8072 }
8073 }
8074 $AUX_FILE = 0;
8075 }
8077 sub do_cmd_htmlurl {
8078 local($_) = @_;
8079 local($url);
8080 $url = &missing_braces unless (
8081 (s/$next_pair_pr_rx/$br_id=$1;$url=$2;''/e)
8082 ||(s/$next_pair_rx/$br_id=$1;$url=$2;''/e));
8083 $url =~ s/\\(html)?url\s*($O|$OP)([^<]*)\2/$3/;
8084 $url =~ s/\\?~/;SPMtilde;/og;
8085 join('','<TT>', &make_href($url,$url), '</TT>', $_);
8086 }
8087 sub do_cmd_url { &do_cmd_htmlurl(@_) }
8089 sub make_href { &make_real_href(@_) }
8090 sub make_real_href {
8091 local($link, $text) = @_;
8092 $href_name++;
8093 my $htarget = '';
8094 $htarget = ' target="'.$target.'"'
8095 if (($target)&&($HTML_VERSION > 3.2));
8096 #HWS: Nested anchors not allowed.
8097 $text =~ s/<A .*><\/A>//go;
8098 #JKR: ~ is handled different - ~ is turned to ~ later.
8099 #$link =~ s/~/$percent_mark . "7E"/geo;
8100 if ($text eq $link) { $text =~ s/~/~/g; }
8101 $link =~ s/~/~/g;
8102 # catch \url or \htmlurl
8103 $link =~ s/\\(html)?url\s*(($O|$OP)\d+($C|$CP))([^<]*)\2/$5/;
8104 $link =~ s:(<TT>)?<A [^>]*>([^<]*)</A>(</TT>)?(([^<]*)|$):$2$4:;
8105 # this should not be here; else TOC, List of Figs, etc. fail:
8106 # $link =~ s/^\Q$CURRENT_FILE\E(\#)/$1/ unless ($SEGMENT||$SEGMENTED);
8107 $text = &simplify($text);
8108 "<A NAME=\"tex2html$href_name\"$htarget\n HREF=\"$link\">$text</A>";
8109 }
8111 sub make_href_noexpand { # clean
8112 my ($link, $name, $text) = @_;
8113 do {$name = "tex2html". $href_name++} unless $name;
8114 #HWS: Nested anchors not allowed.
8115 $text =~ s/<A .*><\/A>//go;
8116 #JKR: ~ is handled different - ~ is turned to ~ later.
8117 #$link =~ s/~/$percent_mark . "7E"/geo;
8118 if ($text eq $link) { $text =~ s/~/~/g; }
8119 $link =~ s/~/~/g;
8120 # catch \url or \htmlurl
8121 $link =~ s/\\(html)?url\s*(($O|$OP)\d+($C|$CP))([^<]*)\2/$5/;
8122 $link =~ s:(<TT>)?<A [^>]*>([^<]*)</A>(</TT>)?(([^<]*)|$):$2$4:;
8123 "<A NAME=\"$name\"\n HREF=\"$link\">$text</A>";
8124 }
8126 sub make_named_href {
8127 local($name, $link, $text) = @_;
8128 $text =~ s/<A .*><\/A>//go;
8129 $text = &simplify($text);
8130 if ($text eq $link) { $text =~ s/~/~/g; }
8131 $link =~ s/~/~/g;
8132 # catch \url or \htmlurl
8133 $link =~ s/\\(html)?url\s*(($O|$OP)\d+($C|$CP))([^<]*)\2/$5/;
8134 $link =~ s:(<TT>)?<A [^>]*>([^<]*)</A>(</TT>)?(([^<]*)|$):$2$4:;
8135 if (!($name)) {"<A\n HREF=\"$link\">$text</A>";}
8136 elsif ($text =~ /^\w/) {"<A NAME=\"$name\"\n HREF=\"$link\">$text</A>";}
8137 else {"<A NAME=\"$name\"\n HREF=\"$link\">$text</A>";}
8138 }
8140 sub make_section_heading {
8141 local($text, $level, $anchors) = @_;
8142 local($elevel) = $level; $elevel =~ s/^(\w+)\s.*$/$1/;
8143 local($section_tag) = join('', @curr_sec_id);
8144 local($align,$pre_anchors);
8146 # separate any invisible anchors or alignment, if this has not already been done
8147 if (!($anchors)){ ($anchors,$text) = &extract_anchors($text) }
8148 else {
8149 $anchors =~ s/(ALIGN=\"\w*\")/$align = " $1";''/e;
8150 $align = '' if ($HTML_VERSION < 2.2);
8151 $anchors = &translate_commands($anchors) if ($anchors =~ /\\/);
8152 }
8154 # strip off remains of bracketings
8155 $text =~ s/$OP\d+$CP//g;
8156 if (!($text)) {
8157 # anchor to a single `.' only
8158 $text = "<A NAME=\"SECTION$section_tag\">.</A>$anchors\n";
8159 } elsif ($anchors) {
8160 # # put anchors immediately after, except if title is too long
8161 # if ((length($text)<60 )&&(!($align)||($align =~/left/))) {
8162 # $text = "<A NAME=\"SECTION$section_tag\">$text</A>\n" . $anchors;
8163 # ...put anchors preceding the title, on a separate when left-aligned
8164 # } else {
8165 $text = "<A NAME=\"SECTION$section_tag\">$anchor_invisible_mark</A>$anchors"
8166 . (!($align)||($align =~ /left/i ) ? "<BR>" : "") . "\n". $text;
8167 # }
8168 } elsif (!($text =~ /<A[^\w]/io)) {
8169 # no embedded anchors, so anchor it all
8170 $text = "<A NAME=\"SECTION$section_tag\">\n" . $text . "</A>";
8171 } else {
8172 # there are embedded anchors; these cannot be nested
8173 local ($tmp) = $text;
8174 $tmp =~ s/<//o ; # find 1st <
8175 if ($`) { # anchor text before the first <
8176 # $text = "<A NAME=\"SECTION$section_tag\">\n" . $` . "</A>\n<" . $';
8177 $text = "<A NAME=\"SECTION$section_tag\">\n" . $` . "</A>";
8178 $pre_anchors = "<" . $';
8179 if ($pre_anchors =~ /^(<A NAME=\"[^\"]+>${anchor_invisible_mark}<\/A>\s*)+$/) {
8180 $pre_anchors .= "\n"
8181 } else { $text .= $pre_anchors; $pre_anchors = '' }
8182 } else {
8183 # $text starts with a tag
8184 local($after,$tmp) = ($','');
8185 if ( $after =~ /^A[^\w]/i ) {
8186 # it is an anchor already, so need a separate line
8187 $text = "<A NAME=\"SECTION$section_tag\">$anchor_invisible_mark</A><BR>\n$text";
8188 } else {
8189 # Is it a tag enclosing the anchor ?
8190 $after =~ s/^(\w)*[\s|>]/$tmp = $1;''/eo;
8191 if ($after =~ /<A.*<\/$tmp>/) {
8192 # it encloses an anchor, so use anchor_mark + break
8193 $text = "<A NAME=\"SECTION$section_tag\">$anchor_invisible_mark</A><BR>\n$text";
8194 } else {
8195 # take up to the anchor
8196 $text =~ s/^(.*)<A([^\w])/"<A NAME=\"SECTION$section_tag\">$1<A$2"/oe;
8197 }
8198 }
8199 }
8200 }
8201 "$pre_anchors\n<$level$align>$text\n<\/$elevel>";
8202 }
8204 sub do_cmd_captionstar { &process_cmd_caption(1, @_) }
8205 sub do_cmd_caption { &process_cmd_caption('', @_) }
8206 sub process_cmd_caption {
8207 local($noLOTentry, $_) = @_;
8208 local($text,$opt,$br_id, $contents);
8209 local($opt) = &get_next_optional_argument;
8210 $text = &missing_braces unless (
8211 (s/$next_pair_pr_rx/$br_id=$1;$text=$2;''/e)
8212 ||(s/$next_pair_rx/$br_id=$1;$text=$2;''/e));
8214 # put it in $contents, so &extract_captions can find it
8215 local($contents) = join('','\caption', ($opt ? "[$opt]" : '')
8216 , "$O$br_id$C" , $text , "$O$br_id$C");
8218 # $cap_env is set by the surrounding figure/table
8219 &extract_captions($cap_env);
8220 $contents.$_;
8221 }
8223 sub extract_captions {
8224 # Uses and modifies $contents and $cap_anchors, defined in translate_environments
8225 # and modifies $figure_captions, $table_captions, $before and $after
8226 # MRO: no effect! local($env,*cap_width) = @_;
8227 local($env) = @_;
8228 local(%captions, %optional_captions, $key, $caption, $optional_caption,
8229 $item, $type, $list, $extra_list, $number, @tmp, $br_id, $_);
8230 # associate the br_id of the caption with the argument of the caption
8231 $contents =~ s/$caption_rx(\n)?/do {
8232 $key = $9; $caption = $10; $optional_caption = $3;
8233 $key = &filter_caption_key($key) if (defined &filter_caption_key);
8234 $optional_captions{$key} = $optional_caption||$caption;
8235 $captions{$key} = $10; ''}/ego;
8236 # $captions{$9} = $10; $caption_mark }/ego;
8237 $key = $caption = $optional_caption = '';
8239 #catch any \captionwidth settings that may remain
8240 $contents =~ s/$caption_width_rx(\n)?/&translate_commands($&);''/eo;
8242 # $after = join("","<P>",$after) if ($&);
8243 # $before .= "</P>" if ($&);
8244 #JKR: Replaced "Figure" and "Table" with variables (see latex2html.config too).
8245 if ($env eq 'figure') {
8246 if ((defined &do_cmd_figurename)||$new_command{'figurename'}){
8247 $br_id = ++$global{'max_id'};
8248 $type = &translate_environments("$O$br_id$C\\figurename$O$br_id$C")
8249 unless ($noLOFentry);
8250 } else { $type = $fig_name }
8251 $list = "\$figure_captions";
8252 # $extra_list = "\$segment_figure_captions" if ($figure_table_captions);
8253 $extra_list = "\$segment_figure_captions" if ($segment_figure_captions);
8254 }
8255 elsif ($env =~ /table/) {
8256 if ((defined &do_cmd_tablename)||$new_command{'tablename'}) {
8257 $br_id = ++$global{'max_id'};
8258 $type = &translate_environments("$O$br_id$C\\tablename$O$br_id$C")
8259 unless ($noLOTentry);
8260 } else { $type = $tab_name }
8261 $list = "\$table_captions";
8262 $extra_list = "\$segment_table_captions" if ($segment_table_captions);
8263 }
8265 # $captions = "";
8266 $cap_anchors = "";
8267 local($this);
8268 foreach $key (sort {$a <=> $b;} keys %captions){ # Sort numerically
8269 $this = $captions{$key};
8270 $this =~ s/\\label\s*($O\d+$C)[^<]+\1//g; # remove \label commands
8271 local($br_id) = ++$global{'max_id'};
8272 local($open_tags_R) = []; # locally, initially no style
8273 $caption = &translate_commands(
8274 &translate_environments("$O$br_id$C$this$O$br_id$C"));
8276 # same again for the optional caption
8277 $this = $optional_captions{$key};
8278 $this =~ s/\\label\s*($O\d+$C)[^<]+\1//g; # remove \label commands
8279 local($open_tags_R) = []; local($br_id) = ++$global{'max_id'};
8280 $this = &translate_environments("$O$br_id$C$this$O$br_id$C");
8281 $optional_caption = &translate_commands($this);
8283 $cap_anchors .= "<A NAME=\"$key\">$anchor_mark</A>";
8284 $_ = $optional_caption || $caption;
8287 # split at embedded anchor or citation marker
8288 local($pre_anchor,$post_anchor) = ('','');
8289 if (/\s*(<A\W|\#[^#]*\#<tex2html_cite_[^>]*>)/){
8290 $pre_anchor = "$`";
8291 $post_anchor = "$&$'";
8292 $pre_anchor = $anchor_invisible_mark
8293 unless (($pre_anchor)||($SHOW_SECTION_NUMBERS));
8294 } else {
8295 $pre_anchor = "$_";
8296 }
8298 #JCL(jcl-tcl)
8299 ## &text_cleanup;
8300 ## $_ = &encode_title($_);
8301 ## s/ //g; # HWS - LaTeX changes ~ in its .aux files
8302 # $_ = &sanitize($_);
8303 ##
8304 # $_ = &revert_to_raw_tex($_);
8306 #replace image-markers by the image params
8307 s/$image_mark\#([^\#]+)\#/&purify_caption($1)/e;
8309 local($checking_caption, $cap_key) = (1, $_);
8310 $cap_key = &simplify($cap_key);
8311 $cap_key = &sanitize($cap_key);
8312 @tmp = split(/$;/, eval ("\$encoded_$env" . "_number{\$cap_key}"));
8313 $number = shift(@tmp);
8314 $number = "" if ($number eq "-1");
8316 if (!$number) {
8317 $cap_key = &revert_to_raw_tex($cap_key);
8318 @tmp = split(/$;/
8319 , eval ("\$encoded_$env" . "_number{\$cap_key}"));
8320 $number = shift(@tmp);
8321 $number = "" if ($number eq "-1");
8322 }
8324 #resolve any embedded cross-references first
8325 $checking_caption = '';
8326 $_ = &simplify($_);
8327 $_ = &sanitize($_);
8330 # @tmp = split(/$;/, eval ("\$encoded_$env" . "_number{\$_}"));
8331 # $number = shift(@tmp);
8332 # $number = "" if ($number eq "-1");
8334 &write_warnings(qq|\nNo number for "$_"|) if (! $number);
8335 eval("\$encoded_$env" . "_number{\$_} = join(\$;, \@tmp)");
8337 $item = join( '', ($SHOW_SECTION_NUMBERS ? $number."\. " : '')
8338 , &make_href("$CURRENT_FILE#$key", $pre_anchor)
8339 , $post_anchor);
8340 undef $_;
8341 undef @tmp;
8343 $captions = join("", ($captions ? $captions."\n<BR>\n" : '')
8344 , "<STRONG>$type" , ($number ? " $number:" : ":")
8345 , "</STRONG>\n$caption" , (($captions) ? "\n" : "" ));
8347 do {
8348 eval "$extra_list .= \"\n<LI>\" .\$item" if ($extra_list);
8349 eval "$list .= \"\n<LI>\" .\$item" }
8350 unless ( $noLOTentry || $noLOFentry);
8351 # eval("print \"\nCAPTIONS:\".$extra_list.\n\"");
8352 }
8353 }
8356 # This processes \label commands found in environments that will
8357 # be handed over to Latex. Sets the table %symbolic_labels
8358 sub do_labels {
8359 local($context,$new_context) = @_;
8360 local($label);
8361 # MRO: replaced $* by /m
8362 $context =~ s/\s*$labels_rx/do {
8363 $label = &do_labels_helper($2);
8364 $new_context = &anchor_label($label,$CURRENT_FILE,$new_context);""}/geom;
8365 $new_context;
8366 }
8368 sub extract_labels {
8369 local($_) = @_;
8370 local($label,$anchors);
8371 # MRO: replaced $* by /m
8372 while (s/[ \t]*$labels_rx//om) {
8373 $label = &do_labels_helper($2);
8374 $anchors .= &anchor_label($label,$CURRENT_FILE,'');
8375 }
8376 ($_, $anchors);
8377 }
8379 # This should be done inside the substitution but it doesn't work ...
8380 sub do_labels_helper {
8381 local($_) = @_;
8382 s/$label_rx/_/g; # replace non-alphanumeric characters
8383 $symbolic_labels{$_} = $latex_labels{$_}; # May be empty;
8384 $_;
8385 }
8387 sub convert_to_description_list {
8388 # MRO: modified to use $_[1]
8389 # local($which, *list) = @_;
8390 my $which = $_[0];
8391 $_[1] =~ s!(</A>\s*)<[OU]L([^>]*)>!$1<DD><DL$2>!ig;
8392 $_[1] =~ s!<(/?)[OU]L([^>]*)>!$1? "<$1DL$2>":"<DL$2>"!eig;
8393 $_[1] =~ s!(</?)LI>!$1D$which>!ig;
8394 # $_[1] =~ s/^\s*<DD>//;
8395 }
8397 sub add_toc { &add_real_toc(@_) }
8398 sub add_real_toc {
8399 local($temp1, $temp2);
8400 print "\nDoing table of contents ...";
8401 local(@keys) = keys %toc_section_info;
8402 @keys = sort numerically @keys;
8403 $temp1 = $MAX_LINK_DEPTH; $temp2 = $MAX_SPLIT_DEPTH;
8404 $MAX_SPLIT_DEPTH = $MAX_LINK_DEPTH = 1000;
8405 #JKR: Here was a "Contents" - replaced it with $toc_title
8406 local($base_key) = $keys[0];
8407 if ($MULTIPLE_FILES) {
8408 $base_key = $THIS_FILE;
8409 }
8410 local($title);
8411 if ((defined &do_cmd_contentsname)||$new_command{'contentsname'}) {
8412 local($br_id)=++$global{'max_id'};
8413 $title = &translate_environments("$O$br_id$C\\contentsname$O$br_id$C");
8414 } else { $title = $toc_title }
8415 local($toc,$on_first_page) = ('','');
8416 $on_first_page = $CURRENT_FILE
8417 unless ($MAX_SPLIT_DEPTH && $MAX_SPLIT_DEPTH <1000);
8418 $toc = &add_child_links($title,$on_first_page,'',1,$keys[0],@keys);
8419 &convert_to_description_list('T',$toc) if ($use_description_list);
8420 s/$toc_mark/$toc/;
8421 $MAX_LINK_DEPTH = $temp1; $MAX_SPLIT_DEPTH = $temp2;
8422 }
8424 # Assign ref value, but postpone naming the label
8425 sub make_half_href {
8426 local($link) = $_[0];
8427 $href_name++;
8428 "<A NAME=\"tex2html$href_name\"\n HREF=\"$link\">";
8429 }
8432 # Redefined in makeidx.perl
8433 sub add_idx {
8434 local($sidx_style, $eidx_style) =('<STRONG>','</STRONG>');
8435 if ($INDEX_STYLES) {
8436 if ($INDEX_STYLES =~/,/) {
8437 local(@styles) = split(/\s*,\s*/,$INDEX_STYLES);
8438 $sidx_style = join('','<', join('><',@styles) ,'>');
8439 $eidx_style = join('','</', join('></',reverse(@styles)) ,'>');
8440 } else {
8441 $sidx_style = join('','<', $INDEX_STYLES,'>');
8442 $eidx_style = join('','</', $INDEX_STYLES,'>');
8443 }
8444 }
8445 &add_real_idx(@_)
8446 }
8447 sub add_real_idx {
8448 print "\nDoing the index ...";
8449 local($key, $str, @keys, $index, $level, $count,
8450 @previous, @current);
8451 @keys = keys %index;
8452 @keys = sort keysort @keys;
8453 $level = 0;
8454 foreach $key (@keys) {
8455 @current = split(/!/, $key);
8456 $count = 0;
8457 while ($current[$count] eq $previous[$count]) {
8458 $count++;
8459 }
8460 while ($count > $level) {
8461 $index .= "\n<DL COMPACT>";
8462 $level++;
8463 }
8464 while ($count < $level) {
8465 $index .= "\n</DL>";
8466 $level--;
8467 }
8468 foreach $term (@current[$count .. $#current-1]) {
8469 # need to "step in" a little
8470 # $index .= "<DT>" . $term . "\n<DL COMPACT>";
8471 $index .= "\n<DT>$sidx_style" . $term . "$eidx_style\n<DD><DL COMPACT>";
8472 $level++;
8473 }
8474 $str = $current[$#current];
8475 $str =~ s/\#\#\#\d+$//o; # Remove the unique id's
8476 $index .= $index{$key} .
8477 # If it's the same string don't start a new line
8478 (&index_key_eq(join('',@current), join('',@previous)) ?
8479 ", $sidx_style" . $cross_ref_visible_mark . "$eidx_style</A>\n" :
8480 "<DT>$sidx_style" . $str . "$eidx_style</A>\n");
8481 @previous = @current;
8482 }
8483 while ($count < $level) {
8484 $index .= "\n</DL>";
8485 $level--;
8486 }
8487 $index = '<DD>'.$index unless ($index =~ /^\s*<D(T|D)>/);
8489 $index =~ s/(<A [^>]*>)(<D(T|D)>)/$2$1/g;
8491 # s/$idx_mark/<DL COMPACT>$index<\/DL>/o;
8492 s/$idx_mark/$preindex\n<DL COMPACT>\n$index<\/DL>\n/o;
8493 }
8495 sub keysort {
8496 local($x, $y) = ($a,$b);
8497 $x = &clean_key($x);
8498 $y = &clean_key($y);
8499 # "\L$x" cmp "\L$y"; # changed sort-rules, by M Ernst.
8500 # Put alphabetic characters after symbols; already downcased
8501 $x =~ s/^([a-z])/~~~$1/;
8502 $y =~ s/^([a-z])/~~~$1/;
8503 $x cmp $y;
8504 }
8506 sub index_key_eq {
8507 local($a,$b) = @_;
8508 $a = &clean_key($a);
8509 $b = &clean_key($b);
8510 $a eq $b;
8511 }
8513 sub clean_key {
8514 local ($_) = @_;
8515 tr/A-Z/a-z/;
8516 s/\s+/ /g; # squeeze white space and newlines into space
8517 s/ (\W)/$1/g; # make foo( ), foo () and foo(), or <TT>foo</TT>
8518 ; # and <TT>foo </TT> to be equal
8519 s/$O\d+$C//go; # Get rid of bracket id's
8520 s/$OP\d+$CP//go; # Get rid of processed bracket id's
8521 s/\#\#\#\d+$//o; # Remove the unique id
8522 $_;
8523 }
8526 sub make_footnotes {
8527 # Uses $footnotes defined in translate and set in do_cmd_footnote
8528 # Also uses $footfile
8529 local($_) = "\n<DL>$footnotes\n<\/DL>";
8530 $footnotes = ""; # else they get used
8531 local($title);
8532 if ((defined &do_cmd_footnotename)||$new_command{'footnotename'}) {
8533 local($br_id)=++$global{'max_id'};
8534 $title = &translate_environments("$O$br_id$C\\footnotename$O$br_id$C");
8535 } else {
8536 $foot_title = "Footnotes" unless $foot_title;
8537 $title = $foot_title;
8538 }
8539 print "\nDoing footnotes ...";
8540 #JCL(jcl-tcl)
8541 # If the footnotes go into a separate file: see &make_file.
8542 if ($footfile) {
8543 $toc_sec_title = $title;
8544 &make_file($footfile, $title, $FOOT_COLOR); # Modifies $_;
8545 $_ = "";
8546 } else {
8547 $footnotes = ""; # else they get re-used
8548 $_ = join ('', '<BR><HR><H4>', $title, '</H4>', $_ );
8549 }
8550 $_;
8551 }
8553 sub post_process_footnotes {
8554 &slurp_input($footfile);
8555 open(OUT, ">$footfile") || die "Cannot write file '$footfile': $!\n";
8556 &replace_markers;
8557 &post_post_process if (defined &post_post_process);
8558 &adjust_encoding;
8559 print OUT $_;
8560 close OUT;
8561 }
8563 sub make_file {
8564 # Uses and modifies $_ defined in the caller
8565 local($filename, $title, $layout) = @_;
8566 $layout = $BODYTEXT unless $layout;
8567 $_ = join('',&make_head_and_body($title,$layout), $_
8568 , (($filename =~ /^\Q$footfile\E$/) ? '' : &make_address )
8569 , (($filename =~ /^\Q$footfile\E$/) ? "\n</BODY>\n</HTML>\n" : '')
8570 );
8571 &replace_markers unless ($filename eq $footfile);
8573 unless(open(FILE,">$filename")) {
8574 print "\nError: Cannot write '$filename': $!\n";
8575 return;
8576 }
8577 print FILE $_;
8578 close(FILE);
8579 }
8581 sub add_to_body {
8582 local($attrib, $value) = @_;
8583 local($body) = $BODYTEXT;
8584 if ($body =~ s/\Q$attrib\E\s*=\s*"[^"]*"/$attrib="$value"/) {
8585 } else {
8586 $body .= " $attrib=\"$value\""; $body =~ s/\s{2,}/ /g;
8587 }
8588 $BODYTEXT = $body if $body;
8589 }
8591 sub replace_verbatim_marks {
8592 # Modifies $_
8593 my($tmp);
8594 s/$math_verbatim_rx/&make_comment('MATH', $verbatim{$1})/eg;
8595 s/$mathend_verbatim_rx/&make_comment('MATHEND', '')/eg;
8596 # s/$verbatim_mark(verbatim\*?)(\d+)#/<PRE>\n$verbatim{$2}\n<\/PRE>/go;
8597 ## s/$verbatim_mark(\w*[vV]erbatim\*?)(\d+)#/\n$verbatim{$2}\n/go;
8598 s!$verbatim_mark(\w*[vV]erbatim\*?|tex2html_code)(\d+)#\n?!$tmp=$verbatim{$2};
8599 $tmp.(($tmp =~/\n\s*$/s)? '':"\n")!eg;
8600 # "\n".$tmp.(($tmp =~/\n\s*$/s)? '':"\n")!eg;
8601 # s/$verbatim_mark(rawhtml)(\d+)#/$verbatim{$2}/eg; # Raw HTML
8602 s/$verbatim_mark(imagesonly)(\d+)#//eg; # imagesonly is *not* replaced
8603 # Raw HTML, but replacements may have protected characters
8604 s/$verbatim_mark(rawhtml)(\d+)#/&unprotect_raw_html($verbatim{$2})/eg;
8605 s/$verbatim_mark$keepcomments_rx(\d+)#/$verbatim{$2}/ego; # Raw TeX
8606 s/$unfinished_mark$keepcomments_rx(\d+)#/$verbatim{$2}/ego; # Raw TeX
8607 }
8609 # TeX's special characters may have been escaped with a '\'; remove it.
8610 sub unprotect_raw_html {
8611 local($raw) = @_;
8612 $raw =~ s/\\($latex_specials_rx|~|\^|@)/$1/g;
8613 $raw;
8614 }
8616 # remove file-markers; special packages may redefine &replace_file_marks
8617 sub remove_file_marks {
8618 s/<(DD|LI)>\n?($file_mark|$endfile_mark)\#.*\#\n<\/\1>(\n|(<))/$4/gm;
8619 s/($file_mark|$endfile_mark)\#.*\#(\n|(<))/$3/gm;
8620 }
8621 sub replace_file_marks { &remove_file_marks }
8623 sub remove_verbatim_marks {
8624 # Modifies $_
8625 s/($math_verbatim_rx|$mathend_verbatim_rx)//go;
8626 # s/$verbatim_mark(verbatim\*?)(\d+)#//go;
8627 s/$verbatim_mark(\w*[Vv]erbatim\w*\*?)(\d+)#//go;
8628 s/$verbatim_mark(rawhtml|imagesonly)(\d+)#//go;
8629 s/$verbatim_mark$keepcomments_rx(\d+)#//go;
8630 s/$unfinished_mark$keepcomments_rx(\d+)#//go;
8631 }
8633 sub replace_verb_marks {
8634 # Modifies $_
8635 s/(?:$verb_mark|$verbstar_mark)(\d+)$verb_mark/
8636 $code = $verb{$1};
8637 $code = &replace_comments($code) if ($code =~ m:$comment_mark:);
8638 "<code>$code<\/code>"/ego;
8639 }
8641 sub replace_comments{
8642 local($_) = @_;
8643 $_ =~ s/$comment_mark(\d+)\n?/$verbatim{$1}/go;
8644 $_ =~ s/$comment_mark\d*\n/%\n/go;
8645 $_;
8646 }
8648 sub remove_verb_marks {
8649 # Modifies $_
8650 s/($verb_mark|$verbstar_mark)(\d+)$verb_mark//go;
8651 }
8653 # This is used by revert_to_raw_tex
8654 sub revert_verbatim_marks {
8655 # Modifies $_
8656 # s/$verbatim_mark(verbatim)(\d+)#/\\begin{verbatim}$verbatim{$2}\\end{verbatim}\n/go;
8657 s/$verbatim_mark(\w*[Vv]erbatim)(\d+)#/\\begin{$1}\n$verbatim{$2}\\end{$1}\n/go;
8658 s/$verbatim_mark(rawhtml)(\d+)#/\\begin{rawhtml}\n$verbatim{$2}\\end{rawhtml}\n/go;
8659 s/$verbatim_mark(imagesonly|tex2html_code)(\d+)#\n?/$verbatim{$2}/go;
8660 s/$verbatim_mark$image_env_rx(\d+)#/\\begin{$1}\n$verbatim{$2}\\end{$1}\n/go;
8661 s/($math_verbatim_rx|$mathend_verbatim_rx)//go;
8662 }
8664 sub revert_verb_marks {
8665 # Modifies $_
8666 s/$verbstar_mark(\d+)$verb_mark/\\verb*$verb_delim{$1}$verb{$1}$verb_delim{$1}/go;
8667 s/$verb_mark(\d+)$verb_mark/\\verb$verb_delim{$1}$verb{$1}$verb_delim{$1}/go;
8668 }
8670 sub replace_cross_ref_marks {
8671 # Modifies $_
8672 local($label,$id,$ref_label,$ref_mark,$after,$name);
8673 local($invis) = "<tex2html_anchor_invisible_mark></A>";
8674 # s/$cross_ref_mark#([^#]+)#([^>]+)>$cross_ref_mark/
8675 s/$cross_ref_mark#([^#]+)#([^>]+)>$cross_ref_mark<\/A>(\s*<A( NAME=\"\d+)\">$invis)?/
8676 do {($label,$id) = ($1,$2); $name = $4;
8677 $ref_label = $external_labels{$label} unless
8678 ($ref_label = $ref_files{$label});
8679 print "\nXLINK<: $label : $id :$name " if ($VERBOSITY > 3);
8680 $ref_label = '' if ($ref_label eq $CURRENT_FILE);
8681 $ref_mark = &get_ref_mark($label,$id);
8682 &extend_ref if ($name); $name = '';
8683 print "\nXLINK: $label : $ref_label : $ref_mark " if ($VERBOSITY > 3);
8684 '"' . "$ref_label#$label" . "\">" . $ref_mark . "<\/A>"
8685 }/geo;
8687 # This is for pagerefs which cannot have symbolic labels ???
8688 # s/$cross_ref_mark#(\w+)#\w+>/
8689 s/$cross_ref_mark#([^#]+)#[^>]+>/
8690 do {$label = $1;
8691 $ref_label = $external_labels{$label} unless
8692 ($ref_label = $ref_files{$label});
8693 $ref_label = '' if ($ref_label eq $CURRENT_FILE);
8694 print "\nXLINKP: $label : $ref_label" if ($VERBOSITY > 3);
8695 '"' . "$ref_files{$label}#$label" . "\">"
8696 }/geo;
8697 }
8699 #RRM: this simply absorbs the name from the invisible anchor following,
8700 # when the anchor itself is not already named.
8701 sub extend_ref {
8702 if ($ref_label !=~ /NAME=/) { $label .= "\"\n".$name }
8703 }
8705 sub remove_cross_ref_marks {
8706 # Modifies $_
8707 # s/$cross_ref_mark#(\w+)#(\w+)>$cross_ref_mark/
8708 s/$cross_ref_mark#([^#]+)#([^>]+)>$cross_ref_mark/
8709 print "\nLOST XREF: $1 : $2" if ($VERBOSITY > 3);''/ego;
8710 # s/$cross_ref_mark#(\w+)#\w+>//go;
8711 s/$cross_ref_mark#([^#]+)#[^#>]+>//go;
8712 }
8714 sub replace_external_ref_marks {
8715 # Modifies $_
8716 local($label, $link);
8717 # s/$external_ref_mark#(\w+)#(\w+)>$external_ref_mark/
8718 s/$external_ref_mark#([^#]+)#([^>]+)>$external_ref_mark/
8719 do {($label,$id) = ($1,$2);
8720 $link = $external_labels{$label};
8721 print "\nLINK: $label : $link" if ($VERBOSITY > 3);
8722 '"'. "$link#$label" . "\">\n"
8723 . &get_ref_mark("userdefined$label",$id)
8724 }
8725 /geo;
8726 }
8728 sub remove_external_ref_marks {
8729 # Modifies $_
8730 # s/$external_ref_mark#(\w+)#(\w+)>$external_ref_mark/
8731 s/$external_ref_mark#([^#]+)#([^>]+)>$external_ref_mark/
8732 print "\nLOST LINK: $1 : $2" if ($VERBOSITY > 3);''/ego;
8733 }
8735 sub get_ref_mark {
8736 local($label,$id) = @_;
8737 ( ( $SHOW_SECTION_NUMBERS && $symbolic_labels{"$label$id"}) ||
8738 $latex_labels{"userdefined$label$id"} ||
8739 $symbolic_labels{"$label$id"} ||
8740 $latex_labels{$label} ||
8741 $external_latex_labels{$label} ||
8742 $cross_ref_visible_mark );
8743 }
8745 sub replace_bbl_marks {
8746 # Modifies $_
8747 s/$bbl_mark#([^#]+)#/$citations{$1}/go;
8748 }
8750 sub remove_bbl_marks {
8751 # Modifies $_
8752 s/$bbl_mark#([^#]+)#//go;
8753 }
8755 sub replace_image_marks {
8756 # Modifies $_
8757 s/$image_mark#([^#]+)#([\.,;:\)\]])?(\001)?([ \t]*\n?)(\001)?/
8758 "$id_map{$1}$2$4"/ego;
8759 # "$id_map{$1}$2".(($4)?"\n":'')/ego;
8760 }
8762 sub remove_image_marks {
8763 # Modifies $_
8764 s/$image_mark#([^#]+)#//go;
8765 }
8767 sub replace_icon_marks {
8768 # Modifies $_
8769 if ($HTML_VERSION < 2.2 ) {
8770 local($icon);
8771 s/$icon_mark_rx/$icon = &img_tag($1);
8772 $icon =~ s| BORDER="?\d+"?||;$icon/ego;
8773 } else {
8774 s/$icon_mark_rx/&img_tag($1)/ego;
8775 }
8776 }
8778 sub remove_icon_marks {
8779 # Modifies $_
8780 s/$icon_mark_rx//go;
8781 }
8783 sub replace_cite_marks {
8784 local($key,$label,$text,$file);
8785 # Modifies $_
8786 # Uses $citefile set by the thebibliography environment
8787 local($citefile) = $citefile;
8788 $citefile =~ s/\#.*$//;
8790 s/#([^#]+)#$cite_mark#([^#]+)#((($OP\d+$CP)|[^#])*)#$cite_mark#/
8791 $text = $3; $label= $1; $file='';
8792 $text = $cite_info{$1} unless $text;
8793 if ($checking_caption){
8794 "$label"
8795 } elsif ($citefiles{$2}){
8796 $file = $citefiles{$2}; $file =~ s:\#.*$::;
8797 &make_named_href('', "$file#$label","$text");
8798 } elsif ($PREAMBLE) {
8799 $text || "\#!$1!\#" ;
8800 } elsif ($simplifying) {
8801 $text
8802 } else {
8803 &write_warnings("\nno reference for citation: $1");
8804 "\#!$1!\#"
8805 }/sge ;
8806 #
8807 #RRM: Associate the cite_key with $citefile , for use by other segments.
8808 if ($citefile) {
8809 local($cite_key, $cite_ref);
8810 while (($cite_key, $cite_ref) = each %cite_info) {
8811 if ($ref_files{'cite_'."$cite_key"} ne $citefile) {
8812 $ref_files{'cite_'."$cite_key"} = $citefile;
8813 $changed = 1; }
8814 }
8815 }
8816 }
8818 sub remove_cite_marks {
8819 # Modifies $_
8820 s/#([^#]+)#$cite_mark#([^#]+)#([^#]*)#$cite_mark#//go;
8821 }
8823 sub remove_anchors {
8824 # modifies $_
8825 s/<A[^>]*>//g;
8826 s/<\/A>//g;
8827 }
8830 # We need two matching keys to determine section/figure/etc. numbers.
8831 # The "keys" are the name of the section/figure/etc. and its
8832 # equivalent in the .aux file (also carrying the number we desire).
8833 # But both keys might have been translated slightly different,
8834 # depending on the usage of math, labels, special characters such
8835 # as umlauts, or simply spacing!
8836 #
8837 # This routine tries to squeeze the HTML translated keys such
8838 # that they match (hopefully very often). -- JCL
8839 #
8840 sub sanitize {
8841 local($_,$mode) = @_;
8842 &remove_markers;
8843 &remove_anchors;
8844 &text_cleanup;
8845 s/(\&|;SPM)nbsp;//g; # HWS - LaTeX changes ~ in its .aux files
8846 #strip unwanted HTML constructs
8847 s/<\/?(P|BR|H)[^>]*>//g;
8848 s/\s+//g; #collapse white space
8849 $_;
8850 }
8852 # This one removes any HTML markup, so that pure
8853 # plain text remains. (perhaps with <SUP>/<SUB> tags)
8854 # As the result will be part of the HTML file, it will be
8855 # &text_cleanup'd later together with its context.
8856 #
8857 sub purify {
8858 local($_,$strict) = @_;
8859 &remove_markers;
8860 #strip unwanted HTML constructs
8861 # s/<[^>]*>/ /g;
8862 s/<(\/?SU[BP])>/>$1>/g unless ($strict); # keep sup/subscripts ...
8863 s/<[^>]*>//g; # remove all other tags
8864 s/>(\/?SU[BP])>/<$1>/g unless ($strict); # ...reinsert them
8865 s/^\s+|\001//g; s/\s\s+/ /g; #collapse white space
8866 $_;
8867 }
8869 # This one is not as strict as &sanitize.
8870 # It is chosen to strip section names etc. a bit from
8871 # constructs so that it better fits a table of contents,
8872 # label files, etc.
8873 # As the result will be part of the HTML file, it will be
8874 # &text_cleanup'd later together with its context.
8875 #
8876 sub simplify {
8877 local($_) = @_;
8878 local($simplifying) = 1;
8879 s/$tex2html_envs_rx//g;
8880 if (/\\/) {
8881 local($USING_STYLES) = 0;
8882 $_ = &translate_commands($_);
8883 undef $USING_STYLES;
8884 }
8885 &replace_external_ref_marks if /$external_ref_mark/;
8886 &replace_cross_ref_marks if /$cross_ref_mark||$cross_ref_visible_mark/;
8887 &replace_cite_marks if /$cite_mark/;
8888 # strip unwanted HTML constructs
8889 # s/<\/?H[^>]*>/ /g;
8890 s/<\/?(H)[^>]*>//g;
8891 s/<\#\d+\#>//g;
8892 s/^\s+//;
8893 $_;
8894 }
8896 #RRM: This extracts $anchor_mark portions from a given chunk of text,
8897 # so they can be positioned separately by the calling subroutine.
8898 # added for v97.2:
8899 # search within the immediately following text also; so that
8900 # \index and \label after section-headings work as expected.
8901 #
8902 sub extract_anchors {
8903 local($search_text, $start_only) = @_;
8904 local($anchors) = '';
8905 local($untranslated_anchors) = '';
8907 do {
8908 while ($search_text =~ s/<A[^>]*>($anchor_mark|$anchor_invisible_mark)<\/A>//) {
8909 $anchors .= $&;
8910 }
8911 } unless ($start_only);
8913 $search_text =~ s/\s*(\\protect)?\\(label|index|markright|markboth\s*(($O|$OP)\d+($C|$CP))[^<]*\3)\s*(($O|$OP)\d+($C|$CP))[^<]*\6/
8914 $anchors .= $&;''/eg unless ($start_only);
8916 while ( s/^\s*<A[^>]*>($anchor_mark|$anchor_invisible_mark)<\/A>//m) {
8917 $untranslated_anchors .= $&;
8918 }
8919 while ( s/^\s*(\\protect)?\\(label|index|markright|markboth\s*(($O|$OP)\d+($C|$CP))[^<]*\3)\s*(($O|$OP)\d+($C|$CP))[^<]*\6//) {
8920 $untranslated_anchors .= $&;
8921 }
8922 if ($TITLE||$start_only) {
8923 $anchors .= &translate_commands($untranslated_anchors);
8924 $untranslated_anchors = '';
8925 }
8926 ($anchors.$untranslated_anchors,$search_text);
8927 }
8929 # This routine must be called once on the text only,
8930 # else it will "eat up" sensitive constructs.
8931 sub text_cleanup {
8932 # MRO: replaced $* with /m
8933 s/(\s*\n){3,}/\n\n/gom; # Replace consecutive blank lines with one
8934 s/<(\/?)P>\s*(\w)/<$1P>\n$2/gom; # clean up paragraph starts and ends
8935 s/$O\d+$C//go; # Get rid of bracket id's
8936 s/$OP\d+$CP//go; # Get rid of processed bracket id's
8937 s/(<!)?--?(>)?/(length($1) || length($2)) ? "$1--$2" : "-"/ge;
8938 # Spacing commands
8939 s/\\( |$)/ /go;
8940 #JKR: There should be no more comments in the source now.
8941 #s/([^\\]?)%/$1/go; # Remove the comment character
8942 # Cannot treat \, as a command because , is a delimiter ...
8943 s/\\,/ /go;
8944 # Replace tilde's with non-breaking spaces
8945 s/ *~/ /g;
8947 ### DANGEROUS ?? ###
8948 # remove redundant (not <P></P>) empty tags, incl. with attributes
8949 s/\n?<([^PD >][^>]*)>\s*<\/\1>//g;
8950 s/\n?<([^PD >][^>]*)>\s*<\/\1>//g;
8951 # remove redundant empty tags (not </P><P> or <TD> or <TH>)
8952 s/<\/(TT|[^PTH][A-Z]+)><\1>//g;
8953 s/<([^PD ]+)(\s[^>]*)?>\n*<\/\1>//g;
8956 #JCL(jcl-hex)
8957 # Replace ^^ special chars (according to p.47 of the TeX book)
8958 # Useful when coming from the .aux file (german umlauts, etc.)
8959 s/\^\^([^0-9a-f])/chr((64+ord($1))&127)/ge;
8960 s/\^\^([0-9a-f][0-9a-f])/chr(hex($1))/ge;
8961 }
8963 # This is useful for getting words from a title which are not cluttered
8964 # with tex2html markers or HTML constructs
8965 sub extract_pure_text {
8966 local($mode) = @_;
8967 &text_cleanup; # Remove marking brackets
8968 #
8969 # HWS <hswan@perc.Arco.com>: Conditionally doing the following
8970 # permits equations in section headings.
8971 #
8972 if ($mode eq "strict") {
8973 s/$image_mark#[^#]*#//g; # Remove image marker
8974 s/$bbl_mark#[^#]*#//g; # Remove citations marker
8975 s/<tex2html_percent_mark>/%/g; # BMcM: Retain % signs...
8976 s/<tex2html_ampersand_mark>/\&/g;
8977 s/tex2html[\w\d]*//g; # Remove other markers
8978 }
8980 #
8981 # HWS <hswan@perc.Arco.com>: Replace next statement with the following two
8982 # to permit symbolic links and images to appear in section headings.
8984 # s/<[^>]*>//go; # Remove HTML constructs
8985 s/$OP[^#]*$CP//go; # Remove <# * #> constructs
8986 s/<\s*>//go; # Remove embedded whitespace
8987 }
8989 ############################ Misc ####################################
8991 # MRO: Print standardized header
8992 sub banner {
8993 print <<"EOF";
8994 This is LaTeX2HTML Version $TEX2HTMLVERSION
8995 by Nikos Drakos, Computer Based Learning Unit, University of Leeds.
8997 EOF
8998 }
9000 # MRO: Extract usage information from POD
9001 sub usage {
9002 my $start = 0;
9003 my $usage = 'Usage: ';
9004 my $indent = '';
9006 print (@_, "\n") if @_;
9008 my $perldoc = "/usr/bin${dd}perldoc";
9009 my $script = $SCRIPT || $0;
9010 open(PIPE, "$perldoc -t $script |")
9011 || die "Fatal: can't open pipe: $!";
9012 while (<PIPE>) {
9013 if (/^\s*$/) {
9014 next;
9015 } elsif (/^SYNOPSIS/) {
9016 $start = 1;
9017 } elsif (/^\w/) {
9018 $start = 0;
9019 } elsif ($start == 1) {
9020 ($indent) = /^(\s*)/;
9021 s/^$indent/$usage/;
9022 $usage =~ s/./ /g;
9023 $start = 2;
9024 print $_;
9025 } elsif ($start == 2) {
9026 s/^$indent/$usage/;
9027 print $_;
9028 }
9029 }
9030 close PIPE;
9031 1;
9032 }
9034 # The bibliographic references, the appendices, the lists of figures and tables
9035 # etc. must appear in the contents table at the same level as the outermost
9036 # sectioning command. This subroutine finds what is the outermost level and
9037 # sets the above to the same level;
9038 sub set_depth_levels {
9039 # Sets $outermost_level
9040 local($level);
9041 # scan the document body, not the preamble, for use of sectioning commands
9042 my ($contents) = $_;
9043 if ($contents =~ /\\begin\s*((?:$O|$OP)\d+(?:$C|$CP))document\1|\\startdocument/s) {
9044 $contents = $';
9045 }
9046 #RRM: do not alter user-set value for $MAX_SPLIT_DEPTH
9047 foreach $level ("part", "chapter", "section", "subsection",
9048 "subsubsection", "paragraph") {
9049 last if (($outermost_level) = $contents =~ /\\($level)$delimiter_rx/);
9050 last if (($outermost_level) = $contents =~ /\\endsegment\s*\[\s*($level)\s*\]/s);
9051 if ($contents =~ /\\segment\s*($O\d+$C)[^<]+\1\s*($O\d+$C)\s*($level)\s*\2/s)
9052 { $outermost_level = $3; last };
9053 }
9054 $level = ($outermost_level ? $section_commands{$outermost_level} :
9055 do {$outermost_level = 'section'; 3;});
9057 #RRM: but calculate value for $MAX_SPLIT_DEPTH when a $REL_DEPTH was given
9058 if ($REL_DEPTH && $MAX_SPLIT_DEPTH) {
9059 $MAX_SPLIT_DEPTH = $level + $MAX_SPLIT_DEPTH;
9060 } elsif (!($MAX_SPLIT_DEPTH)) { $MAX_SPLIT_DEPTH = 1 };
9062 %unnumbered_section_commands = (
9063 'tableofcontents', $level
9064 , 'listoffigures', $level
9065 , 'listoftables', $level
9066 , 'bibliography', $level
9067 , 'textohtmlindex', $level
9068 , %unnumbered_section_commands
9069 );
9071 %section_commands = (
9072 %unnumbered_section_commands
9073 , %section_commands
9074 );
9075 }
9077 # Now ignores accents which cannot be translated to ISO-LATIN-1 characters
9078 # Also replaces ?' and !' ....
9079 sub replace_strange_accents {
9080 &real_replace_strange_accents(@_); # if ($CHARSET =~ /8859[_\-]1$/);
9081 }
9082 sub real_replace_strange_accents {
9083 # Modifies $_;
9084 s/\?`/&iso_map("iquest", "")/geo;
9085 s/!`/&iso_map("iexcl", "")/geo;
9086 s/\\\^\\i /&iso_map("icirc", "")/geo;
9087 my ($charset) = "${CHARSET}_character_map_inv";
9088 $charset =~ s/-/_/g;
9089 # convert upper 8-bit characters
9090 if (defined %$charset &&($CHARSET =~ /8859[_\-]1$/)) {
9091 s/([\200-\377])/
9092 $tmp = $$charset{'&#'.ord($1).';'};
9093 &mark_string($tmp) if ($tmp =~ m!\{!);
9094 &translate_commands($tmp)
9095 /egos
9096 }
9097 };
9099 # Creates a new directory or reuses old, perhaps after deleting its contents
9100 sub new_dir {
9101 local($this_dir,$mode) = @_;
9102 local(@files)=();
9103 $this_dir = '.' unless $this_dir;
9104 $this_dir =~ s/[$dd$dd]+$//o;
9105 local($print_dir) = $this_dir.$dd;
9106 (!$mode && mkdir($this_dir, 0755)) ||
9107 do {
9108 print "\nCannot create directory $print_dir: $!" unless ($mode);
9109 if ($REUSE) {
9110 print ", reusing it.\n" unless ($mode);
9111 &reuse($this_dir,$print_dir);
9112 } else {
9113 print "\n" unless ($mode);
9114 while (! ($answer =~ /^[dqr]$/)) {
9115 if ($mode) {
9116 $answer = $mode;
9117 } else {
9118 print "(r) Reuse the images in the old directory OR\n"
9119 . (($this_dir eq '.') ?
9120 "(d) *** DELETE *** the images in $print_dir OR\n"
9121 : "(d) *** DELETE *** THE CONTENTS OF $print_dir OR\n" )
9122 . "(q) Quit ?\n:";
9123 $answer = scalar(<STDIN>);
9124 };
9125 if ($answer =~ /^d$/) {
9126 @files = ();
9127 if(opendir(DIR,$this_dir)) {
9128 @files = readdir DIR;
9129 closedir DIR;
9130 } else {
9131 print "\nError: Cannot read dir '$this_dir': $!\n";
9132 }
9133 foreach (@files) {
9134 next if /^\.+$/;
9135 if (-d "$this_dir$dd$_") {
9136 &new_dir("$this_dir$dd$_",'d');
9137 } elsif ($this_dir eq '.') {
9138 L2hos->Unlink($_) if (/\.(pl|gif|png)$/)
9139 } else {
9140 L2hos->Unlink("$this_dir$dd$_");
9141 };
9142 }
9143 return(1) if ($this_dir eq '.');
9144 if($mode) {
9145 rmdir($this_dir);
9146 rmdir($print_dir);
9147 }
9148 if (!$mode) { &new_dir($this_dir,'r')};
9149 return(1);
9150 } elsif ($answer =~ /^q$/) {
9151 die "Bye!\n";
9152 } elsif ($answer =~ /^r$/) {
9153 &reuse($this_dir,$print_dir);
9154 return(1);
9155 } else {print "Please answer r d or q!\n";};
9156 }
9157 };
9158 };
9159 1;
9160 }
9162 sub reuse {
9163 local($this_dir,$print_dir) = @_;
9164 $print_dir = $this_dir.$dd unless ($print_dir);
9165 if (-f "$this_dir$dd${PREFIX}images.pl") {
9166 print STDOUT "Reusing directory $print_dir:\n";
9167 local($key);
9168 require("$this_dir$dd${PREFIX}images.pl");
9169 }
9170 }
9173 # JCL(jcl-del) - use $CD rather than a space as delimiter.
9174 # The commands might take white space, or not, depending on
9175 # their definition. Eg. \relax takes white space, because it's a
9176 # letter command, but \/ won't.
9177 # TeX seems to have an internal separator: If \x is " x",
9178 # and \y is "y", then \expandafter\y \x expands to "y x", TeX
9179 # hasn't gobbled the space, meaning that spaces are gobbled once
9180 # when the \y token is consumed, but then never again after \y.
9181 #
9182 # The actions below ensure to insert exactly one space after
9183 # the command name. # what happens to `\ ' ?
9184 # The substition is done twice to handle \one\delimits\another
9185 # cases.
9186 # The internal shortcut $CD is then turned into the single
9187 # space we desire.
9188 #
9189 sub tokenize {
9190 # Modifies $_;
9191 local($rx) = @_;
9192 # $rx must be specially constructed, see &make_new_cmd_rx.
9193 if (length($rx)) {
9194 # $1: non-letter cmd, or $2: letter cmd
9195 s/$rx/\\$1$2$CD$4/g;
9196 s/$rx/\\$1$2$CD$4/g;
9197 s/$CD+/ /g; # puts space after each command name
9198 }
9199 }
9201 # When part of the input text contains special perl characters and the text
9202 # is to be used as a pattern then these specials must be escaped.
9203 sub escape_rx_chars {
9204 my($rx) = @_; # must use a copy of the string
9205 $rx =~ s:([\\(){}[\]\^\$*+?.|]):\\$1:g; $rx; }
9207 # Does not do much but may need it later ...
9208 # The document environment has to be removed because it spans
9209 # more than one sections (the translator can only deal with
9210 # environments wholly contained with sections).
9212 # (Does a little more now ... the end of the preamble is now marked
9213 # with an internally-generated command which causes all output
9214 # erroneously generated from unrecognized commands in the preamble
9215 # to vanish --- rst).
9217 sub remove_document_env {
9218 # s/\\begin$match_br_rx[d]ocument$match_br_rx/\\latextohtmlditchpreceding /o;
9219 if (/\\begin\s*${match_br_rx}document$match_br_rx/) {
9220 s/\\begin\s*$match_br_rx[d]ocument$match_br_rx/\\latextohtmlditchpreceding /
9221 }
9222 # s/\\end$match_br_rx[d]ocument$match_br_rx(.|\n)*//o;
9223 if (/\\end\s*${match_br_rx}document$match_br_rx/) { $_ = $` }
9224 }
9226 # And here's the code to handle the marker ...
9228 sub do_cmd_latextohtmlditchpreceding {
9229 local($_) = @_;
9230 $ref_before = '';
9231 $_;
9232 }
9234 print "\n"; # flushes a cache? This helps, for some unknown reason!!
9236 sub do_AtBeginDocument{
9237 local($_) = @_;
9238 eval $AtBeginDocument_hook;
9239 $_;
9240 }
9242 sub cleanup {
9243 local($explicit) = @_;
9244 return unless $explicit || !$DEBUG;
9246 if (opendir(DIR, '.')) {
9247 while (defined($_ = readdir(DIR))) {
9248 L2hos->Unlink($_)
9249 if /\.ppm$/ || /^${PREFIX}images\.dvi$/ || /^(TMP[-._]|$$\_(image)?)/;
9250 }
9251 closedir (DIR);
9252 }
9254 L2hos->Unlink("WARNINGS") if ($explicit &&(-f "WARNINGS"));
9256 if ($TMPDIR && opendir(DIR, $TMPDIR)) {
9257 local(@files) = grep(!/^\.\.?$/,readdir(DIR));
9258 local($busy);
9259 foreach (@files) {
9260 $busy .= $_." " unless (L2hos->Unlink("$TMPDIR$dd$_"));
9261 }
9262 closedir (DIR);
9263 if ($busy) {
9264 print "\n\nFiles: $busy are still in use.\n\n" if ($DEBUG);
9265 } else {
9266 &write_warnings("\n\n Couldn't remove $TMPDIR : $!")
9267 unless (rmdir $TMPDIR);
9268 }
9269 }
9270 if (opendir(DIR, $TMP_)) {
9271 local(@files) = grep(!/^\.\.?$/,readdir(DIR));
9272 $busy = '';
9273 foreach (@files) {
9274 $busy .= "$_ " unless (L2hos->Unlink("$TMP_$dd$_"));
9275 }
9276 closedir (DIR);
9277 local($full_dir) = L2hos->Make_directory_absolute($TMP_);
9278 if ($busy) {
9279 print "\n\nFiles: $busy in $full_dir are still in use.\n\n"
9280 if ($DEBUG);
9281 } else {
9282 &write_warnings("\n\nCouldn't remove directory '$full_dir': $!")
9283 unless (rmdir $full_dir);
9284 }
9285 }
9286 }
9288 sub handler {
9289 print "\nLaTeX2HTML shutting down.\n";
9290 kill ('INT', $child_pid) if ($child_pid);
9291 &close_dbm_database;
9292 &cleanup();
9293 exit(-1);
9294 }
9296 # Given a filename or a directory it returns the file and the full pathname
9297 # relative to the current directory.
9298 sub get_full_path {
9299 local($file) = @_;
9300 local($path,$dir);
9301 if (-d $file) { # $file is a directory
9302 $path = L2hos->Make_directory_absolute($file);
9303 $file = '';
9305 # JCL(jcl-dir)
9306 } elsif ($file =~ s|\Q$dd\E([^$dd$dd]*)$||o ) {
9307 $path = $file;
9308 $file = $1;
9309 $path = L2hos->Make_directory_absolute($path);
9311 #RRM: check within $TEXINPUTS directories
9312 } elsif (!($TEXINPUTS =~ /^\.$envkey$/)) {
9313 #check along directories in the $TEXINPUTS variable
9314 foreach $dir (split(/$envkey/,$TEXINPUTS)) {
9315 $dir =~ s/[$dd$dd]$//o;
9316 if (-f $dir.$dd.$file) {
9317 $path = L2hos->Make_directory_absolute($dir);
9318 last;
9319 }
9320 }
9321 } else {
9322 $path = L2hos->Cwd();
9323 }
9324 ($path, $file);
9325 }
9328 # Given a directory name in either relative or absolute form, returns
9329 # the absolute form.
9330 # Note: The argument *must* be a directory name.
9331 # The whole function has been moved to override.pm
9335 # Given a relative filename from the directory in which the original
9336 # latex document lives, it tries to expand it to the full pathname.
9337 sub fulltexpath {
9338 # Uses $texfilepath defined in sub driver
9339 local($file) = @_;
9340 $file =~ s/\s//g;
9341 $file = "$texfilepath$dd$file"
9342 unless (L2hos->is_absolute_path($file));
9343 $file;
9344 }
9346 #RRM Extended to allow customised filenames, set $CUSTOM_TITLES
9347 # or long title from the section-name, set $LONG_TITLES
9348 #
9349 sub make_name {
9350 local($sec_name, $packed_curr_sec_id) = @_;
9351 local($title,$making_name,$saved) = ('',1,'');
9352 if ($LONG_TITLES) {
9353 $saved = $_;
9354 &process_command($sections_rx, $_) if /^$sections_rx/;
9355 $title = &make_long_title($TITLE)
9356 unless ((! $TITLE) || ($TITLE eq $default_title));
9357 $_ = $saved;
9358 } elsif ($CUSTOM_TITLES) {
9359 $saved = $_;
9360 &process_command($sections_rx, $_) if /^$sections_rx/;
9361 $title = &custom_title_hook($TITLE)
9362 unless ((! $TITLE) || ($TITLE eq $default_title));
9363 $_ = $saved;
9364 }
9365 if ($title) {
9366 #ensure no more than 32 characters, including .html extension
9367 $title =~ s/^(.{1,27}).*$/$1/;
9368 ++$OUT_NODE;
9369 join("", ${PREFIX}, $title, $EXTN);
9370 } else {
9371 # Remove 0's from the end of $packed_curr_sec_id
9372 $packed_curr_sec_id =~ s/(_0)*$//;
9373 $packed_curr_sec_id =~ s/^\d+$//o; # Top level file
9374 join("",($packed_curr_sec_id ?
9375 "${PREFIX}$NODE_NAME". ++$OUT_NODE : $sec_name), $EXTN);
9376 }
9377 }
9379 #RRM: redefine this subroutine, to create customised file-names
9380 # based upon the actual section title.
9381 # The default is empty, so reverts to: node1, node2, ...
9382 #
9383 sub custom_title_hook {
9384 local($_)= @_;
9385 "";
9386 }
9389 sub make_long_title {
9390 local($_)= @_;
9391 local($num_words) = $LONG_TITLES;
9392 #RRM: scan twice for short words, due to the $4 overlap
9393 # Cannot use \b , else words break at accented letters
9394 $_ =~ s/(^|\s)\s*($GENERIC_WORDS)(\'|(\s))/$4/ig;
9395 $_ =~ s/(^|\s)\s*($GENERIC_WORDS)(\'|(\s))/$4/ig;
9396 #remove leading numbering, unless that's all there is.
9397 local($sec_num);
9398 if (!(/^\d+(\.\d*)*\s*$/)&&(s/^\s*(\d+(\.\d*)*)\s*/$sec_num=$1;''/e))
9399 { $num_words-- };
9400 &remove_markers; s/<[^>]*>//g; #remove tags
9401 #revert entities, etc. to TeX-form...
9402 s/([\200-\377])/"\&#".ord($1).";"/eg;
9403 $_ = &revert_to_raw_tex($_);
9405 # get $LONG_TITLES number of words from what remains
9406 $_ = &get_first_words($_, $num_words) if ($num_words);
9407 # ...and cleanup accents, spaces and punctuation
9408 $_ = join('', ($SHOW_SECTION_NUMBERS ? $sec_num : ''), $_);
9409 s/\\\W\{?|\}//g; s/\s/_/g; s/\W/_/g; s/__+/_/g; s/_+$//;
9410 $_;
9411 }
9414 sub make_first_key {
9415 local($_);
9416 $_ = ('0 ' x keys %section_commands);
9417 s/^0/$THIS_FILE/ if ($MULTIPLE_FILES);
9418 chop;
9419 $_;
9420 }
9422 # This copies the preamble into the variable $preamble.
9423 # It also sets the LaTeX font size, if $FONT_SIZE is set.
9424 sub add_preamble_head {
9425 $preamble = join("\n", $preamble, @preamble);
9426 $preamble = &revert_to_raw_tex($preamble);
9427 $preamble = join ("\n", &revert_to_raw_tex(/$preamble_rx/o),
9428 $preamble);
9429 local($savedRS) = $/; undef $/;
9430 # MRO: replaced $* with /m
9431 $preamble =~ /(\\document(style|class))\s*(\[[^]]*\])?\s*\{/sm;
9432 local($before,$after) = ($`.$1, '{'.$');
9433 $/ = $savedRS;
9434 local ($options) = $3;
9435 if ($FONT_SIZE) {
9436 $options =~ s/(1\dpt)\b//;
9437 $options =~ s/(\[|\])//g;
9438 $options = "[$FONT_SIZE".($options ? ",$options" : '').']';
9439 $preamble = join('', $before, $options, $after );
9440 &write_mydb_simple("preamble", $preamble);
9441 @preamble = split(/\n/, $preamble);
9442 $LATEX_FONT_SIZE = $FONT_SIZE;
9443 }
9444 if (($options =~ /(1\dpt)\b/)&&(!$LATEX_FONT_SIZE)) {
9445 $LATEX_FONT_SIZE = $1;
9446 }
9447 #RRM: need to know the font-size before the .aux file is read
9448 $LATEX_FONT_SIZE = '10pt' unless ($LATEX_FONT_SIZE);
9449 }
9451 # It is necessary to filter some parts of the document back to raw
9452 # tex before passing them to latex for processing.
9453 sub revert_to_raw_tex {
9454 local($_) = @_;
9455 local($character_map) = "";
9456 if ( $CHARSET && $HTML_VERSION ge "2.1" ) {
9457 $character_map = $CHARSET;
9458 $character_map =~ tr/-/_/; }
9459 while (s/$O\s*\d+\s*$C/\{/o) { s/$&/\}/;}
9460 while (s/$O\s*\d+\s*$C/\{/o) { s/$&/\}/;} #repeat this.
9461 # The same for processed markers ...
9462 while ( s/$OP\s*\d+\s*$CP/\{/o ) { s/$&/\}/; }
9463 while ( s/$OP\s*\d+\s*$CP/\{/o ) { s/$&/\}/;} #repeat this.
9465 s/<BR>/\\\\/g; # restores the \\ from \parbox's
9467 # revert any math-entities
9468 s/\&\w+#(\w+);/\\$1/g;
9469 s/\&limits;/\\limits/g;
9470 s/\\underscore/\\_/g;
9471 s/\\circflex/\\^/g;
9472 s/\\space/\\ /g;
9473 s/;SPMthinsp;/\\,/g;
9474 s/;SPMnegsp;/\\!/g;
9475 s/;SPMsp;/\\:/g;
9476 s/;SPMthicksp;/\\;/g;
9477 s/;SPMgg;/\\gg /g;
9478 s/;SPMll;/\\ll /g;
9479 s/;SPMquot;/"/g;
9481 # revert any super/sub-scripts
9482 s/<SUP>/\^\{/g;
9483 s/<SUB>/\_\{/g;
9484 s/<\/SU(B|P)>/\}/g;
9487 # #revert common character entities ??
9488 # s/\/\\/g;
9490 # # revert special marks
9491 # s/$percent_mark/\\%/go;
9492 ## s/$comment_mark(\d+)\n/%$comments{$1}\n/go;
9493 local($tmp,$tmp2);
9494 # s/$comment_mark(\d+)\n/$tmp=$verbatim{$1};chomp($tmp);$tmp."\n"/ego;
9495 s/$comment_mark(\d+)(\n|$|(\$))/$tmp=$verbatim{$1};$tmp2 = $3;
9496 ($tmp=~m!^\%!s ? '':'%').$tmp.(($tmp=~ m!\n\s*$!s)?'':"\n").$tmp2/sego;
9497 s/${verbatim_mark}tex2html_code(\d+)\#/$verbatim{$1}/go;
9498 s/^($file_mark|$endfile_mark).*\#\n//gmo;
9499 s/$comment_mark(\d*)\s*\n/%\n/go;
9500 s/$dol_mark/\$/go;
9501 s/$caption_mark//go;
9503 # From &pre_process.
9504 # MRO: replaced $* with /m
9505 s/\\\\[ \t]*(\n)?/\\\\$1/gm;
9507 # revert any array-cell delimiters
9508 s/$array_col_mark/\&/g;
9509 s/$array_row_mark/\\\\/g;
9510 s/$array_text_mark/\\text/g;
9511 s/$array_mbox_mark/\\mbox/g;
9513 # Replace any verbatim and image markers ...
9514 &revert_verbatim_marks;
9515 &revert_verb_marks;
9518 # &replace_image_marks;
9519 s/$image_mark\#([^\#]+)\#/&recover_image_code($1)/eg;
9521 # remove artificial environments and commands
9523 s/(\n*)\\(begin|end)(($O|$OP)\d+($C|$CP))tex2html_b(egin)?group\3\n?/
9524 ($1? "\n":'')."\\".($6? $2:(($2 =~ m|end|)? 'e':'b'))."group\n"
9525 /gem;
9526 s/\\(begin|end)(\{|(($O|$OP)\d+($C|$CP|\})))(tex2html|verbatim)_code(\}|\3)\n?//gm;
9528 #take care not to concatenate \<cmd> with following letters
9529 local($tmp);
9530 s/(\\\w+)?$tex2html_wrap_rx([^\\\n])?/$tmp=$2;
9531 ((($tmp eq 'end')&&($1)&&!($5)&&($6))? "$1 $6":"$1$5$6")/egs;
9532 undef $tmp;
9533 s/\s*\\newedcommand\s*{/"%\n\\providecommand{\\"/gem;
9534 s/\\newedcommand\s*{/\\providecommand{\\/gom;
9535 # s/(\n*)\\renewedcommand{/($1? "\n":'')."\\renewcommand{\\"/geo;
9536 s/\s*\\providedcommand\s*{/"%\n\\providecommand{\\"/gem;
9537 # s/\\providedcommand{/\\providecommand{\\/go;
9538 s/\\renewedenvironment\s*/\\renewenvironment/gom;
9539 s/\\newedboolean\s*{/\\newboolean{/gom;
9540 s/\\newedcounter\s*{/\\newcounter{/gom;
9541 s/\\newedtheorem\s*{/\\newtheorem{/gom;
9542 s/\\xystar/\\xy\*/gom; # the * has a special meaning in Xy-pic
9544 #fix-up the star'd environment names
9545 s/(\\(begin|end)(($O|$OP)\d+($C|$CP))[^<]*)star\3/$1\*$3/gm;
9546 s/(\\(begin|end)\{[^\}]*)star\}/$1\*\}/gm;
9547 s/\\(begin|end)\{[^\}]*begin(group)\}/\\$1$2/gm;
9548 s/\\(b|e)(egin|end)\{[^\}]*b(group)\}/\\$1$3/gm;
9550 s/(\\(\w+)TeX)/($language_translations{$2}? "\\selectlanguage{$2}": $1)/egom;
9552 if ($PREPROCESS_IMAGES) {
9553 while (/$pre_processor_env_rx/m) {
9554 $done .= $`; $pre_env = $5; $which =$1; $_ = $';
9555 if (($which =~ /begin/)&&($pre_env =~ /indica/)) {
9556 ($indic, $dum) = &get_next_optional_argument;
9557 $done .= "\#$indic";
9558 } elsif (($which =~ /begin/)&&($pre_env =~ /itrans/)) {
9559 ($indic, $dum) = &get_next_optional_argument;
9560 $done .= "\#$indic";
9561 } elsif (($which =~ /end/)&&($pre_env =~ /indica/)) {
9562 $done .= '\#NIL';
9563 } elsif (($which =~ /end/)&&($pre_env =~ /itrans/)) {
9564 $done .= "\#end$indic";
9565 } elsif ($which =~ /begin/) {
9566 $done .= (($which =~ /end/)? $end_preprocessor{$pre_env}
9567 : $begin_preprocessor{$pre_env} )
9568 }
9569 $_ = $done . $_;
9570 }
9571 }
9572 s/\\ITRANSinfo\{(\w+)\}\{([^}]*)\}/\#$1=$2/gm if $itrans_loaded;
9574 s/\n{3,}/\n\n/gm; # remove multiple (3+) new-lines
9575 s/^\n+$//gs; # ...especially if that is all there is!
9576 if ($PREAMBLE) {
9577 s/$comment_mark(\d+\n?)?//g;
9578 # $preamble =~ s/\\par\n?/\n/g;
9579 s/\\par\b/\n/g;
9580 s/^\s*$//g; #remove blank lines in the preamble
9581 };
9583 s/($html_specials_inv_rx)/$html_specials_inv{$1}/geo;
9584 # revert entities to TeX code, except if in {rawhtml} environments
9585 if (!($env =~ /rawhtml/)) {
9586 s/$character_entity_rx/( $character_map ?
9587 eval "\$${character_map}_character_map_inv\{\"$1\"\}" :
9588 $iso_8859_1_character_map_inv{$1} ||
9589 $iso_10646_character_map_inv{$1})/geo;
9590 s/$named_entity_rx/( $character_map ?
9591 eval "\$${character_map}_character_map_inv\{\$${character_map}_character_map{'$1'}}" :
9592 $iso_8859_1_character_map_inv{$iso_8859_1_character_map{$1}} ||
9593 $iso_10646_character_map_inv{$iso_10646_character_map{$1}})/geo;
9595 } else {
9596 #RRM: check for invalid named entities in {rawhtml} environments
9597 s/($named_entity_rx)/&write_warnings(
9598 "An unknown named entity ($1) appears in the source text.") unless (
9599 $character_map && eval
9600 "\$${character_map}_character_map_inv\{\$${character_map}_character_map{'$2'}}");
9601 ";SPM$2;"/ego;
9602 }
9604 #RRM: check for numbered character entity out-of-range
9605 if ($HTML_VERSION < 4.0) {
9606 s/$character_entity_rx/&write_warnings(
9607 "An invalid character entity ($1) appears in the source text.")
9608 if ($2 > 255);
9609 $1/ego; }
9611 #RRM: check for invalid named entities outside {rawhtml} environments
9612 # --- these should have been caught already, but check again
9613 s/$named_entity_rx/&write_warnings(
9614 "An unknown named entity ($1) appears in the source text.") unless (
9615 $character_map && eval
9616 "\$${character_map}_character_map_inv\{\$${character_map}_character_map{'$1'}}");
9617 $1/ego;
9619 &revert_to_raw_tex_hook if (defined &revert_to_raw_tex_hook);
9620 $_;
9621 }
9623 sub next_wrapper {
9624 local($dollar) = @_;
9625 local($_,$id);
9626 $wrap_toggle = (($wrap_toggle eq 'end') ? 'begin' : 'end');
9627 $id = ++$global{'max_id'};
9628 $_ = "\\$wrap_toggle$O$id$C"."tex2html_wrap$O$id$C";
9629 $_ = (($wrap_toggle eq 'end') ? $dollar.$_ : $_.$dollar);
9630 $_;
9631 }
9633 sub make_wrapper {
9634 &make_any_wrapper($_[0], '', "tex2html_wrap");
9635 }
9637 sub make_nowrapper {
9638 &make_any_wrapper($_[0], 1, "tex2html_nowrap");
9639 }
9641 sub make_inline_wrapper {
9642 &make_any_wrapper($_[0], '', "tex2html_wrap_inline");
9643 }
9645 sub make_deferred_wrapper {
9646 &make_any_wrapper($_[0], 1, "tex2html_deferred");
9647 }
9649 sub make_nomath_wrapper {
9650 &make_any_wrapper($_[0], '', "tex2html_nomath_inline");
9651 }
9653 sub make_any_wrapper {
9654 local($toggle,$break,$kind) = @_;
9655 local($max_id) = ++$global{'max_id'};
9656 '\\'. (($toggle) ? 'begin' : 'end')
9657 . "$O$max_id$C"."$kind$O$max_id$C"
9658 . (($toggle || !$break) ? '' : '');
9659 }
9661 sub get_last_word {
9662 # Returns the last word in multi-line strings
9663 local($_) = @_;
9664 local ($word,$lastbit,$which);
9665 #JCL(jcl-tcl)
9666 # also remove anchors and other awkward HTML markup
9667 # &extract_pure_text("strict");
9668 ## $_ = &purify($_); ## No. what if it is a verbatim string or image?
9669 #
9670 # while (/\s(\S+)\s*$/g) { $word = $lastbit = $1;}
9672 if (!$_ && (defined $keep)) {
9673 # inside mathematics !
9674 $_ = $keep . $pre ;
9675 }
9676 if (!$_ && $ref_before) { $_ = $ref_before; }
9677 elsif (!$_) {
9678 # get it from last thing before the current environment
9679 $which = $#processedE;
9680 $_ = $processedE[$which];
9681 }
9683 while (/((($O|$OP)\d+($C|$CP))[.\n]*\2|\s(\S+))\s*$/g)
9684 { $word = $lastbit = $1 }
9685 if (($lastbit =~ s/\$\s*$//)||(defined $keep)) {
9686 local($br_idA) = ++$global{'max_id'};
9687 local($br_idB) = ++$global{'max_id'};
9688 $lastbit = join('', "\\begin $O$br_idA${C}tex2html_wrap_inline$O$br_idA$C\$"
9689 , $lastbit, "\$\\end $O$br_idB${C}tex2html_wrap_inline$O$br_idB$C");
9690 $lastbit = &translate_environments($lastbit);
9691 $lastbit = &translate_commands($lastbit);
9692 return ($lastbit);
9693 }
9694 if ($lastbit =~ s/($O|$OP)\d+($C|$CP)//g) { return ($lastbit); }
9695 elsif ($lastbit eq '') { return ($_) }
9697 local($pre_bit);
9698 if ($lastbit =~/>([^>]*)$/) {
9699 $word = $1; $pre_bit = $`.'>';
9700 if ($pre_bit =~ /($verb_mark|$verbstar_mark)$/) {
9701 $word = $lastbit;
9702 } elsif ($pre_bit =~ /<\w+_mark>$/) {
9703 $word = $& . $word;
9704 } elsif (!($word)) {
9705 if ($lastbit =~ s/<([^\/][^>]*)>$//o)
9706 { $word=$1; $pre_bit = $`; }
9707 elsif ($lastbit =~ s/>([^<]*)<\/[^>]*>//o)
9708 { $word=$1; $pre_bit = $`.'>' }
9709 else { $word = ";SPMnbsp;"; }
9710 }
9711 # if ($pre_bit =~ /<\w+_mark>$/) { $word = $& . $word }
9712 } else { $word = $lastbit };
9713 $word;
9714 }
9716 #JCL(jcl-tcl)
9717 # changed completely
9718 #
9719 # We take the first real words specified by $min from the string.
9720 # Allow for simple HTML constructs like <I>...</I> (but not <H*>
9721 # or <P*> and the like), math, or images to remain in the result,
9722 # not counting as words.
9723 # Take care that eg. <I>...</I> grouping tags are not broken.
9724 # This is achieved by lifting the markup, removing superfluous
9725 # words, re-inserting the markup, and throw empty markup away.
9726 # In later versions images could be modified such that they become
9727 # thumbnail sized.
9728 #
9729 # rawhtml or verbatim environments might introduce lots of awkward
9730 # stuff, but yet we leave the according tex2html markers in.
9731 #
9732 sub get_first_words {
9733 local($_, $min) = @_;
9734 local($words,$i);
9735 local($id,%markup);
9736 #no limit if $min is negative
9737 $min = 1000 if ($min < 0);
9739 &remove_anchors;
9740 #strip unwanted HTML constructs
9741 s/<\/?(P|BR|H)[^>]*>/ /g;
9742 #remove leading white space and \001 characters
9743 s/^\s+|\001//g;
9744 #lift html markup, numbered for recovery
9745 s/(<[^>]*>(#[^#]*#)?)/$markup{++$id}=$1; "\000$id\000"/ge;
9747 foreach (split /\s+|\-{3,}/) {
9748 # count words (incl. HTML markup as part of the word)
9749 ++$i;
9750 # $words .= $_ . " " if (/\000/ || ($i <= $min));
9751 $words .= $_ . " " if ($i <= $min);
9752 }
9753 $_ = $words;
9754 chop;
9756 #re-insert markup
9757 s/\000(\d+)\000/$markup{$1}/g;
9758 # remove empty markup
9759 # it's normalized, because generated by LaTeX2HTML only
9760 s/<([A-Z]+)[^>]*>\s*<\/\1>\s*//g;
9761 $_;
9762 }
9764 sub replace_word {
9765 # Replaces the LAST occurrence of $old with $new in $str;
9766 local($str, $old, $new) = @_;
9767 substr($str,rindex($str,$old),length($old)) = $new;
9768 $str;
9769 }
9771 # Returns the recognised sectioning commands as a string of alternatives
9772 # for use in regular expressions;
9773 sub get_current_sections {
9774 local($_, $key);
9775 foreach $key (keys %section_commands) {
9776 if ($key =~ /star/) {
9777 $_ = $key . "|" . $_}
9778 else {
9779 $_ .= "$key" . '[*]?|';
9780 }
9781 }
9782 chop; # Remove the last "|".
9783 $_;
9784 }
9786 sub numerically {
9787 local(@x) = split(' ',$a);
9788 local(@y) = split(' ',$b);
9789 local($i, $result);
9790 for($i=0;$i<$#x;$i++) {
9791 last if ($result = ($x[$i] <=> $y[$i]));
9792 }
9793 $result
9794 }
9796 # Assumes that the files to be sorted are of the form
9797 # <NAME><NUMBER>
9798 sub file_sort {
9799 local($i,$j) = ($a,$b);
9800 $i =~ s/^[^\d]*(\d+)$/$1/;
9801 $j =~ s/^[^\d]*(\d+)$/$1/;
9802 $i <=> $j
9803 }
9805 # If a normalized command name exists, return it.
9806 sub normalize {
9807 # MRO: modified to use $_[1]
9808 # local($cmd,*after) = @_;
9809 my $cmd =$_[0];
9810 my $ncmd;
9811 # Escaped special LaTeX characters
9812 if ($cmd =~ /^($latex_specials_rx)/) {
9813 # $cmd =~ s/&(.*)$/&$1/o;
9814 $cmd =~ s/&(.*)$/$ampersand_mark$1/o;
9815 $cmd =~ s/%/$percent_mark/o;
9816 $_[1] = join('', $cmd, $_[1]);
9817 $cmd = ""}
9818 elsif ($ncmd = $normalize{$cmd}) {
9819 $ncmd;
9820 }
9821 else {
9822 $cmd =~ s/[*]$/star/;
9823 $cmd =~ s/\@/_at_/g;
9824 $cmd;
9825 }
9826 }
9828 sub normalize_sections {
9829 my $dummy = '';
9830 # MRO: s/$sections_rx/'\\' . &normalize($1.$2,*after) . $4/ge;
9831 s/$sections_rx/'\\' . &normalize($1.$2,$dummy) . $4/ge;
9832 }
9834 sub embed_image {
9835 my ($url,$name,$external,$altst,$thumbnail,$map,$align,
9836 $usemap,$exscale,$exstr) = @_;
9837 my $imgID = '';
9838 my $urlimg = $url;
9839 my $ismap = $map ? " ISMAP" : '';
9840 print "\nembedding $url for $name, with $altst\n" if ($VERBOSITY > 1);
9842 if (! ($NO_IMAGES || $PS_IMAGES)) {
9843 # for over-scaled GIFs with pre-determined sizes # RRM 11-9-96
9844 my $size;
9845 if (($width{$name})&&(($exscale)||($EXTRA_IMAGE_SCALE))) {
9846 $exscale = $EXTRA_IMAGE_SCALE unless ($exscale);
9847 if ($name =~ /inline|indisplay|entity|equation|math|eqn|makeimage/){
9848 ($size, $imgID) = &get_image_size($url, $exscale);
9849 } else {
9850 ($size, $imgID) = &get_image_size($url,'');
9851 }
9852 } else {
9853 ($size,$imgID) = &get_image_size($url,'');
9854 }
9855 $image_size{$url} = $size
9856 unless ((! $size) || ($size eq "WIDTH=\"0\" HEIGHT=\"0\""));
9857 $url = &find_unique($url);
9858 }
9860 $urlimg = $url;
9861 $urlimg =~ s/\.$IMAGE_TYPE$/.html/ if ($map);
9862 if ($exstr =~ s/align\s*=\s*(\"?)(\w+)\1($|\s|,)//io) { $align = $2; }
9863 my $usersize = '';
9864 if ($exstr =~ s/width\s*=\s*(\"?)([^\s,]+)\1($|\s|,)//io) {
9865 my ($pxs,$len) = &convert_length($2);
9866 $usersize = " WIDTH=\"$pxs\"";
9867 }
9868 if ($exstr =~ s/height\s*=\s*(\"?)([^\s,]+)\1($|\s|,)//io) {
9869 my ($pxs,$len) = &convert_length($2);
9870 $usersize .= " HEIGHT=\"$pxs\"";
9871 }
9873 my $border = '';
9874 $border = "\" BORDER=\"0"
9875 unless (($HTML_VERSION < 2.2 )||($exstr =~ /BORDER/i));
9877 my $aalign;
9878 if (($name =~ /figure|table|displaymath\d+|eqnarraystar/)&&(!$align)) {
9879 } elsif ($name =~ /displaymath_/) {
9880 $aalign = "MIDDLE".$border;
9881 } elsif (($name =~ /(equation|eqnarray)($|\d)/)&&(!$align)) {
9882 if ($HTML_VERSION >= 3.2) {
9883 $aalign = ($EQN_TAGS eq "L") ? "RIGHT" : "LEFT";
9884 }
9885 } elsif ($name =~ /inline|display|entity|xy|diagram/ && $depth{$name} != 0) {
9886 $aalign = "MIDDLE".$border;
9887 } elsif ($name =~ /inpar/m) {
9888 $aalign = "TOP".$border;
9889 } else { $aalign = "BOTTOM".$border }
9891 $aalign = "\U$align" if $align;
9892 my $ausemp = $usemap ? "\UUSEMAP=$usemap" : '';
9894 #append any extra valid options
9895 $ismap .= &parse_keyvalues ($exstr, ("IMG")) if ($exstr);
9897 $altst = '' if ($ismap =~ /(^|\s+)ALT\s*=/);
9898 if ($altst) {
9899 if ($altst =~ /\s*ALT="?([^\"]+)"?\s*/io) { $altst=$1 }
9900 $altst =~ s/[<>"&]/'&'.$html_special_entities{$&}.';'/eg;
9901 $altst = "\n ALT=\"$altst\"";
9902 }
9904 my ($extern_image_mark,$imagesize);
9905 if ($thumbnail) {
9906 print "\nmaking thumbnail" if ($VERBOSITY > 1);
9907 if (($image_size{$thumbnail}) = &get_image_size($thumbnail,'')) {
9908 $thumbnail = &find_unique($thumbnail);
9909 $imagesize = " ".$image_size{$thumbnail};
9910 if ($HTML_VERSION < 2.2 ) {
9911 # put the WIDTH/HEIGHT information into the ALT string
9912 # first removing the quotes
9913 my ($noquotes) = $imagesize;
9914 $noquotes =~ s/\"//g;
9915 $altst =~ s/"$/\% $noquotes "/m;
9916 $imagesize = '';
9917 }
9918 $extern_image_mark = join('',"<IMG"
9919 , "\n$imagesize"
9920 , (($aalign) ? " ALIGN=\"$aalign\"" : '')
9921 , ("$aalign$imagesize" ? "\n" : '' )
9922 , " SRC=\"$thumbnail\"$altst>");
9923 }
9924 $extern_image_mark =~ s/\s?BORDER="?\d+"?//
9925 unless ($exstr =~ /BORDER/i);
9926 } else {
9927 # MRO: dubious (&extern_image_mark takes only one arg)
9928 $extern_image_mark = &extern_image_mark($IMAGE_TYPE,$altst);
9929 }
9931 my ($anch1,$anch2) = ('','');
9932 my $result;
9933 if ($external || $thumbnail || $EXTERNAL_IMAGES) {
9934 if ( $extern_image_mark ) {
9935 $result = &make_href_noexpand($urlimg, $name , $extern_image_mark);
9936 &save_image_map($url, $urlimg, $map, $name, $altst, $ausemp) if $map;
9937 }
9938 } else {
9939 if ($map) {
9940 $anch1 = "<A HREF=\"$map\">";
9941 $anch2 = "</A>";
9942 }
9943 # if ($aalign eq "CENTER") {
9944 # if ($HTML_VERSION eq "2.0") {
9945 # $anch1 .= "\n<P ALIGN=\"CENTER\">";
9946 # $anch2 .= "</P>";
9947 # } else {
9948 # $anch1 .= "\n<DIV ALIGN=\"CENTER\">";
9949 # $anch2 .= "</DIV>";
9950 # }
9951 # }
9953 $imagesize = $image_size{$url};
9954 $imagesize = $usersize if (($usersize)&&($HTML_VERSION > 2.1 ));
9955 if ($HTML_VERSION < 2.2 ) {
9956 # put the WIDTH/HEIGHT information into the ALT string
9957 # first removing the quotes
9958 my ($noquotes) = $imagesize;
9959 $noquotes =~ s/\"//g;
9960 $altst =~ s/"$/\% $noquotes "/m;
9961 }
9963 # include a stylesheet entry for each included image
9964 if ($USING_STYLES && $SCALABLE_IMAGES &&(!$imgID)) {
9965 if ($url =~ /($dd|^)([^$dd$dd]+)\.$IMAGE_TYPE$/) {
9966 my $img_name = $2;
9967 $imgID = $img_name . ($img_name =~ /img/ ? '' : $IMAGE_TYPE);
9968 $img_style{"$imgID"} = ' ' unless $img_style{"$imgID"};
9969 $imgID = join('', ' CLASS="', $imgID, '"') if $imgID;
9970 }
9971 }
9973 ### MEH Add width and height to IMG
9974 ### Patched by <hswan@perc.Arco.com>: Fixed \htmladdimg
9975 if ( $imagesize || $name eq "external image" || $NO_IMAGES || $PS_IMAGES) {
9976 $imagesize = '' if ($HTML_VERSION < 2.2 );
9977 if ($border =~ s/^"//) { $border .= '"' };
9978 $result = join(''
9979 , "<IMG$imgID"
9980 , "\n", ($imagesize ? " $imagesize" : '')
9981 , (($aalign)? " ALIGN=\"$aalign\"" : $border)
9982 , $ismap );
9983 if ($ausemp) { $result .= " $ausemp" }
9984 $result .= "\n" unless (($result =~ /\n *$/m)|| !$imagesize);
9985 $result .= " SRC=\"$url\"";
9986 if ($altst) { $result .= $altst }
9987 $result .= ">";
9988 }
9989 }
9990 join('',$anch1, $result, $anch2);
9991 }
9993 # MRO: added PNG support
9994 sub get_image_size { # clean
9995 my ($imagefile, $scale) = @_;
9997 $scale = '' if ($scale == 1);
9998 my ($imgID,$size) = ('','');
9999 if (open(IMAGE, "<$imagefile")) {
10000 my ($buffer,$magic,$dummy,$width,$height) = ('','','',0,0);
10001 binmode(IMAGE); # not harmful un UNIX
10002 if ($IMAGE_TYPE =~ /gif/) {
10003 read(IMAGE,$buffer,10);
10004 ($magic,$width,$height) = unpack('a6vv',$buffer);
10005 # is this image sane?
10006 unless($magic =~ /^GIF8[79]a$/ && ($width * $height) > 0) {
10007 $width = $height = 0;
10008 }
10009 }
10010 elsif ($IMAGE_TYPE =~ /png/) {
10011 read(IMAGE,$buffer,24);
10012 ($magic,$dummy,$width,$height) = unpack('a4a12NN',$buffer);
10013 unless($magic eq "\x89PNG" && ($width * $height) > 0) {
10014 $width = $height = 0;
10015 }
10016 }
10017 close(IMAGE);
10019 # adjust for non-trivial $scale factor.
10020 my ($img_w,$img_h) = ($width,$height);
10021 if ($scale && ($width * $height) > 0) {
10022 $img_w = int($width / $scale + .5);
10023 $img_h = int($height / $scale + .5);
10024 }
10025 $size = qq{WIDTH="$img_w" HEIGHT="$img_h"};
10027 # allow height/width to be stored in the stylesheet
10028 my ($img_name,$imgID);
10029 if ($SCALABLE_IMAGES && $USING_STYLES) {
10030 if ($imagefile =~ /(^|[$dd$dd])([^$dd$dd]+)\.(\Q$IMAGE_TYPE\E|old)$/o) {
10031 $img_name = $2;
10032 $imgID = $img_name . ($img_name =~ /img/ ? '' : $IMAGE_TYPE);
10033 }
10034 if ($imgID) {
10035 $width = $width/$LATEX_FONT_SIZE/$MATH_SCALE_FACTOR;
10036 $height = 1.8 * $height/$LATEX_FONT_SIZE/$MATH_SCALE_FACTOR;
10037 # How wide is an em in the most likely browser font ?
10038 if ($scale) {
10039 # How high is an ex in the most likely browser font ?
10040 $width = $width/$scale; $height = $height/$scale;
10041 }
10042 $width = int(100*$width + .5)/100;
10043 $height = int(100*$height + .5)/100;
10044 $img_style{$imgID} = qq(width:${width}em ; height:${height}ex );
10045 #join('','width:',$width,'em ; height:',$height,'ex ');
10046 $imgID = qq{ CLASS="$imgID"};
10047 }
10048 }
10049 }
10050 ($size, $imgID);
10051 }
10053 sub find_unique { # clean
10054 my ($image1) = @_;
10055 local($/) = undef; # slurp in complete files
10057 my $imagedata;
10058 if(open(IMG1,"<$image1")) {
10059 binmode(IMG1); # needed with .png under DOS
10060 $imagedata = <IMG1>;
10061 close(IMG1);
10062 } else {
10063 print "\nError: Cannot read '$image1': $!\n"
10064 unless ($image1 =~ /^\s*$HTTP_start/i);
10065 return $image1;
10066 }
10068 my ($image2,$result);
10069 foreach $image2 (keys(%image_size)) {
10070 if ( $image1 ne $image2 &&
10071 $image_size{$image1} eq $image_size{$image2} ) {
10072 if(open(IMG2,$image2)) {
10073 binmode(IMG2); # needed with .png under DOS
10074 $result = ($imagedata eq <IMG2>);
10075 close(IMG2);
10076 } else {
10077 print "\nWarning: Cannot read '$image2': $!\n"
10078 unless ($image2 =~ /^\s*$HTTP_start/i);
10079 }
10080 #
10081 # If we've found a match, rename the new image to a temporary one.
10082 # Then try to link the new name to the old image.
10083 # If the link fails, restore the temporary image.
10084 #
10085 if ( $result ) {
10086 my $tmp = "temporary.$IMAGE_TYPE";
10087 L2hos->Unlink($tmp);
10088 L2hos->Rename($image1, $tmp);
10089 if (L2hos->Link($image2, $image1)) {
10090 L2hos->Unlink($tmp);
10091 } else {
10092 L2hos->Rename($tmp, $image1);
10093 }
10094 return $image1;
10095 }
10096 }
10097 }
10098 $image1;
10099 }
10101 sub save_image_map { # clean
10102 my ($url, $urlimg, $map, $name, $altst, $ausemp) = @_;
10103 unless(open(IMAGE_MAP, ">$urlimg")) {
10104 print "\nError: Cannot write '$urlimg': $!\n";
10105 return;
10106 }
10107 ### HWS Pass server map unchanged from user
10108 print IMAGE_MAP "<HTML>\n<BODY>\n<A HREF=\"$map\">\n";
10109 print IMAGE_MAP "<IMG\n SRC=\"$url\" ISMAP $ausemp $altst> </A>";
10110 print IMAGE_MAP "</BODY>\n</HTML>\n";
10111 close IMAGE_MAP;
10112 }
10114 # Subroutine used mainly to rename an old image file about to recycled.
10115 # But for active image maps, we must edit the auxiliary HTML file to point
10116 # to the newly renames image.
10117 sub rename_html {
10118 local ($from, $to) = @_;
10119 local ($from_prefix, $to_prefix, $suffix);
10120 ($from_prefix, $suffix) = split(/\./, $from);
10121 ($to_prefix, $suffix) = split(/\./, $to);
10122 if ($EXTN =~ /$suffix$/) {
10123 if (open(FROM, "<$from") && open(HTMP, ">HTML_tmp")) {
10124 while (<FROM>) {
10125 s/$from_prefix\.$IMAGE_TYPE/$to_prefix.$IMAGE_TYPE/g;
10126 print HTMP;
10127 }
10128 close (FROM);
10129 close (HTMP);
10130 L2hos->Rename ("HTML_tmp", $to);
10131 L2hos->Unlink($from) unless ($from eq $to);
10132 }
10133 else {
10134 &write_warnings("File $from is missing!\n");
10135 }
10136 }
10137 L2hos->Rename("$from_prefix.old", "$to_prefix.$IMAGE_TYPE");
10138 $to;
10139 }
10141 sub save_captions_in_file {
10142 local ($type, $_) = @_;
10143 if ($_) {
10144 s/^\n//om;
10145 &replace_markers;
10146 &add_dir_to_href if ($DESTDIR);
10147 if(open(CAPTIONS, ">${PREFIX}$type.pl")) {
10148 print CAPTIONS $_;
10149 close (CAPTIONS);
10150 } else {
10151 print "\nError: Cannot write '${PREFIX}$type.pl': $!\n";
10152 }
10153 }
10154 }
10156 sub add_dir_to_href {
10157 $_ =~ s/'/\\'/g;
10158 $_ =~ s/(<LI><A )(NAME\=\"tex2html\d+\")?\s*(HREF=\")/$1$3\'.\$dir.\'/og;
10159 $_ = join('', "\'", $_, "\'\n");
10160 }
10162 sub save_array_in_file {
10163 local ($type, $array_name, $append, %array) = @_;
10164 local ($uutxt,$file,$prefix,$suffix,$done_file,$depth,$title);
10165 $prefix = $suffix = "";
10166 my $filespec = ($append ? '>>' : '>') . "${PREFIX}$type.pl";
10167 $prefix = q("$URL/" . )
10168 if ($type eq "labels") && !($array_name eq "external\_latex\_labels");
10169 $suffix = " unless (\$$array_name\{\$key\})"
10170 if (($type =~ /(sections|contents)/)||($array_name eq "printable\_key"));
10171 if ((%array)||($type eq "labels")) {
10172 print "\nSAVE_ARRAY:$array_name in FILE: ${PREFIX}$type.pl"
10173 if ($VERBOSITY > 1);
10174 unless(open(FILE,$filespec)) {
10175 print "\nError: Cannot write '${PREFIX}$type.pl': $!\n";
10176 return;
10177 }
10178 if (($array_name eq "sub\_index") || ($array_name eq "printable\_key")) {
10179 print FILE "\n# LaTeX2HTML $TEX2HTMLVERSION\n";
10180 print FILE "# Printable index-keys from $array_name array.\n\n";
10181 } elsif ($array_name eq "index\_labels") {
10182 print FILE "\n# LaTeX2HTML $TEX2HTMLVERSION\n";
10183 print FILE "# labels from $array_name array.\n\n";
10184 } elsif ($array_name eq "index\_segment") {
10185 print FILE "\n# LaTeX2HTML $TEX2HTMLVERSION\n";
10186 print FILE "# segment identifier from $array_name array.\n\n";
10187 } elsif ($array_name eq "external\_latex\_labels") {
10188 print FILE "\n# LaTeX2HTML $TEX2HTMLVERSION\n";
10189 print FILE "# labels from $array_name array.\n\n";
10190 } else {
10191 print FILE "# LaTeX2HTML $TEX2HTMLVERSION\n";
10192 print FILE "# Associate $type original text with physical files.\n\n";
10193 }
10194 while (($uutxt,$file) = each %array) {
10195 $uutxt =~ s|/|\\/|g;
10196 $uutxt =~ s|\\\\/|\\/|g;
10198 if (!($array_name =~/images/)&&($file =~ /</)) {
10199 do { local $_ = $file;
10200 &replace_markers;
10201 $file = $_; undef $_;
10202 $file =~ s/(\G|[^q])[\\\|]\|/$1\\Vert/sg;
10203 $file =~ s/(\G|[^q])\|/$1\\vert/sg;
10204 };
10205 }
10207 local ($nosave);
10208 if ($MULTIPLE_FILES && $ROOTED &&
10209 $type =~ /(sections|contents)/) {
10210 #RRM: save from $THIS_FILE only
10211 if ( $uutxt =~ /^$THIS_FILE /) {
10212 #RRM: save from $THIS_FILE only
10213 $nosave = ''
10214 } else { $nosave = 1 }
10215 } else {
10216 #RRM: suppress info from other segments
10217 $nosave = $noresave{$uutxt};
10218 }
10220 if (!$nosave && ($file ne '')) {
10221 print FILE "\n\$key = q/$uutxt/;\n";
10223 $file =~ s/\|/\\\|/g; # RRM: escape any occurrences of |
10224 $file =~ s/\\\\\|/\\\|/g; # unless already escaped as \|
10225 $file =~ s|\\\\|\\\\\\\\|g;
10226 $file =~ s/(SRC=")($HTTP_start)?/$1.($2 ? '' :"|.\"\$dir\".q|").$2/seg;
10227 #
10228 #
10229 # added code for $dir with segmented docs; RRM 15/3/96
10230 #
10231 if ($type eq "contents") {
10232 ($depth, $done_file) = split($delim, $file, 2 );
10233 next if ($depth > $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH);
10234 print FILE
10235 "\$$array_name\{\$key\} = '$depth$delim'.\"\$dir\".q|$done_file|$suffix; \n";
10237 } elsif ($type eq "sections") {
10238 ($depth, $done_file) = split($delim, $file, 2 );
10239 next if ($depth > $MAX_SPLIT_DEPTH + $MAX_LINK_DEPTH);
10240 print FILE
10241 "\$$array_name\{\$key\} = '$depth$delim'.\"\$dir\".q|$done_file|$suffix; \n";
10243 } elsif ($type eq "internals") {
10244 print FILE
10245 "\$$array_name\{\$key\} = \"\$dir\".q|$file|$suffix; \n";
10247 } elsif ($array_name eq "sub_index") {
10248 print FILE
10249 "\$$array_name\{\$key\} .= q|$file|$suffix; \n";
10251 } elsif ($array_name eq "index") {
10252 local($tmp_file) = '';
10253 ($depth, $done_file) = split('HREF=\"', $file, 2 );
10254 if ($done_file) {
10255 while ($done_file) {
10256 $depth =~ s/\s*$/ / if ($depth);
10257 $tmp_file .= "q|${depth}HREF=\"|.\"\$dir\".";
10258 ($depth, $done_file) = split('HREF=\"', $done_file, 2 );
10259 }
10260 print FILE
10261 "\$$array_name\{\$key\} .= ${tmp_file}q|$depth|$suffix; \n";
10263 } else {
10264 print FILE
10265 "\$$array_name\{\$key\} .= q|$file|$suffix; \n";
10266 }
10267 } elsif ($array_name eq "printable_key") {
10268 print FILE
10269 "\$$array_name\{\$key\} = q|$file|$suffix; \n";
10271 } else {
10272 print FILE
10273 "\$$array_name\{\$key\} = ${prefix}q|$file|$suffix; \n";
10274 }
10276 if ($type =~ /(figure|table|images)/) {} else {
10277 print FILE "\$noresave\{\$key\} = \"\$nosave\";\n";
10278 }
10280 if ($type eq "sections") {
10281 ($depth, $done_file, $title) = split($delim, $file);
10282 print FILE "\$done\{\"\$\{dir\}$done_file\"\} = 1;\n";
10283 }
10284 }
10285 }
10286 print FILE "\n1;\n\n" unless ( $array_name =~ /index/ );
10287 close (FILE);
10288 } else {
10289 print "\nSAVE_FILE:$array_name: ${PREFIX}$type.pl EMPTY " if ($VERBOSITY > 1);
10290 }
10291 }
10293 # returns true if $AUTO_NAVIGATION is on and there are more words in $_
10294 # than $WORDS_IN_PAGE
10295 sub auto_navigation {
10296 # Uses $_;
10297 local(@tmp) = split(/\W*\s+\W*/, $_);
10298 ($AUTO_NAVIGATION && ( (scalar @tmp) > $WORDS_IN_PAGE));
10299 }
10301 # Returns true if $f1 is newer than $f2
10302 sub newer {
10303 ($f1,$f2) = @_;
10304 local(@f1s) = stat($f1);
10305 local(@f2s) = stat($f2);
10306 ($f1s[9] > $f2s[9]);
10307 };
10309 sub iso_map {
10310 local($char, $kind, $quiet) = @_;
10311 my($character_map,$enc);
10312 local ($this);
10314 if ( $CHARSET && $HTML_VERSION ge "2.1" ) {
10315 # see if it is a character in the charset
10316 $character_map = ((($charset =~ /utf/)&&!$NO_UTF)?
10317 'iso_10646' : $CHARSET );
10318 $character_map =~ tr/-/_/;
10319 eval "\$enc = \$${character_map}_character_map\{\"$char$kind\"\}";
10320 print "\n no support for $CHARSET: $@ " if ($@);
10321 }
10322 if ($USE_ENTITY_NAMES && $enc) { return(";SPM$char$kind;") }
10324 if ($enc) {
10325 $enc =~ /^\&\#(\d{3});$/;
10326 # maybe convert it to an 8-bit character
10327 if ($NO_UTF && !$USE_UTF && ($1<=255)) { $enc = chr($1) }
10328 # elsif (!$USE_UTF &&($1>127)&&($1<160)) { $enc = chr($1) }
10329 elsif ($character_map !~ /^iso_(8859_1|10646)/) {
10330 # get its latin1 or unicode entity encoding
10331 $enc = $iso_8859_1_character_map{"$char$kind"}
10332 ||$iso_8859_1A_character_map{"$char$kind"}
10333 ||$iso_10646_character_map{"$char$kind"}
10334 }
10335 } else {
10336 # get its latin1 or unicode entity encoding, if available
10337 $enc = $iso_8859_1_character_map{"$char$kind"}
10338 ||$iso_8859_1A_character_map{"$char$kind"}
10339 ||$iso_10646_character_map{"$char$kind"};
10340 }
10342 if ($enc) {
10343 $ISOLATIN_CHARS = 1; $enc;
10344 } elsif (!$image_made{"$char$kind"}) {
10345 print "\ncouldn't convert character $char$kind into available encodings"
10346 if (!quiet &&($VERBOSITY > 1));
10347 &write_warnings(
10348 "couldn't convert character $char$kind into available encodings"
10349 . ($ACCENT_IMAGES ? ', using image' : '')) unless ($quiet);
10350 $image_made{"$char$kind"} = 1;
10351 '';
10352 } else {''}
10353 }
10355 sub titles_language {
10356 local($_) = @_;
10357 local($lang) = $_ . "_titles";
10358 if (defined(&$lang)) { &$lang }
10359 else {
10360 &english_titles;
10361 &write_warnings(
10362 "\nThere is currently no support for the $tmp language." .
10363 "\nSee the file $CONFIG_FILE for examples on how to add it\n\n");
10364 }
10365 }
10367 sub translate_titles {
10368 $toc_title = &translate_commands($toc_title) if ($toc_title =~ /\\/);
10369 $lof_title = &translate_commands($lof_title) if ($lof_title =~ /\\/);
10370 $lot_title = &translate_commands($lot_title) if ($lot_title =~ /\\/);
10371 $idx_title = &translate_commands($idx_title) if ($idx_title =~ /\\/);
10372 $ref_title = &translate_commands($ref_title) if ($ref_title =~ /\\/);
10373 $bib_title = &translate_commands($bib_title) if ($bib_title =~ /\\/);
10374 $abs_title = &translate_commands($abs_title) if ($abs_title =~ /\\/);
10375 $app_title = &translate_commands($app_title) if ($app_title =~ /\\/);
10376 $pre_title = &translate_commands($pre_title) if ($pre_title =~ /\\/);
10377 $foot_title = &translate_commands($foot_title) if ($foot_title =~ /\\/);
10378 $fig_name = &translate_commands($fig_name) if ($fig_name =~ /\\/);
10379 $tab_name = &translate_commands($tab_name) if ($tab_name =~ /\\/);
10380 $prf_name = &translate_commands($prf_name) if ($prf_name =~ /\\/);
10381 $page_name = &translate_commands($page_name) if ($page_name =~ /\\/);
10382 $child_name = &translate_commands($child_name) if ($child_name =~ /\\/);
10383 $info_title = &translate_commands($info_title) if ($info_title =~ /\\/);
10384 $part_name = &translate_commands($part_name) if ($part_name =~ /\\/);
10385 $chapter_name = &translate_commands($chapter_name)
10386 if ($chapter_name =~ /\\/);
10387 $section_name = &translate_commands($section_name)
10388 if ($section_name =~ /\\/);
10389 $subsection_name = &translate_commands($subsection_name)
10390 if ($subsection_name =~ /\\/);
10391 $subsubsection_name = &translate_commands($subsubsection_name)
10392 if ($subsubsection_name =~ /\\/);
10393 $paragraph_name = &translate_commands($paragraph_name)
10394 if ($paragraph_name =~ /\\/);
10395 $see_name = &translate_commands($see_name) if ($see_name =~ /\\/);
10396 $also_name = &translate_commands($also_name) if ($also_name =~ /\\/);
10397 $next_name = &translate_commands($next_name) if ($next_name =~ /\\/);
10398 $prev_name = &translate_commands($prev_name) if ($prev_name =~ /\\/);
10399 $up_name = &translate_commands($up_name) if ($up_name =~ /\\/);
10400 $group_name = &translate_commands($group_name) if ($group_name =~ /\\/);
10401 $encl_name = &translate_commands($encl_name) if ($encl_name =~ /\\/);
10402 $headto_name = &translate_commands($headto_name) if ($headto_name =~ /\\/);
10403 $cc_name = &translate_commands($cc_name) if ($cc_name =~ /\\/);
10404 $default_title = &translate_commands($default_title)
10405 if ($default_title =~ /\\/);
10406 }
10407 ####################### Code Generation Subroutines ############################
10408 # This takes a string of commands followed by optional or compulsory
10409 # argument markers and generates a subroutine for each command that will
10410 # ignore the command and its arguments.
10411 # The commands are separated by newlines and have the format:
10412 ## <cmd_name>#{}# []# {}# [] etc.
10413 # {} marks a compulsory argument and [] an optional one.
10414 sub ignore_commands {
10415 local($_) = @_;
10416 foreach (/.*\n?/g) {
10417 s/\n//g;
10418 # For each line
10419 local($cmd, @args) = split('\s*#\s*',$_);
10420 next unless $cmd;
10421 $cmd =~ s/ //;
10422 ++$ignore{$cmd};
10423 local ($body, $code, $thisone) = ("", "");
10425 # alter the pattern here to debug particular commands
10426 $thisone = 1 if ($cmd =~ /let/);
10428 if (@args) {
10429 print "\n$cmd: ".scalar(@args)." arguments" if ($thisone);
10430 # Replace the argument markers with appropriate patterns
10431 foreach $arg (@args) {
10432 print "\nARG: $arg" if ($thisone);
10433 if ($arg =~ /\{\}/) {
10434 $body .= 'local($cmd) = '."\"$cmd\"".";\n";
10435 $body .= '$args .= &missing_braces'."\n ".'unless (';
10436 $body .= '(s/$next_pair_pr_rx/$args .= $2;\'\'/eo)'."\n";
10437 $body .= ' ||(s/$next_pair_rx/$args .= $2;\'\'/eo));'."\n";
10438 print "\nAFTER:$'" if (($thisone)&&($'));
10439 $body .= $' if ($');
10440 } elsif ($arg =~ /\[\]/) {
10441 $body .= '($dummy, $pat) = &get_next_optional_argument;'
10442 . '$args .= $pat;'."\n";
10443 print "\nAFTER:$'" if (($thisone)&&($'));
10444 $body .= $' if ($');
10445 } elsif ($arg =~ /^\s*\\/) {
10446 $body .= '($dummy, $pat) = &get_next_tex_cmd;'
10447 . '$args .= $pat;'."\n";
10448 print "\nAFTER:$'" if (($thisone)&&($'));
10449 $body .= $' if ($');
10450 } elsif ($arg =~ /<<\s*([^>]*)[\b\s]*>>/) {
10451 local($endcmd, $after) = ($1,$');
10452 $after =~ s/(^\s*|\s*$)//g;
10453 $endcmd = &escape_rx_chars($endcmd);
10454 $body .= 'if (/'.$endcmd.'/o) { $args .= $`; $_ = $\' };'."\n";
10455 print "\nAFTER:$after" if (($thisone)&&($after));
10456 $body .= "$after" if ($after);
10457 } else {
10458 print "\nAFTER:$'" if (($thisone)&&($arg));
10459 $body .= $arg ;
10460 }
10461 }
10462 # Generate a new subroutine
10463 # $code = "sub do_cmd_$cmd {\n".'local($_) = @_;'. join('',@args) .'$_}';
10464 $code = "sub do_cmd_$cmd {\n"
10465 . 'local($_,$ot) = @_; '
10466 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R; '
10467 . 'local($args); '
10468 . "\n" . $body . (($body)? ";\n" : '')
10469 . (($thisone)? "print \"\\n$cmd:\".\$args.\"\\n\";\n" : '')
10470 . (($arg)? $arg : '$_') . "}";
10471 print STDOUT "\n$code\n" if ($thisone); # for error-checking
10472 eval ($code); # unless ($thisone);
10473 print STDERR "\n\n*** sub do_cmd_$cmd failed: $@\n" if ($@);
10474 } else {
10475 $code = "sub do_cmd_$cmd {\n".'$_[0]}';
10476 print "\n$code\n" if ($thisone); # for error-checking
10477 eval ($code); # unless ($thisone);
10478 print STDERR "\n\n*** sub do_cmd_$cmd failed: $@\n" if ($@);
10479 }
10480 }
10481 }
10484 sub ignore_numeric_argument {
10485 # Chop this off
10486 #RRM: 2001/11/8: beware of taking too much, when <num> <num>
10487 local($num) = '(^|width|height|plus|minus)\s*[+-]?[\d\.]+(cm|em|ex|in|pc|pt|mm)?\s*';
10488 do { s/^\s*=?\s*//so; s/^($num)*//so } unless (/^(\s*\<\<\d+\>\>|$)/);
10489 }
10491 sub get_numeric_argument {
10492 my ($num_rx,$num) = ('','');
10493 # Collect the numeric part
10494 #RRM: 2001/11/8: beware of taking too much, when <num> <num>
10495 $num_rx = '(^|width|height|plus|minus)\s*[+-]?[\d\.]+(cm|em|ex|in|pc|pt|mm)?\s*';
10496 do { s/^\s*=?\s*//so; s/($num_rx)*/$num=$&;''/soe } unless (/^(\s*\<\<\d+\>\>|$)/);
10497 $num;
10498 }
10500 sub process_in_latex_helper {
10501 local($ctr,$val,$cmd) = @_;
10502 ($ASCII_MODE ? "[$cmd]" :
10503 &process_in_latex("\\setcounter{$ctr}{$val}\\$cmd"))
10504 }
10506 sub do_cmd_catcode {
10507 local($_) = @_;
10508 s/^\s*[^=]+(=?\s*\d+\s|\\active)\s?//;
10509 $_;
10510 }
10512 sub do_cmd_string {
10513 local($_) = @_;
10514 local($tok);
10515 s/^\s*(\\([a-zA-Z]+|.)|[&;]\w+;(#\w+;)?|.)/$tok=$1;''/e;
10516 if ($2) {$tok = "\\$2"};
10517 "$tok".$_
10518 }
10520 sub do_cmd_boldmath {
10521 local($_) = @_;
10522 $BOLD_MATH = 1;
10523 $_;
10524 }
10526 sub do_cmd_unboldmath {
10527 local($_) = @_;
10528 $BOLD_MATH = 0;
10529 $_;
10530 }
10532 sub do_cmd_lq {
10533 local($_) = @_ ;
10534 local($lquote);
10535 # check for double quotes
10536 if (s/^\s*\\lq(\b|$|[^A-Za-z])/$1/) {
10537 $lquote = ((($HTML_VERSION < 4)&&!($charset =~ /utf/)) ? '``'
10538 : &do_leftquotes($_));
10539 } else {
10540 $lquote = ((($HTML_VERSION < 4)&&!($charset =~ /utf/)) ? '`'
10541 : &do_leftquote($_));
10542 }
10543 $lquote . $_;
10544 }
10546 sub do_leftquote {
10547 # MRO: use $_[0] : local(*_) = @_;
10548 local($quote,$lquo) = ('',($HTML_VERSION<5)? '‘' : ';SPMlsquo;');
10549 # select whole quotation, if \lq matches \rq
10550 if ($_[0] =~ /^(.*)((\\rq\\rq|'')*)(\\rq)/) {
10551 $quote = $1.$2; $_[0] = $';
10552 local($rquo) = &do_rightquote();
10553 &process_quote($lquo,$quote,$rquo);
10554 } else { $lquo; }
10555 }
10557 sub do_leftquotes {
10558 # MRO: use $_[0] : local(*_) = @_;
10559 local($quote,$lquo) = ('',($HTML_VERSION<5)? '“' : ';SPMldquo;');
10560 # select whole quotation, if \lq\lq matches \rq\rq or ''
10561 if ($_[0] =~ /^(.*)(\\rq\\rq|'')/) {
10562 $quote = $1; $_[0] = $';
10563 local($rquo) = &do_rightquotes();
10564 &process_quote($lquo,$quote,$rquo);
10565 } else { $lquo; }
10566 }
10568 # RRM: By default this just concatenates the strings; e.g. ` <quote> '
10569 # This can be overridden in a html-version file
10570 sub process_quote { join ('', @_) }
10572 sub do_cmd_rq {
10573 local($_) = @_ ;
10574 local($rquote);
10575 if ($_ =~ s/^\s*\\rq\b//) {
10576 $rquote = ((($HTML_VERSION < 4)&&!($charset =~ /utf/)) ? "''"
10577 : &do_rightquotes());
10578 } else {
10579 $rquote = ((($HTML_VERSION < 4)&&!($charset =~ /utf/)) ? "'"
10580 : &do_rightquote());
10581 }
10582 $rquote . $_;
10583 }
10585 sub do_rightquote { (($HTML_VERSION < 5)? '’' : ';SPMrsquo;') }
10586 sub do_rightquotes { (($HTML_VERSION < 5)? '”' : ';SPMrdquo;') }
10588 sub do_cmd_parbox {
10589 local($_) = @_;
10590 local($args, $contents, $dum, $pat);
10591 $* = 1; # Multiline matching ON
10592 ($dum,$pat) = &get_next_optional_argument; # discard this
10593 ($dum,$pat) = &get_next_optional_argument; # discard this
10594 ($dum,$pat) = &get_next_optional_argument; # discard this
10595 $args .= $pat if ($pat);
10596 $pat = &missing_braces unless (
10597 (s/$next_pair_pr_rx/$pat=$2;''/eo)
10598 ||(s/$next_pair_rx/$pat=$2;''/eo));
10599 $args .= "{".$`.$pat."}";
10600 $contents = &missing_braces unless (
10601 (s/$next_pair_pr_rx/$contents=$2;''/eo)
10602 ||(s/$next_pair_rx/$contents=$2;''/eo));
10603 $* = 0; # Multiline matching OFF
10604 $args .= "{".$`.$contents."}";
10605 if ($NO_PARBOX_IMAGES) {
10606 $contents = join ('', &do_cmd_par(), $contents, '</P>' );
10607 } else {
10608 $contents = &process_math_in_latex('','text',0,"\\parbox$args")
10609 if ($contents);
10610 }
10611 $contents . $_;
10612 }
10615 sub do_cmd_mbox {
10616 local($_) = @_;
10617 local($text,$after)=('','');
10618 $text = &missing_braces unless (
10619 (s/$next_pair_pr_rx/$text = $2;''/eo)
10620 ||(s/$next_pair_rx/$text = $2;''/eo));
10621 $after = $_;
10623 # incomplete macro replacement
10624 if ($text =~ /(^|[^\\<])#\d/) { return($after) }
10626 if ($text =~ /(tex2html_wrap_inline|\$$OP(\d+)$CP$OP\2$CP\$|\$$O(\d+)$C$O\2$C\$)/) {
10627 if ($text =~
10628 /$image_mark#([^#]+)#([\.,;:\)\]])?(\001)?([ \t]*\n?)(\001)?/) {
10629 local($mbefore, $mtext, $mafter) = ($`, $&, $');
10630 $mbefore = &translate_commands($mbefore) if ($mbefore =~ /\\/);
10631 $mafter = &translate_commands($mafter) if ($mafter =~ /\\/);
10632 join('', $mbefore, $mtext, $mafter, $after);
10633 } else {
10634 join ('', &process_math_in_latex('','','',"\\hbox{$text}"), $after )
10635 }
10636 } else {
10637 $text = &translate_environments($text);
10638 $text = &translate_commands($text);
10639 join('', $text, $after);
10640 }
10641 }
10645 # *Generates* subroutines to handle each of the declarations
10646 # like \em, \quote etc., in case they appear with the begin-end
10647 # syntax.
10648 sub generate_declaration_subs {
10649 local($key, $val, $pre, $post, $code );
10650 print "\n *** processing declarations ***\n";
10651 while ( ($key, $val) = each %declarations) {
10652 if ($val) {
10653 ($pre,$post) = ('','');
10654 $val =~ m|</.*$|;
10655 do {$pre = $`; $post = $& } unless ($` =~ /^<>/);
10656 $pre =~ s/"/\\"/g; $post =~ s/"/\\"/g;
10657 $code = "sub do_env_$key {"
10658 # . 'local($_) = @_;' . "\n"
10659 # . 'push(@$open_tags_R, $key);'. "\n"
10660 # . '$_ = &translate_environments($_);'. "\n"
10661 # . '$_ = &translate_commands($_);'. "\n"
10662 # . "join('',\"$pre\",\"\\n\"," .'$_' .",\"$post\");\n};";
10663 . '&declared_env('.$key.',@_)};';
10664 eval $code;
10665 if ($@) {print "\n *** $key ". $@ };
10666 }
10667 }
10668 }
10670 # *Generates* subroutines to handle each of the sectioning commands.
10671 sub generate_sectioning_subs {
10672 local($key, $val, $cmd, $body);
10673 while ( ($key, $val) = each %standard_section_headings) {
10674 $numbered_section{$key} = 0;
10675 eval "sub do_cmd_$key {"
10676 . 'local($after,$ot) = @_;'
10677 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'
10678 . '&reset_dependents('. $key . ');'
10679 . '&do_cmd_section_helper('.$val.','.$key.');}';
10680 print STDERR "\n*** sub do_cmd_$key failed:\n$@\n" if ($@);
10681 # Now define the *-form of the same commands. The difference is that the
10682 # $key is not passed as an argument.
10683 eval "sub do_cmd_$key" . "star {"
10684 . 'local($after,$ot) = @_;'
10685 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'
10686 . '&do_cmd_section_helper(' . $val . ');}';
10687 print STDERR "\n*** sub do_cmd_${key}star failed:\n$@\n" if ($@);
10688 # Now define the macro \the$key
10689 &process_commands_wrap_deferred("the$key \# {}\n");
10690 ### local($_) = "<<1>>$key<<1>>";
10691 $body = "<<1>>$key<<1>>";
10692 &make_unique($body);
10693 $cmd = "the$key";
10694 eval "sub do_cmd_$cmd {"
10695 . 'local($after,$ot) = @_;'
10696 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'
10697 . '&do_cmd_arabic(' . "\"$body\"" . ").\$after;};";
10698 print STDERR "\n*** sub do_cmd_$cmd failed:\n$@\n" if ($@);
10699 $raw_arg_cmds{$cmd} = 1;
10700 }
10701 &addto_dependents('chapter','section');
10702 &addto_dependents('section','subsection');
10703 &addto_dependents('subsection','subsubsection');
10704 &addto_dependents('subsubsection','paragraph');
10705 &addto_dependents('paragraph','subparagraph');
10706 }
10708 sub addto_dependents {
10709 local($ctr, $dep) = @_;
10710 local($tmp, $depends);
10711 if ($depends = $depends_on{$dep}) {
10712 &remove_dependency($depends, $dep) }
10713 $depends_on{$dep} = $ctr;
10715 $tmp = $dependent{$ctr};
10716 if ($tmp) {
10717 $dependent{$ctr} = join($delim, $tmp, $dep);
10718 } else { $dependent{$ctr} = $dep }
10719 }
10721 sub remove_dependency {
10722 local($ctr, $dep) = @_;
10723 local(@tmp, $tmp, $dtmp);
10724 print "\nremoving dependency of counter {$dep} from {$ctr}\n";
10725 foreach $dtmp (split($delim, $dependent{$ctr})) {
10726 push(@tmp, $dtmp) unless ($dtmp =~ /$dep/);
10727 }
10728 $dependent{$ctr} = join($delim, @tmp);
10729 }
10732 # Uses $after which is defined in the caller (the caller is a generated subroutine)
10733 # Also uses @curr_sec_id
10734 #
10735 #JCL(jcl-tcl) (changed almost everything)
10736 #
10737 sub do_cmd_section_helper {
10738 local($H,$key) = @_;
10739 local($section_number, $titletext, $title_key, @tmp, $align, $dummy);
10740 local($anchors,$pre,$run_title,$_) = ('', "\n", '', $after);
10741 local($open_tags_R) = [];
10743 # if we have a $key the current section is not of the *-form, so we need
10744 # to update the counters.
10745 &do_cmd_stepcounter("${O}0$C$key${O}0$C")
10746 # if ($key && !$making_name);
10747 # if ($key && !($unnumbered_section_commands{$key}) && !$making_name);
10748 if ($key && !($unnumbered_section_commands{$key}));
10749 # $latex_body .= "\\stepcounter{$key}\n" if $key;
10750 # &reset_dependents($key) if ($dependent{$key});
10752 local($br_id);
10753 # if ($USING_STYLES) {
10754 # $txt_style{"H$H.$key"} = " " unless $txt_style{"H$H.$key"};
10755 # $H .= " CLASS=\"$key\";
10756 # };
10758 local ($align, $dummy)=&get_next_optional_argument;
10759 if (($align =~/^(left|right|center)$/i)&&($HTML_VERSION > 2.0)) {
10760 $align = "ALIGN=\"$1\"";
10761 } elsif ($align) {
10762 # data was meant to be a running-head !
10763 $br_id = ++$global{'max_id'};
10764 $run_title = &translate_environments("$O$br_id$C$align$O$br_id$C");
10765 $run_title = &translate_commands($run_title) if ($run_title =~ /\\/);
10766 $run_title =~ s/($O|$OP)\d+($C|$CP)//g;
10767 $align = '';
10768 } else {
10769 }
10770 $titletext = &missing_braces
10771 unless s/$next_pair_rx/$titletext=$2;''/eo;
10772 $br_id = ++$global{'max_id'};
10773 $titletext = &translate_environments("$O$br_id$C$titletext$O$br_id$C");
10775 $title_key = $run_title || $titletext;
10776 $title_key =~ s/$image_mark\#([^\#]+)\#(\\space)?/&purify_caption($1)/e;
10777 # This should reduce to the same information as contained in the .aux file.
10778 $title_key = &sanitize(&simplify($title_key));
10780 # RRM: collect all anchors from \label and \index commands
10781 ($anchors,$titletext) = &extract_anchors($titletext);
10782 local($saved_title) = $titletext;
10783 do {
10784 # to ensure a style ID is not saved and re-used in (mini-)TOCs
10785 local($USING_STYLES) = 0;
10786 $titletext = &translate_environments($titletext);
10787 $titletext = &translate_commands($titletext)
10788 if ($titletext =~/\\/);
10789 };
10790 # but the style ID can be used for the title on the HTML page
10791 if (!($titletext eq $saved_title)) {
10792 $saved_title = &translate_environments($saved_title);
10793 $saved_title = &translate_commands($saved_title)
10794 if ($saved_title =~/\\/);
10795 $saved_title = &simplify($saved_title);
10796 }
10797 local($closures) = &close_all_tags();
10798 $saved_title .= $closures;
10799 $title_text .= $closures;
10801 # This is the LaTeX section number read from the $FILE.aux file
10802 @tmp = split(/$;/,$encoded_section_number{$title_key});
10803 $section_number = shift(@tmp);
10804 $section_number = "" if ($section_number eq "-1");
10805 $encoded_section_number{$title_key} = join($;, @tmp)
10806 # unless (defined $title);
10807 unless ($title);
10809 # need to check also &{wrap_cmd_... also, if \renewcommand has been used;
10810 # thanks Bruce Miller
10811 local($thehead,$whead) = ("do_cmd_the$key","wrap_cmd_the$key");
10812 # $thehead = ((defined &$thehead)?
10813 # &translate_commands("\\the$key") : '');
10814 $thehead = ((defined &$thehead)||(defined &$whead)
10815 ? &translate_commands("\\the$key") : '');
10816 $thehead .= $SECNUM_PUNCT
10817 if ($SECNUM_PUNCT &&($thehead)&& !($thehead =~ /\./));
10818 $section_number = $thehead if (($thehead)&&($SHOW_SECTION_NUMBERS));
10820 #JKR: Don't prepend whitespace
10821 if ($section_number) {
10822 $titletext = "$section_number " . $titletext;
10823 $saved_title = "$section_number " . $saved_title;
10824 $run_title = "$section_number " . $run_title if $run_title;
10825 }
10827 # $toc_sec_title = $titletext;
10828 # $toc_sec_title = &purify($titletext);
10829 $toc_sec_title = &simplify($titletext);
10830 $titletext = &simplify($titletext);
10831 # $TITLE = &purify($titletext);
10832 local($after) = $_;
10833 do {
10834 local($_) = $titletext; &remove_anchors;
10835 if ($run_title) {
10836 $TITLE = $run_title;
10837 } elsif ($_) {
10838 $TITLE = $_
10839 } else { $TITLE = '.' };
10840 };
10841 $global{$key}-- if ($key && $making_name);
10842 return ($TITLE) if (defined $title);
10844 #RRM: no preceding \n when this is the first section-head on the page.
10845 if (! $key || $key < $MAX_SPLIT_DEPTH) { $pre = '' };
10846 if ( defined &make_pre_title) {
10847 $pre = &make_pre_title($saved_title, $H);
10848 }
10850 undef $open_tags_R;
10851 $open_tags_R = [ @save_open_tags ];
10853 join('', $pre, &make_section_heading($saved_title, $H, $align.$anchors)
10854 , $open_all, $_);
10855 }
10857 sub do_cmd_documentclass {
10858 local($_) = @_;
10859 local ($docclass)=('');
10860 local ($cloptions,$dum)=&get_next_optional_argument;
10861 $docclass = &missing_braces unless (
10862 (s/$next_pair_pr_rx/$docclass = $2;''/eo)
10863 ||(s/$next_pair_rx/$docclass = $2;''/eo));
10864 local($rest) = $';
10865 &do_require_package($docclass);
10866 if (! $styles_loaded{$docclass}) {
10867 &no_implementation("document class",$docclass);
10868 } else {
10869 if($cloptions =~ /\S+/) { # are there any options?
10870 &do_package_options($docclass,$cloptions);
10871 }
10872 }
10873 $rest;
10874 }
10875 sub do_cmd_documentstyle { &do_cmd_documentclass($_[0]); }
10877 sub do_cmd_usepackage {
10878 local($_) = @_;
10879 # RRM: allow lists of packages and options
10880 local ($package, $packages)=('','');
10881 local ($options,$dum)=&get_next_optional_argument;
10882 $packages = &missing_braces unless (
10883 (s/$next_pair_pr_rx/$packages = $2;''/eo)
10884 ||(s/$next_pair_rx/$packages = $2;''/eo));
10885 local($rest) = $_;
10886 # MRO: The files should have already been loaded by
10887 # TMP_styles, but we better make it sure.
10888 foreach $package (split (',',$packages)) { # allow multiple packages
10889 $package =~ s/\s|\%|$comment_mark\d*//g; # remove whitespace
10890 $package =~ s/\W/_/g; # replace non-alphanumerics
10891 &do_require_package($package);
10892 if (! $styles_loaded{$package}) {
10893 &no_implementation("package",$package);
10894 } else {
10895 if($options =~ /\S+/) { # are there any options?
10896 &do_package_options($package,$options);
10897 }
10898 }
10899 }
10900 $rest;
10901 }
10904 sub no_implementation {
10905 local($what,$which)= @_;
10906 print STDERR "\nWarning: No implementation found for $what: $which";
10907 }
10909 sub do_cmd_RequirePackage {
10910 local($_)= @_;
10911 local($file);
10912 local($options,$dum)=&get_next_optional_argument;
10913 $file = &missing_braces unless (
10914 (s/$next_pair_pr_rx/$file = $2;''/eo)
10915 ||(s/$next_pair_rx/$file = $2;''/eo));
10916 local($rest) = $_;
10917 $file =~ s/^[\s\t\n]*//o;
10918 $file =~ s/[\s\t\n]*$//o;
10919 # load the package, unless that has already been done
10920 &do_require_package($file) unless ($styles_loaded{$file});
10921 # process any options
10922 if (! $styles_loaded{$file}) {
10923 &no_implementation("style",$file);
10924 } else {
10925 # process any options
10926 &do_package_options($file,$options) if ($options);
10927 }
10928 $_ = $rest;
10929 # ignore trailing optional argument
10930 local($date,$dum)=&get_next_optional_argument;
10931 $_;
10932 }
10934 sub do_cmd_PassOptionsToPackage {
10935 local($_) = @_;
10936 local($options,$file);
10937 $options = &missing_braces unless (
10938 (s/$next_pair_pr_rx/$options = $2;''/eo)
10939 ||(s/$next_pair_rx/$options = $2;''/eo));
10940 $file = &missing_braces unless (
10941 (s/$next_pair_pr_rx/$file = $2;''/eo)
10942 ||(s/$next_pair_rx/$file = $2;''/eo));
10943 $passedOptions{$file} = $options;
10944 $_;
10945 }
10946 sub do_cmd_PassOptionsToClass{ &do_cmd_PassOptionsToPackage(@_)}
10948 sub do_package_options {
10949 local($package,$options)=@_;
10950 local($option);
10951 if ($passedOptions{$package}) { $options = $passedOptions{$package}.'.'.$options };
10952 foreach $option (split (',',$options)) {
10953 $option =~ s/^[\s\t\n]*//o;
10954 $option =~ s/[\s\t\n]*$//o;
10955 $option =~ s/\W/_/g; # replace non-alphanumerics
10956 next unless ($option);
10957 if (!($styles_loaded{$package."_$option"})) {
10958 &do_require_packageoption($package."_$option");
10959 if (!($styles_loaded{$package."_$option"})) {
10960 &no_implementation("option","\`$option\' for \`$package\' package\n");
10961 }
10962 }
10963 }
10964 $rest;
10965 }
10967 sub do_class_options {
10968 local($class,$options)=@_;
10969 local($option);
10970 if ($passedOptions{$class}) { $options = $passedOptions{$class}.'.'.$options };
10971 foreach $option (split (',',$options)) {
10972 $option =~ s/^[\s\t\n]*//o;
10973 $option =~ s/[\s\t\n]*$//o;
10974 $option =~ s/\W/_/g; # replace non-alphanumerics
10975 next unless ($option);
10976 &do_require_package($option);
10977 if (!($styles_loaded{$class."_$option"})) {
10978 &do_require_packageoption($class."_$option");
10979 if (!($styles_loaded{$class."_$option"})) {
10980 &no_implementation("option","\`$option\' for document-class \`$class\'\n");
10981 }
10982 }
10983 }
10984 $rest;
10985 }
10987 sub do_require_package {
10988 local($file)= @_;
10989 local($dir);
10990 #RRM: make common ps/eps-packages use epsfig.perl
10991 $file = 'epsfig' if ($file =~ /^(psfig|epsf)$/);
10993 if ($file =~ /^graphicx$/) {
10994 # work-around the CVS repository bug: use graphixx , not graphicx
10995 foreach $dir (split(/$envkey/,$LATEX2HTMLSTYLES)) {
10996 if (-f "$dir${dd}graphixx.perl") {
10997 $file = 'graphixx';
10998 last;
10999 }
11000 }
11001 }
11004 if (! $styles_loaded{$file}) {
11005 # look for a file named ${file}.perl
11006 # MRO: use $texfilepath instead of `..'
11007 if ((-f "$texfilepath$dd${file}.perl") && ! $styles_loaded{$file}){
11008 print STDOUT "\nPackage: loading $texfilepath$dd${file}.perl";
11009 require("$texfilepath$dd${file}.perl");
11010 $styles_loaded{$file} = 1;
11011 } else {
11012 foreach $dir (split(/$envkey/,$LATEX2HTMLSTYLES)) {
11013 if ((-f "$dir$dd${file}.perl") && ! $styles_loaded{$file}){
11014 print STDOUT "\nPackage: loading $dir$dd${file}.perl";
11015 require("$dir$dd${file}.perl");
11016 $styles_loaded{$file} = 1;
11017 last;
11018 }
11019 }
11020 }
11021 }
11022 }
11024 sub do_require_extension {
11025 local($file)= @_;
11026 local($dir);
11028 if (! $styles_loaded{$file}) {
11029 # look for a file named ${file}.pl
11030 # MRO: use $texfilepath instead of `..'
11031 if (-f "$texfilepath$dd${file}.pl") {
11032 print STDOUT "\nExtension: loading $texfilepath$dd${file}.pl";
11033 require("$texfilepath$dd${file}.pl");
11034 ++$styles_loaded{$file};
11035 $NO_UTF = 1 if (($file =~ /latin/)&&($charset =~/utf/));
11036 } else {
11037 foreach $dir (split(/$envkey/,$LATEX2HTMLVERSIONS)) {
11038 if (-f "$dir$dd${file}.pl"){
11039 print STDOUT "\nExtension: loading $dir$dd${file}.pl";
11040 require("$dir$dd${file}.pl");
11041 ++$styles_loaded{$file};
11042 $NO_UTF = 1 if (($file =~ /latin/)&&($charset =~/utf/));
11043 last;
11044 }
11045 }
11046 }
11047 } else {
11048 if (($file =~ /latin|hebrew/)&&($charset =~/utf|10646/)
11049 && $loading_extensions) {
11050 $NO_UTF = 1;
11051 $USE_UTF = 0;
11052 print STDOUT "\n\n ...producing $CHARSET output\n";
11053 $charset = $CHARSET;
11054 }
11055 }
11056 }
11058 sub do_require_packageoption {
11059 local($option)= @_;
11060 local($do_option);
11061 # first look for a file named ${option}.perl
11062 &do_require_package($option) unless ($styles_loaded{$option});
11063 # next look for a subroutine named do_$option
11064 $do_option = "do_$option";
11065 if (!($styles_loaded{$option}) && defined(&$do_option)) {
11066 &$do_option();
11067 $styles_loaded{$option} = 1;
11068 }
11069 }
11071 ############################ Environments ################################
11073 # This is a dummy environment used to synchronise the expansion
11074 # of order-sensitive macros.
11075 sub do_env_tex2html_deferred {
11076 local($_) = @_;
11077 local($tex2html_deferred) = 1;
11078 $_ = &process_command($single_cmd_rx,$_);
11079 }
11081 # catch wrapped commands that need not have been
11082 sub do_env_tex2html_nomath_inline {
11083 local($_) = @_;
11084 s/^\s+|\s+$//gs;
11085 my($cmd) = $_;
11086 if ($cmd=~s/^\\([a-zA-Z]+)//s) { $cmd = $1 };
11087 return (&translate_commands($_)) if ($raw_arg_cmds{$cmd}<1);
11088 &process_undefined_environment($env, $id, $_);
11089 }
11091 # The following list environment subroutines still do not handle
11092 # correctly the case where the list counters are modified (e.g. \alph{enumi})
11093 # and the cases where user defined bullets are mixed with the default ones.
11094 # e.g. \begin{enumerate} \item[(1)] one \item two \end{enumerate} will
11095 # not produce the same bullets as in the dvi output.
11096 sub do_env_itemize {
11097 local($_) = @_;
11098 $itemize_level++;
11099 #RRM - catch nested lists
11100 &protect_useritems($_);
11101 $_ = &translate_environments($_);
11103 local($bullet,$bulletx)=(' ','');
11104 SWITCH: {
11105 if ($itemize_level==1) { $bulletx = "\\bullet"; last SWITCH; }
11106 if ($itemize_level==2) { $bulletx = "\\mathbf{\\circ}"; last SWITCH; }
11107 if ($itemize_level==3) { $bulletx = "\\mathbf{\\ast}"; last SWITCH; }
11108 }
11109 $itemize_level--;
11111 if (/\s*$item_description_rx/) {
11112 # Contains user defined optional labels
11113 $bulletx = &do_cmd_mbox("${O}1$C\$$bulletx\$${O}1$C") if $bulletx;
11114 &do_env_description($_, " COMPACT", $bullet.$bulletx)
11115 } else { &list_helper($_,'UL'); }
11116 }
11118 sub do_env_enumerate {
11119 local($_) = @_;
11120 # Reiner Miericke provided the main code; integrated by RRM: 14/1/97
11121 # works currently only with 'enumerate' and derived environments
11122 # explicit styled labels are computed for each \item
11123 # ultimately the environment is done as: &do_env_description($_, " COMPACT")
11124 ++$enum_level;
11125 local(%enum) = %enum; # to allow local changes
11126 # Reiner: \begin{enumerate}[<standard_label>]
11127 local($standard_label) = "";
11128 local(@label_fields);
11129 local($label_func, $preitems, $enum_type);
11130 local($rlevel) = &froman($enum_level); # e.g. 3 => iii
11132 # \begin{enumerate}[$standard_label]
11133 if (s/^$standard_label_rx//s) { # multiline on/off ?
11134 # standard label should be used later to modify
11135 # entries in %enum
11136 $standard_label = $1; # save the standard label
11137 # s/^$standard_label_rx//; # and cut it off
11138 $standard_label =~ s/([\\\[\]\(\)])/\\$1/g; # protect special chars
11140 # Search for [aAiI1] which is not between a pair of { }
11141 # Other cases like "\theenumi" are not handled
11142 @label_fields = $standard_label =~ /$enum_label_rx/;
11143 if (($standard_label =~ /^[aAiI1]$/)&&(not(/item\s*\[/))) {
11144 $enum_type = ' TYPE="'.$standard_label.'"';
11145 $standard_label = '';
11146 } else {
11147 $label_func = $enum_label_funcs{$label_fields[$#label_fields-1]} .
11148 "(\'enum" . $rlevel . "\')";
11149 $enum{'theenum' . $rlevel} = "\&$label_func";
11150 # local($thislabel) = "\&$label_func";
11151 # do { local($_) = $thislabel; &make_unique($_);
11152 # $enum{'theenum' . $rlevel} = $_; };
11153 $standard_label =
11154 "\"$label_fields[0]\" . eval(\$enum{\"theenum$rlevel\"})"
11155 . ".\"$label_fields[$#label_fields]\"";
11156 $enum{'labelenum' . $rlevel} = $standard_label;
11157 }
11158 } elsif (s/^((.|\n)+?)\\item/$preitems=$1;"\\item"/es) {
11159 my $pre_preitems; local($cmd); $label_part;
11160 my $num_styles = join('|', values %enum_label_funcs );
11161 while ($preitems =~
11162 /\s*\\renew(ed)?command\s*(($O|$OP)\d+($C|$CP))\\?((label|the)enum(\w+))\s*\2/) {
11163 # this catches one \renewcommand{\labelenum}{....}
11164 $pre_preitems .= $`; $preitems = $'; $cmd = $5;
11165 &missing_braces unless (
11166 ($preitems=~s/$next_pair_pr_rx\s*/$label_part=$2;''/oe)
11167 ||($preitems=~s/$next_pair_rx\s*/$label_part=$2;''/oe));
11168 $cmd =~ s/^label/the/;
11169 $label_part=~s/\\($num_styles)\s*(($O|$OP)\d+($C|$CP))(\w+)\2/".\&$1\(\'$5\'\)."/g;
11170 $label_part = '"'.$label_part.'"';
11171 $enum{$cmd} = $label_part;
11172 }
11173 $standard_label =
11174 "\"$label_fields[0]\" . eval(\$enum{\"theenum$rlevel\"})"
11175 . ".\"$label_fields[$#label_fields]\"" if ($cmd);
11176 $_ = $pre_preitems . $preitems . $_ if ($pre_preitems||$preitems);
11177 } else {
11178 @enum_default_type = ('A', '1', 'a', 'i', 'A') unless (@enum_default_type);
11179 $enum_type = $enum_level%4;
11180 $enum_type = ' Type="'.@enum_default_type[$enum_type].'"';
11181 }
11183 # enclose contents of user-defined labels within a group,
11184 # in case of style-change commands, which could bleed outside the label.
11185 &protect_useritems($_);
11186 $_ = &translate_environments($_); #catch nested lists
11188 local($enum_result);
11189 if (($standard_label)||(/\\item\[/)) {
11190 # split it into items
11191 @items = split(/\\item\b/,$_);
11192 # save anything (non-blank) before the items actually start
11193 $preitems = shift(@items);
11194 $preitems =~ s/^\s*$//;
11195 local($enum_label);
11196 # prepend each item with an item label: \item => \item[<label>]
11197 foreach $item (@items) {
11198 # unless ( $item =~ /^\s*$/ ) { # first line may be empty
11199 $enum{"enum" . $rlevel}++; # increase enumi
11200 $enum_label = eval("$enum{'labelenum' . $rlevel}");
11201 # insert a label, removing preceding space, BUT...
11202 # do NOT handle items with existing labels
11203 $item =~ s/^\s*//;
11204 if ($item =~ s/^\s*\[([^]]*)\]//) {
11205 $enum{"enum" . $rlevel}--;
11206 $enum_label = "$1";
11207 local($processed) = ($enum_label =~/$OP/);
11208 $enum_label = join('',($processed ? "<#0#>" : "<<0>>")
11209 ,$enum_label ,($processed ? "<#0#>" : "<<0>>"))
11210 if ($enum_label =~ /\\/);
11211 if ($processed) { &make_unique_p($enum_label) }
11212 elsif ($enum_label =~ /$O/) { &make_unique($enum_label) };
11213 $item = "[${enum_label}]".$item;
11214 } else {
11215 local($processed) = ($enum_label =~/$OP/);
11216 $enum_label = join('',($processed ? "<#0#>" : "<<0>>")
11217 ,$enum_label ,($processed ? "<#0#>" : "<<0>>"))
11218 if ($enum_label =~ /\\/);
11219 if ($processed) { &make_unique_p($enum_label) }
11220 elsif ($enum_label =~ /$O/) { &make_unique($enum_label) };
11221 $item = "[$enum_label\]$item";
11222 $enum_label =~ s/\.$//;
11223 }
11224 if ($standard_label) {
11225 $item =~ s/(\\labelitem$rlevel|$standard_label)/$enum_label/g
11226 } else {
11227 $item =~ s/(\\labelitem$rlevel)/$enum_label/g
11228 }
11229 };
11230 $_ = join("\\item ", $preitems, @items);
11232 # Original, but $enum_result
11233 $enum_result = &do_env_description($_, " COMPACT");
11234 } else {
11235 $enum_result = &list_helper($_, "OL$enum_type", '', '');
11236 }
11238 #clean-up and revert the $enum_level
11239 $enum{"enum" . $rlevel} = 0;
11240 $enum{"enum" . &froman($enum_level)} = 0;
11241 --$enum_level;
11242 $enum_result;
11243 }
11245 sub do_env_list {
11246 local ($_) = @_;
11247 local ($list_type,$labels,$lengths) = ('UL','','');
11249 $labels = &missing_braces unless ( # get the label specifier
11250 (s/$next_pair_pr_rx/$labels=$2;''/e)
11251 ||(s/$next_pair_rx/$labels=$2;''/e));
11253 $lengths = &missing_braces unless ( # get the length declarations
11254 (s/$next_pair_pr_rx/$lengths=$2;''/e)
11255 ||(s/$next_pair_rx/$lengths=$2;''/e));
11256 # switch to enumerated style if they include a \usecounter.
11257 $list_type = 'OL' if $lengths =~ /\\usecounter/;
11259 /\\item\b/; local($preitems) = $`;
11260 $_ =~ s/^\Q$preamble//s if ($preitems);
11261 $preitems =~s/^\s*|\s*$//g;
11262 if ($preitems) {
11263 $preitems = &translate_environments($preitems);
11264 $preitems = &translate_commands($preitems) if ($preitems =~ /\\/);
11265 # &write_warnings("\nDiscarding: $preitems before 1st item in list")
11266 # if ($preitems);
11267 }
11269 #RRM - catch nested lists
11270 #RRM unfortunately any uses of the \\usecounter within \item s
11271 # may be broken --- sigh.
11272 &protect_useritems($_);
11273 $_ = &translate_environments($_);
11275 if (($list_type =~ /OL/)&&($labels)) {
11276 local($br_ida,$br_idb,$label,$aft);
11277 $br_ida = ++$global{'max_id'};
11278 $lengths =~ s/\\usecounter((($O|$OP)\d+($C|$CP))[^<]+\2)/
11279 &make_nowrapper(1)."\\stepcounter$1".&make_nowrapper(0)/e;
11280 $labels = "$O$br_ida$C$lengths$O$br_ida$C".$labels;
11282 # s/\\item\b\s*([^\[])/do {
11283 # $label = $labels; $aft = $1;
11284 # $br_id = ++$global{'max_id'};
11285 # $label = &translate_environments(
11286 # "$O$br_id$C$label$O$br_id$C");
11287 # join('',"\\item\[" , $label, "\]$aft" );
11288 # }/eg;
11289 # $labels ='';
11290 }
11292 if (($labels)||(/\\item\[/)) {
11293 $_ = &list_helper($_, 'DL', $labels, $lengths)
11294 } else {
11295 $_ = &list_helper($_, $list_type, '', $lengths)
11296 }
11297 $_;
11298 }
11300 sub do_env_trivlist {
11301 local($_) = @_;
11302 local($compact,$item_sep,$pre_items) = ' COMPACT';
11303 &protect_useritems($_);
11305 # assume no styles initially for this list
11306 local($close_tags,$reopens) = &close_all_tags();
11307 local($open_tags_R) = [];
11308 local(@save_open_tags) = ();
11310 # include \label anchors from [...] items
11311 s/$item_description_rx\s*($labels_rx8)?\s*/
11312 (($9)? "<A NAME=\"$9\">$1<\/A>" : $1 ) ."\n"/eg;
11313 # remove unwanted space before \item s
11314 s/[ \t]*\\item\b/\\item/g;
11316 local($this_item,$br_id) = ('','');
11317 local($this_sitem,$this_eitem) = ("\n<P>","</P>\n",'');
11319 # assume no sub-lists, else... why use {trivlist} ?
11320 # extract up to the 1st \item
11321 local(@items) = split(/\\item\b/, $_);
11322 $pre_items = shift @items;
11323 $_ = '';
11324 while (@items) {
11325 $br_id = ++$global{'max_id'};
11326 $this_item = shift @items;
11327 $this_item = &translate_environments(
11328 "$O$br_id$C".$pre_items.$this_item."$O$br_id$C" );
11329 if ($this_item =~ /\\/) {
11330 $this_item = &translate_commands($this_item);
11331 $_ .= join('' , $this_sitem
11332 , $this_item
11333 # , $this_eitem
11334 )
11335 } else { $_ .= $this_sitem . $this_item }
11336 }
11338 $_ = &translate_environments($_);
11339 $_ = &translate_commands($_);
11341 join('' , $close_tags , $_ , $reopens);
11343 }
11345 # enclose the contents of any user-defined labels within a group,
11346 # else any style-change commands may bleed outside the label.
11347 sub protect_useritems {
11348 # MRO: use $_[0] instead: local(*_) = @_;
11349 local($preitems, $thisitem);
11350 $_[0] =~ s/^$par_rx\s*//s; # discard any \par before 1st item
11352 # locate \item with optional argument
11353 local($saveRS) = $/; undef $/;
11354 local(@preitems);
11355 # allow one level of nested []
11356 # MRO: Caution! We have a double-wildcarded RX here, this may cause
11357 # trouble. Should be re-coded.
11358 $_[0] =~ s/\\item[\s\r]*(\b(\[(([^\[\]]|\[[^]]*\])*)\])?|[^a-zA-Z\s])/
11359 $thisitem = " $1";
11360 if ($2) {
11361 $br_id = ++$global{'max_id'};
11362 $thisitem = '['.$O.$br_id.$C.$3.$O.$br_id.$C.']';
11363 };
11364 "\\item".$thisitem
11365 /egm;
11367 $/ = $saveRS;
11368 $_[0] = join(@preitems, $_[0]);
11369 }
11371 sub do_env_description {
11372 local($_, $compact, $bullet) = @_;
11373 #RRM - catch nested lists
11374 &protect_useritems($_);
11375 $_ = &translate_environments($_) unless ($bullet);
11377 # MRO: replaced $* with /m
11378 $compact = "" unless $compact;
11379 if ($compact) { # itemize/enumerate with optional labels
11380 s/\n?$item_description_rx\s*($labels_rx8)?\s*/"\n<\/DD>\n<DT>".
11381 (($9)? "<A NAME=\"$9\">$1<\/A>" : $1 ) ."<\/DT>\n<DD>"/egm;
11382 } else {
11383 s/\n?$item_description_rx\s*($labels_rx8)?\s*/"\n<\/DD>\n<DT>".
11384 (($9)? "<A NAME=\"$9\"><STRONG>$1<\/STRONG><\/A>"
11385 : "<STRONG>$1<\/STRONG>") ."<\/DT>\n<DD>"/egm;
11386 }
11387 # and just in case the description is empty ...
11388 #JCL(jcl-del) - $delimiter_rx -> ^$letters
11389 s/\n?\\item\b\s*([^$letters\\]|)\s*/\n<\/DD>\n<DT>$bullet<\/DT>\n<DD>$1/gm;
11390 s/^\s+//m;
11392 $_ = '<DD>'.$_ unless ($_ =~ s/^\s*<\/D(T|D)>\n?//s);
11393 $_ =~ s/\n$//s;
11394 "<DL$compact>\n$_\n</DD>\n</DL>";
11395 }
11397 sub list_helper {
11398 local($_, $tag, $labels, $lengths) = @_;
11399 local($item_sep,$pre_items,$compact,$etag,$ctag);
11400 $ctag = $tag; $ctag =~ s/^(.*)\s.*$/$1/;
11402 # assume no styles initially for this list
11403 local($close_tags,$reopens) = &close_all_tags();
11404 local($open_tags_R) = [];
11405 local(@save_open_tags) = ();
11407 # #RRM: cannot have anything before the first <LI>
11408 # local($savedRS) = $/; $/='';
11409 # $_ =~ /\\item[\b\r]/s;
11410 # if ($`) {
11411 # $preitems = $`; $_ = $&.$';
11412 # $preitems =~ s/<P( [^>]*)?>//g;
11413 # $close_tags .= "\n".$preitems if $preitems;
11414 # }
11415 # $/ = $savedRS;
11416 #
11418 $* = 1; # Multiline matching ON
11419 if (($tag =~ /DL/)&&$labels) {
11420 local($label,$aft,$br_id);
11421 s/\\item\b[\s\r]*([^\[])/do {
11422 $label = $labels; $aft = $1;
11423 $br_id = ++$global{'max_id'};
11424 $label = &translate_environments(
11425 "$O$br_id$C$label$O$br_id$C");
11426 join('',"\\item\[" , $label, "\]$aft" );
11427 }/eg;
11428 }
11429 $* = 0; # Multiline matching OFF
11431 # This deals with \item[xxx] ...
11432 if ($tag =~ /DL/) {
11433 $compact = ' COMPACT';
11434 # include \label anchors in the <DT> part
11435 # and $pre_item tags in the <DD> part:
11436 if ($labels && $lengths) {
11437 $item_sep = "\n</DD>\n<DT>";
11438 } else {
11439 $item_sep = ($labels ? "<DT>$labels\n" : '') ."</DT>\n<DD>";
11440 }
11441 $etag = "\n</DD>";
11442 s/$item_description_rx[\r\s]*($labels_rx8)?[\r\s]*/"<DT>" .
11443 (($9)? "<A NAME=\"$9\">$1<\/A>" : $1 ) ."\n<DD>"/egm;
11444 } else {
11445 $item_sep = "\n</LI>\n<LI>";
11446 $etag = "\n</LI>";
11447 }
11449 # remove unwanted space before \item s
11450 s/[ \t]*\\item\b/\\item/gm;
11452 #JCL(jcl-del) - $delimiter_rx -> ^$letters
11453 s/\n?\\item\b[\r\s]*/$item_sep/egm;
11455 #RRM: cannot have anything before the first <LI>
11456 local($savedRS) = $/; $/='';
11457 $_ =~ /\Q$item_sep\E|<DT>|<LI>/s;
11458 #RRM: ...try putting it before the list-open tag
11459 if ($`) {
11460 $preitems = $`; $_ = $&.$';
11461 $preitems =~ s/<P( [^>]*)?>//gm;
11462 $close_tags .= "\n".$preitems if $preitems;
11463 }
11464 $_ =~ s/^\s*<\/[^>]+>\s*//s;
11466 # remove \n from end of the last item
11467 $_ =~ s/\n$//s;
11468 $/ = $savedRS;
11470 join('' , $close_tags , "\n<$tag$compact>\n"
11471 , $_ , "$etag\n</$ctag>" , $reopens);
11472 }
11475 # RRM: A figure environment generates a picture UNLESS it contains a
11476 # {makeimage} sub-environment; in which case it creates a <DIV>
11477 # inside which the contents are interpreted as much as is possible.
11478 # When there are captions, this modifies $before .
11479 sub do_env_figure {
11480 local($_) = @_;
11481 local($halign, $anchors) = ('CENTER','');
11482 local ($border, $attribs );
11483 local($cap_width) = $cap_width;
11484 my ($opt, $dummy) = &get_next_optional_argument;
11486 my $abovedisplay_space = $ABOVE_DISPLAY_SPACE||"<P></P>\n";
11487 my $belowdisplay_space = $BELOW_DISPLAY_SPACE||"<P></P>\n";
11489 ($_,$anchors) = &extract_labels($_); # extract labels
11490 # Try to establish the alignment
11491 if (/^(\[[^\]]*])?\s*\\begin\s*<<\d*>>(\w*)<<\d*>>|\\(\w*)line/) {
11492 $halign = $2.$3;
11493 if ($halign =~ /right/i) { $halign = 'RIGHT' }
11494 elsif ($halign =~ /left/i) { $halign = 'LEFT' }
11495 elsif ($halign =~ /center/i) { $halign = 'CENTER' }
11496 else { $halign = 'CENTER' }
11497 }
11499 # allow caption-alignment to be variable
11500 local($cap_align);
11501 if ($FIGURE_CAPTION_ALIGN =~ /^(TOP|BOTTOM|LEFT|RIGHT)/i) {
11502 $cap_align = join('', ' ALIGN="', $&, $','"')};
11504 local($cap_env, $captions,$has_minipage) = ('figure','');
11505 if ((/\\begin\s*($O\d+$C)\s*(makeimage|minipage)\s*\1|\\docode/)||
11506 (/\\includegraphics/&&(!/$htmlborder_rx|$htmlborder_pr_rx|\\htmlimage/))){
11507 $has_minipage = ($2 =~ /minipage/sg );
11508 $_ = &translate_environments($_);
11509 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11510 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11511 do { local($contents) = $_;
11512 &extract_captions($cap_env); $_ = $contents;
11513 } if (/\\caption/);
11514 $_ = &translate_commands($_);
11515 while ($_ =~ s/(^\s*<BR>\s*|\s*<BR>\s*$)//sg){}; # remove unneeded breaks
11516 } else {
11517 do { local($contents) = $_;
11518 # MRO: no effect: &extract_captions($cap_env, *cap_width); $_ = $contents;
11519 &extract_captions($cap_env); $_ = $contents;
11520 } if (/\\caption/);
11521 # Generate picture of the whole environment
11522 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11523 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11524 $_ = &process_undefined_environment($env, $id, $_);
11525 $_ = &post_latex_do_env_figure($_);
11526 $_ =~ s/\s*<BR>\s*$//g;
11527 }
11529 if ($captions) {
11530 # MRO: replaced $* with /m
11531 $captions =~ s/^\n//m;
11532 $captions =~ s/\n$//m;
11533 }
11534 s/$caption_mark//g;
11536 local($close_tags) = &close_all_tags;
11537 $_ .= $close_tags;
11539 # place all the pieces inside a TABLE, if available
11540 if ($HTML_VERSION > 2.1) {
11541 if ($captions) {
11542 local($pxs,$len) = &convert_length($cap_width,$MATH_SCALE_FACTOR)
11543 if $cap_width;
11544 local($table) = "<TABLE$env_id"; # WIDTH="65%"';
11545 $table .= " WIDTH=\"$pxs\"" if ($pxs);
11546 if ($border) { $table .= " BORDER=\"$border\"" } # no checking !!
11547 $table .= ">";
11548 s/^\s*|\s*$//g;
11549 join (''
11550 , $above_display_space
11551 , "\n<DIV", ($halign ? " ALIGN=\"$halign\"" :'')
11552 , '>', $anchors , $cap_anchors
11553 , "\n$table\n<CAPTION", $cap_align, '>'
11554 , $captions , "</CAPTION>\n<TR><TD>"
11555 , ($cap_width ? '</TD><TD>' : '')
11556 , $_ , '</TD>'
11557 , ($cap_width ? '<TD></TD>' : '')
11558 , "</TR>\n</TABLE>\n</DIV>\n"
11559 , $below_display_space
11560 )
11561 } elsif ($halign) {
11562 if ($border||($attributes)||$env_id) {
11563 &make_table( $border, $attribs, $anchors, '', $halign, $_ );
11564 } else {
11565 join (''
11566 , $above_display_space
11567 , "\n<DIV ALIGN=\"$halign\">\n"
11568 , ($anchors ? "\n<P>$anchors</P>" : '')
11569 , $_
11570 , "\n</DIV>"
11571 , $below_display_space
11572 )
11573 }
11574 } else {
11575 if ($border||($attributes)||$env_id) {
11576 join (''
11577 , $above_display_space
11578 , "\n<DIV", ($halign ? " ALIGN=\"$halign\"":'')
11579 , '>'
11580 , &make_table( $border, $attribs, $anchors, '', $halign, $_ )
11581 , "\n</DIV><BR"
11582 , (($HTML_VERSION > 3.1)? " CLEAR=\"ALL\"" :'')
11583 , '>'
11584 , $below_display_space
11585 );
11586 } else {
11587 join (''
11588 , $above_display_space
11589 , "\n<DIV", ($halign ? " ALIGN=\"$halign\"":'')
11590 , ">$anchors\n" , $_ , "\n</DIV><BR"
11591 , (($HTML_VERSION > 3.1)? " CLEAR=\"ALL\"" :'')
11592 , '>'
11593 , $below_display_space
11594 );
11595 }
11596 }
11597 } else {
11598 # MRO: replaced $* with /m
11599 s/^\n//m;
11600 s/\n$//m;
11601 if ($captions) {
11602 join('', "\n<BR>\n", (($anchors) ? "$anchors" : '')
11603 , "$cap_anchors\n$captions\n<BR>"
11604 , "\n<P", ($halign ? " ALIGN=\"$halign\"":'')
11605 , '>', $_ , "\n</P>");
11606 } elsif ($halign) {
11607 join ('', "<BR>\n$anchors", $_ , "\n<BR>" )
11608 } else {
11609 join('', "<BR>\n<P", ($halign ? " ALIGN=\"$halign\"":'')
11610 , ">$anchors\n" , $_ , "\n</P><BR>");
11611 }
11612 }
11613 }
11615 sub do_env_figurestar { &do_env_figure(@_) }
11617 sub do_env_table {
11618 local($_) = @_;
11619 local($halign, $anchors) = ('','');
11620 local ( $border, $attribs );
11621 &get_next_optional_argument;
11623 # Try to establish the alignment
11624 if (/^(\[[^\]]*])?\s*\\begin\s*<<\d*>>(\w*)<<\d*>>|\\(\w*)line/) {
11625 $halign = $2.$3;
11626 if ($halign =~ /right/i) { $halign = 'RIGHT' }
11627 elsif ($halign =~ /left/i) { $halign = 'LEFT' }
11628 elsif ($halign =~ /center/i) { $halign = 'CENTER' }
11629 else { $halign = '' }
11630 }
11632 local($cap_env, $captions) = ('table','');
11634 # allow caption-alignment to be variable
11635 local($cap_align);
11636 if ($TABLE_CAPTION_ALIGN =~ /^(TOP|BOTTOM|LEFT|RIGHT)/i) {
11637 $cap_align = join('', ' ALIGN="', $&, $','"')};
11639 if ((/\\(begin|end)\s*($O\d+$C)\s*makeimage\s*\2/)||
11640 ($HTML_VERSION > 2.0 && (
11641 /\\begin\s*($O\d+$C)\s*((super)?tabular|longtable)\s*\1/))) {
11642 $_ = &translate_environments($_);
11643 ($_,$anchors) = &extract_labels($_); # extract labels
11644 do { local($contents) = $_;
11645 &extract_captions($cap_env); $_ = $contents;
11646 } if (/\\caption/);
11647 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11648 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11649 $_ = &translate_commands($_);
11650 while ($_ =~ s/(^\s*<BR>\s*|\s*<BR>\s*$)//g){};
11651 } else {
11652 # Make an image of the whole environment.
11653 ($_,$anchors) = &extract_labels($_); # extract labels
11654 do { local($contents) = $_;
11655 &extract_captions($cap_env); $_ = $contents;
11656 } if (/\\caption/);
11657 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11658 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11659 $_ = &process_undefined_environment($env, $id, $_);
11660 $_ = &post_latex_do_env_table($_);
11661 $_ =~ s/\s*<BR>\s*$//g;
11662 }
11664 if ($captions) {
11665 # MRO: replaced $* with /m
11666 $captions =~ s/^\n//m;
11667 $captions =~ s/\n$//m;
11668 }
11669 s/$caption_mark//g;
11671 local($close_tags) = &close_all_tags;
11672 $_ .= $close_tags;
11674 # when $captions remain place all the pieces inside a TABLE, if available
11675 if ($HTML_VERSION > 2.1) {
11676 if ($captions) {
11677 $halign = 'CENTER' unless $halign;
11678 local($table) = '<TABLE';
11679 if ($border) { $table .= " BORDER=\"$border\"" } # no checking !!
11680 $table .= ">";
11681 join ('', "<BR><P></P>\n<DIV$env_id ALIGN=\"$halign\">"
11682 , "$anchors$cap_anchors\n$table\n<CAPTION", $cap_align, '>'
11683 , $captions , "</CAPTION>\n<TR><TD>"
11684 , $_ , "</TD></TR>\n</TABLE>\n</DIV><P></P><BR>" )
11685 } elsif ($halign) {
11686 if ($halign) {
11687 # MRO: replaced $* with /m
11688 s/^\s*(<(P|DIV)$env_id ALIGN=\"\w+[^>]+>)/$1$anchors/m
11689 if ($anchors);
11690 join('', "<BR>", $_, "\n<BR>" )
11691 } else {
11692 join ('', "<BR>\n$anchors", $_ , "\n<BR>" )
11693 }
11694 } else {
11695 join ('', "<BR><P></P>\n<DIV$env_id ALIGN=\"CENTER\">$anchors\n", $_ , "\n</DIV><BR>" )
11696 }
11697 } else {
11698 # MRO: replaced $* with /m
11699 s/^\n//m;
11700 s/\n$//m;
11701 if ($captions) {
11702 join('', "<BR>\n", (($anchors) ? "$anchors" : ''), "$cap_anchors\n$captions\n<BR>"
11703 , "\n<P ALIGN=\"$halign\">", $_, "\n</P><BR>");
11704 } elsif ($halign) {
11705 join ('', "<BR><P></P>\n$anchors", $_ , "\n<P></P>" )
11706 } else {
11707 join('', "<BR>\n<P ALIGN=\"CENTER\">$anchors\n", $_, "\n</P><BR>");
11708 }
11709 }
11710 }
11712 sub do_env_tablestar { &do_env_table(@_) }
11714 # RRM: A makeimage environment generates a picture of its entire contents,
11715 # UNLESS it is empty.
11716 #
11717 sub do_env_makeimage {
11718 local($_) = @_;
11719 local($attribs, $border);
11720 s/^\s*//;
11721 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11722 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11723 if (/^((\\begin\s*(($O|$OP)\d+($C|$CP))tex2html_deferred\3)?\\par(\\end(($O|$OP)\d+($C|$CP))tex2html_deferred\7)?\%?\s*\n)+$/s) { return("\n<BR>\n") }
11724 if (/^(\s\%?\n)+$/s) { return() }
11725 $_ = &process_undefined_environment($env, $id, $_);
11726 if (($border||($attributes))&&($HTML_VERSION > 2.1 ))
11727 { $_ = &make_table( $border, $attribs, '', '', '', $_ ) }
11728 $_ . ((!$_=~/^\s*$/)? "\n<BR>\n" :'');
11729 }
11731 sub do_env_abstract { &make_abstract($_[0]) }
11733 sub do_env_minipage {
11734 local($_) = @_;
11735 &get_next_optional_argument;
11736 local($width);
11737 $width = &missing_braces unless (
11738 (s/$next_pair_pr_rx/$width=$2;''/e)
11739 ||(s/$next_pair_rx/$width=$2;''/e));
11740 local($pxs,$len) = &convert_length($width,$MATH_SCALE_FACTOR) if $width;
11741 $width = " WIDTH=\"$pxs\"";
11743 local ( %mpfootnotes, $mpfootnotes ) unless ($MINIPAGE);
11744 local ( $border, $attribs, $footfile);
11745 $global{'mpfootnote'} = 0 unless ($MINIPAGE);
11746 $MINIPAGE++;
11747 print "\n *** doing minipage *** " if ($VERBOSITY > 1);
11748 local($open_tags_R) = [ @$open_tags_R ];
11749 local($close_tags,$reopens) = &close_all_tags();
11750 local(@save_open_tags) = @$open_tags_R;
11752 local($minipage_caption) if $cap_env;
11753 if ($cap_env &&($HTML_VERSION>2.1)) {
11754 do {
11755 local($captions);
11756 local($contents) = $_;
11757 &extract_captions($cap_env) if ($_ =~ /\\caption/m);
11758 $minipage_caption = $captions;
11759 $_ = $contents;
11760 undef $contents; undef $captions;
11761 };
11762 }
11764 if (s/^\s*$htmlborder_rx//so) {
11765 $attribs = $2; $border = (($4)? "$4" : 1)
11766 } elsif (s/^\s*$htmlborder_pr_rx//so) {
11767 $attribs = $2; $border = (($4)? "$4" : 1)
11768 }
11769 if (/^\s*\\/) {
11770 local($tmp) = ++$global{'max_id'};
11771 $_ = $O.$tmp.$C.$_.$O.$tmp.$C
11772 }
11773 $_ = &translate_environments($_);
11774 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11775 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11776 $_ = &translate_commands($_);
11777 $MINIPAGE--; $MINIPAGE='' if ($MINIPAGE==0);
11779 $_ .= &balance_tags();
11780 $attribs .= $width unless ($attribs =~ /WIDTH/i);
11781 # if (($border||$attribs)&&$MINIPAGE&&($HTML_VERSION>2.1)) {
11782 if (($border||$attribs||$env_id)&&$MINIPAGE&&($HTML_VERSION>2.1)) {
11783 $_ = &make_table( $border, $attribs, '', '', '', $_ );
11784 } elsif ($MINIPAGE) {
11785 $_ = join ('', '<BR><HR>', $_ , '<BR><HR><BR>' );
11786 } elsif (($border||($attribs)||$minipage_caption)&&($HTML_VERSION > 2.1 )) {
11787 $mpfootnotes = '<DL>'.$mpfootnotes.'</DL>' if $mpfootnotes;
11788 $_ = &make_table( $border, $attribs, '', $mpfootnotes, '', $_ );
11789 $_ = join('','<BR><HR'
11790 , (($HTML_VERSION > 3.0)? ' WIDTH="50\%" ALIGN="CENTER"' : '')
11791 , '>', $_ , '<BR><HR'
11792 , (($HTML_VERSION > 3.0)? ' WIDTH="50\%" ALIGN="CENTER"' : '')
11793 , '><BR>') unless ($border||$attribs||$mpfootnotes);
11794 } else {
11795 $global{'mpfootnote'} = 0;
11796 if ($mpfootnotes) {
11797 $mpfootnotes = '<DD>'.$mpfootnotes unless ($mpfootnotes =~ /^\s*<D(T|D)>/);
11798 $_ = join('','<BR><HR>', $_ , '<BR><HR'
11799 , (($HTML_VERSION > 3.0)? ' WIDTH="200" ALIGN="LEFT"' : '')
11800 , '><DL>', $mpfootnotes , '</DL><HR><BR'
11801 , (($HTML_VERSION > 3.0)? ' CLEAR="all"' : '')
11802 , '>' );
11803 } else {
11804 $_ = join ('', '<BR><HR><P></P>', $_ , '<BR><HR><BR>' );
11805 }
11806 }
11807 join('', $close_tags, $_, $reopens);
11808 }
11810 if (($HTML_VERSION > 2.1)&&($HTML_VERSION < 4.0)) {
11811 $TABLE_attribs = ",ALIGN,";
11812 $TABLE__ALIGN = ",left,right,center,";
11813 $TABLE_attribs_rx_list = ",CELLPADDING,BORDER,WIDTH,CELLSPACING,";
11814 $TABLE__WIDTH_rx = "\^\\d+%?";
11815 $TABLE__BORDER_rx = $TABLE__CELLSPACING_rx = $TABLE__CELLPADDING_rx = "\^\\d+";
11816 }
11818 sub make_table {
11819 local($border, $attribs, $anchors, $extra_cell, $halign, $_) = @_;
11820 local($table,$caption,$div,$end,$Tattribs);
11821 $caption = join('',"<CAPTION$cap_align>"
11822 , $minipage_caption
11823 ,'</CAPTION>') if ($minipage_caption);
11824 $end = "</TD></TR>\n</TABLE>";
11825 $table = join('', "<TABLE$env_id"
11826 , ((($caption)&&!($attribs =~/WIDTH/i)) ? " WIDTH=\"100\%\"" : '')
11827 , ((($border)&&!($attribs =~/BORDER/i)) ? " BORDER=\"$border\"" : '')
11828 );
11829 if ($attribs) {
11830 if (!($attribs =~ /=/)) {
11831 $Tattribs = &parse_valuesonly($attribs,"TABLE");
11832 } else {
11833 $Tattribs = &parse_keyvalues($attribs,"TABLE");
11834 }
11835 $table .= " $Tattribs" if ($Tattribs);
11836 }
11837 print STDOUT "\nTABLE: $table>" if ($VERBOSITY >2 );
11838 $table .= ">".$caption."\n<TR><TD>";
11839 if ($extra_cell) {
11840 local($sep) = "</TD></TR>\n<TR ALIGN=\"LEFT\">\n<TD>";
11841 join ('', $div, $anchors, $table, $_ , $sep, $extra_cell, $end );
11842 } else {
11843 join ('', $div, $anchors, $table, $_ , $end );
11844 }
11845 }
11847 sub do_cmd_etalchar {
11848 local($_) = @_;
11849 my $etalchar;
11850 $etalchar = &missing_braces unless (
11851 (s/$next_pair_pr_rx/$etalchar = $2;''/eo)
11852 ||(s/$next_pair_rx/$etalchar = $2;''/eo));
11853 $etalchar = &translate_commands($etalchar) if ($etalchar =~ /\\/);
11854 if ($HTML_VERSION < 3.0) {
11855 $etalchar = &process_in_latex("\$^\{$etalchar\}\$");
11856 } else {
11857 $etalchar = '<SUP>'.$etalchar.'</SUP>';
11858 }
11859 $etalchar . $_
11860 }
11862 sub do_env_thebibliography {
11863 # Sets $citefile and $citations defined in translate
11864 local($_) = @_;
11865 $bibitem_counter = 0;
11866 $citefile = $CURRENT_FILE;
11867 $citefiles{$bbl_nr} = $citefile;
11868 local($dummy,$title);
11869 $dummy = &missing_braces unless (
11870 (s/$next_pair_pr_rx/$dummy=$2;''/e)
11871 ||(s/$next_pair_rx/$dummy=$2;''/e));
11872 # MRO: replaced $* with /m
11873 s/^\s*$//gm; # Remove empty lines (otherwise will have paragraphs!)
11874 s/^\s*//m;
11876 # Replace non-breaking spaces, particularly in author names.
11877 # s/([^\\])~/$1 /g; # Replace non-breaking spaces.
11879 $_ = &translate_environments($_);
11880 $_ = &translate_commands($_);
11882 # RRM: collect all anchors from initial \label and \index commands
11883 local($anchors) = &extract_anchors('',1);
11884 $_ = '<DD>'.$_ unless ($_ =~ /^\s*<D(T|D)>/);
11885 $citations = join('',"<DL COMPACT>", $_, "</DL>");
11886 $citations{$bbl_nr} = $citations;
11887 local($br_id);
11888 if ((defined &do_cmd_bibname)||$new_command{'bibname'}) {
11889 $br_id=++$global{'max_id'};
11890 $title = &translate_environments("$O$br_id$C\\bibname$O$br_id$C");
11891 } else { $title = $bib_title }
11892 if (! $title ) {
11893 if ((defined &do_cmd_refname)||$new_command{'refname'}) {
11894 $br_id=++$global{'max_id'};
11895 $title = &translate_environments("$O$br_id$C\\refname$O$br_id$C");
11896 } else { $title = $ref_name }
11897 }
11898 local($closures,$reopens) = &preserve_open_tags();
11899 $toc_sec_title = $title ;
11900 local $bib_head = $section_headings{'bibliography'};
11901 $_ = join('', $closures
11902 , &make_section_heading($title, $bib_head, $anchors)
11903 , "$bbl_mark#$bbl_nr#" , $reopens );
11904 $bbl_nr++ if $bbl_cnt > 1;
11905 $_ =~ s/;SPMnbsp;/ /g; # replace non-breaking spaces with real ones
11906 $_;
11907 }
11909 # IGNORE - We construct our own index
11910 sub do_env_theindex { "" }
11912 # This is defined in html.sty
11913 sub do_env_comment { "" }
11916 sub do_env_equation{
11917 local($_)=@_;
11918 local($attribs, $border, $no_num);
11919 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11920 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11921 if (/\\nonumber/) {
11922 $no_num = 1;
11923 $_ = &process_undefined_environment($env,$id,$_);
11924 } else {
11925 $latex_body .= join('', "\n\\setcounter{equation}{"
11926 , $global{'eqn_number'}, "}\n");
11928 #include equation-number into the key, with HTML 2.0
11929 # $_ = join("\n", "%EQNO:".$global{'eqn_number'}, $_)
11930 $_ .= "%EQNO:".$global{'eqn_number'}."\n" if ($HTML_VERSION < 2.2);
11932 $_ = &process_undefined_environment($env,$id,$_);
11933 $global{'eqn_number'}++;
11934 local($save) = $_;
11935 $_ = join('', $save, &post_latex_do_env_equation($eqno_prefix));
11936 }
11937 if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
11938 join('',"<BR>\n<DIV$env_id ALIGN=\"CENTER\">\n"
11939 , &make_table( $border, $attribs, '', '', '', $_ )
11940 , "\n<BR CLEAR=\"ALL\">");
11941 } elsif ($HTML_VERSION < 2.2 ) {
11942 join('', "\n<P>", $_ , "\n<BR></P>" )
11943 } elsif ($HTML_VERSION > 2.1 ) {
11944 join('', "\n<P ALIGN="
11945 , ((!$no_num &&($EQN_TAGS =~ /L/))?
11946 '"LEFT"':($no_num ?'"CENTER"':'"RIGHT"'))
11947 , '>', $_ , "\n<BR></P>" )
11948 } else { $_ }
11949 }
11951 sub do_env_eqnarray{
11952 local($_)=@_;
11953 local($attribs, $border, $no_num);
11954 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11955 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
11956 local($contents) = $_;
11957 # $_ = join("\n", "%EQNO:".$global{'eqn_number'}, $_)
11958 # if ($HTML_VERSION < 3.2); #include equation-number into the key.
11959 $_ .= "%EQNO:".$global{'eqn_number'}."\n" if ($HTML_VERSION < 2.2);
11960 $_ = &process_undefined_environment($env,$id,$_);
11961 $_ .= &post_latex_do_env_eqnarray($eqno_prefix,$contents);
11962 if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
11963 join('',"<BR>\n<DIV ALIGN=\"CENTER\">\n"
11964 , &make_table( $border, $attribs, '', '', '', $_ )
11965 , "\n<BR CLEAR=\"ALL\">");
11966 } elsif ($HTML_VERSION < 2.2 ) {
11967 join('', "\n<P>", $_ , "\n<BR></P>" )
11968 } elsif ($HTML_VERSION > 3.1 ) {
11969 join('',"<BR>\n<DIV ALIGN=\"CENTER\">\n", $_
11970 , "\n</DIV><BR CLEAR=\"ALL\">" );
11971 } else {
11972 join('', "\n<P ALIGN="
11973 , (($EQN_TAGS =~ /L/)? '"LEFT"' : '"RIGHT"')
11974 , '>' , $_ , "\n<BR></P>" )
11975 }
11976 }
11978 #RRM: these are needed with later versions, when {eqnarray}
11979 # environments are split into <TABLE> cells.
11981 sub protect_array_envs {
11982 local($_) = @_;
11983 local($cnt, $arraybit, $thisbit, $which) = (0,'','','');
11984 # MRO: replaced $* with /m
11985 while (/\\(begin|end)\s*(<(<|#)\d+(#|>)>)($sub_array_env_rx)(\*|star)?\2/m ) {
11986 $thisbit = $` . $&; $_ = $'; $which = $1;
11987 do {
11988 # mark rows/columns in nested arrays
11989 $thisbit =~ s/;SPMamp;/$array_col_mark/g;
11990 $thisbit =~ s/\\\\/$array_row_mark/g;
11991 $thisbit =~ s/\\text/$array_text_mark/g;
11992 $thisbit =~ s/\\mbox/$array_mbox_mark/g;
11993 } if ($cnt > 0);
11994 $arraybit .= $thisbit;
11995 if ($which =~ /begin/) {$cnt++} else {$cnt--};
11996 }
11997 $_ = $arraybit . $_;
11999 local($presub,$thisstack) = '';
12000 for (;;) {
12001 # find \\s needing protection within \substack commands
12002 # a while-loop is simpler syntax, but uses longer strings
12003 if ( /(\\substack\s*(<(<|#)\d+(#|>)>)(.|\n)*)\\\\((.|\n)*\2)/m ) {
12004 $presub .= $`; $thisstack =$1.${array_row_mark}.$6; $_ = $';
12005 # convert all \\s in the \substack
12006 $thisstack =~ s/\\\\/${array_row_mark}/og;
12007 $presub .= $thisstack;
12008 } else { last }
12009 }
12010 $_ = $presub . $_ if ($presub);
12011 $_;
12012 }
12014 sub revert_array_envs {
12015 local($array_contents) = @_;
12016 $array_contents =~ s/$array_col_mark/$html_specials{'&'}/go;
12017 $array_contents =~ s/$array_row_mark/\\\\/go;
12018 $array_contents =~ s/$array_text_mark/\\text/go;
12019 $array_contents =~ s/$array_mbox_mark/\\mbox/go;
12020 $array_contents;
12021 }
12025 sub do_env_tabbing {
12026 local($_) = @_;
12027 local($attribs, $border);
12028 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
12029 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
12030 $_ = &tabbing_helper($_);
12031 if (/$image_mark/) {
12032 local($tab_warning) =
12033 "*** Images are not strictly valid within HTML <pre> tags\n"
12034 . "Please change your use of {tabbing} to a {tabular} environment.\n\n";
12035 &write_warnings("\n".$tab_warning);
12036 print "\n\n **** invalid tabbing environment ***\n";
12037 print $tab_warning;
12038 }
12039 if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
12040 join('',"<BR>\n<DIV$env_id ALIGN=\"CENTER\">\n"
12041 , &make_table( $border, $attribs, '', '', '', $_ )
12042 , "\n</DIV><BR CLEAR=\"ALL\">");
12043 } else { $_ }
12044 }
12046 sub tabbing_helper {
12047 local($_) = @_;
12048 s/\\=\s*//go; # cannot alter the tab-stops
12049 s/\t/ /g; # convert any tabs to spaces
12050 # MRO: replaced $* with /m
12051 s/(^|\n)[^\n]*\\kill *\n/\n/gm;
12052 s/( )? *\n/$1/gm; # retain at most 1 space for a \n
12053 # replace \\ by \n ... , ignoring any trailing space
12054 # s/\\\\ */\n/gm;
12055 # ...but make sure successive \\ do not generate a <P> tag
12056 # s/\n( *)?\n/\n \n/gm;
12057 s/\\\>//go;
12058 s/(^| *([^\\]))\\[>]/$2\t\t/go;
12059 s/([^\\])\\>/$1\t\t/go;
12060 s/\n$//; s/^\n//; # strip off leading/trailing \n
12061 local($inside_tabbing) = 1;
12062 $_ = &translate_commands(&translate_environments($_));
12063 "<PRE><TT>\n$_\n</TT></PRE>";
12064 }
12066 ################# Post Processing Latex Generated Images ################
12068 # A subroutine of the form post_latex_do_env_<ENV> can be used to
12069 # format images that have come back from latex
12071 # Do nothing (avoid the paragraph breaks)
12072 sub post_latex_do_env_figure { $_[0] }
12073 sub post_latex_do_env_figurestar { &post_latex_do_env_figure(@_) }
12075 sub post_latex_do_env_table { $_[0] }
12076 sub post_latex_do_env_tablestar { &post_latex_do_env_table(@_) }
12078 sub post_latex_do_env_equation {
12079 local($prefix) = @_;
12080 $global{'eqn_number'}+=1;
12081 # include equation number at the side of the image -- HTML 3.2
12082 if ($HTML_VERSION >= 3.2){
12083 join('',"<P ALIGN=\"" , (($EQN_TAGS eq "L") ? "left" : "right")
12084 , "\">$EQNO_START" , $prefix
12085 , &translate_commands('\theequation')
12086 , "$EQNO_END</P>\n<BR CLEAR=\"all\">" );
12087 # </P> creates unwanted space in some browsers, but others need it.
12088 } else { "" }
12089 }
12091 sub do_cmd_theequation {
12092 if ($USING_STYLES) {
12093 $txt_style{'eqn-number'} = " " unless ($txt_style{'eqn-number'});
12094 join('', "<SPAN CLASS=\"eqn-number\">"
12095 ,&get_counter_value('eqn_number'),"</SPAN>", $_[0]);
12096 } else { join('',&get_counter_value('eqn_number'), $_[0]); }
12097 }
12099 sub post_latex_do_env_eqnarray {
12100 local($prefix,$body) = @_;
12101 local($num_string,$line,@lines) = '';
12102 local($side) = (($EQN_TAGS eq "L") ? "\"left\"" : "\"right\"" );
12103 # MRO: replaced $* with /m
12104 @lines = split(/\\\\\\\\/m, $body);
12105 $line = pop(@lines);
12106 if (!($line=~/^\s*$/)&&!($line =~/\\nonumber/)) {
12107 $global{'eqn_number'}++;
12108 $num_string .= join('', "<BR><BR>\n" , $EQNO_START , $prefix
12109 , &translate_commands('\theequation')
12110 , $EQNO_END);
12111 }
12112 foreach $line (@lines) {
12113 next if ($line=~/^\s*$/);
12114 $num_string .= "\n<BR>". (($MATH_SCALE_FACTOR > 1.3)? '<BR>' : '')
12115 . "<BR CLEAR=$side>";
12116 if (!($line =~/\\(nonumber|(no)?tag)/)) {
12117 $global{'eqn_number'}+=1;
12118 $num_string .= join('', $EQNO_START , $prefix
12119 , &translate_commands('\theequation')
12120 , $EQNO_END);
12121 }
12122 }
12123 # include equation numbers at the side of the image -- HTML 3.2
12124 if ($HTML_VERSION >= 3.2){
12125 "<P ALIGN=\"" . (($EQN_TAGS eq "L") ? "left" : "right")
12126 . "\">" . (($DISP_SCALE_FACTOR >= 1.2 ) ? '<BIG>' : '')
12127 . ${num_string}
12128 . (($DISP_SCALE_FACTOR >= 1.2 ) ? '</BIG>' : '')
12129 . "</P>\n<BR CLEAR=\"all\">"
12130 # </P> creates unwanted space in some browsers, but others need it.
12131 } else { "" };
12132 }
12134 sub post_latex_do_env_eqnarraystar {
12135 local($_) = @_;
12136 if (($HTML_VERSION >= 3.2)&&(!$NO_SIMPLE_MATH)){
12137 join('', "<BR>\n<DIV ALIGN=\"CENTER\">\n"
12138 , $_ , "\n<BR CLEAR=\"ALL\">\n<P>");
12139 } elsif (($HTML_VERSION >= 2.2)&&(!$NO_SIMPLE_MATH)) {
12140 join('', "\n<BR><P ALIGN=\"CENTER\">\n", $_ , "\n<BR></P>\n<P>");
12141 } else {
12142 join('', "\n<BR><P>\n", $_ , "\n<BR></P>\n<P>");
12143 }
12144 }
12146 ############################ Grouping ###################################
12148 sub do_cmd_begingroup { $latex_body .= "\n\\begingroup\n"; $_[0] }
12149 sub do_cmd_endgroup { $latex_body .= "\\endgroup\n\n"; $_[0] }
12150 sub do_cmd_bgroup { $latex_body .= "\n\\bgroup\n"; $_[0] }
12151 sub do_cmd_egroup { $latex_body .= "\\egroup\n\n"; $_[0] }
12153 sub do_env_tex2html_begingroup {
12154 local($_) = @_;
12155 $latex_body .= "\\begingroup ";
12156 $_ = &translate_environments($_);
12157 $_ = &translate_commands($_);
12158 $latex_body .= "\\endgroup\n";
12159 $_;
12160 }
12162 sub do_env_tex2html_bgroup {
12163 local($_) = @_;
12164 $latex_body .= "\\bgroup ";
12165 $_ = &translate_environments($_);
12166 $_ = &translate_commands($_);
12167 $latex_body .= "\\egroup\n";
12168 $_;
12169 }
12172 ############################ Commands ###################################
12174 # Capitalizes what follows the \sc declaration
12175 # *** POTENTIAL ERROR ****
12176 # (This is NOT the correct meaning of \sc in the cases when it
12177 # is followed by another declaration (e.g. \em).
12178 # The scope of \sc should be limited to the next occurence of a
12179 # declaration.
12180 #sub do_cmd_sc {
12181 # local($_) = @_;
12182 # local(@words) = split(" ");
12183 # Capitalize the words which are not commands and do not contain any markers
12184 # grep (do {tr/a-z/A-Z/ unless /(^\\)|(tex2html)/}, @words);
12185 # grep (do {s/([a-z]+)/<small>\U$1\E<\/small>/g unless /(^\\)|(tex2html)/}, @words);
12186 # join(" ", @words);
12187 #}
12188 sub do_cmd_sc { &process_smallcaps(@_) }
12189 sub do_cmd_scshape { &do_cmd_sc(@_) }
12191 # This is supposed to put the font back into roman.
12192 # Since there is no HTML equivalent for reverting
12193 # to roman we keep track of the open font tags in
12194 # the current context and close them.
12195 # *** POTENTIAL ERROR ****#
12196 # This will produce incorrect results in the exceptional
12197 # case where \rm is followed by another context
12198 # containing font tags of the type we are trying to close
12199 # e.g. {a \bf b \rm c {\bf d} e} will produce
12200 # a <b> b </b> c <b> d e</b>
12201 # i.e. it should move closing tags from the end
12202 sub do_cmd_rm { # clean
12203 my ($str, $ot) = @_;
12204 $ot = $open_tags_R unless(defined $ot);
12205 return("<\#rm\#>".$str) if ($inside_tabular);
12207 my ($size,$color,$tags);
12208 while (@$ot) {
12209 my $next = pop (@$ot);
12210 print STDOUT "\n</$next>" if $VERBOSITY > 2;
12211 if ($next =~ /$sizechange_rx/) {
12212 $size = $next unless ($size);
12213 }
12214 # if ($next =~ /$colorchange_rx/) {
12215 # $color = $next unless ($color);
12216 # }
12217 $declarations{$next} =~ m|</.*$|;
12218 $tags .= $& unless ($` =~ /^<>/);
12219 }
12220 if ($size) {
12221 $declarations{$size} =~ m|</.*$|;
12222 $tags .= $` unless ($` =~ /^<>/);
12223 push (@$ot,$size);
12224 print STDOUT "\n<$size>" if $VERBOSITY > 2;
12225 }
12226 $tags.$str;
12227 }
12229 sub do_cmd_rmfamily{ &do_cmd_rm(@_) }
12231 sub do_cmd_textrm {
12232 local($_) = @_;
12233 local($text,$br_id)=('','0');
12234 $text = &missing_braces unless (
12235 (s/$next_pair_pr_rx/$text=$2;$br_id=$1;''/eo)
12236 ||(s/$next_pair_rx/$text=$2;$br_id=$1;''/eo));
12237 join ('' ,
12238 &translate_environments("$O$br_id$C\\rm $text$O$br_id$C")
12239 , $_ );
12240 }
12242 sub do_cmd_emph {
12243 local($_) = @_;
12244 local($ifstyle,$join_tags) = ('',join(',',@$open_tags_R));
12245 $join_tags =~ s/(^|,)(text)?(it|rm|normalfont)/$if_style=$3;''/eg;
12246 if ($if_style =~ /it/) {
12247 ($ifstyle,$join_tags) = ('',join(',',@$open_tags_R));
12248 $join_tags =~ s/(^|,)(text)?(bf|rm|normalfont)/$if_style=$3;''/eg;
12249 if ($if_style =~ /bf/) { &do_cmd_textrm(@_) }
12250 else { &do_cmd_textbf(@_) }
12251 } else { &do_cmd_textit(@_) }
12252 }
12254 #RRM: These cope with declared commands for which one cannot
12255 # simply open a HTML single tag.
12256 # The do_cmd_... gets found before the $declaration .
12258 sub do_cmd_upshape{&declared_env('upshape',$_[0],$tex2html_deferred)}
12259 sub do_cmd_mdseries{&declared_env('mdseries',$_[0],$tex2html_deferred)}
12260 sub do_cmd_normalfont{&declared_env('normalfont',$_[0],$tex2html_deferred)}
12263 # This is supposed to put the font back into normalsize.
12264 # Since there is no HTML equivalent for reverting
12265 # to normalsize we keep track of the open size tags in
12266 # the current context and close them.
12267 sub do_cmd_normalsize { # clean
12268 my ($str, $ot) = @_;
12269 $ot = $open_tags_R unless(defined $ot);
12271 my ($font,$fontwt,$closures,$reopens,@tags);
12273 while (@$ot) {
12274 my $next = pop @$ot;
12275 $declarations{$next} =~ m|</.*$|;
12276 my ($pre,$post) = ($`,$&);
12277 if ($post =~ /$block_close_rx|$all_close_rx/ ) {
12278 push (@$ot, $next);
12279 last;
12280 }
12281 $closures .= $post unless ($pre =~ /^<>/);
12282 print STDOUT "\n</$next>" if $VERBOSITY > 2;
12284 if ($next =~ /$fontchange_rx/) {
12285 $font = $next unless ($font);
12286 } elsif ($next =~ /$fontweight_rx/) {
12287 $fontwt = $next unless ($fontwt);
12288 } elsif ($next =~ /$sizechange_rx/) {
12289 # discard it
12290 } else {
12291 unshift (@tags, $next);
12292 print STDOUT "\n<<$next>" if $VERBOSITY > 2;
12293 $reopens .= $pre unless ($pre =~ /^<>/);
12294 }
12295 }
12296 push (@$ot, @tags);
12297 if ($font) {
12298 $declarations{$font} =~ m|</.*$|;
12299 $reopens .= $` unless ($` =~ /^<>/);
12300 push (@$ot,$font);
12301 print STDOUT "\n<$font>" if $VERBOSITY > 2;
12302 }
12303 if ($fontwt) {
12304 $declarations{$fontwt} =~ m|</.*$|;
12305 $reopens .= $` unless ($` =~ /^<>/);
12306 push (@$ot,$fontwt);
12307 print STDOUT "\n<$fontwt>" if $VERBOSITY > 2;
12308 }
12309 join('', $closures, $reopens, $str);
12310 }
12314 #JCL(jcl-tcl)
12315 # changed everything
12316 #
12317 sub do_cmd_title {
12318 local($_) = @_;
12319 &get_next_optional_argument;
12320 local($making_title,$next) = (1,'');
12321 $next = &missing_braces unless (
12322 (s/$next_pair_pr_rx/$next = $2;''/eo)
12323 ||(s/$next_pair_rx/$next = $2;''/eo));
12324 $t_title = &translate_environments($next);
12325 $t_title = &translate_commands($t_title);
12326 # $toc_sec_title = &simplify(&translate_commands($next));
12327 $toc_sec_title = &purify(&translate_commands($next));
12328 $TITLE = (($toc_sec_title)? $toc_sec_title : $default_title)
12329 unless ($TITLE && !($TITLE =~ /^($default_title|\Q$FILE\E)$/));
12330 # $TITLE = &purify($TITLE);
12332 #RRM: remove superscripts inserted due to \thanks
12333 $TITLE =~ s/<A[^>]*><SUP>\d+<\/SUP><\/A>/$1/g;
12334 $_;
12335 }
12337 sub do_cmd_author {
12338 local($_) = @_;
12339 &get_next_optional_argument;
12340 my $next;
12341 $next = &missing_braces unless (
12342 (s/$next_pair_pr_rx/$next = $2;''/seo)
12343 ||(s/$next_pair_rx/$next = $2;''/seo));
12344 local($after) = $_;
12345 if ($next =~ /\\and/) {
12346 my @author_list = split(/\s*\\and\s*/, $next);
12347 my $t_author, $t_affil, $t_address;
12348 foreach (@author_list) {
12349 $t_author = &translate_environments($_);
12350 $t_author =~ s/\s+/ /g;
12351 $t_author = &simplify(&translate_commands($t_author));
12352 ($t_author,$t_affil,$t_address) = split (/\s*<BR>s*/, $t_author);
12353 push @authors, $t_author;
12354 push @affils, $t_affil;
12355 push @addresses, $t_address;
12356 }
12357 } else {
12358 $_ = &translate_environments($next);
12359 $next = &translate_commands($_);
12360 ($t_author) = &simplify($next);
12361 ($t_author,$t_affil,$t_address) = split (/\s*<BR>s*/, $t_author);
12362 push @authors, $t_author;
12363 push @affils, $t_affil if $t_affil;
12364 push @addresses, $t_address if $t_address;
12365 }
12366 $after;
12367 }
12369 sub do_cmd_address {
12370 local($_) = @_;
12371 &get_next_optional_argument;
12372 local($next);
12373 $next = &missing_braces unless (
12374 (s/$next_pair_pr_rx/$next = $&;''/eo)
12375 ||(s/$next_pair_rx/$next = $&;''/eo));
12376 ($t_address) = &simplify(&translate_commands($next));
12377 push @addresses, $t_address;
12378 $_;
12379 }
12381 sub do_cmd_institute {
12382 local($_) = @_;
12383 &get_next_optional_argument;
12384 local($next);
12385 $next = &missing_braces unless (
12386 (s/$next_pair_pr_rx/$next = $&;''/eo)
12387 ||(s/$next_pair_rx/$next = $&;''/eo));
12388 ($t_institute) = &simplify(&translate_commands($next));
12389 push @affils, $t_institute;
12390 $_;
12391 }
12393 sub do_cmd_dedicatory {
12394 local($_) = @_;
12395 &get_next_optional_argument;
12396 local($next);
12397 $next = &missing_braces unless (
12398 (s/$next_pair_pr_rx/$next = $&;''/eo)
12399 ||(s/$next_pair_rx/$next = $&;''/eo));
12400 ($t_affil) = &simplify(&translate_commands($next));
12401 push @affils, $t_affil;
12402 $_;
12403 }
12405 sub do_cmd_email {
12406 local($_) = @_;
12407 local($next,$target)=('','notarget');
12408 $next = &missing_braces unless (
12409 (s/$next_pair_pr_rx/$next = $2;''/eo)
12410 ||(s/$next_pair_rx/$next = $2;''/eo));
12411 local($mail) = &translate_commands($next);
12412 ($t_email) = &make_href("mailto:$mail","$mail");
12413 push @emails, $t_email;
12414 $_;
12415 }
12417 sub do_cmd_authorURL {
12418 local($_) = @_;
12419 local($next);
12420 $next = &missing_braces unless (
12421 (s/$next_pair_pr_rx/$next = $2;''/eo)
12422 ||(s/$next_pair_rx/$next = $2;''/eo));
12423 ($t_authorURL) = &translate_commands($next);
12424 push @authorURLs, $t_authorURL;
12425 $_;
12426 }
12428 sub do_cmd_date {
12429 local($_) = @_;
12430 local($next);
12431 $next = &missing_braces unless (
12432 (s/$next_pair_pr_rx/$next = $&;''/eo)
12433 ||(s/$next_pair_rx/$next = $&;''/eo));
12434 ($t_date) = &translate_commands($next);
12435 $_;
12436 }
12438 sub make_multipleauthors_title {
12439 local($alignc, $alignl) = (@_);
12440 local($t_author,$t_affil,$t_institute,$t_date,$t_address,$t_email,$t_authorURL)
12441 = ('','','','','','','');
12442 local ($t_title,$auth_cnt) = ('',0);
12443 if ($MULTIPLE_AUTHOR_TABLE) {
12444 $t_title = '<TABLE' .($USING_STYLES? ' CLASS="author_info_table"' : '')
12445 .' WIDTH="90%" ALIGN="CENTER" CELLSPACING=15>'
12446 ."\n<TR VALIGN=\"top\">";
12447 }
12448 foreach $t_author (@authors) {
12449 $t_affil = shift @affils;
12450 $t_institute = ''; # shift @institutes;
12451 $t_address = shift @addresses;
12452 $t_email = shift @emails;
12453 $t_authorURL = shift @authorURLs;
12454 if ($MULTIPLE_AUTHOR_TABLE) {
12455 if ($auth_cnt == $MAX_AUTHOR_COLS) {
12456 $t_title .= join("\n", '</TR><TR>', '');
12457 $auth_cnt -= $MAX_AUTHOR_COLS;
12458 }
12459 $t_title .= join("\n"
12460 , '<TD>'
12461 , &make_singleauthor_title($alignc, $alignl ,$t_author
12462 , $t_affil,$t_institute,$t_date,$t_address,$t_email,$t_authorURL)
12463 , '</TD>' );
12464 ++$auth_cnt;
12465 } else {
12466 $t_title .= &make_singleauthor_title($alignc, $alignl ,$t_author
12467 , $t_affil,$t_institute,$t_date,$t_address,$t_email,$t_authorURL);
12468 }
12469 }
12470 if ($MULTIPLE_AUTHOR_TABLE) {
12471 $t_title .= "\n</TR></TABLE>\n";
12472 }
12473 $t_title;
12474 }
12476 sub do_cmd_maketitle {
12477 local($_) = @_;
12478 local($the_title) = '';
12479 local($alignc, $alignl);
12480 if ($HTML_VERSION > 2.1) {
12481 $alignc = " ALIGN=\"CENTER\"";
12482 $alignl = " ALIGN=\"LEFT\"";
12483 $alignl = $alignc if ($MULTIPLE_AUTHOR_TABLE);
12484 }
12485 if ($t_title) {
12486 $the_title .= "<H1$alignc>$t_title</H1>";
12487 } else { &write_warnings("\nThis document has no title."); }
12488 if (($#authors >= 1)||$MULTIPLE_AUTHOR_TABLE) {
12489 $the_title .= &make_multipleauthors_title($alignc,$alignl);
12490 if ($t_date&&!($t_date=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12491 $the_title .= "\n<P$alignc><STRONG>$t_date</STRONG></P>";}
12492 } else {
12493 $the_title .= &make_singleauthor_title($alignc,$alignl ,$t_author
12494 , $t_affil,$t_institute,$t_date,$t_address,$t_email,$t_authorURL);
12495 }
12496 $the_title . $_ ;
12497 }
12499 sub make_singleauthor_title {
12500 local($alignc, $alignl , $t_author
12501 , $t_affil,$t_institute,$t_date,$t_address,$t_email,$t_authorURL) = (@_);
12502 my $t_title = '';
12503 my ($s_author_info, $e_author_info) = ('<DIV','</DIV>');
12504 $s_author_info .= ($USING_STYLES ? ' CLASS="author_info"' : '').'>';
12506 if ($t_author) {
12507 if ($t_authorURL) {
12508 local($href) = &translate_commands($t_authorURL);
12509 $href = &make_named_href('author'
12510 , $href, "<STRONG>${t_author}</STRONG>");
12511 $t_title .= "\n<P$alignc>$href</P>";
12512 } else {
12513 $t_title .= "\n<P$alignc><STRONG>$t_author</STRONG></P>";
12514 }
12515 } else { &write_warnings("\nThere is no author for this document."); }
12517 if ($t_institute&&!($t_institute=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12518 $t_title .= "\n<P$alignc><SMALL>$t_institute</SMALL></P>";}
12519 if ($t_affil&&!($t_affil=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12520 $t_title .= "\n<P$alignc><I>$t_affil</I></P>";}
12521 if ($t_date&&!($t_date=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12522 $t_title .= "\n<P$alignc><STRONG>$t_date</STRONG></P>";}
12523 if ($t_address&&!($t_address=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12524 $t_title .= "\n<P$alignl><SMALL>$t_address</SMALL></P>";
12525 } # else { $t_title .= "\n<P$alignl>"}
12526 if ($t_email&&!($t_email=~/^\s*(($O|$OP)\d+($C|$CP))\s*\1\s*$/)) {
12527 $t_title .= "\n<P$alignl><SMALL>$t_email</SMALL></P>";
12528 } # else { $t_title .= "</P>" }
12529 join("\n", $s_author_info, $t_title, $e_author_info);
12530 }
12532 sub do_cmd_abstract {
12533 local($_) = @_;
12534 local($abstract);
12535 $abstract = &missing_braces unless (
12536 (s/$next_pair_pr_rx/$abstract = $&;''/eo)
12537 ||(s/$next_pair_rx/$abstract = $&;''/eo));
12538 join('', &make_abstract($abstract), $_);
12539 }
12541 sub make_abstract {
12542 local($_) = @_;
12543 # HWS Removed emphasis (hard to read)
12544 $_ = &translate_environments($_);
12545 $_ = &translate_commands($_);
12546 local($title);
12547 if ((defined &do_cmd_abstractname)||$new_command{'abstractname'}) {
12548 local($br_id)=++$global{'max_id'};
12549 $title = &translate_environments("$O$br_id$C\\abstractname$O$br_id$C");
12550 } else { $title = $abs_title }
12551 local($env_id) = " CLASS=\"ABSTRACT\"" if ($USING_STYLES);
12552 join('',"\n<H3>", $title, ":</H3>\n"
12553 , (($HTML_VERSION > 3)? "<DIV$env_id>" : "<P>"), $_
12554 , (($HTML_VERSION > 3)? "</DIV>" : "</P>"), "\n<P>");
12555 }
12557 sub set_default_language {
12558 # MRO: local($lang,*_) = @_;
12559 my $lang = shift;
12560 push(@language_stack, $default_language);
12561 $default_language = $lang;
12562 $_[0] .= '\popHtmlLanguage';
12563 }
12565 sub do_cmd_popHtmlLanguage {
12566 $default_language = pop(@language_stack);
12567 $_[0];
12568 }
12570 sub do_cmd_today {
12571 local($lang);
12572 if ($PREAMBLE) {
12573 $lang = $TITLES_LANGUAGE || $default_language ;
12574 } else {
12575 $lang = $current_language || $default_language ;
12576 }
12577 local($today) = $lang . '_today';
12578 if (defined &$today) { join('', eval "&$today()", $_[0]) }
12579 else { join('', &default_today(), $_[0]) }
12580 }
12582 sub default_today {
12583 #JKR: Make it more similar to LaTeX
12584 ## AYS: moved french-case to styles/french.perl
12585 my $today = &get_date();
12587 $today =~ s|(\d+)/0?(\d+)/|$Month[$1] $2, |;
12588 join('',$today,$_[0]);
12589 }
12591 sub do_cmd_textbackslash { join('','\', $_[0]);}
12592 sub do_cmd_textbar { join('','|', $_[0]);}
12593 sub do_cmd_textless { join('',';SPMlt;', $_[0]);}
12594 sub do_cmd_textgreater { join('',';SPMgt;', $_[0]);}
12595 sub do_cmd_textasciicircum { join('','^', $_[0]);}
12596 sub do_cmd_textasciitilde { join('','~', $_[0]);}
12597 sub do_cmd_textquoteleft { join('','`', $_[0]);}
12598 sub do_cmd_textquoteright { join('',''', $_[0]);}
12600 sub do_cmd_textcompwordmark { join('','', $_[0]);}
12601 sub do_cmd_texttrademark { join('','<SUP><SMALL>TM</SMALL></SUP>', $_[0]);}
12603 sub do_cmd_textsubscript { &make_text_supsubscript('SUB',$_[0]);}
12604 sub do_cmd_textsuperscript { &make_text_supsubscript('SUP',$_[0]);}
12606 sub make_text_supsubscript {
12607 local ($supsub, $_) = (@_);
12608 my $arg = '';
12609 $arg = &missing_braces unless (
12610 (s/$next_pair_pr_rx/$arg = $&;''/eo)
12611 ||(s/$next_pair_rx/$arg = $&;''/eo));
12612 $arg = &translate_commands($arg) if ($arg =~ m!\\!);
12613 join('', "<$supsub>", $arg, "</$supsub>", $_);
12614 }
12616 sub do_cmd_textcircled {
12617 local ($_) = (@_);
12618 my $arg = '';
12619 $arg = &missing_braces unless (
12620 (s/$next_pair_pr_rx/$arg = $&;''/eo)
12621 ||(s/$next_pair_rx/$arg = $&;''/eo));
12622 my $after = $_;
12623 join('', &process_undefined_environment("tex2html_nomath_inline"
12624 , ++$global{'max_id'}
12625 , "\\vbox{\\kern3pt\\textcircled{$arg}}" )
12626 , $after );
12627 }
12629 # these can be overridded in charset (.pl) extension files:
12630 sub do_cmd_textemdash { join('','---', $_[0]);}
12631 sub do_cmd_textendash { join('','--', $_[0]);}
12632 #sub do_cmd_exclamdown { join('','', $_[0]);}
12633 #sub do_cmd_questiondown { join('','', $_[0]);}
12634 sub do_cmd_textquotedblleft { join('',"``", $_[0]);}
12635 sub do_cmd_textquotedblright { join('',"''", $_[0]);}
12636 sub do_cmd_textbullet { join('','*', $_[0]);}
12637 sub do_cmd_textvisiblespace { join('','_', $_[0]);}
12639 sub do_cmd_ldots {
12640 join('',(($math_mode&&$USE_ENTITY_NAMES) ? ";SPMldots;" : "..."),$_[0]);
12641 }
12643 sub do_cmd_dots {
12644 join('',(($math_mode&&$USE_ENTITY_NAMES) ? ";SPMldots;" : "..."),$_[0]);
12645 }
12647 sub do_cmd_hrule {
12648 local($_) = @_;
12649 &ignore_numeric_argument;
12650 #JKR: No need for <BR>
12651 local($pre,$post) = &minimize_open_tags('<HR>');
12652 join('',$pre,$_);
12653 }
12655 #sub do_cmd_hrulefill {
12656 # "<HR ALIGN=\"right\">\n<BR CLEAR=\"right\">";
12657 #}
12659 sub do_cmd_linebreak {
12660 local($num,$dum) = &get_next_optional_argument;
12661 if (($num)&&($num<4)) { return $_[0] }
12662 join('',"<BR>", $_[0]);
12663 }
12665 sub do_cmd_pagebreak {
12666 local($_) = @_;
12667 local($num,$dum) = &get_next_optional_argument;
12668 if (($num)&&($num<4)) { return($_) }
12669 elsif (/^ *\n *\n/) {
12670 local($after) = $';
12671 local($pre,$post) = &minimize_open_tags("<BR>\n<P>");
12672 join('',$pre, $')
12673 } else { $_ }
12674 }
12677 sub do_cmd_newline { join('',"<BR>", $_[0]); }
12678 # this allows for forced newlines in tables, etc.
12679 sub do_cmd_endgraf { join('',"<BR>", $_[0]); }
12681 sub do_cmd_space { join(''," ",$_[0]); }
12682 sub do_cmd_enspace { join('',"\ ",$_[0]); }
12683 sub do_cmd_quad { join('',"\ "x4,$_[0]); }
12684 sub do_cmd_qquad { join('',"\ "x8,$_[0]); }
12686 sub do_cmd_par {
12687 local ($_) = @_;
12688 my ($pre,$post) = &preserve_open_tags();
12689 my ($spar, $lcode) = ("\n<P", '');
12690 if (($USING_STYLES) &&(!($default_language eq $TITLES_LANGUAGE))) {
12691 $lcode = &get_current_language();
12692 $spar .= $lcode if $lcode;
12693 }
12694 join('', $pre, $spar, ">\n",$post,$_);
12695 }
12697 sub do_cmd_medskip {
12698 local ($_) = @_;
12699 local($pre,$post) = &preserve_open_tags();
12700 join('',$pre,"\n<P><BR>\n",$post,$_);
12701 }
12703 sub do_cmd_smallskip {
12704 local ($_) = @_;
12705 local($pre,$post) = &preserve_open_tags();
12706 join('',$pre,"\n<P></P>\n",$post,$_);
12707 }
12709 sub do_cmd_bigskip {
12710 local ($_) = @_;
12711 local($pre,$post) = &preserve_open_tags();
12712 join('',$pre,"\n<P><P><BR>\n",$post,$_);
12713 }
12715 # MEH: Where does the slash command come from?
12716 # sub do_cmd_slash {
12717 # join('',"/",$_[0]);
12718 #}
12719 sub do_cmd_esc_slash { $_[0]; }
12720 sub do_cmd_esc_hash { "\#". $_[0]; }
12721 sub do_cmd_esc_dollar { "\$". $_[0]; }
12722 sub do_cmd__at_ { $_[0]; }
12723 sub do_cmd_lbrace { "\{". $_[0]; }
12724 sub do_cmd_rbrace { "\}". $_[0]; }
12725 sub do_cmd_Vert { "||". $_[0]; }
12726 sub do_cmd_backslash { "\\". $_[0]; }
12728 #RRM: for subscripts outside math-mode
12729 # e.g. in Chemical formulae
12730 sub do_cmd__sub {
12731 local($_) = @_;
12732 local($next);
12733 $next = &missing_braces unless (
12734 (s/$next_pair_pr_rx/$next = $2;''/e)
12735 ||(s/$next_pair_rx/$next = $2;''/e));
12736 join('',"<SUB>",$next,"</SUB>",$_);
12737 }
12739 #JCL(jcl-del) - the next two ones must only have local effect.
12740 # Yet, we don't have a mechanism to revert such changes after
12741 # a group has closed.
12742 #
12743 sub do_cmd_makeatletter {
12744 $letters =~ s/@//;
12745 $letters .= '@';
12746 &make_letter_sensitive_rx;
12747 $_[0];
12748 }
12750 sub do_cmd_makeatother {
12751 $letters =~ s/@//;
12752 &make_letter_sensitive_rx;
12753 $_[0];
12754 }
12757 ################## Commands to be processed by Latex #################
12758 #
12759 # The following commands are passed to Latex for processing.
12760 # They cannot be processed at the same time as normal commands
12761 # because their arguments must be left untouched by the translator.
12762 # (Normally the arguments of a command are translated before the
12763 # command itself).
12764 #
12765 # In fact, it's worse: it is not correct to process these
12766 # commands after we process environments, because some of them
12767 # (for instance, \parbox) may contain unknown or wrapped
12768 # environments. If math mode occurs in a parbox, the
12769 # translate_environments routine should *not* process it, lest
12770 # we encounter the lossage outlined above.
12771 #
12772 # On the other hand, it is not correct to process these commands
12773 # *before* we process environments, or figures containing
12774 # parboxes, etc., will be mishandled.
12775 #
12776 # RRM: (added for V97.1)
12777 # \parbox now uses the _wrap_deferred mechanism, and has a do_cmd_parbox
12778 # subroutine defined. This means that environments where parboxes are
12779 # common (.g. within table cells), can detect the \parbox command and
12780 # adjust the processing accordingly.
12781 #
12782 # So, the only way to handle these commands is to wrap them up
12783 # in null environments, as for math mode, and let translate_environments
12784 # (which can handle nesting) figure out which is the outermost.
12785 #
12786 # Incidentally, we might as well make these things easier to configure...
12788 sub process_commands_in_tex {
12789 local($_) = @_;
12790 local($arg,$tmp);
12791 foreach (/.*\n?/g) {
12792 chop;
12793 # For each line
12794 local($cmd, @args) = split('#',$_);
12795 next unless $cmd;
12796 $cmd =~ s/ //g;
12798 # skip if a proper implementation already exists
12799 $tmp = "do_cmd_$cmd";
12800 next if (defined &$tmp);
12802 # Build routine body ...
12803 local ($body, $code, $thisone) = ("", "");
12805 # alter the pattern here to debug particular commands
12806 # $thisone = 1 if ($cmd =~ /mathbb/);
12808 print "\n$cmd: ".scalar(@args)." arguments" if ($thisone);
12809 foreach $arg (@args) {
12810 print "\nARG: $arg" if ($thisone);
12811 print "\nARG: $next_pair_rx" if ($thisone);
12812 if ($arg =~ /\{\}/) {
12813 # RRM: the $` is surely wrong, allowing no error-checking.
12814 # Use <<...>> for specific patterns
12815 # $body .= '$args .= "$`$&" if s/$next_pair_rx//o;'."\n";
12816 $body .= '$args .= join("","{", &missing_braces, "}") unless ('."\n";
12817 $body .= ' (s/$next_pair_pr_rx/$args.=$`.$&;""/es)'."\n";
12818 $body .= ' ||(s/$next_pair_rx/$args.=$`.$&;""/es));'."\n";
12819 print "\nAFTER:$'" if (($thisone)&&($'));
12820 $body .= $' if ($');
12821 } elsif ($arg =~ /\[\]/) {
12822 $body .= '($dummy, $pat) = &get_next_optional_argument;'
12823 . '$args .= $pat;'."\n";
12824 print "\nAFTER:$'" if (($thisone)&&($'));
12825 $body .= $' if ($');
12826 } elsif ($arg =~ /^\s*\\/) {
12827 $body .= '($dummy, $pat) = &get_next_tex_cmd;'
12828 . '$args .= $pat;'."\n";
12829 print "\nAFTER:$'" if (($thisone)&&($'));
12830 $body .= $' if ($');
12831 } elsif ($arg =~ /<<\s*/) {
12832 $arg = $';
12833 if ($arg =~ /\s*>>/) {
12834 # MRO: replaced $* with /m
12835 $body .= '$args .= "$`$&" if (/\\'.$`.'/m);' . "\n"
12836 # $body .= '$args .= "$`$&" if (/\\\\'.$`.'/);' . "\n"
12837 . "\$_ = \$\';\n";
12838 print "\nAFTER:$'" if (($thisone)&&($'));
12839 $body .= $' if ($');
12840 } else { $body .= $arg ; }
12841 } else {
12842 print "\nAFTER:$'" if (($thisone)&&($arg));
12843 $body .= $arg ;
12844 }
12845 }
12847 # Generate a new subroutine
12848 local($padding) = " ";
12849 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
12850 $code = "sub wrap_cmd_$cmd {" . "\n"
12851 . 'local($cmd, $_) = @_; local ($args, $dummy, $pat) = "";' . "\n"
12852 . $body
12853 . (($thisone)? "print STDERR \"\\n$cmd:\".\$args.\"\\n\";\n" : '')
12854 . '(&make_wrapper(1).$cmd'
12855 . ($padding ? '"'.$padding.'"' : '')
12856 . '.$args.&make_wrapper(0), $_)}'
12857 . "\n";
12858 print "\nWRAP_CMD: $code " if ($thisone); # for debugging
12859 eval $code; # unless ($thisone);
12860 print STDERR "\n*** sub wrap_cmd_$cmd failed: $@" if ($@);
12862 # And make sure the main loop will catch it ...
12863 # $raw_arg_cmds{$cmd} = 1;
12864 ++$raw_arg_cmds{$cmd};
12865 }
12866 }
12868 sub process_commands_nowrap_in_tex {
12869 local($_) = @_;
12870 local($arg);
12871 foreach (/.*\n?/g) {
12872 chop;
12873 local($cmd, @args) = split('#',$_);
12874 next unless $cmd;
12875 $cmd =~ s/ //g;
12876 # Build routine body ...
12877 local ($bodyA, $codeA, $bodyB, $codeB, $thisone) = ("", "", "", "");
12879 # alter the pattern here to debug particular commands
12880 # $thisone = 1 if ($cmd =~ /epsf/);
12882 print "\n$cmd: ".scalar(@args)." arguments" if ($thisone);
12883 foreach $arg (@args) {
12884 print "\nARG: $arg" if ($thisone);
12885 if ($arg =~ /\{\}/) {
12886 # $bodyA .= '$args .= "$`"."$&" if (s/$any_next_pair_rx//);'."\n";
12887 $bodyA .= 'if (s/$next_pair_rx//s){$args.="$`"."$&"; $_='."\$'};\n";
12888 $bodyB .= '$args .= &missing_braces'."\n unless (";
12889 $bodyB .= '(s/$any_next_pair_pr_rx/$args.=$`.$&;\'\'/eo)'."\n";
12890 $bodyB .= ' ||(s/$any_next_pair_rx/$args.=$`.$&;\'\'/eo));'."\n";
12891 print "\nAFTER:$'" if (($thisone)&&($'));
12892 # $bodyA .= $'.";\n" if ($');
12893 $bodyB .= $'.";\n" if ($');
12894 } elsif ($arg =~ /\[\]/) {
12895 $bodyA .= '($dummy, $pat) = &get_next_optional_argument;'
12896 . '$args .= $pat;'."\n";
12897 print "\nAFTER:$'" if (($thisone)&&($'));
12898 # $bodyA .= $'.";\n" if ($');
12899 $bodyB .= $'.";\n" if ($');
12900 } elsif ($arg =~ /^\s*\\/) {
12901 $bodyA .= '($dummy, $pat) = &get_next_tex_cmd;'
12902 . '$args .= $pat;'."\n";
12903 $bodyB .= '($dummy, $pat) = &get_next_tex_cmd;'
12904 . '$args .= $pat;'."\n";
12905 print "\nAFTER:$'" if (($thisone)&&($'));
12906 $bodyA .= $'.";\n" if ($');
12907 $bodyB .= $'.";\n" if ($');
12908 } elsif ($arg =~ /<<\s*/) {
12909 $arg = $';
12910 if ($arg =~ /\s*>>/) {
12911 # MRO: replaced $* with /m
12912 $bodyA .= '$args .= "$`$&" if (/\\'.$`.'/m);' . "\n"
12913 # $bodyA .= '$args .= $`.$& if (/\\\\'.$`.'/);' . "\n"
12914 . "\$_ = \$\';\n";
12915 $bodyB .= '$args .= "$`$&" if (/\\'.$`.'/m);' . "\n"
12916 . "\$_ = \$\';\n";
12917 print "\nAFTER:$'" if (($thisone)&&($'));
12918 # $bodyA .= $'.";\n" if ($');
12919 $bodyB .= $'.";\n" if ($');
12920 } else {
12921 print "\nAFTER:$arg" if (($thisone)&&($arg));
12922 # $bodyA .= $arg.";\n" if ($arg);
12923 $bodyB .= $arg.";\n" if ($arg);
12924 }
12925 } else {
12926 print "\nAFTER:$arg" if (($thisone)&&($arg));
12927 $bodyA .= '$args .= '.$arg.";\n" if ($');
12928 $bodyB .= $arg.";\n" if ($');
12929 }
12930 }
12931 local($padding) = " ";
12932 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
12933 # Generate 2 new subroutines
12934 $codeA = "sub wrap_cmd_$cmd {" . "\n"
12935 .'local($cmd, $_) = @_; local($args, $dummy, $pat) = "";'."\n"
12936 . $bodyA
12937 . (($thisone)? "print \"\\nwrap $cmd:\\n\".\$args.\"\\n\";\n" : '')
12938 . '(&make_nowrapper(1)."\n".$cmd.'."\"$padding\""
12939 . '.$args.&make_nowrapper(0)," ".$_)}'
12940 ."\n";
12941 print "\nWRAP_CMD: $codeA " if ($thisone); # for debugging
12942 eval $codeA;
12943 print STDERR "\n\n*** sub wrap_cmd_$cmd failed: $@\n" if ($@);
12944 $codeB = "do_cmd_$cmd";
12945 do {
12946 $bodyB = '"";' if !($bodyB);
12947 $codeB = "sub do_cmd_$cmd {" . "\n"
12948 . 'local($_,$ot) = @_;'."\n"
12949 . 'local($open_tags_R) = defined $ot ? $ot : $open_tags_R;'."\n"
12950 . 'local($cmd,$args,$dummy,$pat)=("'.$cmd.'","","","");'."\n"
12951 . $bodyB
12952 . (($thisone)? "print \"\\ndo $cmd:\".\$args.\"\\n\";\n" : '')
12953 # . '$latex_body.="\\n".&revert_to_raw_tex("'."\\\\$cmd$padding".'$args")."\\n\\n";'
12954 . "\$_;}\n";
12955 print STDOUT "\nDO_CMD: $codeB " if ($thisone); # for debugging
12956 eval $codeB;
12957 print STDERR "\n\n*** sub do_cmd_$cmd failed: $@\n" if ($@);
12958 } unless (defined &$codeB );
12960 # And make sure the main loop will catch it ...
12961 # $raw_arg_cmds{$cmd} = 1;
12962 ++$raw_arg_cmds{$cmd};
12963 }
12964 }
12966 sub process_commands_wrap_deferred {
12967 local($_) = @_;
12968 local($arg,$thisone);
12969 foreach (/.*\n?/g) {
12970 chop;
12971 local($cmd, @args) = split('#',$_);
12972 next unless $cmd;
12973 $cmd =~ s/ //g;
12974 # Build routine body ...
12975 local ($bodyA, $codeA, $bodyB, $codeB, $after, $thisone);
12977 # alter the pattern here to debug particular commands
12978 # $thisone = 1 if ($cmd =~ /selectlanguage/);
12980 print "\n$cmd: ".scalar(@args)." arguments" if ($thisone);
12981 foreach $arg (@args) {
12982 print "\nARG: $arg" if ($thisone);
12983 if ($arg =~ /\{\}/) {
12984 # $bodyA .= '$args .= "$`$&" if (s/$any_next_pair_rx//o);';
12985 $bodyA .= '$args .= "$`$&" if (s/$next_pair_rx//so);';
12986 $after = $';
12987 print "\nAFTER:$'" if (($thisone)&&($'));
12988 } elsif ($arg =~ /\[\]/) {
12989 $bodyA .= '($dummy, $pat) = &get_next_optional_argument;' .
12990 "\n". '$args .= $pat;';
12991 $after = $';
12992 print "\nAFTER:$'" if (($thisone)&&($'));
12993 } elsif ($arg =~ /^\s*\\/) {
12994 $bodyA .= '($dummy, $pat) = &get_next_tex_cmd;'
12995 . '$args .= $pat;'."\n";
12996 print "\nAFTER:$'" if (($thisone)&&($'));
12997 $bodyA .= $'.";\n" if ($');
12998 } elsif (/<<\s*([^>]*)[\b\s]*>>/) {
12999 local($endcmd, $afterthis) = ($1,$');
13000 $afterthis =~ s/(^\s*|\s*$)//g;
13001 $endcmd =~ s/\\/\\\\/g;
13002 $bodyA .= "\n". 'if (/'.$endcmd.'/) { $args .= $`.$& ; $_ = $\' };';
13003 $after .= $afterthis if ($afterthis);
13004 print "\nAFTER:$'" if (($thisone)&&($'));
13005 } else {
13006 print "\nAFTER:$arg" if (($thisone)&&($arg));
13007 $bodyB .= $arg.";\n" ; $after = ''
13008 }
13009 $after =~ s/(^\s*|\s*$)//g if ($after);
13010 $bodyB .= $after . ";" if ($after);
13011 $bodyA .= "\$args .= ".$after . ";" if ($after);
13012 }
13013 local($padding) = " ";
13014 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
13015 # Generate 2 new subroutines
13016 $codeA = "sub wrap_cmd_$cmd {" . "\n"
13017 .'local($cmd, $_) = @_; local ($args, $dummy, $pat) = "";'."\n"
13018 . $bodyA #. ($bodyA ? "\n" : '')
13019 . (($thisone)? ";print \"\\nwrap $cmd:\".\$args.\"\\n\";\n" : '')
13020 .'(&make_deferred_wrapper(1).$cmd.'.$padding
13021 .'$args.&make_deferred_wrapper(0),$_)}'
13022 ."\n";
13023 print STDERR "\nWRAP_CMD: $codeA " if ($thisone); # for debugging
13024 eval $codeA;
13025 print STDERR "\n\n*** sub wrap_cmd_$cmd failed: $@\n" if ($@);
13027 #RRM: currently these commands only go to LaTeX or access counters.
13028 # They could be implemented more generally, as below with do_dcmd_$cmd
13029 # requiring replacement to be performed before evaluation.
13030 $codeB = "sub do_dcmd_$cmd {" . "\n"
13031 .'local($cmd, $_) = @_; local ($args, $dummy, $pat) = "";'."\n"
13032 . $bodyA . "\n"
13033 . (($thisone)? ";print \"\\ndo_def $cmd:\".\$args.\"\\n\";\n" : '')
13034 . $bodyB . "}" . "\n";
13035 print "\nDEF_CMD: $codeB " if ($thisone); # for debugging
13036 local($tmp) = "do_cmd_$cmd";
13037 eval $codeB unless (defined &$tmp);
13038 print STDERR "\n\n*** sub do_dcmd_$cmd failed: $@\n" if ($@);
13040 # And make sure the main loop will catch it ...
13041 # $raw_arg_cmds{$cmd} = 1;
13042 ++$raw_arg_cmds{$cmd};
13043 }
13044 }
13046 sub process_commands_inline_in_tex {
13047 local($_) = @_;
13048 foreach (/.*\n?/g) {
13049 chop;
13050 local($cmd, @args) = split('#',$_);
13051 next unless $cmd;
13052 $cmd =~ s/ //g;
13053 # Build routine body ...
13054 local ($body, $code, $thisone) = ("", "");
13056 # uncomment and alter the pattern here to debug particular commands
13057 # $thisone = 1 if ($cmd =~ /L/);
13059 print "\n$cmd: ".scalar(@args)." arguments" if ($thisone);
13060 foreach (@args) {
13061 print "\nARG: $_" if ($thisone);
13062 if (/\{\}/) {
13063 # $body .= '$args .= $`.$& if (/$any_next_pair_rx/);' . "\n"
13064 # . "\$_ = \$\';\n";
13065 $body .= '$args .= $`.$& if (s/$next_pair_rx//s);' . "\n"
13066 } elsif (/\[\]/) {
13067 $body .= 'local($dummy, $pat) = &get_next_optional_argument;' .
13068 "\n". '$args .= $pat;';
13069 } elsif ($arg =~ /^\s*\\/) {
13070 $body .= '($dummy, $pat) = &get_next_tex_cmd;'
13071 . '$args .= $pat;'."\n";
13072 print "\nAFTER:$'" if (($thisone)&&($'));
13073 $body .= $'.";\n" if ($');
13074 } elsif (/<<\s*/) {
13075 $_ = $';
13076 if (/\s*>>/) {
13077 # MRO: replaced $* with /m
13078 $body .= '$args .= "$`$&" if (/\\'.$`.'/m);' . "\n"
13079 . "\$_ = \$\';\n"
13080 } else { $body .= $_.";\n" ; }
13081 } else { $body .= $_.";\n" ; }
13082 }
13083 local($padding) = " ";
13084 $padding = '' if (($cmd =~ /\W$/)||(!$args)||($args =~ /^\W/));
13085 # Generate a new subroutine
13086 my $itype = ($cmd =~ /^f.*box$/ ? 'inline' : 'nomath');
13087 $code = "sub wrap_cmd_$cmd {" . "\n"
13088 .'local($cmd, $_) = @_; local ($args) = "";' . "\n"
13089 . $body . "\n"
13090 . (($thisone)? ";print \"\\ndo $cmd:\".\$args.\"\\n\";\n" : '')
13091 .'(&make_'.$itype.'_wrapper(1).$cmd.$padding.$args.'
13092 . '&make_'.$itype.'_wrapper(0),$_)}'
13093 ."\n";
13094 print "\nWRAP_CMD:$raw_arg_cmds{$cmd}: $code "
13095 if ($thisone); # for debugging
13096 eval $code;
13097 print STDERR "\n\n*** sub wrap_cmd_$cmd failed: $@\n" if ($@);
13098 # And make sure the main loop will catch it ...
13099 # $raw_arg_cmds{$cmd} = 1;
13100 ++$raw_arg_cmds{$cmd};
13101 }
13102 }
13105 # Invoked before actual translation; wraps these commands in
13106 # tex2html_wrap environments, so that they are properly passed to
13107 # TeX in &translate_environments ...
13108 # JCL(jcl-del) - new usage of $raw_arg_cmd_rx
13109 sub wrap_raw_arg_cmds {
13110 local ($processed_text, $cmd, $wrapper, $wrap, $after);
13111 print "\nwrapping raw arg commands " if ($VERBOSITY>1);
13112 local($seg, $par_wrap, $teststar, @processed);
13113 # local(@segments) = split(/\\par\b/,$_);
13114 # foreach (@segments) {
13115 # $par_wrap = join('',&make_deferred_wrapper(1), "\\par"
13116 # , &make_deferred_wrapper(0));
13117 # push(@processed, $par_wrap ) if ($seg); ++$seg;
13118 if (%renew_command) {
13119 local($key);
13120 foreach $key (keys %renew_command) {
13121 $raw_arg_cmds{$key} = 1;
13122 $raw_arg_cmd_rx =~ s/^(\(\)\\\\\()/$1$key\|/;
13123 }
13124 }
13125 print "\n" if (/$raw_arg_cmd_rx/);
13127 # MRO: replaced $* with /m
13128 while (/$raw_arg_cmd_rx/m) {
13129 local($star);
13130 push (@processed, $`); print "\@";
13131 $after = $';
13132 #JCL(jcl-del) - status of starred raw arg cmds yet unclear
13133 ($cmd, $star) = ($1.$2,$4);
13134 if ($star eq '*') { $star = 'star';}
13135 else { $after = $star.$after; $star = ''; }
13136 $wrapper = "wrap_cmd_$cmd"; $teststar = $wrapper.'star';
13137 if ($star && defined &$teststar) { $wrapper = $teststar; $star = '*'; }
13138 # MRO: make {\bf**} work
13139 elsif($star) { $after = '*'.$after; $star = '' }
13140 print "\nWRAPPED: $cmd as $wrapper" if ($VERBOSITY > 5);
13142 # ensure that the result is separated from following words...
13143 my $padding = ($after =~ /^[a-zA-Z]/s)? ($cmd =~ /\W$/ ? '':' '):'';
13145 if ($raw_arg_cmds{$cmd} && defined &$wrapper) {
13146 $* = 1;
13147 ($wrap, $_) = &$wrapper("\\$cmd$star", $padding . $after);
13148 $* = 0;
13149 # ...but don't leave an unwanted space at the beginning
13150 $_ =~ s/^ //s if($padding && $wrap !~ /\w$/m
13151 && (length($_) == length($after)+1) );
13152 push (@processed, $wrap);
13153 } elsif ($raw_arg_cmds{$cmd}) {
13154 print STDERR "\n*** $wrapper not defined, cannot wrap \\$cmd";
13155 &write_warnings("\n*** $wrapper not defined, cannot wrap \\$cmd ");
13156 push (@processed, "\\$cmd$padding");
13157 $_ = $after;
13158 } else {
13159 push (@processed, "\\$cmd$padding");
13160 $_ = $after;
13161 }
13162 last unless ($after =~ /\\/);
13163 }
13165 # recombine the pieces
13166 $_ = join('',@processed, $_);
13167 }
13169 #########################################################################
13171 # To make a table of contents, list of figures and list of tables commands
13172 # create a link to corresponding files which do not yet exist.
13173 # The binding of the file variable in each case acts as a flag
13174 # for creating the actual file at the end, after all the information
13175 # has been gathered.
13177 sub do_cmd_tableofcontents { &do_real_tableofcontents(@_) }
13178 sub do_real_tableofcontents {
13179 # local($_) = @_;
13180 if ((defined &do_cmd_contentsname)||$new_command{'contentsname'}) {
13181 local($br_id)=++$global{'max_id'};
13182 $TITLE = &translate_environments("$O$br_id$C\\contentsname$O$br_id$C");
13183 } else { $TITLE = $toc_title }
13184 $toc_sec_title = $TITLE;
13185 $tocfile = $CURRENT_FILE; # sets $tocfile this globally
13186 local $toc_head = $section_headings{'tableofcontents'};
13187 if ($toc_style) {
13188 $toc_head .= " CLASS=\"$toc_style\"";
13189 $env_style{"$toc_head.$toc_style"} = " "
13190 unless ($env_style{"$toc_head.$toc_style"});
13191 }
13192 local($closures,$reopens) = &preserve_open_tags();
13193 join('', "<BR>\n", $closures
13194 , &make_section_heading($TITLE, $toc_head), $toc_mark
13195 , $reopens, @_[0]);
13196 }
13197 sub do_cmd_listoffigures {
13198 local($_) = @_;
13199 local($list_type) = ($SHOW_SECTION_NUMBERS ? 'UL' : 'OL' );
13200 if ((defined &do_cmd_listfigurename)||$new_command{'listfigurename'}) {
13201 local($br_id)=++$global{'max_id'};
13202 $TITLE = &translate_environments("$O$br_id$C\\listfigurename$O$br_id$C");
13203 } else { $TITLE = $lof_title }
13204 $toc_sec_title = $TITLE;
13205 $loffile = $CURRENT_FILE; # sets $loffile this globally
13206 local $lof_head = $section_headings{'listoffigures'};
13207 local($closures,$reopens) = &preserve_open_tags();
13208 join('', "<BR>\n", $closures
13209 , &make_section_heading($TITLE, $lof_head)
13210 , "<$list_type>", $lof_mark, "</$list_type>"
13211 , $reopens, $_);
13212 }
13213 sub do_cmd_listoftables {
13214 local($_) = @_;
13215 local($list_type) = ($SHOW_SECTION_NUMBERS ? 'UL' : 'OL' );
13216 if ((defined &do_cmd_listtablename)||$new_command{'listtablename'}) {
13217 local($br_id)=++$global{'max_id'};
13218 $TITLE = &translate_environments("$O$br_id$C\\listtablename$O$br_id$C");
13219 } else { $TITLE = $lot_title }
13220 $toc_sec_title = $TITLE;
13221 $lotfile = $CURRENT_FILE; # sets $lotfile this globally
13222 local $lot_head = $section_headings{'listoftables'};
13223 local($closures,$reopens) = &preserve_open_tags();
13224 join('', "<BR>\n", $closures
13225 , &make_section_heading($TITLE, $lot_head)
13226 , "<$list_type>", $lot_mark, "</$list_type>"
13227 , $reopens, $_);
13228 }
13230 # Indicator for where to put the CHILD_LINKS table.
13231 sub do_cmd_tableofchildlinks {
13232 local($_) = @_;
13233 local($thismark) = $childlinks_mark;
13234 local($option,$dum) = &get_next_optional_argument;
13235 $thismark = &check_childlinks_option($option) if ($option);
13236 local($pre,$post) = &minimize_open_tags("$thismark\#0\#");
13237 join('', "<BR>", $pre, $_);
13238 }
13240 # leave out the preceding <BR>
13241 sub do_cmd_tableofchildlinksstar {
13242 local($_) = @_;
13243 local($thismark) = $childlinks_mark;
13244 local($option,$dum) = &get_next_optional_argument;
13245 $thismark = &check_childlinks_option($option) if ($option);
13246 local($pre,$post) = &minimize_open_tags("$thismark\#1\#");
13247 join('', $pre, $_);
13248 }
13250 sub check_childlinks_option {
13251 local($option) = @_;
13252 if ($option =~ /none/i) {
13253 $childlinks_mark = $childlinks_null_mark;
13254 $childlinks_null_mark }
13255 elsif ($option =~ /off/i) { $childlinks_null_mark }
13256 elsif ($option =~ /all/i) {
13257 $childlinks_mark = $childlinks_on_mark;
13258 $childlinks_on_mark }
13259 elsif ($option =~ /on/i) { $childlinks_on_mark }
13260 }
13262 sub remove_child_marks {
13263 # Modifies $_
13264 s/($childlinks_on_mark|$childlinks_null_mark)\#\d\#//go;
13265 }
13268 sub do_cmd_htmlinfo {
13269 local($_) = @_;
13270 local($option,$dum) = &get_next_optional_argument;
13271 if ($option =~ /^(off|none)/i) { $INFO = 0; return ($_) }
13272 local($pre,$post) = &minimize_open_tags($info_title_mark.$info_page_mark);
13273 join('', "<BR>", $pre, $_);
13274 }
13275 sub do_cmd_htmlinfostar {
13276 local($_) = @_;
13277 local($option,$dum) = &get_next_optional_argument;
13278 if ($option =~ /^(off|none)/i) { $INFO = 0; return ($_) }
13279 local($pre,$post) = &minimize_open_tags($info_page_mark);
13280 join('', $pre, $_);
13281 }
13283 # $idx_mark will be replaced with the real index at the end
13284 sub do_cmd_textohtmlindex {
13285 local($_) = @_;
13286 if ((defined &do_cmd_indexname )||$new_command{'indexname'}) {
13287 local($br_id)=++$global{'max_id'};
13288 $TITLE = &translate_environments("$O$br_id$C\\indexname$O$br_id$C");
13289 } else { $TITLE = $idx_title }
13290 $toc_sec_title = $TITLE;
13291 $idxfile = $CURRENT_FILE;
13292 if (%index_labels) { &make_index_labels(); }
13293 if (($SHORT_INDEX) && (%index_segment)) { &make_preindex(); }
13294 else { $preindex = ''; }
13295 local $idx_head = $section_headings{'textohtmlindex'};
13296 local($heading) = join(''
13297 , &make_section_heading($TITLE, $idx_head)
13298 , $idx_mark );
13299 local($pre,$post) = &minimize_open_tags($heading);
13300 join('',"<BR>\n" , $pre, $_);
13301 }
13303 #RRM: added 17 May 1996
13304 # allows labels within the printable key of index-entries,
13305 # when using makeidx.perl
13306 sub make_index_labels {
13307 local($key, @keys);
13308 @keys = keys %index_labels;
13309 foreach $key (@keys) {
13310 if (($ref_files{$key}) && !($ref_files{$key} eq "$idxfile")) {
13311 local($tmp) = $ref_files{$key};
13312 &write_warnings("\nmultiple label $key , target in $idxfile masks $tmp ");
13313 }
13314 $ref_files{$key} .= "$idxfile";
13315 }
13316 }
13317 #RRM: added 17 May 1996
13318 # constructs a legend for the SHORT_INDEX, with segments
13319 # when using makeidx.perl
13320 sub make_preindex { &make_real_preindex }
13321 sub make_real_preindex {
13322 local($key, @keys, $head, $body);
13323 $head = "<HR>\n<H4>Legend:</H4>\n<DL COMPACT>";
13324 @keys = keys %index_segment;
13325 foreach $key (@keys) {
13326 local($tmp) = "segment$key";
13327 $tmp = $ref_files{$tmp};
13328 $body .= "\n<DT>$key<DD>".&make_named_href('',$tmp,$index_segment{$key});
13329 # $body .= "\n<DT>$key<DD>".&make_named_href('',
13330 # $tmp."\#CHILD\_LINKS",$index_segment{$key})
13331 # unless ($CHILD_STAR);
13332 }
13333 $preindex = join('', $head, $body, "\n</DL>") if ($body);
13334 }
13336 sub do_cmd_printindex { &do_real_printindex(@_); }
13337 sub do_real_printindex {
13338 local($_) = @_;
13339 local($which) = &get_next_optional_argument;
13340 $idx_name = $index_names{$which}
13341 if ($which && $index_names{$which});
13342 @_;
13343 }
13345 sub do_cmd_newindex {
13346 local($_) = @_;
13347 local($dum,$key,$title);
13348 $key = &missing_braces unless (
13349 (s/$next_pair_pr_rx/$key=$2;''/eo)
13350 ||(s/$next_pair_rx/$key=$2;''/eo));
13351 $dum = &missing_braces unless (
13352 (s/$next_pair_pr_rx/$dum=$2;''/eo)
13353 ||(s/$next_pair_rx/$dum=$2;''/eo));
13354 $dum = &missing_braces unless (
13355 (s/$next_pair_pr_rx/$dum=$2;''/eo)
13356 ||(s/$next_pair_rx/$dum=$2;''/eo));
13357 $title = &missing_braces unless (
13358 (s/$next_pair_pr_rx/$title=$2;''/eo)
13359 ||(s/$next_pair_rx/$title=$2;''/eo));
13360 $index_names{$key} = $title if ($key && $title);
13361 @_;
13362 }
13364 # FOOTNOTES , also within Mini-page environments
13365 # allow easy way to override and inherit; e.g. for frames
13367 sub do_cmd_footnotestar { &do_real_cmd_footnote(@_) }
13368 sub do_cmd_footnote { &do_real_cmd_footnote(@_) }
13369 sub do_real_cmd_footnote {
13370 local($_) = @_;
13371 local($cnt,$marker,$smark,$emark)=('', $footnote_mark);
13372 local($mark,$dum) = &get_next_optional_argument;
13373 local($anchor_name);
13375 $footfile = "${PREFIX}$FOOT_FILENAME$EXTN"
13376 unless ($footfile||$MINIPAGE||$NO_FOOTNODE);
13378 if ($mark) {
13379 $cnt = $mark;
13380 if ($MINIPAGE) { $global{'mpfootnote'} = $cnt }
13381 else { $global{'footnote'} = $cnt }
13382 } else {
13383 $cnt = (($MINIPAGE)? ++$global{'mpfootnote'} : ++$global{'footnote'});
13384 }
13385 local($br_id, $footnote)=(++$global{'max_id'},'');
13386 $footnote = &missing_braces unless (
13387 (s/$next_pair_pr_rx/${br_id}=$1; $footnote=$2;''/eo)
13388 ||(s/$next_pair_rx/${br_id}=$1; $footnote=$2;''/eo));
13389 $br_id = "mp".$br_id if ($MINIPAGE);
13390 $marker = &get_footnote_mark($MINIPAGE);
13391 local($last_word) = &get_last_word();
13392 local($href) = &make_href("$footfile#foot$br_id",$marker);
13393 if ($href =~ /NAME="([^"]*)"/) { $anchor_name=$1 }
13394 $last_word .= $marker unless ($anchor_name);
13395 &process_footnote($footnote,$cnt,$br_id,$last_word,$mark
13396 ,($MINIPAGE? $marker : '')
13397 ,($MINIPAGE? '' : "$marker:$anchor_name") );
13398 # this may not work if there is a <BASE> tag and !($file) !!! #
13399 # join('',&make_href("$file#foot$br_id",$marker),$_);
13400 $href . $_
13401 }
13403 sub process_image_footnote {
13404 # MRO: modified to use $_[0]
13405 # local(*math) = @_;
13406 local($in_image, $keep, $pre, $this_anchor, $out, $foot_counters_recorded, @foot_anchors) = (1,'','');
13407 local($image_contents) = $_[0];
13408 $image_contents =~ s/\\(begin|end)(($O|$OP)\d+($C|$CP))tex2html_\w+\2//go;
13409 $image_contents =~ s!(\\footnote(mark\b\s*(\[[^\]]*\])?|\s*(\[[^\]]*\])?\s*(($O|$OP)\d+($C|$CP))(.*)\5))!
13410 $keep = $`; $out = '\footnotemark '.$3.$4;
13411 #MRO: $*=1; local($saveRS) = $/; $/='';
13412 if ($8) {
13413 $this_anchor = &do_cmd_footnote($2);
13414 } else {
13415 $this_anchor = &do_cmd_footnotemark($3);
13416 }
13417 #MRO: $*=0; $/ = $saveRS;
13418 $foot_counters_recorded = 1;
13419 push(@foot_anchors, $this_anchor);
13420 $out!oesg;
13421 $_[0] = $image_contents;
13422 @foot_anchors;
13423 }
13425 sub do_cmd_thanks { &do_cmd_footnote(@_); }
13427 sub get_footnote_mark {
13428 local($mini) = @_;
13429 return($footnote_mark) if ($HTML_VERSION < 3.0 );
13430 local($cmd,$tmp,@tmp,$marker);
13431 $cmd = "the". (($mini)? 'mp' : '') . "footnote";
13432 if ($new_command{$cmd}) {
13433 $tmp = "do_cmd_$cmd";
13434 @tmp = split (':!:', $new_command{$cmd});
13435 pop @tmp; $tmp = pop @tmp;
13436 if ($tmp =~ /$O/) {
13437 ### local($_) = &translate_commands($tmp);
13438 $marker = &translate_commands(&translate_environments($tmp));
13439 &make_unique($marker);
13440 ### $marker = $_;
13441 } else { $marker = &translate_commands(&translate_environments($tmp)); }
13442 } elsif ($mini) {
13443 $marker = &translate_commands('\thempfootnote');
13444 } elsif ((defined &do_cmd_thefootnote)||$new_command{'thefootnote'}) {
13445 local($br_id)=++$global{'max_id'};
13446 $marker = &translate_environments("$O$br_id$C\\thefootnote$O$br_id$C");
13447 } else { $marker = $footnote_mark; }
13448 join('','<SUP>',$marker,'</SUP>');
13449 }
13451 sub make_numbered_footnotes {
13452 eval "sub do_cmd_thefootnote {\&numbered_footnotes}" }
13453 sub numbered_footnotes { &do_cmd_arabic('<<0>>footnote<<0>>');}
13455 # default numbering style for minipage notes
13456 sub do_cmd_thempfootnote { &do_cmd_arabic('<<0>>mpfootnote<<0>>'); }
13458 sub do_cmd_footnotemark { &do_real_cmd_footnotemark(@_) }
13459 sub do_real_cmd_footnotemark {
13460 local($_) = @_;
13461 local($br_id, $footnote,$marker,$mpnote,$tmp,$smark,$emark);
13462 # Don't use ()'s for the optional argument!
13463 local($mark,$dum) = &get_next_optional_argument;
13464 local ($cnt,$text_known) = ('','');
13465 if ($mark) {
13466 $cnt = (($mark =~ /\\/)? &translate_commands($mark) : $mark);
13467 if (($MINIPAGE)&&($mpfootnotes{$cnt})) {
13468 $mpnote = 1;
13469 $br_id = $mpfootnotes{$cnt};
13470 $text_known = 1;
13471 } else {
13472 $global{'footnote'} = $cnt;
13473 local($tmp) = $footnotes{$cnt};
13474 if ($tmp) {
13475 $br_id = $tmp;
13476 $text_known = 1;
13477 } else { $footnotes{$cnt} = $br_id }
13478 }
13479 } else {
13480 $cnt = ++$global{'footnote'};
13481 $text_known = 1 if ($footnotes{$cnt});
13482 }
13483 if ($text_known) {
13484 $br_id = ($MINIPAGE ? $mpfootnotes{$cnt} : $footnotes{$cnt});
13485 $marker = &get_footnote_mark($mpnote);
13486 return (join('', &make_href("$footfile#foot$br_id",$marker),$_));
13487 }
13489 local($last_word) = &get_last_word() unless ($mpnote);
13491 # Try to find a \footnotetext further on.
13492 do {
13493 if (s/\\footnotetext\s*\[\s*$cnt\s*]*\]\s*$any_next_pair_pr_rx//o) {
13494 ($br_id, $footnote) = ($2, $3);
13495 } else {
13496 $br_id = "fnm$cnt";
13497 $footnotes{$cnt} = $br_id;
13498 }
13499 } unless ($br_id);
13501 $marker = &get_footnote_mark($mpnote);
13502 $last_word .= $marker unless ($marker =~ /$footnote_mark/ );
13503 if ($footnote) {
13504 # found a \footnotetext further on
13505 &process_footnote($footnote,$cnt,$br_id,$last_word,$mark);
13506 join('',&make_named_href("foot$br_id","$footfile#$br_id",$marker),$_);
13507 } elsif ($br_id =~ /fnm/) {
13508 # no \footnotetext yet, so make the entry in $footnotes
13509 &process_footnote('',$cnt,$br_id,$last_word,$mark);
13510 # this may not work if there is a <BASE> tag and !($footfile) !!! #
13511 join('',&make_named_href("foot$br_id","$footfile#$br_id",$marker),$_);
13512 } elsif ($br_id) {
13513 # \footnotetext already processed
13514 if ($mpnote) {
13515 $mpfootnotes =~ s/(=\"$br_id\">...)(<\/A>)/$1$last_word$3/
13516 if ($last_word);
13517 # this may not work if there is a <BASE> tag !!! #
13518 join('',&make_named_href("foot$br_id","#$br_id",$marker),$_);
13519 } else {
13520 $footnotes =~ s/(=\"$br_id\">...)(<\/A>)/$1$last_word$3/;
13521 # this may not work if there is a <BASE> tag and !($footfile) !!! #
13522 join(''
13523 ,&make_named_href("foot$br_id","$footfile#$br_id",$marker),$_);
13524 }
13525 } else {
13526 print "\nCannot find \\footnotetext for \\footnotemark $cnt";
13527 # this may not work if there is a <BASE> tag and !($footfile) !!! #
13528 join('',&make_named_href("foot$br_id","$footfile",$marker),$_);
13529 }
13530 }
13532 # Under normal circumstances this is never executed. Any commands \footnotetext
13533 # should have been processed when the corresponding \footnotemark was
13534 # encountered. It is possible however that when processing pieces of text
13535 # out of context (e.g. \footnotemarks in figure and table captions)
13536 # the pair of commands gets separated. Until this is fixed properly,
13537 # this command just puts the footnote in the footnote file in the hope
13538 # that its context will be obvious ....
13539 sub do_cmd_footnotetext {
13540 local($_) = @_;
13541 local($mark,$dum) = &get_next_optional_argument;
13542 local($br_id, $footnote, $prev, $key)=(1,'','','');
13543 $footnote = &missing_braces unless (
13544 (s/$next_pair_pr_rx/($br_id,$footnote)=($1,$2);''/eo)
13545 ||(s/$next_pair_rx/($br_id,$footnote)=($1,$2);''/eo));
13547 $mark = $global{'footnote'} unless $mark;
13548 $prev = $footnotes{$mark};
13549 if ($prev) {
13550 $prev = ($MINIPAGE ? 'mp' : '') . $prev;
13551 # first prepare the footnote-text
13552 $footnote = &translate_environments("${OP}$br_id$CP$footnote${OP}$br_id$CP")
13553 if ($footnote);
13554 $footnote = &translate_commands($footnote) if ($footnote =~ /\\/);
13556 # now merge it onto the Footnotes page
13557 $footnotes =~ s/(=\"$prev\">\.\.\.)(.*<\/A>)(<\/DT>\n<DD>)\n/
13558 $1.'<html_this_mark>'.$3.$footnote/e;
13559 local($this_mark) = $2;
13560 $this_mark =~ s|(<SUP>)(?:<#\d+#>)?(\d+)(?:<#\d+#>)?(<\/SUP>)(<\/A>)$|
13561 "$4<A\n HREF=\"$CURRENT_FILE\#foot$prev\">$1$2$3$4"|e;
13562 $footnotes =~ s/<html_this_mark>/$this_mark/;
13563 } else {
13564 &process_footnote($footnote,$mark,$br_id,'','') if $footnote;
13565 }
13566 $_;
13567 }
13570 sub process_footnote {
13571 # Uses $before
13572 # Sets $footfile defined in translate
13573 # Modifies $footnotes defined in translate
13574 local($footnote, $cnt, $br_id, $last_word, $mark, $mini, $same_page) = @_;
13575 local($target) = $target;
13577 # first prepare the footnote-text
13578 local($br_idd, $fcnt); $br_id =~ /\D*(\d+)/; $br_idd = $1;
13579 $footnote = &translate_environments("$O$br_idd$C$footnote$O$br_idd$C")
13580 if ($footnote);
13581 $footnote = &translate_commands($footnote) if ($footnote =~ /\\/);
13583 local($space,$sfoot_style,$efoot_style) = ("\n",'','');
13584 if ((!$NO_FOOTNODE)&&(!$mini)&&(!$target)) {
13585 $footfile = "${PREFIX}$FOOT_FILENAME$EXTN";
13586 $space = ".\n" x 30;
13587 $space = "\n<PRE>$space</PRE>";
13588 } elsif ($target) {
13589 $target = $frame_body_name
13590 if (($frame_body_name)&&($target eq $frame_foot_name));
13591 $sfoot_style = '<SMALL>';
13592 $efoot_style = '</SMALL>';
13593 }
13595 if ($mark) {
13596 if ($mini) {
13597 $cnt = $mpfootnotes{$mark};
13598 if ($in_image) {
13599 $fcnt = $global{'mpfootnote'}; --$fcnt if $fcnt;
13600 $latex_body .= '\setcounter{mpfootnote}{'.($fcnt||"0")."}\n"
13601 unless ($foot_counters_recorded);
13602 }
13603 } else {
13604 $cnt = $footnotes{$mark};
13605 if ($in_image) {
13606 $fcnt = $global{'footnote'}; --$fcnt if $fcnt;
13607 $latex_body .= '\setcounter{footnote}{'.($fcnt||"0")."}\n"
13608 unless ($foot_counters_recorded);
13609 }
13610 }
13611 if ($cnt) {
13612 &write_warnings("\nredefined target for footnote $mark" )
13613 unless ( $cnt eq $br_id )
13614 }
13615 if ($mini) { $mpfootnotes{$mark} = "$br_id" }
13616 elsif ($br_id =~ /fnm\d+/) {
13617 $mark = "$footnotes{$cnt}";
13618 $footnotes{$cnt} = "$br_id";
13619 # $footnotes .= "\n<DT>$sfoot_style<A NAME=\"foot$br_id\">..."
13620 $footnotes .= "\n<DT>$sfoot_style<A NAME=\"$br_id\">..."
13621 . $last_word . "</A>$efoot_style</DT>\n<DD>\n"
13622 . $space . "\n</DD>";
13623 return;
13624 } else { $footnotes{$mark} = "$br_id" }
13625 } else {
13626 if ($mini) {
13627 $mpfootnotes{$cnt} = "$br_id";
13628 if ($in_image) {
13629 $fcnt = $global{'mpfootnote'}; --$fcnt if $fcnt;
13630 $latex_body .= '\setcounter{mpfootnote}{'.($fcnt||"0")."}\n"
13631 unless ($foot_counters_recorded);
13632 }
13633 } else {
13634 $footnotes{$cnt} = "$br_id";
13635 if ($in_image) {
13636 $fcnt = $global{'footnote'}; --$fcnt if $fcnt;
13637 $latex_body .= '\setcounter{footnote}{'.($fcnt||"0")."}\n"
13638 unless ($foot_counters_recorded);
13639 }
13640 }
13641 }
13643 # catch a \footnotemark *after* the \footnotetext
13644 if ((!$footnote)&&($last_word)&&(!$mini)) {
13645 # $footnotes .= "\n<DT>$sfoot_style<A NAME=\"foot$br_id\">..."
13646 $footnotes .= "\n<DT>$sfoot_style<A NAME=\"$br_id\">..."
13647 . $last_word
13648 . "</A>$efoot_style</DT>\n<DD>\n" . $space . "\n</DD>";
13650 } elsif ($mini) {
13651 if ($HTML_VERSION < 3.0) { $mini .= "." }
13652 $mpfootnotes .= "\n<DD>$sfoot_style<A NAME=\"foot$br_id\">$mini</A> " .
13653 $footnote . $efoot_style . "\n</DD>\n";
13654 } elsif ($same_page) {
13655 local($link,$text);
13656 $same_page =~ s/:/$text=$`;$link=$';''/e;
13657 $same_page = &make_named_href("","$CURRENT_FILE\#$link",$text) if($link);
13658 $footnotes .= "\n<DT>$sfoot_style<A NAME=\"foot$br_id\">...$last_word</A>"
13659 . $same_page . $efoot_style . "</DT>\n<DD>" . $sfoot_style
13660 . $footnote . $efoot_style . "\n". $space . "\n</DD>";
13661 } else {
13662 $footnotes .= "\n<DT>$sfoot_style<A NAME=\"foot$br_id\">...$last_word</A>"
13663 . $efoot_style . "</DT>\n<DD>" . $sfoot_style
13664 . $footnote . "$efoot_style\n" . $space . "\n</DD>";
13665 }
13666 }
13669 sub do_cmd_appendix {
13670 $latex_body .= "\\appendix\n";
13671 if ($section_commands{$outermost_level} == 3) {
13672 $global{'section'} = 0;
13673 &reset_dependents('section');
13674 eval "sub do_cmd_thesection{ &do_cmd_the_appendix(3,\@_) }";
13675 } else {
13676 $global{'chapter'} = 0;
13677 &reset_dependents('chapter');
13678 eval "sub do_cmd_thechapter{ &do_cmd_the_appendix(2,\@_) }";
13679 }
13680 $_[0];
13681 }
13683 sub do_cmd_the_appendix {
13684 local($val,$level) = (0,$_[0]);
13685 if ($level == 3) { $val=$global{'section'} }
13686 elsif ($level == 2) { $val=$global{'chapter'} }
13687 join('', &fAlph($val), '.', $_[1]);
13688 }
13690 sub do_cmd_appendixname { $app_title . $_[0] }
13691 sub do_cmd_abstractname { $abs_title . $_[0] }
13692 sub do_cmd_keywordsname { $key_title . $_[0] }
13693 sub do_cmd_subjclassname { $sbj_title . $_[0] }
13694 sub do_cmd_indexname { $idx_title . $_[0] }
13695 sub do_cmd_contentsname { $toc_title . $_[0] }
13696 sub do_cmd_datename { $date_name . $_[0] }
13697 sub do_cmd_refname { $ref_title . $_[0] }
13698 sub do_cmd_bibname { $bib_title . $_[0] }
13699 sub do_cmd_figurename { $fig_name . $_[0] }
13700 sub do_cmd_listfigurename { $lof_title . $_[0] }
13701 sub do_cmd_tablename { $tab_name . $_[0] }
13702 sub do_cmd_listtablename { $lot_title . $_[0] }
13703 sub do_cmd_partname { $part_name . $_[0] }
13704 sub do_cmd_chaptername { $chapter_name . $_[0] }
13705 sub do_cmd_sectionname { $section_name . $_[0] }
13706 sub do_cmd_subsectionname { $subsection_name . $_[0] }
13707 sub do_cmd_subsubsectionname { $subsubsection_name . $_[0] }
13708 sub do_cmd_paragraphname { $paragraph_name . $_[0] }
13709 sub do_cmd_thmname { $thm_title . $_[0] }
13710 sub do_cmd_proofname { $prf_name . $_[0] }
13711 sub do_cmd_footnotename { $foot_title . $_[0] }
13712 sub do_cmd_childlinksname { '<STRONG>'.$child_name.'</STRONG>'. $_[0] }
13713 sub do_cmd_infopagename { $info_title . $_[0] }
13716 sub do_cmd_ref {
13717 local($_) = @_;
13718 &process_ref($cross_ref_mark,$cross_ref_mark);
13719 }
13721 sub do_cmd_eqref {
13722 local($_) = @_;
13723 join('','(',&process_ref($cross_ref_mark,$cross_ref_mark,'',')'));
13724 }
13726 sub do_cmd_pageref {
13727 local($_) = @_;
13728 &process_ref($cross_ref_mark,$cross_ref_visible_mark);
13729 }
13731 # This is used by external style files ...
13732 sub process_ref {
13733 local($ref_mark, $visible_mark, $use_label, $after_label) = @_;
13734 $use_label = &balance_inner_tags($use_label)
13735 if $use_label =~ (/<\/([A-Z]+)>($math_verbatim_rx.*)<\1>/);
13736 $use_label = &translate_environments($use_label);
13737 $use_label = &simplify(&translate_commands($use_label))
13738 if ($use_label =~ /\\/ );
13739 local($label,$id);
13740 local($pretag) = &get_next_optional_argument;
13741 $pretag = &translate_commands($pretag) if ($pretag =~ /\\/);
13742 $label = &missing_braces unless (
13743 (s/$next_pair_pr_rx/($id, $label) = ($1, $2);''/eo)
13744 ||(s/$next_pair_rx/($id, $label) = ($1, $2);''/eo));
13745 if ($label) {
13746 $label =~ s/<[^>]*>//go ; #RRM: Remove any HTML tags
13747 $label =~ s/$label_rx/_/g; # replace non alphanumeric characters
13749 $symbolic_labels{"$pretag$label$id"} = $use_label if ($use_label);
13750 if (($symbolic_labels{$pretag.$label})&&!($use_label)) {
13751 $use_label = $symbolic_labels{$pretag.$label}
13752 }
13753 # if (!($use_label eq $label)) {
13754 # $symbolic_labels{"$label$id"} = $use_label;
13755 # };
13756 # if $use_label is empty then $label is used as the cross_ref_mark
13757 # elseif $use_label is a string then $use_label is used
13758 # else the usual mark will be used
13759 $use_label = ( (!$use_label && $label) || $use_label);
13761 print "\nLINK: $ref_mark\#$label\#$id :$use_label:" if ($VERBOSITY > 3);
13762 # The quotes around the HREF are inserted later
13763 join('',"<A HREF=$ref_mark#$label#$id>$visible_mark<\/A>",$after_label, $_);
13764 }
13765 else {
13766 print "Cannot find label argument after <$last_word>\n" if $last_word;
13767 $after_label . $_;
13768 }
13769 }
13771 #RRM: This removes unbalanced tags, due to closures for math inside
13772 # the label-text for an <A> anchor.
13773 sub balance_inner_tags {
13774 local($text) = @_;
13775 return($text) unless ($text =~ /<\/([A-Z]+)>(\s*$math_verbatim_rx.*)(<\1( [^>]*)?>)/);
13776 local($beforeT,$afterT,$tag,$math_verb,$stag) = ($`,$',$1,$2,$3);
13777 if (!($beforeT =~ /<$tag>/)) {
13778 $text = join('', $beforeT, $math_verb, $afterT);
13779 return (&balance_inner_tags($text));
13780 }
13781 local(@pieces) = split (/<$tag>/, $beforeT );
13782 $beforeT = shift (@pieces);
13783 local($cnt,$this) = (0,'');
13784 while (@pieces) {
13785 $this = shift @pieces;
13786 $cnt++;
13787 $beforeT .= "<$tag>".$this;
13788 $cnt = $cnt - ($this =~ /<\/$tag>/g);
13789 }
13790 if ($cnt) {
13791 $beforeT .= "<\/$tag>" . $math_verb . $stag;
13792 $text = $beforeT . $afterT;
13793 } else {
13794 $beforeT .= $math_verb;
13795 $text = join('', $beforeT, $math_verb, $afterT);
13796 return (&balance_inner_tags($text));
13797 }
13798 $text;
13799 }
13801 # Uses $CURRENT_FILE defined in translate
13802 sub do_cmd_label {
13803 local($_) = @_;
13804 local($label);
13805 $label = &missing_braces unless (
13806 (s/$next_pair_pr_rx\n?/$label = $2;''/eo)
13807 ||(s/$next_pair_rx\n?/$label = $2;''/eo));
13808 &anchor_label($label,$CURRENT_FILE,$_);
13809 }
13811 # This subroutine is also used to process labels in undefined environments
13812 sub anchor_label { &real_anchor_label(@_) }
13813 sub real_anchor_label {
13814 # Modifies entries in %ref_files defined in translate
13815 local($label,$filename,$context) = @_;
13816 $label =~ s/<[^>]*>//go; #RRM: Remove any HTML tags
13817 $label =~ s/$label_rx/_/g; # replace non alphanumeric characters
13818 # Associate the label with the current file
13819 if ($ref_files{$label} ne $filename) {
13820 $ref_files{$label} = $filename;
13821 $noresave{$label} = 0; $changed = 1; }
13822 print "<LABEL: $label>" if ($VERBOSITY > 3);
13823 join('',"<A NAME=\"$label\">$anchor_mark</A>",$context);
13824 }
13826 sub do_cmd_cite {
13827 local($_) = @_;
13828 &process_cite('','');
13829 }
13832 # This just creates a link from a label (yet to be determined) to the
13833 # cite_key in the citation file.
13834 sub process_cite { &process_real_cite(@_) }
13835 sub process_real_cite {
13836 local($mode,$text) = @_;
13837 my $has_text = (($text)? 1 : 0);
13838 # local($target) = 'contents';print "\nCITE:$text";
13839 # process the text from \htmlcite or \hypercite
13840 if ($has_text) {
13841 $text = &balance_inner_tags($text)
13842 if $use_label =~ (/<\/([A-Z]+)>($math_verbatim_rx.*)<\1>/);
13843 $text = &translate_environments($text);
13844 $text = &simplify(&translate_commands($text))
13845 if ($use_label =~ /\\/ );
13846 }
13848 my $label, $cite_key, $pretag, @cite_keys;
13849 local($optional_text,$dummy) = &get_next_optional_argument;
13850 if ($mode =~ /external/) {
13851 # $target = '';
13852 $pretag = $optional_text; $optional_text = '';
13853 $pretag = &translate_commands($pretag) if ($pretag =~ /\\/);
13854 } else {
13855 $optional_text = ", $optional_text" if $optional_text;
13856 }
13857 s/^\s*\\space//o; # Hack - \space is inserted in .aux
13858 s/$next_pair_pr_rx//o||s/$next_pair_rx//o;
13859 if (!($cite_key = $2)) {
13860 print "\n *** Cannot find citation argument\n";
13861 return ($_);
13862 }
13863 @cite_keys = (split(/,/,$cite_key));
13864 my ($citations, $join) = ('',',');
13865 $join = '' if ($text);
13866 foreach $cite_key (@cite_keys) {
13867 $cite_key =~ s/(^\s+|\s+$)//g;
13868 $cite_key =~ s/(^\s+|\s+$)//g;
13869 # RRM: if the URL and printable-key are known already, then use them...
13870 $cite_key =~ s/$label_rx/_/g;
13871 $label = $cite_key;
13872 if ($mode eq "nocite") {
13873 # nothing more to do, no citations
13874 } elsif ( ($SEGMENT) && ($cite_info{$cite_key})
13875 && ($ref_files{"cite_$cite_key"}) ) {
13876 $join = "," unless ($text);
13877 $text = $cite_info{$cite_key} unless ($text);
13878 $citations .= join('', $join
13879 , &make_named_href($label,$ref_files{'cite_'."$cite_key"},$text));
13880 } elsif (($mode eq "external")&&($external_labels{$pretag."cite_$cite_key"})) {
13881 $join = "," unless ($text);
13882 $text = $cross_ref_visible_mark unless ($text);
13883 $citations .= join('', $join
13884 , &make_named_href($label
13885 , $external_labels{$pretag.'cite_'."$cite_key"}."\#$label"
13886 , $text)
13887 );
13888 } elsif ($mode eq 'external') {
13889 $join = "," unless ($text);
13890 &write_warnings("\nExternal reference missing for citation: $pretag$cite_key");
13891 $citations .= "$text$join#!$pretag$cite_key!#";
13892 } else {
13893 $join = "," unless ($text);
13894 #Replace the key...
13895 $citations .= "$join#$cite_key#$cite_mark#$bbl_nr#$text#$cite_mark#";
13896 }
13897 $text = '';
13898 }
13899 $citations =~ s/^\s*,\s*//;
13900 if ($has_text) { join('', $citations, $optional_text, $_) }
13901 else { join('', "[", $citations, $optional_text, "]", $_) }
13902 }
13904 sub do_cmd_index { &do_real_index(@_) }
13905 sub do_real_index {
13906 local($_) = @_;
13907 local($br_id, $str);
13908 local($idx_option) = &get_next_optional_argument;
13909 $str = &missing_braces unless (
13910 (s/$next_pair_pr_rx/($br_id, $str) = ($1, $2);''/eo)
13911 ||(s/$next_pair_rx/($br_id, $str) = ($1, $2);''/eo));
13912 join('',&make_index_entry($br_id,$str),$_);
13913 }
13914 sub do_cmd_indexstar { &do_cmd_index(@_) }
13916 # RRM: \bibcite supplies info via the .aux file; necessary with segmented docs.
13917 sub do_cmd_bibcite {
13918 local($_) = @_;
13919 local($br_id, $cite_key,$print_key);
13920 $cite_key = &missing_braces unless (
13921 (s/$next_pair_pr_rx/($br_id, $cite_key) = ($1, $2);''/eo)
13922 ||(s/$next_pair_rx/($br_id, $cite_key) = ($1, $2);''/eo));
13923 $print_key = &missing_braces unless (
13924 (s/$next_pair_pr_rx/($br_id, $print_key) = ($1, $2);''/eo)
13925 ||(s/$next_pair_rx/($br_id, $print_key) = ($1, $2);''/eo));
13926 $cite_key =~ s/$label_rx/_/g;
13927 $cite_info{$cite_key} = $print_key;
13928 $_;
13929 }
13931 # This command will only be encountered inside a thebibliography environment.
13932 sub do_cmd_bibitem { &do_real_bibitem($CURRENT_FILE, @_) }
13933 sub do_real_bibitem {
13934 local($thisfile, $_) = @_;
13935 # The square brackets may contain the label to be printed
13936 local($label, $dummy) = &get_next_optional_argument;
13937 # Support for the "named" bibliography style
13938 if ($label) {
13939 $label =~ s/\\protect//g;
13940 $label = &translate_commands($label) if ($label =~ /\\/);
13941 }
13942 local($cite_key);
13943 $cite_key = &missing_braces unless (
13944 ( s/$next_pair_pr_rx/$cite_key=$2;''/e )
13945 ||( s/$next_pair_rx/$cite_key=$2;''/e ));
13947 $cite_key =~ s/$label_rx/_/g;
13948 $label = $cite_info{$cite_key} unless $label; # read from .aux file
13949 $label = ++$bibitem_counter unless $label; # Numerical labels
13951 if ($cite_key) {
13952 # Associate the cite_key with the printed label.
13953 # The printed label will be substituted back into the document later.
13954 $cite_info{$cite_key} = &translate_commands($label);
13955 if (!($ref_files{'cite_'."$cite_key"} eq $thisfile)) {
13956 $ref_files{'cite_'."$cite_key"} = $thisfile;
13957 $changed = 1; }
13959 #RRM: apply any special styles, as defined below
13960 $label = &bibitem_style($label) if (defined &bibitem_style);
13961 # Create an anchor around the citation
13962 join('',"<P></P><DT><A NAME=\"$cite_key\">$label</A>\n<DD>", $_);
13964 } else {
13965 print "Cannot find bibitem labels: $label\n";
13967 #RRM: apply any special styles, as defined below
13968 $label = &bibitem_style($label) if (defined &bibitem_style);
13969 join('',"<P></P><DT>$label\n<DD>", $_); # AFEB added this line
13970 }
13971 }
13973 #RRM: override this with a personal style, defined in .latex2html-init
13974 #sub bibitem_style { join('','<STRONG>',$_[0],'</STRONG>') }
13975 sub bibitem_style {
13976 return ($_[0]) unless $BIBITEM_STYLE;
13977 local($text) = join(''
13978 ,"${O}0$C",$BIBITEM_STYLE,"${O}1$C", @_, "${O}1$C","${O}0$C");
13979 $text = &translate_environments($text);
13980 &translate_commands($text);
13981 }
13983 sub do_cmd_newblock {
13984 "<BR>".$_[0]
13985 }
13987 # This just reads in the $FILE.bbl file if it is available and appends
13988 # it to the items that are still to be processed.
13989 # The $FILE.bbl should contain a thebibliography environment which will
13990 # cause its contents to be processed later in the appropriate way.
13991 # (Note that it might be possible for both the \bibliography command and
13992 # the thebibliography environment to be present as the former may have been
13993 # added by the translator as a sectioning command. In this case (both present)
13994 # the $citefile would have already been set by the thebibliography environment)
13996 sub do_cmd_bibliography { &do_real_bibliography($CURRENT_FILE, @_) }
13997 sub do_real_bibliography {
13998 local($thisfile, $after) = @_;
13999 if ((defined &do_cmd_bibname)||$new_command{'bibname'}) {
14000 local($br_id)=++$global{'max_id'};
14001 $TITLE = &translate_environments("$O$br_id$C\\bibname$O$br_id$C");
14002 } else { $TITLE = $bib_title }
14003 $toc_sec_title = $TITLE;
14004 return($_[0]) if ($making_name);
14005 local($bibfile);
14006 $bibfile = &missing_braces unless (
14007 ($after =~ s/$next_pair_rx/$bibfile=$2;''/eo)||
14008 ($after =~ s/$next_pair_rx_rx/$bibfile=$2;''/eo));
14010 do {
14011 unless ($citefile) {
14012 $citefile = $thisfile;
14013 if (&process_ext_file("bbl")) { # *** BINDS $_ as a side effect ***
14014 $after = join('',$_,$after);}
14015 else {
14016 print "\nCannot open $FILE.bbl $!\n";
14017 &write_warnings("\nThe bibliography file was not found.");
14018 $after = join('',"\n<H2>No References!</H2>", $after);
14019 }
14020 }
14021 print "\n";
14022 } if $bibfile;
14023 $after;
14024 }
14026 # allow for customised info-pages, for different languages
14027 sub do_cmd_textohtmlinfopage {
14028 local($_) = @_;
14029 local($linfo) = $TITLES_LANGUAGE . '_infopage';
14030 if (defined &$linfo) { eval "&$linfo"; }
14031 else { &default_textohtmlinfopage }
14032 }
14034 sub default_textohtmlinfopage {
14035 local($_) = @_;
14036 local($argv) = $argv;
14037 if (-f "../$argv") { $argv = &make_href ("../$argv", $argv, ); }
14038 $_ = ($INFO && $INFO =~ /^\d+$/
14039 ? join('', $close_all
14040 , "<STRONG>$t_title</STRONG><P>\nThis document was generated using the\n"
14041 , "<A HREF=\"$TEX2HTMLADDRESS\"><STRONG>LaTeX</STRONG>2<tt>HTML</tt></A>"
14042 , " translator Version $TEX2HTMLVERSION\n"
14043 , "<P>Copyright © 1993, 1994, 1995, 1996,\n"
14044 , "<A HREF=\"$AUTHORADDRESS\">Nikos Drakos</A>, \n"
14045 , "Computer Based Learning Unit, University of Leeds.\n"
14046 , "<BR>Copyright © 1997, 1998, 1999,\n"
14047 , "<A HREF=\"$AUTHORADDRESS2\">Ross Moore</A>, \n"
14048 , "Mathematics Department, Macquarie University, Sydney.\n"
14049 , "<P>The command line arguments were: <BR>\n "
14050 , "<STRONG>latex2html</STRONG> <TT>$argv</TT>\n"
14051 , (($SHOW_INIT_FILE && ($INIT_FILE ne ''))?
14052 "\n<P>with initialization from: <TT>$INIT_FILE</TT>\n$init_file_mark\n" :'')
14053 , "<P>The translation was initiated by $address_data[0] on $address_data[1]"
14054 , $open_all, $_)
14055 : join('', $close_all, "$INFO\n", $open_all, $_));
14056 $_;
14057 }
14060 # Try to translate LaTeX vertical space in a number of <BR>'s.
14061 # Eg. 1cm results in one + two extra <BR>'s.
14062 # To help the browser rendering is quite ugly, but why not.
14063 #
14064 sub get_vspace {
14065 local($_) = @_;
14066 local($vh) = 0;
14068 return("<BR>") if /-/;
14070 $vh = int($1 * $vspace_12pt{$2} + 0.5)
14071 if (/([0-9.]+)\s*([a-z]+)/);
14072 join('',"<BR>","\n<BR>" x $vh);
14073 }
14075 sub do_cmd_vskip {
14076 local($_) = @_;
14077 &ignore_numeric_argument;
14078 join('',&get_vspace($1),$_);
14079 }
14081 sub do_cmd_break {
14082 local($_) = @_;
14083 join('',"<BR>",$_);
14084 }
14086 sub do_cmd_vspace {
14087 local($_) = @_;
14088 local($how_much);
14089 $how_much = &missing_braces unless (
14090 (s/$next_pair_pr_rx/$how_much = $2;''/e)
14091 ||(s/$next_pair_rx/$how_much = $2;''/e));
14092 join('',&get_vspace($how_much),$_);
14093 }
14095 sub do_cmd_vspacestar {
14096 &do_cmd_vspace;
14097 }
14099 sub do_cmd_d_backslash {
14100 local($_) = @_;
14102 # Eat space from &pre_process.
14103 # We could also modifiy $single_cmd_rx and %normalize, but why not here.
14104 s/^ \*?//;
14105 local($spc,$dum)=&get_next_optional_argument;
14106 # If the [...] occurs on the next line, then it is *not* an argument to \\ .
14107 # MRO: replaced $* with /m
14108 if ($dum =~ /\n/m) {
14109 $spc = $`;
14110 $spc =~ s/\s//gm;
14111 $_ = $'.$_
14112 }
14113 join('',(($spc)? &get_vspace($spc): "\n<BR>"),$_);
14114 }
14117 ################## Commands used in the $FILE.aux file #######################
14119 sub do_cmd_jobname { $FILE . $_[0] }
14121 # This is used in $FILE.aux
14122 sub do_cmd_newlabel {
14123 local($_) = @_;
14124 local($label,$val,$tmp);
14125 $label = &missing_braces unless (
14126 (s/$next_pair_pr_rx/$label = $2;''/eo)
14127 ||(s/$next_pair_rx/$label = $2;''/eo));
14128 $tmp = &missing_braces unless (
14129 (s/$next_pair_pr_rx/$tmp=$2;''/eo)
14130 ||(s/$next_pair_rx/$tmp=$2;''/eo));
14131 $val = &missing_braces unless (
14132 ($tmp =~ s/$next_pair_pr_rx/$val=$2;''/eo)
14133 ||($tmp =~ s/$next_pair_rx/$val=$2;''/eo));
14134 $val =~ s/(^\s+|\s+$)//gs;
14135 $label =~ s/$label_rx/_/g; # Replace non alphanumeric characters
14136 $latex_labels{$label} = $val;
14137 &do_labels_helper($label);
14138 $_;
14139 }
14140 sub do_cmd_oldnewlabel { &do_cmd_newlabel(@_) }
14142 #
14143 # Sets %encoded_(section|figure|table)_number, which maps encoded
14144 # section titles to LaTeX numbers
14145 # .= \$number . \"$;\"";
14146 sub do_cmd_oldcontentsline { &do_cmd_contentsline(@_) }
14147 sub do_cmd_contentsline {
14148 local($_) = @_;
14149 local($arg,$after,$title,$number,$hash,$stype,$page);
14150 # The form of the expression is:
14151 # \contentsline{SECTION} {... {SECTION_NUMBER} TITLE}{PAGE}
14152 $stype = &missing_braces unless (
14153 (s/$next_pair_pr_rx/$stype = $2;''/e)
14154 ||(s/$next_pair_rx/$stype = $2;''/e));
14155 $arg = &missing_braces unless (
14156 (s/$next_pair_pr_rx/$arg = $2;''/e)
14157 ||(s/$next_pair_rx/$arg = $2;''/e));
14158 $page = &missing_braces unless (
14159 (s/$next_pair_pr_rx/$page = $2;''/e)
14160 ||(s/$next_pair_rx/$page = $2;''/e));
14162 # s/$any_next_pair_pr_rx/$stype = $2;''/eo; # Chop off {SECTION}
14163 # s/$any_next_pair_pr_rx/$arg = $2;''/eo; # Get {... {SECTION_NUMBER} TITLE}
14164 # s/$any_next_pair_pr_rx/$page = $2;''/eo; # Get page number
14165 $hash = $stype if (($stype =~ /^(figure|table)$/)||($SHOW_SECTION_NUMBERS));
14166 $hash =~ s/(sub)*(section|chapter|part)/section/;
14167 $after = $_;
14168 if ($hash) {
14169 if ($arg =~ /^$OP/) {
14170 $number = &missing_braces unless (
14171 ($arg =~ s/$next_pair_pr_rx/$number = $2;''/eo)
14172 ||($arg =~ s/$next_pair_rx/$number = $2;''/eo));
14173 }
14174 if ($stype eq "part") {
14175 while ($arg =~ s/$next_pair_pr_rx//o) {};
14176 $number =~ tr/a-z/A-Z/;
14177 $number = "Part $number:"}
14178 # This cause problem when picking figure numbers...
14179 # while ($tmp =~ s/$next_pair_pr_rx//o) {};
14180 $number = -1 unless $number;
14181 #JCL(jcl-tcl)
14182 ## $_ = $arg;
14183 # $title = &sanitize($arg);
14184 ## &text_cleanup;
14185 ## $title = &encode_title($_);
14186 ##
14187 #remove surrounding brace-numbering
14188 $arg =~ s/^($O|$OP)\d+($C|$CP)|($O|$OP)\d+($C|$CP)$//g;
14189 $arg =~ s/\\footnote(mark|text)?//g;
14190 # \caption arguments should have had environments translated already
14191 $arg = &translate_environments($arg) if ($arg =~ /\\begin/);
14192 #replace image-markers by the image params
14193 $arg =~ s/$image_mark\#([^\#]+)\#/&purify_caption($1)/e;
14195 #RRM: resolve any embedded cross-references first
14196 local($checking_caption) = 1;
14197 $title = &simplify($arg);
14198 $title = &sanitize($title);
14199 $checking_caption = '';
14200 eval "\$encoded_${hash}_number{\$title} .= \$number . \"$;\"";
14201 }
14202 $after;
14203 }
14205 #
14206 # Before normalizing this was \@input. Used in .aux files.
14207 #
14208 sub do_cmd__at_input {
14209 local ($_) = @_;
14210 local ($file, $after);
14211 $file = &missing_braces unless (
14212 (s/$next_pair_pr_rx/$file=$2;''/eo)
14213 ||(s/$next_pair_rx/$file=$2;''/eo));
14214 local($prefix, $suffix) = split(/\./, $file);
14215 $after = $_;
14216 local($EXTERNAL_FILE) = $prefix;
14217 &process_ext_file($suffix);
14218 $after;
14219 }
14222 ########################### Counter Commands #################################
14223 # Removes the definition from the input string, adds to the preamble
14224 # and stores the body in %new_counter;
14225 sub get_body_newcounter {
14226 # local(*_) = @_;
14227 local($after_R) = @_;
14228 local($_) = $$after_R;
14229 local($within,$ctr,$cmd,$tmp,$body,$pat);
14230 local($new_ctr) = 'counter';
14231 ($ctr,$pat) = &get_next(1); # Get counter name
14232 &write_warnings ("\n*** LaTeX Error: backslash found in counter-name: $ctr")
14233 if ($pat =~ s/\\//);
14234 $ctr =~ s/^\s*\\//;
14235 $new_ctr .= $pat;
14237 ($within,$pat) = &get_next(0); # Get optional within, currently ignored
14238 &addto_dependents($within,$ctr);
14239 $new_ctr .= $pat;
14240 do {
14241 ### local($_) = "\\arabic<<1>>$ctr<<1>>";
14242 $body = "\\arabic<<1>>$ctr<<1>>";
14243 &make_unique($body);
14244 $cmd = "the$ctr";
14245 $tmp = "do_cmd_$cmd";
14246 $new_command{$cmd} = join(':!:',0,$body,'}') unless (defined &$tmp);
14247 &write_mydb("new_command", $cmd, $new_command{$cmd});
14248 undef $body;
14249 };
14250 &do_body_newcounter($ctr);
14252 $$after_R = $_;
14253 if (!$PREAMBLE) {
14254 my $new_cmd = join(''
14255 , "counter{$ctr}", ($within ? "[$within]" : '') );
14256 &add_to_preamble('counter','\\new'.$new_cmd);
14257 return ();
14258 }
14259 'newed'.$new_ctr;
14260 }
14262 sub do_body_newcounter {
14263 local($ctr) = @_;
14264 $latex_body .= &revert_to_raw_tex("\\newcounter{$ctr}\n")
14265 unless ($preamble =~ /\\new(counter|theorem){$ctr}/);
14266 $global{$ctr} = 0;
14267 &process_commands_wrap_deferred("the$ctr ");
14268 $_;
14269 }
14272 #RRM: This doesn't work properly yet.
14273 # The new booleans need to be stored for use in all partitions.
14274 # \if... \else \fi is not yet implemented.
14276 sub get_body_newboolean {
14277 # local(*_) = @_;
14278 local($after_R) = @_;
14279 local($_) = $$after_R;
14280 my $bool;
14281 $bool = &missing_braces unless (
14282 (s/$next_pair_pr_rx/$bool=$2;''/e)
14283 ||(s/$next_pair_rx/$bool=$2;''/e));
14284 $bool = &process_body_newif('',$bool);
14285 $$after_R = $_;
14286 'newed'.$bool;
14287 }
14289 sub get_body_newif {
14290 # local(*_) = @_;
14291 local($after_R) = @_;
14292 local($_) = $$after_R;
14293 local($bool);
14294 if (!(s/^\s*\\if([a-zA-Z]+)//)) {
14295 $$after_R = $_;
14296 return();
14297 }
14298 $bool = $1;
14299 $$after_R = $_;
14300 join('','newed', &process_body_newif('', $bool));
14301 }
14304 sub process_body_newif {
14305 local($texif, $bool) = @_;
14306 local($body,$ifbool,$cmd,$tmp,$pat);
14308 # ($bool,$pat) = &get_next(1); # Get boolean name
14310 # # change the brace-type around the command-name
14311 # $pat =~ s/$O/$OP/; $pat =~ s/$C/$CP/; $new_cmd .= $pat;
14313 $ifbool = "if".$bool;
14314 $global{$ifbool} = 0;
14316 do {
14317 $body = "\$global{'$ifbool'} = 1;";
14318 $cmd = $bool."true";
14319 $code = "sub do_cmd_$cmd { ".$body." \$_[0];}";
14320 eval $code;
14321 print STDERR "\n*** sub do_cmd_$cmd failed:\n$@\n" if ($@);
14322 $raw_arg_cmds{$cmd} = 1;
14324 $body = "\$global{$ifbool} = 0;";
14325 $cmd = $bool."false";
14326 $code = "sub do_cmd_$cmd { ".$body." \$_[0];}";
14327 eval $code;
14328 print STDERR "\n*** sub do_cmd_$cmd failed:\n$@\n" if ($@);
14329 $raw_arg_cmds{$cmd} = 1;
14331 undef $body;
14332 };
14333 &process_commands_wrap_deferred("${bool}true\n${bool}false\nif$bool\n");
14335 # $latex_body .= &revert_to_raw_tex("\\newif\\$ifbool\n")
14336 # unless ($preamble =~ /\\newif\s*\\$ifbool/);
14338 if (!$PREAMBLE) {
14339 local($new_cmd) = "boolean{\\$bool}";
14340 &add_to_preamble ('newif', "\\new$new_cmd" );
14341 return ();
14342 }
14343 local($br_id) = ++$global{'max_id'};
14344 'boolean'."$O$br_id$C$bool$O$br_id$C";
14345 }
14348 sub do_cmd_value {
14349 local($_) = @_;
14350 local($ctr,$val);
14351 $ctr = &missing_braces
14352 unless ((s/$next_pair_pr_rx/$ctr = $2;''/eo)
14353 ||(s/$next_pair_rx/$ctr = $2;''/eo));
14354 $val = &get_counter_value($ctr);
14355 if ($val) { $val.$_ }
14356 else { join(''," 0",$_) }
14357 }
14359 sub do_cmd_boolean {
14360 local($_) = @_;
14361 local($bool,$val);
14362 $bool = &missing_braces
14363 unless ((s/$next_pair_pr_rx/$bool = $2;''/eo)
14364 ||(s/$next_pair_rx/$bool = $2;''/eo));
14365 $val = &get_boolean_value($bool);
14366 if ($val) { $val.$_ }
14367 else { "0".$_ }
14368 }
14370 sub get_counter_value {
14371 local($ctr) = @_;
14372 local($val,$index);
14373 $ctr = 'eqn_number' if ($ctr eq "equation");
14374 $index = $section_commands{$ctr};
14376 if (defined $global{$ctr}) { $val= $global{$ctr}; }
14377 elsif (($SEGMENT)&&($index)) {
14378 $val = $segment_sec_id[$index]
14379 # if ($index) {
14380 # if ($SEGMENT) { $val = $segment_sec_id[$index] }
14381 # else { $val = $curr_sec_id[$index] }
14382 } else {
14383 &write_warnings ("\ncounter $ctr not defined");
14384 $val= 0;
14385 }
14386 print "\nVAL:$ctr: $val " if ($VERBOSITY > 3);
14387 $val;
14388 }
14390 sub get_boolean_value {
14391 local($bool) = @_;
14392 local($val,$index);
14393 if (defined $global{$bool}) { $val= $global{$bool} }
14394 else {
14395 &write_warnings ("boolean $bool not defined\n");
14396 $val="0";
14397 }
14398 print "\nBOOL:$bool: $val " if ($VERBOSITY > 3);
14399 $val;
14400 }
14402 sub do_cmd_addtocounter {
14403 local($_) = @_;
14404 local($ctr,$num,$index);
14405 $ctr = &missing_braces
14406 unless ((s/$next_pair_rx/$ctr = $2;''/eo)
14407 ||(s/$next_pair_pr_rx/$ctr = $2;''/eo));
14408 $num = &missing_braces
14409 unless ((s/$next_pair_rx/$num = $2;''/eo)
14410 ||(s/$next_pair_pr_rx/$num = $2;''/eo));
14412 $num = &translate_commands($num) if ($num =~ /\\/);
14413 if ($num !~ /^\s*(\+|-)?\d+\s*$/) {
14414 print STDERR "\n*** cannot set counter $ctr to $num ***\n";
14415 return($_);
14416 }
14418 $latex_body .= &revert_to_raw_tex("\\addtocounter{$ctr}{$num}\n");
14419 $index = $section_commands{$ctr};
14421 if (defined $global{$ctr}) { $global{$ctr} += $num }
14422 elsif ($index) {
14423 if ($SEGMENT) { $segment_sec_id[$index] += $num }
14424 else { $curr_sec_id[$index] += $num }
14425 $global{$ctr} += $num;
14426 } elsif ($ctr eq "equation") {
14427 $global{'eqn_number'} += $num
14428 } else { $global{$ctr} += $num };
14429 print "\nADD:$ctr:+$num= ". $global{$ctr}." " if ($VERBOSITY > 3);
14430 # &reset_dependents($ctr) if ($dependent{$ctr});
14431 $_;
14432 }
14434 sub do_cmd_setcounter {
14435 local($_) = @_;
14436 local($ctr,$num,$index,$sctr);
14437 $ctr = &missing_braces
14438 unless ((s/$next_pair_rx/$ctr = $2;''/eo)
14439 ||(s/$next_pair_pr_rx/$ctr = $2;''/eo));
14440 $num = &missing_braces
14441 unless ((s/$next_pair_rx/$num = $2;''/eo)
14442 ||(s/$next_pair_pr_rx/$num = $2;''/eo));
14444 $num = &translate_commands($num) if ($num =~ /\\/);
14445 if ($num !~ /^\s*(\+|-)?\d+\s*$/) {
14446 print STDERR "\n*** cannot set counter $ctr to $num ***\n";
14447 return($_);
14448 }
14449 if ($ctr =~ /^l/) {
14450 $sctr = $';
14451 $ctr = $sctr if $section_commands{$sctr};
14452 }
14453 if (! $AUX_FILE && !($ctr =~ /page/ )) {
14454 $latex_body .= &revert_to_raw_tex("\\setcounter{$ctr}{$num}\n");
14455 $index = $section_commands{$ctr};
14456 if ($index) {
14457 if ($curr_sec_id[$index] <= $num ) {
14458 $curr_sec_id[$index] = $num
14459 } else {
14460 print "\nignoring \\setcounter{$ctr}{$num} currently at ",$curr_sec_id[$index] ;
14461 &write_warnings(join('',"\n\\setcounter{$ctr}{$num} ignored,"
14462 ," cannot reduce from ",$curr_sec_id[$index]));
14463 }
14464 $global{$ctr} = $num;
14465 } elsif ($ctr eq "equation") {$global{'eqn_number'} = $num }
14466 else { $global{$ctr} = $num };
14467 }
14468 print "\nSET:$ctr: = $num" if ($VERBOSITY > 3);
14469 # &reset_dependents($ctr) if ($dependent{$ctr});
14470 $_;
14471 }
14473 sub do_cmd_setlength {
14474 local($_) = @_;
14475 local($dimen,$value,$index,$sctr);
14476 $dimen = &missing_braces
14477 unless ((s/$next_pair_rx/$dimen = $2;''/eo)
14478 ||(s/$next_pair_pr_rx/$dimen = $2;''/eo));
14479 $value = &missing_braces
14480 unless ((s/$next_pair_rx/$value = $2;''/eo)
14481 ||(s/$next_pair_pr_rx/$value = $2;''/eo));
14483 # recognise specific length-parameters
14484 if ($dimen =~ /captionwidth/) {
14485 local($pxs,$len) = &convert_length($value, $MATH_SCALE_FACTOR);
14486 $cap_width = $pxs if ($pxs &&($dimen =~ /captionwidth/));
14487 }
14488 if ((! $AUX_FILE)&&(! $PREAMBLE)) {
14489 $latex_body .= &revert_to_raw_tex("\\setlength{$dimen}{$value}\n");
14490 print "\nSETLENGTH:$dimen = $value" if ($VERBOSITY > 3);
14491 }
14492 $_;
14493 }
14495 sub do_cmd_setboolean {
14496 local($_) = @_;
14497 local($bool,$val);
14498 $bool = &missing_braces
14499 unless ((s/$next_pair_rx/$bool = $2;''/eo)
14500 ||(s/$next_pair_pr_rx/$bool = $2;''/eo));
14501 $val = &missing_braces
14502 unless ((s/$next_pair_rx/$val = $2;''/eo)
14503 ||(s/$next_pair_pr_rx/$val = $2;''/eo));
14504 if (! $AUX_FILE) {
14505 $latex_body .= &revert_to_raw_tex("\\setboolean{$bool}{$val}\n");
14506 $global{"if$bool"} = (($val = ~/true/) ? 1 : 0);
14507 print "\nSETBOOL:$bool = $val" if ($VERBOSITY > 3);
14508 }
14509 $_;
14510 }
14512 sub do_cmd_endsegment {
14513 local($_) = @_;
14514 local($ctr,$dum) = &get_next_optional_argument;
14515 local($index,$steps) = ('',1);
14516 # $steps = &missing_braces unless (
14517 # (s/$next_pair_pr_rx/$steps = $2;''/e)
14518 # ||(s/$next_pair_rx/$steps = $2;''/e));
14519 $index = $section_commands{$ctr} if $ctr;
14520 # if ($index) { $curr_sec_id[$index] += $steps }
14521 # if ($index) { ($after_segment,$after_seg_num) = ($index,$steps) }
14522 if ($index) { ($after_segment,$after_seg_num) = ($index,1) }
14523 $_;
14524 }
14526 sub do_cmd_stepcounter {
14527 local($_) = @_;
14528 local($ctr,$index);
14529 $ctr = &missing_braces
14530 unless ((s/$next_pair_rx/$ctr = $2;''/eo)
14531 ||(s/$next_pair_pr_rx/$ctr = $2;''/eo));
14532 if (! $AUX_FILE) {
14533 $latex_body .= &revert_to_raw_tex("\\stepcounter{$ctr}\n");
14534 $index = $section_commands{$ctr};
14535 if ($index) {
14536 # if ($SEGMENT) { $segment_sec_id[$index] += 1 }
14537 # else { $curr_sec_id[$index] += 1 }
14538 $global{$ctr} += 1;
14539 } elsif ($ctr eq "equation") { $global{'eqn_number'} += 1 }
14540 else { $global{$ctr} += 1 };
14541 }
14542 print "\nSTP:$ctr:+1" if ($VERBOSITY > 3);
14543 &reset_dependents($ctr) if ($dependent{$ctr});
14544 $_;
14545 }
14547 #RRM: dependent counters are stored as a comma-separated list
14548 # in the %dependent hash.
14549 sub reset_dependents {
14550 local($ctr) = @_;
14551 local($dep,$subdep,%dependents);
14552 @dependents = (split($delim, $dependent{$ctr}));
14553 print "\n" if (($VERBOSITY > 3)&&(@dependents));
14554 while (@dependents) {
14555 $dep = pop(@dependents);
14556 print "RESET $dep to 0\n" if ($VERBOSITY > 3);
14557 if ($global{$dep}) { $global{$dep} = 0 }
14558 elsif ($dep =~ /equation/) { $global{'eqn_number'} = 0 }
14559 if ($dependent{$dep}) {
14560 push(@dependents,split($delim,$dependent{$dep}));
14561 }
14562 }
14563 }
14565 sub do_cmd_numberwithin {
14566 local($_) = @_;
14567 local($ctr,$within);
14568 $ctr = &missing_braces
14569 unless ((s/$next_pair_rx/$ctr = $2;''/eo)
14570 ||(s/$next_pair_pr_rx/$ctr = $2;''/eo));
14571 $within = &missing_braces
14572 unless ((s/$next_pair_rx/$within = $2;''/eo)
14573 ||(s/$next_pair_pr_rx/$within = $2;''/eo));
14575 # record the counter dependency
14576 &addto_dependents($within,$ctr) if ($within);
14577 local($newsub) = "sub do_cmd_the$ctr {"
14578 . "\$global{'max_id'}++;\n"
14579 # . "local(\$super)=\&do_cmd_the$within();\n"
14580 . "local(\$super)=\&translate_commands('\\the$within');\n"
14581 . "\$super .= '.' unless (\$super =~/\\.\$/);\n"
14582 . "\$super .\&do_cmd_value('<<'.\$global{'max_id'}.'>>"
14583 . $ctr . "<<'.\$global{'max_id'}.'>>')}\n";
14584 eval $newsub;
14585 print " *** sub do_cmd_the$ctr unchanged *** $@ " if ($@);
14586 $_;
14587 }
14589 sub do_cmd_refstepcounter {
14590 local($_) = @_;
14591 local($ctr);
14592 $ctr = &missing_braces
14593 unless ((s/$next_pair_rx/$ctr = $2;''/eo)
14594 ||(s/$next_pair_pr_rx/$ctr = $2;''/eo));
14595 if (! $AUX_FILE) {
14596 $latex_body .= &revert_to_raw_tex("\\refstepcounter{$ctr}\n");
14597 $index = $section_commands{$ctr};
14598 if (defined $global{$ctr}) { $global{$ctr} += 1 }
14599 elsif ($index) {
14600 if ($SEGMENT) { $segment_sec_id[$index] += 1 }
14601 else { $curr_sec_id[$index] += 1 }
14602 } elsif ($ctr eq "equation") { $global{'eqn_number'} += 1 }
14603 else { $global{$ctr} += 1 };
14604 }
14605 print "\nSTP: $ctr : +1" if ($VERBOSITY > 3);
14606 &reset_dependents($ctr) if ($dependent{$ctr});
14607 $_;
14608 }
14610 sub read_counter_value {
14611 local($_) = @_;
14612 local($ctr,$br_id,$val);
14613 $ctr = &missing_braces
14614 unless ((s/$next_pair_pr_rx/$br_id = $1; $ctr = $2;''/eo)
14615 ||(s/$next_pair_rx/$br_id = $1; $ctr = $2;''/eo));
14616 $val = &get_counter_value($ctr);
14617 ($ctr, $val, $br_id, $_)
14618 }
14620 sub styled_number_text {
14621 local($num_style, $val, $txtID) = @_;
14622 if ($USING_STYLES) {
14623 $txt_style{$num_style} = " " unless ($txt_style{$num_style});
14624 join('',"<SPAN CLASS=\"$num_style\">", $val, "</SPAN>", $_);
14625 } else { $val.$_ }
14626 }
14628 sub do_cmd_arabic {
14629 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14630 $val = ($val ? &farabic($val) : "0");
14631 &styled_number_text('arabic', $val, $id);
14632 }
14634 sub do_cmd_roman {
14635 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14636 if ($val < 0 ) { $val = join('',"-",&froman(-$val)); }
14637 elsif ($val) { $val = &froman($val) }
14638 else { $val = "0"; }
14639 &styled_number_text('roman', $val, $id);
14640 }
14642 sub do_cmd_Roman {
14643 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14644 if ($val < 0 ) { $val = join('',"-",&fRoman(-$val)); }
14645 elsif ($val) { $val = &fRoman($val) }
14646 else { $val = "0"; }
14647 &styled_number_text('Roman', $val, $id);
14648 }
14650 sub do_cmd_alph {
14651 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14652 if ($val < 0 ) { $val = join('',"-",&falph(-$val)); }
14653 elsif ($val) { $val = &falph($val) }
14654 else { $val = "0"; }
14655 &styled_number_text('alph', $val, $id);
14656 }
14658 sub do_cmd_Alph {
14659 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14660 if ($val < 0 ) { $val = join('',"-",&fAlph(-$val)); }
14661 elsif ($val) { $val = &fAlph($val) }
14662 else { $val = "0"; }
14663 &styled_number_text('Alph', $val, $id);
14664 }
14667 sub do_cmd_fnsymbol {
14668 local($ctr, $val, $id, $_) = &read_counter_value($_[0]);
14669 $val = &process_in_latex_helper($ctr, $val, "fnsymbol{$ctr}");
14670 &styled_number_text('Alph', $val, $id);
14671 }
14675 # This is a general command for getting counter values;
14676 # e.g. for section-numbers.
14678 sub do_cmd_thecounter {
14679 local($_) = @_;
14680 # Uses $counter bound by the caller
14681 local($val) = &get_counter_value($counter);
14682 $val = &process_in_latex_helper($counter,$val,"the$counter");
14683 &styled_number_text($counter, $val, '');
14684 # join('',&process_in_latex_helper($counter,$val,"the$counter"),$_[0]);
14685 }
14688 ################# Special Naming Macros ##################################
14690 sub do_cmd_LaTeX {
14691 local($_) = @_;
14692 if ($USING_STYLES) {
14693 $env_style{'LaTeX'} = ' ' unless ($env_style{'LaTeX'});
14694 $env_style{'logo-LaTeX'} = ' ' unless ($env_style{'logo-LaTeX'});
14695 join('',"<SPAN CLASS=\"logo,LaTeX\">",$Laname, $TeXname,"</SPAN>",$_);
14696 } else { join('',$Laname, $TeXname, $_); }
14697 }
14699 sub do_cmd_LaTeXe {
14700 local($_) = @_;
14701 if ($USING_STYLES) {
14702 $env_style{'LaTeX2e'} = ' ' unless ($env_style{'LaTeX2e'});
14703 $env_style{'logo-LaTeX2e'} = ' ' unless ($env_style{'logo-LaTeX2e'});
14704 join('',"<SPAN CLASS=\"logo,LaTeX2e\">"
14705 ,$Laname, $TeXname,'2<SUB>e</SUB>',"</SPAN>",$_);
14706 } else { join('',$Laname,$TeXname
14707 ,(($HTML_VERSION >= 3.0)? '2<SUB>e</SUB>':'2e'),$_);
14708 }
14709 }
14711 sub do_cmd_latextohtml {
14712 local($_) = @_;
14713 if ($USING_STYLES) {
14714 $env_style{'LaTeX2HTML'} = ' ' unless ($env_style{'LaTeX2HTML'});
14715 $env_style{'logo-LaTeX2HTML'} = ' ' unless ($env_style{'logo-LaTeX2HTML'});
14716 join('',"<SPAN CLASS=\"logo,LaTeX2HTML\">"
14717 ,$Laname, $TeXname,"2<TT>HTML</TT>","</SPAN>",$_);
14718 } else { join('',$Laname,$TeXname,"2<TT>HTML</TT>",$_);}
14719 }
14721 sub do_cmd_TeX {
14722 local($_) = @_;
14723 if ($USING_STYLES) {
14724 $env_style{'logo-TeX'} = ' ' unless ($env_style{'logo-TeX'});
14725 join('',"<SPAN CLASS=\"logo-TeX\">",$TeXname,"</SPAN>",$_);
14726 } else { join('',$TeXname, $_);}
14727 }
14729 sub do_cmd_MF {
14730 local($_) = @_;
14731 if ($USING_STYLES) {
14732 $env_style{'logo-Metafont'} = ' ' unless ($env_style{'logo-Metafont'});
14733 join('',"<SPAN CLASS=\"logo-Metafont\">",$MFname,"</SPAN>",$_);
14734 } else { join('', $MFname, $_);}
14735 }
14737 sub do_cmd_Xy {
14738 local($_) = @_;
14739 if ($USING_STYLES) {
14740 $env_style{'logo-Xy-pic'} = ' ' unless ($env_style{'logo-Xy-pic'});
14741 join('',"<SPAN CLASS=\"logo-Xy-pic\">",$Xyname,"</SPAN>",$_);
14742 } else { join('',$Xyname, $_);}
14743 }
14745 sub do_cmd_AmS {
14746 local($_) = @_;
14747 if ($USING_STYLES) {
14748 $env_style{'logo-AMS'} = ' ' unless ($env_style{'logo-AMS'});
14749 join('',"<SPAN CLASS=\"logo-AMS\">",$AmSname,"</SPAN>",$_);
14750 } else { join('',$AmSname, $_);}
14751 }
14753 sub do_cmd_AmSTeX {
14754 local($_) = @_;
14755 if ($USING_STYLES) {
14756 $env_style{'logo-AMS'} = ' ' unless ($env_style{'logo-AMS'});
14757 join('',"<SPAN CLASS=\"logo-AMS\">",$AmSname,"-$TeXname","</SPAN>",$_);
14758 } else { join('',$AmSname, "-", $TeXname, $_);}
14759 }
14761 sub do_cmd_char {
14762 local($_) = @_;
14763 # some special characters are already turned into l2h internal
14764 # representation.
14765 # Get its represention from the table and use it like as regexp form.
14766 local($spmquot) = &escape_rx_chars($html_specials{'"'});
14767 # Get all internal special char representations as implied during
14768 # preprocessing.
14769 local($spmrx) = join("\000",values %html_specials);
14770 # escape regexp special chars (not really necessary yet, but why not)
14771 $spmrx = &escape_rx_chars($spmrx); #~ s:([\\(){}[\]\^\$*+?.|]):\\$1:g;
14772 $spmrx =~ s/\000/|/g;
14773 $spmrx = "(.)" unless $spmrx =~ s/(.+)/($1|.)/;
14775 s/^[ \t]*(\d{1,3})[ \t]*/&#$1;/ &&
14776 return($_);
14778 s/^[ \t]*\'(\d{1,3})[ \t]*/"&#".oct($1).";"/e &&
14779 return($_);
14781 s/^[ \t]*$spmquot(\d{1,2})[ \t]*/"&#".hex($1).";"/e &&
14782 return($_);
14784 # This is a kludge to work together with german.perl. Brrr.
14785 s/^[ \t]*\'\'(\d{1,2})[ \t]*/"&#".hex($1).";"/e &&
14786 return($_);
14787 # If l2h's special char marker represents more than one character,
14788 # it's already in the &#xxx; form. Else convert the single character
14789 # into &#xxx; with the ord() command.
14790 s/^[ \t]*\`\\?$spmrx[ \t]*/
14791 (length($html_specials_inv{$1}) > 1 ?
14792 $html_specials_inv{$1} : "&#".ord($html_specials_inv{$1}||$1).";")/e &&
14793 return($_);
14794 &write_warnings(join('',
14795 "Could not find character number in \\char",
14796 (/\n/ ? $` : $_), " etc.\n"));
14797 $_;
14798 }
14801 sub do_cmd_symbol {
14802 local($_) = @_;
14803 local($char);
14804 $char = &missing_braces
14805 unless ((s/$next_pair_pr_rx/$char = $2;''/eo)
14806 ||(s/$next_pair_rx/$char = $2;''/eo));
14807 join('',&do_cmd_char($char),$_);
14808 }
14810 ################# Accent and Special Symbols ##################################
14812 # Generate code for the accents handling commands that are never
14813 # applied to i or j.
14814 # MEH: Now all accents are safe for dotless i or j
14815 # MEH: Math accents supported as well
14816 sub generate_accent_commands {
14817 local($accent,$accent_cmd);
14818 local(%accents) = ("c", "cedil", "pc", "cedil", "d", "bdot", "b", "b",
14819 "tilde", "tilde", "dot", "dot", "bar", "macr",
14820 "hat", "circ", "u", "breve", "v", "caron",
14821 "H", "dblac", "t", "t", "grave", "grave",
14822 "acute", "acute", "ddot", "uml", "check", "caron",
14823 "breve", "breve", "vec", "vec",
14824 "k", "ogon", "r", "ring");
14825 foreach $accent (keys(%accents)) {
14826 $accent_cmd = "sub do_cmd_$accent {" . 'local($_) = @_;' .
14827 "&accent_safe_for_ij('$accents{$accent}','$accent');" . '$_}';
14828 eval $accent_cmd;
14829 $accent_cmd = "do_cmd_$accent";
14830 print STDERR "\n*** sub do_cmd_$accent failed:\nPERL: $@\n" if ($@);
14831 }
14832 }
14834 # These handle accents, taking care of the dotless i's and j's that
14835 # may follow (even though accented j's are not part of any alphabet
14836 # that I know).
14837 #
14838 # Note that many forms of accents over dotless i's and j's are
14839 # handled:
14840 # "\^\i rest"
14841 # "\^\i
14842 # rest"
14843 # "\^{\i}rest"
14844 # "\^\i{}rest"
14845 # They all produce "îrest".
14846 # MEH: now also handles
14847 # "\^{}rest"
14848 # "\^,rest"
14849 # and many more
14851 sub accent_safe_for_ij {
14852 local($type,$acc_cmd) = @_;
14853 local($arg, $first_char,$ij_cmd);
14854 #print STDOUT "\nACCENT: $type <$_>\n" ;
14855 s/^[ \t]*\n?[ \t]*(\S)/$1/; # Remove whitespace
14856 if (s/^\\([ij])([^a-zA-Z]|$)/$2/) {
14857 # Accent of this form: "\^\i rest" or "\^\i{}rest"
14858 ($arg) = $1; $ij_cmd = "\\$1";
14859 s/^[ \t]+//o; # Get rid of whitespaces after \i
14860 if (substr($_, 0, 2) =~ /[\n\r][^\n\r]/) {
14861 $_ = substr($_, 1); # Get rid of 1 newline after \i
14862 }
14863 } else {
14864 # Accent of this form: "\^{\i}rest" or not an accent on i nor j
14865 ($arg) = &get_next_pair_or_char_pr;
14866 }
14867 $arg =~ s/([^\s\\<])/$first_char = $1; ''/eo;
14868 # print STDOUT "\nACCENT1 type:$type arg:|${arg}| first_char: |$first_char| $ij_cmd
14869 # , $ACCENT_IMAGES\n";
14871 local($aafter) = $_;
14872 local($iso) = &iso_map($first_char,$type);
14873 if ($iso) { $_ = join('', $iso, $arg, $aafter) }
14874 elsif ((!($ACCENT_IMAGES))&&(!($ij_cmd))) {
14875 local($err_string) =
14876 "\nNo available accent for $first_char$type , using just \"$first_char$arg\"";
14877 print $err_string if ($DEBUG||$VERBOSITY > 1);
14878 &write_warnings("\n ...set \$ACCENT_IMAGES to get an image ");
14879 $_ = join('', $first_char, $arg, $aafter) }
14880 else {
14881 print ", making image of accent: $first_char$type " if ($VERBOSITY > 1);
14882 $_ = join('', &mbox_accent($acc_cmd, $first_char, $ij_cmd) , $arg, $aafter)
14883 }
14884 }
14886 sub mbox_accent {
14887 local($type, $char, $ij_cmd) = @_;
14888 if (length($type) > 1 ) {
14889 if ($text_accent{$type}) {
14890 $type = $text_accent{$type};
14891 } elsif ($type =~ /^(math)?accent/) {
14892 } else {
14893 print "\n unrecognised accent $type for `$char' ";
14894 return $char;
14895 }
14896 }
14897 local(@styles);
14898 local($cmd,$style,$bstyle,$estyle) = ('','','','');
14899 local(@styles) = split(',',$ACCENT_IMAGES);
14900 foreach $style (@styles) {
14901 $style =~ s/(^\s*\\|\s*)//g;
14902 $cmd = "do_cmd_$style";
14903 if (defined &$cmd) {
14904 $bstyle .= "\\$style\{" ;
14905 $estyle .= "\}";
14906 } else {
14907 &write_warnings("\nunrecognized style \\$style for accented characters");
14908 }
14909 }
14910 if (!($bstyle)) {
14911 $bstyle = "\{";
14912 $estyle = "\}";
14913 } elsif ($bstyle =~ /textit|itshape/) {
14914 $bstyle = '\raise.5pt\hbox{' . $bstyle ;
14915 $estyle .= "\}";
14916 }
14917 $char = $ij_cmd if ($ij_cmd);
14918 print STDOUT "\nACCENT: $type, $char" if ($VERBOSITY > 2);
14919 local($afterkern); # serifs extend too far on some letters...
14920 $afterkern = "\\kern.05em" if (($char =~ /m|n/)||($type=~/[Hv]/));
14921 # ...or the accent is wider than the letter, so pad it out a bit
14922 $afterkern = "\\kern.15em" if ($char =~ /i|l/); #||($type=~/v/));
14924 &process_undefined_environment("tex2html_accent_inline"
14925 , ++$global{'max_id'}, "${bstyle}\\${type}\{$char\\/\}$estyle$afterkern");
14926 }
14928 # MEH: Actually tries to find a dotless i or j
14929 sub do_cmd_i { join('',&iso_map('i', 'nodot') || 'i', $_[0]) }
14930 sub do_cmd_j { join('',&iso_map('j', 'nodot') || 'j', $_[0]) }
14932 sub do_cmd_accent {
14933 local($_) = @_;
14934 local($number);
14935 if (s/\s*(\d+)\s*//o) {$number = $1}
14936 elsif (s/\s*&SMPquot;(\d)(\d)\s*//o) { $number = $1*16 + $2 }
14937 elsif (s/\s*\'(\d)(\d)(\d)\s*//o) { $number = $1*64 + $2*8 + $3 }
14938 else { s/\s*(\W\w+)([\s\W])/$2/o; $number = $1 }
14939 local($type) = $accent_type{uc($number)};
14940 #print STDOUT "\ndo_cmd_accent: $number ($type) |$_|\n";
14941 if (! $type) {
14942 &write_warnings("Accent number $number is unknown.\n");
14943 return $_;
14944 }
14945 &accent_safe_for_ij($type , 'accent$number' );
14946 $_;
14947 }
14949 sub do_cmd_ae { join('', &iso_map("ae", "lig"), $_[0]);}
14950 sub do_cmd_AE { join('', &iso_map("AE", "lig"), $_[0]);}
14951 sub do_cmd_aa { join('', &iso_map("a", "ring"), $_[0]);}
14952 sub do_cmd_AA { join('', &iso_map("A", "ring"), $_[0]);}
14953 sub do_cmd_o { join('', &iso_map("o", "slash"), $_[0]);}
14954 sub do_cmd_O { join('', &iso_map("O", "slash"), $_[0]);}
14955 sub do_cmd_ss { join('', &iso_map("sz", "lig"), $_[0]);}
14956 sub do_cmd_DH { join('', &iso_map("ETH", ""), $_[0]);}
14957 sub do_cmd_dh { join('', &iso_map("eth", ""), $_[0]);}
14958 sub do_cmd_TH { join('', &iso_map("THORN", ""), $_[0]);}
14959 sub do_cmd_th { join('', &iso_map("thorn", ""), $_[0]);}
14961 sub do_cmd_pounds { join('', &iso_map("pounds", ""), $_[0]);}
14962 sub do_cmd_S { join('', &iso_map("S", ""), $_[0]);}
14963 sub do_cmd_copyright { join('', &iso_map("copyright", ""), $_[0]);}
14964 sub do_cmd_P { join('', &iso_map("P", ""), $_[0]);}
14967 sub brackets { ($OP, $CP);}
14969 sub get_date {
14970 local($format,$order) = @_;
14971 local(@lt) = localtime;
14972 local($d,$m,$y) = @lt[3,4,5];
14973 if ($format =~ /ISO/) {
14974 sprintf("%4d-%02d-%02d", 1900+$y, $m+1, $d);
14975 } elsif ($format) {
14976 if ($order) { eval "sprintf(".$format.",".$order.")"; }
14977 else { sprintf($format, $d, $m+1, 1900+$y); }
14978 } else { sprintf("%d/%d/%d", $m+1, $d, 1900+$y); }
14979 }
14981 sub address_data {
14982 local($user, $date, $_);
14983 local($format,$order) = @_;
14984 # Get author, (email address) and current date.
14985 ($user = L2hos->fullname()) =~ s/,.*//;
14986 ($user, &get_date($format,$order));
14987 }
14990 #################################### LaTeX2e ##################################
14992 sub missing_braces {
14993 # local($cmd) = @_;
14994 local($next, $revert, $thisline);
14995 local($this_cmd) = $cmd;
14996 $this_cmd =~ s/^\\// unless ($cmd eq "\\");
14997 &write_warnings("\n? brace missing for \\$this_cmd");
14998 if (/^[\s%]*([^\n]*)\n/ ) {
14999 $thisline = &revert_to_raw_tex($1)
15000 } else {
15001 $thisline = &revert_to_raw_tex($_);
15002 }
15003 print "\n\n*** no brace for \\$this_cmd , before:\n$thisline";
15004 s/^\s*//;
15005 if ($_ =~ s/$next_token_rx//) { $next = $& };
15006 $next =~ s/$comment_mark(\d+\n?)?//g;
15007 # $next = &translate_commands($next) if ($next =~ /^\\/);
15008 if ($next =~ /^\\(\W|\d|[a-zA-z]*\b)/) {
15009 $revert = $next = "\\".$1;
15010 } elsif ($next =~ /\W/) {
15011 $revert = &revert_to_raw_tex($next);
15012 } else { $revert = $next };
15013 print "\n*** using \"$revert\" as the argument instead; is this correct? ***\n\n";
15014 $next;
15015 }
15017 #RRM:
15018 # &styled_text_chunk provides an interface for pieces of styled text,
15019 # within a single paragraph. The visual markup can be obtained through either
15020 # 1. link to a stylesheet (CSS)
15021 # 2. direct markup placed into the output
15022 # 3. calling another function to process the text
15023 #
15024 # parameters (in order):
15025 # $def_tag : markup tag to be used, unless $USING_STYLES or no $property given,
15026 # attributes can be included, only 1st word is used for closing-tag;
15027 # $prefix : prefix for the Unique ID identifier, defaults to 'txt'
15028 # OR contains CLASS= identifier when $property is empty(see below);
15029 # $type : general type of the style-sheet information
15030 # $class : specific type of the style-sheet information
15031 # $property : value to be set, applicable to the $type & $class
15032 # $alt_proc : name of procedure to use, if $USING_STYLES == 0, and no $def_tag
15033 # $_ : current data-stream
15034 # $open_tags_R : current open-tags (not used in this procedure)
15036 sub styled_text_chunk {
15037 local($def_tag, $prefix, $type, $class, $property, $alt_proc, $_,
15038 $ot) = @_;
15039 local($open_tags_R) = defined $ot ? $ot : $open_tags_R;
15040 local($text, $env_id, $def_end);
15041 local($span_tag) = 'SPAN';
15042 $text = &missing_braces
15043 unless ((s/$next_pair_pr_rx/$text = $2; $env_id = $1;''/eo)
15044 || (s/$next_pair_rx/$text = $2; $env_id = $1;''/eo));
15045 $text = &balance_inner_tags($text);
15047 #start from no open tags
15048 local(@save_open_tags) = ();
15049 local($open_tags_R) = [];
15051 # local($decl);
15052 # if ($prefix =~ /CLASS="(\w+)"/ ) {
15053 # $decl=$1;
15054 # push (@$open_tags_R, $decl);
15055 # }
15056 # push (@$open_tags_R, $color_env) if $color_env;
15057 if (!$inside_math) {
15058 $text = &translate_environments($text);
15059 $text = &translate_commands($text) if ($text =~ /\\/);
15060 $text .= &balance_tags;
15061 }
15063 if (($USING_STYLES)&&($env_id =~ /^\d+$/)&&($property)) {
15064 $prefix = 'txt' unless ($prefix);
15065 $env_id = $prefix.$env_id;
15066 $styleID{$env_id} = join('',"$type", ($class ? "-$class" : '')
15067 ,": ", $property,"; ");
15068 return(join('',"<$span_tag ID=\"$env_id\">",$text,"<\/$span_tag>", $_));
15069 }
15071 if (($USING_STYLES)&&($prefix =~ /($span_tag )?CLASS=\"(\w+)\"/o)) {
15072 local($span_class) = $2;
15073 $def_tag = (($1)? $1 : $span_tag." ");
15074 $txt_style{$span_class} = "$type: $class "
15075 unless ($txt_style{$span_class});
15076 return(join('',"<$def_tag CLASS=\"$span_class\">"
15077 , $text,"<\/$span_tag>", $_));
15078 }
15080 if (($def_tag) && (!$USING_STYLES)) {
15081 $def_tag =~ s/^($span_tag)?CLASS=\"(\w+)\"$// ;
15082 }
15084 if ($def_tag =~ /^(\w+)/) {
15085 $def_end = $1;
15086 return(join('',"<$def_tag>",$text,"<\/$def_end>", $_));
15087 }
15089 return (join('', eval ("&$alt_proc(\$text)") , $_)) if (defined "&$alt_proc");
15091 &write_warnings(
15092 "\ncannot honour request for $type-$class:$property style at br$env_id");
15093 join('', $text, $_);
15094 }
15096 sub multi_styled_text_chunk {
15097 local($def_tag, $prefix, $type, $class, $property, $_, $ot) = @_;
15098 local($open_tags_R) = defined $ot ? $ot : $open_tags_R;
15099 $prefix = 'txt' unless ($prefix);
15100 my(@def_tags) = split(',',$def_tag);
15101 my(@types) = split(',',$type);
15102 my(@classes) = split(',',$class);
15103 my(@properties) = split(',',$property);
15104 $text = &missing_braces
15105 unless ((s/$next_pair_pr_rx/$text = $2; $env_id = $1;''/eo)
15106 || (s/$next_pair_rx/$text = $2; $env_id = $1;''/eo));
15107 if (($USING_STYLES)&&($env_id =~ /^\d+$/)&&($property)) {
15108 # $1 contains the bracket-id
15109 $env_id = $prefix.$env_id;
15110 while (@properties) {
15111 $class = shift @classes;
15112 $property = shift @properties;
15113 $styleID{$env_id} .= join(''
15114 , shift @types,
15115 , ($class ? "-".$class : '')
15116 , ($property ? " : $property" : ''), " ; ");
15117 $styleID{$env_id} .= "\n\t\t " if (@properties);
15118 }
15119 }
15120 join('',"<SPAN ID=\"$env_id\">",$text,"<\/SPAN>", $_);
15121 }
15123 #RRM:
15124 # This one takes care of commands with argument that really should be
15125 # environments; e.g. \centerline, \rightline, etc.
15126 # Note that styles are inherited also from the existing @$open_tags_R.
15127 #
15128 sub styled_text_block {
15129 local($def_tag, $attrib, $value, $class, $_, $ot) = @_;
15130 local($open_tags_R) = defined $ot ? $ot : $open_tags_R;
15131 local($text, $env_id, $attribs);
15132 if ($attribs =~ /,/ ) {
15133 local(@attribs) = split(',',$attrib);
15134 local(@values) = split(',',$value);
15135 while (@attribs) {
15136 $attribs .= join('', " " , shift @attribs
15137 ,"=\"" , shift @values, "\"") }
15138 } elsif($value) {
15139 $attribs = join(''," ",$attrib,"=\"",$value,"\"")
15140 } else { $attribs = " " . $attrib }
15142 local(@save_open_tags) = @$open_tags_R;
15143 local($closures) = &close_all_tags();
15144 local($reopens)=&balance_tags();
15145 $text = &missing_braces
15146 unless ((s/$next_pair_pr_rx/$text = $2; $env_id = $1;''/eo)
15147 || (s/$next_pair_rx/$text = $2; $env_id = $1;''/eo));
15148 if (($USING_STYLES)&&($env_id =~ /^\d+$/)) {
15149 $env_id = ++$global{'max_id'};
15150 $env_id = "par".$env_id;
15151 $styleID{$env_id} = " ";
15152 $env_style{$class} = " " if (($class)&&!($env_style{$class}));
15153 $class = " CLASS=\"$class\"" if ($class);
15154 $env_id = " ID=\"$env_id\"";
15155 } else { $class = ''; $env_id = '' };
15157 $text = &translate_environments($text);
15158 $text = &translate_commands($text);
15160 local($closuresA)=&close_all_tags();
15161 local($reopensA) = &balance_tags();
15162 $text =~ s/^\n?/\n/o;
15163 join('', $closures
15164 , "<$def_tag$class$env_id$attribs>"
15165 , $reopens, $text, $closuresA
15166 , "</$def_tag>\n", $reopensA, $_);
15167 }
15170 # this gives a separate ID for each instance
15171 #sub do_cmd_textbf { &styled_text_chunk('B','','font','weight'
15172 # ,'bold', '', @_); }
15173 #
15174 # this uses a single CLASS for all instances
15175 sub do_cmd_textbf { &styled_text_chunk('B','CLASS="textbf"'
15176 ,'font-weight','bold', '', '', @_); }
15179 # this gives a separate ID for each instance
15180 sub do_cmd_texttt { &styled_text_chunk('TT','','font','','', '', @_); }
15182 # this uses a single CLASS for all instances
15183 #sub do_cmd_textit { &styled_text_chunk('TT','CLASS="textit"'
15184 # ,'font-family','monospace', '', '', @_); }
15185 #
15186 # this gives a separate ID for each instance
15187 #sub do_cmd_textit { &styled_text_chunk('I','','font','style'
15188 # ,'italic', '', @_); }
15189 #
15190 # this uses a single CLASS for all instances
15191 sub do_cmd_textit { &styled_text_chunk('I','CLASS="textit"'
15192 ,'font-style','italic', '', '', @_); }
15196 # this gives a separate ID for each instance
15197 #sub do_cmd_textsl { &styled_text_chunk('I','','font','style'
15198 # ,'oblique', '', @_); }
15199 #
15200 # this uses a single CLASS for all instances
15201 #sub do_cmd_textsl { &styled_text_chunk('I','CLASS="textsl"'
15202 # ,'font-style','oblique', '', '', @_); }
15203 #
15204 # ... NS4 implements Italic, not oblique
15205 sub do_cmd_textsl { &styled_text_chunk('I','CLASS="textsl"'
15206 ,'font-style','italic', '', '', @_); }
15209 # this gives a separate ID for each instance
15210 #sub do_cmd_textsf { &styled_text_chunk('I','','font','family'
15211 # ,'sans-serif', '', @_); }
15212 #
15213 # this uses a single CLASS for all instances
15214 #sub do_cmd_textsf { &styled_text_chunk('I','CLASS="textsf"'
15215 # ,'font-family','sans-serif', '', '', @_); }
15216 #
15217 # ... NS4 doesn't implement sans-serif
15218 sub do_cmd_textsf { &styled_text_chunk('I','CLASS="textsf"'
15219 ,'font-style','italic', '', '', @_); }
15222 #sub do_cmd_textsc {
15223 # local($_) = @_;
15224 # local($text, $next, $scstr, $before, $special);
15225 # $text = &missing_braces
15226 # unless ((s/$next_pair_pr_rx/$text = $2;''/eo)
15227 # || (s/$next_pair_rx/$text = $2;''/eo));
15228 # join('', &process_smallcaps($text), $_);
15229 #}
15231 sub lowercase_entity {
15232 local($char) = @_;
15233 local($exent);
15234 if ($exent = $low_entities{$char}) { "\&#$exent;" }
15235 elsif ($exent = $extra_small_caps{$char}) { $exent }
15236 else { "\&#$char;" }
15237 }
15239 sub process_smallcaps {
15240 local($text) = @_;
15241 local($next, $scstr, $scbef, $special, $char);
15242 # is this enough for \sc and \scshape ?
15243 $text = &translate_environments($text);
15245 # MRO: replaced $* with /m
15246 while ($text =~ /(\\[a-zA-Z]+|[&;]SPM\w+;|<[^>]+>)+/m ) {
15247 $scbef = $`; $special = $&; $text = $';
15248 while ( $scbef =~ /(&#\d+;|[a-z$sclower])+[a-z\W\d$sclower]*/m) {
15249 $scstr .= $`; $scbef = $';
15250 $next = $&;
15251 $next =~ s/&#(\d+);/&lowercase_entity($1)/egm;
15252 eval "\$next =~ $scextra" if ($scextra);
15253 eval "\$next =~ tr/a-z$sclower/A-Z$scupper/";
15254 $scstr .= "<SMALL>" . $next ."<\/SMALL>";
15255 }
15256 $scstr .= $scbef . $special;
15257 }
15258 if ($text) {
15259 while ( $text =~ /(&#\d+;|[a-z$sclower])+[a-z\W\d$sclower]*/m) {
15260 $scstr .= $`; $text = $';
15261 $next = $&;
15262 $next =~ s/&#(\d+);/&lowercase_entity($1)/egm;
15263 eval "\$next =~ $scextra" if ($scextra);
15264 eval "\$next =~ tr/a-z$sclower/A-Z$scupper/";
15265 $scstr .= "<SMALL>" . $next ."<\/SMALL>";
15266 }
15267 $scstr .= $text;
15268 }
15269 $scstr;
15270 }
15272 # this gives a separate ID for each instance
15273 #sub do_cmd_textsc { &styled_text_chunk('','','font','variant'
15274 # ,'small-caps', 'process_smallcaps', @_); }
15275 #
15276 # this uses a single CLASS for all instances
15277 #sub do_cmd_textsc { &styled_text_chunk('', 'CLASS="textsc"'
15278 # ,'font-variant','small-caps','', 'process_smallcaps', @_); }
15279 #
15280 # ...but NS 4.03 doesn't implement small-caps !!!
15281 sub do_cmd_textsc { &styled_text_chunk('',''
15282 ,'font-variant','small-caps','', 'process_smallcaps', @_); }
15285 #sub do_cmd_emph { &styled_text_chunk('EM','em','font','variant','','', @_); }
15288 # this gives a separate ID for each instance
15289 #sub do_cmd_underline { &styled_text_chunk('U','','text','decoration','underline','', @_); }
15291 # this uses a single CLASS for all instances
15292 sub do_cmd_underline { &styled_text_chunk('U','CLASS="underline"'
15293 ,'text-decoration','underline','','', @_); }
15294 sub do_cmd_underbar { &do_cmd_underline(@_) }
15297 # this gives a separate ID for each instance
15298 #sub do_cmd_strikeout { &styled_text_chunk('STRIKE',''
15299 # ,'text','decoration','line-through','', @_); }
15301 # this uses a single CLASS for all instances
15302 sub do_cmd_strikeout { &styled_text_chunk('STRIKE','CLASS="strikeout"',
15303 'text-decoration','line-through','','', @_); }
15306 sub do_cmd_uppercase {
15307 local($_) = @_;
15308 local($text,$next,$done,$special,$after);
15309 $text = &missing_braces unless (
15310 (s/$next_pair_pr_rx/$text = $2;''/eo)
15311 ||(s/$next_pair_rx/$text = $2;''/eo));
15312 $after = $_;
15313 while ($text =~ /(\\[a-zA-Z]+|[&;]SPM\w+;)/ ) {
15314 $next = $`;
15315 $special = $&;
15316 $text = $';
15317 $next =~ tr /a-z/A-Z/ if ($next);
15318 $done .= $next . $special;
15319 }
15320 $text =~ tr /a-z/A-Z/ if ($text);
15321 $done .= $text;
15322 $done = &convert_iso_latin_chars($done) if ($done);
15323 join('',$done,$after);
15324 }
15326 sub do_cmd_lowercase {
15327 local($_) = @_;
15328 local($text,$next,$done,$special,$after);
15329 $text = &missing_braces
15330 unless ((s/$next_pair_pr_rx/$text = $2;''/seo)
15331 || (s/$next_pair_rx/$text = $2;''/seo));
15332 $after = $_;
15333 while ($text =~ /(\\[a-zA-Z]+|[&;]SPM\w+;)/ ) {
15334 $next = $`;
15335 $special = $&;
15336 $text = $';
15337 $next =~ tr /A-Z/a-z/ if ($next);
15338 $done .= $next . $special;
15339 }
15340 $text =~ tr /A-Z/a-z/ if ($text);
15341 $done .= $text;
15342 $done = &convert_iso_latin_chars($done) if ($done);
15343 join('',$done,$after);
15344 }
15346 sub do_cmd_MakeUppercase { &do_cmd_uppercase(@_) }
15347 sub do_cmd_MakeLowercase { &do_cmd_lowercase(@_) }
15351 sub do_cmd_ensuremath {
15352 local($_) = @_;
15353 local ($id, $value);
15354 $value = &missing_braces unless (
15355 (s/$next_pair_pr_rx/$value=$2;''/eo)
15356 ||(s/$next_pair_rx/$value=$2;''/eo));
15357 join('', &simple_math_env($value), $');
15358 }
15360 #
15361 # This is mainly for \special{header=PostScript_Prologue},
15362 # and \graphicspath{path} which occur OUTSIDE of an environment
15363 # passed to TeX. \special's INSIDE such environments are, of
15364 # course, left alone.
15366 sub do_cmd_special {
15367 local($_) = @_;
15368 local ($id, $value);
15369 $value = &missing_braces unless (
15370 (s/$next_pair_pr_rx/$value=$2;''/eo)
15371 ||(s/$next_pair_rx/$value=$2;''/eo));
15372 local($special_cmd) = &revert_to_raw_tex($value);
15373 &add_to_preamble($cmd,"\\$cmd\{$special_cmd\}");
15374 $_;
15375 }
15378 ########################## Input and Include commands #########################
15380 sub do_cmd_input {
15381 local($_) = @_;
15382 local($file,$output);
15383 (s/\s*(.*)\s*\n/$file =$1;''/s) unless (
15384 (s/$next_pair_pr_rx/$file=$2;''/eo)
15385 ||(s/$next_pair_rx/$file=$2;''/eo));
15386 local($after) = $_;
15387 $file = &revert_to_raw_tex("\\input{$file}\n") if $file;
15388 if ($PREAMBLE) { &add_to_preamble('include',$file)}
15389 elsif (!($file=~/^\s*$/)) {
15390 $output = &process_undefined_environment('center'
15391 , ++$global{'max_id'},"\\vbox{$file}");
15392 }
15393 $output.$after;
15394 }
15396 sub do_cmd_include {
15397 local($_) = @_;
15398 local($file,$output);
15399 $file = &missing_braces unless (
15400 (s/$next_pair_pr_rx/$file=$2;''/eo)
15401 ||(s/$next_pair_rx/$file=$2;''/eo));
15402 local($after) = $_;
15403 $file = &revert_to_raw_tex("\\include{$file}\n") if $file;
15404 if ($PREAMBLE) { &add_to_preamble('include',$file)}
15405 else {
15406 $output = &process_undefined_environment('figure'
15407 , ++$global{'max_id'},"\\vbox{$file}");
15408 }
15409 $output.$after;
15410 }
15412 ########################## Messages #########################
15414 sub do_cmd_message {
15415 local($_) = @_;
15416 local($message);
15417 $message = &missing_braces unless (
15418 (s/$next_pair_pr_rx/$message=$2;''/eo)
15419 ||(s/$next_pair_rx/$message=$2;''/eo));
15420 local($after) = $_;
15421 $message = &translate_commands($message);
15422 $message =~ s/$comment_mark(\d+)//og;
15423 print STDOUT "\n*** $message ***\n";
15424 $after;
15425 }
15427 sub do_cmd_typeout {
15428 print STDOUT "\n";
15429 local($_) = &do_cmd_message(@_);
15430 print STDOUT "\n";
15431 $_;
15432 }
15434 sub do_cmd_expandafter {
15435 local($_) = @_;
15436 print "\nEXPANDAFTER: " if ($VERBOSITY >3);
15437 return($_) unless (s/^\s*(\\\w+)\s*\\//o);
15438 print " delaying $1 " if ($VERBOSITY >3);
15439 local($delay,$cmd) = ($1,'');
15440 s/^(\w+|\W)/$cmd=$1;''/eo;
15441 local($nextcmd) = "do_cmd_$cmd";
15442 if (defined &$nextcmd) { $_ = &$nextcmd($_) }
15443 elsif ($new_command{$cmd}) {
15444 local($argn, $body, $opt) = split(/:!:/, $new_command{$cmd});
15445 do { ### local($_) = $body;
15446 &make_unique($body);
15447 } if ($body =~ /$O/);
15448 if ($argn) {
15449 do {
15450 local($before) = '';
15451 local($after) = "\\$cmd ".$_;
15452 $after = &substitute_newcmd; # may change $after
15453 $after =~ s/\\\@#\@\@/\\/o unless ($after);
15454 };
15455 } else { $_ = $body . $_; }
15456 } else { print "\nUNKNOWN COMMAND: $cmd "; }
15458 # now put the delayed function back for processing
15459 join('',$delay, " ", $_);
15460 }
15462 sub do_cmd_tracingall {
15463 print "\nTRACING:\n$ref_contents\n$after\n";
15464 $VERBOSITY = 8; ""; }
15466 sub do_cmd_htmltracenv { &do_cmd_htmltracing }
15468 sub do_cmd_htmltracing {
15469 local($_) = @_;
15470 local($value);
15471 $value = &missing_braces
15472 unless ((s/$next_pair_rx/$value = $2;''/eo)
15473 ||(s/$next_pair_pr_rx/$value = $2;''/eo));
15474 if ($value =~ /^\s*(\d+)\s*$/) {
15475 $VERBOSITY = $1;
15476 if ($VERBOSITY) {
15477 print "\n\n *** setting trace-level to $VERBOSITY ***\n";
15478 } else {
15479 print "\n\n *** cancelling all tracing ***\n\n";
15480 }
15481 } else {
15482 &write_warnings("argument to \\htmltracing must be a number");
15483 }
15484 $_ ;
15485 }
15488 ############################ Initialization ####################################
15490 sub initialise {
15491 ############################ Global variables ###############################
15492 $PREAMBLE = 2; # 1 while translating preamble, 0 while translating body
15493 $NESTING_LEVEL = undef; #counter for TeX group nesting level
15494 $OUT_NODE = 0; # Used in making filenames of HTML nodes unique
15495 $eqno_prefix = ''; # default prefix on equation numbers
15496 ($O , $C, $OP, $CP) = ('<<' , '>>', '<#', '#>'); # Open/Close Markers
15497 $href_name = 0; # Used in the HREF NAME= field
15498 $wrap_toggle = 'end';
15499 $delim = '%:%'; # Delimits items of sectioning information
15500 # stored in a string
15502 $LATEX2HTML_META = '<META NAME="Generator" CONTENT="LaTeX2HTML v'.$TEX2HTMLV_SHORT.'">'
15503 . "\n<META HTTP-EQUIV=\"Content-Style-Type\" CONTENT=\"text/css\">"
15504 unless ($LATEX2HTML_META);
15506 $TeXname = (($HTML_VERSION ge "3.0")? "T<SMALL>E</SMALL>X" : "TeX");
15507 $Laname = (($HTML_VERSION ge "3.0")? "L<SUP><SMALL>A</SMALL></SUP>" : "La");
15508 $MFname = (($HTML_VERSION ge "3.0")? "M<SMALL>ETAFONT</SMALL>" : "Metafont");
15509 $Xyname = (($HTML_VERSION ge "3.0")? "X<SUB><BIG>Y</BIG></SUB>" : "Xy");
15510 $AmSname = (($HTML_VERSION ge "3.0")? "A<SUB><BIG>M</BIG></SUB>S" : "AmS");
15512 $EQN_TAGS = "R" unless ($EQN_TAGS);
15513 $EQNO_START = "(";
15514 $EQNO_END = ")";
15516 $AtBeginDocument_hook = "\$AtBeginDocument_hook\=\'\'; "
15517 unless $AtBeginDocument_hook;
15518 $cross_ref_mark = '<tex2html_cr_mark>';
15519 $external_ref_mark = '<tex2html_ext_cr_mark>';
15520 $cite_mark = '<tex2html_cite_mark>';
15521 $hash_mark = '<tex2html_hash_mark>';
15522 $protected_hash = '<tex2html_protected_hash>';
15523 $param_mark = '<tex2html_param_mark>';
15524 $bbl_mark = '<tex2html_bbl_mark>';
15525 $toc_mark = '<tex2html_toc_mark>';
15526 $lof_mark = '<tex2html_lof_mark>';
15527 $lot_mark = '<tex2html_lot_mark>';
15528 $info_page_mark = '<tex2html_info_page_mark>';
15529 $info_title_mark = '<tex2html_info_title_mark>';
15530 $init_file_mark = '<tex2html_init_file_mark>';
15531 $childlinks_on_mark = '<tex2html_childlinks_mark>';
15532 $childlinks_null_mark = '<tex2html_childlinks_null_mark>';
15533 $childlinks_mark = $childlinks_on_mark;
15534 $more_links_mark = '<tex2html_morelinks_mark>';
15535 $idx_mark = '<tex2html_idx_mark>';
15536 $verbatim_mark = '<tex2html_verbatim_mark>';
15537 $unfinished_mark = '<tex2html_unfinished_mark>';
15538 $verb_mark = '<tex2html_verb_mark>';
15539 $verbstar_mark = '<tex2html_verbstar_mark>';
15540 $image_mark = '<tex2html_image_mark>';
15541 $mydb_mark = '<tex2html_mydb_mark>';
15542 $percent_mark = '<tex2html_percent_mark>';
15543 $ampersand_mark = '<tex2html_ampersand_mark>';
15544 $dol_mark = '<tex2html_lone_dollar>';
15545 $comment_mark = '<tex2html_comment_mark>';
15546 $caption_mark = '<tex2html_caption_mark>';
15547 $array_col_mark = '<tex2html_col_mark>';
15548 $array_row_mark = '<tex2html_row_mark>';
15549 $array_text_mark = '<tex2html_text_mark>';
15550 $array_mbox_mark = '<tex2html_mbox_mark>';
15552 $bibitem_counter = 0;
15553 $undef_mark = '<tex2html_undef_mark>';
15554 $file_mark = '<tex2html_file>';
15555 $endfile_mark = '<tex2html_endfile>';
15557 # This defines textual markers for all the icons
15558 # e.g. $up_visible_mark = '<tex2html_up_visible_mark>';
15559 # They will be replaced with the real icons at the very end.
15560 foreach $icon (keys %icons) {eval "\$$icon = '<tex2html_$icon>'"};
15562 # Make sure $HTML_VERSION is in the right range and in the right format.
15563 # $HTML_VERSION =~ /[\d.]*/;
15564 # $HTML_VERSION = 0.0 + $&;
15565 # $HTML_VERSION = 2 if ( $HTML_VERSION < 2 );
15566 # $HTML_VERSION = 9 if ( $HTML_VERSION > 9 );
15567 # $HTML_VERSION = sprintf("%3.1f",$HTML_VERSION);
15569 &banner();
15570 print "Revised and extended by:"
15571 . "\n Marcus Hennecke, Ross Moore, Herb Swan and others\n";
15573 # Collect HTML options and figure out HTML version
15574 $HTML_OPTIONS = '' unless ($HTML_OPTIONS);
15575 $HTML_VERSION =~ s/^html|\s+//g;
15576 local(@HTML_VERSION) = split(/,/, $HTML_VERSION);
15577 foreach ( @HTML_VERSION ) {
15578 if (/^[\d\.]+$/) {
15579 # Make sure $HTML_VERSION is in the right range and in the right format.
15580 $HTML_VERSION = 0.0 + $_;
15581 $HTML_VERSION = 2 if ( $HTML_VERSION < 2 );
15582 $HTML_VERSION = 9 if ( $HTML_VERSION > 9 );
15583 $HTML_VERSION = sprintf("%3.1f",$HTML_VERSION);
15584 } else {
15585 $HTML_OPTIONS .= "$_,";
15586 }
15587 }
15588 $HTML_OPTIONS =~ s/\W$//; # remove any trailing punctuation
15590 print "...producing markup for HTML version $HTML_VERSION ";
15591 print ($HTML_OPTIONS ? "with $HTML_OPTIONS extensions\n\n\n" : "\n\n\n");
15593 # load the character defs for latin-1, but don't set the charset yet
15594 &do_require_extension('latin1');
15595 $charset = $CHARSET = $PREV_CHARSET = '';
15597 if ($HTML_VERSION =~ /(2.0|3.0|3.2|4.0|4.1)/) {
15598 # Require the version specific file
15599 do { $_ = "$LATEX2HTMLVERSIONS${dd}html$1.pl";
15600 if (!(-f $_)) { s/(\d).(\d.pl)$/$1_$2/ };
15601 if (!(-f $_)) { s/(\d)_(\d.pl)$/$1-$2/ };
15602 require $_ || die "\n*** Could not load $_ ***\n";
15603 print "\nHTML version: loading $_\n";
15604 } unless ($HTML_VERSION =~ /2.0/);
15605 $DOCTYPE = "-//".(($HTML_VERSION eq "2.0")? "IETF" : "W3C")
15606 . "//DTD HTML $HTML_VERSION"
15607 .(($HTML_VERSION eq "3.2")? " Final" : "")
15608 .(($HTML_VERSION eq "4.0")? " Transitional" : "");
15610 if ($HTML_OPTIONS) {
15611 local($ext);
15612 local($loading_extensions) = 1;
15613 # Require the option specific files
15614 @HTML_VERSION = split(/,/, $HTML_OPTIONS);
15615 foreach $ext ( @HTML_VERSION ) {
15616 &do_require_extension($ext);
15617 # do {
15618 # print "\nLoading $LATEX2HTMLVERSIONS$dd$ext.pl";
15619 # require "$LATEX2HTMLVERSIONS$dd$ext.pl";
15620 # } if (-f "$LATEX2HTMLVERSIONS$dd$ext.pl");
15621 }
15622 undef $loading_extensions;
15623 }
15624 } else {
15625 print "\n You specified an invalid version: $HTML_VERSION\n"
15626 . "In future please request extensions by name:\n"
15627 . " i18n table math frame latin1 unicode etc.\n";
15629 # Require all necessary version specific files
15630 foreach ( sort <$LATEX2HTMLVERSIONS${dd}html[1-9].[0-9].pl> ) {
15631 last if ( $_ gt "$LATEX2HTMLVERSIONS${dd}html$HTML_VERSION.pl" );
15632 do { print "\nloading $_" if ($DEBUG);
15633 require $_; } unless (
15634 ($NO_SIMPLE_MATH)&&($_ eq "$LATEX2HTMLVERSIONS${dd}html3.1.pl"));
15635 };
15636 $STRICT_HTML = 0;
15637 }
15639 # packages automatically implemented, or clearly irrelevant
15640 %styles_loaded =
15641 ( 'theorem' , 1 , 'enumerate', 1 , 'a4paper' , 1 , 'b5paper' , 1
15642 , '10pt' , 1 , '11pt' , 1 , '12pt' , 1
15643 , %styles_loaded );
15646 %declarations =
15647 ('em' , '<EM></EM>',
15648 'it' , '<I></I>',
15649 'bf' , '<B></B>',
15650 'tt' , '<TT></TT>',
15651 'sl' , '<I></I>', # Oops!
15652 'sf' , '<I></I>', # Oops!
15653 'rm' , '<></>',
15654 'rmfamily' ,'<></>', # see $fontchange_rx
15655 'normalfont' ,'<></>', # see $fontweight_rx and $fontchange_rx
15656 'mdseries' ,'<></>', # see $fontweight_rx
15657 'upshape' ,'<></>', # see $fontchange_rx
15658 'itshape' , '<I></I>',
15659 'bfseries' , '<B></B>',
15660 'ttfamily' , '<TT></TT>',
15661 'slshape' , '<I></I>', # Oops!
15662 'sffamily' , '<I></I>', # Oops!
15663 ## 'scshape' , '<I></I>', # Oops!
15664 # 'boldmath' , '<B></B>',
15665 # 'quote', '<BLOCKQUOTE></BLOCKQUOTE>',
15666 # 'quotation', '<BLOCKQUOTE></BLOCKQUOTE>',
15667 %declarations # Just in case someone extends it in the init file
15668 );
15671 %declarations = (
15672 'tiny', '<FONT SIZE="-2"></FONT>',
15673 'Tiny', '<FONT SIZE="-2"></FONT>',
15674 'scriptsize', '<FONT SIZE="-2"></FONT>',
15675 'small', '<FONT SIZE="-1"></FONT>',
15676 'Small', '<FONT SIZE="-1"></FONT>',
15677 'SMALL', '<FONT SIZE="-1"></FONT>',
15678 'smaller', '<SMALL></SMALL>',
15679 'footnotesize', '<FONT SIZE="-1"></FONT>',
15680 'larger', '<BIG></BIG>',
15681 'large', '<FONT SIZE="+1"></FONT>',
15682 'Large', '<FONT SIZE="+2"></FONT>',
15683 'LARGE', '<FONT SIZE="+2"></FONT>',
15684 'huge', '<FONT SIZE="+3"></FONT>',
15685 'Huge', '<FONT SIZE="+4"></FONT>',
15686 # 'centering', '<DIV ALIGN="CENTER"></DIV>',
15687 # 'center', '<DIV ALIGN="CENTER"></DIV>',
15688 # 'flushleft', '<DIV ALIGN="LEFT"></DIV>',
15689 # 'raggedright', '<DIV ALIGN="LEFT"></DIV>',
15690 # 'flushright', '<DIV ALIGN="RIGHT"></DIV>',
15691 # 'raggedleft', '<DIV ALIGN="RIGHT"></DIV>',
15692 %declarations
15693 ) if ($HTML_VERSION > 2.0 );
15695 # no alignment in HTML 2.0
15696 #%declarations = (
15697 # 'centering', '<P ALIGN="CENTER"></P>',
15698 # 'center', '<P ALIGN="CENTER"></P>',
15699 # 'flushleft', '<P ALIGN="LEFT"></P>',
15700 # 'raggedright', '<P ALIGN="LEFT"></P>',
15701 # 'flushright', '<P ALIGN="RIGHT"></P>',
15702 # 'raggedleft', '<P ALIGN="RIGHT"></P>',
15704 %declarations = (
15705 # 'centering', '<P></P>',
15706 'center', '<P></P>',
15707 'flushleft', '<P></P>',
15708 'raggedright', '<P></P>',
15709 'flushright', '<P></P>',
15710 'raggedleft', '<P></P>',
15711 'quote', '<BLOCKQUOTE></BLOCKQUOTE>',
15712 'quotation', '<BLOCKQUOTE></BLOCKQUOTE>',
15713 'verse', '<BLOCKQUOTE></BLOCKQUOTE>',
15714 'preform', '<PRE></PRE>',
15715 'unord', '<UL></UL>',
15716 'ord', '<OL></OL>',
15717 'desc', '<DL></DL>',
15718 'list', '',
15719 'par', '<P></P>'
15720 ) if ($HTML_VERSION == 2.0 );
15722 &generate_declaration_subs; # Generate code to handle declarations
15724 # ...but these block-level divisions must be handled differently...
15725 %declarations = (
15726 'quote', '<BLOCKQUOTE></BLOCKQUOTE>',
15727 'quotation', '<BLOCKQUOTE></BLOCKQUOTE>',
15728 'verse', '<BLOCKQUOTE></BLOCKQUOTE>',
15729 'preform', '<PRE></PRE>',
15730 'unord', '<UL></UL>',
15731 'ord', '<OL></OL>',
15732 'desc', '<DL></DL>',
15733 # 'list', '<DIV></DIV>',
15734 'par', '<P></P>',
15735 'samepage', '',
15736 # 'centering', '<DIV ALIGN="CENTER"></DIV>',
15737 'center', '<DIV ALIGN="CENTER"></DIV>',
15738 'flushleft', '<DIV ALIGN="LEFT"></DIV>',
15739 'raggedright', '<DIV ALIGN="LEFT"></DIV>',
15740 'flushright', '<DIV ALIGN="RIGHT"></DIV>',
15741 'raggedleft', '<DIV ALIGN="RIGHT"></DIV>',
15742 %declarations
15743 ) if ($HTML_VERSION > 2.0 );
15746 %section_commands =
15747 ('partstar' , '1' , 'chapterstar', '2', 'sectionstar', '3'
15748 , 'subsectionstar', '4', 'subsubsectionstar', '5', 'paragraphstar'
15749 , '6', 'subparagraphstar', '7'
15750 , 'part' , '1' , 'chapter', '2', 'section', '3','subsection', '4'
15751 , 'subsubsection', '5', 'paragraph', '6', 'subparagraph', '7'
15752 , 'slidehead', '3', %section_commands);
15753 # The tableofcontents, listoffigures, listoftables, bibliography and
15754 # textohtmlindex are set after determining what is the outermost level
15755 # in sub set_depth_levels. Appendix is implemented as a command.
15757 %standard_section_headings =
15758 ('part' , 'H1' , 'chapter' , 'H1', 'section', 'H1', 'subsection', 'H2'
15759 , 'subsubsection', 'H3', 'paragraph', 'H4', 'subparagraph', 'H5'
15760 , %standard_section_headings );
15762 # Generates code to handle sectioning commands
15763 # for those sections which take an argument.
15764 &generate_sectioning_subs;
15766 %section_headings =
15767 ('partstar' , 'H1' , 'chapterstar' , 'H1', 'sectionstar', 'H1'
15768 , 'subsectionstar', 'H2', 'subsubsectionstar', 'H3', 'paragraphstar'
15769 , 'H4', 'subparagraphstar', 'H5', %section_headings);
15771 # These need their own custom code but are treated as sectioning commands
15772 %section_headings =
15773 ('tableofcontents', 'H2', 'listoffigures', 'H2', 'listoftables', 'H2'
15774 , 'bibliography', 'H2', 'textohtmlindex', 'H2'
15775 , %standard_section_headings
15776 , %section_headings);
15778 &generate_accent_commands; # Code to handle accent commands
15780 # These are replaced as soon as the text is read in.
15781 %html_specials = ( '<', ';SPMlt;'
15782 , '>', ';SPMgt;'
15783 , '&', ';SPMamp;'
15784 # , '``', '\lq\lq ' # probably not a good idea
15785 # , "''", '\rq\rq ', # probably not a good idea
15786 , '"', ';SPMquot;'
15787 );
15789 %html_specials = ( %html_specials
15790 , '``', ';SPMldquo;', "''", ';SPMrdquo;'
15791 ) if ($HTML_VERSION >= 5 );
15793 # This mapping is needed in sub revert_to_raw_tex
15794 # before passing stuff to latex for processing.
15795 %html_specials_inv = (
15796 ';SPMlt;' ,'<'
15797 , ';SPMgt;','>'
15798 , ';SPMamp;','&'
15799 , ';SPMquot;','"'
15800 , ';SPMldquo;','``'
15801 , ';SPMrdquo;',"''"
15802 , ';SPMdollar;', '$' # for alltt
15803 , ';SPMpct;', '%'
15804 , ';SPMtilde;', '~'
15805 );
15807 # normalsize vertical dimension factors for 12pt (1.0 <=> <BR>)
15808 %vspace_12pt = ('ex', 1.0, 'em', 1.0, 'pt', 0.1, 'pc', 1.0,
15809 'in', 6.0, 'bp', 0.1, 'cm', 2.3, 'mm', 0.2, 'dd', 0.1,
15810 'cc', 1.0, 'sp', 0.0);
15812 # For some commands such as \\, \, etc it is not possible to define
15813 # perl subroutines because perl does not allow some non-ascii characters
15814 # in subroutine names. So we define a table and a subroutine to relate
15815 # such commands to ascii names.
15816 %normalize = ('\\', 'd_backslash'
15817 , '/', 'esc_slash', "`", 'grave'
15818 , "'", 'acute', "^", 'hat', '"', 'ddot'
15819 , '~', 'tilde', '.', 'dot', '=', 'bar'
15820 , '{', 'lbrace' , '}', 'rbrace', '|', 'Vert'
15821 , '#', 'esc_hash', '$', 'esc_dollar'
15822 );
15824 %text_accent = ( 'cedil','c', 'bdot','d', 'b','b' , 'tilde','~'
15825 , 'circ' ,'^', 'hat','^', 'check','v' , 'caron','v'
15826 , 'acute','\'' , 'grave','`' , 'dot','.' , 'breve','u'
15827 , 'ddot','"' , 'uml','"' , 'bar','=','macr','='
15828 , 'dblacc','H' , 't','t' , 'ogon','k' , 'ring','r'
15829 );
15831 # %languages_translations holds for each known language the
15832 # appropriate translation function. The function is called in
15833 # slurp_input.
15834 # The translation functions subtitute LaTeX macros
15835 # with ISO-LATIN-1 character references
15836 %language_translations = (
15837 'english', 'english_translation'
15838 , 'USenglish', 'english_translation'
15839 , 'original', 'english_translation'
15840 , 'german', 'german_translation'
15841 , 'austrian', 'german_translation'
15842 , 'finnish', 'finnish_translation'
15843 , 'french', 'french_translation'
15844 , 'spanish', 'spanish_translation'
15845 , 'swedish', 'swedish_translation'
15846 , 'turkish', 'turkish_translation'
15847 );
15849 # Reiner:
15850 # $standard_label_rx =
15851 # "\\s*[[]\\s*(((\$any_next_pair_rx4)|([[][^]]*[]])|[^]])*)[]]";
15852 # $enum_label_rx = "^((({[^{}]*})|([^{}]))*)([aAiI1])(.*)";
15853 # $enum_level = 0; # level for enumerate (1-4, i-iv)
15854 %enum = (
15855 'enumi', 0, # counter for level 1
15856 'enumii', 0, # counter for level 2
15857 'enumiii', 0,
15858 'enumiv', 0,
15859 'theenumi', "&arabic('enumi')", # eval($enum{"theenumi"})
15860 'theenumii', "&alph('enumii')",
15861 'theenumiii', "&roman('enumiii')",
15862 'theenumiv', "&Alph('enumiv')",
15863 # e.g. eval("$enum{'labelenumi'}")
15864 'labelenumi', 'eval($enum{"theenumi"}) . "."',
15865 'labelenumii', '"(" . eval($enum{"theenumii"}) . ")"',
15866 'labelenumiii', 'eval($enum{"theenumiii"}) . "."',
15867 'labelenumiv', 'eval($enum{"theenumiv"}) . "."'
15868 );
15870 %RomanI = ( '1',"I",'2',"II",'3',"III",'4',"IV"
15871 ,'5',"V",'6',"VI",'7',"VII", '8',"VIII",'9',"IX");
15872 %RomanX = ( '1',"X",'2',"XX",'3',"XXX",'4',"XL"
15873 ,'5',"L",'6',"LX",'7',"LXX", '8',"LXXX",'9',"XC");
15874 %RomanC = ( '1',"C",'2',"CC",'3',"CCC",'4',"CD"
15875 ,'5',"D",'6',"DC",'7',"DCC", '8',"DCCC",'9',"CM");
15876 %RomanM = ( '1',"M",'2',"MM",'3',"MMM",'4',"MH"
15877 ,'5',"H",'6',"HM",'7',"HMM",'8',"HMMM");
15879 %enum_label_funcs = (
15880 "a", "alph", "A", "Alph", "i", "roman", "I", "Roman", "1", "arabic" );
15882 sub farabic{
15883 local($_)=@_;
15884 $_;
15885 }
15886 sub arabic{
15887 local($_)=@_;
15888 eval($enum{$_});
15889 }
15891 sub falph{
15892 local($num)=@_;
15893 # chr($num+64);
15894 substr(" abcdefghijklmnopqrstuvwxyz",$num,1)
15895 }
15896 sub alph{
15897 local($num)=@_;
15898 &falph(eval($enum{$num}));
15899 }
15900 sub fAlph{
15901 local($num)=@_;
15902 # chr($num+32);
15903 substr(" ABCDEFGHIJKLMNOPQRSTUVWXYZ",$num,1)
15904 }
15905 sub Alph{
15906 local($num)=@_;
15907 &falph(eval($enum{$num}));
15908 }
15910 sub Roman{
15911 local($num)=@_;
15912 &fRoman(eval($enum{$num}));
15913 }
15914 sub fRoman{
15915 local($num)=@_;
15916 local($RmI)= $num%10; ($RmI) = (($RmI) ? $RomanI{"$RmI"} : '' );
15917 $num = $num/10; local($RmX)= $num%10; ($RmX) = (($RmX) ? $RomanX{"$RmX"} : '' );
15918 $num = $num/10; local($RmC)= $num%10; ($RmC) = (($RmC) ? $RomanC{"$RmC"} : '' );
15919 $num = $num/10; local($RmM)= $num%10; ($RmM) = (($RmM) ? $RomanM{"$RmM"} : '' );
15920 "$RmM" . "$RmC" . "$RmX" . "$RmI";
15921 }
15922 sub froman{
15923 local($_)=@_;
15924 $_ = &fRoman($_);
15925 $_ =~ tr/A-Z/a-z/;
15926 $_;
15927 }
15928 sub roman{
15929 local($num)=@_;
15930 &froman(eval($enum{$num}));
15931 }
15934 %unitscale = ("in",72,"pt",72.27/72,"pc",12,"mm",72/25.4,"cm",72/2.54
15935 ,"\\hsize",100,"\\vsize",100
15936 ,"\\textwidth",100,"\\textheight",100
15937 ,"\\pagewidth",100,"\\linewidth",100
15938 );
15939 %units = ("in","in","pt","pt","pc","pi","mm","mm","cm","cm"
15940 ,"\\hsize","%","\\vsize","%","\\textwidth","%","\\textheight","%");
15942 sub convert_length { # clean
15943 my ($this,$scale) = @_;
15944 $scale = 1 unless $scale;
15945 my ($pxs,$len,$full);
15946 if ( $this =~ /([\d.]*)\s*(in|pt|pc|mm|cm|\\[hv]size|\\\w+(width|height))?/ ) {
15947 $len = ($1 ? $1 : 1); $full = $2;
15948 if ($full &&($full =~ /\\([hv]size|\w+(width|height))/)) { $scale = 1;};
15949 $pxs = (($full) ? int($len * $unitscale{$full}*$scale + 0.5)
15950 : int($len*$scale + .5) );
15951 if ( $full =~ /\\([hv]size|\w+(width|height))/) { $pxs .= '%';};
15952 };
15953 ($pxs,$len);
15954 }
15959 # Inclusion in this list will cause a command or an environment to be ignored.
15960 # This is suitable for commands without arguments and for environments.
15961 # If however a do_env|cmd_<env|cmd> exists then it will be used.
15962 %ignore = ('sloppypar', 1, 'document', 1, 'newblock', 1,
15963 ',', 1, '@', 1, ' ', 1, '-', 1,
15964 'sloppy', 1,
15965 'hyphen', 1, 'titlepage', 1, 'htmlonly', 1,
15966 'flushleft', 1, 'flushright', 1, 'slide', 1,
15967 'tiny', 1, 'Tiny', 1, 'scriptsize', 1, 'footnotesize', 1,
15968 'small', 1, 'normalsize', 1, 'large', 1, 'Large', 1,
15969 'LARGE', 1, 'huge', 1, 'Huge', 1,
15970 %ignore);
15972 # Specify commands with arguments that should be ignored.
15973 # Arbitrary code can be placed between the arguments
15974 # to be executed while processing the command.
15975 #
15976 # Note that some commands MAY HAVE ARGUMENTS WHICH SHOULD BE LEFT AS TEXT
15977 # EVEN THOUGH THE COMMAND IS IGNORED (e.g. hbox, center, etc)
15979 &ignore_commands( <<_IGNORED_CMDS_);
15980 NeedsTeXFormat # {} # []
15981 ProvidesClass # {} # []
15982 ProvidesFile # {} # []
15983 ProvidesPackage # {} # []
15984 abovedisplayskip # &ignore_numeric_argument
15985 abovedisplayshortskip # &ignore_numeric_argument
15986 addcontentsline # {} # {} # {}
15987 addtocontents # {} # {}
15988 addvspace # {} # &ignore_numeric_argument
15989 and
15990 and # \$_ = join(''," - ",\$_)
15991 backmatter
15992 baselineskip # &ignore_numeric_argument
15993 belowdisplayskip # &ignore_numeric_argument
15994 belowdisplayshortskip # &ignore_numeric_argument
15995 bibdata
15996 bibliographystyle # {}
15997 bibstyle # {}
15998 bigskipamount # &ignore_numeric_argument
15999 smallskipamount # &ignore_numeric_argument
16000 medskipamount # &ignore_numeric_argument
16001 center
16002 citation # {}
16003 citeauthoryear
16004 clearpage
16005 cline # {}
16006 #documentclass # [] # {}
16007 #documentstyle # [] # {}
16008 #end # {}
16009 enlargethispage # {}
16010 evensidemargin # &ignore_numeric_argument
16011 filecontents
16012 filbreak
16013 fil
16014 fill
16015 flushbottom
16016 fontsize # {} # {}
16017 footheight # &ignore_numeric_argument
16018 footskip # &ignore_numeric_argument
16019 frontmatter
16020 fussy
16021 global
16022 goodbreak
16023 hbox
16024 headheight # &ignore_numeric_argument
16025 headsep # &ignore_numeric_argument
16026 hfil
16027 hfill
16028 hfuzz # &ignore_numeric_argument
16029 hline
16030 hspace # {} # \$_ = join(''," ",\$_)
16031 hspacestar # {} # \$_ = join(''," ",\$_)
16032 html
16033 ifcase
16034 ignorespaces
16035 indent
16036 itemindent # &ignore_numeric_argument
16037 itemsep # &ignore_numeric_argument
16038 labelsep # &ignore_numeric_argument
16039 labelwidth # &ignore_numeric_argument
16040 leavevmode
16041 leftmargin # &ignore_numeric_argument
16042 listparindent # &ignore_numeric_argument
16043 lower # &ignore_numeric_argument
16044 long
16045 mainmatter
16046 makebox # [] # []
16047 makeindex
16048 marginpar # {}
16049 marginparsep # &ignore_numeric_argument
16050 marginparwidth # &ignore_numeric_argument
16051 markboth # {} # {}
16052 markright # {}
16053 mathord
16054 mathbin
16055 mathindent # &ignore_numeric_argument
16056 mathrel
16057 mathop
16058 mathtt
16059 #mdseries
16060 newpage
16061 #newedboolean # {}
16062 #newedcommand # {} # [] # [] # {}
16063 #newedcounter # {} # []
16064 #newedenvironment # {} # [] # [] # {} # {}
16065 #newedtheorem # {} # [] # {} # []
16066 #providedcommand # {} # [] # [] # {}
16067 #renewedcommand # {} # [] # [] # {}
16068 #renewedenvironment # {} # [] # [] # {} # {}
16069 nobreakspace # \$_ = join('',";SPMnbsp;",\$_)
16070 nonbreakingspace # \$_ = join('',";SPMnbsp;",\$_)
16071 noalign
16072 nobreak
16073 nocite # {}
16074 noindent
16075 nolinebreak# []
16076 nopagebreak #[]
16077 normalmarginpar
16078 numberline
16079 oddsidemargin # &ignore_numeric_argument
16080 omit
16081 onecolumn
16082 outer
16083 pagenumbering #{}
16084 pagestyle # {}
16085 parindent # &ignore_numeric_argument
16086 parsep # &ignore_numeric_argument
16087 parskip # &ignore_numeric_argument
16088 partopsep # &ignore_numeric_argument
16089 penalty # &ignore_numeric_argument
16090 phantom # {}
16091 protect
16092 raggedright
16093 raggedbottom
16094 raise # &ignore_numeric_argument
16095 raisebox # {} # [] # []
16096 relax
16097 reversemarginpar
16098 rightmargin # &ignore_numeric_argument
16099 #rmfamily
16100 rule # [] # {} # {}
16101 samepage
16102 selectfont
16103 startdocument # \$SEGMENT=1;\$SEGMENTED=1; \$_
16104 strut
16105 suppressfloats # []
16106 textheight # &ignore_numeric_argument
16107 textwidth # &ignore_numeric_argument
16108 textnormal
16109 #textrm
16110 textup
16111 theorempreskipamount # &ignore_numeric_argument
16112 theorempostskipamount # &ignore_numeric_argument
16113 thispagestyle # {}
16114 topmargin # &ignore_numeric_argument
16115 topsep # &ignore_numeric_argument
16116 topskip # &ignore_numeric_argument
16117 twocolumn
16118 unskip
16119 #upshape
16120 vfil
16121 vfill
16122 vfilll
16123 vline
16124 _IGNORED_CMDS_
16126 # Commands which need to be passed, ALONG WITH THEIR ARGUMENTS, to TeX.
16127 # Note that this means that the arguments should *not* be translated,
16128 # This is handled by wrapping the commands in the dummy tex2html_wrap
16129 # environment before translation begins ...
16131 # Also it can be used to specify environments which may be defined
16132 # using do_env_* but whose contents will be passed to LaTeX and
16133 # therefore should not be translated.
16134 # Note that this code squeezes spaces out of the args of psfig;
16137 # Images are cropped to the minimum bounding-box for these...
16139 &process_commands_in_tex (<<_RAW_ARG_CMDS_);
16140 psfig # {} # \$args =~ s/ //g;
16141 usebox # {}
16142 framebox # [] # [] # {}
16143 _RAW_ARG_CMDS_
16145 # ... but these are set in a box to measure height/depth
16146 # so that white space can be preserved in the images.
16148 &process_commands_inline_in_tex (<<_RAW_ARG_CMDS_);
16149 #etalchar # {} \$args =~ s/(.*)/\$\^\{\$1\}\\\$/o;
16150 fbox # {}
16151 #frac # [] # {} # {}
16152 dag
16153 ddag
16154 l
16155 L
16156 oe
16157 OE
16158 textexclamdown
16159 textquestiondown
16160 textregistered
16161 textperiodcentered
16162 #textcircled # {}
16163 #raisebox # {} # [] # [] # {}
16164 _RAW_ARG_CMDS_
16168 # These are handled by wrapping the commands in the dummy tex2html_nowrap
16169 # environment before translation begins. This environment will be
16170 # stripped off later, when the commands are put into images.tex ...
16172 &process_commands_nowrap_in_tex (<<_RAW_ARG_NOWRAP_CMDS_);
16173 #begingroup
16174 #endgroup
16175 #bgroup
16176 #egroup
16177 errorstopmode
16178 nonstopmode
16179 scrollmode
16180 batchmode
16181 psfigurepath # {}
16182 pssilent
16183 psdraft
16184 psfull
16185 thinlines
16186 thicklines
16187 linethickness # {}
16188 hyphenation # {}
16189 hyphenchar # \\ # &get_numeric_argument
16190 hyphenpenalty # &get_numeric_argument
16191 #let # \\ # <<\\(\\W|\\w+)>>
16192 newedboolean # {}
16193 newedcommand # {} # [] # [] # {}
16194 newedcounter # {} # []
16195 newedenvironment # {} # [] # [] # {} # {}
16196 newedtheorem # {} # [] # {} # []
16197 #providedcommand # {} # [] # [] # {}
16198 #renewedcommand # {} # [] # [] # {}
16199 #renewedenvironment # {} # [] # [] # {} # {}
16200 DeclareMathAlphabet # {} # {} # {} # {} # {}
16201 SetMathAlphabet # {} # {} # {} # {} # {} # {}
16202 DeclareMathSizes # {} # {} # {} # {}
16203 DeclareMathVersion # {}
16204 DeclareSymbolFont # {} # {} # {} # {} # {}
16205 DeclareSymbolFontAlphabet # {} # {}
16206 DeclareMathSymbol # {} # {} # {} # {}
16207 SetSymbolFont # {} # {} # {} # {} # {} # {}
16208 DeclareFontShape # {} # {} # {} # {} # {} # {}
16209 DeclareFontFamily # {} # {} # {}
16210 DeclareFontEncoding # {} # {} # {}
16211 DeclareFontSubstitution # {} # {} # {} # {}
16212 mathversion # {}
16213 #newfont # {} # {}
16214 #normalfont
16215 #rmfamily
16216 #mdseries
16217 newlength # {}
16218 setlength # {} # {}
16219 addtolength # {} # {}
16220 settowidth # {}# {}
16221 settoheight # {} # {}
16222 settodepth # {} # {}
16223 newsavebox # {}
16224 savebox # {} # [] # {}
16225 sbox # {} # {}
16226 setbox # {}
16227 TagsOnLeft # \$EQN_TAGS = \"L\" if \$PREAMBLE;
16228 TagsOnRight # \$EQN_TAGS = \"R\" if \$PREAMBLE;
16229 _RAW_ARG_NOWRAP_CMDS_
16232 &process_commands_wrap_deferred (<<_RAW_ARG_DEFERRED_CMDS_);
16233 alph # {}
16234 Alph # {}
16235 arabic # {}
16236 author # [] # {}
16237 boldmath
16238 unboldmath
16239 captionstar # [] # {}
16240 caption # [] # {}
16241 #endsegment # []
16242 #segment # [] # {} # {} # {}
16243 fnsymbol # {}
16244 footnote # [] # {}
16245 footnotemark # []
16246 footnotetext # [] # {}
16247 #thanks # {}
16248 roman # {}
16249 Roman # {}
16250 #mbox # {}
16251 parbox # [] # [] # [] # {} # {}
16252 #selectlanguage # [] # {}
16253 setcounter # {} # {}
16254 addtocounter # {} # {}
16255 stepcounter # {}
16256 refstepcounter # {}
16257 value # {}
16258 par
16259 hrule # &ignore_numeric_argument
16260 linebreak # []
16261 pagebreak # []
16262 newfont # {} # {}
16263 smallskip
16264 medskip
16265 bigskip
16266 centering
16267 raggedright
16268 raggedleft
16269 itshape
16270 #textit # {}
16271 upshape
16272 slshape
16273 #scshape
16274 rmfamily
16275 sffamily
16276 ttfamily
16277 mdseries
16278 bfseries
16279 #textbf # {}
16280 em
16281 normalfont
16282 it
16283 rm
16284 sl
16285 bf
16286 tt
16287 sf
16288 Tiny
16289 tiny
16290 scriptsize
16291 footnotesize
16292 small
16293 Small
16294 SMALL
16295 normalsize
16296 large
16297 Large
16298 LARGE
16299 huge
16300 Huge
16301 lowercase # {}
16302 uppercase # {}
16303 MakeLowercase # {}
16304 MakeUppercase # {}
16305 htmlinfo # []
16306 htmlinfostar # []
16307 tableofchildlinks # []
16308 tableofchildlinksstar # []
16309 tableofcontents
16310 listoffigures
16311 listoftables
16312 thepart
16313 thepage
16314 thechapter
16315 thesection
16316 thesubsection
16317 thesubsubsection
16318 theparagraph
16319 thesubparagraph
16320 theequation
16321 htmltracenv # {}
16322 HTMLsetenv # [] # {} # {}
16323 #newedboolean # {}
16324 #newedcounter # {} # []
16325 #newedcommand # {} # [] # [] # {}
16326 #newedtheorem # {} # [] # {} # []
16327 #newedenvironment # {} # [] # [] # {} # {}
16328 providedcommand # {} # [] # [] # {}
16329 renewedcommand # {} # [] # [] # {}
16330 renewedenvironment # {} # [] # [] # {} # {}
16331 url # {}
16332 htmlurl # {}
16333 latextohtml
16334 TeX
16335 LaTeX
16336 LaTeXe
16337 LaTeXiii
16338 Xy
16339 MF
16340 AmS
16341 AmSTeX
16342 textcircled # {}
16343 _RAW_ARG_DEFERRED_CMDS_
16346 #rrm
16347 # implement the XBit-Hack for Apache servers, to handle
16348 # Server-Side Includes (SSIs) with .html filename extension
16349 #
16350 sub check_htaccess {
16351 my $access_file = '.htaccess';
16352 my $has_access = '';
16353 local $_;
16354 print "\nChecking for .htaccess file";
16355 if (-f $access_file) {
16356 print STDOUT " ... found";
16357 open(HTACCESS, "<$access_file");
16358 while (<HTACCESS>) {
16359 if (/^\s*XBitHack\s*on\s*$/) {
16360 print STDOUT " with XBitHack on";
16361 $has_access =1; last;
16362 };
16363 }
16364 print STDOUT "\n";
16365 close HTACCESS;
16366 return() if $has_access;
16367 open (HTACCESS, ">>$access_file");
16368 &write_warnings("appended to .htaccess in $DESTDIR");
16369 } else {
16370 open (HTACCESS, ">$access_file");
16371 chmod 0644, $access_file;
16372 &write_warnings("created .htaccess file in $DESTDIR");
16373 }
16374 print HTACCESS "\nXBitHack on\n";
16375 close HTACCESS;
16376 }
16378 # This maps the HTML mnemonic names for the ISO-LATIN-1 character references
16379 # to their numeric values. When converting latex specials characters to
16380 # ISO-LATIN-1 equivalents I use the numeric values because this makes any
16381 # conversion back to latex (using revert_raw_tex) more reliable (in case
16382 # the text contains "&mnemonic_name"). Errors may occur if an environment
16383 # passed to latex (e.g. a table) contains the numeric values of character
16384 # references.
16386 # RRM: removed this portion; load from latin1.pl instead
16387 #&do_require_extension('latin1');
16389 sub make_isolatin1_rx {
16390 local($list) = &escape_rx_chars(join($CD,(values %iso_8859_1_character_map_inv)));
16391 $list =~ s/$CD/|/g;
16392 $isolatin1_rx = "($list)";
16393 }
16396 ################### Frequently used regular expressions ###################
16397 # $1 : preamble
16399 $preamble_rx = "(^[\\s\\S]*)(\\\\begin\\s*$O\\d+$C\\s*document\\s*$O\\d+$C|\\\\startdocument)";
16401 # \d (number) should sometimes also be a delimiter but this causes
16402 # problems with command names that are allowed to contain numbers (eg tex2html)
16403 # \d is a delimiter with commands which take numeric arguments?
16404 # JCL: I can't see that. \tex2html is also no valid LaTeX (or TeX).
16405 # It is parsed \tex 2html, and \tex may take 2html as argument, but this
16406 # is invalid LaTeX. \d must be treated as delimiter.
16408 # JCL(jcl-del) - Characters to be treated as letters, everything else
16409 # is a delimiter.
16410 # internal LaTeX command separator, shouldn't be equal to $;
16411 $CD = "\001";
16412 &make_cmd_spc_rx; # determines space to follow a letter command
16413 #old $delimiters = '\'\\s[\\]\\\\<>(=).,#;:~\/!-';
16414 $letters = 'a-zA-Z';
16415 $delimiter_rx = "([^$letters])";
16416 #
16418 # liberalized environment names (white space, optional arg, interpunctuation signs etc.)
16419 # $1 : br_id, $2 : <environment>
16420 $begin_env_rx="(\\\\protect)?\\\\begin\\s*(\\[([^\\]]*)])?$O(\\d+)$C\\s*([^'[\\]\\\\#~]+)\\s*$O\\4$C";
16421 $begin_env_pr_rx="(\\\\protect)?\\\\begin\\s*(\\[([^\\]]*)])?$OP(\\d+)$CP\\s*([^'[\\]\\\\#~]+)\\s*$OP\\4$CP";
16423 $mbox_rx = "\\\\mbox\\s*";
16425 $match_br_rx = "\\s*$O\\d+$C\\s*";
16427 $opt_arg_rx = "\\s*\\[([^\\]]*)\\]\\s*"; # Cannot handle nested []s!
16428 $optional_arg_rx = "^\\s*\\[([^]]*)\\]"; # Cannot handle nested []s!
16430 $block_close_rx = "^<\\/(DIV|P|BLOCKQUOTE)>\$";
16431 $all_close_rx = "^<\\/(BODY|PRE|OL|UL|DL|FORM|ADDRESS)>\$";
16433 # Matches a pair of matching brackets
16434 # $1 : br_id
16435 # $2 : contents
16436 $next_pair_rx = "^[\\s%]*$O(\\d+)$C([\\s\\S]*)$O\\1$C($comment_mark\\d*\\n?)?";
16438 # will comments be a problem after these ???
16439 $any_next_pair_rx = "$O(\\d+)$C([\\s\\S]*)$O\\1$C";
16440 $any_next_pair_rx4 = "$O(\\d+)$C([\\s\\S]*)$O\\4$C";
16441 $any_next_pair_pr_rx4 = "$OP(\\d+)$CP([\\s\\S]*)$OP\\4$CP";
16442 $any_next_pair_rx5 = "$O(\\d+)$C([\\s\\S]*)$O\\5$C";
16443 $any_next_pair_rx6 = "$O(\\d+)$C([\\s\\S]*)$O\\6$C";
16445 # used for labels in {enumerate} environments
16446 $standard_label_rx =
16447 "\\s*[[]\\s*((($any_next_pair_rx4)|([[][^]]*[]])|[^]])*)[]]";
16448 $enum_label_rx = "^((({[^{}]*})|([^{}]))*)([aAiI1])(.*)";
16449 $enum_level = 0; # level for enumerate (1-4, i-iv)
16452 # Matches the \ensuremath command
16453 $enspair = "\\\\ensuremath\\s*" . $any_next_pair_rx;
16454 # $enspair = "\\\\ensuremath\\s*$O(\\d+)$C([\\s\\S]*[\\\\\$&]+[\\s\\S]*)$O\\1$C";
16456 # Matches math comments, from math.pl
16457 $math_verbatim_rx = "$verbatim_mark#math(\\d+)#";
16458 $mathend_verbatim_rx = "$verbatim_mark#mathend([^#]*)#";
16460 # Matches math array environments
16461 $array_env_rx = "array|cases|\\w*matrix";
16463 # initially empty; has a value in HTML 3.2 and 4.0
16464 $math_class = '' unless ($math_class);
16465 $eqno_class = '' unless ($eqno_class);
16467 # Matches to end-of-line and subsequent spaces
16468 $EOL = "[ \\t]*\\n?";
16470 # Matches wrapped \par command
16471 $par_rx = "\\n?\\\\begin(($O|$OP)\\d+($C|$CP))tex2html_deferred\\1\\\\par\\s\*"
16472 . "\\\\end(($O|$OP)\\d+($C|$CP))tex2html_deferred\\4\\n?";
16474 # $1 : br_id
16475 $begin_cmd_rx = "$O(\\d+)$C";
16477 # $1 : image filename prefix
16478 $img_rx = "(\\w*T?img\\d+)";
16480 # $1 : largest argument number
16481 $tex_def_arg_rx = "^[#0-9]*#([0-9])($O|$OP)";
16483 # only some non-alphanumerics are allowed in labels, Why?
16484 $label_rx = "[^\\w\.\\\-\\\+\\\:]";
16486 #JCL(jcl-del) - new face, see also &do_cmd_makeatletter et.al.
16487 # $cmd_delims = q|-#,.~/\'`^"=\$%&_{}@|; # Commands which are also delimiters!
16488 # $single_cmd_atletter_rx = "\\\\([a-zA-Z\\\@]+\\*?|[$cmd_delims]|\\\\)";
16489 # $single_cmd_atother_rx = "\\\\([a-zA-Z]+\\*?|[$cmd_delims]|\\\\)";
16490 # $1 : declaration or command or newline (\\)
16491 &make_single_cmd_rx;
16492 #
16494 # $1 : description in a list environment
16495 $item_description_rx =
16496 # "\\\\item\\s*[[]\\s*((($any_next_pair_rx4)|([[][^]]*[]])|[^]])*)[]]";
16497 "\\\\item\\s*[[]\\s*((($any_next_pair_pr_rx4)|([[][^]]*[]])|[^]])*)[]]";
16499 $fontchange_rx = 'rm|em|it|sl|sf|tt|sc|upshape|normalfont';
16500 $fontweight_rx = 'bf|mdseries|normalfont';
16501 $colorchange_rx = "(text)?color\\s*(\#\\w{6})?";
16502 $sizechange_rx = 'tiny|Tiny|scriptsize|footnotesize|small|Small|SMALL' .
16503 '|normalsize|large|Large|LARGE|huge|Huge';
16505 # $image_switch_rx = "makeimage";
16506 $image_switch_rx = "makeimage|scshape|sc";
16507 $env_switch_rx = "writetolatex";
16508 $raw_arg_cmds{'font'} = 1;
16510 # Matches the \caption command
16511 # $1 : br_id
16512 # $2 : contents
16513 $caption_suffixes = "lof|lot";
16514 # $caption_rx = "\\\\caption\\s*([[]\\s*((($any_next_pair_rx5)|([[][^]]*[]])|[^]])*)[]])?$O(\\d+)$C([\\s\\S]*)$O\\8$C$EOL";
16516 $caption_rx = "\\\\(top|bottom|table)?caption\\s*\\\*?\\s*([[]\\s*((($any_next_pair_rx6)|([[][^]]*[]])|[^]])*)[]])?$O(\\d+)$C([\\s\\S]*)$O\\9$C$EOL";
16517 $caption_width_rx = "\\\\setlength\\s*(($O|$OP)\\d+($C|$CP))\\\\captionwidth\\1\\s*(($O|$OP)\\d+($C|$CP))([^>]*)\\4";
16519 # Matches the \htmlimage command
16520 # $1 : br_id
16521 # $2 : contents
16522 $htmlimage_rx = "\\\\htmlimage\\s*$O(\\d+)$C([\\s\\S]*)$O\\1$C$EOL";
16523 $htmlimage_pr_rx = "\\\\htmlimage\\s*$OP(\\d+)$CP([\\s\\S]*)$OP\\1$CP$EOL";
16525 # Matches the \htmlborder command
16526 # $1 : optional argument...
16527 # $2 : ...contents i.e. extra attributes
16528 # $3 : br_id
16529 # $4 : contents i.e. width
16530 $htmlborder_rx = "\\\\htmlborder\\s*(\\[([^]]*)\\])?\\s*$O(\\d+)$C(\\d*)$O\\3$C$EOL";
16531 $htmlborder_pr_rx = "\\\\htmlborder\\s*(\\[([^]]*)\\])?\\s*$OP(\\d+)$CP(\\d*)$OP\\3$CP$EOL";
16533 # Matches a pair of matching brackets
16534 # USING PROCESSED DELIMITERS;
16535 # (the delimiters are processed during command translation)
16536 # $1 : br_id
16537 # $2 : contents
16538 # $next_pair_pr_rx = "^[\\s%]*$OP(\\d+)$CP([\\s\\S]*)$OP\\1$CP";
16539 $next_pair_pr_rx = "^[\\s%]*$OP(\\d+)$CP([\\s\\S]*)$OP\\1$CP($comment_mark\\d*\\n?)?";
16540 $any_next_pair_pr_rx = "$OP(\\d+)$CP([\\s\\S]*)$OP\\1$CP($comment_mark\\d*\\n?)?";
16541 $next_token_rx = "^[\\s%]*(\\\\[A-Za-z]+|\\\\[^a-zA-Z]|.)";
16543 $HTTP_start = 'http:';
16545 # This will be used to recognise escaped special characters as such
16546 # and not as commands
16547 $latex_specials_rx = '[\$]|&|%|#|{|}|_';
16548 $html_escape_chars = '<>&';
16550 # This is used in sub revert_to_raw_tex before handing text to be processed
16551 # by latex.
16552 $html_specials_inv_rx = join("|", keys %html_specials_inv);
16554 # These are used for direct replacements in/from ALT=... strings
16555 %html_special_entities = ('<','lt','>','gt','"','quot','&','amp');
16556 %html_spec_entities_inv = ('lt','<','gt','>','quot','"','amp','&');
16558 # This is also used in sub revert_to_raw_tex
16559 $character_entity_rx = '(&#(\d+);)';
16560 $named_entity_rx = '&(\w+);';
16562 #commands for altering theorem-styles
16563 $theorem_cmd_rx = 'theorem(style|(header|body)font)';
16566 # Matches a \begin or \end {tex2html_wrap}. Also used by revert_to_raw_tex
16567 $tex2html_wrap_rx = '\\\\(begin|end)\\s*\{\\s*(tex2html_(wrap|nowrap|deferred|nomath|preform|\\w*_inline)[_a-z]*|makeimage)\\s*\}'."($EOL)";
16568 $tex2html_deferred_rx = '\\\\(begin|end)(<<\\d+>>)tex2html_deferred\\2';
16569 $tex2html_deferred_rx2 = '\\\\(begin|end)(<<\\d+>>)tex2html_deferred\\4';
16570 $tex2html_envs_rx = "\\\\(begin|end)\\s*(($O|$OP)\\d+($C|$CP))\\s*(tex2html_(wrap|nowrap|deferred|nomath|preform|\w+_inline)[_a-z]*||makeimage)\\s*\\2";
16572 # The first empty parenthese pair is for non-letter commands.
16573 # $2: meta command, $4: delimiter (may be empty) ignore the *-version distinction
16574 # $meta_cmd_rx = "()\\\\(providecommand|renewcommand|renewenvironment|newcommand|newenvironment|newtheorem|newcounter|newboolean|newif|let)(([^$letters$cmd_spc])|$cmd_spcs_rx)";
16575 $meta_cmd_rx = "()\\\\(providecommand|renewcommand|renewenvironment|newcommand|newenvironment|newtheorem|newcounter|newboolean|newif|DeclareRobustCommand|DeclareMathOperator\\*?)\\\*?(([^$letters$cmd_spc])|$cmd_spcs_rx)";
16577 &make_counters_rx;
16579 # Matches a label command and its argument
16580 $labels_rx = "\\\\label\\s*$O(\\d+)$C([\\s\\S]*)$O\\1$C$EOL";
16581 $labels_rx8 = "\\\\label\\s*$O(\\d+)$C([\\s\\S]*)$O\\8$C$EOL";
16583 # Matches environments that should not be touched during the translation
16584 # $verbatim_env_rx = "\\s*{(verbatim|rawhtml|LVerbatim)[*]?}";
16585 $verbatim_env_rx = "\\s*(\\w*[Vv]erbatim|rawhtml|imagesonly|tex2html_code)[*]?";
16586 $image_env_rx = "\\s*(picture|xy|diagram)[*]?";
16587 $keepcomments_rx = "\\s*(picture|makeimage|xy|diagram)[*]?";
16589 # names of different math environment types
16590 $display_env_rx = "displaymath|makeimage|eqnarray|equation";
16591 $inline_env_rx = "inline|indisplay|entity|xy|diagram";
16592 $sub_array_env_rx = "array|(small|\\w)\?matrix|tabular|cases";
16594 # Matches environments needing pre-processing for images
16595 $pre_processor_env_rx = "\\\\(begin|end)\\s*(($O|$OP|\{)\\d+($C|$CP|\}))pre_(\\w+)\\2";
16597 # Matches icon markers
16598 $icon_mark_rx = "<tex2html_(" . join("|", keys %icons) . ")>";
16600 $start_time = time;
16601 print STDOUT join(" ", "Starting at", $start_time, "seconds\n")
16602 if ($TIMING||$DEBUG||($VERBOSITY>2));
16604 } # end of &initialise
16606 # Frequently used regular expressions with arguments
16607 sub make_end_env_rx {
16608 local($env) = @_;
16609 $env = &escape_rx_chars($env);
16610 "\\\\end\\s*$O(\\d+)$C\\s*$env\\s*$O\\1$C".$EOL;
16611 }
16613 sub make_begin_end_env_rx {
16614 local($env) = @_;
16615 $env = &escape_rx_chars($env);
16616 "\\\\(begin|end)\\s*$O(\\d+)$C\\s*$env\\s*$O\\3$C(\\s*\$)?";
16617 }
16619 sub make_end_cmd_rx {
16620 local($br_id) = @_;
16621 "$O$br_id$C";
16622 }
16624 #JCL(jcl-del) - see also &tokenize.
16625 # Arrange commands into a regexp for tokenisation.
16626 # Any letter command will gobble spaces, but avoids to match
16627 # on ensuing letters (\foo won't match on \foox).
16628 # Any non-letter command retains spaces and matches always
16629 # by itself (\| matches \|... regardless of ...).
16630 #
16631 # This all is a huge kludge. The commands names should stay fix,
16632 # regardless of changing catcodes. If we have \makeatletter,
16633 # and LaTeX2HTML marks \@foo, then \@foo will be expanded
16634 # properly before \makeatother, but does weird things on \@foo
16635 # after \makeatother (\@foo in LaTeX is then \@ and foo, which
16636 # isn't recognized as such).
16637 # The reason is that the text to match the command \@foo
16638 # in LaTeX mustn't be \@foo at all, because any text in LaTeX
16639 # is also attributed with the category codes.
16640 #
16641 # But at least we have proper parsing of letter and non-letter
16642 # commands as long as catcoding won't upset LaTeX2HTML too much.
16643 #
16644 sub make_new_cmd_rx {
16645 return("") if $#_ < 0; # empty regexp if list is empty!
16647 # We have a subtle treatment of ambivalent commands like
16648 # \@foo in situations depicted above!
16649 # Get every command that contains no letters ...
16650 local($nonlettercmds) =
16651 &escape_rx_chars(join($CD, grep(!/[$letters]/,@_)));
16652 # and every command that contains a letter
16653 local($lettercmds) =
16654 &escape_rx_chars(join($CD, grep(/[$letters]/,@_)));
16656 if (%renew_command) {
16657 local($renew);
16658 foreach $renew (keys %renew_command) {
16659 $lettercmds =~ s/(^|$CD)$renew//; }
16660 $lettercmds =~ s/^$CD$//;
16661 }
16663 # replace the temporary $CD delimiter (this enables eg. \| command)
16664 $nonlettercmds =~ s/$CD/|/g;
16665 $lettercmds =~ s/$CD/|/g;
16667 # In case we have no non-letter commands, insert empty parentheses
16668 # to align match strings.
16669 #
16670 $nonlettercmds =~ s/^\||\|$//g;
16671 $lettercmds =~ s/^\||\|$//g;
16672 local($rx) = (length($nonlettercmds) ? "\\\\($nonlettercmds)" : "");
16673 if (length($lettercmds)) {
16674 $rx .= ( length($rx) ? "|" : "()" );
16675 $rx .= "\\\\($lettercmds)(([^$letters$cmd_spc])|$cmd_spcs_rx|\$)";
16676 }
16677 # $1: non-letter cmd, $2: letter cmd, $4: delimiter
16678 # Eg. \\(\@|...|\+)|\\(abc|...|xyz)(([^a-zA-Z \t])|[ \t]+)
16679 # $1 and $2 are guaranteed to alternate, $4 may be empty.
16680 $rx;
16681 }
16683 # Build a simple regexp to use after tokenisation for
16684 # faster translation.
16685 sub make_new_cmd_no_delim_rx {
16686 return("") if $#_ < 0; # empty regexp if list is empty!
16687 # Get every command that contains no letters ...
16688 local($_) = &escape_rx_chars(join($CD, @_));
16689 s/$CD/|/g;
16691 join('',"\\\\(",$_,")");
16692 }
16695 #JCL(jcl-del) - new face: w/o arg (was 'begin' only), escapes env names
16696 sub make_new_env_rx {
16697 local($envs) = &escape_rx_chars(join($CD, keys %new_environment));
16698 $envs =~ s/$CD/|/g;
16699 length($envs) ? "\\\\begin\\s*$O(\\d+)$C\\s*($envs)\\s*$O\\1$C\\s*" : "";
16700 }
16702 sub make_new_end_env_rx {
16703 local($envs) = &escape_rx_chars(join($CD, keys %new_environment));
16704 $envs =~ s/$CD/|/g;
16705 length($envs) ? "\\\\end\\s*$O(\\d+)$C\\s*($envs)\\s*$O\\1$C\\s*" : "";
16706 }
16708 #JCL(jcl-del) - $delimiter_rx -> ^$letters
16709 # don't care for $cmd_spc_rx; space after sectioning commands
16710 # is unlikely and I don't want to try too much new things
16711 #
16712 sub make_sections_rx {
16713 local($section_alts) = &get_current_sections;
16714 # $section_alts includes the *-forms of sectioning commands
16715 $sections_rx = "()\\\\($section_alts)(([^$letters$cmd_spc])|$cmd_spcs_rx|\$)";
16716 # $sections_rx = "()\\\\($section_alts)([^$letters])";
16717 }
16719 sub make_order_sensitive_rx {
16720 local(@theorem_alts, $theorem_alts);
16721 @theorem_alts = ($preamble =~ /\\newtheorem\s*{([^\s}]+)}/og);
16722 $theorem_alts = join('|',@theorem_alts);
16723 #
16724 # HWS: Added kludge to require counters to be more than 2 characters long
16725 # in order to be flagged as order-sensitive. This will permit equations
16726 # with \theta to remain order-insensitive. Also permit \alpha and
16727 # the eqnarray* environment to remain order-insensitive.
16728 #
16729 $order_sensitive_rx =
16730 # "(equation|eqnarray[^*]|\\\\caption|\\\\ref|\\\\the[a-z]{2,2}[a-z]|\\\\stepcounter" .
16731 "(\\\\caption|\\\\ref|\\\\the[a-z]{2,2}[a-z]|\\\\stepcounter" .
16732 "|\\\\arabic|\\\\roman|\\\\Roman|\\\\alph[^a]|\\\\Alph|\\\\fnsymbol)";
16733 $order_sensitive_rx =~ s/\)/|$theorem_alts)/ if $theorem_alts;
16734 }
16736 sub make_language_rx {
16737 local($language_alts) = join("|", keys %language_translations);
16738 # $setlanguage_rx = "\\\\se(lec)?tlanguage\\s*{\\\\?($language_alts)}";
16739 $setlanguage_rx = "\\\\setlanguage\\s*{\\\\?($language_alts)}";
16740 $language_rx = "\\\\($language_alts)TeX";
16741 $case_change_rx = "(\\\\(expandafter|noexpand)\s*)?\\\\((Make)?([Uu]pp|[Ll]ow)ercase)\s*";
16742 }
16744 sub addto_languages {
16745 local($lang) = @_;
16746 local($trans) = "main'".$lang.'_translation';
16747 if (defined &$trans) {
16748 $language_translations {$lang} = $lang.'_translation';
16749 }
16750 }
16752 # JCL(jcl-del) - new rexexp type
16753 sub make_raw_arg_cmd_rx {
16754 # $1 or $2 : commands to be processed in latex (with arguments untouched)
16755 # $4 : delimiter
16756 $raw_arg_cmd_rx = &make_new_cmd_rx(keys %raw_arg_cmds);
16757 $raw_arg_cmd_rx;
16758 }
16760 # There are probably more.
16761 # Interferences not checked out yet, thus in makeat... only.
16762 sub make_letter_sensitive_rx {
16763 $delimiter_rx = "([^$letters])";
16764 &make_sections_rx;
16765 &make_single_cmd_rx;
16766 &make_counters_rx;
16767 }
16769 #JCL(jcl-del) - this could eat one optional newline, too.
16770 # But this might result in large lines... anyway, it *should* be
16771 # handled. A possible solution would be to convert adjacent newlines
16772 # into \par's in preprocessing.
16773 sub make_cmd_spc_rx {
16774 $cmd_spc = " \\t";
16775 $cmd_spc_rx = "[ \\t]*"; # zero or more
16776 $cmd_spcs_rx = "[ \\t]+"; # one or more
16777 }
16779 sub make_single_cmd_rx {
16780 $single_cmd_rx = "\\\\([^$letters])|\\\\([$letters]+\\*?)(([^$letters$cmd_spc])|$cmd_spcs_rx|\n|\$)";
16781 }
16783 sub make_counters_rx {
16784 # Matches counter commands - these are caught early and are appended to the
16785 # file that is passed to latex.
16786 #JCL(jcl-del) - $delimiter_rx -> ^$letters
16787 $counters_rx = "()\\\\(newcounter|addtocounter|setcounter|refstepcounter|stepcounter|arabic|roman|Roman|alph|Alph|fnsymbol)(([^$letters$cmd_spc])|$cmd_spcs_rx|\$)";
16788 }
16791 # Creates an anchor for its argument and saves the information in
16792 # the array %index;
16793 # In the index the word will use the beginning of the title of
16794 # the current section (instead of the usual pagenumber).
16795 # The argument to the \index command is IGNORED (as in latex)
16796 sub make_index_entry { &make_real_index_entry(@_) }
16797 sub make_real_index_entry {
16798 local($br_id,$str) = @_;
16799 local($this_file) = $CURRENT_FILE;
16800 $TITLE = $saved_title if (($saved_title)&&(!($TITLE)||($TITLE eq $default_title)));
16801 # Save the reference
16802 $str = "$str###" . ++$global{'max_id'}; # Make unique
16803 $index{$str} .= &make_half_href($this_file."#$br_id");
16804 "<A NAME=\"$br_id\">$anchor_invisible_mark<\/A>";
16805 }
16807 sub image_message { # clean
16808 print <<"EOF";
16810 To resolve the image conversion problems please consult
16811 the "Troubleshooting" section of your local User Manual
16812 or read it online at
16813 http://www-texdev.ics.mq.edu.au/l2h/docs/manual/
16815 EOF
16816 }
16818 sub image_cache_message { # clean
16819 print <<"EOF";
16821 If you are having problems displaying the correct images with Mosaic,
16822 try selecting "Flush Image Cache" from "Options" in the menu-bar
16823 and then reload the HTML file.
16824 EOF
16825 }
16827 __DATA__
16829 # start of POD documentation
16831 =head1 NAME
16833 latex2html - Translate LaTeX files to HTML (HyperText Markup Language)
16835 =head1 SYNOPSIS
16837 B<latex2html> S<[ B<-help> | B<-h> ]> S<[ B<-version> | B<-V> ]>
16839 B<latex2html> S<[ B<-split> I<num> ]>
16840 S<[ B<-link> I<num> ]>
16841 S<[ B<-toc_depth> I<num> ]>
16842 S<[ B<->(B<no>)B<toc_stars> ]>
16843 S<[ B<->(B<no>)B<short_extn> ]>
16844 S<[ B<-iso_language> I<lang> ]>
16845 S<[ B<->(B<no>)B<validate> ]>
16846 S<[ B<->(B<no>)B<latex> ]>
16847 S<[ B<->(B<no>)B<djgpp> ]>
16848 S<[ B<->(B<no>)B<fork> ]>
16849 S<[ B<->(B<no>)B<external_images> ]>
16850 S<[ B<->(B<no>)B<ascii_mode> ]>
16851 S<[ B<->(B<no>)B<lcase_tags> ]>
16852 S<[ B<->(B<no>)B<ps_images> ]>
16853 S<[ B<-font_size> I<size> ]>
16854 S<[ B<->(B<no>)B<tex_defs> ]>
16855 S<[ B<->(B<no>)B<navigation> ]>
16856 S<[ B<->(B<no>)B<top_navigation> ]>
16857 S<[ B<->(B<no>)B<buttom_navigation> ]>
16858 S<[ B<->(B<no>)B<auto_navigation> ]>
16859 S<[ B<->(B<no>)B<index_in_navigation> ]>
16860 S<[ B<->(B<no>)B<contents_in_navigation> ]>
16861 S<[ B<->(B<no>)B<next_page_in_navigation> ]>
16862 S<[ B<->(B<no>)B<previous_page_in_navigation> ]>
16863 S<[ B<->(B<no>)B<footnode> ]>
16864 S<[ B<->(B<no>)B<numbered_footnotes> ]>
16865 S<[ B<-prefix> I<output_filename_prefix> ]>
16866 S<[ B<->(B<no>)B<auto_prefix> ]>
16867 S<[ B<-long_titles> I<num> ]>
16868 S<[ B<->(B<no>)B<custom_titles> ]>
16869 S<[ B<-title>|B<-t> I<top_page_title> ]>
16870 S<[ B<->(B<no>)B<rooted> ]>
16871 S<[ B<-rootdir> I<output_directory> ]>
16872 S<[ B<-dir> I<output_directory> ]>
16873 S<[ B<-mkdir> ]>
16874 S<[ B<-address> I<author_address> | B<-noaddress> ]>
16875 S<[ B<->(B<no>)B<subdir> ]>
16876 S<[ B<-info> I<0> | I<1> | I<string> ]>
16877 S<[ B<->(B<no>)B<auto_link> ]>
16878 S<[ B<-reuse> I<num> | B<-noreuse> ]>
16879 S<[ B<->(B<no>)B<antialias_text> ]>
16880 S<[ B<->(B<no>)B<antialias> ]>
16881 S<[ B<->(B<no>)B<transparent> ]>
16882 S<[ B<->(B<no>)B<white> ]>
16883 S<[ B<->(B<no>)B<discard> ]>
16884 S<[ B<-image_type> I<type> ]>
16885 S<[ B<->(B<no>)B<images> ]>
16886 S<[ B<-accent_images> I<type> | B<-noaccent_images> ]>
16887 S<[ B<-style> I<style> ]>
16888 S<[ B<->(B<no>)B<parbox_images> ]>
16889 S<[ B<->(B<no>)B<math> ]>
16890 S<[ B<->(B<no>)B<math_parsing> ]>
16891 S<[ B<->(B<no>)B<latin> ]>
16892 S<[ B<->(B<no>)B<entities> ]>
16893 S<[ B<->(B<no>)B<local_icons> ]>
16894 S<[ B<->(B<no>)B<scalable_fonts> ]>
16895 S<[ B<->(B<no>)B<images_only> ]>
16896 S<[ B<->(B<no>)B<show_section_numbers> ]>
16897 S<[ B<->(B<no>)B<show_init> ]>
16898 S<[ B<-init_file> I<Perl_file> ]>
16899 S<[ B<-up_url> I<up_URL> ]>
16900 S<[ B<-up_title> I<up_title> ]>
16901 S<[ B<-down_url> I<down_URL> ]>
16902 S<[ B<-down_title> I<down_title> ]>
16903 S<[ B<-prev_url> I<prev_URL> ]>
16904 S<[ B<-prev_title> I<prev_title> ]>
16905 S<[ B<-index> I<index_URL> ]>
16906 S<[ B<-biblio> I<biblio_URL> ]>
16907 S<[ B<-contents> I<toc_URL> ]>
16908 S<[ B<-external_file> I<external_aux_file> ]>
16909 S<[ B<->(B<no>)B<short_index> ]>
16910 S<[ B<->(B<no>)B<unsegment> ]>
16911 S<[ B<->(B<no>)B<debug> ]>
16912 S<[ B<-tmp> I<path> ]>
16913 S<[ B<->(B<no>)B<ldump> ]>
16914 S<[ B<->(B<no>)B<timing> ]>
16915 S<[ B<-verbosity> I<num> ]>
16916 S<[ B<-html_version> I<num> ]>
16917 S<[ B<->(B<no>)B<strict> ]>
16918 I<file.tex> S<[ I<file2.tex> ... ]>
16920 =head1 DESCRIPTION
16922 I<LaTeX2HTML> is a Perl program that translates LaTeX source files into
16923 HTML. For each source file given as an argument the translator will create
16924 a directory containing the corresponding HTML files.
16926 =head1 OPTIONS
16928 Many options can be specified in a true/false manner. This is indicated by
16929 I<(no)>, e.g. to enable passing unknown environments to LaTeX, say "-latex",
16930 to disable the feature say "-nolatex" or "-no_latex" (portability mode).
16932 =over 4
16934 =item B<-help> | B<-h>
16936 Print this online manual and exit.
16938 =item B<-version> | B<-V>
16940 Print the LaTeX2HTML release and version information and exit.
16942 =item B<-split> I<num>
16944 Stop making separate files at this depth (say "-split 0" for one huge HTML
16945 file).
16947 =item B<-link> I<num>
16949 Stop showing child nodes at this depth.
16951 =item B<-toc_depth> I<num>
16953 MISSING_DESCRIPTION
16955 =item B<->(B<no>)B<toc_stars>
16957 MISSING_DESCRIPTION
16959 =item B<->(B<no>)B<short_extn>
16961 If this is set all HTML file will have extension C<.htm> instead of
16962 C<.html>. This is helpful when shipping the document to PC systems.
16964 =item B<-iso_language> I<lang>
16966 MISSING_DESCRIPTION
16968 =item B<->(B<no>)B<validate>
16970 When this is set true, the HTML validator specified in F<l2hconf.pm>
16971 will run.
16973 =item B<->(B<no>)B<latex>
16975 Pass unknown environments to LaTeX. This is the default.
16977 =item B<->(B<no>)B<djgpp>
16979 Specify this switch if you are running DJGPP on DOS and need to avoid
16980 running out of filehandles.
16982 =item B<->(B<no>)B<fork>
16984 Enable/disable forking. The default is reasonable for this platform.
16986 =item B<->(B<no>)B<external_images>
16988 If set, leave the images outside the document.
16990 =item B<->(B<no>)B<ascii_mode>
16992 This is different from B<-noimages>.
16993 If this is set, B<LaTeX2HTML> will show textual tags rather than
16994 images, both in navigation panel and text (Eg. C<[Up]> instead the up
16995 icon).
16996 You could use this feature to create simple text from your
16997 document, eg. with 'Save as... Text' from B<Netscape> or with
16998 B<lynx -dump>.
17000 =item B<->(B<no>)B<lcase_tags>
17002 writes out HTML tag names using lowercase letters, rather than uppercase.
17004 =item B<->(B<no>)B<ps_images>
17006 If set, use links to external postscript images rather than inlined bitmaps.
17008 =item B<-font_size> I<size>
17010 To set the point size of LaTeX-generated GIF files, specify the desired
17011 value (i.e., C<10pt>, C<11pt>, C<12pt>, etc.).
17012 The default is to use the point size of the original LaTeX document.
17013 This value will be magnified by I<$FIGURE_SCALE_FACTOR> and
17014 I<$MATH_SCALE_FACTOR> defined in F<l2hconf.pm>.
17016 =item B<->(B<no>)B<tex_defs>
17018 Enable interpretation of raw TeX commands (default).
17019 Note: There are many variations of C<\def> that B<LaTeX2HTML> cannot process
17020 correctly!
17022 =item B<->(B<no>)B<navigation>
17024 Put a navigation panel at the top of each page (default).
17026 =item B<->(B<no>)B<top_navigation>
17028 Enables navigation links at the top of each page (default).
17030 =item B<->(B<no>)B<buttom_navigation>
17032 Enables navigation links at the buttom of each page.
17034 =item B<->(B<no>)B<auto_navigation>
17036 Put navigation links at the top of each page. If the page exceeds
17037 I<$WORDS_IN_PAGE> number of words then put one at the bottom of the page.
17039 =item B<->(B<no>)B<index_in_navigation>
17041 Put a link to the index page in the navigation panel.
17043 =item B<->(B<no>)B<contents_in_navigation>
17045 Put a link to the table of contents in the navigation panel.
17047 =item B<->(B<no>)B<next_page_in_navigation>
17049 Put a link to the next logical page in the navigation panel.
17051 =item B<->(B<no>)B<previous_page_in_navigation>
17053 Put a link to the previous logical page in the navigation panel.
17055 =item B<->(B<no>)B<footnode>
17057 Puts all footnotes onto a separate HTML page, called F<footnode.html>,
17058 rather than at the bottom of the page where they are referenced.
17060 =item B<->(B<no>)B<numbered_footnotes>
17062 If true, you will get every footnote applied with a subsequent number, else
17063 with a generic hyperlink icon.
17065 =item B<-prefix> I<output_filename_prefix>
17067 Set the output file prefix, prepended to all C<.html>, C<.gif> and C<.pl>
17068 files. See also B<-auto_prefix>.
17070 =item B<->(B<no>)B<auto_prefix>
17072 Set this to automatically insert the equivalent of B<-prefix >C<basename->",
17073 where "basename" is the base name of the file being translated.
17075 =item B<-long_titles> I<num>
17077 MISSING_DESCRIPTION
17079 =item B<->(B<no>)B<custom_titles>
17081 MISSING_DESCRIPTION
17083 =item B<-title>|B<-t> I<top_page_title>
17085 The title (displayed in the browser's title bar) the document shall get.
17087 =item B<->(B<no>)B<rooted>
17089 MISSING_DESCRIPTION
17091 =item B<-rootdir> I<output_directory>
17093 MISSING_DESCRIPTION
17095 =item B<-dir> I<output_directory>
17097 Put the result in this directory instead of parallel to the LaTeX file,
17098 provided the directory exists, or B<-mkdir> is specified.
17100 =item B<-mkdir>
17102 Allow directory specified with B<-dir> to be created if necessary.
17104 =item B<-address> I<author_address> | B<-noaddress>
17106 Supply your own string if you don't like the default
17107 "E<lt>NameE<gt> E<lt>DateE<gt>". B<-noaddress> suppresses the
17108 generation of an address footer.
17110 =item B<->(B<no>)B<subdir>
17112 If set (default), B<LaTeX2HTML> creates (or reuses) another file directory.
17113 When false, the generated HTML files will be placed in the current
17114 directory.
17116 =item B<-info> I<0> | I<1> | I<string>
17118 =item B<-noinfo>
17120 If 0 is specified (or B<-noinfo> is used), do not generate an I<"About this
17121 document..."> section. If 1 is specified (default), the standard info page is
17122 generated. If a custom string is given, it is used as the info page.
17124 =item B<->(B<no>)B<auto_link>
17126 MISSING_DESCRIPTION
17128 =item B<-reuse> I<num> | B<-noreuse>
17130 If false, do not reuse or recycle identical images generated in previous
17131 runs. If the html subdirectory already exists, start the interactive session.
17132 If I<num> is nonzero, do recycle them and switch off the interactive session.
17133 If 1, only recycle images generated from previous runs.
17134 If 2, recycle images from the current and previous runs (default).
17136 =item B<->(B<no>)B<antialias_text>
17138 Use anti-aliasing in the generation of images of typeset material;
17139 e.g. mathematics and text, e.g. in tables and {makeimage} environments.
17141 =item B<->(B<no>)B<antialias>
17143 Use anti-aliasing in the generation of images of figures. This usually
17144 results in "sharper" bitmap images.
17146 =item B<->(B<no>)B<transparent>
17148 If this is set to false then any inlined images generated from "figure"
17149 environments will NOT be transparent.
17151 =item B<->(B<no>)B<white>
17153 This sets the background of generated images to white for anti-aliasing.
17155 =item B<->(B<no>)B<discard>
17157 if true, the PostScript file created for each generated image
17158 is discarded immediately after its image has been rendered and saved in the
17159 required graphics format. This can lead to significant savings in disk-space,
17160 when there are a lot of images, since otherwise these files are not discarded
17161 until the end of all processing.
17163 =item B<-image_type> I<type>
17165 Specify the type of bitmap images to be generated. Depending on your setup,
17166 B<LaTeX2HTML> can generate B<gif> or B<png> images. Note: Gif images have
17167 certain legal restrictions, as their generation involves an algorithm
17168 patented by Unisys.
17170 =item B<->(B<no>)B<images>
17172 If false, B<LaTeX2HTML> will not attempt to produce any inlined images.
17173 The missing images can be generated "off-line" by restarting B<LaTeX2HTML>
17174 with B<-images_only>.
17176 =item B<-accent_images> I<type> | B<-noaccent_images>
17178 MISSING_DESCRIPTION
17180 =item B<-style> I<style>
17182 MISSING_DESCRIPTION
17184 =item B<->(B<no>)B<parbox_images>
17186 MISSING_DESCRIPTION
17188 =item B<->(B<no>)B<math>
17190 By default the special MATH extensions are not used
17191 since they do not conform with the HTML 3.2 standard.
17193 =item B<->(B<no>)B<math_parsing>
17195 MISSING_DESCRIPTION
17197 =item B<->(B<no>)B<latin>
17199 MISSING_DESCRIPTION
17201 =item B<->(B<no>)B<entities>
17203 MISSING_DESCRIPTION
17205 =item B<->(B<no>)B<local_icons>
17207 Set this if you want to copy the navigation icons to each document directory
17208 so that the document directory is self-contained and can be dropped into
17209 another server tree without further actions.
17211 =item B<->(B<no>)B<scalable_fonts>
17213 MISSING_DESCRIPTION
17215 =item B<->(B<no>)B<images_only>
17217 When true, B<LaTeX2HTML> will only try to convert the inlined images in the
17218 file F<images.tex> which should have been generated automatically during
17219 previous runs. This is very useful for correcting "bad LaTeX" in this file.
17221 =item B<->(B<no>)B<show_section_numbers>
17223 When this is set true, the section numbers are shown. The section numbers
17224 should then match those that would have been produced by LaTeX.
17225 The correct section numbers are obtained from the $FILE.aux file generated
17226 by LaTeX.
17227 Hiding the section numbers encourages use of particular sections
17228 as standalone documents. In this case the cross reference to a section
17229 is shown using the default symbol rather than the section number.
17231 =item B<->(B<no>)B<show_init>
17233 MISSING_DESCRIPTION
17235 =item B<-init_file> I<Perl_file>
17237 MISSING_DESCRIPTION
17239 =item B<-up_url> I<up_URL>, B<-up_title> I<up_title>
17241 =item B<-down_url> I<down_URL>, B<-down_title> I<down_title>
17243 =item B<-prev_url> I<prev_URL>, B<-prev_title> I<prev_title>
17245 =item B<-index> I<index_URL>,
17247 =item B<-contents> I<toc_URL>
17249 =item B<-biblio> I<biblio_URL>
17251 If both of the listed two options are set then the "Up" ("Previous" etc.)
17252 button of the navigation panel in the first node/page of a converted
17253 document will point to I<up_URL> etc. I<up_title> should be set
17254 to some text which describes this external link.
17255 Similarly you might use these options to link external documents
17256 to your navigation panel.
17258 =item B<-external_file> I<external_aux_file>
17260 MISSING_DESCRIPTION
17262 =item B<->(B<no>)B<short_index>
17264 If this is set then B<makeidx.perl> will construct codified names
17265 for the text of index references.
17267 =item B<->(B<no>)B<unsegment>
17269 Use this to translate a segmented document as if it were not
17270 segmented.
17272 =item B<->(B<no>)B<debug>
17274 If this is set then intermediate files are left for later inspection and
17275 a lot of diagnostic output is produced. This output may be useful when
17276 searching for problems and/or submitting bug reports to the developers.
17277 Temporary files include F<$$_images.tex> and F<$$_images.log> created during
17278 image conversion. Caution: Intermediate files can be I<enormous>!
17280 =item B<-tmp> I<path>
17282 Path for temporary files. This should be a local, fast filesystem because it is heavily used during image generation. The default is set in F<l2hconf.pm>.
17284 =item B<->(B<no>)B<ldump>
17286 This will cause LaTeX2HTML to produce a LaTeX dump of images.tex which is read
17287 in on subsequent runs and speeds up startup time of LaTeX on the images.tex
17288 translation. This actually consumes additional time on the first run, but pays
17289 off on subsequent runs. The dump file will need about 1 Meg of disk space.
17291 =item B<->(B<no>)B<timing>
17293 MISSING_DESCRIPTION
17295 =item B<-verbosity> I<num>
17297 The amount of message information printed to the screen during processing
17298 by B<LaTeX2HTML> is controlled by this setting.
17299 By increasing this value, more information is displayed.
17300 Here is the type of extra information that is shown at each level:
17302 0 no extra information
17303 1 section types and titles
17304 2 environment
17305 3 command names
17306 4 links, labels and internal sectioning codes
17308 =item B<-html_version> I<list>
17310 Which HTML version should be generated. Currently available are:
17311 C<2.0>, C<3.0>, C<3.2>, C<4.0>. Some additional options that may be
17312 added are: C<math> (parse mathematics), C<i18n> (?),
17313 C<table> (generate tables), C<frame> (generate frames),
17314 C<latin1>...C<latin9> (use ISO-Latin-x encoding),
17315 C<unicode> (generate unicode characters). Separate the options with ',',
17316 e.g. C<4.0,math,frame>.
17318 =item B<->(B<no>)B<strict>
17320 MISSING_DESCRIPTION
17322 =back
17324 =head1 FILES
17326 =over 4
17328 =item F<$LATEX2HTMLPLATDIR/l2hconf.pm>
17330 This file holds the global defaults and configuration settings for
17331 B<LaTeX2HTML>.
17333 =item F<$HOME/.latex2html-init>
17335 =item F<./.latex2html-init>
17337 These files may contain settings that override the global defaults, just
17338 like specifying command line switches.
17340 =back
17342 =head1 ENVIRONMENT
17344 =over 4
17346 =item LATEX2HTMLDIR
17348 Path where LaTeX2HTML library files are found. On this installation
17349 LATEX2HTMLDIR is F</usr/share/latex2html>
17351 =item PERL5LIB
17353 Set by the B<latex2html> program to find perl modules.
17355 =item L2HCONFIG
17357 An alternative configuration filename. The standard configuration file
17358 is F<$LATEX2HTMLPLATDIR/l2hconf.pm>. You may specify a sole filename (searched
17359 for in F<$LATEX2HTMLPLATDIR> (and F<$PERL5LIB>) or a complete path.
17361 =item L2HINIT_NAME
17363 The standard user-specific configuration filename is F<.latex2html-init>.
17364 This environment variable will override this name.
17366 =item HOME
17368 Evaluated if the system does not know about "home" directories (like
17369 DOS, WinXX, OS/2, ...) to determine the path to F<$L2HINIT_NAME>.
17371 =item TEXE_DONT_INCLUDE, TEXE_DO_INCLUDE
17373 Used internally for communication with B<texexpand>.
17375 =item TEXINPUTS
17377 Used to find TeX includes of all sorts.
17379 =back
17381 =head1 PROBLEMS
17383 For information on various problems and remedies see the WWW online
17384 documentation or the documents available in the distribution.
17385 An online bug reporting form and various archives are available at
17386 F<http://www.latex2html.org/>
17388 There is a mailing list for discussing B<LaTeX2HTML>: C<latex2html@tug.org>
17390 =head1 AUTHOR
17392 Nikos Drakos, Computer Based Learning Unit, University of Leeds
17393 E<lt>nikos@cbl.leeds.ac.ukE<gt>. Several people have contributed
17394 suggestions, ideas, solutions, support and encouragement.
17396 The B<pstoimg> script was written by Marek Rouchal
17397 E<lt>marek@saftsack.fs.uni-bayreuth.deE<gt>
17398 as a generalisation of the B<pstogif> utility to allow graphic formats
17399 other than GIF to be created. Various options and enhancements have
17400 been added by Ross Moore.
17401 Some of the code is based upon the pstoppm.ps postscript program
17402 originally written by Phillip Conrad (Perfect Byte, Inc.)
17403 and modified by L. Peter Deutsch (Aladdin Enterprises).
17405 =head1 SEE ALSO
17407 See the WWW online documentation or the F<$LATEX2HTMLDIR/doc/manual.ps>
17408 file for more detailed information and examples.
17410 L<pstoing>, L<texexpand>
17412 =cut