### Version 0.3, April 3, 1997
### extended math-parsing, when $NO_SIMPLE_MATH is set
### Version 0.4, July, August 1997 by Ross Moore
### extended math-parsing, when $NO_SIMPLE_MATH is set
### Version 0.5, many modifications and extensions
### made during 1997 and 1998 by Ross Moore
## Copyright (C) 1995 by Marcus E. Hennecke
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
if ($HTML_OPTIONS =~ /math/) {
do { $DOCTYPE = ''; $STRICT_HTML = 0 }
unless ($NO_SIMPLE_MATH||$NO_MATH_PARSING);
}
#########################
## Support HTML 3.0 math
#### Mathematical Formulas
package main;
sub do_env_math {
local($_) = @_;
local($math_mode, $failed, $labels, $comment,$img_params) = ("inline",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
local($saved) = $_;
($labels, $comment, $_) = &process_math_env($math_mode,$_);
if ($failed) {
$_ = join ('', $comment, $labels
, ($USING_STYLES ? '' : '')
, &process_undefined_environment("tex2html_wrap", $id, $saved)
, ($USING_STYLES ? '' : ''))
} elsif ($NO_SIMPLE_MATH) {
if ($USING_STYLES) {
$_ = join('', $comment, $labels
, '', $_ , "");
} else {
$_ = join('', $comment, $labels, " ", $_ );
}
} else {
$_ = join('', $comment, $labels, "");
}
if (($border||($attributes))&&($HTML_VERSION > 2.1 )) {
&make_table( $border, $attribs, '', '', '', $_ )
} else { $_ }
}
$math_start_rx = "(\\\$|\\\\\\(|\\\\math\\b)(\\begin(($O|$OP)\\d+($C|$CP))tex2html_wrap\\4)?";
$math_end_rx = "(\\end(($O|$OP)\\d+($C|$CP))tex2html_wrap\\7)?(\\\$|\\\\\\)|\\\\endmath\\b)";
sub do_env_tex2html_wrap {
local($_) = @_;
local($math_mode, $failed, $labels, $comment,$img_params) = ("inline",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
$* = 1; s/^\s*|\s*$//g; $*=0;
local($saved) = $_;
# if (s/^\\\(|^\$|^\\math|\\\)$|\$$|\\endmath//g) {}
if (s/^$math_start_rx|${math_end_rx}$//g) {}
elsif (/^\\ensuremath/om) { }
else { $failed = 1 }; # catch non-math environments or commands
($labels, $comment, $_) = &process_math_env($math_mode,$_);
if ($failed) {
$_ = join ('', $comment, $labels
, &process_undefined_environment("tex2html_wrap", $id, $saved));
} elsif ($NO_SIMPLE_MATH) {
# no need for comment/labels if already inside a math-env
if (defined $math_outer) { s/^\s*|\s*$//g }
else { $_ = $comment . $labels ." ".$_; }
} else {
$_ = $comment . $labels . "";
}
if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
&make_table( $border, $attribs, '', '', '', $_ )
} else { $_ }
}
sub do_env_tex2html_wrap_inline {
local($_) = @_;
local($math_mode, $failed, $labels, $comment) = ("inline",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
local($saved) = $_;
# s/(^\s*(\$|\\\()\s*|\s*(\$|\\\))\s*$)//g; # remove the \$ signs or \(..\)
# s/^\\ensuremath(($O|$OP)\d+($C|$CP))(.*)\1/$4/; # remove an ensuremath wrapper
if (s/^$math_start_rx|$math_end_rx$//gs ) {}
elsif (s/^\\ensuremath(($O|$OP)\d+($C|$CP))(.*)\1/$4/){} # remove an ensuremath wrapper
else { $failed = 1 }
s/\\(begin|end)(($O|$OP)\d+($C|$CP))tex2html_wrap\w*\2//g; # remove wrappers
$_ = &translate_environments($_) unless (($NO_SIMPLE_MATH)||($failed));
($labels, $comment, $_) = &process_math_env($math_mode,$_);
if ($failed) {
if ($USING_STYLES) {
$env_id =~ s/\"$/ image\"/;
$env_id = ' CLASS="MATH"' if ($env_id =~ /^\s*$/);
$_ = join ('', $labels, $comment, ""
, &process_undefined_environment("tex2html_wrap_inline", $id, $saved)
, "");
} else {
$_ = join ('', $labels, $comment
, &process_undefined_environment("tex2html_wrap_inline", $id, $saved));
}
} elsif (($NO_SIMPLE_MATH)&&($USING_STYLES)) {
$env_id = ' CLASS="MATH"' if ($env_id =~ /^\s*$/);
$_ = join('', $labels, $comment, "", $_, "");
} elsif ($NO_SIMPLE_MATH) {
$_ = join('', $labels, $comment, $_);
} else {
$_ = join('', $labels, $comment, "");
}
if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
&make_table( $border, $attribs, '', '', '', $_ )
} else { $_ }
}
# Allocate a fixed width for the equation-numbers:
#$seqno = "| \n";
$mvalign = ' VALIGN="MIDDLE"';
sub do_env_equation {
local($_) = @_;
local($math_mode, $failed, $labels, $comment) = ("equation",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
local($saved) = $_;
local($sbig,$ebig,$pre_math,$post_math);
($sbig,$ebig) = ('','')
if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 ));
local($math_start,$math_end)= ($sbig,$ebig);
local($eqno) = ' '; # spacer, when no numbering
local($seqno) = join('',"\n | \n");
$* = 1;
do { # include the equation number, using a
$global{'eqn_number'}++;
$eqno = join('', $EQNO_START
, &simplify(&translate_commands('\theequation'))
, $EQNO_END);
} unless ((s/(\\nonumber|\\notag)//g)||(/\\tag/));
if (s/\\tag(\*)?//){
# AmS-TEX line-number tags.
local($nobrack,$before) = ($1,$`);
$_ = $';
s/next_pair_pr_rx//o;
if ($nobrack) { $eqno = $2 }
else { $eqno = join('',$EQNO_START, $2, $EQNO_END ) }
$_ = $before;
}
$* = 0;
local($halign) = " ALIGN=\"CENTER\"" unless $FLUSH_EQN;
if ($EQN_TAGS =~ /L/) {
# equation number on left
($math_start,$math_end) =
( "\n\n" . $seqno . $eqno
. "\n| $sbig"
, "$ebig | \n ");
$border = $attribs = $env_id = '';
} else {
# equation number on right
($math_start,$math_end) =
("\n\n | "
. "$sbig"
, "$ebig | ". $seqno . $eqno ." \n ");
$border = $attribs = $env_id = '';
}
($labels, $comment, $_) = &process_math_env($math_mode,$_);
# if ($failed) {
#print "\n MATH EQUATION - UNDEF";
# $_ = join ('', "", $labels
# , $comment, $math_start
# , &process_undefined_environment('displaymath', $id, $saved)
# , $math_end, " " );
# } elsif ($NO_SIMPLE_MATH) {
#print "\n MATH EQUATION - NOMATH";
# $_ = join('', "", $labels
# , $comment, $math_start, "\n$_\n"
# , $math_end, " " );
# } else {
#print "\n MATH EQUATION - PLAIN";
# $_ = join('', ""
# , $labels, $comment, $math_start
# , "\n", $math_end );
# }
#print "\n MATH EQUATION ";
# if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
# join('',"\n \n"
# , &make_table( $border, $attribs, '', '', '', $_ )
# , "\n ");
# } else { $_ }
$pre_math = "\n \n";
$post_math = "\n ";
if ($failed) {
$_ = join ('', $comment, $labels, $math_start
, &process_undefined_environment('displaymath', $id, $saved)
, $math_end );
} elsif ($NO_SIMPLE_MATH) {
$_ = join('', $labels, $comment
, $math_start, "\n$_\n", $math_end );
} else {
$pre_math = " ";
$post_math = ' ';
$_ = join('', $labels, $comment, $math_start
, "\n ", $math_end );
}
if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
$pre_math = " \n \n";
$post_math = "\n ";
$_ = &make_table( $border, $attribs, '', '', '', $_ );
} elsif ($HTML_VERSION < 2.2) {
$pre_math = " \n \n";
$post_math = "\n \n";
}
$pre_math . $_ . $post_math
}
sub do_env_displaymath {
local($_) = @_;
local($math_mode, $failed, $labels, $comment) = ("display",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
local($saved) = $_;
local($sbig,$ebig);
($sbig,$ebig) = (' ','')
if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 ));
($labels, $comment, $_) = &process_math_env($math_mode,$_);
if ($failed) {
$_ = join('', $comment, " " , $labels
, &process_undefined_environment("displaymath", $id, $saved )
, ' ' );
} elsif ($NO_SIMPLE_MATH) {
$_ =~ s/ /$&$sbig/sg;
$_ = "$comment\n$labels\n$sbig$_$ebig\n "
} else {
$_ = join('', $comment, "", $labels
, "$sbig\n\n$ebig ");
}
if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
join(''," \n\n"
, &make_table( $border, $attribs, '', '', '', $_ )
, "\n ");
} else { $_ }
}
### Some Common Structures
## Declare math mode and take care of sub- and superscripts. Also make
## sure to treat curly braces right.
sub make_math {
local($math_mode,$math_style,$math_face,$_) = @_;
# Do spacing
s/\\,/;SPMthinsp;/g;
s/\\!/;SPMnegsp;/g;
s/\\:/;SPMsp;/g;
s/\\;/;SPMthicksp;/g;
s/((^|[^\\])(\\\\)*)\\ /$1\\space /g; # convert \ to \space
s/\\limits/\&limits;/g; # preserve the \limits commands
# Find all _ and ^, but not \_ and \^
s/\\_/\\underscore/g;
s/\\^/\\circflex/g;
#RRM: The following code is just plain wrong !!!
# local(@terms) = split(/([_^])/);
# local($math,$i,$subsup,$level);
# # Do the sub- and superscripts
# $math = $terms[$[];
# for ( $i = $[+1; $i <= $#terms; $i+=2 ) {
# $subsup = ( $terms[$i] eq "_" ? "SUB" : "SUP" );
# $_ = $terms[$i+1];
# if ( s/$next_pair_rx// ) {
# $math .= "<$subsup>$2$subsup>$_";
# } else {
# s/^\s*(\w|\\[a-zA-Z]+)//;
# $math .= "<$subsup>$1$subsup>$_";
# };
# };
# $_ = $math;
#RRM: This works much better (from &simple_math_env ).
if ($NO_SIMPLE_MATH) {
s/\&ldots;/.../g;
$_ = &translate_math_commands($math_mode,$math_style,$math_face,0,$_);
# remove redundant tags
s/ \s*<\/I>//go;
s/<\/I>(\s*)/$1/go;
} else {
s/\^$any_next_pair_rx/$2<\/SUP>/go;
s/_$any_next_pair_rx/$2<\/SUB>/go;
s/\^(\\[a-zA-Z]+|.)/$1<\/SUP>/g;
s/_(\\[a-zA-Z]+|.)/$1<\/SUB>/g;
}
s/\\underscore/\\_/g;
s/\\circflex/\\^/g;
s/&limits;//g; # not implemented, except via an image
# Translate all commands inside the math environment
$_ = &translate_commands($_) unless ($NO_SIMPLE_MATH);
if ($NO_SIMPLE_MATH) {
s/{/{/g; s/}/}/g;
s/\s*×\s*/ x<\/TT> /g;
# s/\s*×\s*/ × /g;
s/\s*÷\s*/ ÷ /g;
s/\s*&circ?;\s*/o<\/TT>/g;
s/\s**\s*/ \*<\/TT> /g;
s/\s*&l?dots;\s*/.../g;
s/\s*∣\s*/ | /g;
s/\s*|\s*/\|/g;
s/\s*∥\s*/ || /g;
s/;SPM(thin)?sp;/ /g; s/ / /g; s/&sp;/ /g;
s/;SPMthicksp;/ /g; s/&thicksp;/ /g; s/ / /g;
# &replace_math_constructions($math_mode);
} else {
# Inside \s*!si) {
join('', $_ , "\n \n");
} else {
join('', $_ , "\n ");
}
}
sub do_env_eqnarraystar {
local($_) = @_;
local($math_mode, $failed, $labels, $comment) = ("equation",'','');
$failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
local($attribs, $border);
local($saved) = $_;
local($sbig,$ebig);
($sbig,$ebig) = ('','')
if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 ));
if (($NO_SIMPLE_MATH)||($failed)) {
local($no_eqn_numbers) = 1;
$_ = &do_env_eqnarray($_) unless ($failed);
if ($failed) {
if ($saved =~ s/$htmlborder_rx//o) {
$attribs = $2; $border = (($4)? "$4" : 1)
} elsif ($saved =~ s/$htmlborder_pr_rx//o) {
$attribs = $2; $border = (($4)? "$4" : 1)
}
$_ = join('', $labels
# , &process_undefined_environment("eqnarraystar", $id, $saved));
, &process_undefined_environment("eqnarray*", $id, $saved));
}
} else {
if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
$saved = $_;
($labels, $comment, $_) = &process_math_env($math_mode,$_);
if ($failed) {
$_ = join('', $labels
# , &process_undefined_environment("eqnarraystar", $id, $saved));
, &process_undefined_environment("eqnarray*", $id, $saved));
} else {
$_ = join('', $comment, "$sbig", $labels
, "\n"
, &do_env_array("$O$max_id${C}rcl$O$max_id$C$_")
, "\n$ebig " );
}
}
if (($border||($attribs))&&($HTML_VERSION > 2.1 )) {
$_ = &make_table( $border, $attribs, '', '', '', $_ )
} else { $_ }
}
sub do_math_cmd_nonumber {
$_[$[];
};
### Putting One Thing Above Another
## Over- and Underlining
sub do_math_cmd_overline {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\overline{$over}$supsub") , $after)
} else {"$over$_" }
}
sub do_math_cmd_underline {
local($_) = @_;
local($under) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\underline{$under}$supsub") , $after)
} else { "$under$_" }
}
sub do_math_cmd_overbrace {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\overbrace{$over}$supsub\\,") , $after)
} else { "$over$_" }
}
sub do_math_cmd_underbrace {
local($_) = @_;
local($under) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\underbrace{$under}$supsub\\,") , $after)
} else { "$under$_" }
}
## Accents
sub do_math_cmd_vec {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
# \vec often makes the arrowhead fall outside its box
# fix this by adding small space when at the end
$supsub = "\\," unless ($supsub);
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\vec{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_bar {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\bar{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_dot {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\dot{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_ddot {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\ddot{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_hat {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\hat{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_tilde {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\tilde{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_widehat {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\widehat{$over}$supsub") , $after)
} else { "$over$_" }
}
sub do_math_cmd_widetilde {
local($_) = @_;
local($over) = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($supsub) = &get_supsub;
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\widetilde{$over}$supsub") , $after)
} else { "$over$_" }
}
## Stacking Symbols
sub do_math_cmd_stackrel {
local ($_) = @_;
local($top,$bot);
$top = &get_next_token(1);
$bot = &get_next_token(1);
if ($NO_SIMPLE_MATH) {
local($after) = $_;
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\;\\stackrel{$top}{$bot}\\;") , $after)
} else { "$2$top$_" }
}
# Kill $ref_before in case we're not in math mode.
sub do_math_cmd_atop {
local ($before) = $ref_before;
$before =~ s/^[\s%]*//; $before =~ s/[\s%]*$//;
$ref_before = "";
$failed = 1 if ($NO_MATH_MARKUP);
"$before$_[$[]";
}
sub do_math_cmd_choose {
local ($before) = $ref_before;
$before =~ s/^\s*//; $before =~ s/\s*$//;
$ref_before = "";
$failed = 1 if ($NO_MATH_MARKUP);
"$before$_[$[]";
}
sub do_math_cmd_binom { &do_math_cmd_choose(@_) }
sub do_math_cmd_mbox {
local($_) = @_;
local($cmd,$text,$after)=('mbox','','');
$text = &missing_braces
unless ((s/$next_pair_pr_rx[\s%]*/$text = $2;''/eo)
||(s/$next_pair_rx[\s%]*/$text = $2;''/eo));
# incomplete macro replacement
if ($text =~ /(^|[^\\<])#\d/) { return($_) }
if ($NO_SIMPLE_MATH) {
$after = $_;
if (!($text)||($text =~ /^\s*$/)) { ("\ ", $after) }
elsif (!($text =~
/tex2html_wrap_inline|^(($O|$OP)\d+($C|$CP))?\$|\$(($O|$OP)\d+($C|$CP))\4\$/)) {
$text =~ s/$OP(\d+)$CP/$O$1$C/g;
if ($text =~ /\$/) {
$_ = $text;
$text = &wrap_math_environment;
}
$text = &translate_environments("${O}1$C$text${O}1$C") if $text;
$text = &translate_commands($text) if ($text =~ /\\/);
$text =~ s/ $/;SPMnbsp;/; # preserve trailing spaces
($text, $after)
} else {
( &process_math_in_latex( $mode, $math_style, $slevel
, "\\mbox{$text}") , $after)
}
} else { "$text$_" }
}
sub do_math_cmd_display {
$_[$[];
}
sub do_math_cmd_text {
$_[$[];
}
sub do_math_cmd_script {
$_[$[];
}
sub do_math_cmd_scriptscript {
$_[$[];
}
# This is supposed to put the font back into math italics.
# Since there is no HTML equivalent for reverting
# to math italics we keep track of the open font tags in
# the current context and close them.
# *** POTENTIAL ERROR ****#
# This will produce incorrect results in the exceptional
# case where \mit is followed by another context
# containing font tags of the type we are trying to close
# e.g. {a \bf b \mit c {\bf d} e} will produce
# a b c d e
# i.e. it should move closing tags from the end
sub do_math_cmd_mit {
local($_, @open_font_tags) = @_;
local($next);
for $next (@open_font_tags) {
$next = ($declarations{$next});
s/<\/$next>//;
$_ = join('',"<\/$next>",$_);
}
$_;
}
$ams_aligned_envs_rx = "((\\w*align\\w*|gather\\w*|split|multline|array|cases)(\\*|star)?)";
$space_commands_rx = "(\\\\(q+uad|[,; ]|hs(kip|pace)(($O|$OP)\\d+($C|$CP))[^<]+\\4)|\\s)*";
sub translate_math_commands {
local($mode,$style,$face,$slevel,$_) = @_;
local($pre_text, $labels);
print "\nTranslating math...".($NO_MATH_PARSING?'no parsing':'')."\n$_"
if ($VERBOSITY > 4);
if ($NO_MATH_PARSING) {
s/\\\n/\\ \n/g;
if ($_ =~ /$space_commands_rx\\(text|mbox)\b/) {
$pre_text = $`; $_ = $& . $';
# Do not split if inside any kind of grouping
local($pre_test,$use_all)=($pre_text,'');
while ($pre_test =~ s/(($O|$OP)\d+($C|$CP))(.*)\1/$4/) {};
$use_all = 1 if ($pre_test=~s/($O|$OP)\d+($C|$CP)//);
if (!$use_all) {
while ($pre_test =~ s/\\begin(($O|$OP)\d+($C|$CP))(.*)\\end\1/$4/){};
$use_all = 1 if ($pre_test=~s/\\(begin|end)($O|$OP)\d+($C|$CP)//);
};
if (!$use_all) {
local($gp_cnt) = 0;
$pre_test =~ s/\\left\b/$gp_cnt++;''/eg;
$pre_test =~ s/\\right\b/$gp_cnt--;''/eg;
$use_all = 1 if $gp_cnt;
};
if ($use_all) { $pre_text .= $_ ; $_ = '' };
} else {
$pre_text = $_; $_ = '';
}
($pre_text,$labels) = &extract_labels($pre_text);
local($savedRS) = $/; $/ = ''; $* = 1;
# if ($pre_text =~ m/^((.|\n)*)\\begin\s*(($O|$OP)\d+($C|$CP))$ams_aligned_envs_rx\3/m) {
if ($pre_text =~ m/^()\\begin\s*(($O|$OP)\d+($C|$CP))$ams_aligned_envs_rx\3/m) {
local($env,$star,$orig,$cnt) = ($7,$8,$pre_text.$_,1);
local($this_env,$pre_pre_text, $post_pre_text,$found) = ('', $1, $'.$_ , 1);
$pre_text = $_ = '';
# local($savedRS) = $/; $/ = ''; $*=1;
while ( $cnt && $found ) {
$found = '';
if ($post_pre_text =~ /\\(begin|end)(($O|$OP)\d+($C|$CP))$env$star\2/s)
{ $pre_text .= $`; $found = $1;
$this_env = $&; $post_pre_text = $'; }
if ($found =~ /begin/) {
$cnt++; $pre_text .= $this_env;
} elsif ($found =~ /end/) {
$cnt--; $pre_text .= $this_env if ($cnt > 0) ;
}
}
$* = 0; $/ = $savedRS;
$env .= 'star' if $star;
local($env_cmd) = 'do_env_'.$env;
# parse it further, when possible...
if ((defined &$env_cmd) && !$cnt) {
$_ = $post_pre_text . $_;
$pre_text = join( '', $labels
, &$env_cmd($pre_text)
, (($_)? &translate_math_commands($mode
,$style,$face,$slevel,$_):'')
);
return( $pre_pre_text . $pre_text );
}
# ...else put it back inside a {displaymath} for an image
if ($cnt) { $orig .= $_; $_ = ''; }
local($math_env) = 'displaymath';
if ($outer_math =~ /^subequations/) {
$math_env = $outer_math;
# this branch is experimental, for AMS-aligned environments
} elsif ($outer_math &&($outer_math !~ /^equation|eqnarray|split/)) {
$math_env = $outer_math;
$math_env .= '*' unless ($outer_math =~ /star$|\*/);
}
$pre_text = join('', '\begin{',$math_env,'}'
, $orig ,'\end{',$math_env,'}' );
local($after_undef) = $_;
$orig = &revert_to_raw_tex($orig);
print "\n\nMaking image from: (orig)\n$orig\n" if ($VERBOSITY > 4);
$pre_text = &process_undefined_environment(
$math_env, ++$global{'max_id'}, $orig);
$_ = $after_undef;
} else {
$pre_text = &revert_to_raw_tex($pre_text);
print "\n\nMaking image from: (pre-\\text)\n$pre_text\n"
if ($VERBOSITY > 4);
$pre_text = &process_math_in_latex($mode,$style,$slevel,$pre_text)
if ($pre_text);
}
$* = 0; $/ = $savedRS;
return($labels . $pre_text) unless ($_);
print "\nMore math:\n$_" if ($VERBOSITY > 4);
local($post_text, $this_text, $which_text);
if (/^$space_commands_rx\\(text|mbox)\b(($O|$OP)\d+($C|$CP))/){
local($end_text) = $8; $which_text = $7;
$post_text = $';
$pre_text .= ";SPMnbsp; ;SPMnbsp;" if ($1);
if ($post_text =~ /$end_text/) {
$post_text = $'; $this_text = $`;
if ($which_text =~ /mbox/) {
$this_text = join('',$end_text,$this_text,$end_text);
($this_text) = &do_math_cmd_mbox($this_text);
} else {
$this_text = &translate_environments($this_text);
$this_text = &translate_commands($this_text);
}
$this_text =~ s/ $/;SPMnbsp;/s;
$post_text = &translate_math_commands( $mode
,$style,$face,$slevel,$post_text) if ($post_text);
}
$pre_text = join('', $pre_text, $this_text, $post_text);
return($labels . $pre_text);
}
if ($pre_text) {
$_ = join('', $labels , $pre_text ,
&translate_math_commands($mode,$style,$face,$slevel,$_));
} else {
print "\n\nMaking image from: (all of it)\n$_\n" if ($VERBOSITY > 4);
$_ = join('', $labels , $pre_text ,
&process_math_in_latex($mode,$style,$slevel,$_));
}
return($_);
}
&replace_strange_accents;
for (;;) { # For each opening bracket ...
last unless (/$begin_cmd_rx/o);
local($before, $contents, $br_id, $after, $pattern);
($before, $br_id, $after, $pattern) = ($`, $1, $', $&);
local($end_cmd_rx) = &make_end_cmd_rx($br_id);
if ($after =~ /$end_cmd_rx/) { # ... find the the matching closing one
$NESTING_LEVEL++;
($contents, $after) = ($`, $');
$_ = join("", $before,"$OP$br_id$CP", $contents,"$OP$br_id$CP", $after);
$NESTING_LEVEL--;
}
else {
$pattern = &escape_rx_chars($pattern);
s/$pattern//;
print STDERR "\nCannot find matching bracket for $br_id";
}
}
# &parse_math_toks($mode,$style,$face,$slevel,1,$_);
&process_math_toks($mode,$style,$face,$slevel,1,$_);
}
sub make_math_comment{
local($_) = @_;
local($scomm,$ecomm)=("\$","\$");
return() if (/$image_mark/);
do {
$scomm = "\\begin{$env}\n";
$ecomm = "\n\\end{$env}";
} unless ($env =~/tex2html/);
$_ = &revert_to_raw_tex;
$* = 1; s/^\s+//; s/\s+$//; $* = 0;
$_ = $scomm . $_ . $ecomm;
return() if (length($_) < 12);
$global{'verbatim_counter'}++;
$verbatim{$global{'verbatim_counter'}} = $_;
&write_mydb('verbatim_counter', $global{'verbatim_counter'}, $_ );
join('', $verbatim_mark, '#math' , $global{'verbatim_counter'},'#')
}
sub process_math_env {
local($mode,$_) = @_;
local($labels, $comment);
($_,$labels) = &extract_labels($_); # extract labels
$comment = &make_math_comment($_);
local($max_id) = ++$global{'max_id'};
if ($failed) { return($labels, $comment, $_) };
$_ = &protect_array_envs($_);
if ($BOLD_MATH) {
($labels, $comment
, join('','',&make_math($mode,'','',$_),''))
} else { ($labels, $comment, &make_math($mode,'','',$_)) }
}
sub process_math_toks {
if ($NO_MATH_PARSING) {
local($mode,$style,$face,$slevel,$math_outer,$_) = @_;
if (/(aligned|gathered|alignedat|split)/) {
#print "\n***SPECIAL AMS:\n$_\n";
}
$_ = &process_math_in_latex($mode,$style,$slevel,$_);
return($_);
}
&parse_math_toks(@_);
}
sub parse_math_toks {
local($mode,$style,$face,$slevel,$math_outer,$_) = @_;
local($pre,$keep,$this,$cmd,$tmp);
local($lastclosespace, $joinspace) = (1,1);
$face = "I" unless (($face)||($slevel)); # default text is italiced
$face =~ s/math//;
local($afterint) = 0; # device to detect integral d
print "\$";
print STDERR "\nMATH_IN:$_" if ($VERBOSITY > 4);
while (
/[\s%]*(\\([a-zA-Z]+|.)|$image_mark#[^#]+#|(<#\d*#>)|(<[^>]*>)(#math\d+#)?|\^|\_|&[a-zA-Z]+;|;SPM[a-z]+;|&)/
) {
$lastclosespace = 1; $joinspace=1;
# $keep holds the results from processed tokens
# $pre should be all simple letters and other characters
$pre = $`;
# $_ holds the tokens yet to come
$_ = $';
# $this holds the current token
$this = $1;
if ($4) {
# tags already processed from an earlier cycle
# includes math-comment markers
$this = $4.$5;
$lastclosespace = 0; $joinspace=0;
} elsif ($3) {
# an opening brace
local($br_idm) = $3;
$_ = $br_idm.$_;
if (s/$next_pair_pr_rx/$br_idm=$1; $this=$2;''/eo) {
$this =~ s/^\s*//; $this =~ s/\s*$//;
} else {
s/$br_idm//;
print "\n ** ignoring unmatched brace $br_idm in math **\n";
$this = ''; $br_idm = '';
}
# if there is \atop.. or \over.. then make an image
# Better would be to create a table after establishing
# the minimum number of tokens involved...
# ...but that's getting pretty complicated.
if ($this =~ /\\(atop|over([^a-zA-Z]|withdelims))/) {
print ".";
print STDERR "$1" if ($VERBOSITY > 2);
$this = "{".$this."}";
$this .= &get_supsub;
$this = &process_math_in_latex($mode, $style, $slevel,$this);
$lastclosespace = 0;
} else {
local($extra) = &get_supsub;
# contents of $extra may require an image !!
# revert the brace-pairs
if ($extra =~ /{|}/) {
&mark_string($extra);
$extra =~ s/$O(\d+)$C/$OP$1$CP/g;
}
$this .= $extra; undef $extra;
# otherwise the braces may delimit style-changes...
do{
local(@save_open_tags) = @$open_tags_R;
local($open_tags_R) = [ @save_open_tags ];
local($env_id) = $br_idm;
$this = &parse_math_toks($mode,$style,$face,$slevel,0,$this);
# $this .= &balance_tags();
undef $open_tags_R; undef @save_open_tags;
};
# ...perhaps deliberate, to suppress space.
$lastclosespace = 0; $joinspace=0;
}
} elsif (($2) && $new_command{$2}) {
# macro-replacement required
print "\nReplacing \\$2 " if ($VERBOSITY > 5);
do {
local($cmd,$after) = ($2,$_);
$_ = &substitute_newcmd;
print " with: $_\n" if ($VERBOSITY > 5);
$_ .= $after;
undef $cmd; undef $after;
};
$this = '';
} elsif (($2) && ($2 =~/^latex$/)) { # discard the argument
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/eo)
||(s/$next_pair_rx\s*/$this = $2;''/eo));
$this = '';
} elsif (($2) && ($2 =~/(acute|breve|check|grave)$/)) {
# accented characters, not implemented separately
print ".";
print STDERR "$1" if ($VERBOSITY > 2);
$this .= join('', "{", &get_next_token(1), "}");
$this .= &get_supsub;
$this = &process_math_in_latex($mode, $style, $slevel,$this);
} elsif (($2) && ($2 =~/^end$/)) {
s/^\s*(<[<#]\d+[#>]>)[^<>]*\1//o;
$this = '';
} elsif (($2) && ($2 =~/^begin$/)) {
# embedded environment; e.g. tex2html_wrap
if (s/^\s*<([<#])(\d+)([#>])>(tex2html_(deferred|wrap(\w*)))<\1\2\3>//so) {
$this = '';
} elsif (s/^\s*(<[<#](\d+)[#>]>)($array_env_rx)(\*|star)?\1//so) {
print ".";
print STDERR "$3$4" if ($VERBOSITY > 2);
# make image, including any sup/sub-scripts
local($id,$env,$star) = ($2,$3,$4);
$this = "\\begin".$&;
local ($saved) = $_;
$_ = $';
# find the \end, including nested environments of same type.
$* = 1;
local($cnt, $thisbit, $which) = (1,'','');
while ( /\\(begin|end)(<#\d+#>)($env|$array_env_rx)(\*|star)?\2/s ) {
$thisbit = $` . $&; $_ = $'; $which = $1;
do {
# mark rows/columns in nested arrays
$thisbit =~ s/;SPMamp;/$array_col_mark/g;
$thisbit =~ s/\\(\\|cr(cr)?(\b|$|\d|\W))/$array_row_mark$3/g;
} if ($cnt > 1);
$this .= $thisbit;
if ($which =~ /begin/) {$cnt++} else {$cnt--};
last if (!$cnt);
}
$* = 0;
# $this =~ s/\\cr(cr)?(\b|$|\d|\\|\W)/\\\\$2/g;
local($env_cmd) = "do_env_$env".(($star)? "star" : '');
if ($cnt) {
print "\n *** cannot find end of environment: $this ";
&write_warnings("\n *** failed to find \\end for: $this ");
$this = ''; $_ = $saved;
# } elsif ($env =~ /^tex2html_wrap_(inline)?$/) {
# $this =~
# s/^\\begin(($O|$OP)\d+($C|$CP))$env\1\s*|\\end(($O|$OP)\d+($C|$CP))$env\4\s*$//sg;
# $_ = $this.$_; $this = '';
} elsif ($env =~ /^array/) {
local($extra) = &get_supsub;
if (($in_array)||($extra)||($pre)||($keep)) {
$this .= $extra;
$this = &process_math_in_latex($mode,$style,$slevel,$this);
} else {
$*=1;
$star =~ s/\*/\\\*/o if ($star);
$this =~ s/^\\begin(<#\d+#>)$env$star\1//s;
$this =~ s/\\end(<#\d+#>)$env$star\1\s*$//s;
$*=0;
do {
local($in_array) = 1;
local($_) = $this;
$this = &do_env_array($this);
};
}
} elsif (defined &$env_cmd) {
$star = '' if ($env =~ /star$|\*/);
$star =~ s/\*/\\\*/o if ($star);
$this =~ s/^\\begin(<#\d+#>)$env$star\1//s;
$this =~ s/\\end(<#\d+#>)$env$star\1\s*$//s;
local($contents) = $_;
$this = &$env_cmd($this);
undef $contents;
} else {
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,$this);
};
undef $cnt;
} else {
#RRM: revert brace-processing, else translation loops
s/$OP(\d+)$CP/$O$1$C/g;
$this = '';
do {
$_ = '\begin'.$_; $_ =~ s/^$begin_env_rx//;
local($env, $mpat, $inner_math) = ($5, $&, $mode);
&find_end_env($env,$this,$_);
s/$O(\d+)$C/$OP$1$CP/g;
local($br_id) = ++$global{'max_id'};
$this .= "\\end$O$br_id$C$env$O$br_id$C";
if ($env =~ /$ams_aligned_envs_rx/) {
do {
$NO_MATH_PARSING = 1; # $inner_math = '';
$this = &make_math($mode,$style,$face,$mpat.$this);
$NO_MATH_PARSING = '';
};
} else {
$this = &translate_environments($mpat.$this);
$this = &translate_commands($this) if ($this =~ /\\/);
s/$O(\d+)$C/$OP$1$CP/g;
}
undef $env; undef $mafter; undef $mpat; undef $inner_math;
};
}
} elsif (($2) && ($2 =~ /(\{|\}|\%|\|)/ )) {
$this = $1;
} elsif (($2) && ($2 =~ /\w+/)) {
# macro or math-entity
$cmd = $&;
print ".";
print STDERR "$cmd" if ($VERBOSITY > 2);
local($mtmp, $ctmp, $wtmp) =
("do_math_cmd_$cmd","do_cmd_$cmd", "wrap_cmd_$cmd");
if ($cmd =~/color/) {
do {
local($color_env,$inside_math) = ($color_env,1);
local(@save_open_tags) = @$open_tags_R;
$open_tags_R = [];
($this, $_) = &$ctmp($_);
$this = &parse_math_toks($mode,$style,$face,$slevel,1,$this);
$open_tags_R = [ @save_open_tags ];
undef $color_env; undef $inside_math; undef @save_open_tags;
};
} elsif ($cmd eq 'mathinner') {
$this = &get_next_token();
$this = &parse_math_toks($mode,$style,$face,$slevel,1,$this);
$this = " ".$this." ";
} elsif ($cmd eq 'left') {
#expandable delimiter: make an image
$this = "\\$cmd";
local($blevel, $delim, $lfence, $rfence) = (1,'','','');
$delim = &get_next_token();
$lfence = $this . $delim; $this = '';
while (($blevel)&&(/(\\(left|right))([^a-zA-Z])/)) {
$this .= $`.$1; $_ = $3.$';
if ($2 =~ /left/) { $blevel++ }
else { $blevel-- }
}
$this =~ s/(\\right)$/$rfence=$1;''/e;
local($mfence) = $this;
local($fenced) = $this;
$mfence =~ s/>\\par\\/>\\phantompar\\/g; # else \mathpalette fails
$delim = &get_next_token(); $rfence .= $delim;
if ($blevel) {
print STDERR "\n *** unclosed \\left$delim starting:\n$this$_\n\n";
&write_warnings("\nunclosed \\left$delim found");
}
undef $blevel;
undef $delim;
# make an image of the left-fence
$this = &process_math_in_latex($mode,$style,$slevel
, "$lfence\\vphantom{$mfence}\\right.")
unless ($lfence eq '.');
#parse the math for the contents, as if in an array-env
do { local($in_array) = 1;
$infence = &parse_math_toks($mode,$style,$face,$slevel,1,$fenced);
# and remove any paragraphing that may wrap the math contents.
$infence =~ s/^]*>| ]*>(\s* \s*)?$|\s$//g;
$this .= $infence;
};
# make an image of the right-fence
local($endthis) = "\\left.\\vphantom{$mfence}$rfence";
# include any super/sub scripts, to position them correctly
local($rsub) = &get_supsub;
$endthis .= $rsub;
$this .= &process_math_in_latex($mode,$style,$slevel,$endthis)
unless (($rfence =~ /\.$/) && !$rsub);
$lastclosespace = 0;
undef $endthis; undef $rsub; undef $infence; undef $in_array;
} elsif ($cmd =~ /^brace(vert|[rl][ud])$/) {
$this = $cmd; $this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$this");
} elsif ($cmd =~ /(b|p)(m)?od$/) {
local($pod) = $2;
if ($cmd =~ /p/) {
$this = &get_next_token();
$this = &parse_math_toks($mode,$style,$face,$slevel,1,$this);
$this = "(".(($pod)? "mod " : '')."$this)";
} elsif (/^\s*\w/) {
$this = " mod ";
}else { $this = " mod" }
} elsif ($cmd =~ /^(t|d)?frac$/) {
($this, $_) = &do_math_cmd_frac($_);
} elsif ($cmd =~ /^(cases|matrix)$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $&;''/eo)
||(s/$next_pair_rx\s*/$this = $&;''/eo));
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this");
} elsif ($cmd =~ /^(under|over|side)set$/) {
# from AMS-math packages
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $&;''/eo)
||(s/$next_pair_rx\s*/$this = $&;''/eo));
if ($cmd =~ /side/) {
$this .= &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this .= $&;''/eo)
||(s/$next_pair_rx\s*/$this .= $&;''/eo));
s/^\s*\\([a-zA-Z]+|[_\d\W])/$this .= $&;''/se;
} else {
$this .= &get_next_token();
}
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this");
} elsif ($cmd =~ /^raisebox$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $&;''/eo)
||(s/$next_pair_rx\s*/$this = $&;''/eo));
local($arg, $pat) = &get_next_optional_argument;
$this .= $pat;
($arg, $pat) = &get_next_optional_argument;
$this .= $pat;
$this .= &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this .= $&;''/eo)
||(s/$next_pair_rx\s*/$this .= $&;''/eo));
undef $arg; undef $pat;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this");
} elsif ($cmd =~ /^choose|binom$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $&;''/eo)
||(s/$next_pair_rx\s*/$this = $&;''/eo));
$this .= &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this .= $&;''/eo)
||(s/$next_pair_rx\s*/$this .= $&;''/eo));
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this");
} elsif ($cmd =~ /^$var_sized_ops_rx|$var_limits_rx$/) {
# entities generally come out too small for these
$this = $cmd . &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$this");
$lastclosespace = 0;
if ($cmd =~ /^(o|i+|idots)?int$/) { $afterint++; }
} elsif (defined &$mtmp) {
if ( grep(/\b$cmd\b/, @mathfunctions)
|| grep(/\b$cmd\b/, @limitfunctions)) {
# it's a named function, to be set in upright text.
$this = "$cmd";
local($orig) = $_;
local($supsub) = &get_supsub;
if ($supsub =~ /^\\limits/) {
undef $orig;
# let LaTeX handle the vertical alignment
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd$supsub" );
} elsif (($supsub)&&(grep(/\b$cmd\b/, @limitfunctions))) {
undef $orig;
# vertical alignment is implicit, use LaTeX
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd$supsub" );
} elsif ($supsub) {
# contents of $supsub may require an image !!
# parse the sup/subscripts
$_ = $orig; undef $orig;
} elsif (/^\s*\w/) {
# ...else just put in the name + a space.
$this .= "\ "; undef $orig;
} else {
# ...else just put in the name, no space needed.
undef $orig;
}
if ($pre =~ /[\w\d]$/) { $this = " ".$this }
undef $supsub;
} elsif ($cmd =~ /^(circ)$/) {
if ($_ =~ /^$/) {$this = "\○"} # ...\degrees
else { $this = " \○ " } # ... as a binary relation
} elsif ($cmd =~ /^text$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/eo)
||(s/$next_pair_rx\s*/$this = $2;''/eo));
$this =~ s/$OP/$O/og; $this =~ s/$CP/$C/og;
$this = &translate_environments($this);
$this = &translate_commands($this) if ($this =~ /\\/);
} elsif ($cmd =~ /^h?phantom$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/eo)
||(s/$next_pair_rx\s*/$this = $2;''/eo));
#reduce all control sequences to a single character.
$this =~ s/\\\w+/A/g; $this =~ s/\\./A/g;
#approximate width with hard-spaces.
$this = ";SPMnbsp;" x length($this);
} elsif ($cmd =~ /^${var_sized_ops_rx}$/) {
# entities generally come out too small for these
$this = $cmd . &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$this");
$lastclosespace = 0;
if ($cmd =~ /^o?int$/) { $afterint++; }
} else {
# do what comes naturally ...
($this, $_) = &$mtmp($_); s/^\s+//;
# if not a box and doesn't return a pair, then add it to $_
# the result should be separated off in subsequent cycles.
if (($this)&&(! $_)&&(!$cmd =~ /box/))
{ $_= $this; $this ='' };
}
} elsif (($mathentities{$cmd})||($latexsyms{$cmd})) {
$ent = ($mathentities{$cmd} || $latexsyms{$cmd});
do {
local($cset) = "${CHARSET}_character_map{$ent}";
$cset =~ s/\-/_/go;
local($char); eval "\$char = \$$cset";
do {
$cset = "${CHARSET}_character_map{$cmd}";
$cset =~ s/\-/_/go; eval "\$char = \$$cset";
$ent = $cmd if ($char);
} unless ($char);
$this = ($char ? $char : ''); undef($char);
};
if ($this) {
# do we want the character-code ...
if ($USE_ENTITY_NAMES) {
# ...or the entity ?
$this = ";SPM$ent;";
}
if ($greekentities{$cmd}) {
# italicise greek symbols
$this = "$this";
}
} elsif ($cmd =~ /^(en|l?dots|gt|lt|times|div|mid|vert|parallel|ast)$/) {
# standard entity
$this = &get_supsub;
if ($this) {
$this = &process_math_in_latex($mode,$style,$slevel
,"\\$cmd$this" );
} else {
$this = "\&$cmd;";
}
} elsif ($cmd =~ /^(l|r)brac(k|e)$/) {
$this = $ord_brackets{$1.$2};
} elsif ($cmd =~ /^cdot(s)?$/) {
$this = join(''," \.",(($1)? "\.\." : '')," <\/SUP>");
} elsif ($cmd =~ /^l?dot(s)?$/) {
$this = "\. ".(($1)? "\.\." : '')." ";
} elsif ($cmd =~ /^backslash$/) {
$this = "\\";
} elsif ($mathnomacros{$cmd}) {
# standard entity, no-macro needed
$cmd = $mathnomacros{$cmd};
$this = &get_supsub;
if ($this) {
$this = &process_math_in_latex($mode,$style,$slevel
,"\\textrm{$cmd}$this" );
} else {
$this = "$cmd";
}
} else {
if ($cmd =~ /^int$/) { $afterint++; }
# need an image
$this = &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
# relations, known to need more space
$this = " $this "
if ($cmd =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/);
}
} elsif (defined &$wtmp) {
if ($cmd =~ /^(math(bb|cal|sf|sfsl)|cal|pmb)$/) { # not accessible !!
# make images of these, including any sup/sub-scripts
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/e)
||(s/$next_pair_rx\s*/$this = $2;''/e));
$this = "\{".$this."\}";
# $this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
} elsif (defined &$ctmp) {
# do what comes naturally ...
($this, $_) = &$ctmp($_);
if (($this =~/\\/)||!($_)) {$_= $this; $this ='' };
} else {
# make an image of all of it
# $this = &missing_braces
# unless ((s/$next_pair_pr_rx\s*//o)&&($this = "{$2}"));
# $this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$_" );
$_ = '';
}
} elsif ($cmd =~ /big+[lrm]?$/i ) {
s/\s*(\\(\W|[a-zA-Z]+)|\W)/$this=$1;''/eo;
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
$lastclosespace = 0; $joinspace=0;
} elsif ($cmd =~ /big(\w+)/ ) {
local($tmpname) = $1;
if (($mathentities{$tmpname})||($latexsyms{$tmpname})) {
# big version standard entity
$this = &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
} else {
# need an image
$this = &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
# relations, known to need more space
$this = " $this "
if ($tmpname =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/);
}
} elsif ($cmd =~ /begin$/) {
local ($contents, $before, $br_id, $env, $after, $pattern);
if ( s/^$begin_env_rx//o ) {
local ($contents, $before, $br_id, $env, $after, $senv);
($before, $br_id, $env, $after, $senv) = ($`, $1, $2, $', $&);
} else { print "\n *** badly formed $cmd *** "; }
if (&find_end_env($env,$contents,$after)) {
local($eenv) = "\\end$O$br_id$C";
$this = &translate_environments($senv.$contents.$eenv);
} else { print "\n *** badly formed environment in math ***" }
$_ = $after;
} elsif ($cmd =~ /^not(in)?$/) {
if ($1) { $this = '' }
else { $this = &get_next_token() }
$this = " ".&process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
} elsif ($cmd =~ /(display|text|(script)+)style$/) {
if ($1 =~ /scriptscript/) {
$this = ""; # $slevel = 2; $this = "";
$pre .= "";
$_ .= "";
} elsif ($1 =~ /script/) {
$this = ""; # $slevel = 1; $this = "";
$pre .= "";
$_ .= "";
} elsif ($slevel) {
if ($1 =~ /display/) { $mode = "display" }# ; $slevel = 0 }
elsif ($1 =~ /text/) { $mode = "inline" }# ; $slevel = 0 }
$this = ""; # &process_math_in_latex($mode,$style,0,$_);
$pre .= ""; $_ .= "";
} elsif ($1 =~ /display/) {
$mode = "display"; $this = ''; # $slevel = 0; $this = '';
} elsif ($1 =~ /text/) {
$mode = "inline"; $this = ''; # $slevel = 0; $this = '';
}
} elsif (defined &$ctmp) {
if ($cmd =~ /(bm|boldsymbol|pmb|(text|math)?(rm|tt|bf|it))$/) {
# simulate these with ordinary fonts
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
#RRM beware special symbols, like: \boldsymbol{\omega}
if ($cmd =~ /boldsymbol/ && $this=~/\\/) {
# don't parse any further, just use an image
$this = &process_math_in_latex
($mode,$style,,$slevel,"\\$cmd$this");
$cmd = '';
} else {
$this = &parse_math_toks($mode,$style
,$cmd,$slevel,$math_outer,$this);
}
if ($cmd =~ /tt/) {
$this =~ s/<(\/)?tt>/<$1TT>/g
} elsif ($cmd =~ /bf|bm|boldsymbol/) {
$this =~ s/<(\/)?($cmd|bf)>/<$1B>/g;
} elsif ($cmd =~ /it/) {
$this =~ s/<(\/)?($cmd|it)>/<$1I>/g
} elsif ($cmd =~ /rm/) {
$this =~ s/<(\/)?($cmd|rm)>//g
}
$this =~ s/\s+$//; # remove trailing space
} elsif ($cmd =~ /^text$/) {
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
$this = &translate_environments($this);
$this = &translate_commands($this);
} elsif ($cmd =~ /mathop/) {
do{
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
local($this_cmd) = "<#0#>".$this."<#0#>";
local($cmd_name) = $this;
local($pre_subp) = $_;
local($cmd_supsub) = &get_supsub;
if (($cmd_supsub)&&!($has_limits =~ /^o$/)) {
$this_cmd .= $cmd_supsub;
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd$this_cmd" );
} else {
$_ = $pre_subp;
$this = &parse_math_toks($mode,$style, "mathrm"
,$slevel, $math_outer, $cmd_name );
$this =~ s/<(\/)?rm>//g;
}
}
} elsif ($cmd =~ /^math(op(en)?|ord|bin|rel|punct|close)/io) {
# explicit math-class
local($mtype,$orig,$supsub) = ($1,'');
# get the contents
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
# see if there are sup/sub-scripts
local($orig) = $_;
local($supsub) = &get_supsub;
if (($mtype =~/^op$/i) && ($supsub =~ /^\\limits/)) {
# need an image for the vertical alignment
undef $orig;
do {
$this = "${O}0$P$this${O}0$P";
&make_unique($this);
};
$this = " ". &process_math_in_latex($mode,$style
,$slevel,"\\$cmd$this$supsub" );
} elsif (($mtype =~/^close$/i) && ($supsub)) {
# need an image for the sup/sub placement
undef $orig;
do {
$this = "${O}0$P$this${O}0$P";
&make_unique($this);
};
$this = " ". &process_math_in_latex($mode,$style
,$slevel,"\\$cmd$this$supsub" );
} else {
$_ = $orig; undef $orig;
$this = &parse_math_toks($mode,$style
,'',$slevel,'',$this);
$this =~ s/^\s*|\s*$//go;
$this = " ".$this unless ($mstyle =~ /ord/i);
$this .= " " if (!($supsub)&&($mstyle =~ /bin|rel|punct/i));
}
undef $supsub;
} elsif ($cmd =~ /^operatorname(\*|star|withlimits)?$/) {
do {
local($has_limits);
$has_limits = 1 if ((s/^\*//)||($cmd=~/limits/));
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
local($this_cmd) = "<#0#>".$this."<#0#>";
local($cmd_name) = $this;
local($pre_subp) = $_;
local($cmd_supsub) = &get_supsub;
if (($cmd_supsub)&&($has_limits)) {
$this_cmd .= $cmd_supsub;
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd$this_cmd" );
} else {
$_ = $pre_subp;
$this = &parse_math_toks($mode,$style, "mathrm"
,$slevel, $math_outer, $cmd_name );
$this =~ s/<(\/)?rm>//g;
}
}
} elsif ($cmd =~ /qopname/) {
do{
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
local($this_cmd) = "<#0#>".$this."<#0#>";
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
$this_cmd .= "<#1#>".$this."<#1#>";
local($has_limits) = $this;
$this = &missing_braces
unless ((s/$next_pair_pr_rx\s*/$this = $2;''/oe)
||(s/$next_pair_rx\s*/$this = $2;''/oe));
$this_cmd .= "<#2#>".$this."<#2#>";
local($cmd_name) = $this;
local($pre_subp) = $_;
local($cmd_supsub) = &get_supsub;
if (($cmd_supsub)&&!($has_limits =~ /^o$/)) {
$this_cmd .= $cmd_supsub;
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd$this_cmd" );
} else {
$_ = $pre_subp;
$this = &parse_math_toks($mode,$style, "mathrm"
,$slevel, $math_outer, $cmd_name );
$this =~ s/<(\/)?rm>//g;
}
}
} elsif ($cmd =~ /^(math|pmb|cal$)/io) {
# catches \mathcal \mathsf \mathbb etc. and \cal \pmb
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $2;''/e)
||(s/$next_pair_rx\s*/$this = $2;''/e));
$this = "<#2#>".$this."<#2#>";
# $this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel
, "\\$cmd $this" );
} elsif ($cmd =~ /(\w*)space/) {
$this = "\ ";
if (($1 =~ /h/)&&((s/$next_pair_pr_rx\s*//)
||(s/$next_pair_rx\s*//)))
{ $this = " \ " }
} else {
# do what comes naturally ...
($this, $_) = &$ctmp($_);
if (($this =~/\\/)||!($_)) {$_= $this; $this ='' };
}
} elsif ($newcommand{$cmd}) {
$_ = &replace_new_command($cmd);
} elsif ($cmd =~ /strut$/) { # ignore it
print "\nignoring \\$cmd ";
} elsif ($cmd =~ /^[vh]rule$/) { # ignore it
$this = "$cmd";
do{ local($which,$len,$pxs,%dims);
while (s/^\s*(height|width|depth)/$which=$1;''/e) {
$this .= " ".$&;
s/^\s*(\d+\.?\d*\w*)//; $this .= $&;
($pxs,$len) = &convert_length($1);
$dims{$which} = $pxs;
}
if ($dims{'width'} == 0 || ($dims{'height'}+$dims{'depth'} == 0)) {
print "\nignoring \\$cmd "; $this = '';
} else {
$this = &process_math_in_latex($mode,$style,$slevel,"\\$this");
}
};
} elsif ($cmd =~ /^$arrow_over_ops_rx$/) {
$this = &missing_braces unless (
(s/$next_pair_pr_rx\s*/$this = $&;''/oe)
||(s/$next_pair_rx\s*/$this = $&;''/oe));
$this .= &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel, "\\$cmd$this" );
} elsif ($cmd =~ /^colon$/) {
$this = " : ";
} elsif ($cmd =~ /^notag$/) {
$this = '';
print "\nThis shouldn't happen; at..." .$_ ;
} else {
# Unknown: send it to LaTeX and hope for the best.
&write_warnings("\nUnknown math command: \\$cmd , image needed.");
$this = &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" );
}
} elsif ($this =~ /^\&(\w+)(#(\w+))?;/) {
# math-entity code
$cmd = $3;
print ".";
print STDERR "$cmd" if ($VERBOSITY > 2);
do {
$this = &get_supsub;
$this = &process_math_in_latex($mode,$style,$slevel,"\\$cmd$this" )
} if ($cmd);
$this = " $this "
if ($cmd =~ /$binary_ops_rx|$binary_rels_rx|$arrow_rels_rx/);
} elsif ($this =~ /^\s*((\^)|\_)/) {
# super/sub-script
print "$1";
print STDERR "$2" if ($VERBOSITY > 2);
$slevel++;
local($BP) = (($2) ? "P" : "B"); $tmp = "";
$this = &get_next_token(1);
if ($this =~ /$array_env_rx/) {
$this = &process_math_in_latex($mode,$style,$slevel
,(($BP =~/P/)? '^':'_')."{$this}" );
} else {
$this = &parse_math_toks($mode,$style,$face,$slevel,1,$this);
}
$this =~ s/^\s+//; $this =~ s/\s+$//;
$this = join('', $tmp, $this, "");
$slevel--;
$lastclosespace = 0;
} elsif ($this =~ /^;SPM([a-z]+)/) {
$this = " $this " if ($this =~ /;SPM(gt|lt|amp);/);
} else {
# just append it; e.g. images, etc.
}
$pre =~ s/\s+//g; #remove all spaces...
if ($pre) {
# put space back around numbers
# $pre =~ s/([\d\.,]+)($|\W)/"$1".(($2)? " $2" :'')/eg;
# $pre =~ s/([^\s\.,\(\[\/\w])(\d+)/$1 $2/g;
#...italiced alphabetics, except if sup/subscripts
if ($face eq "I") {
$pre =~ s/([a-zA-Z][a-zA-Z\']*)/<$face>$1<\/$face>/go unless ($slevel);
# ... but not inside <...> tags
$pre =~ s/(<\/?)<$face>([a-zA-Z][a-zA-Z\']*)<\/$face>>/$1$2>/go;
} else {
# but all alphanumerics, with a special style
$pre =~ s/(([\.\,]?\w[\w\']*)+)/<$face>$1<\/$face>/go
}
# but don't split multipliers from multiplicands
$pre =~ s/(\d) $1)([\(\)\/])\s*/$1 $2/g;
# ...and sometimes don't want spaces at the end
$pre =~ s/([\w>\!\)\]\|])\s+$/$1/;
# # ensure a space after last closing bracket, without sub/sub
# $pre =~ s/([\)\]\|])$/$1 / if ($lastclosespace);
$pre =~ s/\s+/ /g;
}
# remove redundant tags
$this =~ s/<\/SU\1>//g;
$this =~ s/<\/SU(P|B)>//g;
# append processed tokens, forbidding some spaces; e.g. "> <".
if ($pre) {
if (( $keep =~/>\s*$/ )&&( $pre =~ /^\s*[<\(\{\[\w]/ )) {
$keep =~ s/\s+$//; $pre =~ s/^\s+//;
}
if (( $keep =~/\w\s*$/ )&&( $pre =~ /^\s*[<\(\{[]/ )) {
$keep =~ s/\s+$//; $pre =~ s/^\s+//;
}
# if (($pre =~/>\s*$/)&&($this =~ /^\s*)) {
# $pre =~ s/\s+$//; $this =~ s/^\s+//;
# }
}
# elsif (($keep =~/>\s*$/)&&($this =~ /^\s*([<\([\w])/)) {
# $keep =~ s/\s+$//; $this =~ s/^\s+//;
# }
print STDERR "\nMATH:${math_outer}:${keep}:${pre}:${this}:" if ($VERBOSITY > 4);
$keep .= $pre . $this;
}
# the leftovers should be all simple characters also.
s/\s*//g;
if ($_) {
# s/([\d\.,]+)($|\W)/"$1".(($2)? " $2" :'')/eg;
# s/([^\s\.,\(\[\/\w])(\d+)/$1 $2/g;
if ($face eq "I") {
s/([a-zA-Z][a-zA-Z\']*)/$1<\/I>/go unless ($slevel);
# ...but not inside <...> tags
s/(<\/?)([a-zA-Z\']+)<\/I>>/$1$2>/go;
} elsif ($face) {
s/(([\.\,]?\w[\w\']*)+)/<$face>$1<\/$face>/go
}
s/(\d+)<\/I>/$1/go unless ($slevel);
s/(\d) $1)([\(\)\/])\s*/$1 $2/g;
# ensure a space after some final characters, but not all
# suppress this by enclosing the whole expression in {}s
# s/([\)\]\|\.,!>\w])$/$1 /; # Why ?
# $_ .= " " if ($math_outer);
s/ +$//; # ignore trailing spaces
} elsif ($math_outer) {
# final space unless ending with or
$keep .=" " unless (($keep =~/SU[BP]>$/)||(!$joinspace));
}
# don't allow this space: "> <"
if (($keep =~/>\s*$/)&&($_ =~ /^\s*)) {
$keep =~ s/\s+$//; $_=~s/^\s+//;
}
print STDERR "\nMATH_OUT:${math_outer}:${keep}$_:" if ($VERBOSITY > 4);
$keep .= $_;
# # italiced superscripts can be too close to some letters... (what a hack!)
# $keep =~ s/([a-zA-Z]<\/I>)\s*/$1 /g unless ($face =~ /it/);
# $keep =~ s/([a-zA-Z\d]<\/it>)\s*/$1 /g if ($face =~ /it/);
# # ...but nested superscripts are OK
# $keep =~ s/([a-zA-Z]<\/(I|it)> <\2>[^<]+<\/\2>)( |\s)+/$1/g;
# $keep =~ s/\s*( )+\s*/ /g;
$keep =~ s/\s(\s)\s*/\1/g;
$keep =~ s/^(\s*[\+\-]) ([\w\d])/$1$2/o; # unary plus/minus, not binary
# $keep =~ s/([\,\:\|])(|\w)/$1 $2/g; # space after punctuation
$keep =~ s/([\,\|])(|\w)/$1 $2/g; # space after punctuation
# recognise an integral's differential; e.g. dx
if (($afterint)&&($keep =~ s/(;SPM(thin|nb)sp;|~)\s*d/$1d/g)) {
$afterint--; $keep =~ s/<\/I>// }
$keep;
}
# the next token is either {...} or \ or an entity.
sub get_next_token {
local($strict) = @_;
local($this,$cmd)=('',"^ or \_ ");
do {
s/$next_token_rx/$this = $&;''/eo;
if ($strict &&(length($this) > 1)&&($this =~ /^\\/)) {
local($tmp) = 'do_cmd_'.$';
if ((defined &$tmp)||($this =~ /^\\(math|text)/)) {
$_ = $this .' '. $_;
$this = &missing_braces();
}
}
} unless (
(s/$next_pair_pr_rx/$this = $&;''/eo)
||(s/$next_pair_rx/$this = $&;''/eo));
s/^$comment_mark\d+//o; $this =~ s/^\s*//o;
if ($this =~ /^(\&|;)$/) { s/^([a-zA-Z]+;(#\w+;)?)/$this.=$1;''/eo; }
elsif ($this eq '') { s/^\s*([&;][a-zA-Z]+;)/$this =$1;''/eo; }
$this;
}
# This extracts sup/sub-scripts that follow immediately.
# It alters $_ in the caller.
# ...this is meant for code to be passed to LaTeX
sub get_supsub {
local($supsub,$supb,$which,$getit) = ('','','');
$supsub = "\\limits" if (s/^[\s%]*(\\limits|\&limits\;)//);
while (s/^[\s%]*(\^|_|\'|\\prime|\\begin(($O|$OP)\d+($C|$CP))(Sb|Sp)\2)/$supb=$1;''/eo ) {
$which .= $supb;
if ($supb =~ /\^|\_/) {
$getit = &get_next_token(1);
$supsub .= join('', $supb,"\{",$getit,"\}")
unless ($getit eq '');
} elsif ($5) {
$supsub .= $1; $which .= (($5 =~ /b/) ? '_' : '^');
local($multisub_type) = $5;
$* = 1;
s/\\end(($O|$OP)\d+($C|$CP))$multisub_type\1/$supsub .= $`.$&;''/e;
$* = 0;
} else { $supsub .= "\{^\\prime\}" }
}
# include dummy sup/sub-scripts to enhance the vertical spacing
# when not a nested sup/subscript
do {
$supsub .= "_{}" unless ($which =~ /\_|\\prime|\'/);
$supsub .= "^{}" unless ($which =~ /\^|\'|\\prime/ );
} unless (($slevel)||(!$which));
$supsub =~ s/^\\limits$//;
$supsub;
}
# These regular expressions help decide the type of a math-entity,
# so that extra white space may be inserted, as desirable or necessary.
#$binary_ops_rx = "(pm|mp|times|plus|minus|div|ast|star|circ|dot|triangle\\w|cap|cup|vee|wedge|bullet|diamond\$|wr\$|oslash|amalg|dagger|lhd|rhd)";
$binary_ops_rx = "(times|plus|minus|div|circ|dot|cap|cup|vee|wedge|wr\$|amalg|lhd|rhd)";
$binary_rels_rx = "(eq|prec|succ|\^ll\$|\^gg\$|subset|supset|\^in\$|\^ni\$|dash|sim|approx|cong|asymp|prop|models|perp|\^mid\$|parallel|bowtie|Join|smile|frown)";
$arrow_rels_rx = "(arrow|harpoon|mapsto|leadsto)";
&ignore_commands( <<_IGNORED_CMDS_);
allowbreak
mathord
mathbin
mathrel
mathop
mathopen
mathclose
mathpunct
mathinner
mathalpha
mathrm
mathbf
mathtt
mathit
mathbb
mathcal
cal
pmb
mathsf
smash
_IGNORED_CMDS_
# Commands which need to be passed, ALONG WITH THEIR ARGUMENTS, to TeX.
&process_commands_inline_in_tex( <<_LATEX_CMDS_);
#mathbb # {}
#mathcal # {}
#mathsf # {}
_LATEX_CMDS_
1;
|