[gimp-perl] Add podregister, some doc tidy-up



commit 202c80cdc44de251869e8de12ebe4acc6175b6f1
Author: Ed J <m8r-35s8eo mailinator com>
Date:   Mon Apr 21 20:59:51 2014 +0100

    Add podregister, some doc tidy-up

 Gimp.pm                    |  689 ++++++++++++++++++++++++++++----------------
 Gimp/Config.pm.in          |    2 +-
 Gimp/Data.pm               |   14 +-
 Gimp/Fu.pm                 |  442 ++++++++++++++++------------
 Gimp/OO.pod                |  191 ------------
 Gimp/PixelRgn.pod          |    4 +-
 Gimp/Util.pm               |    2 +-
 MANIFEST                   |    1 -
 Net/Net.pm                 |    2 +-
 TODO                       |    3 +-
 examples/billboard         |  327 ++++++++++-----------
 examples/dots              |  161 +++++------
 examples/dust              |   54 +++--
 examples/example-fu        |  142 +++++-----
 examples/exceptiontest     |    2 +-
 examples/fade-alpha        |  408 +++++++--------------------
 examples/layerfuncs        |    4 +-
 examples/redeye            |    7 +-
 examples/selective_sharpen |  107 ++++---
 examples/xachshadow        |   41 ++--
 t/netplugin.t              |    2 +-
 21 files changed, 1229 insertions(+), 1376 deletions(-)
---
diff --git a/Gimp.pm b/Gimp.pm
index 1862796..9b00daf 100644
--- a/Gimp.pm
+++ b/Gimp.pm
@@ -335,13 +335,15 @@ sub AUTOLOAD {
 
 sub _pseudoclass {
   my ($class, @prefixes)= @_;
-  unshift(@prefixes,"");
+  unshift @prefixes,"";
   *{"Gimp::$class\::AUTOLOAD"} = \&AUTOLOAD;
-  push(@{"Gimp::$class\::PREFIXES"}    , @prefixes); @prefixes= {"Gimp::$class\::PREFIXES"};
+  push @{"Gimp::$class\::PREFIXES"}, @prefixes;
+  push @{"Gimp::$class\::ISA"}, 'Gimp::Base';
   push @POLLUTE_CLASSES, $class;
+  @{"Gimp::$class\::PREFIXES"}; # to suppress only-once warning
 }
 
-my @plugin_prefixes = qw(plug_in_ perl_fu_);
+my @plugin_prefixes = qw(plug_in_ perl_fu_ script_fu_);
 my @image_prefixes = (qw(gimp_image_ gimp_), @plugin_prefixes);
 my @item_prefixes = (qw(gimp_item_), @image_prefixes);
 my @drawable_prefixes = (qw(gimp_drawable_), @item_prefixes);
@@ -359,7 +361,7 @@ _pseudoclass qw(Gradient    gimp_gradient_);
 _pseudoclass qw(Gradients      gimp_gradients_);
 _pseudoclass qw(Edit           gimp_edit_);
 _pseudoclass qw(Progress       gimp_progress_);
-_pseudoclass qw(GimpParasite   );
+_pseudoclass qw(Parasite       );
 
 push @Gimp::Drawable::ISA, qw(Gimp::Item);
 push @Gimp::Vectors::ISA, qw(Gimp::Item);
@@ -391,7 +393,6 @@ sub new($$$$$$$$) {
 
 {
 package Gimp::Parasite;
-
 sub is_type($$)                { $_[0]->[0] eq $_[1] }
 sub is_persistent($)   { $_[0]->[1] & &Gimp::PARASITE_PERSISTENT }
 sub is_error($)                { !defined $_[0]->[0] }
@@ -406,154 +407,213 @@ sub compare($$)         { $_[0]->[0] eq $_[1]->[0] and
 sub new($$$$)          { shift; [ _] }
 }
 
+{
+package Gimp::Base;
+use overload '""' => sub { ref($_[0]).'->existing('.${$_[0]}.')'; };
+sub existing($$)       { bless \$_[1], $_[0]; }
+sub become($$)         { bless $_[0], $_[1]; }
+}
+
 1;
 __END__
 =head1 NAME
 
-Gimp - a Perl extension for writing Gimp Extensions/Plug-ins/Load &
-Save-Handlers
-
-This is a release of gimp-perl for gimp-2.8.  It is not compatible with
-version 2.6 or below of GIMP.
-
-This is mostly a reference manual. For a quick intro, look at
-L<Gimp::Fu>.
+Gimp - write GIMP extensions/plug-ins/load- and save-handlers in Perl
 
 =head1 SYNOPSIS
 
   use Gimp;
   use Gimp::Fu;                # easy scripting environment
 
-=head2 IMPORT TAGS
+  podregister {
+    # your code
+    return Gimp::Image->new(100, 100, RGB);
+  };
 
-Place these in your C<use Gimp qw(...)> command to have added features
-available to your plug-in.
+  exit main;
+  __END__
+  =head1 NAME
 
-=over 2
+  function_name - Short description of the function
 
-=item :auto
+  =head1 SYNOPSIS
 
-Import useful constants, like RGB, RUN_NONINTERACTIVE... as well as all
-libgimp and pdb functions automagically into the caller's namespace.
-This will overwrite your AUTOLOAD function, if you have one. The AUTOLOAD
-function that gets installed must only be used in OO mode - either as
-an object or a class method call - the only exception is when the first
-argument is a reference (including objects):
+  <Image>/Filters/Menu/Location...
 
- use Gimp qw(:auto);
- Gimp->displays_flush; # fine
- my $name = $layer->get_name; # also fine
- gimp_quit(0); # will lose its parameter, due to Perl's OO implementation!
- Gimp->quit(0); # works correctly
- gimp_image_undo_disable($image); # as does this, by a coincidence
+  =head1 DESCRIPTION
 
-=item :param
+  Longer description of the function...
 
-Import constants for plugin parameter types (PDB_INT32, PDB_STRING
-etc.) only.
+=head1 DESCRIPTION
 
-=item :consts
+Gimp-Perl is a module for writing plug-ins, extensions, standalone
+scripts, and file-handlers for the GNU Image Manipulation Program (GIMP).
+It can be used to automate repetitive tasks, achieve a precision hard
+to get through manual use of GIMP, interface to a web server, or other
+tasks that involve GIMP.
 
-All constants found by querying GIMP (BG_IMAGE_FILL, RUN_NONINTERACTIVE,
-NORMAL_MODE, PDB_INT32 etc.).
+It is developed on Linux, and should work with similar OSes.
+This is a release of Gimp-Perl for gimp-2.8. It is not compatible with
+version 2.6 or below of GIMP.
 
-=item :pollute
+To jump straight into how to write GIMP plugins, see L<Gimp::Fu>:
+it is recommended for scripts not requiring custom interfaces
+or specialized execution. If you B<do> need a custom interface, see
+C<examples/example-no-fu> - although L<Gimp::Fu> does also offer custom
+widgets, see the same script using Gimp::Fu in C<examples/fade-alpha>.
+Lots of other examples are in the C<examples/> directory of your gimp-perl
+source tree, some of which will be installed in your plug-ins directory
+if you are running from a package.
 
-In previous version of C<gimp-perl>, you could refer to GIMP classes
-as either e.g. Gimp::Image, OR Image. Now in order to not pollute the
-namespace, the second option will be available only when this option
-is specified.
+Using the C<Help/Procedure Browser> is a good way to learn GIMP's
+Procedural Database (PDB). For referencing functions you already know of,
+the included script L<gimpdoc> is useful.
 
-=item spawn_options=I<options>
+Some highlights:
 
-Set default spawn options to I<options>, see L<Gimp::Net>.
+=over 4
 
-=item :DEFAULT
+=item *
+
+Access to GIMP's Procedural Database (PDB) for manipulation of
+most objects.
+
+=item *
+
+Program with either a fully object-oriented syntax, or a (deprecated)
+plain PDB (scheme-like) interface.
+
+=item *
 
-The default set (see below).
+Scripts that use Gimp::Fu can be accessed seamlessly either from
+GIMP's menus, other scripting interfaces like Script-Fu, or from the
+command line (execute the plugin with the C<--help> flag for more
+information).
+
+In the latter case, Gimp::Fu can either connect to a GIMP already running,
+or start up its own.
+
+=item *
+
+Access the pixel-data functions using L<PDL> (see L<Gimp::PixelRgn>)
+giving the same level of control as a C plug-in, with a data language
+wrapper.
+
+=item *
+
+Over 50 example scripts to give you a good starting point, or use out
+of the box.
 
 =back
 
-The default (unless '' is specified) is C<':consts', 'N_', '__'>.
-(C<'__'> is used for i18n purposes).
+=head1 IMPORT TAGS
 
-=head1 GETTING STARTED
+Place these in your C<use Gimp qw(...)> command to have added features
+available to your plug-in.
 
-L<Gimp::Fu> is recommended for scripts not requiring custom interfaces
-or specialized execution.  Lots of examples are in the C<examples/>
-directory of your gimp-perl source tree, or installed in your plug-ins
-directory if you are running from a package.
+=over 4
 
-Using the C<Help/Procedure Browser> is a good way to learn GIMP's
-Procedural Database(pdb).  For referencing functions you already know of,
-the included script L<gimpdoc> is useful.
+=item :consts
 
-=head1 DESCRIPTION
+All constants found by querying GIMP (BG_IMAGE_FILL, RUN_NONINTERACTIVE,
+NORMAL_MODE, PDB_INT32 etc.).
 
-Gimp-Perl is a module for writing plug-ins, extensions, standalone
-scripts, and file-handlers for The GNU Image Manipulation Program (The
-GIMP).  It can be used to automate repetitive tasks, achieve a precision
-hard to get through manual use of GIMP, interface to a web server,
-or other tasks that involve Gimp.
+=item :param
 
-It is developed on Linux, and should work with similar OSes.
+Import constants for plugin parameter types (PDB_INT32, PDB_STRING
+etc.) only.
 
-Some highlights:
+=item net_init=I<options>
 
-=over 2
+This is how to use Gimp-Perl in "net mode". Previous versions of this
+package required a call to Gimp::init. This is no longer necessary. The
+technical reason for this change is that when C<Gimp.pm> loads, it must
+connect to GIMP to load its constants, like C<PDB_INT32>.
 
-=item *
-Access to GIMP's Procedural Database (pdb) for manipulation of
-most objects.
+Possible options include C<spawn/gui> or C<unix/path/to/socket>. See
+L<Gimp::Net/ENVIRONMENT> for other possibilities. If this is not
+specified, C<Gimp> will try various options, falling back to C<spawn>
+which starts a new GIMP instance.
 
-=item *
-Use either a plain pdb (scheme-like but with perl OO
-class method) interface or a fully object-oriented syntax,
-i.e. C<Gimp-E<gt>image_new(600,300,RGB)> is the same as C<new
-Gimp::Image(600,300,RGB)>.
+It is important that C<Gimp> be able to connect to an instance of GIMP
+one way or another: otherwise, it will not be able to load the various
+constants on which modules rely. The connection is made when
+C<Gimp::import> is called, after C<Gimp> has been compiled - so don't
+put C<use Gimp ();>
 
-=item *
-Networked plug-ins look/behave the same as those running from within gimp.
+=item spawn_options=I<options>
 
-=item *
-Gimp::Fu will start GIMP for you, if it cannot connect to an existing
-GIMP process.
+Set default spawn options to I<options>, see L<Gimp::Net>.
 
-=item *
-You can access the pixel-data functions using piddles (see
-L<Gimp::PixelRgn>) giving the same level of control as a C plug-in,
-with a data language wrapper.
+=item :DEFAULT
 
-=item *
-Over 50 example scripts to give you a good starting point, or use as is.
+The default set: C<':consts', 'N_', '__'>. (C<'__'> is used for i18n
+purposes).
+
+=item ''
+
+Over-ride (don't import) the defaults.
+
+=item :auto (DEPRECATED)
+
+Import constants as above, as well as all libgimp and PDB functions
+automagically into the caller's namespace.  This will overwrite your
+AUTOLOAD function, if you have one. The AUTOLOAD function that gets
+installed can only be used with PDB functions whose first argument is
+a reference (including objects):
+
+ use Gimp qw(:auto);
+ Gimp->displays_flush; # fine
+ my $name = $layer->get_name; # also fine
+ gimp_quit(0); # will lose its parameter, due to Perl's OO implementation!
+ Gimp->quit(0); # works correctly
+ gimp_image_undo_disable($image); # as does this, by a coincidence
+
+This tag is deprecated, and you will be far better off using Gimp-Perl
+solely in OO mode.
+
+=item :pollute (DEPRECATED)
+
+In previous version of C<gimp-perl>, you could refer to GIMP classes
+as either e.g. Gimp::Image, B<and> as Image. Now in order to not pollute
+the namespace, the second option will be available only when this option
+is specified.
 
 =back
 
 =head1 ARCHITECTURE
 
 There are two modes of operation: the perl is called by GIMP (as a
-plugin/filter) ("plugin mode"), or GIMP is called by perl (which uses the
+plugin/filter) ("B<plugin mode>"), or GIMP is called by perl (which uses the
 Gimp::Net functionality) - either connecting to an existing GIMP process
-("net mode"), or starting its own one ("batch mode").
+("B<net mode>"), or starting its own one ("B<batch mode>").
 
 =head2 Plugin
 
-The perl script is written as a plug-in using C<Gimp::Fu> as described
-above. The architecture is simply that Gimp, on start-up, runs all
-its plug-ins at startup including all the perl scripts in its plugins
-directory. The perl scripts will register themselves as GIMP "procedures"
-in the PDB. When these procedures are called, typically from the menu
-system, the perl script will be run and supplied with the appropriate
-arguments.
+There are four "entry points" into GIMP plugins: B<init>, B<query>,
+B<run>, and B<quit>. Gimp-Perl provides hooks for the last 3; the first
+is implicitly done as the script executes, then either query or run,
+then quit on exit.
+
+The perl script is written as a plug-in, probably using C<Gimp::Fu>.
+GIMP, on start-up, runs all the plug-ins in its plugins directory at
+startup (including all the perl scripts) in "query" mode.
+
+Any plugin will register itself as a GIMP "procedure" in the PDB, during
+its run in "query" mode.
+
+When such a procedure is called, either from the menu system or a
+scripting interface, the plugin will be run in "run" mode, and GIMP will
+supply it with the appropriate arguments.
 
 =head2 From outside GIMP
 
-The script will use C<Gimp> as above, and use Gimp functions as it
+The script will use C<Gimp> as above, and use GIMP functions as it
 wishes. If you are using GIMP interactively, you need to run the Perl
-server (under "Filters/Perl" to allow your script to connect. Otherwise,
+Server (under "Filters/Perl") to allow your script to connect. Otherwise,
 the script will start its own GIMP, in "batch mode".  Either way,
 your script, when it uses GIMP procedures (and Gimp-Perl functions),
-will actually be communicating with the perl server running under GIMP.
+will actually be communicating with the Perl server running under GIMP.
 
 The architecture may be visualised like this:
 
@@ -573,7 +633,11 @@ The return code should be immediately handed out to exit:
 
  exit Gimp::main;
 
-Before the call to C<Gimp::main>, I<no> other PDB function must be called.
+It used to be the case that before the call to C<Gimp::main>, I<no>
+other PDB function could be called. This is no longer the case (see
+L</"net_init=I<options>">), but there is no point in doing so outside of a
+"run" hook (unless you have the privilege and joy of writing test modules
+for Gimp-Perl!).
 
 In a C<Gimp::Fu>-script, it will actually call C<Gimp::Fu::main> instead
 of C<Gimp::main>:
@@ -592,24 +656,25 @@ C<main> to return at all, but still call C<exit> immediately.
 
 The C<Gimp> module provides routines to be optionally filled in by a
 plug-in writer.  This does not apply if using C<Gimp::Fu>, as these are
-done automatically.
+done automatically. These are specifically how your program can fit into
+the model of query, run and quit hooks.
 
-=over 2
+=over 4
 
 =item Gimp::on_query
 
-Do any activities that must be performed at Gimp startup, when the
-procedure is queried.  Should typically have at least one call to
-Gimp->install_procedure.
+Do any activities that must be performed at GIMP startup, when the
+plugin is queried.  Should typically have at least one call to
+C<Gimp-E<gt>install_procedure>.
 
 =item Gimp::on_net
 
-Run when called from a network interface (from the Perl-Server or from
-running it standalone).
+Run when the plugin is executed from the command line, either in "net
+mode" via the Perl-Server, or "batch mode".
 
 =item Gimp::on_lib
 
-Run only when called from within Gimp.
+Run only when called from within GIMP, i.e. in "plugin mode".
 
 =item Gimp::on_run
 
@@ -617,7 +682,8 @@ Run when anything calls it (network or lib).
 
 =item Gimp::on_quit
 
-Run when plugin terminates.
+Run when plugin terminates - allows a plugin (or extension, see below)
+to clean up after itself before it actually exits.
 
 =back
 
@@ -665,7 +731,7 @@ or also other event sources (including a GUI, or L<Glib::IO>):
              # GIMP will call your quit callback
 
 A working, albeit trivial, example is provided in
-examples/example-extension. A summarised example:
+C<examples/example-extension>. A summarised example:
 
   use Gimp;
   Gimp::register_callback extension_gp_test => sub {
@@ -694,44 +760,251 @@ examples/example-extension. A summarised example:
   };
   exit Gimp::main;
 
-=head1 CALLING GIMP FUNCTIONS
+A more substantial, working, example can be seen in the Perl Server
+extension that enables "net mode": C<examples/Perl-Server>.
 
-There are two different flavours of gimp-functions. Functions from the
-B<PDB> (the Procedural DataBase), and functions from B<libgimp> (the
-C-language interface library).
+=head1 AVAILABLE GIMP FUNCTIONS
+
+There are two different flavours of GIMP functions: those from
+the Procedural Database (the B<PDB>), and functions from B<libgimp>
+(the C-language interface library).
 
 You can get a listing and description of every PDB function by starting
-the B<DB Browser> extension in GIMP's B<Xtns> menu (but remember to change
- "-" (dashes) to  "_" (underscores)).
+GIMP's C<Help/Procedure Browser> extension. Perl requires you to change
+"-" (dashes) to "_" (underscores).
+
+=head1 OBJECT-ORIENTED SYNTAX
+
+Gimp-Perl uses some tricks to map the procedural PDB functions onto full
+classes, with methods. These effectively implement object-oriented C,
+not coincidentally in the style of Glib Objects. GIMP plans to move to
+fully supporting Glib Objects, which may mean some (or no) changes to
+the Gimp-Perl programming interface.
+
+=head2 AVAILABLE CLASSES
+
+Classes for which objects are created:
+
+  Gimp::Base # purely virtual
+    +-Gimp::Color
+    +-Gimp::Image
+    +-Gimp::Selection
+    +-Gimp::Display
+    +-Gimp::Parasite
+    +-Gimp::Item
+        +-Gimp::Vectors
+        +-Gimp::Drawable
+          +-Gimp::Layer
+          +-Gimp::Channel
+
+Classes for which non-PDB objects are created (see L<Gimp::PixelRgn>):
+
+  Gimp::GimpDrawable
+  Gimp::PixelRgn
+  Gimp::Tile
+
+Classes for which objects are not created:
+
+  Gimp
+  Gimp::Brush
+  Gimp::Brushes
+  Gimp::Context
+  Gimp::Edit
+  Gimp::Gradient
+  Gimp::Gradients
+  Gimp::Palette
+  Gimp::Pattern
+  Gimp::Patterns
+  Gimp::Plugin
+  Gimp::Progress
+
+C<Gimp::Base> implements two methods:
 
-C<libgimp> functions can't be traced (and won't be traceable in the
-foreseeable future).
+=over 4
+
+=item $object->become($class)
+
+Allows an object of one class to change its class to another, but with
+the same ID. No checking is performed. It is intended for use in plugins,
+e.g. where GIMP passes a C<Gimp::Drawable>, but you need a C<Gimp::Layer>:
+
+  my ($image, $layer, $color) = @_;
+  die "Can only operate on a layer\n" unless $layer->is_layer;
+  $layer->become('Gimp::Layer'); # now can call layer methods on it
 
-To call pdb functions (or equivalent libgimp functions), just treat them like
-normal perl (this requires the use of the C<:auto> import tag - see
-the import C<:auto> note for non-OO limitation; see below for another
-possibility!):
+=item $class->existing($id)
+
+Allows you to instantiate a Gimp-Perl object with the given C<$class>
+and C<$id>. Again, no checking is performed.
+
+=back
+
+It also provides a "stringify" overload method, so debugging output can
+be more readable.
+
+C<Gimp::Parasite> implements these self-explanatory methods:
+
+=over 4
 
- Gimp->palette_set_foreground([20,5,7]);
- Gimp->palette_set_background("cornsilk");
+=item $parasite = Gimp::Parasite-E<gt>new($name, $flags, $data)
 
-If you don't use the C<:auto> import tag, you can call all Gimp functions
-using OO-Syntax:
+C<$name> and C<$data> are perl strings, C<flags> is the numerical flag value.
 
- Gimp->palette_set_foreground([20,5,7]);
- Gimp->palette_set_background("cornsilk");
- Gimp::Palette->set_foreground('#1230f0');
+=item $parasite-E<gt>name
 
-As you can see, you can also drop part of the name prefixes with this
-syntax, so it's actually shorter to write and hopefully clearer to read.
+=item $parasite-E<gt>flags
+
+=item $parasite-E<gt>data
+
+=item $parasite-E<gt>has_flag($flag)
+
+=item $parasite-E<gt>is_type($type)
+
+=item $parasite-E<gt>is_persistent
+
+=item $parasite-E<gt>is_error
+
+=item $different_parasite = $parasite-E<gt>copy
+
+=item $parasite-E<gt>compare($other_parasite)
+
+=back
+
+=head2 SPECIAL METHODS
+
+Some methods behave differently from how you'd expect, or methods uniquely
+implemented in Perl (that is, not in the PDB). All of these must be
+invoked using the method syntax (C<Gimp-E<gt>> or C<$object-E<gt>>).
+
+=over 4
+
+=item Gimp->install_procedure(name, blurb, help, author, copyright, date, menu_path, image_types, type, 
params[, return_vals])
+
+Mostly the same as gimp_install_procedure from the C library. The
+parameters and return values for the functions are each specified as an
+array ref containing array-refs with three elements,
+C<[PARAM_TYPE, "NAME", "DESCRIPTION"]>, e.g.:
+
+  Gimp::on_query {
+     Gimp->install_procedure(
+       $Gimp::Net::PERLSERVERPROC, "Gimp-Perl scripts net server",
+       "Allow scripting GIMP with Perl providing Gimp::Net server",
+       "Marc Lehmann <pcg\ goof com>", "Marc Lehmann", "1999-12-02",
+       N_"<Image>/Filters/Languages/_Perl/_Server", undef,
+       $Gimp::Net::PERLSERVERTYPE,
+       [
+        [&Gimp::PDB_INT32, "run_mode", "Interactive, [non-interactive]"],
+        [&Gimp::PDB_INT32, "flags", "internal flags (must be 0)"],
+        [&Gimp::PDB_INT32, "extra", "multi-purpose"],
+        [&Gimp::PDB_INT32, "verbose", "Gimp verbose var"],
+       ],
+       [],
+     );
+  };
+
+=item Gimp::Progress->init(message,[display])
+
+=item Gimp::Progress->update(percentage)
+
+Initializes or updates a progress bar. In networked modules these are a no-op.
+
+=item Gimp::Image-E<gt>list
+
+=item $image-E<gt>get_layers
+
+=item $image-E<gt>get_channels
+
+These functions return what you would expect: an array of images, layers or
+channels. The reason why this is documented is that the usual way to return
+C<PDB_INT32ARRAY>s would be to return a B<reference> to an B<array of
+integers>, rather than blessed objects:
+
+  perl -MGimp -e '@x = Gimp::Image->list; print "@x\n"'
+  # returns: Gimp::Image->existing(7) Gimp::Image->existing(6)
+
+=item $drawable-E<gt>bounds, $gdrawable-E<gt>bounds
+
+Returns an array (x,y,w,h) containing the upper left corner and the
+size of currently selected parts of the drawable, just as needed by
+C<Gimp::PixelRgn-E<gt>new> and similar functions. Exist for objects of
+both C<Gimp::Drawable> and C<Gimp::GimpDrawable>.
+
+=back
+
+=head2 NORMAL METHODS
+
+If you call a method, C<Gimp> tries to find a GIMP function by
+prepending a number of prefixes until it finds a valid function:
+
+ $image = Gimp->image_new(...); # calls gimp_image_new(...)
+ $image = Gimp::Image->new(...); # calls gimp_image_new as well
+ $image = new Gimp::Image(...); # the same in green
+ Gimp::Palette->set_foreground(...); # calls gimp_palette_set_foreground(..)
+ $image->histogram(...); # calls gimp_histogram($image,...), since
+                        # gimp_image_histogram does not exist
+
+Return values from functions are automatically blessed to their
+corresponding classes, e.g.:
+
+ $image = new Gimp::Image(...);        # $image is now blessed to Gimp::Image
+ $image->height;               # calls gimp_image_height($image)
+ $image->flatten;              # likewise gimp_flatten($image)
+
+The object argument (C<$image> in the above examples) is prepended to the
+argument list - this is how Perl does OO.
+
+Another shortcut: many functions want a (redundant) image argument, like
+
+ $image->shear ($layer, ...)
+
+Since all you want is to shear the C<$layer>, not the C<$image>, this is
+confusing as well. In cases like this, Gimp-Perl allows you to write:
+
+ $layer->shear (...)
+
+And automatically infers the additional IMAGE-type argument.
+
+Because method call lookup also search the C<plug_in_>, C<perl_fu_> and
+C<script_fu_> namespaces, any plugin can automatically become a method
+for an image or drawable (see below).
+
+As the (currently) last goodie, if the first argument is of type INT32, its
+name is "run_mode" and there are no other ambiguities, you can omit it, i.e.
+these five calls are equivalent:
+
+ plug_in_gauss_rle(RUN_NONINTERACTIVE, $image, $layer, 8, 1, 1);
+ plug_in_gauss_rle($image, $layer, 8, 1, 1);
+ plug_in_gauss_rle($layer, 8, 1, 1);
+ $layer->plug_in_gauss_rle(8, 1, 1);
+ $layer->gauss_rle(8, 1, 1);
+
+You can call all sorts of sensible and not-so-sensible functions,
+so this feature can be abused:
+
+ patterns_list Gimp::Image;    # will call gimp_patterns_list
+ quit Gimp::Plugin;            # will quit the Gimp, not an Plugin.
+
+there is no image involved here whatsoever...
+
+The 'gimpdoc' script will also return OO variants when functions
+are described.  For example:
+
+  gimpdoc image_new
+
+has a section:
+
+  SOME SYNTAX ALTERNATIVES
+       $image = Gimp->image_new (width,height,type)
+       $image = new Gimp::Image (width,height,type)
+       $image = image_new Gimp::Display (width,height,type)
 
 =head1 SPECIAL FUNCTIONS
 
 In this section, you can find descriptions of special functions, functions
-having different calling conventions/semantics than might be expected
-or otherwise interesting functions. All of these functions must either
-be imported explicitly or called using a namespace override (C<Gimp::>),
-not as Methods (C<Gimp-E<gt>>).
+that have unexpected calling conventions/semantics or are otherwise
+interesting. All of these functions must either be imported explicitly
+or called using a namespace override (C<Gimp::>), not as methods
+(C<Gimp-E<gt>>).
 
 =over 4
 
@@ -742,43 +1015,26 @@ supported. Initializations can later be done in the init function.
 
 =item Gimp::gtk_init()
 
-Initialize Gtk in a similar way GIMP itself did it. This automatically
-parses gimp's gtkrc and sets a variety of default settings (visual,
-colormap, gamma, shared memory...).
-
-=item use Gimp qw(net_init=...);
-
-This is how to use Gimp-Perl in "net mode". Previous versions of this
-package required a call to Gimp::init. This is no longer necessary. The
-technical reason for this change is that when C<Gimp.pm> loads, it must
-connect to GIMP to load its constants, like C<PDB_INT32>.
-
-=item Gimp::lock(), Gimp::unlock()
-
-These functions can be used to gain exclusive access to GIMP. After
-calling lock, all accesses by other clients will be blocked and executed
-after the call to unlock. Calls to lock and unlock can be nested.
-
-Currently, these functions only lock the current Perl-Server instance
-against exclusive access, they do nothing when used via the Gimp::Lib
-interface.
+Initialize Gtk in a similar way GIMP itself did. This automatically
+parses GIMP's gtkrc and sets a variety of default settings, including
+visual, colormap, gamma, and shared memory.
 
 =item Gimp::set_rgb_db(filespec)
 
 Use the given rgb database instead of the default one. The format is
 the same as the one used by the X11 Consortiums rgb database (you might
 have a copy in /usr/lib/X11/rgb.txt). You can view the default database
-with C<perldoc -m Gimp::ColorDB>, at the end of the file (the default
-database is similar, but not identical to the X11 default rgb.txt)
+with C<perldoc -m Gimp::ColorDB>, at the end of the file; the default
+database is similar, but not identical to the X11 default C<rgb.txt>.
 
 =item Gimp::initialized()
 
-this function returns true whenever it is safe to call gimp functions. This is
+this function returns true whenever it is safe to call GIMP functions. This is
 usually only the case after gimp_main has been called.
 
 =item Gimp::register_callback(gimp_function_name, perl_function)
 
-Using this function you can overwrite the standard Gimp behaviour of
+Using this function you can override the standard Gimp-Perl behaviour of
 calling a perl subroutine of the same name as the GIMP function.
 
 The first argument is the name of a registered gimp function that you want
@@ -803,63 +1059,10 @@ For example:
 Note that bounds checking is somewhat lax; this assumes relatively
 good input.
 
-=back
-
-=head1 SPECIAL METHODS
-
-This chapter describes methods that behave differently than you might
-expect, or methods uniquely implemented in perl (that is, not in the
-PDB). All of these must be invoked using the method syntax (C<Gimp-E<gt>>
-or C<$object-E<gt>>).
-
-=over 4
-
-=item Gimp->install_procedure(name, blurb, help, author, copyright, date, menu_path, image_types, type, 
[params], [return_vals])
-
-Mostly same as gimp_install_procedure from the C library. The
-parameters and return values for the functions are specified as an
-array ref containing either integers or array-refs with three elements,
-[PARAM_TYPE, \"NAME\", \"DESCRIPTION\"].
-
-=item Gimp::Progress->init(message,[])
-
-Initializes a progress bar. In networked modules this is a no-op.
-
-=item Gimp::Progress->update(percentage)
-
-Updates the progress bar. No-op in networked modules.
-
 =item gimp_tile_*, gimp_pixel_rgn_*, gimp_drawable_get
 
 With these functions you can access the raw pixel data of drawables. They
-are documented in L<Gimp::PixelRgn>, to keep this manual page short.
-
-=item gimp_call_procedure(procname, arguments...)
-
-This function is actually used to implement the fancy stuff. It's your basic
-interface to the PDB. Every function call is eventually done through his
-function, i.e.:
-
- gimp_image_new(args...);
-
-is replaced by
-
- gimp_call_procedure "gimp_image_new",args...;
-
-at runtime.
-
-=item gimp_list_images, gimp_image_get_layers, gimp_image_get_channels
-
-These functions return what you would expect: an array of images, layers or
-channels. The reason why this is documented is that the usual way to return
-C<PDB_INT32ARRAY>'s would be to return a B<reference> to an B<array of
-integers>, rather than blessed objects.
-
-=item gimp_drawable_bounds drawable/gdrawable
-
-Returns an array (x,y,w,h) containing the upper left corner and the
-size of currently selected parts of the drawable, just as needed by
-Gimp::PixelRgn->new and similar functions.
+are documented in L<Gimp::PixelRgn>.
 
 =item server_eval(string)
 
@@ -871,21 +1074,15 @@ reported as runtime errors (i.e. throwing an exception).
 
 =back
 
-=head1 OBJECT ORIENTED SYNTAX
-
-In this manual, only the plain syntax (that lesser languages like C use)
-is described. See L<Gimp::OO> for details on using the object oriented
-syntax.  The 'gimpdoc' script will also return OO varients when functions
-are described.  For example:
+=head1 PROCEDURAL SYNTAX (DEPRECATED)
 
-gimpdoc image_new
+To call PDB functions or libgimp functions, you I<can>
+(but shouldn't) treat them like normal procedural perl (this requires
+the use of the C<:auto> import tag - see L</":auto (DEPRECATED)">):
 
-has a section:
-
-SOME SYNTAX ALTERNATIVES
-       $image = Gimp->image_new (width,height,type)
-       $image = new Gimp::Image (width,height,type)
-       $image = image_new Gimp::Display (width,height,type)
+ gimp_item_set_name($layer, 'bob'); # $layer is an object (i.e. ref) - works
+ gimp_palette_set_foreground([20,5,7]); # works because of array ref
+ gimp_palette_set_background("cornsilk"); # colour turned into array ref!
 
 =head1 DEBUGGING AIDS
 
@@ -895,9 +1092,9 @@ How to debug your scripts:
 
 =item $Gimp::verbose
 
-If set to true, will make Gimp say what it's doing on STDOUT. It will
+If set to true, will make Gimp-Perl say what it's doing on STDOUT. It will
 also stop L<Gimp::Net>'s normal behaviour of the server-side closing
-STDIN, STDOUT and STDERR. If you want it to be set during loading Gimp.pm,
+STDIN, STDOUT and STDERR. If you want it to be set during loading C<Gimp.pm>,
 make sure to do so in a prior C<BEGIN> block:
 
  BEGIN { $Gimp::verbose = 1; }
@@ -905,18 +1102,19 @@ make sure to do so in a prior C<BEGIN> block:
 
 =item Gimp::set_trace (tracemask)
 
-Tracking down bugs in gimp scripts is difficult, due to a lack of
-reasonable error messages.  Often, if anything goes wrong, you only get
-an execution failure.
+You can switch on tracing to see which parameters are used to call PDB
+functions, so you can at least see what was called to cause the error:
 
-You can switch on tracing to see which parameters are used to call pdb
-functions, so you can at least see what was called to cause the error.
+ Gimp::set_trace(TRACE_ALL);
 
 This function is never exported, so you have to qualify it when calling.
 
-tracemask is any number of the following flags or'ed together.
+C<libgimp> functions can't be traced (and won't be traceable in the
+foreseeable future).
 
-=over 8
+C<tracemask> is any number of the following flags or'ed together:
+
+=over 4
 
 =item TRACE_NONE
 
@@ -924,7 +1122,7 @@ nothing is printed (default).
 
 =item TRACE_CALL
 
-all pdb calls (and only pdb calls!) are printed
+all PDB calls (and only PDB calls!) are printed
 with arguments and return values.
 
 =item TRACE_TYPE
@@ -972,19 +1170,20 @@ setting C<MALLOC_CHECK_> (note trailing underscore) to 3.
 
 =head1 SUPPORTED GIMP DATA TYPES
 
-Gimp supports different data types like colors, regions, strings. In
-perl, these are represented as:
+GIMP supports different data types like colors, regions, strings. In
+C, these are represented as (C<GIMP_PDB_> omitted for brevity - in
+Gimp-Perl, they are constants starting C<PDB_>):
 
 =over 4
 
 =item INT32, INT16, INT8, FLOAT, STRING
 
-normal perl scalars. Anything except STRING will be mapped
-to a perl-double.
+normal Perl scalars. Anything except STRING will be mapped
+to a Perl-number.
 
 =item INT32ARRAY, INT16ARRAY, INT8ARRAY, FLOATARRAY, STRINGARRAY, COLORARRAY
 
-array refs containing scalars of the same type, i.e. [1, 2, 3, 4]. Gimp
+array refs containing scalars of the same type, i.e. [1, 2, 3, 4]. Gimp-Perl
 implicitly swallows or generates a preceeding integer argument because the
 preceding argument usually (this is a de-facto standard) contains the number
 of elements.
@@ -993,7 +1192,7 @@ of elements.
 
 on input, either an array ref with 3 or 4 elements (i.e. [0.1,0.4,0.9]
 or [233,40,40]), a X11-like string ("#rrggbb") or a colour name
-("papayawhip") (see set_rgb_db).
+("papayawhip") (see L</"Gimp::set_rgb_db(filespec)">).
 
 =item DISPLAY, IMAGE, LAYER, CHANNEL, DRAWABLE, SELECTION, VECTORS, ITEM
 
@@ -1002,8 +1201,7 @@ trace output you will see small integers (the image/layer/etc..-ID)
 
 =item PARASITE
 
-represented as an array ref [name, flags, data], where name and data
-should be perl strings and flags is the numerical flag value.
+represented as a C<Gimp::Parasite> object (see above).
 
 =item STATUS
 
@@ -1018,9 +1216,14 @@ Marc Lehmann <pcg goof com> (pre-2.0)
 
 Seth Burgess <sjburge gimp org> (2.0+)
 
-Ed J (with oversight and guidance from Kevin Cozens) (2.3+)
+Kevin Cozens (2.2+)
+
+Ed J (with oversight and guidance from Kevin Cozens) (2.3)
+
+Ed J (2.3000_01+)
 
 =head1 SEE ALSO
 
-perl(1), gimp(1), L<Gimp::OO>, L<Gimp::Data>, L<Gimp::PixelRgn>,
-L<Gimp::Util>, L<Gimp::UI>, L<Gimp::Config>, L<Gimp::Net>, and L<Gimp::Lib>.
+perl(1), gimp(1), L<Gimp::Fu>, L<Gimp::PixelRgn>, L<Gimp::UI>,
+L<Gimp::Util>, L<Gimp::Data>, L<Gimp::Config>, L<Gimp::Net>, and
+L<Gimp::Lib>.
diff --git a/Gimp/Config.pm.in b/Gimp/Config.pm.in
index 3e48bc1..e1c2703 100644
--- a/Gimp/Config.pm.in
+++ b/Gimp/Config.pm.in
@@ -2,7 +2,7 @@ package Gimp::Config;
 
 =head1 NAME
 
-  Gimp::Config - config options found during configure time.
+  Gimp::Config - Access config options found during configure time.
 
 =head1 DESCRIPTION
 
diff --git a/Gimp/Data.pm b/Gimp/Data.pm
index 072fcaa..4f5c0c9 100644
--- a/Gimp/Data.pm
+++ b/Gimp/Data.pm
@@ -58,7 +58,7 @@ __END__
 
 =head1 NAME
 
-Gimp::Data - Set and get state data.
+Gimp::Data - Set and get persistent data.
 
 =head1 SYNOPSIS
 
@@ -79,22 +79,20 @@ values again (L<Gimp::Fu> does this already).
 
 =head1 %Gimp::Data
 
-You can store and retrieve anything you like in this hash. It's contents
+You can store and retrieve anything you like in this hash. Its contents
 will automatically be stored in Gimp, and can be accessed in later
 invocations of your plug-in. Be aware that other plug-ins store data
 in the same "hash", so better prefix your key with something unique,
 like your plug-in's name. As an example, the Gimp::Fu module uses
 "function_name/_fu_data" to store its data.
 
-This module might use a persistant implementation, i.e. your data might
-survive a restart of the Gimp application, but you cannot count on this.
+As of L<Gimp> version 2.3 (and GIMP 2.8), your data B<will> survive a
+restart of the Gimp application.
 
 C<Gimp::Data> will try to freeze your data when you pass in a reference. On
-retrieval, the data is thawed again. See L<Storable> for more info. This
-might be implemented through either Storable or Data::Dumper, or not
-implemented at all (i.e. silently fail) ;)
+retrieval, the data is thawed again. See L<Data::Dumper> for more info.
 
-=head1 PERSISTANCE
+=head1 PERSISTENCE
 
 C<Gimp::Data> contains the following functions to ease applications where
 persistence for perl data structures is required:
diff --git a/Gimp/Fu.pm b/Gimp/Fu.pm
index 33d823a..4994cfd 100644
--- a/Gimp/Fu.pm
+++ b/Gimp/Fu.pm
@@ -53,13 +53,13 @@ use constant {
 };
 
 # key is text, bit in array-ref is number!
-# [ int, human-readable-description, GIMP-data-type-if>PDB_END-or-infer ]
+# [int, human-description, GIMP-data-type-if>PDB_END-or-infer, passthru]
 my %pfname2info = (
    PF_INT8             => [ PF_INT8, 'integer (8-bit)', ],
    PF_INT16            => [ PF_INT16, 'integer (16-bit)', ],
    PF_INT32            => [ PF_INT32, 'integer (32-bit)', ],
    PF_FLOAT            => [ PF_FLOAT, 'number', ],
-   PF_STRING           => [ PF_STRING, 'string', ],
+   PF_STRING           => [ PF_STRING, 'string', undef, 1 ],
    PF_INT32ARRAY       => [ PF_INT32ARRAY, 'list of integers (32-bit)' ],
    PF_INT16ARRAY       => [ PF_INT16ARRAY, 'list of integers (16-bit)' ],
    PF_INT8ARRAY                => [ PF_INT8ARRAY, 'list of integers (8-bit)' ],
@@ -74,31 +74,31 @@ my %pfname2info = (
    PF_COLORARRAY       => [ PF_COLORARRAY, 'list of colours' ],
    PF_VECTORS          => [ PF_VECTORS, 'vectors' ],
    PF_PARASITE         => [ PF_PARASITE, 'parasite' ],
-   PF_BRUSH            => [ PF_BRUSH, 'brush', Gimp::PDB_STRING, ],
-   PF_GRADIENT         => [ PF_GRADIENT, 'gradient', Gimp::PDB_STRING, ],
-   PF_PATTERN          => [ PF_PATTERN, 'pattern', Gimp::PDB_STRING, ],
-   PF_FONT             => [ PF_FONT, 'font', Gimp::PDB_STRING, ],
+   PF_BRUSH            => [ PF_BRUSH, 'brush', Gimp::PDB_STRING, 1 ],
+   PF_GRADIENT         => [ PF_GRADIENT, 'gradient', Gimp::PDB_STRING, 1 ],
+   PF_PATTERN          => [ PF_PATTERN, 'pattern', Gimp::PDB_STRING, 1 ],
+   PF_FONT             => [ PF_FONT, 'font', Gimp::PDB_STRING, 1 ],
    PF_TOGGLE           => [ PF_TOGGLE, 'boolean', Gimp::PDB_INT8, ],
    PF_SLIDER           => [ PF_SLIDER, 'number', Gimp::PDB_FLOAT, ],
    PF_SPINNER          => [ PF_SPINNER, 'integer', Gimp::PDB_INT32, ],
    PF_ADJUSTMENT       => [ PF_ADJUSTMENT, 'number', Gimp::PDB_FLOAT, ],
    PF_RADIO            => [ PF_RADIO, 'data', ],
-   PF_CUSTOM           => [ PF_CUSTOM, 'string', Gimp::PDB_STRING, ],
-   PF_FILE             => [ PF_FILE, 'filename', Gimp::PDB_STRING, ],
-   PF_TEXT             => [ PF_TEXT, 'string', Gimp::PDB_STRING, ],
+   PF_CUSTOM           => [ PF_CUSTOM, 'string', Gimp::PDB_STRING, 1 ],
+   PF_FILE             => [ PF_FILE, 'filename', Gimp::PDB_STRING, 1 ],
+   PF_TEXT             => [ PF_TEXT, 'string', Gimp::PDB_STRING, 1 ],
 );
 $pfname2info{PF_COLOUR} = $pfname2info{PF_COLOR};
 $pfname2info{PF_BOOL} = $pfname2info{PF_TOGGLE};
 $pfname2info{PF_VALUE} = $pfname2info{PF_FLOAT};
 my %pf2info = map {
-   my $v = $pfname2info{$_}; ($v->[0] => [ @$v[1,2] ])
+   my $v = $pfname2info{$_}; ($v->[0] => [ @$v[1..3] ])
 } keys %pfname2info;
 
 @EXPORT_OK = qw($run_mode save_image);
 %EXPORT_TAGS = (
    params => [ keys %pfname2info ]
 );
- EXPORT = (qw(register main), @{$EXPORT_TAGS{params}});
+ EXPORT = (qw(podregister register main), @{$EXPORT_TAGS{params}});
 
 my @scripts;
 
@@ -113,29 +113,6 @@ my @save_params  = (@image_params, @load_params);
 
 my $image_retval = [PF_IMAGE, "image", "Output image"];
 
-# expand all the pod directives in string (currently they are only removed)
-sub expand_podsections() {
-   my $pod;
-   for (@scripts) {
-      $_->[2] ||= "=pod(NAME)";
-      $_->[3] ||= "=pod(DESCRIPTION)";
-      $_->[4] ||= "=pod(AUTHOR)";
-      $_->[5] ||= "=pod(AUTHOR)";
-      $_->[6] ||= "=pod(DATE)";
-
-      for (@{$_}[2,3,4,5,6]) {
-         s/=pod\(([^)]*)\)/
-            require Gimp::Pod;
-            $pod ||= new Gimp::Pod;
-            $pod->section($1) || $pod->format;
-         /eg;
-      }
-   }
-}
-
-# the old value of the trace flag
-my $old_trace;
-
 sub interact {
    require Gimp::UI;
    goto &Gimp::UI::interact;
@@ -145,10 +122,10 @@ sub this_script {
    return $scripts[0] if @scripts == 1;
    # well, not-so-easy-day today
    require File::Basename;
-   my $exe = File::Basename::basename($0);
+   my ($exe) = File::Basename::fileparse($RealScript, qr/\.[^.]*/);
    my @names;
    for my $this (@scripts) {
-      my $fun = (split /\//,$this->[1])[-1];
+      my $fun = $this->[0];
       $fun =~ s/^(?:perl_fu|plug_in)_//;
       return $this if lc($exe) eq lc($fun);
       push(@names,$fun);
@@ -160,7 +137,7 @@ my $latest_image;
 
 sub string2pf($$) {
    my ($s, $type, $name, $desc) = ($_[0], @{$_[1]});
-   if($pf2info{$type}->[0] eq 'string') {
+   if($pf2info{$type}->[2]) {
       $s;
    } elsif($pf2info{$type}->[0] =~ /integer/) {
       die __"$s: not an integer\n" unless $s==int($s);
@@ -175,11 +152,11 @@ sub string2pf($$) {
    } elsif($type == PF_IMAGE) {
       my $image;
       if ((my $arg) = $s =~ /%(.+)/) {
-        die "image % argument not integer - if file, put './' in front\n"
+        die "Image % argument not integer - if file, put './' in front\n"
            unless $arg eq int $arg;
-        $image = bless \$arg, 'Gimp::Image';
-        eval { $image->get_layers; };
-        die "'$arg' not a valid image - need to run Perl Server?\n" if $@;
+        $image = Gimp::Image->existing($arg);
+        die "'$arg' not a valid image - need to run Perl Server?\n"
+           unless $image->is_valid;
       } else {
         $image = Gimp->file_load(Gimp::RUN_NONINTERACTIVE, $s, $s),
       }
@@ -190,17 +167,15 @@ sub string2pf($$) {
            $latest_image->get_active_drawable;
         } else {
            # existing GIMP object - rely on autobless
-           die "drawable % argument not integer\n"
+           die "Drawable % argument not integer\n"
               unless $arg eq int $arg;
            $arg;
         }
       } else {
-        die "must specify drawable as %number or %a (active)\n";
+        die "Must specify drawable as %number or %a (active)\n";
       }
-   } elsif($type == PF_GRADIENT) {
-      $s;
    } else {
-      die __"conversion from string to type $pf2info{$type}->[0] is not yet implemented\n";
+      die __"Can't convert '$name' from string to '$pf2info{$type}->[0]'\n";
    }
 }
 
@@ -218,8 +193,8 @@ Gimp::on_net {
    my $this = this_script;
    my(%mangleparam2index,@args);
    my ($interact, $outputfile) = 1;
-   my($perl_sub,$function,$blurb,$help,$author,$copyright,$date,
-      $menupath,$imagetypes,$params,$results,$code,$type)= $this;
+   my ($function,$blurb,$help,$author,$copyright,$date,
+       $menupath,$imagetypes,$type,$params,$results,$perl_sub) = @$this;
    @mangleparam2index{map mangle_key($_->[1]), @$params} = (0..$#{$params});
    die "$0: error - try $0 --help\n" unless Getopt::Long::GetOptions(
       'interact|i' => sub { $interact = 1e6 },
@@ -245,7 +220,7 @@ Gimp::on_net {
       ($interact>0 ? RUN_FULLINTERACTIVE : Gimp::RUN_NONINTERACTIVE),
       @args
    );
-   if ($outputfile and $menupath !~ /^<Load>\//) {
+   if ($outputfile) {
       my @images = grep { defined $_ and ref $_ eq "Gimp::Image" } @retvals;
       if (@images) {
         for my $i (0..$#images) {
@@ -274,46 +249,42 @@ sub datatype(@) {
 }
 
 Gimp::on_query {
-   expand_podsections;
-   script:
-   for(@scripts) {
-      my($perl_sub,$function,$blurb,$help,$author,$copyright,$date,
-         $menupath,$imagetypes,$params,$results,$code,$type)= $_;
-
-      for(@$params) {
-        next if $_->[0] < Gimp::PDB_END;
-        $_->[0] = $pf2info{$_->[0]}->[1] // datatype(values %{+{ {$_->[4]}}});
+   for my $s (@scripts) {
+      for my $p (@{$s->[9]}) {
+        next if $p->[0] < Gimp::PDB_END;
+        $p->[0] = $pf2info{$p->[0]}->[1] // datatype(values %{+{ {$p->[4]}}});
       }
-
-      warn "$$-Gimp::Fu gimp_install_procedure params (@$params)" if $Gimp::verbose;
-      Gimp->install_procedure(
-       $function,
-       $blurb,
-       $help,
-       $author,
-       $copyright,
-       $date,
-       $menupath,
-       $imagetypes,
-       $type,
-       [
-         [Gimp::PDB_INT32, "run_mode", "Interactive, [non-interactive]"],
-         @$params,
-       ],
-       $results,
-      );
+      unshift @{$s->[9]}, [Gimp::PDB_INT32,"run_mode","Interactive:0=yes,1=no"];
+      Gimp->install_procedure(@$s[0..10]);
    }
 };
 
+sub podregister (&) { unshift @_, ('') x 9; goto &register; }
+sub getpod ($$) {
+   require Gimp::Pod; $_[0] ||= new Gimp::Pod; $_[0]->section($_[1]);
+}
+my %IND2SECT = (
+   2 => 'DESCRIPTION', 3 => 'AUTHOR', 4 => 'LICENSE',
+   5 => 'DATE', 6 => 'SYNOPSIS', 7 => 'IMAGE TYPES',
+);
+#(func,blurb,help,author,copyright,date,menupath,imagetypes,params,return,code)
 sub register($$$$$$$$$;@) {
    no strict 'refs';
+   my @p = @_;
+   splice @p, 9, 0, [] if @p == 10; # optional return values
+   die __"register called with too many or wrong arguments\n" unless @p == 11;
+   my $pod;
+   @p[0,1] = getpod($pod,'NAME') =~ /(.*?)\s*-\s*(.*)/ unless $p[0] or $p[1];
+   ($p[0]) = File::Basename::fileparse($RealScript, qr/\.[^.]*/) unless $p[0];
+   while (my ($k, $v) = each %IND2SECT) { $p[$k] ||= getpod($pod, $v); }
+   $p[8] ||= [ eval getpod($pod, 'PARAMETERS') ]; die $@ if $@;
+   $p[9] ||= [ eval getpod($pod, 'RETURN VALUES') ]; die $@ if $@;
+   for my $i (0..6, 10) {
+      croak "$0: Need arg $i (or POD $IND2SECT{$i} section)" unless $p[$i]
+   }
    my ($function, $blurb, $help, $author, $copyright, $date,
-       $menupath, $imagetypes, $params) = splice @_, 0, 9;
-   my ($results, $code, $type);
-
-   $results  = (ref $_[0] eq "ARRAY") ? shift : [];
-   $code = shift;
-
+       $menupath, $imagetypes, $params, $results, $code) = @p;
+   my $type;
    if ($menupath =~ /^<Image>\//) {
       $type = Gimp::PLUGIN;
       if ($imagetypes) {
@@ -338,11 +309,12 @@ sub register($$$$$$$$$;@) {
       undef $menupath;
       undef $imagetypes;
    } else {
-      die __"menupath _must_ start with <Image>, <Load>, <Save>, <Toolbox>/Xtns/, or <None>!";
+      die __<<EOF;
+menupath _must_ start with <Image>, <Load>, <Save>, <Toolbox>/Xtns/, or <None>!
+(got '$menupath')
+EOF
    }
 
-   @_==0 or die __"register called with too many or wrong arguments\n";
-
    for my $p (@$params,@$results) {
       next unless ref $p;
       croak __"$function: argument/return value '$p->[1]' has illegal type '$p->[0]'"
@@ -448,8 +420,8 @@ sub register($$$$$$$$$;@) {
    };
 
    Gimp::register_callback($function,$perl_sub);
-   push(@scripts,[$perl_sub,$function,$blurb,$help,$author,$copyright,$date,
-                  $menupath,$imagetypes,$params,$results,$code,$type]);
+   push(@scripts,[$function,$blurb,$help,$author,$copyright,$date,
+                  $menupath,$imagetypes,$type,$params,$results,$perl_sub]);
 }
 
 sub save_image($$) {
@@ -513,8 +485,8 @@ sub main {
        interface-arguments are
            -o | --output <filespec>   write image to disk
            -i | --interact            let the user edit the values first
-       script-arguments are
 EOF
+   print "       script-arguments are\n" if @{$this->[9]};
    for(@{$this->[9]}) {
       my $type=$pf2info{$_->[0]}->[0];
       my $key=mangle_key($_->[1]);
@@ -526,6 +498,7 @@ EOF
        $_->[2],
        $default_text;
    }
+   0;
 }
 
 1;
@@ -533,65 +506,93 @@ __END__
 
 =head1 NAME
 
-Gimp::Fu - "easy to use" framework for Gimp scripts
+Gimp::Fu - Easy framework for Gimp-Perl scripts
 
 =head1 SYNOPSIS
 
   use Gimp;
   use Gimp::Fu;
+  podregister {
+    # your code
+  };
+  exit main;
+  __END__
+  =head1 NAME
 
-=head1 DESCRIPTION
+  function_name - Short description of the function
+
+  =head1 SYNOPSIS
 
-Currently, there are only three functions in this module. This
-fully suffices to provide a professional interface and the
-ability to run this script from within GIMP and standalone
-from the command line.
+  <Image>/Filters/Menu/Location...
 
-Dov Grobgeld has written an excellent tutorial for Gimp-Perl.
+  =head1 DESCRIPTION
+
+  Longer description of the function...
+
+=head1 DESCRIPTION
+
+This module provides all the infrastructure you need to write Gimp-Perl
+plugins. Dov Grobgeld has written an excellent tutorial for Gimp-Perl.
 You can find it at C<http://www.gimp.org/tutorials/Basic_Perl/>.
 
-=head1 INTRODUCTION
+This distribution comes with many example scripts. One is
+C<examples/example-fu.pl>, which is a small Gimp::Fu-script you can take
+as a starting point for your experiments. You should be able to run it
+from GIMP already by looking at "Filters/Languages/_Perl/Test/Dialog".
 
-In general, a Gimp::Fu script looks like this:
+Your main interface for using C<Gimp::Fu> is the C<podregister> function.
 
-   #!/path/to/your/perl
+=head1 PODREGISTER
 
-   use Gimp;
-   use Gimp::Fu;
+This:
 
-   register <many arguments>, sub {
-      your code;
-   }
+  podregister {
+    # your code
+  };
+
+does the same as this:
 
-   exit main;
-
-(This distribution comes with example scripts. One is
-C<examples/example-fu.pl>, which is a small Gimp::Fu-script you can take as
-a starting point for your experiments)
-
-=head2 THE REGISTER FUNCTION
-
-   register
-     "function_name",
-     "blurb", "help",
-     "author", "copyright",
-     "date",
-     "menu path",
-     "image types",
-     [
-       [PF_TYPE,name,desc,optional-default,optional-extra-args],
-       [PF_TYPE,name,desc,optional-default,optional-extra-args],
-       # etc...
-     ],
-     [
-       # like above, but for return values (optional)
-     ],
-     sub { code };
+  register '', '', '', '', '', '', '', '', '', sub {
+    # your code
+  };
+
+It extracts all the relevant values from your script's POD documentation
+- see the section on L</"EMBEDDED POD DOCUMENTATION"> for an
+explanation. You will also notice you don't need to provide the C<sub>
+keyword, thanks to Perl's prototyping.
+
+=head1 THE REGISTER FUNCTION
+
+  register
+    "function_name",
+    "blurb", "help",
+    "author", "copyright",
+    "date",
+    "menu path",
+    "imagetypes",
+    [
+      [PF_TYPE,name,desc,optional-default,optional-extra-args],
+      [PF_TYPE,name,desc,optional-default,optional-extra-args],
+      # etc...
+    ],
+    [
+      # like above, but for return values (optional)
+    ],
+    sub { code };
+
+All these parameters except the code-ref can be replaced with C<''>, in
+which case they will be substituted with appropriate values from various
+sections (see below) of the POD documentation in your script.
+
+It is B<highly> recommended you use the L</PODREGISTER> interface.
 
 =over 2
 
 =item function name
 
+Defaults to the NAME section of the POD, the part B<before> the first
+C<->. Falls back to the script's filename.
+
 The PDB name of the function, i.e. the name under which it will be
 registered in the GIMP database. If it doesn't start with "perl_fu_",
 "file_", "plug_in_" or "extension_", it will be prepended. If you
@@ -601,32 +602,41 @@ C<perl_fu_>-prefix.
 
 =item blurb
 
-A small description of this script/plug-in. Defaults to "=pod(NAME)" (see
-the section on EMBEDDED POD DOCUMENTATION for an explanation of this
-string).
+Defaults to the NAME section of the POD, the part B<after> the first C<->.
+
+A one-sentence description of this script/plug-in.
 
 =item help
 
-A help text describing this script. Should be longer and more verbose than
-C<blurb>. Default is "=pod(HELP)".
+Defaults to the DESCRIPTION section of the POD.
+
+A help text describing this script. Should give more information than
+C<blurb>.
 
 =item author
 
-The name (and also the e-mail address if possible!) of the
-script-author. Default is "=pod(AUTHOR)".
+Defaults to the AUTHOR section of the POD.
+
+The name (and also the e-mail address if possible!) of the script-author.
 
 =item copyright
 
+Defaults to the LICENSE section of the POD.
+
 The copyright designation for this script. Important! Save your intellectual
-rights! The default is "=pod(AUTHOR)".
+rights!
 
 =item date
 
+Defaults to the DATE section of the POD.
+
 The "last modified" date of this script. There is no strict syntax here, but
-I recommend ISO format (yyyymmdd or yyyy-mm-dd). Default value is "=pod(DATE)".
+I recommend ISO format (yyyymmdd or yyyy-mm-dd).
 
 =item menu path
 
+Defaults to the SYNOPSIS section of the POD.
+
 The menu entry GIMP should create. B<Note> this is different from
 Script-Fu, which asks only for which B<menu> in which to place the entry,
 using the second argument to (its equivalent of) C<register> as the actual
@@ -640,14 +650,14 @@ It should start with one of the following:
 
 If the plugin works on or produces an image.
 
-If the "image types" argument (see below) is defined and non-zero-length,
+If the "imagetypes" argument (see below) is defined and non-zero-length,
 L<Gimp::Fu> will supply a C<PF_IMAGE> and C<PF_DRAWABLE> as the first
 two parameters to the plugin.
 
 If the plugin is intending to create an image rather than to work on
-an existing one, make sure you supply C<undef> or C<""> as the "image
-types". In that case, L<Gimp::Fu> will supply a C<PF_IMAGE> return value
-if the first return value is not a C<PF_IMAGE>.
+an existing one, make sure you supply C<undef> or C<""> as the
+"imagetypes". In that case, L<Gimp::Fu> will supply a C<PF_IMAGE> return
+value if the first return value is not a C<PF_IMAGE>.
 
 In any case, the plugin will be installed in the specified menu location;
 almost always under C<File/Create> or C<Filters>.
@@ -672,14 +682,28 @@ If the script does not need to have a menu entry.
 
 =back
 
-=item image types
+=item imagetypes
+
+Defaults to the "IMAGE TYPES" section of the POD.
 
 The types of images your script will accept. Examples are "RGB", "RGB*",
 "GRAY, RGB" etc... Most scripts will want to use "*", meaning "any type".
-Either C<undef> or "" will mean "none".
+Either C<undef> or "" will mean "none". Not providing the relevant POD
+section is perfectly valid, so long as you intend to create and return
+an image.
 
 =item the parameter array
 
+Defaults to the "PARAMETERS" section of the POD, passed to C<eval>, e.g.:
+
+  =head PARAMETERS
+
+    [ PF_COLOR, 'color', 'Colour', 'black' ],
+    [ PF_FONT, 'font', 'Font', 'Arial' ],
+
+You don't B<have> to indent it so that POD treats it as verbatim, but
+it will be more readable in the Help viewer if you do.
+
 An array reference containing parameter definitions. These are similar to
 the parameter definitions used for C<gimp_install_procedure> but include an
 additional B<default> value used when the caller doesn't supply one, and
@@ -693,8 +717,8 @@ and drawable (C<PF_DRAWABLE>) B<if and only if> the "image types"
 are defined and non-zero-length. Do not specify these yourself - see
 the C<menupath> entry above. Also, the C<run_mode> argument is never
 given to the script but its value can be accessed in the package-global
-C<$Gimp::Fu::run_mode>. The B<name> is used in the dialog box as a hint. The
-B<description> will be used as a tooltip.
+C<$Gimp::Fu::run_mode>. The B<description> will be used in the dialog
+box as a label.
 
 See the section PARAMETER TYPES for the supported types.
 
@@ -709,10 +733,14 @@ a C<PF_COLOR>.
 
 =item the return values
 
+Defaults to the "RETURN VALUES" section of the POD, passed to C<eval>.
+Not providing the relevant POD section is perfectly valid, so long as
+you intend to return no values.
+
 This is just like the parameter array except that it describes the
-return values. Specify the type and variable name only. This argument is
-optional. If you wish your plugin to return an image, you must specify
-that, e.g.:
+return values. Specify the type, variable name and description only. This
+argument is optional. If you wish your plugin to return an image, you
+must specify that (unless your "image types" is false, see below), e.g.:
 
   use Gimp;
   use Gimp::Fu;
@@ -720,12 +748,17 @@ that, e.g.:
      'function_name', "help", "blurb", "author", "copyright", "2014-04-11",
      "<Image>/Filters/Render/Do Something...",
      "*",
-     [ [PF_INT32, "input", "Input value", 1] ],
+     [ [PF_INT32, "imagesize", "Image size", 1] ],
      [ [PF_IMAGE, "output image", "Output image"] ],
      sub { Gimp::Image->new($_[0], $_[0], RGB) };
 
 If your "image types" is false, then L<Gimp::Fu> will ensure your first
-return parameter is a C<PF_IMAGE>.
+return parameter is a C<PF_IMAGE>. If for some reason you need to return
+an image value that will satisfy the requirement to return the right
+number of values but is invalid, you can return either -1 or C<undef>.
+
+You B<must> return the correct number (and types) of values from your
+function.
 
 =item the code
 
@@ -733,7 +766,7 @@ This is either an anonymous sub declaration (C<sub { your code here; }>, or a
 coderef, which is called when the script is run. Arguments (including the
 image and drawable for <Image> plug-ins) are supplied automatically.
 
-You must make sure your plugin returns the correct types of value, or none:
+You B<must> make sure your plugin returns the correct types of value, or none:
 
  sub {
    # no return parameters were specified
@@ -741,12 +774,13 @@ You must make sure your plugin returns the correct types of value, or none:
  };
 
 If you want to display images, you must have your script do
-that. C<Gimp::Fu> plugins will thereby be good GIMP "citizens", able to
-fit in with plugins/filters written in other languages.
+that. Gimp::Fu will no longer automatically do that for you, so your
+plugins will thereby be good GIMP "citizens", able to fit in with
+plugins/filters written in other languages.
 
 =back
 
-=head2 PARAMETER TYPES
+=head1 PARAMETER TYPES
 
 =over 2
 
@@ -757,7 +791,7 @@ All mapped to sliders or spinners with suitable min/max.
 =item PF_FLOAT, PF_VALUE
 
 For C<PF_FLOAT> (or C<PF_VALUE>, a synonym), you should probably use a
-C<PF_ADJUSTMENT> with suitable values.
+C<PF_SPINNER> or C<PF_SLIDER> with suitable values.
 
 =item PF_STRING
 
@@ -774,23 +808,22 @@ needs to be a suitable Gimp-Perl colour; see L<Gimp::canonicalize_colour>.
 
 =item PF_IMAGE
 
-A gimp image.
+A GIMP image.
 
 =item PF_DRAWABLE
 
-A gimp drawable (channel or layer).
+A GIMP drawable (channel or layer).
 
 =item PF_TOGGLE, PF_BOOL
 
-A boolean value (anything Perl would accept as true or false). The
-description will be used for the toggle-button label.
+A boolean value (anything Perl would accept as true or false).
 
 =item PF_SLIDER
 
 Uses a horizontal scale. To set the range and stepsize, append an
 array ref (see L<Gtk2::Adjustment> for an explanation) C<[range_min,
 range_max, step_size, page_increment, page_size]> as "extra argument"
-to the description array.  Default values will be substitued for missing
+to the description array.  Default values will be substituted for missing
 entries, like in:
 
  [PF_SLIDER, "alpha value", "the alpha value", 100, [0, 255, 1] ]
@@ -824,21 +857,57 @@ string. The default brush/pattern/gradient-name can be preset.
 
 =item PF_CUSTOM
 
-PF_CUSTOM is for those of you requiring some non-standard-widget. You have
-to supply a code reference returning three values as the extra argument:
+Example:
+
+  [PF_CUSTOM, "direction", "Direction to fade(0-8)", 4, sub {
+    my $btnTable = new Gtk2::Table(3,3,1);
+    $btnTable->set_border_width(6);
+    my $btn = new Gtk2::RadioButton;
+    my ($u_direction, @buttons);
+    for (my $x=0;$x<3;$x++) {
+      for (my $y=0;$y<3;$y++) {
+       my $dir = $x*3 + $y;
+       $buttons[$dir] = $btn = Gtk2::RadioButton->new_from_widget($btn);
+       $btn->set_mode(0);
+       $btn->signal_connect("clicked", sub { $u_direction = $_[1]; }, $dir);
+       $btn->show;
+       $btnTable->attach_defaults($btn, $x, $x+1, $y, $y+1);
+       my $pixmap = Gtk2::Image->new_from_pixmap(
+         Gtk2::Gdk::Pixmap->colormap_create_from_xpm_d(
+           undef, $btn->get_colormap,
+           $btn->style->bg('normal'), @{$arr[$dir]}
+         )
+       );
+       $pixmap->show;
+       $btn->add($pixmap);
+      }
+    }
+    $btnTable->show;
+    ($btnTable, sub { $buttons[$_[0]]->clicked }, sub { $u_direction });
+  },],
+
+C<PF_CUSTOM> is for those of you requiring some non-standard-widget. You
+supply a reference to code returning three values as the extra argument:
+
+=over 2
+
+=item C<widget>
 
- (widget, settor, gettor)
+Gtk2 widget that should be used.
 
-C<widget> is Gtk widget that should be used.
+=item C<settor>
 
-C<settor> is a function that takes a single argument, the new value for
-the widget (the widget should be updated accordingly).
+Function that takes a single argument, the new value for the widget
+(the widget should be updated accordingly).
 
-C<gettor> is a function that should return the current value of the widget.
+=item C<gettor>
 
-While the values can be of any type (as long as it fits into a scalar),
-you should be prepared to get a string when the script is started from the
-command line or via the PDB.
+Function returning the current value of the widget.
+
+=back
+
+The value set and returned must be a string. For an example of this,
+see C<examples/example-no-fu>.
 
 =item PF_FILE
 
@@ -852,37 +921,26 @@ Save, and Edit (in external editor) buttons.
 
 =back
 
-=head2 EMBEDDED POD DOCUMENTATION
+=head1 EMBEDDED POD DOCUMENTATION
 
-The register functions expects strings (actually scalars) for
-documentation, and nobody wants to embed long parts of documentation into
-a string, cluttering the whole script.
-
-Therefore, Gimp::Fu utilizes the Gimp::Pod module to display the full text
-of the pod sections that are embedded in your scripts (see L<perlpod> for
+Gimp::Fu uses the Gimp::Pod module to display the full text
+of the POD sections that are embedded in your scripts (see L<perlpod> for
 an explanation of the POD documentation format) when the user hits the
-"Help" button in the dialog box.
-
-Since version 1.094, you can embed specific sections or the full pod
-text into any of the blurb, help, author, copyright and date arguments
-to the register functions. Gimp::Fu will look into all these strings
-for sequences of the form "=pod(section-name)". If found, they will
-be replaced by the text of the corresponding section from the pod
-documentation. If the named section is not found (or is empty, as in
-"=pod()"), the full pod documentation is embedded.
+"Help" button in the dialog box. More importantly, various sections of the
+POD can be used instead of hardcoding strings in the call to C<register>.
 
-Most of the mentioned arguments have default values (see THE REGISTER
-FUNCTION) that are used when the arguments are undefined, making the
-register call itself much shorter.
+Most of the mentioned arguments have default values (see
+L</"THE REGISTER FUNCTION">) that are used when the arguments are
+undefined or false, making the register call itself much shorter.
 
-=head2 MISC. FUNCTIONS
+=head1 MISCELLANEOUS FUNCTIONS
 
-=over
+=over 2
 
 =item C<save_image(img,options_and_path)>
 
-This is the internal function used to save images. As it does more than just
-gimp_file_save, I thought it would be handy in other circumstances as well.
+This is the internal function used to save images, which does more than
+C<gimp_file_save>.
 
 The C<img> is the image you want to save (which might get changed during
 the operation!), C<options_and_path> denotes the filename and optional
diff --git a/Gimp/PixelRgn.pod b/Gimp/PixelRgn.pod
index 0c1c27f..4acfc3e 100644
--- a/Gimp/PixelRgn.pod
+++ b/Gimp/PixelRgn.pod
@@ -1,6 +1,6 @@
 =head1 NAME
 
-Gimp::PixelRgn - how to operate on raw pixels.
+Gimp::PixelRgn - Operate on raw pixels in powerful, efficient way.
 
 =head1 SYNOPSIS
 
@@ -12,7 +12,7 @@ Gimp::PixelRgn - how to operate on raw pixels.
   my $gd = $l->get;
   my $region = $gd->pixel_rgn(0,0,10,10,0,0);
   my $piddle = $region->get_pixel($x,$y);
-  print "@{[ unpdl $piddle ]}\n";
+  print $piddle."\n"; # stringified piddle is readable
 
 =head1 DESCRIPTION
 
diff --git a/Gimp/Util.pm b/Gimp/Util.pm
index 1027f41..ccc380b 100644
--- a/Gimp/Util.pm
+++ b/Gimp/Util.pm
@@ -1,6 +1,6 @@
 =head1 NAME
 
- Gimp::Util - some handy routines for Gimp-Perl users
+Gimp::Util - Handy routines for Gimp-Perl users
 
 =head1 SYNOPSIS
 
diff --git a/MANIFEST b/MANIFEST
index 9fd8a9c..cf95f14 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -19,7 +19,6 @@ Gimp/Fu.pm
 Gimp/Lib.pm
 Gimp/Lib.xs
 Gimp/Makefile.PL
-Gimp/OO.pod
 Gimp/PixelRgn.pod
 Gimp/Pod.pm
 Gimp/Util.pm
diff --git a/Net/Net.pm b/Net/Net.pm
index a2c893f..570ae8b 100644
--- a/Net/Net.pm
+++ b/Net/Net.pm
@@ -516,7 +516,7 @@ also *might* be buffer-overflows (although I do care a lot for these).
 The environment variable C<GIMP_HOST> specifies the default server to
 contact and/or the password to use. The syntax is
 [auth ][tcp/]hostname[:port] for tcp, [auth ]unix/local/socket/path for unix
-and spawn/ for a private gimp instance. Examples are:
+and spawn/ for a private GIMP instance. Examples are:
 
  www.yahoo.com               # just kidding ;)
  yahoo.com:11100             # non-standard port
diff --git a/TODO b/TODO
index af54eb1..3f8d079 100644
--- a/TODO
+++ b/TODO
@@ -2,8 +2,7 @@ Items as of 2014-04-19 (by Ed J)
 * <Load> and <Save> need any registration as such done in Gimp::Fu - see pod
 * image in Gimp.pm POD http://perlmaven.com/how-to-add-images-to-cpan -
   input image -> output image of a plugin
-* longer example in Gimp.pm/SYNOPSIS
-* examples POD (and Gimp::Pod TLC)
+* examples POD
 * Add Gimp::existing (Gimp::Fu IMAGE) and ::become (examples/xachshadows)
 * Gimp/Lib.xs is huge, and not very XS-y - lots of it is manually
   pushing GIMP data structures onto perl stack and vice versa. Figure
diff --git a/examples/billboard b/examples/billboard
index 06b6027..59f99aa 100755
--- a/examples/billboard
+++ b/examples/billboard
@@ -1,15 +1,11 @@
-#!/usr/bin/perl
-
-#TODO: figure out why adding a -w gives a bunch of "
-# Use of uninitialized value in subroutine entry at /usr/lib/perl/5.8/Gimp.pm
-# line 627." messages and fix it.
+#!/usr/bin/perl -w
 
 # I'm hacking this on top of my sethspin script, so this is doing even more
 # stuff it wasn't really designed to do.  Hence if you thought sethspin was
 # a bit ugly, look at this one...
 
 # I think it was tigert that suggested this.  It turned out to be less
-# complex than I orginally thought so I figured I'd give it a spin.
+# complex than I originally thought so I figured I'd give it a spin.
 
 # Seth Burgess
 # <sjburges gimp org>
@@ -18,171 +14,171 @@ use Gimp qw(:auto);
 use Gimp::Fu;
 use Gimp::Util;
 
+use constant PI => 3.14159;
+
 # Uncomment below to spew forth much data about whats going on.
 #Gimp::set_trace(TRACE_ALL);
 
 sub saw {  # a sawtooth function on PI
-       ($val) = @_;
-       if ($val < 3.14159/2.0) {
-               return ($val/3.14159) ;
-               }
-       elsif ($val < 3.14159) {
-               return (-1+$val/3.14159);
-               }
-       elsif ($val < 3.14159+3.14159/2.0) {
-               return ($val/3.14159) ;
-               }
-       else {
-               return (-1+$val/3.14159);
-               }
-       }
+  my $val = @_;
+  if ($val < PI * 0.5) {
+    return $val/PI ;
+  } elsif ($val < PI) {
+    return -1 + $val/PI;
+  } elsif ($val < PI * 1.5) {
+    return $val/PI ;
+  } else {
+    return -1 + $val/PI;
+  }
+}
 
 sub spin_layer { # the function for actually spinning the layer
-       my ($img, $spin, $dest, $numframes, $prp, $blinds) = @_;
-    # Now lets spin it!
-       $stepsize = 3.14159/$numframes; # in radians
-       for ($i=0; $i<=3.14159; $i+=$stepsize) {
-               Gimp->progress_update ($i/3.14159);
-               # create a new layer for spinning
-               $framelay = ($i < 3.14159/2.0) ?  $spin->copy(1) : $dest->copy(1);
-               $img->insert_layer($framelay, 0, 0);
-               # spin it a step
-       # Here I need to make the proper selection, repeatedly if necessary
-       $blindheight = $img->height/$blinds;
-               for ($j=0; $j<$blinds; $j++) {
-                       # select a section
-                       $img->select_rectangle(2, 0, $j*$blindheight, $img->width, $blindheight);
-                       @x = $img->selection_bounds();
-                       # x[1],x[2]                  x[3],x[2]
-               # x[1],x[4]                  x[3],x[4]
-                       $framelay->transform_perspective_default(
-               $x[1]+saw($i)*$prp*$framelay->width,$x[2]+$blindheight *sin($i)/2,
-               $x[3]-saw($i)*$prp*$framelay->width,$x[2]+$blindheight *sin($i)/2,
-               $x[1]-saw($i)*$prp*$framelay->width,$x[4]-$blindheight *sin($i)/2,
-               $x[3]+saw($i)*$prp*$framelay->width,$x[4]-$blindheight *sin($i)/2,
-               1, 1);
-
-# Gimp Perspective Functionality has changed.  It used to create a floating
-# selection if there was a selection active already.  Now it only does that
-# in interactive - PDB makes it a new layer.  Fine by me, wish the docs had
-# changed though.
-#                      $floater->floating_sel_anchor;
-
-               } # end for ($j=0;...
-
-               # I need to create another layer behind this spun one now
-               $backlayer = $framelay->layer_copy(0);
-               $img->insert_layer($backlayer, 0, 1);
-               $backlayer->fill(1); # BG-IMAGE-FILL
-       }
-       for ($i=0; $i<$numframes; $i++) {
-               @all_layers = $img->get_layers();
-               $img->set_visible($all_layers[$i],$all_layers[$i+1]);
-               $img->merge_visible_layers(0);
-               }
-       @all_layers = $img->get_layers();
-       $destfram = $all_layers[$numframes]->copy(0);
-       $img->insert_layer($destfram,0,0);
-
-       # clean up my temporary layers
-       $img->remove_layer($all_layers[$numframes]);
-       $img->remove_layer($all_layers[$numframes+1]);
+  my ($img, $spin, $dest, $numframes, $prp, $blinds) = @_;
+  # Now lets spin it!
+  $stepsize = 3.14159/$numframes; # in radians
+  for ($i=0; $i<=3.14159; $i+=$stepsize) {
+    Gimp->progress_update ($i/3.14159);
+    # create a new layer for spinning
+    $framelay = ($i < 3.14159/2.0) ?  $spin->copy(1) : $dest->copy(1);
+    $img->insert_layer($framelay, 0, 0);
+    # spin it a step
+    # Here I need to make the proper selection, repeatedly if necessary
+    $blindheight = $img->height/$blinds;
+    for ($j=0; $j<$blinds; $j++) {
+      # select a section
+      $img->select_rectangle(2, 0, $j*$blindheight, $img->width, $blindheight);
+      @x = $img->selection_bounds();
+      # x[1],x[2]                  x[3],x[2]
+      # x[1],x[4]                  x[3],x[4]
+      $framelay->transform_perspective_default(
+      $x[1]+saw($i)*$prp*$framelay->width,$x[2]+$blindheight *sin($i)/2,
+      $x[3]-saw($i)*$prp*$framelay->width,$x[2]+$blindheight *sin($i)/2,
+      $x[1]-saw($i)*$prp*$framelay->width,$x[4]-$blindheight *sin($i)/2,
+      $x[3]+saw($i)*$prp*$framelay->width,$x[4]-$blindheight *sin($i)/2,
+      1, 1);
+
+      #   Gimp Perspective Functionality has changed.  It used to create
+      #   a floating selection if there was a selection active already.
+      #   Now it only does that in interactive - PDB makes it a new layer.
+      #   Fine by me, wish the docs had changed though.
+      #$floater->floating_sel_anchor;
+
+    } # end for ($j=0;...
+
+    # I need to create another layer behind this spun one now
+    $backlayer = $framelay->layer_copy(0);
+    $img->insert_layer($backlayer, 0, 1);
+    $backlayer->fill(1); # BG-IMAGE-FILL
+  }
+  for ($i=0; $i<$numframes; $i++) {
+    @all_layers = $img->get_layers();
+    $img->set_visible($all_layers[$i],$all_layers[$i+1]);
+    $img->merge_visible_layers(0);
+  }
+  @all_layers = $img->get_layers();
+  $destfram = $all_layers[$numframes]->copy(0);
+  $img->insert_layer($destfram,0,0);
+
+  # clean up my temporary layers
+  $img->remove_layer($all_layers[$numframes]);
+  $img->remove_layer($all_layers[$numframes+1]);
 }
 
-register "billboard",
-        "Billboard",
-        "Take one image.  Spin it about the horizontal axis, and end up with another image.  I made it for 
easy web buttons, mostly because somebody suggested to me.",
-        "Seth Burgess",
-        "Seth Burgess <sjburges\ gimp org>",
-        "1.3",
-        N_"<Image>/Filters/Animation/Billboard...",
-        "*",
-        [
-         [PF_DRAWABLE, "source", "What drawable to spin from?"],
-         [PF_DRAWABLE, "destination","What drawable to spin to?"],
-                 [PF_INT8, "frames", "How many frames to use?", 16],
-                 [PF_COLOR, "background", "What color to use for background if not transparent", [0,0,0]],
-                 [PF_SLIDER, "perspective", "How much perspective effect to get", 40, [0,255,5]],
-                 [PF_TOGGLE, "spin_back", "Also spin back?" , 0],
-         [PF_TOGGLE, "convert_indexed", "Convert to indexed?", 1],
-                 [PF_SPINNER, "billboard_slats", "Number of shades", 3, [1,50,1]],
-        ],
-        [],
-        ['gimp-1.1'],
-        sub {
-   my($in_img,$src,$dest,$frames,$color,$psp,$spinback,$indexed, $shadenum) = _;
-       $maxwide = ($src->width > $dest->width) ? $src->width : $dest->width;
-       $maxhigh = ($src->height > $dest->height) ? $src->height: $dest->height;
-       $img = gimp_image_new($maxwide, $maxhigh, RGB);
-
-
-       $tmpimglayer = $img->add_new_layer(0,3,1);
-       $img->display_new;
-       Gimp->progress_init("Billboard...",-1);
-       Gimp::Context->push();
-       Gimp::Context->set_background($color);
-       $src->edit_copy();
-       $spinlayer = $tmpimglayer->edit_paste(1);
-       $spinlayer->floating_sel_to_layer();
-
-       $dest->edit_copy();
-       $destlayer = $tmpimglayer->edit_paste(1);
-       $destlayer->floating_sel_to_layer();
-
-       $tmpimglayer->remove_layer;
-
-       $spinlayer->resize($maxwide, $maxhigh, $spinlayer->offsets);
-       $destlayer->resize($maxwide, $maxhigh, $destlayer->offsets);
-       # work around for PF_SLIDER when < 1
-       $psp = $psp/255.0;
-
-       # need an even number of frames for spinback
-       if ($frames%2 && $spinback) {
-               $frames++;
-               gimp_message("An even number of frames is needed for spin back.\nAdjusted frames up to 
$frames");
-               }
-
-       spin_layer($img, $spinlayer, $destlayer, $spinback ? $frames/2 : $frames-1, $psp, $shadenum);
-        $img->set_visible($img->add_new_layer(1),($img->get_layers)[0]);
-        $img->merge_visible_layers(0);
-
-       if ($spinback) {
-               @layerlist = $img->get_layers();
-               $img->insert_layer($layerlist[$frames/2]->copy(0),0,0);
-               @layerlist = $img->get_layers();
-               spin_layer($img, $layerlist[1], $layerlist[0], $frames/2, $psp, $shadenum);
-               $img->remove_layer(($img->get_layers)[0]);
-               }
-
-       # unhide and name layers
-       @all_layers = $img->get_layers;
-       $img->set_visible(@all_layers);
-       for ($i=1; $i<=$frames ; $i++) {
-               $all_layers[$i-1]->set_name("Spin Layer $i (50ms)");
-               }
-       $all_layers[$frames-1]->set_name("Spin Layer SRC (250ms)");
-
-       if ($spinback) {
-               $all_layers[$frames/2-1]->set_name("Spin Layer DEST (250ms)");
-               }
-       else { $all_layers[0]->set_name("Spin Layer DEST (250ms)")}
-
-
-       # indexed conversion wants a display for some reason
-       if ($indexed) {
-          $img->convert_indexed(1,            # dither type = fs
-                                MAKE_PALETTE, # palette type
-                                255,          # number of colors
-                                0,            # don't dither transparency
-                                1,            # (ignored)
-                                "Custom"      # custom palette name
-                                );
-          }
-
-       Gimp::Context->pop();
-       gimp_displays_flush();
-       return();
-};
+register
+  "billboard",
+  "Billboard",
+  "Take one image.  Spin it about the horizontal axis, and end up with another image.  I made it for easy 
web buttons, mostly because somebody suggested to me.",
+  "Seth Burgess",
+  "Seth Burgess <sjburges\ gimp org>",
+  "1.3",
+  N_"<Image>/Filters/Animation/Billboard...",
+  "*",
+  [
+    [PF_DRAWABLE, "destination","What drawable to spin to?"],
+    [PF_INT8, "frames", "How many frames to use?", 16],
+    [PF_COLOR, "background", "What color to use for background if not transparent", 'black'],
+    [PF_INT8, "perspective", "How much perspective effect to get", 40],
+    [PF_TOGGLE, "spin_back", "Also spin back?" , 0],
+    [PF_TOGGLE, "convert_indexed", "Convert to indexed?", 1],
+    [PF_SPINNER, "billboard_slats", "Number of shades", 3, [1,50,1]],
+  ],
+  [],
+  sub {
+    my($in_img,$src,$dest,$frames,$color,$psp,$spinback,$indexed,$shadenum)= _;
+    $maxwide = ($src->width > $dest->width) ? $src->width : $dest->width;
+    $maxhigh = ($src->height > $dest->height) ? $src->height: $dest->height;
+    $img = gimp_image_new($maxwide, $maxhigh, RGB);
+
+    $tmpimglayer = $img->add_new_layer(0,3,1);
+    $img->display_new;
+    Gimp->progress_init("Billboard...",-1);
+    Gimp::Context->push();
+    Gimp::Context->set_background($color);
+    $src->edit_copy();
+    $spinlayer = $tmpimglayer->edit_paste(1);
+    $spinlayer->floating_sel_to_layer();
+
+    $dest->edit_copy();
+    $destlayer = $tmpimglayer->edit_paste(1);
+    $destlayer->floating_sel_to_layer();
+
+    $tmpimglayer->remove_layer;
+
+    $spinlayer->resize($maxwide, $maxhigh, $spinlayer->offsets);
+    $destlayer->resize($maxwide, $maxhigh, $destlayer->offsets);
+    # work around for PF_SLIDER when < 1
+    $psp = $psp/255.0;
+
+    # need an even number of frames for spinback
+    if ($frames%2 && $spinback) {
+      $frames++;
+      gimp_message(<<EOF);
+An even number of frames is needed for spin back.
+Adjusted frames up to $frames
+EOF
+    }
+
+    spin_layer($img, $spinlayer, $destlayer, $spinback ? $frames/2 : $frames-1, $psp, $shadenum);
+    $img->set_visible($img->add_new_layer(1),($img->get_layers)[0]);
+    $img->merge_visible_layers(0);
+
+    if ($spinback) {
+      @layerlist = $img->get_layers();
+      $img->insert_layer($layerlist[$frames/2]->copy(0),0,0);
+      @layerlist = $img->get_layers();
+      spin_layer($img, $layerlist[1], $layerlist[0], $frames/2, $psp, $shadenum);
+      $img->remove_layer(($img->get_layers)[0]);
+    }
+
+    # unhide and name layers
+    @all_layers = $img->get_layers;
+    $img->set_visible(@all_layers);
+    for ($i=1; $i<=$frames ; $i++) {
+      $all_layers[$i-1]->set_name("Spin Layer $i (50ms)");
+    }
+    $all_layers[$frames-1]->set_name("Spin Layer SRC (250ms)");
+
+    if ($spinback) {
+      $all_layers[$frames/2-1]->set_name("Spin Layer DEST (250ms)");
+    } else {
+      $all_layers[0]->set_name("Spin Layer DEST (250ms)");
+    }
+
+    # indexed conversion wants a display for some reason
+    if ($indexed) {
+      $img->convert_indexed(1,            # dither type = fs
+        MAKE_PALETTE, # palette type
+        255,          # number of colors
+        0,            # don't dither transparency
+        1,            # (ignored)
+        "Custom"      # custom palette name
+      );
+    }
+
+    Gimp::Context->pop();
+    gimp_displays_flush();
+    return();
+  };
 
 exit main;
 
@@ -190,7 +186,4 @@ exit main;
 
 Copyright Seth Burgess.
 
-Distrubted under the same terms as Gimp-Perl.
-
-=cut
-
+Distributed under the same terms as Gimp-Perl.
diff --git a/examples/dots b/examples/dots
index f29bb44..8312419 100755
--- a/examples/dots
+++ b/examples/dots
@@ -1,109 +1,98 @@
 #!/usr/bin/perl
 
-# <sjburges gimp org>
-# Generate dots within a selection.
-
 #BEGIN { $Gimp::verbose = 1; }
-use Gimp qw(:auto __ N_);
+use Gimp;
 use Gimp::Fu;
-use Gimp::Util;
-
 #Gimp::set_trace(TRACE_ALL);
 
-register "dots",
-         "Dots",
-         "Create evenly spaced dots on a layer, within a selection.",
-         "Seth Burgess",
-         "Seth Burgess <sjburges\ gimp org>",
-         "2003-09-20",
-         N_"<Image>/Filters/Render/Pattern/Dots...",
-         "RGB*, GRAY*",
-         [
-           [PF_SPINNER, "size", "Diameter of dots", 4, [1,255,1]],
-          [PF_COLOR, "dotcolor", "Color of the dots", [0,0,255]],
-          [PF_SLIDER, "opacity", "Opacity of dots", 100, [0,100,1]],
-           [PF_SPINNER, "xspacing", "Spacing of dots in X dimension", 16, [1,255,1]],
-           [PF_SPINNER, "yspacing", "Spacing of dots in Y dimension", 16, [1,255,1]],
-           [PF_SPINNER, "xoffset", "Offset of dots in X dimension", 0, [0,255,1]],
-           [PF_SPINNER, "yoffset", "Offset of dots in y dimension", 0, [0,255,1]],
-            ],
-         [],
-         sub {
-    my($img,$layer,$size,$dotcolor,$opacity,$xspacing,$yspacing,$xoffset,$yoffset) = _;
-    my $has_noselection;
-    $layer->is_layer || die "A layer is required for this plugin";
-
-    $yoffset = $yoffset % $yspacing;
-    $xoffset = $xoffset % $xspacing;
-
-    $img->undo_group_start;
-
+podregister {
+  my($img,$layer,$size,$color,$opacity,$xspacing,$yspacing,$xoffset,$yoffset) = _;
+  my $has_noselection;
+  $layer->is_layer || die "A layer is required for this plugin";
+  $yoffset %= $yspacing;
+  $xoffset %= $xspacing;
+  $img->undo_group_start;
 # Get/save current selection info
-    @bounds = $img->selection_bounds;
-    if (!$bounds[0])
-      {
-         $img->selection_all;
-        $has_noselection=1;
-      }
-    $selchannel = $img->selection_save;
-
+  if (!($img->selection_bounds)[0]) {
+    $img->selection_all;
+    $has_noselection=1;
+  }
+  $selchannel = $img->selection_save;
 # Generate selection mask of dots on entire image
+  $img->selection_none;
+  for ($x=$xoffset-$xspacing; $x<$img->width+$size+$xspacing; $x+=$xspacing) {
+    for (
+      $y=$yoffset-$yspacing; $y<$img->height+$size+$yspacing; $y+=$yspacing
+    ) {
+      $img->select_ellipse(CHANNEL_OP_ADD,$x-0.5*$size,$y-0.5*$size,
+      $size,$size);
+    }
+  }
+# Set opacity of dots via selection mask
+  Gimp::Context->push;
+  $opc = Gimp::Channel->new($img,$img->width,$img->height,"OPC", 50, [0,0,0]);
+  $img->insert_channel($opc,0,0);
+  Gimp::Context->set_foreground([($opacity/100.0)x3]);
+  $opc->fill(FOREGROUND_FILL);
+  $img->select_item(CHANNEL_OP_INTERSECT, $opc);
+# And mask off with original selection
+  $img->select_item(CHANNEL_OP_INTERSECT, $selchannel);
+# Make the dots
+  Gimp::Context->set_foreground($color);
+  $layer->edit_fill(FOREGROUND_FILL);
+# Cleanup to state before plugin was called
+  if ($has_noselection) {
     $img->selection_none;
-    for ($x=$xoffset-$xspacing;
-         $x<$img->width+$size+$xspacing;
-        $x+=$xspacing)
-      {
-         for ($y=$yoffset-$yspacing;
-             $y<$img->height+$size+$yspacing;
-             $y+=$yspacing)
-          {
-            $img->select_ellipse(CHANNEL_OP_ADD,$x-0.5*$size,$y-0.5*$size,
-                                 $size,$size);
-           }
-      }
+  } else {
+    $img->select_item(CHANNEL_OP_REPLACE, $selchannel);
+  }
+  $img->remove_channel($selchannel);
+  $img->remove_channel($opc);
+  Gimp::Context->pop;
+  $img->undo_group_end;
+  $layer->set_active_layer;
+  return;
+};
 
-# Set opacity of dots via selection mask
-    Gimp::Context->push();
+exit main;
+__END__
 
-    $opc = gimp_channel_new($img,$img->width,$img->height,"OPC", 50, [0,0,0]);
-    $img->insert_channel($opc,0,0);
-    Gimp::Context->set_foreground([($opacity/100.0)x3]);
-    $opc->fill(FOREGROUND_FILL);
-    $img->select_item(CHANNEL_OP_INTERSECT, $opc);
+=head1 NAME
 
-# And mask off with original selection
-    $img->select_item(CHANNEL_OP_INTERSECT, $selchannel);
+dots - Create evenly spaced dots on a layer, within a selection
 
-# Make the dots
-    Gimp::Context->set_foreground($dotcolor);
-    $layer->edit_fill(FOREGROUND_FILL);
+=head1 SYNOPSIS
 
-# Cleanup to state before plugin was called
-    if ($has_noselection)
-      {
-        $img->selection_none;
-      }
-    else
-      {
-       $img->select_item(CHANNEL_OP_REPLACE, $selchannel);
-      }
+<Image>/Filters/Render/Pattern/Dots...
 
-    $img->remove_channel($selchannel);
-    $img->remove_channel($opc);
+=head1 DESCRIPTION
 
-    Gimp::Context->pop();
+Create evenly spaced dots of the given colour on a layer, within a
+selection (or on whole layer if no selection).
 
-    $img->undo_group_end;
-    $layer->set_active_layer;
+=head1 PARAMETERS
 
-    return();
-};
-exit main;
+  [PF_SPINNER, "size", "Diameter of dots", 4, [1,255,1]],
+  [PF_COLOR, "dotcolor", "Color of the dots", [0,0,255]],
+  [PF_SLIDER, "opacity", "Opacity of dots", 100, [0,100,1]],
+  [PF_SPINNER, "xspacing", "Spacing of dots in X dimension", 16, [1,255,1]],
+  [PF_SPINNER, "yspacing", "Spacing of dots in Y dimension", 16, [1,255,1]],
+  [PF_SPINNER, "xoffset", "Offset of dots in X dimension", 0, [0,255,1]],
+  [PF_SPINNER, "yoffset", "Offset of dots in y dimension", 0, [0,255,1]],
+
+=head1 IMAGE TYPES
+
+RGB*, GRAY*
+
+=head1 AUTHOR
+
+Seth Burgess <sjburges gimp org>
+
+=head1 DATE
+
+2003-09-20
 
 =head1 LICENSE
 
 Copyright Seth Burgess.
 Distributed under the same terms as Gimp-Perl.
-
-=cut
-
diff --git a/examples/dust b/examples/dust
index 3bb0343..338dd5a 100755
--- a/examples/dust
+++ b/examples/dust
@@ -52,22 +52,7 @@ use Gimp::Util;
 # the next line  just shows a graph of the "random" numbers.
 #set_seed 0; use PDL; use PDL::Graphics::PGPLOT; line(pdl(float,map gen_rand, 1..500));
 
-register "dust",
-         "",
-         "",
-         "Marc Lehmann",
-         "Marc Lehmann <pcg\ goof com",
-         "0.1",
-         N_"<Image>/Filters/Render/Add Dust...",
-         "*",
-         # Eingabeparameter
-         # Typ         Name            Beschreibung            Wert
-         [
-          [PF_FLOAT,   'density',      'dust density in dust/pixel',    0.0001],
-          [PF_INT32,   'seed',         'the random seed (0 == unspecified)', 0],
-          [PF_SPINNER, 'length',       'the average dust corn length', 50, [1,300]],
-         ],
-         sub {                                 # Perl-Code
+podregister {
    # Die Parameter werden ganz "normal" �bergeben:
    my ($image, $layer, $density, $seed, $len) = @_;
 
@@ -135,11 +120,40 @@ register "dust",
 #         };
 
 exit main;
+__END__
 
-=head1 LICENSE
+=head1 NAME
 
-Copyright Marc Lehman.
-Distributed under the same terms as Gimp-Perl.
+dust - Add dust to image
+
+=head1 SYNOPSIS
+
+<Image>/Filters/Render/Add Dust...
+
+=head1 DESCRIPTION
+
+Add the appearance of dust to an image.
+
+=head1 PARAMETERS
+
+  [PF_FLOAT,   'density',      'dust density in dust/pixel',    0.0001],
+  [PF_INT32,   'seed',         'the random seed (0 == unspecified)', 0],
+  [PF_SPINNER, 'length',       'the average dust corn length', 50, [1,300]],
+
+=head1 IMAGE TYPES
 
-=cut
+*
 
+=head1 AUTHOR
+
+Marc Lehmann <pcg goof com>
+
+=head1 DATE
+
+Version 0.1
+
+=head1 LICENSE
+
+Copyright Marc Lehmann.
+
+Distributed under the same terms as Gimp-Perl.
diff --git a/examples/example-fu b/examples/example-fu
index dc98d23..5cf3443 100755
--- a/examples/example-fu
+++ b/examples/example-fu
@@ -1,87 +1,77 @@
 #!/usr/bin/perl
 
+use strict;
 use Gimp;
 use Gimp::Fu;
 
-# expand your terminal to 121 across to read easily...
-
-register
-  "gimp_fu_example_script",                    # fill in a function name
-  "An example of Gimp::Fu usage, mostly non-functional",       # and a short description,
-  "Just a starting point to derive new ".        # a (possibly multiline) help text
-    "scripts. Always remember to put a long".
-    "help message here!",
-  "Marc Lehmann <pcg\ goof com>",              # don't forget your name (author)
-  "(c)1998,1999,2000 Marc Lehmann",            # and your copyright!
-  "20000321",                                  # the date this script was written (YYYYMMDD)
-  N_"<Toolbox>/Xtns/Perl/Gimp::Fu Example...", # the menu path - the 'N_' is for internationalization
-  "",                                          # image types to accept (RGB, RGAB and GRAYA) - blank or 
undef means don't need one
-  [ # one of each type of parameter here
-    # argument type, switch name       , a short description           , default value, extra arguments
-    [PF_SLIDER , "width"       , "The image width"             , 360, [300, 500]],
-    [PF_SPINNER        , "height"      , "The image height"            , 100, [100, 200]],
-    [PF_STRING , "text"        , "The Message"                 , "example text"],
-    [PF_INT32  , "bordersize"  , "The bordersize"              , 10],
-    [PF_FLOAT  , "borderwidth" , "The borderwidth"             , 1/5],
-    [PF_FONT   , "font"        , "The Font Family"             ],
-    [PF_COLOUR , "text_colour" , "The (foreground) text colour", [10,10,10]],
-    [PF_COLOUR , "bg_colour"   , "The background colour"       , [0xff,0x80,0]],
-    [PF_TOGGLE , "ignore_cols" , "Ignore colours"              , 0],
-    [PF_IMAGE  , "extra_image" , "An additonal picture to ignore"],
-    [PF_DRAWABLE       , "extra_draw"  , "Somehting to ignroe as well" ],
-    [PF_RADIO  , "type"        , "The effect type"             , 0, [small => 0, large => 1]],
-    [PF_BRUSH  , "a_brush"     , "An unused brush"             ],
-    [PF_PATTERN        , "a_pattern"   , "An unused pattern"           ],
-    [PF_GRADIENT       , "a_gradients" , "An unused gradients"         ],
-  ],
-  [
-    [PF_IMAGE  , "output image", "Output image"],
-  ],
-  sub {
-
-   # now do something useful with our parameters
-   
my($width,$height,$text,$brd1,$brd2,$font,$fg,$bg,$ignore,$xtraimg,$xtradrw,$effecttype,$brush,$pattern,$gradient)=
 _;
-
-   # set tracing, disable this to get rid of the debugging output
-   Gimp::set_trace(TRACE_CALL);
-
-   # store current context, so that present settings aren't affected
-   Gimp::Context->push();
-
-   my $img = new Gimp::Image ($width, $height, RGB);
-
-   # put an undo group around any modifications, so that
-   # they can be undone in one step.
-   $img->undo_group_start;
-
-   # the __ before the string in the next line indicates text that must be translated
-   my $l = new Gimp::Layer ($img, $width, $height, RGB, __"Background", 100, NORMAL_MODE);
-   $l->insert_layer(0, 0);
-
-   # now a few syntax examples
-
-   Gimp::Context->set_foreground($fg) unless $ignore;
-   Gimp::Context->set_background($bg) unless $ignore;
-
-   fill $l BACKGROUND_FILL;
-   my $text_layer = $img->text_fontname(-1, 10, 10, $text, 5, 1, 10, PIXELS, $font);
-
-   Gimp::Context->set_foreground("green");
-
-   # close the undo push group
-   $img->undo_group_end;
-
-   # restore original context
-   Gimp::Context->pop();
-
-   $img;       # return the image, as it's on our output parameters
+podregister {
+  
my($width,$height,$text,$longtext,$brd1,$brd2,$font,$fg,$bg,$ignore,$xtraimg,$xtradrw,$effecttype,$brush,$pattern,$gradient)=
 _;
+  Gimp::set_trace(TRACE_CALL); # remove this to stop debugging output
+  Gimp::Context->push; # store current settings, so present ones preserved
+  my $img = Gimp::Image->new($width, $height, RGB);
+  $img->undo_group_start; # so all actions can be undone in one step
+  # the __ before the string will translate it if available
+  my $l = Gimp::Layer->new($img, $width, $height, RGB, __"Background", 100, NORMAL_MODE);
+  $l->insert_layer(0, 0); # required!
+  # now a few syntax examples
+  Gimp::Context->set_foreground($fg) unless $ignore;
+  Gimp::Context->set_background($bg) unless $ignore;
+  fill $l BACKGROUND_FILL;
+  my $text_layer = $img->text_fontname(-1, 10, 10, $text, 5, 1, 10, PIXELS, $font);
+  Gimp::Context->set_foreground("green");
+  $img->undo_group_end; # close the undo group
+  Gimp::Context->pop; # restore original context
+  Gimp::Display->new($img);
+  $img; # return image, as Gimp::Fu added that to our output parameters
+        # because no-image-input
 };
 
 exit main;
-=head1 LICENSE
+__END__
 
-Copyright Marc Lehman.
-Distributed under the same terms as Gimp-Perl.
+=head1 NAME
+
+example_script - Gimp::Fu example, mostly non-functional
+
+=head1 SYNOPSIS
+
+<Image>/Filters/Languages/_Perl/_Test/Dialog
+
+=head1 DESCRIPTION
+
+Just a starting point to derive new scripts. Always remember to put a
+long help message here!
+
+=head1 PARAMETERS
 
-=cut
+  # one of each type of parameter here
+  # argument type, variable name, short description, default, extra arguments
+  [PF_SLIDER   , "width"       , "Image width"         , 360, [300, 500]],
+  [PF_SPINNER  , "height"      , "Image height"        , 100, [100, 200]],
+  [PF_STRING   , "text"        , "Message"             , "example text"],
+  [PF_TEXT     , "longtext"    , "Longer text"         , "more example text"],
+  [PF_INT32    , "bordersize"  , "Border size"         , 10],
+  [PF_FLOAT    , "borderwidth" , "Border width"        , 1/5],
+  [PF_FONT     , "font"        , "Font"],
+  [PF_COLOUR   , "text_colour" , "Text colour", [10,10,10]],
+  [PF_COLOUR   , "bg_colour"   , "Background colour"   , [0xff,0x80,0]],
+  [PF_TOGGLE   , "ignore_cols" , "Ignore colours"      , 0],
+  [PF_IMAGE    , "extra_image" , "Additional picture to ignore"],
+  [PF_DRAWABLE , "extra_draw"  , "Something to ignore as well" ],
+  [PF_RADIO    , "type"        , "Effect type"         , 0, [small => 0, large => 1]],
+  [PF_BRUSH    , "a_brush"     , "An unused brush"],
+  [PF_PATTERN  , "a_pattern"   , "An unused pattern"],
+  [PF_GRADIENT , "a_gradients" , "An unused gradients"],
 
+=head1 AUTHOR
+
+Marc Lehmann <pcg goof com>
+
+=head1 DATE
+
+2000-03-21
+
+=head1 LICENSE
+
+(c) 1998,1999,2000 Marc Lehmann
+Distributed under the same terms as Gimp-Perl.
diff --git a/examples/exceptiontest b/examples/exceptiontest
index c4ab5f2..81f9bfd 100755
--- a/examples/exceptiontest
+++ b/examples/exceptiontest
@@ -21,7 +21,7 @@ sub boilerplate_params {
   "test_exception",
   boilerplate_params(
     'exceptions',
-    '<Image>/Filters/Languages/_Perl/Test/Exception', '',
+    '<Image>/Filters/Languages/_Perl/_Test/Exception', '',
   ),
   [],
   sub { die "I DIED\n" }
diff --git a/examples/fade-alpha b/examples/fade-alpha
index 1f455cb..da6136d 100755
--- a/examples/fade-alpha
+++ b/examples/fade-alpha
@@ -1,26 +1,17 @@
 #!/usr/bin/perl -w
 
-use Gtk2;
-use Gimp qw(:auto);
-
-use strict 'vars';
-
-# Gimp::set_trace(TRACE_ALL);
+use Gimp;
+use Gimp::Fu;
+use strict;
 
+# 2014/04/20 Ed J: rewrite to use Gimp::Fu and PF_CUSTOM
 # 12/5/03: <sjburges gimp org>
 #  s/->mask/->get_mask
 # 3/21/04: <sjburges gimp org>
 #  s/AlphaFade/alpha_fade/ to be compatible with PDB naming conventions
 
-###
-# Globals
-###
-my ($direction, $cancelFlag);
-my ($plugin) = "plug_in_alpha_fade";
-
-# XPM's that I removed the $ and the @'s from (they get intrepreted in
+# XPM's that I removed the $ and the @'s from (they get interpreted in
 # strings, which makes for nasty problems).
-
 my @arr = (
 ["24 24 66 1",
 "      c None",
@@ -783,305 +774,106 @@ my @arr = (
 "WWWWWWWWWWWWWWWWWWWWWWWW"
 ]);
 
-###
-# Subroutines
-###
-sub do_fade
-{
-  my ($image, $drawable) = @_;
-  my (@bounds, $mask, $prevBack, $prevFore);
-
-  if (!$drawable->is_layer)
-    {
-      die "$plugin: Cannot operate on anything other than layers; Check that you don't have a channel or 
floating selection currently selected.";
-    }
-
-  $image->undo_group_start;
-  @bounds = $image->selection_bounds;
-
-  if (!$drawable->has_alpha)
-    {
-      $drawable->add_alpha;
-    }
-
-  if ($drawable->get_mask)
-    {
-      $mask = $drawable->get_mask;
-    }
-  else
-    {
+sub avg { ($_[0] + $_[1]) / 2 }
+
+register
+  "alpha_fade",
+  "Fade the alpha channel of a layer from one side to another",
+  <<EOF,
+Rewritten by Ed J to use Gimp::Fu as demo of PF_CUSTOM widget. Original
+by Seth Burgess, inspired by a mailing list question that asked how to do
+exactly what this does, which is fade the alpha from one side to another.
+EOF
+  "Seth Burgess",
+  "Seth Burgess",
+  "2000",
+  "<Image>/Layer/Transparency/_Fade...",
+  "*",
+  [
+    [PF_CUSTOM, "direction", "Direction to fade(0-8)", 4, sub {
+      my $btnTable = new Gtk2::Table(3,3,1);
+      $btnTable->set_border_width(6);
+      my $btn = new Gtk2::RadioButton;
+      my $u_direction;
+      my @buttons;
+      for (my $x=0;$x<3;$x++) {
+       for (my $y=0;$y<3;$y++) {
+         my $dir = $x*3 + $y;
+         $buttons[$dir] = $btn = Gtk2::RadioButton->new_from_widget($btn);
+         $btn->set_mode(0);
+         $btn->signal_connect("clicked", sub { $u_direction = $_[1]; }, $dir);
+         $btn->show;
+         $btnTable->attach_defaults($btn, $x, $x+1, $y, $y+1);
+         my $pixmap = Gtk2::Image->new_from_pixmap(
+           Gtk2::Gdk::Pixmap->colormap_create_from_xpm_d(
+             undef, $btn->get_colormap,
+             $btn->style->bg('normal'), @{$arr[$dir]}
+           )
+         );
+         $pixmap->show;
+         $btn->add($pixmap);
+       }
+      }
+      $btnTable->show;
+      ($btnTable, sub { $buttons[$_[0]]->clicked }, sub { $u_direction });
+    },
+  ]
+  ],
+  [],
+  sub {
+    my ($image, $drawable, $direction) = @_;
+    die "Can only operate on layers\n" unless $drawable->is_layer;
+    $drawable->become('Gimp::Layer');
+    $image->undo_group_start;
+    my @bounds = $image->selection_bounds;
+    $drawable->add_alpha unless $drawable->has_alpha;
+    my $mask;
+    unless ($mask = $drawable->get_mask) {
       $mask = $drawable->create_mask(ADD_ALPHA_MASK);
       $drawable->add_mask($mask);
     }
-
-  Gimp::Context->push();
-
-  Gimp::Context->set_background([0.0,0.0,0.0,1.0]);
-  Gimp::Context->set_foreground([1.0,1.0,1.0,1.0]);
-
-  # Direction Map
-  # 0 3 6
-  # 1 4 7
-  # 2 5 8
-
-  # Bounds Map
-  # (1,2) (3,2)
-  # (1,4) (3,4)
-
-  if ($direction==0)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE,
-                   NORMAL_MODE,
-                  GRADIENT_LINEAR,
-                  100.0,             # opacity
-                  0.0,               # offset
-                   REPEAT_NONE,
-                  0,                 # reverse
-                  0,                 # supersample
-                  1,                 # recursion levels
-                  0.1,               # supersample threshold
-                  0,                 # dither
-                  $bounds[3], $bounds[4],
-                  $bounds[1], $bounds[2]);
-    }
-  elsif ($direction==1)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  $bounds[3], ($bounds[2]+$bounds[4])/2,
-                  $bounds[1], ($bounds[2]+$bounds[4])/2);
-
-    }
-  elsif ($direction==2)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  $bounds[3], $bounds[2],
-                  $bounds[1], $bounds[4]);
-
-    }
-  elsif ($direction==3)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  ($bounds[3]+$bounds[1])/2, $bounds[4],
-                  ($bounds[3]+$bounds[1])/2, $bounds[2]);
-    }
-  elsif ($direction==4)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_RADIAL, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  ($bounds[1]+$bounds[3])/2,
-                  ($bounds[2]+$bounds[4])/2,
-                  ($bounds[3]+$bounds[1])/2, $bounds[4]);
-
-    }
-  elsif ($direction==5)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  ($bounds[3]+$bounds[1])/2, $bounds[2],
-                  ($bounds[3]+$bounds[1])/2, $bounds[4]);
-    }
-  elsif ($direction==6)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  $bounds[1], $bounds[4],
-                  $bounds[3], $bounds[2]);
-    }
-  elsif ($direction==7)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  $bounds[1], ($bounds[2]+$bounds[4])/2,
-                  $bounds[3], ($bounds[2]+$bounds[4])/2);
-    }
-  elsif ($direction==8)
-    {
-      $mask->edit_blend(FG_BG_RGB_MODE, DARKEN_ONLY_MODE, GRADIENT_LINEAR, 100.0, 0.0,
-                   REPEAT_NONE, 0, 0, 0, 1, 0,
-                  $bounds[1], $bounds[2],
-                  $bounds[3], $bounds[4]);
-    }
-  if ($direction >=0 && $direction <9)
-    {
-      $drawable->remove_mask(MASK_APPLY);
-    }
-
-  Gimp::Context->pop();
-  $image->undo_group_end;
-}
-
-sub btn_pressed
-{
-  my ($widget, $btnIndex) = @_;
-  $direction = $btnIndex;
-}
-
-sub add_pixmap
-{
-  my ($window, $but, $num) = @_;
-  my @tar = @{$arr[$num]};
-  my ($pixmap, $mask) = Gtk2::Gdk::Pixmap->colormap_create_from_xpm_d(undef,
-                        $but->get_colormap,
-                        $but->style->bg('normal'),
-                       @{$arr[$num]});
-  my ($pixmapId) = new_from_pixmap Gtk2::Image($pixmap, $mask);
-
-  $pixmapId->show;
-  $but->add($pixmapId);
-}
-
-sub okCbk
-{
-  $cancelFlag = 0;
-  Gtk2->main_quit;
-}
-
-sub create_window
-{
-  my ($window, $frm, $box1, $hbox, $hsep, $btnTable, $i, $j, $btn);
-
-  $window = new Gtk2::Window('toplevel');
-  $window->set_name("Alpha Fader");
-  $window->set_wmclass("Gimp", "AlphaFader");
-
-  $window->signal_connect("destroy" => \&Gtk2::main_quit);
-  $window->signal_connect("delete_event" => \&Gtk2::false);
-
-  $box1 = new Gtk2::VBox(0, 0);
-  $box1->set_spacing(2);
-  $window->add($box1);
-
-  $frm = new Gtk2::Frame "Fade Type";
-  $frm->set_border_width(6);
-  $frm->show;
-
-  $box1->pack_start($frm, 1, 1, 0);
-  $btnTable = new Gtk2::Table(3,3,1);
-  $btnTable->set_border_width(6);
-  $frm->add($btnTable);
-
-  $btn = new Gtk2::RadioButton;
-
-  for ($i=0;$i<3;$i++)
-    {
-      for ($j=0;$j<3;$j++)
-        {
-          $btn = Gtk2::RadioButton->new_from_widget($btn);
-           $btn->set_mode(0);
-          $btn->signal_connect("clicked", \&btn_pressed, $i*3+$j);
-          $btn->show;
-          $btnTable->attach_defaults($btn, $i, $i+1, $j, $j+1);
-          add_pixmap($window, $btn, $i*3+$j);
-
-          if (Gimp->get_data($plugin) ne "")
-            { # if run before, get last data
-              if (Gimp->get_data($plugin) == $i*3+$j)
-                {
-                  $btn->clicked;
-                }
-            }
-          else
-            { # first run of plug-in, set first button
-              if ($i==0 && $j==0)
-                {
-                  $btn->clicked;
-                }
-             }
-       }
-    }
-
-  $hsep = new Gtk2::HSeparator;
-  $box1->pack_start($hsep, 0, 0, 0);
-  $hsep->show;
-
-  $hbox = new Gtk2::HButtonBox;
-  $hbox->set_border_width(2);
-  $hbox->set_spacing(4);
-  $box1->pack_start($hbox, 0, 0, 0);
-  $hbox->show;
-
-  $btn = new Gtk2::Button "OK";
-  $btn->can_default(1);
-  $btn->signal_connect("clicked" => \&okCbk);
-  $btn->show;
-  $hbox->pack_start($btn, 0, 0, 0);
-  $btn->grab_default;
-
-  $btn = new Gtk2::Button "Cancel";
-  $btn->can_default(1);
-  $btn->signal_connect("clicked" => \&Gtk2::main_quit);
-  $btn->show;
-  $hbox->pack_start($btn, 0, 0, 0);
-
-  $btnTable->show;
-  $box1->show;
-  $window->show;
-}
-
-Gimp::on_run
-{
-  my ($interactive, $img, $drw);
-  ($interactive, $img, $drw, $direction) = @_;
-
-  $cancelFlag = 1;
-  if ($interactive==1)
-    {
-       $cancelFlag = 0;
-    }
-  elsif ($interactive==2)
-    {
-       $direction = Gimp->get_data($plugin);
-       $cancelFlag = 0;
-    }
-  else
-    {
-      init Gtk2;
-      create_window;
-      main Gtk2;
-    }
-
-  # Do the gimply stuff on it
-  if (!$cancelFlag)
-    {
-      do_fade($img, $drw);
-      Gimp->displays_flush;
-      Gimp->set_data($plugin, $direction);
-    }
-};
-
-Gimp::on_query {
-gimp_install_procedure(
-$plugin,
-"Fade the alpha channel of a layer from one side to another",
-"This was written as a slightly useful exercise,
-mostly to learn Gtk's excellent perl interface.  It was
-inspired by a mailing list question that asked how to do
-exactly what this does, which is fade the alpha from one
-side to another.",
-"Seth Burgess",
-"Seth Burgess",
-"2000",
-"<Image>/Layer/Transparency/Fade...",
-"*",
-PLUGIN,
-[
- [PDB_INT32, "run_mode", "Interactive, [non-interactive"],
- [PDB_IMAGE, "image", "Input image (unused)"],
- [PDB_DRAWABLE, "drawable", "Input drawable"],
- [PDB_INT32, "direction", "Direction to fade(0-8)"]
-],
-[]);
-};
-
-exit Gimp::main;
+    Gimp::Context->push;
+    Gimp::Context->set_background([0.0,0.0,0.0,1.0]);
+    Gimp::Context->set_foreground([1.0,1.0,1.0,1.0]);
+    # Direction Map
+    # 0 3 6
+    # 1 4 7
+    # 2 5 8
+    # Bounds Map
+    # (1,2) (3,2)
+    # (1,4) (3,4)
+    my @blend_args = (
+      FG_BG_RGB_MODE, NORMAL_MODE,
+      ($direction == 4 ? GRADIENT_RADIAL : GRADIENT_LINEAR),
+      100.0,       # opacity
+      0.0,         # offset
+      REPEAT_NONE,
+      0,           # reverse
+      0,           # supersample
+      1,           # recursion levels
+      0.1,         # supersample threshold
+      0,                # dither
+    );
+    my %dir2argfunc = (
+      0 => sub { @_[3, 4, 1, 2] },
+      1 => sub { ($_[3], avg(@_[2,4]), $_[1], avg(@_[2,4])) },
+      2 => sub { @_[3, 2, 1, 4] },
+      3 => sub { (avg(@_[1,3]), $_[4], avg(@_[1,3]), $_[2]) },
+      4 => sub { (avg(@_[1,3]), avg(@_[2,4]), avg(@_[1,3]), $_[4]) }, # radial
+      5 => sub { (avg(@_[1,3]), $_[2], avg(@_[1,3]), $_[4]) },
+      6 => sub { @_[1, 4, 3, 2] },
+      7 => sub { ($_[1], avg(@_[2,4]), $_[3], avg(@_[2,4])) },
+      8 => sub { @_[1, 2, 3, 4] },
+    );
+    $mask->edit_blend(@blend_args, $dir2argfunc{$direction}->(@bounds));
+    $drawable->remove_mask(MASK_APPLY) if $direction >=0 && $direction <9;
+    Gimp::Context->pop;
+    $image->undo_group_end;
+  };
+
+exit main;
 
 =head1 LICENSE
 
 Copyright Seth Burgess.
 Distributed under the same terms as Gimp-Perl.
-
-=cut
-
diff --git a/examples/layerfuncs b/examples/layerfuncs
index 3a75954..dfe834d 100755
--- a/examples/layerfuncs
+++ b/examples/layerfuncs
@@ -16,7 +16,9 @@ register "center_layer", "Center Layer",
          "Seth Burgess", "Seth Burgess <sjburges\ gimp org>",
          "1.0", N_"<Image>/Layer/Center Layer", "*", [], sub {
        ($img, $layer) = @_;
-       $layer->Gimp::Layer::set_offsets(($img->width  - $layer->width )/2,
+       die "Must have layer selected\n" unless $layer->is_layer;
+       $layer->become('Gimp::Layer');
+       $layer->set_offsets(($img->width  - $layer->width )/2,
                         ($img->height - $layer->height)/2);
        return();
 };
diff --git a/examples/redeye b/examples/redeye
index 7b01e8c..b9ce98f 100755
--- a/examples/redeye
+++ b/examples/redeye
@@ -122,7 +122,7 @@ __END__
 
 =pod
 
-=head1 HELP
+=head1 DESCRIPTION
 
 Searches the selection for pixels in which the red component
 dominates, and removes the red from those components.  The sensitivity
@@ -142,7 +142,4 @@ different sensitivity.
 
 Copyright Geoff Kuenning
 
-Distrubted under the Gnu Public License v2 or higher.
-
-=cut
-
+Distributed under the Gnu Public License v2 or higher.
diff --git a/examples/selective_sharpen b/examples/selective_sharpen
index eee809b..c87a7b8 100755
--- a/examples/selective_sharpen
+++ b/examples/selective_sharpen
@@ -5,7 +5,7 @@ use Gimp::Fu;
 
 # Gimp::set_trace(TRACE_ALL);
 
-sub my_code {
+podregister {
     my ($img,$original_layer,$sharpen_radius,$sharpen_amt,$sharpen_threshold) = @_;
 
     # sanity stuff
@@ -63,54 +63,69 @@ sub my_code {
 
     $img->undo_group_end;
     ();
-}
-
-register "selective_sharpen",
-        "Selective Sharpen - A method used by tigert to sharpen edges",
-        "",
-        "Seth Burgess <sjburges\ gimp org>",
-        "(c) Seth Burgess 2004",
-        "2004/14/04",
-        N_"<Image>/Filters/Enhance/Selective Sharpen...",
-        "RGB*", [
-        [ PF_SPINNER, "sharpen_radius", "Radius of unsharp", 5.0, [0.1,120,0.1]],
-        [ PF_SPINNER, "sharpen_amt", "Amount to unsharp", 1.0, [0.0,4.0,0.1]],
-        [ PF_SPINNER, "threshold", "What delta to decide to sharp on", 20, [0,255,1]],
-        ],
-        \&my_code;
+};
 
 exit main;
+__END__
 
-=head1 LICENSE
-Copyright 2004, Seth Burgess.
-This filter may be distributed under the same terms as Gimp-Perl.
+=head1 NAME
+
+selective_sharpen - Sharpen edges in controlled fashion
+
+=head1 SYNOPSIS
+
+<Image>/Filters/Enhance/Selective Sharpen...
+
+=head1 DESCRIPTION
 
 Taken from an IRC log:
 
-02:00 <@         tigert> selective sharpening
-02:00 <@         tigert> UnNamed: 1) take the original photo, duplicate the
-                        layer
-02:01 <@         tigert> UnNamed: 2) convert the copy to grayscale
-02:01 <@         tigert> 3) run edge detect to the gray layer
-02:01 <@         tigert> 4) blur it slightly
-02:01 <@         tigert> 5) boost contrast (I can give you a specific curve or
-                        such)
-02:01 <        sjburges> tigert: on 3, what edge detect?
-02:01 <@         tigert> sjburges: default works
-02:01 <@         tigert> sjburges: size: 3 or 2 (default)
-02:02 <@         tigert> sjburges: then make the boosted, gray edge-detection
-                        into a selection mask
-02:02 <@         tigert> sjburges: then use unsharp mask to that selection
-                        (scratch the gray layer)
-02:03 <@         tigert> sjburges: sjburges now, one could do two versions
-02:03 <@         tigert> sjburges: so one version could just be "Select edges"
-02:04 <@         tigert> sjburges: another could ask for unsharp mask
-                        parameters as well and sharpen
-02:04 <@         tigert> sjburges: the idea for the script is to sharpen it
-                        without sharpening the noise on flat areas
-02:04 <        sjburges> tigert: could you fire me an email, and I can try to
-                        get to it tonight/tomorrow?  It sounds simple enough.
-                        I need to head to a party for work shortly here
-02:04 <@         tigert> sjburges: ok
-
-=cut
+  02:00 <@         tigert> selective sharpening
+  02:00 <@         tigert> UnNamed: 1) take the original photo, duplicate the
+                          layer
+  02:01 <@         tigert> UnNamed: 2) convert the copy to grayscale
+  02:01 <@         tigert> 3) run edge detect to the gray layer
+  02:01 <@         tigert> 4) blur it slightly
+  02:01 <@         tigert> 5) boost contrast (I can give you a specific curve or
+                          such)
+  02:01 <        sjburges> tigert: on 3, what edge detect?
+  02:01 <@         tigert> sjburges: default works
+  02:01 <@         tigert> sjburges: size: 3 or 2 (default)
+  02:02 <@         tigert> sjburges: then make the boosted, gray edge-detection
+                          into a selection mask
+  02:02 <@         tigert> sjburges: then use unsharp mask to that selection
+                          (scratch the gray layer)
+  02:03 <@         tigert> sjburges: sjburges now, one could do two versions
+  02:03 <@         tigert> sjburges: so one version could just be "Select edges"
+  02:04 <@         tigert> sjburges: another could ask for unsharp mask
+                          parameters as well and sharpen
+  02:04 <@         tigert> sjburges: the idea for the script is to sharpen it
+                          without sharpening the noise on flat areas
+  02:04 <        sjburges> tigert: could you fire me an email, and I can try to
+                          get to it tonight/tomorrow?  It sounds simple enough.
+                          I need to head to a party for work shortly here
+  02:04 <@         tigert> sjburges: ok
+
+=head1 PARAMETERS
+
+ [ PF_SPINNER, "sharpen_radius", "Radius of unsharp", 5.0, [0.1,120,0.1]],
+ [ PF_SPINNER, "sharpen_amt", "Amount to unsharp", 1.0, [0.0,4.0,0.1]],
+ [ PF_SPINNER, "threshold", "What delta to decide to sharp on", 20, [0,255,1]],
+
+=head1 IMAGE TYPES
+
+RGB*
+
+=head1 AUTHOR
+
+Seth Burgess <sjburges gimp org>
+
+=head1 DATE
+
+2004/14/04
+
+=head1 LICENSE
+
+Copyright 2004, Seth Burgess.
+
+This filter may be distributed under the same terms as Gimp-Perl.
diff --git a/examples/xachshadow b/examples/xachshadow
index 5841f48..0aed93b 100755
--- a/examples/xachshadow
+++ b/examples/xachshadow
@@ -13,7 +13,7 @@
 #           a grid into it at pixelize size
 #[Xach] that's a bit roundabout, but it's also in the xcf
 #
-# Because the way xach does it is a bit ackward, I'm switching it around a bit
+# Because the way xach does it is a bit awkward, I'm switching it around a bit
 # and working from the bottom up..
 
 # Revision 1.1: Marc Lehman <pcg goof com> added undo capability
@@ -23,7 +23,7 @@
 # Revision 1.4: Seth Burgess <sjburges gimp org> removed deprecated stuff
 #
 
-use Gimp qw(:auto __ N_);
+use Gimp;
 use Gimp::Fu;
 
 register "xach_shadows",
@@ -38,50 +38,47 @@ register "xach_shadows",
           [PF_SLIDER,  "block_size",   "The size of the blocks...", 10, [4, 255, 1]],
          ],
          sub {
-   my($img,$drawable,$blocksize) = _;
-
-        eval { $img->undo_group_start };
+        my($img,$drawable,$blocksize) = _;
+        die "Must have layer selected\n" unless $drawable->is_layer;
+        $drawable->become('Gimp::Layer');
+        $img->undo_group_start;
         Gimp::Context->push();
- #     $selection_flag = 0;
-       if (!$drawable->has_alpha) {
-               $drawable->Gimp::Layer::add_alpha; # not drawable method
-               };
+#      $selection_flag = 0;
+       $drawable->add_alpha unless $drawable->has_alpha;
         Gimp::Context->set_foreground('white');
         Gimp::Context->set_background('black');
 # This only can be applied to an entire image right now..
 #      $selection = $img->selection_save;
     $img->selection_all;
 # Now the fun begins :)
-       $drawable->plug_in_pixelize($blocksize);
+       $drawable->pixelize($blocksize);
        $shadowlayer = $drawable->layer_copy(0);
        $img->insert_layer($shadowlayer,0,0);
        $checkmask = $shadowlayer->create_mask(ADD_WHITE_MASK);
        $shadowlayer->add_mask($checkmask);
-       plug_in_checkerboard ($img, $checkmask, 0, $blocksize);
+       $img->checkerboard($checkmask, 0, $blocksize);
 
        $frontlayer = $shadowlayer->layer_copy(0);
        $img->insert_layer($frontlayer,0,0);
        Gimp::Context->set_background([0,0,0]);
        $shadowlayer->fill(BACKGROUND_FILL);
-       $checkmask->plug_in_gauss_iir(0.3*$blocksize, 1, 1);
+       $checkmask->gauss_iir(0.3*$blocksize, 1, 1);
        $checkmask->offset (1, 0, 0.2*$blocksize, 0.2*$blocksize);
 
-
        $gridlayer = $img->layer_new($img->width, $img->height, RGBA_IMAGE, "Grid 1", 100, 0);
        $img->insert_layer($gridlayer,0,0);
        $img->selection_all;
-       gimp_edit_clear($gridlayer);
+       $gridlayer->edit_clear;
        Gimp::Context->set_background([255,255,255]);
-       gimp_edit_fill($gridlayer, BACKGROUND_FILL);
-       $gridlayer->plug_in_grid((1, $blocksize, 0, [0,0,0], 255) x 3);
+       $gridlayer->edit_fill(BACKGROUND_FILL);
+       $gridlayer->grid((1, $blocksize, 0, [0,0,0], 255) x 3);
 
-       gimp_layer_set_mode($gridlayer, 3);
+       $gridlayer->set_mode(3);
 # Clean up stuff
-        Gimp::Context->pop();
+        Gimp::Context->pop;
         $img->selection_none;
-        eval { $img->undo_group_end };
-       gimp_displays_flush();
-       return();
+        $img->undo_group_end;
+       return;
 };
 
 exit main;
@@ -90,5 +87,3 @@ exit main;
 
 Copyright Seth Burgess.
 Distributed under the same terms as Gimp-Perl.
-
-=cut
diff --git a/t/netplugin.t b/t/netplugin.t
index 44aeab6..e6a75c7 100644
--- a/t/netplugin.t
+++ b/t/netplugin.t
@@ -29,7 +29,7 @@ our @testbench;
 our %proc2file;
 require 't/examples-api.pl';
 
-my %plug2yes = map { ($_=>1) } qw(dots ); # glowing_steel map_to_gradient
+my %plug2yes = map { ($_=>1) } qw(dots glowing_steel ); # map_to_gradient redeye
 @testbench = grep { $plug2yes{$_->[0]} } @testbench;
 my @duptest = @{$testbench[0]};
 $duptest[3] = [ @{$duptest[3]} ]; # don't change original


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]