[LON-CAPA-cvs] cvs: modules /matthew/spreadsheet Spreadsheet.pm lonspreadsheet.pm

matthew lon-capa-cvs@mail.lon-capa.org
Tue, 13 May 2003 14:36:36 -0000


This is a MIME encoded message

--matthew1052836596
Content-Type: text/plain

matthew		Tue May 13 10:36:36 2003 EDT

  Modified files:              
    /modules/matthew/spreadsheet	Spreadsheet.pm lonspreadsheet.pm 
  Log:
  Many changes on the road to making this work well enough to be integrated
  back in to LON-CAPA.  Soon.  Very soon.
  
  
--matthew1052836596
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20030513103636.txt"

Index: modules/matthew/spreadsheet/Spreadsheet.pm
diff -u modules/matthew/spreadsheet/Spreadsheet.pm:1.3 modules/matthew/spreadsheet/Spreadsheet.pm:1.4
--- modules/matthew/spreadsheet/Spreadsheet.pm:1.3	Thu Apr 17 10:53:36 2003
+++ modules/matthew/spreadsheet/Spreadsheet.pm	Tue May 13 10:36:36 2003
@@ -1,5 +1,5 @@
 #
-# $Id: Spreadsheet.pm,v 1.3 2003/04/17 14:53:36 matthew Exp $
+# $Id: Spreadsheet.pm,v 1.4 2003/05/13 14:36:36 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -66,59 +66,60 @@
 my @UC_Columns = split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
 my @LC_Columns = map { lc($_) } @UC_Columns;
 
+
+######################################################
+
+=pod
+
+=item &new
+
+Returns a new spreadsheet object.
+
+=cut
+
+######################################################
 sub new {
     my $this = shift;
     my $class = ref($this) || $this;
     my ($stype) = ($class =~ /Apache::(.*)$/);
     #
-    my ($name,$domain,$usymb)=@_;
+    my ($name,$domain,$filename,$usymb)=@_;
     #
     my $self = {
-        name    => $name,
-        domain  => $domain,
-        type  => $stype,
-        symb => $usymb,
+        name     => $name,
+        domain   => $domain,
+        type     => $stype,
+        symb     => $usymb,
         errorlog => '',
         maxrow   => '',
-        cid   => $ENV{'request.course.id'},
-        cnum  => $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
-        cdom  => $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
-        chome => $ENV{'course.'.$ENV{'request.course.id'}.'.home'},
+        cid      => $ENV{'request.course.id'},
+        cnum     => $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
+        cdom     => $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+        chome    => $ENV{'course.'.$ENV{'request.course.id'}.'.home'},
         coursedesc => $ENV{'course.'.$ENV{'request.course.id'}.'.description'},
+        coursefilename => $ENV{'request.course.fn'},
+        #
+        # Data storage
+        formulas    => {},
+        constants   => {},
+        rows        => [],
+        row_source  => {}, 
+        othersheets => [],
     };
-    $self->{'coursefilename'} = $ENV{'request.course.fn'};
-    #
-    # Determine filename of spreadsheet
-    my $filename;
-    $filename = $ENV{'form.filename'} if (exists($ENV{'form.filename'}));
-    if (! defined($filename) || 
-        $filename !~ /\w/    || 
-        $filename =~ /\W/) {
-        &Apache::lonnet::logthis('getting filename....');
-        my %tmphash = &Apache::lonnet::get('environment',
-                                  ['spreadsheet_default_'.$self->{'type'}],
-                                           $self->{'cdom'},$self->{'cnum'});
-        my ($tmp) = keys(%tmphash);
-        if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
-            $filename = $tmphash{'spreadsheet_default_'.$stype};
-        } 
-    }
-    if (! defined($filename) || 
-        $filename !~ /\w/    || 
-        $filename =~ /\W/) {
-        $filename = 'default_'.$stype;
-    }
-    $self->{'filename'} = $filename;
-#    &Apache::lonnet::logthis('filename = '.$filename);
     #
     $self->{'uhome'} = &Apache::lonnet::homeserver($name,$domain);
     #
-    $self->{'formulas'} = {};
-    $self->{'constants'} = {};
-    $self->{'othersheets'} = [];
     #
     bless($self,$class);
-    if (exists($ENV{'form.workcopy'}) && $class eq 'Apache::'.$ENV{'form.workcopy'}) {
+    #
+    # Determine filename of spreadsheet
+    if (! defined($filename)) {
+        $filename = 'default_'.$self->{'type'};
+        $filename = $ENV{'form.filename'} if (exists($ENV{'form.filename'}));
+    }
+    $self->filename($filename);
+    if (exists($ENV{'form.workcopy'}) && 
+        $self->{'type'} eq $ENV{'form.workcopy'}) {
         $self->load_tmp();
     } else {
         $self->load();
@@ -126,6 +127,67 @@
     return $self;
 }
 
+######################################################
+
+=pod
+
+=item &filename
+
+get or set the filename for a spreadsheet.
+
+=cut
+
+######################################################
+sub filename {
+    my $self = shift();
+    if (@_) {
+        my ($newfilename) = @_;
+        if (! defined($newfilename) || $newfilename eq 'Default' ||
+            $newfilename !~ /\w/    || $newfilename =~ /\W/) {
+            my %tmphash = &Apache::lonnet::get('environment',
+                                               ['spreadsheet_default_'.
+                                                $self->{'type'}],
+                                               $self->{'cdom'},
+                                               $self->{'cnum'});
+            my ($tmp) = keys(%tmphash);
+            if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
+                $newfilename = $tmphash{'spreadsheet_default_'.
+                                            $self->{'type'}};
+            } 
+        }
+        if (! defined($newfilename) || 
+            $newfilename !~ /\w/    || 
+            $newfilename =~ /\W/) {
+            $newfilename = 'default';
+        }
+        my $regexp = "_$self->{'type'}\$";
+        if ($newfilename !~ /$regexp/) {
+            $newfilename .= '_'.$self->{'type'};
+        }
+        $self->{'filename'} = $newfilename;
+        $self->logthis('filename is '.$self->{'filename'});
+        return;
+    }
+    return $self->{'filename'};
+}
+
+######################################################
+
+=pod
+
+=item &make_default()
+
+Make the current spreadsheet file the default for the course.
+
+=cut
+
+######################################################
+sub make_default {
+    my $self = shift();
+    &Apache::lonnet::logthis('cannot yet make this the default sheet');
+    return;
+}
+
 sub load_spreadsheet_expirationdates {
     undef %expiredates;
     my $cid=$ENV{'request.course.id'};
@@ -154,6 +216,21 @@
     return 1;
 }
 
+######################################################
+
+=pod
+
+=item &initialize_safe_space
+
+Returns the safe space required by a Spreadsheet object.
+
+=head 2 Safe Space Functions
+
+=over 4
+
+=cut
+
+######################################################
 sub initialize_safe_space {
     my $self = shift;
     my $safeeval = new Safe(shift);
@@ -546,10 +623,21 @@
     $self->{'safe'}->reval($initstring);
     return $self;
 }
+######################################################
 
-##
-## mask - used to reside in the safe space.  
-##
+=pod
+
+=back
+
+=cut
+
+######################################################
+
+
+######################################################
+
+
+######################################################
 {
 
 my %memoizer;
@@ -758,71 +846,6 @@
     %{$self->{'safe'}->varglob('t')}=%t;
 }
 
-#
-# sett Set up the temporary hash used for computation
-#
-sub old_sett {
-    my $self = shift;
-    my %t=();
-    my $pattern='';
-    if ($self->{'type'} eq 'assesscalc') {
-	$pattern='A';
-    } else {
-        $pattern='[A-Z]';
-    }
-    # Deal with the template row
-    foreach my $col ($self->template_cells()) {
-        next if ($col=~/^$pattern/);
-        foreach my $trow ($self->rows()) {
-            # Get the name of this cell
-            my $lb=$col.$trow;
-            # Grab the template declaration
-            $t{$lb}=$self->formula('template_'.$col);
-            # Replace '#' with the row number
-            $t{$lb}=~s/\#/$trow/g;
-            # Replace '....' with ','
-            $t{$lb}=~s/\.\.+/\,/g;
-            # Replace 'A0' with the value from 'A0'
-            $t{$lb}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
-            # Replace parameters
-            $t{$lb}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
-        }
-    }
-    # Deal with the normal cells
-    foreach ($self->formulas_keys()) {
-	next if ($_=~/template\_/);
-        if  (($_=~/^$pattern(\d+)/) && ($1)) {
-            if ($self->formula($_) !~ /^\!/) {
-                $t{$_}=$self->{'constants'}->{$_};
-            }
-        } else {
-            $t{$_}=$self->formula($_);
-            $t{$_}=~s/\.\.+/\,/g;
-            $t{$_}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
-            $t{$_}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
-        }
-    }
-    # For inserted lines, [B-Z] is also valid
-    if ($self->{'type'} ne 'assesscalc') {
-        foreach ($self->formulas_keys()) {
-            next if ($_ !~ /[B-Z](\d+)/);
-            next if ($self->formula('A'.$1) !~ /^[\~\-]/);
-            $t{$_}=$self->formula($_);
-            $t{$_}=~s/\.\.+/\,/g;
-            $t{$_}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
-            $t{$_}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
-        }
-    }
-    # For some reason 'A0' gets special treatment...  This seems superfluous
-    # but I imagine it is here for a reason.
-    $t{'A0'}=$self->formula('A0');
-    $t{'A0'}=~s/\.\.+/\,/g;
-    $t{'A0'}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
-    $t{'A0'}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
-    # Put %t into the safe space
-    %{$self->{'safe'}->varglob('t')}=%t;
-}
-
 ##
 ## sync_safe_space:  Called by calcsheet to make sure all the data we 
 #  need to calculate is placed into the safe space
@@ -964,11 +987,12 @@
 sub dump_values_to_log {
     my $self =shift;
     $self->logthis("Spreadsheet Values");
-    $self->logthis("--------------------------------------------------------");
+    $self->logthis("------------------------------------------------------");
     while (my ($cell, $value) = each(%{$self->{'values'}})) {
         $self->logthis('    '.$cell.' = '.$value);
     }
-    $self->logthis("--------------------------------------------------------");}
+    $self->logthis("------------------------------------------------------");
+}
 
 ##
 ## Yet another debugging function
@@ -1135,8 +1159,7 @@
     my $num_cols_output = 0;
     my $row_html;
     foreach my $cell (@rowdata) {
-	if ($requester_is_student || 
-	    $num_cols_output++ < $num_uneditable) {
+	if ($requester_is_student || ($num_cols_output++ < $num_uneditable)) {
 	    $row_html .= '<td bgcolor="#FFDDDD">';
 	    $row_html .= &html_uneditable_cell($cell,'#FFDDDD');
 	} else {
@@ -1182,6 +1205,20 @@
     ## Someday XML
     ## Will be rendered for the user
     ## But not on this day
+    my $Str = '<spreadsheet type="'.$self->{'type'}.'">'."\n";
+    while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {
+        if ($cell =~ /^template_(\d+)/) {
+            my $col = $1;
+            $Str .= '<template col="'.$col.'">'.$formula.'</template>'."\n";
+        } else {
+            my ($row,$col) = ($cell =~ /^([A-z])(\d+)/);
+            next if (! defined($row) || ! defined($col));
+            $Str .= '<field row="'.$row.'" col="'.$col.'" >'.$formula.'</cell>'
+                ."\n";
+        }
+    }
+    $Str.="</spreadsheet>";
+    return $Str;
 }
 
 ############################################
@@ -1194,114 +1231,99 @@
         my $tmp = $sheetxml;
         $sheetxml = \$tmp;
     }
-    my %f;
+    my %formulas;
+    my %sources;
     my $parser=HTML::TokeParser->new($sheetxml);
     my $token;
     while ($token=$parser->get_token) {
         if ($token->[0] eq 'S') {
             if ($token->[1] eq 'field') {
-                $f{$token->[2]->{'col'}.$token->[2]->{'row'}}=
-                    $parser->get_text('/field');
+                my $cell = $token->[2]->{'col'}.$token->[2]->{'row'};
+                my $source = $token->[2]->{'source'};
+                my $formula = $parser->get_text('/field');
+                $formulas{$cell} = $formula;
+                $sources{$cell}  = $source if (defined($source));
+                $parser->get_text('/field');
             }
             if ($token->[1] eq 'template') {
-                $f{'template_'.$token->[2]->{'col'}}=
+                $formulas{'template_'.$token->[2]->{'col'}}=
                     $parser->get_text('/template');
             }
         }
     }
-    return \%f;
+    return (\%formulas,\%sources);
 }
 
-my %defaultsheets;
+{ # scope for %spreadsheets
+
 my %spreadsheets;
 
 sub load {
     my $self = shift;
-    my ($fn)=@_;
     my $includedir = $Apache::lonnet::perlvar{'lonIncludes'};
     #
     my $stype = $self->{'type'};
     my $cnum  = $self->{'cnum'};
     my $cdom  = $self->{'cdom'};
     my $chome = $self->{'chome'};
+    my $filename = $self->{'filename'};
+    #
+    my $cachekey = join('_',($cnum,$cdom,$stype,$filename));
     #
-    if (! defined($fn)) {
-        # There is no filename. Look for defaults in course and global, cache
-        unless ($fn=$defaultsheets{$cnum.'_'.$cdom.'_'.$stype}) {
-            my %tmphash = &Apache::lonnet::get('environment',
-                                               ['spreadsheet_default_'.$stype],
-                                               $cdom,$cnum);
-            my ($tmp) = keys(%tmphash);
-            if ($tmp =~ /^(con_lost|error|no_such_host)/i) {
-                $fn = 'default_'.$stype;
-            } else {
-                $fn = $tmphash{'spreadsheet_default_'.$stype};
-            } 
-            unless (($fn) && ($fn!~/^error\:/)) {
-                $fn='default_'.$stype;
-            }
-            $defaultsheets{$cnum.'_'.$cdom.'_'.$stype}=$fn; 
-        }
-    }
-    # $fn now has a value
-    $self->{'filename'} = $fn;
     # see if sheet is cached
-    if (exists($spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn})) {
-        
-        my %tmp = split(/___;___/,
-                        $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn});
-        $self->formulas(\%tmp);
+    my ($formulas);
+    if (exists($spreadsheets{$cachekey})) {
+        $formulas = $spreadsheets{$cachekey}->{'formulas'};
     } else {
         # Not cached, need to read
-        my %f=();
-        if ($fn=~/^default_/) {
+        if (! defined($self->filename())) {
+            # load in the default defined spreadsheet
             my $sheetxml='';
             my $fh;
-            my $dfn=$fn;
-            $dfn=~s/\_/\./g;
-            if ($fh=Apache::File->new($includedir.'/'.$dfn)) {
+            if ($fh=Apache::File->new($includedir.'/default.'.$filename)) {
                 $sheetxml=join('',<$fh>);
+                $fh->close();
             } else {
                 # $sheetxml='<field row="0" col="A">"Error"</field>';
                 $sheetxml='<field row="0" col="A"></field>';
             }
-            %f=%{&parse_sheet(\$sheetxml)};
-        } elsif($fn=~/\/*\.spreadsheet$/) {
+            $formulas = &parse_sheet(\$sheetxml);
+        } elsif($self->filename() =~ /\/*\.spreadsheet$/) {
+            # Load a spreadsheet definition file
             my $sheetxml=&Apache::lonnet::getfile
-                (&Apache::lonnet::filelocation('',$fn));
+                (&Apache::lonnet::filelocation('',$filename));
             if ($sheetxml == -1) {
                 $sheetxml='<field row="0" col="A">"Error loading spreadsheet '
-                    .$fn.'"</field>';
+                    .$self->filename().'"</field>';
             }
-            %f=%{&parse_sheet(\$sheetxml)};
+            $formulas = &parse_sheet(\$sheetxml);
         } else {
-            my %tmphash = &Apache::lonnet::dump($fn,$cdom,$cnum);
+            # Load the spreadsheet definition file from the save file
+            my %tmphash = &Apache::lonnet::dump($self->filename(),$cdom,$cnum);
             my ($tmp) = keys(%tmphash);
             if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
-                foreach (keys(%tmphash)) {
-                    $f{$_}=$tmphash{$_};
+                while (my ($cell,$formula) = each(%tmphash)) {
+                    $formulas->{$cell}=$formula;
                 }
             } else {
                 # Unable to grab the specified spreadsheet,
                 # so we get the default ones instead.
-                $fn = 'default_'.$stype;
-                $self->{'filename'} = $fn;
-                my $dfn = $fn;
-                $dfn =~ s/\_/\./g;
+                $filename = 'default_'.$stype;
+                $self->filename($filename);
                 my $sheetxml;
-                if (my $fh=Apache::File->new($includedir.'/'.$dfn)) {
+                if (my $fh=Apache::File->new($includedir.'/'.$filename)) {
                     $sheetxml = join('',<$fh>);
+                    $fh->close();
                 } else {
                     $sheetxml='<field row="0" col="A">'.
                         '"Unable to load spreadsheet"</field>';
                 }
-                %f=%{&parse_sheet(\$sheetxml)};
+                $formulas = &parse_sheet(\$sheetxml);
             }
         }
-        # Cache and set
-        $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f);  
-        $self->formulas(\%f);
+        %{$spreadsheets{$cachekey}->{'formulas'}} = %{$formulas};
     }
+    $self->formulas($formulas);
     $self->set_row_numbers();
 }
 
@@ -1323,32 +1345,29 @@
             delete($f{$_}) if ($f{$_} eq 'import');
         }
         my $reply = &Apache::lonnet::put($fn,\%f,$cdom,$cnum);
-        if ($reply eq 'ok') {
-            $reply = &Apache::lonnet::put($stype.'_spreadsheets',
-                            {$fn => $ENV{'user.name'}.'@'.$ENV{'user.domain'}},
+        return $reply if ($reply ne 'ok');
+        $reply = &Apache::lonnet::put($stype.'_spreadsheets',
+                       {$fn => $ENV{'user.name'}.'@'.$ENV{'user.domain'}},
+                                      $cdom,$cnum);
+        return $reply if ($reply ne 'ok');
+        if ($makedef) { 
+            $reply = &Apache::lonnet::put('environment',
+                                {'spreadsheet_default_'.$stype => $fn },
                                           $cdom,$cnum);
-            if ($reply eq 'ok') {
-                if ($makedef) { 
-                    $reply = &Apache::lonnet::put('environment',
-                                    {'spreadsheet_default_'.$stype => $fn },
-                                                  $cdom,$cnum);
-                    if ($reply eq 'ok' && 
-                        ($self->{'type'} eq 'studentcalc' ||
-                         $self->{'type'} eq 'assesscalc')) {
-                        # Expire the spreadsheets of the other students.
-                        &Apache::lonnet::expirespread('','','studentcalc','');
-                    }
-                    return $reply;
-                } 
-                return $reply;
-            } 
-            return $reply;
+            return $reply if ($reply ne 'ok');
+            if ($self->{'type'} eq 'studentcalc' || 
+                $self->{'type'} eq 'assesscalc') {
+                # Expire the spreadsheets of the other students.
+                &Apache::lonnet::expirespread('','','studentcalc','');
+            }
         } 
         return $reply;
     }
     return 'unauthorized';
 }
 
+} # end of scope for %spreadsheets
+
 sub save_tmp {
     my $self = shift;
     my $fn=$ENV{'user.name'}.'_'.
@@ -1360,7 +1379,8 @@
     if ($fh=Apache::File->new('>'.$fn)) {
         my %f = $self->formulas();
         while( my ($cell,$formula) = each(%f)) {
-            print $fh &Apache::lonnet::escape($cell)."=".&Apache::lonnet::escape($formula)."\n";
+            print $fh &Apache::lonnet::escape($cell)."=".
+                &Apache::lonnet::escape($formula)."\n";
         }
         $fh->close();
     }
@@ -1416,7 +1436,8 @@
     my $chome = $self->{'chome'};
     #
     my @alternatives=();
-    my %results=&Apache::lonnet::dump($stype.'_spreadsheets',$cdom,$cnum);
+    my %results=&Apache::lonnet::dump($self->{'type'}.'_spreadsheets',
+                                      $self->{'cdom'}, $self->{'cnum'});
     my ($tmp) = keys(%results);
     unless ($tmp =~ /^(con_lost|error|no_such_host)/i ) {
         @alternatives = sort (keys(%results));
Index: modules/matthew/spreadsheet/lonspreadsheet.pm
diff -u modules/matthew/spreadsheet/lonspreadsheet.pm:1.2 modules/matthew/spreadsheet/lonspreadsheet.pm:1.3
--- modules/matthew/spreadsheet/lonspreadsheet.pm:1.2	Thu Apr 17 10:53:36 2003
+++ modules/matthew/spreadsheet/lonspreadsheet.pm	Tue May 13 10:36:36 2003
@@ -1,5 +1,5 @@
 #
-# $Id: lonspreadsheet.pm,v 1.2 2003/04/17 14:53:36 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.3 2003/05/13 14:36:36 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -150,12 +150,26 @@
     $r->header_out('Pragma','no-cache');
     $r->send_http_header;
     #
+    # Check user permissions - only those able to view others grades
+    # will be allowed to continue if they are not requesting their own.
+    if (($sheettype eq 'classcalc') || 
+        ($name   ne $ENV{'user.name'} ) ||
+        ($domain ne $ENV{'user.domain'})) {
+        if (! &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
+            $r->print('<h1>Access Permission Denied</h1>'.
+                      '</form></body></html>');
+            return OK;
+        }
+    }
+    #
     # Header....
     #
     $r->print('<html><head><title>LON-CAPA Spreadsheet</title>');
     my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
-
-    if ($ENV{'request.role'} !~ /^st\./) {
+    ##
+    ## Spit out the javascript required for editing
+    ##
+    if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) {
         $r->print(<<ENDSCRIPT);
 <script language="JavaScript">
 
@@ -199,34 +213,102 @@
               '<form action="'.$r->uri.'" name="sheet" method="post">');
     $r->print(&hiddenfield('sname'  ,$ENV{'form.sname'}).
               &hiddenfield('sdomain',$ENV{'form.sdomain'}).
-              &hiddenfield('usymb'  ,$ENV{'form.usymb'}).
-              &hiddenfield('cell'  ,'').
-              &hiddenfield('newformula',''));
+              &hiddenfield('usymb'  ,$ENV{'form.usymb'}));
     $r->rflush();
     #
+    my $filename = undef;
+    ##
+    ## Deal with loading a new spreadsheet
+    ##
+    $filename = $ENV{'form.filename'} if (exists($ENV{'form.filename'}));
+    if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'}) &&
+        (exists($ENV{'form.load'}) && exists($ENV{'form.loadfilename'}))) {
+        $filename = $ENV{'form.loadfilename'};
+    }
+    
     my $spreadsheet = undef;
     if ($sheettype eq 'classcalc') {
-        $spreadsheet = Apache::classcalc->new($name,$domain,undef);
+        $spreadsheet = Apache::classcalc->new($name,$domain,$filename,undef);
     } elsif ($sheettype eq 'studentcalc') {
-        $spreadsheet = Apache::studentcalc->new($name,$domain,undef);
+        $spreadsheet = Apache::studentcalc->new($name,$domain,$filename,undef);
     } elsif ($sheettype eq 'assesscalc' && defined($symb)) {
-        $spreadsheet = Apache::assesscalc->new($name,$domain,$symb);
+        $spreadsheet = Apache::assesscalc->new($name,$domain,$filename,$symb);
+        if (exists($ENV{'form.sname'})) {
+
+        }
     } else {
         &Apache::lonnet::logthis('Unable to determine spreadsheet type');
     }
     ##
-    ## Deal with modified work copies
+    ## Editing code
     ##
-    if (exists($ENV{'form.newformula'}) && defined($ENV{'form.newformula'}) && 
-        exists($ENV{'form.cell'})       && defined($ENV{'form.cell'})) {
-        $spreadsheet->logthis("storing cell");
-        $spreadsheet->modify_cell($ENV{'form.cell'},$ENV{'form.newformula'});
-        $spreadsheet->logthis("saving sheet in temp");
-        $spreadsheet->save_tmp();
-        # output that we are dealing with a temporary file
-        $r->print(&hiddenfield('workcopy',$sheettype));
-        $r->print('<pre>'.$ENV{'form.cell'}.' = '.
-                  $ENV{'form.newformula'}.'</pre>'."\n");
+    if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) {
+        ##
+        ## Deal with saving the spreadsheet
+        ##
+        if (exists($ENV{'form.save'}) && 
+            exists($ENV{'form.savefilename'})) {
+            $spreadsheet->filename($ENV{'form.savefilename'});
+            my $save_status = $spreadsheet->save();
+            if ($save_status ne 'ok') {
+                $r->print("An error occurred while saving the spreadsheet".
+                          "There error is:".$save_status);
+            } else {
+                $r->print("Spreadsheet saved as ".$ENV{'form.savefilename'});
+            }
+        }
+        ##
+        ## Output save/load dialog
+        ##
+        $r->print(&hiddenfield('cell','').
+                  &hiddenfield('newformula',''));
+        # save dialog
+        my $fname = $spreadsheet->filename();
+        $fname='course_default' if ($fname eq 'default');
+        my $save_dialog = 
+            '<input type="submit" name="save" value="Save as ..." /> '.
+                '<input type="text" name="savefilename" size="30" value="'.
+                    $fname.'" />';
+
+        my $load_dialog = 
+            '<input type="submit" name="load" value="Load ..." />'.
+                '<select name="loadfilename">'.
+                    '<option name="default">Default</option>';
+        foreach ($spreadsheet->othersheets()) {
+            $load_dialog .= '<option name="'.$_.'"';
+            $load_dialog .= ' selected' if ($ENV{'form.ufn'} eq $_);
+            $load_dialog .= '>'.$_."</option>\n";
+        }
+        my $makedefault_dialog = 
+            '<input type="submit" name="makedefault" value="Make Default"/>';
+        $r->print(<<END);
+<!-- load / save dialogs -->
+<table cellspacing="3">
+<tr>
+<td>$load_dialog</td>
+<td>$save_dialog</td>
+<td>$makedefault_dialog</td>
+</tr>
+</table>
+END
+        $r->rflush();
+        ##
+        ## Deal with modified work copies
+        ##
+        if (exists($ENV{'form.newformula'}) && 
+            $ENV{'form.newformula'} ne ''   && 
+            exists($ENV{'form.cell'})       && 
+            $ENV{'form.cell'} ne '' ) {
+            $spreadsheet->logthis("storing cell");
+            $spreadsheet->modify_cell($ENV{'form.cell'},
+                                      $ENV{'form.newformula'});
+            $spreadsheet->logthis("saving sheet in temp");
+            $spreadsheet->save_tmp();
+            # output that we are dealing with a temporary file
+            $r->print(&hiddenfield('workcopy',$sheettype));
+            $r->print('<pre>'.$ENV{'form.cell'}.' = '.
+                      $ENV{'form.newformula'}.'</pre>'."\n");
+        }
     }
     $r->print($spreadsheet->get_title());
     $r->print($spreadsheet->parent_link());

--matthew1052836596--