--- loncom/xml/londefdef.pm 2008/09/20 01:32:33 1.390.2.1 +++ loncom/xml/londefdef.pm 2023/09/27 14:52:27 1.473 @@ -1,8 +1,8 @@ # The LearningOnline Network with CAPA -# Tags Default Definition Module +# Tags Default Definition Module +# +# $Id: londefdef.pm,v 1.473 2023/09/27 14:52:27 raeburn Exp $ # -# $Id: londefdef.pm,v 1.390.2.1 2008/09/20 01:32:33 raeburn Exp $ -# # # Copyright Michigan State University Board of Trustees # @@ -25,28 +25,29 @@ # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ -## Copyright for TtHfunc and TtMfunc by Ian Hutchinson. -# TtHfunc and TtMfunc (the "Code") may be compiled and linked into -# binary executable programs or libraries distributed by the -# Michigan State University (the "Licensee"), but any binaries so +## Copyright for TtHfunc and TtMfunc by Ian Hutchinson. +# TtHfunc and TtMfunc (the "Code") may be compiled and linked into +# binary executable programs or libraries distributed by the +# Michigan State University (the "Licensee"), but any binaries so # distributed are hereby licensed only for use in the context -# of a program or computational system for which the Licensee is the -# primary author or distributor, and which performs substantial +# of a program or computational system for which the Licensee is the +# primary author or distributor, and which performs substantial # additional tasks beyond the translation of (La)TeX into HTML. # The C source of the Code may not be distributed by the Licensee # to any other parties under any circumstances. # -package Apache::londefdef; +package Apache::londefdef; use Apache::lonnet; use strict; use Apache::lonxml; -use Apache::File(); +use Apache::lontable; use Image::Magick; use Apache::lonmenu(); use Apache::lonmeta(); use Apache::lonlocal; +use Apache::loncommon(); use Apache::Constants qw(:common); use File::Basename; use LONCAPA(); @@ -54,24 +55,11 @@ use LONCAPA(); BEGIN { - &Apache::lonxml::register('Apache::londefdef',('a','abbr','acronym','accessrule','address','allow','applet','area','b','base','basefont','bgo','bgsound','big','blink','blockquote','blankspace','body','br','button','caption','center','cite','code','col','colgroup','dd','del','dfn','dir','div','dl','dt','em','embed','externallink','fieldset','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','insert','isindex','kbd','keygen','label','layer','legend','li','link','m','map','marquee','menu','meta','multicol','nobr','noembed','noframes','nolayer','noscript','object','ol','optgroup','option','output','p','param','pre','q','s','samp','select','server','small','spacer','span','strike','strong','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','tthoption','u','ul','var','wbr','hideweboutput')); + &Apache::lonxml::register('Apache::londefdef',('a','abbr','acronym','accessrule','address','allow','applet','area','b','base','basefont','bgo','bgsound','big','blink','blockquote','blankspace','body','br','button','caption','center','cite','code','col','colgroup','dd','del','dfn','dir','div','dl','dt','em','embed','externallink','fieldset','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','insert','isindex','kbd','keygen','label','layer','legend','li','link','m','map','marquee','menu','meta','multicol','nobr','noembed','noframes','nolayer','noscript','object','ol','optgroup','option','output','p','param','pre','q','s','samp','select','server','small','spacer','span','strike','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','tthoption','u','ul','var','wbr','hideweboutput')); } -# -# 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 = (); @@ -104,10 +92,30 @@ sub start_m { my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser); if ($target eq 'web' || $target eq 'analyze') { &Apache::lonxml::debug("M is starting with:$inside:"); + if (!($inside =~ /^\s*\$.*\$\s*$/ || $inside =~ /^\s*\\[([].*\\[)\]]\s*$/)) { + # Non-math LaTeX will not be rendered correctly with MathJax + # and it should be avoided anyway. + # On top of that, MathJax will render math without $, but + # it will fail with tth. This is worth a warning. + # (even though some people might just use latex for printing) + &Apache::lonxml::warning(&mt('Missing $ in [_1].','<m>')); + } elsif (($env{'browser.type'} eq 'safari') && ($env{'form.editxmltext'}) && + (($env{'form.problemmode'} eq 'view') || ($env{'form.problemmode'} eq 'discard'))) { + my $delimiter; + if ($inside =~ /\$$/) { + $delimiter = '$'; + } elsif ($inside =~ /\\([)\]])$/) { + $delimiter = $1; + } + if ($delimiter) { + &Apache::lonxml::warning(&mt('Insert a space between [_1] and [_2].', + $delimiter,'</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); @@ -139,7 +147,7 @@ sub start_m { # detect simple math mode entry exits, and convert them # to use \ensuremath ... unless there's a \verb inside. if (! ($currentstring=~/\\verb/)) { - if ($currentstring=~/^\s*\$[^\$].*[^\$]\$\s*$/) { + if ($currentstring=~/^\s*\$[^\$].*\$\s*$/) { $currentstring=~s/^(\s*)\$/$1/; $currentstring=~s/\$(\s*)$/$1/; $currentstring='\ensuremath{'.$currentstring.'}'; @@ -186,35 +194,10 @@ sub start_html { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'edit' || $target eq 'webgrade' ) { - # start_body() takes care of emitting the + # start_body() takes care of emitting the } elsif ($target eq 'tex') { - $currentstring .= - '\documentclass[letterpaper,twoside]{article}\raggedbottom'; - if (($env{'form.latex_type'}=~'batchmode') || - (!$env{'request.role.adv'})) {$currentstring .='\batchmode';} - $currentstring .= '\newcommand{\keephidden}[1]{}'. - '\renewcommand{\deg}{$^{\circ}$}'. - '\usepackage{multirow}'. - '\usepackage{longtable}'. - '\usepackage{textcomp}'. - '\usepackage{makeidx}'. - '\usepackage[dvips]{graphicx}'. - '\usepackage{wrapfig}'. - '\usepackage{picins}'. - '\usepackage[T1]{fontenc}'."\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}}'. - '\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}}'; + + $currentstring .= &latex_header(); } return $currentstring; } @@ -234,7 +217,7 @@ sub start_head { my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { &Apache::lonxml::startredirection(); - } + } return $currentstring; } @@ -247,7 +230,7 @@ sub end_head { if ($Apache::lonxml::redirection) { $Apache::londefdef::head = &Apache::lonxml::endredirection(); } - } + } return $currentstring; } @@ -256,8 +239,8 @@ sub start_map { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; - } + $currentstring = $token->[4]; + } return $currentstring; } @@ -265,8 +248,8 @@ sub end_map { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; - } + $currentstring = $token->[2]; + } return $currentstring; } @@ -275,7 +258,7 @@ sub start_select { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; + $currentstring = $token->[4]; } elsif ($target eq 'tex') { $Apache::londefdef::select=0; } @@ -286,8 +269,8 @@ sub end_select { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; - } + $currentstring = $token->[2]; + } return $currentstring; } @@ -296,7 +279,7 @@ sub start_option { my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; + $currentstring = $token->[4]; } elsif ($target eq 'tex') { $Apache::londefdef::select++; if ($Apache::londefdef::select == 1) { @@ -312,7 +295,7 @@ sub end_option { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; + $currentstring = $token->[2]; } elsif ($target eq 'tex') { $currentstring='}'; } @@ -324,8 +307,8 @@ sub start_input { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; - } + $currentstring = $token->[4]; + } return $currentstring; } @@ -333,8 +316,8 @@ sub end_input { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; - } + $currentstring = $token->[2]; + } return $currentstring; } @@ -343,8 +326,8 @@ sub start_textarea { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; - } + $currentstring = $token->[4]; + } return $currentstring; } @@ -352,8 +335,8 @@ sub end_textarea { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; - } + $currentstring = $token->[2]; + } return $currentstring; } @@ -362,8 +345,8 @@ sub start_form { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[4]; - } + $currentstring = $token->[4]; + } return $currentstring; } @@ -371,8 +354,8 @@ sub end_form { my ($target,$token) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $currentstring = $token->[2]; - } + $currentstring = $token->[2]; + } return $currentstring; } @@ -381,10 +364,10 @@ sub start_title { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; my $currentstring = ''; if ($target eq 'web' || $target eq 'webgrade') { - $Apache::londefdef::title = + $Apache::londefdef::title = &Apache::lonxml::get_all_text('/title',$parser,$style); } elsif ($target eq 'tex') { - $currentstring .= '\keephidden{Title of the document: ' + $currentstring .= '\keephidden{Title of the document: '; } if ($target eq 'meta') { $currentstring='
# Some tags are
fragile meaning that
inside of them
-# does not work within TeX mode. This is managed via the
+# does not work within TeX mode. This is managed via the
# counter below:
#
@@ -1219,6 +1329,10 @@ sub start_p {
$currentstring .= &end_p(); # close off prior para if in progress.
my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
+ if (!defined $align) {
+ # check inline CSS
+ $align = &get_css_property('text-align',$parstack,$safeeval);
+ }
if ($align eq 'center') {
$currentstring .='\begin{center}\par ';
$closing_string = '\end{center}';
@@ -1226,13 +1340,13 @@ sub start_p {
$currentstring = ¢er_correction().$currentstring;
}
} elsif ($align eq 'right') {
- $currentstring.="\n".'{\flushright ';
+ $currentstring.="\n".'\begin{flushright}';
# $currentstring.='\makebox['.$env{'form.textwidth'}.']{\hfill\llap{';
- $closing_string= "}\n";
+ $closing_string= '\end{flushright}'."\n";
} elsif ($align eq 'left') {
- $currentstring.= "\n".'{\flushleft ';
+ $currentstring.= "\n".'\begin{flushleft}';
# $currentstring.='\noindent\makebox['.$env{'form.textwidth'}.']{{';
- $closing_string = "}\n";
+ $closing_string = '\end{flushleft}'."\n";
} else {
$currentstring.='\par ';
if (&is_inside_of($tagstack, 'table')) {
@@ -1286,7 +1400,7 @@ sub start_br {
if ($signal != 1) {
$currentstring .= '\strut \\\\ \strut ';
}
-
+
}
return $currentstring;
}
@@ -1308,7 +1422,7 @@ sub start_big {
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
$currentstring .= '{\large ';
- }
+ }
return $currentstring;
}
@@ -1351,7 +1465,7 @@ sub start_basefont {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
if (defined $basesize) {
@@ -1365,7 +1479,7 @@ sub end_basefont {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
if (defined $basesize) {
@@ -1381,11 +1495,7 @@ sub start_font {
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);
- if ($face!~/symbol/i) {
- if (($env{'browser.fontenhance'} eq 'on') ||
- ($env{'browser.blackwhite'} eq 'on')) { return ''; }
- }
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
if (defined $fontsize) {
@@ -1399,7 +1509,7 @@ sub end_font {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
if (defined $fontsize) {
@@ -1408,7 +1518,7 @@ sub end_font {
}
return $currentstring;
}
-
+
#-- in the prior to the list.
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[4];
+ $currentstring .= $token->[4];
} elsif ($target eq 'tex') {
- $currentstring .= " \\begin{itemize} ";
- }
+ $currentstring .= " \\begin{itemize} ";
+ }
return $currentstring;
}
@@ -1834,10 +1973,10 @@ sub end_dir {
my ($target,$token) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
- $currentstring = " \\end{itemize}";
- }
+ $currentstring = " \\end{itemize}";
+ }
return $currentstring;
}
@@ -1846,18 +1985,18 @@ sub start_ol {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = &end_p(); # In case there's a prior to the list.
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[4];
+ $currentstring .= $token->[4];
} elsif ($target eq 'tex') {
$Apache::londefdef::list_index=0;
my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
if ($type eq '1') {
$currentstring .= '\renewcommand{\labelenumi}{\arabic{enumi}.}'.
- '\renewcommand{\labelenumii}{\arabic{enumii}.}'.
+ '\renewcommand{\labelenumii}{\arabic{enumii}.}'.
'\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
'\renewcommand{\labelenumiv}{\arabic{enumiv}.}';
} elsif ($type eq 'A') {
$currentstring .= '\renewcommand{\labelenumi}{\Alph{enumi}.}'.
- '\renewcommand{\labelenumii}{\Alph{enumii}.}'.
+ '\renewcommand{\labelenumii}{\Alph{enumii}.}'.
'\renewcommand{\labelenumiii}{\Alph{enumiii}.}'.
'\renewcommand{\labelenumiv}{\Alph{enumiv}.}';
} elsif ($type eq 'a') {
@@ -1876,8 +2015,8 @@ sub start_ol {
'\renewcommand{\labelenumiii}{\Roman{enumiii}.}'.
'\renewcommand{\labelenumiv}{\Roman{enumiv}.}';
}
- $currentstring .= '\strut \begin{enumerate}';
- }
+ $currentstring .= '\strut \begin{enumerate}';
+ }
return $currentstring;
}
@@ -1885,13 +2024,13 @@ sub end_ol {
my ($target,$token) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
$currentstring = '\end{enumerate}\renewcommand{\labelenumi}{\arabic{enumi}.}'.
'\renewcommand{\labelenumii}{\arabic{enumii}.}'.
'\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
- '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut ';
- }
+ '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut ';
+ }
return $currentstring;
}
@@ -1900,7 +2039,7 @@ sub start_dl {
my ($target,$token) = @_;
my $currentstring = &end_p(); # In case there's a unclosed prior to the list.
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[4];
+ $currentstring .= $token->[4];
} elsif ($target eq 'tex') {
$currentstring .= '\begin{description}';
$Apache::londefdef::DL++;
@@ -1908,7 +2047,7 @@ sub start_dl {
$Apache::londefdef::DD[$Apache::londefdef::DL]=0;
$Apache::londefdef::DT[$Apache::londefdef::DL]=0;
$Apache::londefdef::seenDT[$Apache::londefdef::DL]=0;
- }
+ }
return $currentstring;
}
@@ -1916,7 +2055,7 @@ sub end_dl {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
@@ -1924,12 +2063,12 @@ sub end_dl {
$currentstring.=' '.$element.' ';
}
pop(@Apache::londefdef::description);
- $currentstring.='\end{description}';
+ $currentstring.='\end{description}';
delete($Apache::londefdef::DD[$Apache::londefdef::DL]);
delete($Apache::londefdef::DT[$Apache::londefdef::DL]);
delete($Apache::londefdef::seenDT[$Apache::londefdef::DL]);
$Apache::londefdef::DL--;
- }
+ }
return $currentstring;
}
@@ -1938,14 +2077,14 @@ sub start_dt {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring='';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
&Apache::lonxml::startredirection();
$Apache::londefdef::DT[-1]++;
$Apache::londefdef::seenDT[-1]=1;
- }
+ }
return $currentstring;
}
@@ -1953,21 +2092,21 @@ sub end_dt {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
if ($Apache::londefdef::DT[-1]) {
my $data=&item_cleanup();
push(@{$Apache::londefdef::description[-1]},'\item['.$data.'] \strut \vskip 0mm');
$Apache::londefdef::DT[-1]--;
}
- }
+ }
return $currentstring;
}
sub item_cleanup {
my $item=&Apache::lonxml::endredirection();
- $item=~s/\\begin{center}//g;
- $item=~s/\\end{center}//g;
+ $item=~s/\\begin\{center}//g;
+ $item=~s/\\end\{center}//g;
return $item;
}
@@ -1976,7 +2115,7 @@ sub start_dd {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
if ($Apache::londefdef::DD[-1]) { &end_dd(@_);}
@@ -1987,7 +2126,7 @@ sub start_dd {
$Apache::londefdef::description[-1]->[-1].=' \strut ';
$Apache::londefdef::DD[-1]++;
&Apache::lonxml::startredirection();
- }
+ }
return $currentstring;
}
@@ -1995,7 +2134,7 @@ sub end_dd {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
$Apache::londefdef::description[-1]->[-1].=
&Apache::lonxml::endredirection().' \vskip 0mm ';
@@ -2007,516 +2146,100 @@ sub end_dd {
#-- that is not closed.
# but, unless I allow 's to nest, that's the
-# only way I could think of to allow in
+# only way I could think of to allow in
# in the row.
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[2];
+ $currentstring .= $token->[2];
} elsif ($target eq 'tex') {
+
+ # In case the user is missing a or tag:
+
+ if ($Apache::londefdef::TD_redirection) {
+ &end_td_tex($parstack,$parser,$safeeval);
+ }
+ $Apache::londefdef::table[-1]->end_row();
+
+ #-----------------------------------------------
+ # Old table code
+ #-----------------------------------------------
+
+ if (0) {
if ($Apache::londefdef::TD_redirection) {
- &end_td_tex($parstack,$parser,$safeeval);
+ &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'};
}
-
+ }
}
@@ -2576,17 +2326,17 @@ sub start_td {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
$Apache::londefdef::TD_redirection = 1;
&tag_check('tr','td',$tagstack,$parstack,$parser,$safeeval);
- }
+ }
return $currentstring;
-}
-
+}
+
sub tag_check {
my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_;
- my @ar=@$parstack;
+ my @ar=@$parstack;
for (my $i=$#ar-1;$i>=0;$i--) {
if (lc($$tagstack[$i]) eq $good_tag) {
&start_td_tex($parstack,$parser,$safeeval);
@@ -2600,9 +2350,59 @@ sub tag_check {
}
return '';
}
-
+
+#
+# Factor out cell configuration hash generation:
+#
+
+sub cell_config_hash {
+ my ($align, $rowspan, $colspan, $width) = @_;
+ if ($rowspan ne '') {
+ $rowspan =~ s/^\s+|\s+$//g;
+ }
+ if ($colspan ne '') {
+ $colspan =~ s/^\s+|\s+$//g;
+ }
+ my %config;
+ if ($align ne '') {
+ $config{'halign'} = $align;
+ }
+ if (($colspan =~ /^\d+$/) && ($colspan > 0)) {
+ $config{'colspan'} = $colspan;
+ }
+ if (($rowspan =~ /^\d+$/) && ($rowspan > 0)) {
+ $config{'rowspan'} = $rowspan;
+ }
+ if ($width ne '') {
+ $config{'width'} = $width;
+ }
+ return \%config;
+}
+
sub start_td_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ # At this stage, an empty cell is created with the
+ # appropriate rowspan/colspan and alignment
+ # attributes, but empty of text. end_td_tex will
+ # fetch the contents from the recursive parse and
+ # fill the cell with them:
+ my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval);
+ my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval);
+ my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval);
+ my $width = &Apache::lonxml::get_param('TeXwidth', $parstack, $safeeval);
+ my $config = &cell_config_hash($align, $rowspan, $colspan, $width);
+
+ my $table = $Apache::londefdef::table[-1];
+ $table->add_cell('', $config);
+
+
+ #------------------------------------------------
+ # Old table code.
+ #------------------------------------------------
+
+ if (0) {
+
my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
if ($alignchar eq '') {
$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2615,14 +2415,25 @@ sub start_td_tex {
$current_length=~/(\d+\.?\d*)/;
push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
}
+ }
&Apache::lonxml::startredirection();
return '';
}
sub end_td_tex {
+
+ my $text = &Apache::lonxml::endredirection();
+ my $table = $Apache::londefdef::table[-1];
+ $table->append_cell_text($text);
+
+ #-------------------------------------------------
+ # Old table code
+ #-------------------------------------------------
+
+ if (0) {
my ($parstack,$parser,$safeeval) = @_;
my $current_row = $Apache::londefdef::table[-1]{'row_number'};
- my $current_column = $Apache::londefdef::table[-1]{'counter_columns'};
+ 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.
@@ -2632,14 +2443,14 @@ sub end_td_tex {
# 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])
+ while ((defined $Apache::londefdef::table[-1]{'rowspan'}[$current_row] [$current_column])
&& ($Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column] =~ /[\^\_]/)) {
# Part of a span.
push @ {$Apache::londefdef::table[-1]{'content'}[-1]}, '';
$current_column++;
}
$Apache::londefdef::table[-1]{'counter_columns'} = $current_column;
-
+
# Get the column and row spans.
# Colspan can be done via \multicolumn if I can figure out the data structs.
@@ -2715,9 +2526,9 @@ sub end_td_tex {
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/;
+ $data=~s/\\\\\s*$//;
+ } else {
+ $data=~s/^\s+(\S.*)/$1/;
$data=~s/(.*\S)\s+$/$1/;
$data=~s/(\s)+/$1/;
my ($current_length,$min_length)=(0,0);
@@ -2748,13 +2559,13 @@ sub end_td_tex {
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.
my $nested_count = $#{$Apache::londefdef::table[-1]{'include'}}; # This one is constant...
- for (my $in=0; $in<=$nested_count; $in++) {
+ 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]/;
@@ -2784,7 +2595,7 @@ sub end_td_tex {
}
-
+ }
return '';
}
@@ -2793,7 +2604,7 @@ sub end_td {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[2];
+ $currentstring = $token->[2];
} elsif ($target eq 'tex') {
$Apache::londefdef::TD_redirection =0;
&end_td_tex($parstack,$parser,$safeeval);
@@ -2806,17 +2617,17 @@ sub start_th {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
$Apache::londefdef::TD_redirection = 1;
&tagg_check('tr','th',$tagstack,$parstack,$parser,$safeeval);
- }
+ }
return $currentstring;
-}
-
+}
+
sub tagg_check {
my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_;
- my @ar=@$parstack;
+ my @ar=@$parstack;
for (my $i=$#ar-1;$i>=0;$i--) {
if (lc($$tagstack[$i]) eq $good_tag) {
&start_th_tex($parstack,$parser,$safeeval);
@@ -2830,9 +2641,27 @@ sub tagg_check {
}
return '';
}
-
+
sub start_th_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ my $alignment = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef,1);
+ my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 1);
+ my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 1);
+
+ my $config = cell_config_hash($alignment, $rowspan, $colspan);
+ my $table = $Apache::londefdef::table[-1];
+ $table->add_cell('\textbf{', $config);
+
+ #-------------------------------------------------------------------------------------
+ #
+ # Old table code.
+ #
+ #--------------------------------------------------------------------------------------
+
+ if (0) {
+
+
my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
if ($alignchar eq '') {
$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2845,12 +2674,26 @@ sub start_th_tex {
$current_length=~/(\d+\.?\d*)/;
push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
}
+ }
+
+ # Accept xml until the tag.
+
&Apache::lonxml::startredirection();
return '';
}
sub end_th_tex {
my ($parstack,$parser,$safeeval) = @_;
+
+ my $table = $Apache::londefdef::table[-1];
+ my $text = &Apache::lonxml::endredirection();
+ $table->append_cell_text($text.'}');
+
+ #-----------------------------------------------------------------------------
+ # Old table code:
+ #-----------------------------------------------------------------------------
+
+ if (0) {
my $current_row = $Apache::londefdef::table[-1]{'row_number'};
my $data=&Apache::lonxml::endredirection();
my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
@@ -2877,8 +2720,8 @@ sub end_th_tex {
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';
- } else {
- $data=~s/^\s+(\S.*)/$1/;
+ } else {
+ $data=~s/^\s+(\S.*)/$1/;
$data=~s/(.*\S)\s+$/$1/;
$data=~s/(\s)+/$1/;
my ($current_length,$min_length)=(0,0);
@@ -2907,14 +2750,15 @@ sub end_th_tex {
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 $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {
+ for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {
$data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
}
#make data bold
$data='\textbf{'.$data.'}';
push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
+ }
return'';
}
@@ -2922,60 +2766,53 @@ sub end_th {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = &end_p(); # Close any open in the row.
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[2];
+ $currentstring .= $token->[2];
} elsif ($target eq 'tex') {
$Apache::londefdef::TD_redirection =0;
&end_th_tex($parstack,$parser,$safeeval);
}
return $currentstring;
}
-
+
#-- tag (end tag forbidden)
#
# Render the tag.
-# has the following attributes (in addition to the
+# has the following attributes (in addition to the
# standard HTML ones:
# TeXwrap - Governs how the tex target will try to wrap text around
# horizontally aligned images.
# TeXwidth - The width of the image when rendered for print (mm).
# TeXheight - The height of the image when rendered for print (mm)
# (Note there seems to also be support for this as a % of page size)
-#
+#
sub start_img {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,
undef,1);
- if (! $src &&
+ if (! $src &&
($target eq 'web' || $target eq 'webgrade' || $target eq 'tex')
- ) {
+ ) {
my $inside = &Apache::lonxml::get_all_text("/img",$parser,$style);
return '';
}
- &Apache::lonxml::extlink($src);
+ unless ($src =~ m{^data\:image/gif;base64,}) {
+ &Apache::lonxml::extlink($src);
+ }
my $currentstring = '';
my $scaling = .3;
# Render unto browsers that which are the browser's...
if ($target eq 'web' || $target eq 'webgrade') {
- if ($env{'browser.imagesuppress'} ne 'on') {
- my $enc = ('yes' eq
- lc(&Apache::lonxml::get_param('encrypturl',$parstack,
- $safeeval)));
- $currentstring.=&Apache::lonenc::encrypt_ref($token,{'src'=>$src},
- $enc);
- } else {
- my $alttag = &Apache::lonxml::get_param('alt',$parstack,$safeeval,
- undef,1);
- if (!$alttag) {
- $alttag = &Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],
- $src);
- }
- $currentstring.='[IMAGE: '.$alttag.']';
- }
-
- # and render unto TeX that which is LaTeX
+ my $enc = ('yes' eq
+ lc(&Apache::lonxml::get_param('encrypturl',$parstack,
+ $safeeval)));
+ unless ($src =~ m{^data\:image/gif;base64,}) {
+ $currentstring.=&Apache::lonenc::encrypt_ref($token,{'src'=>$src},
+ $enc);
+ }
+ # and render unto TeX that which is LaTeX
} elsif ($target eq 'tex') {
#
# The alignment will require some superstructure to be put around
@@ -2983,7 +2820,7 @@ sub start_img {
# simulate the alignments offered by html.
#
#
- my $align = lc(&Apache::lonxml::get_param('align',
+ my $align = lc(&Apache::lonxml::get_param('align',
$parstack,
$safeeval,
undef,1));
@@ -2993,7 +2830,7 @@ sub start_img {
#
&Apache::lonxml::debug("Alignemnt = $align");
# LaTeX's image/text wrapping is really bad since it wants to
- # make figures float.
+ # make figures float.
# The user has the optional parameter (applicable only to l/r
# alignment to use the picins/parpic directive to get wrapped text
# this is also imperfect.. that's why we give them a choice...
@@ -3016,7 +2853,7 @@ sub start_img {
# &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src");
- #if original bmp/gif/jpg/png file exist do following:
+ #if original bmp/gif/jpg/png/svg file exist do following:
my $origsrc=$src;
my ($path,$file) = &get_eps_image($src);
# &Apache::lonnet::logthis("Image source: $src result: $path $file");
@@ -3030,25 +2867,25 @@ sub start_img {
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/,$/]/;
+ $size=~s/,$/]/;
$currentstring .= '\graphicspath{{'.$path.'}}'
.'\includegraphics'.$size.'{'.$file.'} ';
my $closure;
- ($currentstring, $closure) = &align_latex_image($align,
- $latex_rendering,
- $currentstring,
- $width_param,
+ ($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
- my $alt =
+ my $alt =
&Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1);
unless ($alt) {
$alt=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src);
@@ -3063,8 +2900,8 @@ sub start_img {
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',$only).' '.
- &Apache::edit::search('src',undef,'alt').' tag (end tag required)
sub start_strike {
my ($target,$token) = @_;
@@ -1417,7 +1527,7 @@ sub start_strike {
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
&Apache::lonxml::startredirection();
- }
+ }
return $currentstring;
}
@@ -1428,8 +1538,8 @@ sub end_strike {
$currentstring .= $token->[2];
} elsif ($target eq 'tex') {
$currentstring=&Apache::lonxml::endredirection();
- $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g;
- $currentstring=~s/^\s*(\S)/\\underline\{$1/;
+ $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g;
+ $currentstring=~s/^\s*(\S)/\\underline\{$1/;
$currentstring=~s/(\S)\s*$/$1\}/;
}
return $currentstring;
@@ -1443,7 +1553,7 @@ sub start_s {
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
&Apache::lonxml::startredirection();
- }
+ }
return $currentstring;
}
@@ -1469,7 +1579,7 @@ sub start_sub {
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
$currentstring .= '\raisebox{-\smallskipamount}{\scriptsize{';
- }
+ }
return $currentstring;
}
@@ -1492,7 +1602,7 @@ sub start_sup {
$currentstring .= $token->[4];
} elsif ($target eq 'tex') {
$currentstring .= '\raisebox{\smallskipamount}{\scriptsize{';
- }
+ }
return $currentstring;
}
@@ -1516,7 +1626,7 @@ sub start_hr {
} elsif ($target eq 'tex') {
#
can't be inside of thank you LaTeX.
- #
+ #
my $restart_sub = 0;
my $restart_sup = 0;
@@ -1526,7 +1636,7 @@ sub start_hr {
if (&is_inside_of($tagstack, "sub")) {
$restart_sub = 1;
- $currentstring .= &end_sub($target, $token, $tagstack,
+ $currentstring .= &end_sub($target, $token, $tagstack,
$parstack, $parser, $safeeval);
}
if (&is_inside_of($tagstack, "sup")) {
@@ -1565,7 +1675,7 @@ sub start_hr {
$currentstring .= &start_sup($target, $token, $tagstack,
$parstack, $parser, $safeeval);
}
- }
+ }
return $currentstring;
}
@@ -1592,12 +1702,12 @@ sub start_div {
my $currentstring = &end_p(); # Close enclosing para.
if ($target eq 'web' || $target eq 'webgrade') {
$currentstring .= $token->[4];
- }
+ }
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 = '';
@@ -1608,7 +1718,7 @@ sub start_div {
$endstring = '\end{center}';
if (&is_inside_of($tagstack, "table")) {
$currentstring = ¢er_correction().$currentstring;
- $endstring .= ¢er_end_correction();
+ $endstring .= ¢er_end_correction();
}
}
elsif ($align eq 'right') {
@@ -1649,6 +1759,35 @@ sub start_a {
my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
undef,1);
$currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href});
+ if ($href =~ /\S/) {
+ if ($href !~ m{^https?://}) {
+ my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
+ my $linkurl;
+ if ($href =~ m{^/uploaded/}) {
+ $linkurl = $href;
+ } elsif ($href =~ m{^[^/]}) {
+ my $path = $url;
+ $path =~ s{[^/]*$}{};
+ $linkurl = $path.$href;
+ }
+ if ($linkurl =~ m{^/uploaded/}) {
+ if (!&Apache::lonnet::allowed('bre',$linkurl)) {
+ if (&Apache::lonnet::is_on_map($url)) {
+ &Apache::lonxml::extlink($linkurl);
+ } elsif ($env{'request.course.id'}) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if ($linkurl =~ m{^([^/]|/uploaded/$cdom/$cnum/(docs|supplemental)/)}) {
+ my $cleanhref = &clean_docs_httpref($linkurl,$url,$cdom,$cnum);
+ if ($cleanhref) {
+ &Apache::lonxml::extlink($cleanhref);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
return $currentstring;
}
@@ -1689,11 +1828,11 @@ sub start_li {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $currentstring = '';
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring = $token->[4];
+ $currentstring = $token->[4];
} elsif ($target eq 'tex') {
my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
my $value=&Apache::lonxml::get_param('value',$parstack,$safeeval,undef,0);
- #FIXME need to support types i and I
+ #FIXME need to support types i and I
if ($type=~/disc/) {
$currentstring .= ' \item[$\bullet$] ';
} elsif ($type=~/circle/) {
@@ -1710,7 +1849,7 @@ sub start_li {
$currentstring .= ' \item['.$value.'] ';
} else {
$currentstring .= ' \item ';
- }
+ }
$Apache::londefdef::list_index++;
}
return $currentstring;
@@ -1720,8 +1859,8 @@ sub end_li {
my ($target,$token) = @_;
my $currentstring = &end_p(); # In case there's a tag (end tag required)
#
also ends any prior
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]) {
- $Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]=$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn];
- }
+ my $table = new Apache::lontable();
+ if ((defined $border) && ($border > 0)) {
+ # &Apache::lonnet::logthis("Turning on table borders: $border");
+ $table->table_border(1);
+ if (!defined $cell_border) {
+ $table->cell_border(1); # Default for rules is all if rules not defined.
}
}
- #free space and number of empty columns
- my ($available_space,$empty_columns)=($Apache::londefdef::table[-1]{'width'},0);
- if ($#Apache::londefdef::table ne 0) {$available_space=0.9*$available_space;}
- for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
- if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]==0) {
- $empty_columns++;
+
+ if ((defined $cell_border)) {
+ if ($cell_border eq 'all') {
+ $table->cell_border(1);
+ } elsif ($cell_border eq 'rows') {
+ $table->cell_border(2);
+ } elsif ($cell_border eq 'cols') {
+ $table->cell_border(3);
+ } elsif($cell_border eq 'groups') {
+ $table->cell_border(4);
} else {
- $available_space=$available_space-$Apache::londefdef::table[-1]{'TeXlen'}[0][$jn];
+ $table->cell_border(0);
}
}
-
- #boundaries for contents columns
- my @min_len=();#columns can not be narrower
- my @max_len=();#maximum length of column
- 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]) {
- $localmin=$Apache::londefdef::table[-1]{'minlen'}[$in][$jn];
- }
- if ($localmax<$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn]) {
- $localmax=$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn];
- }
- }
- push @min_len, $localmin;
- push @max_len, $localmax;
- $avg_max = $localmax + $avg_max;
- $avg_min = $localmin + $avg_min;
+ if (defined $theme) {
+ $table->theme($theme);
}
- # 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;
+ if (defined $align) {
+ $table->alignment($align);
}
+ # Missing width is most of page width
- # 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;
+ if (!(defined $width)) {
+ $width = '70%';
}
-
- 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]) {
- $localmin=$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn];
- }
- }
- if ($max_len[$jn]<$localmin) {
- $max_len[$jn]=$localmin;
- $Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1;
- }#object size is bigger
- if ($min_len[$jn]<$localmin) {
- $min_len[$jn]=$localmin;
- $Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1;
- }#object size is bigger
- if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]!=0) {
- $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_needed=0;
- for (my $jn=0;$jn<=$#max_len;$jn++) {
- $space_needed=$space_needed+$max_len[$jn];
- }
- if ($space_needed<=$available_space) {
-
- for (my $jn=0;$jn<=$#max_len;$jn++) {
- if ($fwidth[$jn]==0) {
- $fwidth[$jn]=$max_len[$jn];
- }
- }
- } else {
- #step 2. adjustment by minimum value (estimation)
- $space_needed=0;
- for (my $jn=0;$jn<=$#min_len;$jn++) {
- $space_needed+=$min_len[$jn];
- }
- if ($space_needed>$available_space) {
- $WARNING=' \textbf{NOT ENOUGH SPACE FOR TABLE} ';
- for (my $jn=0;$jn<=$#max_len;$jn++) {
- if ($fwidth[$jn]==0) {
- $fwidth[$jn]=$min_len[$jn];
- }
- }
- #check if we have objects which can be scaled
- my $how_many_to_scale=0;
- my @to_scale=();
- for (my $jn=0;$jn<=$#max_len;$jn++) {
- if ($Apache::londefdef::table[-1]{'objectsignal'}[$jn] eq '1') {
- $how_many_to_scale++;
- push @to_scale, $jn;
- }
- }
- if ($how_many_to_scale>0) {
- 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)*)/;
- if ($1 ne '') {
- my $current_length=&recalc($1);
- $current_length=~/(\d+\.?\d*)/;
- $current_length=$current_length-$space_to_adjust;
- $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/width=$current_length mm/;
- }
- $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/\[(\d+\.?\d*)\s*mm\]/;
- if ($1 ne '') {
- my $current_length=$1;
- $current_length=$current_length-$space_to_adjust;
- $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/\[(\d+\.?\d*)\s*mm\]/\[$current_length mm\]/;
- }
- }
- $fwidth[$jn]=$fwidth[$jn]-$space_to_adjust;
- }
- }
- } else {
- #step 3. adjustment over minimal + corrections
- 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;
- if ($adjust[$jn]>$max_len[$jn]) {
- $fwidth[$jn]=$max_len[$jn];
- $acsessive=$acsessive+$adjust[$jn]-$max_len[$jn];
- $adjust[$jn]=0;
-
- }
- }
- if ($acsessive>0) {
- #we have an excess of space and can redistribute it
- my $notempty_columns=0;
- for (my $jn=0;$jn<=$#min_len;$jn++) {
- if ($adjust[$jn]!=0) {
- $notempty_columns++;
- }
- }
- my $per_column=$acsessive/$notempty_columns;
- for (my $jn=0;$jn<=$#min_len;$jn++) {
- if ($adjust[$jn]!=0) {
- $adjust[$jn]+=$per_column;
- $fwidth[$jn]=$adjust[$jn];
- }
- }
- } else {
- for (my $jn=0;$jn<=$#min_len;$jn++) {
- $fwidth[$jn]=$adjust[$jn];
- }
- }
- }
- }
- # 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);
- if ($permission eq 'yes') {
- my @cleaned_table=();
- my @cleaned_header=();
- my $colind=0;
- for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
- if ($fwidth[$jn]!=0) {
- #we need to copy column
- for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
- $cleaned_table[$in][$colind]=$Apache::londefdef::table[-1]{'content'}[$in][$jn];
- $cleaned_header[$colind]=$fwidth[$jn];
- }
- $colind++;
- }
- }
- $Apache::londefdef::table[-1]{'content'}=\@cleaned_table;
- @fwidth=@cleaned_header;
+ # If a percentage, need to calculate what this means in terms of
+ # page width:
+
+ if ($width =~ /%$/) {
+ my $textwidth = &recalc($env{'form.textwidth'}); # Page width in mm.
+ $width =~ s/%//;
+ $width = $width * $textwidth / 100.0;
+ $width .= " mm";
+ $table->width($width);
}
+ push(@Apache::londefdef::table, $table);
+ $currentstring.=' \keephidden{NEW TABLE ENTRY}';
- #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;
- for (my $jn=0;$jn<=$#fwidth;$jn++) {
-
- #-----------------------------------------------------------
- # I think this order of doing things will ensure that
- # 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) {
- for (my $spancol = $jn; $spancol < $jn + $colspan; $spancol++) {
- $spanwidth += $fwidth[$spancol];
- }
- $output .= '\multicolumn{'.
- $colspan
- ."}";
- if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') {
- $output .= '{'.$border_char.'c'.$border_char.'}{';
- } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') {
- $output .= '{'.$border_char.'r'.$border_char.'}{';
- }
- else {
- $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
- # to kick in a multicolumn in order to get the alignment spec.
- # this must precede the multirow or LaTex gets quite upset.
- # Naturally if colspan > 1 we've already done that above ^
- #
- my $multirow_aligned = 0;
- if ($rowspan > 1) {
- if ($colspan == 1) {
- if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq '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}{'.$border_char.'r'.$border_char.'}{';
- $multirow_aligned = 1;
- }
- }
- $have_rowspan++;
- 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 {
- # so we close correctly without having to keep additional state
- # around
- #
- if (!$multirow_aligned) {
- $output .= '{';
- }
- }
- if (($rowspan eq '^') || ($rowspan eq '_')) {
- $have_rowspan++;
- }
- #--------------------------------------------------------------
-
-
- # For right and center alignment of single cells.
- # we are going to use a multicolumn with a span of 1 to specify alignment.
- #
- if ($colspan == 1 && $rowspan == 1) {
- if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') {
- $output .= '\multicolumn{1}{'.$border_char.'c'.$border_char.'}{';
- } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') {
- $output .= '\multicolumn{1}{'.$border_char.'r'.$border_char.'}{';
- }
- }
-
- $output.=$Apache::londefdef::table[-1]{'content'}[$in][$jn];
-
- if (($colspan == 1 && $rowspan == 1) &&
- (($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') ||
- ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r'))) {
- $output .= '}';
- }
-
- # Close off any open multirow:
-
- if ($rowspan > 1) {
- $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'};}
- }
- # If have_rowspan > 0, and borders are on, then
- # we need to do more than put an \hline at the bottom of row.
- # we need to do the appropriate \cline to ensure that
- # the spanned rows don't have \hlines through them.
-
- if (($Apache::londefdef::table[-1]{'hinc'} =~ /\\hline/) && $have_rowspan) {
- $output .= ' \\\\ ';
- for (my $jn=0; $jn<=$#fwidth;$jn++) {
- my $rowspan = $Apache::londefdef::table[-1]{'rowspan'}[$in][$jn];
- if ($rowspan ne "^") {
- if (($rowspan <= 1) || ($rowspan eq '_')) {
- my $column = $jn+1;
- $output .= '\cline{'.$column.'-'.$column.'} ';
- }
- }
- }
-
- } else {
- $output.=' \\\\ '.$Apache::londefdef::table[-1]{'hinc'}.' ';
- }
- }
- # Note that \newline destroys alignment env's produced by e.g. bodies
#
-#list of supported attributes: border,width,TeXwidth
+#list of supported attributes: border,width,TeXwidth,TeXtheme
+# align
sub start_table {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
my $textwidth = '';
my $currentstring = &end_p();
if ($target eq 'web' || $target eq 'webgrade') {
- $currentstring .= $token->[4];
+ $currentstring .= $token->[4];
} elsif ($target eq 'tex') {
- 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.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
- $textwidth=$Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}];
- } else {
- #try to use all space not used before (minus 5% for LaTeX table internal) - rather silly
- $textwidth=$Apache::londefdef::table[-2]{'width'};
- for (my $i=0;$i<$Apache::londefdef::table[-2]{'counter_columns'};$i++) {
- $textwidth=$textwidth-$Apache::londefdef::table[-2]{'TeXlen'}[0][$i];
- }
- }
- }
+ &disable_para(); # Can't have paras in a table.
- # width either comes forced from the TeXwidth or the width parameters.
- # in either case it can be a percentage or absolute width.
- # in the width case we ignore absolute width
- my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
- if (!defined($TeXwidth)) {
- my $htmlwidth = &Apache::lonxml::get_param('width',$parstack,
- $safeeval,undef,1);
- if ($htmlwidth =~ /%/) {
- $TeXwidth = $htmlwidth;
- } else {
- $TeXwidth = $textwidth;
- }
- }
- # if the width is specified as a % it is converted to an absolute width.
- # otherwise.. just plugged right in the hash
+ # Get the parameters that we can do something about:
- if ($TeXwidth=~/%/) {
- $TeXwidth=~/(\d+)/;
- $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100;
- } else {
- $Apache::londefdef::table[-1]{'width'}=$TeXwidth;
- }
- # In the end, however the table width cannot be wider than $textwidth...
-
- 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);
- unless (defined $border) { $border = 0; }
- if ($border) {
- $Apache::londefdef::table[-1]{'hinc'} = '\hline ';
- $Apache::londefdef::table[-1]{'vinc'} = '&';
- $Apache::londefdef::table[-1]{'vvinc'} = '|';
- } else {
- $Apache::londefdef::table[-1]{'hinc'} = '';
- $Apache::londefdef::table[-1]{'vinc'} = '&';
- $Apache::londefdef::table[-1]{'vvinc'} = '';
- }
- if ($#Apache::londefdef::table==0) {
- # 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'}=[];
- $Apache::londefdef::table[-1]{'objectlen'}=[];
- $Apache::londefdef::table[-1]{'objectsignal'}=[];
- $Apache::londefdef::table[-1]{'maxlen'}=[];
- $Apache::londefdef::table[-1]{'minlen'}=[];
- $Apache::londefdef::table[-1]{'content'}=[];
- $Apache::londefdef::table[-1]{'align'}=[];
- $currentstring.=' \keephidden{NEW TABLE ENTRY}';
+ my $border = &Apache::lonxml::get_param('border', $parstack, $safeeval, undef, 0);
+ my $width = &Apache::lonxml::get_param('TeXwidth', $parstack, $safeeval, undef, 0);
+ my $theme = &Apache::lonxml::get_param('TeXtheme', $parstack, $safeeval, undef, 0);
+ my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 0);
+ my $cell_border = &Apache::lonxml::get_param('rules', $parstack, $safeeval, undef, 0);
+ # The only thing that needs any figuring out is the width.. and then only if it is
+ # a percent. If not it's assumed to be some valid TeX measurement unit e.g. 3.0cm
+ #
- }
- return $currentstring;
-}
-
-sub end_table {
- my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
- my $currentstring = '';
- 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
';
+ &Apache::edit::browse_or_search('src',undef,'alt',$only,undef,1).
+ '
';
$currentstring .=&Apache::edit::text_arg('Description:','alt',$token,70).'
';
$currentstring .=&Apache::edit::text_arg('width (pixel):','width',$token,5);
$currentstring .=&Apache::edit::text_arg('height (pixel):','height',$token,5).'
';
@@ -3074,22 +2911,31 @@ sub start_img {
['','bottom','middle','top','left','right'],$token,5);
$currentstring .=&Apache::edit::select_arg('TeXwrap:', 'TeXwrap',
['', 'none','parbox', 'parpic', 'wrapfigure'], $token, 2);
+ my $alt= &Apache::lonxml::get_param('alt',$parstack,$safeeval);
+ my $enc= &Apache::lonxml::get_param('encrypturl',$parstack,$safeeval);
+
$currentstring .=&Apache::edit::select_arg('Encrypt URL:','encrypturl',
['no','yes'], $token, 2);
+ if (($alt=~/\S/) && (lc($enc) eq 'yes')) {
+ $currentstring.='
'.&mt('Warning: the description "[_1]" will be available, even for encrypted URL',$alt).'
';
+ }
$currentstring .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
my $src= &Apache::lonxml::get_param('src',$parstack,$safeeval);
- my $alt= &Apache::lonxml::get_param('alt',$parstack,$safeeval);
my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval);
my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
-
+ my $element = &Apache::edit::get_element('src');
+ my $text;
if ($token->[2]{'src'}=~/\$/) {
- $currentstring.='Variable image source';
- } else {
+ $text = &mt('Variable image source');
+ } elsif ($token->[2]{'src'}=~/\S/) {
$currentstring .= '';
+ } else {
+ $text = &mt("No image source specified");
}
+ $currentstring .= ' '.$text.'';
} elsif ($target eq 'modified') {
my ($osrc,$owidth,$oheight)=
($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'});
@@ -3110,7 +2956,7 @@ sub start_img {
}
if ($osrc ne $nsrc || (!$nwidth && !$nheight)) {
# changed image or no size specified,
- # if they didn't explicitly change the
+ # if they didn't explicitly change the
# width or height use the ones from the image
if ($iwidth && $iheight) {
if ($owidth == $nwidth || (!$nwidth && !$nheight)) {
@@ -3149,7 +2995,7 @@ sub end_img {
#--