--- loncom/xml/lonplot.pm	2002/03/22 16:04:09	1.61
+++ loncom/xml/lonplot.pm	2003/05/16 14:50:13	1.83
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Dynamic plot
 #
-# $Id: lonplot.pm,v 1.61 2002/03/22 16:04:09 matthew Exp $
+# $Id: lonplot.pm,v 1.83 2003/05/16 14:50:13 sakharuk Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -97,12 +97,14 @@ my %linestyles =
 my $int_test       = sub {$_[0]=~s/\s+//g;$_[0]=~/^\d+$/};
 my $real_test      = 
     sub {$_[0]=~s/\s+//g;$_[0]=~/^[+-]?\d*\.?\d*([eE][+-]\d+)?$/};
-my $color_test     = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-f]{6}$/};
+my $pos_real_test  =
+    sub {$_[0]=~s/\s+//g;$_[0]=~/^[+]?\d*\.?\d*([eE][+-]\d+)?$/};
+my $color_test     = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-fA-F]{6}$/};
 my $onoff_test     = sub {$_[0]=~/^(on|off)$/};
 my $key_pos_test   = sub {$_[0]=~/^(top|bottom|right|left|outside|below| )+$/};
 my $sml_test       = sub {$_[0]=~/^(small|medium|large)$/};
 my $linestyle_test = sub {exists($linestyles{$_[0]})};
-my $words_test     = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w\(\)]+ ?)+$/};
+my $words_test     = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w~!\@\#\$\%^&\*\(\)-=_\+\[\]\{\}:\;\'<>,\.\/\?\\]+ ?)+$/};
 
 ###################################################################
 ##                                                               ##
@@ -110,7 +112,8 @@ my $words_test     = sub {$_[0]=~s/\s+/
 ##                                                               ##
 ###################################################################
 my @gnuplot_edit_order = 
-    qw/bgcolor fgcolor height width font transparent grid border align/;
+    qw/alttag bgcolor fgcolor height width font transparent grid samples 
+    border align texwidth/;
 
 my $gnuplot_help_text = <<"ENDPLOTHELP";
 <p>
@@ -146,15 +149,22 @@ ENDPLOTHELP
 
 my %gnuplot_defaults = 
     (
+     alttag       => {
+	 default     => 'dynamically generated plot',
+	 test        => $words_test,
+	 description => 'brief description of the plot',
+      	 edit_type   => 'entry',
+	 size        => '40'
+	 },
      height       => {
-	 default     => 200,
+	 default     => 300,
 	 test        => $int_test,
 	 description => 'height of image (pixels)',
       	 edit_type   => 'entry',
 	 size        => '10'
 	 },
      width        => {
-	 default     => 200,
+	 default     => 400,
 	 test        => $int_test,
 	 description => 'width of image (pixels)',
 	 edit_type   => 'entry',
@@ -181,7 +191,7 @@ my %gnuplot_defaults =
 	 edit_type   => 'onoff'
 	 },
      grid         => {
-	 default     => 'off',
+	 default     => 'on',
 	 test        => $onoff_test, 
 	 description => 'Display grid',
 	 edit_type   => 'onoff'
@@ -199,13 +209,27 @@ my %gnuplot_defaults =
 	 edit_type   => 'choice',
 	 choices     => ['small','medium','large']
 	 },
+     samples         => {
+	 default     => '100',
+	 test        => $int_test,
+	 description => 'Number of samples for non-data plots',
+	 edit_type   => 'choice',
+	 choices     => ['100','200','500','1000','2000','5000']
+	 },
      align        => {
-	 default     => 'left',
+	 default     => 'center',
 	 test        => sub {$_[0]=~/^(left|right|center)$/},
 	 description => 'alignment for image in html',
 	 edit_type   => 'choice',
 	 choices     => ['left','right','center']
-	 } 
+	 },
+     texwidth     => {
+         default     => '93',
+         test        => $int_test,
+         description => 'Width of plot when printed (mm)',
+         edit_type   => 'entry',
+         size        => '5'
+         },
      );
 
 my %key_defaults = 
@@ -297,12 +321,13 @@ my %tic_defaults =
 	 },
      );
 
+my @axis_edit_order = ('color','xmin','xmax','ymin','ymax');
 my %axis_defaults = 
     (
      color   => {
 	 default => 'x000000', 
 	 test => $color_test,
-	 description => 'color of axes (x000000)',
+	 description => 'color of grid lines (x000000)',
 	 edit_type   => 'entry',
 	 size        => '10'
 	 },
@@ -367,7 +392,7 @@ is an error in your <b>function</b> tag.
 </dl>
 ENDCURVEHELP
 
-my @curve_edit_order = ('color','name','linestyle','pointsize');
+my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize');
 
 my %curve_defaults = 
     (
@@ -402,10 +427,17 @@ my %curve_defaults =
 #         },
      pointsize => {
          default     => 1,
-         test        => $int_test,
+         test        => $pos_real_test,
          description => 'point size (may not apply to all line styles)',
+         edit_type   => 'entry',
+         size        => '5'
+         },
+     pointtype => {
+         default     => 1,
+         test        => $int_test,
+         description => 'point type (may not apply to all line styles)',
          edit_type   => 'choice',
-         choices     => [0,1,2,3,4,5,6,7,8,9,10]
+         choices     => [0,1,2,3,4,5,6]
          }
      );
 
@@ -467,23 +499,23 @@ sub end_gnuplot {
 	## Determine filename
 	my $tmpdir = '/home/httpd/perl/tmp/';
 	my $filename = $ENV{'user.name'}.'_'.$ENV{'user.domain'}.
-	    '_'.time.'_'.$$.$randnumber.'_plot.data';
+	    '_'.time.'_'.$$.$randnumber.'_plot';
 	## Write the plot description to the file
 	&write_gnuplot_file($tmpdir,$filename,$target);
 	$filename = &Apache::lonnet::escape($filename);
 	## return image tag for the plot
 	if ($target eq 'web') {
 	    $result .= <<"ENDIMAGE";
-<img src    = "/cgi-bin/plot.gif?file=$filename&output=gif" 
-     width  = "$plot{'width'}" 
+<img src    = "/cgi-bin/plot.gif?file=$filename.data&output=gif" 
+     width  = "$plot{'width'}"
      height = "$plot{'height'}"
      align  = "$plot{'align'}"
-     alt    = "image should be /cgi-bin/plot.gif?$filename" />
+     alt    = "$plot{'alttag'}" />
 ENDIMAGE
         } elsif ($target eq 'tex') {
-	    &Apache::lonnet::ssi('cgi-bin/plot.gif?file=$filename'.
-				 '&output=eps');
-	    $result = "$filename.eps";
+	    &Apache::lonnet::ssi("/cgi-bin/plot.gif?file=$filename.data&output=eps");
+
+	    $result = '\graphicspath{{/home/httpd/perl/tmp/}}\includegraphics[width=93 mm]{'.&Apache::lonnet::unescape($filename).'.eps}';
 	}
     } elsif ($target eq 'edit') {
 	$result.=&Apache::edit::tag_end($target,$token);
@@ -590,7 +622,7 @@ sub start_title {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';
     if ($target eq 'web' || $target eq 'tex') {
-	$title = &Apache::lonxml::get_all_text("/title",$$parser[-1]);
+	$title = &Apache::lonxml::get_all_text("/title",$parser);
 	$title=&Apache::run::evaluate($title,$safeeval,$$parstack[-1]);
 	$title =~ s/\n/ /g;
 	if (length($title) > $max_str_len) {
@@ -598,10 +630,10 @@ sub start_title {
 	}
     } elsif ($target eq 'edit') {
 	$result.=&Apache::edit::tag_start($target,$token,'Plot Title');
-	my $text=&Apache::lonxml::get_all_text("/title",$$parser[-1]);
+	my $text=&Apache::lonxml::get_all_text("/title",$parser);
 	$result.=&Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	my $text=$$parser[-1]->get_text("/title");
 	$result.=&Apache::edit::rebuild_tag($token);
@@ -624,7 +656,7 @@ sub start_xlabel {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';
     if ($target eq 'web' || $target eq 'tex') {
-	$xlabel = &Apache::lonxml::get_all_text("/xlabel",$$parser[-1]);
+	$xlabel = &Apache::lonxml::get_all_text("/xlabel",$parser);
 	$xlabel=&Apache::run::evaluate($xlabel,$safeeval,$$parstack[-1]);
 	$xlabel =~ s/\n/ /g;
 	if (length($xlabel) > $max_str_len) {
@@ -632,10 +664,10 @@ sub start_xlabel {
 	}
     } elsif ($target eq 'edit') {
 	$result.=&Apache::edit::tag_start($target,$token,'Plot Xlabel');
-	my $text=&Apache::lonxml::get_all_text("/xlabel",$$parser[-1]);
+	my $text=&Apache::lonxml::get_all_text("/xlabel",$parser);
 	$result.=&Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	my $text=$$parser[-1]->get_text("/xlabel");
 	$result.=&Apache::edit::rebuild_tag($token);	
@@ -659,7 +691,7 @@ sub start_ylabel {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';
     if ($target eq 'web' || $target eq 'tex') {
-	$ylabel = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]);
+	$ylabel = &Apache::lonxml::get_all_text("/ylabel",$parser);
 	$ylabel = &Apache::run::evaluate($ylabel,$safeeval,$$parstack[-1]);
 	$ylabel =~ s/\n/ /g;
 	if (length($ylabel) > $max_str_len) {
@@ -667,10 +699,10 @@ sub start_ylabel {
 	}
     } elsif ($target eq 'edit') {
 	$result .= &Apache::edit::tag_start($target,$token,'Plot Ylabel');
-	my $text = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]);
+	my $text = &Apache::lonxml::get_all_text("/ylabel",$parser);
 	$result .= &Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	my $text=$$parser[-1]->get_text("/ylabel");
 	$result.=&Apache::edit::rebuild_tag($token);
@@ -697,7 +729,7 @@ sub start_label {
 	my %label;
 	&get_attributes(\%label,\%label_defaults,$parstack,$safeeval,
 		    $tagstack->[-1]);
-	my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]);
+	my $text = &Apache::lonxml::get_all_text("/label",$parser);
 	$text = &Apache::run::evaluate($text,$safeeval,$$parstack[-1]);
 	$text =~ s/\n/ /g;
 	$text = substr($text,0,$max_str_len) if (length($text) > $max_str_len);
@@ -706,10 +738,10 @@ sub start_label {
     } elsif ($target eq 'edit') {
 	$result .= &Apache::edit::tag_start($target,$token,'Plot Label');
 	$result .= &edit_attributes($target,$token,\%label_defaults);
-	my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]);
+	my $text = &Apache::lonxml::get_all_text("/label",$parser);
 	$result .= &Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	&Apache::edit::get_new_args
 	    ($token,$parstack,$safeeval,keys(%label_defaults));
@@ -778,15 +810,15 @@ sub start_function {
 	    &Apache::lonxml::warning('Use of <function> precludes use of <data>.  The <data> will be omitted in favor of the <function> declaration.');
 	    delete $curves[-1]->{'data'} ;
 	}
-        my $function = &Apache::lonxml::get_all_text("/function",$$parser[-1]);
+        my $function = &Apache::lonxml::get_all_text("/function",$parser);
 	$function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]);
 	$curves[-1]->{'function'} = $function; 
     } elsif ($target eq 'edit') {
 	$result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function');
-	my $text = &Apache::lonxml::get_all_text("/function",$$parser[-1]);
+	my $text = &Apache::lonxml::get_all_text("/function",$parser);
 	$result .= &Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	$result.=&Apache::edit::rebuild_tag($token);
 	my $text=$$parser[-1]->get_text("/function");
@@ -816,7 +848,7 @@ sub start_data {
             'the <data> declaration.');
 	    delete($curves[-1]->{'function'});
 	}
-	my $datatext = &Apache::lonxml::get_all_text("/data",$$parser[-1]);
+	my $datatext = &Apache::lonxml::get_all_text("/data",$parser);
 	$datatext=&Apache::run::evaluate($datatext,$safeeval,$$parstack[-1]);
 	# Deal with cases where we're given an array...
 	if ($datatext =~ /^\@/) {
@@ -859,10 +891,10 @@ sub start_data {
 	push  @{$curves[-1]->{'data'}},\@data;
     } elsif ($target eq 'edit') {
 	$result .= &Apache::edit::tag_start($target,$token,'Comma or space deliminated curve data');
-	my $text = &Apache::lonxml::get_all_text("/data",$$parser[-1]);
+	my $text = &Apache::lonxml::get_all_text("/data",$parser);
 	$result .= &Apache::edit::end_row().
 	    &Apache::edit::start_spanning_row().
-	    &Apache::edit::textfield('',$text,'',60);
+	    &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {
 	$result.=&Apache::edit::rebuild_tag($token);
 	my $text=$$parser[-1]->get_text("/data");
@@ -890,7 +922,8 @@ sub start_axis {
 			$tagstack->[-1]);
     } elsif ($target eq 'edit') {
 	$result .= &Apache::edit::tag_start($target,$token,'Plot Axes');
-	$result .= &edit_attributes($target,$token,\%axis_defaults);
+	$result .= &edit_attributes($target,$token,\%axis_defaults,
+				    \@axis_edit_order);
     } elsif ($target eq 'modified') {
 	my $constructtag=&Apache::edit::get_new_args
 	    ($token,$parstack,$safeeval,keys(%axis_defaults));
@@ -973,15 +1006,19 @@ sub write_gnuplot_file {
 	# set output
 	$gnuplot_input .= "set output\n";
     } elsif ($target eq 'tex') {
-	$gnuplot_input .= "set term postscript eps monochrome\n";
-	$gnuplot_input .= "set output \"$filename.eps\"\n";
+	$gnuplot_input .= "set term postscript eps monochrome solid\n";
+	$gnuplot_input .= "set output \"/home/httpd/perl/tmp/".
+	    &Apache::lonnet::unescape($filename).".eps\"\n";
     }
     # grid
     $gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on');
     # border
     $gnuplot_input .= ($plot{'border'} eq 'on'?
 		       'set border'.$/           :
-		       'set noborder'.$/         );    # title, xlabel, ylabel
+		       'set noborder'.$/         );
+    # sampling rate for non-data curves
+    $gnuplot_input .= "set samples $plot{'samples'}\n";
+    # title, xlabel, ylabel
     # titles
     $gnuplot_input .= "set title  \"$title\"\n"  if (defined($title)) ;
     $gnuplot_input .= "set xlabel \"$xlabel\"\n" if (defined($xlabel));
@@ -1010,7 +1047,7 @@ sub write_gnuplot_file {
     if (%key) {
 	$gnuplot_input .= 'set key '.$key{'pos'}.' ';
 	if ($key{'title'} ne '') {
-	    $gnuplot_input .= 'title " '.$key{'title'}.'" ';
+	    $gnuplot_input .= 'title "'.$key{'title'}.'" ';
 	} 
 	$gnuplot_input .= ($key{'box'} eq 'on' ? 'box ' : 'nobox ').$/;
     } else {
@@ -1022,6 +1059,10 @@ sub write_gnuplot_file {
 	$gnuplot_input .= 'set label "'.$label->{'text'}.'" at '.
 	    $label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}.$/ ;
     }
+    if ($target eq 'tex') {
+        $gnuplot_input .="set size 1,".$plot{'height'}/$plot{'width'}*1.38;
+        $gnuplot_input .="\n";
+        }
     # curves
     $gnuplot_input .= 'plot ';
     for (my $i = 0;$i<=$#curves;$i++) {
@@ -1031,24 +1072,22 @@ sub write_gnuplot_file {
 	    $gnuplot_input.= 
 		$curve->{'function'}.' title "'.
 		$curve->{'name'}.'" with '.
-		$curve->{'linestyle'};
-#
-# gnuplot's term=gif driver does not handle linewidths :(
-# . ' linewidth '. $curve->{'linewidth'};
-#
+                $curve->{'linestyle'};
+            $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex');
             if (($curve->{'linestyle'} eq 'points')      ||
                 ($curve->{'linestyle'} eq 'linespoints') ||
                 ($curve->{'linestyle'} eq 'errorbars')   ||
                 ($curve->{'linestyle'} eq 'xerrorbars')  ||
                 ($curve->{'linestyle'} eq 'yerrorbars')  ||
                 ($curve->{'linestyle'} eq 'xyerrorbars')) {
+                $gnuplot_input.=' pointtype '.$curve->{'pointtype'};
                 $gnuplot_input.=' pointsize '.$curve->{'pointsize'};
             }
 	} elsif (exists($curve->{'data'})) {
 	    # Store data values in $datatext
 	    my $datatext = '';
 	    #   get new filename
-	    my $datafilename = "$tmpdir/$filename.$i";
+	    my $datafilename = "$tmpdir/$filename.data.$i";
 	    my $fh=Apache::File->new(">$datafilename");
 	    # Compile data
 	    my @Data = @{$curve->{'data'}};
@@ -1067,10 +1106,20 @@ sub write_gnuplot_file {
 	    $gnuplot_input.= '"'.$datafilename.'" title "'.
 		$curve->{'name'}.'" with '.
 		$curve->{'linestyle'};
+            $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex');
+            if (($curve->{'linestyle'} eq 'points')      ||
+                ($curve->{'linestyle'} eq 'linespoints') ||
+                ($curve->{'linestyle'} eq 'errorbars')   ||
+                ($curve->{'linestyle'} eq 'xerrorbars')  ||
+                ($curve->{'linestyle'} eq 'yerrorbars')  ||
+                ($curve->{'linestyle'} eq 'xyerrorbars')) {
+                $gnuplot_input.=' pointtype '.$curve->{'pointtype'};
+                $gnuplot_input.=' pointsize '.$curve->{'pointsize'};
+            }
 	}
     }
     # Write the output to a file.
-    my $fh=Apache::File->new(">$tmpdir$filename");
+    my $fh=Apache::File->new(">$tmpdir$filename.data");
     print $fh $gnuplot_input;
     close($fh);
     # That's all folks.