Diff for /loncom/homework/Attic/lonproblem.pm between versions 1.2 and 1.4

version 1.2, 2000/02/22 21:32:17 version 1.4, 2001/08/06 18:35:51
Line 1 Line 1
 # The LearningOnline Network with CAPA  # The LON-CAPA problem handler
   #
 # Problem Handler  # Problem Handler
 #  #
 # 12/15-01/21,01/24 Gerd Kortemeyer  # 12/15-01/21,01/24 Gerd Kortemeyer
   # 4/12 Guy Albertelli
   # 8/6 Scott Harrison
   
 package Apache::lonproblem;  package Apache::lonproblem;
   
Line 11  use Safe; Line 14  use Safe;
 use Apache::File;  use Apache::File;
   
 # ================================================================ Main Handler  # ================================================================ Main Handler
   
 sub handler {  sub handler {
 my $r=shift;      my $r=shift;
 my @parsecontents;      my @parsecontents;
 my $parsestring;      my $parsestring;
 my $outstring;      my $outstring;
       
 {      {
   my $fh=Apache::File->new($r->filename);   my $fh=Apache::File->new($r->filename);
   @parsecontents=<$fh>;   @parsecontents=<$fh>;
 }      }
       
 $parsestring=join('',@parsecontents);      $parsestring=join('',@parsecontents);
       
 print "<form>";      print "<form>";
       
 &xmlparse($r,$parsestring,'web');      &xmlparse($r,$parsestring,'web');
       
 print "\n---------------\n";      print "\n---------------\n";
 print "<form>";      print "<form>";
 &xmlparse($r,$parsestring,'edit');      &xmlparse($r,$parsestring,'edit');
 $outstring=xmlparse($parsestring,'modified');      $outstring=xmlparse($parsestring,'modified');
 print "\n---------------\n$outstring\n";      print "\n---------------\n$outstring\n";
 return 1; #change to ok      return 1; #change to ok
 }  }
   
 # =============================================================================  
 # ============================================================= Parsing Routine  # ============================================================= Parsing Routine
 # Takes $parsestring and $target  # Takes $parsestring and $target
 # =============================================================================  
   
 sub xmlparse {  sub xmlparse {
     
 my ($r,$parsestring,$target) = @_;      my ($r,$parsestring,$target) = @_;
     
 my $safeeval   = new Safe 'Script';      my $safeeval   = new Safe 'Script';
     
 my $parsereval = new Safe 'Parser';      my $parsereval = new Safe 'Parser';
       
 my $parser=HTML::TokeParser->new(\$parsestring);      my $parser=HTML::TokeParser->new(\$parsestring);
     
 my $outtext='';      my $outtext='';
     
 # ---------------------------------------------------------------- Handled tags  # ---------------------------------------------------------------- Handled tags
   
 my %toptoplevel  = ( 'problem'    => 'Problem',      my %toptoplevel  = ( 'problem'    => 'Problem',
                      'entryform'  => 'Entry Form',   'entryform'  => 'Entry Form',
                      'survey'     => 'Survey',   'survey'     => 'Survey',
                      'graded'     => 'Manually Graded' );   'graded'     => 'Manually Graded' );
     
     
 # --------------------------------------------------------------- Toplevel Tags  # --------------------------------------------------------------- Toplevel Tags
   
 my %topleveltags = ( 'block'   => 'Condition Block',      my %topleveltags = ( 'block'   => 'Condition Block',
                      'part'    => 'Problem Part';   'part'    => 'Problem Part',
                      'include' => 'Include Section',   'include' => 'Include Section',
                      'answer'  => 'Answerfield';   'answer'  => 'Answerfield',
                      'script'  => 'Script',    'script'  => 'Script', 
                      'outtext' => 'Text Block' );   'outtext' => 'Text Block' );
     
 # ---------------------------------------------------------- Preregistered Tags  # ---------------------------------------------------------- Preregistered Tags
   
 my %includetags  = ( 'scriptlib' => 'Script Library',      my %includetags  = ( 'scriptlib' => 'Script Library',
                      'parserlib' => 'Parser Library' );   'parserlib' => 'Parser Library' );
   # -------------------------------------------------------------Answer type Tags
   
 # -------------------------------------------------------------------- All Tags      my %answertags   = ( 'capaanswer' => 'CAPA Standard Answers');
   
 my %xmltags      = ( %includetags, %topleveltags, %toptoplevel );  # -------------------------------------------------------------------- All Tags
   
 my $toplevel     = '';  
 my $above        = '';  
   
       my %xmltags      = ( %includetags, %topleveltags, %toptoplevel, 
    %answertags );
     
       my $toplevel     = '';
       my $above        = '';
     
 # --------------------------------------------------- Depth counter for editing  # --------------------------------------------------- Depth counter for editing
   
 my @depthcounter=();      my @depthcounter = ();
 my $depth=-1;      my $depth = -1;
 my $olddepth=-1;      my $olddepth = -1;
   
 # ----------------------------------------------------------------------- Stack  # ----------------------------------------------------------------------- Stack
   
 my @stack=('');      my @stack = ('');
   
 # -------------------------------------------------------------- Init $saveeval  # -------------------------------------------------------------- Init $saveeval
       
 &init_safeeval($safeeval);      &init_safeeval($safeeval);
   
 # ---------------------------------------------------------- Parse $parsestring  # ---------------------------------------------------------- Parse $parsestring
   
 my $token;      my $token;
   
 while ($token=$parser->get_token) {      while ($token = $parser->get_token) {
 # =============================================================================  # =============================================================================
    if ($token->[0] eq 'S') {   if ($token->[0] eq 'S') {
 # =================================================================== Start Tag  # =================================================================== Start Tag
 # --------------------------------------------------------------- Depth Counter  # --------------------------------------------------------------- Depth Counter
       if (defined($xmltags{$token->[1]})) {      if (defined($xmltags{$token->[1]})) {
          if ($depth<$olddepth-1) {   if ($depth<$olddepth-1) {
             $#depthcounter--;      $#depthcounter--;
             $olddepth=$depth;      $olddepth=$depth;
          }   }
          $depth++;   $depth++;
          $depthcounter[$depth]++;   $depthcounter[$depth]++;
          if ($depthcounter[$depth]==1) {   if ($depthcounter[$depth] == 1) {
             $olddepth=$depth;      $olddepth = $depth;
          }   }
       }        }  
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
   
   
       if ($target eq 'web') {      if ($target eq 'web') {
          my $sub="start_$token->[1]";   my $sub = "start_$token->[1]";
          {   {
            no strict 'refs';      no strict 'refs';
            if (defined (&$sub)) {       if (defined (&$sub)) { 
               &$sub($r,$token,$parser,$safeeval,\@stack);    &$sub($r,$token,$parser,$safeeval,\@stack); 
            } else {      } else {
               $stack[$#stack].=$token->[4];   $stack[$#stack] .= $token->[4];
            }      }
          }   }
       }      }
         
       if ($target eq 'edit') {      if ($target eq 'edit') {
          my $depthlabel=join('_',@depthcounter);   my $depthlabel = join('_',@depthcounter);
          if (defined($xmltags{$token->[1]})) {   if (defined($xmltags{$token->[1]})) {
             if (defined($topleveltags{$token->[1]})) {      if (defined($topleveltags{$token->[1]})) {
                &insertmenu($r,$xmltags{$token->[1]},   &insertmenu($r,$xmltags{$token->[1]},
                            $depthlabel,\%topleveltags);      $depthlabel,\%topleveltags);
               $toplevel=$token->[1];   $toplevel = $token->[1];
             } else {      } else {
                 if ($toplevel eq 'answer') {   if ($toplevel eq 'answer') {
                    &insertmenu($r,$xmltags{$token->[1]},      &insertmenu($r,$xmltags{$token->[1]},
                                $depthlabel,\%answertags);   $depthlabel,\%answertags);
                 }   }
             }      }
             my $sub="start_edit_$token->[1]";      my $sub = "start_edit_$token->[1]";
             {      {
               no strict 'refs';   no strict 'refs';
               if (defined (&$sub)) {    if (defined (&$sub)) { 
                  &$sub($r,$token,$parser,$xmltags{$token->[1]},      &$sub($r,$token,$parser,$xmltags{$token->[1]},
                        $depthlabel,$above,\%answertypes,\@stack);     $depthlabel,$above,\%answertypes,\@stack); 
               }   }
             }       } 
          } else {   } else {
             $stack[$#stack].=$token->[4];      $stack[$#stack] .= $token->[4];
          }   }
       }      }
       
       if ($target eq 'modified') {      if ($target eq 'modified') {
       }      }
       
 # =============================================================================  # =============================================================================
    } elsif ($token->[0] eq 'E') {   } elsif ($token->[0] eq 'E') {
 # ===================================================================== End Tag  # ===================================================================== End Tag
   
       if ($target eq 'web') {      if ($target eq 'web') {
          my $sub="end_$token->[1]";   my $sub = "end_$token->[1]";
          {   {
            no strict 'refs';      no strict 'refs';
            if (defined (&$sub)) {       if (defined (&$sub)) { 
               &$sub($r,$token,$parser,$safeeval,\@stack);   &$sub($r,$token,$parser,$safeeval,\@stack);
            } else {      } else {
               $stack[$#stack].=$token->[2];   $stack[$#stack] .= $token->[2];
            }      }
          }   }
       }      }
       
       if ($target eq 'edit') {      if ($target eq 'edit') {
          if (defined($xmltags{$token->[1]})) {   if (defined($xmltags{$token->[1]})) {
             my $sub="end_edit_$token->[1]";      my $sub = "end_edit_$token->[1]";
             {      {
               no strict 'refs';   no strict 'refs';
               if (defined (&$sub)) {    if (defined (&$sub)) { 
                  &$sub($r,$token,$above,\@stack);       &$sub($r,$token,$above,\@stack); 
               }   }
             }       } 
          }    } 
       }      }
       
       if ($target eq 'modified') {      if ($target eq 'modified') {
       }      }
 # --------------------------------------------------------------- Depth Counter  # --------------------------------------------------------------- Depth Counter
       if (defined($xmltags{$token->[1]})) { $depth--; }      if (defined($xmltags{$token->[1]})) { $depth--; }
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
 # =============================================================================  # =============================================================================
    } elsif ($token->[0] eq 'T') {   } elsif ($token->[0] eq 'T') {
 # ================================================================= Parsed Text  # ================================================================= Parsed Text
       $stack[$#stack].=$token->[1];      $stack[$#stack] .= $token->[1];
    }   }
 }      }
       
 return $outtext;      return $outtext;
 }  }
 # =============================================================================  # =============================================================================
   
Line 212  return $outtext; Line 216  return $outtext;
 # ------------------------------------------------- Helper Routines for Editing  # ------------------------------------------------- Helper Routines for Editing
   
 sub rawprint {  sub rawprint {
    my ($r,$data)=@_;    my ($r,$data) = @_;
    $r->print($data);    $r->print($data);
 }  }
   
 sub insertmenu {  sub insertmenu {
    my ($r,$description,$depthlabel,$xmltagsref)=@_;      my ($r,$description,$depthlabel,$xmltagsref) = @_;
    &rawprint($r,'<br><table bgcolor="#DDDD33" width="100%"><tr><td>');      &rawprint($r,'<br><table bgcolor="#DDDD33" width="100%"><tr><td>');
    &rawprint($r,"\n".'<select name="mod_menu_'.$depthlabel.'">'."\n");      &rawprint($r,"\n".'<select name="mod_menu_'.$depthlabel.'">'."\n");
    &rawprint($r,'<option value="no_changes" selected>(no changes)</option>');      &rawprint($r,'<option value="no_changes" selected>(no changes)</option>');
    &rawprint($r,"\n".      &rawprint($r,"\n".
                 '<option value="delete">Delete '.$description.        '<option value="delete">Delete '.$description.
                                                ' Below</option>');        ' Below</option>');
    my $key;      my $key;
    foreach $key (keys %$xmltagsref) {      foreach $key (keys %$xmltagsref) {
       &rawprint($r,"\n".   &rawprint($r,"\n".
                    '<option value="insert_'.$key.'">Insert '.    '<option value="insert_'.$key.'">Insert '.
                    $$xmltagsref{$key}.'</option>');    $$xmltagsref{$key}.'</option>');
    }      }
    &rawprint($r,"\n".'</select></td></tr></table><br>'."\n");      &rawprint($r,"\n".'</select></td></tr></table><br>'."\n");
 }  }
   
 # =============================================================================  # =============================================================================
Line 240  sub insertmenu { Line 244  sub insertmenu {
 # -------------------------------------------- Initialize routines in $safeeval  # -------------------------------------------- Initialize routines in $safeeval
   
 sub init_safeeval {  sub init_safeeval {
    my $safeeval=shift;      my $safeeval = shift;
    my $initprg=<<'ENDINIT';       my $initprg =<<'ENDINIT'; 
   
 # -------------------------------------------- Initializations inside $safeeval  # -------------------------------------------- Initializations inside $safeeval
   
 $e=25;      $e = 25;
 $c=20;      $c = 20;
   
 ENDINIT    ENDINIT
 # ---------------------------------------------------------------- Execute that  # ---------------------------------------------------------------- Execute that
    $safeeval->reval($initprg);      $safeeval->reval($initprg);
 }  }
   
 # ----------------------------------------------- Routines that use Safe Spaces  # ----------------------------------------------- Routines that use Safe Spaces
   
 sub printout {  sub printout {
    my ($r,$data,$safespace)=@_;      my ($r,$data,$safespace) = @_;
    $r->print($safespace->reval('return qq('.$data.');'));      $r->print($safespace->reval('return qq('.$data.');'));
 }  }
   
 sub runfile {  sub runfile {
    my ($r,$filename,$safespace)=@_;      my ($r,$filename,$safespace) = @_;
    my $includefile;      my $includefile;
    if ($filename=~/^\//) {      if ($filename =~ /^\//) {
        $includefile=$filename;   $includefile = $filename;
    } else {      } else {
        $includefile=$r->dir_config('lonIncludes');   $includefile = $r->dir_config('lonIncludes');
        $includefile.='/'.$filename;   $includefile .= '/'.$filename;
    }      }
    if (-e $includefile) {      if (-e $includefile) {
       $safespace->rdo($includefile);   $safespace->rdo($includefile);
    }         }   
 }  }
   
 sub run {  sub run {
    my ($expression,$safespace)=@_;      my ($expression,$safespace) = @_;
    $safespace->reval($expression);         $safespace->reval($expression);   
 }  }
   
 sub booleanexpr {  sub booleanexpr {
    my ($expression,$safespace)=@_;      my ($expression,$safespace) = @_;
    return $safespace->reval('return '.$expression.';');      return $safespace->reval('return '.$expression.';');
 }  }
   
   
Line 290  sub booleanexpr { Line 294  sub booleanexpr {
 # =============================================================================  # =============================================================================
   
 sub start_block {  sub start_block {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    if (!booleanexpr($token->[2]{'condition'},$safeeval)) {      if (!booleanexpr($token->[2]{'condition'},$safeeval)) {
       my $blockdepth=0;   my $blockdepth = 0;
       my $nexttoken;   my $nexttoken;
       while ($nexttoken=$parser->get_tag()) {    while ($nexttoken=$parser->get_tag()) { 
          if ($nexttoken->[0] eq 'block') { $blockdepth++ };      if ($nexttoken->[0] eq 'block') { $blockdepth++ };
          if ($nexttoken->[0] eq '/block') {      if ($nexttoken->[0] eq '/block') {
             if ($blockdepth==0) {    if ($blockdepth == 0) { 
                return;       return; 
             } else {   } else {
                $blockdepth--;      $blockdepth--;
             }   }
          }      }
       }   }
    }      }
    return;      return;
 }  }
   
 sub start_script {  sub start_script {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    $stackref->[$#$stackref+1]='';      $stackref->[$#$stackref+1] = '';
 }  }
   
 sub end_script {  sub end_script {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    &run($stackref->[$#$stackref],$safeeval);      &run($stackref->[$#$stackref],$safeeval);
    $#$stackref--;      $#$stackref--;
 }  }
   
 sub start_outtext {  sub start_outtext {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    $stackref->[$#$stackref+1]='';      $stackref->[$#$stackref+1] = '';
 }  }
   
 sub end_outtext {  sub end_outtext {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    &printout($r,$stackref->[$#$stackref],$safeeval);      &printout($r,$stackref->[$#$stackref],$safeeval);
    $#$stackref--;      $#$stackref--;
 }  }
   
 sub start_inlinetext {  sub start_inlinetext {
    &start_outtext(@_);      &start_outtext(@_);
 }  }
   
 sub end_inlinetext {  sub end_inlinetext {
    &end_outtext(@_);      &end_outtext(@_);
 }  }
   
 sub start_scriptlib {  sub start_scriptlib {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    &runfile($r,$parser->get_text('/scriptlib'),$safeeval);      &runfile($r,$parser->get_text('/scriptlib'),$safeeval);
 }  }
   
 sub start_parserlib {  sub start_parserlib {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    &runfile($r,$parser->get_text('/parserlib'),$parsereval);      &runfile($r,$parser->get_text('/parserlib'),$parsereval);
 }  }
   
   
 sub start_answer {  sub start_answer {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    $stackref->[$#$stackref+1]='<answer>::'.      $stackref->[$#$stackref+1] = '<answer>::'.
      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});   
    $stackref->[$#$stackref+1]='';      $stackref->[$#$stackref+1] = '';
 }  }
   
 sub end_answer {  sub end_answer {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    my @itemtexts;      my @itemtexts;
    my @itemargs;      my @itemargs;
    my $stackpointer=$#$stackref;      my $stackpointer = $#$stackref;
    while (($stackref->[$stackpointer]!~'<answer>::') && ($stackpointer>0)) {       while (($stackref->[$stackpointer] !~ '<answer>::') &&
       $stackpointer--;      ($stackpointer > 0)) { 
    }   $stackpointer--; 
    my %answerargs=split(/:/,$stackref->[$stackpointer]);      }
       my %answerargs=split(/:/,$stackref->[$stackpointer]);
 }  }
   
 sub start_item {  sub start_item {
    my ($r,$token,$parser,$safeeval,$stackref)=@_;      my ($r,$token,$parser,$safeeval,$stackref) = @_;
    $stackref->[$#$stackref+1]='<item>::'.      $stackref->[$#$stackref+1] = '<item>::'.
      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});      join(':',map{$_.':'.$token->[2]->{$_}} @{$token->[3]});   
    $stackref->[$#$stackref+1]='';      $stackref->[$#$stackref+1]='';
 }  }
   
 sub end_item {}  sub end_item {}
Line 381  sub end_item {} Line 386  sub end_item {}
 # =============================================================================  # =============================================================================
   
 sub start_edit_outtext {  sub start_edit_outtext {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,      my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;   $stackref) = @_;
    &rawprint($r,"\n<h3>$description</h3>".      &rawprint($r,"\n<h3>$description</h3>".
      '<textarea rows="10" cols="80" name="data_'.$depthlabel.'">');        '<textarea rows="10" cols="80" name="data_'.$depthlabel.'">');
    $stackref->[$#$stackref+1]='';      $stackref->[$#$stackref+1] = '';
 }  }
   
 sub end_edit_outtext {  sub end_edit_outtext {
    my ($r,$token,$above,$stackref)=@_;      my ($r,$token,$above,$stackref) = @_;
    &rawprint($r,$stackref->[$#$stackref]."</textarea>\n");         &rawprint($r,$stackref->[$#$stackref]."</textarea>\n");   
    $#$stackref--;      $#$stackref--;
 }  }
   
 sub start_edit_script {  sub start_edit_script {
    &start_edit_outtext(@_);      &start_edit_outtext(@_);
 }  }
   
 sub end_edit_script {  sub end_edit_script {
    &end_edit_outtext(@_);      &end_edit_outtext(@_);
 }  }
   
 sub start_edit_inlinetext {  sub start_edit_inlinetext {
    &start_edit_outtext(@_);      &start_edit_outtext(@_);
 }  }
   
 sub end_edit_inlinetext {  sub end_edit_inlinetext {
    &end_edit_inlinetext(@_);      &end_edit_inlinetext(@_);
 }  }
   
 sub start_edit_block {  sub start_edit_block {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,      my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;   $stackref) = @_;
    my $bgcolor=$depthlabel;      my $bgcolor = $depthlabel;
    $bgcolor=~s/\_//g;      $bgcolor =~ s/\_//g;
    $bgcolor=substr(length($bgcolor),-1,1);      $bgcolor = substr(length($bgcolor),-1,1);
    $bgcolor=~tr/1-5/A-E/;      $bgcolor =~ tr/1-5/A-E/;
    $bgcolor=$bgcolor.'FFF'.$bgcolor.'A';      $bgcolor = $bgcolor.'FFF'.$bgcolor.'A';
    &rawprint($r,"\n".'<br><table border="2" cellpadding="10" bgcolor="#'.      &rawprint($r,"\n".'<br><table border="2" cellpadding="10" bgcolor="#'.
                 $bgcolor.        $bgcolor.
                 '" width="100%"><tr><td><h3>'.$description.'</h3>');        '" width="100%"><tr><td><h3>'.$description.'</h3>');
 }  }
   
 sub end_edit_block {  sub end_edit_block {
    my ($r,$token,$above,$stackref)=@_;      my ($r,$token,$above,$stackref) = @_;
    &rawprint($r,"\n".'</td></tr></table><br>');      &rawprint($r,"\n".'</td></tr></table><br>');
 }  }
   
 sub start_edit_answer {  sub start_edit_answer {
    my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,      my ($r,$token,$parser,$description,$depthlabel,$above,$answertyperef,
        $stackref)=@_;   $stackref) = @_;
    start_edit_block(@_);      start_edit_block(@_);
    $above=$token->[2]{'type'};      $above = $token->[2]{'type'};
    &rawprint($r,"\n".'<select name="mod_type_'.$depthlabel.'">');      &rawprint($r,"\n".'<select name="mod_type_'.$depthlabel.'">');
    my $key;      my $key;
    foreach $key (keys %$answertyperef) {      foreach $key (keys %$answertyperef) {
       &rawprint($r,"\n".'<option value="'.$key.'"');   &rawprint($r,"\n".'<option value="'.$key.'"');
       if ($above eq $key) { &rawprint($r,' selected'); }   if ($above eq $key) { &rawprint($r,' selected'); }
       &rawprint($r,'>'.$$answertyperef{$key}.'</option>');   &rawprint($r,'>'.$$answertyperef{$key}.'</option>');
    }      }
    &rawprint($r,"\n".'</select>'."\n");      &rawprint($r,"\n".'</select>'."\n");
 }  }
   
 sub end_edit_answer {  sub end_edit_answer {
    my ($r,$token,$above,$stackref)=@_;      my ($r,$token,$above,$stackref)=@_;
    end_edit_block(@_);      end_edit_block(@_);
 }  }
   
 sub start_edit_include {  sub start_edit_include {
Line 465  sub end_edit_problem { Line 470  sub end_edit_problem {
 }  }
   
 1;  1;
 __END__  
   
   __END__
     
   
   
   

Removed from v.1.2  
changed lines
  Added in v.1.4


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