--- loncom/xml/lonxml.pm	2007/05/14 08:42:13	1.445
+++ loncom/xml/lonxml.pm	2007/09/11 20:36:18	1.458
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.445 2007/05/14 08:42:13 albertel Exp $
+# $Id: lonxml.pm,v 1.458 2007/09/11 20:36:18 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -125,6 +125,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='';
 
@@ -316,13 +319,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 = ();
@@ -357,6 +361,11 @@ sub xmlparse {
 
  &clean_safespace($safeeval);
 
+ if (@script_var_displays) {
+     $finaloutput .= join('',@script_var_displays);
+     undef(@script_var_displays);
+ }
+
  if ($env{'form.return_only_error_and_warning_counts'}) {
      return "$errorcount:$warningcount";
  }
@@ -599,9 +608,9 @@ sub callsub {
 	      }
 	  }
 	  if ($token->[0] eq 'S') {
-	    $currentstring.=&Apache::edit::handle_insert();
+	      $currentstring.=&Apache::edit::handle_insert();
 	  } elsif ($token->[0] eq 'E') {
-            $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
+	      $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
 	  }
       }
     }
@@ -620,6 +629,7 @@ sub setup_globals {
   &init_counter();
   @Apache::lonxml::pwd=();
   @Apache::lonxml::extlinks=();
+  @script_var_displays=();
   @Apache::lonxml::ssi_info=();
   $Apache::lonxml::post_evaluate=1;
   $Apache::lonxml::warnings_error_header='';
@@ -790,6 +800,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');
@@ -958,8 +969,8 @@ sub decreasedepth {
 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;
@@ -997,6 +1008,24 @@ sub get_all_text_unbalanced {
     return $result
 }
 
+=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)
+
+=cut
+
 sub increment_counter {
     my ($increment) = @_;
     if (defined($increment) && $increment gt 0) {
@@ -1007,6 +1036,14 @@ sub increment_counter {
     $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;
@@ -1228,6 +1265,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
 #
@@ -1308,17 +1351,20 @@ SIMPLECONTENT
 
 
 sub inserteditinfo {
-      my ($result,$filecontents,$filetype)=@_;
+      my ($filecontents,$filetype)=@_;
       $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);
+      my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons();
+      $initialize=&Apache::lonhtmlcommon::spellheader();
+      if ($filetype eq 'html' 
+	  && (!&Apache::lonhtmlcommon::htmlareablocked() &&
+	      &Apache::lonhtmlcommon::htmlareabrowser())) {
+	  $textarea_id .= '_htmlarea';
+	  $initialize.=(<<FULLPAGE);
 <script type="text/javascript">
 $addbuttons
 
@@ -1328,21 +1374,34 @@ $addbuttons
 	var editor=new HTMLArea("filecont",config);
 	editor.registerPlugin(FullPage);
 	editor.generate();
+	setTimeout(
+		   function () {
+		       HTMLArea._addEvents(editor._doc,
+					   ["keypress","mousedown"], unClean);
+		       editor._iframe.id = '$textarea_id';
+		       resize_textarea('$textarea_id','LC_aftertextarea');
+		   },300);
     }
 </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();
@@ -1354,29 +1413,31 @@ FULLPAGE
       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="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 $textarea_events = &Apache::edit::element_change_detection();
+      my $form_events     = &Apache::edit::form_change_detection();
       my $editfooter=(<<ENDFOOTER);
 $initialize
 <hr />
 <a name="editsection" />
-<form method="post" name="xmledit">
+<form $form_events 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>
+<textarea $textarea_events style="width:100%" cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea>
+<div id="LC_aftertextarea">
 <br />$buttons
 <br />
-</form>
 $titledisplay
+</div>
+</form>
 </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 {
@@ -1472,38 +1533,64 @@ 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 ($edit_info, $add_to_onload, $add_to_onresize)=
+		&inserteditinfo($filecontents,$filetype);
+
 	    my $displayfile=$request->uri;
 	    $displayfile=~s/^\/[^\/]*//;
-	    my %options = ();
+	    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);
+		'</h3>'.
+		$edit_info.
+		&Apache::loncommon::end_page();
 	}
     }
     if ($filetype eq 'html') { &writeallows($request->uri); }
-	
     
     &Apache::lonxml::add_messages(\$result);
     $request->print($result);
@@ -1552,12 +1639,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;
@@ -1567,7 +1670,10 @@ 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
@@ -1748,8 +1854,8 @@ sub register_insert_xml {
 	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') {
+	    if (!exists($insertlist{"$element.show"})
+                || $insertlist{"$element.show"} ne 'no') {
 		push(@{ $insertlist{$tag.'.which'} },$element);
 	    }
 	}