diff -Naur latex2html-2018.2.orig/l2hconf.pin latex2html-2018.2/l2hconf.pin --- latex2html-2018.2.orig/l2hconf.pin 2020-11-10 20:50:07.430033162 +0700 +++ latex2html-2018.2/l2hconf.pin 2020-11-10 21:06:46.980047859 +0700 @@ -841,6 +841,7 @@ $PNMROTATE = '@PNMROTATE@'; $PNMSCALE = '@PNMSCALE@'; $PNMCROP = '@PNMCROP@'; +$PPMQUANT = '@PPMQUANT@'; $GIFTOPNM = '@GIFTOPNM@'; $JPEGTOPNM = '@JPEGTOPNM@'; diff -Naur latex2html-2018.2.orig/latex2html.pin latex2html-2018.2/latex2html.pin --- latex2html-2018.2.orig/latex2html.pin 2020-11-10 20:50:07.430033162 +0700 +++ latex2html-2018.2/latex2html.pin 2020-11-10 21:29:35.110067976 +0700 @@ -948,6 +948,7 @@ dbmopen(%verb, "$TMP_${dd}verb",0755); # dbmopen(%verbatim, "$TMP_${dd}verbatim",0755); dbmopen(%verb_delim, "$TMP_${dd}verb_delim",0755); + dbmopen(%verb_lstopt, "$TMP_${dd}verb_lstopt",0755); dbmopen(%expanded,"$TMP_${dd}expanded",0755); # Holds max_id, verb_counter, verbatim_counter, eqn_number dbmopen(%global, "$TMP_${dd}global",0755); @@ -988,6 +989,7 @@ dbmclose(%verb); undef %verb; # dbmclose(%verbatim); undef %verbatim; dbmclose(%verb_delim); undef %verb_delim; + dbmclose(%verb_lstopt); undef %verb_lstopt; dbmclose(%expanded); undef %expanded; dbmclose(%global); undef %global; dbmclose(%env_style); undef %env_style; @@ -1577,16 +1579,25 @@ my $vbmark = $verb_mark; while (s/\\verb(\t*\*\t*)(\S)/"$2"/e || s/\\verb()(\;SPM\w+\;|[^a-zA-Z*\s])/"$2"/e || - s/\\verb(\t\t*)([^*\s])/"$2"/e) { - - $del = $2; - #RRM: retain knowledge of whether \verb* or \verb - $vb_mark = ($1 =~/^\s*\*/? $verbstar_mark : $verb_mark); + s/\\verb(\t\t*)([^*\s])/"$2"/e || + s/\\(lstinline)\s*(\[[^]]*\])?\s*(\;SPM\w+\;|[^a-zA-Z*\s])/"$3"/e || + s/\\(lstinline)\s*(\[[^]]*\])?\s*([^*\s])/"$3"/e) { + + if ($1 eq 'lstinline') { + #SGE: retain knowledge and options of \lstinline + $del = $3; + $vb_mark = $verblst_mark; + $verb_lstopt{$id} = $2; + } else { + $del = $2; + #RRM: retain knowledge of whether \verb* or \verb + $vb_mark = ($1 =~/^\s*\*/? $verbstar_mark : $verb_mark); + } $esc_del = &escape_rx_chars($del); $esc_del = '' if (length($del) > 2); # try to find closing delimiter and substitute the complete - # statement with $verb_mark or $verbstar_mark + # statement with $verb_mark or $verbstar_mark or $verblst_mark # s/(]*$id>[\Q$del\E])([^$esc_del\n]*)([\Q$del\E]|$comment_mark(\d+)\n?)/ s/(]*$id>\Q$del\E)([^$esc_del\n]*?)(\Q$del\E|$comment_mark(\d+)\n?)/ $contents=$2; @@ -3178,7 +3189,7 @@ if ($style_names) { $envS = "$style_names" } elsif (($envS =~ /^pre$/)&& - (/^\\begin.*preform($O|$OP)\d+($C|$CP)$verbatim_mark(\w*[vV]erbatim)(\*?)/)) + (/^\\begin.*preform($O|$OP)\d+($C|$CP)$verbatim_mark(\w*[vV]erbatim|lstlisting)(\*?)/)) { $envS = $3.($4 ? 'star' : '') }; $env_style{$envS} = " " unless (($style_names)||($env_style{$envS})); $env_id = " ID=\"$env_id\"".(($envS) ? " CLASS=\"$envS\"" : ''); @@ -4165,7 +4176,15 @@ $flip, $aalias, $trans, $exscale, $alt, $exstr); my ($lwidth, $val) = (0, ''); - my ($custom_size,$color_depth,$height,$width,$croparg); + my ($custom_size,$color_depth,$color_quant,$height,$width,$croparg); + + # The combination -use_pdftex -use_dvipng uses gs driver png16m + # which can be incompatible with gif format (>256 colors). + $color_depth = $color_quant = ''; + if (($USE_PDFTEX || $USE_LUATEX) && $USE_DVIPNG && $IMAGE_TYPE =~ /gif/) { + $color_depth = "-depth 8 "; + $color_quant = "|$PPMQUANT -floyd 256"; + } print STDOUT "\nextracting $name as $page_num\n" if ($VERBOSITY > 1); # $global_num identifies this image in the original source file @@ -4214,9 +4233,9 @@ print STRUT "P5\n1 3\n255\nEEE\n"; close STRUT} #L2hos->syswait("$PNGTOPNM $p.png|$PNMCROP -sides|tee $p.ppm|$PNMCUT -top $millimeter |$PNMCROP -sides|tee $p-.ppm|$PPMTO{$IMAGE_TYPE} --quiet $transparent >img$new_num.$IMAGE_TYPE;"); if ($name =~ /figure|table/) { - L2hos->syswait("$PNGTOPNM $p.png|$PPMTO --quiet $transparent >img$new_num.$IMAGE_TYPE;"); + L2hos->syswait("$PNGTOPNM $p.png $color_quant|$PPMTO --quiet $transparent >img$new_num.$IMAGE_TYPE;"); } else { - L2hos->syswait("$PNGTOPNM $p.png|$PNMCROP -sides|tee $p.ppm|$PNMCUT -top $millimeter |$PNMCROP -left -right|tee $p-.ppm|$PPMTO --quiet $transparent >img$new_num.$IMAGE_TYPE;"); + L2hos->syswait("$PNGTOPNM $p.png|$PNMCROP -sides|tee $p.ppm|$PNMCUT -top $millimeter |$PNMCROP -left -right|tee $p-.ppm $color_quant|$PPMTO --quiet $transparent >img$new_num.$IMAGE_TYPE;"); } open PPM,"<$p.ppm"; read(PPM,$_,30);close PPM; m/^(\d+) (\d+)$/m; @@ -4328,15 +4347,18 @@ $under = "d" if (($name =~/inline|indisplay/)&&($depth{$name})); } print "\nIMAGE: $name scaled by $scale \n" if ($VERBOSITY > 2); + $color_depth = '' + if (($ANTI_ALIAS_TEXT || $aalias) && $aalias !~ /no/); (L2hos->syswait( "$PSTOIMG -type $IMAGE_TYPE " . ($DEBUG ? '-debug ' : '-quiet ' ) . ($TMPDIR ? "-tmp $TMPDIR " : '' ) . (($DISCARD_PS)? "-discard " : '' ) . (($INTERLACE)? "-interlace " : '' ) - . ((($ANTI_ALIAS_TEXT||($aalias))&&($aalias !=~/no/))? + . ((($ANTI_ALIAS_TEXT||($aalias))&&($aalias !~ /no/))? "-antialias -depth 1 " :'') . (($custom_size)? "-geometry $custom_size " : '' ) . $croparg + . ($color_depth || '') . (($scale != 1)? "-scale $scale " : '' ) . ((($exscale)&&($exscale != 1)&& !($ANTI_ALIAS_TEXT &&($LATEX_COLOR)))? @@ -4362,6 +4384,8 @@ $under = "d" if (($name =~/inline|indisplay/)&&($depth{$name})); } elsif ($mathscale) { $scale = $mathscale; } + $color_depth = '' + if (($ANTI_ALIAS_TEXT || $aalias) && $aalias !~ /no/); (L2hos->syswait("$PSTOIMG -type $IMAGE_TYPE " . ($DEBUG ? '-debug ' : '-quiet ' ) . ($TMPDIR ? "-tmp $TMPDIR " : '' ) @@ -4375,6 +4399,7 @@ . (($scale ne 1) ? "-scale $scale " : '' ) . (($custom_size) ? "-geometry $custom_size " : '' ) . $croparg + . ($color_depth || '') # . (($name =~ /(equation|eqnarray)/) ? "-rightjustify $lwidth " : '') # . (($name =~ /displaymath/) ? "-center $lwidth " : '') . (($name =~ /inline|indisplay/ && (!($custom_size))&&$depth{$name}!= 0) ? @@ -7224,6 +7249,74 @@ . (($length > 500) ? "\\setlength{\\textheight}{${length}pt}\n" : '') } +# Return numeric width and height of text area depending on paper format +# Analogous to adjust_textwidth, used for \includegraphics +sub get_text_size { + local($_) = @_; + local($width,$length) = ('',''); + if (/a4/) {$width = 595; $length= 842; } + elsif (/letter/) {$width = 612; $length= 792; } + elsif (/legal/) {$width = 612; $length= 1008; } + elsif (/note/) {$width = 540; $length= 720; } + elsif (/b5/) {$width = 501; $length= 709; } + elsif (/a5/) {$width = 421; $length= 595; } + elsif (/a6/) {$width = 297; $length= 421; } + elsif (/a7/) {$width = 210; $length= 297; } + elsif (/a8/) {$width = 148; $length= 210; } + elsif (/a9/) {$width = 105; $length= 148; } + elsif (/a10/) {$width = 74; $length= 105; } + elsif (/b4/) {$width = 709; $length= 1002; } + elsif (/a3/) {$width = 842; $length= 1190; } + elsif (/b3/) {$width = 1002; $length= 1418; } + elsif (/a2/) {$width = 1190; $length= 1684; } + elsif (/b2/) {$width = 1418; $length= 2004; } + elsif (/a1/) {$width = 1684; $length= 2380; } + elsif (/b1/) {$width = 2004; $length= 2836; } + elsif (/a0/) {$width = 2380; $length= 3368; } + elsif (/b0/) {$width = 2836; $length= 4013; } + else { + &write_warnings("\nPAPERSIZE: $_ unknown, using a5."); + $width = 421; $length= 595; + } + if ($width > 500) { $width = $width - 144; $length = $length - 288; } + elsif ($width > 250) { $width = $width - 72; $length = $length - 144; } + elsif ($width > 125) { $width = $width - 36; $length = $length - 72; } + + # Evtl adjust according to wrapfigure dimensions + if ($wrapfigure_width) { # defined inside wrapfigure only + my($pxs,$len) = &convert_length($wrapfigure_width, 1); + if ($pxs =~ s/%$//) { # scale width and length by percent + $width *= $pxs/100; + $length *= $pxs/100; + } else { # revert scaling, set explicit width, recalculate length + $pxs /= $FIGURE_SCALE_FACTOR*0.8; + $length *= $pxs/$width; + $width = $pxs; + } + } + + # Evtl adjust according to minipage dimensions (possibly nested) + if ($MINIPAGE) { + my($i, $mw); + for ($i=0; $i<$MINIPAGE; $i++) { + $mw = $minipage_width[$i]; + if ($mw =~ s/%$//) { # scale width and length by percent + $width *= $mw/100; + $length *= $mw/100; + } else { # revert scaling, set explicit width, recalculate length + $mw /= $MATH_SCALE_FACTOR*$FIGURE_SCALE_FACTOR*0.8; + $length *= $mw/$width; + $width = $mw; + } + } + } + + # Round results and return + $width = sprintf("%.0f", $width); + $length = sprintf("%.0f", $length); + ($width, $length); +} + # Given the depth of the current sectioning declaration and the current # section numbers it returns the new section numbers. # It increments the $depth-ieth element of the @curr_sec_id list and @@ -7366,7 +7459,7 @@ print STYLESHEET "SPAN.$env\t\t{ $style }\n"; } elsif ($env =~ /\./) { print STYLESHEET "$env\t\t{ $style }\n"; - } elsif ($env =~ /^(preform|\w*[Vv]erbatim(star)?)$/) { + } elsif ($env =~ /^(preform|lstlisting|\w*[Vv]erbatim(star)?)$/) { print STYLESHEET "PRE.$env\t\t{ $style }\n"; } elsif ($env =~ /figure|table|tabular|equation|$array_env_rx/) { print STYLESHEET "TABLE.$env\t\t{ $style }\n"; @@ -7878,7 +7971,7 @@ if (defined &replace_verbatim_hook) {&replace_verbatim_hook;} else {&replace_verbatim_marks if /$verbatim_mark/;} if (defined &replace_verb_hook) {&replace_verb_hook;} - else {&replace_verb_marks if /$verb_mark|$verbstar_mark/;} + else {&replace_verb_marks if /$verb_mark|$verbstar_mark|$verblst_mark/;} s/;SPMdollar;/\$/g; s/;SPMtilde;/\~/g; s/;SPMpct;/\%/g; s/;SPM/\&/go; s/$percent_mark/%/go; @@ -8785,6 +8878,8 @@ s!$verbatim_mark(\w*[vV]erbatim\*?|tex2html_code)(\d+)#\n?!$tmp=$verbatim{$2}; $tmp.(($tmp =~/\n\s*$/s)? '':"\n")!eg; # "\n".$tmp.(($tmp =~/\n\s*$/s)? '':"\n")!eg; + s/(]*>)?$verbatim_mark(lstlisting|lstset|lststyle|lstfile)(\d+)#(<\/PRE>)?\n?/ + &process_lstlisting($1, $4, $2, $verbatim{$3})/eg; # s/$verbatim_mark(rawhtml)(\d+)#/$verbatim{$2}/eg; # Raw HTML s/$verbatim_mark(imagesonly)(\d+)#//eg; # imagesonly is *not* replaced # Raw HTML, but replacements may have protected characters @@ -8793,6 +8888,8 @@ s/$unfinished_mark$keepcomments_rx(\d+)#/$verbatim{$2}/ego; # Raw TeX } +# Actual lstlisting engine, except initialization, moved to styles/listings.perl + # TeX's special characters may have been escaped with a '\'; remove it. sub unprotect_raw_html { local($raw) = @_; @@ -8813,16 +8910,20 @@ # s/$verbatim_mark(verbatim\*?)(\d+)#//go; s/$verbatim_mark(\w*[Vv]erbatim\w*\*?)(\d+)#//go; s/$verbatim_mark(rawhtml|imagesonly)(\d+)#//go; + s/$verbatim_mark(lstlisting)(\d+)#//go; s/$verbatim_mark$keepcomments_rx(\d+)#//go; s/$unfinished_mark$keepcomments_rx(\d+)#//go; } sub replace_verb_marks { # Modifies $_ - s/(?:$verb_mark|$verbstar_mark)(\d+)$verb_mark/ - $code = $verb{$1}; + s/($verb_mark|$verbstar_mark|$verblst_mark)(\d+)$verb_mark/ + $code = $verb{$2}; $code = &replace_comments($code) if ($code =~ m:$comment_mark:); - "$code<\/code>"/ego; + if ($1 eq $verblst_mark) + {$code=&process_lstinline($verb_lstopt{$2},$code);} + else {$code="$code<\/code>";} + $code/eg; } sub replace_comments{ @@ -8834,7 +8935,7 @@ sub remove_verb_marks { # Modifies $_ - s/($verb_mark|$verbstar_mark)(\d+)$verb_mark//go; + s/($verb_mark|$verbstar_mark|$verblst_mark)(\d+)$verb_mark//go; } # This is used by revert_to_raw_tex @@ -8842,6 +8943,7 @@ # Modifies $_ # s/$verbatim_mark(verbatim)(\d+)#/\\begin{verbatim}$verbatim{$2}\\end{verbatim}\n/go; s/$verbatim_mark(\w*[Vv]erbatim)(\d+)#/\\begin{$1}\n$verbatim{$2}\\end{$1}\n/go; + s/$verbatim_mark(lstlisting)(\d+)#/\\begin{lstlisting}\n$verbatim{$2}\\end{lstlisting}\n/go; s/$verbatim_mark(rawhtml)(\d+)#/\\begin{rawhtml}\n$verbatim{$2}\\end{rawhtml}\n/go; s/$verbatim_mark(imagesonly|tex2html_code)(\d+)#\n?/$verbatim{$2}/go; s/$verbatim_mark$image_env_rx(\d+)#/\\begin{$1}\n$verbatim{$2}\\end{$1}\n/go; @@ -8852,6 +8954,7 @@ # Modifies $_ s/$verbstar_mark(\d+)$verb_mark/\\verb*$verb_delim{$1}$verb{$1}$verb_delim{$1}/go; s/$verb_mark(\d+)$verb_mark/\\verb$verb_delim{$1}$verb{$1}$verb_delim{$1}/go; + s/$verblst_mark(\d+)$verb_mark/\\lstinline$verb_lstopt{$1}$verb_delim{$1}$verb{$1}$verb_delim{$1}/go; } sub replace_cross_ref_marks { @@ -8886,7 +8989,7 @@ #RRM: this simply absorbs the name from the invisible anchor following, # when the anchor itself is not already named. sub extend_ref { - if ($ref_label !=~ /NAME=/) { $label .= "\"\n".$name } + if ($ref_label !~ /NAME=/) { $label .= "\"\n".$name } } sub remove_cross_ref_marks { @@ -9892,7 +9995,7 @@ local($pre_bit); if ($lastbit =~/>([^>]*)$/) { $word = $1; $pre_bit = $`.'>'; - if ($pre_bit =~ /($verb_mark|$verbstar_mark)$/) { + if ($pre_bit =~ /($verb_mark|$verbstar_mark|$verblst_mark)$/) { $word = $lastbit; } elsif ($pre_bit =~ /<\w+_mark>$/) { $word = $& . $word; @@ -11296,6 +11399,8 @@ # not produce the same bullets as in the dvi output. sub do_env_itemize { local($_) = @_; + local($dum1, $dum2); + ($dum,$dum2) = &get_next_optional_argument; # discard optional argument $itemize_level++; #RRM - catch nested lists &protect_useritems($_); @@ -11329,6 +11434,8 @@ } sub do_env_enumerate { local($_) = @_; + local($dum1, $dum2); + ($dum,$dum2) = &get_next_optional_argument; # discard optional argument # Reiner Miericke provided the main code; integrated by RRM: 14/1/97 # works currently only with 'enumerate' and derived environments # explicit styled labels are computed for each \item @@ -11582,6 +11689,8 @@ sub do_env_description { local($_, $compact, $bullet) = @_; + local($dum1, $dum2); + ($dum,$dum2) = &get_next_optional_argument; # discard optional argument #RRM - catch nested lists &protect_useritems($_); $_ = &translate_environments($_) unless ($bullet); @@ -11947,7 +12056,8 @@ $width = &missing_braces unless ( (s/$next_pair_pr_rx/$width=$2;''/e) ||(s/$next_pair_rx/$width=$2;''/e)); - local($pxs,$len) = &convert_length($width,$MATH_SCALE_FACTOR) if $width; + local($pxs,$len); + ($pxs,$len) = &convert_length($width,$MATH_SCALE_FACTOR) if $width; $width = " WIDTH=\"$pxs\""; local ( %mpfootnotes, $mpfootnotes ) unless ($MINIPAGE); @@ -11955,6 +12065,7 @@ $global{'mpfootnote'} = 0 unless ($MINIPAGE); $MINIPAGE++; print "\n *** doing minipage *** " if ($VERBOSITY > 1); + $minipage_width[$MINIPAGE-1] = $pxs if ($MINIPAGE); local($open_tags_R) = [ @$open_tags_R ]; local($close_tags,$reopens) = &close_all_tags(); local(@save_open_tags) = @$open_tags_R; @@ -12905,9 +13016,10 @@ sub do_cmd_endgraf { join('',"
", $_[0]); } sub do_cmd_space { join(''," ",$_[0]); } -sub do_cmd_enspace { join('',"\ ",$_[0]); } -sub do_cmd_quad { join('',"\ "x4,$_[0]); } -sub do_cmd_qquad { join('',"\ "x8,$_[0]); } +sub do_cmd_enspace { join('',";SPMnbsp;",$_[0]); } +sub do_cmd_senspace { join('',";SPMnbsp;",$_[0]); } +sub do_cmd_quad { join('',";SPMnbsp;"x4,$_[0]); } +sub do_cmd_qquad { join('',";SPMnbsp;"x8,$_[0]); } sub do_cmd_par { local ($_) = @_; @@ -15774,6 +15886,7 @@ $unfinished_mark = ''; $verb_mark = ''; $verbstar_mark = ''; + $verblst_mark = ''; $image_mark = ''; $mydb_mark = ''; $percent_mark = ''; @@ -16056,7 +16169,7 @@ , '~', 'tilde', '.', 'dot', '=', 'bar' , '{', 'lbrace' , '}', 'rbrace', '|', 'Vert' , '#', 'esc_hash', '$', 'esc_dollar' - , ',', 'enspace' + , ',', 'enspace', ';', 'senspace' ); %text_accent = ( 'cedil','c', 'bdot','d', 'b','b' , 'tilde','~' @@ -16169,7 +16282,9 @@ } - %unitscale = ("in",72,"pt",72.27/72,"pc",12,"mm",72/25.4,"cm",72/2.54 + %unitscale = ("in",72,"pt",72/72.27,"pc",12*72/72.27 + ,"mm",72/25.4,"cm",72/2.54 + ,"ex",72/25.4*5,"em",72/25.4*5 ,"\\hsize",100,"\\vsize",100 ,"\\textwidth",100,"\\textheight",100 ,"\\pagewidth",100,"\\linewidth",100 @@ -16181,17 +16296,49 @@ my ($this,$scale) = @_; $scale = 1 unless $scale; my ($pxs,$len,$full); - if ( $this =~ /([\d.]*)\s*(in|pt|pc|mm|cm|\\[hv]size|\\\w+(width|height))?/ ) { - $len = ($1 ? $1 : 1); $full = $2; - if ($full &&($full =~ /\\([hv]size|\w+(width|height))/)) { $scale = 1;}; + if ( $this =~ /([\d.]*)\s*(in|pt|pc|mm|cm|ex|em|\\[hv]size|\\\w+(width|height))?/ ) { + $len = (($1 ne '') ? $1 : 1); $full = $2; + if ($full &&($full =~ /\\([hv]size|\w+(width|height))/)) { $scale = 1;} + else { $scale *= $FIGURE_SCALE_FACTOR*0.8; } + if ($full eq 'em' || $full eq 'ex') { + $unitscale{$full} = $LATEX_FONT_SIZE; + $unitscale{$full} = 12 if ($unitscale{$full} < 1); + } $pxs = (($full) ? int($len * $unitscale{$full}*$scale + 0.5) : int($len*$scale + .5) ); if ( $full =~ /\\([hv]size|\w+(width|height))/) { $pxs .= '%';}; }; ($pxs,$len); } - + # Initializations block for verbatim-like lstlisting environment + # Actual lstlisting engine moved to styles/listings.perl + # Currently default option values for lstlisting environment + %lstset_current = ( + 'numbers' => 'none', + 'stepnumber' => 1, + 'numberfirstline' => 'false', + 'numbersep' => '10pt', + 'firstnumber' => 'auto', + 'name' => '', + 'title' => '', + 'caption' => '', + 'captionpos' => 't', + 'basicstyle' => '', + 'style' => '', + 'inputpath' => '', + 'frame' => 'none', + 'framesep' => '3pt', + 'framerule' => '0.4pt', + 'backgroundcolor' => '', + 'rulecolor' => '' ); + # Option sets defined by lstdefinestyle + %lstset_style = (); + # Placeholder for \lstname + $lst_name = ''; + # For line counters + $lst_last_counter = 1; + %lst_auto_counter = (); # Inclusion in this list will cause a command or an environment to be ignored. @@ -16666,6 +16813,7 @@ $opt_arg_rx = "\\s*\\[([^\\]]*)\\]\\s*"; # Cannot handle nested []s! $optional_arg_rx = "^\\s*\\[([^]]*)\\]"; # Cannot handle nested []s! + $verb_braces_rx = "\\s*\\{([^}]*)\\}\\s*"; # Cannot handle nested {}s! $block_close_rx = "^<\\/(DIV|P|BLOCKQUOTE)>\$"; $all_close_rx = "^<\\/(BODY|PRE|OL|UL|DL|FORM|ADDRESS)>\$"; @@ -16822,7 +16970,7 @@ # Matches environments that should not be touched during the translation # $verbatim_env_rx = "\\s*{(verbatim|rawhtml|LVerbatim)[*]?}"; - $verbatim_env_rx = "\\s*(\\w*[Vv]erbatim|rawhtml|imagesonly|tex2html_code)[*]?"; + $verbatim_env_rx = "\\s*(\\w*[Vv]erbatim|lstlisting|rawhtml|imagesonly|tex2html_code)[*]?"; $image_env_rx = "\\s*(picture|xy|diagram)[*]?"; $keepcomments_rx = "\\s*(picture|makeimage|xy|diagram)[*]?"; diff -Naur latex2html-2018.2.orig/styles/graphics-support.perl latex2html-2018.2/styles/graphics-support.perl --- latex2html-2018.2.orig/styles/graphics-support.perl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/styles/graphics-support.perl 2020-11-10 21:32:16.310070346 +0700 @@ -255,14 +255,31 @@ # convert_length rounds up to 1 & uses %. Not quite right for here. # [convert_length(@_)]->[0]; -%BP_conversions=(pt=>72/72.27, pc=>12/72.27, in=>72, bp=>1, +%BP_conversions=(pt=>72/72.27, pc=>12*(72/72.27), in=>72, bp=>1, cm=>72/2.54, mm=>72/25.4, dd=>(72/72.27)*(1238/1157), - cc=>12*(72/72.27)*(1238/1157),sp=>72/72.27/65536); + cc=>12*(72/72.27)*(1238/1157),sp=>(72/72.27)/65536); sub to_bp { my($x)=@_; - $x =~ /^\s*([+-]?[\d\.]+)(\w*)\s*$/; - my($v,$u)=($1,$2); - $v*($u ? $BP_conversions{$u} : 1); } + my($v,$u); + $x =~ /^\s*(([+-]?[\d\.]+)?)\s*(\w*|\\\w+(width|height))\s*$/; + $v = ($1 ? $1 : 1); + $u = $3; + # Induce using native image dimensions if given size totally unrecognized + return '' if($1 eq '' && $3 eq ''); + if ($u =~ /\\\w+(width|height)/) { + my($w,$h); + if ($PAPERSIZE) { ($w,$h) = &get_text_size($PAPERSIZE); } + else { ($w,$h) = &get_text_size("a5"); } + if ($u =~ /height/) { $u = $h; } + else { $u = $w; } + } + elsif ($u eq 'em' || $u eq 'ex') { + $u = $LATEX_FONT_SIZE; + $u = 12 if ($u < 1); + } + else { $u = $u ? $BP_conversions{$u} : 1; } + $u *= $FIGURE_SCALE_FACTOR*0.8; # just an extra empirical coefficient + $v*$u; } sub scaled_image_size { my($imagew,$imageh, $reqw,$reqh,$scale,$keepaspect)=@_; diff -Naur latex2html-2018.2.orig/styles/html.perl latex2html-2018.2/styles/html.perl --- latex2html-2018.2.orig/styles/html.perl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/styles/html.perl 2020-11-10 21:33:29.800071426 +0700 @@ -8,6 +8,17 @@ # Extension to LaTeX2HTML to translate hypermedia extensions # to LaTeX defined in html.sty to equivalent HTML commands. # +# WARNING: \hyperref is also declared in hyperref.sty / hyperref.perl. +# Interfaces of both instances are incompatible. +# Therefore we declare additional command \hyperrefhyper +# whose interface is like that of \hyperref from hyperref.sty. +# +# If both hyperref.sty and html.sty are necessary, +# and \hyperref from hyperref.sty is needed, the following workaround may do: +# +# \usepackage{hyperref} +# \usepackage{html} +# \renewcommand{\hyperref}[2][]{\hyperrefhyper[#1]{#2}} # # # Modifications (Initials see Changes): @@ -556,6 +567,8 @@ &process_cite("external",''); } +# Provide the \hyperref command with interface of the html package. +# Will redefine \hyperref of hyperref package if both are used. sub do_cmd_hyperref { local($_) = @_; local($text,$url,$hypopt); @@ -594,6 +607,33 @@ &process_ref($cross_ref_mark,$cross_ref_mark,$text); } +# Provide the \hyperrefhyper command +# emulating \hyperref interface of the hyperref package +sub do_cmd_hyperrefhyper { + local($_) = @_; + local($text,$url); + local($opt, $dummy) = &get_next_optional_argument; + if ($opt) { + $text = &missing_braces unless + ((s/$next_pair_pr_rx/$text = $2; ''/eo) + ||(s/$next_pair_rx/$text = $2; ''/eo)); + local($br_id) = ++$global{'max_id'}; + $_ = join('', $OP.$br_id.$CP + , $opt + , $OP.$br_id.$CP , $_ ); + return (&process_ref($cross_ref_mark,$cross_ref_mark,$text)); + } + $url = &missing_braces unless + ((s/$next_pair_pr_rx/$url = $2; ''/eo) + ||(s/$next_pair_rx/$url = $2; ''/eo)); + s/$next_pair_pr_rx/$url.="\#$2.";''/eo; + s/$next_pair_pr_rx/$url.= (($url=~ m|\.$|)? '':'#').$2;''/e; + $text = &missing_braces unless + ((s/$next_pair_pr_rx/$text = $2; ''/eo) + ||(s/$next_pair_rx/$text = $2; ''/eo)); + &make_href($url,$text); +} + sub do_cmd_hypercite { local($_) = @_; local($text); diff -Naur latex2html-2018.2.orig/styles/hyperref.perl latex2html-2018.2/styles/hyperref.perl --- latex2html-2018.2.orig/styles/hyperref.perl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/styles/hyperref.perl 2020-11-10 21:34:37.520072422 +0700 @@ -8,6 +8,17 @@ # and therefore allows latex2html to process files # written for hyperref.sty without modifying them for latex2html +# WARNING: html.sty / html.perl also declares its own instance of \hyperref +# with an incompatible interface. Additionally declared is \hyperrefhyper +# whose interface is like that of \hyperref from hyperref.sty. +# +# If both hyperref.sty and html.sty are necessary, +# and \hyperref from hyperref.sty is needed, the following workaround may do: +# +# \usepackage{hyperref} +# \usepackage{html} +# \renewcommand{\hyperref}[2][]{\hyperrefhyper[#1]{#2}} + package main; # Suppress option warning messages: @@ -32,4 +43,45 @@ "$anchor".$_; } +sub do_cmd_hyperref { + local($_) = @_; + local($opt, $dummy) = &get_next_optional_argument; + if ($opt ne '') { + return (&process_hyperref($cross_ref_mark,$opt)); + } + local($url, $anchor, $name, $text); + $url = &missing_braces unless ( + (s/$next_pair_pr_rx/$url = $2;''/eo) + ||(s/$next_pair_rx/$url = $2;''/eo)); + $anchor = &missing_braces unless ( + (s/$next_pair_pr_rx/$anchor=$2;''/eo) + ||(s/$next_pair_rx/$anchor=$2;''/eo)); + $name = &missing_braces unless ( + (s/$next_pair_pr_rx/$name=$2;''/eo) + ||(s/$next_pair_rx/$name=$2;''/eo)); + $text = &missing_braces unless ( + (s/$next_pair_pr_rx/$text=$2;''/eo) + ||(s/$next_pair_rx/$text=$2;''/eo)); + $anchor = $anchor . '.' . $name if $name ne ''; + $url = $url . '#' . $anchor if $anchor ne ''; + # and recode the ~ (don't turn it to space) + $url =~ s/~/~/go; + "$text".$_; +} + +sub process_hyperref { + local($ref_mark, $label) = @_; + local($id, $text); + $text = &missing_braces unless + ((s/$next_pair_pr_rx/($id, $text) = ($1, $2); ''/eo) + ||(s/$next_pair_rx/($id, $text) = ($1, $2); ''/eo)); + $label =~ s/<[^>]*>//go ; #RRM: Remove any HTML tags + $label =~ s/$label_rx/_/g; # replace non alphanumeric characters + + print "\nLINK: $ref_mark\#$label\#$id :$text:" if ($VERBOSITY > 3); + + # The quotes around the HREF are inserted later + join('',"$text<\/A>", $_); +} + 1; diff -Naur latex2html-2018.2.orig/styles/listings.perl latex2html-2018.2/styles/listings.perl --- latex2html-2018.2.orig/styles/listings.perl 1970-01-01 07:00:00.000000000 +0700 +++ latex2html-2018.2/styles/listings.perl 2020-11-10 21:37:14.840074735 +0700 @@ -0,0 +1,520 @@ +# -*- perl -*- +# +# $Id: verbatim.perl,v 1.10 2001/11/29 21:44:13 RRM Exp $ +# +# listings.perl +# Georgy Salnikov 13/10/20 +# +# Extension to LaTeX2HTML V2018 to partly support the "listings" package. +# +# Partly derived from verbatim.perl and verbatimfiles.perl +# +# Change Log: +# =========== +# +# $Log: verbatim.perl,v $ +# +# Note: +# This module provides translation for the \lstlisting environment +# and for some more commands of the listings.sty package +# +# Handling decisions are done together with verbatim by LaTeX2HTML main program +# +# Several global variables and arrays are defined in the initialization block +# of the LaTeX2HTML main program: +# +# %lstset_current +# %lstset_style +# $lst_name +# $lst_last_counter +# %lst_auto_counter +# + +package main; + +# This package very probably may be used in listings +&do_require_package("color"); + +# Implementation of \lstinputlisting[]{}, preparation only +sub do_cmd_lstinputlisting { + local($_) = @_; + local($outer,$file); + + local($dum,$option) = &get_verb_optional_argument; + $file = &missing_braces unless ( + (s/$next_pair_pr_rx/$file=$2;''/eo) + ||(s/$next_pair_rx/$file=$2;''/eo)); + $outer = $_; + + local($closures,$reopens) = &preserve_open_tags; + my ($verb_pre, $verb_post) = ('
','
'); + if ($USING_STYLES) { + $env_id .= ' CLASS="verbatim"' unless ($env_id =~ /(^|\s)CLASS\s*\=/i); + $verb_pre =~ s/>/ $env_id>/; + } + + # %verbatim not coupled to a dbm => will not work in subprocesses, but don't mind + $verbatim{++$global{'verbatim_counter'}} = $option.$file; + + # Do nothing here, just wrap into a verbatim-like lstlisting environment. + # File reading and decorating postponed to &process_lstlisting. + join('', $closures, $verb_pre + , $verbatim_mark, 'lstfile', $global{'verbatim_counter'} + , '#', $verb_post, $reopens, $outer); +} + +# Implementation of \lstset{}, preparation only +sub do_cmd_lstset { + local($_) = @_; + local($option) = &missing_braces unless ( + (s/$next_pair_pr_rx/$option=$2;''/eo) + ||(s/$next_pair_rx/$option=$2;''/eo)); + local($outer) = $_; + + # In preamble this just initializes the defaults + if ($PREAMBLE) { + my(%opts) = &lst_parse_options($option); + @lstset_current{keys %opts} = (values %opts); + return $outer; + } + + # Do nothing here, just wrap into a verbatim-like lstset environment. + # Processing options will be done later by &process_lstlisting. + local($closures,$reopens) = &preserve_open_tags; + $verbatim{++$global{'verbatim_counter'}} = $option; + join('', $closures, $verbatim_mark, 'lstset', $global{'verbatim_counter'}, + '#', $reopens, $outer); +} + +# Implementation of \lstdefinestyle{}{}, preparation only +sub do_cmd_lstdefinestyle { + local($_) = @_; + local($style) = &missing_braces unless ( + (s/$next_pair_pr_rx/$style=$2;''/eo) + ||(s/$next_pair_rx/$style=$2;''/eo)); + local($option) = &missing_braces unless ( + (s/$next_pair_pr_rx/$option=$2;''/eo) + ||(s/$next_pair_rx/$option=$2;''/eo)); + local($outer) = $_; + + # In preamble this just creates the new style + if ($PREAMBLE) { + my(%opts) = &lst_parse_options($option); + @{$lstset_style{$style}}{keys %opts} = (values %opts); + return $outer; + } + + # Do nothing here, just wrap into a verbatim-like lststyle environment. + # Processing options will be done later by &process_lstlisting. + local($closures,$reopens) = &preserve_open_tags; + $verbatim{++$global{'verbatim_counter'}} = join(',', $style, $option); + join('', $closures, $verbatim_mark, 'lststyle', $global{'verbatim_counter'}, + '#', $reopens, $outer); +} + +# Implementation of \lstname, not much to do +sub do_cmd_lstname { $lst_name . $_[0]; } + +# This is the main driver subroutine for the lstlisting environment +sub process_lstlisting { + local($lst_pre, $lst_post, $lst_cmd, $_) = @_; + + # Check if it was an auxiliary command wrapped into an environment + if ($lst_cmd eq 'lstset') { return &set_lstset($_); } + if ($lst_cmd eq 'lststyle') { return &set_lststyle($_); } + + # Process an actual lstlisting environment + local($option,$dum) = &get_verb_optional_argument; + local($contents) = $_; + + # Fetch current defaults and apply specified options... + my(%curopts) = %lstset_current; + my(%opts) = &lst_parse_options($option); + + # First of all, apply either specified or default style if given + if ($opts{'style'} ne '') { + @curopts{keys %{$lstset_style{$opts{'style'}}}} = + (values %{$lstset_style{$opts{'style'}}}); + } + elsif ($lstset_current{'style'} ne '') { + @curopts{keys %{$lstset_style{$lstset_current{'style'}}}} = + (values %{$lstset_style{$lstset_current{'style'}}}); + } + + # Now apply all the other specified options + @curopts{keys %opts} = (values %opts); + + $lst_name = $curopts{'name'}; + + # For wrapped lstinputlisting - replace file name with file contents + if ($lst_cmd eq 'lstfile') { + my($dir); + my($file) = $contents; + $lst_name = $file; + my($file2) = "$file.tex"; + if ($file !~ /\.tex$/) { + # 2nd choice is better than 1st - TeXnical quirk + ($file,$file2) = ($file2,$file); + } + my($inputpath) = $curopts{'inputpath'}; + my($found) = 0; + foreach $dir ("$texfilepath", split(/:/,$ENV{'TEXINPUTS'})) { + if (-f ($_ = "$dir/$inputpath/$file") || + -f ($_ = "$dir/$inputpath/$file2") || + -f ($_ = "$dir/$file") || + -f ($_ = "$dir/$file2")) { + $found = 1; + # overread $_ with file contents + &slurp_input($_); + last; + } + } + &write_warnings("No file <$file> for lstinputlisting.") unless $found; + # pre_process file contents + if (defined &replace_all_html_special_chars) { + &replace_all_html_special_chars; + } else { + &replace_html_special_chars; + } + s/\n$//; # vertical space is contributed by already. + $contents = $_; + } + + # Interpret the rest of options in sequence... + # Line numbering (numbers,stepnumber,numberfirstline,numbersep,firstnumber) + my($i, $counter, $cline, $nlines); + $cline = ''; + $i = $counter = $nlines = 0; + my($step) = sprintf("%.0f", $curopts{'stepnumber'}); + my($incr) = $step<=>0; + $curopts{'numbers'} = 'none' if (! $incr); + my($nspaces); + ($nspaces, $dum) = &convert_length ($curopts{'numbersep'}, 1); + $nspaces = sprintf("%.0f", $nspaces/10); + my($fcount) = $curopts{'firstnumber'}; + if ($fcount eq 'auto') { + $fcount = 1; + if ($lst_name ne '' && $curopts{'numbers'} ne 'none') { + $lst_auto_counter{$lst_name} = 1 + unless (exists ($lst_auto_counter{$lst_name})); + $fcount = $lst_auto_counter{$lst_name}; + } + } elsif ($fcount eq 'last') { + $fcount = $lst_last_counter; + } else { + $fcount = sprintf("%.0f", $fcount); + } + + # Captioning options group (title, caption, captionpos) + my($title, $caption, $cappos); + $cappos = 'TOP'; + $cappos = 'BOTTOM' if ($curopts{'captionpos'} eq 'b'); + $title = ''; + if ($curopts{'title'} ne '') { + $_ = $curopts{'title'}; + # Replace braces with marks and try to interpret this as bracketed command + &lst_translate_option; + &replace_markers; + s/^\s+//; + s/\s+$//; + $title = $_; + } + $caption = ''; + if ($curopts{'caption'} ne '') { + $_ = $curopts{'caption'}; + # Replace braces with marks and try to interpret this as bracketed command + &lst_translate_option; + &replace_markers; + # Evtl separate short and full captions + ($option,$dum) = &get_verb_optional_argument; + s/^\s+//; + s/\s+$//; + $_ = $option if ($_ eq ''); + s/^\s+//; + s/\s+$//; + $caption = $_; + } + # If caption empty, use title + if ($caption ne '') { + $caption = 'Listing: ' . $caption; + } else { + $caption = $title; + } + + # basicstyle option: convert it to a pair of opening and closing HTML tags + my($bstyle_open, $bstyle_close); + $_ = $curopts{'basicstyle'}; + # Replace braces with marks and try to interpret this as bracketed command + &lst_translate_option; + s/$O\d+$C//go; # Get rid of bracket id's + s/$OP\d+$CP//go; # Get rid of processed bracket id's + $bstyle_open = $bstyle_close = '' + unless (s/^\s*((<\w+[^>]*>\s*)+)[^<]*((<\/\w+>\s*)+)$/$bstyle_open=$1;$bstyle_close=$3;''/eo); + $bstyle_open = $bstyle_open."\n" if ($bstyle_open ne ''); + $bstyle_close = "\n".$bstyle_close if ($bstyle_close ne ''); + + # Framing options group (frame, framesep, framerule) + my($frame) = 'VOID'; + $frame = 'LHS' if ($curopts{'frame'} eq 'leftline'); + $frame = 'ABOVE' if ($curopts{'frame'} eq 'topline'); + $frame = 'BELOW' if ($curopts{'frame'} eq 'bottomline'); + $frame = 'HSIDES' if ($curopts{'frame'} eq 'lines'); + $frame = 'BORDER' + if ($curopts{'frame'} eq 'single' || $curopts{'frame'} eq 'shadowbox'); + if ($curopts{'frame'} =~ /^[trblTRBL]+$/) { + my($t, $r, $b, $l, $c); + foreach $c (split //, $curopts{'frame'}) { + $t = 1 if ("\L$c" eq 't'); + $r = 1 if ("\L$c" eq 'r'); + $b = 1 if ("\L$c" eq 'b'); + $l = 1 if ("\L$c" eq 'l'); + } + if ($t && $r && $b && $l) { $frame = 'BORDER'; } + elsif ($t && $b) { $frame = 'HSIDES'; } + elsif ($r && $l) { $frame = 'VSIDES'; } + elsif ($t) { $frame = 'ABOVE'; } + elsif ($b) { $frame = 'BELOW'; } + elsif ($l) { $frame = 'LHS'; } + elsif ($r) { $frame = 'RHS'; } + } + my($framesep); + ($framesep, $dum) = &convert_length ($curopts{'framesep'}, 1); + $framesep = sprintf("%.0f", $framesep); + my($framerule); + ($framerule, $dum) = &convert_length ($curopts{'framerule'}, 1); + $framerule = sprintf("%.0f", $framerule); + if ($framerule == 1) { # Special case specifying a very thin border + $framerule = ''; + } else { + $framerule = " BORDER=\"$framerule\""; + } + + # Coloring options group (backgroundcolor, rulecolor) + my($bgcolor); + $_ = $curopts{'backgroundcolor'}; + if (/^\s*\\/) { + # Translate as a command and extract color value from the HTML tag + &lst_translate_option; + s/$O\d+$C//go; # Get rid of bracket id's + s/$OP\d+$CP//go; # Get rid of processed bracket id's + # Extract color value or clear the malformed contents + $_ = '' + unless (s/^\s*\s*<\/FONT>\s*$//); + } else { + # Must be a \color command + $_ = ''; + } + $bgcolor = $_; + $bgcolor = " BGCOLOR=\"$bgcolor\"" unless ($bgcolor eq ''); + my($rulecolor); + $_ = $curopts{'rulecolor'}; + if (/^\s*\\/) { + # Translate as a command and extract color value from the HTML tag + &lst_translate_option; + s/$O\d+$C//go; # Get rid of bracket id's + s/$OP\d+$CP//go; # Get rid of processed bracket id's + # Extract color value or clear the malformed contents + $_ = '' + unless (s/^\s*\s*<\/FONT>\s*$//); + } else { + # Must be a \color command + $_ = ''; + } + $rulecolor = $_; + $rulecolor = " BORDERCOLOR=\"$rulecolor\"" unless ($rulecolor eq ''); + + $lst_pre = $bstyle_open.$lst_pre."\n"; + $lst_post = "\n".$lst_post.$bstyle_close; + $_ = $contents; + + # Evtl generate line numbers + if ($curopts{'numbers'} eq 'left') { + # Insert numbers from the left side. + $counter = $fcount-$incr; + s/^/$i++; $counter+=$incr; + (($counter % $step) && ($curopts{'numberfirstline'} ne 'true' || $i > 1)) ? + (' ' . ' ' x $nspaces) : + (sprintf("%5d",$counter) . ' ' x $nspaces)/mge; + $lst_last_counter = $counter+$incr; + $lst_auto_counter{$lst_name} = $lst_last_counter + if ($curopts{'firstnumber'} eq 'auto' && $lst_name ne ''); + } + elsif ($curopts{'numbers'} eq 'right' && $HTML_VERSION > 2.1) { + # Inserting right padded numbers for every line is tricky. + # Do it as a table with two huge columns with verbatim contents. + # But only if HTML version is high enough... + s/$/$nlines++;''/mge; + for ($counter=$fcount; $i<$nlines; $i++) { + $cline .= (($counter % $step) && + ($curopts{'numberfirstline'} ne 'true' || $i > 0)) ? + (' ' x $nspaces . " \n") : + (' ' x $nspaces . sprintf("%d\n",$counter)); + $counter += $incr; + } + $lst_last_counter = $counter; + $lst_auto_counter{$lst_name} = $lst_last_counter + if ($curopts{'firstnumber'} eq 'auto' && $lst_name ne ''); + $cline =~ s/\n$//; + $_ = "
" + .$lst_pre.$_.$lst_post."" + .$lst_pre.$cline.$lst_post."
"; + $lst_pre = $lst_post = ''; + } + + # Frames, captions and coloring are generated also as a synthetic table + if ($HTML_VERSION > 2.1) { + $lst_pre = "" + .(($caption ne '') ? + ("\n\n") : '') + ."
".$caption."
\n".$lst_pre; + $lst_post = $lst_post."\n
"; + } + + # WHEW !!! + $lst_pre.$_.$lst_post."\n"; +} + +# Driver subroutine for the real processing of \lstinline command +sub process_lstinline { + local($_, $contents) = @_; + + # Get lstinline options + local($option,$dum) = &get_verb_optional_argument; + + # Fetch current defaults and apply specified options... + my(%curopts) = %lstset_current; + my(%opts) = &lst_parse_options($option); + + # First of all, apply either specified or default style if given + if ($opts{'style'} ne '') { + @curopts{keys %{$lstset_style{$opts{'style'}}}} = + (values %{$lstset_style{$opts{'style'}}}); + } + elsif ($lstset_current{'style'} ne '') { + @curopts{keys %{$lstset_style{$lstset_current{'style'}}}} = + (values %{$lstset_style{$lstset_current{'style'}}}); + } + + # Now apply all the other specified options + @curopts{keys %opts} = (values %opts); + + # basicstyle seems the only option which can be really useful for lstinline + my($bstyle_open, $bstyle_close); + $_ = $curopts{'basicstyle'}; + # Replace braces with marks and try to interpret this as bracketed command + &lst_translate_option; + s/$O\d+$C//go; # Get rid of bracket id's + s/$OP\d+$CP//go; # Get rid of processed bracket id's + $bstyle_open = $bstyle_close = '' + unless (s/^\s*((<\w+[^>]*>\s*)+)[^<]*((<\/\w+>\s*)+)$/$bstyle_open=$1;$bstyle_close=$3;''/eo); + + # Make the actual lstinline output + $bstyle_open.''.$contents.''.$bstyle_close; +} + +# Driver subroutine for \lstset processing +# Just copy the given set of options to the default options set +sub set_lstset { + local($_) = @_; + my(%opts) = &lst_parse_options($_); + @lstset_current{keys %opts} = (values %opts); + ''; +} + +# Driver subroutine for \lstdefinestyle +# Similar to the preceding but maintains distinct named options sets (styles) +sub set_lststyle { + local($_) = @_; + local($style) = '' unless (s/^(\w+),/$style=$1;''/eo); + return '' if ($style eq ''); + my(%opts) = &lst_parse_options($_); + @{$lstset_style{$style}}{keys %opts} = (values %opts); + ''; +} + +# Option parser for lstlisting commands/envs family, this can be tricky +sub lst_parse_options { + local($_) = @_; + + # First get rid of comment marks + s/(\\\w+)$comment_mark\d*\s*?\n[ \t]*/$1 \n/go; + s/($comment_mark\d*\s*)+\n[ \t]*/\n/go; + + # Find any kinds of brackets to keep them intact + # for the case if they might have commas inside + my(@fields, @chunks); + my($before, $match, $after); + while (/$any_next_pair_pr_rx|$any_next_pair_rx4|$opt_arg_rx|$verb_braces_rx/) + { + ($before, $match, $after) = ($`, $&, $'); + @chunks = split(/,/, $before); + $fields[$#fields] .= shift(@chunks) if @fields; + push(@fields, @chunks); + $fields[$#fields] .= $match; + $_ = $after; + } + @chunks = split(/,/); + $fields[$#fields] .= shift(@chunks) if @fields; + push(@fields, @chunks); + + # All options are separated, now split them to option name and value + my(%opts); + my($par, $val); + foreach (@fields) { + next unless ($par, $val) = /^\s*(\w+?)\s*=\s*(.*)\s*$/s; + $opts{$par} = $val; + } + %opts; +} + +# Replace braces with marks and try to interpret this as a bracketed command +sub lst_translate_option { + # Modifies $_ + &mark_string($_); + my($br_id) = ++$global{'max_id'}; + $_ = $O.$br_id.$C.$_.$O.$br_id.$C; + $_ = &translate_environments($_); + $_ = &translate_commands($_); +} + +# &get_next_optional_argument is not well suited for lstlisting +# Here is a special version of &get_next_optional_argument +sub get_verb_optional_argument { + local($next, $pat); + my($before, $match, $after); + $next = $pat = $match = ''; + if (s/^(\[)/$pat=$1;''/eo) { + # Find any kinds of braces not to stuck on [] evtl nested between them + while (/$any_next_pair_pr_rx|$any_next_pair_rx4|$verb_braces_rx|\]/) { + ($before, $match, $after) = ($`, $&, $'); + $next .= $before; + $pat .= $before; + if ($match eq ']') { + $pat .= $match; + $_ = $after; + # Before returning, remove comment mark and newline after closing ] + s/^[ \t]*($comment_mark\d*[ \t]*)*\n//o; + last; + } + $next .= $match; + $pat .= $match; + $_ = $after; + } + if ($match ne ']') { + # Closing ] not found, revert back $_ and clear arguments + $_ = $pat . $_; + $next = $pat = ''; + } + } + # Imitate return of &get_next_optional_argument + ($next, $pat); +} + +&process_commands_wrap_deferred (<<_RAW_ARG_DEFERRED_CMDS_); +lstinputlisting # [] # {} +lstdefinestyle # {} # {} +lstset # {} +_RAW_ARG_DEFERRED_CMDS_ + +1; # Must be last line diff -Naur latex2html-2018.2.orig/styles/verbatimfiles.perl latex2html-2018.2/styles/verbatimfiles.perl --- latex2html-2018.2.orig/styles/verbatimfiles.perl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/styles/verbatimfiles.perl 2020-11-10 21:35:31.090073210 +0700 @@ -80,8 +80,8 @@ #insert numbers for every line #but not the first line if it's empty (LaTeX'ism?) - local($firstemptyline); - $firstemptyline = $1 if s/^([ \t]+\n)//; + local($first); + $first = $1 if s/^([ \t]+\n)//; #and not the last end of line s/\n$//; diff -Naur latex2html-2018.2.orig/styles/wrapfig.perl latex2html-2018.2/styles/wrapfig.perl --- latex2html-2018.2.orig/styles/wrapfig.perl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/styles/wrapfig.perl 2020-11-10 21:36:49.110074357 +0700 @@ -17,11 +17,15 @@ sub do_env_wrapfigure{ local($_) = @_; - $contents =~ s/$optional_arg_rx//o; # ditch [nlines] - $contents =~ s/$next_pair_rx//o; # ditch {placement} - $contents =~ s/$next_pair_rx//o; # ditch {width} + s/$optional_arg_rx//o; # ditch [nlines] + s/$next_pair_rx//o; # ditch {placement} + $wrapfigure_width = &missing_braces unless ( # save {width} + (s/$next_pair_pr_rx/$wrapfigure_width=$2;''/eo) + ||(s/$next_pair_rx/$wrapfigure_width=$2;''/eo)); # &process_environment("figure", $global{'max_id'}++); - &do_env_figure($_); + $_ = &do_env_figure($_); + $wrapfigure_width = ''; # clear width + $_; } &process_commands_in_tex (<<_RAW_ARG_CMDS_); diff -Naur latex2html-2018.2.orig/texexpand.pin latex2html-2018.2/texexpand.pin --- latex2html-2018.2.orig/texexpand.pin 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/texexpand.pin 2020-11-10 21:12:45.960053138 +0700 @@ -13,8 +13,9 @@ # Jens Lippmann # Recognizes \documentclass, \documentstyle, \usepackage, \RequirePackage, -# \begin{verbatim}...\end{verbatim}, %begin{latexonly}...%end{latexonly}, -# \begin{latexonly}...\end{latexonly}, \input, \include, \verb, \latex +# \begin{verbatim}...\end{verbatim}, \begin{lstlisting}...\end{lstlisting}, +# %begin{latexonly}...%end{latexonly}, \begin{latexonly}...\end{latexonly}, +# \input, \include, \verb, \lstinline, \latex # \endinput, \end{document} # \includecomment, \excludecomment # \begin{"to exclude"}, \end{"to exclude"} @@ -40,8 +41,9 @@ # c) \begin{any} introduced with \excludecomment # d) %begin{any} # e) \begin{verbatim} -# f) \begin{latexonly} -# g) %begin{latexonly} +# f) \begin{lstlisting} +# g) \begin{latexonly} +# h) %begin{latexonly} # # a)-d) cause texexpand to drop its contents, it will not show up in the # output file. You can use this to 'comment out' a bunch of files, say. @@ -66,18 +68,18 @@ # 3. [%\]begin{"to exclude"} and [%\]end{"to exclude"} have to be on a # separate line. # Anything between these tags (including the tags) is discarded. -# 4. \begin{verbatim/verbatim*} and \end{verbatim/verbatim*} have to be -# on a separate line. +# 4. \begin{verbatim/verbatim*/lstlisting} and +# \end{verbatim/verbatim*/lstlisting} have to be on a separate line. # Anything between these tags (including the tags) is not expanded. # 5. The scope of any such tags may extend over several files. # The opening tag for latexonly may occur on a different include level # than the closing tag. -# The opening tag for verbatim/"to exclude" must occur within the same -# file than the closing tag. +# The opening tag for verbatim/lstlisting/"to exclude" must occur +# within the same file than the closing tag. # 6. Warnings are printed when the document has been parsed and open # tags remain. -# 7. When in a "to exclude"/verbatim environment, texexpand won't recognize -# ANY command except the corresponding closing tag. +# 7. When in a "to exclude"/verbatim/lstlisting environment, texexpand +# won't recognize ANY command except the corresponding closing tag. # There cannot be any nested constructions. # This behaviour is identical to that of LaTeX. # 8. \begin{latexonly},\end{latexonly} may be nested, whereas @@ -87,8 +89,9 @@ # has to be on a separate line. # 11. Everything behind a `%' that isn't preceded by a `\' is regarded as # a comment, i.e. it is printed but not interpreted. -# 12. If any command listed in 10. is preceded by an occurence of `\verb' or -# `\latex' then it is NOT interpreted. This crashes on lines like this: +# 12. If any command listed in 10. is preceded by an occurence of +# `\verb', `\lstinline' or `\latex' then it is NOT interpreted. +# This crashes on lines like this: # blah blah \verb+foo foo+ \input{bar} % bar won't be loaded! # 13. Packages provided via \usepackage are handled the same way as # `options' in \document(class|style), i.e. they are included when @@ -492,8 +495,8 @@ # Create generic regexp's: # If this matches before a command, the command is ignored. $ignore_cmd_rx = -# '(\\latex\W|\\verb|\\expandafter|\\ifx|\\else\W|[\|\[\@]$)'; - "(\\\\latex\\W|\\\\verb|\\\\expandafter|\\\\ifx|\\\\else\\W|[\\|\\[\\@]\$)"; +# '(\\latex\W|\\verb|\\lstinline|\\expandafter|\\ifx|\\else\W|[\|\[\@]$)'; + "(\\\\latex\\W|\\\\verb|\\\\lstinline|\\\\expandafter|\\\\ifx|\\\\else\\W|[\\|\\[\\@]\$)"; # This matches a square bracket pair (typically an option list). $options_rx = '(\[[^\]]*\]|)'; # This matches a single argument. @@ -534,7 +537,7 @@ sub main { -# Note that verbatim/latexonly may split over different files! +# Note that verbatim/lstlisting/latexonly may split over different files! # $verbatim is 1 if inside a verbatim environment, # $latexonly is > 0 if inside latexonly environments # $includelevel indicates the depth of include/input @@ -597,17 +600,17 @@ # also would retain its body from LaTeX. # => $active false, $mute true # 3) interprete minimal and pass the lines to the out file -# This is inside a verbatim or latexonly environment. +# This is inside a verbatim, lstlisting or latexonly environment. # The line of course must be at least interpreted to # determine the closing tag. # => $active false, $mute false # # Any environment may extend over several include files. -# Any environement except verbatim and latexonly may have its +# Any environement except verbatim, lstlisting and latexonly may have its # opening or closing tag on different input levels. -# The comment and verbatim environments cannot be nested, as +# The comment and verbatim/lstlisting environments cannot be nested, as # is with LaTeX. -# We must at least parse verbatim/comment environments in +# We must at least parse verbatim/lstlisting/comment environments in # latexonly environments, to catch fake latexonly tags. # # The work scheme: @@ -768,7 +771,7 @@ $mute=1 unless $latexonly; } # elsif (!$fakeenv && !$verbatim && /\\begin\s*\{\s*verbatim(\*)?\s*\}/) { - elsif (!$fakeenv && !$verbatim && /\\begin\s*\{\s*(\w*[Vv]erbatim\w*\*?)\s*\}/) { + elsif (!$fakeenv && !$verbatim && /\\begin\s*\{\s*((\w*[Vv]erbatim\w*|lstlisting)\*?)\s*\}/) { ($before,$verbatimname) = ($`,$1); ($active,$verbatim) = (0,1) unless ($before =~ /$ignore_cmd_rx/o); @@ -840,7 +843,7 @@ } } # elsif ( /\\end\s*\{\s*verbatim(\*)?\s*\}/) { - elsif ( /\\end\s*\{\s*(\w*[Vv]erbatim\w*\*?)\s*\}/) { + elsif ( /\\end\s*\{\s*((\w*[Vv]erbatim\w*|lstlisting)\*?)\s*\}/) { if ($1 eq $verbatimname) { $verbatim=0; $active = ($latexonly ? 0 : 1); diff -Naur latex2html-2018.2.orig/versions/html3_2.pl latex2html-2018.2/versions/html3_2.pl --- latex2html-2018.2.orig/versions/html3_2.pl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/versions/html3_2.pl 2020-11-10 21:40:11.570077334 +0700 @@ -580,13 +580,14 @@ s/\\\\\s*\[([^]]+)\]/\\\\/g; # TKM - get rid of [N.n pc] on end of rows... s/\\newline\s*\[([^]]+)\]/\\newline/g; s/\n\s*\n/\n/g; # Remove empty lines (otherwise will have paragraphs!) + s/\\\\\s*\n\s*$par_rx\s*\n/\\\\\n/g; # don't start next row with a \par local($i,@colspec,$char,$cols,$cell,$htmlcolspec,$frames,$rules); local(@rows,@cols,$border,$frame); local($colspan,$cellcount); - + # set a flag to indicate whether there are any \multirow cells my $has_multirow = 1 if (/\\multirow/s); - + # convert \\s inside \parbox commands to \newline s; # catch nestings @@ -607,7 +608,7 @@ if ($color_env) { local($color_test) = join(',',@$open_tags_R); - if ($color_test =~ /(color\{[^}]*})/g ) { + if ($color_test =~ /(color\{[^}]*\})/g ) { $color_env = $1; } } @@ -693,7 +694,7 @@ $return = join('', "") + , $tab_width, ">"); } local($firstrow) = 1; local($lastrow) = ''; @@ -736,8 +737,11 @@ for ( $i = 0; $i <= $#colspec; $i++ ) { # skip this cell if it is covered by a \multirow - next if ($has_multirow && @row_spec[$i] > 0); - + if ($has_multirow && @row_spec[$i] > 0) { + shift(@cols); + next; + } + $colspec = $colspec[$i]; if (!($colspec =~ $content_mark)) { # no data required in this column @@ -899,7 +903,7 @@ } sub do_cmd_multirow { local($_) = @_; - local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$valign,$vspec,$text); + local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$text); $spanrows = &missing_braces unless ( (s/$next_pair_pr_rx/$spanrows=$2;''/eo) ||(s/$next_pair_rx/$spanrows=$2;''/eo)); @@ -910,25 +914,21 @@ $colspec =~ /^<([A-Z]+)/; local($celltag) = $1; - # read the width, save it for later use + # read the width, save it for later use (the last regex matches '*') $rwidth = &missing_braces unless ( (s/$next_pair_pr_rx/$rwidth=$2;''/eo) - ||(s/$next_pair_rx/$rwidth=$2;''/eo)); - - # catch cases where the \textwidth has been discarded - $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; + ||(s/$next_pair_rx/$rwidth=$2;''/eo) + ||(s/^[\s%]*(\*)($comment_mark\d*\n?)?/$rwidth=$1;''/eo)); - ($pxs,$rwidth) = &convert_length($rwidth); - - $valign = &missing_braces unless ( - (s/$next_pair_pr_rx/$valign=$2;''/eo) - ||(s/$next_pair_rx/$valign=$2;''/eo)); - $vspec = ' VALIGN="TOP"' if $valign; - if ($valign =~ /m/i) { $vspec =~ s/TOP/MIDDLE/ } - elsif ($valign =~ /b/i) { $vspec =~ s/TOP/BOTTOM/ } - - $colspec =~ s/VALIGN="\w+"// if $vspec; # avoid duplicate tags - $colspec =~ s/>$content_mark/$vspec ROWSPAN=$rowspan WIDTH=$pxs$&/; + if ($rwidth eq '*') { + # automatic width + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan$&/; + } else { + # catch cases where the \textwidth has been discarded + $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; + ($pxs,$rwidth) = &convert_length($rwidth); + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan WIDTH=$pxs$&/; + } s/$next_pair_pr_rx/$text=$2;''/eo; $text = &translate_commands($text) if ($text =~ /\\/); diff -Naur latex2html-2018.2.orig/versions/html4_01.pl latex2html-2018.2/versions/html4_01.pl --- latex2html-2018.2.orig/versions/html4_01.pl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/versions/html4_01.pl 2020-11-10 21:42:09.380079066 +0700 @@ -949,13 +949,14 @@ s/\\\\\s*\[([^]]+)\]/\\\\/g; # TKM - get rid of [N.n pc] on end of rows... s/\\newline\s*\[([^]]+)\]/\\newline/g; s/\n\s*\n/\n/g; # Remove empty lines (otherwise will have paragraphs!) + s/\\\\\s*\n\s*$par_rx\s*\n/\\\\\n/g; # don't start next row with a \par local($i,@colspec,$char,$cols,$cell,$htmlcolspec,$frames,$rules); local(@rows,@cols,$border,$frame); local($colspan,$cellcount); - + # set a flag to indicate whether there are any \multirow cells my $has_multirow = 1 if (/\\multirow/s); - + # convert \\s inside \parbox commands to \newline s; # catch nestings @@ -976,7 +977,7 @@ if ($color_env) { local($color_test) = join(',',@$open_tags_R); - if ($color_test =~ /(color\{[^}]*})/g ) { + if ($color_test =~ /(color\{[^}]*\})/g ) { $color_env = $1; } } @@ -1109,7 +1110,10 @@ for ( $i = 0; $i <= $#colspec; $i++ ) { # skip this cell if it is covered by a \multirow - next if ($has_multirow && @row_spec[$i] > 0); + if ($has_multirow && @row_spec[$i] > 0) { + shift(@cols); + next; + } $colspec = $colspec[$i]; if (!($colspec =~ $content_mark)) { @@ -1268,7 +1272,7 @@ } sub do_cmd_multirow { local($_) = @_; - local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$valign,$vspec,$text); + local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$text); $spanrows = &missing_braces unless ( (s/$next_pair_pr_rx/$spanrows=$2;''/eo) ||(s/$next_pair_rx/$spanrows=$2;''/eo)); @@ -1279,25 +1283,21 @@ $colspec =~ /^<([A-Z]+)/; local($celltag) = $1; - # read the width, but ignore it + # read the width, save it for later use (the last regex matches '*') $rwidth = &missing_braces unless ( (s/$next_pair_pr_rx/$rwidth=$2;''/eo) - ||(s/$next_pair_rx/$rwidth=$2;''/eo)); + ||(s/$next_pair_rx/$rwidth=$2;''/eo) + ||(s/^[\s%]*(\*)($comment_mark\d*\n?)?/$rwidth=$1;''/eo)); - # catch cases where the \textwidth has been discarded - $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; - - ($pxs,$rwidth) = &convert_length($rwidth); - - $valign = &missing_braces unless ( - (s/$next_pair_pr_rx/$valign=$2;''/eo) - ||(s/$next_pair_rx/$valign=$2;''/eo)); - $vspec = ' VALIGN="TOP"' if $valign; - if ($valign =~ /m/i) { $vspec =~ s/TOP/MIDDLE/ } - elsif ($valign =~ /b/i) { $vspec =~ s/TOP/BOTTOM/ } - - $colspec =~ s/VALIGN="\w+"// if $vspec; # avoid duplicate tags - $colspec =~ s/>$content_mark/$vspec ROWSPAN=$rowspan WIDTH=$pxs$&/; + if ($rwidth eq '*') { + # automatic width + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan$&/; + } else { + # catch cases where the \textwidth has been discarded + $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; + ($pxs,$rwidth) = &convert_length($rwidth); + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan WIDTH=$pxs$&/; + } $text = &styled_text_chunk('SPAN','mrow','','','','', $_); $text = &translate_commands($text) if ($text =~ /\\/); @@ -1356,7 +1356,7 @@ , '' , &process_undefined_environment("tex2html_wrap_inline", $id, $saved) , '' ); - } else { $_ = join('', $comment, $labels, $_ ) } + } else { $_ = join('', $comment, $labels, $_ ); } if ($border||($attributes)) { &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } diff -Naur latex2html-2018.2.orig/versions/html4_0.pl latex2html-2018.2/versions/html4_0.pl --- latex2html-2018.2.orig/versions/html4_0.pl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/versions/html4_0.pl 2020-11-10 21:41:14.280078256 +0700 @@ -79,7 +79,7 @@ $coord_type = "\^\\s*(\$|\\d+(\\s*,\\s*\\d+)+\\s*\$)"; # comma-separated list of numbers $pixel_type = "\^\\d+\$"; $length_type = "\^\\d+\%?\$"; -$name_type = "\^[A-Za-z]([A-Za-z\\d\\-\\.]*\$"; +$name_type = "\^[A-Za-z][A-Za-z\\d\\-\\.]*\$"; $string_type = $URL_type = $script_type = $ISOdate_type = $Internet_type = $CDATA_type = "\^.*\$"; $id_list_type = "\^\\s*\$name_type(\\s+$name_type)*\\s*\$"; @@ -928,6 +928,7 @@ s/\\\\\s*\[([^]]+)\]/\\\\/g; # TKM - get rid of [N.n pc] on end of rows... s/\\newline\s*\[([^]]+)\]/\\newline/g; s/\n\s*\n/\n/g; # Remove empty lines (otherwise will have paragraphs!) + s/\\\\\s*\n\s*$par_rx\s*\n/\\\\\n/g; # don't start next row with a \par local($i,@colspec,$char,$cols,$cell,$htmlcolspec,$frames,$rules); local(@rows,@cols,$border,$frame); local($colspan,$cellcount); @@ -1080,15 +1081,18 @@ $return .= "\n"; @cols = split(/$html_specials{'&'}/o); - if ($has_multirow) { + if ($has_multirow) { # decrement the counters for multi-row cells my @trow_spec = map {$_>0? --$_ : 0 } @row_spec; @row_spec = @trow_spec; } - + for ( $i = 0; $i <= $#colspec; $i++ ) { # skip this cell if it is covered by a \multirow - next if ($has_multirow && @row_spec[$i] > 0); + if ($has_multirow && @row_spec[$i] > 0) { + shift(@cols); + next; + } $colspec = $colspec[$i]; if (!($colspec =~ $content_mark)) { @@ -1247,7 +1251,7 @@ } sub do_cmd_multirow { local($_) = @_; - local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$valign,$vspec,$text); + local($dmy1,$dmy2,$dmy3,$dmy4,$spanrows,$pxs,$rwidth,$text); $spanrows = &missing_braces unless ( (s/$next_pair_pr_rx/$spanrows=$2;''/eo) ||(s/$next_pair_rx/$spanrows=$2;''/eo)); @@ -1258,25 +1262,21 @@ $colspec =~ /^<([A-Z]+)/; local($celltag) = $1; - # read the width, save it for later use + # read the width, save it for later use (the last regex matches '*') $rwidth = &missing_braces unless ( (s/$next_pair_pr_rx/$rwidth=$2;''/eo) - ||(s/$next_pair_rx/$rwidth=$2;''/eo)); - - # catch cases where the \textwidth has been discarded - $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; + ||(s/$next_pair_rx/$rwidth=$2;''/eo) + ||(s/^[\s%]*(\*)($comment_mark\d*\n?)?/$rwidth=$1;''/eo)); - ($pxs,$rwidth) = &convert_length($rwidth); - - $valign = &missing_braces unless ( - (s/$next_pair_pr_rx/$valign=$2;''/eo) - ||(s/$next_pair_rx/$valign=$2;''/eo)); - $vspec = ' VALIGN="TOP"' if $valign; - if ($valign =~ /m/i) { $vspec =~ s/TOP/MIDDLE/ } - elsif ($valign =~ /b/i) { $vspec =~ s/TOP/BOTTOM/ } - - $colspec =~ s/VALIGN="\w+"// if $vspec; # avoid duplicate tags - $colspec =~ s/>$content_mark/$vspec ROWSPAN=$rowspan WIDTH=$pxs$&/; + if ($rwidth eq '*') { + # automatic width + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan$&/; + } else { + # catch cases where the \textwidth has been discarded + $rwidth =~s!^(\w)($OP\d+$CP)\s*(\d|\d*\.\d+)\2$!$1\{$3\\textwidth\}!; + ($pxs,$rwidth) = &convert_length($rwidth); + $colspec =~ s/>$content_mark/ ROWSPAN=$rowspan WIDTH=$pxs$&/; + } $text = &styled_text_chunk('SPAN','mrow','','','','', $_); $text = &translate_commands($text) if ($text =~ /\\/); @@ -1335,7 +1335,7 @@ , '' , &process_undefined_environment("tex2html_wrap_inline", $id, $saved) , '' ); - } else { $_ = join('', $comment, $labels, $_ ) } + } else { $_ = join('', $comment, $labels, $_ ); } if ($border||($attributes)) { &make_table( $border, $attribs, '', '', '', $_ ) } else { $_ } diff -Naur latex2html-2018.2.orig/versions/unicode.pl latex2html-2018.2/versions/unicode.pl --- latex2html-2018.2.orig/versions/unicode.pl 2018-05-16 22:31:33.000000000 +0700 +++ latex2html-2018.2/versions/unicode.pl 2020-11-10 21:42:48.660079644 +0700 @@ -70,9 +70,11 @@ # MRO: by reference; local(*_) = @_; my $char, $uchar; return($_[0]) if ($NO_UTF && !$USE_UTF); - $_[0] =~ s/([\200-\377])/$char="\&#".ord($1).";"; + $_[0] = decode_utf8($_[0]); # enable unicode matches + $_[0] =~ s/([\N{U+0080}-\N{U+FFFF}])/$char="\&#".ord($1).";"; $unicode_table{$char}||$char /eg; + $_[0] = encode_utf8($_[0]); # and convert back to UTF # $uchar = $unicode_table{$char};($uchar ? $uchar : $char)/eg; }