--- loncom/interface/spreadsheet/Spreadsheet.pm	2003/06/18 17:35:14	1.14
+++ loncom/interface/spreadsheet/Spreadsheet.pm	2003/09/08 20:32:22	1.24
@@ -1,5 +1,5 @@
 #
-# $Id: Spreadsheet.pm,v 1.14 2003/06/18 17:35:14 matthew Exp $
+# $Id: Spreadsheet.pm,v 1.24 2003/09/08 20:32:22 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -48,6 +48,8 @@ Spreadsheet
 package Apache::Spreadsheet;
 
 use strict;
+#use warnings FATAL=>'all';
+#no warnings 'uninitialized';
 use Apache::Constants qw(:common :http);
 use Apache::lonnet;
 use Safe;
@@ -90,7 +92,7 @@ sub new {
         type     => $stype,
         symb     => $usymb,
         errorlog => '',
-        maxrow   => '',
+        maxrow   => 0,
         cid      => $ENV{'request.course.id'},
         cnum     => $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
         cdom     => $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
@@ -229,6 +231,16 @@ sub initialize {
     # the descendents of the spreadsheet class.
 }
 
+sub clear_package {
+    # This method is here to remind you that it will be overridden by
+    # the descendents of the spreadsheet class.
+}
+
+sub cleanup {
+    my $self = shift();
+    $self->clear_package();
+}
+
 sub initialize_spreadsheet_package {
     &load_spreadsheet_expirationdates();
     &clear_spreadsheet_definition_cache();
@@ -248,18 +260,28 @@ sub load_spreadsheet_expirationdates {
 sub check_expiration_time {
     my $self = shift;
     my ($time)=@_;
-    my ($key1,$key2,$key3,$key4);
+    return 0 if (! defined($time));
+    my ($key1,$key2,$key3,$key4,$key5);
+    # Description of keys
+    #
+    # key1: all sheets of this type have expired
+    # key2: all sheets of this type for this student
+    # key3: all sheets of this type in this map for this student
+    # key4: this assessment sheet for this student
+    # key5: this assessment sheet for all students
     $key1 = '::'.$self->{'type'}.':';
     $key2 = $self->{'name'}.':'.$self->{'domain'}.':'.$self->{'type'}.':';
     $key3 = $key2.$self->{'container'} if (defined($self->{'container'}));
-    $key4 = $key2.$self->{'usymb'} if (defined($self->{'usymb'}));
-    foreach my $key ($key1,$key2,$key3,$key4) {
+    $key4 = $key2.$self->{'symb'} if (defined($self->{'symb'}));
+    $key5 = $key1.$self->{'symb'} if (defined($self->{'symb'}));
+    my $returnvalue = 1; # default to okay
+    foreach my $key ($key1,$key2,$key3,$key4,$key5) {
         next if (! defined($key));
-        if (exists($expiredates{$key}) &&$expiredates{$key} > $time) {
-            return 0;
+        if (exists($expiredates{$key}) && $expiredates{$key} > $time) {
+            $returnvalue = 0; # need to recompute
         }
     }
-    return 1;
+    return $returnvalue;
 }
 
 ######################################################
@@ -785,8 +807,8 @@ sub expandnamed {
 	my @vars=split(/\W+/,$formula);
         my %values=();
 	foreach my $varname ( @vars ) {
-            if ($varname=~/\D/) {
-               $formula=~s/$varname/'$c{\''.$varname.'\'}'/ge;
+            if ($varname=~/^(parameter|stores|timestamp)/) {
+                $formula=~s/$varname/'$c{\''.$varname.'\'}'/ge;
                $varname=~s/$var/\([\\w:\\- ]\+\)/g;
 	       foreach (keys(%{$self->{'constants'}})) {
 		  if ($_=~/$varname/) {
@@ -1135,6 +1157,7 @@ sub display {
     } elsif ($outputmode eq 'csv') {
         $self->outsheet_csv($r);
     }
+    $self->cleanup();
     return;
 }
 
@@ -1143,13 +1166,15 @@ sub display {
 ############################################
 sub html_export_row {
     my $self = shift();
+    my ($color) = @_;
+    $color = '#CCCCFF' if (! defined($color));
     my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
     my $row_html;
     my @rowdata = $self->get_row(0);
     foreach my $cell (@rowdata) {
         if ($cell->{'name'} =~ /^[A-Z]/) {
-	    $row_html .= '<td bgcolor="#CCCCFF">'.
-                &html_editable_cell($cell,'#CCCCFF',$allowed).'</td>';
+	    $row_html .= '<td bgcolor="'.$color.'">'.
+                &html_editable_cell($cell,$color,$allowed).'</td>';
         } else {
 	    $row_html .= '<td bgcolor="#DDCCFF">'.
                 &html_editable_cell($cell,'#DDCCFF',$allowed).'</td>';
@@ -1161,14 +1186,14 @@ sub html_export_row {
 sub html_template_row {
     my $self = shift();
     my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
-    my ($num_uneditable) = @_;
+    my ($num_uneditable,$importcolor) = @_;
     my $row_html;
     my @rowdata = $self->get_template_row();
     my $count = 0;
     for (my $i = 0; $i<=$#rowdata; $i++) {
         my $cell = $rowdata[$i];
         if ($i < $num_uneditable) {
-	    $row_html .= '<td bgcolor="#FFDDDD">'.
+	    $row_html .= '<td bgcolor="'.$importcolor.'">'.
                 &html_uneditable_cell($cell,'#FFDDDD',$allowed).'</td>';
         } else {
 	    $row_html .= '<td bgcolor="#EOFFDD">'.
@@ -1200,13 +1225,17 @@ sub html_editable_cell {
         $value = &HTML::Entities::encode($value) if ($value !~/&nbsp;/);
     }
     return $value if (! $allowed);
-    # Make the formula safe for outputting
-    $formula =~ s/\'/\"/g;
+    #
     # The formula will be parsed by the browser twice before being 
-    # displayed to the user for editing.
-    $formula = &HTML::Entities::encode(&HTML::Entities::encode($formula));
-    # Escape newlines so they make it into the edit window
-    $formula =~ s/\n/\\n/gs;
+    # displayed to the user for editing. 
+    #
+    # The encoding string "^A-blah" is placed in []'s inside a regexp, so 
+    # we specify the characters we want left alone by putting a '^' in front.
+    $formula = &HTML::Entities::encode($formula,'^A-z0-9 !#$%-;=?~');
+    # HTML::Entities::encode does not catch everything - we need '\' encoded
+    $formula =~ s/\\/&\#092/g;
+    # Escape it again - this time the only encodable character is '&'
+    $formula =~ s/\&/\&amp;/g;
     # Glue everything together
     $result .= "<a href=\"javascript:celledit(\'".
         $name."','".$formula."');\">".$value."</a>";
@@ -1222,14 +1251,19 @@ sub html_uneditable_cell {
 
 sub html_row {
     my $self = shift();
-    my ($num_uneditable,$row) = @_;
+    my ($num_uneditable,$row,$exportcolor,$importcolor) = @_;
     my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'});
     my @rowdata = $self->get_row($row);
     my $num_cols_output = 0;
     my $row_html;
+    my $color = $importcolor;
+    if ($row == 0) {
+        $color = $exportcolor;
+    }
+    $color = '#FFDDDD' if (! defined($color));
     foreach my $cell (@rowdata) {
 	if ($num_cols_output++ < $num_uneditable) {
-	    $row_html .= '<td bgcolor="#FFDDDD">';
+	    $row_html .= '<td bgcolor="'.$color.'">';
 	    $row_html .= &html_uneditable_cell($cell,'#FFDDDD');
 	} else {
 	    $row_html .= '<td bgcolor="#EOFFDD">';
@@ -1317,6 +1351,7 @@ sub create_excel_spreadsheet {
 sub outsheet_excel {
     my $self = shift;
     my ($r) = @_;
+    my $connection = $r->connection();
     $r->print("<h2>Preparing Excel Spreadsheet</h2>");
     #
     # Create excel worksheet
@@ -1340,7 +1375,7 @@ sub outsheet_excel {
     $self->excel_output_row($worksheet,0,$rows_output++,'Summary');
     $rows_output++;    # skip a line
     #
-    $self->excel_rows($worksheet,$cols_output,$rows_output);
+    $self->excel_rows($connection,$worksheet,$cols_output,$rows_output);
     #
     #
     # Close the excel file
@@ -1358,6 +1393,7 @@ sub outsheet_excel {
 sub outsheet_csv   {
     my $self = shift;
     my ($r) = @_;
+    my $connection = $r->connection();
     my $csvdata = '';
     my @Values;
     #
@@ -1381,7 +1417,7 @@ sub outsheet_csv   {
     }
     #
     # Output the body of the spreadsheet
-    $self->csv_rows($file);
+    $self->csv_rows($connection,$file);
     #
     # Close the csv file
     close($file);
@@ -1531,9 +1567,6 @@ sub load {
             } else {
                 $self->filename($newfilename);
             }
-        } elsif ($filename =~ /^default\.$self->{'type'}/) {
-            # if there is an Original_$stype, load it instead
-            $formulas = $self->load_system_default_sheet();
         } else {
             # Load the spreadsheet definition file from the save file
             my %tmphash = &Apache::lonnet::dump($filename,$cdom,$cnum);
@@ -1558,7 +1591,7 @@ sub load {
 sub set_row_sources {
     my $self = shift;
     while (my ($cell,$value) = each(%{$self->{'formulas'}})) {
-        next if ($cell !~ /^A(\d+)/ && $1 > 0);
+        next if ($cell !~ /^A(\d+)/ || $1 < 1);
         my $row = $1;
         $self->{'row_source'}->{$row} = $value;
     }
@@ -1620,7 +1653,12 @@ sub save {
             return $reply if ($reply ne 'ok');
         } 
         if ($self->is_default()) {
-            &Apache::lonnet::expirespread('','',$self->{'type'},'');
+            if ($self->{'type'} eq 'studentcalc') {
+                &Apache::lonnet::expirespread('','','studentcalc','');
+            } elsif ($self->{'type'} eq 'assesscalc') {
+                &Apache::lonnet::expirespread('','','assesscalc','');
+                &Apache::lonnet::expirespread('','','studentcalc','');
+            }
         }
         return $reply;
     }
@@ -1632,7 +1670,7 @@ sub save {
 sub save_tmp {
     my $self = shift;
     my $filename=$ENV{'user.name'}.'_'.
-        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'.
+        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
            $self->{'filename'};
     $filename=~s/\W/\_/g;
     $filename=$Apache::lonnet::tmpdir.$filename.'.tmp';
@@ -1652,7 +1690,7 @@ sub save_tmp {
 sub load_tmp {
     my $self = shift;
     my $filename=$ENV{'user.name'}.'_'.
-        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'.
+        $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'.
             $self->{'filename'};
     $filename=~s/\W/\_/g;
     $filename=$Apache::lonnet::tmpdir.$filename.'.tmp';