changeset 13655:7df7650492e8

Merge with Savannah
author Jordi Gutiérrez Hermoso <jordigh@gmail.com>
date Fri, 26 Aug 2011 13:40:10 -0500
parents c67f7d390a1a (current diff) 38b52a073cfa (diff)
children 1347d498959c
files doc/interpreter/contributors.in
diffstat 88 files changed, 2506 insertions(+), 1340 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Aug 25 20:12:31 2011 +0200
+++ b/NEWS	Fri Aug 26 13:40:10 2011 -0500
@@ -3,6 +3,10 @@
 
  ** The PCRE library is now required to build Octave.
 
+ ** Octave now features a profiler, thanks to the work of Daniel Kraft
+    under the Google Summer of Code mentorship program. The manual has
+    been updated to reflect this addition.
+
  ** strread, textscan, and textread have been completely revamped.
 
     They now support nearly all Matlab functionality including:
@@ -12,12 +16,24 @@
     * ML-compatible options: 'whitespace', treatasempty',
     format string repeat count, user-specified comment style, uneven-length
     output arrays, %n and %u conversion specifiers (provisionally)
+
+ ** Certain string functions have been modified for greater Matlab compatibility
+    and for 15X greater performance when operating on cell array of strings.
+
+    deblank : Now requires character or cellstr input
+    strtrim : Now requires character or cellstr input.
+              No longer trims nulls ("\0") from string for ML compatibility.
+    strmatch: Follows documentation precisely and ignores trailing spaces
+              in pattern and in string.  Note that Matlab documents this 
+              behavior but the implementation does *not* always follow it.
  
  ** New functions added.
 
     iscolumn
     issrow
     zscore
+    profile
+    profshow
 
  ** Deprecated functions.
 
--- a/build-aux/bootstrap.conf	Thu Aug 25 20:12:31 2011 +0200
+++ b/build-aux/bootstrap.conf	Fri Aug 26 13:40:10 2011 -0500
@@ -25,6 +25,10 @@
   fcntl
   filemode
   fnmatch
+  fopen
+  fflush
+  fseek
+  ftell
   getcwd
   gethostname
   getopt-gnu
--- a/doc/interpreter/container.txi	Thu Aug 25 20:12:31 2011 +0200
+++ b/doc/interpreter/container.txi	Fri Aug 26 13:40:10 2011 -0500
@@ -563,16 +563,11 @@
 @example
 @group
 c@{1:2@}
+     @result{} ans = a string
      @result{} ans =
           
-          (,
-            [1] = a string
-            [2] =
-          
                0.593993   0.627732
                0.377037   0.033643
-          
-          ,)
 @end group
 @end example
 
--- a/doc/interpreter/contributors.in	Thu Aug 25 20:12:31 2011 +0200
+++ b/doc/interpreter/contributors.in	Fri Aug 26 13:40:10 2011 -0500
@@ -149,6 +149,7 @@
 Stefan Monnier
 Antoine Moreau
 Kai P. Mueller
+Hannes Müller
 Victor Munoz
 Carmen Navarrete
 Todd Neal
--- a/doc/interpreter/debug.txi	Thu Aug 25 20:12:31 2011 +0200
+++ b/doc/interpreter/debug.txi	Fri Aug 26 13:40:10 2011 -0500
@@ -35,6 +35,8 @@
 * Breakpoints::
 * Debug Mode::
 * Call Stack::
+* Profiling::
+* Profiler Example::
 @end menu
 
 @node Entering Debug Mode
@@ -182,3 +184,256 @@
 @DOCSTRING(dbup)
 
 @DOCSTRING(dbdown)
+
+@node Profiling
+@section Profiling
+@cindex profiler
+@cindex code profiling
+
+Octave supports profiling of code execution on a per-function level. If
+profiling is enabled, each call to a function (supporting built-ins,
+operators, functions in oct- and mex-files, user-defined functions in
+Octave code and anonymous functions) is recorded while running Octave
+code. After that, this data can aid in analyzing the code behaviour, and
+is in particular helpful for finding ``hot spots'' in the code which use
+up a lot of computation time and are the best targets to spend
+optimization efforts on.
+
+The main command for profiling is @code{profile}, which can be used to
+start or stop the profiler and also to query collected data afterwards.
+The data is returned in an Octave data structure which can then be
+examined or further processed by other routines or tools.
+
+@DOCSTRING(profile)
+
+An easy way to get an overview over the collected data is
+@code{profshow}. This function takes the profiler data returned by
+@code{profile} as input and prints a flat profile, for instance:
+
+@example
+@group
+ Function Attr     Time (s)        Calls
+----------------------------------------
+   >myfib    R        2.195        13529
+binary <=             0.061        13529
+ binary -             0.050        13528
+ binary +             0.026         6764
+@end group
+@end example
+
+This shows that most of the runtime was spent executing the function
+@samp{myfib}, and some minor proportion evaluating the listed binary
+operators. Furthermore, it is shown how often the function was called
+and the profiler also records that it is recursive.
+
+@DOCSTRING(profshow)
+
+@node Profiler Example
+@section Profiler Example
+
+Below, we will give a short example of a profiler session. See also
+@ref{Profiling} for the documentation of the profiler functions in
+detail. Consider the code:
+
+@example
+@group
+global N A;
+
+N = 300;
+A = rand (N, N);
+
+function xt = timesteps (steps, x0, expM)
+  global N;
+
+  if (steps == 0)
+    xt = NA (N, 0);
+  else
+    xt = NA (N, steps);
+    x1 = expM * x0;
+    xt(:, 1) = x1;
+    xt(:, 2 : end) = timesteps (steps - 1, x1, expM);
+  endif
+endfunction
+
+function foo ()
+  global N A;
+
+  initial = @@(x) sin (x);
+  x0 = (initial (linspace (0, 2 * pi, N)))';
+
+  expA = expm (A);
+  xt = timesteps (100, x0, expA);
+endfunction
+
+function fib = bar (N)
+  if (N <= 2)
+    fib = 1;
+  else
+    fib = bar (N - 1) + bar (N - 2);
+  endif
+endfunction
+@end group
+@end example
+
+If we execute the two main functions, we get:
+
+@example
+@group
+tic; foo; toc;
+@result{} Elapsed time is 2.37338 seconds.
+
+tic; bar (20); toc;
+@result{} Elapsed time is 2.04952 seconds.
+@end group
+@end example
+
+But this does not give much information about where this time is spent;
+for instance, whether the single call to @code{expm} is more expensive
+or the recursive time-stepping itself. To get a more detailed picture,
+we can use the profiler.
+
+@example
+@group
+profile on;
+foo;
+profile off;
+
+data = profile ('info');
+profshow (data, 10);
+@end group
+@end example
+
+This prints a table like:
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   7      expm             1.034            1
+   3  binary *             0.823          117
+  41  binary \             0.188            1
+  38  binary ^             0.126            2
+  43 timesteps    R        0.111          101
+  44        NA             0.029          101
+  39  binary +             0.024            8
+  34      norm             0.011            1
+  40  binary -             0.004          101
+  33   balance             0.003            1
+@end group
+@end example
+
+The entries are the individual functions which have been executed (only
+the 10 most important ones), together with some information for each of
+them. The entries like @samp{binary *} denote operators, while other
+entries are ordinary functions. They include both built-ins like
+@code{expm} and our own routines (for instance @code{timesteps}). From
+this profile, we can immediately deduce that @code{expm} uses up the
+largest proportion of the processing time, even though it is only called
+once. The second expensive operation is the matrix-vector product in the
+routine @code{timesteps}. @footnote{We only know it is the binary
+multiplication operator, but fortunately this operator appears only at
+one place in the code and thus we know which occurence takes so much
+time. If there were multiple places, we would have to use the
+hierarchical profile to find out the exact place which uses up the time
+which is not covered in this example.}
+
+Timing, however, is not the only information available from the profile.
+The attribute column shows us that @code{timesteps} calls itself
+recursively. This may not be that remarkable in this example (since it's
+clear anyway), but could be helpful in a more complex setting. As to the
+question of why is there a @samp{binary \} in the output, we can easily
+shed some light on that too. Note that @code{data} is a structure array
+(@ref{Structure Arrays}) which contains the field @code{FunctionTable}.
+This stores the raw data for the profile shown. The number in the first
+column of the table gives the index under which the shown function can
+be found there. Looking up @code{data.FunctionTable(41)} gives:
+
+@example
+@group
+  scalar structure containing the fields:
+
+    FunctionName = binary \
+    TotalTime =  0.18765
+    NumCalls =  1
+    IsRecursive = 0
+    Parents =  7
+    Children = [](1x0)
+@end group
+@end example
+
+Here we see the information from the table again, but have additional
+fields @code{Parents} and @code{Children}. Those are both arrays, which
+contain the indices of functions which have directly called the function
+in question (which is entry 7, @code{expm}, in this case) or been called
+by it (no functions). Hence, the backslash operator has been used
+internally by @code{expm}.
+
+Now let's take a look at @code{bar}. For this, we start a fresh
+profiling session (@code{profile on} does this; the old data is removed
+before the profiler is restarted):
+
+@example
+@group
+profile on;
+bar (20);
+profile off;
+
+profshow (profile ('info'));
+@end group
+@end example
+
+This gives:
+
+@example
+   #            Function Attr     Time (s)        Calls
+-------------------------------------------------------
+   1                 bar    R        2.091        13529
+   2           binary <=             0.062        13529
+   3            binary -             0.042        13528
+   4            binary +             0.023         6764
+   5             profile             0.000            1
+   8               false             0.000            1
+   6              nargin             0.000            1
+   7           binary !=             0.000            1
+   9 __profiler_enable__             0.000            1
+@end example
+
+Unsurprisingly, @code{bar} is also recursive. It has been called 13,529
+times in the course of recursively calculating the Fibonacci number in a
+suboptimal way, and most of the time was spent in @code{bar} itself.
+
+Finally, let's say we want to profile the execution of both @code{foo}
+and @code{bar} together. Since we already have the runtime data
+collected for @code{bar}, we can restart the profiler without clearing
+the existing data and collect the missing statistics about @code{foo}.
+This is done by:
+
+@example
+@group
+profile resume;
+foo;
+profile off;
+
+profshow (profile ('info'), 10);
+@end group
+@end example
+
+As you can see in the table below, now we have both profiles mixed
+together.
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   1       bar    R        2.091        13529
+  16      expm             1.122            1
+  12  binary *             0.798          117
+  46  binary \             0.185            1
+  45  binary ^             0.124            2
+  48 timesteps    R        0.115          101
+   2 binary <=             0.062        13529
+   3  binary -             0.045        13629
+   4  binary +             0.041         6772
+  49        NA             0.036          101
+@end group
+@end example
--- a/doc/interpreter/install.txi	Thu Aug 25 20:12:31 2011 +0200
+++ b/doc/interpreter/install.txi	Fri Aug 26 13:40:10 2011 -0500
@@ -32,7 +32,7 @@
 under the terms of the GNU General Public License as published by the
 Free Software Foundation.
 
-@strong{Note:} This file is automatically generated from
+@strong{Note}: This file is automatically generated from
 @file{doc/interpreter/install.txi} in the Octave sources.  To update
 the documentation make changes to the .txi source file rather than this
 derived file.
--- a/doc/interpreter/oop.txi	Thu Aug 25 20:12:31 2011 +0200
+++ b/doc/interpreter/oop.txi	Fri Aug 26 13:40:10 2011 -0500
@@ -578,8 +578,8 @@
 @item @tab a / b @tab mrdivide (a, b) @tab Matrix right division operator @tab
 @item @tab a .\ b @tab ldivide (a, b) @tab Element-wise left division operator @tab
 @item @tab a \ b @tab mldivide (a, b) @tab Matrix left division operator @tab
-@item @tab a .^ b @tab ldivide (a, b) @tab Element-wise power operator @tab
-@item @tab a ^ b @tab mldivide (a, b) @tab Matrix power operator @tab
+@item @tab a .^ b @tab power (a, b) @tab Element-wise power operator @tab
+@item @tab a ^ b @tab mpower (a, b) @tab Matrix power operator @tab
 @item @tab a < b @tab lt (a, b) @tab Less than operator @tab
 @item @tab a <= b @tab le (a, b) @tab Less than or equal to operator @tab
 @item @tab a > b @tab gt (a, b) @tab Greater than operator @tab
--- a/etc/README.MacOS	Thu Aug 25 20:12:31 2011 +0200
+++ b/etc/README.MacOS	Fri Aug 26 13:40:10 2011 -0500
@@ -334,67 +334,83 @@
 includes a port file for octave-devel.  To build and run the most recent
 development snapshots, enter the commands below.
 
-    sudo port selfupdate
-    sudo port install octave-devel
+  sudo port selfupdate
+  sudo port install octave-devel
 
 To build the developers sources in one's own way, or if MacPorts' version is
 outdated, a custom port file can be added.  This requires setting up a local
 port file repository (link below).
 
-    http://guide.macports.org/#development.local-repositories
+  http://guide.macports.org/#development.local-repositories
 
 The octave-devel port file may be used as an initial starting point.  The port
 file is accessible from the web at the link below.
 
-    http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
+  http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
 
 It is also available locally at the location below.  The parameter ${prefix} is
 corresponds to where MacPorts is install, which by default is "/opt/local".
 
-    ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+  ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+
+If the Portfile is missing the dependencies, epstools, epstoedit, and transfig,
+those should be installed manually or added to the Portfile. To install
+manually, type the command below.
+
+  sudo port install epstools epstoedit transfig
 
 The local source tarball must be placed in the location below, where ${name}
 and ${distname} are each specified in the port file.
 
-    ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
+  ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
 
 
 2.4.2 Building for Active Development of Octave
 -----------------------------------------------
 
-To satisfy Octave's dependencies, first install the octave-devel port.
-
-    sudo port selfupdate
-    sudo port install octave-devel
+To satisfy most of Octave's dependencies, first install the octave-devel port.
 
-Next run octave to determine the configure options needed to build Octave
-using MacPorts.  At Octave's prompt type the command below and make note of
-the result, ${config_opts}.
-
-    octave:1> octave_config_info.config_opts
+  sudo port selfupdate
+  sudo port install octave-devel
 
 Now uninstall the Octave port.
 
-    sudo port deactivate octave-devel
+  sudo port deactivate octave-devel
+
+This will remove Octave and leave its dependencies in place. Some additional
+dependencies may be needed.
+
+  sudo port install epstools epstoedit transfig
+
+Octave may now be built from a local mercurial archive by typing the commands
+below (these assume gcc-4.4 is installed by macports).
 
-This will remove Octave and leave its dependencies in place.  Now Octave may
-be built from the local mercurial archive by typing the commands below, where
-the configure options mentioned above are substituted for the parameter
-${config_opts}.  If the sources being built are from the mercurial archive,
-then ./autogen.sh must be run prior to ./configure.
-
-    ./configure ${config_opts}
-    make
+  ./autogen.sh
+  export PREFIX=/opt/local
+  export CC=/opt/local/bin/gcc-mp-4.4
+  export CXX=/opt/local/bin/g++-mp-4.4
+  export CXXCPP="/opt/local/bin/g++-mp-4.4 -E"
+  export F77=/opt/local/bin/gfortran-mp-4.4
+  export FC=/opt/local/bin/gfortran-mp-4.4
+  export CXXFLAGS="-pipe -O2 -m64"
+  export FFLAGS="$CXXFLAGS -D_THREAD_SAFE -pthread"
+  export CFLAGS="$FFLAGS -lstdc++"
+  export LDFLAGS=-L$PREFIX/lib
+  export CPPFLAGS=-I$PREFIX/include
+  export BLAS_LIBS="-lcblas -lf77blas -latlas"
+  export LAPACK_LIBS=-llapack
+  ./configure --prefix="/opt/local" --without-framework-carbon --with-x
+  make
 
 Octave's integrated tests may be run.
 
-    make check
+  make check
 
-However, "make install" should not be run as it may damage or corrupt the
-MacPorts installation.  To run Octave, type the command below from the root of
-the mercurial archive.
+"make install" should not be run as it will bypass the macports package 
+management.  To run Octave, type the command below from the root of the
+mercurial archive.
 
-    ./run-octave
+  ./run-octave
 
 
 John W. Eaton
--- a/liboctave/MArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/MArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -339,7 +339,7 @@
   MArray<T> \
   FCN (const MArray<T>& a, const MArray<T>& b) \
   { \
-    return do_mm_binary_op<T, T, T> (a, b, FN, #FCN); \
+    return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
   }
 
 MARRAY_NDND_OP (operator +, +, mx_inline_add)
--- a/liboctave/MDiagArray2.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/MDiagArray2.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -82,7 +82,7 @@
   { \
     if (a.d1 != b.d1 || a.d2 != b.d2) \
       gripe_nonconformant (#FCN, a.d1, a.d2, b.d1, b.d2); \
-    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, #FCN), a.d1, a.d2); \
+    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN), a.d1, a.d2); \
   }
 
 MARRAY_DADA_OP (operator +, +, mx_inline_add)
--- a/liboctave/Makefile.am	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/Makefile.am	Fri Aug 26 13:40:10 2011 -0500
@@ -188,6 +188,7 @@
   base-dae.h \
   base-de.h \
   base-min.h \
+  bsxfun.h \
   byte-swap.h \
   caseless-str.h \
   cmd-edit.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/bsxfun.h	Fri Aug 26 13:40:10 2011 -0500
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 2011 Jordi Gutiérrez Hermoso <jordigh@octave.org>
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+#if !defined (bsxfun_h)
+#define bsxfun_h 1
+
+#include <algorithm>
+
+#include "Array.h"
+#include "dim-vector.h"
+
+inline
+bool
+is_valid_bsxfun (const dim_vector& dx, const dim_vector& dy)
+{
+  for (int i = 0; i < std::min (dx.length (), dy.length ()); i++)
+    {
+      if ( dx(i) > 1 && dy(i) > 1 && dx(i) != dy(i))
+        return false;
+    }
+  return true;
+}
+
+#include "bsxfun-defs.cc"
+
+#endif
--- a/liboctave/chMatrix.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/chMatrix.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -74,8 +74,8 @@
     elem (0, i) = s[i];
 }
 
-charMatrix::charMatrix (const string_vector& s)
-  : Array<char> (dim_vector (s.length (), s.max_length ()), 0)
+charMatrix::charMatrix (const string_vector& s, char fill_value)
+  : Array<char> (dim_vector (s.length (), s.max_length ()), fill_value)
 {
   octave_idx_type nr = rows ();
 
--- a/liboctave/chMatrix.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/chMatrix.h	Fri Aug 26 13:40:10 2011 -0500
@@ -62,7 +62,7 @@
 
   charMatrix (const std::string& s);
 
-  charMatrix (const string_vector& s);
+  charMatrix (const string_vector& s, char fill_value = '\0');
 
   charMatrix& operator = (const charMatrix& a)
     {
--- a/liboctave/dMatrix.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/dMatrix.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -3111,15 +3111,19 @@
 */
 
 /* Test some simple identities
-%!shared M, cv, rv
-%! M = randn(10,10);
+%!shared M, cv, rv, Mt, rvt
+%! M = randn(10,10)+100*eye(10,10);
+%! Mt = M';
 %! cv = randn(10,1);
 %! rv = randn(1,10);
+%! rvt = rv';
 %!assert([M*cv,M*cv],M*[cv,cv],1e-14)
-%!assert([M'*cv,M'*cv],M'*[cv,cv],1e-14)
-%!assert([rv*M;rv*M],[rv;rv]*M,1e-14)
-%!assert([rv*M';rv*M'],[rv;rv]*M',1e-14)
-%!assert(2*rv*cv,[rv,rv]*[cv;cv],1e-14)
+%!assert([M'*cv,M'*cv],M'*[cv,cv],3e-14)
+%!assert([rv*M;rv*M],[rv;rv]*M,3e-14)
+%!assert([rv*M';rv*M'],[rv;rv]*M',3e-14)
+%!assert(2*rv*cv,[rv,rv]*[cv;cv],3e-14)
+%!assert(M'\cv,Mt\cv,1e-14)
+%!assert(M'\rv',Mt\rvt,1e-14)
 */
 
 static inline char
--- a/liboctave/dNDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/dNDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -925,3 +925,5 @@
 BSXFUN_OP_DEF_MXLOOP (pow, NDArray, mx_inline_pow)
 BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, ComplexNDArray,
                        NDArray, mx_inline_pow)
+BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, NDArray,
+                       ComplexNDArray, mx_inline_pow)
--- a/liboctave/dNDArray.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/dNDArray.h	Fri Aug 26 13:40:10 2011 -0500
@@ -185,5 +185,7 @@
 BSXFUN_OP_DECL (pow, NDArray, OCTAVE_API)
 BSXFUN_OP2_DECL (pow, ComplexNDArray, ComplexNDArray,
                  NDArray, OCTAVE_API)
+BSXFUN_OP2_DECL (pow, ComplexNDArray, NDArray,
+                 ComplexNDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int16NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/int16NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int16NDArray, mx_inline_pow)
--- a/liboctave/int32NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/int32NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int32NDArray, mx_inline_pow)
--- a/liboctave/int64NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/int64NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int64NDArray, mx_inline_pow)
--- a/liboctave/int8NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/int8NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int8NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int8NDArray, mx_inline_pow)
--- a/liboctave/lo-utils.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/lo-utils.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -196,44 +196,57 @@
 }
 
 static inline double
-read_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   double d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
               d = sign == '-' ? -octave_Inf : octave_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
               d = octave_NaN;
             else
               {
-                is.putback (c);
+                is.putback (c2);
                 d = octave_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -346,44 +359,57 @@
 }
 
 static inline float
-read_float_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   float d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
-              d = sign == '-' ? -octave_Inf : octave_Inf;
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
+              d = sign == '-' ? -octave_Float_Inf : octave_Float_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
-              d = octave_NaN;
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
+              d = octave_Float_NaN;
             else
               {
-                is.putback (c);
-                d = octave_NA;
+                is.putback (c2);
+                d = octave_Float_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
--- a/liboctave/mx-inlines.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/mx-inlines.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -37,6 +37,8 @@
 #include "Array.h"
 #include "Array-util.h"
 
+#include "bsxfun.h"
+
 // Provides some commonly repeated, basic loop templates.
 
 template <class R, class S>
@@ -286,7 +288,10 @@
 inline void F (size_t n, R *r, X x, const Y *y) throw () \
 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
 
-DEFMXMAPPER2X (mx_inline_pow, std::pow)
+// Let the compiler decide which pow to use, whichever best matches the
+// arguments provided.
+using std::pow;
+DEFMXMAPPER2X (mx_inline_pow, pow)
 
 // Arbitrary function appliers. The function is a template parameter to enable
 // inlining.
@@ -336,11 +341,12 @@
   return r;
 }
 
-
 template <class R, class X, class Y>
 inline Array<R>
 do_mm_binary_op (const Array<X>& x, const Array<Y>& y,
                  void (*op) (size_t, R *, const X *, const Y *) throw (),
+                 void (*op1) (size_t, R *, X, const Y *) throw (),
+                 void (*op2) (size_t, R *, const X *, Y) throw (),
                  const char *opname)
 {
   dim_vector dx = x.dims (), dy = y.dims ();
@@ -350,6 +356,10 @@
       op (r.length (), r.fortran_vec (), x.data (), y.data ());
       return r;
     }
+  else if (is_valid_bsxfun (dx, dy))
+    {
+      return do_bsxfun_op (x, y, op, op1, op2);
+    }
   else
     {
       gripe_nonconformant (opname, dx, dy);
--- a/liboctave/mx-op-defs.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/mx-op-defs.h	Fri Aug 26 13:40:10 2011 -0500
@@ -72,7 +72,7 @@
   R \
   F (const V1& v1, const V2& v2) \
   { \
-    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, #F); \
+    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \
   }
 
 #define VV_BIN_OPS(R, V1, V2) \
@@ -173,7 +173,7 @@
   R \
   OP (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define MM_BIN_OPS(R, M1, M2) \
@@ -186,7 +186,7 @@
   boolMatrix \
   F (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_CMP_OPS(M1, M2) \
@@ -203,7 +203,7 @@
   { \
     MNANCHK (m1, M1::element_type); \
     MNANCHK (m2, M2::element_type); \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_BOOL_OPS(M1, M2) \
@@ -310,7 +310,7 @@
   R \
   OP (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define NDND_BIN_OPS(R, ND1, ND2) \
@@ -323,7 +323,7 @@
   boolNDArray \
   F (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_CMP_OPS(ND1, ND2) \
@@ -340,7 +340,7 @@
   { \
     MNANCHK (m1, ND1::element_type); \
     MNANCHK (m2, ND2::element_type); \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_BOOL_OPS(ND1, ND2) \
@@ -583,7 +583,7 @@
 T \
 FCN (const T& a, const T& b) \
 { \
-  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, #FCN); \
+  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \
 }
 
 #define MINMAX_FCNS(T, S) \
--- a/liboctave/oct-binmap.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/oct-binmap.h	Fri Aug 26 13:40:10 2011 -0500
@@ -27,9 +27,13 @@
 #include "Sparse.h"
 #include "Array-util.h"
 
-// This source implements a general binary maping function for arrays.
-// The syntax is binmap<type> (a, b, f, [name]). type denotes the expected
-// return type of the operation. a, b, should be one of the 6 combinations:
+#include "bsxfun.h"
+
+// This source file implements a general binary maping function for
+// arrays. The syntax is binmap<type> (a, b, f, [name]). type denotes
+// the expected return type of the operation. a, b, should be one of
+// the 6 combinations:
+//
 // Array-Array
 // Array-scalar
 // scalar-Array
@@ -37,11 +41,12 @@
 // Sparse-scalar
 // scalar-Sparse
 //
-// If both operands are nonscalar, name must be supplied. It is used as the base for error message
-// when operands are nonconforming.
+// If both operands are nonscalar, name must be supplied. It is used
+// as the base for error message when operands are nonconforming.
 //
-// The operation needs not be homogeneous, i.e. a, b and the result may be of distinct types.
-// f can have any of the four signatures:
+// The operation needs not be homogeneous, i.e. a, b and the result
+// may be of distinct types. f can have any of the four signatures:
+//
 // U f (T, R)
 // U f (const T&, R)
 // U f (T, const R&)
@@ -49,7 +54,51 @@
 //
 // Additionally, f can be an arbitrary functor object.
 //
-// octave_quit() is called at appropriate places, hence the operation is breakable.
+// octave_quit() is called at appropriate places, hence the operation
+// is breakable.
+
+// The following template wrappers are provided for automatic bsxfun
+// calls (see the function signature for do_bsxfun_op).
+
+template<typename R, typename X, typename Y, typename F>
+class bsxfun_wrapper
+{
+private:
+  static F f;
+
+public:
+  static void
+  set_f (const F& f_in)
+  {
+    f = f_in;
+  }
+
+  static void
+  op_mm (size_t n, R* r, const X* x , const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y[i]);
+  }
+
+  static void
+  op_sm (size_t n, R* r, X x, const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x, y[i]);
+  }
+
+  static void
+  op_ms (size_t n , R* r, const X* x, Y y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y);
+  }
+};
+
+// Static init
+template<typename R, typename X, typename Y, typename F>
+F bsxfun_wrapper<R, X, Y, F>::f;
+
 
 // scalar-Array
 template <class U, class T, class R, class F>
@@ -118,12 +167,24 @@
 Array<U>
 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
 {
+  dim_vector xad = xa.dims (), yad = ya.dims ();
   if (xa.numel () == 1)
     return binmap<U, T, R, F> (xa(0), ya, fcn);
   else if (ya.numel () == 1)
     return binmap<U, T, R, F> (xa, ya(0), fcn);
-  else if (xa.dims () != ya.dims ())
-    gripe_nonconformant (name, xa.dims (), ya.dims ());
+  else if (xad != yad)
+    {
+      if (is_valid_bsxfun (xad, yad))
+        {
+          bsxfun_wrapper<U, T, R, F>::set_f(fcn);
+          return do_bsxfun_op (xa, ya,
+                               bsxfun_wrapper<U, T, R, F>::op_mm,
+                               bsxfun_wrapper<U, T, R, F>::op_sm,
+                               bsxfun_wrapper<U, T, R, F>::op_ms);
+        }
+      else
+        gripe_nonconformant (name, xad, yad);
+    }
 
   octave_idx_type len = xa.numel ();
 
@@ -273,134 +334,134 @@
                                           fcn, name));
 }
 
-// Overloads for function references.
+// Overloads for function pointers.
 
 // Signature (T, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 // Signature (const T&, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 // Signature (const T&, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 // Signature (T, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 #endif
--- a/liboctave/str-vec.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/str-vec.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -163,6 +163,26 @@
   return *this;
 }
 
+std::string
+string_vector::join (const std::string& sep) const
+{
+  std::string retval;
+
+  octave_idx_type len = length ();
+
+  if (len > 0)
+    {
+      octave_idx_type i;
+
+      for (i = 0; i < len - 1; i++)
+        retval += elem(i) + sep;
+
+      retval += elem(i);
+    }
+
+  return retval;
+}
+
 char **
 string_vector::c_str_vec (void) const
 {
--- a/liboctave/str-vec.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/str-vec.h	Fri Aug 26 13:40:10 2011 -0500
@@ -105,6 +105,8 @@
 
   string_vector& append (const string_vector& sv);
 
+  std::string join (const std::string& sep = std::string ()) const;
+
   char **c_str_vec (void) const;
 
   static void delete_c_str_vec (const char * const*);
--- a/liboctave/uint16NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/uint16NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint16NDArray, mx_inline_pow)
--- a/liboctave/uint32NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/uint32NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint32NDArray, mx_inline_pow)
--- a/liboctave/uint64NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/uint64NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint64NDArray, mx_inline_pow)
--- a/liboctave/uint8NDArray.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/liboctave/uint8NDArray.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -54,3 +54,5 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint8NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint8NDArray, mx_inline_pow)
--- a/scripts/audio/wavread.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/audio/wavread.m	Fri Aug 26 13:40:10 2011 -0500
@@ -55,135 +55,139 @@
     error ("wavread: FILENAME must be a character string");
   endif
 
-  # Open file for binary reading.
-  [fid, msg] = fopen (filename, "rb");
-  if (fid < 0)
-    error ("wavread: %s", msg);
-  endif
+  fid = -1;
+
+  unwind_protect
 
-  ## Get file size.
-  fseek (fid, 0, "eof");
-  file_size = ftell (fid);
-  fseek (fid, 0, "bof");
+    [fid, msg] = fopen (filename, "rb");
+
+    if (fid < 0)
+      error ("wavread: %s", msg);
+    endif
 
-  ## Find RIFF chunk.
-  riff_size = find_chunk (fid, "RIFF", file_size);
-  riff_pos = ftell (fid);
-  if (riff_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no RIFF chunk");
-  endif
+    ## Get file size.
+    fseek (fid, 0, "eof");
+    file_size = ftell (fid);
+    fseek (fid, 0, "bof");
 
-  riff_type = char (fread (fid, 4))';
-  if (! strcmp (riff_type, "WAVE"))
-    fclose (fid);
-    error ("wavread: file contains no WAVE signature");
-  endif
-  riff_pos = riff_pos + 4;
-  riff_size = riff_size - 4;
+    ## Find RIFF chunk.
+    riff_size = find_chunk (fid, "RIFF", file_size);
+    riff_pos = ftell (fid);
+    if (riff_size == -1)
+      error ("wavread: file contains no RIFF chunk");
+    endif
+
+    riff_type = char (fread (fid, 4))';
+    if (! strcmp (riff_type, "WAVE"))
+      error ("wavread: file contains no WAVE signature");
+    endif
+    riff_pos = riff_pos + 4;
+    riff_size = riff_size - 4;
 
-  ## Find format chunk inside the RIFF chunk.
-  fseek (fid, riff_pos, "bof");
-  fmt_size = find_chunk (fid, "fmt ", riff_size);
-  fmt_pos = ftell(fid);
-  if (fmt_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no format chunk");
-  endif
+    ## Find format chunk inside the RIFF chunk.
+    fseek (fid, riff_pos, "bof");
+    fmt_size = find_chunk (fid, "fmt ", riff_size);
+    fmt_pos = ftell(fid);
+    if (fmt_size == -1)
+      error ("wavread: file contains no format chunk");
+    endif
+
+    ## Find data chunk inside the RIFF chunk.
+    ## We don't assume that it comes after the format chunk.
+    fseek (fid, riff_pos, "bof");
+    data_size = find_chunk (fid, "data", riff_size);
+    data_pos = ftell (fid);
+    if (data_size == -1)
+      error ("wavread: file contains no data chunk");
+    endif
 
-  ## Find data chunk inside the RIFF chunk.
-  ## We don't assume that it comes after the format chunk.
-  fseek (fid, riff_pos, "bof");
-  data_size = find_chunk (fid, "data", riff_size);
-  data_pos = ftell (fid);
-  if (data_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no data chunk");
-  endif
+    ### Read format chunk.
+    fseek (fid, fmt_pos, "bof");
 
-  ### Read format chunk.
-  fseek (fid, fmt_pos, "bof");
+    ## Sample format code.
+    format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
+    if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
+      error ("wavread: sample format %#x is not supported", format_tag);
+    endif
 
-  ## Sample format code.
-  format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
-  if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
-    fclose (fid);
-    error ("wavread: sample format %#x is not supported", format_tag);
-  endif
+    ## Number of interleaved channels.
+    channels = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Number of interleaved channels.
-  channels = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ## Sample rate.
+    samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
 
-  ## Sample rate.
-  samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
+    ## Bits per sample.
+    fseek (fid, 6, "cof");
+    bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Bits per sample.
-  fseek (fid, 6, "cof");
-  bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ### Read data chunk.
+    fseek (fid, data_pos, "bof");
 
-  ### Read data chunk.
-  fseek (fid, data_pos, "bof");
+    ## Determine sample data type.
+    if (format_tag == FORMAT_PCM)
+      switch (bits_per_sample)
+        case 8
+          format = "uint8";
+        case 16
+          format = "int16";
+        case 24
+          format = "uint8";
+        case 32
+          format = "int32";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with PCM",
+                 bits_per_sample);
+      endswitch
+    else
+      switch (bits_per_sample)
+        case 32
+          format = "float32";
+        case 64
+          format = "float64";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with IEEE float",
+                 bits_per_sample);
+      endswitch
+    endif
 
-  ## Determine sample data type.
-  if (format_tag == FORMAT_PCM)
-    switch (bits_per_sample)
-      case 8
-        format = "uint8";
-      case 16
-        format = "int16";
-      case 24
-        format = "uint8";
-      case 32
-        format = "int32";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with PCM",
-               bits_per_sample);
-    endswitch
-  else
-    switch (bits_per_sample)
-      case 32
-        format = "float32";
-      case 64
-        format = "float64";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with IEEE float",
-               bits_per_sample);
-    endswitch
-  endif
+    ## Parse arguments.
+    if (nargin == 1)
+      length = idivide (8 * data_size, bits_per_sample);
+    else
+      nparams = numel (param);
+      if (nparams == 1)
+        ## Number of samples is given.
+        length = param * channels;
+      elseif (nparams == 2)
+        ## Sample range is given.
+        if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
+          warning ("wavread: seeking failed");
+        endif
+        length = (param(2)-param(1)+1) * channels;
+      elseif (nparams == 4 && char (param) == "size")
+        ## Size of the file is requested.
+        tmp = idivide (8 * data_size, channels * bits_per_sample);
+        y = [tmp, channels];
+        return;
+      else
+        error ("wavread: invalid PARAM argument");
+      endif
+    endif
 
-  ## Parse arguments.
-  if (nargin == 1)
-    length = 8 * data_size / bits_per_sample;
-  else
-    nparams = numel (param);
-    if (nparams == 1)
-      ## Number of samples is given.
-      length = param * channels;
-    elseif (nparams == 2)
-      ## Sample range is given.
-      if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
-        warning ("wavread: seeking failed");
-      endif
-      length = (param(2)-param(1)+1) * channels;
-    elseif (nparams == 4 && char (param) == "size")
-      ## Size of the file is requested.
+    ## Read samples and close file.
+    if (bits_per_sample == 24)
+      length *= 3;
+    endif
+
+    [yi, n] = fread (fid, length, format, 0, BYTEORDER);
+
+  unwind_protect_cleanup
+
+    if (fid >= 0)
       fclose (fid);
-      y = [data_size/channels/(bits_per_sample/8), channels];
-      return;
-    else
-      fclose (fid);
-      error ("wavread: invalid PARAM argument");
     endif
-  endif
 
-  ## Read samples and close file.
-  if (bits_per_sample == 24)
-    length *= 3;
-  endif
-  [yi, n] = fread (fid, length, format, 0, BYTEORDER);
-  fclose (fid);
+  end_unwind_protect
 
   ## Check data.
   if (mod (numel (yi), channels) != 0)
--- a/scripts/general/accumdim.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/general/accumdim.m	Fri Aug 26 13:40:10 2011 -0500
@@ -42,12 +42,12 @@
 ##
 ## An example of the use of @code{accumdim} is:
 ##
-## @example
+## @smallexample
 ## @group
 ## accumdim ([1, 2, 1, 2, 1], [7,-10,4;-5,-12,8;-12,2,8;-10,9,-3;-5,-3,-13])
 ## @result{} ans = [-10,-11,-1;-15,-3,5]
 ## @end group
-## @end example
+## @end smallexample
 ##
 ## @seealso{accumarray}
 ## @end deftypefn
--- a/scripts/general/profile.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/general/profile.m	Fri Aug 26 13:40:10 2011 -0500
@@ -48,9 +48,13 @@
 ##
 ## @item @var{T} = profile ('info')
 ## Return the collected profiling statistics in the structure @var{T}.
-## Currently, the only field is @code{FunctionTable} which is an array
-## of structures, each entry corresponding to a function which was called
-## and for which profiling statistics are present.
+## The flat profile is returned in the field @code{FunctionTable} which is an
+## array of structures, each entry corresponding to a function which was called
+## and for which profiling statistics are present.  Furthermore, the field
+## @code{Hierarchical} contains the hierarchical call-tree.  Each node
+## has an index into the @code{FunctionTable} identifying the function it
+## corresponds to as well as data fields for number of calls and time spent
+## at this level in the call-tree.
 ## @end table
 ## @end deftypefn
 
@@ -65,20 +69,20 @@
 
   switch (option)
     case 'on'
-      __profiler_reset ();
-      __profiler_enable (true);
+      __profiler_reset__ ();
+      __profiler_enable__ (true);
 
     case 'off'
-      __profiler_enable (false);
+      __profiler_enable__ (false);
 
     case 'clear'
-      __profiler_reset ();
+      __profiler_reset__ ();
 
     case 'resume'
-      __profiler_enable (true);
+      __profiler_enable__ (true);
 
     case 'status'
-      enabled = __profiler_enable ();
+      enabled = __profiler_enable__ ();
       if (enabled)
         enabled = 'on';
       else
@@ -87,8 +91,8 @@
       retval = struct ('ProfilerStatus', enabled);
 
     case 'info'
-      data = __profiler_data ();
-      retval = struct ('FunctionTable', data);
+      [flat, tree] = __profiler_data__ ();
+      retval = struct ('FunctionTable', flat, 'Hierarchical', tree);
 
     otherwise
       warning ("profile: Unrecognized option '%s'", option);
--- a/scripts/general/profshow.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/general/profshow.m	Fri Aug 26 13:40:10 2011 -0500
@@ -63,18 +63,19 @@
   for i = 1 : n
     nameLen = max (nameLen, length (data.FunctionTable(p(i)).FunctionName));
   endfor
-  headerFormat = sprintf ("%%%ds %%4s %%12s %%12s\n", nameLen);
-  rowFormat = sprintf ("%%%ds %%4s %%12.3f %%12d\n", nameLen);
+  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%12s\n", nameLen);
+  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%12d\n", nameLen);
 
-  printf (headerFormat, "Function", "Attr", "Time (s)", "Calls");
-  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 13 + 5));
+  printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls");
+  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13));
   for i = 1 : n
     row = data.FunctionTable(p(i));
     attr = "";
     if (row.IsRecursive)
       attr = "R";
     endif
-    printf (rowFormat, row.FunctionName, attr, row.TotalTime, row.NumCalls);
+    printf (rowFormat, p(i), row.FunctionName, attr, ...
+            row.TotalTime, row.NumCalls);
   endfor
 
 endfunction
--- a/scripts/general/quadl.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/general/quadl.m	Fri Aug 26 13:40:10 2011 -0500
@@ -62,14 +62,12 @@
 ##   * replace global variable terminate2 with local function need_warning
 ##   * add paper ref to docs
 
-function q = quadl (f, a, b, tol, trace, varargin)
-  need_warning (1);
-  if (nargin < 4)
-    tol = [];
+function q = quadl (f, a, b, tol = [], trace = false, varargin)
+
+  if (nargin < 3)
+    print_usage ();
   endif
-  if (nargin < 5)
-    trace = [];
-  endif
+
   if (isa (a, "single") || isa (b, "single"))
     myeps = eps ("single");
   else
@@ -79,16 +77,23 @@
     tol = myeps;
   endif
   if (isempty (trace))
-    trace = 0;
+    trace = false;
   endif
   if (tol < myeps)
     tol = myeps;
   endif
 
+  ## Track whether recursion has occurred
+  global __quadl_recurse_done__;
+  __quadl_recurse_done__ = false;
+  ## Track whether warning about machine precision has been issued
+  global __quadl_need_warning__;
+  __quadl_need_warning__ = true;
+
   m = (a+b)/2;
   h = (b-a)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1/sqrt (5);
 
   x1 = .942882415695480;
   x2 = .641853342345781;
@@ -104,12 +109,12 @@
 
   i2 = (h/6)*(y(1) + y(13) + 5*(y(5)+y(9)));
 
-  i1 = (h/1470)*(77*(y(1)+y(13))
+  i1 = (h/1470)*(   77*(y(1)+y(13))
                  + 432*(y(3)+y(11))
                  + 625*(y(5)+y(9))
                  + 672*y(7));
 
-  is = h*(.0158271919734802*(y(1)+y(13))
+  is = h*( .0158271919734802*(y(1)+y(13))
           +.0942738402188500*(y(2)+y(12))
           + .155071987336585*(y(3)+y(11))
           + .188821573960182*(y(4)+y(10))
@@ -117,102 +122,96 @@
           + .224926465333340*(y(6)+y(8))
           + .242611071901408*y(7));
 
-  s = sign(is);
-
+  s = sign (is);
   if (s == 0)
     s = 1;
   endif
-  erri1 = abs(i1-is);
-  erri2 = abs(i2-is);
-  R = 1;
+  erri1 = abs (i1-is);
+  erri2 = abs (i2-is);
   if (erri2 != 0)
     R = erri1/erri2;
+  else
+    R = 1;
   endif
   if (R > 0 && R < 1)
     tol = tol/R;
   endif
-  is = s*abs(is)*tol/myeps;
+  is = s * abs(is) * tol/myeps;
   if (is == 0)
     is = b-a;
   endif
+
   q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin{:});
+
 endfunction
 
 ## ADAPTLOBSTP  Recursive function used by QUADL.
 ##
 ##   Q = ADAPTLOBSTP('F', A, B, FA, FB, IS, TRACE) tries to
 ##   approximate the integral of F(X) from A to B to
-##   an appropriate relative error. The argument 'F' is
+##   an appropriate relative error.  The argument 'F' is
 ##   a string containing the name of f.  The remaining
 ##   arguments are generated by ADAPTLOB or by recursion.
 ##
 ##   Walter Gautschi, 08/03/98
 
 function q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin)
+  global __quadl_recurse_done__;
+  global __quadl_need_warning__;
+
   h = (b-a)/2;
   m = (a+b)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1 / sqrt(5);
   mll = m-alpha*h;
-  ml = m-beta*h;
-  mr = m+beta*h;
+  ml  = m-beta*h;
+  mr  = m+beta*h;
   mrr = m+alpha*h;
   x = [mll, ml, m, mr, mrr];
-  y = feval(f, x, varargin{:});
+  y = feval (f, x, varargin{:});
   fmll = y(1);
-  fml = y(2);
-  fm = y(3);
-  fmr = y(4);
+  fml  = y(2);
+  fm   = y(3);
+  fmr  = y(4);
   fmrr = y(5);
   i2 = (h/6)*(fa + fb + 5*(fml+fmr));
   i1 = (h/1470)*(77*(fa+fb) + 432*(fmll+fmrr) + 625*(fml+fmr) + 672*fm);
-  if (is+(i1-i2) == is || mll <= a || b <= mrr)
-    if ((m <= a || b <= m) && need_warning ())
+  if ((is+(i1-i2) == is || mll <= a || b <= mrr) && __quadl_recurse_done__)
+    if ((m <= a || b <= m) && __quadl_need_warning__)
       warning ("quadl: interval contains no more machine number");
       warning ("quadl: required tolerance may not be met");
-      need_warning (0);
+      __quadl_need_warning__ = false;
     endif
     q = i1;
     if (trace)
       disp ([a, b-a, q]);
     endif
   else
-    q = (adaptlobstp (f, a, mll, fa, fmll, is, trace, varargin{:})
-         + adaptlobstp (f, mll, ml, fmll, fml, is, trace, varargin{:})
-         + adaptlobstp (f, ml, m, fml, fm, is, trace, varargin{:})
-         + adaptlobstp (f, m, mr, fm, fmr, is, trace, varargin{:})
-         + adaptlobstp (f, mr, mrr, fmr, fmrr, is, trace, varargin{:})
-         + adaptlobstp (f, mrr, b, fmrr, fb, is, trace, varargin{:}));
-  endif
-endfunction
-
-function r = need_warning (v)
-  persistent w = [];
-  if (nargin == 0)
-    r = w;
-  else
-    w = v;
+    __quadl_recurse_done__ = true;
+    q = (  adaptlobstp (f, a  , mll, fa  , fmll, is, trace, varargin{:})
+         + adaptlobstp (f, mll, ml , fmll, fml , is, trace, varargin{:})
+         + adaptlobstp (f, ml , m  , fml , fm  , is, trace, varargin{:})
+         + adaptlobstp (f, m  , mr , fm  , fmr , is, trace, varargin{:})
+         + adaptlobstp (f, mr , mrr, fmr , fmrr, is, trace, varargin{:})
+         + adaptlobstp (f, mrr, b  , fmrr, fb  , is, trace, varargin{:}));
   endif
 endfunction
 
 
 ## basic functionality
-%!assert( quadl (@(x) sin (x), 0, pi, [], []), 2, -3e-16)
+%!assert (quadl (@(x) sin (x), 0, pi, [], []), 2, -3e-16)
 
 ## the values here are very high so it may be unavoidable that this fails
-%!assert ( quadl (@(x) sin (3*x).*cosh (x).*sinh (x),10,15),
+%!assert (quadl (@(x) sin (3*x).*cosh (x).*sinh (x),10,15),
 %!         2.588424538641647e+10, -9e-15)
 
 ## extra parameters
 %!assert (quadl (@(x,a,b) sin (a + b*x), 0, 1, [], [], 2, 3),
 %!        cos(2)/3 - cos(5)/3, - 3e-16)
 
-## test different tolerances. This test currently fails for a very high
-## tolerances.
-%!assert ( quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.3, []),
+## test different tolerances. 
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.3, []),
 %!        (60 + sin(4) - sin(64))/12, -0.3)
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.1, []),
+%!        (60 + sin(4) - sin(64))/12, -0.1)
 
-
-## for lower tolerances the test passes.
-%!assert ( quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.1, []),
-%!        (60 + sin(4) - sin(64))/12, -0.1)
\ No newline at end of file
--- a/scripts/io/strread.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/io/strread.m	Fri Aug 26 13:40:10 2011 -0500
@@ -471,7 +471,7 @@
         endif
       endfor
       ## Done
-      words_period = iwrd - 1;
+      words_period = max (iwrd - 1, 1);
       num_lines = ceil (num_words / words_period);
 
       ## 2. Pad words array so that it can be reshaped
@@ -633,7 +633,7 @@
               if (pad_out)
                 data(end+1:num_lines) = {""}
               endif
-              varargout{k} = strtrunc (data, 3)';
+              varargout{k} = strtrunc (data, swidth)';
               k++;
             otherwise
           endswitch
--- a/scripts/miscellaneous/edit.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/miscellaneous/edit.m	Fri Aug 26 13:40:10 2011 -0500
@@ -54,7 +54,7 @@
 ## filename.  If @file{name.ext} is not modifiable, it will be copied to
 ## @env{HOME} before editing.
 ##
-## @strong{WARNING!} You may need to clear name before the new definition
+## @strong{Warning:} You may need to clear name before the new definition
 ## is available.  If you are editing a .cc file, you will need
 ## to mkoctfile @file{name.cc} before the definition will be available.
 ## @end itemize
--- a/scripts/miscellaneous/private/__xzip__.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/miscellaneous/private/__xzip__.m	Fri Aug 26 13:40:10 2011 -0500
@@ -80,14 +80,16 @@
              commandname, status);
     endif
 
-    if (nargout > 0)
-      if (nargin == 5)
+    if (nargin == 5)
+      if (nargout > 0)
         entries = cellfun(
             @(x) fullfile (outdir, sprintf ("%s.%s", x, extension)),
             f, "uniformoutput", false);
-      else
-        movefile (cellfun(@(x) sprintf ("%s.%s", x, extension), f,
-                          "uniformoutput", false), cwd);
+      endif
+    else
+      movefile (cellfun(@(x) sprintf ("%s.%s", x, extension), f,
+                        "uniformoutput", false), cwd);
+      if (nargout > 0)
         ## FIXME this does not work when you try to compress directories
         entries  = cellfun(@(x) sprintf ("%s.%s", x, extension),
                            files, "uniformoutput", false);
--- a/scripts/miscellaneous/tar.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/miscellaneous/tar.m	Fri Aug 26 13:40:10 2011 -0500
@@ -42,7 +42,7 @@
     files = cellstr (files);
   endif
 
-  if (ischar (tarfile) && iscellstr (files) && ischar (root))
+  if (! (ischar (tarfile) && iscellstr (files) && ischar (root)))
     error ("tar: all arguments must be character strings");
   endif
 
--- a/scripts/miscellaneous/xor.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/miscellaneous/xor.m	Fri Aug 26 13:40:10 2011 -0500
@@ -48,7 +48,11 @@
       ## Typecast to logicals is necessary for other numeric types.
       z = logical (x) != logical (y);
     else
-      error ("xor: X and Y must be of common size or scalars");
+      try
+        z = bsxfun (@xor, x, y);
+      catch
+        error ("xor: X and Y must be of compatible size or scalars");
+      end_try_catch
     endif
   else
     print_usage ();
--- a/scripts/plot/isonormals.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/isonormals.m	Fri Aug 26 13:40:10 2011 -0500
@@ -46,47 +46,49 @@
 ##
 ## For example:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## function [] = isofinish (p)
-##   set (gca, "PlotBoxAspectRatioMode","manual","PlotBoxAspectRatio",[1 1 1]);
-##   set (p, "VertexNormals", -get(p,"VertexNormals")); ## Revert normals
+##   set (gca, "PlotBoxAspectRatioMode", "manual", ...
+##             "PlotBoxAspectRatio",[1 1 1]);
+##   set (p, "VertexNormals", -get(p,"VertexNormals")); # Revert normals
 ##   set (p, "FaceColor", "interp");
 ##   ## set (p, "FaceLighting", "phong");
-##   ## light ("Position", [1 1 5]); ## Available with JHandles
+##   ## light ("Position", [1 1 5]); # Available with JHandles
 ## endfunction
 ##
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v, cdat] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
+##            "FaceColor", "interp", "EdgeColor", "none");
 ## isofinish (p); ## Call user function isofinish
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, p); ## Directly modify patch
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, p); # Directly modify patch
 ## isofinish (p);
 ##
 ## subplot (2, 2, 3); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## n = isonormals (x, y, z, c, v); ## Compute normals of isosurface
-## set (p, "VertexNormals", n);    ## Manually set vertex normals
+##            "FaceColor", "interp", "EdgeColor", "none");
+## n = isonormals (x, y, z, c, v); # Compute normals of isosurface
+## set (p, "VertexNormals", n);    # Manually set vertex normals
 ## isofinish (p);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, v, "negate"); ## Use reverse directly
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, v, "negate"); # Use reverse directly
 ## isofinish (p);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isosurface, isocolors}
 ## @end deftypefn
--- a/scripts/plot/isosurface.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/isosurface.m	Fri Aug 26 13:40:10 2011 -0500
@@ -71,24 +71,27 @@
 ## Another example for an isosurface geometry with different additional
 ## coloring
 ##
-## @example
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## @c Set example in small font to prevent overfull line
+## @smallexample
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v] = isosurface (x, y, z, c, iso);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "green", "FaceLighting", "phong");
-## # light ("Position", [1 1 5]); ## Available with the JHandles package
+## # light ("Position", [1 1 5]); # Available with the JHandles package
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "none", "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
@@ -96,17 +99,19 @@
 ## [f, v, c] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isonormals, isocolors}
 ## @end deftypefn
--- a/scripts/plot/private/__axis_label__.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/private/__axis_label__.m	Fri Aug 26 13:40:10 2011 -0500
@@ -25,24 +25,20 @@
 
 function retval = __axis_label__ (caller, txt, varargin)
 
-  if (ischar (txt))
-    ca = gca ();
+  ca = gca ();
 
-    h = get (gca (), caller);
+  h = get (gca (), caller);
 
-    set (h, "fontangle", get (ca, "fontangle"),
-         "fontname", get (ca, "fontname"),
-         "fontsize", get (ca, "fontsize"),
-         "fontunits", get (ca, "fontunits"),
-         "fontweight", get (ca, "fontweight"),
-         "string", txt,
-         varargin{:});
+  set (h, "fontangle", get (ca, "fontangle"),
+       "fontname", get (ca, "fontname"),
+       "fontsize", get (ca, "fontsize"),
+       "fontunits", get (ca, "fontunits"),
+       "fontweight", get (ca, "fontweight"),
+       "string", txt,
+       varargin{:});
 
-    if (nargout > 0)
-      retval = h;
-    endif
-  else
-    error ("%s: expecting first argument to be character string", caller);
+  if (nargout > 0)
+    retval = h;
   endif
 
 endfunction
--- a/scripts/plot/private/__go_draw_axes__.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/private/__go_draw_axes__.m	Fri Aug 26 13:40:10 2011 -0500
@@ -1250,6 +1250,11 @@
             colorspec = get_text_colorspec (color, mono);
           endif
 
+          if (ischar (obj.string))
+            num_lines = size (obj.string, 1);
+          else
+            num_lines = numel (obj.string);
+          endif
           switch valign
             ## Text offset in characters. This relies on gnuplot for font metrics.
             case "top"
@@ -1257,17 +1262,18 @@
             case "cap"
               dy = -0.5;
             case "middle"
-              dy = 0;
+              dy = 0.5 * (num_lines - 1);
             case "baseline"
-              dy = 0.5;
+              dy = 0.5 + (num_lines - 1);
             case "bottom"
-              dy = 0.5;
+              dy = 0.5 + (num_lines - 1);
           endswitch
           ## Gnuplot's Character units are different for x/y and vary with fontsize. The aspect ratio
           ## of 1:1.7 was determined by experiment to work for eps/ps/etc. For the MacOS aqua terminal
           ## a value of 2.5 is needed. However, the difference is barely noticable.
           dx_and_dy = [(-dy * sind (angle)), (dy * cosd(angle))] .* [1.7 1];
 
+          ## FIXME - Multiline text produced the gnuplot "warning: ft_render: skipping glyph"
           if (nd == 3)
             ## This produces the desired vertical alignment in 3D.
             fprintf (plot_stream,
@@ -2129,10 +2135,31 @@
     bld = false;
   endif
 
+  ## The text object maybe multiline, and may be of any class
   str = getfield (obj, fld);
+  if (ischar (str) && size (str, 1) > 1)
+    str = cellstr (str);
+  elseif (isnumeric (str))
+    str = cellstr (num2str (str(:)));
+  endif
+  if (iscellstr (str))
+    for n = 1:numel(str)
+      if (isnumeric (str{n}))
+        str{n} = num2str (str{n});
+      endif
+    endfor
+    str = sprintf ("%s\n", str{:})(1:end-1);
+  endif
+
   if (enhanced)
     if (strcmpi (obj.interpreter, "tex"))
-      str = __tex2enhanced__ (str, fnt, it, bld);
+      if (iscellstr (str))
+        for n = 1:numel(str)
+          str{n} = __tex2enhanced__ (str{n}, fnt, it, bld);
+        endfor
+      else
+        str = __tex2enhanced__ (str, fnt, it, bld);
+      endif
     elseif (strcmpi (obj.interpreter, "latex"))
       if (! warned_latex)
         warning ("latex markup not supported for text objects");
--- a/scripts/plot/text.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/text.m	Fri Aug 26 13:40:10 2011 -0500
@@ -47,15 +47,33 @@
     endif
 
     label = varargin{offset};
-    if (ischar (label) || iscellstr (label))
-      varargin(1:offset) = [];
-      if (ischar (label))
+    varargin(1:offset) = [];
+
+    nx = numel (x);
+    ny = numel (y);
+    nz = numel (z);
+    if (ischar (label) || isnumeric (label))
+      nt = size (label, 1);
+      if (nx > 1 && nt == 1)
+        ## Mutiple text objects with same string
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (nx > 1 && nt == nx)
+        ## Mutiple text objects with different strings
         label = cellstr (label);
+      elseif (ischar (label))
+        ## Single text object with one or more lines
+        label = {label};
       endif
-      n = numel (label);
-      nx = numel (x);
-      ny = numel (y);
-      nz = numel (z);
+    elseif (iscell (label))
+      nt = numel (label);
+      if (nx > 1 && nt == 1)
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (! (nx > 1 && nt == nx))
+        label = {label};
+        nt = 1;
+      endif
     else
       error ("text: expecting LABEL to be a character string or cell array of character strings");
     endif
@@ -63,35 +81,35 @@
     x = y = z = 0;
     nx = ny = nz = 1;
     label = {""};
-    n = 1;
+    nt = 1;
   endif
 
   if (rem (numel (varargin), 2) == 0)
 
-    if (nx == ny && nx == nz)
+    if (nx == ny && nx == nz && (nt == nx || nt == 1 || nx == 1))
       pos = [x(:), y(:), z(:)];
       ca = gca ();
-      tmp = zeros (n, 1);
-      if (n == 1)
-        label = label{1};
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label,
+      tmp = zeros (nt, 1);
+      if (nx == 1)
+        ## TODO - Modify __go_text__() to accept cell-strings
+        tmp = __go_text__ (ca, "string", "foobar",
+                           varargin{:},
+                           "position", pos);
+        set (tmp, "string", label{1});
+      elseif (nt == nx)
+        for n = 1:nt
+          tmp(n) = __go_text__ (ca, "string", label{n},
                                 varargin{:},
-                                "position", pos(i,:));
-        endfor
-        __request_drawnow__ ();
-      elseif (n == nx)
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label{i},
-                                varargin{:},
-                                "position", pos(i,:));
+                                "position", pos(n,:));
         endfor
         __request_drawnow__ ();
       else
         error ("text: dimension mismatch for coordinates and LABEL");
       endif
+    elseif (nt == nx || nt == 1 || nx == 1)
+      error ("text: dimension mismatch for coordinates");
     else
-      error ("text: dimension mismatch for coordinates");
+      error ("text: mismatch betwween coordinates and strings");
     endif
 
     if (nargout > 0)
@@ -142,3 +160,61 @@
 %! endfor
 %! caxis ([-100 100])
 %! title ("Vertically Aligned at Bottom")
+
+%!demo
+%! clf
+%! axis ([0 8 0 8])
+%! title (["First title";"Second title"])
+%! xlabel (["First xlabel";"Second xlabel"])
+%! ylabel (["First ylabel";"Second ylabel"])
+%! text (4, 4, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! grid on
+
+%!demo
+%! clf
+%! h = mesh (peaks, "edgecolor", 0.7 * [1 1 1], ...
+%!                  "facecolor", "none", ...
+%!                  "facealpha", 0);
+%! title (["First title";"Second title"])
+%! xlabel (["First xlabel";"Second xlabel"])
+%! ylabel (["First ylabel";"Second ylabel"])
+%! zlabel (["First zlabel";"Second zlabel"])
+%! text (0, 0, 5, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! hold on
+%! plot3 (0, 0, 5, "+k")
+%!
+
+%!demo
+%! clf
+%! h = text (0.5, 0.3, "char");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.4, ["char row 1"; "char row 2"]);
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.6, {"cell2str (1,1)", "cell2str (1,2)"; "cell2str (2,1)", "cell2str (2,2)"});
+%! assert ("cell", class (get (h, "string")))
+%! h = text (0.5, 0.8, "foobar");
+%! set (h, "string", 1:3)
+%! h = text ([0.1, 0.1], [0.3, 0.4], "one string & two objects");
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.5, 0.6], {"one cellstr & two objects"});
+%! assert ("cell", class (get (h(1), "string")))
+%! assert ("cell", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.7, 0.8], {"cellstr 1 object 1", "cellstr 2 object 2"});
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.1, 0.2], ["1st string & 1st object"; "2nd string & 2nd object"]);
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text (0.7, 0.6, "single string");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.7, 0.5, {"single cell-string"});
+%! assert ("cell", class (get (h, "string")))
+%! xlabel (1:2)
+%! ylabel (1:2)
+%! title (1:2)
+
--- a/scripts/plot/uimenu.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/plot/uimenu.m	Fri Aug 26 13:40:10 2011 -0500
@@ -66,8 +66,10 @@
 ## @group
 ## f = uimenu("label", "&File", "accelerator", "f");
 ## e = uimenu("label", "&Edit", "accelerator", "e");
-## uimenu(f, "label", "Close", "accelerator", "q", "callback", "close (gcf)");
-## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", "callback", "grid (gca)");
+## uimenu(f, "label", "Close", "accelerator", "q", ...
+##           "callback", "close (gcf)");
+## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", ...
+##           "callback", "grid (gca)");
 ## @end group
 ## @end example
 ## @seealso{figure}
--- a/scripts/polynomial/polyval.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/polynomial/polyval.m	Fri Aug 26 13:40:10 2011 -0500
@@ -20,7 +20,7 @@
 ## @deftypefn  {Function File} {@var{y} =} polyval (@var{p}, @var{x})
 ## @deftypefnx {Function File} {@var{y} =} polyval (@var{p}, @var{x}, [], @var{mu})
 ## Evaluate the polynomial @var{p} at the specified values of @var{x}.  When
-## @var{mu} is present evaluate the polynomial for
+## @var{mu} is present, evaluate the polynomial for
 ## (@var{x}-@var{mu}(1))/@var{mu}(2).
 ## If @var{x} is a vector or matrix, the polynomial is evaluated for each of
 ## the elements of @var{x}.
@@ -39,17 +39,19 @@
 ## Created: June 1994
 ## Adapted-By: jwe
 
-function [y, dy] = polyval (p, x, s, mu)
+function [y, dy] = polyval (p, x, s = [], mu)
 
   if (nargin < 2 || nargin > 4 || (nargout == 2 && nargin < 3))
     print_usage ();
   endif
 
-  if (nargin < 3)
-    s = [];
-  endif
-
-  if (! (isvector (p) || isempty (p)))
+  if (isempty (x))
+    y = [];
+    return;
+  elseif (isempty (p))
+    y = zeros (size (x));
+    return;
+  elseif (! isvector (p))
     error ("polyval: first argument must be a vector");
   endif
 
@@ -57,16 +59,6 @@
     x = (x - mu(1)) / mu(2);
   endif
 
-  if (isempty (x))
-    y = [];
-    return;
-  endif
-
-  if (length (p) == 0)
-    y = p;
-    return;
-  endif
-
   n = length (p) - 1;
   y = p(1) * ones (size (x));
   for i = 2:n+1
@@ -80,10 +72,23 @@
     ##   dy = t * sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df)
     ## If my inference is correct, then t must equal 1 for polyval.
     ## This is because finv (0.5, n, n) = 1.0 for any n.
-    k = numel (x);
-    A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
-    dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
-    dy = reshape (dy, size (x));
+    try
+      k = numel (x);
+      A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
+      dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
+      dy = reshape (dy, size (x));
+    catch
+      if (isempty (s))
+        error ("polyval: third input is required.")
+      elseif (isstruct (s)
+              && all (ismember ({"R", "normr", "df"}, fieldnames (s))))
+        error (lasterr ())
+      elseif (isstruct (s))
+        error ("polyval: third input is missing the required fields.");
+      else
+        error ("polyval: third input is not a structure.");
+      endif
+    end_try_catch
   endif
 
 endfunction
@@ -142,3 +147,6 @@
 %! assert (y, polyval(p,x), eps)
 %! x = reshape(x, [1, 1, 5, 2]);
 
+%!assert (zeros (1, 10), polyval ([], 1:10))
+%!assert ([], polyval (1, []))
+%!assert ([], polyval ([], []))
--- a/scripts/statistics/base/quantile.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/statistics/base/quantile.m	Fri Aug 26 13:40:10 2011 -0500
@@ -90,13 +90,14 @@
 ##
 ## Examples:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## @group
-## x = randi (1000, [10, 1]);  # Create random empirical data in range 1-1000
-## q = quantile (x, [0, 1]);   # Return minimum, maximum of empirical distribution
-## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of empirical distribution
+## x = randi (1000, [10, 1]);  # Create empirical data in range 1-1000
+## q = quantile (x, [0, 1]);   # Return minimum, maximum of distribution
+## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of distribution
 ## @end group
-## @end example
+## @end smallexample
 ## @seealso{prctile}
 ## @end deftypefn
 
--- a/scripts/statistics/tests/wilcoxon_test.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/statistics/tests/wilcoxon_test.m	Fri Aug 26 13:40:10 2011 -0500
@@ -23,7 +23,7 @@
 ## @var{y}) == 1/2.  Under the null, the test statistic @var{z}
 ## approximately follows a standard normal distribution when @var{n} > 25.
 ##
-## @strong{Warning}: This function assumes a normal distribution for @var{z}
+## @strong{Caution:} This function assumes a normal distribution for @var{z}
 ## and thus is invalid for @var{n} @leq{} 25.
 ##
 ## With the optional argument string @var{alt}, the alternative of
--- a/scripts/strings/deblank.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/strings/deblank.m	Fri Aug 26 13:40:10 2011 -0500
@@ -20,8 +20,20 @@
 ## @deftypefn {Function File} {} deblank (@var{s})
 ## Remove trailing whitespace and nulls from @var{s}.  If @var{s}
 ## is a matrix, @var{deblank} trims each row to the length of longest
-## string.  If @var{s} is a cell array, operate recursively on each
-## element of the cell array.
+## string.  If @var{s} is a cell array of strings, operate recursively on each
+## string element.
+##
+## Examples:
+## @example
+## @group
+## deblank ("    abc  ")
+##      @result{}  "    abc"
+##
+## deblank ([" abc   "; "   def   "])
+##      @result{}  [" abc  " ; "   def"]
+## @end group
+## @end example
+## @seealso{strtrim}
 ## @end deftypefn
 
 ## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
@@ -42,7 +54,7 @@
       s = s(:,1:ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell (s))
+  elseif (iscellstr (s))
 
     s = regexprep (s, "[\\s\v\\0]+$", '');
 
@@ -62,4 +74,5 @@
 %!error <Invalid call to deblank> deblank ();
 %!error <Invalid call to deblank> deblank ("foo", "bar");
 %!error <argument must be a string> deblank (1);
+%!error <argument must be a string> deblank ({[]});
 
--- a/scripts/strings/str2num.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/strings/str2num.m	Fri Aug 26 13:40:10 2011 -0500
@@ -17,7 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} str2num (@var{s})
+## @deftypefn {Function File} {@var{x} =} str2num (@var{s})
+## @deftypefnx {Function File} {[@var{x}, @var{state}] =} str2num (@var{s})
 ## Convert the string (or character array) @var{s} to a number (or an
 ## array).  Examples:
 ##
@@ -33,6 +34,10 @@
 ## @end group
 ## @end example
 ##
+## The optional second output, @var{state}, is logically true when the
+## coversion is successful. If the conversion fails the numeric output,
+## @var{n}, is empty and @var{state} is false.
+##
 ## @strong{Caution:} As @code{str2num} uses the @code{eval} function
 ## to do the conversion, @code{str2num} will execute any code contained
 ## in the string @var{s}.  Use @code{str2double} instead if you want to
@@ -42,16 +47,18 @@
 
 ## Author: jwe
 
-function m = str2num (s)
+function [m, state] = str2num (s)
 
   if (nargin == 1 && ischar (s))
     [nr, nc] = size (s);
     sep = ";";
     sep = sep (ones (nr, 1), 1);
     s = sprintf ("m = [%s];", reshape ([s, sep]', 1, nr * (nc + 1)));
-    eval (s, "m = [];");
+    state = true;
+    eval (s, "m = []; state = false;");
     if (ischar (m))
       m = [];
+      state = false;
     endif
   else
     print_usage ();
@@ -65,3 +72,8 @@
 
 %!error str2num ("string", 1);
 
+%!test
+%! [x, state] = str2num ("pi");
+%! assert (state)
+%! [x, state] = str2num (tmpnam);
+%! assert (! state)
--- a/scripts/strings/strmatch.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/strings/strmatch.m	Fri Aug 26 13:40:10 2011 -0500
@@ -43,7 +43,7 @@
 ## @end group
 ## @end example
 ##
-## @strong{Note:} @code{strmatch} is scheduled for deprecation.  Use
+## @strong{Caution:} @code{strmatch} is scheduled for deprecation.  Use
 ## @code{strcmpi} or @code{strncmpi} in all new code.
 ## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
 ## @end deftypefn
--- a/scripts/strings/strtrim.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/strings/strtrim.m	Fri Aug 26 13:40:10 2011 -0500
@@ -20,18 +20,19 @@
 ## @deftypefn {Function File} {} strtrim (@var{s})
 ## Remove leading and trailing whitespace from @var{s}.  If
 ## @var{s} is a matrix, @var{strtrim} trims each row to the length of
-## longest string.  If @var{s} is a cell array, operate recursively on
-## each element of the cell array.  For example:
+## longest string.  If @var{s} is a cell array of strings, operate recursively
+## on each string element.  For example:
 ##
 ## @example
 ## @group
 ## strtrim ("    abc  ")
-##      @result{} "abc"
+##      @result{}  "abc"
 ##
 ## strtrim ([" abc   "; "   def   "])
-##      @result{} ["abc  "; "  def"]
+##      @result{}  ["abc  "  ; "  def"]
 ## @end group
 ## @end example
+## @seealso{deblank}
 ## @end deftypefn
 
 ## Author: John Swensen <jpswensen@jhu.edu>
@@ -53,7 +54,7 @@
       s = s(:, ceil (min (k) / rows (s)):ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell (s))
+  elseif (iscellstr (s))
 
     s = regexprep (s, "^[\\s\v]+|[\\s\v]+$", '');
 
@@ -73,4 +74,5 @@
 %!error <Invalid call to strtrim> strtrim ();
 %!error <Invalid call to strtrim> strtrim ("abc", "def");
 %!error <argument must be a string> strtrim (1);
+%!error <argument must be a string> strtrim ({[]});
 
--- a/scripts/time/datenum.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/scripts/time/datenum.m	Fri Aug 26 13:40:10 2011 -0500
@@ -50,7 +50,7 @@
 ## Days can be fractional.
 ## @end itemize
 ##
-## @strong{Warning:} this function does not attempt to handle Julian
+## @strong{Caution:} this function does not attempt to handle Julian
 ## calendars so dates before Octave 15, 1582 are wrong by as much
 ## as eleven days.  Also be aware that only Roman Catholic countries
 ## adopted the calendar in 1582.  It took until 1924 for it to be
--- a/src/DLD-FUNCTIONS/__init_fltk__.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/DLD-FUNCTIONS/__init_fltk__.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -1840,10 +1840,10 @@
                 case figure::properties::ID_MENUBAR:
                   figure_manager::toggle_menubar_visibility (ov.string_value (), fp.menubar_is("figure"));
                   break;
-                case figure::properties::ID_NAME:
                 case figure::properties::ID_CURRENTAXES:
                   figure_manager::update_canvas (go.get_handle (), fp.get_currentaxes ());
                   break;
+                case figure::properties::ID_NAME:
                 case figure::properties::ID_NUMBERTITLE:
                   figure_manager::set_name (ov.string_value ());
                   break;
--- a/src/DLD-FUNCTIONS/bsxfun.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/DLD-FUNCTIONS/bsxfun.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -312,15 +312,18 @@
 DEFUN_DLD (bsxfun, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {} bsxfun (@var{f}, @var{A}, @var{B})\n\
-Apply a binary function @var{f} element-by-element to two matrix arguments\n\
-@var{A} and @var{B}.  @var{f} is a function handle, inline function, or\n\
-string containing the name of the function to evaluate.\n\
-The function @var{f} must be capable of accepting two column-vector\n\
-arguments of equal length, or one column vector argument and a scalar.\n\
+The binary singleton expansion function applier does what its name\n\
+suggests: applies a binary function @var{f} element-by-element to two\n\
+array arguments @var{A} and @var{B}, and expands as necessary\n\
+singleton dimensions in either input argument. @var{f} is a function\n\
+handle, inline function, or string containing the name of the function\n\
+to evaluate. The function @var{f} must be capable of accepting two\n\
+column-vector arguments of equal length, or one column vector argument\n\
+and a scalar.\n\
 \n\
-The dimensions of @var{A} and @var{B} must be equal or singleton.  The\n\
-singleton dimensions of the matrices will be expanded to the same\n\
-dimensionality as the other matrix.\n\
+The dimensions of @var{A} and @var{B} must be equal or singleton. The\n\
+singleton dimensions of the arrays will be expanded to the same\n\
+dimensionality as the other array.\n\
 @seealso{arrayfun, cellfun}\n\
 @end deftypefn")
 {
--- a/src/DLD-FUNCTIONS/cellfun.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -58,6 +58,8 @@
 #include "ov-uint32.h"
 #include "ov-uint64.h"
 
+#include "ov-fcn-handle.h"
+
 static octave_value_list
 get_output_list (octave_idx_type count, octave_idx_type nargout,
                  const octave_value_list& inputlist,
@@ -222,6 +224,7 @@
     }
 
   octave_value func = args(0);
+  bool symbol_table_lookup = false;
 
   if (! args(1).is_cell ())
     {
@@ -339,6 +342,8 @@
               func = symbol_table::find_function (name);
               if (func.is_undefined ())
                 error ("cellfun: invalid function NAME: %s", name.c_str ());
+
+              symbol_table_lookup = true;
             }
         }
     }
@@ -349,6 +354,30 @@
   if (func.is_function_handle () || func.is_inline_function ()
       || func.is_function ())
     {
+
+      // The following is an optimisation because the symbol table can
+      // give a more specific function class, so this can result in
+      // fewer polymorphic function calls as the function gets called
+      // for each value of the array.
+      if (! symbol_table_lookup )
+        {
+          if (func.is_function_handle ())
+            {
+              octave_fcn_handle* f = func.fcn_handle_value ();
+
+              // Overloaded function handles need to check the type of
+              // the arguments for each element of the array, so they
+              // cannot be optimised this way.
+              if (f -> is_overloaded ())
+                goto nevermind;
+            }
+          octave_value f = symbol_table::find_function (func.function_value ()
+                                                         -> name ());
+          if (f.is_defined ())
+            func = f;
+        }
+      nevermind:
+
       unwind_protect frame;
       frame.protect_var (buffer_error_messages);
 
--- a/src/DLD-FUNCTIONS/urlwrite.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/DLD-FUNCTIONS/urlwrite.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -112,11 +112,11 @@
           {
             BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-            CURLcode res = curl_easy_perform (curl);
-            if (res != CURLE_OK)
+            errnum = curl_easy_perform (curl);
+            if (errnum != CURLE_OK)
               {
                 if (curlerror)
-                  error ("%s", curl_easy_strerror (res));
+                  error ("%s", curl_easy_strerror (errnum));
               }
             else
               retval = true;
@@ -145,6 +145,7 @@
     std::string host;
     bool valid;
     bool ascii;
+    mutable CURLcode errnum;
 
   private:
     CURL *curl;
@@ -250,11 +251,7 @@
 
   std::string lasterror (void) const
     {
-      CURLcode errnum;
-
-      curl_easy_getinfo (rep->handle(), CURLINFO_OS_ERRNO, &errnum);
-
-      return std::string (curl_easy_strerror (errnum));
+      return std::string (curl_easy_strerror (rep->errnum));
     }
 
   void set_ostream (std::ostream& os) const
--- a/src/Makefile.am	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/Makefile.am	Fri Aug 26 13:40:10 2011 -0500
@@ -541,7 +541,7 @@
     ../libcruft/libcruft.la \
     ../libcruft/libranlib.la \
     ../libgnu/libgnu.la \
-    $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
+    $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
     $(QHULL_LDFLAGS) $(QHULL_LIBS) \
     $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) \
     $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) \
--- a/src/OPERATORS/op-int.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/OPERATORS/op-int.h	Fri Aug 26 13:40:10 2011 -0500
@@ -21,6 +21,7 @@
 */
 
 #include "quit.h"
+#include "bsxfun.h"
 
 #define DEFINTBINOP_OP(name, t1, t2, op, t3) \
   BINOPDECL (name, a1, a2) \
@@ -703,8 +704,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -722,8 +730,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, static_cast<T1 ## NDArray> (b)); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -741,8 +756,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (static_cast<T2 ## NDArray> (a), b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -760,8 +782,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, static_cast<T1 ## NDArray> (b)); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -779,8 +808,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (static_cast<T1 ## NDArray> (a), b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
--- a/src/c-file-ptr-stream.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/c-file-ptr-stream.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -195,9 +195,7 @@
 int
 c_file_ptr_buf::seek (long offset, int origin)
 {
-  // gnulib::fseek doesn't seem to work, so don't use it until problem
-  // can be properly diagnosed and fixed.
-  return f ? fseek (f, offset, origin) : -1;
+  return f ? gnulib::fseek (f, offset, origin) : -1;
 }
 
 long
--- a/src/file-io.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/file-io.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -494,7 +494,7 @@
                 {
                   tmode.erase (pos, 1);
 
-                  FILE *fptr = ::fopen (fname.c_str (), tmode.c_str ());
+                  FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ());
 
                   int fd = fileno (fptr);
 
@@ -509,7 +509,7 @@
               else
 #endif
                 {
-                  FILE *fptr = ::fopen (fname.c_str (), tmode.c_str ());
+                  FILE *fptr = gnulib::fopen (fname.c_str (), tmode.c_str ());
 
                   retval = octave_stdiostream::create (fname, fptr, md, flt_fmt);
 
@@ -1176,11 +1176,13 @@
 
 DEFUN (sscanf, args, ,
   "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {[@var{val}, @var{count}] =} sscanf (@var{string}, @var{template}, @var{size})\n\
+@deftypefn  {Built-in Function} {[@var{val}, @var{count}, @var{pos}] =} sscanf (@var{string}, @var{template}, @var{size})\n\
 @deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} sscanf (@var{string}, @var{template}, \"C\")\n\
 This is like @code{fscanf}, except that the characters are taken from the\n\
 string @var{string} instead of from a stream.  Reaching the end of the\n\
-string is treated as an end-of-file condition.\n\
+string is treated as an end-of-file condition.  In addition to the values\n\
+returned by @code{fscanf}, the index of the next character to be read\n\
+is returned in in @var{pos}.\n\
 @seealso{fscanf, scanf, sprintf}\n\
 @end deftypefn")
 {
@@ -1247,7 +1249,8 @@
                           // position will clear it.
                           std::string errmsg = os.error ();
 
-                          retval(3) = os.tell () + 1;
+                          retval(3)
+                            = (os.eof () ? data.length () : os.tell ()) + 1;
                           retval(2) = errmsg;
                           retval(1) = count;
                           retval(0) = tmp;
--- a/src/genprops.awk	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/genprops.awk	Fri Aug 26 13:40:10 2011 -0500
@@ -300,8 +300,9 @@
         emit_get_accessor(i, "graphics_handle", "handle_value");
       else if (type[i] == "string_property")
         emit_get_accessor(i, "std::string", "string_value");
-      else if (type[i] == "string_array_property")
-          emit_get_accessor(i, "octave_value", "get");
+      else if (type[i] == "string_array_property" \
+               || type[i] == "text_label_property")
+        emit_get_accessor(i, "octave_value", "get");
       else if (type[i] == "double_property")
         emit_get_accessor(i, "double", "double_value");
       else if (type[i] == "double_radio_property")
--- a/src/gl-render.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/gl-render.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -2422,7 +2422,7 @@
 void
 opengl_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   const Matrix pos = xform.scale (props.get_data_position ());
--- a/src/gl2ps-renderer.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/gl2ps-renderer.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -199,7 +199,7 @@
 void
 glps_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   set_font (props);
@@ -223,9 +223,15 @@
   // FIXME: handle margin and surrounding box
 
   glRasterPos3d (pos(0), pos(1), pos(2));
-  gl2psTextOpt (props.get_string ().c_str (), fontname.c_str (), fontsize,
+
+  octave_value string_prop = props.get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  std::string s = sv.join ("\n");
+
+  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize, 
                 alignment_to_mode (halign, valign), props.get_rotation ());
-
 }
 
 #endif
--- a/src/gl2ps.c	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/gl2ps.c	Fri Aug 26 13:40:10 2011 -0500
@@ -50,7 +50,7 @@
 #include <png.h>
 #endif
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Private definitions, data structures and prototypes
  *
@@ -167,7 +167,6 @@
      written to the file or not, and 'format' indicates if it is
      visible or not */
   GLenum format, type;
-  GLfloat zoom_x, zoom_y;
   GLfloat *pixels;
 } GL2PSimage;
 
@@ -228,7 +227,7 @@
   GLboolean zerosurfacearea;
   GL2PSbsptree2d *imagetree;
   GL2PSprimitive *primitivetoadd;
-
+  
   /* PDF-specific */
   int streamlength;
   GL2PSlist *pdfprimlist, *pdfgrouplist;
@@ -266,7 +265,7 @@
 
 static GLint gl2psPrintPrimitives(void);
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Utility routines
  *
@@ -283,7 +282,7 @@
     case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
     }
     va_start(args, fmt);
-    vfprintf(stderr, fmt, args);
+    vfprintf(stderr, fmt, args); 
     va_end(args);
     fprintf(stderr, "\n");
   }
@@ -360,16 +359,16 @@
 static int gl2psAllocCompress(unsigned int srcsize)
 {
   gl2psFreeCompress();
-
+  
   if(!gl2ps->compress || !srcsize)
     return GL2PS_ERROR;
-
+  
   gl2ps->compress->srcLen = srcsize;
   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
   gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
   gl2ps->compress->start = gl2ps->compress->src;
   gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
-
+  
   return GL2PS_SUCCESS;
 }
 
@@ -377,18 +376,18 @@
 {
   if(!gl2ps->compress || !srcsize)
     return NULL;
-
+  
   if(srcsize < gl2ps->compress->srcLen)
     return gl2ps->compress->start;
-
+  
   gl2ps->compress->srcLen = srcsize;
   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
-  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
+  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src, 
                                               gl2ps->compress->srcLen);
   gl2ps->compress->start = gl2ps->compress->src;
-  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
+  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest, 
                                                gl2ps->compress->destLen);
-
+  
   return gl2ps->compress->start;
 }
 
@@ -407,8 +406,8 @@
 {
   /* For compatibility with older zlib versions, we use compress(...)
      instead of compress2(..., Z_BEST_COMPRESSION) */
-  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
-                  gl2ps->compress->start, gl2ps->compress->srcLen);
+  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen, 
+                  gl2ps->compress->start, gl2ps->compress->srcLen);  
 }
 
 #endif
@@ -456,7 +455,7 @@
     /* add the gzip file header */
     fwrite(tmp, 10, 1, gl2ps->stream);
   }
-#endif
+#endif  
 }
 
 static void gl2psPrintGzipFooter()
@@ -477,7 +476,7 @@
         n += 4; /* DICTID */
       }
       /* write the data, without the zlib header and footer */
-      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
+      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4), 
              1, gl2ps->stream);
       /* add the gzip file footer */
       crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
@@ -496,7 +495,7 @@
     gl2psFree(gl2ps->compress);
     gl2ps->compress = NULL;
   }
-#endif
+#endif 
 }
 
 /* The list handling routines */
@@ -545,7 +544,7 @@
 
 static void gl2psListDelete(GL2PSlist *list)
 {
-  if(!list) return;
+  if(!list) return;  
   gl2psFree(list->array);
   gl2psFree(list);
 }
@@ -618,7 +617,7 @@
 
 static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
 {
-  static const char cb64[] =
+  static const char cb64[] = 
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
   out[0] = cb64[ in[0] >> 2 ];
@@ -671,7 +670,7 @@
     return GL_FALSE;
   return GL_TRUE;
 }
-
+  
 static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
 {
   int i;
@@ -690,20 +689,20 @@
   int i;
 
   if(n < 2) return GL_TRUE;
-
+  
   for(i = 1; i < n; i++){
     if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
        fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
        fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
       return GL_FALSE;
   }
-
+  
   return GL_TRUE;
 }
 
 static void gl2psSetLastColor(GL2PSrgba rgba)
 {
-  int i;
+  int i;        
   for(i = 0; i < 3; ++i){
     gl2ps->lastrgba[i] = rgba[i];
   }
@@ -712,13 +711,13 @@
 static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
                            GLfloat *red, GLfloat *green, GLfloat *blue)
 {
-
+  
   GLsizei width = im->width;
   GLsizei height = im->height;
   GLfloat *pixels = im->pixels;
   GLfloat *pimag;
 
-  /* OpenGL image is from down to up, PS image is up to down */
+  /* OpenGL image is from down to up, PS image is up to down */  
   switch(im->format){
   case GL_RGBA:
     pimag = pixels + 4 * (width * (height - 1 - y) + x);
@@ -741,13 +740,11 @@
 {
   int size;
   GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
-
+  
   image->width = im->width;
   image->height = im->height;
   image->format = im->format;
   image->type = im->type;
-  image->zoom_x = im->zoom_x;
-  image->zoom_y = im->zoom_y;
 
   switch(image->format){
   case GL_RGBA:
@@ -761,7 +758,7 @@
 
   image->pixels = (GLfloat*)gl2psMalloc(size);
   memcpy(image->pixels, im->pixels, size);
-
+  
   return image;
 }
 
@@ -783,7 +780,7 @@
 {
   unsigned int i;
   GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
-  for(i = 0; i < length; i++)
+  for(i = 0; i < length; i++) 
     gl2psListAdd(png, &data[i]);
 }
 
@@ -801,21 +798,21 @@
 
   if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
     return;
-
+  
   if(!(info_ptr = png_create_info_struct(png_ptr))){
     png_destroy_write_struct(&png_ptr, NULL);
     return;
   }
-
+  
   if(setjmp(png_jmpbuf(png_ptr))) {
     png_destroy_write_struct(&png_ptr, &info_ptr);
     return;
   }
-
+  
   png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
   png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
-               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8, 
+               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
                PNG_FILTER_TYPE_BASE);
   png_write_info(png_ptr, info_ptr);
 
@@ -839,7 +836,7 @@
 
 /* Helper routines for text strings */
 
-static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
+static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 
                           GLshort fontsize, GLint alignment, GLfloat angle)
 {
   GLfloat pos[4];
@@ -871,7 +868,7 @@
   glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
   prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
   prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
-  strcpy(prim->data.text->str, str);
+  strcpy(prim->data.text->str, str); 
   prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
   strcpy(prim->data.text->fontname, fontname);
   prim->data.text->fontsize = fontsize;
@@ -880,7 +877,7 @@
 
   gl2psListAdd(gl2ps->auxprimitives, &prim);
   glPassThrough(GL2PS_TEXT_TOKEN);
-
+    
   return GL2PS_SUCCESS;
 }
 
@@ -888,13 +885,13 @@
 {
   GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
   text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
-  strcpy(text->str, t->str);
+  strcpy(text->str, t->str); 
   text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
   strcpy(text->fontname, t->fontname);
   text->fontsize = t->fontsize;
   text->alignment = t->alignment;
   text->angle = t->angle;
-
+  
   return text;
 }
 
@@ -914,7 +911,7 @@
   /* returns TRUE if gl2ps supports the argument combination: only two
      blending modes have been implemented so far */
 
-  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
+  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) || 
       (sfactor == GL_ONE && dfactor == GL_ZERO) )
     return GL_TRUE;
   return GL_FALSE;
@@ -934,7 +931,7 @@
     v->rgba[3] = 1.0F;
     return;
   }
-
+  
   switch(gl2ps->blendfunc[0]){
   case GL_ONE:
     v->rgba[3] = 1.0F;
@@ -955,9 +952,9 @@
      a remarkable amount of PDF handling code inside this file depends
      on it if activated */
   /*
-  t->prop = T_CONST_COLOR;
+  t->prop = T_CONST_COLOR;    
   for(i = 0; i < 3; ++i){
-    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
+    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) || 
        !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
       t->prop = T_VAR_COLOR;
       break;
@@ -965,7 +962,7 @@
   }
   */
 
-  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
+  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) || 
      !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
     t->prop |= T_VAR_ALPHA;
   }
@@ -1008,7 +1005,7 @@
   }
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-
+  
   prim->type = p->type;
   prim->numverts = p->numverts;
   prim->boundary = p->boundary;
@@ -1044,17 +1041,17 @@
   return GL_TRUE;
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
- * 3D sorting routines
+ * 3D sorting routines 
  *
  *********************************************************************/
 
 static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
 {
-  return (plane[0] * point[0] +
-          plane[1] * point[1] +
-          plane[2] * point[2] +
+  return (plane[0] * point[0] + 
+          plane[1] * point[1] + 
+          plane[2] * point[2] + 
           plane[3]);
 }
 
@@ -1101,13 +1098,13 @@
   switch(prim->type){
   case GL2PS_TRIANGLE :
   case GL2PS_QUADRANGLE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
-    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
-    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
-    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
-    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
+    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0]; 
+    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1]; 
+    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2]; 
+    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || 
        (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
       plane[0] = plane[1] = 0.0F;
       plane[2] = 1.0F;
@@ -1115,16 +1112,16 @@
     }
     else{
       gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
         - plane[2] * prim->verts[0].xyz[2];
     }
     break;
   case GL2PS_LINE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
     if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
       plane[0] = plane[1] = 0.0F;
       plane[2] = 1.0F;
@@ -1135,9 +1132,9 @@
       else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
       else                      w[2] = 1.0F;
       gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
         - plane[2] * prim->verts[0].xyz[2];
     }
     break;
@@ -1172,11 +1169,11 @@
     sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
   else
     sect = 0.0F;
-
+  
   c->xyz[0] = a->xyz[0] + v[0] * sect;
   c->xyz[1] = a->xyz[1] + v[1] * sect;
   c->xyz[2] = a->xyz[2] + v[2] * sect;
-
+  
   c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
   c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
   c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
@@ -1199,10 +1196,10 @@
       numverts = 4;
     }
     switch(numverts){
-    case 1 : child->type = GL2PS_POINT; break;
-    case 2 : child->type = GL2PS_LINE; break;
-    case 3 : child->type = GL2PS_TRIANGLE; break;
-    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    case 1 : child->type = GL2PS_POINT; break; 
+    case 2 : child->type = GL2PS_LINE; break; 
+    case 3 : child->type = GL2PS_TRIANGLE; break; 
+    case 4 : child->type = GL2PS_QUADRANGLE; break;    
     default: child->type = GL2PS_NO_TYPE; break;
     }
   }
@@ -1221,13 +1218,13 @@
       child->verts[i] = parent->verts[index0[i]];
     }
     else{
-      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
+      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]], 
                    plane, &child->verts[i]);
     }
   }
 }
 
-static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
+static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, 
                           GLshort i, GLshort j)
 {
   GLint k;
@@ -1250,9 +1247,9 @@
 {
   GLint type = GL2PS_COINCIDENT;
   GLshort i, j;
-  GLfloat d[5];
-
-  for(i = 0; i < prim->numverts; i++){
+  GLfloat d[5]; 
+
+  for(i = 0; i < prim->numverts; i++){  
     d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
   }
 
@@ -1264,11 +1261,11 @@
       j = gl2psGetIndex(i, prim->numverts);
       if(d[j] > GL2PS_EPSILON){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) return 1;
+        else if(type != GL2PS_IN_BACK_OF) return 1; 
         if(d[i] < -GL2PS_EPSILON)         return 1;
       }
       else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) return 1;
         if(d[i] > GL2PS_EPSILON)           return 1;
       }
@@ -1277,16 +1274,16 @@
   return 0;
 }
 
-static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
+static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, 
                                  GL2PSprimitive **front, GL2PSprimitive **back)
 {
   GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
   GLint type;
-  GLfloat d[5];
+  GLfloat d[5]; 
 
   type = GL2PS_COINCIDENT;
 
-  for(i = 0; i < prim->numverts; i++){
+  for(i = 0; i < prim->numverts; i++){  
     d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
   }
 
@@ -1301,7 +1298,7 @@
       j = gl2psGetIndex(i, prim->numverts);
       if(d[j] > GL2PS_EPSILON){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
+        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; 
         if(d[i] < -GL2PS_EPSILON){
           gl2psAddIndex(in0, in1, &in, i, j);
           gl2psAddIndex(out0, out1, &out, i, j);
@@ -1310,7 +1307,7 @@
         gl2psAddIndex(out0, out1, &out, j, -1);
       }
       else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
         if(d[i] > GL2PS_EPSILON){
           gl2psAddIndex(in0, in1, &in, i, j);
@@ -1337,7 +1334,7 @@
   return type;
 }
 
-static void gl2psDivideQuad(GL2PSprimitive *quad,
+static void gl2psDivideQuad(GL2PSprimitive *quad, 
                             GL2PSprimitive **t1, GL2PSprimitive **t2)
 {
   *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
@@ -1366,17 +1363,17 @@
   GL2PSprimitive *q, *w;
   GLfloat dq = 0.0F, dw = 0.0F, diff;
   int i;
-
+  
   q = *(GL2PSprimitive**)a;
   w = *(GL2PSprimitive**)b;
 
   for(i = 0; i < q->numverts; i++){
-    dq += q->verts[i].xyz[2];
+    dq += q->verts[i].xyz[2]; 
   }
   dq /= (GLfloat)q->numverts;
 
   for(i = 0; i < w->numverts; i++){
-    dw += w->verts[i].xyz[2];
+    dw += w->verts[i].xyz[2]; 
   }
   dw /= (GLfloat)w->numverts;
 
@@ -1427,7 +1424,7 @@
       for(j = 0; j < gl2psListNbr(primitives); j++){
         if(j != i){
           prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
-          count += gl2psTestSplitPrimitive(prim2, plane);
+          count += gl2psTestSplitPrimitive(prim2, plane); 
         }
         if(count > best) break;
       }
@@ -1461,7 +1458,7 @@
 static void gl2psFreePrimitive(void *data)
 {
   GL2PSprimitive *q;
-
+  
   q = *(GL2PSprimitive**)data;
   gl2psFree(q->verts);
   if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
@@ -1486,7 +1483,7 @@
     gl2psListAdd(list, &t2);
     gl2psFreePrimitive(&prim);
   }
-
+  
 }
 
 static void gl2psFreeBspTree(GL2PSbsptree **tree)
@@ -1598,7 +1595,7 @@
     }
     gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
   }
-  else if(GL_TRUE == compare(-epsilon, result)){
+  else if(GL_TRUE == compare(-epsilon, result)){ 
     gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
     if(inverse){
       gl2psListActionInverse(tree->primitives, action);
@@ -1666,18 +1663,18 @@
     else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
       factor = gl2ps->offset[0];
       units = gl2ps->offset[1];
-      area =
-        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
-        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
-        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+      area = 
+        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * 
+        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - 
+        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * 
         (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
       if(!GL2PS_ZERO(area)){
-        dZdX =
+        dZdX = 
           ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
            (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
            (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
-        dZdY =
+        dZdY = 
           ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
            (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
@@ -1695,15 +1692,15 @@
   }
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
- * 2D sorting routines (for occlusion culling)
+ * 2D sorting routines (for occlusion culling) 
  *
  *********************************************************************/
 
 static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
 {
-  GLfloat n;
+  GLfloat n; 
 
   plane[0] = b[1] - a[1];
   plane[1] = a[0] - b[0];
@@ -1712,7 +1709,7 @@
   if(!GL2PS_ZERO(n)){
     plane[0] /= n;
     plane[1] /= n;
-    plane[3] = -plane[0]*a[0]-plane[1]*a[1];
+    plane[3] = -plane[0]*a[0]-plane[1]*a[1]; 
     return 1;
   }
   else{
@@ -1897,8 +1894,8 @@
 }
 
 static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
-                                  GL2PSplane plane,
-                                  GL2PSprimitive **front,
+                                  GL2PSplane plane, 
+                                  GL2PSprimitive **front, 
                                   GL2PSprimitive **back)
 {
   /* cur will hold the position of the current vertex
@@ -1907,10 +1904,10 @@
      v1 and v2 represent the current and previous vertices, respectively
      flag is set if the current vertex should be checked against the plane */
   GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
-
+  
   /* list of vertices that will go in front and back primitive */
   GL2PSvertex *front_list = NULL, *back_list = NULL;
-
+  
   /* number of vertices in front and back list */
   GLshort front_count = 0, back_count = 0;
 
@@ -1927,7 +1924,7 @@
       if(i == 0){
         prev0 = cur;
       }
-    }
+    } 
     if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
        (i < prim->numverts)){
       if(cur == GL2PS_POINT_INFRONT){
@@ -1982,12 +1979,12 @@
 {
   GLint ret = 0;
   GL2PSprimitive *frontprim = NULL, *backprim = NULL;
-
+  
   /* FIXME: until we consider the actual extent of text strings and
      pixmaps, never cull them. Otherwise the whole string/pixmap gets
      culled as soon as the reference point is hidden */
-  if(prim->type == GL2PS_PIXMAP ||
-     prim->type == GL2PS_TEXT ||
+  if(prim->type == GL2PS_PIXMAP || 
+     prim->type == GL2PS_TEXT || 
      prim->type == GL2PS_SPECIAL){
     return 1;
   }
@@ -2001,7 +1998,7 @@
   else{
     switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
     case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
-    case GL2PS_IN_FRONT_OF:
+    case GL2PS_IN_FRONT_OF: 
       if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
       else                       return 0;
     case GL2PS_SPANNING:
@@ -2136,14 +2133,14 @@
   gl2psBuildPolygonBoundary(tree->front);
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Feedback buffer parser
  *
  *********************************************************************/
 
-static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
-                                  GL2PSvertex *verts, GLint offset,
+static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, 
+                                  GL2PSvertex *verts, GLint offset, 
                                   GLushort pattern, GLint factor,
                                   GLfloat width, char boundary)
 {
@@ -2210,7 +2207,7 @@
   while(used > 0){
 
     if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
-
+    
     switch((GLint)*current){
     case GL_POINT_TOKEN :
       current ++;
@@ -2218,7 +2215,7 @@
       i = gl2psGetVertex(&vertices[0], current);
       current += i;
       used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
+      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, 
                             pattern, factor, psize, 0);
       break;
     case GL_LINE_TOKEN :
@@ -2231,7 +2228,7 @@
       i = gl2psGetVertex(&vertices[1], current);
       current += i;
       used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
+      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, 
                             pattern, factor, lwidth, 0);
       break;
     case GL_POLYGON_TOKEN :
@@ -2262,7 +2259,7 @@
         else
           v ++;
       }
-      break;
+      break;      
     case GL_BITMAP_TOKEN :
     case GL_DRAW_PIXEL_TOKEN :
     case GL_COPY_PIXEL_TOKEN :
@@ -2271,7 +2268,7 @@
       i = gl2psGetVertex(&vertices[0], current);
       current += i;
       used    -= i;
-      break;
+      break;      
     case GL_PASS_THROUGH_TOKEN :
       switch((GLint)current[1]){
       case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
@@ -2281,32 +2278,32 @@
       case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
       case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
       case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
-      case GL2PS_BEGIN_STIPPLE_TOKEN :
+      case GL2PS_BEGIN_STIPPLE_TOKEN : 
         current += 2;
-        used -= 2;
-        pattern = (GLushort)current[1];
+        used -= 2; 
+        pattern = (GLushort)current[1]; 
         current += 2;
-        used -= 2;
-        factor = (GLint)current[1];
+        used -= 2; 
+        factor = (GLint)current[1]; 
         break;
-      case GL2PS_SRC_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_SRC_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
         gl2ps->blendfunc[0] = (GLint)current[1];
         break;
-      case GL2PS_DST_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_DST_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
         gl2ps->blendfunc[1] = (GLint)current[1];
         break;
-      case GL2PS_POINT_SIZE_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_POINT_SIZE_TOKEN : 
+        current += 2; 
+        used -= 2; 
         psize = current[1];
         break;
-      case GL2PS_LINE_WIDTH_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_LINE_WIDTH_TOKEN : 
+        current += 2; 
+        used -= 2; 
         lwidth = current[1];
         break;
       case GL2PS_IMAGEMAP_TOKEN :
@@ -2320,26 +2317,24 @@
         prim->pattern = 0;
         prim->factor = 0;
         prim->width = 1;
-
+        
         node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
         node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
         node->image->type = 0;
         node->image->format = 0;
-        node->image->zoom_x = 1.0F;
-        node->image->zoom_y = 1.0F;
         node->next = NULL;
-
+        
         if(gl2ps->imagemap_head == NULL)
           gl2ps->imagemap_head = node;
         else
           gl2ps->imagemap_tail->next = node;
         gl2ps->imagemap_tail = node;
         prim->data.image = node->image;
-
+        
         current += 2; used -= 2;
         i = gl2psGetVertex(&prim->verts[0], &current[1]);
         current += i; used -= i;
-
+        
         node->image->width = (GLint)current[2];
         current += 2; used -= 2;
         node->image->height = (GLint)current[2];
@@ -2359,12 +2354,12 @@
 
         sizeoffloat = sizeof(GLfloat);
         v = 2 * sizeoffloat;
-        vtot = node->image->height + node->image->height *
+        vtot = node->image->height + node->image->height * 
           ((node->image->width - 1) / 8);
         node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
         node->image->pixels[0] = prim->verts[0].xyz[0];
         node->image->pixels[1] = prim->verts[0].xyz[1];
-
+        
         for(i = 0; i < vtot; i += sizeoffloat){
           current += 2; used -= 2;
           if((vtot - i) >= 4)
@@ -2378,15 +2373,15 @@
       case GL2PS_DRAW_PIXELS_TOKEN :
       case GL2PS_TEXT_TOKEN :
         if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
-          gl2psListAdd(gl2ps->primitives,
+          gl2psListAdd(gl2ps->primitives, 
                        gl2psListPointer(gl2ps->auxprimitives, auxindex++));
         else
           gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
         break;
       }
-      current += 2;
-      used -= 2;
-      break;
+      current += 2; 
+      used -= 2; 
+      break;      
     default :
       gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
       current ++;
@@ -2398,7 +2393,7 @@
   gl2psListReset(gl2ps->auxprimitives);
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * PostScript routines
  *
@@ -2428,17 +2423,17 @@
   if((width <= 0) || (height <= 0)) return;
 
   gl2psPrintf("gsave\n");
-  gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%.2f %.2f scale\n", width * im->zoom_x, height * im->zoom_y);
+  gl2psPrintf("%.2f %.2f translate\n", x, y); 
+  gl2psPrintf("%d %d scale\n", width, height); 
 
   if(greyscale){ /* greyscale */
-    gl2psPrintf("/picstr %d string def\n", width);
-    gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("/picstr %d string def\n", width); 
+    gl2psPrintf("%d %d %d\n", width, height, 8); 
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
     gl2psPrintf("image\n");
     for(row = 0; row < height; row++){
-      for(col = 0; col < width; col++){
+      for(col = 0; col < width; col++){ 
         gl2psGetRGB(im, col, row, &dr, &dg, &db);
         fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
         grey = (unsigned char)(255. * fgrey);
@@ -2446,8 +2441,8 @@
       }
       gl2psPrintf("\n");
     }
-    nbhex = width * height * 2;
-    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex);
+    nbhex = width * height * 2; 
+    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex); 
   }
   else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
     nrgb = width  * 3;
@@ -2468,7 +2463,7 @@
         if(icase == 1) {
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2481,7 +2476,7 @@
           b = (b<<2) + blue;
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2493,7 +2488,7 @@
           gl2psWriteByte(b);
           b = 0;
           icase++;
-        }
+        } 
         else if(icase == 2) {
           b = green;
           b = (b<<2) + blue;
@@ -2512,7 +2507,7 @@
           gl2psWriteByte(b);
           b = 0;
           icase++;
-        }
+        } 
         else if(icase == 3) {
           b = blue;
           if(col < width) {
@@ -2540,7 +2535,7 @@
     nrgb = width  * 3;
     nbits = nrgb * nbit;
     nbyte = nbits / 8;
-    if((nbyte * 8) != nbits) nbyte++;
+    if((nbyte * 8) != nbits) nbyte++; 
     gl2psPrintf("/rgbstr %d string def\n", nbyte);
     gl2psPrintf("%d %d %d\n", width, height, nbit);
     gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
@@ -2554,7 +2549,7 @@
         if(icase == 1) {
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2563,12 +2558,12 @@
           green = (unsigned char)(15. * dg);
           gl2psPrintf("%x%x", red, green);
           icase++;
-        }
+        } 
         else if(icase == 2) {
           blue = (unsigned char)(15. * db);
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2591,7 +2586,7 @@
     nbyte = width * 3;
     gl2psPrintf("/rgbstr %d string def\n", nbyte);
     gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
     gl2psPrintf("false 3\n");
     gl2psPrintf("colorimage\n");
@@ -2608,7 +2603,7 @@
       gl2psPrintf("\n");
     }
   }
-
+  
   gl2psPrintf("grestore\n");
 }
 
@@ -2616,14 +2611,14 @@
                                          GLsizei width, GLsizei height,
                                          const unsigned char *imagemap){
   int i, size;
-
+  
   if((width <= 0) || (height <= 0)) return;
-
+  
   size = height + height * (width - 1) / 8;
-
+  
   gl2psPrintf("gsave\n");
   gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height);
+  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height); 
   gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
   for(i = 0; i < size; i++){
     gl2psWriteByte(*imagemap);
@@ -2657,7 +2652,7 @@
               "%%%%LanguageLevel: 3\n"
               "%%%%DocumentData: Clean7Bit\n"
               "%%%%Pages: 1\n",
-              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, 
               GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
               gl2ps->producer, ctime(&now));
 
@@ -2666,18 +2661,18 @@
                 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
                 (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
                 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
-                (int)gl2ps->viewport[2],
-                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+                (int)gl2ps->viewport[2], 
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : 
                 (int)gl2ps->viewport[3]);
   }
 
   gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
               "%%%%EndComments\n",
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : 
               (int)gl2ps->viewport[0],
               (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
               (int)gl2ps->viewport[1],
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : 
               (int)gl2ps->viewport[2],
               (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
               (int)gl2ps->viewport[3]);
@@ -2725,7 +2720,7 @@
   /* rotated text routines: same nameanem with R appended */
 
   gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
-              "/SR  { gsave FCT moveto rotate show grestore } BD\n"
+              "/SR  { gsave FCT moveto rotate show grestore } BD\n"  
               "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
               "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
               "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
@@ -2740,7 +2735,7 @@
               "/L  { lineto } BD\n"
               "/LE { lineto stroke } BD\n"
               "/T  { newpath moveto lineto lineto closepath fill } BD\n");
-
+  
   /* Smooth-shaded triangle with PostScript level 3 shfill operator:
         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
 
@@ -2794,11 +2789,11 @@
               "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
               "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
               "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
-
+  
   /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
 
   gl2psPrintf("      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
-
+  
   /* Gouraud shaded triangle using recursive subdivision until the difference
      between corner colors does not exceed the thresholds:
         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
@@ -2832,7 +2827,7 @@
               "          ifelse }\n"
               "        ifelse }\n"
               "      ifelse } BD\n");
-
+  
   gl2psPrintf("tryPS3shading\n"
               "{ /shfill where\n"
               "  { /ST { STshfill } BD }\n"
@@ -2849,7 +2844,7 @@
               "%%%%EndSetup\n"
               "%%%%Page: 1 1\n"
               "%%%%BeginPageSetup\n");
-
+  
   if(gl2ps->options & GL2PS_LANDSCAPE){
     gl2psPrintf("%d 0 translate 90 rotate\n",
                 (int)gl2ps->viewport[3]);
@@ -2859,14 +2854,14 @@
               "mark\n"
               "gsave\n"
               "1.0 1.0 scale\n");
-
+          
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     gl2psPrintf("%g %g %g C\n"
                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
                 "closepath fill\n",
-                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
-                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2], 
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], 
+                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
   }
 }
@@ -2896,7 +2891,7 @@
   }
 }
 
-static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
+static void gl2psParseStipplePattern(GLushort pattern, GLint factor, 
                                      int *nb, int array[10])
 {
   int i, n;
@@ -2936,10 +2931,10 @@
 
   if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
     return 0;
-
+  
   gl2ps->lastpattern = pattern;
   gl2ps->lastfactor = factor;
-
+  
   if(!pattern || !factor){
     /* solid line */
     len += gl2psPrintf("[] 0 %s\n", str);
@@ -2953,7 +2948,7 @@
     }
     len += gl2psPrintf("] 0 %s\n", str);
   }
-
+  
   return len;
 }
 
@@ -2976,7 +2971,7 @@
   switch(prim->type){
   case GL2PS_POINT :
     gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("%g %g %g P\n",
+    gl2psPrintf("%g %g %g P\n", 
                 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
     break;
   case GL2PS_LINE :
@@ -3139,14 +3134,14 @@
     gl2psPrintf("%g %g %g C\n"
                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
                 "closepath fill\n",
-                rgba[0], rgba[1], rgba[2],
+                rgba[0], rgba[1], rgba[2], 
                 x, y, x+w, y, x+w, y+h, x, y+h);
   }
-
+    
   gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
               "closepath clip\n",
               x, y, x+w, y, x+w, y+h, x, y+h);
-
+  
 }
 
 static GLint gl2psPrintPostScriptEndViewport(void)
@@ -3188,7 +3183,7 @@
   "Encapsulated Postscript"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * LaTeX routines
  *
@@ -3216,7 +3211,7 @@
 
   time(&now);
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "%% Title: %s\n"
           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
           "%% For: %s\n"
@@ -3225,7 +3220,7 @@
           GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
           gl2ps->producer, ctime(&now));
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "\\setlength{\\unitlength}{1pt}\n"
           "\\begin{picture}(0,0)\n"
           "\\includegraphics{%s}\n"
@@ -3243,13 +3238,10 @@
 
   switch(prim->type){
   case GL2PS_TEXT :
-    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont",
+    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", 
             prim->data.text->fontsize);
-    fprintf(gl2ps->stream, "\\put(%g,%g)",
+    fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)",
             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    if(prim->data.text->angle)
-      fprintf(gl2ps->stream, "{\\rotatebox{%g}", prim->data.text->angle);
-    fprintf(gl2ps->stream, "{\\makebox(0,0)");
     switch(prim->data.text->alignment){
     case GL2PS_TEXT_C:
       fprintf(gl2ps->stream, "{");
@@ -3280,6 +3272,8 @@
       fprintf(gl2ps->stream, "[bl]{");
       break;
     }
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle);
     fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
             prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
             prim->data.text->str);
@@ -3307,7 +3301,7 @@
 static void gl2psPrintTeXBeginViewport(GLint viewport[4])
 {
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintTeXHeader();
     gl2ps->header = GL_FALSE;
@@ -3336,7 +3330,7 @@
   "LaTeX text"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * PDF routines
  *
@@ -3372,7 +3366,7 @@
 static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
 {
   int i, offs = 0;
-
+  
   for(i = 0; i < 3; ++i){
     if(GL2PS_ZERO(rgba[i]))
       offs += gl2psPrintf("%.0f ", 0.);
@@ -3398,18 +3392,18 @@
 static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
 {
   GLfloat rad, crad, srad;
-
+  
   if(text->angle == 0.0F){
     gl2ps->streamlength += gl2psPrintf
       ("BT\n"
        "/F%d %d Tf\n"
        "%f %f Td\n"
        "(%s) Tj\n"
-       "ET\n",
+       "ET\n", 
        cnt, text->fontsize, x, y, text->str);
   }
   else{
-    rad = (GLfloat)M_PI * text->angle / 180.0F;
+    rad = M_PI * text->angle / 180.0F;
     srad = (GLfloat)sin(rad);
     crad = (GLfloat)cos(rad);
     gl2ps->streamlength += gl2psPrintf
@@ -3434,23 +3428,23 @@
 
 static void gl2psPDFstacksInit(void)
 {
-  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
-  gl2ps->extgs_stack = 0;
-  gl2ps->font_stack = 0;
-  gl2ps->im_stack = 0;
-  gl2ps->trgroupobjects_stack = 0;
-  gl2ps->shader_stack = 0;
-  gl2ps->mshader_stack = 0;
+  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1; 
+  gl2ps->extgs_stack = 0;   
+  gl2ps->font_stack = 0;    
+  gl2ps->im_stack = 0;      
+  gl2ps->trgroupobjects_stack = 0;    
+  gl2ps->shader_stack = 0;  
+  gl2ps->mshader_stack = 0; 
 }
 
 static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
 {
   if(!gro)
     return;
-
+  
   gro->ptrlist = NULL;
-  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
-    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
+  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno 
+    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno 
     = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
 }
 
@@ -3475,7 +3469,7 @@
   gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
   gl2psInitTriangle(&lastt);
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){  
     p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
     switch(p->type){
     case GL2PS_PIXMAP:
@@ -3493,7 +3487,7 @@
       gl2psListAdd(gl2ps->pdfgrouplist, &gro);
       break;
     case GL2PS_LINE:
-      if(lasttype != p->type || lastwidth != p->width ||
+      if(lasttype != p->type || lastwidth != p->width || 
          lastpattern != p->pattern || lastfactor != p->factor ||
          !gl2psSameColor(p->verts[0].rgba, lastrgba)){
         gl2psPDFgroupObjectInit(&gro);
@@ -3512,7 +3506,7 @@
       lastrgba[2] = p->verts[0].rgba[2];
       break;
     case GL2PS_POINT:
-      if(lasttype != p->type || lastwidth != p->width ||
+      if(lasttype != p->type || lastwidth != p->width || 
          !gl2psSameColor(p->verts[0].rgba, lastrgba)){
         gl2psPDFgroupObjectInit(&gro);
         gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
@@ -3529,10 +3523,10 @@
       break;
     case GL2PS_TRIANGLE:
       gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
-      lastTriangleWasNotSimpleWithSameColor =
+      lastTriangleWasNotSimpleWithSameColor = 
         !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
         !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
-      if(lasttype == p->type && tmpt.prop == lastt.prop &&
+      if(lasttype == p->type && tmpt.prop == lastt.prop && 
          lastTriangleWasNotSimpleWithSameColor){
         /* TODO Check here for last alpha */
         gl2psListAdd(gro.ptrlist, &p);
@@ -3547,7 +3541,7 @@
       break;
     default:
       break;
-    }
+    } 
     lasttype = p->type;
   }
 }
@@ -3556,7 +3550,7 @@
 {
   GL2PStriangle t;
   GL2PSprimitive *prim = NULL;
-
+  
   if(!gro)
     return;
 
@@ -3569,35 +3563,35 @@
     return;
 
   gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
-
-  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
-    gro->gsno = gl2ps->extgs_stack++;
+  
+  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){        
+    gro->gsno = gl2ps->extgs_stack++; 
     gro->gsobjno = gl2ps->objects_stack ++;
   }
-  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){              
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
     gro->trgroupobjno = gl2ps->objects_stack++;
     gro->maskshno = gl2ps->mshader_stack++;
     gro->maskshobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){          
     gro->shno = gl2ps->shader_stack++;
     gro->shobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){             
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
+    gro->shno = gl2ps->shader_stack++; 
     gro->shobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){                
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
+    gro->shno = gl2ps->shader_stack++; 
     gro->shobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
     gro->trgroupobjno = gl2ps->objects_stack++;
     gro->maskshno = gl2ps->mshader_stack++;
     gro->maskshobjno = gl2ps->objects_stack++;
@@ -3630,14 +3624,14 @@
       gl2ps->streamlength += gl2psPrintf("1 J\n");
       gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
-      for(j = 0; j <= lastel; ++j){
+      for(j = 0; j <= lastel; ++j){  
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2ps->streamlength +=
           gl2psPrintf("%f %f m %f %f l\n",
                       prim->verts[0].xyz[0], prim->verts[0].xyz[1],
                       prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
       }
-      gl2ps->streamlength += gl2psPrintf("S\n");
+      gl2ps->streamlength += gl2psPrintf("S\n"); 
       gl2ps->streamlength += gl2psPrintf("0 J\n");
       break;
     case GL2PS_LINE:
@@ -3648,10 +3642,10 @@
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
       gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
       /* start new path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f m\n",
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f m\n", 
                     prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-
+      
       for(j = 1; j <= lastel; ++j){
         prev = prim;
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
@@ -3659,38 +3653,38 @@
           /* the starting point of the new segment does not match the
              end point of the previous line, so we end the current
              path and start a new one */
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f l\n",
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f l\n", 
                         prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f m\n",
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f m\n", 
                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
         }
         else{
           /* the two segements are connected, so we just append to the
              current path */
-          gl2ps->streamlength +=
+          gl2ps->streamlength += 
             gl2psPrintf("%f %f l\n",
                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
         }
       }
       /* end last path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f l\n",
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f l\n", 
                     prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
       gl2ps->streamlength += gl2psPrintf("S\n");
       break;
     case GL2PS_TRIANGLE:
       gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
       gl2psSortOutTrianglePDFgroup(gro);
-
+      
       /* No alpha and const color: Simple PDF draw orders  */
-      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
-        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){         
+        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);        
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3700,17 +3694,17 @@
                            t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
         }
       }
-      /* Const alpha < 1 and const color: Simple PDF draw orders
+      /* Const alpha < 1 and const color: Simple PDF draw orders 
          and an extra extended Graphics State for the alpha const */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
+      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){               
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n",
                                            gro->gsno);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3721,19 +3715,19 @@
         }
         gl2ps->streamlength += gl2psPrintf("Q\n");
       }
-      /* Variable alpha and const color: Simple PDF draw orders
-         and an extra extended Graphics State + Xobject + Shader
+      /* Variable alpha and const color: Simple PDF draw orders 
+         and an extra extended Graphics State + Xobject + Shader 
          object for the alpha mask */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){          
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/TrG%d Do\n",
                                            gro->gsno, gro->trgroupno);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3746,23 +3740,23 @@
       }
       /* Variable color and no alpha: Shader Object for the colored
          triangle(s) */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){              
         gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
       }
-      /* Variable color and const alpha < 1: Shader Object for the
-         colored triangle(s) and an extra extended Graphics State
+      /* Variable color and const alpha < 1: Shader Object for the 
+         colored triangle(s) and an extra extended Graphics State 
          for the alpha const */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){         
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/Sh%d sh\n"
                                            "Q\n",
                                            gro->gsno, gro->shno);
       }
-      /* Variable alpha and color: Shader Object for the colored
-         triangle(s) and an extra extended Graphics State
+      /* Variable alpha and color: Shader Object for the colored 
+         triangle(s) and an extra extended Graphics State 
          + Xobject + Shader object for the alpha mask */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){            
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/TrG%d Do\n"
@@ -3774,12 +3768,12 @@
     case GL2PS_PIXMAP:
       for(j = 0; j <= lastel; ++j){
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
+        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0], 
                          prim->verts[0].xyz[1]);
       }
       break;
     case GL2PS_TEXT:
-      for(j = 0; j <= lastel; ++j){
+      for(j = 0; j <= lastel; ++j){  
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
         gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
@@ -3788,7 +3782,7 @@
       break;
     default:
       break;
-    }
+    } 
   }
 }
 
@@ -3801,15 +3795,15 @@
   int i;
 
   offs += fprintf(gl2ps->stream,
-                  "/ExtGState\n"
+                  "/ExtGState\n" 
                   "<<\n"
                   "/GSa 7 0 R\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->gsno >= 0)
       offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
   }
-  offs += fprintf(gl2ps->stream, ">>\n");
+  offs += fprintf(gl2ps->stream, ">>\n"); 
   return offs;
 }
 
@@ -3824,14 +3818,14 @@
   offs += fprintf(gl2ps->stream,
                   "/Shading\n"
                   "<<\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->shno >= 0)
       offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
     if(gro->maskshno >= 0)
       offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
   }
-  offs += fprintf(gl2ps->stream,">>\n");
+  offs += fprintf(gl2ps->stream,">>\n");  
   return offs;
 }
 
@@ -3848,8 +3842,8 @@
                   "/XObject\n"
                   "<<\n");
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(!gl2psListNbr(gro->ptrlist))
       continue;
     p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
@@ -3881,8 +3875,8 @@
 
   offs += fprintf(gl2ps->stream, "/Font\n<<\n");
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->fontno < 0)
       continue;
     gro->fontobjno = gl2ps->objects_stack++;
@@ -3897,11 +3891,11 @@
 {
   int i;
   GL2PSpdfgroup *gro = NULL;
-
+  
   if(!gl2ps->pdfgrouplist)
     return;
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ 
     gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
     gl2psListDelete(gro->ptrlist);
   }
@@ -3917,10 +3911,10 @@
   int offs;
   time_t now;
   struct tm *newtime;
-
+  
   time(&now);
   newtime = gmtime(&now);
-
+  
   offs = fprintf(gl2ps->stream,
                  "1 0 obj\n"
                  "<<\n"
@@ -3930,20 +3924,20 @@
                  gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
                  GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
                  gl2ps->producer);
-
+  
   if(!newtime){
-    offs += fprintf(gl2ps->stream,
+    offs += fprintf(gl2ps->stream, 
                     ">>\n"
                     "endobj\n");
     return offs;
   }
-
-  offs += fprintf(gl2ps->stream,
+  
+  offs += fprintf(gl2ps->stream, 
                   "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
                   ">>\n"
                   "endobj\n",
-                  newtime->tm_year+1900,
-                  newtime->tm_mon+1,
+                  newtime->tm_year+1900, 
+                  newtime->tm_mon+1, 
                   newtime->tm_mday,
                   newtime->tm_hour,
                   newtime->tm_min,
@@ -3955,7 +3949,7 @@
 
 static int gl2psPrintPDFCatalog(void)
 {
-  return fprintf(gl2ps->stream,
+  return fprintf(gl2ps->stream, 
                  "2 0 obj\n"
                  "<<\n"
                  "/Type /Catalog\n"
@@ -3966,9 +3960,9 @@
 
 static int gl2psPrintPDFPages(void)
 {
-  return fprintf(gl2ps->stream,
+  return fprintf(gl2ps->stream, 
                  "3 0 obj\n"
-                 "<<\n"
+                 "<<\n" 
                  "/Type /Pages\n"
                  "/Kids [6 0 R]\n"
                  "/Count 1\n"
@@ -3981,13 +3975,13 @@
 static int gl2psOpenPDFDataStream(void)
 {
   int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
+  
+  offs += fprintf(gl2ps->stream, 
                   "4 0 obj\n"
-                  "<<\n"
+                  "<<\n" 
                   "/Length 5 0 R\n" );
   offs += gl2psPrintPDFCompressorType();
-  offs += fprintf(gl2ps->stream,
+  offs += fprintf(gl2ps->stream, 
                   ">>\n"
                   "stream\n");
   return offs;
@@ -4000,13 +3994,13 @@
   int offs;
 
   offs = gl2psPrintf("/GSa gs\n");
-
+  
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
     offs += gl2psPrintf("%d %d %d %d re\n",
                         (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                         (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-    offs += gl2psPrintf("f\n");
+    offs += gl2psPrintf("f\n");  
   }
   return offs;
 }
@@ -4019,26 +4013,26 @@
   gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
   gl2psPDFstacksInit();
 
-  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
+  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack); 
 
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psSetupCompress();
   }
-#endif
+#endif    
   gl2ps->xreflist[0] = 0;
   offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
   gl2ps->xreflist[1] = offs;
-
+  
   offs += gl2psPrintPDFInfo();
   gl2ps->xreflist[2] = offs;
-
+  
   offs += gl2psPrintPDFCatalog();
   gl2ps->xreflist[3] = offs;
-
+  
   offs += gl2psPrintPDFPages();
   gl2ps->xreflist[4] = offs;
-
+  
   offs += gl2psOpenPDFDataStream();
   gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
   gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
@@ -4050,7 +4044,7 @@
 {
   GL2PSprimitive *prim = *(GL2PSprimitive**)data;
 
-  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) 
     return;
 
   prim = gl2psCopyPrimitive(prim); /* deep copy */
@@ -4062,7 +4056,7 @@
 static int gl2psClosePDFDataStream(void)
 {
   int offs = 0;
-
+ 
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     if(Z_OK != gl2psDeflate())
@@ -4070,13 +4064,13 @@
     else
       fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
     gl2ps->streamlength += gl2ps->compress->destLen;
-
+    
     offs += gl2ps->streamlength;
     gl2psFreeCompress();
   }
-#endif
-
-  offs += fprintf(gl2ps->stream,
+#endif 
+  
+  offs += fprintf(gl2ps->stream, 
                   "endstream\n"
                   "endobj\n");
   return offs;
@@ -4097,27 +4091,27 @@
 static int gl2psPrintPDFOpenPage(void)
 {
   int offs;
-
+  
   /* Write fixed part */
-
-  offs = fprintf(gl2ps->stream,
+  
+  offs = fprintf(gl2ps->stream, 
                  "6 0 obj\n"
-                 "<<\n"
+                 "<<\n" 
                  "/Type /Page\n"
                  "/Parent 3 0 R\n"
                  "/MediaBox [%d %d %d %d]\n",
                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
+  
   if(gl2ps->options & GL2PS_LANDSCAPE)
     offs += fprintf(gl2ps->stream, "/Rotate -90\n");
-
+  
   offs += fprintf(gl2ps->stream,
                   "/Contents 4 0 R\n"
-                  "/Resources\n"
-                  "<<\n"
+                  "/Resources\n" 
+                  "<<\n" 
                   "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
-
+  
   return offs;
 
   /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
@@ -4126,19 +4120,19 @@
 static int gl2psPDFgroupListWriteVariableResources(void)
 {
   int offs = 0;
-
+  
   /* a) Graphics States for shader alpha masks*/
-  offs += gl2psPDFgroupListWriteGStateResources();
-
-  /* b) Shader and shader masks */
-  offs += gl2psPDFgroupListWriteShaderResources();
-
+  offs += gl2psPDFgroupListWriteGStateResources();  
+  
+  /* b) Shader and shader masks */ 
+  offs += gl2psPDFgroupListWriteShaderResources();  
+ 
   /* c) XObjects (Images & Shader Masks) */
   offs += gl2psPDFgroupListWriteXObjectResources();
-
+  
   /* d) Fonts */
   offs += gl2psPDFgroupListWriteFontResources();
-
+  
   /* End resources and page */
   offs += fprintf(gl2ps->stream,
                   ">>\n"
@@ -4169,10 +4163,10 @@
 
 /* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
 
-static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
-                                                               size_t size),
-                                              GLfloat dx, GLfloat dy,
+static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
+                                                               size_t size), 
+                                              GLfloat dx, GLfloat dy, 
                                               GLfloat xmin, GLfloat ymin)
 {
   int offs = 0;
@@ -4188,7 +4182,7 @@
 
   /* The Shader stream in PDF requires to be in a 'big-endian'
      order */
-
+    
   if(GL2PS_ZERO(dx * dy)){
     offs += (*action)(0, 4);
     offs += (*action)(0, 4);
@@ -4201,7 +4195,7 @@
       diff = 0.0F;
     imap = (unsigned long)(diff * dmax);
     offs += (*action)(imap, 4);
-
+      
     diff = (vertex->xyz[1] - ymin) / dy;
     if(diff > 1)
       diff = 1.0F;
@@ -4210,14 +4204,14 @@
     imap = (unsigned long)(diff * dmax);
     offs += (*action)(imap, 4);
   }
-
+  
   return offs;
 }
 
 /* Put vertex' rgb value (8bit for every component) in shader stream */
 
 static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
-                                            size_t (*action)(unsigned long data,
+                                            size_t (*action)(unsigned long data, 
                                                              size_t size))
 {
   int offs = 0;
@@ -4229,20 +4223,20 @@
 
   imap = (unsigned long)((vertex->rgba[0]) * dmax);
   offs += (*action)(imap, 1);
-
+    
   imap = (unsigned long)((vertex->rgba[1]) * dmax);
   offs += (*action)(imap, 1);
-
+    
   imap = (unsigned long)((vertex->rgba[2]) * dmax);
   offs += (*action)(imap, 1);
-
+  
   return offs;
 }
 
 /* Put vertex' alpha (8/16bit) in shader stream */
 
-static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
+static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
                                                                size_t size),
                                               int sigbyte)
 {
@@ -4255,48 +4249,48 @@
 
   if(sigbyte != 8 && sigbyte != 16)
     sigbyte = 8;
-
+        
   sigbyte /= 8;
-
+  
   imap = (unsigned long)((vertex->rgba[3]) * dmax);
-
+  
   offs += (*action)(imap, sigbyte);
-
+  
   return offs;
 }
 
 /* Put a triangles raw data in shader stream */
 
-static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
-                                         GLfloat dx, GLfloat dy,
+static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle, 
+                                         GLfloat dx, GLfloat dy, 
                                          GLfloat xmin, GLfloat ymin,
-                                         size_t (*action)(unsigned long data,
+                                         size_t (*action)(unsigned long data, 
                                                           size_t size),
                                          int gray)
 {
   int i, offs = 0;
   GL2PSvertex v;
-
+  
   if(gray && gray != 8 && gray != 16)
     gray = 8;
-
+  
   for(i = 0; i < 3; ++i){
     offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
                                                dx, dy, xmin, ymin);
-    if(gray){
+    if(gray){ 
       v = triangle->vertex[i];
-      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
+      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray); 
     }
     else{
       offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
     }
   }
-
+  
   return offs;
 }
 
-static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
-                             GLfloat *ymin, GLfloat *ymax,
+static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax, 
+                             GLfloat *ymin, GLfloat *ymax, 
                              GL2PStriangle *triangles, int cnt)
 {
   int i, j;
@@ -4305,7 +4299,7 @@
   *xmax = triangles[0].vertex[0].xyz[0];
   *ymin = triangles[0].vertex[0].xyz[1];
   *ymax = triangles[0].vertex[0].xyz[1];
-
+  
   for(i = 0; i < cnt; ++i){
     for(j = 0; j < 3; ++j){
       if(*xmin > triangles[i].vertex[j].xyz[0])
@@ -4320,17 +4314,17 @@
   }
 }
 
-/* Writes shaded triangle
+/* Writes shaded triangle 
    gray == 0 means write RGB triangles
    gray == 8             8bit-grayscale (for alpha masks)
    gray == 16            16bit-grayscale (for alpha masks) */
 
-static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles,
+static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles, 
                                int size, int gray)
 {
   int i, offs = 0, vertexbytes, done = 0;
   GLfloat xmin, xmax, ymin, ymax;
-
+        
   switch(gray){
   case 0:
     vertexbytes = 1+4+4+1+1+1;
@@ -4346,9 +4340,9 @@
     vertexbytes = 1+4+4+1;
     break;
   }
-
+  
   gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<< "
@@ -4359,18 +4353,18 @@
                   "/BitsPerFlag 8 "
                   "/Decode [%f %f %f %f 0 1 %s] ",
                   obj,
-                  (gray) ? "/DeviceGray" : "/DeviceRGB",
+                  (gray) ? "/DeviceGray" : "/DeviceRGB", 
                   (gray) ? gray : 8,
                   xmin, xmax, ymin, ymax,
                   (gray) ? "" : "0 1 0 1");
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psAllocCompress(vertexbytes * size * 3);
 
     for(i = 0; i < size; ++i)
       gl2psPrintPDFShaderStreamData(&triangles[i],
-                                    xmax-xmin, ymax-ymin, xmin, ymin,
+                                    xmax-xmin, ymax-ymin, xmin, ymin, 
                                     gl2psWriteBigEndianCompress, gray);
 
     if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
@@ -4380,8 +4374,8 @@
                       ">>\n"
                       "stream\n",
                       (int)gl2ps->compress->destLen);
-      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
-                                                gl2ps->compress->destLen,
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, 
+                                                gl2ps->compress->destLen, 
                                                 1, gl2ps->stream);
       done = 1;
     }
@@ -4402,11 +4396,11 @@
                                             xmax-xmin, ymax-ymin, xmin, ymin,
                                             gl2psWriteBigEndian, gray);
   }
-
+  
   offs += fprintf(gl2ps->stream,
                   "\nendstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
@@ -4415,7 +4409,7 @@
 static int gl2psPrintPDFShaderMask(int obj, int childobj)
 {
   int offs = 0, len;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4427,11 +4421,11 @@
                   obj,
                   (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                   (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
-  len = (childobj>0)
+  
+  len = (childobj>0) 
     ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
-    : strlen("/TrSh0 sh\n");
-
+    : strlen("/TrSh0 sh\n"); 
+  
   offs += fprintf(gl2ps->stream,
                   "/Length %d\n"
                   ">>\n"
@@ -4443,7 +4437,7 @@
   offs += fprintf(gl2ps->stream,
                   "endstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
@@ -4454,16 +4448,16 @@
 static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n",
                   obj);
-
+  
   offs += fprintf(gl2ps->stream,
                   "/SMask << /S /Alpha /G %d 0 R >> ",
                   childobj);
-
+  
   offs += fprintf(gl2ps->stream,
                   ">>\n"
                   "endobj\n");
@@ -4475,7 +4469,7 @@
 static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4489,8 +4483,8 @@
 /* Similar groups of functions for pixmaps and text */
 
 static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
-                                         size_t (*action)(unsigned long data,
-                                                          size_t size),
+                                         size_t (*action)(unsigned long data, 
+                                                          size_t size), 
                                          int gray)
 {
   int x, y, shift;
@@ -4503,7 +4497,7 @@
     gray = 8;
 
   gray /= 8;
-
+  
   shift = (sizeof(unsigned long) - 1) * 8;
 
   for(y = 0; y < im->height; ++y){
@@ -4534,10 +4528,10 @@
 
   if(gray && gray !=8 && gray != 16)
     gray = 8;
-
+  
   if(gray)
-    sigbytes = gray / 8;
-
+    sigbytes = gray / 8; 
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4555,13 +4549,13 @@
                     "/SMask %d 0 R\n",
                     childobj);
   }
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psAllocCompress((int)(im->width * im->height * sigbytes));
-
+    
     gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
-
+    
     if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
       offs += gl2psPrintPDFCompressorType();
       offs += fprintf(gl2ps->stream,
@@ -4576,7 +4570,7 @@
     gl2psFreeCompress();
   }
 #endif
-
+  
   if(!done){
     /* no compression, or too long after compression, or compress error
        -> write non-compressed entry */
@@ -4587,18 +4581,18 @@
                     (int)(im->width * im->height * sigbytes));
     offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
   }
-
+  
   offs += fprintf(gl2ps->stream,
                   "\nendstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
 static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4626,9 +4620,9 @@
 
   if(!gl2ps->pdfgrouplist)
     return offs;
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(!gl2psListNbr(gro->ptrlist))
       continue;
     p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
@@ -4640,7 +4634,7 @@
     case GL2PS_TRIANGLE:
       size = gl2psListNbr(gro->ptrlist);
       triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
-      for(j = 0; j < size; ++j){
+      for(j = 0; j < size; ++j){  
         p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
       }
@@ -4682,7 +4676,7 @@
       break;
     default:
       break;
-    }
+    } 
   }
   return offs;
 }
@@ -4693,29 +4687,29 @@
 
 static void gl2psPrintPDFFooter(void)
 {
-  int i, offs;
+  int i, offs;  
 
   gl2psPDFgroupListInit();
   gl2psPDFgroupListWriteMainStream();
-
-  offs = gl2ps->xreflist[5] + gl2ps->streamlength;
+ 
+  offs = gl2ps->xreflist[5] + gl2ps->streamlength; 
   offs += gl2psClosePDFDataStream();
   gl2ps->xreflist[5] = offs;
-
+  
   offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
   gl2ps->xreflist[6] = offs;
   gl2ps->streamlength = 0;
-
+  
   offs += gl2psPrintPDFOpenPage();
   offs += gl2psPDFgroupListWriteVariableResources();
   gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
                                        sizeof(int) * (gl2ps->objects_stack + 1));
   gl2ps->xreflist[7] = offs;
-
+  
   offs += gl2psPrintPDFGSObject();
   gl2ps->xreflist[8] = offs;
-
-  gl2ps->xreflist[gl2ps->objects_stack] =
+  
+  gl2ps->xreflist[gl2ps->objects_stack] = 
     gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
 
   /* Start cross reference table. The file has to been opened in
@@ -4724,13 +4718,13 @@
           "xref\n"
           "0 %d\n"
           "%010d 65535 f \n", gl2ps->objects_stack, 0);
-
+  
   for(i = 1; i < gl2ps->objects_stack; ++i)
     fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
-
+  
   fprintf(gl2ps->stream,
           "trailer\n"
-          "<<\n"
+          "<<\n" 
           "/Size %d\n"
           "/Info 1 0 R\n"
           "/Root 2 0 R\n"
@@ -4738,13 +4732,13 @@
           "startxref\n%d\n"
           "%%%%EOF\n",
           gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
-
-  /* Free auxiliary lists and arrays */
+  
+  /* Free auxiliary lists and arrays */    
   gl2psFree(gl2ps->xreflist);
   gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive);
   gl2psListDelete(gl2ps->pdfprimlist);
   gl2psPDFgroupListDelete();
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psFreeCompress();
@@ -4762,16 +4756,16 @@
   GLint index;
   GLfloat rgba[4];
   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
+  
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintPDFHeader();
     gl2ps->header = GL_FALSE;
   }
 
   offs += gl2psPrintf("q\n");
-
+  
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
       glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
@@ -4791,18 +4785,18 @@
   }
   else{
     offs += gl2psPrintf("%d %d %d %d re\n"
-                        "W\n"
+                        "W\n"   
                         "n\n",
-                        x, y, w, h);
-  }
-
+                        x, y, w, h);            
+  }
+  
   gl2ps->streamlength += offs;
 }
 
 static GLint gl2psPrintPDFEndViewport(void)
 {
   GLint res;
-
+  
   res = gl2psPrintPrimitives();
   gl2ps->streamlength += gl2psPrintf("Q\n");
   return res;
@@ -4825,13 +4819,13 @@
   "Portable Document Format"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * SVG routines
  *
  *********************************************************************/
 
-static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts,
+static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts, 
                                        GL2PSxyz *xyz, GL2PSrgba *rgba)
 {
   int i, j;
@@ -4861,9 +4855,9 @@
   int x, y, width, height;
   char col[32];
   time_t now;
-
+  
   time(&now);
-
+  
   if (gl2ps->options & GL2PS_LANDSCAPE){
     x = (int)gl2ps->viewport[1];
     y = (int)gl2ps->viewport[0];
@@ -4876,10 +4870,10 @@
     width = (int)gl2ps->viewport[2];
     height = (int)gl2ps->viewport[3];
   }
-
+  
   /* Compressed SVG files (.svgz) are simply gzipped SVG files */
   gl2psPrintGzipHeader();
-
+  
   gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
   gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
   gl2psPrintf("     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
@@ -4899,9 +4893,9 @@
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     gl2psSVGGetColorString(gl2ps->bgcolor, col);
     gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
   }
 
@@ -4924,52 +4918,52 @@
     gl2psSVGGetColorString(rgba[0], col);
     gl2psPrintf("<polygon fill=\"%s\" ", col);
     if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
-    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
+    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1], 
                 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
   }
   else{
     /* subdivide into 4 subtriangles */
     for(i = 0; i < 3; i++){
-      xyz2[0][i] = xyz[0][i];
+      xyz2[0][i] = xyz[0][i]; 
       xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
-      rgba2[0][i] = rgba[0][i];
+      rgba2[0][i] = rgba[0][i]; 
       rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = xyz[1][i];
+      xyz2[1][i] = xyz[1][i]; 
       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = rgba[1][i];
+      rgba2[1][i] = rgba[1][i]; 
       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
-      xyz2[1][i] = xyz[2][i];
+      xyz2[1][i] = xyz[2][i]; 
       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
-      rgba2[1][i] = rgba[2][i];
+      rgba2[1][i] = rgba[2][i]; 
       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
+      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]); 
       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
+      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]); 
       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
@@ -4995,7 +4989,7 @@
 {
   int i;
   if(gl2ps->lastvertex.rgba[0] >= 0.){
-    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
+    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0], 
                 gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
     for(i = 0; i < 3; i++)
       gl2ps->lastvertex.xyz[i] = -1.;
@@ -5017,7 +5011,7 @@
      file), we need to encode the pixmap into PNG in memory, then
      encode it into base64. */
 
-  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
+  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000, 
                         sizeof(unsigned char));
   gl2psConvertPixmapToPNG(pixmap, png);
   gl2psListEncodeBase64(png);
@@ -5086,7 +5080,7 @@
     gl2ps->lastfactor = prim->factor;
     if(newline){
       gl2psSVGGetColorString(rgba[0], col);
-      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
+      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ", 
                   col, prim->width);
       if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
       gl2psPrintSVGDash(prim->pattern, prim->factor);
@@ -5112,42 +5106,6 @@
     if(prim->data.text->angle)
       gl2psPrintf("transform=\"rotate(%g, %g, %g)\" ",
                   -prim->data.text->angle, xyz[0][0], xyz[0][1]);
-    switch(prim->data.text->alignment){
-    case GL2PS_TEXT_C:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_B:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_BR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_T:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_BL:
-    default: /* same as GL2PS_TEXT_BL */
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"0\" ");
-      break;
-    }
     if(!strcmp(prim->data.text->fontname, "Times-Roman"))
       gl2psPrintf("font-family=\"Times\">");
     else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
@@ -5186,8 +5144,8 @@
 static void gl2psPrintSVGFooter(void)
 {
   gl2psPrintf("</g>\n");
-  gl2psPrintf("</svg>\n");
-
+  gl2psPrintf("</svg>\n");  
+  
   gl2psPrintGzipFooter();
 }
 
@@ -5199,7 +5157,7 @@
   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
 
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintSVGHeader();
     gl2ps->header = GL_FALSE;
@@ -5217,18 +5175,18 @@
       rgba[3] = 1.0F;
     }
     gl2psSVGGetColorString(rgba, col);
-    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                x, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - (y + h),
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col, 
+                x, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - (y + h), 
                 x, gl2ps->viewport[3] - (y + h));
   }
 
   gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
-  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
-              x, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - (y + h),
+  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", 
+              x, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - (y + h), 
               x, gl2ps->viewport[3] - (y + h));
   gl2psPrintf("</clipPath>\n");
   gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
@@ -5282,7 +5240,7 @@
 
   time(&now);
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "%% Title: %s\n"
           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
           "%% For: %s\n"
@@ -5336,7 +5294,7 @@
   case GL2PS_TEXT_T  : return "north";
   case GL2PS_TEXT_TL : return "north west";
   case GL2PS_TEXT_TR : return "north east";
-  case GL2PS_TEXT_BL :
+  case GL2PS_TEXT_BL : 
   default            : return "south west";
   }
 }
@@ -5351,7 +5309,7 @@
   case GL2PS_POINT :
     /* Points in openGL are rectangular */
     gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
             "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
             prim->verts[0].xyz[0]-0.5*prim->width,
@@ -5365,7 +5323,7 @@
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
     }
     gl2psPrintPGFDash(prim->pattern, prim->factor);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgfusepath{stroke}\n",
@@ -5378,7 +5336,7 @@
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
     }
     gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
@@ -5447,14 +5405,14 @@
       rgba[3] = 1.0F;
     }
     gl2psPrintPGFColor(rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
             "{\\pgfpoint{%dpt}{%dpt}}\n"
             "\\pgfusepath{fill}\n",
             x, y, w, h);
   }
-
-  fprintf(gl2ps->stream,
+  
+  fprintf(gl2ps->stream, 
           "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
           "{\\pgfpoint{%dpt}{%dpt}}\n"
           "\\pgfusepath{clip}\n",
@@ -5486,7 +5444,7 @@
   "PGF Latex Graphics"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * General primitive printing routine
  *
@@ -5521,7 +5479,7 @@
     if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
       gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
   }
-}
+}  
 
 static GLint gl2psPrintPrimitives(void)
 {
@@ -5542,7 +5500,7 @@
   gl2psRescaleAndOffset();
 
   if(gl2ps->header){
-    if(gl2psListNbr(gl2ps->primitives) &&
+    if(gl2psListNbr(gl2ps->primitives) && 
        (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
       gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
       gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
@@ -5584,7 +5542,7 @@
                            gl2psAddInImageTree, 1);
       gl2psFreeBspImageTree(&gl2ps->imagetree);
     }
-    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater,
+    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater, 
                          gl2psbackends[gl2ps->format]->printPrimitive, 0);
     gl2psFreeBspTree(&root);
     /* reallocate the primitive list (it's been deleted by
@@ -5597,13 +5555,13 @@
   return GL2PS_SUCCESS;
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Public routines
  *
  *********************************************************************/
 
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
                                   GLint viewport[4], GLint format, GLint sort,
                                   GLint options, GLint colormode,
                                   GLint colorsize, GL2PSrgba *colormap,
@@ -5671,7 +5629,7 @@
 
   if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
     gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
-             gl2ps->viewport[0], gl2ps->viewport[1],
+             gl2ps->viewport[0], gl2ps->viewport[1], 
              gl2ps->viewport[2], gl2ps->viewport[3]);
     gl2psFree(gl2ps);
     gl2ps = NULL;
@@ -5695,11 +5653,11 @@
   gl2ps->lastfactor = 0;
   gl2ps->imagetree = NULL;
   gl2ps->primitivetoadd = NULL;
-  gl2ps->zerosurfacearea = GL_FALSE;
+  gl2ps->zerosurfacearea = GL_FALSE;  
   gl2ps->pdfprimlist = NULL;
   gl2ps->pdfgrouplist = NULL;
   gl2ps->xreflist = NULL;
-
+  
   /* get default blending mode from current OpenGL state (enabled by
      default for SVG) */
   gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
@@ -5742,7 +5700,7 @@
     gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
     strcpy(gl2ps->title, title);
   }
-
+    
   if(!producer){
     gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
     gl2ps->producer[0] = '\0';
@@ -5751,7 +5709,7 @@
     gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
     strcpy(gl2ps->producer, producer);
   }
-
+  
   if(!filename){
     gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
     gl2ps->filename[0] = '\0';
@@ -5765,7 +5723,7 @@
   gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
   gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
   glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
-  glRenderMode(GL_FEEDBACK);
+  glRenderMode(GL_FEEDBACK);  
 
   return GL2PS_SUCCESS;
 }
@@ -5780,7 +5738,7 @@
 
   if(res != GL2PS_OVERFLOW)
     (gl2psbackends[gl2ps->format]->printFooter)();
-
+  
   fflush(gl2ps->stream);
 
   gl2psListDelete(gl2ps->primitives);
@@ -5802,7 +5760,7 @@
   if(!gl2ps) return GL2PS_UNINITIALIZED;
 
   (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
-
+  
   return GL2PS_SUCCESS;
 }
 
@@ -5820,7 +5778,7 @@
   return res;
 }
 
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
                                 GLshort fontsize, GLint alignment, GLfloat angle)
 {
   return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
@@ -5838,11 +5796,11 @@
 
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
                                    GLint xorig, GLint yorig,
-                                   GLenum format, GLenum type,
+                                   GLenum format, GLenum type, 
                                    const void *pixels)
 {
   int size, i;
-  GLfloat pos[4], *piv, zoom_x, zoom_y;
+  GLfloat pos[4], *piv;
   GL2PSprimitive *prim;
   GLboolean valid;
 
@@ -5862,8 +5820,6 @@
   if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
 
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  glGetFloatv(GL_ZOOM_X, &zoom_x);
-  glGetFloatv(GL_ZOOM_Y, &zoom_y);
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
   prim->type = GL2PS_PIXMAP;
@@ -5882,8 +5838,6 @@
   prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
   prim->data.image->width = width;
   prim->data.image->height = height;
-  prim->data.image->zoom_x = zoom_x;
-  prim->data.image->zoom_y = zoom_y;
   prim->data.image->format = format;
   prim->data.image->type = type;
 
@@ -5897,9 +5851,9 @@
       piv = (GLfloat*)pixels;
       for(i = 0; i < size; ++i, ++piv){
         prim->data.image->pixels[i] = *piv;
-        if(!((i + 1) % 3))
+        if(!((i+1)%3))
           ++piv;
-      }
+      }   
     }
     else{
       size = height * width * 4;
@@ -5926,11 +5880,11 @@
                                      const unsigned char *imagemap){
   int size, i;
   int sizeoffloat = sizeof(GLfloat);
-
+  
   if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
 
   if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
-
+  
   size = height + height * ((width - 1) / 8);
   glPassThrough(GL2PS_IMAGEMAP_TOKEN);
   glBegin(GL_POINTS);
@@ -6010,7 +5964,7 @@
 
   glPassThrough(GL2PS_POINT_SIZE_TOKEN);
   glPassThrough(value);
-
+  
   return GL2PS_SUCCESS;
 }
 
--- a/src/gl2ps.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/gl2ps.h	Fri Aug 26 13:40:10 2011 -0500
@@ -139,9 +139,9 @@
 #define GL2PS_BLEND               4
 
 /* Text alignment (o=raster position; default mode is BL):
-   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
-   | o | o   | |   o |   | |   | |   | |   | |   | |   |
-   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+
+   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o 
+   | o | o   | |   o |   | |   | |   | |   | |   | |   | 
+   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+ 
     C     CL    CR    B     BL    BR    T     TL    TR */
 
 #define GL2PS_TEXT_C  1
@@ -160,10 +160,10 @@
 extern "C" {
 #endif
 
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
                                   GLint viewport[4], GLint format, GLint sort,
                                   GLint options, GLint colormode,
-                                  GLint colorsize, GL2PSrgba *colormap,
+                                  GLint colorsize, GL2PSrgba *colormap, 
                                   GLint nr, GLint ng, GLint nb, GLint buffersize,
                                   FILE *stream, const char *filename);
 GL2PSDLL_API GLint gl2psEndPage(void);
@@ -171,9 +171,9 @@
 GL2PSDLL_API GLint gl2psGetOptions(GLint *options);
 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
 GL2PSDLL_API GLint gl2psEndViewport(void);
-GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, 
                              GLshort fontsize);
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
                                 GLshort fontsize, GLint align, GLfloat angle);
 GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
--- a/src/graphics.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/graphics.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -4341,7 +4341,7 @@
   text::properties& xlabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_xlabel ()).get_properties ());
 
-  bool is_empty = xlabel_props.get_string ().empty ();
+  bool is_empty = xlabel_props.get_string ().is_empty ();
 
   unwind_protect frame;
   frame.protect_var (updating_xlabel_position);
@@ -4432,7 +4432,7 @@
   text::properties& ylabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_ylabel ()).get_properties ());
 
-  bool is_empty = ylabel_props.get_string ().empty ();
+  bool is_empty = ylabel_props.get_string ().is_empty ();
 
   unwind_protect frame;
   frame.protect_var (updating_ylabel_position);
@@ -4524,7 +4524,7 @@
     (gh_manager::get_object (get_zlabel ()).get_properties ());
 
   bool camAuto = cameraupvectormode_is ("auto");
-  bool is_empty = zlabel_props.get_string ().empty ();
+  bool is_empty = zlabel_props.get_string ().is_empty ();
 
   unwind_protect frame;
   frame.protect_var (updating_zlabel_position);
@@ -4896,7 +4896,7 @@
 
           Matrix text_pos = text_props.get_position ().matrix_value ();
           text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
-          if (text_props.get_string ().empty ())
+          if (text_props.get_string ().is_empty ())
             {
               ext(0) = std::min (ext(0), text_pos(0));
               ext(1) = std::min (ext(1), text_pos(1));
@@ -6006,6 +6006,7 @@
 text::properties::update_text_extent (void)
 {
 #ifdef HAVE_FREETYPE
+
   int halign = 0, valign = 0;
 
   if (horizontalalignment_is ("center"))
@@ -6021,11 +6022,17 @@
     valign = 1;
 
   Matrix bbox;
+
   // FIXME: string should be parsed only when modified, for efficiency
-  renderer.text_to_pixels (get_string (), pixels, bbox,
+
+  octave_value string_prop = get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  renderer.text_to_pixels (sv.join ("\n"), pixels, bbox,
                            halign, valign, get_rotation ());
-
   set_extent (bbox);
+
 #endif
 
   if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel") ||
--- a/src/graphics.h.in	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/graphics.h.in	Fri Aug 26 13:40:10 2011 -0500
@@ -33,6 +33,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <sstream>
 #include <string>
 
 #include "caseless-str.h"
@@ -692,6 +693,178 @@
 
 // ---------------------------------------------------------------------
 
+class text_label_property : public base_property
+{
+public:
+  enum type { char_t, cellstr_t };
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const std::string& val = "")
+    : base_property (s, h), value (val), stored_type (char_t)
+  { }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const NDArray& nda)
+    : base_property (s, h), stored_type (char_t)
+  {
+    octave_idx_type nel = nda.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        std::ostringstream buf;
+        buf << nda(i);
+        value[i] = buf.str ();
+      }
+  }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const Cell& c)
+    : base_property (s, h), stored_type (cellstr_t)
+  {
+    octave_idx_type nel = c.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        octave_value tmp = c(i);
+
+        if (tmp.is_string ())
+          value[i] = c(i).string_value ();
+        else
+          {
+            double d = c(i).double_value ();
+
+            if (! error_state)
+              {
+                std::ostringstream buf;
+                buf << d;
+                value[i] = buf.str ();
+              }
+            else
+              break;
+          }
+      }
+  }
+
+  text_label_property (const text_label_property& p)
+    : base_property (p), value (p.value), stored_type (p.stored_type)
+  { }
+
+  bool empty (void) const
+  {
+    octave_value tmp = get ();
+    return tmp.is_empty ();
+  }
+
+  octave_value get (void) const
+  {
+    if (stored_type == char_t)
+      return octave_value (char_value ());
+    else
+      return octave_value (cell_value ());
+  }
+
+  std::string string_value (void) const
+  {
+    return value.empty () ? std::string () : value[0];
+  }
+
+  string_vector string_vector_value (void) const { return value; }
+
+  charMatrix char_value (void) const { return charMatrix (value, ' '); }
+
+  Cell cell_value (void) const {return Cell (value); }
+
+  text_label_property& operator = (const octave_value& val)
+  {
+    set (val);
+    return *this;
+  }
+
+  base_property* clone (void) const { return new text_label_property (*this); }
+
+protected:
+
+  bool do_set (const octave_value& val)
+  {
+    if (val.is_string ())
+      {
+        value = val.all_strings ();
+
+        stored_type = char_t;
+      }
+    else if (val.is_cell ())
+      {
+        Cell c = val.cell_value ();
+
+        octave_idx_type nel = c.numel ();
+
+        value.resize (nel);
+
+        for (octave_idx_type i = 0; i < nel; i++)
+          {
+            octave_value tmp = c(i);
+
+            if (tmp.is_string ())
+              value[i] = c(i).string_value ();
+            else
+              {
+                double d = c(i).double_value ();
+
+                if (! error_state)
+                  {
+                    std::ostringstream buf;
+                    buf << d;
+                    value[i] = buf.str ();
+                  }
+                else
+                  return false;
+              }
+          }
+
+        stored_type = cellstr_t;
+      }
+    else
+      {
+        NDArray nda = val.array_value ();
+
+        if (! error_state)
+          {
+            octave_idx_type nel = nda.numel ();
+
+            value.resize (nel);
+
+            for (octave_idx_type i = 0; i < nel; i++)
+              {
+                std::ostringstream buf;
+                buf << nda(i);
+                value[i] = buf.str ();
+              }
+
+            stored_type = char_t;
+          }
+        else
+          {
+            error ("set: invalid string property value for \"%s\"",
+                   get_name ().c_str ());
+
+            return false;
+          }
+      }
+
+    return true;
+  }
+
+private:
+  string_vector value;
+  type stored_type;
+};
+
+// ---------------------------------------------------------------------
+
 class radio_values
 {
 public:
@@ -3686,7 +3859,7 @@
     // properties declarations.
 
     BEGIN_PROPERTIES (text)
-      string_property string u , ""
+      text_label_property string u , ""
       radio_property units u , "{data}|pixels|normalized|inches|centimeters|points"
       array_property position mu , Matrix (1, 3, 0.0)
       double_property rotation mu , 0
--- a/src/input.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/input.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -428,7 +428,7 @@
   FILE *instream = 0;
 
   if (name.length () > 0)
-    instream = fopen (name.c_str (), "rb");
+    instream = gnulib::fopen (name.c_str (), "rb");
 
   if (! instream && warn)
     warning ("%s: no such file or directory", name.c_str ());
@@ -951,14 +951,11 @@
 
   unwind_protect frame;
 
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries (false);
 
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  frame.protect_var (Vsaving_history);
   frame.protect_var (Vdebugging);
 
   frame.add_fcn (octave_call_stack::restore_frame,
@@ -970,7 +967,6 @@
   // tree_print_code tpc (octave_stdout);
   // stmt.accept (tpc);
 
-  Vsaving_history = true;
   Vdebugging = true;
 
   std::string prompt = "debug> ";
--- a/src/oct-hist.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/oct-hist.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -88,9 +88,6 @@
   return file;
 }
 
-// Where history is saved.
-static std::string Vhistory_file = default_history_file ();
-
 static int
 default_history_size (void)
 {
@@ -109,27 +106,6 @@
   return size;
 }
 
-// The number of lines to keep in the history file.
-static int Vhistory_size = default_history_size ();
-
-static std::string
-default_history_control (void)
-{
-  std::string retval;
-
-  std::string env_histcontrol = octave_env::getenv ("OCTAVE_HISTCONTROL");
-
-  if (! env_histcontrol.empty ())
-    {
-      return env_histcontrol;
-    }
-
-  return retval;
-}
-
-// The number of lines to keep in the history file.
-static std::string Vhistory_control = default_history_control ();
-
 static std::string
 default_history_timestamp_format (void)
 {
@@ -146,9 +122,6 @@
 static std::string Vhistory_timestamp_format_string
   = default_history_timestamp_format ();
 
-// TRUE if we are saving history.
-bool Vsaving_history = true;
-
 // Display, save, or load history.  Stolen and modified from bash.
 //
 // Arg of -w FILENAME means write file, arg of -r FILENAME
@@ -160,6 +133,10 @@
 {
   int numbered_output = 1;
 
+  unwind_protect frame;
+
+  frame.add_fcn (command_history::set_file, command_history::file ());
+
   int i;
   for (i = 1; i < argc; i++)
     {
@@ -537,8 +514,10 @@
 void
 initialize_history (bool read_history_file)
 {
-  command_history::initialize (read_history_file, Vhistory_file, Vhistory_size,
-                               Vhistory_control);
+  command_history::initialize (read_history_file,
+                               default_history_file (),
+                               default_history_size (),
+                               octave_env::getenv ("OCTAVE_HISTCONTROL"));
 }
 
 void
@@ -691,12 +670,15 @@
 @seealso{history_file, history_size, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  std::string saved_history_control = Vhistory_control;
+  std::string old_history_control = command_history::histcontrol ();
+
+  std::string tmp = old_history_control;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_control);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_control");
 
-  if (Vhistory_control != saved_history_control)
-    command_history::process_histcontrol (Vhistory_control);
+  if (tmp != old_history_control)
+    command_history::process_histcontrol (tmp);
 
   return retval;
 }
@@ -711,13 +693,15 @@
 @seealso{history_file, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  int saved_history_size = Vhistory_size;
+  int old_history_size = command_history::size ();
+
+  int tmp = old_history_size;
 
-  octave_value retval
-    = SET_INTERNAL_VARIABLE_WITH_LIMITS (history_size, -1, INT_MAX);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_size", -1, INT_MAX);
 
-  if (Vhistory_size != saved_history_size)
-    command_history::set_size (Vhistory_size);
+  if (tmp != old_history_size)
+    command_history::set_size (tmp);
 
   return retval;
 }
@@ -733,12 +717,15 @@
 @seealso{history_size, saving_history, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  std::string saved_history_file = Vhistory_file;
+  std::string old_history_file = command_history::file ();
+
+  std::string tmp = old_history_file;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_file);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_file");
 
-  if (Vhistory_file != saved_history_file)
-    command_history::set_file (Vhistory_file);
+  if (tmp != old_history_file)
+    command_history::set_file (tmp);
 
   return retval;
 }
@@ -770,9 +757,15 @@
 @seealso{history_control, history_file, history_size, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  octave_value retval = SET_INTERNAL_VARIABLE (saving_history);
+  bool old_saving_history = ! command_history::ignoring_entries ();
+
+  bool tmp = old_saving_history;
 
-  command_history::ignore_entries (! Vsaving_history);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "saving_history");
+
+  if (tmp != old_saving_history)
+    command_history::ignore_entries (! tmp);
 
   return retval;
 }
--- a/src/oct-hist.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/oct-hist.h	Fri Aug 26 13:40:10 2011 -0500
@@ -35,7 +35,4 @@
 // TRUE means input is coming from temporary history file.
 extern bool input_from_tmp_history_file;
 
-// TRUE if we are saving history.
-extern bool Vsaving_history;
-
 #endif
--- a/src/oct-parse.yy	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/oct-parse.yy	Fri Aug 26 13:40:10 2011 -0500
@@ -3471,18 +3471,11 @@
   parsing_subfunctions = false;
   endfunction_found = false;
 
-  // The next four lines must be in this order.
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries ();
 
-  frame.protect_var (Vsaving_history);
-
-  Vsaving_history = false;
-
   FILE *ffile = get_input_from_file (ff, 0);
 
   frame.add_fcn (safe_fclose, ffile);
@@ -4215,12 +4208,26 @@
 @noindent\n\
 calls the function @code{acos} with the argument @samp{-1}.\n\
 \n\
-The function @code{feval} is necessary in order to be able to write\n\
-functions that call user-supplied functions, because Octave does not\n\
-have a way to declare a pointer to a function (like C) or to declare a\n\
-special kind of variable that can be used to hold the name of a function\n\
-(like @code{EXTERNAL} in Fortran).  Instead, you must refer to functions\n\
-by name, and use @code{feval} to call them.\n\
+The function @code{feval} can also be used with function handles of\n\
+any sort (@pxref{Function Handles}).  Historically, @code{feval} was\n\
+the only way to call user-supplied functions in strings, but\n\
+function handles are now preferred due to the cleaner syntax they\n\
+offer.  For example,\n\
+\n\
+@example\n\
+@group\n\
+@var{f} = @@exp;\n\
+feval (@var{f}, 1)\n\
+     @result{} 2.7183\n\
+@var{f} (1)\n\
+     @result{} 2.7183\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+are equivalent ways to call the function referred to by @var{f}.  If it\n\
+cannot be predicted beforehand that @var{f} is a function handle or the\n\
+function name in a string, @code{feval} can be used instead.\n\
 @end deftypefn")
 {
   octave_value_list retval;
--- a/src/oct-stream.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/oct-stream.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -1379,7 +1379,9 @@
     tmp[n++] = static_cast<char> (c); \
  \
   if (n > 0 && c == EOF) \
-    is.clear ()
+    is.clear (); \
+ \
+  tmp.resize (n)
 
 // For a `%s' format, skip initial whitespace and then read until the
 // next whitespace character or until WIDTH characters have been read.
@@ -2860,38 +2862,60 @@
     {
       clearerr ();
 
+      // Find current position so we can return to it if needed.
+
       long orig_pos = rep->tell ();
 
-      status = rep->seek (offset, origin);
+      // Move to end of file.  If successful, find the offset of the end.
+
+      status = rep->seek (0, SEEK_END);
 
       if (status == 0)
         {
-          long save_pos = rep->tell ();
-
-          rep->seek (0, SEEK_END);
-
-          long pos_eof = rep->tell ();
-
-          // I don't think save_pos can be less than zero, but we'll
-          // check anyway...
-
-          if (save_pos > pos_eof || save_pos < 0)
+          long eof_pos = rep->tell ();
+
+          if (origin == SEEK_CUR)
+            {
+              // Move back to original position, otherwise we will be
+              // seeking from the end of file which is probably not the
+              // original location.
+
+              rep->seek (orig_pos, SEEK_SET);
+            }
+
+          // Attempt to move to desired position; may be outside bounds
+          // of existing file.
+
+          status = rep->seek (offset, origin);
+
+          if (status == 0)
             {
-              // Seek outside bounds of file.  Failure should leave
-              // position unchanged.
+              // Where are we after moving to desired position?
+
+              long desired_pos = rep->tell ();
+
+              // I don't think save_pos can be less than zero, but we'll
+              // check anyway...
+
+              if (desired_pos > eof_pos || desired_pos < 0)
+                {
+                  // Seek outside bounds of file.  Failure should leave
+                  // position unchanged.
+
+                  rep->seek (orig_pos, SEEK_SET);
+
+                  status = -1;
+                }
+            }
+          else
+            {
+              // Seeking to the desired position failed.  Move back to
+              // original position and return failure status.
 
               rep->seek (orig_pos, SEEK_SET);
 
               status = -1;
             }
-          else
-            {
-              // Is it possible for this to fail?  We are just
-              // returning to a position after the first successful
-              // seek.
-
-              rep->seek (save_pos, SEEK_SET);
-            }
         }
     }
 
--- a/src/ov-builtin.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/ov-builtin.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -126,7 +126,7 @@
 
       try
         {
-          profile_data_accumulator::enter pe (profiler, profiler_name ());
+          BEGIN_PROFILER_BLOCK (profiler_name ())
 
           retval = (*f) (args, nargout);
           // Do not allow null values to be returned from functions.
@@ -140,6 +140,8 @@
           // the idiom is very common, so we solve that here.
           if (retval.length () == 1 && retval.xelem (0).is_undefined ())
             retval.clear ();
+
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-mex-fcn.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/ov-mex-fcn.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -148,8 +148,9 @@
 
       try
         {
-          profile_data_accumulator::enter pe (profiler, profiler_name ());
+          BEGIN_PROFILER_BLOCK (profiler_name ())
           retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this);
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-usr-fcn.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/ov-usr-fcn.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -134,11 +134,9 @@
                   frame.protect_var (tree_evaluator::statement_context);
                   tree_evaluator::statement_context = tree_evaluator::script;
 
-                  {
-                    profile_data_accumulator::enter pe (profiler,
-                                                        profiler_name ());
-                    cmd_list->accept (*current_evaluator);
-                  }
+                  BEGIN_PROFILER_BLOCK (profiler_name ())
+                  cmd_list->accept (*current_evaluator);
+                  END_PROFILER_BLOCK
 
                   if (tree_return_command::returning)
                     tree_return_command::returning = 0;
@@ -455,26 +453,26 @@
   bool special_expr = (is_inline_function ()
                        || cmd_list->is_anon_function_body ());
 
-  {
-    profile_data_accumulator::enter pe (profiler, profiler_name ());
+  BEGIN_PROFILER_BLOCK (profiler_name ())
 
-    if (special_expr)
-      {
-        assert (cmd_list->length () == 1);
+  if (special_expr)
+    {
+      assert (cmd_list->length () == 1);
 
-        tree_statement *stmt = 0;
+      tree_statement *stmt = 0;
 
-        if ((stmt = cmd_list->front ())
-            && stmt->is_expression ())
-          {
-            tree_expression *expr = stmt->expression ();
+      if ((stmt = cmd_list->front ())
+          && stmt->is_expression ())
+        {
+          tree_expression *expr = stmt->expression ();
 
-            retval = expr->rvalue (nargout);
-          }
-      }
-    else
-      cmd_list->accept (*current_evaluator);
-  }
+          retval = expr->rvalue (nargout);
+        }
+    }
+  else
+    cmd_list->accept (*current_evaluator);
+
+  END_PROFILER_BLOCK
 
   if (echo_commands)
     print_code_function_trailer ();
--- a/src/profiler.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/profiler.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -24,6 +24,7 @@
 #include <config.h>
 #endif
 
+#include <cstddef>
 #include <iostream>
 
 #include "defun.h"
@@ -56,11 +57,8 @@
     parents (), children ()
 {}
 
-// With the help of a mapping name -> index, convert a function_set list
-// to an Octave array of indices.
 octave_value
-profile_data_accumulator::stats::function_set_value (const function_set& list,
-                                                     const fcn_index_map& idx)
+profile_data_accumulator::stats::function_set_value (const function_set& list)
 {
   const octave_idx_type n = list.size ();
 
@@ -68,9 +66,7 @@
   octave_idx_type i = 0;
   for (function_set::const_iterator p = list.begin (); p != list.end (); ++p)
     {
-      fcn_index_map::const_iterator q = idx.find (*p);
-      assert (q != idx.end ());
-      retval (i) = q->second;
+      retval(i) = *p;
       ++i;
     }
   assert (i == n);
@@ -78,19 +74,144 @@
   return retval;
 }
 
+profile_data_accumulator::tree_node::tree_node (tree_node* p, octave_idx_type f)
+  : parent (p), fcn_id (f), children (), time (0.0), calls (0)
+{}
+
+profile_data_accumulator::tree_node::~tree_node ()
+{
+  for (child_map::iterator i = children.begin (); i != children.end (); ++i)
+    delete i->second;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::enter (octave_idx_type fcn)
+{
+  tree_node* retval;
+
+  child_map::iterator pos = children.find (fcn);
+  if (pos == children.end ())
+    {
+      retval = new tree_node (this, fcn);
+      children[fcn] = retval;
+    }
+  else
+    retval = pos->second;
+
+  ++retval->calls;
+  return retval;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::exit (octave_idx_type fcn)
+{
+  assert (parent);
+  assert (fcn_id == fcn);
+
+  return parent;
+}
+
+void
+profile_data_accumulator::tree_node::build_flat (flat_profile& data) const
+{
+  // If this is not the top-level node, update profile entry for this function.
+  if (fcn_id != 0)
+    {
+      stats& entry = data[fcn_id - 1];
+      
+      entry.time += time;
+      entry.calls += calls;
+
+      assert (parent);
+      if (parent->fcn_id != 0)
+        {
+          entry.parents.insert (parent->fcn_id);
+          data[parent->fcn_id - 1].children.insert (fcn_id);
+        }
+
+      if (!entry.recursive)
+        for (const tree_node* i = parent; i; i = i->parent)
+          if (i->fcn_id == fcn_id)
+            {
+              entry.recursive = true;
+              break;
+            }
+    }
+
+  // Recurse on children.
+  for (child_map::const_iterator i = children.begin ();
+       i != children.end (); ++i)
+    i->second->build_flat (data);
+}
+
+octave_value
+profile_data_accumulator::tree_node::get_hierarchical (void) const
+{
+  /* Note that we don't generate the entry just for this node, but rather
+     a struct-array with entries for all children.  This way, the top-node
+     (for which we don't want a real entry) generates already the final
+     hierarchical profile data.  */
+
+  const octave_idx_type n = children.size ();
+
+  Cell rv_indices (n, 1);
+  Cell rv_times (n, 1);
+  Cell rv_calls (n, 1);
+  Cell rv_children (n, 1);
+
+  octave_idx_type i = 0;
+  for (child_map::const_iterator p = children.begin ();
+       p != children.end (); ++p)
+    {
+      const tree_node& entry = *p->second;
+
+      rv_indices(i) = octave_value (p->first);
+      rv_times(i) = octave_value (entry.time);
+      rv_calls(i) = octave_value (entry.calls);
+      rv_children(i) = entry.get_hierarchical ();
+
+      ++i;
+    }
+  assert (i == n);
+
+  Octave_map retval;
+
+  retval.assign ("Index", rv_indices);
+  retval.assign ("SelfTime", rv_times);
+  retval.assign ("NumCalls", rv_calls);
+  retval.assign ("Children", rv_children);
+
+  return retval;
+}
+
 profile_data_accumulator::profile_data_accumulator ()
-  : enabled (false), call_stack (), data (), last_time (-1.0)
+  : known_functions (), fcn_index (),
+    enabled (false), call_tree (NULL), last_time (-1.0)
 {}
 
+profile_data_accumulator::~profile_data_accumulator ()
+{
+  if (call_tree)
+    delete call_tree;
+}
+
 void
 profile_data_accumulator::set_active (bool value)
 {
-  // If we enable, clear the call-stack.  This ensures we freshly start
-  // with collecting times now.
   if (value)
     {
-      while (!call_stack.empty ())
-        call_stack.pop_back ();
+      // Create a call-tree top-node if there isn't yet one.
+      if (!call_tree)
+        call_tree = new tree_node (NULL, 0);
+
+      // Let the top-node be the active one.  This ensures we have a clean
+      // fresh start collecting times.
+      active_fcn = call_tree;
+    }
+  else
+    {
+      // Make sure we start with fresh timing if we're re-enabled later.
+      last_time = -1.0;
     }
 
   enabled = value;
@@ -101,39 +222,34 @@
 {
   // The enter class will check and only call us if the profiler is active.
   assert (is_active ());
+  assert (call_tree);
 
   // If there is already an active function, add to its time before
   // pushing the new one.
-  if (!call_stack.empty ())
+  if (active_fcn != call_tree)
     add_current_time ();
 
-  // Update non-timing related data for the function entered.
-  stats& entry = data[fcn];
-  ++entry.calls;
-  if (!call_stack.empty ())
+  // Map the function's name to its index.
+  octave_idx_type fcn_idx;
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  if (pos == fcn_index.end ())
     {
-      const std::string parent_name = call_stack.back ();
-      entry.parents.insert (parent_name);
-      data[parent_name].children.insert (fcn);
+      known_functions.push_back (fcn);
+      fcn_idx = known_functions.size ();
+      fcn_index[fcn] = fcn_idx;
     }
-  if (!entry.recursive)
-    for (call_stack_type::iterator i = call_stack.begin ();
-         i != call_stack.end (); ++i)
-      if (*i == fcn)
-        {
-          entry.recursive = true;
-          break;
-        }
+  else
+    fcn_idx = pos->second;
 
-  call_stack.push_back (fcn);
+  active_fcn = active_fcn->enter (fcn_idx);
   last_time = query_time ();
 }
 
 void
 profile_data_accumulator::exit_function (const std::string& fcn)
 {
-  assert (!call_stack.empty ());
-  assert (fcn == call_stack.back ());
+  assert (call_tree);
+  assert (active_fcn != call_tree);
 
   // Usually, if we are disabled this function is not even called.  But the
   // call disabling the profiler is an exception.  So also check here
@@ -141,7 +257,9 @@
   if (is_active ())
     add_current_time ();
 
-  call_stack.pop_back ();
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  assert (pos != fcn_index.end ());
+  active_fcn = active_fcn->exit (pos->second);
 
   // If this was an "inner call", we resume executing the parent function
   // up the stack.  So note the start-time for this!
@@ -157,26 +275,26 @@
       return;
     }
 
-  data.clear ();
+  known_functions.clear ();
+  fcn_index.clear ();
+
+  if (call_tree)
+    {
+      delete call_tree;
+      call_tree = NULL;
+    }
+
   last_time = -1.0;
 }
 
 octave_value
-profile_data_accumulator::get_data (void) const
+profile_data_accumulator::get_flat (void) const
 {
-  const octave_idx_type n = data.size ();
+  const octave_idx_type n = known_functions.size ();
 
-  // For the parent/child data, we need to map function key-names
-  // to the indices they correspond to in the output array.  Find them out
-  // in a preparation step.
-  fcn_index_map fcn_indices;
-  octave_idx_type i = 0;
-  for (stats_map::const_iterator p = data.begin (); p != data.end (); ++p)
-    {
-      fcn_indices[p->first] = i + 1;
-      ++i;
-    }
-  assert (i == n);
+  flat_profile flat (n);
+  assert (call_tree);
+  call_tree->build_flat (flat);
 
   Cell rv_names (n, 1);
   Cell rv_times (n, 1);
@@ -185,21 +303,15 @@
   Cell rv_parents (n, 1);
   Cell rv_children (n, 1);
 
-  i = 0;
-  for (stats_map::const_iterator p = data.begin (); p != data.end (); ++p)
+  for (octave_idx_type i = 0; i != n; ++i)
     {
-      const stats& entry = p->second;
-
-      rv_names (i) = octave_value (p->first);
-      rv_times (i) = octave_value (entry.time);
-      rv_calls (i) = octave_value (entry.calls);
-      rv_recursive (i) = octave_value (entry.recursive);
-      rv_parents (i) = stats::function_set_value (entry.parents, fcn_indices);
-      rv_children (i) = stats::function_set_value (entry.children, fcn_indices);
-
-      ++i;
+      rv_names(i) = octave_value (known_functions[i]);
+      rv_times(i) = octave_value (flat[i].time);
+      rv_calls(i) = octave_value (flat[i].calls);
+      rv_recursive(i) = octave_value (flat[i].recursive);
+      rv_parents(i) = stats::function_set_value (flat[i].parents);
+      rv_children(i) = stats::function_set_value (flat[i].children);
     }
-  assert (i == n);
 
   Octave_map retval;
 
@@ -213,6 +325,13 @@
   return retval;
 }
 
+octave_value
+profile_data_accumulator::get_hierarchical (void) const
+{
+  assert (call_tree);
+  return call_tree->get_hierarchical ();
+}
+
 double
 profile_data_accumulator::query_time (void) const
 {
@@ -226,20 +345,14 @@
   const double t = query_time ();
   assert (last_time >= 0.0 && last_time <= t);
 
-  assert (!call_stack.empty ());
-  const std::string name = call_stack.back ();
-
-  // The entry for this function should already be created; namely
-  // when entering the function via the non-timing data collection!
-  stats_map::iterator pos = data.find (name);
-  assert (pos != data.end ());
-  pos->second.time += t - last_time;
+  assert (call_tree && active_fcn != call_tree);
+  active_fcn->add_time (t - last_time);
 }
 
 profile_data_accumulator profiler;
 
 // Enable or disable the profiler data collection.
-DEFUN (__profiler_enable, args, ,
+DEFUN (__profiler_enable__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Function File} __profiler_enable ()\n\
 Undocumented internal function.\n\
@@ -265,7 +378,7 @@
 }
 
 // Clear all collected profiling data.
-DEFUN (__profiler_reset, args, ,
+DEFUN (__profiler_reset__, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Function File} __profiler_reset ()\n\
 Undocumented internal function.\n\
@@ -283,7 +396,7 @@
 }
 
 // Query the timings collected by the profiler.
-DEFUN (__profiler_data, args, ,
+DEFUN (__profiler_data__, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Function File} __profiler_data ()\n\
 Undocumented internal function.\n\
@@ -295,7 +408,9 @@
   if (nargin > 0)
     warning ("profiler_data: ignoring extra arguments");
 
-  retval(0) = profiler.get_data ();
+  retval(0) = profiler.get_flat ();
+  if (nargout > 1)
+    retval(1) = profiler.get_hierarchical ();
 
   return retval;
 }
--- a/src/profiler.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/profiler.h	Fri Aug 26 13:40:10 2011 -0500
@@ -40,72 +40,113 @@
   // functions in a manner protected from stack unwinding.
   class enter
   {
-    private:
-
-      profile_data_accumulator& acc;
+  private:
 
-      std::string fcn;
+    profile_data_accumulator& acc;
+    std::string fcn;
 
-    public:
-
-      enter (profile_data_accumulator&, const std::string&);
+  public:
 
-      virtual ~enter (void);
-
-    private:
+    enter (profile_data_accumulator&, const std::string&);
+    virtual ~enter (void);
 
-      // No copying!
+  private:
 
-      enter (const enter&);
-
-      enter& operator = (const enter&);
+    // No copying!
+    enter (const enter&);
+    enter& operator = (const enter&);
   };
 
   profile_data_accumulator (void);
+  virtual ~profile_data_accumulator ();
 
   bool is_active (void) const { return enabled; }
-
   void set_active (bool);
 
   void reset (void);
 
-  octave_value get_data (void) const;
+  octave_value get_flat (void) const;
+  octave_value get_hierarchical (void) const;
 
 private:
 
-  typedef std::set<std::string> function_set;
+  // One entry in the flat profile (i.e., a collection of data for a single
+  // function).  This is filled in when building the flat profile from the
+  // hierarchical call tree.
+  struct stats
+  {
+    stats ();
+
+    double time;
+    unsigned calls;
+
+    bool recursive;
+
+    typedef std::set<octave_idx_type> function_set;
+    function_set parents;
+    function_set children;
+
+    // Convert a function_set list to an Octave array of indices.
+    static octave_value function_set_value (const function_set&);
+  };
+
+  typedef std::vector<stats> flat_profile;
+  
+  // Store data for one node in the call-tree of the hierarchical profiler
+  // data we collect.
+  class tree_node
+  {
+  public:
+
+    tree_node (tree_node*, octave_idx_type);
+    virtual ~tree_node ();
+
+    void add_time (double dt) { time += dt; }
+
+    // Enter a child function.  It is created in the list of children if it
+    // wasn't already there.  The now-active child node is returned.
+    tree_node* enter (octave_idx_type);
+
+    // Exit function.  As a sanity-check, it is verified that the currently
+    // active function actually is the one handed in here.  Returned is the
+    // then-active node, which is our parent.
+    tree_node* exit (octave_idx_type);
+
+    void build_flat (flat_profile&) const;
+    octave_value get_hierarchical (void) const;
+
+  private:
+
+    tree_node* parent;
+    octave_idx_type fcn_id;
+
+    typedef std::map<octave_idx_type, tree_node*> child_map;
+    child_map children;
+
+    // This is only time spent *directly* on this level, excluding children!
+    double time;
+
+    unsigned calls;
+
+    // No copying!
+    tree_node (const tree_node&);
+    tree_node& operator = (const tree_node&);
+  };
+
+  // Each function we see in the profiler is given a unique index (which
+  // simply counts starting from 1).  We thus have to map profiler-names to
+  // those indices.  For all other stuff, we identify functions by their index.
+
+  typedef std::vector<std::string> function_set;
   typedef std::map<std::string, octave_idx_type> fcn_index_map;
 
-  // Store some statistics data collected for a function.
-  class stats
-  {
-    private:
-
-      double time;
-      unsigned calls;
-
-      bool recursive;
-
-      function_set parents;
-      function_set children;
-
-    public:
-
-      stats ();
-
-      static octave_value
-      function_set_value (const function_set&, const fcn_index_map&);
-
-      friend class profile_data_accumulator;
-  };
+  function_set known_functions;
+  fcn_index_map fcn_index;
 
   bool enabled;
 
-  typedef std::vector<std::string> call_stack_type;
-  call_stack_type call_stack;
-
-  typedef std::map<std::string, stats> stats_map;
-  stats_map data;
+  tree_node* call_tree;
+  tree_node* active_fcn;
 
   // Store last timestamp we had, when the currently active function was called.
   double last_time;
@@ -117,23 +158,28 @@
 
   // Query a timestamp, used for timing calls (obviously).
   // This is not static because in the future, maybe we want a flag
-  // in the profiler or something to choose between cputime, wall-time
+  // in the profiler or something to choose between cputime, wall-time,
   // user-time, system-time, ...
   double query_time () const;
 
-  // Add the time elapsed since last_time to the function on the top
-  // of our call-stack.  This is called from two different positions,
-  // thus it is useful to have it as a seperate function.
+  // Add the time elapsed since last_time to the function we're currently in.
+  // This is called from two different positions, thus it is useful to have
+  // it as a seperate function.
   void add_current_time (void);
 
   // No copying!
-
   profile_data_accumulator (const profile_data_accumulator&);
-
   profile_data_accumulator& operator = (const profile_data_accumulator&);
 };
 
 // The instance used.
 extern profile_data_accumulator profiler;
 
+// Helper macro to profile a block of code.
+#define BEGIN_PROFILER_BLOCK(name) \
+  { \
+    profile_data_accumulator::enter pe (profiler, (name));
+#define END_PROFILER_BLOCK \
+  }
+
 #endif
--- a/src/pt-binop.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/pt-binop.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -121,8 +121,7 @@
 
           if (! error_state && b.is_defined ())
             {
-              profile_data_accumulator::enter pe (profiler,
-                                                  "binary " + oper ());
+              BEGIN_PROFILER_BLOCK ("binary " + oper ())
 
               // Note: The profiler does not catch the braindead
               // short-circuit evaluation code above, but that should be
@@ -134,6 +133,8 @@
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
--- a/src/pt-unop.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/pt-unop.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -73,13 +73,14 @@
 
           if (! error_state)
             {
-              profile_data_accumulator::enter pe (profiler,
-                                                  "prefix " + oper ());
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
               
               ref.do_unary_op (etype);
 
               if (! error_state)
                 retval = ref.value ();
+
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -88,8 +89,7 @@
 
           if (! error_state && val.is_defined ())
             {
-              profile_data_accumulator::enter pe (profiler,
-                                                  "prefix " + oper ());
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
 
               // Attempt to do the operation in-place if it is unshared
               // (a temporary expression).
@@ -100,6 +100,8 @@
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
@@ -160,10 +162,9 @@
             {
               retval = ref.value ();
 
-              profile_data_accumulator::enter pe (profiler,
-                                                  "postfix " + oper ());
-
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
               ref.do_unary_op (etype);
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -172,13 +173,14 @@
 
           if (! error_state && val.is_defined ())
             {
-              profile_data_accumulator::enter pe (profiler,
-                                                  "postfix " + oper ());
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
 
               retval = ::do_unary_op (etype, val);
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
--- a/src/toplev.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/toplev.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -39,6 +39,7 @@
 #include <unistd.h>
 
 #include "cmd-edit.h"
+#include "cmd-hist.h"
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-mappers.h"
@@ -1053,7 +1054,7 @@
 
       SAFE_CALL (octave_history_write_timestamp, ())
 
-      if (Vsaving_history)
+      if (! command_history::ignoring_entries ())
         SAFE_CALL (command_history::clean_up_and_save, ())
 
       SAFE_CALL (close_files, ())
--- a/src/txt-eng-ft.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/txt-eng-ft.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -202,7 +202,8 @@
 
 ft_render::ft_render (void)
     : text_processor (), face (0), bbox (1, 4, 0.0),
-      xoffset (0), yoffset (0), mode (MODE_BBOX),
+      xoffset (0), yoffset (0), multiline_halign (0), 
+      multiline_align_xoffsets(), mode (MODE_BBOX),
       red (0), green (0), blue (0)
 {
 }
@@ -270,15 +271,23 @@
 {
   if (face)
     {
+      int line_index = 0;
+      FT_UInt box_line_width = 0;
       std::string str = e.string_value ();
       FT_UInt glyph_index, previous = 0;
 
+      if (mode == MODE_BBOX)
+        multiline_align_xoffsets.clear();
+      else if (mode == MODE_RENDER)
+        xoffset += multiline_align_xoffsets[line_index];
+
       for (size_t i = 0; i < str.length (); i++)
         {
           glyph_index = FT_Get_Char_Index (face, str[i]);
 
-          if (! glyph_index
-              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+          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]);
           else
@@ -286,7 +295,21 @@
               switch (mode)
                 {
                 case MODE_RENDER:
-                  if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                  if (str[i] == '\n')
+                    {
+                    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 ` '");
+                      } 
+                    else 
+                      {
+                        line_index++;
+                        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]);
                   else
@@ -304,6 +327,14 @@
 
                       x0 = xoffset+face->glyph->bitmap_left;
                       y0 = yoffset+face->glyph->bitmap_top;
+
+                      // 'w' seems to have a negative -1
+                      // face->glyph->bitmap_left, this is so we don't
+                      // index out of bound, and assumes we we allocated
+                      // the right amount of horizontal space in the bbox.
+                      if (x0 < 0)
+                        x0 = 0;
+
                       for (int r = 0; r < bitmap.rows; r++)
                         for (int c = 0; c < bitmap.width; c++)
                           {
@@ -327,43 +358,89 @@
                   break;
 
                 case MODE_BBOX:
-                  // width
-                  if (previous)
+                  if (str[i] == '\n')
                     {
-                      FT_Vector delta;
-
-                      FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-                      bbox(2) += (delta.x >> 6);
-                    }
-                  bbox(2) += (face->glyph->advance.x >> 6);
-
-                  int asc, desc;
-
-                  if (false /*tight*/)
+                      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 ` '");
+                      }
+                    else
+                      {
+                        multiline_align_xoffsets.push_back(box_line_width);
+                        // Reset the pixel width for this newline, so we don't
+                        // allocate a bounding box larger than the horizontal
+                        // width of the multi-line
+                        box_line_width = 0; 
+                        bbox(1) -= (face->size->metrics.height >> 6);
+                      }
+                    } 
+                  else 
                     {
-                      desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
-                      asc = face->glyph->metrics.horiBearingY;
-                    }
-                  else
-                    {
-                      asc = face->size->metrics.ascender;
-                      desc = face->size->metrics.descender;
-                    }
+                    // width
+                    if (previous)
+                      {
+                        FT_Vector delta;
+
+                        FT_Get_Kerning (face, previous, glyph_index,
+                                        FT_KERNING_DEFAULT, &delta);
+
+                        box_line_width += (delta.x >> 6);
+                      }
+
+                    box_line_width += (face->glyph->advance.x >> 6);
+
+                    int asc, desc;
 
-                  asc = yoffset + (asc >> 6);
-                  desc = yoffset + (desc >> 6);
+                    if (false /*tight*/)
+                      {
+                        desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
+                        asc = face->glyph->metrics.horiBearingY;
+                      }
+                    else
+                      {
+                        asc = face->size->metrics.ascender;
+                        desc = face->size->metrics.descender;
+                      }
 
-                  if (desc < bbox(1))
-                    {
-                      bbox(3) += (bbox(1) - desc);
-                      bbox(1) = desc;
-                    }
-                  if (asc > (bbox(3)+bbox(1)))
-                    bbox(3) = asc-bbox(1);
+                    asc = yoffset + (asc >> 6);
+                    desc = yoffset + (desc >> 6);
+
+                    if (desc < bbox(1))
+                      {
+                        bbox(3) += (bbox(1) - desc);
+                        bbox(1) = desc;
+                      }
+                    if (asc > (bbox(3)+bbox(1)))
+                      bbox(3) = asc-bbox(1);
+                    if (bbox(2) < box_line_width)
+                      bbox(2) = box_line_width;
+                  }
                   break;
                 }
+                if (str[i] == '\n')
+                  previous = 0;
+                else
+                  previous = glyph_index;
+            }
+        }
+      if (mode == MODE_BBOX)
+        {
+          /* Push last the width associated with the last line */ 
+          multiline_align_xoffsets.push_back(box_line_width);
 
-              previous = glyph_index;
+          for (unsigned int i = 0; i < multiline_align_xoffsets.size(); i++)
+            {
+            /* Center align */
+            if (multiline_halign == 1) 
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i])/2;
+            /* Right align */
+            else if (multiline_halign == 2)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i]);
+            /* Left align */
+            else 
+              multiline_align_xoffsets[i] = 0;
             }
         }
     }
@@ -506,6 +583,8 @@
 {
   // FIXME: clip "rotation" between 0 and 360
   int rot_mode = rotation_to_mode (rotation);
+  
+  multiline_halign = halign;
 
   text_element *elt = text_parser_none ().parse (txt);
   pixels_ = render (elt, box, rot_mode);
--- a/src/txt-eng-ft.h	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/txt-eng-ft.h	Fri Aug 26 13:40:10 2011 -0500
@@ -25,6 +25,8 @@
 
 #if HAVE_FREETYPE
 
+#include <vector>
+
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
@@ -94,6 +96,8 @@
   uint8NDArray pixels;
   int xoffset;
   int yoffset;
+  int multiline_halign;
+  std::vector<int> multiline_align_xoffsets;
   int mode;
   uint8_t red, green, blue;
 };
--- a/src/xdiv.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/xdiv.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -64,14 +64,14 @@
 
 template <class T1, class T2>
 bool
-mx_leftdiv_conform (const T1& a, const T2& b)
+mx_leftdiv_conform (const T1& a, const T2& b, blas_trans_type blas_trans)
 {
-  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nr = blas_trans == blas_no_trans ? a.rows () : a.cols ();
   octave_idx_type b_nr = b.rows ();
 
   if (a_nr != b_nr)
     {
-      octave_idx_type a_nc = a.cols ();
+      octave_idx_type a_nc = blas_trans == blas_no_trans ? a.cols () : a.rows ();
       octave_idx_type b_nc = b.cols ();
 
       gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
@@ -82,7 +82,7 @@
 }
 
 #define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
-  template bool mx_leftdiv_conform (const T1&, const T2&)
+  template bool mx_leftdiv_conform (const T1&, const T2&, blas_trans_type)
 
 INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, Matrix);
 INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, ComplexMatrix);
@@ -352,7 +352,7 @@
 Matrix
 xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return Matrix ();
 
   octave_idx_type info;
@@ -364,7 +364,7 @@
 ComplexMatrix
 xleftdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return ComplexMatrix ();
 
   octave_idx_type info;
@@ -377,7 +377,7 @@
 ComplexMatrix
 xleftdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return ComplexMatrix ();
 
   octave_idx_type info;
@@ -389,7 +389,7 @@
 ComplexMatrix
 xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return ComplexMatrix ();
 
   octave_idx_type info;
@@ -650,7 +650,7 @@
 FloatMatrix
 xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return FloatMatrix ();
 
   octave_idx_type info;
@@ -662,7 +662,7 @@
 FloatComplexMatrix
 xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return FloatComplexMatrix ();
 
   octave_idx_type info;
@@ -675,7 +675,7 @@
 FloatComplexMatrix
 xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return FloatComplexMatrix ();
 
   octave_idx_type info;
@@ -687,7 +687,7 @@
 FloatComplexMatrix
 xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
 {
-  if (! mx_leftdiv_conform (a, b))
+  if (! mx_leftdiv_conform (a, b, transt))
     return FloatComplexMatrix ();
 
   octave_idx_type info;
@@ -782,7 +782,7 @@
 MT
 dmm_leftdiv_impl (const DMT& d, const MT& a)
 {
-  if (! mx_leftdiv_conform (d, a))
+  if (! mx_leftdiv_conform (d, a, blas_no_trans))
     return MT ();
 
   octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length ();
@@ -931,7 +931,7 @@
 MT
 dmdm_leftdiv_impl (const DMT& d, const MT& a)
 {
-  if (! mx_leftdiv_conform (d, a))
+  if (! mx_leftdiv_conform (d, a, blas_no_trans))
     return MT ();
 
   octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
--- a/src/xpow.cc	Thu Aug 25 20:12:31 2011 +0200
+++ b/src/xpow.cc	Fri Aug 26 13:40:10 2011 -0500
@@ -49,6 +49,8 @@
 #include "utils.h"
 #include "xpow.h"
 
+#include "bsxfun.h"
+
 #ifdef _OPENMP
 #include <omp.h>
 #endif
@@ -1243,8 +1245,21 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          //Potentially complex results
+          NDArray xa = octave_value_extract<NDArray> (a);
+          NDArray xb = octave_value_extract<NDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   int len = a.length ();
@@ -1318,8 +1333,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1410,8 +1432,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1453,8 +1482,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
--- a/test/test_io.m	Thu Aug 25 20:12:31 2011 +0200
+++ b/test/test_io.m	Fri Aug 26 13:40:10 2011 -0500
@@ -242,6 +242,30 @@
 %% test/octave.test/io/puts-4.m
 %!error <Invalid call to puts.*> puts (1, 2);
 
+%!assert (sscanf ('123456', '%10c'), '123456')
+%!assert (sscanf ('123456', '%10s'), '123456')
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3I2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3In2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3Inf2", "%f");
+%! assert (val, [3; Inf; 2]);
+%! assert (count, 3);
+%! assert (msg, "");
+%! assert (pos, 6);
+
 %% test/octave.test/io/sscanf-1.m
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");