--- loncom/xml/lonxml.pm	2006/12/19 14:24:07	1.431
+++ loncom/xml/lonxml.pm	2007/05/17 21:00:59	1.446
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.431 2006/12/19 14:24:07 www Exp $
+# $Id: lonxml.pm,v 1.446 2007/05/17 21:00:59 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -42,6 +42,7 @@ package Apache::lonxml;
 use vars 
 qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount);
 use strict;
+use LONCAPA;
 use HTML::LCParser();
 use HTML::TreeBuilder();
 use HTML::Entities();
@@ -550,7 +551,6 @@ sub callsub {
     }
 
     my $deleted=0;
-    $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
     if (($token->[0] eq 'S') && ($target eq 'modified')) {
       $deleted=&Apache::edit::handle_delete($space,$target,$token,$tagstack,
 					     $parstack,$parser,$safeeval,
@@ -586,17 +586,23 @@ sub callsub {
 	  } elsif ($token->[0] eq 'E') {
 	    $currentstring = &Apache::edit::tag_end($target,$token);
 	  }
-	} elsif ($target eq 'modified') {
+	}
+      }
+      if ($target eq 'modified' && $nodefault eq '') {
+	  if ($currentstring eq '') {
+	      if ($token->[0] eq 'S') {
+		  $currentstring = $token->[4];
+	      } elsif ($token->[0] eq 'E') {
+		  $currentstring = $token->[2];
+	      } else {
+		  $currentstring = $token->[2];
+	      }
+	  }
 	  if ($token->[0] eq 'S') {
-	    $currentstring = $token->[4];
 	    $currentstring.=&Apache::edit::handle_insert();
 	  } elsif ($token->[0] eq 'E') {
-	    $currentstring = $token->[2];
             $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
-	  } else {
-	    $currentstring = $token->[2];
 	  }
-	}
       }
     }
     use strict 'refs';
@@ -676,6 +682,12 @@ sub init_safespace {
   $safehole->wrap(\&Apache::response::check_status,$safeeval,'&check_status');
 
   $safehole->wrap(\&Apache::lonmaxima::maxima_eval,$safeeval,'&maxima_eval');
+  $safehole->wrap(\&Apache::lonmaxima::maxima_check,$safeeval,'&maxima_check');
+  $safehole->wrap(\&Apache::lonmaxima::maxima_cas_formula_fix,$safeeval,
+		  '&maxima_cas_formula_fix');
+
+  $safehole->wrap(\&Apache::caparesponse::capa_formula_fix,$safeeval,
+		  '&capa_formula_fix');
 
   $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin');
   $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos');
@@ -896,51 +908,50 @@ sub end_tag {
 
 sub initdepth {
   @Apache::lonxml::depthcounter=();
-  $Apache::lonxml::depth=-1;
-  $Apache::lonxml::olddepth=-1;
+  undef($Apache::lonxml::last_depth_count);
 }
 
+
 my @timers;
 my $lasttime;
+# @Apache::lonxml::depthcounter -> count of tags that exist so
+#                                  far at each level
+# $Apache::lonxml::last_depth_count -> when ascending, need to
+# remember the count for the level below the current level (for
+# example going from 1_2 -> 1 -> 1_3 need to remember the 2 )
+
 sub increasedepth {
   my ($token) = @_;
-  $Apache::lonxml::depth++;
-  $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++;
-  if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) {
-    $Apache::lonxml::olddepth=$Apache::lonxml::depth;
-  }
+  push(@Apache::lonxml::depthcounter,$Apache::lonxml::last_depth_count+1);
+  undef($Apache::lonxml::last_depth_count);
   my $time;
   if ($Apache::lonxml::debug eq "1") {
       push(@timers,[&gettimeofday()]);
       $time=&tv_interval($lasttime);
       $lasttime=[&gettimeofday()];
   }
-  my $spacing='  'x($Apache::lonxml::depth-1);
-  my $curdepth=join('_',@Apache::lonxml::depthcounter);
-  &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : \n");
+  my $spacing='  'x($#Apache::lonxml::depthcounter);
+  $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
+#  &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time");
 #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n";
 }
 
 sub decreasedepth {
   my ($token) = @_;
-  $Apache::lonxml::depth--;
-  if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) {
-    $#Apache::lonxml::depthcounter--;
-    $Apache::lonxml::olddepth=$Apache::lonxml::depth+1;
-  }
-  if (  $Apache::lonxml::depth < -1) {
-    &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file."));
-    $Apache::lonxml::depth='-1';
+  if (  $#Apache::lonxml::depthcounter == -1) {
+      &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file."));
   }
+  $Apache::lonxml::last_depth_count = pop(@Apache::lonxml::depthcounter);
+
   my ($timer,$time);
   if ($Apache::lonxml::debug eq "1") {
       $timer=pop(@timers);
       $time=&tv_interval($lasttime);
       $lasttime=[&gettimeofday()];
   }
-  my $spacing='  'x$Apache::lonxml::depth;
-  my $curdepth=join('_',@Apache::lonxml::depthcounter);
-  &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : ".&tv_interval($timer)."\n");
+  my $spacing='  'x($#Apache::lonxml::depthcounter);
+  $Apache::lonxml::curdepth = join('_',@Apache::lonxml::depthcounter);
+#  &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time : ".&tv_interval($timer));
 #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n";
 }
 
@@ -1198,7 +1209,7 @@ sub writeallows {
     my %httpref=();
     foreach (@extlinks) {
        $httpref{'httpref.'.
- 	        &Apache::lonnet::hreflocation($thisdir,$_)}=$thisurl;
+ 	        &Apache::lonnet::hreflocation($thisdir,&unescape($_))}=$thisurl;
     }
     @extlinks=();
     &Apache::lonnet::appenv(%httpref);
@@ -1460,7 +1471,6 @@ ENDNOTFOUND
             &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
 						    ['editmode']);
 	}
-	&Apache::lonnet::logthis("edit mode is ".$env{'form.editmode'});
 	if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) {
 	    $result = &Apache::lonxml::xmlparse($request,$target,$filecontents,
 						'',%mystyle);
@@ -1564,8 +1574,9 @@ sub error {
 	if ( $symb && $env{'request.course.id'} ) {
 	    my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'};
 	    my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
-	    my (undef,%users)=&Apache::lonfeedback::decide_receiver(undef,0,1,1,1);
+	    my (undef,%users)=&Apache::lonmsg::decide_receiver(undef,0,1,1,1);
 	    my $declutter=&Apache::lonnet::declutter($env{'request.filename'});
+            my $baseurl = &Apache::lonnet::clutter($declutter);
 	    my @userlist;
 	    foreach (keys %users) {
 		my ($user,$domain) = split(/:/, $_);
@@ -1576,8 +1587,11 @@ sub error {
 						      $cdom,$cnum);
 		my $now=time;
 		if ($now-$lastnotified{$key}>86400) {
+                    my $title = &Apache::lonnet::gettitle($symb);
+                    my $sentmessage;
 		    &Apache::lonmsg::user_normal_msg($user,$domain,
-						 "Error [$declutter]",$msg);
+		        "Error [$title]",$msg,'',$baseurl,'','',
+                        \$sentmessage,$symb,$title,1);
 		    &Apache::lonnet::put('nohist_xmlerrornotifications',
 					 {$key => $now},
 					 $cdom,$cnum);		
@@ -1685,71 +1699,144 @@ sub get_param_var {
   }
 }
 
-sub register_insert {
-  my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab');
-  my $i;
-  my $tagnum=0;
-  my @order;
-  for ($i=0;$i < $#data; $i++) {
-    my $line = $data[$i];
-    if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; }
-    if ( $line =~ /TABLE/ ) { last; }
-    my ($tag,$descrip,$color,$function,$show,$helpfile,$helpdesc) = split(/,/, $line);
-    if ($tag) {
-      $insertlist{"$tagnum.tag"} = $tag;
-      $insertlist{"$tagnum.description"} = $descrip;
-      $insertlist{"$tagnum.color"} = $color;
-      $insertlist{"$tagnum.function"} = $function;
-      if (!defined($show)) { $show='yes'; }
-      $insertlist{"$tagnum.show"}= $show;
-      $insertlist{"$tagnum.helpfile"} = $helpfile;
-      $insertlist{"$tagnum.helpdesc"} = $helpdesc;
-      $insertlist{"$tag.num"}=$tagnum;
-      $tagnum++;
+sub register_insert_xml {
+    my $parser = HTML::LCParser->new($Apache::lonnet::perlvar{'lonTabDir'}
+				     .'/insertlist.xml');
+    my ($tagnum,$in_help)=(0,0);
+    my @alltags;
+    my $tag;
+    while (my $token = $parser->get_token()) {
+	if ($token->[0] eq 'S') {
+	    my $key;
+	    if      ($token->[1] eq 'tag') {
+		$tag = $token->[2]{'name'};
+		$insertlist{"$tagnum.tag"} = $tag;
+		$insertlist{"$tag.num"}   = $tagnum;
+		push(@alltags,$tag);
+	    } elsif ($in_help && $token->[1] eq 'file') {
+		$key = $tag.'.helpfile';
+	    } elsif ($in_help && $token->[1] eq 'description') {
+		$key = $tag.'.helpdesc';
+	    } elsif ($token->[1] eq 'description' ||
+		     $token->[1] eq 'color'       ||
+		     $token->[1] eq 'show'          ) {
+		$key = $tag.'.'.$token->[1];
+	    } elsif ($token->[1] eq 'insert_sub') {
+		$key = $tag.'.function';
+	    } elsif ($token->[1] eq 'help') {
+		$in_help=1;
+	    } elsif ($token->[1] eq 'allow') {
+		$key = $tag.'.allow';
+	    }
+	    if (defined($key)) {
+		$insertlist{$key} = $parser->get_text();
+		$insertlist{$key} =~ s/(^\s*|\s*$ )//gx;
+	    }
+	} elsif ($token->[0] eq 'E') {
+	    if      ($token->[1] eq 'tag') {
+		undef($tag);
+		$tagnum++;
+	    } elsif ($token->[1] eq 'help') {
+		undef($in_help);
+	    }
+	}
     }
-  }
-  $i++; #skipping TABLE line
-  $tagnum = 0;
-  for (;$i < $#data;$i++) {
-    my $line = $data[$i];
-    my ($mnemonic,@which) = split(/ +/,$line);
-    my $tag = $insertlist{"$tagnum.tag"};
-    for (my $j=0;$j <=$#which;$j++) {
-      if ( $which[$j] eq 'Y' ) {
-	if ($insertlist{"$j.show"} ne 'no') {
-	  push(@{ $insertlist{"$tag.which"} },$j);
+    
+    # parse the allows and ignore tags set to <show>no</show>
+    foreach my $tag (@alltags) {	
+        next if (!exists($insertlist{"$tag.allow"}));
+	my $allow =  $insertlist{"$tag.allow"};
+       	foreach my $element (split(',',$allow)) {
+	    $element =~ s/(^\s*|\s*$ )//gx;
+	    if (!exists($insertlist{"$element.show"})
+                || $insertlist{"$element.show"} ne 'no') {
+		push(@{ $insertlist{$tag.'.which'} },$element);
+	    }
 	}
-      }
     }
-    $tagnum++;
-  }
+}
+
+sub register_insert {
+    return &register_insert_xml(@_);
+#    &dump_insertlist('2');
+}
+
+sub dump_insertlist {
+    my ($ext) = @_;
+    open(XML,">/tmp/insertlist.xml.$ext");
+    print XML ("<insertlist>");
+    my $i=0;
+
+    while (exists($insertlist{"$i.tag"})) {
+	my $tag = $insertlist{"$i.tag"};
+	print XML ("
+\t<tag name=\"$tag\">");
+	if (defined($insertlist{"$tag.description"})) {
+	    print XML ("
+\t\t<description>".$insertlist{"$tag.description"}."</description>");
+	}
+	if (defined($insertlist{"$tag.color"})) {
+	    print XML ("
+\t\t<color>".$insertlist{"$tag.color"}."</color>");
+	}
+	if (defined($insertlist{"$tag.function"})) {
+	    print XML ("
+\t\t<insert_sub>".$insertlist{"$tag.function"}."</insert_sub>");
+	}
+	if (defined($insertlist{"$tag.show"})
+	    && $insertlist{"$tag.show"} ne 'yes') {
+	    print XML ("
+\t\t<show>".$insertlist{"$tag.show"}."</show>");
+	}
+	if (defined($insertlist{"$tag.helpfile"})) {
+	    print XML ("
+\t\t<help>
+\t\t\t<file>".$insertlist{"$tag.helpfile"}."</file>");
+	    if ($insertlist{"$tag.helpdesc"} ne '') {
+		print XML ("
+\t\t\t<description>".$insertlist{"$tag.helpdesc"}."</description>");
+	    }
+	    print XML ("
+\t\t</help>");
+	}
+	if (defined($insertlist{"$tag.which"})) {
+	    print XML ("
+\t\t<allow>".join(',',sort(@{ $insertlist{"$tag.which"} }))."</allow>");
+	}
+	print XML ("
+\t</tag>");
+	$i++;
+    }
+    print XML ("\n</insertlist>\n");
+    close(XML);
 }
 
 sub description {
-  my ($token)=@_;
-  my $tagnum;
-  my $tag=$token->[1];
-  foreach my $namespace (reverse @Apache::lonxml::namespace) {
-    my $testtag=$namespace.'::'.$tag;
-    $tagnum=$insertlist{"$testtag.num"};
-    if (defined($tagnum)) { last; }
-  }
-  if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; }
-  return $insertlist{$tagnum.'.description'};
+    my ($token)=@_;
+    my $tag = &get_tag($token);
+    return $insertlist{$tag.'.description'};
 }
 
 # Returns a list containing the help file, and the description
 sub helpinfo {
-  my ($token)=@_;
-  my $tagnum;
-  my $tag=$token->[1];
-  foreach my $namespace (reverse @Apache::lonxml::namespace) {
-    my $testtag=$namespace.'::'.$tag;
-    $tagnum=$insertlist{"$testtag.num"};
-    if (defined($tagnum)) { last; }
-  }
-  if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; }
-  return ($insertlist{$tagnum.'.helpfile'}, $insertlist{$tagnum.'.helpdesc'});
+    my ($token)=@_;
+    my $tag = &get_tag($token);
+    return ($insertlist{$tag.'.helpfile'}, $insertlist{$tag.'.helpdesc'});
+}
+
+sub get_tag {
+    my ($token)=@_;
+    my $tagnum;
+    my $tag=$token->[1];
+    foreach my $namespace (reverse(@Apache::lonxml::namespace)) {
+	my $testtag = $namespace.'::'.$tag;
+	$tagnum = $insertlist{"$testtag.num"};
+	last if (defined($tagnum));
+    }
+    if (!defined($tagnum)) {
+	$tagnum = $Apache::lonxml::insertlist{"$tag.num"};
+    }
+    return $insertlist{"$tagnum.tag"};
 }
 
 1;