changeset 13740:510237e67c2b gui

Merge with default
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Sat, 22 Oct 2011 16:22:04 -0700
parents 59fd35807941 (current diff) 0206484682c6 (diff)
children 5f71ab377898
files configure.ac
diffstat 78 files changed, 2160 insertions(+), 545 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/bootstrap.conf	Wed Oct 12 13:45:43 2011 -0500
+++ b/build-aux/bootstrap.conf	Sat Oct 22 16:22:04 2011 -0700
@@ -20,6 +20,7 @@
 gnulib_modules="
   c-strcase
   copysign
+  copysignf
   closedir
   crypto/md5
   fclose
--- a/configure.ac	Wed Oct 12 13:45:43 2011 -0500
+++ b/configure.ac	Sat Oct 22 16:22:04 2011 -0700
@@ -2062,6 +2062,26 @@
 
 AC_LANG_PUSH(C++)
 AC_CHECK_HEADERS(sstream)
+AC_CHECK_HEADERS([unordered_map], [], [
+  AC_CHECK_HEADERS([tr1/unordered_map])])
+AC_MSG_CHECKING([whether unordered_map requires tr1 namespace])
+unordered_map_requires_tr1_namespace=no
+if test "$ac_cv_header_unordered_map" = "yes"; then
+  ### Have <unordered_map>, but still have to check whether
+  ### tr1 namespace is required (like MSVC, for instance).
+  AC_COMPILE_IFELSE([
+    AC_LANG_PROGRAM([
+      #include <unordered_map>
+    ], [
+      std::unordered_map m;
+    ])], [], [unordered_map_requires_tr1_namespace=yes])
+elif test "$ac_cv_header_tr1_unordered_map" = "yes"; then
+  unordered_map_requires_tr1_namespace=yes
+fi
+if test "$unordered_map_requires_tr1_namespace" = "yes"; then
+  AC_DEFINE(USE_UNORDERED_MAP_WITH_TR1, 1, [Defines whether unordered_map requires the use of tr1 namespace.])
+fi
+AC_MSG_RESULT([$unordered_map_requires_tr1_namespace])
 AC_LANG_POP(C++)
 
 have_termios_h=no
--- a/etc/gdbinit	Wed Oct 12 13:45:43 2011 -0500
+++ b/etc/gdbinit	Sat Oct 22 16:22:04 2011 -0700
@@ -1,5 +1,6 @@
 ## Helpful macros for debugging Octave.
 
+############################################################
 ## Display a dim-vector object.
 
 define display-dims
@@ -11,6 +12,12 @@
   dont-repeat
 end
 
+document display-dims
+Usage: display-dims DIM_VECTOR
+Display the contents of an Octave dimension vector.
+end
+
+############################################################
 ## Display a dense array object.
 
 define display-dense-array
@@ -26,6 +33,15 @@
   dont-repeat
 end
 
+document display-dense-array
+Usage: display-dense-array ARRAY
+Display the contents of an ordinary, i.e., dense Octave array.
+
+See also [display-sparse-array] for showing the contents
+of sparse Octave arrays.
+end
+
+############################################################
 ## Display a sparse array object.
 
 define display-sparse-array
@@ -46,3 +62,28 @@
   echo \n
   dont-repeat
 end
+
+document display-sparse-array
+Usage: display-sparse-array SPARSE_ARRAY
+Display the contents of a sparse Octave array.
+
+See also [display-dense-array] for showing the contents
+of ordinary Octave arrays.
+end
+
+############################################################
+
+## Display Octave debugging stack 
+
+define show-octave-dbstack
+  call show_octave_dbstack ()
+end
+
+document show-octave-dbstack
+Usage: show-octave-dbstack
+Display the contents of the current Octave debugging stack.
+
+This is the function stack that the Octave interpreter is processing
+and will be different from the C++ stack being debugged with gdb.
+end
+
--- a/liboctave/CRowVector.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/CRowVector.h	Sat Oct 22 16:22:04 2011 -0700
@@ -125,9 +125,9 @@
 
 // row vector by column vector -> scalar
 
-Complex operator * (const ComplexRowVector& a, const ColumnVector& b);
+Complex OCTAVE_API operator * (const ComplexRowVector& a, const ColumnVector& b);
 
-Complex operator * (const ComplexRowVector& a, const ComplexColumnVector& b);
+Complex OCTAVE_API operator * (const ComplexRowVector& a, const ComplexColumnVector& b);
 
 // other operations
 
--- a/liboctave/MArray-i.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/MArray-i.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -34,6 +34,13 @@
 template class OCTAVE_API MArray<int>;
 template class OCTAVE_API MArray<long>;
 
+// Explicit instantiation, as this seems to be required by weird compilers
+// like MSVC. This should be harmless on other compilers.
+template int xmin<int> (int, int);
+template int xmax<int> (int, int);
+template long xmin<long> (long, long);
+template long xmax<long> (long, long);
+
 INSTANTIATE_MARRAY_FRIENDS (int, OCTAVE_API)
 INSTANTIATE_MARRAY_FRIENDS (long, OCTAVE_API)
 
--- a/liboctave/MArray-s.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/MArray-s.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -31,6 +31,11 @@
 
 template class OCTAVE_API MArray<short>;
 
+// Explicit instantiation, as this seems to be required by weird compilers
+// like MSVC. This should be harmless on other compilers.
+template short xmin<short> (short, short);
+template short xmax<short> (short, short);
+
 INSTANTIATE_MARRAY_FRIENDS (short, OCTAVE_API)
 
 #include "MDiagArray2.h"
--- a/liboctave/Sparse-op-defs.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/Sparse-op-defs.h	Sat Oct 22 16:22:04 2011 -0700
@@ -1119,7 +1119,7 @@
       gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
     else \
       { \
-        if (do_mx_check (m1, mx_inline_all_finite)) \
+        if (do_mx_check (m1, mx_inline_all_finite<M1::element_type>)) \
           { \
             /* Sparsity pattern is preserved. */ \
             octave_idx_type m2_nz = m2.nnz (); \
@@ -1335,12 +1335,12 @@
   }
 
 // sm .* m preserves sparsity if m contains no Infs nor Nans.
-#define SPARSE_SMM_BIN_OP_2_CHECK_product \
-  do_mx_check (m2, mx_inline_all_finite)
+#define SPARSE_SMM_BIN_OP_2_CHECK_product(ET) \
+  do_mx_check (m2, mx_inline_all_finite<ET>)
 
 // sm ./ m preserves sparsity if m contains no NaNs or zeros.
-#define SPARSE_SMM_BIN_OP_2_CHECK_quotient \
-  ! do_mx_check (m2, mx_inline_any_nan) && m2.nnz () == m2.numel ()
+#define SPARSE_SMM_BIN_OP_2_CHECK_quotient(ET) \
+  ! do_mx_check (m2, mx_inline_any_nan<ET>) && m2.nnz () == m2.numel ()
 
 #define SPARSE_SMM_BIN_OP_2(R, F, OP, M1, M2) \
   R \
@@ -1360,7 +1360,7 @@
       gripe_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc); \
     else \
       { \
-        if (SPARSE_SMM_BIN_OP_2_CHECK_ ## F) \
+        if (SPARSE_SMM_BIN_OP_2_CHECK_ ## F(M2::element_type)) \
           { \
             /* Sparsity pattern is preserved. */ \
             octave_idx_type m1_nz = m1.nnz (); \
--- a/liboctave/boolNDArray.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/boolNDArray.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -40,7 +40,7 @@
 boolNDArray
 boolNDArray::operator ! (void) const
 {
-  return do_mx_unary_op<bool> (*this, mx_inline_not);
+  return do_mx_unary_op<bool, bool> (*this, mx_inline_not);
 }
 
 boolNDArray&
--- a/liboctave/bsxfun-defs.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/bsxfun-defs.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -69,8 +69,7 @@
   R *rvec = retval.fortran_vec ();
 
   // Fold the common leading dimensions.
-  int start;
-  octave_idx_type ldr = 1;
+  octave_idx_type start, ldr = 1;
   for (start = 0; start < nd; start++)
     {
       if (dvx(start) != dvy(start))
@@ -98,7 +97,7 @@
         }
       dim_vector cdvx = dvx.cumulative (), cdvy = dvy.cumulative ();
       // Nullify singleton dims to achieve a spread effect.
-      for (int i = std::max (start, 1); i < nd; i++)
+      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)
         {
           if (dvx(i) == 1)
             cdvx(i-1) = 0;
@@ -176,7 +175,7 @@
 
       dim_vector cdvx = dvx.cumulative ();
       // Nullify singleton dims to achieve a spread effect.
-      for (int i = std::max (start, 1); i < nd; i++)
+      for (int i = std::max (start, octave_idx_type (1)); i < nd; i++)
         {
           if (dvx(i) == 1)
             cdvx(i-1) = 0;
--- a/liboctave/fCRowVector.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/fCRowVector.h	Sat Oct 22 16:22:04 2011 -0700
@@ -129,9 +129,9 @@
 
 // row vector by column vector -> scalar
 
-FloatComplex operator * (const FloatComplexRowVector& a, const ColumnVector& b);
+FloatComplex OCTAVE_API operator * (const FloatComplexRowVector& a, const ColumnVector& b);
 
-FloatComplex operator * (const FloatComplexRowVector& a, const FloatComplexColumnVector& b);
+FloatComplex OCTAVE_API operator * (const FloatComplexRowVector& a, const FloatComplexColumnVector& b);
 
 // other operations
 
--- a/liboctave/idx-vector.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/idx-vector.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -27,7 +27,6 @@
 #endif
 
 #include <cstdlib>
-#include <memory>
 
 #include <iostream>
 
--- a/liboctave/idx-vector.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/idx-vector.h	Sat Oct 22 16:22:04 2011 -0700
@@ -29,6 +29,7 @@
 
 #include <algorithm>
 #include <iosfwd>
+#include <memory>
 
 #include "dim-vector.h"
 #include "oct-inttypes.h"
@@ -63,6 +64,8 @@
       class_mask
     };
 
+  template<class T> friend class std::auto_ptr;
+
 private:
 
   class OCTAVE_API idx_base_rep
--- a/liboctave/kpse.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/kpse.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -49,8 +49,8 @@
 #include <fcntl.h>
 #include <dirent.h>
 #elif defined(WIN32)
+#ifndef _MSC_VER
 #define __STDC__ 1
-#ifndef _MSC_VER
 #include "win32lib.h"
 #endif
 #endif /* not WIN32 */
--- a/liboctave/lo-cieee.c	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/lo-cieee.c	Sat Oct 22 16:22:04 2011 -0700
@@ -47,11 +47,6 @@
 #define HAVE_FINITE 1
 #endif
 
-#if ! defined (HAVE_COPYSIGN) && defined (HAVE__COPYSIGN)
-#define copysign _copysign
-#define HAVE_COPYSIGN 1
-#endif
-
 #if defined (_AIX) && defined (__GNUG__)
 #undef finite
 #define finite(x) ((x) < DBL_MAX && (x) > -DBL_MAX)
--- a/liboctave/lo-mappers.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/lo-mappers.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -48,6 +48,12 @@
   return gnulib::trunc (x);
 }
 
+double
+xcopysign (double x, double y)
+{
+  return gnulib::copysign (x, y);
+}
+
 double xfloor (double x)
 {
   return gnulib::floor (x);
@@ -268,6 +274,12 @@
 }
 
 float
+xcopysign (float x, float y)
+{
+  return gnulib::copysignf (x, y);
+}
+
+float
 xround (float x)
 {
   return gnulib::round (x);
--- a/liboctave/lo-mappers.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/lo-mappers.h	Sat Oct 22 16:22:04 2011 -0700
@@ -31,7 +31,7 @@
 
 // Double Precision
 extern OCTAVE_API double xtrunc (double x);
-inline double xcopysign (double x, double y) { return copysign (x, y); }
+extern OCTAVE_API double xcopysign (double x, double y);
 inline double xceil (double x) { return ceil (x); }
 extern OCTAVE_API double xfloor (double x);
 inline double arg (double x) { return atan2 (0.0, x); }
@@ -117,7 +117,7 @@
 
 // Single Precision
 extern OCTAVE_API float xtrunc (float x);
-inline float xcopysign (float x, float y) { return copysignf (x, y); }
+extern OCTAVE_API float xcopysign (float x, float y);
 inline float xceil (float x) { return ceilf (x); }
 inline float xfloor (float x) { return floorf (x); }
 inline float arg (float x) { return atan2f (0.0f, x); }
@@ -227,7 +227,6 @@
 extern OCTAVE_API int NINT (float x);
 
 template <typename T>
-OCTAVE_API
 T
 X_NINT (T x)
 {
@@ -305,7 +304,6 @@
 }
 
 template <typename T>
-OCTAVE_API
 T
 xmod (T x, T y)
 {
@@ -353,7 +351,6 @@
 }
 
 template <typename T>
-OCTAVE_API
 T
 xrem (T x, T y)
 {
--- a/liboctave/oct-inttypes.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/liboctave/oct-inttypes.h	Sat Oct 22 16:22:04 2011 -0700
@@ -452,7 +452,7 @@
 
   // Returns 1 for negative number, 0 otherwise.
   static T
-  signbit (T x)
+  __signbit (T x)
     {
 #ifdef HAVE_FAST_INT_OPS
       return static_cast<UT> (x) >> std::numeric_limits<T>::digits;
@@ -496,7 +496,7 @@
   signum (T x)
     {
       // With modest optimizations, this will compile without a jump.
-      return ((x > 0) ? 1 : 0) - signbit (x);
+      return ((x > 0) ? 1 : 0) - __signbit (x);
     }
 
   // FIXME -- we do not have an authority what signed shifts should
@@ -544,7 +544,7 @@
       T ux = u ^ x, uy = u ^ y;
       if ((ux & uy) < 0)
         {
-          u = octave_int_base<T>::max_val () + signbit (~u);
+          u = octave_int_base<T>::max_val () + __signbit (~u);
         }
       return u;
 #else
@@ -585,7 +585,7 @@
       T ux = u ^ x, uy = u ^ ~y;
       if ((ux & uy) < 0)
         {
-          u = octave_int_base<T>::max_val () + signbit (~u);
+          u = octave_int_base<T>::max_val () + __signbit (~u);
         }
       return u;
 #else
@@ -651,7 +651,7 @@
               z = x / y;
               T w = -octave_int_abs (x % y); // Can't overflow, but std::abs (x) can!
               if (w <= y - w)
-                z -= 1 - (signbit (x) << 1);
+                z -= 1 - (__signbit (x) << 1);
             }
         }
       else
@@ -663,7 +663,7 @@
           T w = octave_int_abs (x % y);
 
           if (w >= y - w)
-            z += 1 - (signbit (x) << 1);
+            z += 1 - (__signbit (x) << 1);
         }
       return z;
     }
--- a/m4/acinclude.m4	Wed Oct 12 13:45:43 2011 -0500
+++ b/m4/acinclude.m4	Sat Oct 22 16:22:04 2011 -0700
@@ -565,7 +565,7 @@
 AC_DEFUN([OCTAVE_PROG_GHOSTSCRIPT], [
   case "$canonical_host_type" in
     *-*-mingw* | *-*-msdosmsvc)
-      gs_names="gswin32c gs"
+      gs_names="gswin32c gs mgs"
     ;;
     *)
       gs_names="gs"
--- a/scripts/image/imshow.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/image/imshow.m	Sat Oct 22 16:22:04 2011 -0700
@@ -115,6 +115,12 @@
     endif
   endwhile
 
+  ## Check for complex images.
+  if (iscomplex (im))
+    warning ("imshow: only showing real part of complex image");
+    im = real (im);
+  endif
+
   ## Set default display range if display_range not set yet.
   if (isempty (display_range))
     display_range = [min(im(:)), max(im(:))];
@@ -130,12 +136,6 @@
     endswitch
   endif
 
-  ## Check for complex images.
-  if (iscomplex (im))
-    warning ("imshow: only showing real part of complex image");
-    im = real (im);
-  endif
-
   nans = isnan (im(:));
   if (any (nans))
     warning ("Octave:imshow-NaN",
--- a/scripts/io/strread.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/io/strread.m	Sat Oct 22 16:22:04 2011 -0700
@@ -226,15 +226,24 @@
         endswitch
       case "delimiter"
         delimiter_str = varargin{n+1};
+        if (is_sq_string (delimiter_str))
+          delimiter_str = do_string_escapes (delimiter_str);
+        endif
       case "emptyvalue"
         numeric_fill_value = varargin{n+1};
       case "expchars"
         warning ('strread: property "expchars" is not implemented');
       case "whitespace"
         white_spaces = varargin{n+1};
+        if (is_sq_string (white_spaces))
+          white_spaces = do_string_escapes (white_spaces);
+        endif
       ## The following parameters are specific to textscan and textread
       case "endofline"
         eol_char = varargin{n+1};
+        if (is_sq_string (eol_char))
+          eol_char = do_string_escapes (eol_char);
+        endif
       case "returnonerror"
         err_action = varargin{n+1};
       case "multipledelimsasone"
@@ -800,3 +809,10 @@
 %! assert (c', [13, 24, 34]);
 %! assert (d', [15, 25, 35]);
 
+%% delimiter as sq_string and dq_string
+%! assert (strread ("1\n2\n3", "%d", "delimiter", "\n"),
+%!         strread ("1\n2\n3", "%d", "delimiter", '\n'))
+
+%% whitespace as sq_string and dq_string
+%! assert (strread ("1\b2\r3\b4\t5", "%d", "whitespace", "\b\r\n\t"),
+%!         strread ("1\b2\r3\b4\t5", "%d", "whitespace", '\b\r\n\t'))
--- a/scripts/plot/axes.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/axes.m	Sat Oct 22 16:22:04 2011 -0700
@@ -28,8 +28,7 @@
 function h = axes (varargin)
 
   if (nargin == 0 || nargin > 1)
-    ## make default axes object, and make it the current axes for the
-    ## current figure.
+    ## Create an axes object.
     idx = find (strcmpi (varargin(1:2:end), "parent"), 1, "first");
     if (! isempty (idx) && length (varargin) >= 2*idx)
       cf = varargin{2*idx};
@@ -38,16 +37,19 @@
       cf = gcf ();
     endif
     tmp = __go_axes__ (cf, varargin{:});
-    set (ancestor (cf, "figure"), "currentaxes", tmp);
+    if (__is_handle_visible__ (tmp))
+      set (ancestor (cf, "figure"), "currentaxes", tmp);
+    endif
   else
-    ## arg is axes handle, make it the current axes for the current
-    ## figure.
+    ## arg is axes handle.
     tmp = varargin{1};
     if (length(tmp) == 1 && ishandle (tmp)
         && strcmp (get (tmp, "type"), "axes"))
-      parent = ancestor (tmp, "figure");
-      set (0, "currentfigure", parent);
-      set (parent, "currentaxes", tmp);
+      if (__is_handle_visible__ (tmp))
+        parent = ancestor (tmp, "figure");
+        set (0, "currentfigure", parent);
+        set (parent, "currentaxes", tmp);
+      endif
     else
       error ("axes: expecting argument to be a scalar axes handle");
     endif
--- a/scripts/plot/axis.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/axis.m	Sat Oct 22 16:22:04 2011 -0700
@@ -502,3 +502,48 @@
 %! loglog (1:20, "-s")
 %! axis tight
 
+%!demo
+%! x = -10:0.1:10;
+%! y = sin(x)./(1+abs(x)) + x*0.1 - .4;
+%! plot (x, y)
+%! title ("no plot box")
+%! set (gca, "xaxislocation", "zero")
+%! set (gca, "yaxislocation", "zero")
+%! box off
+
+%!demo
+%! x = -10:0.1:10;
+%! y = sin(x)./(1+abs(x)) + x*0.1 - .4;
+%! plot (x, y)
+%! title ("no plot box")
+%! set (gca, "xaxislocation", "zero")
+%! set (gca, "yaxislocation", "left")
+%! box off
+
+%!demo
+%! x = -10:0.1:10;
+%! y = sin(x)./(1+abs(x)) + x*0.1 - .4;
+%! plot (x, y)
+%! title ("no plot box")
+%! set (gca, "xaxislocation", "zero")
+%! set (gca, "yaxislocation", "right")
+%! box off
+
+%!demo
+%! x = -10:0.1:10;
+%! y = sin(x)./(1+abs(x)) + x*0.1 - .4;
+%! plot (x, y)
+%! title ("no plot box")
+%! set (gca, "xaxislocation", "bottom")
+%! set (gca, "yaxislocation", "zero")
+%! box off
+
+%!demo
+%! x = -10:0.1:10;
+%! y = sin(x)./(1+abs(x)) + x*0.1 - .4;
+%! plot (x, y)
+%! title ("no plot box")
+%! set (gca, "xaxislocation", "top")
+%! set (gca, "yaxislocation", "zero")
+%! box off
+
--- a/scripts/plot/clf.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/clf.m	Sat Oct 22 16:22:04 2011 -0700
@@ -21,17 +21,19 @@
 ## @deftypefnx {Function File} {} clf ("reset")
 ## @deftypefnx {Function File} {} clf (@var{hfig})
 ## @deftypefnx {Function File} {} clf (@var{hfig}, "reset")
+## @deftypefnx {Function File} {@var{h} =} clf (@dots{})
 ## Clear the current figure window.  @code{clf} operates by deleting child
 ## graphics objects with visible handles (@code{handlevisibility} = on).
 ## If @var{hfig} is specified operate on it instead of the current figure.
 ## If the optional argument @code{"reset"} is specified, all objects including
-## those with hidden handles are deleted.
+## those with hidden handles are deleted.  If an output value is
+## requested, return the handle of the figure window that was cleared.
 ## @seealso{cla, close, delete}
 ## @end deftypefn
 
 ## Author: jwe
 
-function clf (varargin)
+function retval = clf (varargin)
 
   if (nargin > 2)
     print_usage ();
@@ -74,6 +76,10 @@
   ## Delete the children.
   delete (hc);
 
+  if (nargout > 0)
+    retval = hfig;
+  endif
+
 endfunction
 
 %!test
--- a/scripts/plot/figure.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/figure.m	Sat Oct 22 16:22:04 2011 -0700
@@ -73,7 +73,9 @@
   endif
 
   cf = get (0, "currentfigure");
-  __add_default_menu__ (cf);
+  if (strcmp (get (cf, "__graphics_toolkit__"), "fltk"))
+    __add_default_menu__ (cf);
+  endif
 
   if (nargout > 0)
     h = f;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/guidata.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,52 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{data} =} guidata (@var{handle})
+## @deftypefnx {Function File} guidata (@var{handle}, @var{data})
+## @end deftypefn
+
+## Author: goffioul
+
+function varargout = guidata (varargin)
+
+  if (nargin == 1 || nargin == 2)
+    h = varargin{1};
+    if (ishandle (h))
+      h = ancestor (h, "figure");
+      if (! isempty (h))
+        if (nargin == 1)
+          varargout{1} = get (h, "__guidata__");
+        else
+          data = varargin{2};
+          set (h, "__guidata__", data);
+          if (nargout == 1)
+            varargout{1} = data;
+          endif
+        endif
+      else
+        error ("no ancestor figure found");
+      endif
+    else
+      error ("invalid object handle");
+    endif
+  else
+    print_usage ();
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/guihandles.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,70 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{hdata} =} guihandles (@var{handle})
+## @deftypefnx {Function File} {@var{hdata} =} guihandles
+## @end deftypefn
+
+## Author: goffioul
+
+function hdata = guihandles (varargin)
+
+  hdata = [];
+
+  if (nargin == 0 || nargin == 1)
+    if (nargin == 1)
+      h = varargin{1};
+      if (ishandle (h))
+        h = ancestor (h, "figure");
+        if (isempty (h))
+          error ("no ancestor figure found");
+        endif
+      else
+        error ("invalid object handle");
+      endif
+    else
+      h = gcf ();
+    endif
+    hdata = __make_guihandles_struct__ (h, hdata);
+  else
+    print_usage ();
+  endif
+
+endfunction
+
+function hdata = __make_guihandles_struct__ (h, hdata)
+
+  tag = get (h, "tag");
+  if (! isempty (tag))
+    if (isfield (hdata, tag))
+      hdata.(tag) = [hdata.(tag), h];
+    else
+      try
+        hdata.(tag) = h;
+      catch
+      end_try_catch
+    endif
+  endif
+
+  kids = allchild (h);
+  for i = 1 : length (kids)
+    hdata = __make_guihandles_struct__ (kids(i), hdata);
+  endfor
+
+endfunction
--- a/scripts/plot/ishold.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/ishold.m	Sat Oct 22 16:22:04 2011 -0700
@@ -30,16 +30,12 @@
 function retval = ishold (h)
 
   if (nargin == 0)
-    ax = gca ();
     fig = gcf ();
+    ax = get (fig, "currentaxes");
   elseif (nargin == 1)
     if (ishandle (h))
       if (isfigure (h))
         ax = get (h, "currentaxes");
-        if (isempty (ax))
-          ax = __go_axes__ (h);
-          set (h, "currentaxes", ax);
-        endif
         fig = h;
       elseif (strcmpi (get (h, "type"), "axes"))
         ax = h;
@@ -55,13 +51,16 @@
   endif
 
   retval = (strcmpi (get (fig, "nextplot"), "add")
-            && strcmpi (get (ax, "nextplot"), "add"));
+            && ! isempty (ax) && strcmpi (get (ax, "nextplot"), "add"));
 
 endfunction
 
 %!test
 %! hf = figure ("visible", "off");
 %! unwind_protect
+%!   assert (!ishold);
+%!   assert (isempty (get (hf, "currentaxes")));
+%!   assert (get (hf, "NextPlot"), "add");
 %!   l = plot ([0 1]);
 %!   assert (!ishold);
 %!   assert (!ishold (gca));
--- a/scripts/plot/module.mk	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/module.mk	Sat Oct 22 16:22:04 2011 -0700
@@ -19,6 +19,7 @@
   plot/private/__errcomm__.m \
   plot/private/__errplot__.m \
   plot/private/__ezplot__.m \
+  plot/private/__file_filter__.m \
   plot/private/__fltk_file_filter__.m \
   plot/private/__fltk_ginput__.m \
   plot/private/__fltk_print__.m \
@@ -34,6 +35,7 @@
   plot/private/__go_draw_axes__.m \
   plot/private/__go_draw_figure__.m \
   plot/private/__interp_cube__.m \
+  plot/private/__is_function__.m \
   plot/private/__line__.m \
   plot/private/__marching_cube__.m \
   plot/private/__next_line_color__.m \
@@ -47,6 +49,9 @@
   plot/private/__scatter__.m \
   plot/private/__stem__.m \
   plot/private/__tight_eps_bbox__.m \
+  plot/private/__uigetdir_fltk__.m \
+  plot/private/__uigetfile_fltk__.m \
+  plot/private/__uiputfile_fltk__.m \
   plot/private/__uiobject_split_args__.m
 
 plot_FCN_FILES = \
@@ -104,6 +109,8 @@
   plot/graphics_toolkit.m \
   plot/grid.m \
   plot/gtext.m \
+  plot/guidata.m \
+  plot/guihandles.m \
   plot/hggroup.m \
   plot/hidden.m \
   plot/hist.m \
@@ -175,12 +182,16 @@
   plot/trimesh.m \
   plot/triplot.m \
   plot/trisurf.m \
+  plot/uicontextmenu.m \
   plot/uicontrol.m \
   plot/uigetdir.m \
   plot/uigetfile.m \
   plot/uimenu.m \
   plot/uipanel.m \
+  plot/uipushtool.m \
   plot/uiputfile.m \
+  plot/uitoggletool.m \
+  plot/uitoolbar.m \
   plot/view.m \
   plot/waitforbuttonpress.m \
   plot/whitebg.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__file_filter__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,93 @@
+## Copyright (C) 2010-2011 Kai Habel
+##
+## 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} {} __file_filter__ (@var{file_filter})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Kai Habel
+
+function [retval, defname, defdir] = __file_filter__ (file_filter, name)
+
+  revtal = {};
+  defname = "";
+  defdir = "";
+
+  if (iscell (file_filter))
+    [r, c] = size (file_filter);
+    if (c != 1 && c != 2)
+      error ("%s: invalid filter specification", name);
+    endif
+    if (c == 1)
+      retval = cell (r, 2);
+      for i = 1:r
+        retval{i, 1} = file_filter{i};
+        retval{i, 2} = __default_filtername__ (file_filter{i});
+      endfor
+    else
+      retval = file_filter;
+      for i = 1:r
+        if (isempty (retval{i, 2}))
+          retval{i, 2} = __default_filtername__ (retval{i, 1});
+        endif
+      endfor
+    endif
+  elseif (ischar (file_filter))
+    [defdir, fname, fext] = fileparts (file_filter);
+    if (! strcmp (fname, "*"))
+      defname = strcat (fname, fext);
+    endif
+    if (length (fext) > 0)
+      fext = strcat ("*", fext);
+      retval = {fext, __default_filtername__(fext)};
+    endif
+  endif
+
+  retval(end+1,:) = {"*", __default_filtername__("*")};
+
+endfunction
+
+function name = __default_filtername__ (filterext)
+
+  name = "";
+
+  switch (filterext)
+    case "*"
+      name = "All Files";
+    case "*.m"
+      name = "Octave Source Files";
+    case "*.c"
+      name = "C Source Files";
+    case {"*.cc" "*.c++" "*.cpp"}
+      name = "C++ Source Files";
+    case "*.oct"
+      name = "Octave Compiled Files";
+  endswitch
+
+  if (isempty (name))
+    extlist = strsplit(filterext, ";");
+    extlist = strrep (extlist, "*.", "");
+    extlist = toupper (extlist);
+    extlist(end+1, :) = repmat ({","}, 1, length (extlist));
+    extlist = strcat (extlist{:});
+    extlist = extlist(1:end-1);
+    name = strcat (extlist, "-Files");
+  endif
+
+endfunction
--- a/scripts/plot/private/__fltk_file_filter__.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/private/__fltk_file_filter__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -1,4 +1,4 @@
-## Copyright (C) 2010-2011 Kai Habel
+## Copyright (C) 2011 Michael Goffioul
 ##
 ## This file is part of Octave.
 ##
@@ -17,56 +17,48 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} __fltk_file_filter__ (@var{file_filter})
+## @deftypefn  {Function File} {@var{filterspec} =} __fltk_file_filter__ (@var{filter})
 ## Undocumented internal function.
 ## @end deftypefn
 
-## Author: Kai Habel
+## Author: Michael Goffioul
 
 function retval = __fltk_file_filter__ (file_filter)
-  # converts octave's file filter format into fltk's.
-  retval = "";
-  if (iscell (file_filter))
-    [r, c] = size (file_filter);
-    if ((c == 0) || (c > 2))
-      error ("expecting 1 or to 2 columns for file filter cell");
-    endif
-    fltk_str = "";
-    for idx = 1 : r
 
-      curr_ext = file_filter{idx, 1};
-      curr_ext = strsplit (curr_ext, ";");
+  retval = "";
+  [r, c] = size (file_filter);
+  if ((c == 0) || (c > 2))
+    error ("expecting 1 or to 2 columns for file filter cell");
+  endif
+  fltk_str = "";
+  for idx = 1 : r
 
-      if (length (curr_ext) > 1)
-        curr_ext = regexprep (curr_ext, '\*\.', ',');
-        curr_ext = strcat (curr_ext{:})(2 : end);
-        curr_ext = strcat ("*.{", curr_ext, "}");
-      else
-        curr_ext = curr_ext{:};
-      endif
-
-      curr_desc = strcat (curr_ext(3:end), "-Files");
+    curr_ext = file_filter{idx, 1};
+    curr_ext = strsplit (curr_ext, ";");
 
-      if (c == 2)
-        curr_desc = file_filter{idx, 2};
-        curr_desc = regexprep (curr_desc, '\(', '<');
-        curr_desc = regexprep (curr_desc, '\)', '>');
-      endif
+    if (length (curr_ext) > 1)
+      curr_ext = regexprep (curr_ext, '\*\.', ',');
+      curr_ext = strcat (curr_ext{:})(2 : end);
+      curr_ext = strcat ("*.{", curr_ext, "}");
+    else
+      curr_ext = curr_ext{:};
+    endif
 
-      if (length (fltk_str) > 0)
-        fltk_str = strcat (fltk_str, "\t", curr_desc, " (", curr_ext, ")");
-      else
-        fltk_str = strcat (curr_desc, " (", curr_ext, ")");
-      endif
+    curr_desc = strcat (curr_ext(3:end), "-Files");
 
-    endfor
-    retval = fltk_str;
-  elseif (ischar (file_filter))
-    if (!isdir (file_filter))
-      [fdir, fname, fext] = fileparts (file_filter);
-      if (length (fext) > 0)
-        retval = strcat ("*", fext, "\t*");
-      endif
+    if (c == 2)
+      curr_desc = file_filter{idx, 2};
+      curr_desc = regexprep (curr_desc, '\(', '<');
+      curr_desc = regexprep (curr_desc, '\)', '>');
     endif
-  endif
+
+    if (length (fltk_str) > 0)
+      fltk_str = strcat (fltk_str, "\t", curr_desc, " (", curr_ext, ")");
+    else
+      fltk_str = strcat (curr_desc, " (", curr_ext, ")");
+    endif
+
+  endfor
+  retval = fltk_str;
+
 endfunction
--- a/scripts/plot/private/__go_draw_axes__.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/private/__go_draw_axes__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -1460,23 +1460,57 @@
             fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
                      axis_obj.tickdir);
             fputs (plot_stream, "set border 12;\n");
-          else
+          elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
             fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
                      axis_obj.tickdir);
             fputs (plot_stream, "set border 9;\n");
+          else # xaxislocation == zero
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 8;\n");
+            fprintf (plot_stream, "set xzeroaxis lt -1 lw %f;\n",
+                     axis_obj.linewidth);
           endif
-        else
+        elseif (strcmpi (axis_obj.yaxislocation, "left"))
           fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
                    axis_obj.tickdir);
           if (strcmpi (axis_obj.xaxislocation, "top"))
             fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
                      axis_obj.tickdir);
             fputs (plot_stream, "set border 6;\n");
-          else
+          elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
             fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
                      axis_obj.tickdir);
             fputs (plot_stream, "set border 3;\n");
+          else # xaxislocation == zero
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 2;\n");
+            fprintf (plot_stream, "set xzeroaxis lt -1 lw %f;\n",
+                     axis_obj.linewidth);
           endif
+        else # yaxislocation == zero
+          fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
+                   axis_obj.tickdir);
+          if (strcmpi (axis_obj.xaxislocation, "top"))
+            fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 4;\n");
+          elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "set border 1;\n");
+          else # xaxislocation == zero
+            fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
+                     axis_obj.tickdir);
+            fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                     axis_obj.tickdir);
+            fputs (plot_stream, "unset border;\n");
+            fprintf (plot_stream, "set xzeroaxis lt -1 lw %f;\n",
+                     axis_obj.linewidth);
+          endif
+          fprintf (plot_stream, "set yzeroaxis lt -1 lw %f;\n",
+                   axis_obj.linewidth);
         endif
       endif
     endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__is_function__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,31 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{result} =} __is_function__ (@var{func})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Michael Goffioul
+
+function result = __is_function__ (func)
+
+  existval = exist (func);
+  result = (existval == 2 || existval == 3 || existval == 5 || existval == 6);
+
+endfunction
--- a/scripts/plot/private/__patch__.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/private/__patch__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -67,9 +67,15 @@
       elseif (nargin > 3 && all (is_numeric_arg(1:3)))
         x = varargin{1};
         y = varargin{2};
-        z = [];
-        c = varargin{3};
         iarg = 4;
+        if (rem (nargin - iarg, 2) == 1)
+          c = varargin {iarg};
+          z = varargin{3};
+          iarg = 5;
+        else
+          z = [];
+          c = varargin{3};
+        endif
       elseif (nargin > 2 && all (is_numeric_arg(1:2)))
         x = varargin{1};
         y = varargin{2};
@@ -134,17 +140,13 @@
             args{8} = "interp";
             args{9} = "cdata";
             args{10} = [];
+          elseif (isequal (size (c), size (x)) && isequal (size (c), size (y)))
+            args{7} = "facecolor";
+            args{8} = "interp";
+            args{9} = "cdata";
+            args{10} = c;
           else
-            if (rows (c) != rows (x) || rows (c) != length (y))
-              error ("patch: size of x, y, and c must be equal");
-            elseif (rows (c) == rows (x) && rows (c) == rows (y))
-              args{7} = "facecolor";
-              args{8} = "interp";
-              args{9} = "cdata";
-              args{10} = c;
-            else
-              error ("patch: color value not valid");
-            endif
+            error ("patch: size of x, y, and c must be equal");
           endif
         endif
       elseif (ischar (c) && rem (nargin - iarg, 2) == 0)
@@ -320,7 +322,7 @@
   elseif (isvector (c))
     fvc = c(:);
   else
-    fvc = c.';
+    fvc = c.'(:);
   endif
 
   args = {"faces", faces, "vertices", vert, "facevertexcdata", fvc, args{:}};
--- a/scripts/plot/private/__print_parse_opts__.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/private/__print_parse_opts__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -449,7 +449,7 @@
       gs_binaries = horzcat (gs_binaries, {"gs", "gs.exe"});
     else
       ## pc - Includes Win32 and mingw.
-      gs_binaries = horzcat (gs_binaries, {"gs.exe", "gswin32c.exe"});
+      gs_binaries = horzcat (gs_binaries, {"gs.exe", "gswin32c.exe", "mgs.exe"});
     endif
     n = 0;
     while (n < numel (gs_binaries) && isempty (ghostscript_binary))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__uigetdir_fltk__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,34 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{dirname} =} __uigetdir_fltk__ (@var{start_path}, @var{dialog_title})
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Michael Goffioul
+
+function dirname = __uigetdir_fltk__ (start_path, dialog_title)
+
+  if (exist("__fltk_uigetfile__") != 3)
+    error ("uigetdir: fltk graphics toolkit required");
+  endif
+
+  dirname = __fltk_uigetfile__ ("", dialog_title, start_path, [240, 120], "dir");
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__uigetfile_fltk__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,38 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{fname}, @var{fpath}, @var{fltidx}] =} __uigetfile_fltk__ ()
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Michael Goffioul
+
+function [retval, retpath, retindex] = __uigetfile_fltk__ (filters, title, defval, position, multiselect, defdir)
+
+  if (exist("__fltk_uigetfile__") != 3)
+    error ("uigetfile: fltk graphics toolkit required");
+  endif
+
+  filters = __fltk_file_filter__ (filters);
+  if (length (defdir) > 0)
+    defval = fullfile (defdir, defval);
+  endif
+  [retval, retpath, retindex] = __fltk_uigetfile__ (filters, title, defval, position, multiselect);
+
+endfunction
--- a/scripts/plot/private/__uiobject_split_args__.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/private/__uiobject_split_args__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -17,28 +17,30 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{p}, @var{args}] =} __uiobject_split_args__ (@var{who}, @dots{})
+## @deftypefn  {Function File} {[@var{p}, @var{args}] =} __uiobject_split_args__ (@var{who}, @var{args}, @var{parent_type}, @var{use_gcf})
 ## @end deftypefn
 
 ## Author: goffioul
 
-function [parent, args] = __uiobject_split_args__ (who, varargin)
+function [parent, args] = __uiobject_split_args__ (who, in_args, parent_type = {}, use_gcf = 1)
 
   parent = [];
   args = {};
   offset = 1;
 
-  if (nargin > 1)
-    if (ishandle (varargin{1}))
-      parent = varargin{1};
+  if (! isempty (in_args))
+    if (ishandle (in_args{1}))
+      parent = in_args{1};
       offset = 2;
-    elseif (! ischar (varargin{1}))
+    elseif (! ischar (in_args{1}))
       error ("%s: invalid parent handle.", who);
     endif
 
-    if (nargin > offset)
-      args = varargin(offset:end);
-    endif
+    args = in_args(offset:end);
+  endif
+
+  if (rem (length (args), 2))
+    error ("%s: expecting PROPERTY/VALUE pairs", who);
   endif
 
   if (! isempty (args))
@@ -53,10 +55,11 @@
   endif
 
   if (! isempty (parent))
-    if (isempty (find (strcmpi (get (parent, "type"), {"figure", "uipanel", "uibuttongroup"}))))
-      error ("%s: invalid parent, the parent must be a figure, uipanel or uibuttongroup handle", who);
+    if (! isempty (parent_type) && isempty (find (strcmpi (get (parent, "type"), parent_type))))
+      error ("%s: invalid parent, the parent type must be: %s", ...
+             who, sprintf ("%s, ", parent_type{:})(1:end-2));
     endif
-  else
+  elseif (use_gcf)
     parent = gcf ();
   endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/private/__uiputfile_fltk__.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,38 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{fname}, @var{fpath}, @var{fltidx}] =} __uiputfile_fltk__ ()
+## Undocumented internal function.
+## @end deftypefn
+
+## Author: Michael Goffioul
+
+function [retval, retpath, retindex] = __uiputfile_fltk__ (filters, title, defval, position, tag, defdir)
+
+  if (exist("__fltk_uigetfile__") != 3)
+    error ("uiputfile: fltk graphics toolkit required");
+  endif
+
+  filters = __fltk_file_filter__ (filters);
+  if (length (defdir) > 0)
+    defval = fullfile (defdir, defval);
+  endif
+  [retval, retpath, retindex] = __fltk_uigetfile__ (filters, title, defval, position, tag);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/uicontextmenu.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,30 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{handle} =} uicontextmenu ('Name', value, @dots{})
+## @end deftypefn
+
+## Author: goffioul
+
+function handle = uicontextmenu (varargin)
+
+  [h, args] = __uiobject_split_args__ ("uicontextmenu", varargin, {"figure"});
+  handle = __go_uicontextmenu__ (h, args{:});
+
+endfunction
--- a/scripts/plot/uicontrol.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uicontrol.m	Sat Oct 22 16:22:04 2011 -0700
@@ -29,7 +29,7 @@
   if (nargin == 1 && ishandle (varargin{1}) && strcmpi (get (varargin{1}, "type"), "uicontrol"))
     error ("uicontrol focusing not implemented yet.");
   else
-    [h, args] = __uiobject_split_args__ ("uicontrol", varargin{:});
+    [h, args] = __uiobject_split_args__ ("uicontrol", varargin, {"figure", "uipanel", "uibuttongroup"});
     handle = __go_uicontrol__ (h, args{:});
   endif
 
--- a/scripts/plot/uigetdir.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uigetdir.m	Sat Oct 22 16:22:04 2011 -0700
@@ -28,10 +28,19 @@
 
 ## Author: Kai Habel
 
-function dirname = uigetdir (init_path = pwd, dialog_name = "Choose directory?")
+function dirname = uigetdir (init_path = pwd, dialog_name = "Select Directory to Open")
 
-  if (exist("__fltk_uigetfile__") != 3)
-    error ("uigetfile: fltk graphics toolkit required");
+  defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
+  funcname = ["__uigetdir_", defaulttoolkit, "__"];
+  functype = exist (funcname);
+  if (! __is_function__ (funcname))
+    funcname = "__uigetdir_fltk__";
+    if (! __is_function__ (funcname))
+      error ("uigetdir: fltk graphics toolkit required");
+    elseif (! strcmp (defaulttoolkit, "gnuplot"))
+      warning ("uigetdir: no implementation for toolkit `%s', using `fltk' instead",
+               defaulttoolkit);
+    endif
   endif
 
   if (nargin > 2)
@@ -45,7 +54,7 @@
   if (!isdir (init_path))
     init_path = fileparts (init_path);
   endif
-  dirname = __fltk_uigetfile__ ("", dialog_name, init_path, [240, 120], "dir");
+  dirname = feval (funcname, init_path, dialog_name);
 
 endfunction
 
--- a/scripts/plot/uigetfile.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uigetfile.m	Sat Oct 22 16:22:04 2011 -0700
@@ -64,22 +64,32 @@
 
 function [retfile, retpath, retindex] = uigetfile (varargin)
 
-  if (exist("__fltk_uigetfile__") != 3)
-    error ("uigetfile: fltk graphics toolkit required");
+  defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
+  funcname = ["__uigetfile_", defaulttoolkit, "__"];
+  functype = exist (funcname);
+  if (! __is_function__ (funcname))
+    funcname = "__uigetfile_fltk__";
+    if (! __is_function__ (funcname))
+      error ("uigetfile: fltk graphics toolkit required");
+    elseif (! strcmp (defaulttoolkit, "gnuplot"))
+      warning ("uigetfile: no implementation for toolkit `%s', using `fltk' instead",
+               defaulttoolkit);
+    endif
   endif
 
   if (nargin > 7)
     error ("uigetfile: number of input arguments must be less than eight");
   endif
 
-  defaultvals = {"All Files(*)", #FLTK File Filter
-                 "Open File?",   #Dialog Title
-                 pwd,            #FLTK default file name
-                 [240, 120],     #Dialog Position (pixel x/y)
-                 "off"};         #MultiSelect on/off
+  defaultvals = {cell(0, 2),         # File Filter
+                 "Open File",        # Dialog Title
+                 "",                 # Default file name
+                 [240, 120],         # Dialog Position (pixel x/y)
+                 "off",              # MultiSelect on/off
+                 pwd};               # Default directory
 
-  outargs = cell (5, 1);
-  for i = 1 : 5
+  outargs = cell (6, 1);
+  for i = 1 : 6
     outargs{i} = defaultvals{i};
   endfor
 
@@ -88,9 +98,9 @@
     for i = 1 : length (varargin)
       val = varargin{i};
       if (ischar (val))
-        if (strncmp (tolower (val), "multiselect", 11))
+        if (strncmpi (val, "multiselect", 11))
           idx1 = i;
-        elseif (strncmp(tolower (val), "position", 8))
+        elseif (strncmpi (val, "position", 8))
           idx2 = i;
         endif
       endif
@@ -110,18 +120,36 @@
   len = length (args);
   if (len > 0)
     file_filter = args{1};
-    outargs{1} = __fltk_file_filter__ (file_filter);
-    if (ischar (file_filter))
-      outargs{3} = file_filter;
+    [outargs{1}, outargs{3}, defdir] = __file_filter__ (file_filter);
+    if (length (defdir) > 0)
+      outargs{6} = defdir;
+    endif
+  else
+    outargs{1} = __file_filter__ (outargs{1});
+  endif
+
+  if (len > 1)
+    if (ischar (args{2}))
+      if (length (args{2}) > 0)
+        outargs{2} = args{2};
+      endif
+    elseif (! isempty (args{2}))
+      print_usage ();
     endif
   endif
 
-  if (len > 1)
-    outargs{2} = args{2};
-  endif
-
   if (len > 2)
-    outargs{3} = args{3};
+    if (ischar (args{3}))
+      [fdir, fname, fext] = fileparts (args{3});
+      if (length (fdir) > 0)
+        outargs{6} = fdir;
+      endif
+      if (length (fname) > 0 || length (fext) > 0)
+        outargs{3} = strcat (fname, fext);
+      endif
+    elseif (! isempty (args{3}))
+      print_usage ();
+    endif
   endif
 
   if (stridx)
@@ -153,7 +181,7 @@
     endfor
   endif
 
-  [retfile, retpath, retindex] = __fltk_uigetfile__ (outargs{:});
+  [retfile, retpath, retindex] = feval (funcname, outargs{:});
 
 endfunction
 
--- a/scripts/plot/uimenu.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uimenu.m	Sat Oct 22 16:22:04 2011 -0700
@@ -79,18 +79,7 @@
 
 function hui = uimenu (varargin)
 
-  args = varargin;
-
-  if (ishandle (args{1}))
-    h = args{1};
-    args(1) = [];
-  else
-    h = gcf ();
-  endif
-
-  if (rem (length (args), 2))
-    error ("uimenu: expecting PROPERTY/VALUE pairs");
-  endif
+  [h, args] = __uiobject_split_args__ ("uimenu", varargin, {"figure", "uicontextmenu", "uimenu"});
 
   tmp = __go_uimenu__ (h, args{:});
 
--- a/scripts/plot/uipanel.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uipanel.m	Sat Oct 22 16:22:04 2011 -0700
@@ -25,7 +25,7 @@
 
 function handle = uipanel (varargin)
 
-  [h, args] = __uiobject_split_args__ ("uipanel", varargin{:});
+  [h, args] = __uiobject_split_args__ ("uipanel", varargin, {"figure", "uipanel", "uibuttongroup"});
   handle = __go_uipanel__ (h, args{:});
 
 endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/uipushtool.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,39 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{handle} =} uipushtool ('Name', value, @dots{})
+## @deftypefnx {Function File} {@var{handle} =} uipushtool (@var{parent}, 'Name', value, @dots{})
+## @end deftypefn
+
+## Author: goffioul
+
+function handle = uipushtool (varargin)
+
+  [h, args] = __uiobject_split_args__ ("uipushtool", varargin, {"uitoolbar"}, 0);
+  if (isempty (h))
+    h = findobj (gcf, "-depth", 1, "type", "uitoolbar");
+    if (isempty (h))
+      h = uitoolbar ();
+    else
+      h = h(1);
+    endif
+  endif
+  handle = __go_uipushtool__ (h, args{:});
+
+endfunction
--- a/scripts/plot/uiputfile.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/plot/uiputfile.m	Sat Oct 22 16:22:04 2011 -0700
@@ -55,42 +55,68 @@
 
 function [retfile, retpath, retindex] = uiputfile (varargin)
 
-  if (exist("__fltk_uigetfile__") != 3)
-    error ("uiputfile: fltk graphics toolkit required");
+  defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
+  funcname = ["__uiputfile_", defaulttoolkit, "__"];
+  functype = exist (funcname);
+  if (! __is_function__ (funcname))
+    funcname = "__uiputfile_fltk__";
+    if (! __is_function__ (funcname))
+      error ("uiputfile: fltk graphics toolkit required");
+    elseif (! strcmp (defaulttoolkit, "gnuplot"))
+      warning ("uiputfile: no implementation for toolkit `%s', using `fltk' instead",
+               defaulttoolkit);
+    endif
   endif
 
   if (nargin > 3)
     print_usage ();
   endif
 
-  defaultvals = {"All Files(*)", #FLTK File Filter
-                 "Save File?",   #Dialog Title
-                 pwd,            #FLTK default file name
-                 [240, 120],     #Dialog Position (pixel x/y)
-                 "create"};
+  defaultvals = {cell(0, 2),     # File Filter
+                 "Save File",    # Dialog Title
+                 "",             # Default file name
+                 [240, 120],     # Dialog Position (pixel x/y)
+                 "create",
+                 pwd};           # Default directory
 
-  outargs = cell(5, 1);
-  for i = 1 : 5
+  outargs = cell(6, 1);
+  for i = 1 : 6
     outargs{i} = defaultvals{i};
   endfor
 
   if (nargin > 0)
     file_filter = varargin{1};
-    outargs{1} = __fltk_file_filter__ (file_filter);
-    if (ischar (file_filter))
-      outargs{3} = file_filter;
+    [outargs{1}, outargs{3}, defdir] = __file_filter__ (file_filter);
+    if (length (defdir) > 0)
+      outargs{6} = defdir;
     endif
+  else
+    outargs{1} = __file_filter__ (outargs{1});
   endif
 
   if (nargin > 1)
-    outargs{2} = varargin{2};
+    if (ischar (varargin{2}))
+      outargs{2} = varargin{2};
+    elseif (! isempty (varargin{2}))
+      print_usage ();
+    endif
   endif
 
   if (nargin > 2)
-    outargs{3} = varargin{3};
+    if (ischar (varargin{3}))
+      [fdir, fname, fext] = fileparts (varargin{3});
+      if (! isempty (fdir))
+        outargs{6} = fdir;
+      endif
+      if (! isempty (fname) || ! isempty (fext))
+        outargs{3} = strcat (fname, fext);
+      endif
+    elseif (! isempty (varargin{3}))
+      print_usage ();
+    endif
   endif
 
-  [retfile, retpath, retindex] = __fltk_uigetfile__ (outargs{:});
+  [retfile, retpath, retindex] = feval (funcname, outargs{:});
 
 endfunction
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/uitoggletool.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,39 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{handle} =} uitoggletool ('Name', value, @dots{})
+## @deftypefnx {Function File} {@var{handle} =} uitoggletool (@var{parent}, 'Name', value, @dots{})
+## @end deftypefn
+
+## Author: goffioul
+
+function handle = uitoggletool (varargin)
+
+  [h, args] = __uiobject_split_args__ ("uitoggletool", varargin, {"uitoolbar"}, 0);
+  if (isempty (h))
+    h = findobj (gcf, "-depth", 1, "type", "uitoolbar");
+    if (isempty (h))
+      h = uitoolbar ();
+    else
+      h = h(1);
+    endif
+  endif
+  handle = __go_uitoggletool__ (h, args{:});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/uitoolbar.m	Sat Oct 22 16:22:04 2011 -0700
@@ -0,0 +1,31 @@
+## Copyright (C) 2011 Michael Goffioul
+##
+## 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{handle} =} uitoolbar ('Name', value, @dots{})
+## @deftypefnx {Function File} {@var{handle} =} uitoolbar (@var{parent}, 'Name', value, @dots{})
+## @end deftypefn
+
+## Author: goffioul
+
+function handle = uitoolbar (varargin)
+
+  [h, args] = __uiobject_split_args__ ("uitoolbar", varargin, {"figure"});
+  handle = __go_uitoolbar__ (h, args{:});
+
+endfunction
--- a/scripts/sparse/spy.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/sparse/spy.m	Sat Oct 22 16:22:04 2011 -0700
@@ -21,7 +21,7 @@
 ## @deftypefnx {Function File} {} spy (@dots{}, @var{markersize})
 ## @deftypefnx {Function File} {} spy (@dots{}, @var{line_spec})
 ## Plot the sparsity pattern of the sparse matrix @var{x}.  If the argument
-## @var{markersize} is given as an scalar value, it is used to determine the
+## @var{markersize} is given as a scalar value, it is used to determine the
 ## point size in the plot.  If the string @var{line_spec} is given it is
 ## passed to @code{plot} and determines the appearance of the plot.
 ## @seealso{plot}
@@ -41,7 +41,11 @@
   endif
   for i = 1:length (varargin)
     if (ischar (varargin{i}))
-      line_spec = varargin{i};
+      if (length (varargin{i}) == 1)
+        line_spec = [line_spec, varargin{i}];
+      else
+        line_spec = varargin{i};
+      endif
     elseif (isscalar (varargin{i}))
       markersize = varargin{i};
     else
--- a/scripts/strings/dec2base.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/dec2base.m	Sat Oct 22 16:22:04 2011 -0700
@@ -89,7 +89,7 @@
 
   ## determine number of digits required to handle all numbers, can overflow
   ## by 1 digit
-  max_len = round (log (max (max (d), 1)) ./ log (base)) + 1;
+  max_len = round (log (max (max (d(:)), 1)) / log (base)) + 1;
 
   if (nargin == 3)
     max_len = max (max_len, len);
@@ -103,7 +103,7 @@
   endfor
 
   ## convert digits to symbols
-  retval = reshape (symbols (digits+1), size (digits));
+  retval = reshape (symbols(digits+1), size (digits));
 
   ## Check if the first element is the zero symbol. It seems possible
   ## that LEN is provided, and is less than the computed MAX_LEN and
@@ -111,7 +111,7 @@
   ## have a leading zero to remove.  But if LEN >= MAX_LEN, we should
   ## not remove any leading zeros.
   if ((nargin == 2 || (nargin == 3 && max_len > len))
-      && all (retval(:,1) == symbols(1)) && length (retval) != 1)
+      && length (retval) != 1 && ! any (retval(:,1) != symbols(1)))
     retval = retval(:,2:end);
   endif
 
@@ -125,9 +125,9 @@
 %!     pp = dec2base (b^n+1, b);
 %!     assert (dec2base(b^n, b), ['1',s0,'0']);
 %!     assert (dec2base(b^n+1, b), ['1',s0,'1']);
-%!   end
+%!   endfor
 %!   s0 = [s0,'0'];
-%! end
+%! endfor
 
 %!test
 %! digits='0123456789ABCDEF';
@@ -136,18 +136,19 @@
 %!     pm = dec2base(b^n-1, b);
 %!     assert (length (pm), n);
 %!     assert (all (pm==digits(b)));
-%!   end
-%! end
+%!   endfor
+%! endfor
 
 %!test
 %! for b = 2:16
 %!   assert (dec2base (0, b), '0');
-%! end
+%! endfor
 
 %!assert(dec2base (0, 2, 4), "0000");
 %!assert(dec2base (2^51-1, 2), ...
 %!       '111111111111111111111111111111111111111111111111111');
 %!assert(dec2base(uint64(2)^63-1, 16), '7FFFFFFFFFFFFFFF');
+%!assert(dec2base([1, 2; 3, 4], 2, 3), ["001"; "011"; "010"; "100"]);
 %!assert(dec2base({1, 2; 3, 4}, 2, 3), ["001"; "011"; "010"; "100"]);
 
 %%Test input validation
@@ -158,8 +159,8 @@
 %!error dec2base (2i)
 %!error dec2base (-1)
 %!error dec2base (1.1)
-%!error dec2base (1,"ABA")
-%!error dec2base (1,"A B")
+%!error dec2base (1, "ABA")
+%!error dec2base (1, "A B")
 %!error dec2base (1, ones(2))
 %!error dec2base (1, 1)
 %!error dec2base (1, 37)
--- a/scripts/strings/isstrprop.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/isstrprop.m	Sat Oct 22 16:22:04 2011 -0700
@@ -84,47 +84,52 @@
 
 function retval = isstrprop (str, prop)
 
-  if (nargin == 2)
-    switch (prop)
-      case "alpha"
-        retval = isalpha (str);
-      case {"alnum", "alphanum"}
-        retval = isalnum (str);
-      case "ascii"
-        retval = isascii (str);
-      case "cntrl"
-        retval = iscntrl (str);
-      case "digit"
-        retval = isdigit (str);
-      case {"graph", "graphic"}
-        retval = isgraph (str);
-      case "lower"
-        retval = islower (str);
-      case "print"
-        retval = isprint (str);
-      case "punct"
-        retval = ispunct (str);
-      case {"space", "wspace"}
-        retval = isspace (str);
-      case "upper"
-        retval = isupper (str);
-      case "xdigit"
-        retval = isxdigit (str);
-      otherwise
-        error ("isstrprop: invalid string property");
-    endswitch
-  else
+  if (nargin != 2)
     print_usage ();
   endif
 
+  switch (prop)
+    case "alpha"
+      retval = isalpha (str);
+    case {"alnum", "alphanum"}
+      retval = isalnum (str);
+    case "ascii"
+      retval = isascii (str);
+    case "cntrl"
+      retval = iscntrl (str);
+    case "digit"
+      retval = isdigit (str);
+    case {"graph", "graphic"}
+      retval = isgraph (str);
+    case "lower"
+      retval = islower (str);
+    case "print"
+      retval = isprint (str);
+    case "punct"
+      retval = ispunct (str);
+    case {"space", "wspace"}
+      retval = isspace (str);
+    case "upper"
+      retval = isupper (str);
+    case "xdigit"
+      retval = isxdigit (str);
+    otherwise
+      error ("isstrprop: invalid string property");
+  endswitch
+
 endfunction
 
-%!error <invalid string property> isstrprop ("abc123", "foo")
+
 %!assert (isstrprop ("abc123", "alpha"), logical ([1, 1, 1, 0, 0, 0]))
+%!assert (isstrprop ("abc123", "digit"), logical ([0, 0, 0, 1, 1, 1]))
 %!assert (isstrprop ("Hello World", "wspace"), isspace ("Hello World"))
 %!assert (isstrprop ("Hello World", "graphic"), isgraph ("Hello World"))
+%!assert (isstrprop (char ("AbC", "123"), "upper"), logical ([1 0 1; 0 0 0]))
+%!assert (isstrprop ({"AbC", "123"}, "lower"), {logical([0 1 0]), logical([0 0 0])})
 
 %%Input Validation
 %!error isstrprop ()
 %!error isstrprop ("abc123")
 %!error isstrprop ("abc123", "alpha", "alpha")
+%!error <invalid string property> isstrprop ("abc123", "foo")
+
--- a/scripts/strings/mat2str.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/mat2str.m	Sat Oct 22 16:22:04 2011 -0700
@@ -19,9 +19,9 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{s} =} mat2str (@var{x}, @var{n})
 ## @deftypefnx {Function File} {@var{s} =} mat2str (@var{x}, @var{n}, "class")
-## Format real/complex numerical matrices as strings.  This function
-## returns values that are suitable for the use of the @code{eval}
-## function.
+## Format real, complex, and logical matrices as strings.  The 
+## returned string may be used to reconstruct the original matrix by using
+## the @code{eval} function.
 ##
 ## The precision of the values is given by @var{n}.  If @var{n} is a
 ## scalar then both real and imaginary parts of the matrix are printed
@@ -29,7 +29,7 @@
 ## precision of the real part and @code{@var{n}(2)} defines the
 ## precision of the imaginary part.  The default for @var{n} is 15.
 ##
-## If the argument "class" is given, then the class of @var{x} is
+## If the argument "class" is given then the class of @var{x} is
 ## included in the string in such a way that @code{eval} will result in the
 ## construction of a matrix of the same class.
 ##
@@ -39,10 +39,16 @@
 ##      @result{} "[-0.3333+0.14i;0.3333-0.14i]"
 ##
 ## mat2str ([ -1/3 +i/7; 1/3 -i/7 ], [4 2])
-##      @result{} "[-0.3333+0i,0+0.14i;0.3333+0i,-0-0.14i]"
+##      @result{} "[-0.3333+0i 0+0.14i;0.3333+0i -0-0.14i]"
 ##
 ## mat2str (int16([1 -1]), "class")
-##      @result{} "int16([1,-1])"
+##      @result{} "int16([1 -1])"
+##
+## mat2str (logical (eye (2)))
+##      @result{} "[true false;false true]"
+##
+## isequal (x, eval (mat2str (x)))
+##      @result{} 1
 ## @end group
 ## @end example
 ##
@@ -51,34 +57,26 @@
 
 ## Author: Rolf Fabian <fabian@tu-cottbus.de>
 
-function s = mat2str (x, n, cls)
+function s = mat2str (x, n = 15, cls = "")
 
   if (nargin < 1 || nargin > 3 || ! (isnumeric (x) || islogical (x)))
     print_usage ();
-  endif
-
-  if (ndims (x) > 2)
+  elseif (ndims (x) > 2)
     error ("mat2str: X must be two dimensional");
   endif
 
-  if (nargin < 2 || isempty (n))
+  if (nargin == 2 && ischar (n))
+    cls = n;
+    n = 15;
+  elseif (isempty (n))
     n = 15;   # Default precision
   endif
 
-  if (nargin < 3)
-    if (ischar (n))
-      cls = n;
-      n = 15;
-    else
-      cls = "";
-    endif
-  endif
-
   x_islogical = islogical (x);
   x_iscomplex = iscomplex (x);
 
   if (x_iscomplex)
-    if (length (n) == 1)
+    if (isscalar (n))
       n = [n, n];
     endif
     fmt = sprintf ("%%.%dg%%+.%dgi", n(1), n(2));
@@ -105,7 +103,7 @@
     endif
   else
     ## Non-scalar X, print brackets
-    fmt = cstrcat (fmt, ",");
+    fmt = cstrcat (fmt, " ");
     if (x_iscomplex)
       t = x.';
       s = sprintf (fmt, [real(t(:))'; imag(t(:))']);
@@ -118,7 +116,7 @@
 
     s = cstrcat ("[", s);
     s(end) = "]";
-    idx = find (s == ",");
+    idx = strfind (s, " ");
     nc = columns (x);
     s(idx(nc:nc:end)) = ";";
   endif
@@ -135,11 +133,11 @@
 %!assert (mat2str (pi, 5), "3.1416");
 %!assert (mat2str (single (pi), 5, "class"), "single(3.1416)");
 %!assert (mat2str ([-1/3 + i/7; 1/3 - i/7], [4 2]), "[-0.3333+0.14i;0.3333-0.14i]")
-%!assert (mat2str ([-1/3 +i/7; 1/3 -i/7], [4 2]), "[-0.3333+0i,0+0.14i;0.3333+0i,-0-0.14i]")
-%!assert (mat2str (int16 ([1 -1]), 'class'), "int16([1,-1])")
+%!assert (mat2str ([-1/3 +i/7; 1/3 -i/7], [4 2]), "[-0.3333+0i 0+0.14i;0.3333+0i -0-0.14i]")
+%!assert (mat2str (int16 ([1 -1]), 'class'), "int16([1 -1])")
 %!assert (mat2str (true), "true");
 %!assert (mat2str (false), "false");
-%!assert (mat2str (logical (eye (2))), "[true,false;false,true]");
+%!assert (mat2str (logical (eye (2))), "[true false;false true]");
 
 %% Test input validation
 %!error mat2str ()
--- a/scripts/strings/str2num.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/str2num.m	Sat Oct 22 16:22:04 2011 -0700
@@ -53,15 +53,12 @@
 
   if (nargin != 1) 
     print_usage ();
-  endif
-  
-  if (! ischar (s))
+  elseif (! ischar (s))
     error ("str2num: S must be a string or string array");
   endif
 
-  [nr, nc] = size (s);
-  sep = repmat (";", nr, 1);
-  s = sprintf ("m = [%s];", reshape ([s, sep]', 1, nr * (nc + 1)));
+  s(:, end+1) = ";";
+  s = sprintf ("m = [%s];", reshape (s', 1, numel (s)));
   state = true;
   eval (s, "m = []; state = false;");
   if (ischar (m))
@@ -75,13 +72,14 @@
 %!assert(str2num ("-1.3e2"), -130);
 %!assert(str2num ("[1, 2; 3, 4]"), [1, 2; 3, 4]);
 
+%!test
+%! [x, state] = str2num ("pi");
+%! assert (state);
+%! [x, state] = str2num ("Hello World");
+%! assert (! state);
+
 %% Test input validation
 %!error str2num ()
 %!error str2num ("string", 1)
-%!error str2num ({"string"})
+%!error <S must be a string> str2num ({"string"})
 
-%!test
-%! [x, state] = str2num ("pi");
-%! assert (state);
-%! [x, state] = str2num (tmpnam);
-%! assert (! state);
--- a/scripts/strings/strchr.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/strchr.m	Sat Oct 22 16:22:04 2011 -0700
@@ -20,8 +20,9 @@
 ## @deftypefn  {Function File} {@var{idx} =} strchr (@var{str}, @var{chars})
 ## @deftypefnx {Function File} {@var{idx} =} strchr (@var{str}, @var{chars}, @var{n})
 ## @deftypefnx {Function File} {@var{idx} =} strchr (@var{str}, @var{chars}, @var{n}, @var{direction})
+## @deftypefnx {Function File} {[@var{i}, @var{j}] =} strchr (@dots{})
 ## Search for the string @var{str} for occurrences of characters from
-## the set @var{chars}.  The return value, as well as the @var{n} and
+## the set @var{chars}.  The return value(s), as well as the @var{n} and
 ## @var{direction} arguments behave identically as in @code{find}.
 ##
 ## This will be faster than using regexp in most cases.
@@ -30,12 +31,18 @@
 ## @end deftypefn
 
 function varargout = strchr (str, chars, varargin)
-  if (nargin < 2 || ! ischar (str) || ! ischar (chars))
+
+  if (nargin < 2)
     print_usage ();
+  elseif (! ischar (str))
+    error ("strchr: STR argument must be a string or string array");
+  elseif (! ischar (chars))
+    error ("strchr: CHARS argument must be a string");
   endif
+
   if (isempty (chars))
     mask = false (size (str));
-  elseif (length (chars) <= 6)
+  elseif (length (chars) <= 4)
     ## With a few characters, it pays off to build the mask incrementally.
     ## We do it via a for loop to save memory.
     mask = str == chars(1);
@@ -43,22 +50,31 @@
       mask |= str == chars(i);
     endfor
   else
-    ## Index the str into a mask of valid values.  This is slower than
-    ## it could be because of the +1 issue.
-    f = false (1, 256);
+    ## Index the str into a mask of valid values.
+    ## This is slower than it could be because of the +1 issue.
+    f = false (256, 1);
     f(uint8(chars)+1) = true;
     ## Default goes via double -- unnecessarily long.
     si = uint32 (str);
-    ## in-place
+    ## in-place is faster than str+1
     ++si;
     mask = reshape (f(si), size (str));
   endif
+
   varargout = cell (1, nargout);
   varargout{1} = [];
   [varargout{:}] = find (mask, varargin{:});
+
 endfunction
 
-%!assert(strchr("Octave is the best software",""),zeros(1,0))
-%!assert(strchr("Octave is the best software","best"),[3, 6, 9, 11, 13, 15, 16, 17, 18, 20, 23, 27])
-%!assert(strchr("Octave is the best software","software"),[3, 4, 6, 9, 11, 13, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27])
+
+%!assert (strchr ("Octave is the best software", ""), zeros (1,0))
+%!assert (strchr ("Octave is the best software", "best"), [3, 6, 9, 11, 13, 15, 16, 17, 18, 20, 23, 27])
+%!assert (strchr ("Octave is the best software", "software"), [3, 4, 6, 9, 11, 13, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27])
 
+%% Test input validation
+%!error strchr ()
+%!error strchr (1)
+%!error <STR argument must be a string> strchr (1, "aeiou")
+%!error <CHARS argument must be a string> strchr ("aeiou", 1)
+
--- a/scripts/strings/strjust.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/strjust.m	Sat Oct 22 16:22:04 2011 -0700
@@ -18,10 +18,11 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} strjust (@var{s}, @var{pos})
+## @deftypefn  {Function File} {} strjust (@var{s})
+## @deftypefnx {Function File} {} strjust (@var{s}, @var{pos})
 ## Return the text, @var{s}, justified according to @var{pos}, which may
 ## be @samp{"left"}, @samp{"center"}, or @samp{"right"}.  If @var{pos}
-## is omitted, @samp{"right"} is assumed.
+## is omitted it defaults to @samp{"right"}.
 ##
 ## Null characters are replaced by spaces.  All other character
 ## data are treated as non-white space.
@@ -41,69 +42,71 @@
 ## @seealso{deblank, strrep, strtrim, untabify}
 ## @end deftypefn
 
-function y = strjust (s, pos)
+function y = strjust (s, pos = "right")
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
-  endif
-
-  if (nargin == 1)
-    pos = "right";
-  else
-    pos = tolower (pos);
-  endif
-
-  if (ndims (s) != 2)
-    error ("strjust: input must be a string or character matrix");
+  elseif (! ischar (s) || ndims (s) > 2)
+    error ("strjust: S must be a string or 2-D character matrix");
   endif
 
   if (isempty (s))
     y = s;
-  else
-    ## Apparently, Matlab considers nulls to be blanks as well; however, does
-    ## not preserve the nulls, but rather converts them to blanks.  That's a
-    ## bit unexpected, but it allows simpler processing, because we can move
-    ## just the nonblank characters. So we'll do the same here.
+    return;
+  endif
 
-    [nr, nc] = size (s);
-    ## Find the indices of all nonblanks.
-    nonbl = s != " " & s != "\0";
-    [idx, jdx] = find (nonbl);
+  ## Apparently, Matlab considers nulls to be blanks as well; however, does
+  ## not preserve the nulls, but rather converts them to blanks.  That's a
+  ## bit unexpected, but it allows simpler processing, because we can move
+  ## just the nonblank characters. So we'll do the same here.
+
+  [nr, nc] = size (s);
+  ## Find the indices of all nonblanks.
+  nonbl = s != " " & s != "\0";
+  [idx, jdx] = find (nonbl);
 
-    if (strcmp (pos, "right"))
-      ## We wish to find the maximum column index for each row. Because jdx is
-      ## sorted, we can take advantage of the fact that assignment is processed
-      ## sequentially and for duplicate indices the last value will remain.
-      maxs = nc * ones (nr, 1);
-      maxs(idx) = jdx;
-      shift = nc - maxs;
-    elseif (strcmp (pos, "left"))
-      ## See above for explanation.
-      mins = ones (nr, 1);
-      mins(flipud (idx(:))) = flipud (jdx(:));
-      shift = 1 - mins;
-    else
-      ## Use both of the above.
-      mins = ones (nr, 1);
-      mins(flipud (idx(:))) = flipud (jdx(:));
-      maxs = nc * ones (nr, 1);
-      maxs(idx) = jdx;
-      shift = floor ((nc + 1 - maxs - mins) / 2);
-    endif
+  if (strcmpi (pos, "right"))
+    ## We wish to find the maximum column index for each row. Because jdx is
+    ## sorted, we can take advantage of the fact that assignment is processed
+    ## sequentially and for duplicate indices the last value will remain.
+    maxs = repmat (nc, [nr, 1]);
+    maxs(idx) = jdx;
+    shift = nc - maxs;
+  elseif (strcmpi (pos, "left"))
+    ## See above for explanation.
+    mins = ones (nr, 1);
+    mins(flipud (idx(:))) = flipud (jdx(:));
+    shift = 1 - mins;
+  else
+    ## Use both of the above to achieve centering.
+    mins = ones (nr, 1);
+    mins(flipud (idx(:))) = flipud (jdx(:));
+    maxs = repmat (nc, [nr, 1]);
+    maxs(idx) = jdx;
+    shift = floor ((nc + 1 - maxs - mins) / 2);
+  endif
 
-    ## Adjust the column indices.
-    jdx += shift (idx);
+  ## Adjust the column indices.
+  jdx += shift(idx);
 
-    ## Create a blank matrix and position the nonblank characters.
-    y = " "(ones (1, nr), ones (1, nc));
-    y(sub2ind ([nr, nc], idx, jdx)) = s(nonbl);
-  endif
+  ## Create a blank matrix and position the nonblank characters.
+  y = repmat (" ", nr, nc);
+  y(sub2ind ([nr, nc], idx, jdx)) = s(nonbl);
 
 endfunction
 
-%!error <Invalid call to strjust> strjust();
-%!error <Invalid call to strjust> strjust(["a";"ab"], "center", 1);
+
 %!assert (strjust (["a"; "ab"; "abc"; "abcd"]),
 %!        ["   a";"  ab"; " abc"; "abcd"]);
-%!assert (strjust (["a"; "ab"; "abc"; "abcd"], "center"),
+%!assert (strjust ([" a"; "  ab"; "abc"; "abcd"], "left"),
+%!        ["a   "; "ab  "; "abc "; "abcd"]);
+%!assert (strjust (["a"; "ab"; "abc"; "abcd"], "CENTER"),
 %!        [" a  "; " ab"; "abc "; "abcd"]);
+%!assert (strjust (["";""]), "");
+
+%% Test input validation
+%!error <Invalid call to strjust> strjust ()
+%!error <Invalid call to strjust> strjust (["a";"ab"], "center", 1)
+%!error <S must be a string> strjust (ones(3,3))
+%!error <S must be a string> strjust (char (ones(3,3,3)))
+
--- a/scripts/strings/strsplit.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/strsplit.m	Sat Oct 22 16:22:04 2011 -0700
@@ -17,53 +17,100 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{s}] =} strsplit (@var{p}, @var{sep}, @var{strip_empty})
-## Split a single string using one or more delimiters and return a cell
+## @deftypefn {Function File} {[@var{cstr}] =} strsplit (@var{p}, @var{sep}, @var{strip_empty})
+## Split a string using one or more delimiters and return a cell
 ## array of strings.  Consecutive delimiters and delimiters at
 ## boundaries result in empty strings, unless @var{strip_empty} is true.
 ## The default value of @var{strip_empty} is false.
+##
+## 2-D character arrays are split at delimiters and at the original column
+## boundaries.
+##
+## Example:
+## @example
+## strsplit ("a,b,c", ",")
+##        @result{}
+##           @{
+##             [1,1] = a
+##             [1,2] = b
+##             [1,3] = c
+##           @}
+##
+## strsplit (["a,b" ; "cde"], ",")
+##        @result{}
+##           @{
+##             [1,1] = a
+##             [1,2] = b
+##             [1,3] = cde
+##           @}
+## @group
+## @end group
+## @end example
 ## @seealso{strtok}
 ## @end deftypefn
 
 function s = strsplit (p, sep, strip_empty = false)
 
-  if (nargin < 2 || nargin > 3 || ! ischar (p) || rows (p) > 1
-      || ! ischar (sep) || ! isscalar (strip_empty))
+  if (nargin < 2 || nargin > 3)
     print_usage ();
+  elseif (! ischar (p) || ! ischar (sep))
+    error ("strsplit: P and SEP must be string values");
+  elseif (! isscalar (strip_empty))
+    error ("strsplit: STRIP_EMPTY must be a scalar value");
   endif
 
   if (isempty (p))
     s = cell (size (p));
   else
-    ## Split p according to delimiter.
+    if (rows (p) > 1)
+      ## For 2-D arrays, add separator character at line boundaries
+      ## and transform to single string
+      p(:, end+1) = sep(1);
+      p = reshape (p.', 1, numel (p));
+      p(end) = []; 
+    endif
+
+    ## Split p according to delimiter
     if (isscalar (sep))
-      ## Single separator.
+      ## Single separator
       idx = find (p == sep);
     else
-      ## Multiple separators.
+      ## Multiple separators
       idx = strchr (p, sep);
     endif
 
-    ## Get substring sizes.
+    ## Get substring lengths.
     if (isempty (idx))
-      sizes = numel (p);
+      strlens = length (p);
     else
-      sizes = [idx(1)-1, diff(idx)-1, numel(p)-idx(end)];
+      strlens = [idx(1)-1, diff(idx)-1, numel(p)-idx(end)];
     endif
     ## Remove separators.
     p(idx) = [];
     if (strip_empty)
       ## Omit zero lengths.
-      sizes = sizes (sizes != 0);
+      strlens = strlens(strlens != 0);
     endif
+
     ## Convert!
-    s = mat2cell (p, 1, sizes);
+    s = mat2cell (p, 1, strlens);
   endif
 
 endfunction
 
-%!assert (all (strcmp (strsplit ("road to hell", " "), {"road", "to", "hell"})))
+
+%!assert (strsplit ("road to hell", " "), {"road", "to", "hell"})
+%!assert (strsplit ("road to^hell", " ^"), {"road", "to", "hell"})
+%!assert (strsplit ("road   to--hell", " -", true), {"road", "to", "hell"})
+%!assert (strsplit (["a,bc";",de"], ","), {"a", "bc", ones(1,0), "de "})
+%!assert (strsplit (["a,bc";",de"], ",", true), {"a", "bc", "de "})
+%!assert (strsplit (["a,bc";",de"], ", ", true), {"a", "bc", "de"})
 
-%!assert (all (strcmp (strsplit ("road to^hell", " ^"), {"road", "to", "hell"})))
+%% Test input validation
+%!error strsplit ()
+%!error strsplit ("abc")
+%!error strsplit ("abc", "b", true, 4)
+%!error <P and SEP must be string values> strsplit (123, "b")
+%!error <P and SEP must be string values> strsplit ("abc", 1)
+%!error <STRIP_EMPTY must be a scalar value> strsplit ("abc", "def", ones(3,3))
 
-%!assert (all (strcmp (strsplit ("road   to--hell", " -", true), {"road", "to", "hell"})))
--- a/scripts/strings/validatestring.m	Wed Oct 12 13:45:43 2011 -0500
+++ b/scripts/strings/validatestring.m	Sat Oct 22 16:22:04 2011 -0700
@@ -21,18 +21,37 @@
 ## @deftypefnx {Function File} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname})
 ## @deftypefnx {Function File} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname}, @var{varname})
 ## @deftypefnx {Function File} {@var{validstr} =} validatestring (@dots{}, @var{position})
-## Verify that @var{str} is a string or substring of an element of
+## Verify that @var{str} is an element, or substring of an element, in
 ## @var{strarray}.
 ##
-## @var{str} is a character string to be tested, and @var{strarray} is a
-## cellstr of valid values.  @var{validstr} will be the validated form
+## When @var{str} is a character string to be tested, and @var{strarray} is a
+## cellstr of valid values, then @var{validstr} will be the validated form
 ## of @var{str} where validation is defined as @var{str} being a member
-## or substring of @var{validstr}.  If @var{str} is a substring of
-## @var{validstr} and there are multiple matches, the shortest match
-## will be returned if all matches are substrings of each other, and an
-## error will be raised if the matches are not substrings of each other.
+## or substring of @var{validstr}.  This is useful for both verifying
+## and expanding short options, such as "r", to their longer forms, such as
+## "red".  If @var{str} is a substring of @var{validstr}, and there are
+## multiple matches, the shortest match will be returned if all matches are
+## substrings of each other.  Otherwise, an error will be raised because the
+## expansion of @var{str} is ambiguous.  All comparisons are case insensitive.
+##
+## The additional inputs @var{funcname}, @var{varname}, and @var{position}
+## are optional and will make any generated validation error message more
+## specific.
+##
+## Examples:
 ##
-## All comparisons are case insensitive.
+## @example
+## @group
+## validatestring ("r", @{"red", "green", "blue"@})
+##    @result{} "red"
+##
+## validatestring ("b", @{"red", "green", "blue", "black"@})
+##    @result{} error: validatestring: multiple unique matches were found for 'b':
+##       blue, black
+## @end group
+## @end example
+##
+## 
 ## @seealso{strcmp, strcmpi}
 ## @end deftypefn
 
@@ -44,55 +63,40 @@
     print_usage ();
   endif
 
-  ## set the defaults
-  funcname = "";
-  varname = "";
   position = 0;
-  ## set the actual values
-  if (! isempty (varargin))
-    if (isnumeric (varargin{end}))
-      position = varargin{end};
-      varargin(end) = [];
-    endif
+  ## Process input arguments
+  if (! isempty (varargin) && isnumeric (varargin{end}))
+    position = varargin{end};
+    varargin(end) = [];
   endif
-  funcnameset = false;
-  varnameset = false;
-  for i = 1:numel (varargin)
-    if (ischar (varargin{i}))
-      if (varnameset)
-        error ("validatestring: invalid number of character inputs: %d",
-               numel (varargin));
-      elseif (funcnameset)
-        varname = varargin{i};
-        varnameset = true;
-      else
-        funcname = varargin{i};
-        funcnameset = true;
-      endif
-    endif
-  endfor
+  
+  funcname = varname = "";
+  char_idx = cellfun ("isclass", varargin, "char");
+  n_chararg = sum (char_idx);
+  if (n_chararg > 2)
+    error ("validatestring: invalid number of character inputs (3)");
+  elseif (n_chararg == 2)
+    [funcname, varname] = deal (varargin{char_idx});
+  elseif (n_chararg == 1)
+    funcname = varargin{char_idx};
+  endif
 
   ## Check the inputs
   if (! ischar (str))
     error ("validatestring: STR must be a character string");
-  elseif (rows (str) != 1)
-    error ("validatestring: STR must have only one row");
+  elseif (! isrow (str))
+    error ("validatestring: STR must be a single row vector");
   elseif (! iscellstr (strarray))
     error ("validatestring: STRARRAY must be a cellstr");
-  elseif (! ischar (funcname))
-    error ("validatestring: FUNCNAME must be a character string");
-  elseif (! isempty (funcname) && (rows (funcname) != 1))
-    error ("validatestring: FUNCNAME must be exactly one row");
-  elseif (! ischar (varname))
-    error ("validatestring: VARNAME must be a character string");
-  elseif (! isempty (varname) && (rows (varname) != 1))
-    error ("validatestring: VARNAME must be exactly one row");
+  elseif (! isempty (funcname) && ! isrow (funcname))
+    error ("validatestring: FUNCNAME must be a single row vector");
+  elseif (! isempty (varname) && ! isrow (varname))
+    error ("validatestring: VARNAME must be a single row vector");
   elseif (position < 0)
     error ("validatestring: POSITION must be >= 0");
   endif
 
-  ## make the part of the error that will use funcname, varname, and
-  ## position
+  ## Make static part of error string that uses funcname, varname, and position
   errstr = "";
   if (! isempty (funcname))
     errstr = sprintf ("Function: %s ", funcname);
@@ -109,35 +113,51 @@
 
   matches = strncmpi (str, strarray(:), numel (str));
   nmatches = sum (matches);
-  if (nmatches == 1)
+  if (nmatches == 0)
+    error ("validatestring: %s'%s' does not match any of\n%s", errstr, str,
+           sprintf ("%s, ", strarray{:})(1:end-2));
+  elseif (nmatches == 1)
     str = strarray{matches};
-  elseif (nmatches == 0)
-    error ("validatestring: %s%s does not match any of\n%s", errstr, str,
-           sprintf ("%s, ", strarray{:})(1:end-1));
   else
-    ## are the matches a substring of each other, if so, choose the
-    ## shortest.  If not, raise an error.
+    ## Are the matches substrings of each other?
+    ## If true, choose the shortest.  If not, raise an error.
     match_idx = find (matches);
-    match_l = cellfun ("length", strarray(match_idx));
-    longest_idx = find (match_l == max (match_l), 1);
-    shortest_idx = find (match_l == min (match_l), 1);
-    longest = strarray(match_idx)(longest_idx);
-    for i = 1:numel(match_idx)
-      currentmatch = strarray(match_idx(i));
-      if (! strncmpi (longest, currentmatch, length(currentmatch)))
-        error ("validatestring: %smultiple unique matches were found for %s:\n%s",
-               errstr, sprintf ("%s, ", strarray(match_idx))(1:end-2));
-      endif
-    endfor
-    str = strarray{shortest_idx};
+    match_len = cellfun ("length", strarray(match_idx));
+    [min_len, min_idx] = min (match_len); 
+    short_str = strarray{match_idx(min_idx)};
+    submatch = strncmpi (short_str, strarray(match_idx), min_len);    
+    if (all (submatch))
+      str = short_str;
+    else
+      error ("validatestring: %smultiple unique matches were found for '%s':\n%s",
+             errstr, str, sprintf ("%s, ", strarray{match_idx})(1:end-2));
+    endif
   endif
 
 endfunction
 
-## Tests
+
 %!shared strarray
 %!  strarray = {"octave" "Oct" "octopus" "octaves"};
 %!assert (validatestring ("octave", strarray), "octave")
 %!assert (validatestring ("oct", strarray), "Oct")
-%!assert (validatestring ("octave", strarray), "octave")
-%!assert (validatestring ("octav", strarray), "octave")
+%!assert (validatestring ("octa", strarray), "octave")
+%!  strarray = {"abc1" "def" "abc2"};
+%!assert (validatestring ("d", strarray), "def")
+%!error <'xyz' does not match any> validatestring ("xyz", strarray)
+%!error <Function: DUMMY_TEST> validatestring ("xyz", strarray, "DUMMY_TEST")
+%!error <Function: DUMMY_TEST Variable: DUMMY_VAR:> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
+%!error <Function: DUMMY_TEST Variable: DUMMY_VAR Argument position 5> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
+%!error <multiple unique matches were found for 'abc'> validatestring ("abc", strarray)
+
+%% Test input validation
+%!error validatestring ("xyz")
+%!error validatestring ("xyz", {"xyz"}, "3", "4", 5, 6)
+%!error <invalid number of character inputs> validatestring ("xyz", {"xyz"}, "3", "4", "5")
+%!error <STR must be a character string> validatestring (1, {"xyz"}, "3", "4", 5)
+%!error <STR must be a single row vector> validatestring ("xyz".', {"xyz"}, "3", "4", 5)
+%!error <STRARRAY must be a cellstr> validatestring ("xyz", "xyz", "3", "4", 5)
+%!error <FUNCNAME must be a single row vector> validatestring ("xyz", {"xyz"}, "33".', "4", 5)
+%!error <VARNAME must be a single row vector> validatestring ("xyz", {"xyz"}, "3", "44".', 5)
+%!error <POSITION must be> validatestring ("xyz", {"xyz"}, "3", "4", -5)
+
--- a/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -26,6 +26,10 @@
 
 #if defined (HAVE_FLTK)
 
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#endif
+
 #include <FL/Fl.H>
 #include <FL/Fl_File_Chooser.H>
 
--- a/src/DLD-FUNCTIONS/__init_fltk__.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/__init_fltk__.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -40,6 +40,10 @@
 #include <sstream>
 #include <iostream>
 
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#endif
+
 #include <FL/Fl.H>
 #include <FL/Fl_Box.H>
 #include <FL/Fl_Button.H>
--- a/src/DLD-FUNCTIONS/cellfun.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -45,6 +45,7 @@
 #include "gripes.h"
 #include "utils.h"
 
+#include "ov-class.h"
 #include "ov-scalar.h"
 #include "ov-float.h"
 #include "ov-complex.h"
@@ -1711,6 +1712,66 @@
     }
 }
 
+// FIXME -- this is a mess, but if a size method for the object exists,
+// we have to call it to get the size of the object instead of using the
+// internal dims method.
+
+static dim_vector
+get_object_dims (octave_value& obj)
+{
+  dim_vector retval;
+
+  Matrix m = obj.size ();
+
+  int n = m.numel ();
+
+  retval.resize (n);
+
+  for (int i = 0; i < n; i++)
+    retval(i) = m(i);
+
+  return retval;
+}
+
+static Cell
+do_object2cell (const octave_value& obj, const Array<int>& dimv)
+{
+  Cell retval;
+
+  // FIXME -- this copy is only needed because the octave_value::size
+  // method is not const.
+  octave_value array = obj;
+
+  if (dimv.is_empty ())
+    {
+      dim_vector dv = get_object_dims (array);
+
+      if (! error_state)
+        {
+          retval.resize (dv);
+
+          octave_value_list idx (1);
+
+          for (octave_idx_type i = 0; i < dv.numel (); i++)
+            {
+              octave_quit ();
+
+              idx(0) = double (i+1);
+
+              retval.xelem(i) = array.single_subsref ("(", idx);
+
+              if (error_state)
+                break;
+            }
+        }
+    }
+  else
+    {
+      error ("num2cell (A, dim) not implemented for class objects");
+    }
+
+  return retval;
+}
 
 DEFUN_DLD (num2cell, args, ,
   "-*- texinfo -*-\n\
@@ -1800,10 +1861,14 @@
                 retval = do_num2cell (array.array_value (), dimv);
             }
         }
+      else if (array.is_object ())
+        retval = do_object2cell (array, dimv);
       else if (array.is_map ())
         retval = do_num2cell (array.map_value (), dimv);
       else if (array.is_cell ())
         retval = do_num2cell (array.cell_value (), dimv);
+      else if (array.is_object ())
+        retval = do_num2cell (array.cell_value (), dimv);
       else
         gripe_wrong_type_arg ("num2cell", array);
     }
--- a/src/DLD-FUNCTIONS/max.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/max.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -178,7 +178,7 @@
             }
 
           if (! args(1).is_empty ())
-            warning ("%s: second argument is ignored");
+            warning ("%s: second argument is ignored", func);
         }
 
       switch (arg.builtin_type ())
--- a/src/DLD-FUNCTIONS/rand.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/rand.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -26,7 +26,11 @@
 #endif
 
 #include <ctime>
+#if defined (HAVE_UNORDERED_MAP)
+#include <unordered_map>
+#elif defined (HAVE_TR1_UNORDERED_MAP)
 #include <tr1/unordered_map>
+#endif
 #include <string>
 
 #include "f77-fcn.h"
@@ -1027,6 +1031,13 @@
 @seealso{perms}\n\
 @end deftypefn")
 {
+
+#ifdef USE_UNORDERED_MAP_WITH_TR1
+using std::tr1::unordered_map;
+#else
+using std::unordered_map;
+#endif
+
   int nargin = args.length ();
   octave_value retval;
 
@@ -1066,8 +1077,7 @@
 
           if (short_shuffle)
             {
-              std::tr1::unordered_map<octave_idx_type,
-                                      octave_idx_type> map (m);
+              unordered_map<octave_idx_type, octave_idx_type> map (m);
 
               // Perform the Knuth shuffle only keeping track of moved
               // entries in the map
--- a/src/DLD-FUNCTIONS/regexp.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/DLD-FUNCTIONS/regexp.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -168,9 +168,10 @@
           freespacing = true;
           nopts--;
         }
-      else if (str.find ("start", 0) && str.find ("end", 0) &&
-               str.find ("tokenextents", 0) && str.find ("match", 0) &&
-               str.find ("tokens", 0) && str.find ("names", 0))
+      else if (str.find ("start", 0) && str.find ("end", 0)
+               && str.find ("tokenextents", 0) && str.find ("match", 0)
+               && str.find ("tokens", 0) && str.find ("names", 0)
+               && str.find ("split", 0))
         error ("%s: unrecognized option", nm.c_str ());
     }
 
@@ -524,6 +525,8 @@
       octave_idx_type i = 0;
       octave_scalar_map nmap;
 
+      retval.resize (7);
+
       if (sz == 1)
         {
           for (int j = 0; j < named.length (); j++)
@@ -547,78 +550,64 @@
           retval(5) = nmap;
         }
 
+      std::string buffer = args(0).string_value ();
+
       if (once)
-        retval(4) = sz ? lst.front ().t : Cell ();
+        {
+          retval(4) = sz ? lst.front ().t : Cell ();
+          retval(3) = sz ? lst.front ().m : std::string ();
+          retval(2) = sz ? lst.front ().te : Matrix ();
+
+          if (sz)
+            {
+              double e = lst.front ().e;
+              double s = lst.front ().s;
+
+              Cell sp (dim_vector (1, 2));
+              sp(0) = buffer.substr (0, s-1);
+              sp(1) = buffer.substr (e);
+
+              retval(6) = sp;
+              retval(1) = e;
+              retval(0) = s;
+            }
+          else
+            {
+              retval(6) = buffer;
+              retval(1) = Matrix ();
+              retval(0) = Matrix ();
+            }
+        }
       else
         {
           Cell t (dim_vector (1, sz));
-
-          i = 0;
-          for (const_iterator p = lst.begin (); p != lst.end (); p++)
-            t(i++) = p->t;
-
-          retval(4) = t;
-        }
-
-      if (once)
-        retval(3) = sz ? lst.front ().m : std::string ();
-      else
-        {
           Cell m (dim_vector (1, sz));
-
-          i = 0;
-          for (const_iterator p = lst.begin (); p != lst.end (); p++)
-            m(i++) = p->m;
-
-          retval(3) = m;
-        }
-
-      if (once)
-        retval(2) = sz ? lst.front ().te : Matrix ();
-      else
-        {
           Cell te (dim_vector (1, sz));
+          NDArray e (dim_vector (1, sz));
+          NDArray s (dim_vector (1, sz));
+          Cell sp (dim_vector (1, sz+1));
+          size_t sp_start = 0;
 
           i = 0;
           for (const_iterator p = lst.begin (); p != lst.end (); p++)
-            te(i++) = p->te;
-
-          retval(2) = te;
-        }
-
-      if (once)
-        {
-          if (sz)
-            retval(1) = lst.front ().e;
-          else
-            retval(1) = Matrix ();
-        }
-      else
-        {
-          NDArray e (dim_vector (1, sz));
+            {
+              t(i) = p->t;
+              m(i) = p->m;
+              te(i) = p->te;
+              e(i) = p->e;
+              s(i) = p->s;
+              sp(i) = buffer.substr (sp_start, p->s-sp_start-1);
+              sp_start = p->e;
+              i++;
+            }
 
-          i = 0;
-          for (const_iterator p = lst.begin (); p != lst.end (); p++)
-            e(i++) = p->e;
-
-          retval(1) = e;
-        }
+          sp(i) = buffer.substr (sp_start);
 
-      if (once)
-        {
-          if (sz)
-            retval(0) = lst.front ().s;
-          else
-            retval(0) = Matrix ();
-        }
-      else
-        {
-          NDArray s (dim_vector (1, sz));
-
-          i = 0;
-          for (const_iterator p = lst.begin (); p != lst.end (); p++)
-            s(i++) = p->s;
-
+          retval(6) = sp;
+          retval(4) = t;
+          retval(3) = m;
+          retval(2) = te;
+          retval(1) = e;
           retval(0) = s;
         }
 
@@ -661,6 +650,8 @@
                 k = 4;
               else if (str.find ("names", 0) == 0)
                 k = 5;
+              else if (str.find ("split", 0) == 0)
+                k = 6;
 
               new_retval(n++) = retval(k);
               arg_used[k] = true;
@@ -947,6 +938,8 @@
 A structure containing the text of each matched named token, with the name\n\
 being used as the fieldname.  A named token is denoted by\n\
 @code{(?<name>@dots{})}.\n\
+@item sp\n\
+A cell array of the text not returned by match.\n\
 @end table\n\
 \n\
 Particular output arguments, or the order of the output arguments, can be\n\
@@ -961,6 +954,7 @@
 @item @tab 'match'        @tab @var{m}  @tab\n\
 @item @tab 'tokens'       @tab @var{t}  @tab\n\
 @item @tab 'names'        @tab @var{nm} @tab\n\
+@item @tab 'split'        @tab @var{sp} @tab\n\
 @end multitable\n\
 \n\
 Additional arguments are summarized below.\n\
@@ -1200,6 +1194,45 @@
 %! assert(regexp("qit",'q(?=u*)','match'), {'q'})
 %! assert(regexp('thingamabob','(?<=a)b'), 9)
 
+## Tests for split option.
+%!shared str
+%! str = "foo bar foo";
+%!test
+%! [a, b] = regexp (str, "f..", "match", "split");
+%! assert (a, {"foo", "foo"});
+%! assert (b, {"", " bar ", ""});
+%!test
+%! [a, b] = regexp (str, "f..", "match", "split", "once");
+%! assert (a, "foo");
+%! assert (b, {"", " bar foo"});
+%!test
+%! [a, b] = regexp (str, "fx.", "match", "split");
+%! assert (a, cell (1, 0));
+%! assert (b, {"foo bar foo"});
+%!test
+%! [a, b] = regexp (str, "fx.", "match", "split", "once");
+%! assert (a, "");
+%! assert (b, "foo bar foo")
+
+%!shared str
+%! str = "foo bar";
+%!test
+%! [a, b] = regexp (str, "f..", "match", "split");
+%! assert (a, {"foo"});
+%! assert (b, {"", " bar"});
+%!test
+%! [a, b] = regexp (str, "b..", "match", "split");
+%! assert (a, {"bar"});
+%! assert (b, {"foo ", ""});
+%!test
+%! [a, b] = regexp (str, "x", "match", "split");
+%! assert (a, cell (1, 0));
+%! assert (b, {"foo bar"});
+%!test
+%! [a, b] = regexp (str, "[o]+", "match", "split");
+%! assert (a, {"oo"});
+%! assert (b, {"f", " bar"});
+
 */
 
 DEFUN_DLD (regexpi, args, nargout,
@@ -1395,7 +1428,7 @@
       const std::string opt = args(i).string_value ();
       if (opt != "tokenize" && opt != "start" && opt != "end"
           && opt != "tokenextents" && opt != "match" && opt != "tokens"
-          && opt != "names"  && opt != "warnings")
+          && opt != "names"  && opt != "split" && opt != "warnings")
         {
           regexpargs(len++) = args(i);
         }
@@ -1670,7 +1703,8 @@
             }
 
           if (!error_state)
-            retval = octave_value (ret);
+            retval = args(0).is_cell ()
+              ? octave_value (ret) : octave_value (ret(0));
         }
     }
   else
@@ -1726,7 +1760,7 @@
 %!assert(regexprep("abc","(b)","$1.."),"ab..c");
 
 ## Test cell array arguments
-%!assert(regexprep("abc",{"b","a"},"?"),{"??c"})
+%!assert(regexprep("abc",{"b","a"},"?"),"??c")
 %!assert(regexprep({"abc","cba"},"b","?"),{"a?c","c?a"})
 %!assert(regexprep({"abc","cba"},{"b","a"},{"?","!"}),{"!?c","c?!"})
 
--- a/src/data.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/data.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -589,7 +589,7 @@
             {
               FloatNDArray a0 = args(0).float_array_value ();
               FloatNDArray a1 = args(1).float_array_value ();
-              retval = binmap<float> (a0, a1, xrem, "rem");
+              retval = binmap<float> (a0, a1, xrem<float>, "rem");
             }
         }
       else
@@ -603,13 +603,13 @@
             {
               SparseMatrix m0 = args(0).sparse_matrix_value ();
               SparseMatrix m1 = args(1).sparse_matrix_value ();
-              retval = binmap<double> (m0, m1, xrem, "rem");
+              retval = binmap<double> (m0, m1, xrem<double>, "rem");
             }
           else
             {
               NDArray a0 = args(0).array_value ();
               NDArray a1 = args(1).array_value ();
-              retval = binmap<double> (a0, a1, xrem, "rem");
+              retval = binmap<double> (a0, a1, xrem<double>, "rem");
             }
         }
     }
@@ -722,7 +722,7 @@
             {
               FloatNDArray a0 = args(0).float_array_value ();
               FloatNDArray a1 = args(1).float_array_value ();
-              retval = binmap<float> (a0, a1, xmod, "mod");
+              retval = binmap<float> (a0, a1, xmod<float>, "mod");
             }
         }
       else
@@ -736,13 +736,13 @@
             {
               SparseMatrix m0 = args(0).sparse_matrix_value ();
               SparseMatrix m1 = args(1).sparse_matrix_value ();
-              retval = binmap<double> (m0, m1, xmod, "mod");
+              retval = binmap<double> (m0, m1, xmod<double>, "mod");
             }
           else
             {
               NDArray a0 = args(0).array_value ();
               NDArray a1 = args(1).array_value ();
-              retval = binmap<double> (a0, a1, xmod, "mod");
+              retval = binmap<double> (a0, a1, xmod<double>, "mod");
             }
         }
     }
--- a/src/debug.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/debug.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -835,13 +835,8 @@
   return retval;
 }
 
-DEFUN (dbstack, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {[@var{stack}, @var{idx}]} dbstack (@var{n})\n\
-Print or return current stack information.  With optional argument\n\
-@var{n}, omit the @var{n} innermost stack frames.\n\
-@seealso{dbclear, dbstatus, dbstop}\n\
-@end deftypefn")
+static octave_value_list
+do_dbstack (const octave_value_list& args, int nargout, std::ostream& os)
 {
   octave_value_list retval;
 
@@ -882,7 +877,7 @@
 
           if (nframes_to_display > 0)
             {
-              octave_stdout << "stopped in:\n\n";
+              os << "stopped in:\n\n";
 
               Cell names = stk.contents ("name");
               Cell files = stk.contents ("file");
@@ -908,15 +903,15 @@
                   if (show_top_level && i == curr_frame)
                     show_top_level = false;
 
-                  octave_stdout << (i == curr_frame ? "  --> " : "      ")
-                                << std::setw (max_name_len) << name
-                                << " at line " << line
-                                << " [" << file << "]"
-                                << std::endl;
+                  os << (i == curr_frame ? "  --> " : "      ")
+                     << std::setw (max_name_len) << name
+                     << " at line " << line
+                     << " [" << file << "]"
+                     << std::endl;
                 }
 
               if (show_top_level)
-                octave_stdout << "  --> top level" << std::endl;
+                os << "  --> top level" << std::endl;
             }
         }
       else
@@ -929,6 +924,28 @@
   return retval;
 }
 
+// A function that can be easily called from a debugger print the Octave
+// stack.  This can be useful for finding what line of code the
+// interpreter is currently executing when the debugger is stopped in
+// some C++ function, for example.
+
+static void
+show_octave_dbstack (void)
+{
+  do_dbstack (octave_value_list (), 0, std::cerr);
+}
+
+DEFUN (dbstack, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {[@var{stack}, @var{idx}]} dbstack (@var{n})\n\
+Print or return current stack information.  With optional argument\n\
+@var{n}, omit the @var{n} innermost stack frames.\n\
+@seealso{dbclear, dbstatus, dbstop}\n\
+@end deftypefn")
+{
+  return do_dbstack (args, nargout, octave_stdout);
+}
+
 static void
 do_dbupdown (const octave_value_list& args, const std::string& who)
 {
--- a/src/error.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/error.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -1062,6 +1062,10 @@
         }
       else if (nargin == 1 && args(0).is_map ())
         {
+          // empty struct is not an error.  return and resume calling function.
+          if (args(0).is_empty ())
+            return retval;
+
           octave_value_list tmp;
 
           octave_scalar_map m = args(0).scalar_map_value ();
--- a/src/gl-render.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/gl-render.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -567,7 +567,9 @@
     draw_text (dynamic_cast<const text::properties&> (props));
   else if (go.isa ("image"))
     draw_image (dynamic_cast<const image::properties&> (props));
-  else if (go.isa ("uimenu") || go.isa ("uicontrol"))
+  else if (go.isa ("uimenu") || go.isa ("uicontrol")
+           || go.isa ("uicontextmenu") || go.isa ("uitoolbar")
+           || go.isa ("uipushtool") || go.isa ("uitoggletool"))
     /* SKIP */;
   else if (go.isa ("uipanel"))
     {
--- a/src/gl2ps.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/gl2ps.h	Sat Oct 22 16:22:04 2011 -0700
@@ -46,6 +46,7 @@
 #    pragma warning(disable:4115)
 #    pragma warning(disable:4996)
 #  endif
+#  define WIN32_LEAN_AND_MEAN
 #  include <windows.h>
 #  if defined(GL2PSDLL)
 #    if defined(GL2PSDLL_EXPORTS)
--- a/src/graphics.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/graphics.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -813,14 +813,36 @@
                   pfx = name.substr (0, 7);
 
                   if (pfx.compare ("surface") || pfx.compare ("hggroup")
-		      || pfx.compare ("uipanel"))
+                      || pfx.compare ("uipanel"))
                     offset = 7;
                   else if (len >= 9)
                     {
                       pfx = name.substr (0, 9);
 
-                      if (pfx.compare ("uicontrol"))
+                      if (pfx.compare ("uicontrol")
+                          || pfx.compare ("uitoolbar"))
                         offset = 9;
+                      else if (len >= 10)
+                        {
+                          pfx = name.substr (0, 10);
+
+                          if (pfx.compare ("uipushtool"))
+                            offset = 10;
+                          else if (len >= 12)
+                            {
+                              pfx = name.substr (0, 12);
+
+                              if (pfx.compare ("uitoggletool"))
+                                offset = 12;
+                              else if (len >= 13)
+                                {
+                                  pfx = name.substr (0, 13);
+
+                                  if (pfx.compare ("uicontextmenu"))
+                                    offset = 13;
+                                }
+                            }
+                        }
                     }
                 }
             }
@@ -866,6 +888,14 @@
     go = new uicontrol (h, p);
   else if (type.compare ("uipanel"))
     go = new uipanel (h, p);
+  else if (type.compare ("uicontextmenu"))
+    go = new uicontextmenu (h, p);
+  else if (type.compare ("uitoolbar"))
+    go = new uitoolbar (h, p);
+  else if (type.compare ("uipushtool"))
+    go = new uipushtool (h, p);
+  else if (type.compare ("uitoggletool"))
+    go = new uitoggletool (h, p);
   return go;
 }
 
@@ -1387,11 +1417,33 @@
   return false;
 }
 
+// If TRUE, we are executing any callback function, or the functions it
+// calls.  Used to determine handle visibility inside callback
+// functions.
+static bool executing_callback = false;
+
 void
 callback_property::execute (const octave_value& data) const
 {
-  if (callback.is_defined () && ! callback.is_empty ())
-    gh_manager::execute_callback (get_parent (), callback, data);
+  unwind_protect frame;
+
+  // We are executing the callback function associated with this
+  // callback property.  When set to true, we avoid recursive calls to
+  // callback routines.
+  frame.protect_var (executing);
+
+  // We are executing a callback function, so allow handles that have
+  // their handlevisibility property set to "callback" to be visible.
+  frame.protect_var (executing_callback);
+
+  if (! executing)
+    {
+      executing = true;
+      executing_callback = true;
+
+      if (callback.is_defined () && ! callback.is_empty ())
+        gh_manager::execute_callback (get_parent (), callback, data);
+    }
 }
 
 // Used to cache dummy graphics objects from which dynamic
@@ -1635,8 +1687,30 @@
                     {
                       pfx = name.substr (0, 9);
 
-                      if (pfx.compare ("uicontrol"))
+                      if (pfx.compare ("uicontrol")
+                          || pfx.compare ("uitoolbar"))
                         offset = 9;
+                      else if (len > 10)
+                        {
+                          pfx = name.substr (0, 10);
+
+                          if (pfx.compare ("uipushtool"))
+                            offset = 10;
+                          else if (len > 12)
+                            {
+                              pfx = name.substr (0, 12);
+
+                              if (pfx.compare ("uitoogletool"))
+                                offset = 12;
+                              else if (len > 13)
+                                {
+                                  pfx = name.substr (0, 13);
+
+                                  if (pfx.compare ("uicontextmenu"))
+                                    offset = 13;
+                                }
+                            }
+                        }
                     }
                 }
             }
@@ -1674,6 +1748,12 @@
             has_property = uicontrol::properties::has_core_property (pname);
           else if (pfx == "uipanel")
             has_property = uipanel::properties::has_core_property (pname);
+          else if (pfx == "uicontextmenu")
+            has_property = uicontextmenu::properties::has_core_property (pname);
+          else if (pfx == "uitoolbar")
+            has_property = uitoolbar::properties::has_core_property (pname);
+          else if (pfx == "uipushtool")
+            has_property = uipushtool::properties::has_core_property (pname);
 
           if (has_property)
             {
@@ -1745,8 +1825,30 @@
                     {
                       pfx = name.substr (0, 9);
 
-                      if (pfx.compare ("uicontrol"))
+                      if (pfx.compare ("uicontrol")
+                          || pfx.compare ("uitoolbar"))
                         offset = 9;
+                      else if (len > 10)
+                        {
+                          pfx = name.substr (0, 10);
+
+                          if (pfx.compare ("uipushtool"))
+                            offset = 10;
+                          else if (len > 12)
+                            {
+                              pfx = name.substr (0, 12);
+
+                              if (pfx.compare ("uitoggletool"))
+                                offset = 12;
+                              else if (len > 13)
+                                {
+                                  pfx = name.substr (0, 13);
+
+                                  if (pfx.compare ("uicontextmenu"))
+                                    offset = 13;
+                                }
+                            }
+                        }
                     }
                 }
             }
@@ -2436,6 +2538,13 @@
     obj.update_axis_limits (axis_type, h);
 }
 
+bool
+base_properties::is_handle_visible (void) const
+{
+  return (handlevisibility.is ("on")
+          || (executing_callback && ! handlevisibility.is ("off")));
+}
+
 graphics_toolkit
 base_properties::get_toolkit (void) const
 {
@@ -2957,13 +3066,14 @@
 }
 
 Matrix
-figure::properties::get_boundingbox (bool, const Matrix&) const
+figure::properties::get_boundingbox (bool internal, const Matrix&) const
 {
   Matrix screen_size = screen_size_pixels ();
-  Matrix pos;
-
-  pos = convert_position (get_position ().matrix_value (), get_units (),
-                          "pixels", screen_size);
+  Matrix pos = (internal ?
+                get_position ().matrix_value () :
+                get_outerposition ().matrix_value ());
+
+  pos = convert_position (pos, get_units (), "pixels", screen_size);
 
   pos(0)--;
   pos(1)--;
@@ -2973,7 +3083,8 @@
 }
 
 void
-figure::properties::set_boundingbox (const Matrix& bb)
+figure::properties::set_boundingbox (const Matrix& bb, bool internal,
+                                     bool do_notify_toolkit)
 {
   Matrix screen_size = screen_size_pixels ();
   Matrix pos = bb;
@@ -2983,7 +3094,10 @@
   pos(0)++;
   pos = convert_position (pos, "pixels", get_units (), screen_size);
 
-  set_position (pos);
+  if (internal)
+    set_position (pos, do_notify_toolkit);
+  else
+    set_outerposition (pos, do_notify_toolkit);
 }
 
 Matrix
@@ -3021,14 +3135,15 @@
 }
 
 void
-figure::properties::set_position (const octave_value& v)
+figure::properties::set_position (const octave_value& v,
+                                  bool do_notify_toolkit)
 {
   if (! error_state)
     {
       Matrix old_bb, new_bb;
 
       old_bb = get_boundingbox ();
-      position = v;
+      position.set (v, true, do_notify_toolkit);
       new_bb = get_boundingbox ();
 
       if (old_bb != new_bb)
@@ -3045,6 +3160,19 @@
 }
 
 void
+figure::properties::set_outerposition (const octave_value& v,
+                                       bool do_notify_toolkit)
+{
+  if (! error_state)
+    {
+      if (outerposition.set (v, true, do_notify_toolkit))
+        {
+          mark_modified ();
+        }
+    }
+}
+
+void
 figure::properties::set_paperunits (const octave_value& v)
 {
   if (! error_state)
@@ -6818,8 +6946,8 @@
 {
   Matrix m = extent.get ().matrix_value ();
 
-  graphics_handle parent = get_parent ();
-  graphics_object parent_obj = gh_manager::get_object (parent);
+  graphics_object parent_obj =
+    gh_manager::get_object (get_parent ());
   Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
          parent_size = parent_bbox.extract_n (0, 2, 1, 2);
 
@@ -6841,9 +6969,9 @@
   elt = text_parser_none ().parse (get_string_string ());
 #ifdef HAVE_FONTCONFIG
   text_renderer.set_font (get_fontname (),
-			  get_fontweight (),
-			  get_fontangle (),
-			  get_fontsize ());
+                          get_fontweight (),
+                          get_fontangle (),
+                          get_fontsize ());
 #endif
   box = text_renderer.get_extent (elt, 0);
 
@@ -6865,8 +6993,7 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_handle parent = get_parent ();
-  graphics_object parent_obj = gh_manager::get_object (parent);
+  graphics_object parent_obj = gh_manager::get_object (get_parent ());
   Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
          parent_size = parent_bbox.extract_n (0, 2, 1, 2);
   
@@ -7037,8 +7164,7 @@
 {
   Matrix pos = get_position ().matrix_value ();
 
-  graphics_handle parent = get_parent ();
-  graphics_object parent_obj = gh_manager::get_object (parent);
+  graphics_object parent_obj = gh_manager::get_object (get_parent ());
   Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
          parent_size = parent_bbox.extract_n (0, 2, 1, 2);
   
@@ -7087,6 +7213,30 @@
 // ---------------------------------------------------------------------
 
 octave_value
+uitoolbar::get_default (const caseless_str& name) const
+{
+  octave_value retval = default_properties.lookup (name);
+
+  if (retval.is_undefined ())
+    {
+      graphics_handle parent = get_parent ();
+      graphics_object parent_obj = gh_manager::get_object (parent);
+
+      retval = parent_obj.get_default (name);
+    }
+
+  return retval;
+}
+
+void
+uitoolbar::reset_default_properties (void)
+{
+  ::reset_default_properties (default_properties);
+}
+
+// ---------------------------------------------------------------------
+
+octave_value
 base_graphics_object::get_default (const caseless_str& name) const
 {
   graphics_handle parent = get_parent ();
@@ -7549,7 +7699,7 @@
           gh_manager::unlock ();
 
           if (e.ok ())
-	    e.execute ();
+            e.execute ();
         }
       while (e.ok ());
 
@@ -7576,7 +7726,7 @@
 void 
 gh_manager::do_enable_event_processing (bool enable)
 {
-  gh_manager::auto_lock lock;
+  gh_manager::auto_lock guard;
 
   if (enable)
     {
@@ -7609,6 +7759,10 @@
   plist_map["uimenu"] = uimenu::properties::factory_defaults ();
   plist_map["uicontrol"] = uicontrol::properties::factory_defaults ();
   plist_map["uipanel"] = uipanel::properties::factory_defaults ();
+  plist_map["uicontextmenu"] = uicontextmenu::properties::factory_defaults ();
+  plist_map["uitoolbar"] = uitoolbar::properties::factory_defaults ();
+  plist_map["uipushtool"] = uipushtool::properties::factory_defaults ();
+  plist_map["uitoggletool"] = uitoggletool::properties::factory_defaults ();
 
   return plist_map;
 }
@@ -7637,6 +7791,59 @@
   return retval;
 }
 
+static bool
+is_handle_visible (const graphics_handle& h)
+{
+  return h.ok () && gh_manager::is_handle_visible (h);
+}
+
+static bool
+is_handle_visible (double val)
+{
+  return is_handle_visible (gh_manager::lookup (val));
+}
+
+static octave_value
+is_handle_visible (const octave_value& val)
+{
+  octave_value retval = false;
+
+  if (val.is_real_scalar () && is_handle_visible (val.double_value ()))
+    retval = true;
+  else if (val.is_numeric_type () && val.is_real_type ())
+    {
+      const NDArray handles = val.array_value ();
+
+      if (! error_state)
+        {
+          boolNDArray result (handles.dims ());
+
+          for (octave_idx_type i = 0; i < handles.numel (); i++)
+            result.xelem (i) = is_handle_visible (handles (i));
+
+          retval = result;
+        }
+    }
+
+  return retval;
+}
+
+DEFUN (__is_handle_visible__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} __is_handle_visible__ (@var{h})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    retval = is_handle_visible (args(0));
+  else
+    print_usage ();
+
+  return retval;
+}
+
 DEFUN (reset, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} reset (@var{h}, @var{property})\n\
@@ -8084,7 +8291,7 @@
 
               if (xisnan (val))
                 h = gh_manager::make_graphics_handle ("figure", 0, false,
-						      false);
+                                                      false);
               else if (val > 0 && D_NINT (val) == val)
                 h = gh_manager::make_figure_handle (val, false);
               else
@@ -8276,6 +8483,42 @@
   GO_BODY (uipanel);
 }
 
+DEFUN (__go_uicontextmenu__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __go_uicontextmenu__ (@var{parent})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  GO_BODY (uicontextmenu);
+}
+
+DEFUN (__go_uitoolbar__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __go_uitoolbar__ (@var{parent})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  GO_BODY (uitoolbar);
+}
+
+DEFUN (__go_uipushtool__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __go_uipushtool__ (@var{parent})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  GO_BODY (uipushtool);
+}
+
+DEFUN (__go_uitoggletool__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __go_uitoggletool__ (@var{parent})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  GO_BODY (uitoggletool);
+}
+
 DEFUN (__go_delete__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} __go_delete__ (@var{h})\n\
--- a/src/graphics.h.in	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/graphics.h.in	Sat Oct 22 16:22:04 2011 -0700
@@ -364,8 +364,8 @@
 
   // Sets property value, notifies graphics toolkit.
   // If do_run is true, runs associated listeners.
-  bool set (const octave_value& v, bool do_run = true,
-            bool do_notify_toolkit = true);
+  OCTINTERP_API bool set (const octave_value& v, bool do_run = true,
+                          bool do_notify_toolkit = true);
 
   virtual octave_value get (void) const
     {
@@ -1813,10 +1813,10 @@
 public:
   callback_property (const std::string& nm, const graphics_handle& h,
                      const octave_value& m)
-    : base_property (nm, h), callback (m) { }
+    : base_property (nm, h), callback (m), executing (false) { }
 
   callback_property (const callback_property& p)
-    : base_property (p), callback (p.callback) { }
+    : base_property (p), callback (p.callback), executing (false) { }
 
   octave_value get (void) const { return callback; }
 
@@ -1854,6 +1854,9 @@
 
 private:
   octave_value callback;
+
+  // If TRUE, we are executing this callback.
+  mutable bool executing;
 };
 
 // ---------------------------------------------------------------------
@@ -2379,10 +2382,7 @@
   virtual bool is_climinclude (void) const { return false; }
   virtual bool is_aliminclude (void) const { return false; }
 
-  bool is_handle_visible (void) const
-  {
-    return ! handlevisibility.is ("off");
-  }
+  bool is_handle_visible (void) const;
 
   std::set<std::string> dynamic_property_names (void) const;
 
@@ -2699,9 +2699,12 @@
 
   // No copying!
 
-  base_graphics_object (const base_graphics_object&);
-
-  base_graphics_object& operator = (const base_graphics_object&);
+  base_graphics_object (const base_graphics_object&) : count (0) { }
+
+  base_graphics_object& operator = (const base_graphics_object&)
+  {
+    return *this;
+  }
 };
 
 class OCTINTERP_API graphics_object
@@ -3095,10 +3098,17 @@
         }
     }
 
+    void set_position (const octave_value& val,
+                       bool do_notify_toolkit = true);
+
+    void set_outerposition (const octave_value& val,
+                            bool do_notify_toolkit = true);
+
     Matrix get_boundingbox (bool internal = false,
                             const Matrix& parent_pix_size = Matrix ()) const;
 
-    void set_boundingbox (const Matrix& bb);
+    void set_boundingbox (const Matrix& bb, bool internal = false,
+                          bool do_notify_toolkit = true);
 
     Matrix map_from_boundingbox (double x, double y) const;
 
@@ -3137,6 +3147,7 @@
       double_property mincolormap , 64
       string_property name , ""
       bool_property numbertitle , "on"
+      array_property outerposition s , Matrix (1, 4, -1.0)
       radio_property paperunits Su , "{inches}|centimeters|normalized|points"
       array_property paperposition , default_figure_paperposition ()
       radio_property paperpositionmode , "auto|{manual}"
@@ -3145,7 +3156,7 @@
       radio_property pointer , "crosshair|fullcrosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
       array_property pointershapecdata , Matrix (16, 16, 0)
       array_property pointershapehotspot , Matrix (1, 2, 0)
-      array_property position S , default_figure_position ()
+      array_property position s , default_figure_position ()
       radio_property renderer , "{painters}|zbuffer|opengl|none"
       radio_property renderermode , "{auto}|manual"
       bool_property resize , "on"
@@ -3165,6 +3176,7 @@
       radio_property xvisualmode , "{auto}|manual"
       callback_property buttondownfcn , Matrix ()
       string_property __graphics_toolkit__ s , "gnuplot"
+      any_property __guidata__ h , Matrix ()
     END_PROPERTIES
 
   protected:
@@ -3176,6 +3188,7 @@
         pointershapecdata.add_constraint (dim_vector (16, 16));
         pointershapehotspot.add_constraint (dim_vector (1, 2));
         position.add_constraint (dim_vector (1, 4));
+        outerposition.add_constraint (dim_vector (1, 4));
       }
 
   private:
@@ -4573,6 +4586,7 @@
     // properties declarations.
 
     BEGIN_PROPERTIES (uimenu)
+      any_property __object__ , Matrix ()
       string_property accelerator , ""
       callback_property callback , Matrix()
       bool_property checked , "off"
@@ -4611,6 +4625,52 @@
 
 // ---------------------------------------------------------------------
 
+class OCTINTERP_API uicontextmenu : public base_graphics_object
+{
+public:
+  class OCTINTERP_API properties : public base_properties
+  {
+  public:
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES (uicontextmenu)
+      any_property __object__ , Matrix ()
+      callback_property callback , Matrix()
+      array_property position , Matrix (1, 2, 0.0)
+    END_PROPERTIES
+
+  protected:
+    void init (void)
+      {
+        position.add_constraint (dim_vector (1, 2));
+        position.add_constraint (dim_vector (2, 1));
+        visible.set (octave_value (false));
+      }
+  };
+
+private:
+  properties xproperties;
+
+public:
+  uicontextmenu (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~uicontextmenu (void) { xproperties.delete_children (); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  const base_properties& get_properties (void) const { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+};
+
+// ---------------------------------------------------------------------
+
 class OCTINTERP_API uicontrol : public base_graphics_object
 {
 public:
@@ -4661,6 +4721,8 @@
     void init (void)
       {
         cdata.add_constraint ("double");
+        cdata.add_constraint ("single");
+        cdata.add_constraint ("uint8");
         cdata.add_constraint (dim_vector (-1, -1, 3));
         position.add_constraint (dim_vector (1, 4));
         sliderstep.add_constraint (dim_vector (1, 2));
@@ -4767,6 +4829,197 @@
 
 // ---------------------------------------------------------------------
 
+class OCTINTERP_API uitoolbar : public base_graphics_object
+{
+public:
+  class OCTINTERP_API properties : public base_properties
+  {
+  public:
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES (uitoolbar)
+      any_property __object__ , Matrix ()
+    END_PROPERTIES
+
+  protected:
+    void init (void)
+      { }
+  };
+
+private:
+  properties xproperties;
+
+public:
+  uitoolbar (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p), default_properties ()
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~uitoolbar (void) { xproperties.delete_children (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+
+    // Now override with our defaults.  If the default_properties
+    // list includes the properties for all defaults (line,
+    // surface, etc.) then we don't have to know the type of OBJ
+    // here, we just call its set function and let it decide which
+    // properties from the list to use.
+    obj.set_from_list (default_properties);
+  }
+
+  void set (const caseless_str& name, const octave_value& value)
+  {
+    if (name.compare ("default", 7))
+      // strip "default", pass rest to function that will
+      // parse the remainder and add the element to the
+      // default_properties map.
+      default_properties.set (name.substr (7), value);
+    else
+      xproperties.set (name, value);
+  }
+
+  octave_value get (const caseless_str& name) const
+  {
+    octave_value retval;
+
+    if (name.compare ("default", 7))
+      retval = get_default (name.substr (7));
+    else
+      retval = xproperties.get (name);
+
+    return retval;
+  }
+
+  octave_value get_default (const caseless_str& name) const;
+
+  octave_value get_defaults (void) const
+  {
+    return default_properties.as_struct ("default");
+  }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  const base_properties& get_properties (void) const { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+  void reset_default_properties (void);
+
+private:
+  property_list default_properties;
+};
+
+// ---------------------------------------------------------------------
+
+class OCTINTERP_API uipushtool : public base_graphics_object
+{
+public:
+  class OCTINTERP_API properties : public base_properties
+  {
+  public:
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES (uipushtool)
+      any_property __object__ , Matrix ()
+      array_property cdata , Matrix ()
+      callback_property clickedcallback , Matrix()
+      bool_property enable , "on"
+      bool_property separator , "off"
+      string_property tooltipstring , ""
+    END_PROPERTIES
+
+  protected:
+    void init (void)
+      {
+        cdata.add_constraint ("double");
+        cdata.add_constraint ("single");
+        cdata.add_constraint ("uint8");
+        cdata.add_constraint (dim_vector (-1, -1, 3));
+      }
+  };
+
+private:
+  properties xproperties;
+
+public:
+  uipushtool (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~uipushtool (void) { xproperties.delete_children (); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  const base_properties& get_properties (void) const { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+};
+
+// ---------------------------------------------------------------------
+
+class OCTINTERP_API uitoggletool : public base_graphics_object
+{
+public:
+  class OCTINTERP_API properties : public base_properties
+  {
+  public:
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES (uitoggletool)
+      any_property __object__ , Matrix ()
+      array_property cdata , Matrix ()
+      callback_property clickedcallback , Matrix()
+      bool_property enable , "on"
+      callback_property offcallback , Matrix()
+      callback_property oncallback , Matrix()
+      bool_property separator , "off"
+      bool_property state , "off"
+      string_property tooltipstring , ""
+    END_PROPERTIES
+
+  protected:
+    void init (void)
+      {
+        cdata.add_constraint ("double");
+        cdata.add_constraint ("single");
+        cdata.add_constraint ("uint8");
+        cdata.add_constraint (dim_vector (-1, -1, 3));
+      }
+  };
+
+private:
+  properties xproperties;
+
+public:
+  uitoggletool (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~uitoggletool (void) { xproperties.delete_children (); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  const base_properties& get_properties (void) const { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+};
+
+// ---------------------------------------------------------------------
+
 octave_value
 get_property_from_handle (double handle, const std::string &property,
                           const std::string &func);
--- a/src/ov-base-mat.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov-base-mat.h	Sat Oct 22 16:22:04 2011 -0700
@@ -89,6 +89,9 @@
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
+  octave_value_list do_multi_index_op (int, const octave_value_list& idx)
+    { return do_index_op (idx); }
+
   void assign (const octave_value_list& idx, const MT& rhs);
 
   void assign (const octave_value_list& idx, typename MT::element_type rhs);
--- a/src/ov-class.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov-class.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -88,7 +88,15 @@
             {
               parent_list.push_back (cnm);
 
-              map.assign (cnm, parent);
+              if (map.numel () > 1)
+                {
+                  // If MAP has more than one element, put the parent
+                  // class object in each element.
+
+                  map.assign (cnm, Cell (map.dims (), parent));
+                }
+              else
+                map.assign (cnm, parent);
             }
         }
     }
@@ -322,6 +330,17 @@
       else
         error ("@%s/size: invalid return value", class_name ().c_str ());
     }
+  else
+    {
+      dim_vector dv = dims ();
+
+      int nel = dv.numel ();
+
+      retval.resize (1, nel);
+
+      for (int i = 0; i < nel; i++)
+        retval(i) = dv(i);
+    }
 
   return retval;
 }
@@ -475,7 +494,8 @@
       else
         {
           if (type.length () == 1 && type[0] == '(')
-            retval(0) = octave_value (map.index (idx.front ()), class_name ());
+            retval(0) = octave_value (map.index (idx.front ()), class_name (),
+                                      parent_class_name_list ());
           else
             gripe_invalid_index1 ();
         }
@@ -996,6 +1016,35 @@
   return retval;
 }
 
+string_vector
+octave_class::all_strings (bool pad) const
+{
+  string_vector retval;
+
+  octave_value meth = symbol_table::find_method ("char", class_name ());
+
+  if (meth.is_defined ())
+    {
+      octave_value_list args;
+      args(0) = octave_value (new octave_class (map, c_name));
+
+      octave_value_list tmp = feval (meth.function_value (), args, 1);
+
+      if (!error_state && tmp.length () >= 1)
+        {
+          if (tmp(0).is_string ())
+            retval = tmp(0).all_strings (pad);
+          else
+            error ("cname/char method did not return a character string");
+        }
+    }
+  else
+    error ("no char method defined for class %s", class_name().c_str ());
+
+  return retval;
+}
+
+
 void
 octave_class::print (std::ostream& os, bool) const
 {
--- a/src/ov-class.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov-class.h	Sat Oct 22 16:22:04 2011 -0700
@@ -168,6 +168,8 @@
 
   octave_base_value *unique_parent_class (const std::string&);
 
+  string_vector all_strings (bool pad) const;
+
   void print (std::ostream& os, bool pr_as_read_syntax = false) const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
--- a/src/ov-fcn-handle.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov-fcn-handle.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -1956,3 +1956,12 @@
 
   return retval;
 }
+
+/*
+%!function r = f (g, i)
+%!  r = g(i);
+%!endfunction
+%!test
+%! x = [1,2;3,4];
+%! assert (f (@(i) x(:,i), 1), [1;3]);
+*/
--- a/src/ov-struct.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov-struct.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -480,7 +480,7 @@
               }
             else
               {
-                if (t_rhs.is_map())
+                if (t_rhs.is_map() || t_rhs.is_object ())
                   {
                     octave_map rhs_map = t_rhs.map_value ();
 
--- a/src/ov.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -2882,3 +2882,52 @@
 
 */
 
+DEFUN (is_sq_string, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} is_sq_string (@var{val})\n\
+Return true if @var{val} is a single-quoted character string\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    retval = args(0).is_sq_string ();
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (is_sq_string ('foo'), true);
+%!assert (is_sq_string ("foo"), false);
+%!assert (is_sq_string (1.0), false);
+%!assert (is_sq_string ({2.0}), false);
+%!error is_sq_string ()
+%!error is_sq_string ('foo', 2)
+*/
+
+DEFUN (is_dq_string, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} is_dq_string (@var{val})\n\
+Return true if @var{val} is a double-quoted character string\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    retval = args(0).is_dq_string ();
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (is_dq_string ("foo"), true);
+%!assert (is_dq_string ('foo'), false);
+%!assert (is_dq_string (1.0), false);
+%!assert (is_dq_string ({2.0}), false);
+%!error is_dq_string ()
+%!error is_dq_string ("foo", 2)
+*/
--- a/src/ov.h	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/ov.h	Sat Oct 22 16:22:04 2011 -0700
@@ -1371,4 +1371,13 @@
 DEF_VALUE_EXTRACTOR (SparseBoolMatrix, sparse_bool_matrix)
 #undef DEF_VALUE_EXTRACTOR
 
+#define DEF_DUMMY_VALUE_EXTRACTOR(VALUE,DEFVAL) \
+template<> \
+inline VALUE octave_value_extract<VALUE> (const octave_value&) \
+  { assert (false); return DEFVAL; }
+
+DEF_DUMMY_VALUE_EXTRACTOR (char, 0)
+DEF_DUMMY_VALUE_EXTRACTOR (octave_value, octave_value ())
+#undef DEF_DUMMY_VALUE_EXTRACTOR
+
 #endif
--- a/src/txt-eng-ft.cc	Wed Oct 12 13:45:43 2011 -0500
+++ b/src/txt-eng-ft.cc	Sat Oct 22 16:22:04 2011 -0700
@@ -36,6 +36,33 @@
 #include "pr-output.h"
 #include "txt-eng-ft.h"
 
+// FIXME -- maybe issue at most one warning per glyph/font/size/weight
+// combination.
+
+static void
+gripe_missing_glyph (char c)
+{
+  warning_with_id ("Octave:missing-glyph",
+                   "ft_render: skipping missing glyph for character `%c'",
+                   c);
+}
+
+static void
+gripe_glyph_render (char c)
+{
+  warning_with_id ("Octave:glyph-render",
+                   "ft_render: unable to render glyph for character `%c'",
+                   c);
+}
+
+#ifdef _MSC_VER
+// This is just a trick to avoid multiply symbols definition.
+// PermMatrix.h contains a dllexport'ed Array<octave_idx_type>
+// that will make MSVC not to generate new instantiation and
+// use the imported one.
+#include "PermMatrix.h"
+#endif
+
 class
 ft_manager
 {
@@ -288,8 +315,7 @@
           if (str[i] != '\n'
               && (! glyph_index
               || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
-            ::warning ("ft_render: skipping missing glyph for character `%c'",
-                       str[i]);
+            gripe_missing_glyph (str[i]);
           else
             {
               switch (mode)
@@ -300,7 +326,7 @@
                     glyph_index = FT_Get_Char_Index(face, ' ');
                     if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
                       {
-                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                        gripe_missing_glyph (' ');
                       }
                     else
                       {
@@ -308,10 +334,11 @@
                         xoffset = multiline_align_xoffsets[line_index];
                         yoffset -= (face->size->metrics.height >> 6);
                       }
-                  }
+                    }
                   else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
-                    ::warning ("ft_render: unable to render glyph for character `%c'",
-                               str[i]);
+                    {
+                      gripe_glyph_render (str[i]);
+                    }
                   else
                     {
                       FT_Bitmap& bitmap = face->glyph->bitmap;
@@ -364,7 +391,7 @@
                       if (! glyph_index
                           || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
                       {
-                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                        gripe_missing_glyph (' ');
                       }
                     else
                       {