Diff for /loncom/xml/londefdef.pm between versions 1.111 and 1.467

version 1.111, 2003/02/05 23:17:32 version 1.467, 2023/03/15 16:47:59
Line 25 Line 25
 # /home/httpd/html/adm/gpl.txt  # /home/httpd/html/adm/gpl.txt
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  ## Copyright for TtHfunc and TtMfunc by Ian Hutchinson. 
 # Copyright for TtHfunc and TtMfunc by Ian Hutchinson.   
 # TtHfunc and TtMfunc (the "Code") may be compiled and linked into   # TtHfunc and TtMfunc (the "Code") may be compiled and linked into 
 # binary executable programs or libraries distributed by the   # binary executable programs or libraries distributed by the 
 # Michigan State University (the "Licensee"), but any binaries so   # Michigan State University (the "Licensee"), but any binaries so 
Line 37 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::File();  use Apache::lontable;
 use Image::Magick;  use Image::Magick;
   use Apache::lonmenu();
   use Apache::lonmeta();
   use Apache::lonlocal;
   use Apache::loncommon();
   use Apache::Constants qw(:common);
   use File::Basename;
   use LONCAPA();
   # use Data::Dumper;
   
 BEGIN {  BEGIN {
   
     &Apache::lonxml::register('Apache::londefdef',('a','abbr','acronym','address','allow','applet','area','b','base','basefont','bgo','bgsound','big','blink','blockquote','blankspace','body','br','button','caption','center','cite','code','col','colgroup','dd','del','dfn','dir','div','dl','dt','em','embed','externallink','fieldset','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','insert','isindex','kbd','keygen','label','layer','legend','li','link','m','map','marquee','menu','meta','multicol','nobr','noembed','noframes','nolayer','noscript','object','ol','optgroup','option','output','p','param','pre','q','s','samp','select','server','small','spacer','span','strike','strong','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','tthoption','u','ul','var','wbr'));      &Apache::lonxml::register('Apache::londefdef',('a','abbr','acronym','accessrule','address','allow','applet','area','b','base','basefont','bgo','bgsound','big','blink','blockquote','blankspace','body','br','button','caption','center','cite','code','col','colgroup','dd','del','dfn','dir','div','dl','dt','em','embed','externallink','fieldset','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','insert','isindex','kbd','keygen','label','layer','legend','li','link','m','map','marquee','menu','meta','multicol','nobr','noembed','noframes','nolayer','noscript','object','ol','optgroup','option','output','p','param','pre','q','s','samp','select','server','small','spacer','span','strike','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','tthoption','u','ul','var','wbr','hideweboutput'));
   
   }
   
   
   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 {
   my ($target) = @_;      my ($target) = @_;
   if ($target eq 'meta') { $Apache::lonxml::metamode--; }      if ($target eq 'meta') { $Apache::lonxml::metamode--; }
   return '';      return '';
 }  }
 sub end_output {  sub end_output {
   my ($target) = @_;      my ($target) = @_;
   if ($target eq 'meta') { $Apache::lonxml::metamode++; }      if ($target eq 'meta') { $Apache::lonxml::metamode++; }
   return '';      return '';
 }  }
 #-- <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') {  
     $Apache::lonxml::prevent_entity_encode++;  
     my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);  
     $inside ='\\documentstyle{article}'.$inside;  
     &Apache::lonxml::debug("M is starting with:$inside:");  
     my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);  
     if ($eval eq 'on') {  
       $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);  
       #&Apache::lonxml::debug("M is evaulated to:$inside:");  
     }  
     $currentstring = &Apache::lontexconvert::converted(\$inside);  
     if ($Apache::lontexconvert::errorstring) {  
       &Apache::lonxml::warning("tth error: ".  
        $Apache::lontexconvert::errorstring);  
       $Apache::lontexconvert::errorstring='';  
     }  
     #&Apache::lonxml::debug("M is ends with:$currentstring:");  
   } elsif ($target eq 'tex') {  
     $currentstring = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);  
     if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}  
   } else {  
     my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);      my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);
   }      if ($target eq 'web' || $target eq 'analyze') {
   return $currentstring;   &Apache::lonxml::debug("M is starting with:$inside:");
           if (!($inside =~ /^\s*\$.*\$\s*$/ || $inside =~ /^\s*\\[([].*\\[)\]]\s*$/)) {
               # Non-math LaTeX will not be rendered correctly with MathJax
               # and it should be avoided anyway.
               # On top of that, MathJax will render math without $, but
               # it will fail with tth. This is worth a warning.
               # (even though some people might just use latex for printing)
               &Apache::lonxml::warning(&mt('Missing $ in [_1].','&lt;m&gt;'));
           } elsif (($env{'browser.type'} eq 'safari') && ($env{'form.editxmltext'}) &&
                    (($env{'form.problemmode'} eq 'view') || ($env{'form.problemmode'} eq 'discard'))) {
               my $delimiter;
               if ($inside =~ /\$$/) {
                   $delimiter = '$';
               } elsif ($inside =~ /\\([)\]])$/) {
                   $delimiter = $1;
               }
               if ($delimiter) {
                   &Apache::lonxml::warning(&mt('Insert a space between [_1] and [_2].',
                                                $delimiter,'&lt;/m&gt;'));
               }
           }
    my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
    if ($eval eq 'on') {
       $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
       #&Apache::lonxml::debug("M is evaluated to:$inside:");
    }
    my $tex = $inside;
    my $display=&Apache::lonxml::get_param('display',$parstack,$safeeval);
    $currentstring = &Apache::lontexconvert::converted(\$inside,$display);
    if ($Apache::lontexconvert::errorstring) {
       my $errormsg='<pre>'.&HTML::Entities::encode($Apache::lontexconvert::errorstring,'<>&"').'</pre> occurred while attempting to convert this TeX: <pre>';
       $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::lonxml::debug("M is ends with:$currentstring:");
    $Apache::lonxml::post_evaluate=0;
       } elsif ($target eq 'tex') {
   
    $currentstring = $inside;
    my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
    if ($eval eq 'on') {
       $currentstring=&Apache::run::evaluate($currentstring,$safeeval,$$parstack[-1]);
    }
    if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}
    # detect simple math mode entry exits, and convert them
           # to use \ensuremath ... unless there's a \verb inside.
    if (! ($currentstring=~/\\verb/)) {
       if ($currentstring=~/^\s*\$[^\$].*\$\s*$/) {
    $currentstring=~s/^(\s*)\$/$1/;
    $currentstring=~s/\$(\s*)$/$1/;
    $currentstring='\ensuremath{'.$currentstring.'}';
       }
    }
    $Apache::lonxml::post_evaluate=0;
       }
       return $currentstring;
 }  }
   
 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--;   $currentstring = "";
   } elsif ($target eq 'tex') {      }
     $currentstring = "";      return $currentstring;
   } elsif ($target eq 'meta') {  
   }  
   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,
       $inside=~s/^\s*//;     $style);
       if ($ENV{'browser.mathml'}) {   $inside=~s/^\s*//;
   &tth::ttmoptions($inside);   if ($env{'browser.mathml'}) {
       } else {      &tth::ttmoptions($inside);
   &tth::tthoptions($inside);   } else {
       }      &tth::tthoptions($inside);
   }   }
       }
       return $result;
 }  }
   
 sub end_tthoption {  sub end_tthoption {
   my ($target,$token) = @_;      my ($target,$token) = @_;
   my $result;      my $result;
   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'}) {      } elsif ($target eq 'tex') {
     &tth::ttmoptions('-L -u1');  
  } else {   $currentstring .= &latex_header();
     &tth::ttmoptions('-L -u0');      }
       return $currentstring;
   }
   
   sub end_html {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    # end_body takes care of the </html>
       }
       return $currentstring;
   }
   
   #-- <head> tag (end tag optional)
   sub start_head {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    &Apache::lonxml::startredirection();
       } 
       return $currentstring;
   }
   
   sub end_head {
       my ($target,$token) = @_;
       my $currentstring = '';
       if (($target eq 'web'      && $env{'request.state'} eq 'published') ||
    ($target eq 'webgrade' && $env{'request.state'} eq 'published')) {
    # in case there is a </head> but no <head>
    if ($Apache::lonxml::redirection) {
       $Apache::londefdef::head = &Apache::lonxml::endredirection();
  }   }
     } else {      } 
  &tth::tthinit();      return $currentstring;
  if ($ENV{'browser.unicode'}) {  }
     &tth::tthoptions('-L -u1');  
   #-- <map> tag (end tag required)
   sub start_map {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_map {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <select> tag (end tag required)
   sub start_select {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       }  elsif ($target eq 'tex') {
    $Apache::londefdef::select=0;
       }
       return $currentstring;
   }
   
   sub end_select {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <option> tag (end tag optional)
   sub start_option {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $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 {   } else {
     &tth::tthoptions('-L -u0');      $currentstring='\keephidden{';
  }   }
     }      }
     if ($target eq 'web') {      return $currentstring;
  $currentstring = &Apache::lonxml::xmlbegin().  }
     &Apache::lonxml::fontsettings();       
   sub end_option {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       }  elsif ($target eq 'tex') {
    $currentstring='}';
       }
       return $currentstring;
   }
   
   #-- <input> tag (end tag forbidden)
   sub start_input {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_input {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <textarea> tag (end tag required)
   sub start_textarea {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_textarea {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <form> tag (end tag required)
   sub start_form {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_form {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <title> tag (end tag required)
   sub start_title {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $Apache::londefdef::title = 
       &Apache::lonxml::get_all_text('/title',$parser,$style);
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  @Apache::londefdef::table = ();   $currentstring .= '\keephidden{Title of the document:  ';
  $currentstring .= '\documentclass[letterpaper]{article}      }
                                  \newcommand{\keephidden}[1]{}      if ($target eq 'meta') {
                                  \renewcommand{\deg}{$^{\circ}$}   $currentstring='<title>';
                                  \usepackage[dvips]{graphicx}   &start_output($target);
                                  \usepackage{epsfig}\usepackage{calc}      }
                                  \newenvironment{choicelist}{\begin{enumerate}}{\end{enumerate}}';      return $currentstring;
     }  }
     return $currentstring;  
 }  sub end_title {
         sub end_html {      my ($target,$token) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   # start_title takes care of swallowing the title
  $currentstring = &Apache::lonxml::xmlend();      } elsif ($target eq 'tex') {
     }   $currentstring .= '}';
    return $currentstring;      }  
  }      if ($target eq 'meta') {
 #-- <head> tag   &end_output($target);
       sub start_head {   $currentstring='</title>';
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   #-- <meta> tag (end tag forbidden)
    return $currentstring;  sub start_meta {
  }      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
         sub end_head {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   my $args='';
             if ($target eq 'web') {   if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
               $currentstring = &Apache::lonxml::registerurl(undef,$target).   if ($args eq '') {
                                $token->[2];          &Apache::lonxml::get_all_text("/meta",$parser,$style);
             }    } else {
    return $currentstring;      $currentstring = $token->[4];
  }  
 #-- <map> tag  
       sub start_map {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_map {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <select> tag  
       sub start_select {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_select {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <option> tag  
       sub start_option {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_option {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <input> tag  
       sub start_input {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_input {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <textarea> tag  
       sub start_textarea {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_textarea {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <form> tag  
       sub start_form {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_form {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }  
 #-- <title> tag  
       sub start_title {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {  
               $currentstring .= '\keephidden{'   
     }  
             if ($target eq 'meta') {  
  $currentstring='<title>';  
                 &start_output();  
             }  
    return $currentstring;  
  }   }
         sub end_title {          if ($env{'form.grade_imsexport'}) {
     my ($target,$token) = @_;              $currentstring = '';
             my $currentstring = '';          }
             if ($target eq 'web') {      } elsif ($target eq 'meta') {
               $currentstring = $token->[2];       unless (&Apache::lonxml::get_param
             } elsif ($target eq 'tex') {   ('http-equiv',$parstack,$safeeval,undef,1)) {
               $currentstring .= '}';      my $name=$token->[2]->{'name'};
     }        $name=~tr/A-Z/a-z/;
             if ($target eq 'meta') {      $name=~s/\s/\_/gs;
                &end_output();      $name=~s/\W//gs;
                $currentstring='</title>';      if ($name) {
             }    $currentstring='<'.$name;
    return $currentstring;                   my $display=&Apache::lonxml::get_param
  }   ('display',$parstack,$safeeval,undef,1);
 #-- <meta> tag                  if ($display) {
       sub start_meta {                      $display=~s/\"/\'/g;
     my ($target,$token,$tagstack,$parstack,$parser) = @_;      $currentstring.=' display="'.$display.'"';
             my $currentstring = '';  
             if ($target eq 'web') {  
       my $args='';  
       if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }  
       if ($args eq '') {  
  &Apache::lonxml::get_all_text("/meta",$$parser[$#$parser]);  
       } else {  
  $currentstring = $token->[4];  
       }  
     }  
             if ($target eq 'meta') {  
  unless ($token->[2]->{'http-equiv'}) {  
     my $name=$token->[2]->{'name'};  
                     $name=~tr/A-Z/a-z/;  
                     $name=~s/\s/\_/g;  
                     if ($name) {  
                        $currentstring='<'.$name.'>'.  
                                          $token->[2]->{'content'}.  
               '</'.$name.'>';  
     }  
                 }                  }
    $currentstring.='>'.
       &Apache::lonxml::get_param
    ('content',$parstack,$safeeval,undef,1).
    '</'.$name.'>';
     }      }
    return $currentstring;              my $display=&Apache::lonxml::get_param
    ('display',$parstack,$safeeval,undef,1);
               if ($display) {
    $display=&HTML::Entities::encode($display,'<>&"');
    $currentstring.='<'.$name.'.display>'.$display.
                                  '</'.$name.'.display>';
               }
  }   }
       sub end_meta {      } elsif ($target eq 'tex') {
  my ($target,$token,$tagstack,$parstack,$parser) = @_;   my $content=&Apache::lonxml::get_param('content',$parstack,$safeeval);
  my $currentstring = '';   my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval);
  if ($target eq 'web') {   if ((not defined $content) && (not defined $name)) {
   my $args='';      &Apache::lonxml::startredirection();
   if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }   }
   if ($args ne '') {      } 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;
   }
   
   sub end_meta {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    my $args='';
    if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
    if ($args ne '') {
     $currentstring = $token->[4];      $currentstring = $token->[4];
   }   }
  }       } elsif ($target eq 'tex') {
    my $content=&Apache::lonxml::get_param('content',$parstack,$safeeval);
    my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval);
    if ((not defined $content) && (not defined $name)) {
       &Apache::lonxml::endredirection();
    }
       }
       return $currentstring;
   }
   
   sub insert_meta {
       return '
       <meta />';
   }
   
   #-- <start> tag
   sub start_style {
    my ($target, $token, $tagstack, $parstack, $parser, $safeeval, $style) = @_;
    my $currentstring = '';
   
    if ($target eq 'tex') {
    Apache::lonxml::startredirection();
    } else {
    $currentstring = $token->[4];
    }
   
  return $currentstring;   return $currentstring;
       }  }
 #-- <body> tag  
         sub start_body {  sub end_style {
             my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;   my ($target, $token, $tagstack, $parstack, $parser, $safeeval) = @_;
             my $currentstring = '';   my $currentstring = '';
             if ($target eq 'web') {  
       if (!$Apache::lonxml::registered) {   if ($target eq 'tex') {
  $currentstring.='<head>'.   Apache::lonxml::endredirection();
     &Apache::lonxml::registerurl(undef,$target).'</head>';   } else {
       }   $currentstring = $token->[2];
       my $onLoad='';   }
       foreach my $key (keys(%{$token->[2]})) {   return $currentstring;
  if ($key =~ /^onload$/i) {  }
   $onLoad.=$token->[2]->{$key}.';';  
   delete($token->[2]->{$key});  # accessrule
  }  sub start_accessrule {
       }      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
       $token->[2]->{'onload'}=&Apache::lonxml::loadevents().      my $currentstring = '';
                        ';'.$onLoad;      my $eff  =&Apache::lonxml::get_param('effect',$parstack,$safeeval,undef,1);
       my $onUnload='';      my $realm=&Apache::lonxml::get_param('realm', $parstack,$safeeval,undef,1);
       foreach my $key (keys(%{$token->[2]})) {      my $role =&Apache::lonxml::get_param('role',  $parstack,$safeeval,undef,1);
  if ($key =~ /^onunload$/i) {      my $type =&Apache::lonxml::get_param('type',  $parstack,$safeeval,undef,1);
   $onUnload.=$token->[2]->{$key}.';';  
   delete($token->[2]->{$key});      my ($dom,$crs,$sec,$separator);
  }      if ($type eq 'user') {
       }   ($dom,$crs,$sec)=split(m{/},$realm);
       $token->[2]->{'onunload'}=&Apache::lonxml::unloadevents().   $crs = &LONCAPA::clean_username($crs);
                          ';'.$onUnload;   $separator = '/';
       } else {
       $currentstring .= '<'.$token->[1];   ($dom,$crs,$sec)=split(/\_/,$realm);
       foreach (keys %{$token->[2]}) {   $crs = &LONCAPA::clean_courseid($crs);
        $currentstring.=' '.$_.'="'.$token->[2]->{$_}.'"';   $separator = '_';
       }      }
       $currentstring.='>';      $dom = &LONCAPA::clean_domain($dom);
       if ($ENV{'request.state'} ne 'published') {  
  $currentstring.=(<<EDITBUTTON);      $sec =~s/\W//;
  <form method="post">      $realm = $dom;
  <input type="submit" name="editmode" value="Edit" />      if ($crs =~ /\S/) { $realm .= $separator.$crs; }
  </form>      if ($sec =~ /\S/) { $realm .= $separator.$sec; }
 EDITBUTTON      $role=~s/\W//g;
       }  
            } elsif ($target eq 'tex') {      if ($target eq 'web') {
               $currentstring = '\begin{document}';     my $args='';
     }    if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
    return $currentstring;   if ($args eq '') {
  }      &Apache::lonxml::get_all_text("/accessrule",$parser,$style);
         sub end_body {   } else {
     my ($target,$token) = @_;      $currentstring = $token->[4];
             my $currentstring = '';   }
             if ($target eq 'web') {      }
               $currentstring = $token->[2];           if ($target eq 'meta') {
     } elsif ($target eq 'tex') {   $currentstring='<rule>'.$eff.':'.$realm.':'.$role.':'.$type.'</rule>';
               $currentstring = '\end{document}';        }
     }       return $currentstring;
    return $currentstring;  }
  }  
 #-- <center> tag  sub end_accessrule {
         sub start_center {      my ($target,$token,$tagstack,$parstack,$parser) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web') {
             if ($target eq 'web') {   my $args='';
               $currentstring = $token->[4];        if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; }
     } elsif ($target eq 'tex') {   if ($args ne '') {
               $currentstring = '\begin{center}';        $currentstring = $token->[4];
     }  elsif ($target eq 'latexsource') {   }
               $currentstring = '\begin{center}';        } 
     }       return $currentstring;
    return $currentstring;  }
  }  
         sub end_center {  sub generate_css_links {
     my ($target,$token) = @_;      my $links;
             my $currentstring = '';      my $css_href = &Apache::lonnet::EXT('resource.0.cssfile');
             if ($target eq 'web') {      if ($css_href =~ /\S/) {
               $currentstring = $token->[2];        &Apache::lonxml::extlink($css_href);
     } elsif ($target eq 'tex') {   $links .= 
               $currentstring = '\end{center}';        '<link rel="stylesheet" type="text/css" href="'.$css_href.'" />';
     }  elsif ($target eq 'latexsource') {      }
               $currentstring = '\end{center}';        return $links;
     }   }
    return $currentstring;  
  }  #-- <body> tag (end tag required)
 #-- <b> tag  sub start_body {
         sub start_b {      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';  
             if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
               $currentstring = $token->[4];        if ($Apache::lonhomework::parsing_a_problem) {
     } elsif ($target eq 'tex') {      &Apache::lonxml::warning("<body> tag found inside of <problem> tag this can cause problems.");
               $currentstring = '\textbf{';        return '';
     }  elsif ($target eq 'latexsource') {   }
               $currentstring = '\textbf{';    
     }    if (&is_inside_of($tagstack, "head")) {
    return $currentstring;      &end_head(@_);
  }   }
         sub end_b {  
     my ($target,$token) = @_;   my $extra_head = &generate_css_links();
             my $currentstring = '';  
             if ($target eq 'web') {      # Breadcrumbs
               $currentstring = $token->[2];           &Apache::lonhtmlcommon::clear_breadcrumbs();
     } elsif ($target eq 'tex') {      if ($env{'request.state'} eq 'construct') {
               $currentstring = '}';            my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
           &Apache::lonhtmlcommon::add_breadcrumb({
     } elsif ($target eq 'latexsource') {              'text'  => 'Authoring Space',
               $currentstring = '}';                'href'  => &Apache::loncommon::authorspace($url),
     }           });
    return $currentstring;          &Apache::lonhtmlcommon::add_breadcrumb({
  }              'text'  => 'HTML Editor',
 #-- <strong> tag              'href'  => '',
         sub start_strong {          });
     my ($target,$token) = @_;          # breadcrumbs (and tools) will be created 
             my $currentstring = '';          # in start_page->bodytag->innerregister
             if ($target eq 'web') {      } else {
               $currentstring = $token->[4];               # FIXME Where are we?
     } elsif ($target eq 'tex') {      }
               $currentstring = '\textbf{';    
     } elsif ($target eq 'latexsource') {          my $args = {'add_entries'    => $token->[2],
               $currentstring = '\textbf{';                        'force_register' => 1,};
     }           if ($target eq 'web') {
    return $currentstring;              $args->{'print_suppress'} = 1;
  }              if ($env{'request.use_absolute'}) {
         sub end_strong {                  $args->{'use_absolute'} = $env{'request.use_absolute'};
     my ($target,$token) = @_;              }
             my $currentstring = '';          }
             if ($target eq 'web') {   $currentstring = 
       &Apache::loncommon::start_page($Apache::londefdef::title,
               $currentstring = $token->[2];          $Apache::londefdef::head
     } elsif ($target eq 'tex') {        .$extra_head,$args);
               $currentstring = '}';            my $header = '';
     }  elsif ($target eq 'latexsource') {          if ($env{'request.state'} ne 'published' &&
               $currentstring = '}';                $env{'request.state'} ne 'construct') {
     }               $header=&Apache::lonmenu::constspaceform();
    return $currentstring;          }
  }          if ($env{'request.state'} ne 'published') {
 #-- <h1> tag              unless ($env{'form.inhibitmenu'} eq 'yes') {
         sub start_h1 {                  $header.=&edit_controls();
     my ($target,$token) = @_;              }
             my $currentstring = '';          }
             if ($target eq 'web') {          if ($env{'request.state'} eq 'construct') {
        $currentstring .= $token->[4];              unless ($env{'form.inhibitmenu'} eq 'yes') {
     } elsif ($target eq 'tex') {                  $currentstring.=&Apache::loncommon::head_subbox(
  $currentstring .= '{\large \textbf{';                                      &Apache::loncommon::CSTR_pageheader()
     } elsif ($target eq 'meta') {                                     .$header);
  $currentstring='<subject>';              }
                 &start_output();          } elsif ($env{'request.state'} eq 'edit') {
               $currentstring.=&Apache::loncommon::head_subbox($header);
           }
           $currentstring.=&Apache::lonxml::message_location();
       } elsif ($target eq 'tex') {
           $currentstring = '';   #  '\begin{document}' is in header.
       }
   
       return $currentstring;
   }
   
   sub edit_controls {
       my ($nochgview) = @_;
       my $result .= '
   <form method="post" action="">
   <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><input type="submit" name="editmode" accesskey="e" value="'.&mt('Edit').'" />';
       if ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9) {
           my $uri = $env{'request.uri'};
           my $daxeurl = '/daxepage'.$uri;
           $result .= '<input type="button" value="'.&mt('Edit with Daxe').'" '.
                     'onclick="window.open(\''.$daxeurl.'\',\'_blank\');" />';
       }
       if (($env{'request.course.id'}) && ($env{'form.forceedit'})) {
           my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
           if ($url =~ /\.html?$/i) {
               my ($cdom,$cnum);
               if ($env{'request.course.id'}) {
                   $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   if ($env{'request.filename'} =~ m{/userfiles/supplemental/default|\d+/}) {
                       if (&Apache::lonnet::is_course_upload($env{'request.filename'},
                                                             $cnum,$cdom)) {
                           &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                                                   ['folderpath','title']);
                       }
                   }
               }
               my ($symb,$itemtitle,$displayfile,$caller);
               if ($url =~ m{^/uploaded/$cdom/$cnum/portfolio/syllabus/}) {
                   $itemtitle = &mt('Syllabus');
                   $caller = "/public/$cdom/$cnum/syllabus";
               } else {
                   $caller = $url;
                   ($symb,$itemtitle,$displayfile) =
                       &Apache::lonxml::get_courseupload_hierarchy($url,
                                                                   $env{'form.folderpath'},
                                                                   $env{'form.title'});
             }              }
            return $currentstring;              if (($symb ne '') || ($env{'httpref.'.$url} ne '') ||
                   ($url =~ m{^/uploaded/$cdom/$cnum/portfolio/syllabus/})) {
                     $result .= ('&nbsp;' x 3).
                                &Apache::lonhtmlcommon::dependencies_button()."\n".
                                &Apache::lonhtmlcommon::dependencycheck_js($symb,
                                    $itemtitle,$url,$env{'form.folderpath'},$caller)."\n";
               }
           }
       }
       $result .= '</div>
   </div>
   </form>
   ';
       return $result;
   }
   
   sub end_body {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # Close off unclosed <p>
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= &Apache::loncommon::end_page({'discussion' => 1});
       } elsif ($target eq 'tex') {
    $currentstring .= '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent \end{document}';  
       } 
       return $currentstring;
   }
   
   # \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 {
       my ($target,$token,$tagstack) = @_;
       my $currentstring = &end_p(); # Close off any prior para.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];     
       } elsif ($target eq 'tex') {
    if (&is_inside_of($tagstack, "table")) {
       $currentstring .= &center_correction();
  }   }
         sub end_h1 {   $currentstring .= '\begin{center}';  
     my ($target,$token) = @_;      }
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  sub end_center {
  $currentstring .= '}}';      my ($target,$token,$tagstack) = @_;
     } elsif ($target eq 'meta') {      my $currentstring = '';
                 &end_output();      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring='</subject>';   $currentstring = $token->[2];     
             }       } elsif ($target eq 'tex') {
            return $currentstring;   $currentstring = '\end{center}';  
    if (&is_inside_of($tagstack, "table")) {
       $currentstring .= &center_end_correction();
  }   }
       }
       return $currentstring;
   }
   
   #-- <b> tag (end tag required)
   #      NOTE: In TeX mode disables internal <p>
   sub start_b {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    &disable_para();
    $currentstring .= '\textbf{';  
       } 
       return $currentstring;
   }
   
   sub end_b {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
    &enable_para();
    $currentstring = '}';
       } 
       return $currentstring;
   }
   
   #-- <strong> tag (end tag required)
   #    NOTE: in TeX mode disables internal <p>
   sub start_strong {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    &disable_para();
    $currentstring = '\textbf{';  
       } 
       return $currentstring;
   }
   
   sub end_strong {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
    &enable_para();
    $currentstring = '}';  
       }
       return $currentstring;
   }
   
   #-- <h1> tag (end tag required)
   sub start_h1 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # Close off any prior para.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    my $pre;
    my $align=lc(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1));
    if ($align eq 'center') {
       $pre='\begin{center}';
    } elsif ($align eq 'left') {
       $pre='\rlap{';
    } elsif ($align eq 'right') {
       $pre=' \hfill \llap{';
    }
    my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
    if (not defined $TeXsize) {$TeXsize="large";}
    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
       } elsif ($target eq 'meta') {
    $currentstring.='<subject>';
    &start_output($target);
       }
       return $currentstring;
   }
   
   sub end_h1 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    my $post='\vskip 0 mm ';
    my $align=lc(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1));
    if ($align eq 'center') {
       $post='\end{center}';
    } elsif ($align eq 'left') {
       $post='} \hfill'.'\vskip 0 mm ';
    } elsif ($align eq 'right') {
       $post='}'.'\vskip 0 mm ';
    }
    $currentstring .= '}}'.$post;
       } elsif ($target eq 'meta') {
    &end_output($target);
    $currentstring='</subject>';
       } 
       return $currentstring;
   }
   
 #-- <h2> tag  #-- <h2> tag
         sub start_h2 {  sub start_h2 {
     my ($target,$token) = @_;      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') {
  $currentstring .= '{\large \textbf{';   my $pre;
     }    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
            return $currentstring;   if ($align eq 'center') {
  }      $pre='\begin{center}';
         sub end_h2 {   } elsif ($align eq 'left') {
     my ($target,$token) = @_;      $pre='\rlap{';
             my $currentstring = '';   } elsif ($align eq 'right') {
             if ($target eq 'web') {      $pre=' \hfill \llap{';
        $currentstring .= $token->[2];   }
     } elsif ($target eq 'tex') {   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  $currentstring .= '}}';   if (not defined $TeXsize) {$TeXsize="large";}
     }    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
            return $currentstring;      } 
       return $currentstring;
   }
   
   sub end_h2 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    my $post='\vskip 0 mm ';
    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($align eq 'center') {
       $post='\end{center}';
    } elsif ($align eq 'left') {
       $post='} \hfill'.'\vskip 0 mm ';
    } elsif ($align eq 'right') {
       $post='}'.'\vskip 0 mm ';
  }   }
    $currentstring .= '}}'.$post;
       } 
       return $currentstring;
   }
   
 #-- <h3> tag  #-- <h3> tag
         sub start_h3 {  sub start_h3 {
     my ($target,$token) = @_;      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') {
  $currentstring .= '{\large \textbf{';   my $pre;
     }    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
            return $currentstring;   if ($align eq 'center') {
  }      $pre='\begin{center}';
         sub end_h3 {   } elsif ($align eq 'left') {
     my ($target,$token) = @_;      $pre='\rlap{';
             my $currentstring = '';   } elsif ($align eq 'right') {
             if ($target eq 'web') {      $pre=' \hfill \llap{';
        $currentstring .= $token->[2];   }
     } elsif ($target eq 'tex') {   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  $currentstring .= '}}';   if (not defined $TeXsize) {$TeXsize="large";}
     }    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
            return $currentstring;      } 
       return $currentstring;
   }
   
   sub end_h3 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    my $post='\vskip 0 mm ';
    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($align eq 'center') {
       $post='\end{center}';
    } elsif ($align eq 'left') {
       $post='} \hfill'.'\vskip 0 mm ';
    } elsif ($align eq 'right') {
       $post='}'.'\vskip 0 mm ';
  }   }
    $currentstring .= '}}'.$post;
       } 
       return $currentstring;
   }
   
 #-- <h4> tag  #-- <h4> tag
         sub start_h4 {  sub start_h4 {
     my ($target,$token) = @_;      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') {
  $currentstring .= '{\large \textbf{';   my $pre;
     }    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
            return $currentstring;   if ($align eq 'center') {
  }      $pre='\begin{center}';
         sub end_h4 {   } elsif ($align eq 'left') {
     my ($target,$token) = @_;      $pre='\rlap{';
             my $currentstring = '';   } elsif ($align eq 'right') {
             if ($target eq 'web') {      $pre=' \hfill \llap{';
        $currentstring .= $token->[2];   }
     } elsif ($target eq 'tex') {   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  $currentstring .= '}}';   if (not defined $TeXsize) {$TeXsize="large";}
     }    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
            return $currentstring;      } 
       return $currentstring;
   }
   
   sub end_h4 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    my $post='\vskip 0 mm ';
    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($align eq 'center') {
       $post='\end{center}';
    } elsif ($align eq 'left') {
       $post='} \hfill'.'\vskip 0 mm ';
    } elsif ($align eq 'right') {
       $post='}'.'\vskip 0 mm ';
  }   }
    $currentstring .= '}}'.$post;
       } 
       return $currentstring;
   }
   
 #-- <h5> tag  #-- <h5> tag
         sub start_h5 {  sub start_h5 {
     my ($target,$token) = @_;      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') {
  $currentstring .= '{\large \textbf{';   my $pre;
     }    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
            return $currentstring;   if ($align eq 'center') {
  }      $pre='\begin{center}';
         sub end_h5 {   } elsif ($align eq 'left') {
     my ($target,$token) = @_;      $pre='\rlap{';
             my $currentstring = '';   } elsif ($align eq 'right') {
             if ($target eq 'web') {      $pre=' \hfill \llap{';
        $currentstring .= $token->[2];   }
     } elsif ($target eq 'tex') {   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  $currentstring .= '}}';   if (not defined $TeXsize) {$TeXsize="large";}
     }    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
            return $currentstring;      } 
       return $currentstring;
   }
   
   sub end_h5 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    my $post='\vskip 0 mm ';
    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($align eq 'center') {
       $post='\end{center}';
    } elsif ($align eq 'left') {
       $post='} \hfill'.'\vskip 0 mm ';
    } elsif ($align eq 'right') {
       $post='}'.'\vskip 0 mm ';
  }   }
    $currentstring .= '}}'.$post;
       } 
       return $currentstring;
   }
   
 #-- <h6> tag  #-- <h6> tag
         sub start_h6 {  sub start_h6 {
     my ($target,$token) = @_;      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') {
  $currentstring .= '{\large \textbf{';   my $pre;
     }    my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
            return $currentstring;   if ($align eq 'center') {
  }      $pre='\begin{center}';
         sub end_h6 {   } elsif ($align eq 'left') {
     my ($target,$token) = @_;      $pre='\rlap{';
             my $currentstring = '';   } elsif ($align eq 'right') {
             if ($target eq 'web') {      $pre=' \hfill \llap{';
        $currentstring .= $token->[2];   }
     } elsif ($target eq 'tex') {   my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0);
  $currentstring .= '}}';   if (not defined $TeXsize) {$TeXsize="large";}
     }    $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 
            return $currentstring;      } 
  }      return $currentstring;
 #--- <cite> tag  }
         sub start_cite {  
     my ($target,$token) = @_;  sub end_h6 {
             my $currentstring = '';      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
             if ($target eq 'web') {      my $currentstring = '';
        $currentstring .= $token->[4];      if ($target eq 'web' || $target eq 'webgrade') {
     } elsif ($target eq 'tex') {   $currentstring .= $token->[2];
  $currentstring .= "\\textit{";      } elsif ($target eq 'tex') {
     }  elsif ($target eq 'latexsource') {   my $post='\vskip 0 mm ';
  $currentstring .= "\\textit{";   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
     }    if ($align eq 'center') {
            return $currentstring;      $post='\end{center}';
  }   } elsif ($align eq 'left') {
         sub end_cite {      $post='} \hfill'.'\vskip 0 mm ';
     my ($target,$token) = @_;   } elsif ($align eq 'right') {
             my $currentstring = '';      $post='}'.'\vskip 0 mm ';
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "}";  
     }  elsif ($target eq 'latexsource') {  
  $currentstring .= "}";  
     }   
            return $currentstring;  
  }  
 #-- <i> tag  
         sub start_i {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '\textit{';  
     }  elsif ($target eq 'latexsource') {  
  $currentstring .= '\textit{';  
     }   
            return $currentstring;  
  }  
         sub end_i {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '}';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '}';  
     }   
            return $currentstring;  
  }  
 #-- <address> tag  
         sub start_address {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "\\textit{";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "\\textit{";  
     }   
            return $currentstring;  
  }  
         sub end_address {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "}";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "}";  
     }  
            return $currentstring;  
  }  
 #-- <dfn> tag  
         sub start_dfn {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "\\textit{";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "\\textit{";  
     }   
            return $currentstring;  
  }  
         sub end_dfn {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "}";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "}";  
     }   
            return $currentstring;  
  }  
 #-- <tt> tag  
         sub start_tt {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '\texttt{';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '\texttt{';  
     }   
            return $currentstring;  
  }  
         sub end_tt {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '}';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '}';  
     }  
            return $currentstring;  
  }  
 #-- <kbd> tag  
         sub start_kbd {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "\\texttt";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "\\texttt{";  
     }   
            return $currentstring;  
  }  
         sub end_kbd {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "}";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "}";  
     }   
            return $currentstring;  
  }  
 #-- <code> tag  
         sub start_code {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '\texttt{';  
     }   
            return $currentstring;  
  }  
         sub end_code {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '}';  
     }   
            return $currentstring;  
  }  
 #-- <em> tag  
         sub start_em {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '\emph{';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '\emph{';  
     }   
            return $currentstring;  
  }  
         sub end_em {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '}';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '}';  
     }    
            return $currentstring;  
  }  
 #-- <q> tag  
         sub start_q {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "\\emph{";  
     }  elsif ($target eq 'latexsource') {  
  $currentstring .= "\\emph{";  
     }  
            return $currentstring;  
  }  
         sub end_q {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
  $currentstring .= "}";  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= "}";  
     }    
            return $currentstring;  
  }  
 #-- <p> tag  
         sub start_p {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
  $currentstring .= '{\par ';  
     } elsif ($target eq 'latexsource') {  
  $currentstring .= '{\par ';  
     }   
            return $currentstring;  
  }  
         sub end_p {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
         $currentstring .= '}';  
             } elsif ($target eq 'latexsource') {  
         $currentstring .= '}';  
             }  
            return $currentstring;  
  }   }
 #-- <br> tag   $currentstring .= '}}'.$post;
         sub start_br {      } 
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  #--- <cite> tag (end tag required)
     } elsif ($target eq 'tex') {  sub start_cite {
  if ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') {      my ($target,$token) = @_;
     $currentstring .= '\vskip 0.2 mm';      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
     } elsif ($target eq 'latexsource') {   $currentstring .= $token->[4];
  $currentstring .= '\\';      } elsif ($target eq 'tex') {
     }    $currentstring .= '\textit{';
            return $currentstring;      }
  }      return $currentstring;
         sub end_br {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  sub end_cite {
             if ($target eq 'web') {      my ($target,$token) = @_;
        $currentstring .= $token->[2];      my $currentstring = '';
     }      if ($target eq 'web' || $target eq 'webgrade') {
            return $currentstring;   $currentstring .= $token->[2];
  }      } elsif ($target eq 'tex') {
 #-- <big> tag   $currentstring .= '}';
         sub start_big {      }
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  #-- <i> tag (end tag required)
     } elsif ($target eq 'tex') {  sub start_i {
  $currentstring .= '\large{';      my ($target,$token) = @_;
     } elsif ($target eq 'latexsource') {      my $currentstring = '';
  $currentstring .= '{\Large ';      if ($target eq 'web' || $target eq 'webgrade') {
     }     $currentstring .= $token->[4];
            return $currentstring;      } elsif ($target eq 'tex') {
  }   $currentstring .= '\textit{';
         sub end_big {      }
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  sub end_i {
     } elsif ($target eq 'tex') {      my ($target,$token) = @_;
         $currentstring .= '}';      my $currentstring = '';
             } elsif ($target eq 'latexsource') {      if ($target eq 'web' || $target eq 'webgrade') {
         $currentstring .= '}';   $currentstring .= $token->[2];
             }      } elsif ($target eq 'tex') {
            return $currentstring;   $currentstring .= '}';
       } 
       return $currentstring;
   }
   
   #-- <address> tag (end tag required)
   sub start_address {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\textit{';
       }
       return $currentstring;
   }
   
   sub end_address {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <dfn> tag (end tag required)
   sub start_dfn {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\textit{';
       } 
       return $currentstring;
   }
   
   sub end_dfn {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <tt> tag (end tag required)
   sub start_tt {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\texttt{';
       }
       return $currentstring;
   }
   
   sub end_tt {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <kbd> tag (end tag required)
   sub start_kbd {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\texttt{';
       }
       return $currentstring;
   }
   
   sub end_kbd {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <code> tag (end tag required)
   sub start_code {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\texttt{';
       } 
       return $currentstring;
   }
   
   sub end_code {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       } 
       return $currentstring;
   }
   
   #-- <em> tag (end tag required)
   sub start_em {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\emph{';
       }
       return $currentstring;
   }
   
   sub end_em {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       } 
       return $currentstring;
   }
   
   #-- <q> tag (end tag required)
   sub start_q {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\emph{';
       }
       return $currentstring;
   }
   
   sub end_q {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       } 
       return $currentstring;
   }
   
   #  <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 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= &end_p(); # close off prior para if in progress.
    $currentstring .= $token->[4];
    if (! ($currentstring =~ /\//)) {
       $closing_string = '</p>'; # Deal correctly with <p /> e.g.
  }   }
 #-- <small> tag      } elsif ($target eq 'tex' && !$para_disabled) {
         sub start_small {  
     my ($target,$token) = @_;   $currentstring .= &end_p(); # close off prior para if in progress.
             my $currentstring = '';   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
             if ($target eq 'web') {   if (!defined $align) {
        $currentstring .= $token->[4];            # check inline CSS
     } elsif ($target eq 'tex') {            $align = &get_css_property('text-align',$parstack,$safeeval);
  $currentstring .= '{\footnotesize ';          }
     } elsif ($target eq 'latexsource') {   if ($align eq 'center') {
  $currentstring .= '{\footnotesize ';      $currentstring .='\begin{center}\par ';
     }       $closing_string = '\end{center}';
            return $currentstring;      if (&is_inside_of($tagstack, "table")) {
  }   $currentstring = &center_correction().$currentstring;
         sub end_small {      }
     my ($target,$token) = @_;   } elsif ($align eq 'right') {
             my $currentstring = '';      $currentstring.="\n".'\begin{flushright}';
             if ($target eq 'web') {  #    $currentstring.='\makebox['.$env{'form.textwidth'}.']{\hfill\llap{';
        $currentstring .= $token->[2];      $closing_string= '\end{flushright}'."\n";
     } elsif ($target eq 'tex') {   } elsif ($align eq 'left') {
         $currentstring .= '}';      $currentstring.= "\n".'\begin{flushleft}';
             } elsif ($target eq 'latexsource') {  #    $currentstring.='\noindent\makebox['.$env{'form.textwidth'}.']{{';
         $currentstring .= '}';      $closing_string = '\end{flushleft}'."\n";
             }   } else {
            return $currentstring;              $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;
   }
   #
   #  End paragraph processing just requires that we output the
   #  closing string that was saved and blank it.
   sub end_p {
       #  Note only 'tex' mode uses disable_para and enable_para
       #  so we don't need to know the target in the check below:
   
       if (!$para_disabled) {
    my $current_string = $closing_string;
    $closing_string = ''; # Not in a para anymore.
    return $current_string;
       } else {
    return '';
       }
   
   }
   }
   #-- <br> tag (end tag forbidden)
   sub start_br {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    my @tempo=@$tagstack;
    my $signal=0;
    #  Not going to factor this to is_inside_of since that would require
           #  multiple stack traversals.
    #
    for (my $i=$#tempo;$i>=0;$i--) {
       if (($tempo[$i] eq 'b') || ($tempo[$i] eq 'strong') ||
                   ($tempo[$i] eq 'ol') || ($tempo[$i] eq 'ul'))  {
    $signal=1;
       }
       if (($tempo[$i] eq 'td') || ($tempo[$i] eq 'th')) {
    $signal = 1;
       }
  }   }
 #-- <basefont> tag   if ($signal != 1) {
       sub start_basefont {      $currentstring .= '\strut \\\\ \strut ';
  my ($target,$token) = @_;  
  my $currentstring = '';  
  if ($target eq 'web') {  
   $currentstring = $token->[4];       
  }   
  return $currentstring;  
       }  
       sub end_basefont {  
  my ($target,$token) = @_;  
  my $currentstring = '';  
  if ($target eq 'web') {  
   $currentstring = $token->[4];       
  }   
  return $currentstring;  
       }  
 #-- <font> tag  
          sub start_font {  
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
       my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);  
       if ($face=~/symbol/i) {$Apache::lonxml::prevent_entity_encode++;}  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_font {  
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
       my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);  
       if ($face=~/symbol/i) {$Apache::lonxml::prevent_entity_encode--;}  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }   
 #-- <strike> tag  
         sub start_strike {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  
     } elsif ($target eq 'tex') {  
        &Apache::lonxml::startredirection();  
     }   
            return $currentstring;  
  }  
         sub end_strike {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
        $currentstring=&Apache::lonxml::endredirection();  
        $currentstring=~s/(\S)(\s+)(\S)/$1}$2\\underline{$3/g;  
        $currentstring=~s/^\s*(\S)/\\underline{$1/;  
        $currentstring=~s/(\S)\s*$/$1}/;         
             }  
            return $currentstring;  
  }   }
 #-- <s> tag      
         sub start_s {      }
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
        $currentstring .= $token->[4];  sub end_br {
     } elsif ($target eq 'tex') {      my ($target,$token) = @_;
        &Apache::lonxml::startredirection();      my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
            return $currentstring;   $currentstring .= $token->[2];
  }      }
         sub end_s {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <big> tag (end tag required)
        $currentstring .= $token->[2];  sub start_big {
     } elsif ($target eq 'tex') {      my ($target,$token) = @_;
        $currentstring=&Apache::lonxml::endredirection();      my $currentstring = '';
        $currentstring=~s/(\S)(\s+)(\S)/$1}$2\\underline{$3/g;      if ($target eq 'web' || $target eq 'webgrade') {
        $currentstring=~s/^\s*(\S)/\\underline{$1/;   $currentstring .= $token->[4];
        $currentstring=~s/(\S)\s*$/$1}/;      } elsif ($target eq 'tex') {
             }   $currentstring .= '{\large ';
            return $currentstring;      } 
       return $currentstring;
   }
   
   sub end_big {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <small> tag (end tag required)
   sub start_small {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '{\footnotesize ';
       }
       return $currentstring;
   }
   
   sub end_small {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}';
       }
       return $currentstring;
   }
   
   #-- <basefont> tag (end tag forbidden)
   sub start_basefont {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
    if (defined $basesize) {
       $currentstring = '{\\'.$basesize.' ';
  }   }
 #-- <sub> tag      }
         sub start_sub {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_basefont {
        $currentstring .= $token->[4];      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     } elsif ($target eq 'tex') {      my $currentstring = '';
  $currentstring .= "\$_{ ";      if ($target eq 'web' || $target eq 'webgrade') {
     }    $currentstring = $token->[4];     
            return $currentstring;      } elsif ($target eq 'tex') {
  }   my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
         sub end_sub {   if (defined $basesize) {
     my ($target,$token) = @_;      $currentstring = '}';
             my $currentstring = '';  
             if ($target eq 'web') {  
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
         $currentstring .= " }\$";  
             }  
            return $currentstring;  
  }   }
 #-- <sup> tag      }
         sub start_sup {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <font> tag (end tag required)
        $currentstring .= $token->[4];  sub start_font {
     } elsif ($target eq 'tex') {      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
  $currentstring .= "\$^{ ";      my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
            return $currentstring;   my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);
  }   $currentstring = $token->[4];     
         sub end_sup {      }  elsif ($target eq 'tex') {
     my ($target,$token) = @_;   my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
             my $currentstring = '';   if (defined $fontsize) {
             if ($target eq 'web') {      $currentstring = '{\\'.$fontsize.' ';
        $currentstring .= $token->[2];  
     } elsif ($target eq 'tex') {  
         $currentstring .= " }\$";  
             }  
            return $currentstring;  
  }   }
 #-- <hr> tag      }
         sub start_hr {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_font {
        $currentstring .= $token->[4];      my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     } elsif ($target eq 'tex') {      my $currentstring = '';
  $currentstring .= '\vskip 0 mm \noindent\makebox[\textwidth/2 ][b]{\hrulefill}\vskip 0 mm ';      if ($target eq 'web' || $target eq 'webgrade') {
     }    $currentstring = $token->[2];    
            return $currentstring;      }  elsif ($target eq 'tex') {
  }   my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
         sub end_hr {   if (defined $fontsize) {
     my ($target,$token) = @_;      $currentstring = '}';
             my $currentstring = '';   }
             if ($target eq 'web') {      }
        $currentstring .= $token->[2];      return $currentstring;
     } elsif ($target eq 'tex') {  }
     }    
            return $currentstring;  #-- <strike> tag (end tag required)
  }  sub start_strike {
 #-- <div> tag      my ($target,$token) = @_;
         sub start_div {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring .= $token->[4];
             if ($target eq 'web') {      } elsif ($target eq 'tex') {
        $currentstring .= $token->[4];   &Apache::lonxml::startredirection();
     }       } 
            return $currentstring;      return $currentstring;
  }  }
         sub end_div {  
     my ($target,$token) = @_;  sub end_strike {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
        $currentstring .= $token->[2];      if ($target eq 'web' || $target eq 'webgrade') {
     }    $currentstring .= $token->[2];
            return $currentstring;      } elsif ($target eq 'tex') {
  }   $currentstring=&Apache::lonxml::endredirection();
 #-- <a> tag   $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g; 
         sub start_a {   $currentstring=~s/^\s*(\S)/\\underline\{$1/; 
     my ($target,$token) = @_;   $currentstring=~s/(\S)\s*$/$1\}/;
             my $currentstring = '';      }
             if ($target eq 'web') {      return $currentstring;
        $currentstring .= $token->[4];  }
     } elsif ($target eq 'tex') {  
     }  #-- <s> tag (end tag required)
            return $currentstring;  sub start_s {
  }      my ($target,$token) = @_;
         sub end_a {      my $currentstring = '';
     my ($target,$token,$tagstack,$stackref) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring .= $token->[4];
             if ($target eq 'web') {      } elsif ($target eq 'tex') {
        $currentstring .= $token->[2];   &Apache::lonxml::startredirection();
     } elsif ($target eq 'tex') {      } 
                 my  $tempor_var = $stackref->[$#$stackref];      return $currentstring;
  if (index($tempor_var,'name') != -1 ) {  }
     $tempor_var =~ s/name=([^,]*),/$1/g;  
         } elsif (index($tempor_var,'href') != -1 ) {  sub end_s {
     $tempor_var =~ s/href=([^,]*),/$1/g;      my ($target,$token) = @_;
         $currentstring .= " \\ref{$tempor_var}";      my $currentstring = '';
         }      if ($target eq 'web' || $target eq 'webgrade') {
             }   $currentstring .= $token->[2];
            return $currentstring;      } elsif ($target eq 'tex') {
    $currentstring=&Apache::lonxml::endredirection();
    $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g;
    $currentstring=~s/^\s*(\S)/\\underline\{$1/;
    $currentstring=~s/(\S)\s*$/$1\}/;
       }
       return $currentstring;
   }
   
   #-- <sub> tag (end tag required)
   sub start_sub {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\raisebox{-\smallskipamount}{\scriptsize{';
       } 
       return $currentstring;
   }
   
   sub end_sub {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}}';
       }
       return $currentstring;
   }
   
   #-- <sup> tag (end tag required)
   sub start_sup {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\raisebox{\smallskipamount}{\scriptsize{';
       } 
       return $currentstring;
   }
   
   sub end_sup {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '}}';
       }
       return $currentstring;
   }
   
   #-- <hr> tag (end tag forbidden)
   sub start_hr {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # End enclosing para.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } 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);
    if (defined $LaTeXwidth) {
       if ($LaTeXwidth=~/^%/) {
    substr($LaTeXwidth,0,1)='';
    $LaTeXwidth=($LaTeXwidth/100).'\textwidth';
       }
    } else {
       $LaTeXwidth ='0.9\textwidth';
  }   }
 #-- <li> tag   my ($pre,$post);
         sub start_li {   my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
     my ($target,$token,$tagstack,$stackref) = @_;   if (($align eq 'center') || (not defined $align)) {
             my $currentstring = '';      $pre=''; $post='';
             if ($target eq 'web') {   } elsif ($align eq 'left') {
               $currentstring = $token->[4];           $pre='\rlap{'; $post='} \hfill';
     } elsif ($target eq 'tex') {   } elsif ($align eq 'right') {
                 my  $tempor_var = $stackref->[$#$stackref];      $pre=' \hfill \llap{'; $post='}';
                 if (index($tempor_var,'circle') != -1 ) {   }
           $currentstring .= " \\item[o] ";   $currentstring .= ' \vskip 0 mm \noindent\makebox['.$LaTeXwidth.']{'.$pre.'\makebox['.
         } elsif (index($tempor_var,'square') != -1 ) {                                      $LaTeXwidth.'][b]{\hrulefill}'.$post.'}\vskip 0 mm ';
                $currentstring .= " \\item[$\Box$] ";   # Turn stuff back on that we can't be inside of.
         } elsif ($tempor_var ne '') {   
        $_ = $tempor_var;   if ($restart_sub) {
                        m/my\s*([^=]*)=/;      $currentstring .= &start_sub($target, $token, $tagstack,
        $currentstring .= " \\item[$1] ";   $parstack, $parser, $safeeval);
  } else {   }
     $currentstring .= " \\item ";   if ($restart_sup) {
         }        $currentstring .= &start_sup($target, $token, $tagstack,
     }    $parstack, $parser, $safeeval);
    return $currentstring;   }
  }      } 
         sub end_li {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_hr {
               $currentstring = $token->[2];           my ($target,$token) = @_;
     }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring .= $token->[2];
 #-- <u> tag      }
         sub start_u {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <div> tag (end tag required)
        $currentstring .= $token->[4];  {
     } elsif ($target eq 'tex') {  
        &Apache::lonxml::startredirection();  #  Since div can be nested, the stack below is used
     }   #  in 'tex' mode to store the ending strings
            return $currentstring;  #  for the div stack.
  }  
         sub end_u {      my @div_end_stack;
     my ($target,$token) = @_;  
             my $currentstring = '';  sub start_div {
             if ($target eq 'web') {      my ($target,$token, $tagstack, $parstack, $parser, $safeeval) = @_;
        $currentstring .= $token->[2];      my $currentstring = &end_p(); # Close enclosing para.
     } elsif ($target eq 'tex') {      if ($target eq 'web' || $target eq 'webgrade') {
        $currentstring=&Apache::lonxml::endredirection();   $currentstring .= $token->[4];
        $currentstring=~s/(\S)(\s+)(\S)/$1}$2\\underline{$3/g;      } 
        $currentstring=~s/^\s*(\S)/\\underline{$1/;      if ($target eq 'tex') {
        $currentstring=~s/(\S)\s*$/$1}/;   # 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;
   }
   
   sub end_div {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       }
       if ($target eq 'tex') {
    my $endstring = pop @div_end_stack;
    $currentstring .= $endstring;
       }
       return $currentstring;
   }
   }
   
   #-- <a> tag (end tag required)
   sub start_a {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
       undef,1);
    $currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href});
           if ($href =~ /\S/) {
               if ($href !~ m{^https?://}) {
                   my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
                   my $linkurl;
                   if ($href =~ m{^/uploaded/}) {
                       $linkurl = $href;
                   } elsif ($href =~ m{^[^/]}) {
                       my $path = $url;
                       $path  =~ s{[^/]*$}{};
                       $linkurl = $path.$href;
                   }
                   if ($linkurl =~ m{^/uploaded/}) {
                       if (!&Apache::lonnet::allowed('bre',$linkurl)) {
                           if (&Apache::lonnet::is_on_map($url)) {
                               &Apache::lonxml::extlink($linkurl);
                           } elsif ($env{'request.course.id'}) {
                               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                               if ($linkurl =~ m{^([^/]|/uploaded/$cdom/$cnum/(docs|supplemental)/)}) {
                                   my $cleanhref = &clean_docs_httpref($linkurl,$url,$cdom,$cnum);
                                   if ($cleanhref) {
                                       &Apache::lonxml::extlink($cleanhref);
                                   }
                               }
                           }
                       }
                   }
             }              }
            return $currentstring;          }
       }
       return $currentstring;
   }
   
   sub end_a {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       }
       if ($target eq 'tex') {
    my $href =
       &Apache::lonxml::get_param('href',$parstack,$safeeval,undef,1);
    my $name =
       &Apache::lonxml::get_param('name',$parstack,$safeeval,undef,1);
           my $uriprint =
               &Apache::lonxml::get_param('uriprint',$parstack,$safeeval,undef,1);
           my $anchorprint =
               &Apache::lonxml::get_param('anchorprint',$parstack,$safeeval,undef,1);
    if (($href =~ /\S/) && ($uriprint=~/^on|uriprint|yes|1$/i)) {
       $href =~ s/([^\\])%/$1\\\%/g;
       # Substitute special symbols... and allow line breaks at each /
       #
       $href = &Apache::lonxml::latex_special_symbols($href);
       $href =~ s/\//\/\\-/g;              # Map / to /\- to allow hyphenation.
       $currentstring .= ' ({\tt URI:'.$href.'})';
    } elsif (($name =~ /\S/) && ($anchorprint=~/^on|anchorprint|yes|1$/i)) {
       $currentstring .= ' ({\tt Anchor:'.&Apache::lonxml::latex_special_symbols($name).'})';
    } else {
       $currentstring.='';
    }
       }
       return $currentstring;
   }
   
   #-- <li> tag (end tag optional)
   sub start_li {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
    my $value=&Apache::lonxml::get_param('value',$parstack,$safeeval,undef,0);
    #FIXME need to support types i and I 
    if ($type=~/disc/) {
       $currentstring .= ' \item[$\bullet$] ';
    } elsif ($type=~/circle/) {
       $currentstring .= ' \item[$\circ$] ';
    } elsif ($type=~/square/) {
       $currentstring .= ' \item[$\diamond$] ';
    } elsif ($type eq '1') {
       $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 {
       $currentstring .= ' \item ';
    }  
    $Apache::londefdef::list_index++;
       }
       return $currentstring;
   }
   
   sub end_li {
       my ($target,$token) = @_;
       my $currentstring = &end_p(); # In case there's a <p> in the <li>
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];     
       } 
       return $currentstring;
   }
   
   #-- <u> tag (end tag required)
   sub start_u {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    &Apache::lonxml::startredirection();
       } 
       return $currentstring;
   }
   
   sub end_u {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring=&Apache::lonxml::endredirection();
    $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g;
    $currentstring=~s/^\s*(\S)/\\underline\{$1/;
    $currentstring=~s/(\S)\s*$/$1\}/;
       }
       return $currentstring;
   }
   
   #-- <ul> tag (end tag required)
   sub start_ul {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # Close off enclosing list.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];     
       } elsif ($target eq 'tex') {
    my $TeXtype=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
    $Apache::londefdef::list_index=0;
    if ($TeXtype eq 'disc') {
       $currentstring .= '\renewcommand{\labelitemi}{$\bullet$}'.
                                 '\renewcommand{\labelitemii}{$\bullet$}'. 
                                 '\renewcommand{\labelitemiii}{$\bullet$}'.
                                 '\renewcommand{\labelitemiv}{$\bullet$}';
    } elsif ($TeXtype eq 'circle') {
       $currentstring .= '\renewcommand{\labelitemi}{$\circ$}'.
                                 '\renewcommand{\labelitemii}{$\circ$}'. 
                                 '\renewcommand{\labelitemiii}{$\circ$}'.
                                 '\renewcommand{\labelitemiv}{$\circ$}';
    } elsif ($TeXtype eq 'square') {
       $currentstring .= '\renewcommand{\labelitemi}{$\diamond$}'.
                                 '\renewcommand{\labelitemii}{$\diamond$}'. 
                                 '\renewcommand{\labelitemiii}{$\diamond$}'.
                                 '\renewcommand{\labelitemiv}{$\diamond$}';
    }
    $currentstring .= '\strut \begin{itemize}';  
       } 
       return $currentstring;
   }
   
   sub end_ul {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
    $currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}'.
                                  '\renewcommand{\labelitemii}{$\bullet$}'. 
                                  '\renewcommand{\labelitemiii}{$\bullet$}'.
                                  '\renewcommand{\labelitemiv}{$\bullet$}\strut ';  
       } 
       return $currentstring;
   }
   
   #-- <menu> tag (end tag required)
   sub start_menu {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    $currentstring = " \\begin{itemize} ";  
       } 
       return $currentstring;
   }
   
   sub end_menu {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
    $currentstring = " \\end{itemize}";  
       } 
       return $currentstring;
   }
   
   #-- <dir> tag (end tag required)
   sub start_dir {
       my ($target,$token) = @_;
       my $currentstring = &end_p(); # In case there's a <p> prior to the list.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];     
       } elsif ($target eq 'tex') {
    $currentstring .= " \\begin{itemize} ";  
       } 
       return $currentstring;
   }
   
   sub end_dir {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
    $currentstring = " \\end{itemize}";  
       } 
       return $currentstring;
   }
   
   #-- <ol> tag (end tag required)
   sub start_ol {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # In case there's a <p> prior to the list.
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];     
       } elsif ($target eq 'tex') {
    $Apache::londefdef::list_index=0;
    my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0);
    if ($type eq '1') {
       $currentstring .= '\renewcommand{\labelenumi}{\arabic{enumi}.}'.
                                 '\renewcommand{\labelenumii}{\arabic{enumii}.}'. 
                                 '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
                                 '\renewcommand{\labelenumiv}{\arabic{enumiv}.}';
    } elsif ($type eq 'A') {
       $currentstring .= '\renewcommand{\labelenumi}{\Alph{enumi}.}'.
                                 '\renewcommand{\labelenumii}{\Alph{enumii}.}'. 
                                 '\renewcommand{\labelenumiii}{\Alph{enumiii}.}'.
                                 '\renewcommand{\labelenumiv}{\Alph{enumiv}.}';
    } elsif ($type eq 'a') {
       $currentstring .= '\renewcommand{\labelenumi}{\alph{enumi}.}'.
                                 '\renewcommand{\labelenumii}{\alph{enumii}.}'.
                                 '\renewcommand{\labelenumiii}{\alph{enumiii}.}'.
                                 '\renewcommand{\labelenumiv}{\alph{enumiv}.}';
    } elsif ($type eq 'i') {
       $currentstring .= '\renewcommand{\labelenumi}{\roman{enumi}.}'.
                                 '\renewcommand{\labelenumii}{\roman{enumii}.}'.
                                 '\renewcommand{\labelenumiii}{\roman{enumiii}.}'.
                                 '\renewcommand{\labelenumiv}{\roman{enumiv}.}';
    } elsif ($type eq 'I') {
       $currentstring .= '\renewcommand{\labelenumi}{\Roman{enumi}.}'.
                                 '\renewcommand{\labelenumii}{\Roman{enumii}.}'.
                                 '\renewcommand{\labelenumiii}{\Roman{enumiii}.}'.
                                 '\renewcommand{\labelenumiv}{\Roman{enumiv}.}';
  }   }
 #-- <ul> tag   $currentstring .= '\strut \begin{enumerate}';  
         sub start_ul {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[4];       sub end_ol {
     } elsif ($target eq 'tex') {      my ($target,$token) = @_;
               $currentstring = '\begin{itemize}';        my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[2];     
  }      } elsif ($target eq 'tex') {
         sub end_ul {   $currentstring = '\end{enumerate}\renewcommand{\labelenumi}{\arabic{enumi}.}'.
     my ($target,$token) = @_;                                          '\renewcommand{\labelenumii}{\arabic{enumii}.}'.
             my $currentstring = '';                                          '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
             if ($target eq 'web') {                                          '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut ';  
               $currentstring = $token->[2];           } 
     } elsif ($target eq 'tex') {      return $currentstring;
               $currentstring = '\end{itemize}';    }
     }   
    return $currentstring;  #-- <dl> tag (end tag required)
  }  sub start_dl {
 #-- <menu> tag      my ($target,$token) = @_;
         sub start_menu {      my $currentstring = &end_p(); # In case there's a <p> unclosed prior to the list.
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring .= $token->[4];     
             if ($target eq 'web') {      } elsif ($target eq 'tex') {
               $currentstring = $token->[4];        $currentstring .= '\begin{description}';
     } elsif ($target eq 'tex') {   $Apache::londefdef::DL++;
               $currentstring = " \\begin{itemize} ";     push(@Apache::londefdef::description,[]);
     }    $Apache::londefdef::DD[$Apache::londefdef::DL]=0;
    return $currentstring;   $Apache::londefdef::DT[$Apache::londefdef::DL]=0;
  }   $Apache::londefdef::seenDT[$Apache::londefdef::DL]=0;
         sub end_menu {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[2];       sub end_dl {
     } elsif ($target eq 'tex') {      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
               $currentstring = " \\end{itemize}";        my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[2];     
  }      } elsif ($target eq 'tex') {
 #-- <dir> tag   if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
         sub start_dir {   if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
     my ($target,$token) = @_;   foreach my $element (@{$Apache::londefdef::description[-1]}) {
             my $currentstring = '';      $currentstring.=' '.$element.' ';
             if ($target eq 'web') {   }
               $currentstring = $token->[4];        pop(@Apache::londefdef::description);
     } elsif ($target eq 'tex') {   $currentstring.='\end{description}';  
               $currentstring = " \\begin{itemize} ";     delete($Apache::londefdef::DD[$Apache::londefdef::DL]);
     }    delete($Apache::londefdef::DT[$Apache::londefdef::DL]);
    return $currentstring;   delete($Apache::londefdef::seenDT[$Apache::londefdef::DL]);
  }   $Apache::londefdef::DL--;
         sub end_dir {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[2];       #-- <dt> tag (end tag optional)
     } elsif ($target eq 'tex') {  sub start_dt {
               $currentstring = " \\end{itemize}";        my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     }       my $currentstring='';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
 #-- <ol> tag      } elsif ($target eq 'tex') {
         sub start_ol {   if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
     my ($target,$token) = @_;   if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
             my $currentstring = '';   &Apache::lonxml::startredirection();
             if ($target eq 'web') {   $Apache::londefdef::DT[-1]++;
               $currentstring = $token->[4];        $Apache::londefdef::seenDT[-1]=1;
     } elsif ($target eq 'tex') {      } 
               $currentstring = '\begin{enumerate}';        return $currentstring;
     }   }
    return $currentstring;  
  }  sub end_dt {
         sub end_ol {      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   $currentstring = $token->[2];    
               $currentstring = $token->[2];           } elsif ($target eq 'tex') {
     } elsif ($target eq 'tex') {   if ($Apache::londefdef::DT[-1]) {
               $currentstring = '\end{enumerate}';        my $data=&item_cleanup();
     }       push(@{$Apache::londefdef::description[-1]},'\item['.$data.'] \strut \vskip 0mm');
    return $currentstring;      $Apache::londefdef::DT[-1]--;
  }  
 #-- <dl> tag  
         sub start_dl {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {  
               $currentstring = '\begin{description}';    
     }   
    return $currentstring;  
  }  
         sub end_dl {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];       
     } elsif ($target eq 'tex') {  
               $currentstring = '\end{description}';    
     }   
    return $currentstring;  
  }  
 #-- <dt> tag  
         sub start_dt {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {  
               $currentstring = '\item[';    
     }   
    return $currentstring;  
  }  
         sub end_dt {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             } elsif ($target eq 'tex') {  
               $currentstring = ']';    
     }   
    return $currentstring;  
  }  
 #-- <dd> tag  
         sub start_dd {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     }   
    return $currentstring;  
  }  
         sub end_dd {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];      
             }   
    return $currentstring;  
  }   }
 #-- <table> tag      } 
       return $currentstring;
   }
   
   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 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
    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;
   }
   
   sub end_dd {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       }  elsif ($target eq 'tex') {
    $Apache::londefdef::description[-1]->[-1].=
       &Apache::lonxml::endredirection().' \vskip 0mm ';
    $Apache::londefdef::DD[-1]--;
       }
       return $currentstring;
   }
   
   #-- <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 $currentstring = &end_p();
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];     
       } elsif ($target eq 'tex') {
    &disable_para(); # Can't have paras in a table.
   
    #  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);
    my $cell_border = &Apache::lonxml::get_param('rules', $parstack, $safeeval, undef, 0);
   
    # The only thing that needs any figuring out is the width.. and then only if it is
    # a percent. If not it's assumed to be some valid TeX measurement unit e.g. 3.0cm
    #
   
    my $table = new Apache::lontable();
    if ((defined $border) && ($border > 0)) {
    #    &Apache::lonnet::logthis("Turning on table borders: $border");
       $table->table_border(1);
       if (!defined $cell_border) {
    $table->cell_border(1); # Default for rules is all if rules not defined.
       }
    }
   
    if ((defined $cell_border)) {
       if ($cell_border eq 'all') {
    $table->cell_border(1);
       } elsif ($cell_border eq 'rows') {
    $table->cell_border(2);
       } elsif ($cell_border eq 'cols') {
    $table->cell_border(3);
       } elsif($cell_border eq 'groups') {
    $table->cell_border(4);
       } else {
    $table->cell_border(0);
       }
    }
    if (defined $theme) {
       $table->theme($theme);
    }
    if (defined $align) {
       $table->alignment($align);
    }
   
    # Missing width is most of page width
   
    if (!(defined $width)) {
       $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}';
   
       }
       return $currentstring;
   }
    
   sub end_table {
       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];     
       } elsif ($target eq 'tex') {
   
   
    my $table = pop(@Apache::londefdef::table);
    my $t     = $table->generate();
    # &Apache::lonnet::logthis("Generating string");
    $currentstring = $t->generate_string();
    # &Apache::lonnet::logthis("Generated: $currentstring");
    &enable_para();
   
       }
       return $currentstring;
   }
   
   #-- <tr> tag (end tag optional)
   sub start_tr {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];        $currentstring = $token->[4];     
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  my $aa = {};  
  push @Apache::londefdef::table, $aa;    my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
  $Apache::londefdef::table[-1]{'row_number'} = -1;   $Apache::londefdef::table[-1]->start_row();
  $Apache::londefdef::table[-1]{'output'} = ' \noindent \begin{tabular} ';  
  my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval,undef,1);    if ($align ne '') {
  unless (defined $border) { $border = 0; }      $Apache::londefdef::table[-1]->configure_row({default_halign => $align});
  if ($border) {    }
     $Apache::londefdef::table[-1]{'hinc'} = '\hline ';   
     $Apache::londefdef::table[-1]{'vinc'} = '&';    #---------------------------------------------------------------
     $Apache::londefdef::table[-1]{'vvinc'} = '|';   # Old table code.
    #---------------------------------------------------------------
   
    if (0) {
    $Apache::londefdef::table[-1]{'row_number'}++;
    my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
    if ($alignchar ne '') {
       push @ {$Apache::londefdef::table[-1]{'rows'} },substr($alignchar,0,1);
  } else {   } else {
     $Apache::londefdef::table[-1]{'hinc'} = '';       push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l';
     $Apache::londefdef::table[-1]{'vinc'} = '&';    }
     $Apache::londefdef::table[-1]{'vvinc'} = '';   push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'});
  }   #
  my $width;   #  Need to save the number of table columns to preserve the max # columns.
  foreach my $key (keys(%{$token->[2]})) {   #
     if ($key =~ /^width$/i) {   $Apache::londefdef::table[-1]{'prior_columns'}   = $Apache::londefdef::table[-1]{'counter_columns'};
  $width = &Apache::lonxml::get_param($key,$parstack,$safeeval,undef,1);   $Apache::londefdef::table[-1]{'counter_columns'} = -1;
     }   push @ {$Apache::londefdef::table[-1]{'TeXlen'}}, [];
  }   push @ {$Apache::londefdef::table[-1]{'objectlen'}}, [];
  if (defined($width)) { $Apache::londefdef::table[-1]{'width'}=$width; }   push @ {$Apache::londefdef::table[-1]{'minlen'}}, [];
    push @ {$Apache::londefdef::table[-1]{'maxlen'}}, [];
    push @ {$Apache::londefdef::table[-1]{'content'}}, [];
     }      }
       } 
     return $currentstring;      return $currentstring;
 }  }
         sub end_table {          
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;  sub end_tr {
             my $currentstring = '';      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
             if ($target eq 'web') {      my $currentstring = &end_p(); # Close any pending <p> in the row.
               $currentstring = $token->[2];           if ($target eq 'web' || $target eq 'webgrade') {
     } elsif ($target eq 'tex') {   $currentstring .= $token->[2];     
  my $inmemory = '';      } elsif ($target eq 'tex') {
  my $output = '';  
                 #construct header of the table   # In case the user is missing a </td> or </th> tag:
  my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'};  
  my $in;   if ($Apache::londefdef::TD_redirection) {
  for ($in=0;$in<=$Apache::londefdef::table[-1]{'counter_columns'};$in++) {      &end_td_tex($parstack,$parser,$safeeval);    
     $header_of_table .= $Apache::londefdef::table[-1]{'columns'}[$in].$Apache::londefdef::table[-1]{'vvinc'};   }
  }   $Apache::londefdef::table[-1]->end_row();
  $header_of_table .= '}';  
                 #fill the table   #-----------------------------------------------
  for ($in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {   # Old table code
     $output .=  $Apache::londefdef::table[-1]{'rowdata'}[$in];   #-----------------------------------------------
     chop $output;  
     $output .= ' \\\\ ';   if (0) {
  }   if ($Apache::londefdef::TD_redirection) {
                 #define the length of the table cells      &end_td_tex($parstack,$parser,$safeeval);    
  my @lengthforoutput = split(/,/,$Apache::londefdef::table[-1]{'lengthrow'}[0]);   }
  my $how_many_columns = $#lengthforoutput + 1; #total number of columns in the table    # Counter columns must be the maximum number of columns seen
  my $filled_columns = 0; #number of columns with information about width   # in the table so far so:
  my $available_space = ' ';   if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) {
  foreach my $tempo_length (@{ $Apache::londefdef::table[-1]{'lengthrow'} }) {      $Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'};
     my @length = split(/,/,$tempo_length);   }
     for (my $ico=0;$ico<=$#lengthforoutput;$ico++) {      }
  $lengthforoutput[$ico] =~ m/(\d*\.?\d*)\s*(\w+)/;  
  my $old_value = $1;  
  my $old_unit = $2;       }
  if ($old_unit eq 'cm') {       return $currentstring;
     $old_value = $old_value * 10;  }
  } elsif ($old_unit eq 'in') {   
     $old_value = $old_value * 25.4;  #-- <td> tag (end tag optional)
  } elsif ($old_unit eq 'pt') {  sub start_td {
     $old_value = $old_value * 25.4/72.27;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
  } elsif ($old_unit eq 'pc') {      my $currentstring = '';
     $old_value = $old_value * 25.4/6.022;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
  $old_unit = 'mm';      } elsif ($target eq 'tex') {
   $length[$ico] =~ m/(\d*\.?\d*)\s*(\w+)/;   $Apache::londefdef::TD_redirection = 1;
  my $new_value = $1;   &tag_check('tr','td',$tagstack,$parstack,$parser,$safeeval);
  my $new_unit = $2;      } 
  if ($new_unit eq 'cm') {       return $currentstring;
     $new_value = $new_value * 10;  }   
  } elsif ($old_unit eq 'in') {       
     $new_value = $new_value * 25.4;  sub tag_check {
  } elsif ($old_unit eq 'pt') {      my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_;
     $new_value = $new_value * 25.4/72.27;      my @ar=@$parstack; 
  } elsif ($old_unit eq 'pc') {      for (my $i=$#ar-1;$i>=0;$i--) {
     $new_value = $new_value * 25.4/6.022;   if (lc($$tagstack[$i]) eq $good_tag) {
  }      &start_td_tex($parstack,$parser,$safeeval);
  $new_unit = 'mm';      last;
  if ($old_value < $new_value) {   } elsif (lc($$tagstack[$i]) eq $bad_tag) {
     $lengthforoutput[$ico] = $new_value.' mm';      splice @ar, $i+1;
  } else {      &end_td_tex(\@ar,$parser,$safeeval);
     $lengthforoutput[$ico] = $old_value.' mm';      &start_td_tex($parstack,$parser,$safeeval);
  }        last;
    }
       }
       return '';
   }
   
   #
   #  Factor out cell configuration hash generation:
   #
   
   sub cell_config_hash {
       my ($align, $rowspan, $colspan, $width) = @_;
       if ($rowspan ne '') {
           $rowspan =~ s/^\s+|\s+$//g; 
       }
       if ($colspan ne '') {
           $colspan =~ s/^\s+|\s+$//g;
       }
       my %config;
       if ($align ne '') {
    $config{'halign'} = $align;
       }
       if (($colspan =~ /^\d+$/) && ($colspan > 0)) {
    $config{'colspan'} = $colspan;
       }
       if (($rowspan =~ /^\d+$/) && ($rowspan > 0)) {
    $config{'rowspan'} = $rowspan;
       }
       if ($width ne '') {
    $config{'width'} = $width;
       }
       return \%config;
   }
    
   sub start_td_tex {
       my ($parstack,$parser,$safeeval) = @_;
   
       # At this stage, an empty cell is created with the
       # appropriate rowspan/colspan and alignment
       # attributes, but empty of text.  end_td_tex will
       # fetch the contents from the recursive parse and
       # fill the cell with them:
       my $align   = &Apache::lonxml::get_param('align', $parstack, $safeeval);
       my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval);
       my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval);
       my $width   = &Apache::lonxml::get_param('TeXwidth', $parstack, $safeeval);
       my $config = &cell_config_hash($align, $rowspan, $colspan, $width);
   
       my $table = $Apache::londefdef::table[-1];
       $table->add_cell('', $config);
       
   
       #------------------------------------------------
       #  Old table code.
       #------------------------------------------------
   
       if (0) {
   
       my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
       if ($alignchar eq '') {
    $alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
       }
       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;
       }
       }
       &Apache::lonxml::startredirection();
       return '';
   }
   
   sub end_td_tex {
   
       my $text = &Apache::lonxml::endredirection();
       my $table = $Apache::londefdef::table[-1];
       $table->append_cell_text($text);
   
       #-------------------------------------------------
       # Old table code
       #-------------------------------------------------
   
       if (0) {
       my ($parstack,$parser,$safeeval) = @_;
       my $current_row    = $Apache::londefdef::table[-1]{'row_number'};
       my $current_column = $Apache::londefdef::table[-1]{'counter_columns'}; 
       my $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);
       if (defined $TeXwidth) {
    for (my $c = 0; $c < $colspan; $c++) {
       push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
       push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
       push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
    }
       } else {
    if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) {
       my $garbage_data=$data;
       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\]//;
       }
       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 {  
       $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;}
     }      }
  }   }
  for (my $ico=0;$ico<=$#lengthforoutput;$ico++) {      } else {
     if (not $lengthforoutput[$ico]=~m/^\s*0\s*\w*\s*$/) {   $current_length=2.5*&LATEX_length($data);
  $filled_columns++;                      my @words=split(/ /,$data);
  $available_space = $available_space.' - '.$lengthforoutput[$ico];      foreach my $word (@words) {
    my $lengthword=2*&LATEX_length($word);
    if ($min_length<$lengthword) {$min_length=$lengthword;}
     }      }
  }      }
  my $temp_file;      for (my $c = 0; $c < $colspan; $c++) {
  my $filename = "/home/httpd/prtspool/$ENV{'user.name'}_$ENV{'user.domain'}_printout.tbl";   push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
  if (-e $filename) {   push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
     $temp_file = Apache::File->new($filename);    push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length;
     my @tbl_file_content = <$temp_file>;   push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length;
     my ($one,$two,$three) = split(/,/,$tbl_file_content[0]);      }
         $how_many_columns+=$one-1;   }        
         $filled_columns+=$two;      }
     if($three=~/\S/) {$available_space = $available_space.' - '.$three;}      # Substitute all of the tables nested in this cell in their appropriate places.
  } else {  
     $temp_file = Apache::File->new('>>'.$filename);   
  }      my $nested_count = $#{$Apache::londefdef::table[-1]{'include'}}; # This one is constant...
  print $temp_file "$how_many_columns,$filled_columns,$available_space\n";      for (my $in=0; $in<=$nested_count; $in++) {    
  $output =~ s/\\parbox{TOBECHANGEDONNUMBER}{}/\\parbox{1 mm}{}/g;   my $nested = shift @{$Apache::londefdef::table[-1]{'include'}};
  $output =~ s/\\parbox{TOBECHANGEDONNUMBER}/\\parbox{\$SpacePerColumn}/g;   $nested =~ s/\\end\{tabular\}\\strut\\\\/\\end\{tabular\}/;
  my @tagar = @$tagstack;   # $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
  my $signature = 1;   $data =~ s/\\keephidden\{NEW TABLE ENTRY\}/$nested/;
  for (my $ico=0;$ico<$#tagar;$ico++) {  
      if ($tagar[$ico] eq 'table') { $signature = 0; }      }
  }      # Should be be killing off the 'include' elements as they're used up?
  if ($signature) {  
     my $NumberEmptyLength = $how_many_columns - $filled_columns;      push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
     my $SpacePerColumn = '(\textwidth '.$available_space.')/'.$NumberEmptyLength;  
     my $shorthand = ($filled_columns+1)*4;  
     $output =~ s/\$SpacePerColumn/$SpacePerColumn - $shorthand mm/g;  
  }  
  if ($how_many_columns==1) {  #start of block with width correction for one column table      #  the colspan array will indicate how many columns will be spanned by this
   $output=~s/^\s*\\parbox{([^}]*)}/\\parbox{\\textwidth - 1 cm}/;      #  cell..this requires that counter_columns also be adjusted accordingly
  }                            #end of block with width correction for one column table      #  so that the next bunch of text goes in the right cell.  Note that since
  $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$output.$Apache::londefdef::table[-1]{'hinc'}.'\end{tabular}\vskip 0 mm ';      #  counter_columns is incremented in the start_td_tex, we adjust by colspan-1.
  if ($#Apache::londefdef::table > 0) {      #
     $inmemory = $Apache::londefdef::table[-1]{'output'};  
     pop @Apache::londefdef::table;      $Apache::londefdef::table[-1]{'counter_columns'} += $colspan -1;
     $Apache::londefdef::table[-1]{'rowdata'}[$Apache::londefdef::table[-1]{'row_number'}] .= $inmemory      for (my $i = 0; $i < ($colspan -1); $i++) {
  } else {   push @ {$Apache::londefdef::table[-1]{'content'}[-1] },'';
     $currentstring = $Apache::londefdef::table[-1]{'output'};      }
     $currentstring =~ s/\\\\\s+\\\\/\\\\/g;       for (my $r = 0; $r < $rowspan; $r++) {
     pop @Apache::londefdef::table;   $Apache::londefdef::table[-1]{'colspan'}[$current_row+$r][$current_column] = $colspan;
     if (-e $filename) {   # Put empty text in spanned cols.
  unlink $filename;  
       }
   
       }
   
       return '';
   }
   
   sub end_td {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
           $Apache::londefdef::TD_redirection =0;
    &end_td_tex($parstack,$parser,$safeeval);
       }
       return $currentstring;
   }
   
   #-- <th> tag (end tag optional)
   sub start_th {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    $Apache::londefdef::TD_redirection = 1;
    &tagg_check('tr','th',$tagstack,$parstack,$parser,$safeeval);
       } 
       return $currentstring;
   }   
       
   sub tagg_check {
       my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_;
       my @ar=@$parstack; 
       for (my $i=$#ar-1;$i>=0;$i--) {
    if (lc($$tagstack[$i]) eq $good_tag) {
       &start_th_tex($parstack,$parser,$safeeval);
       last;
    } elsif (lc($$tagstack[$i]) eq $bad_tag) {
       splice @ar, $i+1;
       &end_th_tex(\@ar,$parser,$safeeval);
       &start_th_tex($parstack,$parser,$safeeval);
       last;
    }
       }
       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;}
       }
     }      }
    return $currentstring;      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]/;
    }
       #make data bold
       $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;
   }
        
   #-- <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 {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
       my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,
    undef,1);
       if (! $src && 
    ($target eq 'web' || $target eq 'webgrade' || $target eq 'tex')
    ) { 
    my $inside = &Apache::lonxml::get_all_text("/img",$parser,$style);
    return '';
       }
       unless ($src =~ m{^data\:image/gif;base64,}) {
           &Apache::lonxml::extlink($src);
       }
       my $currentstring = '';
       my $scaling = .3;
   
      # Render unto browsers that which are the browser's...
   
       if ($target eq 'web' || $target eq 'webgrade') {
           my $enc = ('yes' eq 
                      lc(&Apache::lonxml::get_param('encrypturl',$parstack,
                         $safeeval)));
           unless ($src =~ m{^data\:image/gif;base64,}) {
               $currentstring.=&Apache::lonenc::encrypt_ref($token,{'src'=>$src},
                               $enc);
           }
   
       # and render unto TeX that which is LaTeX
       } elsif ($target eq 'tex') {
    #
    #  The alignment will require some superstructure to be put around
    #  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';
  }   }
 #-- <tr> tag  
         sub start_tr {   # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src");
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;  
             my $currentstring = '';   #if original bmp/gif/jpg/png/svg file exist do following:
             if ($target eq 'web') {   my $origsrc=$src;
               $currentstring = $token->[4];        my ($path,$file) = &get_eps_image($src);
     } elsif ($target eq 'tex') {   # &Apache::lonnet::logthis("Image source: $src result: $path $file");
  $Apache::londefdef::table[-1]{'row_number'}++;   $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);
  my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);   &Apache::lonxml::debug("path = $path file = $file src = $src");
  if ($alignchar ne '') {   if (-e $src) {
     push @ {$Apache::londefdef::table[-1]{'rows'} }, $alignchar;      &Apache::lonxml::debug("$src exists");
  } else {      my ($height_param,$width_param)=
     push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l';   &image_size($origsrc,0.3,$parstack,$safeeval);
       my $size;
       if ($width_param)  { $size.='width='.$width_param.' mm,'; }
       if ($height_param) { $size.='height='.$height_param.' mm]'; }
       # Default size if not able to extract that (e.g. eps image).
       
       # &Apache::lonnet::logthis("Size = $size");
       
       $size='['.$size;
       $size=~s/,$/]/; 
       $currentstring .= '\graphicspath{{'.$path.'}}'
    .'\includegraphics'.$size.'{'.$file.'} ';
       my $closure;
       ($currentstring, $closure) = &align_latex_image($align, 
       $latex_rendering, 
       $currentstring, 
       $width_param, 
       $height_param);
       $currentstring .= $closure;
   
    } else {
       &Apache::lonxml::debug("$src does not exist");
       #original image file doesn't exist so check the alt attribute
       my $alt = 
    &Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1);
       unless ($alt) {
    $alt=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src);
       }
   
       if ($alt) { $currentstring .= ' '.$alt.' '; }
    }
   
    # 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_or_search('src',undef,'alt',$only,undef,1).
                            '<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);
           my $alt=    &Apache::lonxml::get_param('alt',$parstack,$safeeval);
           my $enc=    &Apache::lonxml::get_param('encrypturl',$parstack,$safeeval);
    
    $currentstring .=&Apache::edit::select_arg('Encrypt URL:','encrypturl',
      ['no','yes'], $token, 2);
           if (($alt=~/\S/) && (lc($enc) eq 'yes')) {
              $currentstring.='<br /><span class="LC_warning">'.&mt('Warning: the description "[_1]" will be available, even for encrypted URL',$alt).'</span><br />';
           }
    $currentstring .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
    my $src=    &Apache::lonxml::get_param('src',$parstack,$safeeval);
    my $width=  &Apache::lonxml::get_param('width',$parstack,$safeeval);
    my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval);
           my $element = &Apache::edit::get_element('src'); 
           my $text;
           if ($token->[2]{'src'}=~/\$/) {
              $text = &mt('Variable image source');
           } elsif ($token->[2]{'src'}=~/\S/) {
      $currentstring .= '<img src="'.$src.'" alt="'.$alt.'" ';
      if ($width) { $currentstring.=' width="'.$width.'" '; }
      if ($height) { $currentstring.=' height="'.$height.'" '; }
      $currentstring .= ' id="previewimg_'.$element.'" />';
           } else {
              $text = &mt("No image source specified");
           }
           $currentstring .= ' <span id="showimg_'.$element.'">'.$text.'</span>';
       } 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;
  }   }
  push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'});   if ($oheight == $nheight || (!$nwidth && !$nheight)) {
  $Apache::londefdef::table[-1]{'counter_columns'} = -1;      $token->[2]{'height'}=$iheight;$ctag=1;
  $Apache::londefdef::table[-1]{'length'} = '';   
     }   
    return $currentstring;  
  }          
         sub end_tr {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
  $currentstring = $token->[2];       
     } elsif ($target eq 'tex') {  
  push @{ $Apache::londefdef::table[-1]{'lengthrow'} },$Apache::londefdef::table[-1]{'length'};  
   
     }  
    return $currentstring;  
  }  
 #-- <td> tag  
         sub start_td {  
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {  
  my $what_to_push = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);  
  if ($what_to_push eq '') {  
     $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;  
  }          
         sub end_td {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             my $tempolen = '';  
             if ($target eq 'web') {  
  $currentstring = $token->[2];       
     } elsif ($target eq 'tex') {  
  my $current_row = $Apache::londefdef::table[-1]{'row_number'};  
  my $data=&Apache::lonxml::endredirection();  
  if ($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt))/) {                   
                     $Apache::londefdef::table[-1]{'length'} .= $1.',';  
     $tempolen = $1;           
  } else {  
     if (length($data)<5) {  
  $Apache::londefdef::table[-1]{'length'} .= '0 mm,';  
  $tempolen = '6 mm';  
     } else {  
  $Apache::londefdef::table[-1]{'length'} .= '0 mm,';  
  $tempolen = 'TOBECHANGEDONNUMBER';  
     }  
                 }                                          
  @{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{'.$tempolen.'}{'.$data.'} '.$Apache::londefdef::table[-1]{'vinc'};  
     }      }
    return $currentstring;  
  }   }
 #-- <th> tag   my ($cwidth,$cheight)=($token->[2]{'width'},$token->[2]{'height'});
         sub start_th {   # if we don't have a width or height
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;   if ($iwidth && $cwidth && !$cheight) {
             my $currentstring = '';      $token->[2]{'height'}=int(($cwidth/$iwidth)*$iheight);$ctag=1;
             if ($target eq 'web') {  
               $currentstring = $token->[4];       
     } elsif ($target eq 'tex') {  
  my $what_to_push = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);  
  if ($what_to_push eq '') {  
     $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;  
  }          
         sub end_th {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
  $currentstring = $token->[2];       
     } elsif ($target eq 'tex') {  
  my $current_row = $Apache::londefdef::table[-1]{'row_number'};  
  my $data=&Apache::lonxml::endredirection();  
  if ($data=~m/width\s*=\s*(\d+\.*\d*\s*(mm|cm))/) {                   
                     $Apache::londefdef::table[-1]{'length'} .= $1.',';               
  } else {  
     $Apache::londefdef::table[-1]{'length'} .= '0 mm,';   
                 }                                                             
  @{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{'.$1.'}{\textbf{'.$data.'}} '.$Apache::londefdef::table[-1]{'vinc'};  
     }  
    return $currentstring;  
  }  
 #-- <img> tag  
         sub start_img {  
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;  
     my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,  
  undef,1);  
             $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$src;  
             my $currentstring = '';  
     my $width_param = '';  
     my $height_param = '';  
     my $scaling = .3;  
   
     if ($target eq 'web') {  
               $currentstring = $token->[4];  
     } elsif ($target eq 'tex') {  
       &image_replication($src);  
       $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);  
               #if original gif/jpg/png file exist do following:  
               if (-e $src) {            
                   #defines the default size of image  
   my $image = Image::Magick->new;  
   my $current_figure = $image->Read($src);  
   $width_param = $image->Get('width') * $scaling;;  
   $height_param = $image->Get('height') * $scaling;;  
   undef $image;  
   #do we have any specified size of the picture?  
   my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval);  
   my $TeXheight = &Apache::lonxml::get_param('TeXheight',$parstack,$safeeval);  
   my $width = &Apache::lonxml::get_param('width',$parstack,$safeeval,  
                                                          undef,1);  
   if ($TeXwidth ne '') {    
       if ($TeXwidth=~/(\d+)\s*\%/) {  
   $width_param = $1*$ENV{'form.textwidth'}/100;  
       } else {   
   $width_param = $TeXwidth;  
       }  
   } elsif ($TeXheight ne '') {  
   $width_param = $TeXheight/$height_param*$width_param;  
   } elsif ($width ne '') {  
       $width_param = $width*$scaling;        
   }  
   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 {  
   #original image file doesn't exist so check the alt attribute  
   my $alt = &Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1);  
                   if ($alt) {  
       $currentstring .= ' '.$alt.' ';  
   } else {  
                      #<allow> tag will care about replication   
   }  
       }  
     }  
     return $currentstring;  
  }  
         sub end_img {  
     my ($target,$token) = @_;  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[2];  
     } elsif ($target eq 'tex') {  
               $currentstring = '';  
     }  
    return $currentstring;  
  }  
 #-- <applet> tag  
   
         sub start_applet {  
     my ($target,$token) = @_;  
               $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=     
                                         $token->[2]->{'code'};  
               $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=  
                                         $token->[2]->{'archive'};  
             my $currentstring = '';  
             if ($target eq 'web') {  
               $currentstring = $token->[4];  
     } elsif ($target eq 'tex') {  
               $currentstring = " \\begin{figure} ";  
     }   
    return $currentstring;  
  }   }
 sub end_applet {   if ($iheight && $cheight && !$cwidth) {
       $token->[2]{'width'}=int(($cheight/$iheight)*$iwidth);$ctag=1;
    }
    if ($ctag) {$currentstring=&Apache::edit::rebuild_tag($token);}
       }
   
       return $currentstring;
   }
   
   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 = " \\end{figure}";   $currentstring = '';
       }
       return $currentstring;
   }
   
   #-- <applet> tag (end tag required)
   sub start_applet {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       
       my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,undef,1);
       &Apache::lonxml::extlink($code);
       my $archive=&Apache::lonxml::get_param('archive',$parstack,$safeeval,
      undef,1);
       &Apache::lonxml::extlink($archive);
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
           $currentstring = $token->[4];
       } elsif ($target eq 'tex') {
           # Turn off some stuff we can't be inside thank you LaTeX
   
    my $restart_sub = 0;
    my $restart_sup = 0;
   
    # Since <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;
 }  }
   
 #-- <embed> tag  sub end_applet {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];
       } elsif ($target eq 'tex') {
       } 
       return $currentstring;
   }
   
   #-- <embed> tag (end tag optional/required)
 sub start_embed {      sub start_embed {    
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=      my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
  $token->[2]->{'src'};      &Apache::lonxml::extlink($src);
     my $currentstring = '';      my $currentstring = '';
     if ($target eq 'web') {      if ($target eq 'web' || $target eq 'webgrade') {
  $currentstring = $token->[4];      $currentstring=&Apache::lonenc::encrypt_ref($token,{'src'=>$src}); 
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $currentstring = " \\begin{figure} ";    
     }       } 
     return $currentstring;      return $currentstring;
 }  }
         sub end_embed {  
     my ($target,$token) = @_;  sub end_embed {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];           if ($target eq 'web' || $target eq 'webgrade') {
     } elsif ($target eq 'tex') {          $currentstring = $token->[2];
               $currentstring = " \\end{figure}";        } elsif ($target eq 'tex') {
     }           # ./.
    return $currentstring;      }
  }      return $currentstring;
   }
 #-- <param> tag  
   #-- <param> tag (end tag forbidden)
         sub start_param {  sub start_param {
     my ($target,$token) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     if ($token->[2]->{'name'} eq 'cabbase') {      my $name = &Apache::lonxml::get_param('name',$parstack,$safeeval,
                       $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=                                            undef,1);
      $token->[2]->{'value'};      if ($name =~/^cabbase$/i) {
             }      my $value=&Apache::lonxml::get_param('value',$parstack,
             $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=          $safeeval,undef,1);
                                         $token->[2]->{'src'};   &Apache::lonxml::extlink($value);
             my $currentstring = '';      } elsif ($name eq 'flashvars') {
             if ($target eq 'web') {          if (lc(&Apache::lonxml::get_param('type',$parstack,$safeeval,-2,1))
               $currentstring = $token->[4];                   eq 'application/x-shockwave-flash') {
     } elsif ($target eq 'tex') {              my $launcher =
               $currentstring = " \\begin{figure} ";                    &Apache::lonxml::get_param('data',$parstack,$safeeval,-2,1);
     }               if ($launcher) {
    return $currentstring;                  &Apache::lonxml::extlink($launcher);
  }              }
         sub end_param {              my $flashvars=&Apache::lonxml::get_param('value',$parstack,
     my ($target,$token) = @_;                                                       $safeeval,undef,1);
             my $currentstring = '';              if ($flashvars ne '') {
             if ($target eq 'web') {                  foreach my $item (split(/\&/,$flashvars)) {
               $currentstring = $token->[2];                           my ($key,$value)=split(/=/,$item,2);
     } elsif ($target eq 'tex') {                      if ($key eq 'content') {
               $currentstring = " \\end{figure}";                            if ($value ne '') {
     }                               my ($dir) = ($launcher =~ m{(.+/)[^/]+$});
    return $currentstring;                              &Apache::lonxml::extlink($dir.$value);
                           }
                       } elsif ($key eq 'thumb') {
                           if ($value ne '') {
                               &Apache::lonxml::extlink($value);
                           }
                       }
                   }
               }
           }
       }
       my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
       if ($src ne '') {
           &Apache::lonxml::extlink($src);
       }
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    my %toconvert;
    if ($src) { $toconvert{'src'}= $src; }
    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') {
       } 
       return $currentstring;
   }
   
   sub end_param {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];     
       } elsif ($target eq 'tex') {
       } 
       return $currentstring;
   }
   
 #-- <allow> tag  #-- <allow> tag
 sub start_allow {  sub start_allow {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=  
  $token->[2]->{'src'};  
     my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);      my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
     &image_replication($src);      &Apache::lonxml::extlink($src);
   
       if ($target eq 'tex') { &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 1782  sub end_allow { Line 3163  sub end_allow {
     if ( $target eq 'edit') { return (&Apache::edit::end_table()); }      if ( $target eq 'edit') { return (&Apache::edit::end_table()); }
     return '';      return '';
 }  }
 #-- Frames  
  sub start_frameset {  #-- Frames (end tag required)
   my ($target,$token) = @_;  #-- <frameset>
   my $currentstring = '';  sub start_frameset {
   if ($target eq 'web') {       my ($target,$token) = @_;
     if (!$Apache::lonxml::registered) {      my $currentstring = ''; # Close any pending para.
       $currentstring.='<head>'.      if ($target eq 'web' || $target eq 'webgrade') { 
   &Apache::lonxml::registerurl(undef,$target).'</head>';   $currentstring = 
     }      &Apache::loncommon::start_page($Apache::londefdef::title,
     $currentstring .= $token->[4];     $Apache::londefdef::head,
   }     {'add_entries'    => $token->[2],
   return $currentstring;  #    'no_title'       => 1,
  }      'force_register' => 1,
         sub end_frameset {      'frameset'       => 1,});
   my ($target,$token) = @_;  
   my $currentstring = '';      }
   if ($target eq 'web') {      return $currentstring;
     $currentstring = $token->[2];  }
   }  
   return $currentstring;  sub end_frameset {
  }      my ($target,$token) = @_;
 #-- <pre>      my $currentstring = '';
  sub start_pre {      if ($target eq 'web' || $target eq 'webgrade') {
     my ($target,$token) = @_;   $currentstring = $token->[2];
             my $currentstring = '';      }
             if ($target eq 'web') {      return $currentstring;
        $currentstring .= $token->[4];  }
     } elsif ($target eq 'tex') {  
  $currentstring .= '\begin{verbatim}';  #-- <xmp> (end tag required)
     }   sub start_xmp {
            return $currentstring;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
  }      my $currentstring = '';
         sub end_pre {      if ($target eq 'web' || $target eq 'webgrade') {
     my ($target,$token) = @_;   $currentstring .= $token->[4];
             my $currentstring = '';      } elsif ($target eq 'tex') {
             if ($target eq 'web') {   $currentstring .= '\begin{verbatim}';
        $currentstring .= $token->[2];      } 
     } elsif ($target eq 'tex') {      return $currentstring;
  $currentstring .= '\end{verbatim}';  }
     }  
            return $currentstring;  sub end_xmp {
  }      my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '\end{verbatim}';
       }
       return $currentstring;
   }
   
   #-- <pre> (end tag required)
   sub start_pre {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
       my $currentstring = &end_p(); # close off pending <p>
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[4];
       } elsif ($target eq 'tex') {
    $currentstring .= '\begin{verbatim}';
    &Apache::lonxml::disable_LaTeX_substitutions();
       } 
       return $currentstring;
   }
   
   sub end_pre {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring .= $token->[2];
       } elsif ($target eq 'tex') {
    $currentstring .= '\end{verbatim}';
    &Apache::lonxml::enable_LaTeX_substitutions();
       }
       return $currentstring;
   }
   
 #-- <insert>  #-- <insert>
  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>';;
     }      }
            return $currentstring;      return $currentstring;
  }  }
         sub end_insert {  
     my ($target,$token) = @_;  sub end_insert {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
        $currentstring .= '';      if ($target eq 'web' || $target eq 'webgrade') {
     }   $currentstring .= '';
            return $currentstring;      }
  }      return $currentstring;
   }
   
 #-- <externallink>  #-- <externallink>
  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>';;
     }      }
            return $currentstring;      return $currentstring;
  }  }
         sub end_externallink {  
     my ($target,$token) = @_;  sub end_externallink {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
        $currentstring .= '';      if ($target eq 'web' || $target eq 'webgrade') {
     }   $currentstring .= '';
            return $currentstring;      }
  }      return $currentstring;
   }
   
 #-- <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.' ';
     }      }
            return $currentstring;      return $currentstring;
  }  }
         sub end_blankspace {  
     my ($target,$token) = @_;  sub end_blankspace {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'tex') {      my $currentstring = '';
        $currentstring .= '';      if ($target eq 'tex') {
     }   $currentstring .= '';
            return $currentstring;      }
  }      return $currentstring;
 #-- <abbr> tag  }
       sub start_abbr {  
     my ($target,$token) = @_;  #-- <abbr> tag (end tag required)
             my $currentstring = '';  sub start_abbr {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[4];           my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[4];     
  }      } 
         sub end_abbr {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_abbr {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
 #-- <acronym> tag      } 
       sub start_acronym {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <acronym> tag (end tag required)
               $currentstring = $token->[4];       sub start_acronym {
     }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
         sub end_acronym {   $currentstring = $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[2];      
             }   sub end_acronym {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
 #-- <area> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_area {   $currentstring = $token->[2];    
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   #-- <area> tag (end tag forbidden)
    return $currentstring;  sub start_area {
  }      my ($target,$token) = @_;
         sub end_area {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[4];     
             if ($target eq 'web') {      } 
               $currentstring = $token->[2];          return $currentstring;
             }   }
    return $currentstring;  
  }  sub end_area {
 #-- <base> tag      my ($target,$token) = @_;
       sub start_base {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[2];    
             if ($target eq 'web') {      } 
               $currentstring = $token->[4];           return $currentstring;
     }   }
    return $currentstring;  
  }  #-- <base> tag (end tag forbidden)
         sub end_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->[2];       $currentstring = $token->[4];     
             }       }
    return $currentstring;      return $currentstring;
  }  }
 #-- <bdo> tag  
       sub start_bdo {  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->[4];        $currentstring = $token->[2];    
     }       } 
    return $currentstring;      return $currentstring;
  }  }
         sub end_bdo {  
     my ($target,$token) = @_;  #-- <bdo> tag (end tag required)
             my $currentstring = '';  sub start_bdo {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[2];          my $currentstring = '';
             }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[4];     
  }      } 
 #-- <bgsound> tag      return $currentstring;
       sub start_bgsound {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  sub end_bdo {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[4];           my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[2];    
  }      } 
         sub end_bgsound {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <bgsound> tag (end tag optional)
               $currentstring = $token->[2];      sub start_bgsound {
             }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
 #-- <blink> tag   $currentstring = $token->[4];     
       sub start_blink {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[4];       sub end_bgsound {
     }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
         sub end_blink {   $currentstring = $token->[2];    
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[2];      
             }   #-- <blink> tag (end tag required)
    return $currentstring;  sub start_blink {
  }      my ($target,$token) = @_;
 #-- <blockquote> tag      my $currentstring = '';
       sub start_blockquote {      if ($target eq 'web' || $target eq 'webgrade') {
     my ($target,$token) = @_;   $currentstring = $token->[4];     
             my $currentstring = '';      } 
             if ($target eq 'web') {      return $currentstring;
               $currentstring = $token->[4];       }
     }   
    return $currentstring;  sub end_blink {
  }      my ($target,$token) = @_;
         sub end_blockquote {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[2];    
             if ($target eq 'web') {      } 
               $currentstring = $token->[2];          return $currentstring;
             }   }
    return $currentstring;  
  }  #-- <blockquote> tag (end tag required)
 #-- <button> tag  sub start_blockquote {
       sub start_button {      my ($target,$token) = @_;
     my ($target,$token) = @_;      my $currentstring = &end_p(); # Close any unclosed <p>
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   $currentstring .= $token->[4];     
               $currentstring = $token->[4];           } 
     }       if ($target eq 'tex') {
    return $currentstring;   $currentstring .= '\begin{quote}';
  }      }
         sub end_button {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_blockquote {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
 #-- <caption> tag      } 
       sub start_caption {      if ($target eq 'tex') {
     my ($target,$token) = @_;   $currentstring = '\end{quote}';
             my $currentstring = '';      }
             if ($target eq 'web') {      return $currentstring;
               $currentstring = $token->[4];       }
     }   
    return $currentstring;  #-- <button> tag (end tag required)
  }  sub start_button {
         sub end_caption {      my ($target,$token) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   $currentstring = $token->[4];     
               $currentstring = $token->[2];          } 
             }       return $currentstring;
    return $currentstring;  }
  }  
 #-- <col> tag  sub end_button {
       sub start_col {      my ($target,$token) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   $currentstring = $token->[2];    
               $currentstring = $token->[4];           } 
     }       return $currentstring;
    return $currentstring;  }
  }  
         sub end_col {  #-- <caption> tag (end tag required)
     my ($target,$token) = @_;  sub start_caption {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];          if ($target eq 'web' || $target eq 'webgrade') {
             }    $currentstring = $token->[4];     
    return $currentstring;      }
  }      return $currentstring;
 #-- <colgroup> tag  }
       sub start_colgroup {  
     my ($target,$token) = @_;  sub end_caption {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[4];           if ($target eq 'web' || $target eq 'webgrade') {
     }    $currentstring = $token->[2];
    return $currentstring;      } 
  }      return $currentstring;
         sub end_colgroup {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  #-- <col> tag (end tag forbdden)
             if ($target eq 'web') {  sub start_col {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
 #-- <del> tag      } 
       sub start_del {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_col {
               $currentstring = $token->[4];           my ($target,$token) = @_;
     }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
         sub end_del {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[2];      #-- <colgroup tag (end tag optional)
             }   sub start_colgroup {
    return $currentstring;      my ($target,$token,$tagstack, $parstack, $parser, $safeeval, $style) = @_;
  }      my $currentstring = '';
 #-- <fieldset> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_fieldset {   $currentstring = $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      if ($target eq 'tex') {
             if ($target eq 'web') {   # TODO: Ensure this tag is in a table:
               $currentstring = $token->[4];       
     }    # Fetch the attributes and build the hash for the
    return $currentstring;   # call to define_colgroup.
  }  
         sub end_fieldset {   my $span    = &Apache::lonxml::get_param('span',   $parstack, $safeeval);
     my ($target,$token) = @_;   my $halign  = &Apache::lonxml::get_param('halign', $parstack, $safeeval);
             my $currentstring = '';  
             if ($target eq 'web') {   my %colgroup_params;
               $currentstring = $token->[2];       if ($span ne '') {
             }       $colgroup_params{'span'} = $span;
    return $currentstring;   }
  }   if ($halign ne '') {
 #-- <frame> tag      $colgroup_params{'halign'} = $halign;
       sub start_frame {   }
     my ($target,$token) = @_;  
             my $currentstring = '';   my $table = $Apache::londefdef::table[-1];
             if ($target eq 'web') {   $table->define_colgroup(\%colgroup_params);
               $currentstring = $token->[4];       
     }       }
    return $currentstring;      return $currentstring;
  }  }
         sub end_frame {  
     my ($target,$token) = @_;  sub end_colgroup {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];          if ($target eq 'web' || $target eq 'webgrade') {
             }    $currentstring = $token->[2];    
    return $currentstring;      } 
  }      return $currentstring;
 #-- <iframe> tag  }
       sub start_iframe {  
     my ($target,$token) = @_;  
             my $currentstring = '';  #-- <del> tag (end tag required)
             if ($target eq 'web') {  sub start_del {
               $currentstring = $token->[4];           my ($target,$token) = @_;
     }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
         sub end_iframe {      } elsif ($target eq 'tex') {
     my ($target,$token) = @_;   &disable_para();
             my $currentstring = '';   $currentstring .= '\st{';  
             if ($target eq 'web') {      } 
               $currentstring = $token->[2];          return $currentstring;
             }   }
    return $currentstring;  
  }  sub end_del {
 #-- <ins> tag      my ($target,$token) = @_;
       sub start_ins {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[2];     
             if ($target eq 'web') {      } elsif ($target eq 'tex') {
               $currentstring = $token->[4];        &enable_para();
     }    $currentstring = '}';
    return $currentstring;      } 
  }      return $currentstring;
         sub end_ins {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  #-- <fieldset> tag (end tag required)
             if ($target eq 'web') {  sub start_fieldset {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
 #-- <isindex> tag      } 
       sub start_isindex {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_fieldset {
               $currentstring = $token->[4];           my ($target,$token) = @_;
     }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
         sub end_isindex {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[2];      #-- <frame> tag (end tag forbidden)
             }   sub start_frame {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
 #-- <keygen> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_keygen {   $currentstring = $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   sub end_frame {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
         sub end_keygen {      if ($target eq 'web' || $target eq 'webgrade') {
     my ($target,$token) = @_;   $currentstring = $token->[2];    
             my $currentstring = '';      } 
             if ($target eq 'web') {      return $currentstring;
               $currentstring = $token->[2];      }
             }   
    return $currentstring;  #-- <iframe> tag (end tag required)
  }  sub start_iframe {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
           my ($src,$url,$query);
           if ($token->[2]->{'src'}) {
               $src = $token->[2]->{'src'};
           } elsif ($token->[2]->{'SRC'}) {
               $src = $token->[2]->{'SRC'};
           }
           if ($src) {
               ($url,$query) = ($src =~ /^([^?]+)\??([^?]*)$/);
               if ($query =~ /inhibitmenu=yes/) {
                   $currentstring = $token->[4];
               } else {
                   my $inhibit;
                   if ($url =~ m{^[^/.].*\.x?html?$}) {
                       $inhibit = 1;
                   } elsif ($url =~ m{^/(uploaded|res)/.*\.x?html?$}) {
                       $inhibit = 1;
                   }
                   if ($inhibit) {
                       $currentstring = '<iframe ';
                       foreach my $attrib (@{$token->[3]}) {
                           if (lc($attrib) eq 'src') {
                               if ($query) {
                                   $query.='&amp;inhibitmenu=yes';
                               } else {
                                   $query = 'inhibitmenu=yes';
                               } 
                               $currentstring .= 'src="'.$url.'?'.$query.'" ';
                           } else {
                               $currentstring .= lc($attrib).'="'.$token->[2]->{$attrib}.'" ';
                           }
                       }
                       $currentstring =~ s/\s+$//;
                       if ($token->[4] =~ m{/>$}) {
                           $currentstring .= ' />';
                       } else {
                           $currentstring .= '>';
                       }
                   } else {
                       $currentstring = $token->[4];
                   }
               }
               if (($url !~ m{^https?://}) && ($env{'request.course.id'})) {
                   my $docuri = &Apache::lonnet::hreflocation('',$env{'request.filename'});
                   my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   if ($url =~ m{^([^/]|/uploaded/)}) {
                       my $cleanhref = &clean_docs_httpref($url,$docuri,$cdom,$cnum);
                       if ($cleanhref) {
                           &Apache::lonxml::extlink($cleanhref);
                       }
                   } elsif (($url =~ m{/res/$LONCAPA::domain_re/}) && ($docuri =~ m{^\Q/uploaded/$cdom/$cnum/docs/\E})) {
                       if (!&Apache::lonnet::allowed('bre',$url)) {
                           if (&Apache::lonnet::is_on_map($url)) {
                               &Apache::lonxml::extlink($url);
                           }
                       }
                   }
               }
           } else {
               $currentstring = $token->[4];
           }
       }
       return $currentstring;
   }
   
   sub end_iframe {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <ins> tag (end tag required)
   sub start_ins {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_ins {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <isindex> tag (end tag forbidden)
   sub start_isindex {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_isindex {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <keygen> tag (end tag forbidden)
   sub start_keygen {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_keygen {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
 #-- <label> tag  #-- <label> tag
       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;
  }  }
         sub end_label {  
     my ($target,$token) = @_;  sub end_label {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];          if ($target eq 'web' || $target eq 'webgrade') {
             }    $currentstring = $token->[2];    
    return $currentstring;      } 
  }      return $currentstring;
 #-- <layer> tag  }
       sub start_layer {  
     my ($target,$token) = @_;  #-- <layer> tag (end tag required)
             my $currentstring = '';  sub start_layer {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[4];           my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[4];     
  }      } 
         sub end_layer {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_layer {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
 #-- <legend> tag      } 
       sub start_legend {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <legend> tag (end tag required)
               $currentstring = $token->[4];       sub start_legend {
     }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
         sub end_legend {   $currentstring = $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[2];      
             }   sub end_legend {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
 #-- <link> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_link {   $currentstring = $token->[2];    
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   #-- <link> tag (end tag forbidden)
    return $currentstring;  sub start_link {
  }      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
         sub end_link {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
             if ($target eq 'web') {      undef,1);
               $currentstring = $token->[2];       &Apache::lonxml::extlink($href);
             }    $currentstring = $token->[4];     
    return $currentstring;      } 
  }      return $currentstring;
 #-- <marquee> tag  }
       sub start_marquee {  
     my ($target,$token) = @_;  sub end_link {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[4];           if ($target eq 'web' || $target eq 'webgrade') {
     }    $currentstring = $token->[2];    
    return $currentstring;      } 
  }      return $currentstring;
         sub end_marquee {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  #-- <marquee> tag (end tag optional)
             if ($target eq 'web') {  sub start_marquee {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[4];     
 #-- <malticol> tag      } 
       sub start_malticol {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_marquee {
               $currentstring = $token->[4];           my ($target,$token) = @_;
     }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
         sub end_malticol {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[2];      #-- <multicol> tag (end tag required)
             }   sub start_multicol {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = &end_p(); # Close any pending <p>
 #-- <nobr> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_nobr {   $currentstring .= $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   sub end_multicol {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
         sub end_nobr {      if ($target eq 'web' || $target eq 'webgrade') {
     my ($target,$token) = @_;   $currentstring = $token->[2];    
             my $currentstring = '';      } 
             if ($target eq 'web') {      return $currentstring;
               $currentstring = $token->[2];      }
             }   
    return $currentstring;  #-- <nobr> tag (end tag required)
  }  sub start_nobr {
 #-- <noembed> tag      my ($target,$token) = @_;
       sub start_noembed {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[4];     
             if ($target eq 'web') {      }  elsif ($target eq 'tex') {
               $currentstring = $token->[4];        $currentstring='\mbox{';
     }       }
    return $currentstring;      return $currentstring;
  }  }
         sub end_noembed {  
     my ($target,$token) = @_;  sub end_nobr {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];          if ($target eq 'web' || $target eq 'webgrade') {
             }    $currentstring = $token->[2];    
    return $currentstring;      }   elsif ($target eq 'tex') {
  }   $currentstring='}';
 #-- <noframes> tag      }
       sub start_noframes {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <noembed> tag (end tag required)
               $currentstring = $token->[4];       sub start_noembed {
     }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
         sub end_noframes {   $currentstring = $token->[4];     
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[2];      
             }   sub end_noembed {
    return $currentstring;      my ($target,$token) = @_;
  }      my $currentstring = '';
 #-- <nolayer> tag      if ($target eq 'web' || $target eq 'webgrade') {
       sub start_nolayer {   $currentstring = $token->[2];    
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   #-- <noframes> tag (end tag required)
    return $currentstring;  sub start_noframes {
  }      my ($target,$token) = @_;
         sub end_nolayer {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[4];     
             if ($target eq 'web') {      } 
               $currentstring = $token->[2];          return $currentstring;
             }   }
    return $currentstring;  
  }  sub end_noframes {
 #-- <noscript> tag      my ($target,$token) = @_;
       sub start_noscript {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[2];    
             if ($target eq 'web') {      } 
               $currentstring = $token->[4];           return $currentstring;
     }   }
    return $currentstring;  
  }  #-- <nolayer> tag (end tag required)
         sub end_noscript {  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->[2];       $currentstring = $token->[4];     
             }       } 
    return $currentstring;      return $currentstring;
  }  }
 #-- <object> tag  
       sub start_object {  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->[4];        $currentstring = $token->[2];    
     }       } 
    return $currentstring;      return $currentstring;
  }  }
         sub end_object {  
     my ($target,$token) = @_;  #-- <noscript> tag (end tag required)
             my $currentstring = '';  sub start_noscript {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[2];          my $currentstring = '';
             }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[4];     
  }      } 
 #-- <optgroup> tag      return $currentstring;
       sub start_optgroup {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  sub end_noscript {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[4];           my $currentstring = '';
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[2];    
  }      } 
         sub end_optgroup {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <object> tag (end tag required)
               $currentstring = $token->[2];      sub start_object {
             }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
 #-- <samp> tag   $currentstring = $token->[4];     
       sub start_samp {      } 
     my ($target,$token) = @_;      return $currentstring;
             my $currentstring = '';  }
             if ($target eq 'web') {  
               $currentstring = $token->[4];       sub end_object {
     }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
         sub end_samp {   $currentstring = $token->[2];    
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[2];      
             }   #-- <optgroup> tag (end tag required)
    return $currentstring;  sub start_optgroup {
  }      my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       return $currentstring;
   }
   
   sub end_optgroup {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <samp> tag (end tag required)
   sub start_samp {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } elsif ($target eq 'tex') {
    $currentstring='\texttt{';
       }
       return $currentstring;
   }
   
   sub end_samp {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } elsif ($target eq 'tex') {
    $currentstring='}';
       }
       return $currentstring;
   }
   
 #-- <server> tag  #-- <server> tag
       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;
  }  }
         sub end_server {  
     my ($target,$token) = @_;  sub end_server {
             my $currentstring = '';      my ($target,$token) = @_;
             if ($target eq 'web') {      my $currentstring = '';
               $currentstring = $token->[2];          if ($target eq 'web' || $target eq 'webgrade') {
             }    $currentstring = $token->[2];    
    return $currentstring;      } 
  }      return $currentstring;
 #-- <spacer> tag  }
       sub start_spacer {  
     my ($target,$token) = @_;  #-- <spacer> tag (end tag forbidden)
             my $currentstring = '';  sub start_spacer {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[4];           my $currentstring = &end_p(); # Close off any open <p> tag.
     }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring .= $token->[4];     
  }      } 
         sub end_spacer {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_spacer {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];    
 #-- <span> tag      } 
       sub start_span {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  my @span_end_stack; # for span tex target
               $currentstring = $token->[4];       
     }   #-- <span> tag (end tag required)
    return $currentstring;  sub start_span {
  }      my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
         sub end_span {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[4];     
             if ($target eq 'web') {      } elsif ($target eq 'tex') {
               $currentstring = $token->[2];              my $endstring = '';
             }           my $family = &get_css_property('font-family',$parstack,$safeeval);
    return $currentstring;          if ($family eq 'monospace') {
  }              $currentstring .= '\texttt{';
 #-- <tbody> tag              $endstring .= '}';
       sub start_tbody {          }
     my ($target,$token) = @_;          my $weight = &get_css_property('font-weight',$parstack,$safeeval);
             my $currentstring = '';          if ($weight eq 'bold') {
             if ($target eq 'web') {              $currentstring .= '\textbf{';
               $currentstring = $token->[4];                   $endstring .= '}';
     }           }
    return $currentstring;          my $style = &get_css_property('font-style',$parstack,$safeeval);
  }          if ($style eq 'italic') {
         sub end_tbody {              $currentstring .= '\textit{';
     my ($target,$token) = @_;              $endstring .= '}';
             my $currentstring = '';          }
             if ($target eq 'web') {          push(@span_end_stack, $endstring);
               $currentstring = $token->[2];          }
             }       return $currentstring;
    return $currentstring;  }
  }  
 #-- <tfoot> tag  sub end_span {
       sub start_tfoot {      my ($target,$token) = @_;
     my ($target,$token) = @_;      my $currentstring = '';
             my $currentstring = '';      if ($target eq 'web' || $target eq 'webgrade') {
             if ($target eq 'web') {   $currentstring = $token->[2];    
               $currentstring = $token->[4];           } elsif ($target eq 'tex') {
     }           my $endstring = pop @span_end_stack;
    return $currentstring;          $currentstring .= $endstring;
  }      }
         sub end_tfoot {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  #-- <tbody> tag (end tag optional)
               $currentstring = $token->[2];      sub start_tbody {
             }       my ($target,$token) = @_;
    return $currentstring;      my $currentstring = '';
  }      if ($target eq 'web' || $target eq 'webgrade') {
 #-- <thead> tag   $currentstring = $token->[4];     
       sub start_thead {      } 
     my ($target,$token) = @_;      if ($target eq 'tex') {
             my $currentstring = '';   # TODO: Ensure this tag is within a table:
             if ($target eq 'web') {  
               $currentstring = $token->[4];        my $table = $Apache::londefdef::table[-1];
     }    $table->start_body();
    return $currentstring;      }
  }      return $currentstring;
         sub end_thead {  }
     my ($target,$token) = @_;  
             my $currentstring = '';  sub end_tbody {
             if ($target eq 'web') {      my ($target,$token) = @_;
               $currentstring = $token->[2];          my $currentstring = '';
             }       if ($target eq 'web' || $target eq 'webgrade') {
    return $currentstring;   $currentstring = $token->[2];    
  }      } 
       if($target eq 'tex') {
    # TODO: Ensure this tag is within a table:
   
    my $table = $Apache::londefdef::table[-1];
    $table->end_body();
       }
       return $currentstring;
   }
   
   #-- <tfoot> tag (end tag optional)
   sub start_tfoot {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       if ($target eq 'tex') {
           # TODO: ensure this is within a table tag.
    my $table = $Apache::londefdef::table[-1];
    $table->start_foot();
       }
       return $currentstring;
   }
   
   sub end_tfoot {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       if ($target eq 'tex') {
    #  TODO: Ensure this is in side a table 
    my $table = $Apache::londefdef::table[-1];
    $table->end_foot();
       }
       return $currentstring;
   }
   
   #-- <thead> tag (end tag optional)
   sub start_thead {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[4];     
       } 
       if ($target eq 'tex') {
    # Assume we're in a table... TODO: Verify that and ignore tag if not.
    my $table = $Apache::londefdef::table[-1];
    $table->start_head();
       }
       return $currentstring;
   }
   
   sub end_thead {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       if ($target eq 'tex') {
         # TODO: Verify we are in a table and ignore tag if not.
   
    my $table = $Apache::londefdef::table[-1];
    $table->end_head();
       }
       return $currentstring;
   }
   
 #-- <var> tag  #-- <var> tag
       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') {
    return $currentstring;   $currentstring = '\textit{'; 
  }      }
         sub end_var {      return $currentstring;
     my ($target,$token) = @_;  }
             my $currentstring = '';  
             if ($target eq 'web') {  sub end_var {
               $currentstring = $token->[2];          my ($target,$token) = @_;
             }       my $currentstring = '';
    return $currentstring;      if ($target eq 'web' || $target eq 'webgrade') {
  }   $currentstring = $token->[2];
 #-- <wbr> tag      } elsif ($target eq 'tex') {
       sub start_wbr {   $currentstring = '}'; 
     my ($target,$token) = @_;      } 
             my $currentstring = '';      return $currentstring;
             if ($target eq 'web') {  }
               $currentstring = $token->[4];       
     }   #-- <wbr> tag (end tag forbidden)
    return $currentstring;  sub start_wbr {
  }      my ($target,$token) = @_;
         sub end_wbr {      my $currentstring = '';
     my ($target,$token) = @_;      if ($target eq 'web' || $target eq 'webgrade') {
             my $currentstring = '';   $currentstring = $token->[4];     
             if ($target eq 'web') {      } 
               $currentstring = $token->[2];          return $currentstring;
             }   }
    return $currentstring;  
  }  sub end_wbr {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = $token->[2];    
       } 
       return $currentstring;
   }
   
   #-- <hideweboutput> tag
   sub start_hideweboutput {
       my ($target,$token) = @_;
       if ($target eq 'web' || $target eq 'webgrade') {
    &Apache::lonxml::startredirection();     
       } 
       return '';
   }
   
   sub end_hideweboutput {
       my ($target,$token) = @_;
       my $currentstring = '';
       if ($target eq 'web' || $target eq 'webgrade') {
    $currentstring = &Apache::lonxml::endredirection();    
       } 
       return '';
   }
   
   
 sub image_replication {  sub image_replication {
     my $src = shift;      my $src = shift;
     if (not -e '/home/httpd/html'.$src) {      if (not -e $src) { &Apache::lonnet::repcopy($src); }
  #replicates image itself      #replicates eps or ps 
  &Apache::lonnet::repcopy('/home/httpd/html'.$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|png)$/.eps/;      if (not -e $epssrc && not -e $pssrc) {
  if (not-e $newsrc && &Apache::lonnet::repcopy('/home/httpd/html'.$newsrc) ne 'OK') {   my $result=&Apache::lonnet::repcopy($epssrc);
     $newsrc =~ s/\.eps$/\.ps/;   if ($result ne 'ok') { &Apache::lonnet::repcopy($pssrc); }
     &Apache::lonnet::repcopy('/home/httpd/html'.$newsrc);  
  }  
     }      }
     return '';      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|svg)/i);
       $src=~s/\.(bmp|gif|png|jpg|jpeg|svg)$/\.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/;
    if (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/httpd/html/priv/[^/]+/([^/]*)/|/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/httpd/html/priv/[^/]+/([^/]*)/|/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";
       if (open(my $tmpfile,">>$filename")) { 
           print $tmpfile "$src\n";
           close($tmpfile);
       }
       my $newsrc = $src;
       $newsrc =~ s/(\.bmp|\.gif|\.jpg|\.jpeg)$/\.eps/i;
       $newsrc=~s{/home/httpd/html/res}{};
       $newsrc=~s{/home/httpd/html/priv/[^/]+/($LONCAPA::username_re)/}{/$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.'} ';
       }
   }
   
   sub file_path {     
       my $src=shift;
       my ($file,$path); 
       if ($src =~ m!(.*)/([^/]*)$!) {
    $file = $2; 
    $path = $1.'/'; 
       } 
       return $file,$path;
   }
   
   
   sub recalc {
       my $argument = shift;
       if (not $argument=~/(mm|cm|in|pc|pt)/) {return $argument.' mm';}
       $argument=~/\s*(\d+\.?\d*)\s*(mm|cm|in|pc|pt)/;
       my $value=$1;
       my $units=$2;
       if ($units eq 'cm') {
    $value*=10;
       } elsif ($units eq 'in') {
    $value*=25.4;
       } elsif ($units eq 'pc') {
    $value*=(25.4*12/72.27);
       } elsif ($units eq 'pt') {
    $value*=(25.4/72.27);
       }
       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 = '';
       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       = '}';
       }
       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}'."\n".
    '\usepackage{longtable}'."\n".
    '\usepackage{textcomp}'."\n".
    '\usepackage{makeidx}'."\n".
    '\usepackage[dvips]{graphicx}'."\n".
    '\usepackage{wrapfig}'."\n".
    '\usepackage{picins}'."\n".
    '\usepackage[T1]{fontenc}'."\n".
    '\usepackage{lmodern}'."\n".
    '\usepackage[postscript]{ucs}'."\n".
    '\usepackage[utf8x]{inputenc}'."\n".
    '\usepackage{pifont}'."\n".
    '\usepackage{latexsym}'."\n".
    '\usepackage{epsfig}'."\n".
    '\usepackage{xtab}'."\n".
    '\usepackage{tabularx}'."\n".
    '\usepackage{booktabs}'."\n".
    '\usepackage{array}'."\n".
    '\usepackage{colortbl}'."\n".
    '\usepackage{xcolor}'."\n".
    '\usepackage{calc}'."\n".
    '\usepackage{amsmath}'."\n".
    '\usepackage{soul}'."\n".
    '\usepackage{amssymb}'."\n".
    '\usepackage{amsfonts}'."\n".
    '\usepackage{amsthm}'."\n".
    '\usepackage{amscd}'."\n".
    '\usepackage{actuarialangle}'."\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;
   
   }
   
   sub clean_docs_httpref {
       my ($href,$docuri,$cdom,$cnum) = @_;
       if ($docuri eq '') {
           $docuri = &Apache::lonnet::hreflocation('',$env{'request.filename'});
       }
       if ($cdom eq '') {
           $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       }
       if ($cnum eq '') {
           $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       }
       my $cleanhref;
       if ($docuri =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/)(.+/)[^/]+$}) {
           my $prefix = $1;
           my $relpath = $2;
           my ($hrefpath,$fname);
           if ($href =~ m{^/}) {
               if ($href =~ m{^\Q$prefix\E(.+/)([^/]+)$}) {
                   $hrefpath = $1;
                   $fname = $2;
               } else {
                   return $cleanhref;
               }
           } else {
               if ($href =~ m{/}) {  
                   (my $path,$fname) = ($href =~ m{^(.*)/([^/]*)$});
                   $hrefpath = $relpath.$path;
                   if ($path eq '') {
                       $hrefpath =~ s{/$}{};
                   }
               } else {
                   $fname = $href;
                   $hrefpath = $relpath;
                   $hrefpath =~ s{/$}{};
               }
           }
           if ($fname ne '') {
               my $cleanrelpath;
               foreach my $dir (split(/\//,$hrefpath)) {
                   next if ($dir eq '.');
                   if ($dir eq '..') {
                       $cleanrelpath =~ s{([^/]+/)$}{};
                   } else {
                       $cleanrelpath .= $dir.'/';
                   }
               }
               if ($cleanrelpath ne '') {
                   $cleanhref = $prefix.$cleanrelpath.$fname;
               } else {
                   $cleanhref = $prefix.$fname;
               }
           }
       }
       return $cleanhref;
   }
   
   # This is retrieving a CSS property from the style attribute of the current element.
   # It is not checking <style> elements or linked stylesheets yet.
   sub get_css_property {
       my ($property,$parstack,$safeeval) = @_;
       my $style=&Apache::lonxml::get_param('style',$parstack,$safeeval,undef,1);
       my @style_components=split(/;/,$style);
       foreach my $css_pair (@style_components) {
           my ($name, $value) = split(/:/, $css_pair);
           $name =~ s/^\s+|\s+$//g;
           $value =~ s/^\s+|\s+$//g;
           if ($name eq $property) {
               return $value;
           }
       }
       return undef;
   }
   
   =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....
         }
   
   =item clean_docs_httpref($href,$docuri,$cdom,$cnum)
           HTML pages uploaded to a course which contain dependencies either from iframes,
           javascript files or objects (FlashPlayerSwf, MediaSrc, XMPSrc, ConfigurationSrc,
           and PosterImageSrc) for which dependency is another file uploaded to the same
           course.
   
           Required input: 
           href - dependency (either a relative URL, or an absolute URL)
           Optional inputs:
           docuri - URL of HTML page containing the dependency
           cdom - Course domain
           cnum - CourseID
   
           Output:
           returns an absolute URL constructed from the href provided, and the calling context.
           (this will be null, if the URL does not begin: /uploaded/$cdom/$cnum/docs/ or
           /uploaded/$cdom/$cnum/supplemental/).
   
   =back
   
   =cut
   
   
 1;  1;
 __END__  __END__

Removed from v.1.111  
changed lines
  Added in v.1.467


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