--- loncom/xml/londefdef.pm	2003/08/14 14:46:06	1.161
+++ loncom/xml/londefdef.pm	2004/12/27 14:06:32	1.248
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Tags Default Definition Module 
 #
-# $Id: londefdef.pm,v 1.161 2003/08/14 14:46:06 sakharuk Exp $
+# $Id: londefdef.pm,v 1.248 2004/12/27 14:06:32 foxr Exp $
 # 
 #
 # Copyright Michigan State University Board of Trustees
@@ -50,8 +50,8 @@ use Apache::File();
 use Image::Magick;
 use Apache::lonmenu();
 use Apache::lonmeta();
+use Apache::Constants qw(:common);
 
-$Apache::londefdef::TD_redirection=0;
 
 BEGIN {
 
@@ -59,6 +59,17 @@ BEGIN {
 
 }
 
+sub initialize_londefdef {
+    $Apache::londefdef::TD_redirection=0;
+    @Apache::londefdef::table = ();
+    $Apache::londefdef::select=0;
+    undef(@Apache::londefdef::description);
+    @Apache::londefdef::DD=(0);
+    @Apache::londefdef::DT=(0);
+    @Apache::londefdef::seenDT=(0);
+    $Apache::londefdef::list_index=0;
+}
+
 #======================= TAG SUBROUTINES =====================
 #-- <output>
 sub start_output {
@@ -73,11 +84,10 @@ sub end_output {
 }
 #-- <m> tag
 sub start_m {
-    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
     my $currentstring = '';
-    if ($target eq 'web') {
-	$Apache::lonxml::prevent_entity_encode++;
-	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') {
 	$inside ='\\documentstyle{article}'.$inside;
 	&Apache::lonxml::debug("M is starting with:$inside:");
 	my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
@@ -92,11 +102,15 @@ sub start_m {
 	    $Apache::lontexconvert::errorstring='';
 	}
 	#&Apache::lonxml::debug("M is ends with:$currentstring:");
+	$Apache::lonxml::post_evaluate=0;
     } elsif ($target eq 'tex') {
-	$currentstring = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);
+	$currentstring = $inside;
+	my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval);
+	if ($eval eq 'on') {
+	    $currentstring=&Apache::run::evaluate($currentstring,$safeeval,$$parstack[-1]);
+	}
 	if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';}
-    } else {
-	my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser);
+	$Apache::lonxml::post_evaluate=0;
     }
     return $currentstring;
 }
@@ -104,11 +118,8 @@ sub start_m {
 sub end_m {
     my ($target,$token) = @_;
     my $currentstring = '';
-    if ($target eq 'web') {
-	$Apache::lonxml::prevent_entity_encode--;
-    } elsif ($target eq 'tex') {
+    if ($target eq 'tex') {
 	$currentstring = "";
-    } elsif ($target eq 'meta') {
     }
     return $currentstring;
 }
@@ -134,60 +145,53 @@ sub end_tthoption {
     return $result;
 }
 
-#-- <html> tag    
+#-- <html> tag (end tag optional)
 sub start_html {
     my ($target,$token) = @_;
     my $currentstring = '';
-    if ($ENV{'browser.mathml'}) {
-	&tth::ttminit();
-	if ($ENV{'browser.unicode'}) {
-	    &tth::ttmoptions('-L -u1');
-	} else {
-	    &tth::ttmoptions('-L -u0');
-	}
-    } else {
-	&tth::tthinit();
-	if ($ENV{'browser.unicode'}) {
-	    &tth::tthoptions('-L -u1');
-	} else {
-	    &tth::tthoptions('-L -u0');
-	}
-    }
-    if ($target eq 'web') {
-	$currentstring = &Apache::lonxml::xmlbegin().
-	    &Apache::lonxml::fontsettings();     
+    my $options=$ENV{'course.'.$ENV{'request.course.id'}.'.tthoptions'};
+    &Apache::lontexconvert::init_tth();
+    if ($target eq 'web' || $target eq 'edit') {
+	$currentstring = &Apache::lonxml::xmlbegin();
     } elsif ($target eq 'tex') {
 	@Apache::londefdef::table = ();
 	$currentstring .= '\documentclass[letterpaper]{article}';
 	if ($ENV{'form.latex_type'}=~'batchmode') {$currentstring .='\batchmode';} 
-	$currentstring .= '\newcommand{\keephidden}[1]{}
-                           \renewcommand{\deg}{$^{\circ}$}
-                           \usepackage{longtable}
-                           \usepackage{textcomp}
-                           \usepackage{makeidx}
-                           \usepackage[dvips]{graphicx}
-                           \usepackage{epsfig}\usepackage{calc}
-\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}
-\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{-0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}';
+	$currentstring .= '\newcommand{\keephidden}[1]{}'.
+                          '\renewcommand{\deg}{$^{\circ}$}'.
+                          '\usepackage{longtable}'.
+                          '\usepackage{textcomp}'.
+                          '\usepackage{makeidx}'.
+                          '\usepackage[dvips]{graphicx}'.
+			  '\usepackage{picins}'.
+                          '\usepackage{epsfig}'.
+                          '\usepackage{calc}'.
+                          '\usepackage{amsmath}'.
+                          '\usepackage{amssymb}'.
+                          '\usepackage{amsfonts}'.
+                          '\usepackage{amsthm}'.
+                          '\usepackage{amscd}'.
+                          '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'.
+                          '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}';
     }
     return $currentstring;
 }
 
 sub end_html {
-    my ($target,$token) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
-	$currentstring = &Apache::lonxml::xmlend();
+	$currentstring = &Apache::lonxml::xmlend($target,$parser);
     }
     return $currentstring;
 }
 
-#-- <head> tag
+#-- <head> tag (end tag optional)
 sub start_head {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
-	$currentstring = $token->[4];     
+	$currentstring = $token->[4].&Apache::lonxml::fontsettings();
     } 
     return $currentstring;
 }
@@ -195,14 +199,14 @@ sub start_head {
 sub end_head {
     my ($target,$token) = @_;
     my $currentstring = '';
-    if ($target eq 'web') {
+    if ($target eq 'web' && $ENV{'request.state'} eq 'published') {
 	$currentstring = &Apache::lonmenu::registerurl(undef,$target).
 	    $token->[2];    
     } 
     return $currentstring;
 }
 
-#-- <map> tag
+#-- <map> tag (end tag required)
 sub start_map {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -221,13 +225,15 @@ sub end_map {
     return $currentstring;
 }
 
-#-- <select> tag
+#-- <select> tag (end tag required)
 sub start_select {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
-    } 
+    }  elsif ($target eq 'tex') {
+	$Apache::londefdef::select=0;
+    }
     return $currentstring;
 }
 
@@ -240,13 +246,20 @@ sub end_select {
     return $currentstring;
 }
 
-#-- <option> tag
+#-- <option> tag (end tag optional)
 sub start_option {
-    my ($target,$token) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
-    } 
+    } elsif ($target eq 'tex') {
+	$Apache::londefdef::select++;
+	if ($Apache::londefdef::select == 1) {
+	    $currentstring='\noindent\fbox{'.&Apache::lonxml::get_param('value',$parstack,$safeeval).'}\keephidden{';
+	} else {
+	    $currentstring='\keephidden{';
+	}
+    }
     return $currentstring;
 }
 
@@ -255,11 +268,13 @@ sub end_option {
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];    
-    } 
+    }  elsif ($target eq 'tex') {
+	$currentstring='}';
+    }
     return $currentstring;
 }
 
-#-- <input> tag
+#-- <input> tag (end tag forbidden)
 sub start_input {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -278,7 +293,7 @@ sub end_input {
     return $currentstring;
 }
 
-#-- <textarea> tag
+#-- <textarea> tag (end tag required)
 sub start_textarea {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -297,7 +312,7 @@ sub end_textarea {
     return $currentstring;
 }
 
-#-- <form> tag
+#-- <form> tag (end tag required)
 sub start_form {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -316,18 +331,18 @@ sub end_form {
     return $currentstring;
 }
 
-#-- <title> tag
+#-- <title> tag (end tag required)
 sub start_title {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	$currentstring .= '\keephidden{' 
+	$currentstring .= '\keephidden{Title of the document:  ' 
     }
     if ($target eq 'meta') {
 	$currentstring='<title>';
-	&start_output();
+	&start_output($target);
     }
     return $currentstring;
 }
@@ -341,13 +356,13 @@ sub end_title {
 	$currentstring .= '}';
     }  
     if ($target eq 'meta') {
-	&end_output();
+	&end_output($target);
 	$currentstring='</title>';
     } 
     return $currentstring;
 }
 
-#-- <meta> tag
+#-- <meta> tag (end tag forbidden)
 sub start_meta {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -382,7 +397,7 @@ sub start_meta {
             my $display=&Apache::lonxml::get_param
 		('display',$parstack,$safeeval,undef,1);
             if ($display) {
-		$display=&HTML::Entities::encode($display);
+		$display=&HTML::Entities::encode($display,'<>&"');
 		$currentstring.='<'.$name.'.display>'.$display.
                                '</'.$name.'.display>';
             }
@@ -398,7 +413,7 @@ sub start_meta {
 }
 
 sub end_meta {
-    my ($target,$token,$tagstack,$parstack,$parser) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	my $args='';
@@ -407,8 +422,11 @@ sub end_meta {
 	    $currentstring = $token->[4];
 	}
     } elsif ($target eq 'tex') {
-	$currentstring=&Apache::lonxml::endredirection();
-	$currentstring='';
+	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;
 }
@@ -458,12 +476,18 @@ sub end_accessrule {
     return $currentstring;
 }
 
-#-- <body> tag
+#-- <body> tag (end tag required)
 sub start_body {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
+
     if ($target eq 'web') {
-	if (!$Apache::lonxml::registered) {
+	if ($Apache::lonhomework::parsing_a_problem) {
+	    &Apache::lonxml::warning("<body> tag found inside of <problem> tag this can cause problems.");
+	    return '';
+	}
+	if (!$Apache::lonxml::registered && 
+	    $ENV{'request.state'} eq 'published') {
 	    $currentstring.='<head>'.
 		&Apache::lonmenu::registerurl(undef,$target).'</head>';
 	}
@@ -508,20 +532,28 @@ sub start_body {
 	$token->[2]->{'onunload'}=&Apache::lonmenu::unloadevents().
 	    ';'.$onUnload;
 	
-	$currentstring .= '<'.$token->[1];
+	if ($ENV{'request.state'} ne 'construct') {
+	    $currentstring .= '<'.$token->[1];
+	}
 	foreach (keys %{$token->[2]}) {
 	    $currentstring.=' '.$_.'="'.$token->[2]->{$_}.'"';
 	}
-	$currentstring.='>';
+	if ($ENV{'request.state'} ne 'construct') {
+	    $currentstring.='>';
+	}
 	if ($ENV{'request.state'} ne 'published') {
+	    my $remote=($ENV{'environment.remote'} ne 'off');
+	    $currentstring=&Apache::loncommon::bodytag(undef,undef,
+						       $currentstring,$remote);
 	    $currentstring.=(<<EDITBUTTON);
 		<form method="post">
-		<input type="submit" name="editmode" value="Edit" />
+		<input type="submit" name="editmode" accesskey="e" value="Edit" />
 		</form>
 EDITBUTTON
 	} else {
 	    $currentstring.=&Apache::lonmenu::menubuttons(undef,$target,1);
 	}
+	$currentstring.=&Apache::lonxml::message_location();
     } elsif ($target eq 'tex') {
 	$currentstring = '\begin{document}';  
     } 
@@ -534,12 +566,12 @@ sub end_body {
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\end{document}';  
+	$currentstring = '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent \end{document}';  
     } 
     return $currentstring;
 }
 
-#-- <center> tag
+#-- <center> tag (end tag required)
 sub start_center {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -562,7 +594,7 @@ sub end_center {
     return $currentstring;
 }
 
-#-- <b> tag
+#-- <b> tag (end tag required)
 sub start_b {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -585,7 +617,7 @@ sub end_b {
     return $currentstring;
 }
 
-#-- <strong> tag
+#-- <strong> tag (end tag required)
 sub start_strong {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -600,8 +632,7 @@ sub start_strong {
 sub end_strong {
     my ($target,$token) = @_;
     my $currentstring = '';
-    if ($target eq 'web') {
-	
+    if ($target eq 'web') {	
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
 	$currentstring = '}';  
@@ -609,7 +640,7 @@ sub end_strong {
     return $currentstring;
 }
 
-#-- <h1> tag
+#-- <h1> tag (end tag required)
 sub start_h1 {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -617,8 +648,8 @@ sub start_h1 {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
 	my $pre;
-	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	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{';
@@ -630,7 +661,7 @@ sub start_h1 {
 	$currentstring .= $pre.'{\\'.$TeXsize.' \textbf{'; 
     } elsif ($target eq 'meta') {
 	$currentstring='<subject>';
-	&start_output();
+	&start_output($target);
     }
     return $currentstring;
 }
@@ -641,9 +672,9 @@ sub end_h1 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -652,7 +683,7 @@ sub end_h1 {
 	}
 	$currentstring .= '}}'.$post;
     } elsif ($target eq 'meta') {
-	&end_output();
+	&end_output($target);
 	$currentstring='</subject>';
     } 
     return $currentstring;
@@ -667,7 +698,7 @@ sub start_h2 {
     } elsif ($target eq 'tex') {
 	my $pre;
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $pre='\begin{center}';
 	} elsif ($align eq 'left') {
 	    $pre='\rlap{';
@@ -687,9 +718,9 @@ sub end_h2 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -710,7 +741,7 @@ sub start_h3 {
     } elsif ($target eq 'tex') {
 	my $pre;
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $pre='\begin{center}';
 	} elsif ($align eq 'left') {
 	    $pre='\rlap{';
@@ -730,9 +761,9 @@ sub end_h3 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -753,7 +784,7 @@ sub start_h4 {
     } elsif ($target eq 'tex') {
 	my $pre;
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $pre='\begin{center}';
 	} elsif ($align eq 'left') {
 	    $pre='\rlap{';
@@ -773,9 +804,9 @@ sub end_h4 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -796,7 +827,7 @@ sub start_h5 {
     } elsif ($target eq 'tex') {
 	my $pre;
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $pre='\begin{center}';
 	} elsif ($align eq 'left') {
 	    $pre='\rlap{';
@@ -816,9 +847,9 @@ sub end_h5 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -839,7 +870,7 @@ sub start_h6 {
     } elsif ($target eq 'tex') {
 	my $pre;
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $pre='\begin{center}';
 	} elsif ($align eq 'left') {
 	    $pre='\rlap{';
@@ -859,9 +890,9 @@ sub end_h6 {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	my $post;
+	my $post='\vskip 0 mm ';
 	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
-	if (($align eq 'center') || (not defined $align)) {
+	if ($align eq 'center') {
 	    $post='\end{center}';
 	} elsif ($align eq 'left') {
 	    $post='} \hfill'.'\vskip 0 mm ';
@@ -873,14 +904,14 @@ sub end_h6 {
     return $currentstring;
 }
 
-#--- <cite> tag
+#--- <cite> tag (end tag required)
 sub start_cite {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\\textit{";
+	$currentstring .= '\textit{';
     }
     return $currentstring;
 }
@@ -891,12 +922,12 @@ sub end_cite {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= "}";
+	$currentstring .= '}';
     }
     return $currentstring;
 }
 
-#-- <i> tag
+#-- <i> tag (end tag required)
 sub start_i {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -919,14 +950,14 @@ sub end_i {
     return $currentstring;
 }
 
-#-- <address> tag
+#-- <address> tag (end tag required)
 sub start_address {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\\textit{";
+	$currentstring .= '\textit{';
     }
     return $currentstring;
 }
@@ -937,19 +968,19 @@ sub end_address {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= "}";
+	$currentstring .= '}';
     }
     return $currentstring;
 }
 
-#-- <dfn> tag
+#-- <dfn> tag (end tag required)
 sub start_dfn {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\\textit{";
+	$currentstring .= '\textit{';
     } 
     return $currentstring;
 }
@@ -960,12 +991,12 @@ sub end_dfn {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= "}";
+	$currentstring .= '}';
     }
     return $currentstring;
 }
 
-#-- <tt> tag
+#-- <tt> tag (end tag required)
 sub start_tt {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -988,14 +1019,14 @@ sub end_tt {
     return $currentstring;
 }
 
-#-- <kbd> tag
+#-- <kbd> tag (end tag required)
 sub start_kbd {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\\texttt";
+	$currentstring .= '\texttt{';
     }
     return $currentstring;
 }
@@ -1006,12 +1037,12 @@ sub end_kbd {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= "}";
+	$currentstring .= '}';
     }
     return $currentstring;
 }
 
-#-- <code> tag
+#-- <code> tag (end tag required)
 sub start_code {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1034,7 +1065,7 @@ sub end_code {
     return $currentstring;
 }
 
-#-- <em> tag
+#-- <em> tag (end tag required)
 sub start_em {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1057,14 +1088,14 @@ sub end_em {
     return $currentstring;
 }
 
-#-- <q> tag
+#-- <q> tag (end tag required)
 sub start_q {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\\emph{";
+	$currentstring .= '\emph{';
     }
     return $currentstring;
 }
@@ -1075,43 +1106,78 @@ sub end_q {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= "}";
+	$currentstring .= '}';
     } 
     return $currentstring;
 }
 
-#-- <p> tag
+#-- <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') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	my $signal=1;
-	foreach my $tag (@$tagstack) {if (lc($tag) eq 'b') {$signal=0;}}
-	if ($signal) {$currentstring .= '\par ';}
+	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
+	if ($align eq 'center') {
+	    $currentstring='\begin{center}\par';
+	} elsif ($align eq 'right') {
+	    $currentstring='\makebox['.$ENV{'form.textwidth'}.']{\hfill\llap{';
+	} elsif ($align eq 'left') {
+	    $currentstring='\noindent\makebox['.$ENV{'form.textwidth'}.']{\rlap{';
+	} else {
+            $currentstring='\par ';
+        }
+	my $signal=1;#<p> does not work inside <b>...</b> 
+	foreach my $tag (@$tagstack) {if (lc($tag) eq 'b') {$signal=0;}
+	if (!$signal) {$currentstring = '';}
+	}
     }
     return $currentstring;
 }
 
 sub end_p {
-    my ($target,$token) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
+    } elsif ($target eq 'tex') {
+	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
+	if (not defined $align) {
+	    $currentstring.='\strut\\\\\strut ';
+	} elsif ($align eq 'center') {		
+	    $currentstring .= '\end{center}';
+	} elsif ($align eq 'right') {
+	    $currentstring .= '}}';
+	} elsif ($align eq 'left') {
+	    $currentstring .= '}\hfill}';
+	} 
     }
     return $currentstring;
 }
 
-#-- <br> tag
+#-- <br> tag (end tag forbidden)
 sub start_br {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	if ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') {
-	    $currentstring .= '\vskip 0.2 mm ';
+	my @tempo=@$tagstack;
+	my $signal=0;
+	for (my $i=$#tempo;$i>=0;$i--) {
+	    if (($tempo[$i] eq 'b') || ($tempo[$i] eq 'strong') ||
+                ($tempo[$i] eq 'ol') || ($tempo[$i] eq 'ul') ||
+                ($tempo[$i] eq 'td') || ($tempo[$i] eq 'th'))  {
+		$signal=1;
+		last;
+	    }
+	}
+	if ($signal) {
+	    $currentstring .= ' \vskip 0 mm ';
+	} elsif ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') {
+	    $currentstring .= '\strut \\\\ \strut ';
 	}
     }
     return $currentstring;
@@ -1126,7 +1192,7 @@ sub end_br {
     return $currentstring;
 }
 
-#-- <big> tag
+#-- <big> tag (end tag required)
 sub start_big {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1149,7 +1215,7 @@ sub end_big {
     return $currentstring;
 }
 
-#-- <small> tag
+#-- <small> tag (end tag required)
 sub start_small {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1172,7 +1238,7 @@ sub end_small {
     return $currentstring;
 }
 
-#-- <basefont> tag
+#-- <basefont> tag (end tag forbidden)
 sub start_basefont {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $currentstring = '';
@@ -1201,15 +1267,13 @@ sub end_basefont {
     return $currentstring;
 }
 
-#-- <font> tag
+#-- <font> tag (end tag required)
 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++;
-	} else {
+	if ($face!~/symbol/i) {
 	    if (($ENV{'browser.fontenhance'} eq 'on') || 
 		($ENV{'browser.blackwhite'} eq 'on')) { return ''; }
 	}
@@ -1227,8 +1291,6 @@ 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];    
     }  elsif ($target eq 'tex') {
 	my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
@@ -1239,7 +1301,7 @@ sub end_font {
     return $currentstring;
 }
  
-#-- <strike> tag
+#-- <strike> tag (end tag required)
 sub start_strike {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1265,7 +1327,7 @@ sub end_strike {
     return $currentstring;
 }
 
-#-- <s> tag
+#-- <s> tag (end tag required)
 sub start_s {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1291,14 +1353,14 @@ sub end_s {
     return $currentstring;
 }
 
-#-- <sub> tag
+#-- <sub> tag (end tag required)
 sub start_sub {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\$_{ ";
+	$currentstring .= '\ensuremath{_{';
     } 
     return $currentstring;
 }
@@ -1309,19 +1371,19 @@ sub end_sub {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= " }\$";
+	$currentstring .= '}}';
     }
     return $currentstring;
 }
 
-#-- <sup> tag
+#-- <sup> tag (end tag required)
 sub start_sup {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[4];
     } elsif ($target eq 'tex') {
-	$currentstring .= "\$^{ ";
+	$currentstring .= '\ensuremath{^{';
     } 
     return $currentstring;
 }
@@ -1332,12 +1394,12 @@ sub end_sup {
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring .= " }\$";
+	$currentstring .= '}}';
     }
     return $currentstring;
 }
 
-#-- <hr> tag
+#-- <hr> tag (end tag forbidden)
 sub start_hr {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -1377,7 +1439,7 @@ sub end_hr {
     return $currentstring;
 }
 
-#-- <div> tag
+#-- <div> tag (end tag required)
 sub start_div {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1396,7 +1458,7 @@ sub end_div {
     return $currentstring;
 }
 
-#-- <a> tag
+#-- <a> tag (end tag required)
 sub start_a {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -1418,7 +1480,7 @@ sub start_a {
 }
 
 sub end_a {
-    my ($target,$token,$tagstack,$parstack,$safeeval) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring .= $token->[2];
@@ -1426,24 +1488,35 @@ sub end_a {
     return $currentstring;
 }
 
-#-- <li> tag
+#-- <li> tag (end tag optional)
 sub start_li {
-    my ($target,$token,$tagstack,$parstack,$safeeval) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	my  $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,1);
-	if ($type=~/circle/) {
-	    $currentstring .= ' \item[o] ';
+	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[$\Box$] ';
-	} elsif ($type ne '') { 
-	    $currentstring .= ' \item['.$type.'] ';
+	    $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;
 }
 
@@ -1456,7 +1529,7 @@ sub end_li {
     return $currentstring;
 }
 
-#-- <u> tag
+#-- <u> tag (end tag required)
 sub start_u {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1482,7 +1555,7 @@ sub end_u {
     return $currentstring;
 }
 
-#-- <ul> tag
+#-- <ul> tag (end tag required)
 sub start_ul {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -1490,23 +1563,24 @@ sub start_ul {
 	$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$}';
+	    $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$}';
+	    $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 .= '\renewcommand{\labelitemi}{$\diamond$}'.
+                              '\renewcommand{\labelitemii}{$\diamond$}'. 
+                              '\renewcommand{\labelitemiii}{$\diamond$}'.
+                              '\renewcommand{\labelitemiv}{$\diamond$}';
 	}
-	$currentstring .= '\begin{itemize}';  
+	$currentstring .= '\strut \begin{itemize}';  
     } 
     return $currentstring;
 }
@@ -1517,15 +1591,15 @@ sub end_ul {
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}
-                                \renewcommand{\labelitemii}{$\bullet$} 
-                                \renewcommand{\labelitemiii}{$\bullet$}
-                                \renewcommand{\labelitemiv}{$\bullet$}';  
+	$currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}'.
+                               '\renewcommand{\labelitemii}{$\bullet$}'. 
+                               '\renewcommand{\labelitemiii}{$\bullet$}'.
+                               '\renewcommand{\labelitemiv}{$\bullet$}\strut ';  
     } 
     return $currentstring;
 }
 
-#-- <menu> tag
+#-- <menu> tag (end tag required)
 sub start_menu {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1548,7 +1622,7 @@ sub end_menu {
     return $currentstring;
 }
 
-#-- <dir> tag
+#-- <dir> tag (end tag required)
 sub start_dir {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -1571,41 +1645,42 @@ sub end_dir {
     return $currentstring;
 }
 
-#-- <ol> tag
+#-- <ol> tag (end tag required)
 sub start_ol {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$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}.}';
+	    $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}.}';
+	    $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}.} ';
+	    $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}.} ';
+	    $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}.} ';
+	    $currentstring .= '\renewcommand{\labelenumi}{\Roman{enumi}.}'.
+                              '\renewcommand{\labelenumii}{\Roman{enumii}.}'.
+                              '\renewcommand{\labelenumiii}{\Roman{enumiii}.}'.
+                              '\renewcommand{\labelenumiv}{\Roman{enumiv}.}';
 	}
-	$currentstring .= '\begin{enumerate}';  
+	$currentstring .= '\strut \begin{enumerate}';  
     } 
     return $currentstring;
 }
@@ -1616,123 +1691,172 @@ sub end_ol {
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\end{enumerate} \renewcommand{\labelenumi}{\arabic{enumi}.}
-                                          \renewcommand{\labelenumii}{\arabic{enumii}.}
-                                          \renewcommand{\labelenumiii}{\arabic{enumiii}.}
-                                          \renewcommand{\labelenumiv}{\arabic{enumiv}.}';  
+	$currentstring = '\end{enumerate}\renewcommand{\labelenumi}{\arabic{enumi}.}'.
+                                        '\renewcommand{\labelenumii}{\arabic{enumii}.}'.
+                                        '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'.
+                                        '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut ';  
     } 
     return $currentstring;
 }
 
-#-- <dl> tag
+#-- <dl> tag (end tag required)
 sub start_dl {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\begin{description}';  
+	$currentstring = '\begin{description}';
+	$Apache::londefdef::DL++;
+	push(@Apache::londefdef::description,[]);
+	$Apache::londefdef::DD[$Apache::londefdef::DL]=0;
+	$Apache::londefdef::DT[$Apache::londefdef::DL]=0;
+	$Apache::londefdef::seenDT[$Apache::londefdef::DL]=0;
     } 
     return $currentstring;
 }
 
 sub end_dl {
-    my ($target,$token) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\end{description}';  
+	if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
+	if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
+	foreach my $element (@{$Apache::londefdef::description[-1]}) {
+	    $currentstring.=' '.$element.' ';
+	}
+	pop(@Apache::londefdef::description);
+	$currentstring.='\end{description}';  
+	delete($Apache::londefdef::DD[$Apache::londefdef::DL]);
+	delete($Apache::londefdef::DT[$Apache::londefdef::DL]);
+	delete($Apache::londefdef::seenDT[$Apache::londefdef::DL]);
+	$Apache::londefdef::DL--;
     } 
     return $currentstring;
 }
 
-#-- <dt> tag
+#-- <dt> tag (end tag optional)
 sub start_dt {
-    my ($target,$token) = @_;
-    my $currentstring = '';
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
+    my $currentstring='';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	$currentstring = '\item[';  
+	if ($Apache::londefdef::DT[-1]) { &end_dt(@_); }
+	if ($Apache::londefdef::DD[-1]) { &end_dd(@_); }
+	&Apache::lonxml::startredirection();
+	$Apache::londefdef::DT[-1]++;
+	$Apache::londefdef::seenDT[-1]=1;
     } 
     return $currentstring;
 }
 
 sub end_dt {
-    my ($target,$token) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];    
     } elsif ($target eq 'tex') {
-	$currentstring = ']';  
+	if ($Apache::londefdef::DT[-1]) {
+	    my $data=&item_cleanup();
+	    push(@{$Apache::londefdef::description[-1]},'\item['.$data.'] \strut \vskip 0mm');
+	    $Apache::londefdef::DT[-1]--;
+	}
     } 
     return $currentstring;
 }
 
-#-- <dd> tag
+sub item_cleanup {
+    my $item=&Apache::lonxml::endredirection();
+    $item=~s/\\begin{center}//g;
+    $item=~s/\\end{center}//g;
+    return $item;
+}
+
+#-- <dd> tag (end tag optional)
 sub start_dd {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	if ($$tagstack[-2] eq 'dl') {
-	    $currentstring = ' \item [] ';  
-	} elsif ($$tagstack[-2] eq 'dt') {
-	    $currentstring = ']'; 
-	}
+	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) = @_;
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$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
+#-- <table> tag (end tag required)
+#list of supported attributes: border,width,TeXwidth
 sub start_table {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
-    my $textwidth='';
-    if (not defined @Apache::londefdef::table) {
-	$textwidth=&recalc($ENV{'form.textwidth'});
-	$textwidth=~/(\d+\.?\d*)/;
-	$textwidth=0.95*$1;
-    } else {
-	$textwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
-    }
-    my $currentstring = '';
+    my ($textwidth,$currentstring)=('','');
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
 	my $aa = {};
 	push @Apache::londefdef::table, $aa; 
 	$Apache::londefdef::table[-1]{'row_number'} = -1;
-        #table's width
+        #maximum table's width (default coincides with text line length)
+	if ($#Apache::londefdef::table==0) {
+	    $textwidth=&recalc($ENV{'form.textwidth'}); #result is always in mm
+	    $textwidth=~/(\d+\.?\d*)/;
+	    $textwidth=0.95*$1; #accounts "internal" LaTeX space for table frame
+	} else {
+	    if ($Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]=~/\d/) {
+		#the maximum width of nested table is determined by LATeX width of parent cell
+		$textwidth=$Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]; 
+	    } else {
+              #try to use all space not used before (minus 5% for LaTeX table internal) - rather silly
+		$textwidth=$Apache::londefdef::table[-2]{'width'};
+		for (my $i=0;$i<$Apache::londefdef::table[-2]{'counter_columns'};$i++) {
+		    $textwidth=$textwidth-$Apache::londefdef::table[-2]{'TeXlen'}[0][$i];
+		}
+	    }
+	}
 	my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
 	if (not defined $TeXwidth) {
 	    my $htmlwidth = &Apache::lonxml::get_param('width',$parstack,$safeeval,undef,1);
 	    if ($htmlwidth=~/%/) {
+                $Apache::londefdef::table[-1]{'percent'}=1;
 		$htmlwidth=~/(\d+)/;
-		my $value=$1*$textwidth/100;
-		$Apache::londefdef::table[-1]{'width'}=$value;
+		$Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100;;
 	    } else {
 		$Apache::londefdef::table[-1]{'width'}=$textwidth;
 	    }
 	} elsif ($TeXwidth=~/%/) {
+	    $Apache::londefdef::table[-1]{'percent'}=1;
 	    $TeXwidth=~/(\d+)/;
-	    my $value=$1*$textwidth/100;
-            $Apache::londefdef::table[-1]{'width'}=$value;
+            $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100;
 	} else {
-	    $Apache::londefdef::table[-1]{'width'}=$textwidth;
+	    $Apache::londefdef::table[-1]{'forcetablewidth'}=1;
+	    $Apache::londefdef::table[-1]{'width'}=$TeXwidth;
 	}        
         #table's border
-	my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval,undef,1); 
+	my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval); 
+        my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0);
 	unless (defined $border) { $border = 0; }
 	if ($border) { 
 	    $Apache::londefdef::table[-1]{'hinc'} = '\hline '; 
@@ -1743,9 +1867,19 @@ sub start_table {
 	    $Apache::londefdef::table[-1]{'vinc'} = '&'; 
 	    $Apache::londefdef::table[-1]{'vvinc'} = '';
 	}
-	$Apache::londefdef::table[-1]{'output'} = ' \noindent \begin{tabular} ';
-	$currentstring = '\keephidden{NEW TABLE ENTRY}';
-    }
+	if ($#Apache::londefdef::table==0) {
+	    $Apache::londefdef::table[-1]{'output'}='\strut\newline\strut\setlength{\tabcolsep}{1 mm}';
+	}
+	$Apache::londefdef::table[-1]{'output'}.=' \noindent \begin{tabular} ';
+        $Apache::londefdef::table[-1]{'TeXlen'}=[];
+        $Apache::londefdef::table[-1]{'objectlen'}=[];
+        $Apache::londefdef::table[-1]{'objectsignal'}=[];
+        $Apache::londefdef::table[-1]{'maxlen'}=[];
+        $Apache::londefdef::table[-1]{'minlen'}=[];
+        $Apache::londefdef::table[-1]{'content'}=[];
+        $Apache::londefdef::table[-1]{'align'}=[];
+        $currentstring='\keephidden{NEW TABLE ENTRY}';
+   }
     return $currentstring;
 }
  
@@ -1757,64 +1891,207 @@ sub end_table {
     } elsif ($target eq 'tex') {
 	my $inmemory = '';
 	my $output = '';
-	#construct header of the table
-	my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'};
-	for (my $in=0;$in<=$Apache::londefdef::table[-1]{'counter_columns'};$in++) {
-	    $header_of_table .= $Apache::londefdef::table[-1]{'columns'}[$in].$Apache::londefdef::table[-1]{'vvinc'};
+	my $WARNING='';
+        #width of columns from TeXwidth attributes
+	for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
+	    for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
+		if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]<$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn]) {
+		    $Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]=$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn];
+		}	
+	    }
 	}
-	$header_of_table .= '}';
-	#define the length of the table cells
-	#always starts with TeXwidth (if defined everything else is ignored)
-	my @length_row_final = split(/,/,$Apache::londefdef::table[-1]{'TeXlengthrow'}[0]);
-	for (my $in=1;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
-	    my @length_row = split(/,/,$Apache::londefdef::table[-1]{'TeXlengthrow'}[$in]);
-	    for (my $jn=0;$jn<=$#length_row;$jn++) {
-		if ($length_row_final[$jn]<$length_row[$jn]) {$length_row_final[$jn]=$length_row[$jn];}
-	    }
-	}
-	#continues trying estimate the width of raw data
-	my @length_raw_row = split(/,/,$Apache::londefdef::table[-1]{'lengthrow'}[0]);
-	for (my $in=1;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
-	    my @length_row = split(/,/,$Apache::londefdef::table[-1]{'lengthrow'}[$in]);
-	    for (my $jn=0;$jn<=$#length_row;$jn++) {
-		if ($length_raw_row[$jn]<$length_row[$jn]) {$length_raw_row[$jn]=$length_row[$jn];}
-	    }
-	}
-        #comparing of TeXwidth and raw data width
-	my $available_length=$Apache::londefdef::table[-1]{'width'};
-	my $needed=0;
-	for (my $jn=0;$jn<=$#length_row_final;$jn++) {
-	    if ($length_row_final[$jn]!=0) {
-		$available_length=$available_length-$length_row_final[$jn];
-		$needed++;
-	    }
-	}
-	$needed=$#length_row_final-$needed+1;
-	for (my $jn=0;$jn<=$#length_row_final;$jn++) {
-	    if ($length_row_final[$jn]==0) {
-		if ($length_raw_row[$jn]<$available_length/3) {
-		    $length_row_final[$jn]=$length_raw_row[$jn];
-		    $available_length=$available_length-$length_raw_row[$jn];
-		    $needed--;
+        #free space and number of empty columns
+	my ($available_space,$empty_columns)=($Apache::londefdef::table[-1]{'width'},0);
+	if ($#Apache::londefdef::table ne 0) {$available_space=0.9*$available_space;} 
+	for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
+	    if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]==0) {
+		$empty_columns++;
+	    } else {
+		$available_space=$available_space-$Apache::londefdef::table[-1]{'TeXlen'}[0][$jn];
+	    }
+	}
+        #boundaries for contents columns
+	my @min_len=();#columns can not be narrower 
+	my @max_len=();#maximum length of column
+	for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
+		my ($localmin,$localmax)=(0,0);
+		for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
+		    if ($localmin<$Apache::londefdef::table[-1]{'minlen'}[$in][$jn]) {
+			$localmin=$Apache::londefdef::table[-1]{'minlen'}[$in][$jn];
+		    }
+		    if ($localmax<$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn]) {
+			$localmax=$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn];
+		    }
+		}
+		push @min_len, $localmin;
+		push @max_len, $localmax;
+	}
+	for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
+	    my $localmin=0,;
+	    for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
+		if ($localmin<$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn]) {
+		    $localmin=$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn];
+		}
+	    }
+	    if ($max_len[$jn]<$localmin) {
+		$max_len[$jn]=$localmin;
+	    	$Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1;
+	    }#object size is bigger
+	    if ($min_len[$jn]<$localmin) {
+		$min_len[$jn]=$localmin;
+		$Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1;
+	    }#object size is bigger
+	    if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]!=0) {
+		$min_len[$jn]=0;
+		$max_len[$jn]=0;
+	    }
+	}
+       #final adjustment of column width
+	my @fwidth=@{$Apache::londefdef::table[-1]{'TeXlen'}[0]};#final width array
+	my @adjust=();
+        #step 1. adjustment by maximum value
+	my $space_neeeded=0;
+	for (my $jn=0;$jn<=$#max_len;$jn++) {
+	    $space_neeeded=$space_neeeded+$max_len[$jn];
+	}
+	if ($space_neeeded<=$available_space) {
+	    for (my $jn=0;$jn<=$#max_len;$jn++) {
+		if ($fwidth[$jn]==0) {
+		    $fwidth[$jn]=$max_len[$jn];
+		}
+	    }
+	} else {
+        #step 2. adjustment by minimum value (estimation)
+	    $space_neeeded=0;
+	    for (my $jn=0;$jn<=$#min_len;$jn++) {
+		$space_neeeded+=$min_len[$jn];
+	    }
+	    if ($space_neeeded>$available_space) {
+		$WARNING=' \textbf{NOT ENOUGH SPACE FOR TABLE} ';
+		for (my $jn=0;$jn<=$#max_len;$jn++) {
+		    if ($fwidth[$jn]==0) {
+			$fwidth[$jn]=$min_len[$jn];
+		    }
+		}
+		#check if we have objects which can be scaled
+		my $how_many_to_scale=0;
+		my @to_scale=();
+		for (my $jn=0;$jn<=$#max_len;$jn++) {
+		    if ($Apache::londefdef::table[-1]{'objectsignal'}[$jn] eq '1') {
+			$how_many_to_scale++;
+			push @to_scale, $jn;
+		    }
+		}
+		if ($how_many_to_scale>0) {
+		    my $space_to_adjust=($space_neeeded-$available_space)/$how_many_to_scale;
+		    foreach my $jn (@to_scale) {
+			for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
+			    $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/;
+			    if ($1 ne '') {
+				my $current_length=&recalc($1);
+				$current_length=~/(\d+\.?\d*)/;
+				$current_length=$current_length-$space_to_adjust;
+				$Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/width=$current_length mm/;
+			    }
+			    $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/\[(\d+\.?\d*)\s*mm\]/;
+			    if ($1 ne '') {
+				my $current_length=$1;
+				$current_length=$current_length-$space_to_adjust;
+				$Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/\[(\d+\.?\d*)\s*mm\]/\[$current_length mm\]/;
+			    }				
+			}
+			$fwidth[$jn]=$fwidth[$jn]-$space_to_adjust;
+		    }
+		}
+	    } else {
+	      #step 3. adjustment over minimal + corrections
+		my $enlarge_coef=$available_space/$space_neeeded;
+		my $acsessive=0;
+		for (my $jn=0;$jn<=$#min_len;$jn++) {
+		    $adjust[$jn]=$min_len[$jn]*$enlarge_coef;
+		    if ($adjust[$jn]>$max_len[$jn]) {
+			$fwidth[$jn]=$max_len[$jn];
+			$acsessive=$acsessive+$adjust[$jn]-$max_len[$jn];
+			$adjust[$jn]=0;
+		    }
+		}
+		if ($acsessive>0) {
+		#we have an excess of space and can redistribute it
+		    my $notempty_columns=0;
+		    for (my $jn=0;$jn<=$#min_len;$jn++) {
+			if ($adjust[$jn]!=0) {
+			    $notempty_columns++;
+			}
+		    }
+		    my $per_column=$acsessive/$notempty_columns;
+		    for (my $jn=0;$jn<=$#min_len;$jn++) {
+			if ($adjust[$jn]!=0) {
+			    $adjust[$jn]+=$per_column;
+			    $fwidth[$jn]=$adjust[$jn];
+			}
+		    }
+		} else {
+		    for (my $jn=0;$jn<=$#min_len;$jn++) {
+			$fwidth[$jn]=$adjust[$jn];
+		    }
 		}
 	    }
 	}
-	for (my $jn=0;$jn<=$#length_row_final;$jn++) {
-	    if ($length_row_final[$jn]==0) {
-		$length_row_final[$jn]=0.9*$available_length/$needed;
+        #use all available width if it is defined in % or as TeXwidth
+        if (($Apache::londefdef::table[-1]{'percent'}==1) || ($Apache::londefdef::table[-1]{'forcetablewidth'}==1)) {
+	    my $current=0; 
+	    for (my $i=0;$i<=$#fwidth;$i++) {  
+		$current+=$fwidth[$i];
+	    }
+	    my $coef=$Apache::londefdef::table[-1]{'width'}/$current;
+	    for (my $i=0;$i<=$#fwidth;$i++) {  
+		$fwidth[$i]*=$coef;
+	    }
+	}
+        #removing of empty columns if allowed
+        my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0);
+	if ($permission eq 'yes') {
+	    my @cleaned_table=();
+            my @cleaned_header=();
+	    my $colind=0;
+	    for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) {
+		if ($fwidth[$jn]!=0) {
+		    #we need to copy column
+		    for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
+			$cleaned_table[$in][$colind]=$Apache::londefdef::table[-1]{'content'}[$in][$jn];
+			$cleaned_header[$colind]=$fwidth[$jn];
+		    }
+		    $colind++;
+		}
 	    }
+	    $Apache::londefdef::table[-1]{'content'}=\@cleaned_table;
+	    @fwidth=@cleaned_header;
+	}
+	#construct header of the table
+	my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'};
+	for (my $in=0;$in<=$#fwidth;$in++) {
+	    $header_of_table.='p{'.$fwidth[$in].' mm}'.$Apache::londefdef::table[-1]{'vvinc'};
 	}
+	$header_of_table .= '}';
 	#fill the table
 	for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) {
-	    for (my $jn=0;$jn<=$#length_row_final;$jn++) {
-		my $substituted=$length_row_final[$jn];
-		$Apache::londefdef::table[-1]{'rowdata'}[$in]=~s/TOBECHANGEDONNUMBER/$substituted mm/;
-	    }
-	    $output .=  $Apache::londefdef::table[-1]{'rowdata'}[$in];
-	    chop $output;
-	    $output .= ' \\\\ ';
+	    for (my $jn=0;$jn<=$#fwidth;$jn++) {
+		if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') {
+		    $output.='\vspace*{-6 mm}\begin{center}';
+		} elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') {
+		    $output.=' \hfill \llap{'
+		}
+		$output.=$Apache::londefdef::table[-1]{'content'}[$in][$jn];
+		if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') {
+		    $output.='\end{center}\vspace*{-6 mm}';
+		} elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') {
+		    $output.='} ';
+		}
+                if ($jn!=$#fwidth) {$output.=' '.$Apache::londefdef::table[-1]{'vinc'};}
+	    }
+	    $output.=' \\\\ '.$Apache::londefdef::table[-1]{'hinc'}.' ';
 	}
-	$Apache::londefdef::table[-1]{'output'} .= $header_of_table.$output.$Apache::londefdef::table[-1]{'hinc'}.'\end{tabular}\vskip 0 mm ';
+	$Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut\newline\strut ';
 	if ($#Apache::londefdef::table > 0) {	    
 	    my $inmemory = $Apache::londefdef::table[-1]{'output'};
 	    pop @Apache::londefdef::table;
@@ -1828,7 +2105,7 @@ sub end_table {
     return $currentstring;
 }
 
-#-- <tr> tag
+#-- <tr> tag (end tag optional)
 sub start_tr {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -1836,16 +2113,19 @@ sub start_tr {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
 	$Apache::londefdef::table[-1]{'row_number'}++;
-	my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
+	my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
 	if ($alignchar ne '') {
-	    push @ {$Apache::londefdef::table[-1]{'rows'} }, $alignchar;
+	    push @ {$Apache::londefdef::table[-1]{'rows'} },substr($alignchar,0,1);
 	} else {
 	    push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l';
 	}
 	push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'});
 	$Apache::londefdef::table[-1]{'counter_columns'} = -1;
-	$Apache::londefdef::table[-1]{'TeXlength'} = '';
- 	$Apache::londefdef::table[-1]{'length'} = '';
+	push @ {$Apache::londefdef::table[-1]{'TeXlen'}}, [];
+	push @ {$Apache::londefdef::table[-1]{'objectlen'}}, [];
+	push @ {$Apache::londefdef::table[-1]{'minlen'}}, [];
+	push @ {$Apache::londefdef::table[-1]{'maxlen'}}, [];
+	push @ {$Apache::londefdef::table[-1]{'content'}}, [];
     } 
     return $currentstring;
 }
@@ -1859,13 +2139,11 @@ sub end_tr {
 	if ($Apache::londefdef::TD_redirection) {
 	    &end_td_tex($parstack,$parser,$safeeval);    
 	}
-	push @{ $Apache::londefdef::table[-1]{'TeXlengthrow'} },$Apache::londefdef::table[-1]{'TeXlength'};
-	push @{ $Apache::londefdef::table[-1]{'lengthrow'} },$Apache::londefdef::table[-1]{'length'};
     }
     return $currentstring;
 }
 
-#-- <td> tag
+#-- <td> tag (end tag optional)
 sub start_td {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $currentstring = '';
@@ -1897,12 +2175,18 @@ sub tag_check {
  
 sub start_td_tex {
     my ($parstack,$parser,$safeeval) = @_;
-    my $what_to_push = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
-    if ($what_to_push eq '') {
-	$what_to_push = substr($Apache::londefdef::table[-1]{'rows'}[0],0,1);;
+    my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
+    if ($alignchar eq '') {
+	$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
     }
-    push @{ $Apache::londefdef::table[-1]{'columns'} }, $what_to_push;
+    push @{ $Apache::londefdef::table[-1]{'align'}[$Apache::londefdef::table[-1]{'row_number'}] }, $alignchar;
     $Apache::londefdef::table[-1]{'counter_columns'}++;
+    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 '';
 }
@@ -1913,28 +2197,84 @@ sub end_td_tex {
     my $data=&Apache::lonxml::endredirection();
     my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
     if (defined $TeXwidth) {		
-	my $current_length=&recalc($TeXwidth);
-	$current_length=~/(\d+)/;
-	$Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';
-	$Apache::londefdef::table[-1]{'length'} .= '0,';
+	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)*)/) {
-	    my $current_length=&recalc($1);
-	    $current_length=~/(\d+\.?\d*)/;
-	    $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';
-	    $Apache::londefdef::table[-1]{'length'} .= '0,';
+	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';
+	} 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)*)//;
+	    }
+	    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)\s+$/$1/;
-	    my $current_length=2*length($data);
-	    $Apache::londefdef::table[-1]{'length'} .= $current_length.',';
-	    $Apache::londefdef::table[-1]{'TeXlength'} .= '0,';
+	    $data=~s/(\s)+/$1/;
+	    my ($current_length,$min_length)=(0,0);
+	    if ($data=~/\\vskip/) {
+                my $newdata=$data;
+		$newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g;
+		my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata);
+		foreach my $elementdata (@newdata) {
+		    my $lengthnewdata=2.5*&LATEX_length($elementdata);
+		    if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;}
+                    my @words=split(/ /,$elementdata);
+		    foreach my $word (@words) {
+			my $lengthword=2.5*&LATEX_length($word);
+			if ($min_length<$lengthword) {$min_length=$lengthword;}
+		    }
+		}
+	    } else {
+		$current_length=2.5*&LATEX_length($data);
+                    my @words=split(/ /,$data);
+		    foreach my $word (@words) {
+			my $lengthword=2*&LATEX_length($word);
+			if ($min_length<$lengthword) {$min_length=$lengthword;}
+		    }
+	    }
+	    push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length;
+	    push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length;
 	}        
     }
 	for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {         
 	    $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
 	}
-    @{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{TOBECHANGEDONNUMBER}{'.$data.'} '.$Apache::londefdef::table[-1]{'vinc'};
+    push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
     return'';
 }
 
@@ -1950,71 +2290,146 @@ sub end_td {
     return $currentstring;
 }
 
-#-- <th> tag
+#-- <th> tag (end tag optional)
 sub start_th {
     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();
+	$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 $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_th_tex {
+    my ($parstack,$parser,$safeeval) = @_;
+    my $current_row = $Apache::londefdef::table[-1]{'row_number'};
+    my $data=&Apache::lonxml::endredirection();
+    my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
+    if (defined $TeXwidth) {		
+	push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+    } else {
+	if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) {
+	    my $garbage_data=$data;
+	    my $fwidth=0;
+            while ($garbage_data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {
+		my $current_length=&recalc($1);
+		$current_length=~/(\d+\.?\d*)/;
+		if ($fwidth<$1) {$fwidth=$1;}
+		$garbage_data=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//;
+	    }
+            while ($garbage_data=~m/\[(\d+\.?\d*)\s*mm\]/) {
+		my $current_length=$1;
+		if ($fwidth<$current_length) {$fwidth=$current_length;}
+		$garbage_data=~s/\[(\d+\.?\d*)\s*mm\]//;
+	    }
+	    push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth;
+	    push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	} else {  
+	    $data=~s/^\s+(\S.*)/$1/; 
+	    $data=~s/(.*\S)\s+$/$1/;
+	    $data=~s/(\s)+/$1/;
+	    my ($current_length,$min_length)=(0,0);
+	    if ($data=~/\\vskip/) {
+                my $newdata=$data;
+		$newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g;
+		my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata);
+		foreach my $elementdata (@newdata) {
+		    my $lengthnewdata=2.5*&LATEX_length($elementdata);
+		    if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;}
+                    my @words=split(/ /,$elementdata);
+		    foreach my $word (@words) {
+			my $lengthword=2.5*&LATEX_length($word);
+			if ($min_length<$lengthword) {$min_length=$lengthword;}
+		    }
+		}
+	    } else {
+		$current_length=2.5*&LATEX_length($data);
+                    my @words=split(/ /,$data);
+		    foreach my $word (@words) {
+			my $lengthword=2*&LATEX_length($word);
+			if ($min_length<$lengthword) {$min_length=$lengthword;}
+		    }
+	    }
+	    push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0';
+	    push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length;
+	    push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length;
+	}        
+    }
+	for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {         
+	    $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
+	}
+    #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 = '';
     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();
-	my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
-	if (defined $TeXwidth) {		
-	    my $current_length=&recalc($TeXwidth);
-	    $current_length=~/(\d+)/;
-	    $Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';
-	    $Apache::londefdef::table[-1]{'length'} .= '0,';
-	} else {
-	    if ($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) {
-		my $current_length=&recalc($1);
-		$current_length=~/(\d+)/;
-		$Apache::londefdef::table[-1]{'TeXlength'} .= $1.',';
-		$Apache::londefdef::table[-1]{'length'} .= '0,';
-	    } else {     
-		$data=~/^\s*(\S.*)/;
-		$data=$1;
-		$data=~/(.*\S)\s*$/;
-		$data=$1;
-		my $current_length=2*length($data);
-		$Apache::londefdef::table[-1]{'length'} .= $current_length.',';
-		$Apache::londefdef::table[-1]{'TeXlength'} .= '0,';
-	    }        
-	}
-	for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) {                                
-	    $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/;
-	}
-	$data='\textbf{'.$data.'}';
-	@{ $Apache::londefdef::table[-1]{'rowdata'} }[$current_row] .= '\parbox{TOBECHANGEDONNUMBER}{'.$data.'} '.$Apache::londefdef::table[-1]{'vinc'};
+        $Apache::londefdef::TD_redirection =0;
+	&end_th_tex($parstack,$parser,$safeeval);
     }
     return $currentstring;
 }
-#-- <img> tag
+     
+#-- <img> tag (end tag forbidden)
 sub start_img {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,
 					 undef,1);
+    if (not $src and ($target eq 'web' or $target eq 'tex')) { 
+	my $inside = &Apache::lonxml::get_all_text("/img",$parser);
+	return '';
+    }
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=$src;
     my $currentstring = '';
-    my $width_param = '';
-    my $height_param = '';
     my $scaling = .3;
     if ($target eq 'web') {
 	if ($ENV{'browser.imagesuppress'} ne 'on') {
@@ -2029,47 +2444,57 @@ sub start_img {
 	    $currentstring.='[IMAGE: '.$alttag.']';
 	}
     } 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 = "parbox";
+	}
+	&Apache::lonxml::debug("LaTeX rendering = $latex_rendering");
+
+	my $oldSRC=$src;
+        $oldSRC=~s/\.(gif|jpg|png)$/\.eps/;
 	$src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);
-	&image_replication($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;      
-	    }
-	    if ($width_param > $ENV{'form.textwidth'}) {$width_param =0.95*$ENV{'form.textwidth'}}
-	    my $file;
-	    my $path;	
-	    if ($src =~ m!(.*)/([^/]*)$!) {
-		$file = $2; 
-		$path = $1.'/'; 
-	    } 
+	if (-e $src) {
+	    #what is the image size?
+	    my $width_param=&image_width($src,$scaling,$parstack,$safeeval);
+	    my $height_param=&image_height($src,$scaling,$parstack,$safeeval);
+            my ($file,$path)=&file_path($src); 
 	    my $newsrc = $src;
 	    $newsrc =~ s/\.(gif|jpg|png)$/.eps/i;
+	    &Apache::lonnet::repcopy($oldSRC);
 	    $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.'} ';
+		    $currentstring .= '\graphicspath{{'.$path.'}}'
+			             .'\includegraphics[width='.$width_param.' mm,height='.$height_param.'mm]{'.$file.'} ';
 		}
 	    } else {
 		#there is no eps counterpart for image - check for ps one
@@ -2078,16 +2503,41 @@ sub start_img {
 		    #ps counterpart for image exist 
 		    $file =~ s/\.eps$/\.ps/;
 		    if ($path) {
-			$currentstring .= '\vskip 1 mm \noindent\graphicspath{{'.$path.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';
+			$currentstring .= '\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.'} ';
+		    #care about eps dynamical generation
+		    $currentstring.=&eps_generation($src,$file,$width_param);
+		}
+	    }
+	    #    If there's an alignment specification we need to honor it here.
+	    #    For the horizontal alignments, we will also honor the
+	    #    value of the latex specfication.  The default is parbox,
+	    #    and that's used for illegal values too.  
+	    #    
+	    #    Even though we set a default alignment value, the user
+	    #    could have given us an illegal value.  In that case we
+	    #    just use the default alignment of bottom..
+	    if      ($align eq "top")    {
+		$currentstring = '\raisebox{-'.$height_param.'mm}{'.$currentstring.'}';
+	    } elsif (($align eq "center") || ($align eq "middle")) { # Being kind
+		my $offset = $height_param/2;
+		$currentstring = '\raisebox{-'.$offset.'mm}{'.$currentstring.'}';
+	    } elsif ($align eq "left")   { 
+		if ($latex_rendering eq "parpic") { 
+		    $currentstring = '\parpic[l]{'.$currentstring.'}';
+		} else {    	                                 # parbox rendering
+		    $currentstring = '\newline'."\n".'\parbox{'.$width_param.'mm}{'.$currentstring.'}';
 		}
+	    } elsif ($align eq "right")  {   
+		if ($latex_rendering eq "parpic") {
+		    $currentstring = '\parpic[r]{'.$currentstring.'}';
+		} else {	                                 # parbox rendering. 
+		    $currentstring = '\parbox{'.$width_param.'mm}{\begin{flushright}'
+			             .$currentstring.'\end{flushright}} \newline'."\n";
+		}
+	    } else {		# Bottom is also default.
+		# $currentstring = '\raisebox{'.$height_param.'mm}{'.$currentstring.'}';
 	    }
 	} else {
 	    #original image file doesn't exist so check the alt attribute
@@ -2103,6 +2553,67 @@ sub start_img {
 		#<allow> tag will care about replication 
 	    }
 	}
+    } elsif ($target eq 'edit') {
+	$currentstring .=&Apache::edit::tag_start($target,$token);
+	$currentstring .=&Apache::edit::text_arg('Image Url:','src',$token,70).
+	    &Apache::edit::browse('src',undef,'alt').' '.
+	    &Apache::edit::search('src',undef,'alt').'<br />';
+	$currentstring .=&Apache::edit::text_arg('Description:','alt',$token,70).'<br />';
+	$currentstring .=&Apache::edit::text_arg('width (pixel):','width',$token,5);
+	$currentstring .=&Apache::edit::text_arg('height (pixel):','height',$token,5).'<br />';
+	$currentstring .=&Apache::edit::text_arg('TeXwidth (mm):','TeXwidth',$token,5);
+	$currentstring .=&Apache::edit::text_arg('TeXheight (mm):','TeXheight',$token,5);
+	$currentstring .=&Apache::edit::select_arg('Alignment:','align',
+						   ['','bottom','middle','top','left','right'],$token,5);
+	$currentstring .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
+	my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval);
+	my $alt=&Apache::lonxml::get_param('alt',$parstack,$safeeval);
+	my $width=&Apache::lonxml::get_param('width',$parstack,$safeeval);
+	my $height=&Apache::lonxml::get_param('height',$parstack,$safeeval);
+	$currentstring .= '<img src="'.$src.'" alt="'.$alt.'" ';
+	if ($width) { $currentstring.=' width="'.$width.'" '; }
+	if ($height) { $currentstring.=' height="'.$height.'" '; }
+	$currentstring .= ' />';
+    } elsif ($target eq 'modified') {
+	my ($osrc,$owidth,$oheight)=
+	    ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'});
+	my $ctag=&Apache::edit::get_new_args($token,$parstack,
+					     $safeeval,'src','alt','align',
+					     'TeXwidth','TeXheight',
+					     'width','height');
+	my ($nsrc,$nwidth,$nheight)=
+	    ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'});
+	my $loc=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$nsrc);
+	&image_replication($loc);
+	my ($iwidth,$iheight);
+	if (-e $loc) {
+	    my $image = Image::Magick->new;
+	    $image->Read($loc);
+	    ($iwidth, $iheight) = ($image->Get('width'),
+				   $image->Get('height'));
+	}
+	if ($osrc ne $nsrc || (!$nwidth && !$nheight)) {
+	    # changed image or no size specified,
+            # if they didn't explicitly change the 
+            # width or height use the ones from the image
+	    if ($iwidth && $iheight) {
+		if ($owidth == $nwidth || (!$nwidth && !$nheight)) {
+		    $token->[2]{'width'} = $iwidth;$ctag=1;
+		}
+		if ($oheight == $nheight || (!$nwidth && !$nheight)) {
+		    $token->[2]{'height'}=$iheight;$ctag=1;
+		}
+	    }
+	}
+	my ($cwidth,$cheight)=($token->[2]{'width'},$token->[2]{'height'});
+	# if we don't have a width or height
+	if ($iwidth && $cwidth && !$cheight) {
+	    $token->[2]{'height'}=int(($cwidth/$iwidth)*$iheight);$ctag=1;
+	}
+	if ($iheight && $cheight && !$cwidth) {
+	    $token->[2]{'width'}=int(($cheight/$iheight)*$iwidth);$ctag=1;
+	}
+	if ($ctag) {$currentstring=&Apache::edit::rebuild_tag($token);}
     }
     return $currentstring;
 }
@@ -2118,7 +2629,7 @@ sub end_img {
     return $currentstring;
 }
 
-#-- <applet> tag
+#-- <applet> tag (end tag required)
 sub start_applet {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     
@@ -2143,7 +2654,16 @@ sub start_applet {
 	    $currentstring='[APPLET: '.$alttag.']';
 	}
     } elsif ($target eq 'tex') {
-	$currentstring = " \\begin{figure} ";
+	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}';
     } 
     return $currentstring;
 }
@@ -2154,12 +2674,11 @@ sub end_applet {
     if ($target eq 'web') {
 	$currentstring = $token->[2];
     } elsif ($target eq 'tex') {
-	$currentstring = " \\end{figure}";
     } 
     return $currentstring;
 }
 
-#-- <embed> tag
+#-- <embed> tag (end tag optional/required)
 sub start_embed {    
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1);
@@ -2177,7 +2696,6 @@ sub start_embed {
 	    $currentstring='[EMBED: '.$alttag.']';
 	}
     } elsif ($target eq 'tex') {
-	$currentstring = " \\begin{figure} ";  
     } 
     return $currentstring;
 }
@@ -2187,13 +2705,12 @@ sub end_embed {
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
-    } elsif ($target eq 'tex') {
-	$currentstring = " \\end{figure}";  
+    } elsif ($target eq 'tex') {  
     } 
     return $currentstring;
 }
 
-#-- <param> tag
+#-- <param> tag (end tag forbidden)
 sub start_param {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     if (&Apache::lonxml::get_param
@@ -2207,7 +2724,6 @@ sub start_param {
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
-	$currentstring = " \\begin{figure} ";  
     } 
     return $currentstring;
 }
@@ -2218,7 +2734,6 @@ sub end_param {
     if ($target eq 'web') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
-	$currentstring = " \\end{figure}";  
     } 
     return $currentstring;
 }
@@ -2230,7 +2745,7 @@ sub start_allow {
     $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src);
     $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=
 	&Apache::lonnet::clutter($src);
-    &image_replication($src);
+    if ($target eq 'tex') { &image_replication($src); }
     my $result;
     if ($target eq 'edit') {
 	$result .=&Apache::edit::tag_start($target,$token);
@@ -2250,12 +2765,14 @@ sub end_allow {
     return '';
 }
 
-#-- Frames
+#-- Frames (end tag required)
+#-- <frameset>
 sub start_frameset {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') { 
-	if (!$Apache::lonxml::registered) {
+	if (!$Apache::lonxml::registered &&
+	    $ENV{'request.state'} eq 'published') {
 	    $currentstring.='<head>'.
 		&Apache::lonmenu::registerurl(undef,$target).'</head>';
 	}
@@ -2295,7 +2812,30 @@ sub end_frameset {
     return $currentstring;
 }
 
-#-- <pre>
+#-- <xmp> (end tag required)
+sub start_xmp {
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
+    my $currentstring = '';
+    if ($target eq 'web') {
+	$currentstring .= $token->[4];
+    } elsif ($target eq 'tex') {
+	$currentstring .= '\begin{verbatim}';
+    } 
+    return $currentstring;
+}
+
+sub end_xmp {
+    my ($target,$token) = @_;
+    my $currentstring = '';
+    if ($target eq 'web') {
+	$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 = '';
@@ -2378,7 +2918,7 @@ sub end_blankspace {
     return $currentstring;
 }
 
-#-- <abbr> tag
+#-- <abbr> tag (end tag required)
 sub start_abbr {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2397,7 +2937,7 @@ sub end_abbr {
     return $currentstring;
 }
 
-#-- <acronym> tag
+#-- <acronym> tag (end tag required)
 sub start_acronym {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2416,7 +2956,7 @@ sub end_acronym {
     return $currentstring;
 }
 
-#-- <area> tag
+#-- <area> tag (end tag forbidden)
 sub start_area {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2435,7 +2975,7 @@ sub end_area {
     return $currentstring;
 }
 
-#-- <base> tag
+#-- <base> tag (end tag forbidden)
 sub start_base {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2454,7 +2994,7 @@ sub end_base {
     return $currentstring;
 }
 
-#-- <bdo> tag
+#-- <bdo> tag (end tag required)
 sub start_bdo {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2473,7 +3013,7 @@ sub end_bdo {
     return $currentstring;
 }
 
-#-- <bgsound> tag
+#-- <bgsound> tag (end tag optional)
 sub start_bgsound {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2492,7 +3032,7 @@ sub end_bgsound {
     return $currentstring;
 }
 
-#-- <blink> tag
+#-- <blink> tag (end tag required)
 sub start_blink {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2511,7 +3051,7 @@ sub end_blink {
     return $currentstring;
 }
 
-#-- <blockquote> tag
+#-- <blockquote> tag (end tag required)
 sub start_blockquote {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2530,7 +3070,7 @@ sub end_blockquote {
     return $currentstring;
 }
 
-#-- <button> tag
+#-- <button> tag (end tag required)
 sub start_button {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2549,7 +3089,7 @@ sub end_button {
     return $currentstring;
 }
 
-#-- <caption> tag
+#-- <caption> tag (end tag required)
 sub start_caption {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2568,7 +3108,7 @@ sub end_caption {
     return $currentstring;
 }
 
-#-- <col> tag
+#-- <col> tag (end tag forbdden)
 sub start_col {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2587,7 +3127,7 @@ sub end_col {
     return $currentstring;
 }
 
-#-- <colgroup> tag
+#-- <colgroup> tag (end tag optional)
 sub start_colgroup {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2606,7 +3146,7 @@ sub end_colgroup {
     return $currentstring;
 }
 
-#-- <del> tag
+#-- <del> tag (end tag required)
 sub start_del {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2625,7 +3165,7 @@ sub end_del {
     return $currentstring;
 }
 
-#-- <fieldset> tag
+#-- <fieldset> tag (end tag required)
 sub start_fieldset {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2644,7 +3184,7 @@ sub end_fieldset {
     return $currentstring;
 }
 
-#-- <frame> tag
+#-- <frame> tag (end tag forbidden)
 sub start_frame {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2663,7 +3203,7 @@ sub end_frame {
     return $currentstring;
 }
 
-#-- <iframe> tag
+#-- <iframe> tag (end tag required)
 sub start_iframe {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2682,7 +3222,7 @@ sub end_iframe {
     return $currentstring;
 }
 
-#-- <ins> tag
+#-- <ins> tag (end tag required)
 sub start_ins {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2701,7 +3241,7 @@ sub end_ins {
     return $currentstring;
 }
 
-#-- <isindex> tag
+#-- <isindex> tag (end tag forbidden)
 sub start_isindex {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2720,7 +3260,7 @@ sub end_isindex {
     return $currentstring;
 }
 
-#-- <keygen> tag
+#-- <keygen> tag (end tag forbidden)
 sub start_keygen {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2758,7 +3298,7 @@ sub end_label {
     return $currentstring;
 }
 
-#-- <layer> tag
+#-- <layer> tag (end tag required)
 sub start_layer {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2777,7 +3317,7 @@ sub end_layer {
     return $currentstring;
 }
 
-#-- <legend> tag
+#-- <legend> tag (end tag required)
 sub start_legend {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2796,7 +3336,7 @@ sub end_legend {
     return $currentstring;
 }
 
-#-- <link> tag
+#-- <link> tag (end tag forbidden)
 sub start_link {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2815,7 +3355,7 @@ sub end_link {
     return $currentstring;
 }
 
-#-- <marquee> tag
+#-- <marquee> tag (end tag optional)
 sub start_marquee {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2834,8 +3374,8 @@ sub end_marquee {
     return $currentstring;
 }
 
-#-- <malticol> tag
-sub start_malticol {
+#-- <multicol> tag (end tag required)
+sub start_multicol {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
@@ -2844,7 +3384,7 @@ sub start_malticol {
     return $currentstring;
 }
 
-sub end_malticol {
+sub end_multicol {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
@@ -2853,13 +3393,15 @@ sub end_malticol {
     return $currentstring;
 }
 
-#-- <nobr> tag
+#-- <nobr> tag (end tag required)
 sub start_nobr {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
-    } 
+    }  elsif ($target eq 'tex') {
+	$currentstring='\mbox{';
+    }
     return $currentstring;
 }
 
@@ -2868,11 +3410,13 @@ sub end_nobr {
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];    
-    } 
+    }   elsif ($target eq 'tex') {
+	$currentstring='}';
+    }
     return $currentstring;
 }
 
-#-- <noembed> tag
+#-- <noembed> tag (end tag required)
 sub start_noembed {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2891,7 +3435,7 @@ sub end_noembed {
     return $currentstring;
 }
 
-#-- <noframes> tag
+#-- <noframes> tag (end tag required)
 sub start_noframes {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2910,7 +3454,7 @@ sub end_noframes {
     return $currentstring;
 }
 
-#-- <nolayer> tag
+#-- <nolayer> tag (end tag required)
 sub start_nolayer {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2929,7 +3473,7 @@ sub end_nolayer {
     return $currentstring;
 }
 
-#-- <noscript> tag
+#-- <noscript> tag (end tag required)
 sub start_noscript {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2948,7 +3492,7 @@ sub end_noscript {
     return $currentstring;
 }
 
-#-- <object> tag
+#-- <object> tag (end tag required)
 sub start_object {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2967,7 +3511,7 @@ sub end_object {
     return $currentstring;
 }
 
-#-- <optgroup> tag
+#-- <optgroup> tag (end tag required)
 sub start_optgroup {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -2986,13 +3530,15 @@ sub end_optgroup {
     return $currentstring;
 }
 
-#-- <samp> tag
+#-- <samp> tag (end tag required)
 sub start_samp {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
-    } 
+    } elsif ($target eq 'tex') {
+	$currentstring='\texttt{';
+    }
     return $currentstring;
 }
 
@@ -3001,7 +3547,9 @@ sub end_samp {
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[2];    
-    } 
+    } elsif ($target eq 'tex') {
+	$currentstring='}';
+    }
     return $currentstring;
 }
 
@@ -3024,7 +3572,7 @@ sub end_server {
     return $currentstring;
 }
 
-#-- <spacer> tag
+#-- <spacer> tag (end tag forbidden)
 sub start_spacer {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3043,7 +3591,7 @@ sub end_spacer {
     return $currentstring;
 }
 
-#-- <span> tag
+#-- <span> tag (end tag required)
 sub start_span {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3062,7 +3610,7 @@ sub end_span {
     return $currentstring;
 }
 
-#-- <tbody> tag
+#-- <tbody> tag (end tag optional)
 sub start_tbody {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3081,7 +3629,7 @@ sub end_tbody {
     return $currentstring;
 }
 
-#-- <tfoot> tag
+#-- <tfoot> tag (end tag optional)
 sub start_tfoot {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3100,7 +3648,7 @@ sub end_tfoot {
     return $currentstring;
 }
 
-#-- <thead> tag
+#-- <thead> tag (end tag optional)
 sub start_thead {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3125,7 +3673,9 @@ sub start_var {
     my $currentstring = '';
     if ($target eq 'web') {
 	$currentstring = $token->[4];     
-    } 
+    } elsif ($target eq 'tex') {
+	$currentstring = '\textit{'; 
+    }
     return $currentstring;
 }
 
@@ -3133,12 +3683,14 @@ sub end_var {
     my ($target,$token) = @_;
     my $currentstring = '';
     if ($target eq 'web') {
-	$currentstring = $token->[2];    
+	$currentstring = $token->[2];
+    } elsif ($target eq 'tex') {
+	$currentstring = '}'; 
     } 
     return $currentstring;
 }
 
-#-- <wbr> tag
+#-- <wbr> tag (end tag forbidden)
 sub start_wbr {
     my ($target,$token) = @_;
     my $currentstring = '';
@@ -3178,22 +3730,92 @@ sub end_hideweboutput {
 
 sub image_replication {
     my $src = shift;
-    if (not -e $src) {
-	#replicates image itself
-	&Apache::lonnet::repcopy($src);
-	#replicates eps or ps 
-	my $newsrc = $src;
-	$newsrc =~ s/\.(gif|jpg|jpeg|png)$/.eps/i;
-	if (not -e $newsrc) {
-	    if (&Apache::lonnet::repcopy($newsrc) ne 'OK') {
-		$newsrc =~ s/\.eps$/\.ps/;
-		&Apache::lonnet::repcopy($newsrc);
-	    }
-	}
+    if (not -e $src) { &Apache::lonnet::repcopy($src); }
+    #replicates eps or ps 
+    my $epssrc = my $pssrc = $src;
+    $epssrc =~ s/\.(gif|jpg|jpeg|png)$/.eps/i;
+    $pssrc  =~ s/\.(gif|jpg|jpeg|png)$/.ps/i;
+    if (not -e $epssrc && not -e $pssrc) {
+	my $result=&Apache::lonnet::repcopy($epssrc);
+	if ($result ne OK) { &Apache::lonnet::repcopy($pssrc); }
     }
     return '';
 }
 
+sub image_size {
+    my ($src,$scaling,$parstack,$safeeval)=@_;
+    #size of image from gif/jpg/jpeg/png 
+    my $image = Image::Magick->new;
+    my $current_figure = $image->Read($src);
+    my $width_param = $image->Get('width') * $scaling;;
+    my $height_param = $image->Get('height') * $scaling;;
+    undef $image;
+    #do we have any specified LaTeX size of the picture?
+    my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval);
+    my $TeXheight = &Apache::lonxml::get_param('TeXheight',$parstack,$safeeval);
+    #do we have any specified web size of the picture?
+    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 '') {
+	$height_param = $TeXheight;
+	$width_param  = $TeXheight/$height_param*$width_param;
+    } elsif ($width ne '') {
+	$width_param = $width*$scaling;      
+    }
+    if ($width_param > $ENV{'form.textwidth'}) {$width_param =0.95*$ENV{'form.textwidth'}}
+    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 eps_generation {
+    my ($src,$file,$width_param) = @_;	     
+    my $filename = "/home/httpd/prtspool/$ENV{'user.name'}_$ENV{'user.domain'}_printout.dat";
+    my $temp_file = Apache::File->new('>>'.$filename); 
+    print $temp_file "$src\n";
+    my $newsrc = $src;
+    $newsrc =~ s/(\.gif|\.jpg|\.jpeg)$/\.eps/i;
+    $newsrc=~s/\/home\/httpd\/html\/res//;
+    $newsrc=~s/\/home\/([^\/]*)\/public_html\//\/$1\//;
+    $newsrc=~s/\/\.\//\//;
+    $newsrc=~s/\/([^\/]+)\.(ps|eps)/\//;
+    if ($newsrc=~/\/home\/httpd\/lonUsers\//) {
+	$newsrc=~s/\/home\/httpd\/lonUsers//;
+	$newsrc=~s/\/([^\/]+)\/(\w)\/(\w)\/(\w)\//\/$1\//;
+    }
+    if ($newsrc=~/\/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';}
@@ -3212,5 +3834,33 @@ sub recalc {
     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;
+}
+
+
+
+
 1;
 __END__