--- loncom/xml/londefdef.pm 2006/09/19 10:57:11 1.337 +++ loncom/xml/londefdef.pm 2008/12/11 23:57:04 1.396.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Tags Default Definition Module # -# $Id: londefdef.pm,v 1.337 2006/09/19 10:57:11 foxr Exp $ +# $Id: londefdef.pm,v 1.396.2.1 2008/12/11 23:57:04 raeburn Exp $ # # # Copyright Michigan State University Board of Trustees @@ -46,8 +46,10 @@ use Apache::File(); use Image::Magick; use Apache::lonmenu(); use Apache::lonmeta(); +use Apache::lonlocal; use Apache::Constants qw(:common); use File::Basename; +use LONCAPA(); # use Data::Dumper; BEGIN { @@ -105,13 +107,13 @@ sub start_m { my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval); if ($eval eq 'on') { $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]); - #&Apache::lonxml::debug("M is evaulated to:$inside:"); + #&Apache::lonxml::debug("M is evaluated to:$inside:"); } my $tex = $inside; my $display=&Apache::lonxml::get_param('display',$parstack,$safeeval); $currentstring = &Apache::lontexconvert::converted(\$inside,$display); if ($Apache::lontexconvert::errorstring) { - my $errormsg='
'.&HTML::Entities::encode($Apache::lontexconvert::errorstring,'<>&"').'
occured while attempting to convert this TeX:
';
+	    my $errormsg='
'.&HTML::Entities::encode($Apache::lontexconvert::errorstring,'<>&"').'
occurred while attempting to convert this TeX:
';
 	    $tex = &HTML::Entities::encode($tex,'<>&"');
 	    my ($linenumber) =
 		($Apache::lontexconvert::errorstring =~ /Line (\d+)/);
@@ -127,6 +129,7 @@ sub start_m {
 	#&Apache::lonxml::debug("M is ends with:$currentstring:");
 	$Apache::lonxml::post_evaluate=0;
     } elsif ($target eq 'tex') {
+
 	$currentstring = $inside;
 	my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
 	if ($eval eq 'on') {
@@ -134,11 +137,13 @@ sub start_m {
 	}
 	if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}
 	# detect simple math mode entry exits, and convert them
-        # to use \ensuremath
-	if ($currentstring=~/^\s*\$[^\$].*[^\$]\$\s*$/) {
-	    $currentstring=~s/^(\s*)\$/$1/;
-	    $currentstring=~s/\$(\s*)$/$1/;
-	    $currentstring='\ensuremath{'.$currentstring.'}';
+        # to use \ensuremath ... unless there's a \verb inside.
+	if (! ($currentstring=~/\\verb/)) {
+	    if ($currentstring=~/^\s*\$[^\$].*\$\s*$/) {
+		$currentstring=~s/^(\s*)\$/$1/;
+		$currentstring=~s/\$(\s*)$/$1/;
+		$currentstring='\ensuremath{'.$currentstring.'}';
+	    }
 	}
 	$Apache::lonxml::post_evaluate=0;
     }
@@ -196,14 +201,20 @@ sub start_html {
                           '\usepackage[dvips]{graphicx}'.
 			  '\usepackage{wrapfig}'.
 			  '\usepackage{picins}'.
+			  '\usepackage[T1]{fontenc}'."\n".
+                          '\usepackage{lmodern}'."\n".
+			  '\usepackage[postscript]{ucs}'."\n".
+			  '\usepackage[utf8x]{inputenc}'."\n".
+			  '\usepackage{pifont}' ."\n".
+			  '\usepackage{latexsym}'."\n".
                           '\usepackage{epsfig}'.
                           '\usepackage{calc}'.
                           '\usepackage{amsmath}'.
                           '\usepackage{amssymb}'.
                           '\usepackage{amsfonts}'.
-                          '\usepackage{amsthm}'.
-                          '\usepackage{amscd}'.
-                          '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'.
+                          '\usepackage{amsthm}';
+
+        $currentstring .= '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'.
                           '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}';
     }
     return $currentstring;
@@ -444,6 +455,16 @@ sub start_meta {
 	if ((not defined $content) && (not defined $name)) {
 	    &Apache::lonxml::startredirection();
 	}
+    } elsif ($target eq 'edit') {
+	$currentstring .= &Apache::edit::tag_start($target,$token);
+	$currentstring .= &Apache::edit::text_arg('Name:','name',$token,30);
+	$currentstring .= &Apache::edit::text_arg('Content:','content',$token,70);
+	$currentstring .= &Apache::edit::end_row();
+    } elsif ($target eq 'modified') {
+	my $constructtag =
+	    &Apache::edit::get_new_args($token,$parstack,$safeeval,
+					'name','content');
+	if ($constructtag) { $currentstring = &Apache::edit::rebuild_tag($token); }
     }
     return $currentstring;
 }
@@ -467,23 +488,38 @@ sub end_meta {
     return $currentstring;
 }
 
+sub insert_meta {
+    return '
+    ';
+}
+
 # accessrule
 sub start_accessrule {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';
-    my $eff=&Apache::lonxml::get_param
-	('effect',$parstack,$safeeval,undef,1);
-    my $realm=&Apache::lonxml::get_param
-	('realm',$parstack,$safeeval,undef,1);
-    my $role=&Apache::lonxml::get_param
-	('role',$parstack,$safeeval,undef,1);
-    $realm=~s/\s+//g;
-    $realm=~s/\//\_/g;
-    $realm=~s/^\_//;
-    $realm=~s/\W/\;/g;
-    $role=~s/\s+//g;
-    $role=~s/\//\_/g;
-    $role=~s/\W/\;/g;
+    my $eff  =&Apache::lonxml::get_param('effect',$parstack,$safeeval,undef,1);
+    my $realm=&Apache::lonxml::get_param('realm', $parstack,$safeeval,undef,1);
+    my $role =&Apache::lonxml::get_param('role',  $parstack,$safeeval,undef,1);
+    my $type =&Apache::lonxml::get_param('type',  $parstack,$safeeval,undef,1);
+
+    my ($dom,$crs,$sec,$separator);
+    if ($type eq 'user') {
+	($dom,$crs,$sec)=split(m{/},$realm);
+	$crs = &LONCAPA::clean_username($crs);
+	$separator = '/';
+    } else {
+	($dom,$crs,$sec)=split(/\_/,$realm);
+	$crs = &LONCAPA::clean_courseid($crs);
+	$separator = '_';
+    }
+    $dom = &LONCAPA::clean_domain($dom);
+
+    $sec =~s/\W//;
+    $realm = $dom;
+    if ($crs =~ /\S/) { $realm .= $separator.$crs; }
+    if ($sec =~ /\S/) { $realm .= $separator.$sec; }
+    $role=~s/\W//g;
+
     if ($target eq 'web') {
 	my $args='';
 	if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
@@ -494,7 +530,7 @@ sub start_accessrule {
 	}
     }
     if ($target eq 'meta') {
-	$currentstring=''.$eff.':'.$realm.':'.$role.'';
+	$currentstring=''.$eff.':'.$realm.':'.$role.':'.$type.'';
     }
     return $currentstring;
 }
@@ -512,6 +548,17 @@ sub end_accessrule {
     return $currentstring;
 }
 
+sub generate_css_links {
+    my $links;
+    my $css_href = &Apache::lonnet::EXT('resource.0.cssfile');
+    if ($css_href =~ /\S/) {
+	&Apache::lonxml::extlink($css_href);
+	$links .= 
+	    '';
+    }
+    return $links;
+}
+
 #--  tag (end tag required)
 sub start_body {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
@@ -526,21 +573,20 @@ sub start_body {
 	if (&is_inside_of($tagstack, "head")) {
 	    &end_head(@_);
 	}
+	
+	my $extra_head = &generate_css_links();
+
 	$currentstring = 
 	    &Apache::loncommon::start_page($Apache::londefdef::title,
-					   $Apache::londefdef::head,
+					   $Apache::londefdef::head
+					      .$extra_head,
 					   {'add_entries'    => $token->[2],
 					    'no_title'       => 1,
 					    'force_register' => 1});
 
 	if ($env{'request.state'} ne 'published') {
 	    $currentstring.=&Apache::lonmenu::constspaceform();
-	    $currentstring.=(<
-
-
-
-EDITBUTTON + $currentstring.=&Apache::londefdef::edit_controls(); } $currentstring.=&Apache::lonxml::message_location(); } elsif ($target eq 'tex') { @@ -549,6 +595,20 @@ EDITBUTTON return $currentstring; } +sub edit_controls { + my $result .= ' +
+
+
'. +&Apache::lonxml::renderingoptions().' + +
+
+
+
'; + return $result; +} + sub end_body { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $currentstring = &end_p(); # Close off unclosed

@@ -1224,11 +1284,10 @@ sub start_br { $signal = 1; } } - if ($signal eq 1) { - $currentstring .= ' \vskip 0 mm '; - } elsif ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') { + if ($signal != 1) { $currentstring .= '\strut \\\\ \strut '; } + } return $currentstring; } @@ -1410,7 +1469,7 @@ sub start_sub { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { - $currentstring .= '\ensuremath{_{'; + $currentstring .= '\raisebox{-\smallskipamount}{\scriptsize{'; } return $currentstring; } @@ -1433,7 +1492,7 @@ sub start_sup { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { - $currentstring .= '\ensuremath{^{'; + $currentstring .= '\raisebox{\smallskipamount}{\scriptsize{'; } return $currentstring; } @@ -1456,6 +1515,27 @@ sub start_hr { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { + + #


can't be inside of thank you LaTeX. + # + my $restart_sub = 0; + my $restart_sup = 0; + + # Since and are simple tags it's ok to turn off/on + # using the start_ stop_ functions.. those tags only care about + # $target. + + if (&is_inside_of($tagstack, "sub")) { + $restart_sub = 1; + $currentstring .= &end_sub($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + if (&is_inside_of($tagstack, "sup")) { + $restart_sup = 1; + $currentstring .= &end_sup($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + my $LaTeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); if (defined $LaTeXwidth) { if ($LaTeXwidth=~/^%/) { @@ -1476,6 +1556,16 @@ sub start_hr { } $currentstring .= ' \vskip 0 mm \noindent\makebox['.$LaTeXwidth.']{'.$pre.'\makebox['. $LaTeXwidth.'][b]{\hrulefill}'.$post.'}\vskip 0 mm '; + # Turn stuff back on that we can't be inside of. + + if ($restart_sub) { + $currentstring .= &start_sub($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + if ($restart_sup) { + $currentstring .= &start_sup($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } } return $currentstring; } @@ -1506,6 +1596,9 @@ sub start_div { } if ($target eq 'tex') { # 4 possible alignments: left, right, center, and -missing-. + # If inside a table row, we must let the table logic + # do the alignment, however. + # my $endstring = ''; @@ -1516,6 +1609,7 @@ sub start_div { $endstring = '\end{center}'; if (&is_inside_of($tagstack, "table")) { $currentstring = ¢er_correction().$currentstring; + $endstring .= ¢er_end_correction(); } } elsif ($align eq 'right') { @@ -1556,17 +1650,6 @@ sub start_a { my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval, undef,1); $currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href}); - } elsif ($target eq 'tex') { - my $a=&Apache::lonxml::get_param('href',$parstack,$safeeval,undef,1); - my $b=&Apache::lonxml::get_param('name',$parstack,$safeeval,undef,1); - if ($a=~/\S/) { - $a=~s/([^\\])%/$1\\\%/g; - $currentstring .= '\ref{URI: '.$a.'}'; - } elsif ($b=~/\S/) { - $currentstring .= '\ref{Anchor: '.$b.'}'; - } else { - $currentstring.=''; - } } return $currentstring; } @@ -1577,6 +1660,28 @@ sub end_a { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[2]; } + if ($target eq 'tex') { + my $href = + &Apache::lonxml::get_param('href',$parstack,$safeeval,undef,1); + my $name = + &Apache::lonxml::get_param('name',$parstack,$safeeval,undef,1); + my $uriprint = + &Apache::lonxml::get_param('uriprint',$parstack,$safeeval,undef,1); + my $anchorprint = + &Apache::lonxml::get_param('anchorprint',$parstack,$safeeval,undef,1); + if (($href =~ /\S/) && ($uriprint=~/^on|uriprint|yes|1$/i)) { + $href =~ s/([^\\])%/$1\\\%/g; + # Substitute special symbols... and allow line breaks at each / + # + $href = &Apache::lonxml::latex_special_symbols($href); + $href =~ s/\//\/\\-/g; # Map / to /\- to allow hyphenation. + $currentstring .= ' ({\tt URI:'.$href.'})'; + } elsif (($name =~ /\S/) && ($anchorprint=~/^on|anchorprint|yes|1$/i)) { + $currentstring .= ' ({\tt Anchor:'.&Apache::lonxml::latex_special_symbols($name).'})'; + } else { + $currentstring.=''; + } + } return $currentstring; } @@ -1914,14 +2019,14 @@ sub start_table { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[4]; } elsif ($target eq 'tex') { - my $aa = {}; - push @Apache::londefdef::table, $aa; + &disable_para(); # Can't have paras in a table. + push(@Apache::londefdef::table, {}); $Apache::londefdef::table[-1]{'row_number'} = -1; #maximum table's width (default coincides with text line length) if ($#Apache::londefdef::table==0) { $textwidth=&recalc($env{'form.textwidth'}); #result is always in mm $textwidth=~/(\d+\.?\d*)/; - $textwidth=0.95*$1; #accounts "internal" LaTeX space for table frame + $textwidth=0.85*$1; #accounts "internal" LaTeX space for table frame } else { if ($Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]=~/\d/) { #the maximum width of nested table is determined by LATeX width of parent cell @@ -1947,11 +2052,11 @@ sub start_table { } else { $TeXwidth = $textwidth; } - } else { - $Apache::londefdef::table[-1]{'forcedtablewidth'} = 1; } + # if the width is specified as a % it is converted to an absolute width. + # otherwise.. just plugged right in the hash + if ($TeXwidth=~/%/) { - $Apache::londefdef::table[-1]{'percent'}=1; $TeXwidth=~/(\d+)/; $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100; } else { @@ -1962,7 +2067,6 @@ sub start_table { if ($Apache::londefdef::table[-1]{'width'} > $textwidth) { $Apache::londefdef::table[-1]{'width'} = $textwidth; } - #table's border my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval); my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0); @@ -1989,7 +2093,7 @@ sub start_table { $Apache::londefdef::table[-1]{'minlen'}=[]; $Apache::londefdef::table[-1]{'content'}=[]; $Apache::londefdef::table[-1]{'align'}=[]; - $currentstring.='\keephidden{NEW TABLE ENTRY}'; + $currentstring.=' \keephidden{NEW TABLE ENTRY}'; } @@ -2002,11 +2106,16 @@ sub end_table { if ($target eq 'web' || $target eq 'webgrade') { $currentstring = $token->[2]; } elsif ($target eq 'tex') { + my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval); my $inmemory = ''; my $output = ''; my $WARNING=''; #width of columns from TeXwidth attributes + # Protect against unbalanced tag. + + if (scalar(@Apache::londefdef::table) > 0) { + 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]) { @@ -2024,10 +2133,14 @@ sub end_table { $available_space=$available_space-$Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]; } } + #boundaries for contents columns my @min_len=();#columns can not be narrower my @max_len=();#maximum length of column - for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { + my $avg_max; + my $avg_min; + my $counter_cols = $Apache::londefdef::table[-1]{'counter_columns'}; + for (my $jn=0;$jn<=$counter_cols; $jn++) { my ($localmin,$localmax)=(0,0); for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { if ($localmin<$Apache::londefdef::table[-1]{'minlen'}[$in][$jn]) { @@ -2039,8 +2152,28 @@ sub end_table { } push @min_len, $localmin; push @max_len, $localmax; + $avg_max = $localmax + $avg_max; + $avg_min = $localmin + $avg_min; } - for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { + # Does not really matter what the average max/min are if there are no cols. + # and this prevents div 0 in that case. + + if ($counter_cols != 0) { + $avg_max = $avg_max/$counter_cols; + $avg_min = $avg_min/$counter_cols; + } + + + # I don't think the below is needed.. but just in case: + + if ($avg_min > $avg_max) { + my $temp = $avg_min; + $avg_min = $avg_max; + $avg_max = $temp; + } + + + for (my $jn=0;$jn<=$counter_cols;$jn++) { my $localmin=0,; for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { if ($localmin<$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn]) { @@ -2059,16 +2192,27 @@ sub end_table { $min_len[$jn]=0; $max_len[$jn]=0; } + # Spans seem to be really bothered by max/min = 0. So if we have one + # make it an average joe max/min. + + if ($max_len[$jn] == 0) { + $max_len[$jn] = $avg_max; + } + if ($min_len[$jn] == 0) { + $min_len[$jn] = $avg_min; + } + } #final adjustment of column width my @fwidth=@{$Apache::londefdef::table[-1]{'TeXlen'}[0]};#final width array my @adjust=(); #step 1. adjustment by maximum value - my $space_neeeded=0; + my $space_needed=0; for (my $jn=0;$jn<=$#max_len;$jn++) { - $space_neeeded=$space_neeeded+$max_len[$jn]; + $space_needed=$space_needed+$max_len[$jn]; } - if ($space_neeeded<=$available_space) { + if ($space_needed<=$available_space) { + for (my $jn=0;$jn<=$#max_len;$jn++) { if ($fwidth[$jn]==0) { $fwidth[$jn]=$max_len[$jn]; @@ -2076,11 +2220,11 @@ sub end_table { } } else { #step 2. adjustment by minimum value (estimation) - $space_neeeded=0; + $space_needed=0; for (my $jn=0;$jn<=$#min_len;$jn++) { - $space_neeeded+=$min_len[$jn]; + $space_needed+=$min_len[$jn]; } - if ($space_neeeded>$available_space) { + if ($space_needed>$available_space) { $WARNING=' \textbf{NOT ENOUGH SPACE FOR TABLE} '; for (my $jn=0;$jn<=$#max_len;$jn++) { if ($fwidth[$jn]==0) { @@ -2097,7 +2241,7 @@ sub end_table { } } if ($how_many_to_scale>0) { - my $space_to_adjust=($space_neeeded-$available_space)/$how_many_to_scale; + my $space_to_adjust=($space_needed-$available_space)/$how_many_to_scale; foreach my $jn (@to_scale) { for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/; @@ -2119,7 +2263,7 @@ sub end_table { } } else { #step 3. adjustment over minimal + corrections - my $enlarge_coef=$available_space/$space_neeeded; + my $enlarge_coef=$available_space/$space_needed; my $acsessive=0; for (my $jn=0;$jn<=$#min_len;$jn++) { $adjust[$jn]=$min_len[$jn]*$enlarge_coef; @@ -2127,6 +2271,7 @@ sub end_table { $fwidth[$jn]=$max_len[$jn]; $acsessive=$acsessive+$adjust[$jn]-$max_len[$jn]; $adjust[$jn]=0; + } } if ($acsessive>0) { @@ -2151,16 +2296,19 @@ sub end_table { } } } - #use all available width if it is defined in % or as TeXwidth - if (($Apache::londefdef::table[-1]{'percent'}==1) || ($Apache::londefdef::table[-1]{'forcetablewidth'}==1)) { - my $current=0; - for (my $i=0;$i<=$#fwidth;$i++) { - $current+=$fwidth[$i]; - } - my $coef=$Apache::londefdef::table[-1]{'width'}/$current; - for (my $i=0;$i<=$#fwidth;$i++) { - $fwidth[$i]*=$coef; - } + # use all available width or specified width as if not specified, + # the specified width gets defaulted to the available width. + + my $current=0; + for (my $i=0;$i<=$#fwidth;$i++) { + $current+=$fwidth[$i]; + } + if ($current == 0) { + $current = $Apache::londefdef::table[-1]{'width'}; + } + my $coef=$Apache::londefdef::table[-1]{'width'}/$current; + for (my $i=0;$i<=$#fwidth;$i++) { + $fwidth[$i]*=$coef; } #removing of empty columns if allowed my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0); @@ -2181,12 +2329,15 @@ sub end_table { $Apache::londefdef::table[-1]{'content'}=\@cleaned_table; @fwidth=@cleaned_header; } + + #construct header of the table my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'}; for (my $in=0;$in<=$#fwidth;$in++) { $header_of_table.='p{'.$fwidth[$in].' mm}'.$Apache::londefdef::table[-1]{'vvinc'}; } $header_of_table .= '}'; + #fill the table for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { my $have_rowspan = 0; @@ -2197,17 +2348,22 @@ sub end_table { # single rowspan, columspan and combined row/colspans will # work correctly. LaTeX is delicate here. # RF. - + # Start a rowspan if necessary: - + + my $primary_col_width = $fwidth[$jn]; # Width of primary column. my $rowspan = $Apache::londefdef::table[-1]{'rowspan'}[$in][$jn]; my $colspan = $Apache::londefdef::table[-1]{'colspan'}[$in][$jn]; # # Do the appropriate magic if this has a colspan # - + + my $border_char = ""; + if ($border) { + $border_char = "|"; + } + my $spanwidth = 0; if ($colspan > 1) { - my $spanwidth = 0; for (my $spancol = $jn; $spancol < $jn + $colspan; $spancol++) { $spanwidth += $fwidth[$spancol]; } @@ -2215,14 +2371,16 @@ sub end_table { $colspan ."}"; if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { - $output .= '{|c|}{'; + $output .= '{'.$border_char.'c'.$border_char.'}{'; } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { - $output .= '{|r|}{'; + $output .= '{'.$border_char.'r'.$border_char.'}{'; } else { - $output .= "{|p{$spanwidth mm}|}{"; + $output .= '{'.$border_char."p{$spanwidth mm}".$border_char.'}{'; } - + + } else { + $spanwidth = $primary_col_width; # If no span width will be just colwidth } # Rowspan... if colspan is 1, and there's an alignment we'll need @@ -2234,15 +2392,25 @@ sub end_table { if ($rowspan > 1) { if ($colspan == 1) { if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { - $output .= '\multicolumn{1}{|c|}{'; + $output .= '\multicolumn{1}{'.$border_char.'c'.$border_char.'}{'; $multirow_aligned = 1; } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { - $output .= '\multicolumn{1}{|r|}{'; + $output .= '\multicolumn{1}{'.$border_char.'r'.$border_char.'}{'; $multirow_aligned = 1; } } $have_rowspan++; - $output .= '\multirow{'.$rowspan.'}[0]{*}{'; + if ($multirow_aligned) { + $output .= '\multirow{'.$rowspan.'}[0]{*}{'; + } else { + $output .= '\multirow{'.$rowspan."}[0]{$spanwidth mm}{"; + } + + $Apache::londefdef::table[-1]{'content'}[$in][$jn] =~ + s{^\s*\\par\s*}{}; + $Apache::londefdef::table[-1]{'content'}[$in][$jn] =~ + s{\s*\\vskip\s*0pt\s*$}{}; + # # If we did not throw in a multicolumn to align, then add # an extra { @@ -2256,7 +2424,7 @@ sub end_table { if (($rowspan eq '^') || ($rowspan eq '_')) { $have_rowspan++; } - #-------------------------------------------------------------- + #-------------------------------------------------------------- # For right and center alignment of single cells. @@ -2264,9 +2432,9 @@ sub end_table { # if ($colspan == 1 && $rowspan == 1) { if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { - $output .= '\multicolumn{1}{|c|}{'; + $output .= '\multicolumn{1}{'.$border_char.'c'.$border_char.'}{'; } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { - $output .= '\multicolumn{1}{|r|}{'; + $output .= '\multicolumn{1}{'.$border_char.'r'.$border_char.'}{'; } } @@ -2350,6 +2518,8 @@ sub end_table { pop @Apache::londefdef::table; undef @Apache::londefdef::table; } + } + &enable_para(); } return $currentstring; } @@ -2501,9 +2671,11 @@ sub end_td_tex { 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'; - push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + for (my $c = 0; $c < $colspan; $c++) { + push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + } } else { if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) { my $garbage_data=$data; @@ -2519,10 +2691,12 @@ sub end_td_tex { if ($fwidth<$current_length) {$fwidth=$current_length;} $garbage_data=~s/\[(\d+\.?\d*)\s*mm\]//; } - push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; - push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + for (my $c = 0; $c < $colspan; $c++) { + push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; + push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + } } elsif ($data=~/\\parbox\{\s*\d+\.?\d*\s*(mm|cm|in|pc|pt)*\s*\}/ or $data=~/\\epsfxsize\s*=\s*\d+\.?\d*\s*(mm|cm|in|pc|pt)*/) { my $garbage_data=$data; my $fwidth=0; @@ -2538,10 +2712,12 @@ sub end_td_tex { if ($fwidth<$1) {$fwidth=$1;} $garbage_data=~s/\\epsfxsize\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//; } - push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; - push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + for (my $c = 0; $c < $colspan; $c++) { + push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; + push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + } $data=~s/\\\\\s*$//; } else { $data=~s/^\s+(\S.*)/$1/; @@ -2569,10 +2745,12 @@ sub end_td_tex { if ($min_length<$lengthword) {$min_length=$lengthword;} } } - push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; - push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length; - push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length; + for (my $c = 0; $c < $colspan; $c++) { + push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; + push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length; + push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length; + } } } # Substitute all of the tables nested in this cell in their appropriate places. @@ -2841,58 +3019,35 @@ sub start_img { # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src"); - #if original gif/jpg/png file exist do following: + #if original bmp/gif/jpg/png file exist do following: my $origsrc=$src; my ($path,$file) = &get_eps_image($src); + # &Apache::lonnet::logthis("Image source: $src result: $path $file"); $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); &Apache::lonxml::debug("path = $path file = $file src = $src"); if (-e $src) { &Apache::lonxml::debug("$src exists"); my ($height_param,$width_param)= &image_size($origsrc,0.3,$parstack,$safeeval); - my $destpath = $path; - $destpath =~ s/ /\_/g; # Spaces in path cause LaTex to vomit. - my $destfile = $file; - $destfile =~ s/ /\_/g; my $size; if ($width_param) { $size.='width='.$width_param.' mm,'; } if ($height_param) { $size.='height='.$height_param.' mm]'; } + # Default size if not able to extract that (e.g. eps image). + + # &Apache::lonnet::logthis("Size = $size"); + $size='['.$size; $size=~s/,$/]/; - $currentstring .= '\graphicspath{{'.$destpath.'}}' - .'\includegraphics'.$size.'{'.$destfile.'} '; - - # If there's an alignment specification we need to honor it here. - # For the horizontal alignments, we will also honor the - # value of the latex specfication. The default is parbox, - # and that's used for illegal values too. - # - # Even though we set a default alignment value, the user - # could have given us an illegal value. In that case we - # just use the default alignment of bottom.. - if ($align eq "top") { - $currentstring = '\raisebox{-'.$height_param.'mm}{'.$currentstring.'}'; - } elsif (($align eq "center") || ($align eq "middle")) { # Being kind - my $offset = $height_param/2; - $currentstring = '\raisebox{-'.$offset.'mm}{'.$currentstring.'}'; - } elsif ($align eq "left") { - if ($latex_rendering eq "parpic") { - $currentstring = '\parpic[l]{'.$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 { # 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.'}'; - } + $currentstring .= '\graphicspath{{'.$path.'}}' + .'\includegraphics'.$size.'{'.$file.'} '; + my $closure; + ($currentstring, $closure) = &align_latex_image($align, + $latex_rendering, + $currentstring, + $width_param, + $height_param); + $currentstring .= $closure; + } else { &Apache::lonxml::debug("$src does not exist"); #original image file doesn't exist so check the alt attribute @@ -2908,9 +3063,10 @@ sub start_img { # And here's where the semi-quote breaks down: allow the user # to edit the beast as well by rendering the problem for edit: } elsif ($target eq 'edit') { + my $only = join(',',&Apache::loncommon::filecategorytypes('Pictures')); $currentstring .=&Apache::edit::tag_start($target,$token); $currentstring .=&Apache::edit::text_arg('Image Url:','src',$token,70). - &Apache::edit::browse('src',undef,'alt').' '. + &Apache::edit::browse('src',undef,'alt',$only).' '. &Apache::edit::search('src',undef,'alt').'
'; $currentstring .=&Apache::edit::text_arg('Description:','alt',$token,70).'
'; $currentstring .=&Apache::edit::text_arg('width (pixel):','width',$token,5); @@ -2920,7 +3076,7 @@ sub start_img { $currentstring .=&Apache::edit::select_arg('Alignment:','align', ['','bottom','middle','top','left','right'],$token,5); $currentstring .=&Apache::edit::select_arg('TeXwrap:', 'TeXwrap', - ['', 'parbox', 'parpic'], $token, 2); + ['', 'none','parbox', 'parpic', 'wrapfigure'], $token, 2); $currentstring .=&Apache::edit::select_arg('Encrypt URL:','encrypturl', ['no','yes'], $token, 2); $currentstring .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); @@ -2929,11 +3085,14 @@ sub start_img { my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval); my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval); - - $currentstring .= ''.$alt.'[2]{'src'}=~/\$/) { + $currentstring.='Variable image source'; + } else { + $currentstring .= ''.$alt.'[2]{'src'},$token->[2]{'width'},$token->[2]{'height'}); @@ -3016,6 +3175,29 @@ sub start_applet { $currentstring='[APPLET: '.$alttag.']'; } } elsif ($target eq 'tex') { + # Turn off some stuff we can't be inside thank you LaTeX + + + my $restart_sub = 0; + my $restart_sup = 0; + + # Since and are simple tags it's ok to turn off/on + # using the start_ stop_ functions.. those tags only care about + # $target. + + if (&is_inside_of($tagstack, "sub")) { + $restart_sub = 1; + $currentstring .= &end_sub($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + if (&is_inside_of($tagstack, "sup")) { + $restart_sup = 1; + $currentstring .= &end_sup($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + + # Now process the applet; just replace it with its alt attribute. + my $alttag= &Apache::lonxml::get_param('alt',$parstack, $safeeval,undef,1); unless ($alttag) { @@ -3026,6 +3208,17 @@ sub start_applet { } $currentstring.='\begin{center} \fbox{Java Applet: '.$alttag. '.}\end{center}'; + + # Turn stuff back on that we can't be inside of. + + if ($restart_sub) { + $currentstring .= &start_sub($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } + if ($restart_sup) { + $currentstring .= &start_sup($target, $token, $tagstack, + $parstack, $parser, $safeeval); + } } return $currentstring; } @@ -3412,6 +3605,9 @@ sub start_blockquote { if ($target eq 'web' || $target eq 'webgrade') { $currentstring .= $token->[4]; } + if ($target eq 'tex') { + $currentstring .= '\begin{quote}'; + } return $currentstring; } @@ -3421,6 +3617,9 @@ sub end_blockquote { if ($target eq 'web' || $target eq 'webgrade') { $currentstring = $token->[2]; } + if ($target eq 'tex') { + $currentstring = '\end{quote}'; + } return $currentstring; } @@ -4221,8 +4420,8 @@ sub get_eps_image { &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; + my ($spath, $sname, $sext) = &fileparse($src, qr/\.(bmp|gif|png|jpg|jpeg)/i); + $src=~s/\.(bmp|gif|png|jpg|jpeg)$/\.eps/i; $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); &Apache::lonxml::debug("Filelocation gives: $src"); if (! -e $src) { @@ -4246,17 +4445,33 @@ sub get_eps_image { my $newsrc=$orig_src; $newsrc =~ s|(.*)/res/|/home/httpd/html/res/|; &Apache::lonxml::debug("queueing $newsrc for dynamic eps production."); - print FILE "$newsrc\n"; - close FILE; + print FILE ("$newsrc\n"); + 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/; } + } + } + } else { + # If the postscript file has spaces in its name, + # LaTeX will gratuitiously vomit. Therefore + # queue such files for copy with " " replaced by "_". + # printout.pm will know them by their .ps or .eps extensions. + my $newsrc = $orig_src; + $newsrc =~ s|(.*)/res/|/home/httpd/html/res/|; + open(FILE,">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"); + print FILE "$src\n"; + close FILE; + $src=~s|/home/httpd/html/res|/home/httpd/prtspool|; + $src=~s|/home/([^/]*)/public_html/|/home/httpd/prtspool/$1/|; } my ($path,$file)=($src=~m|(.*)/([^/]*)$|); + $path =~ s/ /\_/g; + $file =~ s/ /\_/g; &Apache::lonxml::debug("get_eps_image returning: $path / $file
"); return ($path.'/',$file); } @@ -4267,16 +4482,16 @@ sub eps_generation { my $temp_file = Apache::File->new('>>'.$filename); print $temp_file "$src\n"; my $newsrc = $src; - $newsrc =~ s/(\.gif|\.jpg|\.jpeg)$/\.eps/i; - $newsrc=~s/\/home\/httpd\/html\/res//; - $newsrc=~s/\/home\/([^\/]*)\/public_html\//\/$1\//; - $newsrc=~s/\/\.\//\//; - $newsrc=~s/\/([^\/]+)\.(ps|eps)/\//; - if ($newsrc=~/\/home\/httpd\/lonUsers\//) { - $newsrc=~s/\/home\/httpd\/lonUsers//; - $newsrc=~s/\/([^\/]+)\/(\w)\/(\w)\/(\w)\//\/$1\//; + $newsrc =~ s/(\.bmp|\.gif|\.jpg|\.jpeg)$/\.eps/i; + $newsrc=~s{/home/httpd/html/res}{}; + $newsrc=~s{/home/($LONCAPA::username_re)/public_html/}{/$1/}; + $newsrc=~s{/\./}{/}; + $newsrc=~s{/([^/]+)\.(ps|eps)}{/}; + if ($newsrc=~m{/home/httpd/lonUsers/}) { + $newsrc=~s{/home/httpd/lonUsers}{}; + $newsrc=~s{/($LONCAPA::domain_re)/./././}{/$1/}; } - if ($newsrc=~/\/userfiles\//) { + if ($newsrc=~m{/userfiles/}) { return ' \graphicspath{{'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} '; } else { return ' \graphicspath{{/home/httpd/prtspool'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} '; @@ -4340,6 +4555,84 @@ sub LATEX_length { return $value; } +# Wrap image 'stuff' inside of the LaTeX required to implement +# alignment: +# align_tex_image(align, latex_rendering, image) +# Where: +# align - The HTML alignment specification. +# latex_rendering - rendering hint for latex. +# image - The LaTeX needed to insert the image itsef. +# width,height - dimensions of the image. +# Returns: +# The 1/2 wrapped image and the stuff required to close the +# wrappage. This allows e.g. randomlabel to insert more stuff +# into the closure. +# +sub align_latex_image { + my ($align, $latex_rendering, $image, $width, $height) = @_; + my $currentstring; # The 1/2 wrapped image. + my $closure; # The closure of the wrappage. + + # if it's none just return it back + if ($latex_rendering eq 'none') { + return ($image,''); + } + + # If there's an alignment specification we need to honor it here. + # For the horizontal alignments, we will also honor the + # value of the latex specfication. The default is parbox, + # and that's used for illegal values too. + # + # Even though we set a default alignment value, the user + # could have given us an illegal value. In that case we + # just use the default alignment of bottom.. + $currentstring = "\n% figurewrapping \n"; + if ($align eq "top") { + $currentstring .= '\raisebox{-'.$height.'mm}{'.$image; + $closure = '}'; + } elsif (($align eq "center") || ($align eq "middle")) { # Being kind + my $offset = $height/2; + $currentstring .= '\raisebox{-'.$offset.'mm}{'.$image; + $closure = '}'; + } elsif ($align eq "left") { + if ($latex_rendering eq "parpic") { + $currentstring .= '\parpic[l]{'.$image; + $closure = '}'; + } elsif ($latex_rendering eq "parbox") { + $currentstring .= '\begin{minipage}[l]{'.$width.'mm}' + .$image; + $closure = '\end{minipage}'; + } elsif ($latex_rendering eq "wrapfigure" + || $latex_rendering ne 'none') { # wrapfig render + $currentstring .= + '\begin{wrapfigure}{l}{'.$width.'mm}' + .'\scalebox{1.0}{'.$image; + $closure = '}\end{wrapfigure}'; + } + } elsif ($align eq "right") { + if ($latex_rendering eq "parpic") { + $currentstring .= '\parpic[r]{'.$image; + $closure = '}'; + } elsif ($latex_rendering eq "parbox") { + $currentstring .= '\begin{minipage}[r]{'.$width.'mm}' + .$image; + $closure = '\end{minipage}'; + } elsif ($latex_rendering eq "wrapfigure" + || $latex_rendering ne 'none') { # wrapfig render + $currentstring .= + '\begin{wrapfigure}{r}{'.$width.'mm}' + .'\scalebox{1.0}{'.$image; + $closure = '}\end{wrapfigure}'; + } + } else { # Bottom is also default. + # $currentstring = '\raisebox{'.$height.'mm}{'.$image.'}'; + $currentstring .= "{$image"; + $closure = '}'; + } + $currentstring .= "\n% end wrappage\n"; + $closure = "\n% Begin closure\n".$closure."\n% End closure\n"; + return ($currentstring, $closure); +} # is_inside_of $tagstack $tag # This sub returns true if the current state of Xml processing