# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1319325724 25200 # Node ID 510237e67c2bfbc95e8375565fdd65ce5dffb236 # Parent 59fd358079417057cbf7c372deeb6a2b99abff63# Parent 0206484682c61534292d78be1d77d0f31b5f5029 Merge with default diff --git a/build-aux/bootstrap.conf b/build-aux/bootstrap.conf --- a/build-aux/bootstrap.conf +++ b/build-aux/bootstrap.conf @@ -20,6 +20,7 @@ gnulib_modules=" c-strcase copysign + copysignf closedir crypto/md5 fclose diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -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 , but still have to check whether + ### tr1 namespace is required (like MSVC, for instance). + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + ], [ + 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 diff --git a/etc/gdbinit b/etc/gdbinit --- a/etc/gdbinit +++ b/etc/gdbinit @@ -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 + diff --git a/libcruft/arpack/util/second.f b/libcruft/arpack/util/second.f diff --git a/liboctave/CRowVector.h b/liboctave/CRowVector.h --- a/liboctave/CRowVector.h +++ b/liboctave/CRowVector.h @@ -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 diff --git a/liboctave/MArray-i.cc b/liboctave/MArray-i.cc --- a/liboctave/MArray-i.cc +++ b/liboctave/MArray-i.cc @@ -34,6 +34,13 @@ template class OCTAVE_API MArray; template class OCTAVE_API MArray; +// 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); +template int xmax (int, int); +template long xmin (long, long); +template long xmax (long, long); + INSTANTIATE_MARRAY_FRIENDS (int, OCTAVE_API) INSTANTIATE_MARRAY_FRIENDS (long, OCTAVE_API) diff --git a/liboctave/MArray-s.cc b/liboctave/MArray-s.cc --- a/liboctave/MArray-s.cc +++ b/liboctave/MArray-s.cc @@ -31,6 +31,11 @@ template class OCTAVE_API MArray; +// 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); +template short xmax (short, short); + INSTANTIATE_MARRAY_FRIENDS (short, OCTAVE_API) #include "MDiagArray2.h" diff --git a/liboctave/Sparse-op-defs.h b/liboctave/Sparse-op-defs.h --- a/liboctave/Sparse-op-defs.h +++ b/liboctave/Sparse-op-defs.h @@ -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)) \ { \ /* 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) // 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) && 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 (); \ diff --git a/liboctave/boolNDArray.cc b/liboctave/boolNDArray.cc --- a/liboctave/boolNDArray.cc +++ b/liboctave/boolNDArray.cc @@ -40,7 +40,7 @@ boolNDArray boolNDArray::operator ! (void) const { - return do_mx_unary_op (*this, mx_inline_not); + return do_mx_unary_op (*this, mx_inline_not); } boolNDArray& diff --git a/liboctave/bsxfun-defs.cc b/liboctave/bsxfun-defs.cc --- a/liboctave/bsxfun-defs.cc +++ b/liboctave/bsxfun-defs.cc @@ -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; diff --git a/liboctave/fCRowVector.h b/liboctave/fCRowVector.h --- a/liboctave/fCRowVector.h +++ b/liboctave/fCRowVector.h @@ -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 diff --git a/liboctave/idx-vector.cc b/liboctave/idx-vector.cc --- a/liboctave/idx-vector.cc +++ b/liboctave/idx-vector.cc @@ -27,7 +27,6 @@ #endif #include -#include #include diff --git a/liboctave/idx-vector.h b/liboctave/idx-vector.h --- a/liboctave/idx-vector.h +++ b/liboctave/idx-vector.h @@ -29,6 +29,7 @@ #include #include +#include #include "dim-vector.h" #include "oct-inttypes.h" @@ -63,6 +64,8 @@ class_mask }; + template friend class std::auto_ptr; + private: class OCTAVE_API idx_base_rep diff --git a/liboctave/kpse.cc b/liboctave/kpse.cc --- a/liboctave/kpse.cc +++ b/liboctave/kpse.cc @@ -49,8 +49,8 @@ #include #include #elif defined(WIN32) +#ifndef _MSC_VER #define __STDC__ 1 -#ifndef _MSC_VER #include "win32lib.h" #endif #endif /* not WIN32 */ diff --git a/liboctave/lo-cieee.c b/liboctave/lo-cieee.c --- a/liboctave/lo-cieee.c +++ b/liboctave/lo-cieee.c @@ -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) diff --git a/liboctave/lo-mappers.cc b/liboctave/lo-mappers.cc --- a/liboctave/lo-mappers.cc +++ b/liboctave/lo-mappers.cc @@ -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); diff --git a/liboctave/lo-mappers.h b/liboctave/lo-mappers.h --- a/liboctave/lo-mappers.h +++ b/liboctave/lo-mappers.h @@ -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 -OCTAVE_API T X_NINT (T x) { @@ -305,7 +304,6 @@ } template -OCTAVE_API T xmod (T x, T y) { @@ -353,7 +351,6 @@ } template -OCTAVE_API T xrem (T x, T y) { diff --git a/liboctave/oct-inttypes.h b/liboctave/oct-inttypes.h --- a/liboctave/oct-inttypes.h +++ b/liboctave/oct-inttypes.h @@ -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 (x) >> std::numeric_limits::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::max_val () + signbit (~u); + u = octave_int_base::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::max_val () + signbit (~u); + u = octave_int_base::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; } diff --git a/m4/acinclude.m4 b/m4/acinclude.m4 --- a/m4/acinclude.m4 +++ b/m4/acinclude.m4 @@ -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" diff --git a/scripts/image/imshow.m b/scripts/image/imshow.m --- a/scripts/image/imshow.m +++ b/scripts/image/imshow.m @@ -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", diff --git a/scripts/io/strread.m b/scripts/io/strread.m --- a/scripts/io/strread.m +++ b/scripts/io/strread.m @@ -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')) diff --git a/scripts/plot/axes.m b/scripts/plot/axes.m --- a/scripts/plot/axes.m +++ b/scripts/plot/axes.m @@ -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 diff --git a/scripts/plot/axis.m b/scripts/plot/axis.m --- a/scripts/plot/axis.m +++ b/scripts/plot/axis.m @@ -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 + diff --git a/scripts/plot/clf.m b/scripts/plot/clf.m --- a/scripts/plot/clf.m +++ b/scripts/plot/clf.m @@ -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 diff --git a/scripts/plot/figure.m b/scripts/plot/figure.m --- a/scripts/plot/figure.m +++ b/scripts/plot/figure.m @@ -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; diff --git a/scripts/plot/guidata.m b/scripts/plot/guidata.m new file mode 100644 --- /dev/null +++ b/scripts/plot/guidata.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/guihandles.m b/scripts/plot/guihandles.m new file mode 100644 --- /dev/null +++ b/scripts/plot/guihandles.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/ishold.m b/scripts/plot/ishold.m --- a/scripts/plot/ishold.m +++ b/scripts/plot/ishold.m @@ -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)); diff --git a/scripts/plot/module.mk b/scripts/plot/module.mk --- a/scripts/plot/module.mk +++ b/scripts/plot/module.mk @@ -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 \ diff --git a/scripts/plot/private/__file_filter__.m b/scripts/plot/private/__file_filter__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/private/__file_filter__.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/private/__fltk_file_filter__.m b/scripts/plot/private/__fltk_file_filter__.m --- a/scripts/plot/private/__fltk_file_filter__.m +++ b/scripts/plot/private/__fltk_file_filter__.m @@ -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 @@ ## . ## -*- 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 diff --git a/scripts/plot/private/__go_draw_axes__.m b/scripts/plot/private/__go_draw_axes__.m --- a/scripts/plot/private/__go_draw_axes__.m +++ b/scripts/plot/private/__go_draw_axes__.m @@ -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 diff --git a/scripts/plot/private/__is_function__.m b/scripts/plot/private/__is_function__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/private/__is_function__.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/private/__patch__.m b/scripts/plot/private/__patch__.m --- a/scripts/plot/private/__patch__.m +++ b/scripts/plot/private/__patch__.m @@ -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{:}}; diff --git a/scripts/plot/private/__print_parse_opts__.m b/scripts/plot/private/__print_parse_opts__.m --- a/scripts/plot/private/__print_parse_opts__.m +++ b/scripts/plot/private/__print_parse_opts__.m @@ -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)) diff --git a/scripts/plot/private/__uigetdir_fltk__.m b/scripts/plot/private/__uigetdir_fltk__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/private/__uigetdir_fltk__.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/private/__uigetfile_fltk__.m b/scripts/plot/private/__uigetfile_fltk__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/private/__uigetfile_fltk__.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/private/__uiobject_split_args__.m b/scripts/plot/private/__uiobject_split_args__.m --- a/scripts/plot/private/__uiobject_split_args__.m +++ b/scripts/plot/private/__uiobject_split_args__.m @@ -17,28 +17,30 @@ ## . ## -*- 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 diff --git a/scripts/plot/private/__uiputfile_fltk__.m b/scripts/plot/private/__uiputfile_fltk__.m new file mode 100644 --- /dev/null +++ b/scripts/plot/private/__uiputfile_fltk__.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/uicontextmenu.m b/scripts/plot/uicontextmenu.m new file mode 100755 --- /dev/null +++ b/scripts/plot/uicontextmenu.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/uicontrol.m b/scripts/plot/uicontrol.m --- a/scripts/plot/uicontrol.m +++ b/scripts/plot/uicontrol.m @@ -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 diff --git a/scripts/plot/uigetdir.m b/scripts/plot/uigetdir.m --- a/scripts/plot/uigetdir.m +++ b/scripts/plot/uigetdir.m @@ -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 diff --git a/scripts/plot/uigetfile.m b/scripts/plot/uigetfile.m --- a/scripts/plot/uigetfile.m +++ b/scripts/plot/uigetfile.m @@ -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 diff --git a/scripts/plot/uimenu.m b/scripts/plot/uimenu.m old mode 100644 new mode 100755 --- a/scripts/plot/uimenu.m +++ b/scripts/plot/uimenu.m @@ -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{:}); diff --git a/scripts/plot/uipanel.m b/scripts/plot/uipanel.m --- a/scripts/plot/uipanel.m +++ b/scripts/plot/uipanel.m @@ -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 diff --git a/scripts/plot/uipushtool.m b/scripts/plot/uipushtool.m new file mode 100755 --- /dev/null +++ b/scripts/plot/uipushtool.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/uiputfile.m b/scripts/plot/uiputfile.m --- a/scripts/plot/uiputfile.m +++ b/scripts/plot/uiputfile.m @@ -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 diff --git a/scripts/plot/uitoggletool.m b/scripts/plot/uitoggletool.m new file mode 100755 --- /dev/null +++ b/scripts/plot/uitoggletool.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/plot/uitoolbar.m b/scripts/plot/uitoolbar.m new file mode 100755 --- /dev/null +++ b/scripts/plot/uitoolbar.m @@ -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 +## . + +## -*- 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 diff --git a/scripts/sparse/spy.m b/scripts/sparse/spy.m --- a/scripts/sparse/spy.m +++ b/scripts/sparse/spy.m @@ -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 diff --git a/scripts/strings/dec2base.m b/scripts/strings/dec2base.m --- a/scripts/strings/dec2base.m +++ b/scripts/strings/dec2base.m @@ -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) diff --git a/scripts/strings/isstrprop.m b/scripts/strings/isstrprop.m --- a/scripts/strings/isstrprop.m +++ b/scripts/strings/isstrprop.m @@ -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 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 isstrprop ("abc123", "foo") + diff --git a/scripts/strings/mat2str.m b/scripts/strings/mat2str.m --- a/scripts/strings/mat2str.m +++ b/scripts/strings/mat2str.m @@ -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 -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 () diff --git a/scripts/strings/str2num.m b/scripts/strings/str2num.m --- a/scripts/strings/str2num.m +++ b/scripts/strings/str2num.m @@ -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 str2num ({"string"}) -%!test -%! [x, state] = str2num ("pi"); -%! assert (state); -%! [x, state] = str2num (tmpnam); -%! assert (! state); diff --git a/scripts/strings/strchr.m b/scripts/strings/strchr.m --- a/scripts/strings/strchr.m +++ b/scripts/strings/strchr.m @@ -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 strchr (1, "aeiou") +%!error strchr ("aeiou", 1) + diff --git a/scripts/strings/strjust.m b/scripts/strings/strjust.m --- a/scripts/strings/strjust.m +++ b/scripts/strings/strjust.m @@ -18,10 +18,11 @@ ## . ## -*- 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 strjust(); -%!error 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 strjust () +%!error strjust (["a";"ab"], "center", 1) +%!error strjust (ones(3,3)) +%!error strjust (char (ones(3,3,3))) + diff --git a/scripts/strings/strsplit.m b/scripts/strings/strsplit.m --- a/scripts/strings/strsplit.m +++ b/scripts/strings/strsplit.m @@ -17,53 +17,100 @@ ## . ## -*- 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

strsplit (123, "b") +%!error

strsplit ("abc", 1) +%!error strsplit ("abc", "def", ones(3,3)) -%!assert (all (strcmp (strsplit ("road to--hell", " -", true), {"road", "to", "hell"}))) diff --git a/scripts/strings/validatestring.m b/scripts/strings/validatestring.m --- a/scripts/strings/validatestring.m +++ b/scripts/strings/validatestring.m @@ -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 validatestring ("xyz", strarray, "DUMMY_TEST") +%!error validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR") +%!error validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5) +%!error validatestring ("abc", strarray) + +%% Test input validation +%!error validatestring ("xyz") +%!error validatestring ("xyz", {"xyz"}, "3", "4", 5, 6) +%!error validatestring ("xyz", {"xyz"}, "3", "4", "5") +%!error validatestring (1, {"xyz"}, "3", "4", 5) +%!error validatestring ("xyz".', {"xyz"}, "3", "4", 5) +%!error validatestring ("xyz", "xyz", "3", "4", 5) +%!error validatestring ("xyz", {"xyz"}, "33".', "4", 5) +%!error validatestring ("xyz", {"xyz"}, "3", "44".', 5) +%!error validatestring ("xyz", {"xyz"}, "3", "4", -5) + diff --git a/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc b/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc --- a/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc +++ b/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc @@ -26,6 +26,10 @@ #if defined (HAVE_FLTK) +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#endif + #include #include diff --git a/src/DLD-FUNCTIONS/__init_fltk__.cc b/src/DLD-FUNCTIONS/__init_fltk__.cc --- a/src/DLD-FUNCTIONS/__init_fltk__.cc +++ b/src/DLD-FUNCTIONS/__init_fltk__.cc @@ -40,6 +40,10 @@ #include #include +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#endif + #include #include #include diff --git a/src/DLD-FUNCTIONS/cellfun.cc b/src/DLD-FUNCTIONS/cellfun.cc --- a/src/DLD-FUNCTIONS/cellfun.cc +++ b/src/DLD-FUNCTIONS/cellfun.cc @@ -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& 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); } diff --git a/src/DLD-FUNCTIONS/max.cc b/src/DLD-FUNCTIONS/max.cc --- a/src/DLD-FUNCTIONS/max.cc +++ b/src/DLD-FUNCTIONS/max.cc @@ -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 ()) diff --git a/src/DLD-FUNCTIONS/rand.cc b/src/DLD-FUNCTIONS/rand.cc --- a/src/DLD-FUNCTIONS/rand.cc +++ b/src/DLD-FUNCTIONS/rand.cc @@ -26,7 +26,11 @@ #endif #include +#if defined (HAVE_UNORDERED_MAP) +#include +#elif defined (HAVE_TR1_UNORDERED_MAP) #include +#endif #include #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 map (m); + unordered_map map (m); // Perform the Knuth shuffle only keeping track of moved // entries in the map diff --git a/src/DLD-FUNCTIONS/regexp.cc b/src/DLD-FUNCTIONS/regexp.cc --- a/src/DLD-FUNCTIONS/regexp.cc +++ b/src/DLD-FUNCTIONS/regexp.cc @@ -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{(?@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?!"}) diff --git a/src/data.cc b/src/data.cc --- a/src/data.cc +++ b/src/data.cc @@ -589,7 +589,7 @@ { FloatNDArray a0 = args(0).float_array_value (); FloatNDArray a1 = args(1).float_array_value (); - retval = binmap (a0, a1, xrem, "rem"); + retval = binmap (a0, a1, xrem, "rem"); } } else @@ -603,13 +603,13 @@ { SparseMatrix m0 = args(0).sparse_matrix_value (); SparseMatrix m1 = args(1).sparse_matrix_value (); - retval = binmap (m0, m1, xrem, "rem"); + retval = binmap (m0, m1, xrem, "rem"); } else { NDArray a0 = args(0).array_value (); NDArray a1 = args(1).array_value (); - retval = binmap (a0, a1, xrem, "rem"); + retval = binmap (a0, a1, xrem, "rem"); } } } @@ -722,7 +722,7 @@ { FloatNDArray a0 = args(0).float_array_value (); FloatNDArray a1 = args(1).float_array_value (); - retval = binmap (a0, a1, xmod, "mod"); + retval = binmap (a0, a1, xmod, "mod"); } } else @@ -736,13 +736,13 @@ { SparseMatrix m0 = args(0).sparse_matrix_value (); SparseMatrix m1 = args(1).sparse_matrix_value (); - retval = binmap (m0, m1, xmod, "mod"); + retval = binmap (m0, m1, xmod, "mod"); } else { NDArray a0 = args(0).array_value (); NDArray a1 = args(1).array_value (); - retval = binmap (a0, a1, xmod, "mod"); + retval = binmap (a0, a1, xmod, "mod"); } } } diff --git a/src/debug.cc b/src/debug.cc --- a/src/debug.cc +++ b/src/debug.cc @@ -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) { diff --git a/src/error.cc b/src/error.cc --- a/src/error.cc +++ b/src/error.cc @@ -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 (); diff --git a/src/gl-render.cc b/src/gl-render.cc --- a/src/gl-render.cc +++ b/src/gl-render.cc @@ -567,7 +567,9 @@ draw_text (dynamic_cast (props)); else if (go.isa ("image")) draw_image (dynamic_cast (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")) { diff --git a/src/gl2ps.h b/src/gl2ps.h --- a/src/gl2ps.h +++ b/src/gl2ps.h @@ -46,6 +46,7 @@ # pragma warning(disable:4115) # pragma warning(disable:4996) # endif +# define WIN32_LEAN_AND_MEAN # include # if defined(GL2PSDLL) # if defined(GL2PSDLL_EXPORTS) diff --git a/src/graphics.cc b/src/graphics.cc old mode 100644 new mode 100755 --- a/src/graphics.cc +++ b/src/graphics.cc @@ -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\ diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -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 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); diff --git a/src/ov-base-mat.h b/src/ov-base-mat.h --- a/src/ov-base-mat.h +++ b/src/ov-base-mat.h @@ -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); diff --git a/src/ov-class.cc b/src/ov-class.cc --- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -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 { diff --git a/src/ov-class.h b/src/ov-class.h --- a/src/ov-class.h +++ b/src/ov-class.h @@ -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; diff --git a/src/ov-fcn-handle.cc b/src/ov-fcn-handle.cc --- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -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]); +*/ diff --git a/src/ov-struct.cc b/src/ov-struct.cc --- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -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 (); diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -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) +*/ diff --git a/src/ov.h b/src/ov.h --- a/src/ov.h +++ b/src/ov.h @@ -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 (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 diff --git a/src/txt-eng-ft.cc b/src/txt-eng-ft.cc --- a/src/txt-eng-ft.cc +++ b/src/txt-eng-ft.cc @@ -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 +// 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 { diff --git a/test/classes/test_classes.m b/test/classes/test_classes.m