1# more_amsmath.perl
2# by Ross Moore <ross@mpce.mq.edu.au>  1-19-98
3#
4# Extension to LaTeX2HTML to load further features from
5# the AMS packages, using advanced parsing
6# This package requires the `math' extension to be loaded
7# e.g. via switches:
8#
9#	-no_math -html_version 3.2,math
10# OR    -no_math -html_version 4.0,math
11#
12# This extension is loaded automatically from  amstex.perl
13# when the \usepackage{amstex}  or \usepackage{amsmath}
14# commands are used.
15#
16# Change Log:
17# ===========
18
19package main;
20#
21
22if ($HTML_VERSION < 3) {
23    print "\n*** advanced features of the AMS math packages require HTML 3.2 or later ***\n";
24    return(1);
25}
26
27$display_env_rx = join('|', $display_env_rx
28	,'gather','multline','align','split');
29
30sub do_htmlmath_array {
31    local($colspec) = @_;
32    if (defined &do_env_array) {
33	join('', $comment, "<P ALIGN=\"CENTER\">$sbig"
34	    , $labels, "\n<MATH CLASS=\"EQNARRAY\">"
35	    , &do_env_array("$O$max_id${C}$colspec$O$max_id$C$_")
36	    , "</MATH>\n$ebig</P>" )
37    } else {
38	join('', $comment, '<P ALIGN="CENTER">', $labels,
39	    , &process_undefined_environment($env, $id , $_),'</P>')
40    }
41}
42
43
44sub set_math_size {
45    local($mode) = @_;
46    local($ssize,$esize);
47    ($ssize,$esize) = ("<BIG>","</BIG>")
48	if (!($mode =~ /inline/)&&($DISP_SCALE_FACTOR)
49	    &&($DISP_SCALE_FACTOR >= 1.2 ));
50    if ($USING_STYLES) {
51	$ssize .= '<SPAN CLASS="MATH">';
52	$esize = '</SPAN>'.$esize;
53    }
54    ($ssize,$esize)
55}
56
57sub set_math_valign {
58    local($numbering) = @_;
59    if (($numbering)&&(/^\s*\\begin<([<#])(\d+)([#>])>($array_env_rx)/)) {
60    #RRM: align on the middle, if a array-environment follows...
61    #  (since aligning to the top/bottom of a table looks terrible)
62	" VALIGN=\"MIDDLE\""
63    } else {
64    #  ...otherwise align on the baseline, where possible
65	join(''," VALIGN=\"",
66	    ($NETSCAPE_HTML)? "BASELINE" : "MIDDLE","\"");
67    }
68}
69
70sub get_eqn_number {
71    local($outer_num, $scan) = @_;
72    # an explicit \tag overrides \notag , \nonumber or *-variant
73    local($labels,$tag);
74    ($scan,$labels) = &extract_labels($scan); # extract labels
75    $scan =~ s/\n/ /g;
76    if ($scan =~ s/\\tag(\*|star\b)?\s*(($O|$OP)\d+($C|$CP))(.*)\2//) {
77	local($star) = $1; $tag = $5;
78	$tag = &translate_environments($tag) if ($tag =~ /\\begin/);
79	$tag = &translate_commands($tag) if ($tag =~ /\\/);
80	$tag = (($star)? $tag : $EQNO_START.$tag.$EQNO_END );
81    } elsif (($outer_num)&&(!($scan)||!($scan =~ s/\\no(tag|number)//))
82	&&(!($scan =~ /^\s*\\begin(<(<|#)\d+(>|#)>)($outer_math_rx)\b/))
83    ){
84	$global{'eqn_number'}++ ;
85	if ($subequation_level) {
86	    local($sub_tag) =  &get_counter_value('equation');
87	    $tag = join('', $EQNO_START
88		, $eqno_prefix
89		, &falph($sub_tag)
90		, $EQNO_END);
91	} else {
92	    $tag = join('', $EQNO_START
93		, &simplify(&translate_commands('\theequation'))
94		, $EQNO_END);
95	}
96    } else { $tag = ';SPMnbsp;;SPMnbsp;;SPMnbsp;' }
97    if ($labels) {
98	$labels =~ s/$anchor_mark/$tag/o;
99	($labels , $scan);
100    } else { ($tag , $scan) }
101}
102
103$outer_math_rx = "(fl|x|xx)?align(at)?|multline|gather|(sub)?equation";
104
105sub get_mult_eqn_number {
106    local($num_rows,$valign, $scan) = @_;
107    local($align,$tag);
108    $align = " VALIGN=\"$valign\"" if $valign;
109    ($tag,$scan) = &get_eqn_number(1,$scan);
110    $tag = join('', $align, " ROWSPAN=$num_rows", $etag , $tag);
111    ($tag , $scan);
112}
113
114sub start_math_display {
115    join(''
116#	, (($border||($attribs)||!($outer_math))? '': "<P></P>")
117	, ((($doimage)||!($outer_math))? '': "\n<DIV$math_class>")
118	, (($labels)? $labels : '') , $comment
119	, @_ );
120}
121
122sub end_math_display {
123    join('', @_ , ((($doimage)||!($outer_math))? '' :
124	"</DIV>\n<BR CLEAR=\"ALL\">" ));
125}
126
127sub embed_display {
128    # cancel <BIG> tags when alignment inside subequations
129    return( join('', $ebig, @_[0], $sbig) )
130	 if ($outer_math && $subequation_level);
131    # just return contents when alignment inside equation/multline
132    return(@_[0]) if $outer_math;
133
134    # at the outermost level
135    if (($border)||($attribs)) {
136	join('',"<BR>\n<DIV$math_class>\n"
137	    , &make_table( $border, $attribs, '', '', '', @_ )
138	    , "\n<BR CLEAR=\"ALL\">");
139    } else { join('', "<P></P>", @_ , "<P></P>") }
140}
141
142$smdiv_rx = "<(BR|DIV)";
143$spdisplay = (($HTML_VERSION > 3.1)? "<DIV ":"<P "). "ALIGN=\"CENTER\">";
144$epdisplay = (($HTML_VERSION > 3.1)? "</DIV>\n":'')."<BR CLEAR=\"ALL\">\n<P>";
145$mdisp_width = " WIDTH=\"100%\"";
146$smarray = "<TABLE";
147$smarrayB = " CELLPADDING=\"0\"";
148$emarray = "\n</TABLE>";
149$smrow = "\n<TR"; # must be followed by alignment or ">"
150$emrow = "</TR>";
151$emtag = ">";
152$smncell = "\n<TD NOWRAP";
153$smcell = "\n<TD";
154$emcell = "</TD>";
155$mcalign = " ALIGN=\"CENTER\">";
156$mlalign = " ALIGN=\"LEFT\">";
157$mralign = " ALIGN=\"RIGHT\">";
158$mvalign = " VALIGN=\"MIDDLE\"";
159$smlcell = $smncell.$mlalign;
160$smccell = $smncell.$mcalign;
161$smrcell = $smncell.$mralign;
162$mnocell = "\n<TD>";
163$mspace = "\&nbsp;";
164$mdlim = $html_specials{'&'};
165
166$lseqno = "$eqno_class WIDTH=\"10\" ALIGN=\"LEFT\">\n";
167$rseqno = "$eqno_class WIDTH=\"10\" ALIGN=\"RIGHT\">\n";
168
169
170# do these indirectly, so that they only over-ride the existing
171# ones when the right combination of packages is present.
172
173eval "sub do_env_equation { \&process_env_equation(1,\@_); }";
174eval "sub do_env_equationstar { \&process_env_equation(0,\@_); }";
175
176sub do_env_subequations {
177    local($contents) = @_[0];
178    local($prev_eqn_number) = $global{'eqn_number'}++;
179    local($eqno_prefix) = &translate_commands('\theequation');
180    $eqno_prefix =~ s/\s+$//;
181    ++$subequation_level;
182    local($outer_math) = 'subequations' unless $outer_math;
183    $global{'eqn_number'} = 0;
184    $contents = &process_env_equation(1, $contents);
185    --$subequation_level;
186    $global{'eqn_number'} = ++$prev_eqn_number;
187    $contents;
188}
189
190sub process_env_equation {
191    local($numbered, $_) = @_;
192    local($math_mode, $failed, $labels, $comment, $doimage) = ("equation",'','','','');
193    local($attribs, $border);
194    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
195    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
196    local($saved) = &revert_array_envs($_);
197    local($falign) = 'CENTER';
198    local($sbig,$ebig)= &set_math_size($math_mode);
199    $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call
200    ($labels, $comment, $_) = &process_math_env($math_mode,$_);
201    $failed = 0;
202
203    $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
204    local($outer_math) = $env unless ($outer_math);
205
206    if ($USING_STYLES) {
207	$env_id =~ s/(CLASS=\")(\w+)/$1$outer_math/;
208	$env_style{$outer_math} = "" unless ($env_style{$outer_math});
209	$env_id = ' CLASS="'.$outer_math.'"' unless $env_id;
210    }
211
212    if ($failed) {
213	local($this_env) = $outer_math;
214	if (!($this_env =~ s/(star|\*)$/\*/)) { $global{'eqn_number'}++ };
215	$_ = &process_undefined_environment($this_env, $id, $saved);
216	$falign = (($EQN_TAGS =~ /L/)? 'LEFT' : 'RIGHT') if $numbered;
217	local($fsdisplay,$fedisplay) = ($spdisplay,$epdisplay);
218	if (!($fsdisplay =~ s/(ALIGN\s*=\s*\")[^\"]*\"/$1$falign\"/)) {
219	    $fsdisplay .= "<DIV$env_id ALIGN=\"$falign\">";
220	    $fedisplay = '</DIV>'.$epdisplay;
221	}
222	$_ = join('', $fsdisplay, $labels, $comment, $_, $fedisplay);
223
224    } elsif ($NO_SIMPLE_MATH) {
225#    if ($NO_SIMPLE_MATH) {
226	$failed = 0;
227	s/$htmlimage_rx/$doimage = $&;''/eo ; # force an image
228	s/$htmlimage_pr_rx/$doimage .= $&;''/eo ; # force an image
229	local($valign) = &set_math_valign();
230	local($sarray, $srow, $scell, $calign, $ecell, $erow, $earray);
231
232#	local($env_id) = $env_id;
233#	if ($USING_STYLES) {
234#	    $env_id =~ s/(CLASS=\")(\w+)/$1$outer_math/;
235#	    $env_style{$env} = "" unless ($env_style{$env});
236#	}
237
238	($sarray, $erow, $earray, $sempty, $calign) = (
239	    $smarray.$env_id.$smarrayB.$mdisp_width.$mcalign
240	    , $emrow , $emarray, $emcell.$mnocell, $mcalign );
241	$env_id = '';
242
243	local($return) = &start_math_display ( $sarray );
244
245	local($eqno, $inner_numbered);
246	($eqno, $_) = &get_eqn_number($numbered,$_);
247	local($valign) = &set_math_valign($eqno);
248
249	$_ = &protect_array_envs($_);
250	if ($_ =~ /\s*\\begin\s*$O\d+$C\s*align/) {
251	    # no equation numbering --- handled by the inner-alignment
252	    $inner_numbered = 1;
253	    ($srow, $scell, $ecell) = (
254		$smrow.$valign.$emtag, $smncell , $emcell);
255	    $return .= $srow . $scell;
256	} elsif ($EQN_TAGS =~ /L/) {
257	    # equation number on left
258	    ($srow, $scell, $ecell) = (
259#		$smrow.$valign.$emtag.$smcell.$mcalign, $smncell , $emcell);
260		$smrow.$valign.$emtag.$smcell.$lseqno, $smncell , $emcell);
261	    $return .= $srow . $eqno . $ecell . $scell;
262	} else {
263	    # equation number on right
264	    ($srow, $scell, $ecell) = (
265		$smrow.$valign.$emtag , $smncell , $emcell);
266	    $return .= $srow . $scell ;
267	}
268
269	if (s/\\shove(righ|lef)t//) {
270	    local($whichway) = $1;
271	    $return .= (($1 =~/lef/)? $mlalign : $mralign );
272	    if (($doimage)||($failed)) {
273		$_ = &process_math_in_latex("indisplay",'',''
274		    , $doimage.$_ ) unless ($_ eq '');
275	    } else {
276		$_ = &make_math('display','','',$_) unless ($_ eq '')
277	    }
278	    if (!($_ eq '')) {
279	        $return .= join(''
280		    , (($whichway =~ /lef/)? $mspace.$mspace : '')
281		    , ((/^$smarray/)? $_ : $sbig.$_.$ebig )
282		    , (($whichway =~ /lef/)? '' : $mspace.$mspace )
283		    , $ecell , $erow);
284	    } else { $return .= join('', $mspace , $ecell, $erow); }
285	} else {
286	    $thismath = $_;
287	    $thismath =~ s/(^\s*|\s*$)//gm;
288	    if (($doimage)||($failed)) {
289	        $thismath = &process_math_in_latex("indisplay",'',''
290		    , $doimage.$thismath ) unless ($thismath eq '' );
291	    } else {
292		if ($thismath =~ /$subAMS_array_env_rx/) {
293		    $outer_math =~ s/(equation)(star)?$/$1star/;
294		    $thismath = &make_math($outer_math,'','', $thismath);
295		} else {
296		    $thismath = &make_math('display','','', $thismath)
297			unless ( $thismath eq '' );
298		}
299	    }
300	    if ($thismath ne '') {
301	        $return .= join('', $calign
302		    , (($thismath =~ /^$smarray/)? $thismath
303			: $sbig . $thismath . $ebig )
304		    , $ecell);
305	    } else {
306		$return .= join('', $sempty, "\&nbsp;", $ecell);
307	    }
308	}
309#	$return .= $smncell.$mcalign.$eqno.$ecell
310	$return .= $smncell.$rseqno.$eqno.$ecell
311	    unless (($EQN_TAGS =~ /L/)||$inner_numbered); # eqn-num on right
312	$return .= $erow;
313
314        $_ = &end_math_display($return , $earray );
315    } else {
316        $_ = &do_htmlmath_array('c');
317    }
318
319    undef $outer_math unless ($subequation_level);
320    &embed_display($_);
321}
322
323
324### Multiline formulas
325
326
327sub do_env_multline {
328    &process_env_multline(1,@_);
329}
330sub do_env_multlinestar {
331    &process_env_multline(0,@_);
332}
333
334sub process_env_multline {
335    local($numbered, $_) = @_;
336    local($math_mode, $failed, $labels, $comment, $doimage) = ("equation",'','','','');
337    local($attribs, $border);
338    local($outer_math) = $env unless ($outer_math);
339    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
340    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
341    local($saved) = $_;
342    local($sbig,$ebig)= &set_math_size($math_mode);
343    $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call
344    ($labels, $comment, $_) = &process_math_env($math_mode,$_);
345
346    local($falign) = 'CENTER';
347    $failed = (/$htmlimage_rx|$htmlimage_pr_rx/) unless ($outer_math); # force an image
348    local($outer_math) = $env unless ($outer_math);
349
350    if ($failed) {
351	$_ = &process_undefined_environment(
352		'multline'.(($numbered) ? '':"*"), $id, $saved);
353	$falign = (($EQN_TAGS =~ /L/)? 'LEFT' : 'RIGHT') if $numbered;
354	local($fsdisplay,$fedisplay) = ($spdisplay,$epdisplay);
355	if (!($fsdisplay =~ s/(ALIGN\s*=\s*\")[^\"]*\"/$1$falign\"/)) {
356	    $fsdisplay .= "<DIV ALIGN=\"$falign\">";
357	    $fedisplay = '</DIV>'.$epdisplay;
358	}
359	$_ = join('', $fsdisplay, $labels, $comment, $_, $fedisplay);
360
361    } elsif ($NO_SIMPLE_MATH) {
362	$failed = 0;
363	s/$htmlimage_rx/$doimage = $&;''/eo ; # force an image
364	s/$htmlimage_pr_rx/$doimage .= $&;''/eo ; # force an image
365	local($valign) = &set_math_valign();
366	local($sarray, $srow, $scell, $calign, $ecell, $erow, $earray);
367
368	local($env_id) = $env_id;
369	if ($USING_STYLES) {
370	    $env_style{$env} = "" unless ($env_style{$env});
371	}
372	($sarray, $erow, $earray, $sempty, $calign) = (
373	    $smarray.$env_id.$smarrayB.$mdisp_width.$mcalign
374	    , $emrow , $emarray, $emcell.$mnocell, $mlalign );
375	$env_id = '';
376
377	local($return) = &start_math_display ( $sarray );
378
379	local($eqno);
380	($eqno, $_) = &get_eqn_number($numbered,$_);
381	local($valign) = &set_math_valign($eqno);
382
383	$_ = &protect_array_envs($_);
384
385	if ($EQN_TAGS =~ /L/) {
386	    # equation number on left
387	    ($srow, $scell, $ecell) = (
388#		$smrow.$valign.$emtag.$smcell.$mcalign , $smncell , $emcell);
389		$smrow.$valign.$emtag.$smcell.$lseqno , $smncell , $emcell);
390	    $return .= $srow . $eqno . $ecell . $scell;
391	} else { # equation number on right
392	    ($srow, $scell, $ecell) = (
393		$smrow.$valign.$emtag , $smncell, $emcell);
394	    $return .= $srow . $scell ;
395	}
396
397	local(@rows,$thismath);
398	s/\\\\[ \t]*(\*|\[[^\]]*])/\\\\/g; # remove forced line-heights
399	@rows = split(/\\\\/);
400	$#rows-- if ( $rows[$#rows] =~ /^\s*$/ );
401	local($row_cnt);
402	foreach (@rows) { # displaymath
403	    if ($row_cnt) {
404		$eqno = '' if ($EQN_TAGS =~ /L/);
405		$calign = $mcalign;
406		$calign = $mralign if ($row_cnt == $#rows );
407		$return .= $erow . $srow . $scell ;
408	    }
409	    $row_cnt++;
410
411	    if (s/\\shove(righ|lef)t//) {
412		local($whichway) = $1;
413		$return .= (($1 =~/lef/)? $mlalign : $mralign );
414		if (($doimage)||($failed)) {
415		    $_ = &process_math_in_latex("indisplay",'',''
416		        , $doimage.$_ ) unless ($_ eq '');
417		} else {
418		    $_ = &make_math('display','','',$_) unless ($_ eq '')
419		}
420		if (!($_ eq '')) {
421		    $return .= join(''
422			, (($whichway =~ /lef/)? $mspace.$mspace : '')
423			, ((/^$smarray/)? $_ : $sbig.$_.$ebig )
424			, (($whichway =~ /lef/)? '' : $mspace.$mspace )
425			, $ecell , $erow);
426		} else { $return .= join('', $mspace , $ecell , $erow); }
427		next;
428	    }
429
430	    # columns to be set using \displaystyle
431	    $thismath = $_;
432	    $thismath =~ s/(^\s*|\s*$)//gm;
433	    if (($doimage)||($failed)) {
434	        $thismath = &process_math_in_latex("indisplay",'',''
435		    , $doimage.$thismath ) unless ($thismath eq '' );
436	    } else {
437	        $thismath = &make_math('displaymath','',''
438		    , $thismath) unless ( $thismath eq '' );
439	    }
440	    if ($thismath ne '') {
441	        $return .= join('', $calign
442		    , (($row_cnt == 1)? $mspace.$mspace : '')
443		    , (($thismath=~/^$smarray/)? $thismath
444			    : $sbig.$thismath.$ebig )
445		    , (($row_cnt == 1+$#rows )?  $mspace.$mspace : '')
446		    , $ecell);
447	    } else {
448		$return .= join('', $sempty, "\&nbsp;", $ecell);
449	    }
450	}
451
452#	$return .= $smncell.$mcalign.$eqno.$ecell
453	$return .= $smncell.$rseqno.$eqno.$ecell
454		unless ($EQN_TAGS =~ /L/); # eqn-num on right
455	$return .= $erow;
456
457	$_ = &end_math_display($return , $earray );
458    } else {
459	$_ = &do_htmlmath_array('c');
460    }
461    undef $outer_math unless ($subequation_level);
462    &embed_display($_);
463}
464
465
466sub process_intertext {
467    local($eq_nums, $_) = @_;
468    local($text,$post);
469    s/\\intertext//o; $_ = $';
470    local($pre) = $`; $pre =~ s/(^\s*|\s*$)//go;
471    local($span) = (/$mdlim/) + $eq_nums + 1;
472    $text = &missing_braces unless (
473	(s/$next_pair_pr_rx/$text = $2;''/e)
474	||(s/$next_pair_rx/$text = $2;''/e));
475    $post = $_; $post =~ s/(^\s*|\s*$)//go;
476    $text = &translate_commands(&translate_environments($text))
477	if ($text =~ /\\/);
478    $text = join('', $smrow, $emtag
479	, (($span > 1) ? $smcell." COLSPAN=$span".$mlalign : $smlcell)
480	, "<BR>", $text, "<P><BR>", $emcell, $emrow);
481    ($text, $pre . $post );
482}
483
484sub do_env_align {
485    local($_) = @_;
486    local($math_mode, $attribs, $border) = ("equation",'','');
487    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
488    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
489    $_ = &process_env_align(1,"align",'','',$_);
490    &embed_display($_);
491}
492
493sub do_env_alignstar {
494    local($_) = @_;
495    local($math_mode, $attribs, $border) = ("equation",'','');
496    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
497    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
498    $_ = &process_env_align(0,"align*",'','',$_);
499    &embed_display($_);
500}
501
502sub do_env_alignat {
503    local($_) = @_;
504    local($aligns);
505    $aligns = &missing_braces unless (
506	(s/$next_pair_pr_rx/$aligns = $2;''/e)
507	||(s/$next_pair_rx/$aligns = $2;''/e ));
508    local($math_mode, $attribs, $border) = ("equation",'','');
509    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
510    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
511    $_ = &process_env_align(1,"alignat",$aligns,'',$_);
512    &embed_display($_);
513}
514
515sub do_env_alignatstar {
516    local($_) = @_;
517    local($aligns);
518    $aligns = &missing_braces unless (
519	(s/$next_pair_pr_rx/$aligns = $2;''/e)
520	||(s/$next_pair_rx/$aligns = $2;''/e ));
521    local($math_mode, $attribs, $border) = ("equation",'','');
522    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
523    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
524    $_ = &process_env_align(0,"alignat*",$aligns,'',$_);
525    &embed_display($_);
526}
527
528sub do_env_xalignat {
529    local($_) = @_;
530    local($aligns);
531    $aligns = &missing_braces unless (
532	(s/$next_pair_pr_rx/$aligns = $2;''/e)
533	||(s/$next_pair_rx/$aligns = $2;''/e ));
534    local($math_mode, $attribs, $border) = ("equation",'','');
535    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
536    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
537    $_ = &process_env_align(1,"xalignat",$aligns,'',$_);
538    &embed_display($_);
539}
540
541sub do_env_xalignatstar {
542    local($_) = @_;
543    local($aligns);
544    $aligns = &missing_braces unless (
545	(s/$next_pair_pr_rx/$aligns = $2;''/e)
546	||(s/$next_pair_rx/$aligns = $2;''/e ));
547    local($math_mode, $attribs, $border) = ("equation",'','');
548    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
549    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
550    $_ = &process_env_align(0,"xalignat*",$aligns,'',$_);
551    &embed_display($_);
552}
553
554sub do_env_xxalignat {
555    local($_) = @_;
556    local($aligns);
557    $aligns = &missing_braces unless (
558	(s/$next_pair_pr_rx/$aligns = $2;''/e)
559	||(s/$next_pair_rx/$aligns = $2;''/e ));
560    local($math_mode, $attribs, $border) = ("equation",'','');
561    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
562    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
563    $_ = &process_env_align(1,"xxalignat",$aligns,'',$_);
564    &embed_display($_);
565}
566
567sub do_env_xxalignatstar {
568    local($_) = @_;
569    local($aligns);
570    $aligns = &missing_braces unless (
571	(s/$next_pair_pr_rx/$aligns = $2;''/e)
572	||(s/$next_pair_rx/$aligns = $2;''/e ));
573    local($math_mode, $attribs, $border) = ("equation",'','');
574    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
575    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
576    $_ = &process_env_align(0,"xxalignat*",$aligns,'',$_);
577    &embed_display($_);
578}
579
580sub do_env_flalign {
581    local($_) = @_;
582    local($math_mode, $attribs, $border) = ("equation",'','');
583    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
584    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
585    $_ = &process_env_align(1,"flalign",'','',$_);
586    &embed_display($_);
587}
588
589sub do_env_flalignstar {
590    local($_) = @_;
591    local($math_mode, $attribs, $border) = ("equation",'','');
592    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
593    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
594    $_ = &process_env_align(0,"flalign*",'','',$_);
595    &embed_display($_);
596}
597
598sub do_env_gather {
599    local($_) = @_;
600    local($math_mode, $attribs, $border) = ("equation",'','');
601    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
602    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
603    $_ = &process_env_align(1,"gather",'','c',$_);
604    &embed_display($_);
605}
606
607sub do_env_gatherstar {
608    local($_) = @_;
609    local($math_mode, $attribs, $border) = ("equation",'','');
610    if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
611    elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) }
612    $_ = &process_env_align(0,"gather*",'','c',$_);
613    &embed_display($_);
614}
615
616sub process_env_align{
617    # parameters
618    #   $numbered :  0 = *-version, no implicit equation-numbering
619    #   $outer-math : outer-most environment
620    #   $num_aligns : expected number of alignment pairs per row
621    #   $align_spec : alignment of rows without any `&'s
622    #   $_  :   the row/column data
623    #
624    # if $num_aligns is empty, count the number of cells delimiters (`&`)
625    # per row --- align columns alternating right-/left-
626    #
627    # use the $align_spec only when there is just a single column
628    #
629    local($numbered, $outer_math, $num_aligns, $align_spec, $_) = @_;
630    local($failed, $labels, $comment, $def_align) = ('','','','');
631    local($saved)= $_;
632    local($falign)= 'CENTER';
633    $saved = join('',"\\begin\{$env\}$num_aligns"
634		, $_, "\\end\{$env\}\n") if ($outer_math);
635    $num_aligns = 2*$num_aligns - 1 if ($num_aligns);
636    if ($align_spec =~ /(l|r)/) {
637	$def_align = (($1 eq 'l')? $smlcell : $smrcell ) }
638    elsif ($align_spec eq 'c') { $def_align = $smccell }
639#    elsif (!$num_aligns) { $def_align = $smlcell }
640    elsif (!$num_aligns) { $def_align = $smccell }
641
642    local($sbig,$ebig)= &set_math_size($math_mode);
643    $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call
644    ($labels, $comment, $_) = &process_math_env($math_mode,$_)
645	unless ($outer_math);
646
647    $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image
648    if ($failed) {
649	local($this_env) = ($outer_math ? $outer_math : $env );
650	if ($saved =~ s/^\s*\\begin((($O|$OP)\d+($C|$CP|))|\{)\Q$this_env\E(\2|\})//){
651	    $saved =~ s/\\end((($O|$OP)\d+($C|$CP))|\{)\Q$this_env\E(\2|\})\s*$//s;
652	}
653	$_ = &process_undefined_environment($this_env,$id,$saved);
654
655	$falign = (($EQN_TAGS =~ /L/)? 'LEFT' : 'RIGHT') if $numbered;
656	local($fsdisplay,$fedisplay) = ($spdisplay,$epdisplay);
657	if (!($fsdisplay =~ s/(ALIGN\s*=\s*\")[^\"]*\"/$1$falign\"/)) {
658	    $fsdisplay .= "<DIV ALIGN=\"$falign\">";
659	    $fedisplay = '</DIV>'.$epdisplay;
660	}
661	$_ = join('', $fsdisplay, $labels, $comment, $_, $fedisplay);
662
663    } elsif ($NO_SIMPLE_MATH) {
664	$failed = 0;
665	s/$htmlimage_rx/$doimage = $&;''/eo ; # force images of parts
666	s/$htmlimage_pr_rx/$doimage .= $&;''/eo ; # force an image
667
668	local($env_id) = $env_id;
669	if ($USING_STYLES) {
670	    $env_id =~ s/(CLASS=\")(\w+)/$1$outer_math/;
671	    $env_style{$env} = "" unless ($env_style{$env});
672	}
673	local($sarray, $erow, $earray, $sempty, $calign) = (
674	    $smarray.$env_id.$smarrayB.$mdisp_width.$mcalign, $emrow
675	    , $emarray, $mnocell.$mspace, $mcalign );
676	$env_id = '';
677
678	local($valign, $scell, $eqno) = ($mvalign,'','');
679	local($srow, $ecell, $slcell, $srcell) = (
680	    $smrow.$valign.$emtag , $emcell
681	    , $smncell.$mlalign, $smncell.$mralign );
682
683	local($return) = &start_math_display ( $sarray );
684
685	# revert all protection, before protecting alignment in sub-envs
686	$_ = &revert_array_envs($_);
687	$_ = &protect_array_envs($_);
688
689	if ($EQN_TAGS =~ /L/) {
690	    # equation number on left
691	    ($srow, $scell, $ecell) = ( $smrow.$valign.$emtag.$smcell
692		, $smncell , $emcell);
693	} else {
694	    # equation number on right
695	    ($srow, $scell, $ecell) = (
696		$smrow.$valign.$emtag , $smncell, $emcell );
697	}
698
699	local($xcols) = '0';
700
701	local(@rows, @cols, $eqno, $thismath);
702	s/\\\\[ \t]*(\*|\[[^\]]*])/\\\\/g; # remove forced line-heights
703	@rows = split(/\\\\/);
704	$#rows-- if ( $rows[$#rows] =~ /^\s*$/ );
705	foreach (@rows) { # displaymath
706	    next if (/^\s*$/); # ignore last row, if empty
707
708	    if (/\\intertext/) {
709		local($extra_row);
710		#der -- David Rourke
711		#there is an equation-number cell, even if empty
712		#($extra_row,$_) = &process_intertext($numbered,$_);
713		($extra_row,$_) = &process_intertext(1,$_);
714		$return .= $extra_row;
715	    }
716	    ($eqno, $_) = &get_eqn_number($numbered,$_);
717	    $valign = &set_math_valign($eqno);
718
719	    if ($EQN_TAGS =~ /L/) {
720#		$return .= $srow.$mcalign.$eqno.$ecell
721		$return .= $srow.$lseqno.$eqno.$ecell
722	    } else { $return .= $srow }
723
724	    local($scell) = $srcell; # so 1st cell is right-aligned...
725
726	    local($xcols) = $num_aligns - (/$mdlim/g);
727	    if ($num_aligns) {
728		while ($xcols > 0) { $_ .= $mdlim; $xcols--; }
729		if ($xcols < 0) {
730		    local($orig_code) = &revert_to_raw_tex($_);
731		    &write_warnings("\ntoo many cols in alignment:\n\t$orig_code");
732		    print "\ntoo many columns in alignment:\n$orig_code\n";
733		}
734	    # ... unless there is no explicit alignment
735	    } elsif ($xcols == 0) { $scell = $def_align }
736
737	    if (s/\\shove(righ|lef)t//) {
738		local($whichway) = $1;
739		$return .= (($1 =~/lef/)? $slcell : $srcell );
740		if (($doimage)||($failed)) {
741		    $_ = &process_math_in_latex("indisplay",'',''
742			, $doimage.$_ ) unless ($_ eq '');
743		} else {
744		    $_ = &revert_array_envs($_);
745		    $_ = &make_math('display','','',$_) unless ($_ eq '')
746		}
747		if (!($_ eq '')) {
748		    $return .= join(''
749			, (($whichway =~ /lef/)? $mspace.$mspace : '')
750			, ((/^$smarray/)? $_ : $sbig.$_.$ebig )
751			, (($whichway =~ /lef/)? '' : $mspace.$mspace )
752			, $ecell);
753		} else { $return .= join('', $mspace , $ecell); }
754
755#		$return .= $smncell.$mcalign.$eqno.$ecell
756		$return .= $smncell.$rseqno.$eqno.$ecell
757		    unless ($EQN_TAGS =~ /L/); # eqn-num on right
758		$return .= $erow;
759		next;
760	    }
761
762	    # columns to be set using \displaystyle
763	    @cols = split(/$mdlim/o);
764	    local($col_cnt);
765	    foreach (@cols) { # set in displaymath
766		# alternating right/left aligned
767		$scell =  (($scell eq $slcell)? $srcell : $slcell) if ($col_cnt);
768		$thismath = $_; $col_cnt++;
769		$thismath =~ s/(^\s*|\s*$)//gm;
770		if (($doimage)||($failed)) {
771		    $thismath = &process_math_in_latex("indisplay",'',''
772	 		, $doimage.$thismath ) unless ($thismath eq '' );
773		} elsif ($thismath ne '') {
774		    $thismath = &revert_array_envs($thismath);
775		    $thismath = &make_math('display','','',$thismath);
776		}
777		if ($thismath ne '') {
778		    $return .= join('', $scell
779                        , (($thismath=~/^$smarray/)? $thismath
780			    : $sbig.$thismath.$ebig )
781			, $ecell);
782		} else { $return .= $sempty.$ecell; }
783	    }
784
785#	    $return .= $smncell.$mcalign.$eqno.$ecell
786	    $return .= $smncell.$rseqno.$eqno.$ecell
787		unless ($EQN_TAGS =~ /L/); # eqn-num on right
788	    $return .= $erow;
789	}
790	$_ = &end_math_display($return , $earray );
791    } else {
792	$_ = &do_htmlmath_array('');
793    }
794    $_;
795}
796
797sub do_env_aligned {
798    local($_) = @_;
799    local($saved) = join(''
800	, "\\begin\{aligned\}"
801	, &revert_array_envs($_)
802	, "\\end\{aligned\}\n"
803	);
804    local($inner_math) = 'aligned';
805    &process_undefined_environment(
806	'displaymath' , ++$global{'max_id'}, $saved);
807}
808sub do_env_alignedat {
809    local($_) = @_;
810    $_ = &revert_array_envs($_);
811    local($saved) = join(''
812	, "\\begin\{alignedat\}"
813	, &revert_array_envs($_)
814	, "\\end\{alignedat\}\n"
815	);
816    local($inner_math) = 'alignedat';
817    &process_undefined_environment(
818	'displaymath' , ++$global{'max_id'}, $saved);
819}
820sub do_env_gathered {
821    local($_) = @_;
822    $_ = &revert_array_envs($_);
823    local($saved) = join(''
824	, "\\begin\{gathered\}\n"
825	, &revert_array_envs($_)
826	, "\\end\{gathered\}\n"
827	);
828    local($inner_math) = 'gathered';
829    &process_undefined_environment(
830	'displaymath' , ++$global{'max_id'}, $saved);
831}
832sub do_env_cases {
833    local($_) = @_;
834    $_ = &revert_array_envs($_);
835    local($saved) = join(''
836	,"\\begin\{cases\}\n"
837	, &revert_array_envs($_)
838	, "\\end\{cases\}\n"
839	);
840    local($inner_math) = 'cases';
841    &process_undefined_environment(
842	'displaymath' , ++$global{'max_id'}, $saved);
843}
844
845sub do_env_split {
846    local($_) = @_;
847    local($failed, $labels, $comment, $doimage) = ('','');
848    local($saved) = join('',"\\begin\{split\}\n", $_, "\\end\{split\}\n");
849    local($sbig,$ebig)= &set_math_size($math_mode);
850    $failed = 1 if ($NO_SIMPLE_MATH); # simplifies the next call
851
852    local($falign) = 'CENTER';
853    $failed = (/$htmlimage_rx|$htmlimage_pr_rx/) unless ($outer_math); # force an image
854    local($outer_math) = $env unless ($outer_math);
855
856    if ($failed) {
857	$_ = &process_undefined_environment(
858		$outer_math.(($numbered) ? '':"*"), $id, $saved);
859	$falign = (($EQN_TAGS =~ /L/)? 'LEFT' : 'RIGHT') if $numbered;
860	local($fsdisplay,$fedisplay) = ($spdisplay,$epdisplay);
861	if (!($fsdisplay =~ s/(ALIGN\s*=\s*\")[^\"]*\"/$1$falign\"/)) {
862	    $fsdisplay .= "<DIV ALIGN=\"$falign\">";
863	    $fedisplay = '</DIV>'.$epdisplay;
864	}
865	$_ = join('', $fsdisplay, $labels, $comment, $_, $fedisplay);
866
867    } elsif ($NO_SIMPLE_MATH) {
868	$failed = 0;
869	local($outer_math) = 0; #  not an "outer" environment
870
871	s/$htmlimage_rx/$doimage = $&;''/eo ; # forces images of cells
872	s/$htmlimage_pr_rx/$doimage .= $&;''/eo ; # force an image
873	local($valign) = &set_math_valign();
874	local($sarray, $srow, $scell, $calign, $ecell, $erow, $earray);
875
876	local($env_id) = $env_id;
877	if ($USING_STYLES) {
878	    $env_style{$env} = "" unless ($env_style{$env});
879	}
880	($sarray, $erow, $earray, $sempty, $calign) = (
881	    $smarray.$env_id.$smarrayB.$emtag, $emrow
882	    , $emarray, $mnocell.$mspace, $mcalign );
883	$env_id = '';
884
885	($srow, $scell, $ecell, $slcell, $srcell) = (
886	    $smrow.$valign.$emtag , $smncell, $emcell
887	    , $smcell.$mralign, $smncell.$mlalign );
888
889	local($return) = &start_math_display ( $sarray );
890
891	$_ = &protect_array_envs($_);
892
893	local(@rows,$eqno,$thismath);
894	s/\\\\[ \t]*(\*|\[[^\]]*])/\\\\/g; # remove forced line-heights
895	@rows = split(/\\\\/);
896	$#rows-- if ( $rows[$#rows] =~ /^\s*$/ );
897	foreach (@rows) { # displaymath
898	    next if (/^\s*$/); # ignore last row, if empty
899
900	    if (s/\\shove(righ|lef)t//) {
901		local($whichway) = $1;
902	        $return .= (($1 =~/lef/)? $mlalign : $mralign );
903		if (($doimage)||($failed)) {
904		    $_ = &process_math_in_latex("indisplay",'',''
905		        , $doimage.$_ ) unless ($_ eq '');
906		} else {
907		    $_ = &make_math('display','','',$_) unless ($_ eq '')
908		}
909		if (!($_ eq '')) {
910		    $return .= join(''
911			, (($whichway =~ /lef/)? $mspace.$mspace : '')
912			, ((/^$smarray/)? $_ : $sbig.$_.$ebig )
913			, (($whichway =~ /lef/)? '' : $mspace.$mspace )
914			, $ecell , $erow);
915		} else { $return .= join('', $mspace , $ecell, $erow); }
916		next;
917	    } else {
918		$return .= $srow;
919	    }
920
921	    # columns to be set using \displaystyle
922	    @cols = split(/$mdlim/o);
923	    # left column, set using \displaystyle
924	    $thismath = shift(@cols);
925	    $thismath =~ s/(^\s*|\s*$)//gm;
926	    if (($doimage)||($failed)) {
927	        $thismath = &process_math_in_latex("indisplay",'',''
928		    , $doimage.$thismath ) unless ($thismath eq '' );
929	    } else {
930	        $thismath = &make_math('display','',''
931		    , $thismath) unless ( $thismath eq '' );
932	    }
933	    if (!($thismath eq '')) {
934	        $return .= join('', $slcell
935                        , (($thismath=~/^$smarray/)? $thismath
936			    : $sbig.$thismath.$ebig )
937			, $ecell);
938	    } else { $return .= $sempty.$ecell; }
939
940	    # right column, set using \displaystyle
941	    $thismath = shift(@cols);
942	    $thismath =~ s/(^\s*|\s*$)//gm;
943	    if (($doimage)||($failed)) {
944		$thismath = &process_math_in_latex("indisplay",'',''
945		    , $doimage.$thismath ) unless ($thismath eq '' );
946	    } else {
947		$thismath = &make_math('display','',''
948		    , $thismath) unless ( $thismath eq '' );
949	    }
950	    if (!($thismath eq '')) {
951		$return .= join('', $srcell
952		    , (($thismath=~/^$smarray/)? $thismath
953			: $sbig.$thismath.$ebig )
954		    , $ecell);
955	    } else { $return .= $sempty . $ecell}
956
957	    $return .= $erow;
958	}
959	$_ = &end_math_display($return , $earray );
960    } else {
961	$_ = &do_htmlmath_array('rl');
962    }
963    $_;
964}
965
9661;                              # This must be the last line
967
968
969
970
971
972
973
974
975
976
977
978
979