1## 2## File: webtex.perl by Ross Moore <ross@mpce.mq.edu.au> 3## 4################################################################# 5## 6## work done at the Geometry Center, University of Minnesota 7## commenced during a visit to: 8## 9## The National Science Foundation, 10## Science and Technology Research Center for the 11## Computation and Visualization of Geometric Structures 12## funded by NSF/DMS89-20161 13## 14################################################################# 15 16package main; 17# 18 19# configuration variable defaults 20 21$WEBEQ_OLD = 1 unless $WEBEQ_OLD; # default until new version is available 22$WEBEQ_MML_ONLY = '' unless $WEBEQ_MML_ONLY; 23$WEBEQ_APP_ONLY = '' unless $WEBEQ_APP_ONLY; 24$WEBEQ_IMG_ONLY = '' unless $WEBEQ_IMG_ONLY; 25$WEBEQ_APPMML = 1 unless ($WEBEQ_APPMML); 26$WEBEQ_NOIMG = '' unless ($WEBEQ_NOIMG); 27 28 29# Package options 30 31sub do_webtex_old { $WEBEQ_OLD = 1; } 32sub do_webtex_new { $WEBEQ_OLD = ''; } 33 34sub do_webtex_mmlonly { $WEBEQ_MML_ONLY = 1; 35 $WEBEQ_IMG_ONLY = $WEBEQ_APP_ONLY = ''; } 36sub do_webtex_apponly { $WEBEQ_APP_ONLY = 1; 37 $WEBEQ_MML_ONLY = $WEBEQ_IMG_ONLY = ''; } 38sub do_webtex_imgonly { $WEBEQ_IMG_ONLY = 1; 39 $WEBEQ_MML_ONLY = $WEBEQ_APP_ONLY = ''; } 40sub do_webtex_mmlapp { $WEBEQ_APPMML = 0; $WEBEQ_IMG_ONLY = ''; } 41sub do_webtex_appmml { $WEBEQ_APPMML = 1; $WEBEQ_IMG_ONLY = ''; } 42sub do_webtex_noimg { $WEBEQ_NOIMG = 1; $WEBEQ_IMG_ONLY = ''; } 43 44 45sub do_webtex_white { $WEBEQ_BKG = 'ffffff'; } 46 47sub do_webtex_text { $WEBEQ_MIME = ' TYPE="text/mathml"'; } 48sub do_webtex_application { $WEBEQ_MIME = ' TYPE="application/mathml"'; } 49 50## Mathematics environments 51 52 53# 54# Inline math, $...$ 55# 56sub do_env_tex2html_wrap_inline { 57 local($_) = @_; 58 local($math_mode, $failed, $labels, $comment) = ("inline",'',''); 59 $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image 60 local($attribs, $border, $web_failed, $alt_math); 61 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } 62 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } 63 local($saved) = $_; 64 s/(^\s*(\$|\\\()\s*|\s*(\$|\\\))\s*$)//g; # remove the \$ signs or \(..\) 65 66 ($labels, $comment, $alt_math) = &process_math_env($math_mode,$_); 67 $comment =~ s/^\n//; # remove the leading \n 68 ($web_failed, $_) = &convert_to_webtex('inline',$saved,$alt_math); 69 if ($failed) { 70 $_ = join ('', $labels, $comment 71 , &process_undefined_environment("tex2html_wrap_inline", $id, $saved)); 72 } else { $_ = join('', $labels, $comment, $_); } 73 if ($border||($attribs)) { 74 &make_table( $border, $attribs, '', '', '', $_ ) 75 } else { $_ } 76} 77 78 79 80sub do_env_displaymath { 81 local($_) = @_; 82 local($math_mode, $failed, $labels, $comment) = ("display",'',''); 83 $failed = (/$htmlimage_rx|$htmlimage_pr_rx/); # force an image 84 local($attribs, $border); 85 if (s/$htmlborder_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } 86 elsif (s/$htmlborder_pr_rx//o) { $attribs = $2; $border = (($4)? "$4" : 1) } 87 local($saved) = $_; 88 local($halign) = $math_class unless $FLUSH_EQN; 89 local($sbig,$ebig,$web_failed); 90 ($sbig,$ebig) = ('<BIG>','</BIG>') 91 if (($DISP_SCALE_FACTOR)&&($DISP_SCALE_FACTOR >= 1.2 )); 92 93 ($labels, $comment, $alt_math) = &process_math_env($math_mode,$_); 94 ($web_failed, $_) = &convert_to_webtex('display',$saved,$alt_math); 95 96 if ($failed) { 97 $_ = &process_undefined_environment("displaymath", $id, $saved); 98 s/^[ \t]*\n?/\n/; s/\n?[ \t]*$/\n/; 99 $_ = (($comment.$labels)? "$comment$labels\n":''). $_; 100 } else { 101 s/^[ \t]*\n?/\n/; s/\n?[ \t]*$/\n/; 102 $_ = (($comment.$labels)? "$comment$labels\n":'').$sbig.$_.$ebig; 103 } 104 if ($border||($attribs)) { 105 join('',"<BR>\n<DIV$math_class>\n" 106 , &make_table( $border, $attribs, '', '', '', $_ ) 107 , "</DIV>\n<BR CLEAR=\"ALL\">"); 108 } else { 109 join('',"<BR><P></P>\n<DIV$math_class>",$_ 110 ,"</DIV><BR CLEAR=\"ALL\">\n<P></P>"); 111 } 112} 113 114 115sub convert_to_webtex { 116 local($mode,$orig,$no_applet) = @_; 117 118 print "\nWebTeX:$mode:". ($WEBEQ_NOIMG ? 'no' : 'with') 119 . ' images' . ($WEBEQ_IMG_ONLY ? ' only' : '') . "\n$_\n" 120 if ($VERBOSITY > 1); 121 if($WEBEQ_IMG_ONLY) { return (1,$no_applet) }; 122 123 local($savedRS, $failed, $env_id, $_) = ($/,'','',$orig); 124 $/=''; 125 if ($mode =~ /inline/) { 126 if (/^\s*\\\(/) { $failed = 1 } 127 else { 128 $_ = &revert_to_raw_tex($_); 129 $_ =~ s/^\s*\$?/\$/sm; 130 $_ =~ s/\$?$/\$/sm; 131 $env_id .= $WEBEQ_INL if $USING_STYLES; 132 } 133 } elsif ($mode =~ /display/) { 134 if (/^\s*\$\$/) { $failed = 1 } 135 else { 136 $_ = &revert_to_raw_tex($_); 137 $_ =~ s/^\s*(\\\[|\$\$)?/\\\[/sm; 138 $_ =~ s/(\$\$|\\\])?\s*$/\\\]/sm; 139 $env_id .= $WEBEQ_DIS if $USING_STYLES; 140 } 141 } else { 142 print " *** Unknown WebTeX mode, no applet ***"; 143 $/ = $savedRS; 144 return (0,$no_applet) 145 } 146 $/ = $savedRS; 147 return (0,$no_applet) if $failed; 148 149 ($failed,$_) = &check_only_webtex($_); 150 return (0,$no_applet) if $failed; 151 152 local($webeq_abbrev); 153 SWITCH: { 154 if ($WEBEQ_IMG_ONLY) { $webeq_abbrev = ''; last SWITCH; }; 155 if ($WEBEQ_MML_ONLY) { $webeq_abbrev = 'MML'; last SWITCH; }; 156 if ($WEBEQ_APP_ONLY) { $webeq_abbrev = 'APP'; last SWITCH; }; 157 if ($WEBEQ_APPMML) { $webeq_abbrev = 'APPMML'; last SWITCH; } 158 else { $webeq_abbrev = 'MMLAPP'; last SWITCH; } 159 }; 160 $webeq_abbrev .= (($WEBEQ_NOIMG || $WEBEQ_MML_ONLY) ? ':' : 'IMG:' ); 161 162 local($uucontents) = &encode(&addto_encoding('webeq'.$mode.$webeq_abbrev,$_)); 163# local($cached) = $WEBEQ_CACHE{$uucontents}; 164 local($cached) = $cached_env_image{$uucontents}; 165 if ($cached) { 166 $_ = $cached; 167 } else { 168 $verbatim{++$global{'verbatim_counter'}} = $_; 169 local($verb_math) = join("",$verbatim_mark 170 , 'verbatim',$global{'verbatim_counter'},'#'); 171 172 # don't bother making an image, use LaTeX2HTML's one 173 $WEBEQ_IMG = $WEBEQ_NONE; 174 175 ++$WEBEQ_CTR; 176 local($WEBEQ_CMD); 177 local($WEBEQ_PRE) = "wbq${WEBEQ_CTR}" 178 . (($WEBEQ_OLD &&(!$WEBEQ_IMG eq $WEBEQ_NONE))? 'a':''); 179 local($wbq_src) = $WEBEQ_PRE.'.src'; 180 local($out_app) = $WEBEQ_PRE.'.app'; 181 local($out_tag) = $WEBEQ_PRE.'.tag'; 182 local($out_jpg) = $WEBEQ_PRE.'1.jpg'; 183 local($out_png) = $WEBEQ_PRE.'1.png'; 184 local($out_mml) = $WEBEQ_PRE.'.mml'; 185 local($out_err) = $WEBEQ_PRE.'.err'; 186 local($mml_tag, $app_tag, $ewebeq) = ('','','</NOEMBED>'); 187 188# local($WEBEQ_IMG) = (($IMAGE_TYPE =~ /png/) ? $WEBEQ_PNG : $WEBEQ_JPG); 189# local($out_img) = (($IMAGE_TYPE =~ /png/) ? $out_png : $out_jpg); 190 191 192 open (SRC , ">$wbq_src"); 193 print SRC $_; 194 close SRC; 195 196 local($eapplet) = '</applet>'; 197 local($snoembed) = "<NOEMBED>\n"; 198 local($enoembed) = '</NOEMBED>'; 199 local($width,$height,$align); 200 201 if (!$WEBEQ_APP_ONLY) { 202 $WEBEQ_CMD = $WEBEQ.$WEBEQ_OPTS.$WEBEQ_MML.$WEBEQ_PARSER.$WEBEQ_IMG 203 ." -errors $out_err -o $out_mml $wbq_src\n"; 204 print "\n$WEBEQ_CMD" if $DEBUG; 205 if (system $WEBEQ_CMD) { 206 &webeq_failed($out_mml); $out_mml = ''; 207 } else { 208 ($width,$height,$align) = 209 &cleanup_mml_attribs($out_mml,$mode,$no_applet); 210 $mml_tag = join('', '<EMBED SRC="', $out_mml, '"' 211 , $WEBEQ_MIME , "\n " 212 , ($height ? " HEIGHT=\"$height\"" : '') 213 , ($width ? " WIDTH=\"$width\"" : '') 214 , ' ALIGN="'.($align ? $align : 'MIDDLE').'"' 215 , ">\n</EMBED>\n"); 216 } 217 print "\nMATHML:\n$mml_tag\n" if ($DEBUG ||($VERBOSITY>1)); 218 }; 219 220 221 if (!$WEBEQ_MML_ONLY) { 222 $WEBEQ_CMD = $WEBEQ.$WEBEQ_OPTS.$WEBEQ_APP.$WEBEQ_IMG.$WEBEQ_PARSER 223 ." -imgtype none -errors $out_err -o $out_tag $wbq_src\n"; 224 print "\n$WEBEQ_CMD" if $DEBUG; 225 if (system $WEBEQ_CMD) { 226 $_ = $no_applet; 227 &webeq_failed($out_tag); $out_tag = ''; 228 } else { 229 open(TAG, "<$out_tag"); 230 $app_tag = join('',<TAG>); 231 close(TAG); 232 # replace webeq fall-back image by LaTeX2HTML's own, or none at all 233# $app_tag =~ s/<img[^>]*>/($WEBEQ_NOIMG ? '' : $no_applet)/e; 234# $app_tag =~ s|(\n?</applet>)\s*|($WEBEQ_NOIMG ? '' : $no_applet).$1|e; 235 if ($mode =~ /display/) { 236 # remove initial space, line-ends and HTML tags 237 $app_tag =~ s/^\s*(<P><CENTER>)?//s; 238 $app_tag =~ s|(</CENTER><P>)?\s*$||s; 239 } 240 241 # cleanup blank lines 242 $app_tag =~ s/\n[ \t]*\n/\n/sg; 243 244 local($code); 245 $app_tag =~ s/(<param[^"\n]*name=eq value=")([^"]*)(">)/ 246 $code = $2; 247 $code =~ s|[<>"&]|'&'.$html_special_entities{$&}.';'|eg; 248 $verbatim{++$global{'verbatim_counter'}} = $code; 249 join("", $1, $verbatim_mark 250 , 'rawhtml', $global{'verbatim_counter'},'#',$3)/e; 251 } 252 } 253 254 SWITCH: { 255 if ($WEBEQ_MML_ONLY) { 256 return (0,$no_applet) unless $mml_tag; 257 $_ = $mml_tag . $snoembed . $enoembed; 258 last SWITCH } 259 260 if ($WEBEQ_APP_ONLY) { 261 return (0,$no_applet) unless $app_tag; 262 $_ = $app_tag; 263 last SWITCH } 264 265 if ($WEBEQ_APPMML) { 266 $_ = $app_tag; 267 $_ =~ s/(\Q$eapplet\E)\s*$/$mml_tag$snoembed$enoembed$1/; 268 last SWITCH; 269 } else { 270 $_ = join('', $mml_tag 271 , $snoembed, $app_tag , $enoembed ); 272 last SWITCH; 273 } 274 } 275 276 if (($WEBEQ_IMG eq $WEBEQ_NONE)&&(!$WEBEQ_NOIMG)) { 277 # insert the fall-back material 278 $_ =~ s/((\s*($eapplet|$enoembed))+)\s*$/$no_applet$1/; 279 } elsif ($WEBEQ_NOIMG) { 280 $_ =~ s/$snoembed\s*$enoembed//g; 281 } 282 283 if ($HTML_VERSION >= 4.0) { 284 # use <OBJECT> tag, not the deprecated <APPLET> tag 285 $_ =~ s/^\s*<(APPLET|EMBED)/<OBJECT$env_id/igs; 286# $_ =~ s/<(APPLET|EMBED)/<OBJECT$env_id/igs; 287 $_ =~ s/<\/(APPLET|(NO)?EMBED)>\s*$/<\/OBJECT>/igs; 288 $_ =~ s/<\/(OBJECT|EMBED)>\s*<NOEMBED>//g; 289 $_ =~ s/ SRC=/ DATA=/gi; 290 $_ =~ s/ NAME=/ ID=/gi; 291 $_ =~ s/ PLUGINURL=/ CLASSID=/gi; 292 $_ =~ s/ PLUGINSPAGE=/ CODEBASE=/gi; 293 print "\nOBJECT:$_\n" if ($DEBUG||($VERBOSITY > 1)); 294 } 295 296 297# $WEBEQ_CACHE{$uucontents} = $_; 298 $cached_env_image{$uucontents} = $_ unless $WEBEQ_IMG_ONLY; 299 300 } # end of if($cached) { ... } else { 301 302 ($failed,$_); 303} 304 305# check that the only macro-names are those known to WebTeX 306sub check_only_webtex { 307 local($webtex) = @_; 308# $webtex =~ s/\'/\\prime /g; # coerce ' --> \prime 309 (0,$webtex); 310} 311 312sub webeq_failed { 313 local($err_str) = "\n*** WebEQ failed to make image @_[0] ***"; 314 print $err_str."\n" if ($DEBUG || ($VERBOSITY > 1)); 315 &write_warnings($err_str); 316} 317 318# early versions of webeq started with <P><CENTER> tags and their ends 319# remove these, if they exist. 320sub cleanup_mml_attribs { 321 local($mml_file,$mode,$_) = @_; 322 local($width,$height,$align); 323 open (MML, "<$mml_file"); 324 local($mml_code) = join('',<MML>); 325 close MML; 326 327 local($savedRS) = $/; $/=''; 328 $mml_code =~ s/^\s*<P><CENTER>\n?//s; 329 $mml_code =~ s/\s*<applet code="[^"]*" width=(\d+) height=(\d+) align=(\w+)>\s*/ 330 $width=$1;$height=$2;$align=$3;''/e; 331 $mml_code =~ s/<param[^>\n]*>?\n//g; 332 $mml_code =~ s|(\n\">\s*</applet>\s*)?\s*</CENTER><P>\s*||s; 333 $mml_code =~ s|\n\">\s*</applet>\s*||s; 334 $mml_code =~ s/\&($WEBEQ_mml_name_rx);/$WEBEQ_mml_name{$1}/eg; 335 $mml_code =~ s/\&($WEBEQ_mml_punct_rx);/$WEBEQ_mml_punct{$1}/eg; 336 # catch superscripted primes --- put them into the preceding tag 337 $mml_code =~ s|<(msup>)\s*<([^>]*>)([^<>]*)</\2\s*<mo>\′</mo>\s*</\1|<$2$3\'</$2|sg; 338 open (MML, ">$mml_file"); 339 print MML $mml_code; 340 close MML; 341 342 if ($mode =~/display/) { 343 # webweq has already used a scaling for \displaystyle 344 if ($width) { $width *= $WEBEQ_TCX_REL_SCALE; $width = int($width + 0.5) } 345 if ($height) { $height *= $WEBEQ_TCX_REL_SCALE; $height = int($height + 0.5) } 346 } elsif ($no_applet) { 347 local($find_width,$find_height,$val) = ($width,$height); 348 &replace_image_marks; 349 if (s/(WIDTH|HEIGHT)\s*=\s*"?(\d+)"?/$val=$2; 350 if ($1 eq 'WIDTH') { $find_width = $val if ($val > $find_width) } 351 else { $find_height = $val if ($val > $find_height) };''/esg ) { 352 if (/ALIGN="MIDDLE"/) { $height *= 2; } 353 else { $height *= $WEBEQ_TCX_INL_SCALE; } 354 $width *= $WEBEQ_TCX_INL_SCALE; 355 if ($find_width > $width) { $width = $find_width }; 356 if ($find_height > $height) { $height = $find_height }; 357 } else { 358 print "\nNo HEIGHT/WIDTH info within: $_ ***"; 359 if ($width) { $width *= $WEBEQ_TCX_INL_SCALE } 360 if ($height) { $height *= $WEBEQ_TCX_INL_SCALE } 361 } 362 } else { 363 # tech-explorer uses a scaling of roughly 1.5 364 if ($width) { $width *= $WEBEQ_TCX_INL_SCALE } 365 if ($height) { $height *= $WEBEQ_TCX_INL_SCALE } 366 } 367 $width = 10 + int($width + 0.5) if $width; 368 $height = 5 + int($height + 0.5) if $height; 369 ($width,$height,$align); 370} 371 372# Fix entity-name errors in webeq output 373%WEBEQ_mml_name = ( 374 'in' , '∈' # 375 , 'setminus' , "\\" # ∖ 376 , 'mapsto' , ' - > ' # ∖ 377 , 'times' , ' x ' # × 378 , 'rightarrow' , ' -- > ' # &rarrow; 379 , 'longrightarrow' , ' --- > ' # &rrarrow; 380 ); 381$WEBEQ_mml_name_rx = join('|', keys %WEBEQ_mml_name); 382 383 384%WEBEQ_mml_punct = ( 385 ',' , ' ' # ' ' 386# '.' , '˙' # dot accent 387 , ':' , ' ' # '&medsp;' 388 , ';' , ' ' # '&thicksp;' 389 , '!' , '&negsp;' 390 , '~' , ' ' 391# , '`' , '`' # acute accent 392# , ''' , ''' # grave -- accent; 393# , '"' , '"' # umlaut -- accent; 394 , '@' , '@' 395 , '#' , '#' 396 , '$' , '$' 397 , '%' , '%' 398# , '^' , '^' # caret -- accent; 399 , '&' , '&' 400 , '*' , '☆' 401 , '(' , '' 402 , ')' , '' 403 , '-' , '' 404 , '_' , '_' 405 , '+' , '' 406 , '=' , '' 407 , '=' , '' 408 , '[' , '[' 409 , ']' , ']' 410 , '|' , '||' # ‖ or ‖ 411 , '<' , '⟨' 412 , '>' , '⟩' 413 , '{' , '{' # { 414 , '}' , '}' # } 415 ); 416$WEBEQ_mml_punct_rx = "\\W"; 417 418 419$WEBEQ_CLASSES = $ENV{'CLASSPATH'}; 420print " *** no JAVA classes*** \n 421 please set the CLASSPATH variable\n" unless $WEBEQ_CLASSES; 422 423$WEBEQ_CTR = ''; 424$WEBEQ = 'java webeq.wizard.clwizard '; 425$WEBEQ_OPTS = ' -colorspace colors -quality excellent -linewrap true -allow_selection true '; 426$WEBEQ_PARSER = ' -parser WebTeX -delims WebTeX '; 427$WEBEQ_PMML = ' -parser MathML -delims MathML '; 428$WEBEQ_APP = ' -outtype Applets'; 429$WEBEQ_IMG = ' -outtype Images_Only'; 430#$WEBEQ_MML = ' -outtype MathML_Only'; 431$WEBEQ_MML = ' -outtype MathML_Applets'; 432$WEBEQ_JPG = ' -imgtype jpeg'; 433$WEBEQ_PNG = ' -imgtype png'; 434$WEBEQ_NONE = ' -imgtype none'; 435$WEBEQ_ERR = ' -errors '; 436$WEBEQ_OUT = ' -o '; 437#$WEBEQ_MIME = ' TYPE="application/mathml"'; 438$WEBEQ_MIME = ' TYPE="text/mathml"'; 439$WEBEQ_JAVA = ' TYPE="application/java"'; 440$WEBEQ_INL = ' CLASS="INLINE"'; 441$WEBEQ_DIS = ' CLASS="DISPLAY"'; 442$WEBEQ_BKG = ' color=#ffffff'; 443$WEBEQ_TCX_REL_SCALE = 1.2; 444$WEBEQ_TCX_INL_SCALE = 1.6; 445 446%WEBEQ_CACHE = (); 447 448&ignore_commands( <<_IGNORED_CMDS_); 449_IGNORED_CMDS_ 450 451 452&process_commands_wrap_deferred (<<_RAW_ARG_DEFERRED_CMDS_); 453_RAW_ARG_DEFERRED_CMDS_ 454 4551; 456 457