Diff for /loncom/xml/londefdef.pm between versions 1.172 and 1.402

version 1.172, 2003/09/25 15:52:57 version 1.402, 2009/04/20 10:40:04
Line 36 Line 36
 # The C source of the Code may not be distributed by the Licensee  # The C source of the Code may not be distributed by the Licensee
 # to any other parties under any circumstances.  # to any other parties under any circumstances.
 #  #
 #  
 # last modified 06/26/00 by Alexander Sakharuk  
 # 11/6,11/30,02/01/01,5/4 Gerd Kortemeyer  
 # 01/18 Alex Sakharuk  
   
 package Apache::londefdef;   package Apache::londefdef; 
   
 use Apache::lonnet();  use Apache::lonnet;
 use strict;  use strict;
 use Apache::lonxml;  use Apache::lonxml;
   use Apache::lontable;
 use Apache::File();  use Apache::File();
 use Image::Magick;  use Image::Magick;
 use Apache::lonmenu();  use Apache::lonmenu();
 use Apache::lonmeta();  use Apache::lonmeta();
   use Apache::lonlocal;
 $Apache::londefdef::TD_redirection=0;  use Apache::Constants qw(:common);
   use File::Basename;
   use LONCAPA();
   # use Data::Dumper;
   
 BEGIN {  BEGIN {
   
Line 59  BEGIN { Line 59  BEGIN {
   
 }  }
   
   
   sub initialize_londefdef {
       $Apache::londefdef::TD_redirection=0;
       @Apache::londefdef::table = ();
       $Apache::londefdef::select=0;
       undef(@Apache::londefdef::description);
       @Apache::londefdef::DD=(0);
       @Apache::londefdef::DT=(0);
       @Apache::londefdef::seenDT=(0);
       $Apache::londefdef::list_index=0;
       undef($Apache::londefdef::head);
       undef($Apache::londefdef::title);
   }
   
 #======================= TAG SUBROUTINES =====================  #======================= TAG SUBROUTINES =====================
 #-- <output>  #-- <output>
 sub start_output {  sub start_output {
Line 73  sub end_output { Line 87  sub end_output {
 }  }
 #-- <m> tag  #-- <m> tag
 sub start_m {  sub start_m {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);
  $Apache::lonxml::prevent_entity_encode++;      if ($target eq 'web' || $target eq 'analyze') {
  my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);  
  $inside ='\\documentstyle{article}'.$inside;  
  &Apache::lonxml::debug("M is starting with:$inside:");   &Apache::lonxml::debug("M is starting with:$inside:");
  my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);   my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
  if ($eval eq 'on') {   if ($eval eq 'on') {
     $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);      $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
     #&Apache::lonxml::debug("M is evaulated to:$inside:");      #&Apache::lonxml::debug("M is evaluated to:$inside:");
  }   }
  $currentstring = &Apache::lontexconvert::converted(\$inside);   my $tex = $inside;
    my $display=&Apache::lonxml::get_param('display',$parstack,$safeeval);
    $currentstring = &Apache::lontexconvert::converted(\$inside,$display);
  if ($Apache::lontexconvert::errorstring) {   if ($Apache::lontexconvert::errorstring) {
     &Apache::lonxml::warning("tth error: ".      my $errormsg='<pre>'.&HTML::Entities::encode($Apache::lontexconvert::errorstring,'<>&"').'</pre> occurred while attempting to convert this TeX: <pre>';
      $Apache::lontexconvert::errorstring);      $tex = &HTML::Entities::encode($tex,'<>&"');
       my ($linenumber) =
    ($Apache::lontexconvert::errorstring =~ /Line (\d+)/);
       if (defined($linenumber)) {
    my @tex=split("\n",$tex);
    $tex[$linenumber]='<b><font color="red">'.
       $tex[$linenumber].'</font></b>';
    $tex=join("\n",@tex);
       }
       &Apache::lonxml::warning($errormsg.$tex.'</pre>');
     $Apache::lontexconvert::errorstring='';      $Apache::lontexconvert::errorstring='';
  }   }
  #&Apache::lonxml::debug("M is ends with:$currentstring:");   #&Apache::lonxml::debug("M is ends with:$currentstring:");
    $Apache::lonxml::post_evaluate=0;
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);  
    $currentstring = $inside;
    my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
    if ($eval eq 'on') {
       $currentstring=&Apache::run::evaluate($currentstring,$safeeval,$$parstack[-1]);
    }
  if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}   if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}
     } else {   # detect simple math mode entry exits, and convert them
  my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);          # 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;
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 104  sub start_m { Line 141  sub start_m {
 sub end_m {  sub end_m {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'tex') {
  $Apache::lonxml::prevent_entity_encode--;  
     } elsif ($target eq 'tex') {  
  $currentstring = "";   $currentstring = "";
     } elsif ($target eq 'meta') {  
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 sub start_tthoption {  sub start_tthoption {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $result;      my $result;
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $inside = &Apache::lonxml::get_all_text("/tthoption",$parser);   my $inside = &Apache::lonxml::get_all_text("/tthoption",$parser,
      $style);
  $inside=~s/^\s*//;   $inside=~s/^\s*//;
  if ($ENV{'browser.mathml'}) {   if ($env{'browser.mathml'}) {
     &tth::ttmoptions($inside);      &tth::ttmoptions($inside);
  } else {   } else {
     &tth::tthoptions($inside);      &tth::tthoptions($inside);
Line 134  sub end_tthoption { Line 169  sub end_tthoption {
     return $result;      return $result;
 }  }
   
 #-- <html> tag      #-- <html> tag (end tag optional)
 sub start_html {  sub start_html {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($ENV{'browser.mathml'}) {      if ($target eq 'web' || $target eq 'edit' || $target eq 'webgrade' ) {
  &tth::ttminit();   # start_body() takes care of emitting the <html> 
  if ($ENV{'browser.unicode'}) {  
     &tth::ttmoptions('-L -u1');  
  } else {  
     &tth::ttmoptions('-L -u0');  
  }  
     } else {  
  &tth::tthinit();  
  if ($ENV{'browser.unicode'}) {  
     &tth::tthoptions('-L -u1');  
  } else {  
     &tth::tthoptions('-L -u0');  
  }  
     }  
     if ($target eq 'web') {  
  $currentstring = &Apache::lonxml::xmlbegin().  
     &Apache::lonxml::fontsettings();       
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  @Apache::londefdef::table = ();  
  $currentstring .= '\documentclass[letterpaper]{article}';   $currentstring .= &latex_header();
  if ($ENV{'form.latex_type'}=~'batchmode') {$currentstring .='\batchmode';}   
  $currentstring .= '\newcommand{\keephidden}[1]{}  
                            \renewcommand{\deg}{$^{\circ}$}  
                            \usepackage{longtable}  
                            \usepackage{textcomp}  
                            \usepackage{makeidx}  
                            \usepackage[dvips]{graphicx}  
                            \usepackage{epsfig}\usepackage{calc}  
 \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;      return $currentstring;
 }  }
   
 sub end_html {  sub end_html {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = &Apache::lonxml::xmlend();   # end_body takes care of the </html>
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <head> tag  #-- <head> tag (end tag optional)
 sub start_head {  sub start_head {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        &Apache::lonxml::startredirection();
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 195  sub start_head { Line 204  sub start_head {
 sub end_head {  sub end_head {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if (($target eq 'web'      && $env{'request.state'} eq 'published') ||
  $currentstring = &Apache::lonmenu::registerurl(undef,$target).   ($target eq 'webgrade' && $env{'request.state'} eq 'published')) {
     $token->[2];       # in case there is a </head> but no <head>
    if ($Apache::lonxml::redirection) {
       $Apache::londefdef::head = &Apache::lonxml::endredirection();
    }
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <map> tag  #-- <map> tag (end tag required)
 sub start_map {  sub start_map {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 215  sub start_map { Line 227  sub start_map {
 sub end_map {  sub end_map {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <select> tag  #-- <select> tag (end tag required)
 sub start_select {  sub start_select {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       }  elsif ($target eq 'tex') {
    $Apache::londefdef::select=0;
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_select {  sub end_select {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <option> tag  #-- <option> tag (end tag optional)
 sub start_option {  sub start_option {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      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) {
       $currentstring='\noindent\fbox{'.&Apache::lonxml::get_param('value',$parstack,$safeeval).'}\keephidden{';
    } else {
       $currentstring='\keephidden{';
    }
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_option {  sub end_option {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       }  elsif ($target eq 'tex') {
    $currentstring='}';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <input> tag  #-- <input> tag (end tag forbidden)
 sub start_input {  sub start_input {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 272  sub start_input { Line 295  sub start_input {
 sub end_input {  sub end_input {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <textarea> tag  #-- <textarea> tag (end tag required)
 sub start_textarea {  sub start_textarea {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 291  sub start_textarea { Line 314  sub start_textarea {
 sub end_textarea {  sub end_textarea {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <form> tag  #-- <form> tag (end tag required)
 sub start_form {  sub start_form {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 310  sub start_form { Line 333  sub start_form {
 sub end_form {  sub end_form {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <title> tag  #-- <title> tag (end tag required)
 sub start_title {  sub start_title {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $Apache::londefdef::title = 
       &Apache::lonxml::get_all_text('/title',$parser,$style);
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\keephidden{Title of the document:  '    $currentstring .= '\keephidden{Title of the document:  ' 
     }      }
     if ($target eq 'meta') {      if ($target eq 'meta') {
  $currentstring='<title>';   $currentstring='<title>';
  &start_output();   &start_output($target);
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 335  sub start_title { Line 359  sub start_title {
 sub end_title {  sub end_title {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       # start_title takes care of swallowing the title
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
     }        }  
     if ($target eq 'meta') {      if ($target eq 'meta') {
  &end_output();   &end_output($target);
  $currentstring='</title>';   $currentstring='</title>';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <meta> tag  #-- <meta> tag (end tag forbidden)
 sub start_meta {  sub start_meta {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $args='';   my $args='';
  if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }   if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
  if ($args eq '') {   if ($args eq '') {
     &Apache::lonxml::get_all_text("/meta",$parser);      &Apache::lonxml::get_all_text("/meta",$parser,$style);
  } else {   } else {
     $currentstring = $token->[4];      $currentstring = $token->[4];
  }   }
Line 382  sub start_meta { Line 406  sub start_meta {
             my $display=&Apache::lonxml::get_param              my $display=&Apache::lonxml::get_param
  ('display',$parstack,$safeeval,undef,1);   ('display',$parstack,$safeeval,undef,1);
             if ($display) {              if ($display) {
  $display=&HTML::Entities::encode($display);   $display=&HTML::Entities::encode($display,'<>&"');
  $currentstring.='<'.$name.'.display>'.$display.   $currentstring.='<'.$name.'.display>'.$display.
                                '</'.$name.'.display>';                                 '</'.$name.'.display>';
             }              }
Line 393  sub start_meta { Line 417  sub start_meta {
  if ((not defined $content) && (not defined $name)) {   if ((not defined $content) && (not defined $name)) {
     &Apache::lonxml::startredirection();      &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;      return $currentstring;
 }  }
Line 400  sub start_meta { Line 434  sub start_meta {
 sub end_meta {  sub end_meta {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $args='';   my $args='';
  if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }   if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
  if ($args ne '') {   if ($args ne '') {
Line 416  sub end_meta { Line 450  sub end_meta {
     return $currentstring;      return $currentstring;
 }  }
   
   sub insert_meta {
       return '
       <meta />';
   }
   
 # accessrule  # accessrule
 sub start_accessrule {  sub start_accessrule {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';      my $currentstring = '';
     my $eff=&Apache::lonxml::get_param      my $eff  =&Apache::lonxml::get_param('effect',$parstack,$safeeval,undef,1);
  ('effect',$parstack,$safeeval,undef,1);      my $realm=&Apache::lonxml::get_param('realm', $parstack,$safeeval,undef,1);
     my $realm=&Apache::lonxml::get_param      my $role =&Apache::lonxml::get_param('role',  $parstack,$safeeval,undef,1);
  ('realm',$parstack,$safeeval,undef,1);      my $type =&Apache::lonxml::get_param('type',  $parstack,$safeeval,undef,1);
     my $role=&Apache::lonxml::get_param  
  ('role',$parstack,$safeeval,undef,1);      my ($dom,$crs,$sec,$separator);
     $realm=~s/\s+//g;      if ($type eq 'user') {
     $realm=~s/\//\_/g;   ($dom,$crs,$sec)=split(m{/},$realm);
     $realm=~s/^\_//;   $crs = &LONCAPA::clean_username($crs);
     $realm=~s/\W/\;/g;   $separator = '/';
     $role=~s/\s+//g;      } else {
     $role=~s/\//\_/g;   ($dom,$crs,$sec)=split(/\_/,$realm);
     $role=~s/\W/\;/g;   $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') {      if ($target eq 'web') {
  my $args='';   my $args='';
  if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }   if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
  if ($args eq '') {   if ($args eq '') {
     &Apache::lonxml::get_all_text("/accessrule",$parser);      &Apache::lonxml::get_all_text("/accessrule",$parser,$style);
  } else {   } else {
     $currentstring = $token->[4];      $currentstring = $token->[4];
  }   }
     }      }
     if ($target eq 'meta') {      if ($target eq 'meta') {
  $currentstring='<rule>'.$eff.':'.$realm.':'.$role.'</rule>';   $currentstring='<rule>'.$eff.':'.$realm.':'.$role.':'.$type.'</rule>';
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 461  sub end_accessrule { Line 510  sub end_accessrule {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <body> tag  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 .= 
       '<link rel="stylesheet" type="text/css" href="'.$css_href.'" />';
       }
       return $links;
   }
   
   #-- <body> tag (end tag required)
 sub start_body {  sub start_body {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {  
       if ($target eq 'web' || $target eq 'webgrade') {
  if ($Apache::lonhomework::parsing_a_problem) {   if ($Apache::lonhomework::parsing_a_problem) {
     &Apache::lonxml::warning("<body> tag found inside of <problem> tag this can cause problems.");      &Apache::lonxml::warning("<body> tag found inside of <problem> tag this can cause problems.");
     return '';      return '';
  }   }
  if (!$Apache::lonxml::registered) {  
     $currentstring.='<head>'.   if (&is_inside_of($tagstack, "head")) {
  &Apache::lonmenu::registerurl(undef,$target).'</head>';      &end_head(@_);
  }  
 # Accessibility  
  if ($ENV{'browser.imagesuppress'} eq 'on') {  
     delete($token->[2]->{'background'});  
  }  
  if ($ENV{'browser.fontenhance'} eq 'on') {  
     my $style='';  
     foreach my $key (keys(%{$token->[2]})) {  
  if ($key =~ /^style$/i) {  
     $style.=$token->[2]->{$key}.';';  
     delete($token->[2]->{$key});  
  }  
     }  
     $token->[2]->{'style'}=$style.'; font-size: x-large;';  
  }  
  if ($ENV{'browser.blackwhite'} eq 'on') {  
     delete($token->[2]->{'font'});  
     delete($token->[2]->{'link'});  
     delete($token->[2]->{'alink'});  
     delete($token->[2]->{'vlink'});  
     delete($token->[2]->{'bgcolor'});  
     delete($token->[2]->{'background'});  
  }  
 # Overload loads  
  my $onLoad='';  
  foreach my $key (keys(%{$token->[2]})) {  
     if ($key =~ /^onload$/i) {  
  $onLoad.=$token->[2]->{$key}.';';  
  delete($token->[2]->{$key});  
     }  
  }  
  $token->[2]->{'onload'}=&Apache::lonmenu::loadevents().';'.$onLoad;  
  my $onUnload='';  
  foreach my $key (keys(%{$token->[2]})) {  
     if ($key =~ /^onunload$/i) {  
  $onUnload.=$token->[2]->{$key}.';';  
  delete($token->[2]->{$key});  
     }  
  }   }
  $token->[2]->{'onunload'}=&Apache::lonmenu::unloadevents().  
     ';'.$onUnload;  
   
  $currentstring .= '<'.$token->[1];   my $extra_head = &generate_css_links();
  foreach (keys %{$token->[2]}) {  
     $currentstring.=' '.$_.'="'.$token->[2]->{$_}.'"';   $currentstring = 
  }      &Apache::loncommon::start_page($Apache::londefdef::title,
  $currentstring.='>';     $Apache::londefdef::head
  if ($ENV{'request.state'} ne 'published') {        .$extra_head,
     $currentstring.=(<<EDITBUTTON);     {'add_entries'    => $token->[2],
  <form method="post">      'no_title'       => 1,
  <input type="submit" name="editmode" value="Edit" />      'force_register' => 1});
  </form>  
 EDITBUTTON   if ($env{'request.state'} ne 'published') {
  } else {      $currentstring.=&Apache::lonmenu::constspaceform();
     $currentstring.=&Apache::lonmenu::menubuttons(undef,$target,1);      $currentstring.=&Apache::londefdef::edit_controls();
  }   }
    $currentstring.=&Apache::lonxml::message_location();
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\begin{document}';     $currentstring = '\begin{document}';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
   sub edit_controls {
       my ($nochgview) = @_;
       my $result .= '
   <form method="post">
   <div class="LC_edit_problem_header">';
       unless ($nochgview) {
           $result .= '
   <div class="LC_edit_problem_header_row1">'.
   &Apache::lonxml::renderingoptions().'
   <input type="submit" name="changeproblemmode" value="'.&mt('Change View').'" />
   </div>';
       }
       $result .= '
   <div class="LC_edit_problem_header_edit_row"><input type="submit" name="editmode" accesskey="e" value="'.&mt('Edit').'" /></div></div>
   </form>
   <br />';
       return $result;
   }
   
 sub end_body {  sub end_body {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off unclosed <p>
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring .= &Apache::loncommon::end_page({'discussion' => 1});
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent \end{document}';     $currentstring .= '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent \end{document}';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <center> tag  # \begin{center} causes a new paragprah spacing that looks odd inside 
   # of a table cell.  Same at the end of a \center but with a slightly
   # larger space .. hence center_correction and center_end_correction.
   #
   sub center_correction { return '\vspace*{-6 mm}'; } 
   sub center_end_correction { return '\vspace*{-7 mm}'; }
   
   #-- <center> tag (end tag required)
 sub start_center {  sub start_center {
     my ($target,$token) = @_;      my ($target,$token,$tagstack) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\begin{center}';     if (&is_inside_of($tagstack, "table")) {
       $currentstring .= &center_correction();
    }
    $currentstring .= '\begin{center}';  
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_center {  sub end_center {
     my ($target,$token) = @_;      my ($target,$token,$tagstack) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\end{center}';     $currentstring = '\end{center}';  
    if (&is_inside_of($tagstack, "table")) {
       $currentstring .= &center_end_correction();
    }
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <b> tag  #-- <b> tag (end tag required)
   #      NOTE: In TeX mode disables internal <p>
 sub start_b {  sub start_b {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\textbf{';     &disable_para();
    $currentstring .= '\textbf{';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 584  sub start_b { Line 640  sub start_b {
 sub end_b {  sub end_b {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '}';     &enable_para();
    $currentstring = '}';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <strong> tag  #-- <strong> tag (end tag required)
   #    NOTE: in TeX mode disables internal <p>
 sub start_strong {  sub start_strong {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
    &disable_para();
  $currentstring = '\textbf{';     $currentstring = '\textbf{';  
     }       } 
     return $currentstring;      return $currentstring;
Line 607  sub start_strong { Line 666  sub start_strong {
 sub end_strong {  sub end_strong {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
   
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
    &enable_para();
  $currentstring = '}';     $currentstring = '}';  
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <h1> tag  #-- <h1> tag (end tag required)
 sub start_h1 {  sub start_h1 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=lc(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1));
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 634  sub start_h1 { Line 693  sub start_h1 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     } elsif ($target eq 'meta') {      } elsif ($target eq 'meta') {
  $currentstring='<subject>';   $currentstring.='<subject>';
  &start_output();   &start_output($target);
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 645  sub start_h1 { Line 704  sub start_h1 {
 sub end_h1 {  sub end_h1 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 659  sub end_h1 { Line 718  sub end_h1 {
  }   }
  $currentstring .= '}}'.$post;   $currentstring .= '}}'.$post;
     } elsif ($target eq 'meta') {      } elsif ($target eq 'meta') {
  &end_output();   &end_output($target);
  $currentstring='</subject>';   $currentstring='</subject>';
     }       } 
     return $currentstring;      return $currentstring;
Line 668  sub end_h1 { Line 727  sub end_h1 {
 #-- <h2> tag  #-- <h2> tag
 sub start_h2 {  sub start_h2 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 683  sub start_h2 { Line 742  sub start_h2 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 691  sub start_h2 { Line 750  sub start_h2 {
 sub end_h2 {  sub end_h2 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 711  sub end_h2 { Line 770  sub end_h2 {
 #-- <h3> tag  #-- <h3> tag
 sub start_h3 {  sub start_h3 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 726  sub start_h3 { Line 785  sub start_h3 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 734  sub start_h3 { Line 793  sub start_h3 {
 sub end_h3 {  sub end_h3 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 754  sub end_h3 { Line 813  sub end_h3 {
 #-- <h4> tag  #-- <h4> tag
 sub start_h4 {  sub start_h4 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 769  sub start_h4 { Line 828  sub start_h4 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 777  sub start_h4 { Line 836  sub start_h4 {
 sub end_h4 {  sub end_h4 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 797  sub end_h4 { Line 856  sub end_h4 {
 #-- <h5> tag  #-- <h5> tag
 sub start_h5 {  sub start_h5 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior paras.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 812  sub start_h5 { Line 871  sub start_h5 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 820  sub start_h5 { Line 879  sub start_h5 {
 sub end_h5 {  sub end_h5 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 840  sub end_h5 { Line 899  sub end_h5 {
 #-- <h6> tag  #-- <h6> tag
 sub start_h6 {  sub start_h6 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any prior paras.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $pre;   my $pre;
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $pre='\begin{center}';      $pre='\begin{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $pre='\rlap{';      $pre='\rlap{';
Line 855  sub start_h6 { Line 914  sub start_h6 {
  }   }
  my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  if (not defined $TeXsize) {$TeXsize="large";}   if (not defined $TeXsize) {$TeXsize="large";}
  $currentstring .= $pre.'{\\'.$TeXsize.' \textbf{';    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 863  sub start_h6 { Line 922  sub start_h6 {
 sub end_h6 {  sub end_h6 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $post;   my $post='\vskip 0 mm ';
  my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if (($align eq 'center') || (not defined $align)) {   if ($align eq 'center') {
     $post='\end{center}';      $post='\end{center}';
  } elsif ($align eq 'left') {   } elsif ($align eq 'left') {
     $post='} \hfill'.'\vskip 0 mm ';      $post='} \hfill'.'\vskip 0 mm ';
Line 880  sub end_h6 { Line 939  sub end_h6 {
     return $currentstring;      return $currentstring;
 }  }
   
 #--- <cite> tag  #--- <cite> tag (end tag required)
 sub start_cite {  sub start_cite {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\\textit{";   $currentstring .= '\textit{';
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 895  sub start_cite { Line 954  sub start_cite {
 sub end_cite {  sub end_cite {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "}";   $currentstring .= '}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <i> tag  #-- <i> tag (end tag required)
 sub start_i {  sub start_i {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\textit{';   $currentstring .= '\textit{';
Line 918  sub start_i { Line 977  sub start_i {
 sub end_i {  sub end_i {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 926  sub end_i { Line 985  sub end_i {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <address> tag  #-- <address> tag (end tag required)
 sub start_address {  sub start_address {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\\textit{";   $currentstring .= '\textit{';
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 941  sub start_address { Line 1000  sub start_address {
 sub end_address {  sub end_address {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "}";   $currentstring .= '}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <dfn> tag  #-- <dfn> tag (end tag required)
 sub start_dfn {  sub start_dfn {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\\textit{";   $currentstring .= '\textit{';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 964  sub start_dfn { Line 1023  sub start_dfn {
 sub end_dfn {  sub end_dfn {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "}";   $currentstring .= '}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <tt> tag  #-- <tt> tag (end tag required)
 sub start_tt {  sub start_tt {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\texttt{';   $currentstring .= '\texttt{';
Line 987  sub start_tt { Line 1046  sub start_tt {
 sub end_tt {  sub end_tt {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 995  sub end_tt { Line 1054  sub end_tt {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <kbd> tag  #-- <kbd> tag (end tag required)
 sub start_kbd {  sub start_kbd {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\\texttt";   $currentstring .= '\texttt{';
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1010  sub start_kbd { Line 1069  sub start_kbd {
 sub end_kbd {  sub end_kbd {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "}";   $currentstring .= '}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <code> tag  #-- <code> tag (end tag required)
 sub start_code {  sub start_code {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\texttt{';   $currentstring .= '\texttt{';
Line 1033  sub start_code { Line 1092  sub start_code {
 sub end_code {  sub end_code {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 1041  sub end_code { Line 1100  sub end_code {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <em> tag  #-- <em> tag (end tag required)
 sub start_em {  sub start_em {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\emph{';   $currentstring .= '\emph{';
Line 1056  sub start_em { Line 1115  sub start_em {
 sub end_em {  sub end_em {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 1064  sub end_em { Line 1123  sub end_em {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <q> tag  #-- <q> tag (end tag required)
 sub start_q {  sub start_q {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\\emph{";   $currentstring .= '\emph{';
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1079  sub start_q { Line 1138  sub start_q {
 sub end_q {  sub end_q {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "}";   $currentstring .= '}';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <p> tag  #  <p> is a bit strange since it does not require a closing </p>
   #  However in latex, we must often output closing stuff to end
   #  environments and {}'s etc.  Therefore we do all the work
   #  of figuring out the ending strings in the start tag processing,
   #  and provide a mechanism to output the stop text external
   #  to tag processing.
   #
   {
   
       my $closing_string = ''; # String required to close <p>
   
   #   Some tags are <p> fragile meaning that <p> inside of them
   #   does not work within TeX mode.  This is managed via the 
   #   counter below:
   #
   
       my $para_disabled = 0;
   
   sub disable_para {
       $para_disabled++;
   }
   sub enable_para {
       $para_disabled--;
   }
   
   
   #-- <p> tag (end tag optional)
   #optional attribute - align="center|left|right"
 sub start_p {  sub start_p {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= &end_p(); # close off prior para if in progress.
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {   if (! ($currentstring =~ /\//)) {
  my $signal=1;      $closing_string = '</p>'; # Deal correctly with <p /> e.g.
  foreach my $tag (@$tagstack) {if (lc($tag) eq 'b') {$signal=0;}}   }
  if ($signal) {$currentstring .= '\par ';}      } elsif ($target eq 'tex' && !$para_disabled) {
   
    $currentstring .= &end_p(); # close off prior para if in progress.
    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($align eq 'center') {
       $currentstring .='\begin{center}\par ';
       $closing_string = '\end{center}';
       if (&is_inside_of($tagstack, "table")) {
    $currentstring = &center_correction().$currentstring;
       }
    } elsif ($align eq 'right') {
       $currentstring.="\n".'{\flushright ';
   #    $currentstring.='\makebox['.$env{'form.textwidth'}.']{\hfill\llap{';
       $closing_string= "}\n";
    } elsif ($align eq 'left') {
       $currentstring.= "\n".'{\flushleft ';
   #    $currentstring.='\noindent\makebox['.$env{'form.textwidth'}.']{{';
       $closing_string = "}\n";
    } else {
               $currentstring.='\par ';
       if (&is_inside_of($tagstack, 'table')) {
    $closing_string = '\vskip 0pt'; # Seems to be consistent with <p> in tables.
       } else {
    $closing_string = '\strut\\\\\strut ';
       }
           }
   
     }      }
     return $currentstring;      return $currentstring;
 }  }
   #
   #  End paragraph processing just requires that we output the
   #  closing string that was saved and blank it.
 sub end_p {  sub end_p {
     my ($target,$token) = @_;      #  Note only 'tex' mode uses disable_para and enable_para
     my $currentstring = '';      #  so we don't need to know the target in the check below:
     if ($target eq 'web') {  
  $currentstring .= $token->[2];      if (!$para_disabled) {
    my $current_string = $closing_string;
    $closing_string = ''; # Not in a para anymore.
    return $current_string;
       } else {
    return '';
     }      }
     return $currentstring;  
 }  
   
 #-- <br> tag  }
   }
   #-- <br> tag (end tag forbidden)
 sub start_br {  sub start_br {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  if ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') {   my @tempo=@$tagstack;
     $currentstring .= '\vskip 0.2 mm ';   my $signal=0;
    #  Not going to factor this to is_inside_of since that would require
           #  multiple stack traversals.
    #
    for (my $i=$#tempo;$i>=0;$i--) {
       if (($tempo[$i] eq 'b') || ($tempo[$i] eq 'strong') ||
                   ($tempo[$i] eq 'ol') || ($tempo[$i] eq 'ul'))  {
    $signal=1;
       }
       if (($tempo[$i] eq 'td') || ($tempo[$i] eq 'th')) {
    $signal = 1;
       }
    }
    if ($signal != 1) {
       $currentstring .= '\strut \\\\ \strut ';
  }   }
       
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1127  sub start_br { Line 1262  sub start_br {
 sub end_br {  sub end_br {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <big> tag  #-- <big> tag (end tag required)
 sub start_big {  sub start_big {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '{\large ';   $currentstring .= '{\large ';
Line 1148  sub start_big { Line 1283  sub start_big {
 sub end_big {  sub end_big {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 1156  sub end_big { Line 1291  sub end_big {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <small> tag  #-- <small> tag (end tag required)
 sub start_small {  sub start_small {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '{\footnotesize ';   $currentstring .= '{\footnotesize ';
Line 1171  sub start_small { Line 1306  sub start_small {
 sub end_small {  sub end_small {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '}';   $currentstring .= '}';
Line 1179  sub end_small { Line 1314  sub end_small {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <basefont> tag  #-- <basefont> tag (end tag forbidden)
 sub start_basefont {  sub start_basefont {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);   my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
Line 1197  sub start_basefont { Line 1332  sub start_basefont {
 sub end_basefont {  sub end_basefont {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);   my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
Line 1208  sub end_basefont { Line 1343  sub end_basefont {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <font> tag  #-- <font> tag (end tag required)
 sub start_font {  sub start_font {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);   my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);
  if ($face=~/symbol/i) {   if ($face!~/symbol/i) {
     $Apache::lonxml::prevent_entity_encode++;      if (($env{'browser.fontenhance'} eq 'on') || 
  } else {   ($env{'browser.blackwhite'} eq 'on')) { return ''; }
     if (($ENV{'browser.fontenhance'} eq 'on') ||   
  ($ENV{'browser.blackwhite'} eq 'on')) { return ''; }  
  }   }
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }  elsif ($target eq 'tex') {      }  elsif ($target eq 'tex') {
Line 1233  sub start_font { Line 1366  sub start_font {
 sub end_font {  sub end_font {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);  
  if ($face=~/symbol/i) {$Apache::lonxml::prevent_entity_encode--;}  
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }  elsif ($target eq 'tex') {      }  elsif ($target eq 'tex') {
  my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);   my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
Line 1246  sub end_font { Line 1377  sub end_font {
     return $currentstring;      return $currentstring;
 }  }
     
 #-- <strike> tag  #-- <strike> tag (end tag required)
 sub start_strike {  sub start_strike {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  &Apache::lonxml::startredirection();   &Apache::lonxml::startredirection();
Line 1261  sub start_strike { Line 1392  sub start_strike {
 sub end_strike {  sub end_strike {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring=&Apache::lonxml::endredirection();   $currentstring=&Apache::lonxml::endredirection();
Line 1272  sub end_strike { Line 1403  sub end_strike {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <s> tag  #-- <s> tag (end tag required)
 sub start_s {  sub start_s {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  &Apache::lonxml::startredirection();   &Apache::lonxml::startredirection();
Line 1287  sub start_s { Line 1418  sub start_s {
 sub end_s {  sub end_s {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring=&Apache::lonxml::endredirection();   $currentstring=&Apache::lonxml::endredirection();
Line 1298  sub end_s { Line 1429  sub end_s {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <sub> tag  #-- <sub> tag (end tag required)
 sub start_sub {  sub start_sub {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\$_{ ";   $currentstring .= '\raisebox{-\smallskipamount}{\scriptsize{';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 1313  sub start_sub { Line 1444  sub start_sub {
 sub end_sub {  sub end_sub {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= " }\$";   $currentstring .= '}}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <sup> tag  #-- <sup> tag (end tag required)
 sub start_sup {  sub start_sup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= "\$^{ ";   $currentstring .= '\raisebox{\smallskipamount}{\scriptsize{';
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 1336  sub start_sup { Line 1467  sub start_sup {
 sub end_sup {  sub end_sup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= " }\$";   $currentstring .= '}}';
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <hr> tag  #-- <hr> tag (end tag forbidden)
 sub start_hr {  sub start_hr {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # End enclosing para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
   
    # <hr /> can't be inside of <sup><sub> thank you LaTeX.
    # 
    my $restart_sub = 0;
    my $restart_sup = 0;
   
    # Since <sub> and <sup> 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);   my $LaTeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
  if (defined $LaTeXwidth) {   if (defined $LaTeXwidth) {
     if ($LaTeXwidth=~/^%/) {      if ($LaTeXwidth=~/^%/) {
Line 1371  sub start_hr { Line 1523  sub start_hr {
  }   }
  $currentstring .= ' \vskip 0 mm \noindent\makebox['.$LaTeXwidth.']{'.$pre.'\makebox['.   $currentstring .= ' \vskip 0 mm \noindent\makebox['.$LaTeXwidth.']{'.$pre.'\makebox['.
                                     $LaTeXwidth.'][b]{\hrulefill}'.$post.'}\vskip 0 mm ';                                      $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;      return $currentstring;
 }  }
Line 1378  sub start_hr { Line 1540  sub start_hr {
 sub end_hr {  sub end_hr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <div> tag  #-- <div> tag (end tag required)
   {
   
   #  Since div can be nested, the stack below is used
   #  in 'tex' mode to store the ending strings
   #  for the div stack.
   
       my @div_end_stack;
   
 sub start_div {  sub start_div {
     my ($target,$token) = @_;      my ($target,$token, $tagstack, $parstack, $parser, $safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close enclosing para.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $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 = '';
   
    my $align = lc(&Apache::lonxml::get_param('align', $parstack,
     $safeeval, undef, 1));
    if ($align eq 'center') {
       $currentstring .= '\begin{center}';
       $endstring      = '\end{center}';
       if (&is_inside_of($tagstack, "table")) {
    $currentstring = &center_correction().$currentstring;
    $endstring    .= &center_end_correction(); 
       }
    }
    elsif ($align eq 'right') {
       $currentstring .= '\begin{flushright}';
       $endstring     .= '\end{flushright}';
    } elsif ($align eq 'left') {
       $currentstring .= '\begin{flushleft}';
       $endstring     = '\end{flushleft}';
    } else {
   
    }
    $currentstring .= "\n";   # For human readability.
    $endstring       = "\n$endstring\n"; # For human readability
    push(@div_end_stack, $endstring);
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_div {  sub end_div {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     }       }
       if ($target eq 'tex') {
    my $endstring = pop @div_end_stack;
    $currentstring .= $endstring;
       }
     return $currentstring;      return $currentstring;
 }  }
   }
   
 #-- <a> tag  #-- <a> tag (end tag required)
 sub start_a {  sub start_a {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
     } elsif ($target eq 'tex') {      undef,1);
  my $a=&Apache::lonxml::get_param('href',$parstack,$safeeval,undef,1);   $currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href});
  my $b=&Apache::lonxml::get_param('name',$parstack,$safeeval,undef,1);          if ($href =~ /\S/) {
  if ($a=~/\S/) {              if ($href !~ m{^https?://}) {
     $a=~s/([^\\])%/$1\\\%/g;                  my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
     $currentstring .= '\ref{URI: '.$a.'}';                  my $linkurl;
  } elsif ($b=~/\S/) {                  if ($href =~ m{^/uploaded/}) {
     $currentstring .= '\ref{Anchor: '.$b.'}';                      $linkurl = $href;
  } else {                  } elsif ($href =~ m{^[^/]}) {
     $currentstring.='';                      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);
                           }
                       }
                   }
               }
           }
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1427  sub start_a { Line 1644  sub start_a {
 sub end_a {  sub end_a {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $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;      return $currentstring;
 }  }
   
 #-- <li> tag  #-- <li> tag (end tag optional)
 sub start_li {  sub start_li {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my  $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,1);   my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
  if ($type=~/circle/) {   my $value=&Apache::lonxml::get_param('value',$parstack,$safeeval,undef,0);
     $currentstring .= ' \item[o] ';   #FIXME need to support types i and I 
    if ($type=~/disc/) {
       $currentstring .= ' \item[$\bullet$] ';
    } elsif ($type=~/circle/) {
       $currentstring .= ' \item[$\circ$] ';
  } elsif ($type=~/square/) {   } elsif ($type=~/square/) {
     $currentstring .= ' \item[$\Box$] ';      $currentstring .= ' \item[$\diamond$] ';
  } elsif ($type ne '') {    } elsif ($type eq '1') {
     $currentstring .= ' \item['.$type.'] ';      $currentstring .= ' \item['.($Apache::londefdef::list_index+1).'.]';
    } elsif ($type eq 'A') {
       $currentstring .= ' \item['.('A'..'Z')[$Apache::londefdef::list_index].'.]';
    } elsif ($type eq 'a') {
       $currentstring .= ' \item['.('a'..'z')[$Apache::londefdef::list_index].'.]';
    } elsif ($value ne '') {
       $currentstring .= ' \item['.$value.'] ';
  } else {   } else {
     $currentstring .= ' \item ';      $currentstring .= ' \item ';
  }     }  
     }    $Apache::londefdef::list_index++;
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_li {  sub end_li {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # In case there's a <p> in the <li>
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring .= $token->[2];     
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <u> tag  #-- <u> tag (end tag required)
 sub start_u {  sub start_u {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  &Apache::lonxml::startredirection();   &Apache::lonxml::startredirection();
Line 1478  sub start_u { Line 1728  sub start_u {
 sub end_u {  sub end_u {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring=&Apache::lonxml::endredirection();   $currentstring=&Apache::lonxml::endredirection();
Line 1489  sub end_u { Line 1739  sub end_u {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <ul> tag  #-- <ul> tag (end tag required)
 sub start_ul {  sub start_ul {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off enclosing list.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $TeXtype=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);   my $TeXtype=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
    $Apache::londefdef::list_index=0;
  if ($TeXtype eq 'disc') {   if ($TeXtype eq 'disc') {
     $currentstring .= ' \renewcommand{\labelitemi}{$\bullet$}      $currentstring .= '\renewcommand{\labelitemi}{$\bullet$}'.
                                 \renewcommand{\labelitemii}{$\bullet$}                                 '\renewcommand{\labelitemii}{$\bullet$}'. 
                                 \renewcommand{\labelitemiii}{$\bullet$}                                '\renewcommand{\labelitemiii}{$\bullet$}'.
                                 \renewcommand{\labelitemiv}{$\bullet$}';                                '\renewcommand{\labelitemiv}{$\bullet$}';
  } elsif ($TeXtype eq 'circle') {   } elsif ($TeXtype eq 'circle') {
     $currentstring .= ' \renewcommand{\labelitemi}{$\circ$}      $currentstring .= '\renewcommand{\labelitemi}{$\circ$}'.
                                 \renewcommand{\labelitemii}{$\circ$}                                 '\renewcommand{\labelitemii}{$\circ$}'. 
                                 \renewcommand{\labelitemiii}{$\circ$}                                '\renewcommand{\labelitemiii}{$\circ$}'.
                                 \renewcommand{\labelitemiv}{$\circ$}';                                '\renewcommand{\labelitemiv}{$\circ$}';
  } elsif ($TeXtype eq 'square') {   } elsif ($TeXtype eq 'square') {
     $currentstring .= ' \renewcommand{\labelitemi}{$\diamond$}      $currentstring .= '\renewcommand{\labelitemi}{$\diamond$}'.
                                 \renewcommand{\labelitemii}{$\diamond$}                                 '\renewcommand{\labelitemii}{$\diamond$}'. 
                                 \renewcommand{\labelitemiii}{$\diamond$}                                '\renewcommand{\labelitemiii}{$\diamond$}'.
                                 \renewcommand{\labelitemiv}{$\diamond$}';                                '\renewcommand{\labelitemiv}{$\diamond$}';
  }   }
  $currentstring .= '\begin{itemize}';     $currentstring .= '\strut \begin{itemize}';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 1521  sub start_ul { Line 1772  sub start_ul {
 sub end_ul {  sub end_ul {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}   $currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}'.
                                 \renewcommand{\labelitemii}{$\bullet$}                                  '\renewcommand{\labelitemii}{$\bullet$}'. 
                                 \renewcommand{\labelitemiii}{$\bullet$}                                 '\renewcommand{\labelitemiii}{$\bullet$}'.
                                 \renewcommand{\labelitemiv}{$\bullet$}';                                   '\renewcommand{\labelitemiv}{$\bullet$}\strut ';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <menu> tag  #-- <menu> tag (end tag required)
 sub start_menu {  sub start_menu {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{itemize} ";     $currentstring = " \\begin{itemize} ";  
Line 1547  sub start_menu { Line 1798  sub start_menu {
 sub end_menu {  sub end_menu {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\end{itemize}";     $currentstring = " \\end{itemize}";  
Line 1555  sub end_menu { Line 1806  sub end_menu {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <dir> tag  #-- <dir> tag (end tag required)
 sub start_dir {  sub start_dir {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # In case there's a <p> prior to the list.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{itemize} ";     $currentstring .= " \\begin{itemize} ";  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 1570  sub start_dir { Line 1821  sub start_dir {
 sub end_dir {  sub end_dir {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\end{itemize}";     $currentstring = " \\end{itemize}";  
Line 1578  sub end_dir { Line 1829  sub end_dir {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <ol> tag  #-- <ol> tag (end tag required)
 sub start_ol {  sub start_ol {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # In case there's a <p> prior to the list.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
    $Apache::londefdef::list_index=0;
  my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);   my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
  if ($type eq '1') {   if ($type eq '1') {
     $currentstring .= ' \renewcommand{\labelenumi}{\arabic{enumi}.}      $currentstring .= '\renewcommand{\labelenumi}{\arabic{enumi}.}'.
                                 \renewcommand{\labelenumii}{\arabic{enumii}.}                                 '\renewcommand{\labelenumii}{\arabic{enumii}.}'. 
                                 \renewcommand{\labelenumiii}{\arabic{enumiii}.}                                '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
                                 \renewcommand{\labelenumiv}{\arabic{enumiv}.}';                                '\renewcommand{\labelenumiv}{\arabic{enumiv}.}';
  } elsif ($type eq 'A') {   } elsif ($type eq 'A') {
     $currentstring .= ' \renewcommand{\labelenumi}{\Alph{enumi}.}      $currentstring .= '\renewcommand{\labelenumi}{\Alph{enumi}.}'.
                                 \renewcommand{\labelenumii}{\Alph{enumii}.}                                 '\renewcommand{\labelenumii}{\Alph{enumii}.}'. 
                                 \renewcommand{\labelenumiii}{\Alph{enumiii}.}                                '\renewcommand{\labelenumiii}{\Alph{enumiii}.}'.
                                 \renewcommand{\labelenumiv}{\Alph{enumiv}.}';                                '\renewcommand{\labelenumiv}{\Alph{enumiv}.}';
  } elsif ($type eq 'a') {   } elsif ($type eq 'a') {
     $currentstring .= ' \renewcommand{\labelenumi}{\alph{enumi}.}      $currentstring .= '\renewcommand{\labelenumi}{\alph{enumi}.}'.
                                 \renewcommand{\labelenumii}{\alph{enumii}.}                                '\renewcommand{\labelenumii}{\alph{enumii}.}'.
                                 \renewcommand{\labelenumiii}{\alph{enumiii}.}                                '\renewcommand{\labelenumiii}{\alph{enumiii}.}'.
                                 \renewcommand{\labelenumiv}{\alph{enumiv}.} ';                                '\renewcommand{\labelenumiv}{\alph{enumiv}.}';
  } elsif ($type eq 'i') {   } elsif ($type eq 'i') {
     $currentstring .= ' \renewcommand{\labelenumi}{\roman{enumi}.}      $currentstring .= '\renewcommand{\labelenumi}{\roman{enumi}.}'.
                                 \renewcommand{\labelenumii}{\roman{enumii}.}                                '\renewcommand{\labelenumii}{\roman{enumii}.}'.
                                 \renewcommand{\labelenumiii}{\roman{enumiii}.}                                '\renewcommand{\labelenumiii}{\roman{enumiii}.}'.
                                 \renewcommand{\labelenumiv}{\roman{enumiv}.} ';                                '\renewcommand{\labelenumiv}{\roman{enumiv}.}';
  } elsif ($type eq 'I') {   } elsif ($type eq 'I') {
     $currentstring .= ' \renewcommand{\labelenumi}{\Roman{enumi}.}      $currentstring .= '\renewcommand{\labelenumi}{\Roman{enumi}.}'.
                                 \renewcommand{\labelenumii}{\Roman{enumii}.}                                '\renewcommand{\labelenumii}{\Roman{enumii}.}'.
                                 \renewcommand{\labelenumiii}{\Roman{enumiii}.}                                '\renewcommand{\labelenumiii}{\Roman{enumiii}.}'.
                                 \renewcommand{\labelenumiv}{\Roman{enumiv}.} ';                                '\renewcommand{\labelenumiv}{\Roman{enumiv}.}';
  }   }
  $currentstring .= '\begin{enumerate}';     $currentstring .= '\strut \begin{enumerate}';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 1620  sub start_ol { Line 1872  sub start_ol {
 sub end_ol {  sub end_ol {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\end{enumerate} \renewcommand{\labelenumi}{\arabic{enumi}.}   $currentstring = '\end{enumerate}\renewcommand{\labelenumi}{\arabic{enumi}.}'.
                                           \renewcommand{\labelenumii}{\arabic{enumii}.}                                          '\renewcommand{\labelenumii}{\arabic{enumii}.}'.
                                           \renewcommand{\labelenumiii}{\arabic{enumiii}.}                                          '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
                                           \renewcommand{\labelenumiv}{\arabic{enumiv}.}';                                            '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut ';  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <dl> tag  #-- <dl> tag (end tag required)
 sub start_dl {  sub start_dl {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # In case there's a <p> unclosed prior to the list.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\begin{description}';     $currentstring .= '\begin{description}';
    $Apache::londefdef::DL++;
    push(@Apache::londefdef::description,[]);
    $Apache::londefdef::DD[$Apache::londefdef::DL]=0;
    $Apache::londefdef::DT[$Apache::londefdef::DL]=0;
    $Apache::londefdef::seenDT[$Apache::londefdef::DL]=0;
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_dl {  sub end_dl {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\end{description}';     if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
    if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
    foreach my $element (@{$Apache::londefdef::description[-1]}) {
       $currentstring.=' '.$element.' ';
    }
    pop(@Apache::londefdef::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;      return $currentstring;
 }  }
Line 1658  sub end_dl { Line 1925  sub end_dl {
 sub start_dt {  sub start_dt {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring='';      my $currentstring='';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  &Apache::lonxml::startredirection();;    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;      return $currentstring;
 }  }
Line 1669  sub start_dt { Line 1940  sub start_dt {
 sub end_dt {  sub end_dt {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $data=&Apache::lonxml::endredirection();   if ($Apache::londefdef::DT[-1]) {
  $data=~s/\\begin{center}//g;      my $data=&item_cleanup();
  $data=~s/\\end{center}//g;      push(@{$Apache::londefdef::description[-1]},'\item['.$data.'] \strut \vskip 0mm');
  $currentstring.='\item['.$data.']';      $Apache::londefdef::DT[-1]--;
    }
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <dd> tag  sub item_cleanup {
       my $item=&Apache::lonxml::endredirection();
       $item=~s/\\begin{center}//g;
       $item=~s/\\end{center}//g;
       return $item;
   }
   
   #-- <dd> tag (end tag optional)
 sub start_dd {  sub start_dd {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  if ($$tagstack[-2] eq 'dt') {   if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
     $currentstring.='\item['.&Apache::lonxml::endredirection().']';   if ($Apache::londefdef::DD[-1]) { &end_dd(@_);}
    if (!$Apache::londefdef::seenDT[-1]) {
       push(@{$Apache::londefdef::description[-1]},'\item[\strut] \strut \vskip 0mm ');
  }   }
    push(@{$Apache::londefdef::description[-1]},'');
    $Apache::londefdef::description[-1]->[-1].=' \strut ';
    $Apache::londefdef::DD[-1]++;
    &Apache::lonxml::startredirection();
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_dd {  sub end_dd {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      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 ';
    $Apache::londefdef::DD[-1]--;
       }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <table> tag  #-- <table> tag (end tag required)
   #       <table> also ends any prior <p> that is not closed.
   #               but, unless I allow <p>'s to nest, that's the
   #               only way I could think of to allow <p> in 
   #               <tr> <th> bodies
   #
   #list of supported attributes: border,width,TeXwidth,TeXtheme
   #                              align
 sub start_table {  sub start_table {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $textwidth='';      my $textwidth = '';
     if (not defined @Apache::londefdef::table) {      my $currentstring = &end_p();
  $textwidth=&recalc($ENV{'form.textwidth'});      if ($target eq 'web' || $target eq 'webgrade') {
  $textwidth=~/(\d+\.?\d*)/;   $currentstring .= $token->[4];     
  $textwidth=0.95*$1;  
     } else {  
  $textwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);  
     }  
     my $currentstring = '';  
     if ($target eq 'web') {  
  $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $aa = {};   &disable_para(); # Can't have paras in a table.
  push @Apache::londefdef::table, $aa;   
   
    #  New table code:
   
    #  Get the parameters that we can do something about:
   
    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);
   
    # 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
    #
   
    my $table = new Apache::lontable();
    if ($border ne '') {
       $table->table_border(1);
       $table->cell_border(1);
    }
    if ($theme ne '') {
       $table->theme($theme);
    }
    if ($align ne '') {
       $table->alignment($align);
    }
   
    # Missing width is most of page width
   
    if ($width eq "") {
       $width = '70%';
    }
   
    # 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}';
   
    #--------------------------------------------------------
    #  Old table code here.
    #--------------------------------------------------------
   
   
    if (0) {
    push(@Apache::londefdef::table, {}); 
  $Apache::londefdef::table[-1]{'row_number'} = -1;   $Apache::londefdef::table[-1]{'row_number'} = -1;
         #table's width          #maximum table's width (default coincides with text line length)
  my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);   if ($#Apache::londefdef::table==0) {
  if (not defined $TeXwidth) {      $textwidth=&recalc($env{'form.textwidth'}); #result is always in mm
     my $htmlwidth = &Apache::lonxml::get_param('width',$parstack,$safeeval,undef,1);      $textwidth=~/(\d+\.?\d*)/;
     if ($htmlwidth=~/%/) {      $textwidth=0.85*$1; #accounts "internal" LaTeX space for table frame
  $htmlwidth=~/(\d+)/;   } else {
  my $value=$1*$textwidth/100;      if ($Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]=~/\d/) {
  $Apache::londefdef::table[-1]{'width'}=$value;   #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 {      } else {
  $Apache::londefdef::table[-1]{'width'}=$textwidth;                #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];
    }
       }
    }
   
    # 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;
     }      }
  } elsif ($TeXwidth=~/%/) {   }
    # if the width is specified as a % it is converted to an absolute width.
    # otherwise.. just plugged right in the hash
   
    if ($TeXwidth=~/%/) {
     $TeXwidth=~/(\d+)/;      $TeXwidth=~/(\d+)/;
     my $value=$1*$textwidth/100;              $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100;
             $Apache::londefdef::table[-1]{'width'}=$value;  
  } else {   } else {
     $Apache::londefdef::table[-1]{'width'}=$textwidth;      $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          #table's border
  my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval,undef,1);    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; }   unless (defined $border) { $border = 0; }
  if ($border) {    if ($border) { 
     $Apache::londefdef::table[-1]{'hinc'} = '\hline ';       $Apache::londefdef::table[-1]{'hinc'} = '\hline '; 
Line 1751  sub start_table { Line 2121  sub start_table {
     $Apache::londefdef::table[-1]{'vinc'} = '&';       $Apache::londefdef::table[-1]{'vinc'} = '&'; 
     $Apache::londefdef::table[-1]{'vvinc'} = '';      $Apache::londefdef::table[-1]{'vvinc'} = '';
  }   }
  $Apache::londefdef::table[-1]{'output'} = ' \noindent \begin{tabular} ';   if ($#Apache::londefdef::table==0) {
  $currentstring = '\keephidden{NEW TABLE ENTRY}';      #    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}';
       }
   
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1760  sub start_table { Line 2144  sub start_table {
 sub end_table {  sub end_table {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
   
   
    #  New table code:
   
    my $table = pop(@Apache::londefdef::table);
    my $t     = $table->generate();
    $currentstring = $t->generate_string();
    &enable_para();
    #--------------------------------------------------------------
    #  Old table code:
    #--------------------------------------------------------------
   
    if (0) {
   
    my $border =  &Apache::lonxml::get_param('border',$parstack,$safeeval);
  my $inmemory = '';   my $inmemory = '';
  my $output = '';   my $output = '';
  #construct header of the table   my $WARNING='';
  my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'};          #width of columns from TeXwidth attributes
  for (my $in=0;$in<=$Apache::londefdef::table[-1]{'counter_columns'};$in++) {  
     $header_of_table .= $Apache::londefdef::table[-1]{'columns'}[$in].$Apache::londefdef::table[-1]{'vvinc'};   # Protect against unbalanced </table> 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];
    }
       }
  }   }
  $header_of_table .= '}';          #free space and number of empty columns
  #define the length of the table cells   my ($available_space,$empty_columns)=($Apache::londefdef::table[-1]{'width'},0);
  #always starts with TeXwidth (if defined everything else is ignored)   if ($#Apache::londefdef::table ne 0) {$available_space=0.9*$available_space;} 
  my @length_row_final = split(/,/,$Apache::londefdef::table[-1]{'TeXlengthrow'}[0]);   for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
  for (my $in=1;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {      if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]==0) {
     my @length_row = split(/,/,$Apache::londefdef::table[-1]{'TeXlengthrow'}[$in]);   $empty_columns++;
     for (my $jn=0;$jn<=$#length_row;$jn++) {      } else {
  if ($length_row_final[$jn]<$length_row[$jn]) {$length_row_final[$jn]=$length_row[$jn];}   $available_space=$available_space-$Apache::londefdef::table[-1]{'TeXlen'}[0][$jn];
     }      }
  }   }
  #continues trying estimate the width of raw data  
  my @length_raw_row = split(/,/,$Apache::londefdef::table[-1]{'lengthrow'}[0]);          #boundaries for contents columns
  for (my $in=1;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {   my @min_len=();#columns can not be narrower 
     my @length_row = split(/,/,$Apache::londefdef::table[-1]{'lengthrow'}[$in]);   my @max_len=();#maximum length of column
     for (my $jn=0;$jn<=$#length_row;$jn++) {   my $avg_max;
  if ($length_raw_row[$jn]<$length_row[$jn]) {$length_raw_row[$jn]=$length_row[$jn];}   my $avg_min;
     }   my $counter_cols = $Apache::londefdef::table[-1]{'counter_columns'};
  }   for (my $jn=0;$jn<=$counter_cols; $jn++) {
         #comparing of TeXwidth and raw data width   my ($localmin,$localmax)=(0,0);
  my $available_length=$Apache::londefdef::table[-1]{'width'};   for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
  my $needed=0;      if ($localmin<$Apache::londefdef::table[-1]{'minlen'}[$in][$jn]) {
  for (my $jn=0;$jn<=$#length_row_final;$jn++) {   $localmin=$Apache::londefdef::table[-1]{'minlen'}[$in][$jn];
     if ($length_row_final[$jn]!=0) {      }
  $available_length=$available_length-$length_row_final[$jn];      if ($localmax<$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn]) {
  $needed++;   $localmax=$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn];
     }      }
  }   }
  $needed=$#length_row_final-$needed+1;   push @min_len, $localmin;
  for (my $jn=0;$jn<=$#length_row_final;$jn++) {   push @max_len, $localmax;
     if ($length_row_final[$jn]==0) {   $avg_max = $localmax + $avg_max;
  if ($length_raw_row[$jn]<$available_length) {   $avg_min = $localmin + $avg_min;
     $length_row_final[$jn]=$length_raw_row[$jn];   }
     $available_length=$available_length-$length_raw_row[$jn];   # Does not really matter what the average max/min are if there are no cols.
     $needed--;   # 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]) {
       $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];
       }
  }   }
     }      }
  }   }
  for (my $jn=0;$jn<=$#length_row_final;$jn++) {          # use all available width or specified width as if not specified,
     if ($length_row_final[$jn]==0) {   # the specified width gets defaulted to the available width.
  $length_row_final[$jn]=0.9*$available_length/$needed;  
    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;
  }   }
   
   
    #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   #fill the table
  for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {   for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
     for (my $jn=0;$jn<=$#length_row_final;$jn++) {      my $have_rowspan = 0;
  my $substituted=$length_row_final[$jn];      for (my $jn=0;$jn<=$#fwidth;$jn++) {
  $Apache::londefdef::table[-1]{'rowdata'}[$in]=~s/TOBECHANGEDONNUMBER/$substituted mm/;  
     }   #-----------------------------------------------------------
     $output .=  $Apache::londefdef::table[-1]{'rowdata'}[$in];                  #   I think this order of doing things will ensure that
     chop $output;   #   single rowspan, columspan and combined row/colspans will
     $output .= ' \\\\ ';                  #   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'}.' ';
       }
  }   }
  $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$output.$Apache::londefdef::table[-1]{'hinc'}.'\end{tabular}\vskip 0 mm ';   # Note that \newline destroys alignment env's produced  by e.g. <div>
    # $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut\newline\strut ';
    $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut'.'\\\\'."\n".'\strut ';
  if ($#Apache::londefdef::table > 0) {       if ($#Apache::londefdef::table > 0) {    
     my $inmemory = $Apache::londefdef::table[-1]{'output'};      my $inmemory = $Apache::londefdef::table[-1]{'output'};
       # Figure out max/and min width  by summing us and then
       # apply that to the current column of the table we nest in
       # if it's larger than the current width or the current width
       # is undefined.
       #
       my $min_nested_width = 0;
       my $max_nested_width = 0;
       for (my $col = 0; $col <= $Apache::londefdef::table[-1]{'counter_columns'}; $col++) {
    $min_nested_width +=  $min_len[$col];
    $max_nested_width +=  $max_len[$col];
   
       }
       # Fudge in an extra 5 mm for borders etc:
       
       $min_nested_width += 5;
       $max_nested_width += 5;
   
       my $outer_column = $Apache::londefdef::table[-2]{'counter_columns'};
       my $outer_row    = $Apache::londefdef::table[-2]{'row_number'};
       if ($min_nested_width > $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column]) {
    $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column] = $min_nested_width;
       }
       if ($max_nested_width > $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column]) {
    $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column] = $max_nested_width;
       }
   
     pop @Apache::londefdef::table;      pop @Apache::londefdef::table;
     push @{$Apache::londefdef::table[-1]{'include'}}, $inmemory;      push @{$Apache::londefdef::table[-1]{'include'}}, $inmemory;
  } else {   } else {
Line 1832  sub end_table { Line 2573  sub end_table {
     pop @Apache::londefdef::table;      pop @Apache::londefdef::table;
     undef @Apache::londefdef::table;      undef @Apache::londefdef::table;
  }   }
    }
    &enable_para();
       }
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1840  sub end_table { Line 2584  sub end_table {
 sub start_tr {  sub start_tr {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
   
    my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
    $Apache::londefdef::table[-1]->start_row();
   
    if ($align ne '') {
       $Apache::londefdef::table[-1]->configure_row({default_halign => $align});
    }
   
    #---------------------------------------------------------------
    # Old table code.
    #---------------------------------------------------------------
   
    if (0) {
  $Apache::londefdef::table[-1]{'row_number'}++;   $Apache::londefdef::table[-1]{'row_number'}++;
  my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);   my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
  if ($alignchar ne '') {   if ($alignchar ne '') {
     push @ {$Apache::londefdef::table[-1]{'rows'} }, $alignchar;      push @ {$Apache::londefdef::table[-1]{'rows'} },substr($alignchar,0,1);
  } else {   } else {
     push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l';      push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l';
  }   }
  push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'});   push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'});
    #
    #  Need to save the number of table columns to preserve the max # columns.
    #
    $Apache::londefdef::table[-1]{'prior_columns'}   = $Apache::londefdef::table[-1]{'counter_columns'};
  $Apache::londefdef::table[-1]{'counter_columns'} = -1;   $Apache::londefdef::table[-1]{'counter_columns'} = -1;
  $Apache::londefdef::table[-1]{'TeXlength'} = '';   push @ {$Apache::londefdef::table[-1]{'TeXlen'}}, [];
   $Apache::londefdef::table[-1]{'length'} = '';   push @ {$Apache::londefdef::table[-1]{'objectlen'}}, [];
    push @ {$Apache::londefdef::table[-1]{'minlen'}}, [];
    push @ {$Apache::londefdef::table[-1]{'maxlen'}}, [];
    push @ {$Apache::londefdef::table[-1]{'content'}}, [];
       }
     }       } 
     return $currentstring;      return $currentstring;
 }  }
                   
 sub end_tr {  sub end_tr {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close any pending <p> in the row.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring .= $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
   
    # In case the user is missing a </td> or </th> 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) {   if ($Apache::londefdef::TD_redirection) {
     &end_td_tex($parstack,$parser,$safeeval);          &end_td_tex($parstack,$parser,$safeeval);    
  }   }
  push @{ $Apache::londefdef::table[-1]{'TeXlengthrow'} },$Apache::londefdef::table[-1]{'TeXlength'};   # Counter columns must be the maximum number of columns seen
  push @{ $Apache::londefdef::table[-1]{'lengthrow'} },$Apache::londefdef::table[-1]{'length'};   # in the table so far so:
    if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) {
       $Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'};
    }
       }
   
   
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 1877  sub end_tr { Line 2661  sub end_tr {
 sub start_td {  sub start_td {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $Apache::londefdef::TD_redirection = 1;   $Apache::londefdef::TD_redirection = 1;
Line 1902  sub tag_check { Line 2686  sub tag_check {
     }      }
     return '';      return '';
 }  }
   
   #
   #  Factor out cell configuration hash generation:
   #
   
   sub cell_config_hash {
       my ($align, $rowspan, $colspan) = @_;
       my %config;
       if ($align ne '') {
    $config{'halign'} = $align;
       }
       if ($colspan ne "") {
    $config{'colspan'} = $colspan;
       }
       if ($rowspan ne '') {
    $config{'rowspan'} = $rowspan;
       }
       return \%config;
   }
     
 sub start_td_tex {  sub start_td_tex {
     my ($parstack,$parser,$safeeval) = @_;      my ($parstack,$parser,$safeeval) = @_;
     my $what_to_push = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);  
     if ($what_to_push eq '') {      # At this stage, an empty cell is created with the
  $what_to_push = substr($Apache::londefdef::table[-1]{'rows'}[0],0,1);;      # 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, 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($align, $rowspan, $colspan);
   
       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];
     }      }
     push @{ $Apache::londefdef::table[-1]{'columns'} }, $what_to_push;      push @{ $Apache::londefdef::table[-1]{'align'}[$Apache::londefdef::table[-1]{'row_number'}] }, $alignchar;
     $Apache::londefdef::table[-1]{'counter_columns'}++;      $Apache::londefdef::table[-1]{'counter_columns'}++;
       my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
       if (defined $TeXwidth) {
    my $current_length=&recalc($TeXwidth);
    $current_length=~/(\d+\.?\d*)/;
    push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
       }
       }
     &Apache::lonxml::startredirection();      &Apache::lonxml::startredirection();
     return '';      return '';
 }  }
   
 sub end_td_tex {  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 ($parstack,$parser,$safeeval) = @_;
     my $current_row = $Apache::londefdef::table[-1]{'row_number'};      my $current_row    = $Apache::londefdef::table[-1]{'row_number'};
     my $data=&Apache::lonxml::endredirection();      my $current_column = $Apache::londefdef::table[-1]{'counter_columns'}; 
       my $data = &Apache::lonxml::endredirection();
   
       #  The rowspan array of the table indicates which cells are part of a span.
       #  n indicates the start of a span set of n rows.
       #  ^ indicates a cell that continues a span set.
       #  _ indicates the cell is at the bottom of a span set.
       #  If this and subsequent cells are part of a rowspan, we must
       #  push along the row until we find one that is not.
   
       while ((defined $Apache::londefdef::table[-1]{'rowspan'}[$current_row] [$current_column]) 
      && ($Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column] =~ /[\^\_]/)) {
    # 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.
   
       my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 0);
       if (!$colspan) {
    $colspan = 1;
       }
   
       my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 0);
       if (!$rowspan) {
    $rowspan = 1;
       }
   
   
   
       for (my $c = 0; $c < $colspan; $c++) {
    $Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column+$c] = $rowspan;
    for (my $i = 1; $i < $rowspan; $i++) {
       $Apache::londefdef::table[-1]{'rowspan'}[$current_row+$i][$current_column+$c] = '^';
       if ($i == ($rowspan-1)) {
    $Apache::londefdef::table[-1]{'rowspan'}[$current_row+$i][$current_column+$c] = '_';
       }
    }
       }
   
     my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);      my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
     if (defined $TeXwidth) {      if (defined $TeXwidth) {
  my $current_length=&recalc($TeXwidth);   for (my $c = 0; $c < $colspan; $c++) {
  $current_length=~/(\d+)/;      push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
  $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';      push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
  $Apache::londefdef::table[-1]{'length'} .= '0,';      push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
    }
     } else {      } else {
  if ($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {   if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) {
     my $current_length=&recalc($1);      my $garbage_data=$data;
     $current_length=~/(\d+\.?\d*)/;      my $fwidth=0;
     $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';              while ($garbage_data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {
     $Apache::londefdef::table[-1]{'length'} .= '0,';   my $current_length=&recalc($1);
    $current_length=~/(\d+\.?\d*)/;
    if ($fwidth<$1) {$fwidth=$1;}
    $garbage_data=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//;
       }
               while ($garbage_data=~m/\[(\d+\.?\d*)\s*mm\]/) {
    my $current_length=$1;
    if ($fwidth<$current_length) {$fwidth=$current_length;}
    $garbage_data=~s/\[(\d+\.?\d*)\s*mm\]//;
       }
       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;
               while ($garbage_data=~/\\parbox\{\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)\s*\}/) {
    my $current_length=&recalc($1);
    $current_length=~/(\d+\.?\d*)/;
    if ($fwidth<$1) {$fwidth=$1;}
    $garbage_data=~s/\\parbox\{\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//;
       }
               while ($garbage_data=~/\\epsfxsize\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {
    my $current_length=&recalc($1);
    $current_length=~/(\d+\.?\d*)/;
    if ($fwidth<$1) {$fwidth=$1;}
    $garbage_data=~s/\\epsfxsize\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//;
       }
       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 {     } else {  
     $data=~s/^\s+(\S.*)/$1/;       $data=~s/^\s+(\S.*)/$1/; 
     $data=~s/(.*\S)\s+$/$1/;      $data=~s/(.*\S)\s+$/$1/;
     $data=~s/(\s)+/$1/;      $data=~s/(\s)+/$1/;
     my $current_length=0;      my ($current_length,$min_length)=(0,0);
     if ($data=~/\\vskip/) {      if ($data=~/\\vskip/) {
                 my $newdata=$data;                  my $newdata=$data;
  $newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g;   $newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g;
  my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata);   my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata);
  foreach my $elementdata (@newdata) {   foreach my $elementdata (@newdata) {
     $elementdata=~s/^\s+(\S.*)/$1/;       my $lengthnewdata=2.5*&LATEX_length($elementdata);
     $elementdata=~s/(.*\S)\s+$/$1/;  
     $elementdata=~s/(\s)+/$1/;  
     my $lengthnewdata=1.8*length($elementdata);  
     if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;}      if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;}
                       my @words=split(/ /,$elementdata);
       foreach my $word (@words) {
    my $lengthword=2.5*&LATEX_length($word);
    if ($min_length<$lengthword) {$min_length=$lengthword;}
       }
  }   }
     } else {      } else {
  $current_length=1.8*length($data);   $current_length=2.5*&LATEX_length($data);
                       my @words=split(/ /,$data);
       foreach my $word (@words) {
    my $lengthword=2*&LATEX_length($word);
    if ($min_length<$lengthword) {$min_length=$lengthword;}
       }
       }
       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;
     }      }
     $Apache::londefdef::table[-1]{'length'} .= $current_length.',';  
     $Apache::londefdef::table[-1]{'TeXlength'} .= '0,';  
  }           }        
     }      }
  for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {               # Substitute all of the tables nested in this cell in their appropriate places.
     $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;  
  }  
     @{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{TOBECHANGEDONNUMBER}{'.$data.'} '.$Apache::londefdef::table[-1]{'vinc'};      my $nested_count = $#{$Apache::londefdef::table[-1]{'include'}}; # This one is constant...
     return'';      for (my $in=0; $in<=$nested_count; $in++) {    
    my $nested = shift @{$Apache::londefdef::table[-1]{'include'}};
    $nested =~ s/\\end\{tabular\}\\strut\\\\/\\end\{tabular\}/;
    # $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
    $data =~ s/\\keephidden\{NEW TABLE ENTRY\}/$nested/;
   
       }
       # Should be be killing off the 'include' elements as they're used up?
   
       push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
   
   
   
   
       #  the colspan array will indicate how many columns will be spanned by this
       #  cell..this requires that counter_columns also be adjusted accordingly
       #  so that the next bunch of text goes in the right cell.  Note that since
       #  counter_columns is incremented in the start_td_tex, we adjust by colspan-1.
       #
   
       $Apache::londefdef::table[-1]{'counter_columns'} += $colspan -1;
       for (my $i = 0; $i < ($colspan -1); $i++) {
    push @ {$Apache::londefdef::table[-1]{'content'}[-1] },'';
       }
       for (my $r = 0; $r < $rowspan; $r++) {
    $Apache::londefdef::table[-1]{'colspan'}[$current_row+$r][$current_column] = $colspan;
    # Put empty text in spanned cols.
   
       }
   
       }
   
       return '';
 }  }
   
 sub end_td {  sub end_td {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
         $Apache::londefdef::TD_redirection =0;          $Apache::londefdef::TD_redirection =0;
Line 1977  sub end_td { Line 2943  sub end_td {
 sub start_th {  sub start_th {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $what_to_push = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);   $Apache::londefdef::TD_redirection = 1;
  if ($what_to_push eq '') {   &tagg_check('tr','th',$tagstack,$parstack,$parser,$safeeval);
     $what_to_push = substr($Apache::londefdef::table[-1]{'rows'}[0],0,1);;  
  }  
  push @{ $Apache::londefdef::table[-1]{'columns'} }, $what_to_push;  
  $Apache::londefdef::table[-1]{'counter_columns'}++;  
  &Apache::lonxml::startredirection();  
     }       } 
     return $currentstring;      return $currentstring;
 }     }   
            
 sub end_th {  sub tagg_check {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my @ar=@$parstack; 
     if ($target eq 'web') {      for (my $i=$#ar-1;$i>=0;$i--) {
  $currentstring = $token->[2];        if (lc($$tagstack[$i]) eq $good_tag) {
     } elsif ($target eq 'tex') {      &start_th_tex($parstack,$parser,$safeeval);
  my $current_row = $Apache::londefdef::table[-1]{'row_number'};      last;
  my $data=&Apache::lonxml::endredirection();   } elsif (lc($$tagstack[$i]) eq $bad_tag) {
  my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);      splice @ar, $i+1;
  if (defined $TeXwidth) {      &end_th_tex(\@ar,$parser,$safeeval);
     my $current_length=&recalc($TeXwidth);      &start_th_tex($parstack,$parser,$safeeval);
     $current_length=~/(\d+)/;      last;
     $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';  
     $Apache::londefdef::table[-1]{'length'} .= '0,';  
  } else {  
     if ($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {  
  my $current_length=&recalc($1);  
  $current_length=~/(\d+)/;  
  $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';  
  $Apache::londefdef::table[-1]{'length'} .= '0,';  
     } else {       
  $data=~/^\s*(\S.*)/;  
  $data=$1;  
  $data=~/(.*\S)\s*$/;  
  $data=$1;  
  my $current_length=2*length($data);  
  $Apache::londefdef::table[-1]{'length'} .= $current_length.',';  
  $Apache::londefdef::table[-1]{'TeXlength'} .= '0,';  
     }          
  }   }
  for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {                                      }
       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];
       }
       push @{ $Apache::londefdef::table[-1]{'align'}[$Apache::londefdef::table[-1]{'row_number'}] }, $alignchar;
       $Apache::londefdef::table[-1]{'counter_columns'}++;
       my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
       if (defined $TeXwidth) {
    my $current_length=&recalc($TeXwidth);
    $current_length=~/(\d+\.?\d*)/;
    push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
       }
       }
   
       # Accept xml until the </th> 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);
       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';
       } 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;
       my $fwidth=0;
               while ($garbage_data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {
    my $current_length=&recalc($1);
    $current_length=~/(\d+\.?\d*)/;
    if ($fwidth<$1) {$fwidth=$1;}
    $garbage_data=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//;
       }
               while ($garbage_data=~m/\[(\d+\.?\d*)\s*mm\]/) {
    my $current_length=$1;
    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';
    } else {  
       $data=~s/^\s+(\S.*)/$1/; 
       $data=~s/(.*\S)\s+$/$1/;
       $data=~s/(\s)+/$1/;
       my ($current_length,$min_length)=(0,0);
       if ($data=~/\\vskip/) {
                   my $newdata=$data;
    $newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g;
    my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata);
    foreach my $elementdata (@newdata) {
       my $lengthnewdata=2.5*&LATEX_length($elementdata);
       if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;}
                       my @words=split(/ /,$elementdata);
       foreach my $word (@words) {
    my $lengthword=2.5*&LATEX_length($word);
    if ($min_length<$lengthword) {$min_length=$lengthword;}
       }
    }
       } else {
    $current_length=2.5*&LATEX_length($data);
                       my @words=split(/ /,$data);
       foreach my $word (@words) {
    my $lengthword=2*&LATEX_length($word);
    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 $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {         
     $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;      $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
  }   }
  $data='\textbf{'.$data.'}';      #make data bold
  @{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{TOBECHANGEDONNUMBER}{'.$data.'} '.$Apache::londefdef::table[-1]{'vinc'};      $data='\textbf{'.$data.'}';
       push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
       }
       return'';
   }
   
   sub end_th {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # Close any open <p> in the row.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];     
       } elsif ($target eq 'tex') {
           $Apache::londefdef::TD_redirection =0;
    &end_th_tex($parstack,$parser,$safeeval);
     }      }
     return $currentstring;      return $currentstring;
 }  }
 #-- <img> tag       
   #-- <img> tag (end tag forbidden)
   #
   #  Render the <IMG> tag.
   #     <IMG> 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 {  sub start_img {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,      my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,
  undef,1);   undef,1);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$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);
     my $currentstring = '';      my $currentstring = '';
     my $width_param = '';  
     my $height_param = '';  
     my $scaling = .3;      my $scaling = .3;
     if ($target eq 'web') {  
  if ($ENV{'browser.imagesuppress'} ne 'on') {     # Render unto browsers that which are the browser's...
     $currentstring.= $token->[4];  
       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 {   } else {
     my $alttag= &Apache::lonxml::get_param      my $alttag = &Apache::lonxml::get_param('alt',$parstack,$safeeval,
  ('alt',$parstack,$safeeval,undef,1);      undef,1);
     unless ($alttag) {      if (!$alttag) {
  $alttag=&Apache::lonmeta::alttag   $alttag = &Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],
     ($Apache::lonxml::pwd[-1],$src);     $src);
     }      }
     $currentstring.='[IMAGE: '.$alttag.']';      $currentstring.='[IMAGE: '.$alttag.']';
  }   }
   
    # and render unto TeX that which is LaTeX
   
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
    #
    #  The alignment will require some superstructure to be put around
    #  the \includegraphics stuff.  At present we can only partially
    #  simulate the alignments offered by html.
    #
    #
    my $align = lc(&Apache::lonxml::get_param('align', 
     $parstack,
     $safeeval,
     undef,1));
    if(!$align) {
    $align = "bottom"; # This is html's default so it's ours too.
    }
    #
    &Apache::lonxml::debug("Alignemnt = $align");
    #  LaTeX's image/text wrapping is really bad since it wants to
    #  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...
    # so they can't yell at us for our choice.
    #
    my $latex_rendering = &Apache::lonxml::get_param('TeXwrap',
       $parstack,
       $safeeval,
       undef,0);
    # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering");
    if(!$latex_rendering) {
    $latex_rendering = "texwrap";
    }
    # using texwrap inside a table does not work. So, if after all of this,
    # texwrap is on, we turn it off if we detect we're in a table:
    #
    if (($latex_rendering eq 'texwrap') && &is_inside_of($tagstack, "table")) {
       $latex_rendering = 'parpic';
    }
   
    # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src");
   
    #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);   $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);
  &image_replication($src);   &Apache::lonxml::debug("path = $path file = $file src = $src");
  #if original gif/jpg/png file exist do following:   if (-e $src) {
  if (-e $src) {                &Apache::lonxml::debug("$src exists");
     #defines the default size of image      my ($height_param,$width_param)=
     my $image = Image::Magick->new;   &image_size($origsrc,0.3,$parstack,$safeeval);
     my $current_figure = $image->Read($src);      my $size;
     $width_param = $image->Get('width') * $scaling;;      if ($width_param)  { $size.='width='.$width_param.' mm,'; }
     $height_param = $image->Get('height') * $scaling;;      if ($height_param) { $size.='height='.$height_param.' mm]'; }
     undef $image;      # Default size if not able to extract that (e.g. eps image).
     #do we have any specified size of the picture?      
     my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval);      # &Apache::lonnet::logthis("Size = $size");
     my $TeXheight = &Apache::lonxml::get_param('TeXheight',$parstack,$safeeval);      
     my $width = &Apache::lonxml::get_param('width',$parstack,$safeeval,      $size='['.$size;
    undef,1);      $size=~s/,$/]/; 
     if ($TeXwidth ne '') {        $currentstring .= '\graphicspath{{'.$path.'}}'
  if ($TeXwidth=~/(\d+)\s*\%/) {   .'\includegraphics'.$size.'{'.$file.'} ';
     $width_param = $1*$ENV{'form.textwidth'}/100;      my $closure;
  } else {       ($currentstring, $closure) = &align_latex_image($align, 
     $width_param = $TeXwidth;      $latex_rendering, 
  }      $currentstring, 
     } elsif ($TeXheight ne '') {      $width_param, 
  $width_param = $TeXheight/$height_param*$width_param;      $height_param);
     } elsif ($width ne '') {      $currentstring .= $closure;
  $width_param = $width*$scaling;        
     }  
     if ($width_param > $ENV{'form.textwidth'}) {$width_param =0.95*$ENV{'form.textwidth'}}  
     my $file;  
     my $path;  
     if ($src =~ m!(.*)/([^/]*)$!) {  
  $file = $2;   
  $path = $1.'/';   
     }   
     my $newsrc = $src;  
     $newsrc =~ s/\.(gif|jpg|png)$/.eps/i;  
     $file=~s/\.(gif|jpg|png)$/.eps/i;  
     #where can we find the picture?  
     if (-e $newsrc) {  
  #eps counterpart for image exist   
  if ($path) {  
     $currentstring .= '\vskip 1 mm \noindent\graphicspath{{'.$path.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';  
  }  
     } else {  
  #there is no eps counterpart for image - check for ps one  
  $newsrc =~ s/\.eps$/\.ps/;  
  if (-e $newsrc) {  
     #ps counterpart for image exist   
     $file =~ s/\.eps$/\.ps/;  
     if ($path) {  
  $currentstring .= '\vskip 1 mm \noindent\graphicspath{{'.$path.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';  
     }  
  } else {  
     #there aren't eps or ps - so create eps   
     my $temp_file;  
     my $filename = "/home/httpd/prtspool/$ENV{'user.name'}_$ENV{'user.domain'}_printout.dat";  
     $temp_file = Apache::File->new('>>'.$filename);   
     print $temp_file "$src\n";  
     $currentstring .= '\vskip 1 mm \graphicspath{{/home/httpd/prtspool/}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';  
  }  
     }  
  } else {   } else {
       &Apache::lonxml::debug("$src does not exist");
     #original image file doesn't exist so check the alt attribute      #original image file doesn't exist so check the alt attribute
     my $alt =       my $alt = 
  &Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1);   &Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1);
Line 2120  sub start_img { Line 3225  sub start_img {
  $alt=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src);   $alt=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src);
     }      }
   
     if ($alt) {      if ($alt) { $currentstring .= ' '.$alt.' '; }
  $currentstring .= ' '.$alt.' ';   }
     } else {  
  #<allow> tag will care about replication    # 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',$only).' '.
       &Apache::edit::search('src',undef,'alt').'<br />';
    $currentstring .=&Apache::edit::text_arg('Description:','alt',$token,70).'<br />';
    $currentstring .=&Apache::edit::text_arg('width (pixel):','width',$token,5);
    $currentstring .=&Apache::edit::text_arg('height (pixel):','height',$token,5).'<br />';
    $currentstring .=&Apache::edit::text_arg('TeXwidth (mm):','TeXwidth',$token,5);
    $currentstring .=&Apache::edit::text_arg('TeXheight (mm):','TeXheight',$token,5);
    $currentstring .=&Apache::edit::select_arg('Alignment:','align',
      ['','bottom','middle','top','left','right'],$token,5);
    $currentstring .=&Apache::edit::select_arg('TeXwrap:', 'TeXwrap',
      ['', '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();
    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);
   
           if ($token->[2]{'src'}=~/\$/) {
              $currentstring.='Variable image source';
           } else {
      $currentstring .= '<img src="'.$src.'" alt="'.$alt.'" ';
      if ($width) { $currentstring.=' width="'.$width.'" '; }
      if ($height) { $currentstring.=' height="'.$height.'" '; }
      $currentstring .= ' />';
           }
       } elsif ($target eq 'modified') {
    my ($osrc,$owidth,$oheight)=
       ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'});
    my $ctag=&Apache::edit::get_new_args($token,$parstack,
        $safeeval,'src','alt','align',
        'TeXwidth','TeXheight', 'TeXwrap',
        'width','height','encrypturl');
    my ($nsrc,$nwidth,$nheight)=
       ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'});
    my $loc=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$nsrc);
    &image_replication($loc);
    my ($iwidth,$iheight);
    if (-e $loc) {
       my $image = Image::Magick->new;
       $image->Read($loc);
       ($iwidth, $iheight) = ($image->Get('width'),
      $image->Get('height'));
    }
    if ($osrc ne $nsrc || (!$nwidth && !$nheight)) {
       # changed image or no size specified,
               # if they didn't explicitly change the 
               # width or height use the ones from the image
       if ($iwidth && $iheight) {
    if ($owidth == $nwidth || (!$nwidth && !$nheight)) {
       $token->[2]{'width'} = $iwidth;$ctag=1;
    }
    if ($oheight == $nheight || (!$nwidth && !$nheight)) {
       $token->[2]{'height'}=$iheight;$ctag=1;
    }
     }      }
  }   }
    my ($cwidth,$cheight)=($token->[2]{'width'},$token->[2]{'height'});
    # if we don't have a width or height
    if ($iwidth && $cwidth && !$cheight) {
       $token->[2]{'height'}=int(($cwidth/$iwidth)*$iheight);$ctag=1;
    }
    if ($iheight && $cheight && !$cwidth) {
       $token->[2]{'width'}=int(($cheight/$iheight)*$iwidth);$ctag=1;
    }
    if ($ctag) {$currentstring=&Apache::edit::rebuild_tag($token);}
     }      }
   
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_img {  sub end_img {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];   $currentstring = $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '';   $currentstring = '';
Line 2141  sub end_img { Line 3317  sub end_img {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <applet> tag  #-- <applet> tag (end tag required)
 sub start_applet {  sub start_applet {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
           
     my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,undef,1);      my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,undef,1);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$code;      &Apache::lonxml::extlink($code);
       
     my $archive=&Apache::lonxml::get_param('archive',$parstack,$safeeval,      my $archive=&Apache::lonxml::get_param('archive',$parstack,$safeeval,
    undef,1);     undef,1);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$archive;      &Apache::lonxml::extlink($archive);
       
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  if ($ENV{'browser.appletsuppress'} ne 'on') {   if ($env{'browser.appletsuppress'} ne 'on') {
     $currentstring = $token->[4];      $currentstring = &Apache::lonenc::encrypt_ref($token,
     {'code'=>$code,
      'archive'=>$archive}
     );
  } else {   } else {
     my $alttag= &Apache::lonxml::get_param('alt',$parstack,      my $alttag= &Apache::lonxml::get_param('alt',$parstack,
    $safeeval,undef,1);     $safeeval,undef,1);
Line 2166  sub start_applet { Line 3343  sub start_applet {
     $currentstring='[APPLET: '.$alttag.']';      $currentstring='[APPLET: '.$alttag.']';
  }   }
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{figure} ";   # Turn off some stuff we can't be inside thank you LaTeX
   
   
    my $restart_sub = 0;
    my $restart_sup = 0;
   
    # Since <sub> and <sup> 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) {
       my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,
    undef,1);
       $alttag=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],
        $code);
    }
    $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;      return $currentstring;
 }  }
Line 2174  sub start_applet { Line 3394  sub start_applet {
 sub end_applet {  sub end_applet {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];   $currentstring = $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\end{figure}";  
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <embed> tag  #-- <embed> tag (end tag optional/required)
 sub start_embed {      sub start_embed {    
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);      my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$src;      &Apache::lonxml::extlink($src);
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  if ($ENV{'browser.embedsuppress'} ne 'on') {   if ($env{'browser.embedsuppress'} ne 'on') {
     $currentstring = $token->[4];      $currentstring=&Apache::lonenc::encrypt_ref($token,{'src'=>$src});
  } else {   } else {
     my $alttag=&Apache::lonxml::get_param      my $alttag=&Apache::lonxml::get_param
  ('alt',$parstack,$safeeval,undef,1);   ('alt',$parstack,$safeeval,undef,1);
Line 2200  sub start_embed { Line 3419  sub start_embed {
     $currentstring='[EMBED: '.$alttag.']';      $currentstring='[EMBED: '.$alttag.']';
  }   }
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{figure} ";    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 2208  sub start_embed { Line 3426  sub start_embed {
 sub end_embed {  sub end_embed {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {  
  $currentstring = " \\end{figure}";    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <param> tag  #-- <param> tag (end tag forbidden)
 sub start_param {  sub start_param {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     if (&Apache::lonxml::get_param      if (&Apache::lonxml::get_param('name',$parstack,
  ('name',$parstack,$safeeval,undef,1)=~/^cabbase$/i) {     $safeeval,undef,1)=~/^cabbase$/i) {
  $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=   my $value=&Apache::lonxml::get_param('value',$parstack,
     &Apache::lonxml::get_param('value',$parstack,$safeeval,undef,1);       $safeeval,undef,1);
     }      &Apache::lonxml::extlink($value);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=         } 
  &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);    
       my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
       &Apache::lonxml::extlink($src);
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        my %toconvert;
    my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
    if ($src) { $toconvert{'src'}= $src; }
    my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval,
       undef,1);
    if ($name=~/^cabbase$/i) {
       $toconvert{'value'}=&Apache::lonxml::get_param('value',$parstack,
      $safeeval,undef,1);
    }
    $currentstring = &Apache::lonenc::encrypt_ref($token,\%toconvert);
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{figure} ";    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 2238  sub start_param { Line 3465  sub start_param {
 sub end_param {  sub end_param {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];        $currentstring = $token->[2];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\end{figure}";    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 2250  sub end_param { Line 3476  sub end_param {
 sub start_allow {  sub start_allow {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);      my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
     $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);      &Apache::lonxml::extlink($src);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=  
  &Apache::lonnet::clutter($src);      if ($target eq 'tex') { &image_replication($src); }
     &image_replication($src);  
     my $result;      my $result;
     if ($target eq 'edit') {      if ($target eq 'edit') {
  $result .=&Apache::edit::tag_start($target,$token);   $result .=&Apache::edit::tag_start($target,$token);
Line 2273  sub end_allow { Line 3498  sub end_allow {
     return '';      return '';
 }  }
   
 #-- Frames  #-- Frames (end tag required)
   #-- <frameset>
 sub start_frameset {  sub start_frameset {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = ''; # Close any pending para.
     if ($target eq 'web') {       if ($target eq 'web' || $target eq 'webgrade') { 
  if (!$Apache::lonxml::registered) {   $currentstring = 
     $currentstring.='<head>'.      &Apache::loncommon::start_page($Apache::londefdef::title,
  &Apache::lonmenu::registerurl(undef,$target).'</head>';     $Apache::londefdef::head,
  }     {'add_entries'    => $token->[2],
  my $onLoad='';      'no_title'       => 1,
  foreach my $key (keys(%{$token->[2]})) {      'force_register' => 1,
     if ($key =~ /^onload$/i) {      'frameset'       => 1,});
  $onLoad.=$token->[2]->{$key}.';';  
  delete($token->[2]->{$key});  
     }  
  }  
  $token->[2]->{'onload'}=&Apache::lonmenu::loadevents().';'.$onLoad;  
  my $onUnload='';  
  foreach my $key (keys(%{$token->[2]})) {  
     if ($key =~ /^onunload$/i) {  
  $onUnload.=$token->[2]->{$key}.';';  
  delete($token->[2]->{$key});  
     }  
  }  
  $token->[2]->{'onunload'}=&Apache::lonmenu::unloadevents().  
     ';'.$onUnload;  
   
  $currentstring .= '<'.$token->[1];  
  foreach (keys %{$token->[2]}) {  
     $currentstring.=' '.$_.'="'.$token->[2]->{$_}.'"';  
  }  
  $currentstring.='>';  
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 2312  sub start_frameset { Line 3519  sub start_frameset {
 sub end_frameset {  sub end_frameset {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];   $currentstring = $token->[2];
     }      }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <xmp>  #-- <xmp> (end tag required)
 sub start_xmp {  sub start_xmp {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\begin{verbatim}';   $currentstring .= '\begin{verbatim}';
Line 2333  sub start_xmp { Line 3540  sub start_xmp {
 sub end_xmp {  sub end_xmp {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\end{verbatim}';   $currentstring .= '\end{verbatim}';
Line 2341  sub end_xmp { Line 3548  sub end_xmp {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <pre>  #-- <pre> (end tag required)
 sub start_pre {  sub start_pre {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # close off pending <p>
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[4];   $currentstring .= $token->[4];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\begin{verbatim}';   $currentstring .= '\begin{verbatim}';
    &Apache::lonxml::disable_LaTeX_substitutions();
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 2356  sub start_pre { Line 3564  sub start_pre {
 sub end_pre {  sub end_pre {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= $token->[2];   $currentstring .= $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring .= '\end{verbatim}';   $currentstring .= '\end{verbatim}';
    &Apache::lonxml::enable_LaTeX_substitutions();
     }      }
     return $currentstring;      return $currentstring;
 }  }
Line 2368  sub end_pre { Line 3577  sub end_pre {
 sub start_insert {  sub start_insert {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1);   my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1);
  $currentstring .= '<b>'.$display.'</b>';;   $currentstring .= '<b>'.$display.'</b>';;
     }      }
Line 2378  sub start_insert { Line 3587  sub start_insert {
 sub end_insert {  sub end_insert {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= '';   $currentstring .= '';
     }      }
     return $currentstring;      return $currentstring;
Line 2388  sub end_insert { Line 3597  sub end_insert {
 sub start_externallink {  sub start_externallink {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1);   my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1);
  $currentstring .= '<b>'.$display.'</b>';;   $currentstring .= '<b>'.$display.'</b>';;
     }      }
Line 2398  sub start_externallink { Line 3607  sub start_externallink {
 sub end_externallink {  sub end_externallink {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring .= '';   $currentstring .= '';
     }      }
     return $currentstring;      return $currentstring;
Line 2407  sub end_externallink { Line 3616  sub end_externallink {
 #-- <blankspace heigth="">  #-- <blankspace heigth="">
 sub start_blankspace {  sub start_blankspace {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # closes off any unclosed <p>
     if ($target eq 'tex') {      if ($target eq 'tex') {
  my $howmuch = &Apache::lonxml::get_param('heigth',$parstack,$safeeval,undef,1);   my $howmuch = &Apache::lonxml::get_param('heigth',$parstack,$safeeval,undef,1);
  $currentstring .= '\vskip '.$howmuch.' ';   $currentstring .= '\vskip '.$howmuch.' ';
Line 2424  sub end_blankspace { Line 3633  sub end_blankspace {
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <abbr> tag  #-- <abbr> tag (end tag required)
 sub start_abbr {  sub start_abbr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2437  sub start_abbr { Line 3646  sub start_abbr {
 sub end_abbr {  sub end_abbr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <acronym> tag  #-- <acronym> tag (end tag required)
 sub start_acronym {  sub start_acronym {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2456  sub start_acronym { Line 3665  sub start_acronym {
 sub end_acronym {  sub end_acronym {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <area> tag  #-- <area> tag (end tag forbidden)
 sub start_area {  sub start_area {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2475  sub start_area { Line 3684  sub start_area {
 sub end_area {  sub end_area {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <base> tag  #-- <base> tag (end tag forbidden)
 sub start_base {  sub start_base {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }      }
     return $currentstring;      return $currentstring;
Line 2494  sub start_base { Line 3703  sub start_base {
 sub end_base {  sub end_base {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <bdo> tag  #-- <bdo> tag (end tag required)
 sub start_bdo {  sub start_bdo {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2513  sub start_bdo { Line 3722  sub start_bdo {
 sub end_bdo {  sub end_bdo {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <bgsound> tag  #-- <bgsound> tag (end tag optional)
 sub start_bgsound {  sub start_bgsound {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2532  sub start_bgsound { Line 3741  sub start_bgsound {
 sub end_bgsound {  sub end_bgsound {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <blink> tag  #-- <blink> tag (end tag required)
 sub start_blink {  sub start_blink {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2551  sub start_blink { Line 3760  sub start_blink {
 sub end_blink {  sub end_blink {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <blockquote> tag  #-- <blockquote> tag (end tag required)
 sub start_blockquote {  sub start_blockquote {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close any unclosed <p>
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     }       } 
       if ($target eq 'tex') {
    $currentstring .= '\begin{quote}';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_blockquote {  sub end_blockquote {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
       if ($target eq 'tex') {
    $currentstring = '\end{quote}';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <button> tag  #-- <button> tag (end tag required)
 sub start_button {  sub start_button {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2589  sub start_button { Line 3804  sub start_button {
 sub end_button {  sub end_button {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <caption> tag  #-- <caption> tag (end tag required)
 sub start_caption {  sub start_caption {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2608  sub start_caption { Line 3823  sub start_caption {
 sub end_caption {  sub end_caption {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <col> tag  #-- <col> tag (end tag forbdden)
 sub start_col {  sub start_col {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2627  sub start_col { Line 3842  sub start_col {
 sub end_col {  sub end_col {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <colgroup> tag  #-- <colgroup> tag (end tag optional)
 sub start_colgroup {  sub start_colgroup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2646  sub start_colgroup { Line 3861  sub start_colgroup {
 sub end_colgroup {  sub end_colgroup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <del> tag  #-- <del> tag (end tag required)
 sub start_del {  sub start_del {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2665  sub start_del { Line 3880  sub start_del {
 sub end_del {  sub end_del {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <fieldset> tag  #-- <fieldset> tag (end tag required)
 sub start_fieldset {  sub start_fieldset {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2684  sub start_fieldset { Line 3899  sub start_fieldset {
 sub end_fieldset {  sub end_fieldset {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <frame> tag  #-- <frame> tag (end tag forbidden)
 sub start_frame {  sub start_frame {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2703  sub start_frame { Line 3918  sub start_frame {
 sub end_frame {  sub end_frame {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <iframe> tag  #-- <iframe> tag (end tag required)
 sub start_iframe {  sub start_iframe {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2722  sub start_iframe { Line 3937  sub start_iframe {
 sub end_iframe {  sub end_iframe {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <ins> tag  #-- <ins> tag (end tag required)
 sub start_ins {  sub start_ins {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2741  sub start_ins { Line 3956  sub start_ins {
 sub end_ins {  sub end_ins {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <isindex> tag  #-- <isindex> tag (end tag forbidden)
 sub start_isindex {  sub start_isindex {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2760  sub start_isindex { Line 3975  sub start_isindex {
 sub end_isindex {  sub end_isindex {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <keygen> tag  #-- <keygen> tag (end tag forbidden)
 sub start_keygen {  sub start_keygen {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2779  sub start_keygen { Line 3994  sub start_keygen {
 sub end_keygen {  sub end_keygen {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
Line 2789  sub end_keygen { Line 4004  sub end_keygen {
 sub start_label {  sub start_label {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2798  sub start_label { Line 4013  sub start_label {
 sub end_label {  sub end_label {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <layer> tag  #-- <layer> tag (end tag required)
 sub start_layer {  sub start_layer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2817  sub start_layer { Line 4032  sub start_layer {
 sub end_layer {  sub end_layer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <legend> tag  #-- <legend> tag (end tag required)
 sub start_legend {  sub start_legend {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2836  sub start_legend { Line 4051  sub start_legend {
 sub end_legend {  sub end_legend {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <link> tag  #-- <link> tag (end tag forbidden)
 sub start_link {  sub start_link {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
    my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
       undef,1);
    &Apache::lonxml::extlink($href);
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2855  sub start_link { Line 4073  sub start_link {
 sub end_link {  sub end_link {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <marquee> tag  #-- <marquee> tag (end tag optional)
 sub start_marquee {  sub start_marquee {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2874  sub start_marquee { Line 4092  sub start_marquee {
 sub end_marquee {  sub end_marquee {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <malticol> tag  #-- <multicol> tag (end tag required)
 sub start_malticol {  sub start_multicol {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close any pending <p>
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_malticol {  sub end_multicol {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <nobr> tag  #-- <nobr> tag (end tag required)
 sub start_nobr {  sub start_nobr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       }  elsif ($target eq 'tex') {
    $currentstring='\mbox{';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_nobr {  sub end_nobr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       }   elsif ($target eq 'tex') {
    $currentstring='}';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <noembed> tag  #-- <noembed> tag (end tag required)
 sub start_noembed {  sub start_noembed {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2931  sub start_noembed { Line 4153  sub start_noembed {
 sub end_noembed {  sub end_noembed {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <noframes> tag  #-- <noframes> tag (end tag required)
 sub start_noframes {  sub start_noframes {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2950  sub start_noframes { Line 4172  sub start_noframes {
 sub end_noframes {  sub end_noframes {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <nolayer> tag  #-- <nolayer> tag (end tag required)
 sub start_nolayer {  sub start_nolayer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2969  sub start_nolayer { Line 4191  sub start_nolayer {
 sub end_nolayer {  sub end_nolayer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <noscript> tag  #-- <noscript> tag (end tag required)
 sub start_noscript {  sub start_noscript {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 2988  sub start_noscript { Line 4210  sub start_noscript {
 sub end_noscript {  sub end_noscript {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <object> tag  #-- <object> tag (end tag required)
 sub start_object {  sub start_object {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3007  sub start_object { Line 4229  sub start_object {
 sub end_object {  sub end_object {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <optgroup> tag  #-- <optgroup> tag (end tag required)
 sub start_optgroup {  sub start_optgroup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3026  sub start_optgroup { Line 4248  sub start_optgroup {
 sub end_optgroup {  sub end_optgroup {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <samp> tag  #-- <samp> tag (end tag required)
 sub start_samp {  sub start_samp {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } elsif ($target eq 'tex') {
    $currentstring='\texttt{';
       }
     return $currentstring;      return $currentstring;
 }  }
   
 sub end_samp {  sub end_samp {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } elsif ($target eq 'tex') {
    $currentstring='}';
       }
     return $currentstring;      return $currentstring;
 }  }
   
Line 3055  sub end_samp { Line 4281  sub end_samp {
 sub start_server {  sub start_server {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3064  sub start_server { Line 4290  sub start_server {
 sub end_server {  sub end_server {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <spacer> tag  #-- <spacer> tag (end tag forbidden)
 sub start_spacer {  sub start_spacer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = &end_p(); # Close off any open <p> tag.
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring .= $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
 }  }
Line 3083  sub start_spacer { Line 4309  sub start_spacer {
 sub end_spacer {  sub end_spacer {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <span> tag  #-- <span> tag (end tag required)
 sub start_span {  sub start_span {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3102  sub start_span { Line 4328  sub start_span {
 sub end_span {  sub end_span {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
   
 #-- <tbody> tag  #-- <tbody> tag (end tag optional)
 sub start_tbody {  sub start_tbody {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3121  sub start_tbody { Line 4347  sub start_tbody {
 sub end_tbody {  sub end_tbody {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
Line 3131  sub end_tbody { Line 4357  sub end_tbody {
 sub start_tfoot {  sub start_tfoot {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3140  sub start_tfoot { Line 4366  sub start_tfoot {
 sub end_tfoot {  sub end_tfoot {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
Line 3150  sub end_tfoot { Line 4376  sub end_tfoot {
 sub start_thead {  sub start_thead {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3159  sub start_thead { Line 4385  sub start_thead {
 sub end_thead {  sub end_thead {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
Line 3169  sub end_thead { Line 4395  sub end_thead {
 sub start_var {  sub start_var {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '\textit{';    $currentstring = '\textit{'; 
Line 3180  sub start_var { Line 4406  sub start_var {
 sub end_var {  sub end_var {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];   $currentstring = $token->[2];
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = '}';    $currentstring = '}'; 
Line 3192  sub end_var { Line 4418  sub end_var {
 sub start_wbr {  sub start_wbr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     }       } 
     return $currentstring;      return $currentstring;
Line 3201  sub start_wbr { Line 4427  sub start_wbr {
 sub end_wbr {  sub end_wbr {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[2];       $currentstring = $token->[2];    
     }       } 
     return $currentstring;      return $currentstring;
Line 3210  sub end_wbr { Line 4436  sub end_wbr {
 #-- <hideweboutput> tag  #-- <hideweboutput> tag
 sub start_hideweboutput {  sub start_hideweboutput {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  &Apache::lonxml::startredirection();        &Apache::lonxml::startredirection();     
     }       } 
     return '';      return '';
Line 3219  sub start_hideweboutput { Line 4445  sub start_hideweboutput {
 sub end_hideweboutput {  sub end_hideweboutput {
     my ($target,$token) = @_;      my ($target,$token) = @_;
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = &Apache::lonxml::endredirection();       $currentstring = &Apache::lonxml::endredirection();    
     }       } 
     return '';      return '';
Line 3228  sub end_hideweboutput { Line 4454  sub end_hideweboutput {
   
 sub image_replication {  sub image_replication {
     my $src = shift;      my $src = shift;
     if (not -e $src) {      if (not -e $src) { &Apache::lonnet::repcopy($src); }
  #replicates image itself      #replicates eps or ps 
  &Apache::lonnet::repcopy($src);      my $epssrc = my $pssrc = $src;
  #replicates eps or ps       $epssrc =~ s/\.(gif|jpg|jpeg|png)$/.eps/i;
  my $newsrc = $src;      $pssrc  =~ s/\.(gif|jpg|jpeg|png)$/.ps/i;
  $newsrc =~ s/\.(gif|jpg|jpeg|png)$/.eps/i;      if (not -e $epssrc && not -e $pssrc) {
  if (not -e $newsrc) {   my $result=&Apache::lonnet::repcopy($epssrc);
     if (&Apache::lonnet::repcopy($newsrc) ne 'OK') {   if ($result ne 'ok') { &Apache::lonnet::repcopy($pssrc); }
  $newsrc =~ s/\.eps$/\.ps/;      }
  &Apache::lonnet::repcopy($newsrc);      return '';
   }
   
   
   
   sub resize_image {
       my ($height_param, $width_param, $scaling,
    $parstack, $safeeval, $depth, $cis) = @_;
   
       # First apply the scaling...
   
       $height_param = $height_param * $scaling;
       $width_param  = $width_param  * $scaling;
   
       #do we have any specified LaTeX size of the picture?
       my $toget='TeXwidth'; 
       if ($cis) { 
    $toget=lc($toget); 
       }
       my $TeXwidth = &Apache::lonxml::get_param($toget,$parstack,
         $safeeval,$depth,$cis);
       $toget='TeXheight'; if ($cis) { $toget=lc($toget); }
       my $TeXheight = &Apache::lonxml::get_param($toget,$parstack,
          $safeeval,$depth,$cis);
       #do we have any specified web size of the picture?
       my $width = &Apache::lonxml::get_param('width',$parstack,$safeeval,
      $depth,1);
       if ($TeXwidth) { 
    my $old_width_param=$width_param;
    if ($TeXwidth=~/(\d+)\s*\%/) {
       $width_param = $1*$env{'form.textwidth'}/100;
    } else { 
       $width_param = $TeXwidth;
    }
    if ($TeXheight) {
       $height_param = $TeXheight;
    } elsif ($old_width_param) {
       $height_param=$TeXwidth/$old_width_param*$height_param;
    }
       } elsif ($TeXheight) {
    $height_param = $TeXheight;
    if ($height_param) {
       $width_param  = $TeXheight/$height_param*$width_param;
    }
       } elsif ($width) {
    my $old_width_param=$width_param;
    $width_param = $width*$scaling;
    if ($old_width_param) {
       $height_param=$width_param/$old_width_param*$height_param;
    }
       }
       if ($width_param > $env{'form.textwidth'}) {
           my $old_width_param=$width_param;
    $width_param =0.95*$env{'form.textwidth'};
    if ($old_width_param) {
       $height_param=$width_param/$old_width_param*$height_param;
    }
       }
   
       return ($height_param, $width_param);
   }
   
   sub image_size {
       my ($src,$scaling,$parstack,$safeeval,$depth,$cis)=@_;
   
       #size of image from gif/jpg/jpeg/png 
       my $ressrc=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);
       if (-e $ressrc) {
    $src = $ressrc;
       }
       my $image = Image::Magick->new;
       my $current_figure = $image->Read($src);
       my $width_param = $image->Get('width');
       my $height_param = $image->Get('height');
       &Apache::lonxml::debug("Image magick says: $src :  Height = $height_param width = $width_param");
       undef($image);
   
       ($height_param, $width_param) = &resize_image($height_param, $width_param,
     $scaling, $parstack, $safeeval, 
     $depth, $cis);
   
       return ($height_param, $width_param);
   }
   
   sub image_width {
       my ($height, $width) = &image_size(@_);
       return $width;
   }
   #  Not yet 100% sure this is correct in all circumstances..
   #  due to my uncertainty about mods to image_size.
   #
   sub image_height {
       my ($height, $width) = &image_size(@_);
       return $height;
   }
   
   sub get_eps_image {
       my ($src)=@_;
       my $orig_src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1], $src);
   
       # In order to prevent the substitution of the alt text, we need to
       # be sure the orig_src file is on system now so:
   
       if (! -e $orig_src) {
    &Apache::lonnet::repcopy($orig_src); # Failure is not completely fatal.
       }
       &Apache::lonxml::debug("get_eps_image: Original image: $orig_src");
       my ($spath, $sname, $sext) = &fileparse($src, qr/\.(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) {
    &Apache::lonxml::debug("$src does not exist");
    if (&Apache::lonnet::repcopy($src) ne 'ok' ) {
       &Apache::lonxml::debug("Repcopy of $src failed (1)");
       #if replication failed try to find ps file
       $src=~s/\.eps$/\.ps/;
       &Apache::lonxml::debug("Now looking for $src");
       #if no ps file try to replicate it.
       my $didrepcopy = &Apache::lonnet::repcopy($src);
       &Apache::lonxml::debug("repcopy of $src ... $didrepcopy");
       if ( (not -e $src) ||
    ($didrepcopy ne 'ok')) {
    &Apache::lonxml::debug("Failed to find or replicate $src");
   
    #if replication failed try to produce eps file dynamically
    $src=~s/\.ps$/\.eps/;
    my $temp_file;
    open(FILE,">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat");
    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);
    $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<BR />");
       return ($path.'/',$file);
   }
   
   sub eps_generation {
       my ($src,$file,$width_param) = @_;     
       my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat";
       my $temp_file = Apache::File->new('>>'.$filename); 
       print $temp_file "$src\n";
       my $newsrc = $src;
       $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=~m{/userfiles/}) {
    return ' \graphicspath{{'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';
       } else {
    return ' \graphicspath{{/home/httpd/prtspool'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';
     }      }
     return '';  
 }  }
   
   sub file_path {     
       my $src=shift;
       my ($file,$path); 
       if ($src =~ m!(.*)/([^/]*)$!) {
    $file = $2; 
    $path = $1.'/'; 
       } 
       return $file,$path;
   }
   
   
 sub recalc {  sub recalc {
     my $argument = shift;      my $argument = shift;
     if (not $argument=~/(mm|cm|in|pc|pt)/) {return $argument.' mm';}      if (not $argument=~/(mm|cm|in|pc|pt)/) {return $argument.' mm';}
Line 3262  sub recalc { Line 4677  sub recalc {
     return $value.' mm';      return $value.' mm';
 }  }
   
   sub LATEX_length {
       my $garbage=shift;
       $garbage=~s/^\s+$//;
       $garbage=~s/^\s+(\S.*)/$1/;#space before 
       $garbage=~s/(.*\S)\s+$/$1/;#space after 
       $garbage=~s/(\s)+/$1/;#only one space
       $garbage=~s/(\\begin{([^\}]+)}|\\end{([^\}]+)})//g;#remove LaTeX \begin{...} and \end{...}
       $garbage=~s/(\$\_\{|\$\_|\$\^{|\$\^|\}\$)//g;#remove $_{,$_,$^{,$^,}$
       $garbage=~s/([^\\])\$/$1/g;#$
       $garbage=~s/(\\ensuremath\{\_\{|\\ensuremath\{\_|\\ensuremath\{\^{|\\ensuremath\{\^|\})//g;#remove \ensuremath{...}
      $garbage=~s/(\\alpha|\\beta|\\gamma|\\delta|\\epsilon|\\verepsilon|\\zeta|\\eta|\\theta|\\vartheta|\\iota|\\kappa|\\lambda|\\mu|\\nu|\\xi|\\pi|\\varpi|\\rho|\\varrho|\\sigma|\\varsigma|\\tau|\\upsilon|\\phi|\\varphi|\\chi|\\psi|\\omega|\\Gamma|\\Delta|\\Theta|\\Lambda|\\Xi|\\Pi|\\Sigma|\\Upsilon|\\Phi|\\Psi|\\Omega)/1/g;
       $garbage=~s/(\\pm|\\mp|\\times|\\div|\\cdot|\\ast|\\star|\\dagger|\\ddagger|\\amalg|\\cap|\\cup|\\uplus|\\sqcap|\\sqcup|\\vee|\\wedge|\\oplus|\\ominus|\\otimes|\\circ|\\bullet|\\diamond|\\lhd|\\rhd|\\unlhd|\\unrhd|\\oslash|\\odot|\\bigcirc|\\Box|\\Diamond|\\bigtriangleup|\\bigtriangledown|\\triangleleft|\\triangleright|\\setminus|\\wr)/1/g;
       $garbage=~s/(\\le|\\ll|\\leq|\\ge|\\geq|\\gg|\\neq|\\doreq|\\sim|\\simeq|\\subset|\\subseteq|\\sqsubset|\\sqsubseteq|\\in|\\vdash|\\models|\\supset|\\supseteq|\\sqsupset|\\sqsupseteq|\\ni|\\dash|\\perp|\\approx|\\cong|\\equiv|\\propto|\\prec|\\preceq|\\parallel|\\asymp|\\smile|\\frown|\\bowtie|\\succ|\\succeq|\\mid)/1/g;
       $garbage=~s/(\\not<|\\\\not\\le|\\not\\prec|\\not\\preceq|\\not\\subset|\\not\\subseteq|\\not\\sqsubseteq|\\not\\in|\\not>|\\not\\ge|\\not\\succ|\\notsucceq|\\not\\supset|\\notsupseteq|\\not\\sqsupseteq|\\notin|\\not=|\\not\\equiv|\\not\\sim|\\not\\simeq|\\not\\approx|\\not\\cong|\\not\\asymp)/1/g;
       $garbage=~s/(\\leftarrow|\\gets|\\Leftarrow|\\rightarrow|\\to|\\Rightarrow|\\leftrightarrow|\\Leftrightarrow|\\mapsto|\\hookleftarrow|\\leftharpoonup|\\leftkarpoondown|\\rightleftharpoons|\\longleftarrow|\\Longleftarrow|\\longrightarrow|\\Longrightarrow|\\longleftrightarrow|\\Longleftrightarrow|\\longmapsto|\\hookrightarrow|\\rightharpoonup|\\rightharpoondown|\\uparrow|\\Uparrow|\\downarrow|\\Downarrow|\\updownarrow|\\Updownarrow|\\nearrow|\\searrow|\\swarrow|\\nwarrow)/11/g;
       $garbage=~s/(\\aleph|\\hbar|\\imath|\\jmath|\\ell|\\wp|\\Re|\\Im|\\mho|\\prime|\\emptyset|\\nabla|\\surd|\\partial|\\top|\\bot|\\vdash|\\dashv|\\forall|\\exists|\\neg|\\flat|\\natural|\\sharp|\\\||\\angle|\\backslash|\\Box|\\Diamond|\\triangle|\\clubsuit|\\diamondsuit|\\heartsuit|\\spadesuit|\\Join|\\infty)/11/g;
       $garbage=~s/(\\hat{([^}]+)}|\\check{([^}]+)}|\\dot{([^}]+)}|\\breve{([^}]+)}|\\acute{([^}]+)}|\\ddot{([^}]+)}|\\grave{([^}]+)}|\\tilde{([^}]+)}|\\mathring{([^}]+)}|\\bar{([^}]+)}|\\vec{([^}]+)})/$1/g;
       #remove some other LaTeX command
       $garbage=~s|\\(\w+)\\|\\|g;  
       $garbage=~s|\\(\w+)(\s*)|$2|g;  
       $garbage=~s|\+|11|g;
       my  $value=length($garbage);
       return $value;
   }
   
   
   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);
   }
   
   
   sub is_inside_of {
       my ($tagstack, $tag) = @_;
       my @stack = @$tagstack;
       for (my $i = ($#stack - 1); $i >= 0; $i--) {
    if ($stack[$i] eq $tag) {
       return 1;
    }
       }
       return 0;
   }
   
   
   #
   #   This sub provides the typical LaTeX prefix matter for tex output:
   #
   sub latex_header
   {
       my ($mode) = @_;
       my $currentstring = '';
   
       $currentstring .= 
    "\n% &Apache::lonxml::londefdef \n" .
    '\documentclass[letterpaper,twoside]{article}\raggedbottom';
       if (($env{'form.latex_type'}=~'batchmode') ||
    (!$env{'request.role.adv'}) || 
    ($mode eq 'batchmode')) {$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{lmodern}'."\n".
    '\usepackage[postscript]{ucs}'."\n".
    '\usepackage[utf8x]{inputenc}'."\n".
    '\usepackage{pifont}' ."\n".
    '\usepackage{latexsym}'."\n".
    '\usepackage{epsfig}'.
    "\\usepackage{xtab}\n".
    "\\usepackage{tabularx}\n".
    "\\usepackage{booktabs}\n".
    "\\usepackage{array}\n".
    "\\usepackage{colortbl}\n".
    "\\usepackage{xcolor}\n".
    '\usepackage{calc}'.
    '\usepackage{amsmath}'.
    '\usepackage{amssymb}'.
    '\usepackage{amsfonts}'.
    '\usepackage{amsthm}'.
    '\usepackage{amscd}'
           .'\usepackage{picins}\usepackage{calc}'."\n". # From lonprintout.pm
    '\usepackage[T1]{fontenc}'."\n".
    '\usepackage{lmodern}'."\n".
    '\usepackage[postscript]{ucs}'."\n".
    '\usepackage[utf8x]{inputenc}'."\n".
    '\usepackage{pifont}'  . "\n";
   
       if($env{'form.pdfFormFields'} eq 'yes') {
    $currentstring .= '\usepackage{hyperref}'.
       '\usepackage{eforms}'.
       '\usepackage{tabularx}';
       } 
       
           $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}}';
       $currentstring .= '\begin{document}';
       
       return $currentstring;
   
   }
   
   =pod
   
   =head1 NAME
   
   Apache::londefdef.pm
   
   =head1 SYNOPSIS
   
   Tags Default Definition Module
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   
   =head1 NOTABLE SUBROUTINES
   
   =over
   
   =item start_hideweboutput()
   
   =item end_hideweboutput()
   
   =item image_replication()
   
   =item resize_image()
   
    Get correct sizing parameter for an image given
    it's initial ht. and wid.  This allows sizing of
    images that are generated on-the-fly (e.g. gnuplot)
    as well as serving as a utility for image_size.
    
    Parameter:
           height_param
           width_param    - Initial picture dimensions.
           scaling        - A scale factor.
           parstack,      - the current stack of tag attributes 
                            from the xml parser
           safeeval,      - pointer to the safespace
           depth,         - from what level in the stack to look for attributes
                            (assumes -1 if unspecified)
           cis            - look for attrubutes case insensitively
                            (assumes false)
   
    Returns:
    height, width   - new dimensions.
   
   =item image_size()
   
   =item image_width()
   
   =item image_height()
   
   =item get_eps_image()
   
   =item eps_generation()
   
   =item file_path()
   
   =item recalc()
   
    Converts a measurement in to mm from any of 
    the other valid LaTeX units of measure.
    If the units of measure are missing from the 
    parameter, it is assumed to be in and returned
    with mm units of measure
   
   =item LATEX_length()
   
   =item align_latex_image()
   
     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.
   
   
   =item is_inside_of($tagstack, $tag)
       This sub returns true if the current state of Xml processing is inside of the tag.   
    Parameters:
       tagstack   - The tagstack from the parser.
       tag        - The tag (without the <>'s.).
    Sample usage:
       if (is_inside_of($tagstack "table")) {
           I'm in a table....
         }
   
   
   
   =back
   
   =cut
   
   
 1;  1;
 __END__  __END__

Removed from v.1.172  
changed lines
  Added in v.1.402


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>