--- loncom/xml/lonxml.pm	2007/09/12 10:58:18	1.460
+++ loncom/xml/lonxml.pm	2007/12/05 14:52:15	1.470
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.460 2007/09/12 10:58:18 foxr Exp $
+# $Id: lonxml.pm,v 1.470 2007/12/05 14:52:15 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -92,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
@@ -135,12 +137,15 @@ $Apache::lonxml::request='';
 $Apache::lonxml::counter=1;
 $Apache::lonxml::counter_changed=0;
 
-# A count of bubble lines needed for a set.. and a check on 
-# whether or not it is ever used too:
+# 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::bubble_line_counter         = 1;
-$Apache::lonxml::bubble_line_counter_changed = 0;
 
+%Apache::lonxml::counters_per_part = ();
 
 #internal check on whether to look at style defs
 $Apache::lonxml::usestyle=1;
@@ -365,9 +370,6 @@ sub xmlparse {
  }
  &do_registered_ssi();
  if ($Apache::lonxml::counter_changed) { &store_counter() }
- if ($Apache::lonxml::bubble_line_counter_changed) {
-     &store_bubble_counter();
- }
 
  &clean_safespace($safeeval);
 
@@ -375,7 +377,7 @@ sub xmlparse {
      $finaloutput .= join('',@script_var_displays);
      undef(@script_var_displays);
  }
-
+ &init_state();
  if ($env{'form.return_only_error_and_warning_counts'}) {
      return "$errorcount:$warningcount";
  }
@@ -629,6 +631,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;
@@ -637,7 +657,9 @@ sub setup_globals {
   $Apache::lonxml::default_homework_loaded=0;
   $Apache::lonxml::usestyle=1;
   &init_counter();
-  &init_bubble_counter();
+  &clear_bubble_lines_for_part();
+  &init_state();
+  &set_state('target',$target);
   @Apache::lonxml::pwd=();
   @Apache::lonxml::extlinks=();
   @script_var_displays=();
@@ -1020,116 +1042,14 @@ 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.bubble_line_counter', and is modifed and handled by 
-the following routines.
-
-The value of it is stored in $Apache:lonxml::bubble_line_counter when 
-live and stored back to env after done.
-
-=item &increment_bubble_counter($increment)
-
-Increments the bubble line counter by the optional value
-$increment (defaults to 1).
-
- 'bad increments' are also treated as an increment of 1.
-('bad' means <=0).
-
-=cut
-
-sub increment_bubble_counter {
-    my ($increment) = @_;
-    if (!defined($increment) || $increment le 0) {
-	$increment = 1;
-    }
-    $Apache::lonxml::bubble_line_counter         += $increment;
-    $Apache::lonxml::bubble_line_counter_changed  = 1;
-}
-=pod
-    
-=item &init_bubble_counter
-
-Initialize the internal counter to the env. variable
-or 1 if we are inconstruction space, or if the env var
-is not defined.
-
-=cut
-
-sub init_bubble_counter {
-    if ($env{'request.state'} eq 'construct') {
-	$Apache::lonxml::bubble_line_counter         = 1;
-	$Apache::lonxml::bubble_line_counter_changed = 1;
-    } elsif (defined($env{'form.bubble_line_counter'})) {
-	$Apache::lonxml::bubble_line_counter         =
-	                                   $env{'form.bubble_line_counter'};
-	$Aapche::lonxml::bubble_line_counter_changed = 0;
-    } else {
-	$Apache::lonxml::bubble_line_counter         = 1;
-	$Apache::lonxml::bubble_line_counter_changed = 1;
-    }
 
 }
 
-=pod
-
-=item store_bubble_counter;
-
-   Store the bubble line counter in its env var.  The changed flag
-    is reset indicating the env is up to date with respect to the
-    local variable.
-=cut
-
-sub store_bubble_counter {
-    &Apache::lonnet::appenv(('form.bubble.counter' => 
-			            $Apache::lonxml::bubble_line_counter));
-    $Apache::lonnet::bubble_line_counter_changed = 0;
-
-    return '';
-}
-
-=pod
-  
-The next set of subs allow a single level of save/restore for the
-bubble_line_counter.
-
-=cut
-
-{
-    my $bubble_counter_state;
-
-    sub clear_bubble_counter {
-	undef($bubble_counter_state);
-	&Apache::lonnet::delenv('form.bubble_line_counter');
-	&Apache::lonxml::init_bubble_counter();
-	&Apache::lonxml::store_bubble_counter();
-    }
-
-    sub remember_bubble_counter {
-	&Apache::lonnet::transfer_profile_to_env(undef,undef, 1);
-	$bubble_counter_state = $env{'form.bubble_line_counter'};
-    }
-
-    sub restore_bubble_counter {
-	if (defined($bubble_counter_state)) {
-	    &Apache::lonnet::appenv(('form.bubble_line_counter' => 
-				                 $bubble_counter_state));
-	}
-    }
-
-    sub get_bubble_counter {
-	if ($Apache::lonxml::bubble_line_counter_changed) {
-	    &store_bubble_counter();
-	}
-	&Apache::lonnet::transfer_profile_to_env(undef, undef, 1);
-	return $env{'form.bubble_line_counter'};
-    }
-}
+#########################################################################
+#                                                                       #
+#           bubble line counter management                              #
+#                                                                       #
+#########################################################################
 
 =pod
 
@@ -1146,22 +1066,37 @@ Increments the internal counter environm
 
 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;
+=item &init_counter($increment);
 
 Initialize the internal counter environment variable
 
@@ -1205,15 +1140,80 @@ sub store_counter {
 	    &Apache::lonnet::appenv(('form.counter' => $state));
 	}
     }
-
     sub get_problem_counter {
 	if ($Apache::lonxml::counter_changed) { &store_counter() }
 	&Apache::lonnet::transfer_profile_to_env(undef,undef,1);
 	return $env{'form.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;
@@ -1476,43 +1476,44 @@ SIMPLECONTENT
 
 
 sub inserteditinfo {
-      my ($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='';
       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';
+	  $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();
-	setTimeout(
-		   function () {
-		       HTMLArea._addEvents(editor._doc,
-					   ["keypress","mousedown"], unClean);
-		       editor._iframe.id = '$textarea_id';
-		       resize_textarea('$textarea_id','LC_aftertextarea');
-		   },300);
+        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);
 <script type="text/javascript">
-$addbuttons
     function initDocument() {
 	resize_textarea('$textarea_id','LC_aftertextarea');
     }
@@ -1527,38 +1528,41 @@ FULLPAGE
 	  $xml_help=&Apache::loncommon::helpLatexCheatsheet();
       }
 
-      my $cleanbut = '';
-
       my $titledisplay=&display_title();
       my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit',
 					 'vi' => 'Save and View',
 					 '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 $editfooter=(<<ENDFOOTER);
 $initialize
-<hr />
 <a name="editsection" />
 <form $form_events method="post" name="xmledit">
-$xml_help
-<input type="hidden" name="editmode" value="$lt{'ed'}" />
-$buttons<br />
-<textarea $textarea_events style="width:100%" cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea>
-<div id="LC_aftertextarea">
-<br />$buttons
-<br />
-$titledisplay
-</div>
+  <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
+    </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>
 </body>
 ENDFOOTER
@@ -1688,11 +1692,12 @@ ENDNOTFOUND
     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 ($edit_info, $add_to_onload, $add_to_onresize)=
+		&inserteditinfo($filecontents,$filetype,$displayfile);
+
 	    my %options = 
 		('add_entries' =>
                    {'onresize' => $add_to_onresize,
@@ -1708,9 +1713,7 @@ ENDNOTFOUND
 	    my $start_page = &Apache::loncommon::start_page(undef,$js,
 							    \%options);
 	    $result=$start_page.
-		&Apache::lonxml::message_location().'<h3>'.
-		$displayfile.
-		'</h3>'.
+		&Apache::lonxml::message_location().
 		$edit_info.
 		&Apache::loncommon::end_page();
 	}