--- loncom/xml/lonxml.pm	2007/02/18 02:07:11	1.438
+++ loncom/xml/lonxml.pm	2008/03/21 18:52:28	1.473.2.1
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.438 2007/02/18 02:07:11 albertel Exp $
+# $Id: lonxml.pm,v 1.473.2.1 2008/03/21 18:52:28 raeburn 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();
@@ -91,8 +92,10 @@ use Apache::loncacc();
 use Apache::lonmaxima();
 use Apache::lonlocal;
 
-#==================================================   Main subroutine: xmlparse  
+#====================================   Main subroutine: xmlparse  
+
 #debugging control, to turn on debugging modify the correct handler
+
 $Apache::lonxml::debug=0;
 
 # keeps count of the number of warnings and errors generated in a parse
@@ -124,6 +127,9 @@ $evaluate = 1;
 # stores the list of active tag namespaces
 @namespace=();
 
+# stores all Scrit Vars displays for later showing
+my @script_var_displays=();
+
 # a pointer the the Apache request object
 $Apache::lonxml::request='';
 
@@ -131,6 +137,16 @@ $Apache::lonxml::request='';
 $Apache::lonxml::counter=1;
 $Apache::lonxml::counter_changed=0;
 
+# Part counter hash.   In analysis mode, the
+# problems can use this to record which parts increment the counter
+# by how much.  The counter subs will maintain this hash via
+# their optional part parameters.  Note that the assumption is that
+# analysis is done in one request and therefore it is not necessary to
+# save this information request-to-request.
+
+
+%Apache::lonxml::counters_per_part = ();
+
 #internal check on whether to look at style defs
 $Apache::lonxml::usestyle=1;
 
@@ -315,13 +331,14 @@ sub xmlparse {
 	     }
 	 }
      }
- } elsif ($env{'construct.style'} && ($env{'request.state'} eq 'construct')) {
+ } elsif ($env{'construct.style'}
+	  && ($env{'request.state'} eq 'construct')) {
      my $location=&Apache::lonnet::filelocation('',$env{'construct.style'});
      my $styletext=&Apache::lonnet::getfile($location);
-       if ($styletext ne '-1') {
-          %style_for_target = (%style_for_target,
-                          &Apache::style::styleparser($target,$styletext));
-      }
+     if ($styletext ne '-1') {
+	 %style_for_target = (%style_for_target,
+			      &Apache::style::styleparser($target,$styletext));
+     }
  }
 #&printalltags();
  my @pars = ();
@@ -356,7 +373,16 @@ sub xmlparse {
 
  &clean_safespace($safeeval);
 
+ if (@script_var_displays) {
+     $finaloutput .= join('',@script_var_displays);
+     undef(@script_var_displays);
+ }
+ &init_state();
  if ($env{'form.return_only_error_and_warning_counts'}) {
+     if ($env{'request.filename'}=~/\.(html|htm|xml)$/i) { 
+        my $error=&verify_html($content_file_string);
+        if ($error) { $errorcount++; }
+     }
      return "$errorcount:$warningcount";
  }
  return $finaloutput;
@@ -585,17 +611,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();
+	      $currentstring.=&Apache::edit::handle_insert();
 	  } elsif ($token->[0] eq 'E') {
-	    $currentstring = $token->[2];
-            $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
-	  } else {
-	    $currentstring = $token->[2];
+	      $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
 	  }
-	}
       }
     }
     use strict 'refs';
@@ -603,6 +635,24 @@ sub callsub {
   return $currentstring;
 }
 
+{
+    my %state;
+
+    sub init_state {
+	undef(%state);
+    }
+    
+    sub set_state {
+	my ($key,$value) = @_;
+	$state{$key} = $value;
+	return $value;
+    }
+    sub get_state {
+	my ($key) = @_;
+	return $state{$key};
+    }
+}
+
 sub setup_globals {
   my ($request,$target)=@_;
   $Apache::lonxml::request=$request;
@@ -611,8 +661,12 @@ sub setup_globals {
   $Apache::lonxml::default_homework_loaded=0;
   $Apache::lonxml::usestyle=1;
   &init_counter();
+  &clear_bubble_lines_for_part();
+  &init_state();
+  &set_state('target',$target);
   @Apache::lonxml::pwd=();
   @Apache::lonxml::extlinks=();
+  @script_var_displays=();
   @Apache::lonxml::ssi_info=();
   $Apache::lonxml::post_evaluate=1;
   $Apache::lonxml::warnings_error_header='';
@@ -673,6 +727,7 @@ sub init_safespace {
   $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval,
 		  '&chem_standard_order');
   $safehole->wrap(\&Apache::response::check_status,$safeeval,'&check_status');
+  $safehole->wrap(\&Apache::response::implicit_multiplication,$safeeval,'&implicit_multiplication');
 
   $safehole->wrap(\&Apache::lonmaxima::maxima_eval,$safeeval,'&maxima_eval');
   $safehole->wrap(\&Apache::lonmaxima::maxima_check,$safeeval,'&maxima_check');
@@ -783,6 +838,7 @@ sub init_safespace {
   $safehole->wrap(\&Math::Random::random_set_seed_from_phrase,$safeeval,'&random_set_seed_from_phrase');
   $safehole->wrap(\&Math::Random::random_get_seed,$safeeval,'&random_get_seed');
   $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed');
+  $safehole->wrap(\&Apache::loncommon::languages,$safeeval,'&languages');
   $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR');
   $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG');
   $safehole->wrap(\&Apache::lonnet::logthis,$safeeval,'&LONCAPA_INTERNAL_LOGTHIS');
@@ -891,6 +947,9 @@ sub endredirection {
     }
     pop @Apache::lonxml::outputstack;
 }
+sub in_redirection {
+    return ($Apache::lonxml::redirection > 0)
+}
 
 sub end_tag {
   my ($tagstack,$parstack,$token)=@_;
@@ -901,66 +960,58 @@ 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::depth -> current stack depth
 # @Apache::lonxml::depthcounter -> count of tags that exist so
 #                                  far at each level
-# $Apache::lonxml::olddepth -> 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 rember that ) 
+# $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 $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");
+#  &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;
-  $Apache::lonxml::curdepth=
-      join('_',@Apache::lonxml::depthcounter[0..$Apache::lonxml::depth]);
-  &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time : ".&tv_interval($timer));
+  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";
 }
 
 sub get_id {
     my ($parstack,$safeeval)=@_;
     my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval);
-    if ($env{'request.state'} eq 'construct' && $id =~ /(\.|_)/) {
-	&error(&mt("IDs are not allowed to contain &quot;<tt>_</tt>&quot; or &quot;<tt>.</tt>&quot;"));
+    if ($env{'request.state'} eq 'construct' && $id =~ /([._]|[^\w\d\s[:punct:]])/) {
+	&error(&mt("ID &quot;[_1]&quot; contains invalid characters, IDs are only allowed to contain letters, numbers, spaces and -",'<tt>'.$id.'</tt>'));
     }
     if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; }
     return $id;
@@ -996,18 +1047,66 @@ sub get_all_text_unbalanced {
 	}
     }
     return $result
+
 }
 
+#########################################################################
+#                                                                       #
+#           bubble line counter management                              #
+#                                                                       #
+#########################################################################
+
+=pod
+
+For bubble grading mode and exam bubble printing mode, the tracking of
+the current 'bubble line number' is stored in the %env element
+'form.counter', and is modifed and handled by the following routines.
+
+The value of it is stored in $Apache:lonxml::counter when live and
+stored back to env after done.
+
+=item &increment_counter($increment);
+
+Increments the internal counter environment variable a specified amount
+
+Optional Arguments:
+  $increment - amount to increment by (defaults to 1)
+               Also 1 if the value is negative or zero.
+  $part_response - A concatenation of the part and response id
+                   identifying exactly what is being 'answered'.
+
+
+=cut
+
 sub increment_counter {
-    my ($increment) = @_;
-    if (defined($increment) && $increment gt 0) {
-	$Apache::lonxml::counter+=$increment;
-    } else {
-	$Apache::lonxml::counter++;
+    my ($increment, $part_response) = @_;
+    if (!defined($increment) || $increment le 0) {
+	$increment = 1;
     }
+    $Apache::lonxml::counter += $increment;
+
+    # If the caller supplied the response_id parameter, 
+    # Maintain its counter.. creating if necessary.
+
+    if (defined($part_response)) {
+	if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
+	    $Apache::lonxml::counters_per_part{$part_response} = 0;
+	}
+	$Apache::lonxml::counters_per_part{$part_response} += $increment;
+	my $new_value = $Apache::lonxml::counters_per_part{$part_response};
+    }
+	
     $Apache::lonxml::counter_changed=1;
 }
 
+=pod
+
+=item &init_counter($increment);
+
+Initialize the internal counter environment variable
+
+=cut
+
 sub init_counter {
     if ($env{'request.state'} eq 'construct') {
 	$Apache::lonxml::counter=1;
@@ -1053,6 +1152,73 @@ sub store_counter {
     }
 }
 
+=pod
+
+=item  bubble_lines_for_part(part_response)
+
+Returns the number of lines required to get a response for
+$part_response (this is just $Apache::lonxml::counters_per_part{$part_response}
+
+=cut
+
+sub bubble_lines_for_part {
+    my ($part_response) = @_;
+
+    if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
+	return 0;
+    } else {
+	return $Apache::lonxml::counters_per_part{$part_response};
+    }
+}
+
+=pod
+
+=item clear_bubble_lines_for_part
+
+Clears the hash of bubble lines per part.  If a caller
+needs to analyze several resources this should be called between
+resources to reset the hash for each problem being analyzed.
+
+=cut
+
+sub clear_bubble_lines_for_part {
+    undef(%Apache::lonxml::counters_per_part);
+}
+
+=pod
+
+=item set_bubble_lines(part_response, value)
+
+If there is a problem part, that for whatever reason
+requires bubble lines that are not
+the same as the counter increment, it can call this sub during
+analysis to set its hash value explicitly.
+
+=cut
+
+sub set_bubble_lines {
+    my ($part_response, $value) = @_;
+
+    $Apache::lonxml::counters_per_part{$part_response} = $value;
+}
+
+=pod
+
+=item get_bubble_line_hash
+
+Returns the current bubble line hash.  This is assumed to 
+be small so we return a copy
+
+
+=cut
+
+sub get_bubble_line_hash {
+    return %Apache::lonxml::counters_per_part;
+}
+
+
+#--------------------------------------------------
+
 sub get_all_text {
     my($tag,$pars,$style)= @_;
     my $gotfullstack=1;
@@ -1210,7 +1376,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);
@@ -1229,6 +1395,12 @@ sub do_registered_ssi {
 	&Apache::lonnet::ssi($url,%form);
     }
 }
+
+sub add_script_result {
+    my ($display) = @_;
+    push(@script_var_displays, $display);
+}
+
 #
 # Afterburner handles anchors, highlights and links
 #
@@ -1307,44 +1479,74 @@ SIMPLECONTENT
   return $filecontents;
 }
 
+sub verify_html {
+    my ($filecontents)=@_;
+    if ($filecontents!~/(?:\<|\&lt\;)(?:html|xml)[^\<]*(?:\>|\&gt\;)/is) {
+       return &mt('File does not have [_1] or [_2] starting tag','&lt;html&gt;','&lt;xml&gt;');
+    }
+    if ($filecontents!~/(?:\<|\&lt\;)\/(?:html|xml)(?:\>|\&gt\;)/is) {
+       return &mt('File does not have [_1] or [_2] ending tag','&lt;html&gt;','&lt;xml&gt;');
+    }
+    if ($filecontents!~/(?:\<|\&lt\;)(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
+       return &mt('File does not have [_1] or [_2] starting tag','&lt;body&gt;','&lt;frameset&gt;');
+    }
+    if ($filecontents!~/(?:\<|\&lt\;)\/(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
+       return &mt('File does not have [_1] or [_2] ending tag','&lt;body&gt;','&lt;frameset&gt;');
+    }
+    return '';
+}
 
 sub inserteditinfo {
-      my ($result,$filecontents,$filetype)=@_;
+      my ($filecontents, $filetype, $filename)=@_;
       $filecontents = &HTML::Entities::encode($filecontents,'<>&"');
-#      my $editheader='<a href="#editsection">Edit below</a><hr />';
       my $xml_help = '';
       my $initialize='';
-      if ($filetype eq 'html') {
-	  my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons();
-	  $initialize=&Apache::lonhtmlcommon::spellheader();
-	  if (!&Apache::lonhtmlcommon::htmlareablocked() &&
-	      &Apache::lonhtmlcommon::htmlareabrowser()) {
-	      $initialize.=(<<FULLPAGE);
+      my $textarea_id = 'filecont';
+      my ($add_to_onload, $add_to_onresize);
+      $initialize=&Apache::lonhtmlcommon::spellheader();
+      if ($filetype eq 'html' 
+	  && (!&Apache::lonhtmlcommon::htmlareablocked() &&
+	      &Apache::lonhtmlcommon::htmlareabrowser())) {
+	  $textarea_id .= '___Frame';
+	  my $lang = &Apache::lonhtmlcommon::htmlarea_lang();
+	  $initialize.=(<<FULLPAGE);
 <script type="text/javascript">
-$addbuttons
-
-    HTMLArea.loadPlugin("FullPage");
-
+lonca
     function initDocument() {
-	var editor=new HTMLArea("filecont",config);
-	editor.registerPlugin(FullPage);
-	editor.generate();
+        var oFCKeditor = new FCKeditor('filecont');
+	oFCKeditor.Config['CustomConfigurationsPath'] = '/fckeditor/loncapaconfig.js'  ;
+	oFCKeditor.Config['FullPage'] = true
+	oFCKeditor.Config['AutoDetectLanguage'] = false;
+        oFCKeditor.Config['DefaultLanguage'] = "$lang";
+	oFCKeditor.ReplaceTextarea();
+    }
+    function check_if_dirty(editor) {
+	if (editor.IsDirty()) {
+	    unClean();
+	}
+    }
+    function FCKeditor_OnComplete(editor) {
+	editor.Events.AttachEvent("OnSelectionChange",check_if_dirty);
+	resize_textarea('$textarea_id','LC_aftertextarea');
     }
 </script>
 FULLPAGE
-          } else {
-	      $initialize.=(<<FULLPAGE);
+      } else {
+	  $initialize.=(<<FULLPAGE);
 <script type="text/javascript">
-$addbuttons
     function initDocument() {
+	resize_textarea('$textarea_id','LC_aftertextarea');
     }
 </script>
 FULLPAGE
-	  }
-          $result=~s/\<body([^\>]*)\>/\<body onload="initDocument()" $1\>/i;
+      }
+
+      $add_to_onload = 'initDocument();';
+      $add_to_onresize = "resize_textarea('$textarea_id','LC_aftertextarea');";
+
+      if ($filetype eq 'html') {
 	  $xml_help=&Apache::loncommon::helpLatexCheatsheet();
       }
-      my $cleanbut = '';
 
       my $titledisplay=&display_title();
       my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit',
@@ -1352,32 +1554,43 @@ FULLPAGE
 					 'dv' => 'Discard Edits and View',
 					 'un' => 'undo',
 					 'ed' => 'Edit');
-      my $buttons=(<<BUTTONS);
-$cleanbut
-<input type="submit" name="discardview" accesskey="d"  value="$lt{'dv'}" />
-<input type="submit" name="Undo" accesskey="u"  value="$lt{'un'}" /><hr>
-<input type="submit" name="savethisfile" accesskey="s"  value="$lt{'st'}" />
-<input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" />
-BUTTONS
-      $buttons.=&Apache::lonhtmlcommon::spelllink('xmledit','filecont');
+      my $spelllink .=&Apache::lonhtmlcommon::spelllink('xmledit','filecont');
+      my $textarea_events = &Apache::edit::element_change_detection();
+      my $form_events     = &Apache::edit::form_change_detection();
+      my $htmlerror=&verify_html($filecontents);
+      if ($htmlerror) {
+         $htmlerror='<span class="LC_error">'.$htmlerror.'</span>';
+      }
       my $editfooter=(<<ENDFOOTER);
 $initialize
-<hr />
 <a name="editsection" />
-<form method="post" name="xmledit">
-$xml_help
-<input type="hidden" name="editmode" value="$lt{'ed'}" />
-$buttons<br />
-<textarea style="width:100%" cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea>
-<br />$buttons
-<br />
+<form $form_events method="post" name="xmledit">
+  <div class="LC_edit_problem_editxml_header">
+    <table class="LC_edit_problem_header_title"><tr><td>
+        $filename
+      </td><td align="right">
+        $xml_help
+      </td></tr>
+    </table>
+    <div class="LC_edit_problem_discards">
+      <input type="submit" name="discardview" accesskey="d" value="$lt{'dv'}" />
+      <input type="submit" name="Undo" accesskey="u" value="$lt{'un'}" />
+      $spelllink $htmlerror
+    </div>
+    <div class="LC_edit_problem_saves">
+      <input type="submit" name="savethisfile" accesskey="s" value="$lt{'st'}" />
+      <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" />
+    </div>
+  </div>
+  <textarea $textarea_events style="width:100%" cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea>
+  <div id="LC_aftertextarea">
+    <br />
+    $titledisplay
+  </div>
 </form>
-$titledisplay
 </body>
 ENDFOOTER
-#      $result=~s/(\<body[^\>]*\>)/$1$editheader/is;
-      $result=~s/(\<\/body\>)/$editfooter/is;
-      return $result;
+      return ($editfooter,$add_to_onload,$add_to_onresize);;
 }
 
 sub get_target {
@@ -1439,6 +1652,9 @@ sub handler {
 	if ($env{'form.savethisfile'} || $env{'form.viewmode'} || $env{'form.Undo'}) {
 	    my $html_file=&Apache::lonnet::getfile($file);
 	    my $error = &Apache::lonhomework::handle_save_or_undo($request, \$html_file, \$env{'form.filecont'});
+            if ($env{'form.savethisfile'}) {
+                $env{'form.editmode'}='Edit'; #force edit mode
+            }
 	}
     }
     my %mystyle;
@@ -1473,38 +1689,63 @@ ENDNOTFOUND
 						    ['editmode']);
 	}
 	if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) {
+	    &Apache::structuretags::reset_problem_globals();
 	    $result = &Apache::lonxml::xmlparse($request,$target,$filecontents,
 						'',%mystyle);
-	    undef($Apache::lonhomework::parsing_a_task);
+	    # .html files may contain <problem> or <Task> need to clean
+	    # up if it did
+	    &Apache::structuretags::reset_problem_globals();
+	    &Apache::lonhomework::finished_parsing();
 	    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
 						    ['rawmode']);
 	    if ($env{'form.rawmode'}) { $result = $filecontents; }
+	    if ($filetype eq 'sty') {
+		my $controls =
+		    ($env{'request.state'} eq 'construct') ? &Apache::londefdef::edit_controls()
+		                                           : '';
+		my %options = ('bgcolor' => '#FFFFFF');
+		$result = 
+		    &Apache::loncommon::start_page(undef,undef,\%options).
+		    $controls.
+		    $result.
+		    &Apache::loncommon::end_page();
+	    }
 	}
     }
-    
+
 #
 # Edit action? Insert editing commands
 #
     unless ($env{'request.state'} eq 'published') {
 	if ($env{'form.editmode'} && (!($env{'form.viewmode'})) && (!($env{'form.discardview'})))
-	    {
+	{
 	    my $displayfile=$request->uri;
 	    $displayfile=~s/^\/[^\/]*//;
-	    my %options = ();
+
+	    my ($edit_info, $add_to_onload, $add_to_onresize)=
+		&inserteditinfo($filecontents,$filetype,$displayfile);
+
+	    my %options = 
+		('add_entries' =>
+                   {'onresize' => $add_to_onresize,
+		    'onload'   => $add_to_onload,   });
+
 	    if ($env{'environment.remote'} ne 'off') {
 		$options{'bgcolor'}   = '#FFFFFF';
+		$options{'only_body'} = 1;
 	    }
-	    my $start_page = &Apache::loncommon::start_page(undef,undef,
+	    my $js =
+		&Apache::edit::js_change_detection().
+		&Apache::loncommon::resize_textarea_js();
+	    my $start_page = &Apache::loncommon::start_page(undef,$js,
 							    \%options);
 	    $result=$start_page.
-		&Apache::lonxml::message_location().'<h3>'.
-		$displayfile.
-		'</h3>'.&Apache::loncommon::end_page();
-	    $result=&inserteditinfo($result,$filecontents,$filetype);
+		&Apache::lonxml::message_location().
+		$edit_info.
+		&Apache::loncommon::end_page();
 	}
     }
     if ($filetype eq 'html') { &writeallows($request->uri); }
-	
     
     &Apache::lonxml::add_messages(\$result);
     $request->print($result);
@@ -1553,12 +1794,28 @@ sub show_error_warn_msg {
 }
 
 sub error {
+    my @errors = @_;
+
     $errorcount++;
+
+    if (defined($Apache::inputtags::part)) {
+	if ( @Apache::inputtags::response ) {
+	    push(@errors,
+		 &mt("This error occurred while processing response [_1] in part [_2]",
+		     $Apache::inputtags::response[-1],
+		     $Apache::inputtags::part));
+	} else {
+	    push(@errors,
+		 &mt("This error occurred while processing part [_1]",
+		     $Apache::inputtags::part));
+	}
+    }
+
     if ( &show_error_warn_msg() ) {
 	# If printing in construction space, put the error inside <pre></pre>
 	push(@Apache::lonxml::error_messages,
 	     $Apache::lonxml::warnings_error_header.
-	     "<b>ERROR:</b>".join("<br />\n",@_)."<br />\n");
+	     "<b>ERROR:</b>".join("<br />\n",@errors)."<br />\n");
 	$Apache::lonxml::warnings_error_header='';
     } else {
 	my $errormsg;
@@ -1568,14 +1825,17 @@ sub error {
 	    $errormsg=&mt("An error occured while processing this resource. The author has been notified.");
 	}
 	my $host=$Apache::lonnet::perlvar{'lonHostID'};
-	my $msg = join('<br />',(@_,"The error occurred on host <tt>$host</tt>"));
+	push(@errors, "The error occurred on host <tt>$host</tt>");
+
+	my $msg = join('<br />', @errors);
+
 	#notify author
 	&Apache::lonmsg::author_res_msg($env{'request.filename'},$msg);
 	#notify course
 	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;
@@ -1700,50 +1960,11 @@ sub get_param_var {
   }
 }
 
-sub register_insert_tab {
-  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{"$tag.description"} = $descrip;
-      $insertlist{"$tag.color"} = $color;
-      $insertlist{"$tag.function"} = $function;
-      if (!defined($show)) { $show='yes'; }
-      $insertlist{"$tag.show"}= $show;
-      $insertlist{"$tag.helpfile"} = $helpfile;
-      $insertlist{"$tag.helpdesc"} = $helpdesc;
-      $insertlist{"$tag.num"}=$tagnum;
-      $tagnum++;
-    }
-  }
-  $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"} },$insertlist{"$j.tag"});
-	}
-      }
-    }
-    $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') {
@@ -1752,6 +1973,7 @@ sub register_insert_xml {
 		$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') {
@@ -1765,11 +1987,7 @@ sub register_insert_xml {
 	    } elsif ($token->[1] eq 'help') {
 		$in_help=1;
 	    } elsif ($token->[1] eq 'allow') {
-		my $allow = $parser->get_text();
-		foreach my $element (split(',',$allow)) {
-		    $element =~ s/(^\s*|\s*$ )//gx;
-		    push(@{ $insertlist{$tag.'.which'} },$element);
-		}
+		$key = $tag.'.allow';
 	    }
 	    if (defined($key)) {
 		$insertlist{$key} = $parser->get_text();
@@ -1784,12 +2002,22 @@ sub register_insert_xml {
 	    }
 	}
     }
+    
+    # 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);
+	    }
+	}
+    }
 }
 
 sub register_insert {
-#    &register_insert_tab(@_);
-#    &dump_insertlist('1');
-#    undef(%insertlist);
     return &register_insert_xml(@_);
 #    &dump_insertlist('2');
 }