--- loncom/xml/londefdef.pm 2005/07/07 10:09:50 1.277 +++ loncom/xml/londefdef.pm 2005/12/23 00:12:32 1.305 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Tags Default Definition Module # -# $Id: londefdef.pm,v 1.277 2005/07/07 10:09:50 foxr Exp $ +# $Id: londefdef.pm,v 1.305 2005/12/23 00:12:32 foxr Exp $ # # # Copyright Michigan State University Board of Trustees @@ -47,7 +47,8 @@ use Image::Magick; use Apache::lonmenu(); use Apache::lonmeta(); use Apache::Constants qw(:common); - +use File::Basename; +# use Data::Dumper; BEGIN { @@ -55,6 +56,20 @@ BEGIN { } +# +# Dumps all elements of the table structure. +# Need this 'cause evidently when given an array, Data::Dumper only seems +# to dump element 0. +# +#sub debug_dump_table { +# my $lastrow = $#Apache::londefdef::table; +# &Apache::lonnet::logthis("Dumping table: Last row index: $lastrow"); +# my $row; +# for ($row =0; $row <= $lastrow; $row++ ) { +# my $text = Dumper($Apache::londefdef::table[$row]); +# &Apache::lonnet::logthis("table [ $row ]".$text); +# } +#} sub initialize_londefdef { $Apache::londefdef::TD_redirection=0; @Apache::londefdef::table = (); @@ -109,8 +124,8 @@ sub start_m { # detect simple math mode entry exits, and convert them # to use \ensuremath if ($currentstring=~/^\s*\$[^\$].*[^\$]\$\s*$/) { - $currentstring=~s/^\$//; - $currentstring=~s/\$$//; + $currentstring=~s/^(\s*)\$/$1/; + $currentstring=~s/\$(\s*)$/$1/; $currentstring='\ensuremath{'.$currentstring.'}'; } $Apache::lonxml::post_evaluate=0; @@ -128,10 +143,11 @@ sub end_m { } sub start_tthoption { - my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; my $result; if ($target eq 'web') { - my $inside = &Apache::lonxml::get_all_text("/tthoption",$parser); + my $inside = &Apache::lonxml::get_all_text("/tthoption",$parser, + $style); $inside=~s/^\s*//; if ($env{'browser.mathml'}) { &tth::ttmoptions($inside); @@ -166,6 +182,7 @@ sub start_html { '\usepackage{textcomp}'. '\usepackage{makeidx}'. '\usepackage[dvips]{graphicx}'. + '\usepackage{wrapfig}'. '\usepackage{picins}'. '\usepackage{epsfig}'. '\usepackage{calc}'. @@ -367,13 +384,13 @@ sub end_title { #-- tag (end tag forbidden) sub start_meta { - my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; my $currentstring = ''; if ($target eq 'web') { my $args=''; if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } if ($args eq '') { - &Apache::lonxml::get_all_text("/meta",$parser); + &Apache::lonxml::get_all_text("/meta",$parser,$style); } else { $currentstring = $token->[4]; } @@ -436,7 +453,7 @@ sub end_meta { # accessrule sub start_accessrule { - my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; my $currentstring = ''; my $eff=&Apache::lonxml::get_param ('effect',$parstack,$safeeval,undef,1); @@ -455,7 +472,7 @@ sub start_accessrule { my $args=''; if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } if ($args eq '') { - &Apache::lonxml::get_all_text("/accessrule",$parser); + &Apache::lonxml::get_all_text("/accessrule",$parser,$style); } else { $currentstring = $token->[4]; } @@ -535,23 +552,25 @@ sub start_body { $token->[2]->{'onunload'}=&Apache::lonmenu::unloadevents(). ';'.$onUnload; - if ($env{'request.state'} ne 'construct') { - $currentstring .= '<'.$token->[1]; - } + $currentstring .= '<'.$token->[1]; foreach (keys %{$token->[2]}) { $currentstring.=' '.$_.'="'.$token->[2]->{$_}.'"'; } - if ($env{'request.state'} ne 'construct') { - $currentstring.='>'; + $currentstring.='>'; + &Apache::lontexconvert::jsMath_reset(); + if ($env{'environment.texengine'} eq 'jsMath') { + $currentstring.=&Apache::lontexconvert::jsMath_header(); } if ($env{'request.state'} ne 'published') { - my $remote=($env{'environment.remote'} ne 'off'); - $currentstring=&Apache::loncommon::bodytag(undef,undef, - $currentstring,$remote); + if ($env{'environment.remote'} eq 'off') { + $currentstring.= + &Apache::lonmenu::constspaceform(). + &Apache::lonmenu::menubuttons(1,'web',1); + } $currentstring.=(< - - +
+ +
EDITBUTTON } else { $currentstring.=&Apache::lonmenu::menubuttons(undef,$target,1); @@ -565,7 +584,7 @@ EDITBUTTON sub end_body { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off unclosed

+ my $currentstring = &end_p(); # Close off unclosed

if ($target eq 'web') { $currentstring .= &Apache::lonxml::xmlend($target,$parser); } elsif ($target eq 'tex') { @@ -577,7 +596,7 @@ sub end_body { #--

tag (end tag required) sub start_center { my ($target,$token) = @_; - my $currentstring = &end_p; # Close off any prior para. + my $currentstring = &end_p(); # Close off any prior para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -598,13 +617,15 @@ sub end_center { } #-- tag (end tag required) +# NOTE: In TeX mode disables internal

sub start_b { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web') { $currentstring = $token->[4]; } elsif ($target eq 'tex') { - $currentstring = '\textbf{'; + &disable_para(); + $currentstring .= '\textbf{'; } return $currentstring; } @@ -615,18 +636,21 @@ sub end_b { if ($target eq 'web') { $currentstring = $token->[2]; } elsif ($target eq 'tex') { - $currentstring = '}'; + &enable_para(); + $currentstring = '}'; } return $currentstring; } #-- tag (end tag required) +# NOTE: in TeX mode disables internal

sub start_strong { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web') { $currentstring = $token->[4]; } elsif ($target eq 'tex') { + &disable_para(); $currentstring = '\textbf{'; } return $currentstring; @@ -638,6 +662,7 @@ sub end_strong { if ($target eq 'web') { $currentstring = $token->[2]; } elsif ($target eq 'tex') { + &enable_para(); $currentstring = '}'; } return $currentstring; @@ -646,7 +671,7 @@ sub end_strong { #--

tag (end tag required) sub start_h1 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior para. + my $currentstring = &end_p(); # Close off any prior para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -695,7 +720,7 @@ sub end_h1 { #--

tag sub start_h2 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior para. + my $currentstring = &end_p(); # Close off any prior para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -738,7 +763,7 @@ sub end_h2 { #--

tag sub start_h3 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior para. + my $currentstring = &end_p(); # Close off any prior para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -781,7 +806,7 @@ sub end_h3 { #--

tag sub start_h4 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior para. + my $currentstring = &end_p(); # Close off any prior para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -824,7 +849,7 @@ sub end_h4 { #--

tag sub start_h5 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior paras. + my $currentstring = &end_p(); # Close off any prior paras. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -867,7 +892,7 @@ sub end_h5 { #--
tag sub start_h6 { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off any prior paras. + my $currentstring = &end_p(); # Close off any prior paras. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1125,15 +1150,34 @@ sub end_q { my $closing_string = ''; # String required to close

+# Some tags are

fragile meaning that

inside of them +# does not work within TeX mode. This is managed via the +# counter below: +# + + my $para_disabled = 0; + +sub disable_para { + $para_disabled++; +} +sub enable_para { + $para_disabled--; +} + + #--

tag (end tag optional) #optional attribute - align="center|left|right" sub start_p { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # close off prior para if in progress. + my $currentstring = ''; if ($target eq 'web') { + $currentstring .= &end_p(); # close off prior para if in progress. $currentstring .= $token->[4]; - $closing_string = '

'; # Not sure this is correct. - } elsif ($target eq 'tex') { + if (! ($currentstring =~ /\//)) { + $closing_string = '

'; # Deal correctly with

e.g. + } + } elsif ($target eq 'tex' && !$para_disabled) { + $currentstring .= &end_p(); # close off prior para if in progress. my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); if ($align eq 'center') { $currentstring .='\begin{center}\par'; @@ -1146,18 +1190,8 @@ sub start_p { $closing_string = '}\hfill}'; } else { $currentstring.='\par '; - $closing_string = '\strut\\\\\strut'; + $closing_string = '\strut\\\\\strut '; } - my $signal=1;#

does not work inside ... - foreach my $tag (@$tagstack) { - if (lc($tag) eq 'b') { - $signal=0; - } - } - if (!$signal) { - $currentstring = &end_p; # Just close the prior? Not sure this is correct - $closing_string = ''; # Probably correct? - } } return $currentstring; @@ -1166,9 +1200,16 @@ sub start_p { # End paragraph processing just requires that we output the # closing string that was saved and blank it. sub end_p { - my $current_string = $closing_string; - $closing_string = ''; # Not in a para anymore. - return $current_string; + # Note only 'tex' mode uses disable_para and enable_para + # so we don't need to know the target in the check below: + + if (!$para_disabled) { + my $current_string = $closing_string; + $closing_string = ''; # Not in a para anymore. + return $current_string; + } else { + return ''; + } } } @@ -1181,6 +1222,9 @@ sub start_br { } elsif ($target eq 'tex') { my @tempo=@$tagstack; my $signal=0; + # Not going to factor this to is_inside_of since that would require + # multiple stack traversals. + # for (my $i=$#tempo;$i>=0;$i--) { if (($tempo[$i] eq 'b') || ($tempo[$i] eq 'strong') || ($tempo[$i] eq 'ol') || ($tempo[$i] eq 'ul') || @@ -1417,7 +1461,7 @@ sub end_sup { #--


tag (end tag forbidden) sub start_hr { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # End enclosing para. + my $currentstring = &end_p(); # End enclosing para. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1455,12 +1499,44 @@ sub end_hr { } #--
tag (end tag required) +{ + +# Since div can be nested, the stack below is used +# in 'tex' mode to store the ending strings +# for the div stack. + + my @div_end_stack; + sub start_div { - my ($target,$token) = @_; - my $currentstring = &end_p; # Close enclosing para. + my ($target,$token, $tagstack, $parstack, $parser, $safeeval) = @_; + my $currentstring = &end_p(); # Close enclosing para. if ($target eq 'web') { $currentstring .= $token->[4]; } + if ($target eq 'tex') { + # 4 possible alignments: left, right, center, and -missing-. + + my $endstring = ''; + + my $align = lc(&Apache::lonxml::get_param('align', $parstack, + $safeeval, undef, 1)); + if ($align eq 'center') { + $currentstring .= '\begin{center}'; + $endstring = '\end{center}'; + } + elsif ($align eq 'right') { + $currentstring .= '\begin{flushright}'; + $endstring .= '\end{flushright}'; + } elsif ($align eq 'left') { + $currentstring .= '\begin{flushleft}'; + $endstring = '\end{flushleft}'; + } else { + + } + $currentstring .= "\n"; # For human readability. + $endstring = "\n$endstring\n"; # For human readability + push(@div_end_stack, $endstring); + } return $currentstring; } @@ -1469,9 +1545,14 @@ sub end_div { my $currentstring = ''; if ($target eq 'web') { $currentstring .= $token->[2]; - } + } + if ($target eq 'tex') { + my $endstring = pop @div_end_stack; + $currentstring .= $endstring; + } return $currentstring; } +} #-- tag (end tag required) sub start_a { @@ -1539,7 +1620,7 @@ sub start_li { sub end_li { my ($target,$token) = @_; - my $currentstring = &end_p; # In case there's a

in the

  • + my $currentstring = &end_p(); # In case there's a

    in the

  • if ($target eq 'web') { $currentstring .= $token->[2]; } @@ -1575,7 +1656,7 @@ sub end_u { #--
      tag (end tag required) sub start_ul { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close off enclosing list. + my $currentstring = &end_p(); # Close off enclosing list. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1642,7 +1723,7 @@ sub end_menu { #-- tag (end tag required) sub start_dir { my ($target,$token) = @_; - my $currentstring = &end_p; # In case there's a

      prior to the list. + my $currentstring = &end_p(); # In case there's a

      prior to the list. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1665,7 +1746,7 @@ sub end_dir { #--

        tag (end tag required) sub start_ol { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # In case there's a

        prior to the list. + my $currentstring = &end_p(); # In case there's a

        prior to the list. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1719,7 +1800,7 @@ sub end_ol { #--

        tag (end tag required) sub start_dl { my ($target,$token) = @_; - my $currentstring = &end_p; # In case there's a

        unclosed prior to the list. + my $currentstring = &end_p(); # In case there's a

        unclosed prior to the list. if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1835,7 +1916,7 @@ sub end_dd { sub start_table { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $textwidth = ''; - my $currentstring = &end_p; + my $currentstring = &end_p(); if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -1859,24 +1940,25 @@ sub start_table { } } } + + # width either comes forced from the TeXwidth or the width parameters. + # in either case it can be a percentage or absolute width. + my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); if (not defined $TeXwidth) { - my $htmlwidth = &Apache::lonxml::get_param('width',$parstack,$safeeval,undef,1); - if ($htmlwidth=~/%/) { - $Apache::londefdef::table[-1]{'percent'}=1; - $htmlwidth=~/(\d+)/; - $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100;; - } else { - $Apache::londefdef::table[-1]{'width'}=$textwidth; - } - } elsif ($TeXwidth=~/%/) { + $TeXwidth = &Apache::lonxml::get_param('width',$parstack,$safeeval,undef,1); + + } else { + $Apache::londefdef::table[-1]{'forcedtablewidth'} = 1; + } + if ($TeXwidth=~/%/) { $Apache::londefdef::table[-1]{'percent'}=1; $TeXwidth=~/(\d+)/; $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100; } else { - $Apache::londefdef::table[-1]{'forcetablewidth'}=1; $Apache::londefdef::table[-1]{'width'}=$TeXwidth; } + #table's border my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval); my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0); @@ -1891,7 +1973,9 @@ sub start_table { $Apache::londefdef::table[-1]{'vvinc'} = ''; } if ($#Apache::londefdef::table==0) { - $Apache::londefdef::table[-1]{'output'}='\strut\newline\strut\setlength{\tabcolsep}{1 mm}'; + # Note that \newline seems to destroy the alignment envs. + # $Apache::londefdef::table[-1]{'output'}='\strut\newline\strut\setlength{\tabcolsep}{1 mm}'; + $Apache::londefdef::table[-1]{'output'}='\strut'.'\\\\'."\n".'\strut\setlength{\tabcolsep}{1 mm}'; } $Apache::londefdef::table[-1]{'output'}.=' \noindent \begin{tabular} '; $Apache::londefdef::table[-1]{'TeXlen'}=[]; @@ -1902,7 +1986,9 @@ sub start_table { $Apache::londefdef::table[-1]{'content'}=[]; $Apache::londefdef::table[-1]{'align'}=[]; $currentstring.='\keephidden{NEW TABLE ENTRY}'; - } + + + } return $currentstring; } @@ -1915,7 +2001,9 @@ sub end_table { my $inmemory = ''; my $output = ''; my $WARNING=''; + # &debug_dump_table($Apache::londefdef::table[-1]); #width of columns from TeXwidth attributes + for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]<$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn]) { @@ -2099,24 +2187,69 @@ sub end_table { #fill the table for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { for (my $jn=0;$jn<=$#fwidth;$jn++) { + # + # Do the appropriate magic if this has a colspan + # + my $colspan = $Apache::londefdef::table[-1]{'colspan'}[$in][$jn]; + if ($colspan > 1) { + $output .= '\multicolumn{'. + $colspan + .'}{|l|}{'; + } if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { - $output.='\vspace*{-6 mm}\begin{center}'; + # $output.='\vspace*{-6 mm}\begin{center}'; + $output.='\begin{center}'; } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { $output.=' \hfill \llap{' } $output.=$Apache::londefdef::table[-1]{'content'}[$in][$jn]; if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { - $output.='\end{center}\vspace*{-6 mm}'; + # $output.='\end{center}\vspace*{-6 mm}'; + $output.='\end{center}'; } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { $output.='} '; } + # Close off the colspan... + # + if ($colspan > 1) { + $output .= '}'; + $jn += $colspan-1; # Adjust for number of rows really left. + } if ($jn!=$#fwidth) {$output.=' '.$Apache::londefdef::table[-1]{'vinc'};} } $output.=' \\\\ '.$Apache::londefdef::table[-1]{'hinc'}.' '; } - $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut\newline\strut '; + # Note that \newline destroys alignment env's produced by e.g.

        + # $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut\newline\strut '; + $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut'.'\\\\'."\n".'\strut '; if ($#Apache::londefdef::table > 0) { my $inmemory = $Apache::londefdef::table[-1]{'output'}; + # Figure out max/and min width by summing us and then + # apply that to the current column of the table we nest in + # if it's larger than the current width or the current width + # is undefined. + # + my $min_nested_width = 0; + my $max_nested_width = 0; + for (my $col = 0; $col <= $Apache::londefdef::table[-1]{'counter_columns'}; $col++) { + $min_nested_width += $min_len[$col]; + $max_nested_width += $max_len[$col]; + + } + # Fudge in an extra 5 mm for borders etc: + + $min_nested_width += 5; + $max_nested_width += 5; + + my $outer_column = $Apache::londefdef::table[-2]{'counter_columns'}; + my $outer_row = $Apache::londefdef::table[-2]{'row_number'}; + if ($min_nested_width > $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column]) { + $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column] = $min_nested_width; + } + if ($max_nested_width > $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column]) { + $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column] = $max_nested_width; + } + pop @Apache::londefdef::table; push @{$Apache::londefdef::table[-1]{'include'}}, $inmemory; } else { @@ -2143,6 +2276,10 @@ sub start_tr { push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l'; } push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'}); + # + # Need to save the number of table columns to preserve the max # columns. + # + $Apache::londefdef::table[-1]{'prior_columns'} = $Apache::londefdef::table[-1]{'counter_columns'}; $Apache::londefdef::table[-1]{'counter_columns'} = -1; push @ {$Apache::londefdef::table[-1]{'TeXlen'}}, []; push @ {$Apache::londefdef::table[-1]{'objectlen'}}, []; @@ -2155,13 +2292,21 @@ sub start_tr { sub end_tr { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close any pending

        in the row. + my $currentstring = &end_p(); # Close any pending

        in the row. if ($target eq 'web') { $currentstring .= $token->[2]; } elsif ($target eq 'tex') { if ($Apache::londefdef::TD_redirection) { &end_td_tex($parstack,$parser,$safeeval); } + # Counter columns must be the maximum number of columns seen + # in the table so far so: + if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) { + $Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'}; + } + + + } return $currentstring; } @@ -2216,8 +2361,38 @@ sub start_td_tex { sub end_td_tex { my ($parstack,$parser,$safeeval) = @_; - my $current_row = $Apache::londefdef::table[-1]{'row_number'}; - my $data=&Apache::lonxml::endredirection(); + my $current_row = $Apache::londefdef::table[-1]{'row_number'}; + my $current_column = $Apache::londefdef::table[-1]{'counter_columns'}; + my $data = &Apache::lonxml::endredirection(); + + # The rowspan array of the table indicates which cells are part of a span. + # n indicates the start of a span set of n rows. + # ^ indicates a cell that continues a span set. + # If this and subsequent cells are part of a rowspan, we must + # push along the row until we find one that is not. + + while ((defined $Apache::londefdef::table[-1]{'rowspan'}[$current_row] [$current_column]) + && $Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column] eq '^') { + # Part of a span. + push @ {$Apache::londefdef::table[-1]{'content'}[-1]}, ''; + $current_column++; + } + $Apache::londefdef::table[-1]{'counter_columns'} = $current_column; + + + + my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 0); + if (!$rowspan) { + $rowspan = 1; + } + + + + $Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column] = $rowspan; + for (my $i = 1; $i < $rowspan; $i++) { + $Apache::londefdef::table[-1]{'rowspan'}[$current_row+$i][$current_column] = '^'; + } + my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); if (defined $TeXwidth) { push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; @@ -2294,11 +2469,47 @@ sub end_td_tex { push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length; } } - for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) { - $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/; - } + # Substitute all of the tables nested in this cell in their appropriate places. + + + my $nested_count = $#{$Apache::londefdef::table[-1]{'include'}}; # This one is constant... + for (my $in=0; $in<=$nested_count; $in++) { + my $nested = shift @{$Apache::londefdef::table[-1]{'include'}}; + $nested =~ s/\\end\{tabular\}\\strut\\\\/\\end\{tabular\}/; + # $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/; + $data =~ s/\\keephidden\{NEW TABLE ENTRY\}/$nested/; + + } + # Should be be killing off the 'include' elements as they're used up? + push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data; - return''; + + # Get the column and row spans. + # Colspan can be done via \multicolumn if I can figure out the data structs. + + my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 0); + if (!$colspan) { + $colspan = 1; + } + + + # the colspan array will indicate how many columns will be spanned by this + # cell..this requires that counter_columns also be adjusted accordingly + # so that the next bunch of text goes in the right cell. Note that since + # counter_columns is incremented in the start_td_tex, we adjust by colspan-1. + # + + $Apache::londefdef::table[-1]{'colspan'}[$current_row][$current_column] = $colspan; + $Apache::londefdef::table[-1]{'counter_columns'} += $colspan -1; + + # Put empty text in spanned cols. + + for (my $i = 0; $i < ($colspan -1); $i++) { + push @ {$Apache::londefdef::table[-1]{'content'}[-1] },''; + } + + + return ''; } sub end_td { @@ -2432,7 +2643,7 @@ sub end_th_tex { sub end_th { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # Close any open

        in the row. + my $currentstring = &end_p(); # Close any open

        in the row. if ($target eq 'web') { $currentstring .= $token->[2]; } elsif ($target eq 'tex') { @@ -2454,14 +2665,14 @@ sub end_th { # (Note there seems to also be support for this as a % of page size) # sub start_img { - my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval, undef,1); if (not $src and ($target eq 'web' or $target eq 'tex')) { - my $inside = &Apache::lonxml::get_all_text("/img",$parser); + my $inside = &Apache::lonxml::get_all_text("/img",$parser,$style); return ''; } - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$src; + &Apache::lonxml::extlink($src); my $currentstring = ''; my $scaling = .3; @@ -2494,7 +2705,11 @@ sub start_img { $safeeval, undef,1)); if(!$align) { - $align = "bottom"; # This is html's default so it's ours too. + if (&is_inside_of($tagstack, "table")) { + $align = "right"; # Force wraptext use. + } else { + $align = "bottom"; # This is html's default so it's ours too. + } } # &Apache::lonxml::debug("Alignemnt = $align"); @@ -2511,7 +2726,7 @@ sub start_img { undef,0); &Apache::lonxml::debug("LaTeX rendering = $latex_rendering"); if(!$latex_rendering) { - $latex_rendering = "parbox"; + $latex_rendering = "texwrap"; } &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src"); @@ -2552,16 +2767,17 @@ sub start_img { } elsif ($align eq "left") { if ($latex_rendering eq "parpic") { $currentstring = '\parpic[l]{'.$currentstring.'}'; - } else { # parbox rendering - $currentstring = "\\strut\\newline\n". - '\parbox{'.$width_param.'mm}{'.$currentstring.'}'; + } else { # wrapfig render + $currentstring = '\begin{wrapfigure}{l}{'.$width_param.'mm}' + .'\scalebox{1.0}{'.$currentstring.'}\end{wrapfigure}'; } } elsif ($align eq "right") { if ($latex_rendering eq "parpic") { $currentstring = '\parpic[r]{'.$currentstring.'}'; - } else { # parbox rendering. - $currentstring = '\parbox{'.$width_param.'mm}{\begin{flushright}' - .$currentstring.'\end{flushright}} \newline'."\n"; + } else { # wrapfig rendering + $currentstring = '\begin{wrapfigure}{r}{'.$width_param.'mm}' + .'\scalebox{1.0}{'.$currentstring.'}\end{wrapfigure}'; + } } else { # Bottom is also default. # $currentstring = '\raisebox{'.$height_param.'mm}{'.$currentstring.'}'; @@ -2666,12 +2882,10 @@ sub start_applet { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,undef,1); - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$code; - + &Apache::lonxml::extlink($code); my $archive=&Apache::lonxml::get_param('archive',$parstack,$safeeval, undef,1); - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$archive; - + &Apache::lonxml::extlink($archive); my $currentstring = ''; if ($target eq 'web') { if ($env{'browser.appletsuppress'} ne 'on') { @@ -2717,7 +2931,7 @@ sub end_applet { sub start_embed { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$src; + &Apache::lonxml::extlink($src); my $currentstring = ''; if ($target eq 'web') { if ($env{'browser.embedsuppress'} ne 'on') { @@ -2748,13 +2962,15 @@ sub end_embed { #-- tag (end tag forbidden) sub start_param { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - if (&Apache::lonxml::get_param - ('name',$parstack,$safeeval,undef,1)=~/^cabbase$/i) { - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]= - &Apache::lonxml::get_param('value',$parstack,$safeeval,undef,1); - } - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]= - &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); + if (&Apache::lonxml::get_param('name',$parstack, + $safeeval,undef,1)=~/^cabbase$/i) { + my $value=&Apache::lonxml::get_param('value',$parstack, + $safeeval,undef,1); + &Apache::lonxml::extlink($value); + } + + my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); + &Apache::lonxml::extlink($src); my $currentstring = ''; if ($target eq 'web') { my %toconvert; @@ -2786,9 +3002,8 @@ sub end_param { sub start_allow { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); - $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); - $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]= - &Apache::lonnet::clutter($src); + &Apache::lonxml::extlink($src); + if ($target eq 'tex') { &image_replication($src); } my $result; if ($target eq 'edit') { @@ -2882,7 +3097,7 @@ sub end_xmp { #--

         (end tag required)
         sub start_pre {
             my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
        -    my $currentstring = &end_p;	# close off pending 

        + my $currentstring = &end_p(); # close off pending

        if ($target eq 'web') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { @@ -2945,7 +3160,7 @@ sub end_externallink { #-- sub start_blankspace { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; - my $currentstring = &end_p; # closes off any unclosed

        + my $currentstring = &end_p(); # closes off any unclosed

        if ($target eq 'tex') { my $howmuch = &Apache::lonxml::get_param('heigth',$parstack,$safeeval,undef,1); $currentstring .= '\vskip '.$howmuch.' '; @@ -3098,7 +3313,7 @@ sub end_blink { #--

        tag (end tag required) sub start_blockquote { my ($target,$token) = @_; - my $currentstring = &end_p; # Close any unclosed

        + my $currentstring = &end_p(); # Close any unclosed

        if ($target eq 'web') { $currentstring .= $token->[4]; } @@ -3382,9 +3597,12 @@ sub end_legend { #-- tag (end tag forbidden) sub start_link { - my ($target,$token) = @_; + my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $currentstring = ''; if ($target eq 'web') { + my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval, + undef,1); + &Apache::lonxml::extlink($href); $currentstring = $token->[4]; } return $currentstring; @@ -3421,7 +3639,7 @@ sub end_marquee { #-- tag (end tag required) sub start_multicol { my ($target,$token) = @_; - my $currentstring = &end_p; # Close any pending

        + my $currentstring = &end_p(); # Close any pending

        if ($target eq 'web') { $currentstring .= $token->[4]; } @@ -3619,7 +3837,7 @@ sub end_server { #-- tag (end tag forbidden) sub start_spacer { my ($target,$token) = @_; - my $currentstring = &end_p; # Close off any open

        tag. + my $currentstring = &end_p(); # Close off any open

        tag. if ($target eq 'web') { $currentstring .= $token->[4]; } @@ -3900,7 +4118,15 @@ sub image_height { sub get_eps_image { my ($src)=@_; my $orig_src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1], $src); + + # In order to prevent the substitution of the alt text, we need to + # be sure the orig_src file is on system now so: + + if (! -e $orig_src) { + &Apache::lonnet::repcopy($orig_src); # Failure is not completely fatal. + } &Apache::lonxml::debug("get_eps_image: Original image: $orig_src"); + my ($spath, $sname, $sext) = fileparse($src, qr/\.(gif|png|jpg|jpeg)/i); $src=~s/\.(gif|png|jpg|jpeg)$/\.eps/i; $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); &Apache::lonxml::debug("Filelocation gives: $src"); @@ -3929,6 +4155,9 @@ sub get_eps_image { close FILE; $src=~s|/home/httpd/html/res|/home/httpd/prtspool|; $src=~s|/home/([^/]*)/public_html/|/home/httpd/prtspool/$1/|; + if ($sext ne "") { # Put the ext. back in to uniquify. + $src =~ s/\.eps$/$sext.eps/; + } } } } @@ -3968,7 +4197,11 @@ sub file_path { } return $file,$path; } - +# Converts a measurement in to mm from any of +# the other valid LaTeX units of measure. +# If the units of measure are missing from the +# parameter, it is assumed to be in and returned +# with mm units of measure sub recalc { my $argument = shift; if (not $argument=~/(mm|cm|in|pc|pt)/) {return $argument.' mm';} @@ -4013,6 +4246,26 @@ sub LATEX_length { } +# is_inside_of $tagstack $tag +# This sub returns true if the current state of Xml processing +# is inside of the tag. +# Parameters: +# tagstack - The tagstack from the parser. +# tag - The tag (without the <>'s.). +# Sample usage: +# if (is_inside_of($tagstack "table")) { +# # I'm in a table.... +# } +sub is_inside_of { + my ($tagstack, $tag) = @_; + my @stack = @$tagstack; + for (my $i = ($#stack - 1); $i >= 0; $i--) { + if ($stack[$i] eq $tag) { + return 1; + } + } + return 0; +} 1;