changeset 7189:e8d953d03f6a

[project @ 2007-11-26 20:42:09 by dbateman]
author dbateman
date Mon, 26 Nov 2007 20:42:11 +0000
parents fdd7cd70dc14
children 9e7377f41b78
files ChangeLog NEWS PROJECTS doc/ChangeLog doc/interpreter/Makefile.in doc/interpreter/image.txi doc/interpreter/plot.txi doc/interpreter/plotimages.m doc/interpreter/sparse.txi liboctave/Array.cc liboctave/ChangeLog liboctave/int16NDArray.cc liboctave/int16NDArray.h liboctave/int32NDArray.cc liboctave/int32NDArray.h liboctave/int64NDArray.cc liboctave/int64NDArray.h liboctave/int8NDArray.cc liboctave/int8NDArray.h liboctave/intNDArray.cc liboctave/intNDArray.h liboctave/mx-op-defs.h liboctave/uint16NDArray.cc liboctave/uint16NDArray.h liboctave/uint32NDArray.cc liboctave/uint32NDArray.h liboctave/uint64NDArray.cc liboctave/uint64NDArray.h liboctave/uint8NDArray.cc liboctave/uint8NDArray.h scripts/ChangeLog scripts/image/Makefile.in scripts/image/gmap40.m scripts/image/image.m scripts/image/imagesc.m scripts/linear-algebra/Makefile.in scripts/linear-algebra/condest.m scripts/linear-algebra/onenormest.m scripts/plot/Makefile.in scripts/plot/__bar__.m scripts/plot/__bars__.m scripts/plot/__contour__.m scripts/plot/__go_draw_axes__.m scripts/plot/__go_draw_figure__.m scripts/plot/__patch__.m scripts/plot/__quiver__.m scripts/plot/__scatter__.m scripts/plot/axis.m scripts/plot/bar.m scripts/plot/barh.m scripts/plot/caxis.m scripts/plot/colorbar.m scripts/plot/contour.m scripts/plot/drawnow.m scripts/plot/hist.m scripts/plot/print.m scripts/plot/quiver.m scripts/plot/quiver3.m scripts/plot/scatter.m scripts/plot/scatter3.m scripts/plot/sphere.m scripts/plot/stem.m scripts/plot/surface.m scripts/plot/surfnorm.m src/ChangeLog src/DLD-FUNCTIONS/minmax.cc src/data.cc src/graphics.cc src/graphics.h.in
diffstat 69 files changed, 3665 insertions(+), 702 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Nov 26 20:31:25 2007 +0000
+++ b/ChangeLog	Mon Nov 26 20:42:11 2007 +0000
@@ -1,3 +1,13 @@
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* PROJECTS: condest now implemented.
+
+	* NEWS: Document the TeX interpreter mode and its limitations with
+	gnuplot 4.0.
+
+	* NEWS: Document the use of "colormap gmap40" to workaround some
+	gnuplot 4.0 colormap issues.
+
 2007-11-14  John W. Eaton  <jwe@octave.org>
 
 	* configure.in: Don't create Makefrag.bsd.
--- a/NEWS	Mon Nov 26 20:31:25 2007 +0000
+++ b/NEWS	Mon Nov 26 20:42:11 2007 +0000
@@ -20,6 +20,12 @@
       and 1 for the R, G and B values. Invalid values are all mapped
       to the same color.
 
+      This also affects patch objects used in the bar, countour, meshc
+      and surfc functions, where the bars and contours will be
+      monochrome. A workaround for this is to type "colormap gmap40"
+      that loads a colormap that in many cases will be adequate for
+      simple bar and contour plots.
+
     + You can control the width of lines using (for example):
 
 	line (x, y, "linewidth", 4, "color", [1, 0, 0.5]);
@@ -34,6 +40,12 @@
       this allows you to plot additional 2-d data on top of a contour
       plot.
 
+    + With the gnuplot "extended" terminals the TeX interpreter is
+    emulated. However, this means that the TeX interpreter is only
+    supported on the postscript terminals with gnuplot 4.0. Under
+    gnuplot 4.2 the terminals aqua, dumb, png, jpeg, gif, pm, windows,
+    wxt, svg and x11 are supported as well.
+
     + The following plot commands are now considered obsolete and will
       be removed from a future version of Octave:
 
--- a/PROJECTS	Mon Nov 26 20:31:25 2007 +0000
+++ b/PROJECTS	Mon Nov 26 20:42:11 2007 +0000
@@ -109,7 +109,6 @@
       - colmmd      Superseded by colamd
       - treelayout
       - cholinc
-      - condest
       - bicg        Can this be taken from octave-forge?
       - bicgstab
       - cgs
--- a/doc/ChangeLog	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/ChangeLog	Mon Nov 26 20:42:11 2007 +0000
@@ -1,3 +1,15 @@
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* interpreter/sparse.txi: Document condest.
+	* interpreter/plot.txi: Document the new text properties and the
+	TeX interpreter mode of text objects.
+	* interpreter/plotimages.m: Add an example for the TeX
+	interpreter.
+	* interpreter/Makefile.in (PLOTIMAGES): Add the TeX example
+
+	* interpreter/plot.txi: Document caxis.
+	* interpreter/image.txi: Document gmap40.
+
 2007-11-12  Joseph P. Skudlarek  <Jskud@Jskud.com>
 
 	* interpreter/gpl.txi: Move index commands after sectioning commands.
--- a/doc/interpreter/Makefile.in	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/interpreter/Makefile.in	Mon Nov 26 20:42:11 2007 +0000
@@ -61,7 +61,7 @@
 GEOMETRYIMAGES_PDF = $(addsuffix .pdf, $(GEOMETRYIMAGES))
 GEOMETRYIMAGES_PNG = $(addsuffix .png, $(GEOMETRYIMAGES))
 
-PLOTIMAGES = plot hist errorbar polar mesh plot3
+PLOTIMAGES = plot hist errorbar polar mesh plot3 extended
 PLOTIMAGES_EPS = $(addsuffix .eps, $(PLOTIMAGES))
 PLOTIMAGES_PDF = $(addsuffix .pdf, $(PLOTIMAGES))
 PLOTIMAGES_PNG = $(addsuffix .png, $(PLOTIMAGES))
--- a/doc/interpreter/image.txi	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/interpreter/image.txi	Mon Nov 26 20:42:11 2007 +0000
@@ -152,6 +152,15 @@
 
 @DOCSTRING(winter)
 
+An additional colormap is @code{gmap40}. This code map contains only
+colors with integer values of the red, green and blue components. This
+workaround a limitation on gnuplot 4.0, that does not allow the color of
+line or patch objects to be set, and so @code{gmap40} is useful for
+gnuplot 4.0 users, and in particular in conjunction with the @var{bar},
+@var{barh} or @var{contour} functions.
+
+@DOCSTRING(gmap40)
+
 @node Plotting on top of Images
 @section Plotting on top of Images
 
--- a/doc/interpreter/plot.txi	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/interpreter/plot.txi	Mon Nov 26 20:42:11 2007 +0000
@@ -189,6 +189,11 @@
 
 @DOCSTRING(axis)
 
+Similarly the axis limits of the colormap can be changed with the caxis
+function.
+
+@DOCSTRING(caxis)
+
 @node Three-Dimensional Plotting
 @subsection Three-Dimensional Plotting
 
@@ -806,8 +811,190 @@
 
 @item color
 The color of the text.  @xref{Colors}.
+
+@item fontname
+The font used for the text.
+
+@item fontsize
+The size of the font, in points to use.
+
+@item fontangle
+Flag whether the font is italic or normal. Valid values are 'normal',
+'italic' and 'oblique'.
+
+@item fontweight
+Flag whether the font is bold, etc. Valid values are 'normal', 'bold',
+'demi' or 'light'.
+
+@item interpreter
+Determines how the text is rendered. Valid values are 'none', 'tex' or
+'latex'.
 @end table
 
+All text objects, including titles, labels, legends, and text, include
+the property 'interpreter', this property determines the manner in which
+special control sequences in the text are rendered. If the interpreter
+is set to 'none', then no rendering occurs. At this point the 'latex'
+option is not implemented and so the 'latex' interpreter also does not
+interpret the text.
+
+The 'tex' option implements a subset of @sc{TeX} functionality in the
+rendering of the text. This allows the insertion of special characters
+such as Greek or mathematical symbols within the text. The special
+characters are also inserted with a code starting with the back-slash
+(\) character, as in the table @ref{tab:extended}. 
+
+In addition, the formating of the text can be changed within the string
+with the codes 
+
+@multitable @columnfractions .2 .2 .6 .2
+@item @tab \bf @tab Bold font @tab
+@item @tab \it @tab Italic font @tab
+@item @tab \sl @tab Oblique Font @tab
+@item @tab \rm @tab Normal font @tab
+@end multitable
+
+These are be used in conjunction with the @{ and @} characters to limit
+the change in the font to part of the string. For example
+
+@example
+xlabel ('@{\bf H@} = a @{\bf V@}')
+@end example
+
+where the character 'a' will not appear in a bold font. Note that to
+avoid having Octave interpret the backslash characters in the strings,
+the strings should be in single quotes.
+
+It is also possible to change the fontname and size within the text 
+
+@multitable @columnfractions .1 .4 .6 .1
+@item @tab \fontname@{@var{fontname}@} @tab Specify the font to use @tab
+@item @tab \fontsize@{@var{size}@} @tab Specify the size of the font to
+use @tab
+@end multitable
+
+Finally, the superscript and subscripting can be controlled with the '^'
+and '_' characters. If the '^' or '_' is followed by a @{ character,
+then all of the block surrounded by the @{ @} pair is super- or
+sub-scripted. Without the @{ @} pair, only the character immediately
+following the '^' or '_' is super- or sub-scripted.
+
+@float Table,tab:extended
+@iftex
+@tex
+\vskip 6pt
+{\hbox to \hsize {\hfill\vbox{\offinterlineskip \tabskip=0pt 
+\halign{
+\vrule height2.0ex depth1.ex width 0.6pt #\tabskip=0.3em &
+# \hfil & \vrule # & # \hfil & # \vrule &
+# \hfil & \vrule # & # \hfil & # \vrule &
+# \hfil & \vrule # & # \hfil & # \vrule 
+width 0.6pt \tabskip=0pt\cr
+\noalign{\hrule height 0.6pt}
+& Code && Sym && Code && Sym && Code && Sym &\cr
+\noalign{\hrule}
+& $\backslash$forall && $\forall$ && $\backslash$exists && $\exists$ && $\backslash$ni && $\ni$ &\cr
+& $\backslash$cong && $\cong$ && $\backslash$Delta && $\Delta$ && $\backslash$Phi && $\Phi$ &\cr
+& $\backslash$Gamma && $\Gamma$ && $\backslash$vartheta && $\vartheta$ && $\backslash$Lambda && $\Lambda$ &\cr
+& $\backslash$Pi && $\Pi$ && $\backslash$Theta && $\Theta$ && $\backslash$Sigma && $\Sigma$ &\cr
+& $\backslash$varsigma && $\varsigma$ && $\backslash$Omega && $\Omega$ && $\backslash$Xi && $\Xi$ &\cr
+& $\backslash$Psi && $\Psi$ && $\backslash$perp && $\perp$ && $\backslash$alpha && $\alpha$ &\cr
+& $\backslash$beta && $\beta$ && $\backslash$chi && $\chi$ && $\backslash$delta && $\delta$ &\cr
+& $\backslash$epsilon && $\epsilon$ && $\backslash$phi && $\phi$ && $\backslash$gamma && $\gamma$ &\cr
+& $\backslash$eta && $\eta$ && $\backslash$iota && $\iota$ && $\backslash$kappa && $\kappa$ &\cr
+& $\backslash$lambda && $\lambda$ && $\backslash$mu && $\mu$ && $\backslash$nu && $\nu$ &\cr
+& $\backslash$o && $\o$ && $\backslash$pi && $\pi$ && $\backslash$theta && $\theta$ &\cr
+& $\backslash$rho && $\rho$ && $\backslash$sigma && $\sigma$ && $\backslash$tau && $\tau$ &\cr
+& $\backslash$upsilon && $\upsilon$ && $\backslash$varpi && $\varpi$ && $\backslash$omega && $\omega$ &\cr
+& $\backslash$xi && $\xi$ && $\backslash$psi && $\psi$ && $\backslash$zeta && $\zeta$ &\cr
+& $\backslash$sim && $\sim$ && $\backslash$Upsilon && $\Upsilon$ && $\backslash$prime && $\prime$ &\cr
+& $\backslash$leq && $\leq$ && $\backslash$infty && $\infty$ && $\backslash$clubsuit && $\clubsuit$ &\cr
+& $\backslash$diamondsuit && $\diamondsuit$ && $\backslash$heartsuit && $\heartsuit$ && $\backslash$spadesuit && $\spadesuit$ &\cr
+& $\backslash$leftrightarrow && $\leftrightarrow$ && $\backslash$leftarrow && $\leftarrow$ && $\backslash$uparrow && $\uparrow$ &\cr
+& $\backslash$rightarrow && $\rightarrow$ && $\backslash$downarrow && $\downarrow$ && $\backslash$circ && $\circ$ &\cr
+& $\backslash$pm && $\pm$ && $\backslash$geq && $\geq$ && $\backslash$times && $\times$ &\cr
+& $\backslash$propto && $\propto$ && $\backslash$partial && $\partial$ && $\backslash$bullet && $\bullet$ &\cr
+& $\backslash$div && $\div$ && $\backslash$neq && $\neq$ && $\backslash$equiv && $\equiv$ &\cr
+& $\backslash$approx && $\approx$ && $\backslash$ldots && $\ldots$ && $\backslash$mid && $\mid$ &\cr
+& $\backslash$aleph && $\aleph$ && $\backslash$Im && $\Im$ && $\backslash$Re && $\Re$ &\cr
+& $\backslash$wp && $\wp$ && $\backslash$otimes && $\otimes$ && $\backslash$oplus && $\oplus$ &\cr
+& $\backslash$oslash && $\oslash$ && $\backslash$cap && $\cap$ && $\backslash$cup && $\cup$ &\cr
+& $\backslash$supset && $\supset$ && $\backslash$supseteq && $\supseteq$ && $\backslash$subset && $\subset$ &\cr
+& $\backslash$subseteq && $\subseteq$ && $\backslash$in && $\in$ && $\backslash$langle && $\langle$ &\cr
+& $\backslash$rangle && $\rangle$ && $\backslash$nabla && $\nabla$ && $\backslash$surd && $\surd$ &\cr
+& $\backslash$cdot && $\cdot$ && $\backslash$neg && $\neg$ && $\backslash$wedge && $\wedge$ &\cr
+& $\backslash$vee && $\vee$ && $\backslash$copyright && $\copyright$ && $\backslash$rfloor && $\rfloor$ &\cr
+& $\backslash$lceil && $\lceil$ && $\backslash$lfloor && $\lfloor$ && $\backslash$rceil && $\rceil$ &\cr
+& $\backslash$int && $\int$ && && && && &\cr
+\noalign{\hrule height 0.6pt}
+}}\hfill}}
+@end tex
+@end iftex
+@ifnottex
+@multitable @columnfractions .125 .25 .25 .25 .125
+@item @tab  \forall  @tab  \exists  @tab  \ni  @tab
+@item @tab  \cong  @tab  \Delta  @tab  \Phi  @tab
+@item @tab  \Gamma  @tab  \vartheta  @tab  \Lambda  @tab
+@item @tab  \Pi  @tab  \Theta  @tab  \Sigma  @tab
+@item @tab  \varsigma  @tab  \Omega  @tab  \Xi  @tab
+@item @tab  \Psi  @tab  \perp  @tab  \alpha  @tab
+@item @tab  \beta  @tab  \chi  @tab  \delta  @tab  
+@item @tab  \epsilon  @tab  \phi  @tab  \gamma  @tab
+@item @tab  \eta  @tab  \iota  @tab  \kappa  @tab
+@item @tab  \lambda  @tab  \mu  @tab  \nu  @tab
+@item @tab  \o  @tab  \pi  @tab  \theta  @tab
+@item @tab  \rho  @tab  \sigma  @tab  \tau  @tab
+@item @tab  \upsilon  @tab  \varpi  @tab  \omega  @tab
+@item @tab  \xi  @tab  \psi  @tab  \zeta  @tab
+@item @tab  \sim  @tab  \Upsilon  @tab  \prime  @tab
+@item @tab  \leq  @tab  \infty  @tab  \clubsuit  @tab
+@item @tab  \diamondsuit  @tab  \heartsuit  @tab  \spadesuit  @tab
+@item @tab  \leftrightarrow  @tab  \leftarrow  @tab  \uparrow  @tab
+@item @tab  \rightarrow  @tab  \downarrow  @tab  \circ  @tab
+@item @tab  \pm  @tab  \geq  @tab  \times  @tab
+@item @tab  \propto  @tab  \partial  @tab  \bullet  @tab
+@item @tab  \div  @tab  \neq  @tab  \equiv  @tab
+@item @tab  \approx  @tab  \ldots  @tab  \mid  @tab
+@item @tab  \aleph  @tab  \Im  @tab  \Re  @tab
+@item @tab  \wp  @tab  \otimes  @tab  \oplus  @tab
+@item @tab  \oslash  @tab  \cap  @tab  \cup  @tab  
+@item @tab  \supset  @tab  \supseteq  @tab  \subset  @tab
+@item @tab  \subseteq  @tab  \in  @tab  \langle  @tab
+@item @tab  \rangle  @tab  \nabla  @tab  \surd  @tab
+@item @tab  \cdot  @tab  \neg  @tab  \wedge  @tab
+@item @tab  \vee  @tab  \copyright  @tab  \rfloor  @tab
+@item @tab  \lceil  @tab  \lfloor  @tab  \rceil  @tab
+@item @tab  \int  @tab  @tab  @tab
+@end multitable
+@end ifnottex
+@caption{Available special characters in @sc{TeX} mode}
+@end float
+
+A complete example showing the capabilities of the extended text is
+
+@example
+@group
+x = 0:0.01:3;
+plot(x,erf(x));
+hold on;
+plot(x,x,"r");
+axis([0, 3, 0, 1]);
+text(0.65, 0.6175, strcat('\leftarrow x = @{2/\surd\pi',
+' @{\fontsize@{16@}\int_@{\fontsize@{8@}0@}^@{\fontsize@{8@}x@}@}',
+' e^@{-t^2@} dt@} = 0.6175'))
+@end group
+@end example
+
+@ifnotinfo
+@noindent
+The result of which can be seen in @ref{fig:extendedtext}
+
+@float Figure,fig:extendedtext
+@image{extended,8cm}
+@caption{Example of inclusion of text with the @sc{TeX} interpreter}
+@end float
+@end ifnotinfo
+
 @node Image Properties
 @subsubsection Image Properties
 
--- a/doc/interpreter/plotimages.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/interpreter/plotimages.m	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,15 @@
     z = linspace (0, 1, numel (t));
     plot3 (r.*sin(t), r.*cos(t), z);
     print (strcat (nm, ".", typ), strcat ("-d", typ))    
+  elseif (strcmp (nm, "extended"))
+    x = 0:0.01:3;
+    plot(x,erf(x));
+    hold on;
+    plot(x,x,"r");
+    axis([0, 3, 0, 1]);
+    text(0.65, 0.6175, strcat('\leftarrow x = {2/\surd\pi {\fontsize{16}',
+      '\int_{\fontsize{8}0}^{\fontsize{8}x}} e^{-t^2} dt} = 0.6175'))
+    print (strcat (nm, ".", typ), strcat ("-d", typ))
   else
     error ("unrecognized plot requested");
   endif
--- a/doc/interpreter/sparse.txi	Mon Nov 26 20:31:25 2007 +0000
+++ b/doc/interpreter/sparse.txi	Mon Nov 26 20:42:11 2007 +0000
@@ -490,9 +490,9 @@
 @item Linear algebra:
   @dfn{matrix_type}, @dfn{spchol}, @dfn{cpcholinv}, 
   @dfn{spchol2inv}, @dfn{spdet}, @dfn{spinv}, @dfn{spkron},
-  @dfn{splchol}, @dfn{splu}, @dfn{spqr}, @dfn{normest}, 
+  @dfn{splchol}, @dfn{splu}, @dfn{spqr}, @dfn{normest}, @dfn{condest},
   @dfn{sprank}
-@c @dfn{condest}, @dfn{spaugment}
+@c @dfn{spaugment}
 @c @dfn{eigs}, @dfn{svds} but these are in octave-forge for now
 
 @item Iterative techniques:
@@ -828,6 +828,8 @@
 
 @DOCSTRING(normest)
 
+@DOCSTRING(condest)
+
 @DOCSTRING(spchol)
 
 @DOCSTRING(spcholinv)
--- a/liboctave/Array.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/Array.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -2315,7 +2315,13 @@
 {
   Array<T> retval;
 
-  assert (ndims () == 2);
+  if (ndims () != 2)
+    {
+      Array<idx_vector> ra_idx (2);
+      ra_idx(0) = idx_i;
+      ra_idx(1) = idx_j;
+      return index (ra_idx, resize_ok, rfv);
+    }
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
--- a/liboctave/ChangeLog	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/ChangeLog	Mon Nov 26 20:42:11 2007 +0000
@@ -1,3 +1,28 @@
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* intNDArray.cc (template <class T> intNDArray<T>
+	intNDArray<T>::max (int) const, template <class T> intNDArray<T>
+	intNDArray<T>::max (ArrayN<octave_idx_type>&, int) const,
+	template <class T> intNDArray<T> intNDArray<T>::min (int) const, 
+	template <class T> intNDArray<T> intNDArray<T>::min 
+	(ArrayN<octave_idx_type>&, int) const): New methods for integer
+	classes.
+	* intNDArray.h (class intNDArray): Add min/max methods
+	* mx-op-defs.h (MIXMAX_DECLS, MINMAX_FCNS, SND_MINMAX_FCN,
+	NDS_MINMAX_FCN, NDND_MINMAX_FCN): New macro for instantiation of
+	min/max functions.
+	* int8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h, 
+	uint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h
+	(MINMAX_DECLS(T)): Declare the min/max functions for integer
+	types.
+	* int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc, 
+	uint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc
+	(MINMAX_FCNS(T)): Instantiate the min/max functions for integer
+	types.
+
+	* Arrayc.cc (Array<T>::index (idx_vector&, idx_vector&, int,
+	const T& rfv) const): If ndims != 2 call ND version of index.
+
 2007-11-14  John W. Eaton  <jwe@octave.org>
 
 	* oct-inttypes.h (opeator T (void) const): New conversion operator.
--- a/liboctave/int16NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int16NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (int16NDArray, , int16NDArray, )
 NDND_BOOL_OPS (int16NDArray, int16NDArray, octave_int16 (0))
 
+MINMAX_FCNS (int16)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/int16NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int16NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, int16NDArray, octave_int16)
 
+MINMAX_DECLS (int16)
+
 #endif
 
 /*
--- a/liboctave/int32NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int32NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (int32NDArray, , int32NDArray, )
 NDND_BOOL_OPS (int32NDArray, int32NDArray, octave_int32 (0))
 
+MINMAX_FCNS (int32)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/int32NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int32NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, int32NDArray, octave_int32)
 
+MINMAX_DECLS (int32)
+
 #endif
 
 /*
--- a/liboctave/int64NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int64NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (int64NDArray, , int64NDArray, )
 NDND_BOOL_OPS (int64NDArray, int64NDArray, octave_int64 (0))
 
+MINMAX_FCNS (int64)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/int64NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int64NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, int64NDArray, octave_int64)
 
+MINMAX_DECLS (int64)
+
 #endif
 
 /*
--- a/liboctave/int8NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int8NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (int8NDArray, , int8NDArray, )
 NDND_BOOL_OPS (int8NDArray, int8NDArray, octave_int8 (0))
 
+MINMAX_FCNS (int8)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/int8NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/int8NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, int8NDArray, octave_int8)
 
+MINMAX_DECLS (int8)
+
 #endif
 
 /*
--- a/liboctave/intNDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/intNDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -229,6 +229,140 @@
   MX_ND_REDUCTION (retval(result_idx) += intNDArray<T>::elem (iter_idx), 0, intNDArray<T>);
 }
 
+template <class T>
+intNDArray<T>
+intNDArray<T>::max (int dim) const
+{
+  ArrayN<octave_idx_type> dummy_idx;
+  return max (dummy_idx, dim);
+}
+
+template <class T>
+intNDArray<T>
+intNDArray<T>::max (ArrayN<octave_idx_type>& idx_arg, int dim) const
+{
+  dim_vector dv = this->dims ();
+  dim_vector dr = this->dims ();
+
+  if (dv.numel () == 0 || dim > dv.length () || dim < 0)
+    return intNDArray<T> ();
+  
+  dr(dim) = 1;
+
+  intNDArray<T> result (dr);
+  idx_arg.resize (dr);
+
+  octave_idx_type x_stride = 1;
+  octave_idx_type x_len = dv(dim);
+  for (int i = 0; i < dim; i++)
+    x_stride *= dv(i);
+
+  for (octave_idx_type i = 0; i < dr.numel (); i++)
+    {
+      octave_idx_type x_offset;
+      if (x_stride == 1)
+	x_offset = i * x_len;
+      else
+	{
+	  octave_idx_type x_offset2 = 0;
+	  x_offset = i;
+	  while (x_offset >= x_stride)
+	    {
+	      x_offset -= x_stride;
+	      x_offset2++;
+	    }
+	  x_offset += x_offset2 * x_stride * x_len;
+	}
+
+      octave_idx_type idx_j = 0;
+
+      T tmp_max = this->elem (x_offset);
+
+      for (octave_idx_type j = 1; j < x_len; j++)
+	{
+	  T tmp = this->elem (j * x_stride + x_offset);
+
+	  if (tmp > tmp_max)
+	    {
+	      idx_j = j;
+	      tmp_max = tmp;
+	    }
+	}
+
+      result.elem (i) = tmp_max;
+      idx_arg.elem (i) = idx_j;
+    }
+
+  return result;
+}
+
+template <class T>
+intNDArray<T>
+intNDArray<T>::min (int dim) const
+{
+  ArrayN<octave_idx_type> dummy_idx;
+  return min (dummy_idx, dim);
+}
+
+template <class T>
+intNDArray<T>
+intNDArray<T>::min (ArrayN<octave_idx_type>& idx_arg, int dim) const
+{
+  dim_vector dv = this->dims ();
+  dim_vector dr = this->dims ();
+
+  if (dv.numel () == 0 || dim > dv.length () || dim < 0)
+    return intNDArray<T> ();
+  
+  dr(dim) = 1;
+
+  intNDArray<T> result (dr);
+  idx_arg.resize (dr);
+
+  octave_idx_type x_stride = 1;
+  octave_idx_type x_len = dv(dim);
+  for (int i = 0; i < dim; i++)
+    x_stride *= dv(i);
+
+  for (octave_idx_type i = 0; i < dr.numel (); i++)
+    {
+      octave_idx_type x_offset;
+      if (x_stride == 1)
+	x_offset = i * x_len;
+      else
+	{
+	  octave_idx_type x_offset2 = 0;
+	  x_offset = i;
+	  while (x_offset >= x_stride)
+	    {
+	      x_offset -= x_stride;
+	      x_offset2++;
+	    }
+	  x_offset += x_offset2 * x_stride * x_len;
+	}
+
+      octave_idx_type idx_j = 0;
+
+      T tmp_min = this->elem (x_offset);
+
+      for (octave_idx_type j = 1; j < x_len; j++)
+	{
+	  T tmp = this->elem (j * x_stride + x_offset);
+
+	  if (tmp < tmp_min)
+	    {
+	      idx_j = j;
+	      tmp_min = tmp;
+	    }
+	}
+
+      result.elem (i) = tmp_min;
+      idx_arg.elem (i) = idx_j;
+    }
+
+  return result;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/intNDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/intNDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -73,6 +73,11 @@
   boolNDArray all (int dim = -1) const;
   boolNDArray any (int dim = -1) const;
 
+  intNDArray max (int dim = 0) const;
+  intNDArray max (ArrayN<octave_idx_type>& index, int dim = 0) const;
+  intNDArray min (int dim = 0) const;
+  intNDArray min (ArrayN<octave_idx_type>& index, int dim = 0) const;
+  
   intNDArray sum (int dim) const;
 
   intNDArray squeeze (void) const
--- a/liboctave/mx-op-defs.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/mx-op-defs.h	Mon Nov 26 20:42:11 2007 +0000
@@ -1159,6 +1159,95 @@
 
 #endif
 
+#define SND_MINMAX_FCN(FCN, OP, T) \
+T ## NDArray \
+FCN (octave_ ## T d, const T ## NDArray& m) \
+{ \
+  dim_vector dv = m.dims (); \
+  octave_idx_type nel = dv.numel (); \
+\
+  if (nel == 0)	\
+    return T ## NDArray (dv); \
+\
+  T ## NDArray result (dv); \
+\
+  for (octave_idx_type i = 0; i < nel; i++) \
+    { \
+      OCTAVE_QUIT; \
+      result (i) = d OP m (i) ? d : m(i); \
+    } \
+\
+  return result; \
+}
+
+#define NDS_MINMAX_FCN(FCN, OP, T) \
+T ## NDArray \
+FCN (const T ## NDArray& m, octave_ ## T d) \
+{ \
+  dim_vector dv = m.dims (); \
+  octave_idx_type nel = dv.numel (); \
+\
+  if (nel == 0)	\
+    return T ## NDArray (dv); \
+\
+  T ## NDArray result (dv); \
+\
+  for (octave_idx_type i = 0; i < nel; i++) \
+    { \
+      OCTAVE_QUIT; \
+      result (i) = m (i) OP d ? m(i) : d; \
+    } \
+\
+  return result; \
+}
+
+#define NDND_MINMAX_FCN(FCN, OP, T) \
+T ## NDArray \
+FCN (const T ## NDArray& a, const T ## NDArray& b) \
+{ \
+  dim_vector dv = a.dims (); \
+  octave_idx_type nel = dv.numel (); \
+\
+  if (dv != b.dims ()) \
+    { \
+      (*current_liboctave_error_handler) \
+	("two-arg min expecting args of same size"); \
+      return T ## NDArray (); \
+    } \
+\
+  if (nel == 0)	\
+    return T ## NDArray (dv); \
+\
+  T ## NDArray result (dv); \
+\
+  for (octave_idx_type i = 0; i < nel; i++) \
+    { \
+      OCTAVE_QUIT; \
+      result (i) = a(i) OP b(i) ? a(i) : b(i); \
+    } \
+\
+  return result; \
+}
+
+#define MINMAX_FCNS(T) \
+  SND_MINMAX_FCN (min, <, T) \
+  NDS_MINMAX_FCN (min, <, T) \
+  NDND_MINMAX_FCN (min, <, T) \
+  SND_MINMAX_FCN (max, >, T) \
+  NDS_MINMAX_FCN (max, >, T) \
+  NDND_MINMAX_FCN (max, >, T)
+
+#define MINMAX_DECLS(T) \
+  extern OCTAVE_API T ## NDArray min (octave_ ## T d, const T ## NDArray& m); \
+  extern OCTAVE_API T ## NDArray min (const T ## NDArray& m, octave_ ## T d); \
+  extern OCTAVE_API T ## NDArray min (const T ## NDArray& a,  \
+				       const T ## NDArray& b); \
+  extern OCTAVE_API T ## NDArray max (octave_ ## T d, const T ## NDArray& m); \
+  extern OCTAVE_API T ## NDArray max (const T ## NDArray& m, octave_ ## T d); \
+  extern OCTAVE_API T ## NDArray max (const T ## NDArray& a, \
+				       const T ## NDArray& b);
+
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/uint16NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint16NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (uint16NDArray, , uint16NDArray, )
 NDND_BOOL_OPS (uint16NDArray, uint16NDArray, octave_uint16 (0))
 
+MINMAX_FCNS (uint16)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/uint16NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint16NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, uint16NDArray, octave_uint16)
 
+MINMAX_DECLS (uint16)
+
 #endif
 
 /*
--- a/liboctave/uint32NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint32NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (uint32NDArray, , uint32NDArray, )
 NDND_BOOL_OPS (uint32NDArray, uint32NDArray, octave_uint32 (0))
 
+MINMAX_FCNS (uint32)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/uint32NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint32NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, uint32NDArray, octave_uint32)
 
+MINMAX_DECLS (uint32)
+
 #endif
 
 /*
--- a/liboctave/uint64NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint64NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (uint64NDArray, , uint64NDArray, )
 NDND_BOOL_OPS (uint64NDArray, uint64NDArray, octave_uint64 (0))
 
+MINMAX_FCNS (uint64)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/uint64NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint64NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, uint64NDArray, octave_uint64)
 
+MINMAX_DECLS (uint64)
+
 #endif
 
 /*
--- a/liboctave/uint8NDArray.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint8NDArray.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -48,6 +48,8 @@
 NDND_CMP_OPS (uint8NDArray, , uint8NDArray, )
 NDND_BOOL_OPS (uint8NDArray, uint8NDArray, octave_uint8 (0))
 
+MINMAX_FCNS (uint8)
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/uint8NDArray.h	Mon Nov 26 20:31:25 2007 +0000
+++ b/liboctave/uint8NDArray.h	Mon Nov 26 20:42:11 2007 +0000
@@ -40,6 +40,8 @@
 
 MARRAY_FORWARD_DEFS (MArrayN, uint8NDArray, octave_uint8)
 
+MINMAX_DECLS (uint8)
+
 #endif
 
 /*
--- a/scripts/ChangeLog	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/ChangeLog	Mon Nov 26 20:42:11 2007 +0000
@@ -1,3 +1,95 @@
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* plot/quiver3.m, plot/surfnorm.m, plot/__quiver__.m: New functions.
+	* plot/Makefile.in (SOURCES): Add them to the sources.
+	* plot/quiver.m: Modify to use __quiver__.m.
+
+	* plot/hist.m: Avoid saturation when the x values are in an
+	inetger type.
+
+2007-11-26  Jason Riedy  <ejr@cs.berkeley.edu>
+
+	* linear-algebra/condest.m, linear-algebra/onenormest.m: New
+	functions.
+	* linear-algebra/Makefile.in (SOURCES): Add them to the sources.
+
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* plot/__go_draw_axes__.m: Prevent the cbrange from being of zero
+	extent.
+
+	* plot/colorbar.m: New function.
+	* plot/Makefile.in (SOURCES): Add it to the sources.
+	* plot/__go_draw_axes__.m: Calculate the colorbar position,
+	precalculate the clim, set pm3d except for mesh.
+	* plot/__contour__.m: Don't scale the contours to clim, but rather
+	save the real values so that colorbar corresponds to the contour
+	levels.
+
+	* plot/stem.m: Set marker color the same as the line color. Draw 
+	a single discontinous line object for the stems.
+
+	* plot/sphere.m: New function ported from JHandles.
+	* plot/Makefile.in (SOURCES): Add it to the sources.
+
+	* plot/__go_draw_axes__.m: Pass the have_newer_gnuplot arg to
+	__maybe_munge_text__. Use it to reforce fontname for gnuplot 4.0
+	to get enhanced mode to work correctly for the X11 terminal.
+
+	* plot/imagesc.m, plot/image.m: Scale colormap to image and not
+	the reverse. Allow an axes handle to be passed and/or returned.
+	* plot/__go_draw_axes__.m: Autoscale colormap for images.
+
+	* plot/__go_draw_axes__.m: Add depthorder flag to "set pm3d" to
+	sort surface patches by their depth and not the order they are
+	rendered in.
+
+	* plot/__patch__.m: Set clim correctly.
+	* plot__go_draw_axes__.m: Allow patch objects to have markers, and 
+	the marker color is determined by the cmap.
+	* plot/scatter.m: New function to 2D scatter plots.
+	* plot/scatter3.m: New function to 3D scatter plots.
+	* plot/__scatter__.m: Support function for scatter plots
+	* Makefile.in (SOURCES): Ad dnew functions here.
+
+	* plot/drawnow.m (open_gnuplot_stream, init_gnuplot_stream):
+	Return whether the terminal supports enhanced text or not.
+	(drawnow:enhanced_term): New sub-function to determine if terminal
+	supports enhanced mode.
+	* plot/__go_draw_figure__.m: Accept enhanced flag and pass to
+	__go_draw_axes__.
+	* plot/__go_draw_axes__.m: Accept enhanced flag and munge text if
+	needed to support the enhanced mode.
+	* plot/print.m: Remove "enhanced" option as this is now treated in
+	drawnow.m.
+
+
+	* plot/caxis.m: New function to control the color axis limits.
+	* plot/Makefile.in (SOURCES): Include it.
+	* plot/axis.m: Allow the first argument to be an axes handle.
+	* plot/__go_draw_axes__.m: Move the setting of the caxis, also
+	autoscale caxis for patches. If any(isinf(clim)) don't set the
+	caxis limits.
+
+	* image/gmap40.m: New gnuplot 4.0 specific colormap fucntion.
+	* image/Makefile.in (SOURCES): Include it.
+	* plot/__bar__.h: Allow axis handles to be passed. Set the color
+	of the bars for the colormap. 
+	* plot/bar.m, plot/barh.m: Document that axis handles can be
+	passed.
+	* plot/__contour.m: Avoid possible divide by zero error.
+	* plot/contour.m: Missing semicolon.
+	* plot/surface.m: Don't attempt to set additional arguments if
+	there are none.
+	* plot/Makefile.in (SOURCES): Include __bars__.m
+	
+2007-11-19  Michael Goffioul <michael.goffioul@gmail.com>
+
+	* plot/__bar__.m: put bar creation code into separate function
+	to allow easy hook up from other graphic backends
+
+	* plot/__bars__.m: new function containing bar creation code
+
 2007-11-26  Alexander Barth  <barth.alexander@gmail.com>
 
 	* general/accumarray.m: Correct dimension check.
--- a/scripts/image/Makefile.in	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/image/Makefile.in	Mon Nov 26 20:42:11 2007 +0000
@@ -34,9 +34,9 @@
 INSTALL_DATA = @INSTALL_DATA@
 
 SOURCES = __img__.m __img_via_file__.m autumn.m bone.m brighten.m colormap.m \
-  cool.m copper.m flag.m gray.m gray2ind.m hot.m hsv.m hsv2rgb.m image.m \
-  image_viewer.m imagesc.m imshow.m ind2gray.m ind2rgb.m jet.m loadimage.m \
-  ntsc2rgb.m ocean.m pink.m prism.m rainbow.m rgb2hsv.m rgb2ind.m \
+  cool.m copper.m flag.m gmap40.m gray.m gray2ind.m hot.m hsv.m hsv2rgb.m \
+  image.m image_viewer.m imagesc.m imshow.m ind2gray.m ind2rgb.m jet.m \
+  loadimage.m ntsc2rgb.m ocean.m pink.m prism.m rainbow.m rgb2hsv.m rgb2ind.m \
   rgb2ntsc.m saveimage.m spring.m summer.m white.m winter.m
 
 IMAGES = default.img
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/image/gmap40.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,49 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} gmap40 (@var{n})
+## Create a color colormap. The colormap is red, green, blue, yellow,
+## magneta and cyan. These are the colors that are allowed with patch
+## objects using gnuplot 4.0, and so this colormap function is specially
+## designed for users of gnuplot 4.0.  The argument @var{n} should be 
+## a scalar.  If it is omitted, a length of 6 is assumed. Larger values
+## of @var{n} result in a repetition of the above colors
+## @seealso{colormap}
+## @end deftypefn
+
+function map = gmap40 (number)
+
+  if (nargin == 0)
+    number = 6;
+  elseif (nargin == 1)
+    if (! isscalar (number))
+      error ("gmap40: argument must be a scalar");
+    endif
+  else
+    print_usage ();
+  endif
+
+  if (number >= 1)
+    map = repmat ([1, 0, 0; 0, 1, 0; 0, 0, 1; 1, 1, 0; 1, 0, 1; 0, 1, 1],
+		  ceil (number / 6), 1) (1:number, :);
+  else
+    map = [];
+  endif
+
+endfunction
--- a/scripts/image/image.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/image/image.m	Mon Nov 26 20:42:11 2007 +0000
@@ -21,8 +21,8 @@
 ## @deftypefn {Function File} {} image (@var{img})
 ## @deftypefnx {Function File} {} image (@var{x}, @var{y}, @var{img})
 ## Display a matrix as a color image.  The elements of @var{x} are indices
-## into the current colormap and should have values between 1 and the
-## length of the colormap.
+## into the current colormap, and the colormap will be scaled so that the
+## extremes of @var{x} are mapped to the extremes of teh colormap.
 ##
 ## It first tries to use @code{gnuplot}, then @code{display} from 
 ## @code{ImageMagick}, then @code{xv}, and then @code{xloadimage}.
@@ -39,35 +39,57 @@
 ## Created: July 1994
 ## Adapted-By: jwe
 
-function h = image (x, y, img)
+function retval = image (varargin)
+
+  if (nargin < 2)
+    print_usage ();
+  elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("image: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      tmp = __image__ (h, varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    tmp = __image__ (gca (), varargin{:});
+  endif
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
+
+function h = __image__ (ax, x, y, img)
 
   ## Deprecated zoom.  Remove this hunk of code if old zoom argument
   ## is outmoded.
-  if ((nargin == 2 && isscalar (y)) || nargin == 4)
+  if ((nargin == 3 && isscalar (y)) || nargin == 5)
     warning ("image: zoom argument ignored -- use GUI features");
   endif
-  if (nargin == 4)
-    nargin = 3;
+  if (nargin == 5)
+    nargin = 4;
   endif
-  if (nargin == 2 && isscalar (y))
-    nargin = 1;
+  if (nargin == 3 && isscalar (y))
+    nargin = 2;
   endif
 
-  if (nargin == 0)
+  if (nargin == 1)
     ## Load Bobbie Jo Richardson (Born 3/16/94)
     img = loadimage ("default.img");
     x = y = [];
-  elseif (nargin == 1)
+  elseif (nargin == 2)
     img = x;
     x = y = [];
-  elseif (nargin == 2 || nargin > 3)
+  elseif (nargin == 3 || nargin > 4)
     print_usage ();
   endif
 
-  tmp = __img__ (x, y, img);
-
-  if (nargout > 0)
-    h = tmp;
-  endif
+  h = __img__ (x, y, img);
 
 endfunction
--- a/scripts/image/imagesc.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/image/imagesc.m	Mon Nov 26 20:42:11 2007 +0000
@@ -21,92 +21,100 @@
 ## @deftypefn {Function File} {} imagesc (@var{A})
 ## @deftypefnx {Function File} {} imagesc (@var{x}, @var{y}, @var{A})
 ## @deftypefnx {Function File} {} imagesc (@dots{}, @var{limits})
-## @deftypefnx {Function File} { @var{B} = } imagesc (@dots{})
+## @deftypefnx {Function File} {} imagesc (@var{h}, @dots{})
+## @deftypefnx {Function File} { @var{h} = } imagesc (@dots{})
 ## Display a scaled version of the matrix @var{A} as a color image.  The
-## matrix is scaled so that its entries are indices into the current
-## colormap.  The scaled matrix is returned.  If @var{limits} = [@var{lo}, @var{hi}] are
-## given, then that range maps into the full range of the colormap rather 
-## than the minimum and maximum values of @var{A}.
+## colormap is scaled so that the entries of the matrix occupy the entire
+## colormap.  If @var{limits} = [@var{lo}, @var{hi}] are given, then that
+## range is set to the 'clim' of the current axes.
 ##
 ## The axis values corresponding to the matrix elements are specified in
 ## @var{x} and @var{y}, either as pairs giving the minimum and maximum
 ## values for the respective axes, or as values for each row and column
 ## of the matrix @var{A}.
-## @seealso{image, imshow}
+##
+## @seealso{image, imshow, clim, caxis}
 ## @end deftypefn
 
 ## Author: Tony Richardson <arichard@stark.cc.oh.us>
 ## Created: July 1994
 ## Adapted-By: jwe
 
-function ret = imagesc (x, y, A, limits, DEPRECATEDZOOM)
+function retval = imagesc (varargin)
+
+  if (nargin < 1)
+    print_usage ();
+  elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("imagesc: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      tmp = __imagesc__ (h, varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    tmp = __imagesc__ (gca (), varargin{:});
+  endif
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
+
+function ret = __imagesc__ (ax, x, y, A, limits, DEPRECATEDZOOM)
 
   ## Deprecated zoom.  Remove this hunk of code if old zoom argument
   ## is outmoded.
-  if ((nargin == 2 && isscalar (y))
-      || (nargin == 3 && (isscalar (y) || isscalar (A)))
-      || (nargin == 4 && isscalar (limits))
-      || nargin == 5)
+  if ((nargin == 3 && isscalar (y))
+      || (nargin == 4 && (isscalar (y) || isscalar (A)))
+      || (nargin == 5 && isscalar (limits))
+      || nargin == 6)
     warning ("image: zoom argument ignored -- use GUI features");
   endif
-  if (nargin == 5)
+  if (nargin == 6)
     if (isscalar (limits))
       limits = DEPRECATEDZOOM;
     endif
+    nargin = 5;
+  endif
+  if (nargin == 5 && isscalar (limits))
     nargin = 4;
   endif
-  if (nargin == 4 && isscalar (limits))
-    nargin = 3;
-  endif
-  if (nargin == 3 && (isscalar (y) || isscalar (A)))
+  if (nargin == 4 && (isscalar (y) || isscalar (A)))
     if (isscalar (y))
       y = A;
     endif
-    nargin = 2;
+    nargin = 3;
   endif
-  if (nargin == 2 && isscalar (y))
-    nargin = 1;
+  if (nargin == 3 && isscalar (y))
+    nargin = 2;
   endif
 
-  if (nargin < 1 || nargin > 4)
+  if (nargin < 2 || nargin > 5)
     print_usage ();
-  elseif (nargin == 1)
+  elseif (nargin == 2)
     A = x;
     x = y = limits = [];
-  elseif (nargin == 2)
+  elseif (nargin == 3)
     A = x;
     limits = y;
     x = y = [];
-  elseif (nargin == 3 && !isscalar (x) && !isscalar (y) && !isscalar (A))
+  elseif (nargin == 4 && !isscalar (x) && !isscalar (y) && !isscalar (A))
     limits = [];
   endif
 
+  ret = image (ax, x, y, A);
+
   ## use given limits or guess them from the matrix
   if (length (limits) == 2 && limits(2) >= limits(1))
-     minval = limits(1);
-     maxval = limits(2);
-     A(A < minval) = minval;
-     A(A > maxval) = maxval;
-  elseif (length (limits) == 0)
-     maxval = max (A(:));
-     minval = min (A(:));
-  else
+     set (ax, "clim", limits);
+  elseif (!isempty (limits))
      error ("expected data limits to be [lo, hi]");
   endif
 
-  ## scale the limits to the range of the colormap
-  if (maxval == minval)
-    B = ones (size (A));
-  else
-    ## Rescale values to between 1 and length (colormap) inclusive.
-    B = round ((A - minval) / (maxval - minval) * (rows (colormap) - 1)) + 1;
-  endif
-
-  ## display or return the image
-  if (nargout == 0)
-    image (x, y, B);
-  else
-    ret = B;
-  endif
-
 endfunction
--- a/scripts/linear-algebra/Makefile.in	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/linear-algebra/Makefile.in	Mon Nov 26 20:42:11 2007 +0000
@@ -33,9 +33,9 @@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_DATA = @INSTALL_DATA@
 
-SOURCES = __norm__.m commutation_matrix.m cond.m cross.m dmult.m \
-  dot.m duplication_matrix.m housh.m krylov.m krylovb.m logm.m \
-  null.m orth.m qzhess.m rank.m rref.m trace.m vec.m vech.m
+SOURCES = __norm__.m commutation_matrix.m cond.m condest.m cross.m \
+  dmult.m dot.m duplication_matrix.m housh.m krylov.m krylovb.m logm.m \
+  null.m onenormest.m orth.m qzhess.m rank.m rref.m trace.m vec.m vech.m
 
 DISTFILES = $(addprefix $(srcdir)/, Makefile.in $(SOURCES))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/condest.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,218 @@
+## Copyright (C) 2007, Regents of the University of California
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{est}, @var{v}] =} condest (@var{A}, @var{t}) 
+## @deftypefnx {Function File} {[@var{est}, @var{v}] =} condest (@var{A}, @var{solve}, @var{solve_t}, @var{t})
+## @deftypefnx {Function File} {[@var{est}, @var{v}] =} condest (@var{apply}, @var{apply_t}, @var{solve}, @var{solve_t}, @var{n}, @var{t})
+##
+## Estimate the 1-norm condition number of a matrix matrix @var{A}
+## using @var{t} test vectors using a randomized 1-norm estimator.
+## If @var{t} exceeds 5, then only 5 test vectors are used.
+##
+## If the matrix is not explicit, e.g. when  estimating the condition 
+## number of @var{A} given an LU factorization, @code{condest} uses the 
+## following functions:
+##
+## @table @var
+## @item apply
+## @code{A*x} for a matrix @code{x} of size @var{n} by @var{t}.
+## @item apply_t
+## @code{A'*x} for a matrix @code{x} of size @var{n} by @var{t}.
+## @item solve
+## @code{A \ b} for a matrix @code{b} of size @var{n} by @var{t}.
+## @item solve_t
+## @code{A' \ b} for a matrix @code{b} of size @var{n} by @var{t}.
+## @end table
+##
+## The implicit version requires an explicit dimension @var{n}.
+##
+## @code{condest} uses a randomized algorithm to approximate
+## the 1-norms.
+##
+## @code{condest} returns the 1-norm condition estimate @var{est} and
+## a vector @var{v} satisfying @code{norm (@var{A}*@var{v}, 1) == norm
+## (@var{A}, 1) * norm (@var{v}, 1) / @var{est}}. When @var{est} is
+## large, @var{v} is an approximate null vector.
+##
+## References: 
+## @itemize
+## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm
+## for Matrix 1-Norm Estimation, with an Application to 1-Norm
+## Pseudospectra." SIMAX vol 21, no 4, pp 1185-1201.
+## @url{http://dx.doi.org/10.1137/S0895479899356080}
+## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm
+## for Matrix 1-Norm Estimation, with an Application to 1-Norm
+## Pseudospectra." @url{http://citeseer.ist.psu.edu/223007.html}
+## @end itemize
+##
+## @seealso{norm, cond, onenormest}
+##
+## @end deftypefn
+
+## Code originally licensed under
+##
+##  Copyright (c) 2007, Regents of the University of California
+##  All rights reserved.
+##  Redistribution and use in source and binary forms, with or without
+##  modification, are permitted provided that the following conditions are met:
+##
+##     * Redistributions of source code must retain the above copyright
+##       notice, this list of conditions and the following disclaimer.
+##     * Redistributions in binary form must reproduce the above copyright
+##       notice, this list of conditions and the following disclaimer in the
+##       documentation and/or other materials provided with the distribution.
+##     * Neither the name of the University of California, Berkeley nor the
+##       names of its contributors may be used to endorse or promote products
+##       derived from this software without specific prior written permission.
+##
+##  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+##  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+##  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+##  DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR
+##  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+##  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+##  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+##  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+##  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+##  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+##  SUCH DAMAGE.
+##
+## Relicensed to GPL for inclusion in Octave.
+
+## Author: Jason Riedy <ejr@cs.berkeley.edu>
+## Keywords: linear-algebra norm estimation
+## Version: 0.2
+
+function [est, v] = condest (varargin)
+  if size (varargin, 2) < 1 || size (varargin, 2) > 5,
+    usage("condest: Incorrect arguments.");
+  endif
+
+  default_t = 5;
+
+  if (ismatrix (varargin{1}))
+    n = size (varargin{1}, 1);
+    if (n != size (varargin{1}, 2))
+      error ("condest: matrix must be square.");
+    endif
+    A = varargin{1};
+
+    if (size (varargin, 2) > 1)
+      if (isscalar (varargin{2}))
+	t = varargin{2};
+      else
+	if (size (varargin, 2) < 3)
+	  error ("condest: must supply both solve and solve_t.");
+	else
+	  solve = varargin{2};
+	  solve_t = varargin{3};
+	  if size (varargin, 2) > 3,
+	    t = varargin{4};
+	  endif
+	endif
+      endif
+    endif
+  else
+    if (size (varargin, 2) < 5)
+      error ("condest: implicit form of condest requires at least 5 arguments.");
+    endif
+    apply = varargin{1};
+    apply_t = varargin{2};
+    solve = varargin{3};
+    solve_t = varargin{4};
+    n = varargin{5};
+    if (! isscalar (n))
+      error ("condest: dimension argument of implicit form must be scalar.");
+    endif
+    if (size (varargin, 2) > 5)
+      t = varargin{6};
+    endif
+  endif
+
+  if (! exist ("t", "var"))
+    t = min (n, default_t);
+  endif
+
+  if (! exist ("solve", "var"))
+    if (issparse (A))
+      [L, U, P, Pc] = splu (A);
+      solve = @(x) Pc' * (U\ (L\ (P*x)));
+      solve_t = @(x) P'*(L'\ (U'\ (Pc*x)));
+    else
+      [L, U, P] = lu (A);
+      solve = @(x) U\ (L\ (P*x));
+      solve_t = @(x) P' * (L'\ (U'\x));
+    endif
+  endif
+
+  if (exist ("A", "var"))
+    Anorm = norm (A, 1);
+  else
+    Anorm = onenormest (apply, apply_t, n, t);
+  endif
+
+  [Ainv_norm, v, w] = onenormest (solve, solve_t, n, t);
+
+  est = Anorm * Ainv_norm;
+  v = w / norm (w, 1);
+
+endfunction
+
+%!demo
+%!  N = 100;
+%!  A = randn (N) + eye (N);
+%!  condest (A)
+%!  [L,U,P] = lu (A);
+%!  condest (A, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x)))
+%!  condest (@(x) A*x, @(x) A'*x, @(x) U\ (L\ (P*x)), @(x) P'*(L'\ (U'\x)), N)
+%!  norm (inv (A), 1) * norm (A, 1)
+
+## Yes, these test bounds are really loose.  There's
+## enough randomization to trigger odd cases with hilb().
+
+%!test
+%!  N = 6;
+%!  A = hilb (N);
+%!  cA = condest (A);
+%!  cA_test = norm (inv (A), 1) * norm (A, 1);
+%!  assert (cA, cA_test, 2^-12);
+
+%!test
+%!  N = 6;
+%!  A = hilb (N);
+%!  solve = @(x) A\x; solve_t = @(x) A'\x;
+%!  cA = condest (A, solve, solve_t);
+%!  cA_test = norm (inv (A), 1) * norm (A, 1);
+%!  assert (cA, cA_test, 2^-12);
+
+%!test
+%!  N = 6;
+%!  A = hilb (N);
+%!  apply = @(x) A*x; apply_t = @(x) A'*x;
+%!  solve = @(x) A\x; solve_t = @(x) A'\x;
+%!  cA = condest (apply, apply_t, solve, solve_t, N);
+%!  cA_test = norm (inv (A), 1) * norm (A, 1);
+%!  assert (cA, cA_test, 2^-6);
+
+%!test
+%!  N = 12;
+%!  A = hilb (N);
+%!  [rcondA, v] = condest (A);
+%!  x = A*v;
+%!  assert (norm(x, inf), 0, eps);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/onenormest.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,265 @@
+## Copyright (C) 2007, Regents of the University of California
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{A}, @var{t}) 
+## @deftypefnx {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{apply}, @var{apply_t}, @var{n}, @var{t})
+##
+## Apply Higham and Tisseur's randomized block 1-norm estimator to
+## matrix @var{A} using @var{t} test vectors. If @var{t} exceeds 5, then
+## only 5 test vectors are used.
+##
+## If the matrix is not explicit, e.g. when estimating the norm of 
+## @code{inv (@var{A})} given an LU factorization, @code{onenormest} applies 
+## @var{A} and its conjugate transpose through a pair of functions 
+## @var{apply} and @var{apply_t}, respectively, to a dense matrix of size 
+## @var{n} by @var{t}. The implicit version requires an explicit dimension 
+## @var{n}.
+##
+## Returns the norm estimate @var{est}, two vectors @var{v} and
+## @var{w} related by norm
+## @code{(@var{w}, 1) = @var{est} * norm (@var{v}, 1)},
+## and the number of iterations @var{iter}.  The number of
+## iterations is limited to 10 and is at least 2.
+##
+## References: 
+## @itemize
+## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm
+## for Matrix 1-Norm Estimation, with an Application to 1-Norm
+## Pseudospectra." SIMAX vol 21, no 4, pp 1185-1201.
+## @url{http://dx.doi.org/10.1137/S0895479899356080}
+## @item Nicholas J. Higham and Françoise Tisseur, "A Block Algorithm
+## for Matrix 1-Norm Estimation, with an Application to 1-Norm
+## Pseudospectra." @url{http://citeseer.ist.psu.edu/223007.html}
+## @end itemize
+##
+## @seealso{condest, norm, cond}
+## @end deftypefn
+
+## Code originally licensed under
+##
+##  Copyright (c) 2007, Regents of the University of California
+##  All rights reserved.
+##  Redistribution and use in source and binary forms, with or without
+##  modification, are permitted provided that the following conditions are met:
+##
+##     * Redistributions of source code must retain the above copyright
+##       notice, this list of conditions and the following disclaimer.
+##     * Redistributions in binary form must reproduce the above copyright
+##       notice, this list of conditions and the following disclaimer in the
+##       documentation and/or other materials provided with the distribution.
+##     * Neither the name of the University of California, Berkeley nor the
+##       names of its contributors may be used to endorse or promote products
+##       derived from this software without specific prior written permission.
+##
+##  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+##  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+##  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+##  DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR
+##  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+##  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+##  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+##  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+##  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+##  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+##  SUCH DAMAGE.
+##
+## Relicensed to GPL for inclusion in Octave.
+
+## Author: Jason Riedy <ejr@cs.berkeley.edu>
+## Keywords: linear-algebra norm estimation
+## Version: 0.2
+
+function [est, v, w, iter] = onenormest (varargin)
+
+  if (size (varargin, 2) < 1 || size (varargin, 2) > 4)
+    print_usage ();
+  endif
+
+  default_t = 5;
+  itmax = 10;
+
+  if (ismatrix (varargin{1}))
+    n = size (varargin{1}, 1);
+    if n != size (varargin{1}, 2),
+      error ("onenormest: matrix must be square.");
+    endif
+    apply = @(x) varargin{1} * x;
+    apply_t = @(x) varargin{1}' * x;
+    if (size (varargin) > 1)
+      t = varargin{2};
+    else
+      t = min (n, default_t);
+    endif
+  else
+    if (size (varargin, 2) < 3)
+      print_usage();
+    endif
+    n = varargin{3};
+    apply = varargin{1};
+    apply_t = varargin{2};
+    if (size (varargin) > 3)
+      t = varargin{4};
+    else
+      t = default_t;
+    endif
+  endif
+
+  ## Initial test vectors X.
+  X = rand (n, t);
+  X = X ./ (ones (n,1) * sum (abs (X), 1));
+
+  been_there = zeros (n, 1); # Track if a vertex has been visited.
+  est_old = 0; # To check if the estimate has increased.
+  S = zeros (n, t); # Normalized vector of signs.  The normalization is 
+
+  for iter = 1 : itmax + 1
+    Y = feval (apply, X);
+
+    ## Find the initial estimate as the largest A*x.
+    [est, ind_best] = max (sum (abs (Y), 1));
+    if (est > est_old || iter == 2)
+      w = Y(:,ind_best);
+    endif
+    if (iter >= 2 && est < est_old)
+      ## No improvement, so stop.
+      est = est_old;
+      break;
+    endif
+
+    est_old = est;
+    S_old = S;
+    if (iter > itmax),
+      ## Gone too far.  Stop.
+      break;
+    endif
+
+    S = sign (Y);
+
+    ## Test if any of S are approximately parallel to previous S
+    ## vectors or current S vectors.  If everything is parallel,
+    ## stop. Otherwise, replace any parallel vectors with
+    ## rand{-1,+1}.
+    partest = any (abs (S_old' * S - n) < 4*eps*n);
+    if (all (partest))
+      ## All the current vectors are parallel to old vectors.
+      ## We've hit a cycle, so stop.
+      break;
+    endif
+    if (any (partest))
+      ## Some vectors are parallel to old ones and are cycling,
+      ## but not all of them.  Replace the parallel vectors with
+      ## rand{-1,+1}.
+      numpar = sum (partest);
+      replacements = 2*(rand (n,numpar) < 0.5) - 1;
+      S(:,partest) = replacements;
+    endif
+    ## Now test for parallel vectors within S.
+    partest = any ( (S' * S - eye (t)) == n );
+    if (any (partest))
+      numpar = sum (partest);
+      replacements = 2*(rand (n,numpar) < 0.5) - 1;
+      S(:,partest) = replacements;
+    endif
+    
+    Z = feval (apply_t, S);
+
+    ## Now find the largest non-previously-visted index per
+    ## vector.
+    h = max (abs (Z),2);
+    [mh, mhi] = max (h);
+    if (iter >= 2 && mhi == ind_best)
+      ## Hit a cycle, stop.
+      break;
+    endif
+    [h, ind] = sort (h, 'descend');
+    if (t > 1)
+      firstind = ind(1:t);
+      if (all (been_there(firstind)))
+	## Visited all these before, so stop.
+	break;
+      endif
+      ind = ind (!been_there (ind));
+      if (length (ind) < t)
+	## There aren't enough new vectors, so we're practically
+	## in a cycle. Stop.
+	break;
+      endif
+    endif
+
+    ## Visit the new indices.
+    X = zeros (n, t);
+    for zz = 1 : t
+      X(ind(zz),zz) = 1;
+    endfor
+    been_there (ind (1 : t)) = 1;
+  endfor
+
+  ## The estimate est and vector w are set in the loop above. The
+  ## vector v selects the ind_best column of A.
+  v = zeros (n, 1);
+  v(ind_best) = 1;
+endfunction
+
+%!demo
+%!  N = 100;
+%!  A = randn(N) + eye(N);
+%!  [L,U,P] = lu(A);
+%!  nm1inv = onenormest(@(x) U\(L\(P*x)), @(x) P'*(L'\(U'\x)), N, 30)
+%!  norm(inv(A), 1)
+
+%!test
+%!  N = 10;
+%!  A = ones (N);
+%!  [nm1, v1, w1] = onenormest (A);
+%!  [nminf, vinf, winf] = onenormest (A', 6);
+%!  assert (nm1, N, -2*eps);
+%!  assert (nminf, N, -2*eps);
+%!  assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps)
+%!  assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps)
+
+%!test
+%!  N = 10;
+%!  A = ones (N);
+%!  [nm1, v1, w1] = onenormest (@(x) A*x, @(x) A'*x, N, 3);
+%!  [nminf, vinf, winf] = onenormest (@(x) A'*x, @(x) A*x, N, 3);
+%!  assert (nm1, N, -2*eps);
+%!  assert (nminf, N, -2*eps);
+%!  assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps)
+%!  assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps)
+
+%!test
+%!  N = 5;
+%!  A = hilb (N);
+%!  [nm1, v1, w1] = onenormest (A);
+%!  [nminf, vinf, winf] = onenormest (A', 6);
+%!  assert (nm1, norm (A, 1), -2*eps);
+%!  assert (nminf, norm (A, inf), -2*eps);
+%!  assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps)
+%!  assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps)
+
+## Only likely to be within a factor of 10.
+%!test
+%!  N = 100;
+%!  A = rand (N);
+%!  [nm1, v1, w1] = onenormest (A);
+%!  [nminf, vinf, winf] = onenormest (A', 6);
+%!  assert (nm1, norm (A, 1), -.1);
+%!  assert (nminf, norm (A, inf), -.1);
+%!  assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps)
+%!  assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps)
--- a/scripts/plot/Makefile.in	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/Makefile.in	Mon Nov 26 20:42:11 2007 +0000
@@ -38,6 +38,7 @@
   __axes_limits__.m \
   __axis_label__.m \
   __bar__.m \
+  __bars__.m \
   __contour__.m \
   __default_plot_options__.m \
   __errcomm__.m \
@@ -62,6 +63,8 @@
   __plt_get_axis_arg__.m \
   __pltopt1__.m \
   __pltopt__.m \
+  __quiver__.m \
+  __scatter__.m \
   ancestor.m \
   area.m \
   axes.m \
@@ -69,9 +72,11 @@
   bar.m \
   barh.m \
   box.m \
+  caxis.m \
   clf.m \
   close.m \
   closereq.m \
+  colorbar.m \
   contour3.m \
   contour.m \
   contourc.m \
@@ -110,8 +115,11 @@
   polar.m \
   print.m \
   quiver.m \
+  quiver3.m \
   replot.m \
   ribbon.m \
+  scatter.m \
+  scatter3.m \
   semilogx.m \
   semilogxerr.m \
   semilogy.m \
@@ -120,6 +128,7 @@
   shg.m \
   slice.m \
   sombrero.m \
+  sphere.m \
   spinmap.m \
   stairs.m \
   stem.m \
@@ -127,6 +136,7 @@
   surf.m \
   surface.m \
   surfc.m \
+  surfnorm.m \
   text.m \
   title.m \
   view.m \
--- a/scripts/plot/__bar__.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/__bar__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -22,15 +22,36 @@
 
 function varargout = __bar__ (vertical, func, varargin)
 
+  varargout = cell (nargout, 1);
+  if (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin{1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("%s: expecting first argument to be an axes object", func);
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      [varargout{:}] = __bar2__ (h, vertical, func, varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    [varargout{:}] = __bar2__ (gca(), vertical, func, varargin{:});
+  endif
+
+endfunction
+
+function varargout = __bar2__ (h, vertical, func, varargin)
+
   ## Slightly smaller than 0.8 to avoid clipping issue in gnuplot 4.0
   width = 0.8 - 10 * eps; 
   group = true;
 
-  if (nargin < 3)
+  if (nargin < 4)
     print_usage ();
   endif
 
-  if (nargin > 3 && isnumeric (varargin{2}))
+  if (nargin > 4 && isnumeric (varargin{2}))
     x = varargin{1};
     if (isvector (x))
       x = x(:);
@@ -63,7 +84,7 @@
       
   newargs = {};
   have_line_spec = false;
-  while (idx <= nargin -2)
+  while (idx <= nargin - 3)
     if (isstr (varargin{idx}) && strcmp (varargin{idx}, "grouped"))
       group = true;
       idx++;
@@ -83,7 +104,7 @@
       endif
       if (isscalar(varargin{idx}))
 	width = varargin{idx++};
-      elseif (idx == nargin - 2)
+      elseif (idx == nargin - 3)
 	newargs = [newargs,varargin(idx++)];
       else
 	newargs = [newargs,varargin(idx:idx+1)];
@@ -107,9 +128,8 @@
     width = width / ycols;
   endif
 
-  cutoff = (x(1:end-1) + x(2:end)) / 2;
-  delta_p = [(cutoff - x(1:end-1)); (x(end) - cutoff(end))]  * width;
-  delta_m = [(cutoff(1) - x(1)); (x(2:end) - cutoff)] * width;
+  cutoff = min (diff (double(x))) / 2;
+  delta_p = delta_m = repmat (cutoff * width, size (x));
   x1 = (x - delta_m)(:)';
   x2 = (x + delta_p)(:)';
   xb = repmat ([x1; x1; x2; x2](:), 1, ycols);
@@ -137,43 +157,19 @@
   xb = reshape (xb, [4, numel(xb) / 4 / ycols, ycols]);
   yb = reshape (yb, [4, numel(yb) / 4 / ycols, ycols]);
 
-  color = [1, 0, 0; 0, 1, 0; 0, 0, 1; 1, 1, 0; 1, 0, 1; 0, 1, 1];
-  if (vertical)
-    if (nargout < 2)
-      newplot ();
-      tmp = [];
-      for i = 1 : ycols
-	if (! have_line_spec)
-	  tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), color(i,:), newargs {:})];
-	else
-	  tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), newargs {:})];
-	endif
-      endfor
-      if (nargout == 1)
-	varargout{1} = tmp;
-      endif
-    else
+  if (nargout < 2)
+    newplot ();
+    tmp = __bars__ (h, vertical, x, y, xb, yb, width, group, have_line_spec, newargs {:});
+    if (nargout == 1)
+      varargout{1} = tmp;
+    endif
+  else
+    if (vertical)
       varargout{1} = xb;
       varargout{2} = yb;
-    endif
-  else
-    if (nargout < 2)
-      newplot ();
-      tmp = [];
-      for i = 1 : ycols
-	if (! have_line_spec)
-	  tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), color(i,:), newargs {:})];
-	else
-	  tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), newargs {:})];
-	endif
-      endfor
-      if (nargout == 1)
-	varargout{1} = tmp;
-      endif
     else
       varargout{1} = yb;
       varargout{2} = xb;
     endif
   endif
-
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/__bars__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,59 @@
+## Copyright (C) 1996, 1997, 2007 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## Undocumented internal function.
+
+## Author: jwe
+
+function tmp = __bars__ (h, vertical, x, y, xb, yb, width, group, have_color_spec, varargin)
+
+  ycols = columns (y);
+  clim = get (h, "clim");
+
+  if (vertical)
+    tmp = [];
+    for i = 1 : ycols
+      if (! have_color_spec)
+	if (ycols == 1)
+	  lev = clim (1);
+	else
+	  lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
+	endif
+	tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), "FaceColor", "flat", 
+			  "cdata", lev, varargin {:})];
+      else
+	tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), varargin {:})];
+      endif
+    endfor
+  else
+    tmp = [];
+    for i = 1 : ycols
+      if (! have_color_spec)
+	if (ycols == 1)
+	  lev = clim (1)
+	else
+	  lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
+	endif
+	tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), "FaceColor", "flat", 
+			  "cdata", lev, varargin {:})];
+      else
+	tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), varargin {:})];
+      endif
+    endfor
+  endif
+endfunction
--- a/scripts/plot/__contour__.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/__contour__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -38,15 +38,11 @@
     endif
   endif
 
-  clim = get (ax, "clim");
-
   [c, lev] = contourc (varargin{3:end});
 
   ## Decode contourc output format.
   i1 = 1;
   h = [];
-  maxlev = max (lev);
-  minlev = min (lev);
   while (i1 < length (c))
     clev = c(1,i1);
     clen = c(2,i1);
@@ -57,17 +53,15 @@
       p = [c(:, i1+1:i1+clen), NaN(2, 1)];
     endif
 
-    lev = (clev - minlev) * (clim(2) - clim(1)) / (maxlev - minlev) + clim(1);
-
     if (isnan (z))
       h = [h; patch(ax, p(1,:), p(2,:), "facecolor", "none", 
-		    "edgecolor", "flat", "cdata", lev)];
+		    "edgecolor", "flat", "cdata", clev)];
     elseif (!ischar(z))
       h = [h; patch(ax, p(1,:), p(2,:), z * ones (1, columns (p)), "facecolor",
-		    "none", "edgecolor", "flat", "cdata", lev)];
+		    "none", "edgecolor", "flat", "cdata", clev)];
     else
       h = [h; patch(ax, p(1,:), p(2,:), clev * ones (1, columns (p)),
-		    "facecolor", "none", "edgecolor", "flat", "cdata", lev)];
+		    "facecolor", "none", "edgecolor", "flat", "cdata", clev)];
     endif
     i1 += clen+1;
   endwhile
--- a/scripts/plot/__go_draw_axes__.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/__go_draw_axes__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -20,9 +20,9 @@
 
 ## Author: jwe
 
-function __go_draw_axes__ (h, plot_stream)
+function __go_draw_axes__ (h, plot_stream, enhanced)
 
-  if (nargin == 2)
+  if (nargin == 3)
 
     axis_obj = get (h);
 
@@ -32,19 +32,23 @@
       = compare_versions (__gnuplot_version__ (), "4.0", ">");
 
     ## Set axis properties here?
-
+    pos = [0,0,1,1];
     if (! isempty (axis_obj.outerposition))
       pos = axis_obj.outerposition;
-      fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2));
-      fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4));
     endif
 
     if (! isempty (axis_obj.position))
       pos = axis_obj.position;
-      fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2));
-      fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4));
     endif
 
+    if (! strcmp (axis_obj.__colorbar__, "none"))
+      [pos, cbox_orient, cbox_size, cbox_origin, cbox_mirror] = ...
+	  gnuplot_postion_colorbox (pos, axis_obj.__colorbar__);
+    endif
+
+    fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2));
+    fprintf (plot_stream, "set size %.15g, %.15g;\n", pos(3), pos(4));
+
     if (strcmpi (axis_obj.dataaspectratiomode, "manual"))
       r = axis_obj.dataaspectratio;
       fprintf (plot_stream, "set size ratio %.15g;\n", -r(2)/r(1));
@@ -52,6 +56,7 @@
       fputs (plot_stream, "set size noratio;\n");
     endif
 
+    fputs (plot_stream, "set pm3d;\n");
     fputs (plot_stream, "unset label;\n");
 
     if (! isempty (axis_obj.title))
@@ -59,9 +64,10 @@
       if (isempty (t.string))
 	fputs (plot_stream, "unset title;\n");
       else
-	[f, s] = get_fontname_and_size (t);
+	[tt, f, s] = __maybe_munge_text__ (enhanced, t, "string", 
+					   have_newer_gnuplot);
 	fprintf (plot_stream, "set title \"%s\" font \"%s,%d\";\n",
-		 undo_string_escapes (t.string), f, s);
+		 undo_string_escapes (tt), f, s);
       endif
     endif
 
@@ -71,9 +77,10 @@
       if (isempty (t.string))
 	fputs (plot_stream, "unset xlabel;\n");
       else
-	[f, s] = get_fontname_and_size (t);
+	[tt, f, s] = __maybe_munge_text__ (enhanced, t, "string",
+					   have_newer_gnuplot);
 	fprintf (plot_stream, "set xlabel \"%s\" font \"%s,%d\"",
-		 undo_string_escapes (t.string), f, s);
+		 undo_string_escapes (tt), f, s);
 	if (have_newer_gnuplot)
 	  ## Rotation of xlabel not yet support by gnuplot as of 4.2, but
 	  ## there is no message about it.
@@ -89,9 +96,10 @@
       if (isempty (t.string))
 	fputs (plot_stream, "unset ylabel;\n");
       else
-	[f, s] = get_fontname_and_size (t);
+	[tt, f, s] = __maybe_munge_text__ (enhanced, t, "string",
+					   have_newer_gnuplot);
 	fprintf (plot_stream, "set ylabel \"%s\" font \"%s,%d\"",
-		 undo_string_escapes (t.string), f, s);
+		 undo_string_escapes (tt), f, s);
 	if (have_newer_gnuplot)
 	  fprintf (plot_stream, " rotate by %f;\n", angle);
 	endif
@@ -105,8 +113,10 @@
       if (isempty (t.string))
 	fputs (plot_stream, "unset zlabel;\n");
       else
-	fprintf (plot_stream, "set zlabel \"%s\"",
-		 undo_string_escapes (t.string));
+	[tt, f, s] = __maybe_munge_text__ (enhanced, t, "string",
+					   have_newer_gnuplot);
+	fprintf (plot_stream, "set zlabel \"%s\" font \"%s,%d\"",
+		 undo_string_escapes (tt), f, s);
 	if (have_newer_gnuplot)
 	  ## Rotation of zlabel not yet support by gnuplot as of 4.2, but
 	  ## there is no message about it.
@@ -210,6 +220,27 @@
     xmax = ymax = zmax = cmax = -Inf;
     xmin = ymin = zmin = cmin = Inf;
 
+    ## This has to be done here as some of the code below depends on the
+    ## final clim
+    if (cautoscale)
+      for i = 1:length (kids)
+	obj = get (kids(i));
+	if (isfield (obj, "cdata"))
+	  [cmin, cmax, cminp] = get_data_limits (cmin, cmax, cminp, 
+						 obj.cdata(:));
+	endif
+      endfor
+      if (cmin == cmax)
+	cmax = cmin + 1;
+      endif      
+      clim = [cmin, cmax];
+    else
+      clim = axis_obj.clim;
+      if (clim(1) == clim(2))
+	clim = [clim(1), clim(1) + 1];
+      endif
+    endif
+
     [view_cmd, view_fcn, view_zoom] = image_viewer ();
     use_gnuplot_for_images = (ischar (view_fcn)
 			      && strcmp (view_fcn, "gnuplot_internal"));
@@ -232,7 +263,6 @@
 	  endif
 
 	  img_data = obj.cdata;
-	  img_colormap = parent_figure_obj.colormap;
 	  img_xdata = obj.xdata;
 	  img_ydata = obj.ydata;
 
@@ -281,15 +311,6 @@
 	      data{data_idx} = img_data(:);
 	      format = "1";
 	      imagetype = "image";
-
-	      palette_size = rows (img_colormap);
-	      fprintf (plot_stream,
-		       "set palette positive color model RGB maxcolors %i;\n",
-		       palette_size);
-	      fprintf (plot_stream,
-		       "set palette file \"-\" binary record=%d using 1:2:3:4;\n",
-		       palette_size);
-	      fwrite (plot_stream, [1:palette_size; img_colormap'], "float32");
 	    endif
 
 	    titlespec{data_idx} = "title \"\"";
@@ -315,7 +336,7 @@
 	  if (isempty (obj.keylabel))
 	    titlespec{data_idx} = "title \"\"";
 	  else
-	    tmp = undo_string_escapes (obj.keylabel);
+	    tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot));
 	    titlespec{data_idx} = strcat ("title \"", tmp, "\"");
 	  endif
 	  [style, typ, with] = do_linestyle_command (obj, data_idx, plot_stream);
@@ -435,9 +456,14 @@
 
        case "patch"
          cmap = parent_figure_obj.colormap;
-         clim = axis_obj.clim;
 	 [nr, nc] = size (obj.xdata);
 
+	 if (! isempty (obj.cdata))
+	   cdat = obj.cdata;
+	 else
+	   cdat = [];
+	 endif
+
 	 for i = 1:nc
 	   xcol = obj.xdata(:,i);
 	   ycol = obj.ydata(:,i);
@@ -480,29 +506,40 @@
 	       if (i > 1 || isempty (obj.keylabel))
 		 titlespec{data_idx} = "title \"\"";
 	       else
-		 tmp = undo_string_escapes (obj.keylabel);
+		 tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot));
 		 titlespec{data_idx} = strcat ("title \"", tmp, "\"");
 	       endif
 	       usingclause{data_idx} = "";
-               if (isfield (obj, "facecolor") && isfield (obj, "cdata"))
-		 if (strncmp (obj.facecolor, "flat", 4)
-		     || strncmp (obj.facecolor, "interp", 6))
+               if (isfield (obj, "facecolor"))
+		 if ((strncmp (obj.facecolor, "flat", 4)
+		     || strncmp (obj.facecolor, "interp", 6)) &&
+		     isfield (obj, "cdata"))
 		   if (ndims (obj.cdata) == 2
-		       && ((nr > 3 && size (obj.cdata, 2) == nc)
-			   || (size (obj.cdata, 1) > 1
-			       && size (obj.cdata, 2) == nc)))
-		     ccol = obj.cdata (:, i);
+		       && (size (obj.cdata, 2) == nc
+			   && (size (obj.cdata, 1) == 1
+			       || size (obj.cdata, 1) == 3)))
+		     ccol = cdat (:, i);
+		   elseif (ndims (obj.cdata) == 2
+		       && (size (obj.cdata, 1) == nc
+			   && (size (obj.cdata, 2) == 1
+			       || size (obj.cdata, 2) == 3)))
+		     ccol = cdat (i, :);
 		   elseif (ndims (obj.cdata) == 3)
-		     ccol = permute (obj.cdata (:, i, :), [1, 3, 2]);
+		     ccol = permute (cdat (:, i, :), [1, 3, 2]);
 		   else
-		     ccol = obj.cdata;
+		     ccol = cdat;
 		   endif
 		   if (strncmp (obj.facecolor, "flat", 4))
 		     if (numel(ccol) == 3)
 		       color = ccol;
 		     else
-		       r = 1 + round ((size (cmap, 1) - 1)
-				      * (ccol - clim(1))/(clim(2) - clim(1)));
+		       if (cautoscale)
+			 r = 1 + round ((size (cmap, 1) - 1)
+					* (ccol - cmin)/(cmax - cmin));
+		       else
+			 r = 1 + round ((size (cmap, 1) - 1)
+					* (ccol - clim(1))/(clim(2) - clim(1)));
+		       endif
 		       r = max (1, min (r, size (cmap, 1)));
 		       color = cmap(r, :);
 		     endif
@@ -512,8 +549,10 @@
 		     r = max (1, min (r, size (cmap, 1)));
 		     color = cmap(r,:);
 		   endif
+		 elseif (isnumeric (obj.facecolor))
+		   color = obj.facecolor;
 		 else
-		   color = obj.facecolor;
+		   color = [0, 1, 0];
 		 endif
                else
 		 color = [0, 1, 0];
@@ -564,25 +603,41 @@
 	     have_cdata(data_idx) = false;
              titlespec{data_idx} = "title \"\"";
 	     usingclause{data_idx} = "";
-             if (isfield (obj, "edgecolor") && isfield (obj, "cdata"))
-	       if (strncmp (obj.edgecolor, "flat", 4)
-		   || strncmp (obj.edgecolor, "interp", 6))
+
+	     if (isfield (obj, "markersize"))
+	       mdat = obj.markersize;
+	     endif
+
+             if (isfield (obj, "edgecolor"))
+	       if ((strncmp (obj.edgecolor, "flat", 4)
+		    || strncmp (obj.edgecolor, "interp", 6)) &&
+		   isfield (obj, "cdata"))
 		 if (ndims (obj.cdata) == 2
-		     && ((nr > 3 && size (obj.cdata, 2) == nc)
-			 || (size (obj.cdata, 1) > 1
-			     && size (obj.cdata, 2) == nc)))
-		   ccol = obj.cdata (:, i);
+		     && (size (obj.cdata, 2) == nc
+			 && (size (obj.cdata, 1) == 1
+			     || size (obj.cdata, 1) == 3)))
+		   ccol = cdat (:, i);
+		 elseif (ndims (obj.cdata) == 2
+			 && (size (obj.cdata, 1) == nc
+			     && (size (obj.cdata, 2) == 1
+				 || size (obj.cdata, 2) == 3)))
+		   ccol = cdat (i, :);
 		 elseif (ndims (obj.cdata) == 3)
-		   ccol = permute (obj.cdata (:, i, :), [1, 3, 2]);
+		   ccol = permute (cdat (:, i, :), [1, 3, 2]);
 		 else
-		   ccol = obj.cdata;
+		   ccol = cdat;
 		 endif
 		 if (strncmp (obj.edgecolor, "flat", 4))
-		   if (numel (ccol) == 3)
+		   if (numel(ccol) == 3)
 		     color = ccol;
 		   else
-		     r = 1 + round ((size (cmap, 1) - 1)
-				    * (ccol - clim(1))/(clim(2) - clim(1)));
+		     if (cautoscale)
+		       r = 1 + round ((size (cmap, 1) - 1)
+				      * (ccol - cmin)/(cmax - cmin));
+		     else
+		       r = 1 + round ((size (cmap, 1) - 1)
+				      * (ccol - clim(1))/(clim(2) - clim(1)));
+		     endif
 		     r = max (1, min (r, size (cmap, 1)));
 		     color = cmap(r, :);
 		   endif
@@ -592,16 +647,105 @@
 		   r = max (1, min (r, size (cmap, 1)));
 		   color = cmap(r,:);
 		 endif
+	       elseif (isnumeric (obj.edgecolor))
+		 color = obj.edgecolor;
+	       else
+		 color = [0, 0, 0];
 	       endif
-             elseif (isfield (obj, "edgecolor") && isnumeric (obj.edgecolor))
-	       color = obj.edgecolor;
              else
-               color = [0, 0, 0];
+	       color = [0, 0, 0];
              endif
+
+	     if (isfield (obj, "linestyle"))
+	       switch (obj.linestyle)
+		 case "-"
+		   lt = "1";
+		 case "--"
+		   lt = "2";
+		 case ":"
+		   lt = "3";
+		 case "-."
+		   lt = "6";
+		 case "none"
+		   lt = "";
+		 otherwise
+		   lt = "";
+	       endswitch
+	     else
+	       lt = "";
+	     endif
+
+	     if (isfield (obj, "marker"))
+	       if (isfield (obj, "marker"))
+		 switch (obj.marker)
+		   case "+"
+		     pt = "pt 1";
+		   case "o"
+		     pt = "pt 6";
+		   case "*"
+		     pt = "pt 3";
+		   case "."
+		     pt = "pt 0";
+		   case "x"
+		     pt = "pt 2";
+		   case {"square", "s"}
+		     pt = "pt 5";
+		   case {"diamond", "d"}
+		     pt = "pt 13";
+		   case "^"
+		     pt = "pt 9";
+		   case "v"
+		     pt = "pt 11";
+		   case ">"
+		     pt = "pt 8";
+		   case "<"
+		     pt = "pt 10";
+		   case {"pentagram", "p"}
+		     pt = "pt 4";
+		   case {"hexagram", "h"}
+		     pt = "pt 12";
+		   case "none"
+		     pt = "";
+		   otherwise
+		     pt = "";
+		 endswitch
+	       endif
+	     else
+	       pt = "";
+	     endif
+
+	     style = "lines";
+	     if (isempty (lt))
+	       if (! isempty (pt))
+		 style = "points";
+	       endif
+	     elseif (! isempty (pt))
+	       style = "linespoints";
+	     endif
+
+	     if (isfield (obj, "markersize"))
+	       if (length (mdat) == nc)
+		 m = mdat(i);
+	       else
+		 m = mdat;
+	       endif
+	       if (! strcmpi (style, "lines"))
+		 if (have_newer_gnuplot)
+		   ps = sprintf("pointsize %f", m);
+		 else
+		   ps = sprintf("ps %f", m);
+		 endif
+	       else
+		 ps = "";
+	       endif
+	     else
+	       ps = "";
+	     endif
+
 	     if (have_newer_gnuplot)
 	       withclause{data_idx} ...
-		   = sprintf ("with lines lc rgb \"#%02x%02x%02x\"",
-			      round (255*color));
+		   = sprintf ("with %s %s %s lc rgb \"#%02x%02x%02x\"",
+			      style, pt, ps, round (255*color));
 	     else
 	       if (isequal (color, [0,0,0]))
 		 typ = -1;
@@ -622,7 +766,8 @@
 	       else
 		 typ = -1;
 	       endif
-	       withclause{data_idx} = sprintf ("with lines lt %d", typ);
+	       withclause{data_idx} = sprintf ("with %s %s %s lt %d", 
+					       style, pt, ps, typ);
 	     endif
 
 	     if (! isempty (zcol))
@@ -657,7 +802,7 @@
 	    if (isempty (obj.keylabel))
 	      titlespec{data_idx} = "title \"\"";
 	    else
-	      tmp = undo_string_escapes (obj.keylabel);
+	      tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "keylabel", have_newer_gnuplot));
 	      titlespec{data_idx} = strcat ("title \"", tmp, "\"");
 	    endif
 	    usingclause{data_idx} = "";
@@ -686,10 +831,6 @@
 	      tz = zdat(:);
 	      [zmin, zmax, zminp] = get_data_limits (zmin, zmax, zminp, tz);
 	    endif
-	    if (cautoscale)
-	      tc = cdat(:);
-	      [cmin, cmax, cminp] = get_data_limits (cmin, cmax, cminp, tc);
-	    endif
 
   	    err = false;
             if (! size_equal(zdat, cdat))
@@ -729,18 +870,15 @@
 	      data{data_idx} = zz.';
 	    endif
 	    usingclause{data_idx} = "using ($1):($2):($3):($4)";
-	    withclause{data_idx} = "with line palette";
 
 	    fputs (plot_stream, "unset parametric;\n");
 	    fputs (plot_stream, "set style data lines;\n");
 	    fputs (plot_stream, "set surface;\n");
 	    fputs (plot_stream, "unset contour;\n");
-	    fprintf (plot_stream, "set cbrange [%g:%g];\n", cmin, cmax);
 
 	    ## Interpolation does not work for flat surfaces (e.g. pcolor)
             ## and color mapping --> currently set empty.
             interp_str = "";
-            surf_colormap = parent_figure_obj.colormap;
             flat_interp_face = (strncmp (obj.facecolor, "flat", 4)
 				|| strncmp (obj.facecolor, "interp", 6));
             flat_interp_edge = (strncmp (obj.edgecolor, "flat", 4)
@@ -749,8 +887,6 @@
 	    facecolor_none_or_white = (strncmp (obj.facecolor, "none", 4)
 				       || (isnumeric (obj.facecolor)
 					   && all (obj.facecolor == 1)));
-            palette_data = [];
-
 	    if (strncmp (obj.facecolor, "none", 4))
 	      if (isnan (hidden_removal))
 		hidden_removal = false;
@@ -761,28 +897,32 @@
 
             if (flat_interp_face
 		|| (flat_interp_edge && facecolor_none_or_white))
-              palette_data = [1:rows(surf_colormap); surf_colormap'];
-	    elseif (isnumeric (obj.facecolor))
-              palette_data = [1:2; [obj.facecolor; obj.facecolor]'];
+	      withclause{data_idx} = "with line palette";
             endif
 
-	    if (facecolor_none_or_white && isnumeric (obj.edgecolor))
-              palette_data = [1:2; [obj.edgecolor; obj.edgecolor]'];
-            endif
+	    if (have_newer_gnuplot)
+	      dord = "depthorder";
+	    else
+	      dord = "";
+	    endif
 
 	    if (facecolor_none_or_white)
-	      ## Do nothing.
+	      ## Ensure faces aren't drawn
+	      fprintf (plot_stream, "unset pm3d;\n");
             elseif (flat_interp_face && strncmp (obj.edgecolor, "flat", 4))
-              fprintf (plot_stream, "set pm3d at s %s;\n", interp_str);
+              fprintf (plot_stream, "set pm3d at s %s %s;\n", 
+		       interp_str, dord);
             else
               if (strncmp (obj.edgecolor, "none", 4))
-                fprintf (plot_stream, "set pm3d at s %s;\n", interp_str);
+                fprintf (plot_stream, "set pm3d at s %s ;\n", 
+			 interp_str, dord);
               else
                 edgecol = obj.edgecolor;
                 if (ischar (obj.edgecolor))
                   edgecol = [0,0,0];
                 endif
-                fprintf (plot_stream, "set pm3d at s hidden3d %d %s;\n", data_idx, interp_str);
+                fprintf (plot_stream, "set pm3d at s hidden3d %d %s %s;\n", 
+			 data_idx, interp_str, dord);
 
 		if (have_newer_gnuplot)
                   fprintf (plot_stream,
@@ -814,37 +954,12 @@
 		endif
               endif
             endif
-
-	    if (have_newer_gnuplot)
-              if (length(palette_data) > 0)
-                fprintf (plot_stream,
-	                 "set palette positive color model RGB maxcolors %i;\n",
-	                 columns(palette_data));
-	        fprintf (plot_stream,
-	                 "set palette file \"-\" binary record=%d using 1:2:3:4;\n",
-	                 columns(palette_data));
-	        fwrite (plot_stream, palette_data, "float32");
-              endif
-	    else
-	      fputs (plot_stream, "set palette defined (");
-	      for i = 1: columns(palette_data)
-		col = floor(palette_data(2:end,i).' * 255);
-	        if (i == 1)
-		  fputs (plot_stream, sprintf("%d \"#%02X%02X%02X\"", i - 1, 
-					      col(1), col(2), col(3)));
-		else
-		  fputs (plot_stream, sprintf(", %d \"#%02X%02X%02X\"", i - 1, 
-					      col(1), col(2), col(3)));
-		endif
-	      endfor
-	      fputs (plot_stream, ");\n");
-	    endif
-	    fputs (plot_stream, "unset colorbox;\n");
 	  endif
 
 	case "text"
+	  [label, f, s] = __maybe_munge_text__ (enhanced, obj, "string",
+						have_newer_gnuplot);
 	  lpos = obj.position;
-	  label = obj.string;
 	  halign = obj.horizontalalignment;
 	  angle = obj.rotation;
           units = obj.units;
@@ -883,8 +998,6 @@
 	    endif
 	  endif
 
-	  [f, s] = get_fontname_and_size (obj);
-
 	  if (nd == 3)
 	    fprintf (plot_stream,
 		     "set label \"%s\" at %s %.15g,%.15g,%.15g font \"%s,%d\" %s rotate by %f %s;\n",
@@ -964,6 +1077,13 @@
       fprintf (plot_stream, "set zrange [%.15e:%.15e] %s;\n", zlim, zdir);
     endif
 
+    if (cautoscale && have_data)
+      set (h, "clim", clim, "climmode", "auto");
+    endif
+    if (! any (isinf (clim)))
+      fprintf (plot_stream, "set cbrange [%g:%g];\n", clim);
+    endif
+
     if (strcmpi (axis_obj.box, "on"))
       if (nd == 3)
 	fputs (plot_stream, "set border 4095;\n");
@@ -1051,6 +1171,43 @@
       endfor
     endif
 
+    cmap = parent_figure_obj.colormap;    
+    cmap_sz = rows(cmap);
+    if (length(cmap) > 0)
+      if (have_newer_gnuplot)
+        fprintf (plot_stream,
+		 "set palette positive color model RGB maxcolors %i;\n",
+	         cmap_sz);
+	fprintf (plot_stream,
+	         "set palette file \"-\" binary record=%d using 1:2:3:4;\n",
+	         cmap_sz);
+	fwrite (plot_stream, [1:cmap_sz; cmap.'], "float32");
+      else
+	fputs (plot_stream, "set palette defined (");
+	for i = 1: cmap_sz
+	  col = floor(cmap(i, :) * 255);
+          if (i == 1)
+	    fputs (plot_stream, sprintf("%d \"#%02X%02X%02X\"", i - 1, 
+					col(1), col(2), col(3)));
+	  else
+	    fputs (plot_stream, sprintf(", %d \"#%02X%02X%02X\"", i - 1, 
+					col(1), col(2), col(3)));
+	  endif
+	endfor
+	fputs (plot_stream, ");\n");
+      endif
+    endif
+	    
+    if (strcmp (axis_obj.__colorbar__, "none"))
+      fputs (plot_stream, "unset colorbox;\n");
+    else
+      ## FIXME If cbox_mirror is true we want to invert the tic labels
+      ## but gnuplot doesn't allow that
+      fputs (plot_stream, 
+	     sprintf ("set colorbox %s user origin %f,%f size %f,%f;\n",
+		      cbox_orient, cbox_origin, cbox_size));
+    endif
+
     if (have_data)
       if (nd == 2)
 	plot_cmd = "plot";
@@ -1436,24 +1593,31 @@
   endif
 endfunction
 
-function [f, s] = get_fontname_and_size (t)
+function [f, s, fnt, it, bld] = get_fontname_and_size (t)
   if (isempty (t.fontname))
-    f = "helvetica";
+    fnt = "helvetica";
   else
-    f = tolower (t.fontname);
+    fnt = tolower (t.fontname);
   endif
+  f = fnt;
+  it = false;
+  bld = false;
   if (! isempty (t.fontweight) && strcmp (tolower (t.fontweight), "bold"))
     if (! isempty(t.fontangle)
 	&& (strcmp (tolower (t.fontangle), "italic")
 	    || strcmp (tolower (t.fontangle), "oblique")))
       f = strcat (f, "-bolditalic");
+      it = true;
+      bld = true;
     else
       f = strcat (f, "-bold");
+      bld = true;
     endif
   elseif (! isempty(t.fontangle)
 	  && (strcmp (tolower (t.fontangle), "italic")
 	      || strcmp (tolower (t.fontangle), "oblique")))
     f = strcat (f, "-italic");
+    it = true;
   endif
   if (isempty (t.fontsize))
     s = 10;
@@ -1461,3 +1625,394 @@
     s = t.fontsize;
   endif
 endfunction
+
+function [str, f, s] = __maybe_munge_text__ (enhanced, obj, fld, 
+					     have_newer_gnuplot)
+  persistent warned_latex = false;
+
+  if (strcmp (fld, "string"))
+    [f, s, fnt, it, bld] = get_fontname_and_size (obj);
+  else
+    f = "Helvectica";
+    s = 10;
+    fnt = f;
+    it = false;
+    bld = false;
+  endif
+
+  str = getfield (obj, fld);
+  if (enhanced)
+    if (strcmp (obj.interpreter, "tex"))
+      str = __tex2enhanced__ (str, fnt, it, bld);
+      if (! have_newer_gnuplot)
+	## Set the font to work around gnuplot 4.0 X11 enhanced terminal bug
+	str = strcat ('{/', f, ' ', str, ' }'); 
+      endif
+    elseif (strcmp (obj.interpreter, "latex"))
+      if (! warned_latex)
+	warning ("latex text objects not supported");
+	warned_latex = true;
+      endif
+    endif
+  endif
+endfunction
+
+function str = __tex2enhanced__ (str, fnt, it, bld)
+  persistent sym = __setup_sym_table__ ();
+  persistent flds = fieldnames (sym);
+
+  [s, e, m] = regexp(str,'\\([a-zA-Z]+|0)','start','end','matches');
+
+  for i = length (s) : -1 : 1
+    ## special case for "\0"  and replace with "{/Symbol \306}'
+    if (strncmp (m{i}, '\0', 2))
+      str = strcat (str(1:s(i) - 1), '{\Symbol \306}', str(s(i) + 2:end));
+    else
+      f = m{i}(2:end);
+      if (isfield (sym, f))
+	g = getfield(sym, f);
+	## FIXME The symbol font doesn't seem to support bold or italic
+	##if (bld)
+	##  if (it)
+	##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
+	##  else
+	##    g = regexprep (g, '/Symbol', '/Symbol-bold');
+	##  endif
+	##elseif (it)
+	##  g = regexprep (g, '/Symbol', '/Symbol-italic');
+	##endif
+        str = strcat (str(1:s(i) - 1), g, str(e(i) + 1:end));
+      elseif (strncmp (f, "rm", 2))
+	bld = false;
+	it = false;
+        str = strcat (str(1:s(i) - 1), '/', fnt, ' ', str(s(i) + 3:end));
+      elseif (strncmp (f, "it", 2) || strncmp (f, "sl", 2))
+	it = true;
+	if (bld)
+          str = strcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ', 
+			str(s(i) + 3:end));
+        else
+          str = strcat (str(1:s(i) - 1), '/', fnt, '-italic ', 
+			str(s(i) + 3:end));
+        endif
+      elseif (strncmp (f, "bf", 2))
+	bld = true;
+	if (it)
+          str = strcat (str(1:s(i) - 1), '/', fnt, '-bolditalic ', 
+			str(2(i) + 3:end));
+        else
+          str = strcat (str(1:s(i) - 1), '/', fnt, '-bold ', 
+			str(s(i) + 3:end));
+        endif
+      elseif (strcmp (f, "color"))
+	## FIXME Ignore \color but remove trailing {} block as well
+	d = strfind(str(e(i) + 1:end),'}');
+        if (isempty (d))
+	  warning ('syntax error in \color argument');
+	else
+	  str = strcat (str(1:s(i) - 1), str(e(i) + d + 1:end));
+        endif
+      elseif(strcmp (f, "fontname"))
+	b1 = strfind(str(e(i) + 1:end),'{');
+	b2 = strfind(str(e(i) + 1:end),'}');
+        if (isempty(b1) || isempty(b2))
+	  warning ('syntax error in \fontname argument');
+	else
+          str = strcat (str(1:s(i) - 1), '/', 
+			str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
+			str(e(i) + b2(1) + 1:end));
+        endif
+      elseif(strcmp (f, "fontsize"))
+	b1 = strfind(str(e(i) + 1:end),'{');
+	b2 = strfind(str(e(i) + 1:end),'}');
+        if (isempty(b1) || isempty(b2))
+	  warning ('syntax error in \fontname argument');
+	else
+          str = strcat (str(1:s(i) - 1), '/=', 
+			str(e(i)+b1(1) + 1:e(i)+b2(1)-1), '{}',
+			str(e(i) + b2(1) + 1:end));
+        endif
+      else
+	## Last desperate attempt to treat the symbol. Look for things
+	## like \pix, that should be translated to the symbol Pi and x
+	for j = 1 : length (flds)
+	  if (strncmp (flds{j}, f, length (flds{j})))
+	    g = getfield(sym, flds{j});
+	    ## FIXME The symbol font doesn't seem to support bold or italic
+	    ##if (bld)
+	    ##  if (it)
+	    ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
+	    ##  else
+	    ##    g = regexprep (g, '/Symbol', '/Symbol-bold');
+	    ##  endif
+	    ##elseif (it)
+	    ##  g = regexprep (g, '/Symbol', '/Symbol-italic');
+	    ##endif
+            str = strcat (str(1:s(i) - 1), g, 
+	    		  str(s(i) + length (flds{j}) + 1:end));
+	    break;
+	  endif
+	endfor
+      endif
+    endif
+  endfor
+
+  ## Prepend @ to things  things like _0^x or _{-100}^{100} for alignment
+  ## But need to put the shorter of the two arguments first. Carful of 
+  ## nested {} and unprinted characters when defining shortest.. Don't 
+  ## have to worry about things like ^\theta as they are already converted to
+  ## ^{/Symbol q}.
+
+  ## FIXME.. This is a mess... Is it worth it just for a "@" character?
+
+  [s, m] = regexp(str,'[_\^]','start','matches');
+  i = 1;
+  p = 0;
+  while (i < length (s))
+    if (i < length(s))
+      if (str(s(i) + p + 1) == "{")
+	s1 = strfind(str(s(i) + p + 2:end),'{');
+	si = 1;
+	l1 = strfind(str(s(i) + p + 1:end),'}');
+        li = 1;
+	while (li <= length (l1) && si <= length (s1))
+          if (l1(li) < s1(si))
+	    if (li == si)
+	      break;
+	    endif
+	    li++;
+	  else
+	    si++;
+	  endif
+	endwhile
+	l1 = l1 (min (length(l1), si));
+        if (s(i) + l1 + 1 == s(i+1))
+	  if (str(s(i + 1) + p + 1) == "{")
+	    s2 = strfind(str(s(i + 1) + p + 2:end),'{');
+	    si = 1;
+	    l2 = strfind(str(s(i + 1) + p + 1:end),'}');
+            li = 1;
+	    while (li <= length (l2) && si <= length (s2))
+              if (l2(li) < s2(si))
+		if (li == si)
+		  break;
+		endif
+		li++;
+	      else
+		si++;
+	      endif
+	    endwhile
+	    l2 = l2 (min (length(l2), si));
+	    if (length_string (str(s(i)+p+2:s(i)+p+l1-1)) <=
+		length_string(str(s(i+1)+p+2:s(i+1)+p+l2-1)))
+	      ## shortest already first!
+	      str = strcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
+	    else
+	      ## Have to swap sub/super-script to get shortest first
+	      str = strcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+l2),
+			    str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+l2+1:end));
+	    endif
+	  else
+	    ## Have to swap sub/super-script to get shortest first
+	    str = strcat (str(1:s(i)+p-1), "@", str(s(i+1)+p:s(i+1)+p+1),
+			  str(s(i)+p:s(i)+p+l1), str(s(i+1)+p+2:end));
+	  endif
+          i += 2;
+	  p ++;
+	else
+	  i++;
+	endif
+      else
+	if (s(i+1) == s(i) + 2)
+	  ## shortest already first!
+	  str = strcat (str(1:s(i)+p-1), "@", str(s(i)+p:end));
+	  p ++;
+          i += 2;
+	else
+	  i ++;
+	endif
+      endif
+    else
+      i ++;
+    endif
+  endwhile
+
+endfunction
+
+function l = length_string (s)
+  l = length (s) - length (strfind(s,'{')) - length (strfind(s,'}'));
+  m = regexp (s, '/([\w\-]+|[\w\-]+=\d+)', 'matches');
+  if (!isempty (m))
+    l = l - sum (cellfun (@length, m));
+  endif
+endfunction
+
+function sym = __setup_sym_table__ ()
+  ## Setup the translation table for TeX to gnuplot enhanced mode.
+  sym.forall = '{/Symbol \042}';
+  sym.exists = '{/Symbol \044}';
+  sym.ni = '{/Symbol \047}';
+  sym.cong = '{/Symbol \100}';
+  sym.Delta = '{/Symbol D}';
+  sym.Phi = '{/Symbol F}';
+  sym.Gamma = '/Symbol G}';
+  sym.vartheta = '{\Symbol J}';
+  sym.Lambda = '{/Symbol L}';
+  sym.Pi = '{/Symbol P}';
+  sym.Theta = '{/Symbol Q}';
+  sym.Sigma = '{/Symbol S}';
+  sym.varsigma = '{/Symbol V}';
+  sym.Omega = '{/Symbol O}';
+  sym.Xi = '{/Symbol X}';
+  sym.Psi = '{/Symbol Y}';
+  sym.perp = '{/Symbol \136}';
+  sym.alpha = '{/Symbol a}';
+  sym.beta = '{/Symbol b}';
+  sym.chi = '{/Symbol c}';
+  sym.delta = '{/Symbol d}';
+  sym.epsilon = '{/Symbol e}';
+  sym.phi = '{/Symbol f}';
+  sym.gamma = '/Symbol g}';
+  sym.eta = '{/Symbol h}';
+  sym.iota = '{/Symbol i}';
+  sym.kappa = '{/Symbol k}';
+  sym.lambda = '{/Symbol l}';
+  sym.mu = '{/Symbol m}';
+  sym.nu = '{/Symbol n}';
+  sym.o =  '{/Symbol o}';
+  sym.pi = '{/Symbol p}';
+  sym.theta = '{/Symbol q}';
+  sym.rho = '{/Symbol r}';
+  sym.sigma = '{/Symbol s}';
+  sym.tau = '{/Symbol t}';
+  sym.upsilon = '{/Symbol u}';
+  sym.varpi = '{/Symbol v}';
+  sym.omega = '{/Symbol w}';
+  sym.xi = '{/Symbol x}';
+  sym.psi = '{/Symbol y}';
+  sym.zeta = '{/Symbol z}';
+  sym.sim = '{/Symbol \176}';
+  sym.Upsilon = '{/Symbol \241}';
+  sym.prime = '{/Symbol \242}';
+  sym.leq = '{/Symbol \243}';
+  sym.infty = '{/Symbol \245}';
+  sym.clubsuit = '{/Symbol \247}';
+  sym.diamondsuit = '{/Symbol \250}';
+  sym.heartsuit = '{/Symbol \251}';
+  sym.spadesuit = '{/Symbol \252}';
+  sym.leftrightarrow = '{/Symbol \253}';
+  sym.leftarrow = '{/Symbol \254}';
+  sym.uparrow = '{/Symbol \255}';
+  sym.rightarrow = '{/Symbol \256}';
+  sym.downarrow = '{/Symbol \257}';
+  sym.circ = '{/Symbol \260}';
+  sym.pm = '{/Symbol \261}';
+  sym.geq = '{/Symbol \263}';
+  sym.times = '{/Symbol \264}';
+  sym.propto = '{/Symbol \265}';
+  sym.partial = '{/Symbol \266}';
+  sym.bullet = '{/Symbol \267}';
+  sym.div = '{/Symbol \270}';
+  sym.neq = '{/Symbol \271}';
+  sym.equiv = '{/Symbol \272}';
+  sym.approx = '{/Symbol \273}';
+  sym.ldots = '{/Symbol \274}';
+  sym.mid = '{/Symbol \275}';
+  sym.aleph = '{/Symbol \300}';
+  sym.Im = '{/Symbol \301}';
+  sym.Re = '{/Symbol \302}';
+  sym.wp = '{/Symbol \303}';
+  sym.otimes = '{/Symbol \304}';
+  sym.oplus = '{/Symbol \305}';
+  sym.oslash = '{/Symbol \306}';
+  sym.cap = '{/Symbol \307}';
+  sym.cup = '{/Symbol \310}';
+  sym.supset = '{/Symbol \311}';
+  sym.supseteq = '{/Symbol \312}';
+  sym.subset = '{/Symbol \314}';
+  sym.subseteq = '{/Symbol \315}';
+  sym.in = '{/Symbol \316}';
+  sym.langle = '{/Symbol \320}';
+  sym.rangle = '{/Symbol \320}';
+  sym.nabla = '{/Symbol \321}';
+  sym.surd = '{/Symbol \326}';
+  sym.cdot = '{/Symbol \327}';
+  sym.neg = '{/Symbol \330}';
+  sym.wedge = '{/Symbol \331}';
+  sym.vee = '{/Symbol \332}';
+  sym.copyright = '{/Symbol \343}';
+  sym.rfloor = '{/Symbol \353}';
+  sym.lceil  = '{/Symbol \351}';
+  sym.lfloor = '{/Symbol \373}';
+  sym.rceil  = '{/Symbol \371}';
+  sym.int = '{/Symbol \362}';
+endfunction
+
+function [pos, orient, sz, origin, mirr] = gnuplot_postion_colorbox (pos, cbox)
+  ## This is an emprically derived function that 
+
+  if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5))
+    scl = pos([2,4]);
+  else
+    scl = pos([1,3]);
+  endif
+
+  if (length(cbox) > 7 && strncmp (cbox(end-6:end), "outside", 7))
+    scl(2) -= 0.2 * scl(2);
+    if (strncmp (cbox, "west", 4) || strncmp (cbox, "south", 5))
+      scl(1) += 0.2 * scl(2);
+    endif
+  endif
+
+  switch (cbox)
+    case "northoutside"
+      sz = pos(3:4) - 0.08;
+      origin = [0.05, 0.06] + [0.00, 0.88] .* sz + pos(1:2);
+      mirr = true;
+      orient = "horizontal";
+    case "north"
+      sz = pos(3:4) - 0.16;
+      origin = [0.09, 0.09] + [0.00, 0.94] .* sz + pos(1:2);
+      mirr = false;
+      orient = "horizontal";
+    case "southoutside"
+      sz = pos(3:4) - 0.08;
+      origin = [0.05, 0.06] + [0.00, 0.00] .* sz + pos(1:2);
+      mirr = false;
+      orient = "horizontal";
+    case "south"
+      sz = pos(3:4) - 0.16;
+      origin = [0.08, 0.09] + [0.03, 0.05] .* sz + pos(1:2);
+      mirr = true;
+      orient = "horizontal";
+    case "eastoutside"
+      sz = pos(3:4) - 0.08;
+      origin = [0.00, 0.06] + [0.94, 0.00] .* sz + pos(1:2);
+      mirr = false;
+      orient = "vertical";
+    case "east"
+      sz = pos(3:4) - 0.16;
+      origin = [0.09, 0.10] + [0.91, 0.01] .* sz + pos(1:2);
+      mirr = true;
+      orient = "vertical";
+    case "westoutside"
+      sz = pos(3:4) - 0.08;
+      origin = [0.00, 0.06] + [0.06, 0.00] .* sz + pos(1:2);
+      mirr = true;
+      orient = "vertical";
+    case "west"
+      sz = pos(3:4) - 0.16;
+      origin = [0.06, 0.09] + [0.04, 0.03] .* sz + pos(1:2);
+      mirr = false;
+      orient = "vertical";
+  endswitch
+
+  if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5))
+    sz = sz .* [1, 0.07];
+    pos([2,4]) = scl;
+  else
+    sz = sz .* [0.07, 1];
+    pos([1,3]) = scl;
+  endif
+
+endfunction
--- a/scripts/plot/__go_draw_figure__.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/__go_draw_figure__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -20,9 +20,9 @@
 
 ## Author: jwe
 
-function __go_draw_figure__ (f, plot_stream)
+function __go_draw_figure__ (f, plot_stream, enhanced)
 
-  if (nargin == 2)
+  if (nargin == 3)
     if (strcmp (f.type, "figure"))
 
       ## Set figure properties here?
@@ -52,8 +52,7 @@
 	  obj = get (kids(i));
 	  switch (obj.type)
 	    case "axes"
-	      __go_draw_axes__ (kids(i), plot_stream);
-
+	      __go_draw_axes__(kids (i), plot_stream, enhanced);
 	    otherwise
 	      error ("__go_draw_figure__: unknown object class, %s",
 		     obj.type);
--- a/scripts/plot/__patch__.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/__patch__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -127,11 +127,11 @@
         idx(t1,i) = idx(t2,i);
       endif
     endfor
-    x = vert(:,1)(idx);
-    y = vert(:,2)(idx);
+    x = reshape (vert(:,1)(idx), size (idx));
+    y = reshape (vert(:,2)(idx), size (idx));
     if (size(vert,2) > 2)
       have_z = true;
-      z = vert(:,3)(idx);
+      z = reshape (vert(:,3)(idx), size (idx));
     endif
   else
     error ("patch: not supported");
@@ -159,6 +159,7 @@
 	clim = get(ax, "clim");
 	if (c(1) < clim(1))
           set (ax, "clim", [c(1), clim(2)])
+	  clim(1) = c(1);
 	endif
 	if (c(1) > clim(2))
           set (ax, "clim", [clim(1), c(1)])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/__quiver__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,222 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## Undocumented internal function
+
+function hlist = __quiver__ (varargin)
+  h = varargin {1};
+  is3d = varargin {2};
+
+  s = 1;
+  arrowsize = 0.33;
+
+  firstnonnumeric = Inf;
+  for i = 3:nargin
+    if (! isnumeric (varargin {i}))
+      firstnonnumeric = i;
+      break;
+    endif
+  endfor
+
+  ioff = 3;
+  if (nargin < (6 + is3d) || firstnonnumeric < (6 + is3d))
+    u = varargin{ioff++};
+    v = varargin{ioff++};
+    if (is3d)
+      w = varargin{ioff++}
+      [x, y, z] = meshgrid (1:size(u,1), 1:size(u,2), 1:max(size(w)));
+    else
+      [x, y] = meshgrid (1:size(u,1), 1:size(u,2));
+    endif
+    if (nargin >= ioff && isnumeric (varargin{ioff}) && 
+	isscalar (varargin{ioff}))
+      s = varargin{ioff++};
+    endif
+  else
+    x = varargin{ioff++};
+    y = varargin{ioff++};
+    if (is3d)
+      z = varargin{ioff++};
+    endif
+    u = varargin{ioff++};
+    v = varargin{ioff++}; 
+    if (is3d)
+      w = varargin{ioff++};
+      if (isvector(x) && isvector(y) && isvector(z) && 
+	  (!isvector (u) || !isvector (v) || !isvector(w)))
+	[x, y, z] = meshgrid (x, y, z);
+      endif
+    else
+      if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v)))
+	[x, y] = meshgrid (x, y);
+      endif
+    endif
+    if (nargin >= ioff && isnumeric (varargin{ioff}) && 
+	isscalar (varargin{ioff}))
+      s = varargin{ioff++};
+    endif
+  endif
+
+  have_filled = false;
+  have_line_spec = false;
+  while (ioff <= nargin)
+    arg = varargin {ioff++};
+    if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
+      have_filled = true;
+    elseif ((isstr (arg) || iscell (arg))
+	    && ! have_line_spec)
+      [linespec, valid] = __pltopt__ ("quiver", arg, false);
+      if (valid)
+	have_line_spec = true;
+	if (strncmp (linespec.linestyle, "none", 4))
+	  linespec.linestyle = "-";
+	endif
+      else
+	error ("quiver: invalid linespec");
+      endif
+    else
+      error ("quiver: unrecognized argument");
+    endif
+  endwhile
+
+  if (s)
+    ## Scale the arrows to fit in the grid
+    dx = (max(x(:)) - min(x(:))) ./ size (x, 2);
+    dy = (max(y(:)) - min(y(:))) ./ size (y, 1);
+    if (is3d)
+      ## What should this be divided by? The below seems right
+      dz = (max(z(:)) - min(z(:))) ./ max (size (z));
+      len = max (sqrt (u(:).^2 + dy(:).^2) + dz(:).^2);
+    else
+      len = max (sqrt (u(:).^2 + dy(:).^2));
+      dz = 0;
+    endif
+    if (len > 0)
+      s = s / sqrt (2) * sqrt (dx.^2 + dy.^2 + dz.^2) / len; 
+      u = s * u;
+      v = s * v;
+      if (is3d)
+	w = s*w;
+      endif
+    endif
+  endif
+
+  x = x(:);
+  y = y(:);
+  xend = x + u(:);
+  yend = y + v(:);
+  if (is3d)
+    z = z(:);
+    zend = z + w(:);
+  endif
+
+  hstate = get (h, "nextplot");
+  unwind_protect
+    if (have_line_spec)
+      if (is3d)
+	h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
+		    [y.'; yend.'; NaN(1, length (y))](:),
+		    [z.'; zend.'; NaN(1, length (z))](:),
+		    "linestyle", linespec.linestyle);
+      else
+	h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
+		   [y.'; yend.'; NaN(1, length (y))](:),
+		   "linestyle", linespec.linestyle);
+      endif
+    else
+      if (is3d)
+	h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
+		    [y.'; yend.'; NaN(1, length (y))](:),
+		    [z.'; zend.'; NaN(1, length (z))](:));
+      else
+	h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
+		   [y.'; yend.'; NaN(1, length (y))](:));
+      endif
+    endif
+    hold on;
+
+    xtmp = x + u(:) .* (1 - arrowsize);
+    ytmp = y + v(:) .* (1 - arrowsize);
+    xarrw1 = xtmp + (y - yend) * arrowsize / 3;
+    xarrw2 = xtmp - (y - yend) * arrowsize / 3;
+    yarrw1 = ytmp - (x - xend) * arrowsize / 3;
+    yarrw2 = ytmp + (x - xend) * arrowsize / 3;
+    if (is3d)
+      zarrw1 = zarrw2 = zend - w(:) * arrowsize / 3;
+    endif
+
+    if (have_line_spec)
+      if (isfield (linespec, "marker") && 
+	! strncmp (linespec.marker, "none", 4))
+	if (is3d)
+	  h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		      [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+		      [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
+		      "linestyle", "none");
+	else
+	  h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		     [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+		     "linestyle", "none");
+	endif
+      else
+	if (is3d)
+	  h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		      [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+		      [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
+		      "linestyle", linespec.linestyle);
+	else
+	  h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		     [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+		     "linestyle", linespec.linestyle);
+	endif
+      endif
+    elseif (is3d)
+      h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		  [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+		  [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:));
+    else
+      h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+		 [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
+    endif
+
+    if (! have_line_spec || (isfield (linespec, "marker") && 
+			     strncmp (linespec.marker, "none", 4)))
+      if (is3d)
+	h3 = plot3 (x, y, z, "linestyle", "none", "marker", "none");
+      else
+	h3 = plot (x, y, "linestyle", "none", "marker", "none");
+      endif
+    else
+      if (is3d)
+	h3 = plot3 (x, y, z, "linestyle", "none", "marker", linespec.marker);
+      else
+
+	h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker);
+      endif
+    endif
+    if (have_filled)
+      ## FIXME gnuplot doesn't respect the markerfacecolor field
+      set(h3, "markerfacecolor", get (h1, "color")); 
+    endif
+  unwind_protect_cleanup
+    set (h, "nextplot", hstate);
+  end_unwind_protect
+
+  hlist = [h1; h2; h3];
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/__scatter__.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,124 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## Undocumented internal function.
+
+function h = __scatter__ (varargin)
+  h = varargin {1};
+  nd = varargin {2};
+  fcn = varargin {3};
+  x = varargin {4}(:);
+  y = varargin {5}(:);
+  istart = 6;
+  if (nd == 3)
+    z = varargin {6}(:);
+    istart = 7;
+  else
+    z = zeros (length(x), 0);
+  endif
+
+  firstnonnumeric = Inf;
+  for i = istart:nargin
+    if (! isnumeric (varargin {i}))
+      firstnonnumeric = i;
+      break;
+    endif
+  endfor
+
+  if (firstnonnumeric > istart)
+    s = varargin {istart};
+    if (isempty (s))
+      s = 8;
+    endif
+  else
+    s = 8;
+  endif
+  ## Note markersize is in points^2 for 2D and points for 3D, and 
+  ## the below is an approximation, that is empircally visually correct.
+  if (nd == 2)
+    s = sqrt (s) / 2;
+  else
+    s = s / 4;
+  endif
+
+  if (istart < nargin && firstnonnumeric > istart + 1)
+    c = varargin {istart + 1};
+    if (isvector (c))
+      c = c(:);
+    endif
+  elseif (firstnonnumeric == istart + 1 && ischar (varargin {istart + 1}))
+    c = varargin{istart + 1};
+    firstnonnumeric++;
+  else
+    c = 1 : length(x);
+  endif
+
+  newargs = {};
+  filled = false;
+  have_marker = false;
+  marker = "o";
+  iarg = firstnonnumeric;
+  while (iarg <= nargin)
+    arg = varargin {iarg++};
+    if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
+      filled = true;
+    elseif ((isstr (arg) || iscell (arg)) && ! have_marker)
+      [linespec, valid] = __pltopt__ ("scatter", arg, false);
+      if (valid)
+	have_marker = true;
+	marker = linespec.marker;
+	if (strncmp (marker, "none", 4))
+	  marker = "o";
+	endif
+      else
+	error ("scatter: invalid linespec");
+      endif
+    else
+      newargs{end+1} = arg;
+      if (iarg <= nargin)
+	newargs{end+1} = varagin{iarg++};
+      endif
+    endif
+  endwhile
+
+  if (ischar (c))
+    h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor',
+	      'none', 'edgecolor', c, 'marker', marker, 
+	      'markersize', s, 'linestyle', 'none');
+    if (filled)
+      set(h, 'markerfacecolor', c); 
+    endif
+  else
+    h = patch('faces', [1:length(x)].', 'vertices', [x, y, z], 'facecolor',
+	      'none', 'edgecolor', 'flat', 'cdata', c, 'marker', marker, 
+	      'markersize', s, 'linestyle', 'none');
+    if (filled)
+      set(h, 'markerfacecolor', 'flat'); 
+    endif
+    ax = get (h, "parent");
+    clim = get (ax, "clim");
+    if (min(c(:)) < clim(1))
+      clim(1) = min(c(:));
+      set (ax, "clim", clim);
+    endif
+    if (max(c(:)) > clim(2))
+      set (ax, "clim", [clim(1), max(c(:))]);
+    endif
+  endif
+
+endfunction
--- a/scripts/plot/axis.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/axis.m	Mon Nov 26 20:42:11 2007 +0000
@@ -29,7 +29,6 @@
 ## Without any arguments, @code{axis} turns autoscaling on.  
 ##
 ## With one output argument, @code{x=axis} returns the current axes 
-## (this is not yet implemented for automatic axes).
 ##
 ## The vector argument specifying limits is optional, and additional
 ## string arguments may be used to specify various axis properties.  For
@@ -109,17 +108,47 @@
 ## Restore y-axis, so higher values are nearer the top. 
 ## @end table
 ## 
+## If an axes handle is passed as the first argument, then operate on
+## this axes rather than the current axes.
 ## @end deftypefn
 
 ## Author: jwe
 
 ## PKG_ADD: mark_as_command axis
 
-function curr_axis = axis (ax, varargin)
+function varargout = axis (varargin)
 
-  ca = gca ();
+  if (nargin > 0 && isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin{1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("axis: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      varargout = cell (max (nargin == 1, nargout), 1);
+      if (isempty (varargout))
+	__axis__ (h, varargin{2:end});
+      else
+        [varargout{:}] = __axis__ (h, varargin{2:end});
+      endif
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    varargout = cell (max (nargin == 0, nargout), 1);
+    if (isempty (varargout))
+      __axis__ (gca (), varargin{:});
+    else
+      [varargout{:}] = __axis__ (gca (), varargin{:});
+    endif
+  endif
 
-  if (nargin == 0)
+endfunction
+
+function curr_axis = __axis__ (ca, ax, varargin)
+
+  if (nargin == 1)
     if (nargout == 0)
       set (ca, "xlimmode", "auto", "ylimmode", "auto", "zlimmode", "auto");
     else
@@ -254,8 +283,8 @@
     error ("axis: expecting no args, or a vector with 2, 4, or 6 elements");
   endif
 
-  if (nargin > 1)
-    axis (varargin{:});
+  if (nargin > 2)
+    __axis__ (ca, varargin{:});
   endif
 
 endfunction
--- a/scripts/plot/bar.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/bar.m	Mon Nov 26 20:42:11 2007 +0000
@@ -23,6 +23,7 @@
 ## @deftypefnx {Function File} {} bar (@var{x}, @var{y}, @var{w})
 ## @deftypefnx {Function File} {} bar (@var{x}, @var{y}, @var{w}, @var{style})
 ## @deftypefnx {Function File} {@var{h} =} bar (@dots{}, @var{prop}, @var{val})
+## @deftypefnx {Function File} {} bar (@var{h}, @dots{})
 ## Produce a bar graph from two vectors of x-y data.
 ##
 ## If only one argument is given, it is taken as a vector of y-values
@@ -37,6 +38,7 @@
 ## or @code{"stacked"}.
 ##
 ## The optional return value @var{h} provides a handle to the patch object.
+## Whereas the option input handle @var{h} allows an axis handle to be passed.
 ## Properties of the patch graphics object can be changed using 
 ## @var{prop}, @var{val} pairs.
 ##
--- a/scripts/plot/barh.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/barh.m	Mon Nov 26 20:42:11 2007 +0000
@@ -22,6 +22,7 @@
 ## @deftypefnx {Function File} {} barh (@var{x}, @var{y}, @var{w})
 ## @deftypefnx {Function File} {} barh (@var{x}, @var{y}, @var{w}, @var{style})
 ## @deftypefnx {Function File} {@var{h} =} barh (@dots{}, @var{prop}, @var{val})
+## @deftypefnx {Function File} {} barh (@var{h}, @dots{})
 ## Produce a horizontal bar graph from two vectors of x-y data.
 ##
 ## If only one argument is given, it is taken as a vector of y-values
@@ -36,6 +37,7 @@
 ## or @code{"stacked"}.
 ##
 ## The optional return value @var{h} provides a handle to the patch object.
+## Whereas the option input handle @var{h} allows an axis handle to be passed.
 ## Properties of the patch graphics object can be changed using 
 ## @var{prop}, @var{val} pairs.
 ##
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/caxis.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,102 @@
+## Copyright (C)  2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} caxis (@var{limits})
+## @deftypefnx {Function File} {} caxis (@var{h}, @dots{})
+## Set color axis limits for plots.
+##
+## The argument @var{limits} should be a 2 element vector specifying the 
+## lower and upper limits to assign to the first and last value in the
+## colormap. Values outside this range are clamped to the first and last
+## colormap entries. 
+##
+## If @var{limits} is 'auto', then automatic colormap scaling is applied,
+## whereas if @var{limits} is 'manual' the colormap scaling is set to manual.
+##
+## Called without any arguments to current color axis limits are returned.
+##
+## If an axes handle is passed as the first argument, then operate on
+## this axes rather than the current axes.
+## @end deftypefn
+
+## PKG_ADD: mark_as_command caxis
+
+function varargout = caxis (varargin)
+
+  if (nargin > 0 && isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin{1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("caxis: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      varargout = cell (max (nargin == 1, nargout), 1);
+      if (isempty (varargout))
+	__caxis__ (h, varargin{2:end});
+      else
+        [varargout{:}] = __caxis__ (h, varargin{2:end});
+      endif
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    varargout = cell (max (nargin == 0, nargout), 1);
+    if (isempty (varargout))
+      __caxis__ (gca (), varargin{:});
+    else
+      [varargout{:}] = __caxis__ (gca (), varargin{:});
+    endif
+  endif
+
+endfunction
+
+function [cmin, cmax] = __caxis__ (ca, ax, varargin)
+
+  if (nargin == 1)
+    cmin = get (ca, "clim");
+    if (nargout > 1)
+      cmax = cmin(2);
+      cmin = cmin(1);
+    endif
+  elseif (ischar (ax))
+    ax = tolower (ax);
+    if (strcmp (ax, "auto"))
+      set (ca, "climmode", "auto");
+    elseif (strcmp (ax, "manual"))
+      set (ca, "climmode", "manual");
+    endif
+  elseif (isvector (ax))
+    len = length (ax);
+
+    if (len != 2)
+      error ("caxis: expecting vector with 2 elements");
+    endif
+
+    set (ca, "clim", [ax(1), ax(2)]);
+  else
+    error ("caxis: expecting no args, a string or a 2 element vector");
+  endif
+
+  if (nargin > 2)
+    __caxis__ (ca, varargin{:})'
+  endif
+
+endfunction
+      
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/colorbar.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,149 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} colorbar (@var{s})
+## @deftypefnx {Function File} {} colorbar ('peer', @var{h}, @dots{})
+## Adds a colorbar to the current axes. Valid values for @var{s} are
+##
+## @table @asis
+## @item 'EastOutside'
+## Place the colorbar outside the plot to the right. This is the default.
+## @item 'East'
+## Place the colorbar inside the plot to the right.
+## @item 'WestOutside'
+## Place the colorbar outside the plot to the left.
+## @item 'West'
+## Place the colorbar inside the plot to the left.
+## @item 'NorthOutside'
+## Place the colorbar above the plot.
+## @item 'North'
+## Place the colorbar at the top of the plot.
+## @item 'SouthOutside'
+## Place the colorbar under the plot.
+## @item 'South'
+## Place the colorbar at the bottom of the plot.
+## @item 'Off', 'None'
+## Remove any existing colorbar from the plot.
+## @end table
+##
+## If the argument 'peer' is given, then the following argument is treated a
+## the axes handle on which to add the colorbar.
+## @end deftypefn
+
+
+## PKG_ADD: mark_as_command colorbar
+
+function colorbar (varargin)
+  
+  if (nargin > 0 && strcmpi(varargin{1}, "peer"))
+    if (nargin > 1)
+      ax = varargin{2};
+      if (!isscalar (ax) || !ishandle (ax) || 
+	  strcmp (get (ax, "type"), "axes"))
+	error ("colorbar: expecting an axes handle following 'peer'");
+      endif
+    else
+      error ("colorbar: misisng axes handle after 'peer'");
+    endif
+  else
+    ax = gca ();
+  endif
+
+  pos = "eastoutside";
+  for i = 1 : length (varargin)
+    arg = varargin {i};
+    if (length(arg) < 1)
+      pos = "eastoutside";
+    elseif (ischar (arg))
+      arg = tolower (arg);
+      if (strcmp (arg, "off") || strcmp (arg, "none"))
+	pos = "none";
+      elseif (strcmp (arg, "north") || strcmp (arg, "south") ||
+	      strcmp (arg, "east") || strcmp (arg, "west") ||
+	      strcmp (arg, "northoutside") || strcmp (arg, "southoutside") ||
+	      strcmp (arg, "eastoutside") || strcmp (arg, "westoutside"))
+	pos = arg;
+      else
+	error ("colorbar: unrecognized position argument");
+      endif
+    else
+      error ("colorbar: expecting string arguments");
+    endif
+  endfor
+
+  set (ax, "__colorbar__", pos);
+endfunction
+
+
+%!demo
+%! hold off;
+%! close all;
+%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); 
+%! imagesc(x)
+%! colorbar();
+
+%!demo
+%! hold off;
+%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); 
+%! imagesc(x)
+%! colorbar("westoutside");
+
+%!demo
+%! hold off;
+%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); 
+%! imagesc(x)
+%! colorbar("northoutside");
+
+%!demo
+%! hold off;
+%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); 
+%! imagesc(x)
+%! colorbar("southoutside");
+
+%!demo
+%! hold off;
+%! subplot(2,2,1)
+%! contour(peaks())
+%! colorbar("east");
+%! subplot(2,2,2)
+%! contour(peaks())
+%! colorbar("west");
+%! subplot(2,2,3)
+%! contour(peaks())
+%! colorbar("north");
+%! subplot(2,2,4)
+%! contour(peaks())
+%! colorbar("south");
+
+%!demo
+%! hold off;
+%! n = 64; x = kron (1:n,ones(n,1)); x = abs(x - x.'); 
+%! subplot(2,2,1)
+%! imagesc(x)
+%! colorbar();
+%! subplot(2,2,2)
+%! imagesc(x)
+%! colorbar("westoutside");
+%! subplot(2,2,3)
+%! imagesc(x)
+%! colorbar("northoutside");
+%! subplot(2,2,4)
+%! imagesc(x)
+%! colorbar("southoutside");
+
--- a/scripts/plot/contour.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/contour.m	Mon Nov 26 20:42:11 2007 +0000
@@ -69,7 +69,7 @@
 
   if (nargout > 0)
     c = ctmp;
-    h = htmp
+    h = htmp;
   endif
 
 endfunction
--- a/scripts/plot/drawnow.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/drawnow.m	Mon Nov 26 20:42:11 2007 +0000
@@ -45,12 +45,12 @@
 	plot_stream = [];
 	fid = [];
 	unwind_protect
-	  plot_stream = open_gnuplot_stream ([], term, file);
-	  __go_draw_figure__ (f, plot_stream);
+	  [plot_stream, enhanced] = open_gnuplot_stream ([], term, file);
+	  __go_draw_figure__ (f, plot_stream, enhanced);	
 	  if (nargin == 3)
 	    fid = fopen (debug_file, "wb");
-	    init_plot_stream (fid, [], term, file);
-	    __go_draw_figure__ (f, fid);
+	    enhanced = init_plot_stream (fid, [], term, file);
+	    __go_draw_figure__ (f, fid, enhanced);
 	  endif
 	unwind_protect_cleanup
 	  if (! isempty (plot_stream))
@@ -72,12 +72,16 @@
 	    figure_is_visible = strcmp (f.visible, "on");
 	    if (figure_is_visible)
 	      if (isempty (plot_stream))
-		plot_stream = open_gnuplot_stream (h);
+		[plot_stream, enhanced] = open_gnuplot_stream (h);
+		set (h, "__enhanced__", enhanced);
+	      else
+		enhanced = f.__enhanced__;
 	      endif
-	      __go_draw_figure__ (f, plot_stream);
+	      __go_draw_figure__ (f, plot_stream, enhanced);
 	    elseif (! isempty (plot_stream))
 	      pclose (plot_stream);
 	      set (h, "__plot_stream__", []);
+	      set (h, "__enhanced__", false);
 	    endif
 	    set (h, "__modified__", false);
 	  endif
@@ -96,7 +100,7 @@
 
 endfunction
 
-function plot_stream = open_gnuplot_stream (h, varargin)
+function [plot_stream, enhanced] = open_gnuplot_stream (h, varargin)
 
   ## If drawnow is cleared, it is possible to register __go_close_all__
   ## more than once, but that is not fatal.
@@ -114,7 +118,7 @@
       set (h, "__plot_stream__", plot_stream);
     endif
 
-    init_plot_stream (plot_stream, h, varargin{:})
+    enhanced = init_plot_stream (plot_stream, h, varargin{:});
 
     if (isempty (__go_close_all_registered__))
       atexit ("__go_close_all__");
@@ -125,11 +129,16 @@
 
 endfunction
 
-function init_plot_stream (plot_stream, h, term, file)
+function enhanced = init_plot_stream (plot_stream, h, term, file)
 
   if (nargin == 4)
+    enhanced = enhanced_term (term);
     if (! isempty (term))
-      fprintf (plot_stream, "set terminal %s;\n", term);
+      if (enhanced)
+	fprintf (plot_stream, "set terminal %s enhanced;\n", term);
+      else
+	fprintf (plot_stream, "set terminal %s;\n", term);
+      endif
     endif
     if (! isempty (file))
       fprintf (plot_stream, "set output \"%s\";\n", file);
@@ -153,24 +162,62 @@
       endif
     endif
 
+    enhanced = enhanced_term (term);
+    if (enhanced)
+      enh_str = "enhanced";
+    else
+      enh_str = "";
+    endif
+
     ## If no 'h' (why not?) then open the terminal as Figure 0.
     if (isempty (h))
       h = 0;
     endif
 
     if (strcmp (term, "x11"))
-      fprintf (plot_stream, "set terminal x11 title \"Figure %d\"\n", h);
+      fprintf (plot_stream, "set terminal x11 %s title \"Figure %d\"\n",
+	       enh_str, h);
     elseif (strcmp (term, "aqua"))
       ## Aqua doesn't understand the 'title' option despite what the
       ## gnuplot 4.2 documentation says.
-      fprintf (plot_stream, "set terminal aqua %d\n", h);
+      fprintf (plot_stream, "set terminal aqua %d %s\n", h, enh_str);
     elseif (strcmp (term, "wxt"))
-      fprintf (plot_stream, "set terminal wxt title \"Figure %d\"\n", h);
+      fprintf (plot_stream, "set terminal wxt %s title \"Figure %d\"\n", 
+	       enh_str, h);
+
+    elseif (enhanced)
+      fprintf (plot_stream "set terminal %s %s\n", term, enh_str);
     endif
     ## gnuplot will pick up the GNUTERM environment variable itself
     ## so no need to set the terminal type if not also setting the
-    ## figure title.
+    ## figure title or enhanced mode.
 
   endif
 
 endfunction
+
+function have_enhanced = enhanced_term (term)
+  persistent enhanced_terminals;
+
+  if (isempty (enhanced_terminals))
+    ## Don't include pstex, pslatex or epslatex here as the TeX commands
+    ## should not be interpreted in that case.
+    if (compare_versions (__gnuplot_version__ (), "4.0", ">"))
+      enhanced_terminals = {"aqua", "dumb", "png", "jpeg", "gif", "pm", ...
+	                    "windows", "wxt", "svg", "postscript", "x11"};
+    else 
+      enhanced_terminals = {"x11", "postscript"};
+    endif
+  endif
+
+  term = tolower (term);
+
+  have_enhanced = false;
+  for i = 1 : length (enhanced_terminals)
+    t = enhanced_terminals{i};
+    if (strncmp (term, t, min (length (term), length(t))))
+      have_enhanced = true;
+      break;
+    endif
+  endfor
+endfunction
--- a/scripts/plot/hist.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/hist.m	Mon Nov 26 20:42:11 2007 +0000
@@ -91,6 +91,10 @@
     endif
   endif
 
+  ## Avoid issues with integer types for x and y
+  x = double (x);
+  y = double (y);
+
   cutoff = (x(1:end-1,:) + x(2:end,:)) / 2;
   n = rows (x);
   if (n < 30 && columns (x) == 1)
--- a/scripts/plot/print.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/print.m	Mon Nov 26 20:42:11 2007 +0000
@@ -257,7 +257,6 @@
       else
 	options = strcat (orientation, " ");
       endif
-      options = strcat (options, "enhanced ");
       termn = "postscript";
     endif
     
--- a/scripts/plot/quiver.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/quiver.m	Mon Nov 26 20:42:11 2007 +0000
@@ -69,13 +69,13 @@
     unwind_protect
       axes (h);
       newplot ();
-      tmp = __quiver__ (h, varargin{2:end});
+      tmp = __quiver__ (h, 0, varargin{2:end});
     unwind_protect_cleanup
       axes (oldh);
     end_unwind_protect
   else
     newplot ();
-    tmp = __quiver__ (gca (), varargin{:});
+    tmp = __quiver__ (gca (), 0, varargin{:});
   endif
 
   if (nargout > 0)
@@ -84,138 +84,6 @@
 
 endfunction
 
-function hlist = __quiver__ (varargin)
-  h = varargin {1};
-
-  s = 1;
-  arrowsize = 0.33;
-
-  firstnonnumeric = Inf;
-  for i = 2:nargin
-    if (! isnumeric (varargin {i}))
-      firstnonnumeric = i;
-      break;
-    endif
-  endfor
-
-  if (nargin < 5 || firstnonnumeric < 5)
-    u = varargin{2};
-    v = varargin{3};
-    if (nargin == 4 && isnumeric (varargin{4}) && isscalar (varargin{4}))
-      s = varargin{4};
-      iarg = 5;
-    else
-      iarg = 4;
-    endif
-    [x, y] = meshgrid (1:size(u,1), 1:size(u,2));
-  else
-    x = varargin{2};
-    y = varargin{3};
-    u = varargin{4};
-    v = varargin{5};
-    if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v)))
-      [x, y] = meshgrid (x, y);
-    endif
-    if (nargin > 5 && isnumeric (varargin{6}) && isscalar (varargin{6}))
-      s = varargin{6};
-      iarg = 7;
-    else
-      iarg = 6;
-    endif
-  endif
-
-  have_filled = false;
-  have_line_spec = false;
-  while (iarg <= nargin)
-    arg = varargin {iarg++};
-    if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
-      have_filled = true;
-    elseif ((isstr (arg) || iscell (arg))
-	    && ! have_line_spec)
-      [linespec, valid] = __pltopt__ ("quiver", arg, false);
-      if (valid)
-	have_line_spec = true;
-	if (strncmp (linespec.linestyle, "none", 4))
-	  linespec.linestyle = "-";
-	endif
-      else
-	error ("quiver: invalid linespec");
-      endif
-    else
-      error ("quiver: unrecognized argument");
-    endif
-  endwhile
-
-  if (s)
-    ## Scale the arrows to fit in the grid
-    dx = (max(x(:)) - min(x(:))) ./ size (x, 2);
-    dy = (max(y(:)) - min(y(:))) ./ size (y, 1);
-    len = max (sqrt (u(:).^2 + dy(:).^2));
-    if (len > 0)
-      s = s / sqrt (2) * sqrt (dx.^2 + dy.^2) / len; 
-      u = s * u;
-      v = s * v;
-    endif
-  endif
-
-  x = x(:);
-  y = y(:);
-  xend = x + u(:);
-  yend = y + v(:);
-
-  hstate = get (h, "nextplot");
-  unwind_protect
-    if (have_line_spec)
-      h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
-		 [y.'; yend.'; NaN(1, length (y))](:),
-		 "linestyle", linespec.linestyle);
-    else
-      h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
-		 [y.'; yend.'; NaN(1, length (y))](:));
-    endif
-    hold on;
-
-    xtmp = x + u(:) .* (1 - arrowsize);
-    ytmp = y + v(:) .* (1 - arrowsize);
-    xarrw1 = xtmp + (y - yend) * arrowsize / 3;
-    xarrw2 = xtmp - (y - yend) * arrowsize / 3;
-    yarrw1 = ytmp - (x - xend) * arrowsize / 3;
-    yarrw2 = ytmp + (x - xend) * arrowsize / 3;
-
-    if (have_line_spec)
-      if (isfield (linespec, "marker") && 
-	! strncmp (linespec.marker, "none", 4))
-	h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
-		   [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
-		   "linestyle", "none");
-      else
-	h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
-		   [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
-		   "linestyle", linespec.linestyle);
-      endif
-    else
-      h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
-		 [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
-    endif
-
-    if (! have_line_spec || (isfield (linespec, "marker") && 
-			     strncmp (linespec.marker, "none", 4)))
-      h3 = plot (x, y, "linestyle", "none", "marker", "none");
-    else
-      h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker);
-    endif
-    if (have_filled)
-      ## FIXME gnuplot doesn't respect the markerfacecolor field
-      set(h3, "markerfacecolor", get (h1, "color")); 
-    endif
-  unwind_protect_cleanup
-    set (h, "nextplot", hstate);
-  end_unwind_protect
-
-  hlist = [h1; h2; h3];
-
-endfunction
-
 %!demo
 %! [x,y] = meshgrid(1:2:20);
 %! quiver(x,y,sin(2*pi*x/10),sin(2*pi*y/10))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/quiver3.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,97 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} quiver3 (@var{u}, @var{v}, @var{w})
+## @deftypefnx {Function File} {} quiver3 (@var{x}, @var{y}, @var{z}, @var{u}, @var{v}, @var{w})
+## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{s})
+## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{style})
+## @deftypefnx {Function File} {} quiver3 (@dots{}, 'filled')
+## @deftypefnx {Function File} {} quiver3 (@var{h}, @dots{})
+## @deftypefnx {Function File} {@var{h} =} quiver3 (@dots{})
+##
+## Plot the @code{(@var{u}, @var{v}, @var{w})} components of a vector field in 
+## an @code{(@var{x}, @var{y}), @var{z}} meshgrid. If the grid is uniform, you 
+## can specify @var{x}, @var{y} @var{z} as vectors.
+##
+## If @var{x}, @var{y} and @var{z} are undefined they are assumed to be
+## @code{(1:@var{m}, 1:@var{n}, 1:@var{p})} where @code{[@var{m}, @var{n}] = 
+## size(@var{u})} and @code{@var{p} = max (size (@var{w}))}.
+##
+## The variable @var{s} is a scalar defining a scaling factor to use for
+##  the arrows of the field relative to the mesh spacing. A value of 0 
+## disables all scaling. The default value is 1.
+##
+## The style to use for the plot can be defined with a line style @var{style}
+## in a similar manner to the line styles used with the @code{plot} command.
+## If a marker is specified then markers at the grid points of the vectors are
+## printed rather than arrows. If the argument 'filled' is given then the
+## markers as filled.
+##
+## The optional return value @var{h} provides a list of handles to the 
+## the parts of the vector field (body, arrow and marker).
+##
+## @example
+## @group
+## [x, y, z] = peaks (25);
+## surf (x, y, z);
+## hold on;
+## [u, v, w] = surfnorm (x, y, z / 10);
+## quiver3 (x, y, z, u, v, w);
+## @end group
+## @end example
+##
+## @seealso{plot}
+## @end deftypefn
+
+function retval = quiver3 (varargin)
+
+  if (nargin < 2)
+    print_usage ();
+  elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("quiver: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      newplot ();
+      tmp = __quiver__ (h, 1, varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    newplot ();
+    tmp = __quiver__ (gca (), 1, varargin{:});
+  endif
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
+
+%!demo
+%! [x,y]=meshgrid (-1:0.1:1); 
+%! z=sin(2*pi*sqrt(x.^2+y.^2)); 
+%! theta=2*pi*sqrt(x.^2+y.^2)+pi/2;
+%! quiver3(x,y,z,sin(theta),cos(theta),ones(size(z)));
+%! hold on; 
+%! mesh(x,y,z); 
+%! hold off;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/scatter.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,83 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} scatter (@var{x}, @var{y}, @var{s}, @var{c})
+## @deftypefnx {Function File} {} scatter (@dots{}, 'filled')
+## @deftypefnx {Function File} {} scatter (@dots{}, @var{style})
+## @deftypefnx {Function File} {} scatter (@dots{}, @var{prop}, @var{val})
+## @deftypefnx {Function File} {} scatter (@var{h}, @dots{})
+## @deftypefnx {Function File} {@var{h} =} scatter (@dots{})
+##
+## Plot a scatter plot of the data. A marker is ploted at each point 
+## defined by the points in the vectors @var{x} and @var{y}. The size of
+## the markers used is determined by the @var{s}, which can be a scalar, 
+## a vector of the same length of @var{x} and @var{y}. If @var{s} is not 
+## given or is an empty matrix, then the default value of 8 points is used.
+##
+## The color of the markers is determined by @var{c}, which can be a string
+## defining a fixed color, a 3 element vector giving the red, green and blue 
+## components of the color, a vector of the same length as @var{x} that gives
+## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining
+## the colors of each of the markers individually.
+##
+## The marker to use can be changed with the @var{style} argument, that is a 
+## string defining a marker in the same manner as the @code{plot} command. 
+## If the argument 'filled' is given then the markers as filled. All 
+## additional arguments are passed to the underlying patch command.
+##
+## The optional return value @var{h} provides a handle to the patch object
+##
+## @example
+## @group
+## x = randn (100, 1);
+## y = randn (100, 1);
+## scatter (x, y, [], sqrt(x.^2 + y.^2));
+## @end group
+## @end example
+##
+## @seealso{plot, patch, scatter3}
+## @end deftypefn
+
+function retval = scatter (varargin)
+
+  if (nargin < 2)
+    print_usage ();
+  elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("scatter: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      newplot ();
+      tmp = __scatter__ (h, 2, "scatter", varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    newplot ();
+    tmp = __scatter__ (gca (), 2, "scatter", varargin{:});
+  endif
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/scatter3.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,86 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} scatter3 (@var{x}, @var{y}, @var{s}, @var{c})
+## @deftypefnx {Function File} {} scatter3 (@dots{}, 'filled')
+## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{style})
+## @deftypefnx {Function File} {} scatter3 (@dots{}, @var{prop}, @var{val})
+## @deftypefnx {Function File} {} scatter3 (@var{h}, @dots{})
+## @deftypefnx {Function File} {@var{h} =} scatter3 (@dots{})
+##
+## Plot a scatter plot of the data in 3D. A marker is ploted at each point 
+## defined by the points in the vectors @var{x} and @var{y}. The size of
+## the markers used is determined by the @var{s}, which can be a scalar, 
+## a vector of the same length of @var{x} and @var{y}. If @var{s} is not 
+## given or is an empty matrix, then the default value of 8 points is used.
+##
+## The color of the markers is determined by @var{c}, which can be a string
+## defining a fixed color, a 3 element vector giving the red, green and blue 
+## components of the color, a vector of the same length as @var{x} that gives
+## a scaled index into the current colormap, or a @var{n}-by-3 matrix defining
+## the colors of each of the markers individually.
+##
+## The marker to use can be changed with the @var{style} argument, that is a 
+## string defining a marker in the same manner as the @code{plot} command. 
+## If the argument 'filled' is given then the markers as filled. All 
+## additional arguments are passed to the underlying patch command.
+##
+## The optional return value @var{h} provides a handle to the patch object
+##
+## @example
+## @group
+## [x, y, z] = peaks (20);
+## scatter3 (x(:), y(:), z(:), [], z(:));
+## @end group
+## @end example
+##
+## @seealso{plot, patch, scatter}
+## @end deftypefn
+
+function retval = scatter3 (varargin)
+
+  if (nargin < 2)
+    print_usage ();
+  elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("scatter3: expecting first argument to be an axes object");
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      newplot ();
+      tmp = __scatter__ (h, 3, "scatter3", varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    newplot ();
+    tmp = __scatter__ (gca (), 3, "scatter3", varargin{:});
+  endif
+
+  if (! ishold ())
+    set (get (tmp, "parent"), "view", [-37.5, 30]);
+  endif
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/sphere.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,77 @@
+## Copyright (C) 2007 Michael Goffioul
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{x}, @var{y}, @var{z}] =} sphere (@var{n})
+## @deftypefnx {Function File} {} sphere (@var{h}, @dots{})
+## Generates three matrices in @code{meshgrid} format, such that 
+## @code{surf (@var{x}, @var{y}, @var{z})} generates a unit sphere. 
+## The matrices of @code{@var{n}+1}-by-@code{@var{n}+1}. If @var{n} is 
+## omitted then a default value of 20 is assumed.
+##
+## Called with no return arguments, @code{sphere} call directly 
+## @code{surf (@var{x}, @var{y}, @var{z})}. If an axes handle is passed
+## as the first argument, the the surface is plotted to this set of axes.
+## @seealso{peaks}
+## @end deftypefn
+
+function [xx,yy,zz] = sphere (h, n)
+
+  have_h = false;
+  if (nargin > 1 && isscalar (h) && ishandle (h))
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("sphere: expecting first argument to be an axes object");
+    endif
+    if (nargin == 1)
+      n = 20;
+    endif
+    have_h = true;
+  else
+    if (nargin == 1)
+      n = h;
+    else
+      n = 20;
+    endif
+  endif
+
+  theta = linspace (0, 2*pi, n+1);
+  phi = linspace (-pi/2, pi/2, n+1);
+  [theta,phi] = meshgrid (theta, phi);
+
+  x = cos(phi).*cos(theta);
+  y = cos(phi).*sin(theta);
+  z = sin(phi);
+
+  if (nargout > 0)
+    xx = x;
+    yy = y;
+    zz = z;
+  else
+    if (have_h)
+      oldh = gca ();
+      unwind_protect
+	axes (h);
+	surf (x, y, z);
+      unwind_protect_cleanup
+	axes (oldh);
+      end_unwind_protect
+    else
+      surf (x, y, z);
+    endif
+  endif
+
+endfunction
--- a/scripts/plot/stem.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/stem.m	Mon Nov 26 20:42:11 2007 +0000
@@ -107,11 +107,12 @@
   endif
 
   newplot ();
-
-  z = zeros (1, numel (x));
+  nx = numel (x);
   xt = x(:)';
+  xt = [xt; xt; NaN(1, nx)](:);
   yt = y(:)';
-  h_stems = plot ([xt; xt], [z; yt], "color", lc, "linestyle", ls,
+  yt = [zeros(1, nx); yt; NaN(1, nx)](:);
+  h_stems = plot (xt, yt, "color", lc, "linestyle", ls,
 		  x, y, "color", mc, "marker", ms, "linestyle", "",
 		  "markerfacecolor", fc);
 
@@ -262,10 +263,8 @@
   ## Parse the line specifier string.
   cur_props = __pltopt__ ("stem", str, false);
   for i = 1:length(cur_props)
-    if (isfield (cur_props(i), "markeredgecolor"))
-      mc = cur_props(i).markeredgecolor;
-    elseif (isfield (cur_props(i), "color") && ! isempty (cur_props(i).color)); # means line color
-      lc = cur_props(i).color;
+    if (isfield (cur_props(i), "color") && ! isempty (cur_props(i).color)); # means line color
+      mc = lc = cur_props(i).color;
     elseif (isfield (cur_props(i), "linestyle"))
       ls = cur_props(i).linestyle;
     elseif (isfield (cur_props(i), "marker") && ! strcmp (cur_props(i).marker, "none"))
--- a/scripts/plot/surface.m	Mon Nov 26 20:31:25 2007 +0000
+++ b/scripts/plot/surface.m	Mon Nov 26 20:42:11 2007 +0000
@@ -123,7 +123,9 @@
   ## Make a default surface object.
   tmp = __go_surface__ (ax, "xdata", x, "ydata", y, "zdata", z, "cdata", c);
   set (tmp, "facecolor","flat");
-  set (tmp, varargin {firststring:end});
+  if (firststring <= nargin)
+    set (tmp, varargin {firststring:end});
+  endif
 
   if (! ishold ())
     set (ax, "view", [0, 90], "box", "off", "xgrid", "on", "ygrid", "on", "zgrid", "on");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/surfnorm.m	Mon Nov 26 20:42:11 2007 +0000
@@ -0,0 +1,155 @@
+## Copyright (C) 2007 David Bateman
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} surfnorm (@var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {} surfnorm (@var{z})
+## @deftypefnx {Function File} {[@var{nx}, @var{ny}, @var{nz}] =} surfnorm (@dots{})
+## @deftypefnx {Function File} {} surfnorm (@var{h}, @dots{})
+## Find the vectors normal to a meshgridded surface. The meshed gridded 
+## surface is defined by @var{x}, @var{y}, and @var{z}. If @var{x} and 
+## @var{y} are not defined, then it is assumed that they are given by
+##
+## @example
+## [@var{x}, @var{y}] = meshgrid (1:size(@var{z}, 1), 
+##                      1:size(@var{z}, 2));
+## @end example
+##
+## If no return arguments are requested, a surface plot with the normal 
+## vectors to the surface is plotted. Otherwise the componets of the normal
+## vectors at the mesh gridded points are returned in @var{nx}, @var{ny},
+## and @var{nz}.
+##
+## The normal vectors are calculated by taking the cross product of the 
+## diagonals of eash of teh quadrilaterals in the meshgrid to find the 
+## normal vectors of the centers of these quadrilaterals. The four nearest
+## normal vectors to the meshgrid points are then averaged to obtain the 
+## normal to the surface at the meshgridded points.
+##
+## An example of the use of @code{surfnorm} is
+##
+## @example
+## surfnorm (peaks (25));
+## @end example
+## @seealso{surf, quiver3}
+## @end deftypefn
+
+function varargout = surfnorm (varargin)
+
+  if (nargout > 0)
+    varargout = cell (nargout, 1);
+  else
+    varargout = cell (0, 0);
+  endif
+  if (isscalar (varargin{1}) && ishandle (varargin{1}))
+    h = varargin {1};
+    if (! strcmp (get (h, "type"), "axes"))
+      error ("surfnorm: expecting first argument to be an axes object");
+    endif
+    if (nargin != 2 && nargin != 4)
+      print_usage ();
+    endif
+    oldh = gca ();
+    unwind_protect
+      axes (h);
+      [varargout{:}] = __surfnorm__ (h, varargin{2:end});
+    unwind_protect_cleanup
+      axes (oldh);
+    end_unwind_protect
+  else
+    if (nargin != 1 && nargin != 3)
+      print_usage ();
+    endif
+    [varargout{:}] = __surfnorm__ (gca (), varargin{:});
+  endif
+
+endfunction
+
+function [Nx, Ny, Nz] = __surfnorm__ (h, varargin)
+
+  if (nargin == 2)
+    z = varargin{1};
+    [x, y] = meshgrid (1:size(z,1), 1:size(z,2));
+    ioff = 2;
+  else
+    x = varargin{1};
+    y = varargin{2};
+    z = varargin{3};
+    ioff = 4;
+  endif
+
+  if (nargout == 0)
+    newplot();
+    surf (x, y, z, varargin{ioff:end});
+    hold on;
+  endif
+
+  ## Make life easier, and avoid having to do the extrapolation later, do
+  ## a simpler linear extrapolation here. This is approximative, and works
+  ## badly for closed surfaces like spheres.
+  xx = [2 .* x(:,1) - x(:,2), x, 2 .* x(:,end) - x(:,end-1)];
+  xx = [2 .* xx(1,:) - xx(2,:); xx; 2 .* xx(end,:) - xx(end-1,:)];
+  yy = [2 .* y(:,1) - y(:,2), y, 2 .* y(:,end) - y(:,end-1)];
+  yy = [2 .* yy(1,:) - yy(2,:); yy; 2 .* yy(end,:) - yy(end-1,:)];
+  zz = [2 .* z(:,1) - z(:,2), z, 2 .* z(:,end) - z(:,end-1)];
+  zz = [2 .* zz(1,:) - zz(2,:); zz; 2 .* zz(end,:) - zz(end-1,:)];
+
+  u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end);
+  u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end);
+  u.z = zz(1:end-1,1:end-1) - zz(2:end,2:end);
+  v.x = xx(1:end-1,2:end) - xx(2:end,1:end-1);
+  v.y = yy(1:end-1,2:end) - yy(2:end,1:end-1);
+  v.z = zz(1:end-1,2:end) - zz(2:end,1:end-1);
+
+  c = cross ([u.x(:), u.y(:), u.z(:)], [v.x(:), v.y(:), v.z(:)]);
+  w.x = reshape (c(:,1), size(u.x));
+  w.y = reshape (c(:,2), size(u.y));
+  w.z = reshape (c(:,3), size(u.z));
+
+  ## Create normal vectors as mesh vectices from normals at mesh centers
+  nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) +
+	w.x(2:end,1:end-1) + w.x(2:end,2:end)) ./ 4; 
+  ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) +
+	w.y(2:end,1:end-1) + w.y(2:end,2:end)) ./ 4; 
+  nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) +
+	w.z(2:end,1:end-1) + w.z(2:end,2:end)) ./ 4; 
+
+  ## Normalize the normal vectors
+  len = sqrt (nx.^2 + ny.^2 + nz.^2);
+  nx = nx ./ len;
+  ny = ny ./ len;
+  nz = nz ./ len;
+
+  if (nargout == 0)
+    plot3 ([x(:)'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:),
+	   [y(:)'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:),
+	   [z(:)'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:), 
+	   varargin{ioff:end});
+  else
+    Nx = nx;
+    Ny = ny;
+    Nz = nz;
+  endif
+endfunction
+
+%!demo
+%! [x, y, z] = peaks(10);
+%! surfnorm (x, y, z);
+
+%!demo
+%! surfnorm (peaks(10));
--- a/src/ChangeLog	Mon Nov 26 20:31:25 2007 +0000
+++ b/src/ChangeLog	Mon Nov 26 20:42:11 2007 +0000
@@ -1,3 +1,29 @@
+2007-11-26  David Bateman  <dbateman@free.fr>
+
+	* DLD-FUNCTIONS/minmax.cc (MINMAX_DOUBLE_BODY): New version of
+	MINMAX_BODY macro without the initialization.
+	(MINMAX_INT_BODY): Macro for min/max for the integer types
+	(MINMAX_BODY): New macro that calls the appropriate instantiation
+	of the other two macros.
+
+	* graphics.cc (class axes): Add __colorbar__ property.
+	* graphics.h.in (class axes): ditto.
+
+	* data.cc (Fnorm): Document the "inf" string argument for matrice
+	and vectors and the "fro" argument for vectors.
+
+	* graphics.h.in (class figure): Add __enhanced__ property to cache
+	whether the terminal supports enhanced mode. Add interpreter
+	property to all text classes, to determine the renderer for the
+	text.
+	* graphics.cc (class figure): ditto.
+
+2007-11-26  Shai Ayal  <shaiay@users.sourceforge.net>
+
+	* graphics.cc (string_properties): delete class 
+	(property_name): rename class to caseless_str. 
+	(radio_values::possible_vals): change type to caseless_str.
+
 2007-11-26  Michael Goffioul <michael.goffioul@gmail.com>
 
 	* builtins.h (install_builtins): Tag with OCTINTERP_API.
--- a/src/DLD-FUNCTIONS/minmax.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/src/DLD-FUNCTIONS/minmax.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -40,65 +40,8 @@
 
 #include "ov-cx-mat.h"
 
-#define MINMAX_BODY(FCN) \
- \
-  octave_value_list retval;  \
- \
-  int nargin = args.length (); \
- \
-  if (nargin < 1 || nargin > 3 || nargout > 2) \
-    { \
-      print_usage (); \
-      return retval; \
-    } \
- \
-  octave_value arg1; \
-  octave_value arg2; \
-  octave_value arg3; \
- \
-  switch (nargin) \
-    { \
-    case 3: \
-      arg3 = args(2); \
- \
-    case 2: \
-      arg2 = args(1); \
- \
-    case 1: \
-      arg1 = args(0); \
-      break; \
- \
-    default: \
-      panic_impossible (); \
-      break; \
-    } \
- \
-  int dim; \
-  dim_vector dv = arg1.dims (); \
-  if (error_state) \
-    { \
-      gripe_wrong_type_arg (#FCN, arg1);  \
-      return retval; \
-    } \
- \
-  if (nargin == 3) \
-    { \
-      dim = arg3.nint_value () - 1;  \
-      if (dim < 0 || dim >= dv.length ()) \
-        { \
-	  error ("%s: invalid dimension", #FCN); \
-	  return retval; \
-	} \
-    } \
-  else \
-    { \
-      dim = 0; \
-      while ((dim < dv.length ()) && (dv (dim) <= 1)) \
-	dim++; \
-      if (dim == dv.length ()) \
-	dim = 0; \
-    } \
- \
+#define MINMAX_DOUBLE_BODY(FCN) \
+{ \
   bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3);	\
  \
   if (single_arg && (nargout == 1 || nargout == 0)) \
@@ -271,8 +214,185 @@
 	    } \
 	} \
     } \
+}
+
+#define MINMAX_INT_BODY(FCN, TYP) \
+ { \
+  bool single_arg = (nargin == 1) || (arg2.is_empty() && nargin == 3);	\
  \
-  return retval
+  if (single_arg && (nargout == 1 || nargout == 0)) \
+    { \
+      TYP ## NDArray m = arg1. TYP ## _array_value (); \
+ \
+      if (! error_state) \
+	{ \
+	  TYP ## NDArray n = m. FCN (dim); \
+	  retval(0) = n; \
+	} \
+    } \
+  else if (single_arg && nargout == 2) \
+    { \
+      ArrayN<octave_idx_type> index; \
+ \
+      TYP ## NDArray m = arg1. TYP ## _array_value (); \
+ \
+      if (! error_state) \
+        { \
+	  TYP ## NDArray n = m. FCN (index, dim);	\
+	  retval(0) = n; \
+	} \
+ \
+      octave_idx_type len = index.numel (); \
+ \
+      if (len > 0) \
+	{ \
+	  double nan_val = lo_ieee_nan_value (); \
+ \
+	  NDArray idx (index.dims ()); \
+ \
+	  for (octave_idx_type i = 0; i < len; i++) \
+	    { \
+	      OCTAVE_QUIT; \
+	      int tmp = index.elem (i) + 1; \
+	      idx.elem (i) = (tmp <= 0) \
+		? nan_val : static_cast<double> (tmp); \
+	    } \
+ \
+	  retval(1) = idx; \
+	} \
+      else \
+	retval(1) = NDArray (); \
+    } \
+  else \
+    { \
+      int arg1_is_scalar = arg1.is_scalar_type (); \
+      int arg2_is_scalar = arg2.is_scalar_type (); \
+ \
+      if (arg1_is_scalar) \
+	{ \
+	  octave_ ## TYP d1 = arg1. TYP ## _scalar_value (); \
+	  TYP ## NDArray m2 = arg2. TYP ## _array_value (); \
+ \
+	  if (! error_state) \
+	    { \
+	      TYP ## NDArray result = FCN (d1, m2); \
+	      if (! error_state) \
+		retval(0) = result; \
+	    } \
+	} \
+      else if (arg2_is_scalar) \
+	{ \
+	  TYP ## NDArray m1 = arg1. TYP ## _array_value (); \
+ \
+	  if (! error_state) \
+	    { \
+	      octave_ ## TYP d2 = arg2. TYP ## _scalar_value (); \
+	      TYP ## NDArray result = FCN (m1, d2); \
+	      if (! error_state) \
+		retval(0) = result; \
+	    } \
+	} \
+      else \
+	{ \
+	  TYP ## NDArray m1 = arg1. TYP ## _array_value (); \
+ \
+	  if (! error_state) \
+	    { \
+	      TYP ## NDArray m2 = arg2. TYP ## _array_value (); \
+ \
+	      if (! error_state) \
+		{ \
+		  TYP ## NDArray result = FCN (m1, m2); \
+		  if (! error_state) \
+		    retval(0) = result; \
+		} \
+	    } \
+	} \
+    } \
+}
+
+#define MINMAX_BODY(FCN) \
+ \
+  octave_value_list retval;  \
+ \
+  int nargin = args.length (); \
+ \
+  if (nargin < 1 || nargin > 3 || nargout > 2) \
+    { \
+      print_usage (); \
+      return retval; \
+    } \
+ \
+  octave_value arg1; \
+  octave_value arg2; \
+  octave_value arg3; \
+ \
+  switch (nargin) \
+    { \
+    case 3: \
+      arg3 = args(2); \
+ \
+    case 2: \
+      arg2 = args(1); \
+ \
+    case 1: \
+      arg1 = args(0); \
+      break; \
+ \
+    default: \
+      panic_impossible (); \
+      break; \
+    } \
+ \
+  int dim; \
+  dim_vector dv = arg1.dims (); \
+  if (error_state) \
+    { \
+      gripe_wrong_type_arg (#FCN, arg1);  \
+      return retval; \
+    } \
+ \
+  if (nargin == 3) \
+    { \
+      dim = arg3.nint_value () - 1;  \
+      if (dim < 0 || dim >= dv.length ()) \
+        { \
+	  error ("%s: invalid dimension", #FCN); \
+	  return retval; \
+	} \
+    } \
+  else \
+    { \
+      dim = 0; \
+      while ((dim < dv.length ()) && (dv (dim) <= 1)) \
+	dim++; \
+      if (dim == dv.length ()) \
+	dim = 0; \
+    } \
+ \
+  if (arg1.is_integer_type ()) \
+    { \
+      if (arg1.is_uint8_type ()) \
+        MINMAX_INT_BODY (FCN, uint8) \
+      else if (arg1.is_uint16_type ()) \
+        MINMAX_INT_BODY (FCN, uint16) \
+      else if (arg1.is_uint32_type ()) \
+        MINMAX_INT_BODY (FCN, uint32) \
+      else if (arg1.is_uint64_type ()) \
+        MINMAX_INT_BODY (FCN, uint64) \
+      else if (arg1.is_int8_type ()) \
+        MINMAX_INT_BODY (FCN, int8) \
+      else if (arg1.is_int16_type ()) \
+        MINMAX_INT_BODY (FCN, int16) \
+      else if (arg1.is_int32_type ()) \
+        MINMAX_INT_BODY (FCN, int32) \
+      else if (arg1.is_int64_type ()) \
+        MINMAX_INT_BODY (FCN, int64) \
+    } \
+  else \
+    MINMAX_DOUBLE_BODY (FCN) \
+ \
+ return retval;
 
 DEFUN_DLD (min, args, nargout,
   "-*- texinfo -*-\n\
--- a/src/data.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/src/data.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -2775,7 +2775,7 @@
 @item @var{p} = @code{2}\n\
 Largest singular value of @var{a}.\n\
 \n\
-@item @var{p} = @code{Inf}\n\
+@item @var{p} = @code{Inf} or @code{\"inf\"}\n\
 @cindex infinity norm\n\
 Infinity norm, the largest row sum of the absolute values of @var{a}.\n\
 \n\
@@ -2787,12 +2787,15 @@
 If @var{a} is a vector or a scalar:\n\
 \n\
 @table @asis\n\
-@item @var{p} = @code{Inf}\n\
+@item @var{p} = @code{Inf} or @code{\"inf\"}\n\
 @code{max (abs (@var{a}))}.\n\
 \n\
 @item @var{p} = @code{-Inf}\n\
 @code{min (abs (@var{a}))}.\n\
 \n\
+@item @var{p} = @code{\"fro\"}\n\
+Frobenius norm of @var{a}, @code{sqrt (sumsq (abs (a)))}.\n\
+\n\
 @item other\n\
 p-norm of @var{a}, @code{(sum (abs (@var{a}) .^ @var{p})) ^ (1/@var{p})}.\n\
 @end table\n\
--- a/src/graphics.cc	Mon Nov 26 20:31:25 2007 +0000
+++ b/src/graphics.cc	Mon Nov 26 20:42:11 2007 +0000
@@ -219,7 +219,7 @@
 
 
 void
-property_list::set (const property_name& name, const octave_value& val)
+property_list::set (const caseless_str& name, const octave_value& val)
 {
   size_t offset = 0;
 
@@ -227,7 +227,7 @@
 
   if (len > 4)
     {
-      property_name pfx = name.substr (0, 4);
+      caseless_str pfx = name.substr (0, 4);
 
       if (pfx.compare ("axes") || pfx.compare ("line")
 	  || pfx.compare ("text"))
@@ -266,7 +266,7 @@
 	  bool remove = false;
 	  if (val.is_string ())
 	    {
-	      property_name tval = val.string_value ();
+	      caseless_str tval = val.string_value ();
 
 	      remove = tval.compare ("remove");
 	    }
@@ -290,7 +290,7 @@
 }
 
 octave_value
-property_list::lookup (const property_name& name) const
+property_list::lookup (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -300,7 +300,7 @@
 
   if (len > 4)
     {
-      property_name pfx = name.substr (0, 4);
+      caseless_str pfx = name.substr (0, 4);
 
       if (pfx.compare ("axes") || pfx.compare ("line")
 	  || pfx.compare ("text"))
@@ -398,7 +398,7 @@
     {
       for (int i = 0; i < nargin; i += 2)
 	{
-	  property_name name = args(i).string_value ();
+	  caseless_str name = args(i).string_value ();
 
 	  if (! error_state)
 	    {
@@ -406,7 +406,7 @@
 
 	      if (val.is_string ())
 		{
-		  property_name tval = val.string_value ();
+		  caseless_str tval = val.string_value ();
 
 		  if (tval.compare ("default"))
 		    val = get_default (name);
@@ -485,7 +485,7 @@
 gh_manager *gh_manager::instance = 0;
 
 static void
-xset (const graphics_handle& h, const property_name& name,
+xset (const graphics_handle& h, const caseless_str& name,
       const octave_value& val)
 {
   graphics_object obj = gh_manager::get_object (h);
@@ -504,7 +504,7 @@
 
 
 static octave_value
-xget (const graphics_handle& h, const property_name& name)
+xget (const graphics_handle& h, const caseless_str& name)
 {
   graphics_object obj = gh_manager::get_object (h);
   return obj.get (name);
@@ -784,7 +784,7 @@
 }
 
 void
-root_figure::properties::set (const property_name& name,
+root_figure::properties::set (const caseless_str& name,
 			      const octave_value& val)
 {
   if (name.compare ("tag"))
@@ -813,7 +813,7 @@
 }
 
 octave_value 
-root_figure::properties::get (const property_name& name) const
+root_figure::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -844,6 +844,7 @@
 				const graphics_handle& p)
   : base_properties (go_name, mh, p),
     __plot_stream__ (Matrix ()),
+    __enhanced__ (false),
     nextplot ("replace"),
     closerequestfcn (make_fcn_handle ("closereq")),
     currentaxes (octave_NaN),
@@ -879,7 +880,7 @@
 }
 
 void
-figure::properties::set (const property_name& name, const octave_value& val)
+figure::properties::set (const caseless_str& name, const octave_value& val)
 {
   bool modified = true;
 
@@ -894,6 +895,8 @@
     }
   else if (name.compare ("__plot_stream__"))
     set___plot_stream__ (val);
+  else if (name.compare ("__enhanced__"))
+    set___enhanced__ (val);
   else if (name.compare ("nextplot"))
     set_nextplot (val);
   else if (name.compare ("closerequestfcn"))
@@ -927,6 +930,7 @@
   m.assign ("children", children);
   m.assign ("__modified__", __modified__);
   m.assign ("__plot_stream__", __plot_stream__);
+  m.assign ("__enhanced__", __enhanced__);
   m.assign ("nextplot", nextplot);
   m.assign ("closerequestfcn", closerequestfcn);
   m.assign ("currentaxes", currentaxes.as_octave_value ());
@@ -938,7 +942,7 @@
 }
 
 octave_value
-figure::properties::get (const property_name& name) const
+figure::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -954,6 +958,8 @@
     retval = __modified__;
   else if (name.compare ("__plot_stream__"))
     retval = __plot_stream__;
+  else if (name.compare ("__enhanced__"))
+    retval = __enhanced__;
   else if (name.compare ("nextplot"))
     retval = nextplot;
   else if (name.compare ("closerequestfcn"))
@@ -1008,7 +1014,7 @@
 }
 
 octave_value
-figure::get_default (const property_name& name) const
+figure::get_default (const caseless_str& name) const
 {
   octave_value retval = default_properties.lookup (name);
 
@@ -1106,7 +1112,8 @@
     view (),
     visible ("on"),
     nextplot ("replace"),
-    outerposition ()
+    outerposition (),
+    __colorbar__ (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"))
 {
   Matrix tlim (1, 2, 0.0);
   tlim(1) = 1;
@@ -1192,7 +1199,7 @@
 }
 
 void
-axes::properties::set (const property_name& name, const octave_value& val)
+axes::properties::set (const caseless_str& name, const octave_value& val)
 {
   bool modified = true;
 
@@ -1307,6 +1314,8 @@
     set_nextplot (val);
   else if (name.compare ("outerposition"))
     set_outerposition (val);
+  else if (name.compare ("__colorbar__"))
+    set___colorbar__ (val);
   else
     {
       modified = false;
@@ -1393,6 +1402,8 @@
       outerposition = touterposition;
     }
 
+  __colorbar__  = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"));
+
   delete_children ();
 
   children = Matrix ();
@@ -1496,12 +1507,13 @@
   m.assign ("visible", visible);
   m.assign ("nextplot", nextplot);
   m.assign ("outerposition", outerposition);
+  m.assign ("__colorbar__", __colorbar__);
 
   return m;
 }
 
 octave_value
-axes::properties::get (const property_name& name) const
+axes::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -1615,6 +1627,8 @@
     retval = nextplot;
   else if (name.compare ("outerposition"))
     retval = outerposition;
+  else if (name.compare ("__colorbar__"))
+    retval = __colorbar__;
   else
     warning ("get: invalid property `%s'", name.c_str ());
 
@@ -1721,12 +1735,13 @@
   touterposition(3) = 1;
 
   m["outerposition"] = touterposition;
+  m["__colorbar__"] = radio_property (radio_values ("{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside"));
 
   return m;
 }
 
 octave_value
-axes::get_default (const property_name& name) const
+axes::get_default (const caseless_str& name) const
 {
   octave_value retval = default_properties.lookup (name);
 
@@ -1773,11 +1788,12 @@
     markeredgecolor ("auto"),
     markerfacecolor ("none"),
     markersize (1),
-    keylabel ("")
+    keylabel (""),
+    interpreter (radio_values ("{tex}|none|latex"))
 { }
 
 void
-line::properties::set (const property_name& name, const octave_value& val)
+line::properties::set (const caseless_str& name, const octave_value& val)
 {
   bool modified = true;
 
@@ -1822,6 +1838,8 @@
     set_markersize (val);
   else if (name.compare ("keylabel"))
     set_keylabel (val);
+  else if (name.compare ("interpreter"))
+    set_interpreter (val);
   else
     {
       modified = false;
@@ -1857,12 +1875,13 @@
   m.assign ("markerfacecolor", markerfacecolor);
   m.assign ("markersize", markersize);
   m.assign ("keylabel", keylabel);
+  m.assign ("interpreter", interpreter);
 
   return m;
 }
 
 octave_value
-line::properties::get (const property_name& name) const
+line::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -1906,6 +1925,8 @@
     retval = markersize;
   else if (name.compare ("keylabel"))
     retval = keylabel;
+  else if (name.compare ("interpreter"))
+    retval = interpreter;
   else
     warning ("get: invalid property `%s'", name.c_str ());
 
@@ -1932,6 +1953,8 @@
   m["markerfacecolor"] = "none";
   m["markersize"] = 1;
   m["keylabel"] = "";
+  m["interpreter"] = 
+    radio_property (radio_values ("{tex}|none|latex"));
 
   return m;
 }
@@ -1952,11 +1975,12 @@
     fontname ("Helvetica"),
     fontsize (10),
     fontangle (radio_values ("{normal}|italic|oblique")),
-    fontweight (radio_values ("{normal}|bold|demi|light"))
+    fontweight (radio_values ("{normal}|bold|demi|light")),
+    interpreter (radio_values ("{tex}|none|latex"))
 { }
 
 void
-text::properties::set (const property_name& name, const octave_value& val)
+text::properties::set (const caseless_str& name, const octave_value& val)
 {
   bool modified = true;
 
@@ -1991,6 +2015,8 @@
     set_fontangle (val);
   else if (name.compare ("fontweight"))
     set_fontweight (val);
+  else if (name.compare ("interpreter"))
+    set_interpreter (val);
   else
     {
       modified = false;
@@ -2021,12 +2047,13 @@
   m.assign ("fontsize", fontsize);
   m.assign ("fontangle", fontangle);
   m.assign ("fontweight", fontweight);
+  m.assign ("interpreter", interpreter);
 
   return m;
 }
 
 octave_value
-text::properties::get (const property_name& name) const
+text::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -2060,6 +2087,8 @@
     retval = fontangle;
   else if (name.compare ("fontweight"))
     retval = fontweight;
+  else if (name.compare ("interpreter"))
+    retval = interpreter;
   else
     warning ("get: invalid property `%s'", name.c_str ());
 
@@ -2080,9 +2109,11 @@
   m["fontname"] = "Helvetica";
   m["fontsize"] = 10;
   m["fontangle"] = 
-      string_property ("normal", radio_values ("{normal}|italic|oblique"));
+      radio_property (radio_values ("{normal}|italic|oblique"));
   m["fontweight"] = 
-    string_property ("normal", radio_values ("{normal}|bold|demi|light"));
+    radio_property (radio_values ("{normal}|bold|demi|light"));
+  m["interpreter"] = 
+    radio_property (radio_values ("{tex}|none|latex"));
 
   return m;
 }
@@ -2100,7 +2131,7 @@
 { }
 
 void
-image::properties::set (const property_name& name,
+image::properties::set (const caseless_str& name,
 			const octave_value& val)
 {
   bool modified = true;
@@ -2150,7 +2181,7 @@
 }
 
 octave_value
-image::properties::get (const property_name& name) const
+image::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -2210,11 +2241,12 @@
     markeredgecolor ("auto"),
     markerfacecolor ("none"),
     markersize (1),
-    keylabel ("")
+    keylabel (""),
+    interpreter (radio_values ("{tex}|none|latex"))
 { }
 
 void
-patch::properties::set (const property_name& name,
+patch::properties::set (const caseless_str& name,
 			const octave_value& val)
 {
   bool modified = true;
@@ -2262,6 +2294,8 @@
     set_markersize (val);
   else if (name.compare ("keylabel"))
     set_keylabel (val);
+  else if (name.compare ("interpreter"))
+    set_interpreter (val);
   else
     {
       modified = false;
@@ -2298,12 +2332,13 @@
   m.assign ("markerface", markerfacecolor);
   m.assign ("markersize", markersize);
   m.assign ("keylabel", keylabel);
+  m.assign ("interpreter", interpreter);
 
   return m;
 }
 
 octave_value
-patch::properties::get (const property_name& name) const
+patch::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -2349,6 +2384,8 @@
     retval = markersize;
   else if (name.compare ("keylabel"))
     retval = keylabel;
+  else if (name.compare ("interpreter"))
+    retval = interpreter;
   else
     warning ("get: invalid property `%s'", name.c_str ());
 
@@ -2376,6 +2413,8 @@
   m["markerfacecolor"] = "none";
   m["markersize"] = 1;
   m["keylabel"] = "";
+  m["interpreter"] = 
+    radio_property (radio_values ("{tex}|none|latex"));
 
   return m;
 }
@@ -2400,11 +2439,12 @@
     markeredgecolor ("auto"),
     markerfacecolor ("none"),
     markersize (1),
-    keylabel ("")
+    keylabel (""),
+    interpreter (radio_values ("{tex}|none|latex"))
 { }
 
 void
-surface::properties::set (const property_name& name,
+surface::properties::set (const caseless_str& name,
 			  const octave_value& val)
 {
   bool modified = true;
@@ -2448,6 +2488,8 @@
     set_markersize (val);
   else if (name.compare ("keylabel"))
     set_keylabel (val);
+  else if (name.compare ("interpreter"))
+    set_interpreter (val);
   else
     {
       modified = false;
@@ -2482,12 +2524,13 @@
   m.assign ("markerface", markerfacecolor);
   m.assign ("markersize", markersize);
   m.assign ("keylabel", keylabel);
+  m.assign ("interpreter", interpreter);
 
   return m;
 }
 
 octave_value
-surface::properties::get (const property_name& name) const
+surface::properties::get (const caseless_str& name) const
 {
   octave_value retval;
 
@@ -2529,6 +2572,8 @@
     retval = markersize;
   else if (name.compare ("keylabel"))
     retval = keylabel;
+  else if (name.compare ("interpreter"))
+    retval = interpreter;
   else
     warning ("get: invalid property `%s'", name.c_str ());
 
@@ -2554,6 +2599,8 @@
   m["markerfacecolor"] = "none";
   m["markersize"] = 1;
   m["keylabel"] = "";
+  m["interpreter"] = 
+    radio_property (radio_values ("{tex}|none|latex"));
 
   return m;
 }
@@ -2563,7 +2610,7 @@
 // ---------------------------------------------------------------------
 
 octave_value
-base_graphics_object::get_default (const property_name& name) const
+base_graphics_object::get_default (const caseless_str& name) const
 {
   graphics_handle parent = get_parent ();
   graphics_object parent_obj = gh_manager::get_object (parent);
@@ -2572,7 +2619,7 @@
 }
 
 octave_value
-base_graphics_object::get_factory_default (const property_name& name) const
+base_graphics_object::get_factory_default (const caseless_str& name) const
 {
   graphics_object parent_obj = gh_manager::get_object (0);
 
@@ -2765,7 +2812,7 @@
                     vlist(n) = obj.get ();
                   else
                     {
-                      property_name property = args(1).string_value ();
+                      caseless_str property = args(1).string_value ();
 
                       if (! error_state)
                         vlist(n) = obj.get (property);
@@ -3075,7 +3122,7 @@
 
   if (obj)
     {
-      property_name p = std::string (property);
+      caseless_str p = std::string (property);
       retval = obj.get (p);
     }
   else
@@ -3093,7 +3140,7 @@
 
   if (obj)
     {
-      property_name p = std::string (property);
+      caseless_str p = std::string (property);
       obj.set (p, arg);
       if (!error_state)
 	ret = true;
--- a/src/graphics.h.in	Mon Nov 26 20:31:25 2007 +0000
+++ b/src/graphics.h.in	Mon Nov 26 20:42:11 2007 +0000
@@ -39,6 +39,49 @@
 #include "oct-map.h"
 #include "ov.h"
 
+class caseless_str : public std::string
+{
+public:
+  typedef std::string::iterator iterator;
+  typedef std::string::const_iterator const_iterator;
+
+  caseless_str (void) : std::string () { }
+  caseless_str (const std::string& s) : std::string (s) { }
+  caseless_str (const char *s) : std::string (s) { }
+
+  caseless_str (const caseless_str& name) : std::string (name) { }
+
+  caseless_str& operator = (const caseless_str& pname)
+  {
+    std::string::operator = (pname);
+    return *this;
+  }
+
+  operator std::string (void) const { return *this; }
+
+  // Case-insensitive comparison.
+  bool compare (const std::string& s, size_t limit = NPOS) const
+  {
+    const_iterator p1 = begin ();
+    const_iterator p2 = s.begin ();
+
+    size_t k = 0;
+
+    while (p1 != end () && p2 != s.end () && k++ < limit)
+      {
+	if (std::tolower (*p1) != std::tolower (*p2))
+	  return false;
+
+	*p1++;
+	*p2++;
+      }
+
+    return (limit == NPOS) ? size () == s.size () : k == limit;
+  }
+};
+
+// ---------------------------------------------------------------------
+
 class
 radio_values
 {
@@ -61,8 +104,6 @@
 
   std::string default_value (void) const { return default_val; }
 
-  std::set<std::string> possible_values (void) const { return possible_vals; }
-
   bool validate (const std::string& val)
   {
     bool retval = true;
@@ -84,7 +125,7 @@
 private:
   // Might also want to cache
   std::string default_val;
-  std::set<std::string> possible_vals;
+  std::set<caseless_str> possible_vals;
 };
 
 class
@@ -115,10 +156,30 @@
   {
     if (vals.validate (newval))
       current_val = newval;
+    else
+      error ("invalid value");
 
     return *this;
   }
 
+  radio_property& operator = (const octave_value& newval) 
+  {
+    if (newval.is_string ())
+      {
+	std::string s = newval.string_value ();
+	if (vals.validate (s))
+	  current_val = s;
+	else
+	  error ("invalid value");
+      }
+    else	
+      error ("invalid value");
+
+    return *this;
+  }
+
+  operator octave_value (void) const { return current_val; }
+
   const std::string& current_value (void) const { return current_val; }
 
 private:
@@ -352,152 +413,6 @@
   Matrix cmap;
 };
 
-class 
-string_property
-{
-public:
-  string_property (const octave_value& c = octave_value (std::string ()),
-		   const radio_values& v = radio_values ())
-    : radio_val (v)
-  { 
-    if (c.is_defined ())
-      {
-	std::string newval = c.string_value ();
-
-	std::transform (newval.begin (), newval.end (),
-			newval.begin (), tolower);
-
-	if (! error_state)
-	  {
-	    if (radio_val.validate (newval))
-	      current_val = newval;
-	  }
-      }
-    else
-      current_val = v.default_value ();
-  }
-
-  string_property (const radio_values& v)
-    : current_val (v.default_value()), radio_val (v)
-  { }
-
-  string_property (const radio_values& v, const std::string& initial_value)
-    : radio_val (v)
-  { 
-    current_val = initial_value;
-    std::transform (current_val.begin (), current_val.end (), 
-		    current_val.begin (), tolower);
-  }
-
-  operator octave_value (void) const { return current_val; }
-
-  string_property& operator = (const string_property& a)
-  {
-    if (&a != this)
-      {
-	current_val = a.current_val;
-	radio_val = a.radio_val;
-      }
-
-    return *this;
-  }
-
-  string_property& operator = (const std::string& s)
-  {
-    std::string newval = s;
-
-    std::transform (newval.begin (), newval.end (), 
-		    newval.begin (), tolower);    
-
-    if (! newval.empty ())
-      {
-	if (radio_val.contains (newval))
-	  current_val = newval;
-	else
-	  error ("invalid string specification");	  
-      }
-    else
-      error ("invalid string specification");	  
-
-    return *this;
-  }
-
-  string_property& operator = (const octave_value& val)
-  {
-    if (val.is_string ())
-      {
-	std::string newval = val.string_value ();
-
-	std::transform (newval.begin (), newval.end (), 
-			newval.begin (), tolower);
-
-	if (! newval.empty ())
-	  {
-	    if (radio_val.contains (newval))
-	      current_val = newval;
-	    else
-	      error ("invalid string specification");	  
-	  }
-	else
-	  error ("invalid string specification");	  
-      }
-    else
-      error ("invalid string specification");	  
-
-    return *this;
-  }
-
-  const std::string& current_value (void) const { return current_val; }
-
-private:
-  std::string current_val;
-  radio_values radio_val;
-};
-
-// ---------------------------------------------------------------------
-
-class property_name : public std::string
-{
-public:
-  typedef std::string::iterator iterator;
-  typedef std::string::const_iterator const_iterator;
-
-  property_name (void) : std::string () { }
-  property_name (const std::string& s) : std::string (s) { }
-  property_name (const char *s) : std::string (s) { }
-
-  property_name (const property_name& name) : std::string (name) { }
-
-  property_name& operator = (const property_name& pname)
-  {
-    std::string::operator = (pname);
-    return *this;
-  }
-
-  operator std::string (void) const { return *this; }
-
-  // Case-insensitive comparison.
-  bool compare (const std::string& s, size_t limit = NPOS) const
-  {
-    const_iterator p1 = begin ();
-    const_iterator p2 = s.begin ();
-
-    size_t k = 0;
-
-    while (p1 != end () && p2 != s.end () && k++ < limit)
-      {
-	if (std::tolower (*p1) != std::tolower (*p2))
-	  return false;
-
-	*p1++;
-	*p2++;
-      }
-
-    return (limit == NPOS) ? size () == s.size () : k == limit;
-  }
-};
-
-// ---------------------------------------------------------------------
 
 class property_list
 {
@@ -516,9 +431,9 @@
 
   ~property_list (void) { }
 
-  void set (const property_name& name, const octave_value& val);
+  void set (const caseless_str& name, const octave_value& val);
 
-  octave_value lookup (const property_name& name) const;
+  octave_value lookup (const caseless_str& name) const;
 
   plist_map_iterator begin (void) { return plist_map.begin (); }
   plist_map_const_iterator begin (void) const { return plist_map.begin (); }
@@ -668,7 +583,7 @@
 
   void set_from_list (base_graphics_object& obj, property_list& defaults);
 
-  virtual void set (const property_name&, const octave_value&) { }
+  virtual void set (const caseless_str&, const octave_value&) { }
 
   std::string get_tag (void) const { return tag; }
 
@@ -726,7 +641,7 @@
     error ("base_graphics_object::set_from_list: invalid graphics object");
   }
 
-  virtual void set (const property_name&, const octave_value&)
+  virtual void set (const caseless_str&, const octave_value&)
   {
     error ("base_graphics_object::set: invalid graphics object");
   }
@@ -742,15 +657,15 @@
     return octave_value ();
   }
 
-  virtual octave_value get (const property_name&) const
+  virtual octave_value get (const caseless_str&) const
   {
     error ("base_graphics_object::get: invalid graphics object");
     return octave_value ();
   }
 
-  virtual octave_value get_default (const property_name&) const;
+  virtual octave_value get_default (const caseless_str&) const;
 
-  virtual octave_value get_factory_default (const property_name&) const;
+  virtual octave_value get_factory_default (const caseless_str&) const;
 
   virtual octave_value get_defaults (void) const
   {
@@ -857,7 +772,7 @@
     rep->set_from_list (plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     rep->set (name, val);
   }
@@ -874,7 +789,7 @@
     return rep->get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return name.compare ("default")
       ? get_defaults ()
@@ -882,12 +797,12 @@
 	 ? get_factory_defaults () : rep->get (name));
   }
 
-  octave_value get_default (const property_name& name) const
+  octave_value get_default (const caseless_str& name) const
   {
     return rep->get_default (name);
   }
 
-  octave_value get_factory_default (const property_name& name) const
+  octave_value get_factory_default (const caseless_str& name) const
   {
     return rep->get_factory_default (name);
   }
@@ -937,11 +852,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -984,7 +899,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& value)
+  void set (const caseless_str& name, const octave_value& value)
   {
     if (name.compare ("default", 7))
       // strip "default", pass rest to function that will
@@ -1000,7 +915,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     octave_value retval;
 
@@ -1014,7 +929,7 @@
     return retval;
   }
 
-  octave_value get_default (const property_name& name) const
+  octave_value get_default (const caseless_str& name) const
   {
     octave_value retval = default_properties.lookup (name);
 
@@ -1024,7 +939,7 @@
     return retval;
   }
 
-  octave_value get_factory_default (const property_name& name) const
+  octave_value get_factory_default (const caseless_str& name) const
   {
     octave_value retval = factory_properties.lookup (name);
 
@@ -1081,11 +996,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     void close (void);
 
@@ -1098,6 +1013,7 @@
 
     BEGIN_PROPERTIES
       octave_value __plot_stream__
+      octave_value __enhanced__
       octave_value nextplot
       octave_value closerequestfcn
       graphics_handle currentaxes S
@@ -1148,7 +1064,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& value)
+  void set (const caseless_str& name, const octave_value& value)
   {
     if (name.compare ("default", 7))
       // strip "default", pass rest to function that will
@@ -1164,7 +1080,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     octave_value retval;
 
@@ -1176,7 +1092,7 @@
     return retval;
   }
 
-  octave_value get_default (const property_name& name) const;
+  octave_value get_default (const caseless_str& name) const;
 
   octave_value get_defaults (void) const
   {
@@ -1213,13 +1129,13 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     void set_defaults (base_graphics_object& obj, const std::string& mode);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     void remove_child (const graphics_handle& h);
 
@@ -1283,7 +1199,8 @@
       octave_value visible
       octave_value nextplot
       octave_value outerposition
-    END_PROPERTIES
+      radio_property __colorbar__ a
+   END_PROPERTIES
 
     static std::string go_name;
   };
@@ -1323,7 +1240,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& value)
+  void set (const caseless_str& name, const octave_value& value)
   {
     if (name.compare ("default", 7))
       // strip "default", pass rest to function that will
@@ -1344,7 +1261,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     octave_value retval;
 
@@ -1357,7 +1274,7 @@
     return retval;
   }
 
-  octave_value get_default (const property_name& name) const;
+  octave_value get_default (const caseless_str& name) const;
 
   octave_value get_defaults (void) const
   {
@@ -1394,11 +1311,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -1423,6 +1340,7 @@
       octave_value markerfacecolor
       octave_value markersize
       octave_value keylabel
+      radio_property interpreter a
     END_PROPERTIES
 
     static std::string go_name;
@@ -1456,7 +1374,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     xproperties.set (name, val);
   }
@@ -1466,7 +1384,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return xproperties.get (name);
   }
@@ -1498,11 +1416,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -1520,8 +1438,9 @@
       color_property color
       octave_value fontname
       octave_value fontsize
-      string_property fontangle a
-      string_property fontweight a
+      radio_property fontangle a
+      radio_property fontweight a
+      radio_property interpreter a
     END_PROPERTIES
 
     static std::string go_name;
@@ -1555,7 +1474,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     xproperties.set (name, val);
   }
@@ -1565,7 +1484,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return xproperties.get (name);
   }
@@ -1597,11 +1516,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -1647,7 +1566,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     xproperties.set (name, val);
   }
@@ -1657,7 +1576,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return xproperties.get (name);
   }
@@ -1689,11 +1608,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -1719,6 +1638,7 @@
       octave_value markerfacecolor
       octave_value markersize
       octave_value keylabel
+      radio_property interpreter a
     END_PROPERTIES
 
     static std::string go_name;
@@ -1752,7 +1672,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     xproperties.set (name, val);
   }
@@ -1762,7 +1682,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return xproperties.get (name);
   }
@@ -1794,11 +1714,11 @@
 
     ~properties (void) { }
 
-    void set (const property_name& name, const octave_value& val);
+    void set (const caseless_str& name, const octave_value& val);
 
     octave_value get (void) const;
 
-    octave_value get (const property_name& name) const;
+    octave_value get (const caseless_str& name) const;
 
     std::string graphics_object_name (void) const { return go_name; }
 
@@ -1822,6 +1742,7 @@
       octave_value markerfacecolor
       octave_value markersize
       octave_value keylabel
+      radio_property interpreter a
     END_PROPERTIES
 
     static std::string go_name;
@@ -1855,7 +1776,7 @@
     xproperties.set_from_list (*this, plist);
   }
 
-  void set (const property_name& name, const octave_value& val)
+  void set (const caseless_str& name, const octave_value& val)
   {
     xproperties.set (name, val);
   }
@@ -1865,7 +1786,7 @@
     return xproperties.get ();
   }
 
-  octave_value get (const property_name& name) const
+  octave_value get (const caseless_str& name) const
   {
     return xproperties.get (name);
   }