--- loncom/xml/londefdef.pm	2008/11/24 18:55:01	1.397
+++ loncom/xml/londefdef.pm	2009/05/28 12:39:12	1.408
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Tags Default Definition Module 
 #
-# $Id: londefdef.pm,v 1.397 2008/11/24 18:55:01 jms Exp $
+# $Id: londefdef.pm,v 1.408 2009/05/28 12:39:12 bisitz Exp $
 # 
 #
 # Copyright Michigan State University Board of Trustees
@@ -42,6 +42,7 @@ package Apache::londefdef;
 use Apache::lonnet;
 use strict;
 use Apache::lonxml;
+use Apache::lontable;
 use Apache::File();
 use Image::Magick;
 use Apache::lonmenu();
@@ -58,20 +59,7 @@ BEGIN {
 
 }
 
-#
-#   Dumps all elements of the table structure.
-#   Need this 'cause evidently when given an array, Data::Dumper only seems
-#   to dump element 0.
-#
-#sub debug_dump_table {
-#    my $lastrow = $#Apache::londefdef::table;
-#    &Apache::lonnet::logthis("Dumping table:  Last row index: $lastrow");
-#    my $row;
-#    for ($row =0; $row <= $lastrow; $row++ ) {
-#	my $text = Dumper($Apache::londefdef::table[$row]);
-#	&Apache::lonnet::logthis("table [ $row ]".$text);
-#    }
-#}
+
 sub initialize_londefdef {
     $Apache::londefdef::TD_redirection=0;
     @Apache::londefdef::table = ();
@@ -188,41 +176,8 @@ sub start_html {
     if ($target eq 'web' || $target eq 'edit' || $target eq 'webgrade' ) {
 	# start_body() takes care of emitting the <html> 
     } elsif ($target eq 'tex') {
-	$currentstring .= 
-	    '\documentclass[letterpaper,twoside]{article}\raggedbottom';
-	if (($env{'form.latex_type'}=~'batchmode') ||
-            (!$env{'request.role.adv'})) {$currentstring .='\batchmode';} 
-	$currentstring .= '\newcommand{\keephidden}[1]{}'.
-                          '\renewcommand{\deg}{$^{\circ}$}'.
-			  '\usepackage{multirow}'.
-                          '\usepackage{longtable}'.
-                          '\usepackage{textcomp}'.
-                          '\usepackage{makeidx}'.
-                          '\usepackage[dvips]{graphicx}'.
-			  '\usepackage{wrapfig}'.
-			  '\usepackage{picins}'.
-			  '\usepackage[T1]{fontenc}'."\n".
-                          '\usepackage{lmodern}'."\n".
-			  '\usepackage[postscript]{ucs}'."\n".
-			  '\usepackage[utf8x]{inputenc}'."\n".
-			  '\usepackage{pifont}' ."\n".
-			  '\usepackage{latexsym}'."\n".
-                          '\usepackage{epsfig}'.
-                          '\usepackage{calc}'.
-                          '\usepackage{amsmath}'.
-                          '\usepackage{amssymb}'.
-                          '\usepackage{amsfonts}'.
-                          '\usepackage{amsthm}'.
-                          '\usepackage{amscd}';
-
-        if($env{'form.pdfFormFields'} eq 'yes') {
-            $currentstring .= '\usepackage{hyperref}'.
-                              '\usepackage{eforms}'.
-                              '\usepackage{tabularx}';
-        } 
 
-        $currentstring .= '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'.
-                          '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}';
+	$currentstring .= &latex_header();
     }
     return $currentstring;
 }
@@ -583,36 +538,60 @@ sub start_body {
 	
 	my $extra_head = &generate_css_links();
 
+    # Breadcrumbs
+    &Apache::lonhtmlcommon::clear_breadcrumbs();
+    &Apache::lonhtmlcommon::add_breadcrumb({
+        'text'  => 'Construction Space',
+        'href'  => '', # FIXME Add link to /priv/[user]
+    });
+    &Apache::lonhtmlcommon::add_breadcrumb({
+        'text'  => 'HTML Editor',
+        'href'  => '',
+    });    
+
 	$currentstring = 
 	    &Apache::loncommon::start_page($Apache::londefdef::title,
 					   $Apache::londefdef::head
 					      .$extra_head,
 					   {'add_entries'    => $token->[2],
-					    'no_title'       => 1,
+#					    'no_title'       => 1,
 					    'force_register' => 1});
 
-	if ($env{'request.state'} ne 'published') {
-	    $currentstring.=&Apache::lonmenu::constspaceform();
-	    $currentstring.=&Apache::londefdef::edit_controls();
-	}
-	$currentstring.=&Apache::lonxml::message_location();
+    $currentstring .= &Apache::lonhtmlcommon::breadcrumbs();
+
+        my $header = '';
+        if ($env{'request.state'} ne 'published') {
+            $header=&Apache::lonmenu::constspaceform()
+                   .&Apache::londefdef::edit_controls();
+        }
+        $currentstring.=&Apache::loncommon::head_subbox(
+                            &Apache::loncommon::CSTR_pageheader()
+                           .$header);
+        $currentstring.=&Apache::lonxml::message_location();
     } elsif ($target eq 'tex') {
-	$currentstring = '\begin{document}';  
-    } 
+        $currentstring = '';   #  '\begin{document}' is in header.
+    }
+
     return $currentstring;
 }
 
 sub edit_controls {
+    my ($nochgview) = @_;
     my $result .= '
 <form method="post">
-<div class="LC_edit_problem_header">
+<div class="LC_edit_problem_header">';
+    unless ($nochgview) {
+        $result .= '
 <div class="LC_edit_problem_header_row1">'.
 &Apache::lonxml::renderingoptions().'
 <input type="submit" name="changeproblemmode" value="'.&mt('Change View').'" />
+</div>';
+    }
+    $result .= '
+<div><input type="submit" name="editmode" accesskey="e" value="'.&mt('Edit').'" /></div>
 </div>
-<div class="LC_edit_problem_header_edit_row"><input type="submit" name="editmode" accesskey="e" value="'.&mt('Edit').'" /></div></div>
 </form>
-<br />';
+';
     return $result;
 }
 
@@ -1389,10 +1368,6 @@ sub start_font {
     my $currentstring = '';
     if ($target eq 'web' || $target eq 'webgrade') {
 	my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval);
-	if ($face!~/symbol/i) {
-	    if (($env{'browser.fontenhance'} eq 'on') || 
-		($env{'browser.blackwhite'} eq 'on')) { return ''; }
-	}
 	$currentstring = $token->[4];     
     }  elsif ($target eq 'tex') {
 	my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval);
@@ -1657,6 +1632,26 @@ sub start_a {
 	my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval,
 					    undef,1);
 	$currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href});
+        if ($href =~ /\S/) {
+            if ($href !~ m{^https?://}) {
+                my $url=&Apache::lonnet::hreflocation('',$env{'request.filename'});
+                my $linkurl;
+                if ($href =~ m{^/uploaded/}) {
+                    $linkurl = $href;
+                } elsif ($href =~ m{^[^/]}) {
+                    my $path = $url;
+                    $path  =~ s{[^/]*$}{};
+                    $linkurl = $path.$href;
+                }
+                if ($linkurl =~ m{^/uploaded/}) {
+                    if (!&Apache::lonnet::allowed('bre',$linkurl)) {
+                        if (&Apache::lonnet::is_on_map($url)) {
+                            &Apache::lonxml::extlink($linkurl);
+                        }
+                    }
+                }
+            }
+        }
     }
     return $currentstring;
 }
@@ -2018,7 +2013,8 @@ sub end_dd {
 #               only way I could think of to allow <p> in 
 #               <tr> <th> bodies
 #
-#list of supported attributes: border,width,TeXwidth
+#list of supported attributes: border,width,TeXwidth,TeXtheme
+#                              align
 sub start_table {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_;
     my $textwidth = '';
@@ -2027,6 +2023,59 @@ sub start_table {
 	$currentstring .= $token->[4];     
     } elsif ($target eq 'tex') {
 	&disable_para();	# Can't have paras in a table.
+
+
+	#  New table code:
+
+	#  Get the parameters that we can do something about:
+
+	my $border = &Apache::lonxml::get_param('border', $parstack, $safeeval, undef, 0);
+	my $width  = &Apache::lonxml::get_param('TeXwidth', $parstack, $safeeval, undef, 0);
+	my $theme  = &Apache::lonxml::get_param('TeXtheme', $parstack, $safeeval, undef, 0);
+	my $align  = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 0);
+
+	# The only thing that needs any figuring out is the width.. and then only if it is
+	# a percent. If not it's assumed to be some valid TeX measurement unit e.g. 3.0cm
+	#
+
+	my $table = new Apache::lontable();
+	if ($border ne '') {
+	    $table->table_border(1);
+	    $table->cell_border(1);
+	}
+	if ($theme ne '') {
+	    $table->theme($theme);
+	}
+	if ($align ne '') {
+	    $table->alignment($align);
+	}
+
+	# Missing width is most of page width
+
+	if ($width eq "") {
+	    $width = '70%';
+	}
+	
+	# If a percentage, need to calculate what this means in terms of
+	# page width:
+	
+	if ($width =~ /%$/) {
+	    my $textwidth = &recalc($env{'form.textwidth'});  # Page width in mm.
+	    $width =~ s/%//;
+	    $width = $width * $textwidth / 100.0;
+	    $width .= " mm";
+	    $table->width($width);
+	}
+
+	push(@Apache::londefdef::table, $table);
+        $currentstring.=' \keephidden{NEW TABLE ENTRY}';
+
+	#--------------------------------------------------------
+	#  Old table code here.
+	#--------------------------------------------------------
+
+
+	if (0) {
 	push(@Apache::londefdef::table, {}); 
 	$Apache::londefdef::table[-1]{'row_number'} = -1;
         #maximum table's width (default coincides with text line length)
@@ -2101,7 +2150,7 @@ sub start_table {
         $Apache::londefdef::table[-1]{'content'}=[];
         $Apache::londefdef::table[-1]{'align'}=[];
         $currentstring.=' \keephidden{NEW TABLE ENTRY}';
-
+    }
 
     }
     return $currentstring;
@@ -2113,6 +2162,20 @@ sub end_table {
     if ($target eq 'web' || $target eq 'webgrade') {
 	$currentstring = $token->[2];     
     } elsif ($target eq 'tex') {
+
+
+	#  New table code:
+
+	my $table = pop(@Apache::londefdef::table);
+	my $t     = $table->generate();
+	$currentstring = $t->generate_string();
+	&enable_para();
+	#--------------------------------------------------------------
+	#  Old table code:
+	#--------------------------------------------------------------
+
+	if (0) {
+
 	my $border =  &Apache::lonxml::get_param('border',$parstack,$safeeval);
 	my $inmemory = '';
 	my $output = '';
@@ -2528,6 +2591,7 @@ sub end_table {
 	}
 	&enable_para();
     }
+    }
     return $currentstring;
 }
 
@@ -2538,6 +2602,19 @@ sub start_tr {
     if ($target eq 'web' || $target eq 'webgrade') {
 	$currentstring = $token->[4];     
     } elsif ($target eq 'tex') {
+
+	my $align = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
+	$Apache::londefdef::table[-1]->start_row();
+	
+	if ($align ne '') {
+	    $Apache::londefdef::table[-1]->configure_row({default_halign => $align});
+	}
+
+	#---------------------------------------------------------------
+	# Old table code.
+	#---------------------------------------------------------------
+
+	if (0) {
 	$Apache::londefdef::table[-1]{'row_number'}++;
 	my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1);
 	if ($alignchar ne '') {
@@ -2556,6 +2633,7 @@ sub start_tr {
 	push @ {$Apache::londefdef::table[-1]{'minlen'}}, [];
 	push @ {$Apache::londefdef::table[-1]{'maxlen'}}, [];
 	push @ {$Apache::londefdef::table[-1]{'content'}}, [];
+    }
     } 
     return $currentstring;
 }
@@ -2566,6 +2644,19 @@ sub end_tr {
     if ($target eq 'web' || $target eq 'webgrade') {
 	$currentstring .= $token->[2];     
     } elsif ($target eq 'tex') {
+
+	# In case the user is missing a </td> or </th> tag:
+
+	if ($Apache::londefdef::TD_redirection) {
+	    &end_td_tex($parstack,$parser,$safeeval);    
+	}
+	$Apache::londefdef::table[-1]->end_row();
+
+	#-----------------------------------------------
+	# Old table code
+	#-----------------------------------------------
+
+	if (0) {
 	if ($Apache::londefdef::TD_redirection) {
 	    &end_td_tex($parstack,$parser,$safeeval);    
 	}
@@ -2574,7 +2665,7 @@ sub end_tr {
 	if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) {
 	    $Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'};
 	}
-
+    }
 
 	
     }
@@ -2610,9 +2701,50 @@ sub tag_check {
     }
     return '';
 }
+
+#
+#  Factor out cell configuration hash generation:
+#
+
+sub cell_config_hash {
+    my ($align, $rowspan, $colspan) = @_;
+    my %config;
+    if ($align ne '') {
+	$config{'halign'} = $align;
+    }
+    if ($colspan ne "") {
+	$config{'colspan'} = $colspan;
+    }
+    if ($rowspan ne '') {
+	$config{'rowspan'} = $rowspan;
+    }
+    return \%config;
+}
  
 sub start_td_tex {
     my ($parstack,$parser,$safeeval) = @_;
+
+    # At this stage, an empty cell is created with the
+    # appropriate rowspan/colspan and alignment
+    # attributes, but empty of text.  end_td_tex will
+    # fetch the contents from the recursive parse and
+    # fill the cell with them:
+    my $align   = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef, 1);
+    my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 1);
+    my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 1);
+
+    my $config = &cell_config_hash($align, $rowspan, $colspan);
+
+    my $table = $Apache::londefdef::table[-1];
+    $table->add_cell('', $config);
+    
+
+    #------------------------------------------------
+    #  Old table code.
+    #------------------------------------------------
+
+    if (0) {
+
     my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
     if ($alignchar eq '') {
 	$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2625,11 +2757,22 @@ sub start_td_tex {
 	$current_length=~/(\d+\.?\d*)/;
 	push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
     }
+    }
     &Apache::lonxml::startredirection();
     return '';
 }
 
 sub end_td_tex {
+
+    my $text = &Apache::lonxml::endredirection();
+    my $table = $Apache::londefdef::table[-1];
+    $table->append_cell_text($text);
+
+    #-------------------------------------------------
+    # Old table code
+    #-------------------------------------------------
+
+    if (0) {
     my ($parstack,$parser,$safeeval) = @_;
     my $current_row    = $Apache::londefdef::table[-1]{'row_number'};
     my $current_column = $Apache::londefdef::table[-1]{'counter_columns'}; 
@@ -2794,7 +2937,7 @@ sub end_td_tex {
 	
     }
 
-
+    }
 
     return '';
 }
@@ -2843,6 +2986,24 @@ sub tagg_check {
  
 sub start_th_tex {
     my ($parstack,$parser,$safeeval) = @_;
+
+    my $alignment = &Apache::lonxml::get_param('align', $parstack, $safeeval, undef,1);
+    my $rowspan  =  &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 1);
+    my $colspan  =  &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 1);
+
+    my $config   = cell_config_hash($alignment, $rowspan, $colspan);
+    my $table    = $Apache::londefdef::table[-1];
+    $table->add_cell('\textbf{', $config);
+
+    #-------------------------------------------------------------------------------------
+    #
+    #  Old table code.
+    #
+    #--------------------------------------------------------------------------------------
+
+    if (0) {
+
+
     my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1);
     if ($alignchar eq '') {
 	$alignchar = $Apache::londefdef::table[-1]{'rows'}[-1];
@@ -2855,12 +3016,26 @@ sub start_th_tex {
 	$current_length=~/(\d+\.?\d*)/;
 	push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1;
     }
+    }
+
+    # Accept xml until the </th> tag.
+
     &Apache::lonxml::startredirection();
     return '';
 }
 
 sub end_th_tex {
     my ($parstack,$parser,$safeeval) = @_;
+
+    my $table = $Apache::londefdef::table[-1];
+    my $text  = &Apache::lonxml::endredirection();
+    $table->append_cell_text($text.'}');
+
+    #-----------------------------------------------------------------------------
+    #  Old table code:
+    #-----------------------------------------------------------------------------
+
+    if (0) {
     my $current_row = $Apache::londefdef::table[-1]{'row_number'};
     my $data=&Apache::lonxml::endredirection();
     my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0);
@@ -2925,6 +3100,7 @@ sub end_th_tex {
     #make data bold
     $data='\textbf{'.$data.'}';
     push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data;
+    }
     return'';
 }
 
@@ -3347,7 +3523,7 @@ sub start_frameset {
 	    &Apache::loncommon::start_page($Apache::londefdef::title,
 					   $Apache::londefdef::head,
 					   {'add_entries'    => $token->[2],
-					    'no_title'       => 1,
+#					    'no_title'       => 1,
 					    'force_register' => 1,
 					    'frameset'       => 1,});
 
@@ -4621,6 +4797,69 @@ sub is_inside_of {
 }
 
 
+#
+#   This sub provides the typical LaTeX prefix matter for tex output:
+#
+sub latex_header
+{
+    my ($mode) = @_;
+    my $currentstring = '';
+
+    $currentstring .= 
+	"\n% &Apache::lonxml::londefdef \n" .
+	'\documentclass[letterpaper,twoside]{article}\raggedbottom';
+    if (($env{'form.latex_type'}=~'batchmode') ||
+	(!$env{'request.role.adv'}) || 
+	($mode eq 'batchmode')) {$currentstring .='\batchmode';} 
+    $currentstring .= '\newcommand{\keephidden}[1]{}'.
+	'\renewcommand{\deg}{$^{\circ}$}'.
+	'\usepackage{multirow}'.
+	'\usepackage{longtable}'.
+	'\usepackage{textcomp}'.
+	'\usepackage{makeidx}'.
+	'\usepackage[dvips]{graphicx}'.
+	'\usepackage{wrapfig}'.
+	'\usepackage{picins}'.
+	'\usepackage[T1]{fontenc}'."\n".
+	'\usepackage{lmodern}'."\n".
+	'\usepackage[postscript]{ucs}'."\n".
+	'\usepackage[utf8x]{inputenc}'."\n".
+	'\usepackage{pifont}' ."\n".
+	'\usepackage{latexsym}'."\n".
+	'\usepackage{epsfig}'.
+	"\\usepackage{xtab}\n".
+	"\\usepackage{tabularx}\n".
+	"\\usepackage{booktabs}\n".
+	"\\usepackage{array}\n".
+	"\\usepackage{colortbl}\n".
+	"\\usepackage{xcolor}\n".
+	'\usepackage{calc}'.
+	'\usepackage{amsmath}'.
+	'\usepackage{amssymb}'.
+	'\usepackage{amsfonts}'.
+	'\usepackage{amsthm}'.
+	'\usepackage{amscd}'
+        .'\usepackage{picins}\usepackage{calc}'."\n". # From lonprintout.pm
+	'\usepackage[T1]{fontenc}'."\n".
+	'\usepackage{lmodern}'."\n".
+	'\usepackage[postscript]{ucs}'."\n".
+	'\usepackage[utf8x]{inputenc}'."\n".
+	'\usepackage{pifont}'  . "\n";
+	
+    if($env{'form.pdfFormFields'} eq 'yes') {
+	$currentstring .= '\usepackage{hyperref}'.
+	    '\usepackage{eforms}'.
+	    '\usepackage{tabularx}';
+    } 
+    
+        $currentstring .= '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'.
+                          '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}';
+    $currentstring .= '\begin{document}';
+    
+    return $currentstring;
+
+}
+
 =pod
 
 =head1 NAME