gimp r26978 - in trunk: . plug-ins/script-fu



Author: mitch
Date: Wed Sep 17 21:39:44 2008
New Revision: 26978
URL: http://svn.gnome.org/viewvc/gimp?rev=26978&view=rev

Log:
2008-09-17  Michael Natterer  <mitch gimp org>

	* plug-ins/script-fu/script-fu-types.h: add struct SFArg which
	keeps all a script argument's type, label, value and default
	value.

	(struct SFScript): replace separate arrays of type, label etc. by
	one array of SFArg. Remove array of GimpParamDef because they are
	only needed while registering the temp proc.

	* plug-ins/script-fu/Makefile.am
	* plug-ins/script-fu/script-fu-script.[ch]: new files implementing
	script_fu_script_new(), script_fu_script_free(),
	script_fu_script_register_proc() and
	script_fu_script_unregister_proc().

	* plug-ins/script-fu/script-fu-scripts.c: remove lots of code now
	implemented in script-fu-script.c. Changed stuff according to the
	introduction of SFArg. Moved variables to local scopes. Most
	changes are in script_fu_add_script(), almost every line changed
	and it's hopefully more readable now. Lots of cleanup all over the
	place.

	* plug-ins/script-fu/script-fu-interface.c: changed stuff
	according to the introduction of SFArg



Added:
   trunk/plug-ins/script-fu/script-fu-script.c   (contents, props changed)
      - copied, changed from r26971, /trunk/plug-ins/script-fu/script-fu-scripts.c
   trunk/plug-ins/script-fu/script-fu-script.h
Modified:
   trunk/ChangeLog
   trunk/plug-ins/script-fu/Makefile.am
   trunk/plug-ins/script-fu/script-fu-interface.c
   trunk/plug-ins/script-fu/script-fu-scripts.c
   trunk/plug-ins/script-fu/script-fu-types.h

Modified: trunk/plug-ins/script-fu/Makefile.am
==============================================================================
--- trunk/plug-ins/script-fu/Makefile.am	(original)
+++ trunk/plug-ins/script-fu/Makefile.am	Wed Sep 17 21:39:44 2008
@@ -46,6 +46,8 @@
 	script-fu-intl.h		\
 	script-fu-regex.c		\
 	script-fu-regex.h		\
+	script-fu-script.c		\
+	script-fu-script.h		\
 	script-fu-scripts.c		\
 	script-fu-scripts.h		\
 	script-fu-server.c		\

Modified: trunk/plug-ins/script-fu/script-fu-interface.c
==============================================================================
--- trunk/plug-ins/script-fu/script-fu-interface.c	(original)
+++ trunk/plug-ins/script-fu/script-fu-interface.c	Wed Sep 17 21:39:44 2008
@@ -217,7 +217,7 @@
 
   sf_interface = g_slice_new0 (SFInterface);
 
-  sf_interface->widgets = g_new0 (GtkWidget *, script->num_args);
+  sf_interface->widgets = g_new0 (GtkWidget *, script->n_args);
 
   /* strip mnemonics from the menupath */
   sf_interface->title   = gimp_strip_uline (gettext (script->menu_path));
@@ -280,7 +280,7 @@
   gtk_widget_show (vbox);
 
   /*  The argument table  */
-  sf_interface->table = gtk_table_new (script->num_args - start_arg, 3, FALSE);
+  sf_interface->table = gtk_table_new (script->n_args - start_arg, 3, FALSE);
 
   gtk_table_set_col_spacings (GTK_TABLE (sf_interface->table), 6);
   gtk_table_set_row_spacings (GTK_TABLE (sf_interface->table), 6);
@@ -289,7 +289,7 @@
 
   group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
-  for (i = start_arg; i < script->num_args; i++)
+  for (i = start_arg; i < script->n_args; i++)
     {
       GtkWidget *widget       = NULL;
       GtkObject *adj;
@@ -298,45 +298,46 @@
       gint      *ID_ptr       = NULL;
       gint       row          = i;
       gboolean   left_align   = FALSE;
+      SFArg     *arg          = &script->args[i];
 
       row -= start_arg;
 
       /*  we add a colon after the label;
           some languages want an extra space here  */
-      label_text = g_strdup_printf (_("%s:"), gettext (script->arg_labels[i]));
+      label_text = g_strdup_printf (_("%s:"), gettext (arg->label));
 
-      switch (script->arg_types[i])
+      switch (arg->type)
         {
         case SF_IMAGE:
         case SF_DRAWABLE:
         case SF_LAYER:
         case SF_CHANNEL:
         case SF_VECTORS:
-          switch (script->arg_types[i])
+          switch (arg->type)
             {
             case SF_IMAGE:
               widget = gimp_image_combo_box_new (NULL, NULL);
-              ID_ptr = &script->arg_values[i].sfa_image;
+              ID_ptr = &arg->value.sfa_image;
               break;
 
             case SF_DRAWABLE:
               widget = gimp_drawable_combo_box_new (NULL, NULL);
-              ID_ptr = &script->arg_values[i].sfa_drawable;
+              ID_ptr = &arg->value.sfa_drawable;
               break;
 
             case SF_LAYER:
               widget = gimp_layer_combo_box_new (NULL, NULL);
-              ID_ptr = &script->arg_values[i].sfa_layer;
+              ID_ptr = &arg->value.sfa_layer;
               break;
 
             case SF_CHANNEL:
               widget = gimp_channel_combo_box_new (NULL, NULL);
-              ID_ptr = &script->arg_values[i].sfa_channel;
+              ID_ptr = &arg->value.sfa_channel;
               break;
 
             case SF_VECTORS:
               widget = gimp_vectors_combo_box_new (NULL, NULL);
-              ID_ptr = &script->arg_values[i].sfa_vectors;
+              ID_ptr = &arg->value.sfa_vectors;
               break;
 
             default:
@@ -354,27 +355,26 @@
           widget = gimp_color_button_new (_("Script-Fu Color Selection"),
                                           COLOR_SAMPLE_WIDTH,
                                           COLOR_SAMPLE_HEIGHT,
-                                          &script->arg_values[i].sfa_color,
+                                          &arg->value.sfa_color,
                                           GIMP_COLOR_AREA_FLAT);
 
           gimp_color_button_set_update (GIMP_COLOR_BUTTON (widget), TRUE);
 
           g_signal_connect (widget, "color-changed",
                             G_CALLBACK (gimp_color_button_get_color),
-                            &script->arg_values[i].sfa_color);
+                            &arg->value.sfa_color);
           break;
 
         case SF_TOGGLE:
           g_free (label_text);
           label_text = NULL;
-          widget =
-            gtk_check_button_new_with_mnemonic (gettext (script->arg_labels[i]));
+          widget = gtk_check_button_new_with_mnemonic (gettext (arg->label));
           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
-                                        script->arg_values[i].sfa_toggle);
+                                        arg->value.sfa_toggle);
 
           g_signal_connect (widget, "toggled",
                             G_CALLBACK (gimp_toggle_button_update),
-                            &script->arg_values[i].sfa_toggle);
+                            &arg->value.sfa_toggle);
           break;
 
         case SF_VALUE:
@@ -383,8 +383,7 @@
           gtk_widget_set_size_request (widget, TEXT_WIDTH, -1);
           gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
 
-          gtk_entry_set_text (GTK_ENTRY (widget),
-                              script->arg_values[i].sfa_value);
+          gtk_entry_set_text (GTK_ENTRY (widget), arg->value.sfa_value);
           break;
 
         case SF_TEXT:
@@ -407,125 +406,125 @@
             buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
             gtk_text_view_set_editable (GTK_TEXT_VIEW (view), TRUE);
 
-            gtk_text_buffer_set_text (buffer,
-                                      script->arg_values[i].sfa_value, -1);
+            gtk_text_buffer_set_text (buffer, arg->value.sfa_value, -1);
 
             label_yalign = 0.0;
           }
           break;
 
         case SF_ADJUSTMENT:
-          switch (script->arg_defaults[i].sfa_adjustment.type)
+          switch (arg->default_value.sfa_adjustment.type)
             {
             case SF_SLIDER:
-              script->arg_values[i].sfa_adjustment.adj = (GtkAdjustment *)
+              arg->value.sfa_adjustment.adj = (GtkAdjustment *)
                 gimp_scale_entry_new (GTK_TABLE (sf_interface->table),
                                       0, row,
                                       label_text, SLIDER_WIDTH, -1,
-                                      script->arg_values[i].sfa_adjustment.value,
-                                      script->arg_defaults[i].sfa_adjustment.lower,
-                                      script->arg_defaults[i].sfa_adjustment.upper,
-                                      script->arg_defaults[i].sfa_adjustment.step,
-                                      script->arg_defaults[i].sfa_adjustment.page,
-                                      script->arg_defaults[i].sfa_adjustment.digits,
+                                      arg->value.sfa_adjustment.value,
+                                      arg->default_value.sfa_adjustment.lower,
+                                      arg->default_value.sfa_adjustment.upper,
+                                      arg->default_value.sfa_adjustment.step,
+                                      arg->default_value.sfa_adjustment.page,
+                                      arg->default_value.sfa_adjustment.digits,
                                       TRUE, 0.0, 0.0,
                                       NULL, NULL);
-              gtk_entry_set_activates_default (GIMP_SCALE_ENTRY_SPINBUTTON (script->arg_values[i].sfa_adjustment.adj), TRUE);
+              gtk_entry_set_activates_default (GIMP_SCALE_ENTRY_SPINBUTTON (arg->value.sfa_adjustment.adj), TRUE);
               break;
 
             default:
               g_warning ("unexpected adjustment type: %d",
-                         script->arg_defaults[i].sfa_adjustment.type);
+                         arg->default_value.sfa_adjustment.type);
               /* fallthrough */
 
             case SF_SPINNER:
               left_align = TRUE;
               widget =
                 gimp_spin_button_new (&adj,
-                                      script->arg_values[i].sfa_adjustment.value,
-                                      script->arg_defaults[i].sfa_adjustment.lower,
-                                      script->arg_defaults[i].sfa_adjustment.upper,
-                                      script->arg_defaults[i].sfa_adjustment.step,
-                                      script->arg_defaults[i].sfa_adjustment.page,
+                                      arg->value.sfa_adjustment.value,
+                                      arg->default_value.sfa_adjustment.lower,
+                                      arg->default_value.sfa_adjustment.upper,
+                                      arg->default_value.sfa_adjustment.step,
+                                      arg->default_value.sfa_adjustment.page,
                                       0, 0,
-                                      script->arg_defaults[i].sfa_adjustment.digits);
+                                      arg->default_value.sfa_adjustment.digits);
               gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
-              script->arg_values[i].sfa_adjustment.adj = GTK_ADJUSTMENT (adj);
+              arg->value.sfa_adjustment.adj = GTK_ADJUSTMENT (adj);
               break;
             }
 
-          g_signal_connect (script->arg_values[i].sfa_adjustment.adj,
+          g_signal_connect (arg->value.sfa_adjustment.adj,
                             "value-changed",
                             G_CALLBACK (gimp_double_adjustment_update),
-                            &script->arg_values[i].sfa_adjustment.value);
+                            &arg->value.sfa_adjustment.value);
           break;
 
         case SF_FILENAME:
         case SF_DIRNAME:
-          if (script->arg_types[i] == SF_FILENAME)
+          if (arg->type == SF_FILENAME)
             widget = gtk_file_chooser_button_new (_("Script-Fu File Selection"),
                                                   GTK_FILE_CHOOSER_ACTION_OPEN);
           else
             widget = gtk_file_chooser_button_new (_("Script-Fu Folder Selection"),
                                                   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-          if (script->arg_values[i].sfa_file.filename)
+
+          if (arg->value.sfa_file.filename)
             gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget),
-                                           script->arg_values[i].sfa_file.filename);
+                                           arg->value.sfa_file.filename);
 
           g_signal_connect (widget, "selection-changed",
                             G_CALLBACK (script_fu_file_callback),
-                            &script->arg_values[i].sfa_file);
+                            &arg->value.sfa_file);
           break;
 
         case SF_FONT:
           widget = gimp_font_select_button_new (_("Script-Fu Font Selection"),
-                                                script->arg_values[i].sfa_font);
+                                                arg->value.sfa_font);
           g_signal_connect_swapped (widget, "font-set",
                                     G_CALLBACK (script_fu_font_callback),
-                                    &script->arg_values[i].sfa_font);
+                                    &arg->value.sfa_font);
           break;
 
         case SF_PALETTE:
           widget = gimp_palette_select_button_new (_("Script-Fu Palette Selection"),
-                                                   script->arg_values[i].sfa_palette);
+                                                   arg->value.sfa_palette);
           g_signal_connect_swapped (widget, "palette-set",
                                     G_CALLBACK (script_fu_palette_callback),
-                                    &script->arg_values[i].sfa_palette);
+                                    &arg->value.sfa_palette);
           break;
 
         case SF_PATTERN:
           left_align = TRUE;
           widget = gimp_pattern_select_button_new (_("Script-Fu Pattern Selection"),
-                                                   script->arg_values[i].sfa_pattern);
+                                                   arg->value.sfa_pattern);
           g_signal_connect_swapped (widget, "pattern-set",
                                     G_CALLBACK (script_fu_pattern_callback),
-                                    &script->arg_values[i].sfa_pattern);
+                                    &arg->value.sfa_pattern);
           break;
 
         case SF_GRADIENT:
           left_align = TRUE;
           widget = gimp_gradient_select_button_new (_("Script-Fu Gradient Selection"),
-                                                    script->arg_values[i].sfa_gradient);
+                                                    arg->value.sfa_gradient);
           g_signal_connect_swapped (widget, "gradient-set",
                                     G_CALLBACK (script_fu_gradient_callback),
-                                    &script->arg_values[i].sfa_gradient);
+                                    &arg->value.sfa_gradient);
           break;
 
         case SF_BRUSH:
           left_align = TRUE;
           widget = gimp_brush_select_button_new (_("Script-Fu Brush Selection"),
-                                                 script->arg_values[i].sfa_brush.name,
-                                                 script->arg_values[i].sfa_brush.opacity,
-                                                 script->arg_values[i].sfa_brush.spacing,
-                                                 script->arg_values[i].sfa_brush.paint_mode);
+                                                 arg->value.sfa_brush.name,
+                                                 arg->value.sfa_brush.opacity,
+                                                 arg->value.sfa_brush.spacing,
+                                                 arg->value.sfa_brush.paint_mode);
           g_signal_connect_swapped (widget, "brush-set",
                                     G_CALLBACK (script_fu_brush_callback),
-                                    &script->arg_values[i].sfa_brush);
+                                    &arg->value.sfa_brush);
           break;
 
         case SF_OPTION:
           widget = gtk_combo_box_new_text ();
-          for (list = script->arg_defaults[i].sfa_option.list;
+          for (list = arg->default_value.sfa_option.list;
                list;
                list = g_slist_next (list))
             {
@@ -534,22 +533,22 @@
             }
 
           gtk_combo_box_set_active (GTK_COMBO_BOX (widget),
-                                    script->arg_values[i].sfa_option.history);
+                                    arg->value.sfa_option.history);
 
           g_signal_connect (widget, "changed",
                             G_CALLBACK (script_fu_combo_callback),
-                            &script->arg_values[i].sfa_option);
+                            &arg->value.sfa_option);
           break;
 
         case SF_ENUM:
-          widget = gimp_enum_combo_box_new (g_type_from_name (script->arg_defaults[i].sfa_enum.type_name));
+          widget = gimp_enum_combo_box_new (g_type_from_name (arg->default_value.sfa_enum.type_name));
 
           gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget),
-                                         script->arg_values[i].sfa_enum.history);
+                                         arg->value.sfa_enum.history);
 
           g_signal_connect (widget, "changed",
                             G_CALLBACK (gimp_int_combo_box_get_active),
-                            &script->arg_values[i].sfa_enum.history);
+                            &arg->value.sfa_enum.history);
           break;
 
         case SF_DISPLAY:
@@ -621,8 +620,8 @@
 
   g_free (sf_interface->title);
 
-  for (i = 0; i < script->num_args; i++)
-    switch (script->arg_types[i])
+  for (i = 0; i < script->n_args; i++)
+    switch (script->args[i].type)
       {
       case SF_FONT:
       case SF_PALETTE:
@@ -780,14 +779,14 @@
   s = g_string_new ("(");
   g_string_append (s, script->name);
 
-  for (i = 0; i < script->num_args; i++)
+  for (i = 0; i < script->n_args; i++)
     {
-      SFArgValue *arg_value = &script->arg_values[i];
+      SFArgValue *arg_value = &script->args[i].value;
       GtkWidget  *widget    = sf_interface->widgets[i];
 
       g_string_append_c (s, ' ');
 
-      switch (script->arg_types[i])
+      switch (script->args[i].type)
         {
         case SF_IMAGE:
         case SF_DRAWABLE:
@@ -934,11 +933,12 @@
 {
   gint i;
 
-  for (i = 0; i < script->num_args; i++)
+  for (i = 0; i < script->n_args; i++)
     {
+      SFArg     *arg    = &script->args[i];
       GtkWidget *widget = sf_interface->widgets[i];
 
-      switch (script->arg_types[i])
+      switch (arg->type)
         {
         case SF_IMAGE:
         case SF_DRAWABLE:
@@ -950,18 +950,18 @@
 
         case SF_COLOR:
           gimp_color_button_set_color (GIMP_COLOR_BUTTON (widget),
-                                       &script->arg_defaults[i].sfa_color);
+                                       &arg->default_value.sfa_color);
           break;
 
         case SF_TOGGLE:
           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
-                                        script->arg_defaults[i].sfa_toggle);
+                                        arg->default_value.sfa_toggle);
           break;
 
         case SF_VALUE:
         case SF_STRING:
           gtk_entry_set_text (GTK_ENTRY (widget),
-                              script->arg_defaults[i].sfa_value);
+                              arg->default_value.sfa_value);
           break;
 
         case SF_TEXT:
@@ -969,65 +969,63 @@
             GtkWidget     *view;
             GtkTextBuffer *buffer;
 
-            g_free (script->arg_values[i].sfa_value);
-            script->arg_values[i].sfa_value =
-              g_strdup (script->arg_defaults[i].sfa_value);
+            g_free (arg->value.sfa_value);
+            arg->value.sfa_value = g_strdup (arg->default_value.sfa_value);
 
             view = gtk_bin_get_child (GTK_BIN (widget));
             buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
 
-            gtk_text_buffer_set_text (buffer,
-                                      script->arg_values[i].sfa_value, -1);
+            gtk_text_buffer_set_text (buffer, arg->value.sfa_value, -1);
           }
           break;
 
         case SF_ADJUSTMENT:
-          gtk_adjustment_set_value (script->arg_values[i].sfa_adjustment.adj,
-                                    script->arg_defaults[i].sfa_adjustment.value);
+          gtk_adjustment_set_value (arg->value.sfa_adjustment.adj,
+                                    arg->default_value.sfa_adjustment.value);
           break;
 
         case SF_FILENAME:
         case SF_DIRNAME:
           gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget),
-                                         script->arg_defaults[i].sfa_file.filename);
+                                         arg->default_value.sfa_file.filename);
           break;
 
         case SF_FONT:
           gimp_font_select_button_set_font (GIMP_FONT_SELECT_BUTTON (widget),
-                                            script->arg_defaults[i].sfa_font);
+                                            arg->default_value.sfa_font);
           break;
 
         case SF_PALETTE:
           gimp_palette_select_button_set_palette (GIMP_PALETTE_SELECT_BUTTON (widget),
-                                                  script->arg_defaults[i].sfa_palette);
+                                                  arg->default_value.sfa_palette);
           break;
 
         case SF_PATTERN:
           gimp_pattern_select_button_set_pattern (GIMP_PATTERN_SELECT_BUTTON (widget),
-                                                  script->arg_defaults[i].sfa_pattern);
+                                                  arg->default_value.sfa_pattern);
           break;
 
         case SF_GRADIENT:
           gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (widget),
-                                                    script->arg_defaults[i].sfa_gradient);
+                                                    arg->default_value.sfa_gradient);
           break;
 
         case SF_BRUSH:
           gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (widget),
-                                              script->arg_defaults[i].sfa_brush.name,
-                                              script->arg_defaults[i].sfa_brush.opacity,
-                                              script->arg_defaults[i].sfa_brush.spacing,
-                                              script->arg_defaults[i].sfa_brush.paint_mode);
+                                              arg->default_value.sfa_brush.name,
+                                              arg->default_value.sfa_brush.opacity,
+                                              arg->default_value.sfa_brush.spacing,
+                                              arg->default_value.sfa_brush.paint_mode);
           break;
 
         case SF_OPTION:
           gtk_combo_box_set_active (GTK_COMBO_BOX (widget),
-                                    script->arg_defaults[i].sfa_option.history);
+                                    arg->default_value.sfa_option.history);
           break;
 
         case SF_ENUM:
           gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget),
-                                         script->arg_defaults[i].sfa_enum.history);
+                                         arg->default_value.sfa_enum.history);
           break;
         }
     }

Copied: trunk/plug-ins/script-fu/script-fu-script.c (from r26971, /trunk/plug-ins/script-fu/script-fu-scripts.c)
==============================================================================
--- /trunk/plug-ins/script-fu/script-fu-scripts.c	(original)
+++ trunk/plug-ins/script-fu/script-fu-script.c	Wed Sep 17 21:39:44 2008
@@ -20,1424 +20,292 @@
 
 #include <string.h>
 
-#include <glib.h>
-
-#ifdef G_OS_WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
 #include <libgimp/gimp.h>
 #include <libgimp/gimpui.h>
 
-#include "tinyscheme/scheme-private.h"
-
-#include "scheme-wrapper.h"
-
 #include "script-fu-types.h"
 
-#include "script-fu-interface.h"
-#include "script-fu-scripts.h"
-
-#include "script-fu-intl.h"
-
-
-typedef struct
-{
-  SFScript *script;
-  gchar    *menu_path;
-} SFMenu;
-
-
-/*
- *  Local Functions
- */
-
-static gboolean  script_fu_run_command    (const gchar             *command,
-                                           GError                 **error);
-static void      script_fu_load_script    (const GimpDatafileData  *file_data,
-                                           gpointer                 user_data);
-static gboolean  script_fu_install_script (gpointer                 foo,
-                                           GList                   *scripts,
-                                           gpointer                 bar);
-static void      script_fu_install_menu   (SFMenu                  *menu);
-static gboolean  script_fu_remove_script  (gpointer                 foo,
-                                           GList                   *scripts,
-                                           gpointer                 bar);
-static void      script_fu_script_proc    (const gchar             *name,
-                                           gint                     nparams,
-                                           const GimpParam         *params,
-                                           gint                    *nreturn_vals,
-                                           GimpParam              **return_vals);
-
-static SFScript *script_fu_find_script    (const gchar             *name);
-static void      script_fu_free_script    (SFScript                *script);
-
-static void      script_fu_menu_map       (SFScript                *script);
-static gint      script_fu_menu_compare   (gconstpointer            a,
-                                           gconstpointer            b);
-
-
-/*
- *  Local variables
- */
-
-static GTree *script_tree      = NULL;
-static GList *script_menu_list = NULL;
+#include "script-fu-script.h"
 
 
 /*
  *  Function definitions
  */
 
-void
-script_fu_find_scripts (const gchar *path)
+SFScript *
+script_fu_script_new (const gchar *name,
+                      const gchar *menu_path,
+                      const gchar *blurb,
+                      const gchar *author,
+                      const gchar *copyright,
+                      const gchar *date,
+                      const gchar *image_types,
+                      gint         n_args)
 {
-  /*  Make sure to clear any existing scripts  */
-  if (script_tree != NULL)
-    {
-      g_tree_foreach (script_tree,
-                      (GTraverseFunc) script_fu_remove_script,
-                      NULL);
-      g_tree_destroy (script_tree);
-    }
-
-  if (! path)
-    return;
-
-  script_tree = g_tree_new ((GCompareFunc) g_utf8_collate);
-
-  gimp_datafiles_read_directories (path, G_FILE_TEST_IS_REGULAR,
-                                   script_fu_load_script,
-                                   NULL);
-
-  /*  Now that all scripts are read in and sorted, tell gimp about them  */
-  g_tree_foreach (script_tree,
-                  (GTraverseFunc) script_fu_install_script,
-                  NULL);
-
-  script_menu_list = g_list_sort (script_menu_list,
-                                  (GCompareFunc) script_fu_menu_compare);
-
-  g_list_foreach (script_menu_list,
-                  (GFunc) script_fu_install_menu,
-                  NULL);
-
-  /*  Now we are done with the list of menu entries  */
-  g_list_free (script_menu_list);
-  script_menu_list = NULL;
-}
-
-pointer
-script_fu_add_script (scheme  *sc,
-                      pointer  a)
-{
-  GimpParamDef *args;
-  SFScript     *script;
-  GType         enum_type;
-  GEnumValue   *enum_value;
-  const gchar  *val;
-  gint          i;
-  guchar        r, g, b;
-  pointer       color_list;
-  pointer       adj_list;
-  pointer       brush_list;
-  pointer       option_list;
-
-  /*  Check the length of a  */
-  if (sc->vptr->list_length (sc, a) < 7)
-  {
-    g_message (_("Too few arguments to 'script-fu-register' call"));
-
-    return sc->NIL;
-  }
+  SFScript *script;
 
-  /*  Create a new script  */
   script = g_slice_new0 (SFScript);
 
-  /*  Find the script name  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->name = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
-
-  /*  Find the script menu_path  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->menu_path = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
-
-  /*  Find the script blurb  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->blurb = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
-
-  /*  Find the script author  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->author = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
-
-  /*  Find the script copyright  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->copyright = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
-
-  /*  Find the script date  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->date = g_strdup (val);
-  a = sc->vptr->pair_cdr (a);
+  script->name        = g_strdup (name);
+  script->menu_path   = g_strdup (menu_path);
+  script->blurb       = g_strdup (blurb);
+  script->author      = g_strdup (author);
+  script->copyright   = g_strdup (copyright);
+  script->date        = g_strdup (date);
+  script->image_types = g_strdup (image_types);
 
-  /*  Find the script image types  */
-  if (sc->vptr->is_pair (a))
-    {
-      val = sc->vptr->string_value (sc->vptr->pair_car (a));
-      a = sc->vptr->pair_cdr (a);
-    }
-  else
-    {
-      val = sc->vptr->string_value (a);
-      a = sc->NIL;
-    }
-  script->img_types = g_strdup (val);
-
-  /*  Check the supplied number of arguments  */
-  script->num_args = sc->vptr->list_length (sc, a) / 3;
-
-  args = g_new0 (GimpParamDef, script->num_args + 1);
-
-  args[0].type        = GIMP_PDB_INT32;
-  args[0].name        = "run-mode";
-  args[0].description = "Interactive, non-interactive";
-
-  script->arg_types    = g_new0 (SFArgType, script->num_args);
-  script->arg_labels   = g_new0 (gchar *, script->num_args);
-  script->arg_defaults = g_new0 (SFArgValue, script->num_args);
-  script->arg_values   = g_new0 (SFArgValue, script->num_args);
-
-  if (script->num_args > 0)
-    {
-      for (i = 0; i < script->num_args; i++)
-        {
-          if (a != sc->NIL)
-            {
-              if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                return foreign_error (sc, "script-fu-register: argument types must be integer values", 0);
-              script->arg_types[i] = sc->vptr->ivalue (sc->vptr->pair_car (a));
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            return foreign_error (sc, "script-fu-register: missing type specifier", 0);
-
-          if (a != sc->NIL)
-            {
-              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                return foreign_error (sc, "script-fu-register: argument labels must be strings", 0);
-              script->arg_labels[i] = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            return foreign_error (sc, "script-fu-register: missing arguments label", 0);
-
-          if (a != sc->NIL)
-            {
-              gchar *type_name;
-
-              switch (script->arg_types[i])
-                {
-                case SF_IMAGE:
-                case SF_DRAWABLE:
-                case SF_LAYER:
-                case SF_CHANNEL:
-                case SF_VECTORS:
-                case SF_DISPLAY:
-                  if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0);
-                  script->arg_defaults[i].sfa_image =
-                      sc->vptr->ivalue (sc->vptr->pair_car (a));
-                  script->arg_values[i].sfa_image =
-                    script->arg_defaults[i].sfa_image;
-
-                  switch (script->arg_types[i])
-                    {
-                    case SF_IMAGE:
-                      args[i + 1].type = GIMP_PDB_IMAGE;
-                      args[i + 1].name = "image";
-                      break;
-
-                    case SF_DRAWABLE:
-                      args[i + 1].type = GIMP_PDB_DRAWABLE;
-                      args[i + 1].name = "drawable";
-                      break;
-
-                    case SF_LAYER:
-                      args[i + 1].type = GIMP_PDB_LAYER;
-                      args[i + 1].name = "layer";
-                      break;
-
-                    case SF_CHANNEL:
-                      args[i + 1].type = GIMP_PDB_CHANNEL;
-                      args[i + 1].name = "channel";
-                      break;
-
-                    case SF_VECTORS:
-                      args[i + 1].type = GIMP_PDB_VECTORS;
-                      args[i + 1].name = "vectors";
-                      break;
-
-                    case SF_DISPLAY:
-                      args[i + 1].type = GIMP_PDB_DISPLAY;
-                      args[i + 1].name = "display";
-                      break;
-
-                    default:
-                      break;
-                    }
-
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_COLOR:
-                  if (sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    {
-                      if (! gimp_rgb_parse_css (&script->arg_defaults[i].sfa_color,
-                                                sc->vptr->string_value (sc->vptr->pair_car (a)),
-                                                -1))
-                        return foreign_error (sc, "script-fu-register: invalid default color name", 0);
-                      gimp_rgb_set_alpha (&script->arg_defaults[i].sfa_color,
-                                          1.0);
-                    }
-                  else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) &&
-                           sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3)
-                    {
-                      color_list = sc->vptr->pair_car (a);
-                      r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
-                      color_list = sc->vptr->pair_cdr (color_list);
-                      g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
-                      color_list = sc->vptr->pair_cdr (color_list);
-                      b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
-
-                      gimp_rgb_set_uchar (&script->arg_defaults[i].sfa_color, r, g, b);
-                    }
-                  else
-                    {
-                      return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0);
-                    }
-
-                  script->arg_values[i].sfa_color = script->arg_defaults[i].sfa_color;
-
-                  args[i + 1].type        = GIMP_PDB_COLOR;
-                  args[i + 1].name        = "color";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_TOGGLE:
-                  if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0);
-
-                  script->arg_defaults[i].sfa_toggle =
-                    (sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE;
-                  script->arg_values[i].sfa_toggle =
-                    script->arg_defaults[i].sfa_toggle;
-
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "toggle";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_VALUE:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: value defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_value =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_value =
-                    g_strdup (script->arg_defaults[i].sfa_value);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "value";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_STRING:
-                case SF_TEXT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: string defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_value =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_value =
-                    g_strdup (script->arg_defaults[i].sfa_value);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "string";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_ADJUSTMENT:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0);
-
-                  adj_list = sc->vptr->pair_car (a);
-                  script->arg_defaults[i].sfa_adjustment.value =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.lower =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.upper =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.step =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.page =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.digits =
-                    sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.type =
-                    sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
-
-                  script->arg_values[i].sfa_adjustment.adj = NULL;
-                  script->arg_values[i].sfa_adjustment.value =
-                    script->arg_defaults[i].sfa_adjustment.value;
-
-                  args[i + 1].type        = GIMP_PDB_FLOAT;
-                  args[i + 1].name        = "value";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_FILENAME:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0);
-                  /* fallthrough */
-
-                case SF_DIRNAME:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_file.filename =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-
-#ifdef G_OS_WIN32
-                  {
-                    /* Replace POSIX slashes with Win32 backslashes. This
-                     * is just so script-fus can be written with only
-                     * POSIX directory separators.
-                     */
-                    gchar *filename = script->arg_defaults[i].sfa_file.filename;
-
-                    while (*filename)
-                      {
-                        if (*filename == '/')
-                          *filename = G_DIR_SEPARATOR;
-
-                        filename++;
-                      }
-                  }
-#endif
-                  script->arg_values[i].sfa_file.filename =
-                    g_strdup (script->arg_defaults[i].sfa_file.filename);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = (script->arg_types[i] == SF_FILENAME ?
-                                             "filename" : "dirname");
-                  args[i + 1].description = script->arg_labels[i];
-                 break;
-
-                case SF_FONT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: font defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_font =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_font =
-                    g_strdup (script->arg_defaults[i].sfa_font);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "font";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_PALETTE:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_palette =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_palette =
-                    g_strdup (script->arg_defaults[i].sfa_pattern);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "palette";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_PATTERN:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_pattern =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_pattern =
-                    g_strdup (script->arg_defaults[i].sfa_pattern);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "pattern";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_BRUSH:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
-
-                  brush_list = sc->vptr->pair_car (a);
-                  script->arg_defaults[i].sfa_brush.name =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
-                  script->arg_values[i].sfa_brush.name =
-                    g_strdup (script->arg_defaults[i].sfa_brush.name);
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.opacity =
-                    sc->vptr->rvalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.opacity =
-                    script->arg_defaults[i].sfa_brush.opacity;
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.spacing =
-                    sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.spacing =
-                    script->arg_defaults[i].sfa_brush.spacing;
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.paint_mode =
-                    sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.paint_mode =
-                    script->arg_defaults[i].sfa_brush.paint_mode;
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "brush";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_GRADIENT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_gradient =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_gradient =
-                    g_strdup (script->arg_defaults[i].sfa_gradient);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "gradient";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_OPTION:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: option defaults must be a list", 0);
-
-                  for (option_list = sc->vptr->pair_car (a);
-                       option_list != sc->NIL;
-                       option_list = sc->vptr->pair_cdr (option_list))
-                    {
-                      script->arg_defaults[i].sfa_option.list =
-                        g_slist_append (script->arg_defaults[i].sfa_option.list,
-                                        g_strdup (sc->vptr->string_value
-                                           (sc->vptr->pair_car (option_list))));
-                    }
-
-                  script->arg_defaults[i].sfa_option.history = 0;
-                  script->arg_values[i].sfa_option.history = 0;
-
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "option";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_ENUM:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0);
-
-                  option_list = sc->vptr->pair_car (a);
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
-                    return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0);
-
-                  val =
-                    sc->vptr->string_value (sc->vptr->pair_car (option_list));
-
-                  if (g_str_has_prefix (val, "Gimp"))
-                    type_name = g_strdup (val);
-                  else
-                    type_name = g_strconcat ("Gimp", val, NULL);
-
-                  enum_type = g_type_from_name (type_name);
-                  if (! G_TYPE_IS_ENUM (enum_type))
-                    {
-                      g_free (type_name);
-                      return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0);
-                    }
-
-                  script->arg_defaults[i].sfa_enum.type_name = type_name;
-
-                  option_list = sc->vptr->pair_cdr (option_list);
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
-                    return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0);
-
-                  enum_value =
-                    g_enum_get_value_by_nick (g_type_class_peek (enum_type),
-                      sc->vptr->string_value (sc->vptr->pair_car (option_list)));
-                  if (enum_value)
-                    script->arg_defaults[i].sfa_enum.history =
-                      script->arg_values[i].sfa_enum.history = enum_value->value;
-
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "enum";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-                }
-
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            {
-              return foreign_error (sc, "script-fu-register: missing default argument", 0);
-            }
-        }
-    }
-
-  script->args = args;
-
-  script_fu_menu_map (script);
-
-  {
-    const gchar *key  = gettext (script->menu_path);
-    GList       *list = g_tree_lookup (script_tree, key);
+  script->n_args = n_args;
+  script->args   = g_new0 (SFArg, script->n_args);
 
-    g_tree_insert (script_tree, (gpointer) key, g_list_append (list, script));
-  }
-
-  return sc->NIL;
+  return script;
 }
 
-pointer
-script_fu_add_menu (scheme  *sc,
-                    pointer  a)
+void
+script_fu_script_free (SFScript *script)
 {
-  SFScript    *script;
-  SFMenu      *menu;
-  const gchar *name;
-
-  /*  Check the length of a  */
-  if (sc->vptr->list_length (sc, a) != 2)
-    return foreign_error (sc, "Incorrect number of arguments for script-fu-menu-register", 0);
-
-  /*  Find the script PDB entry name  */
-  name = sc->vptr->string_value (sc->vptr->pair_car (a));
-  a = sc->vptr->pair_cdr (a);
-
-  script = script_fu_find_script (name);
-
-  if (! script)
-  {
-    g_message ("Procedure %s in script-fu-menu-register does not exist", name);
-    return sc->NIL;
-  }
+  gint i;
 
-  /*  Create a new list of menus  */
-  menu = g_slice_new0 (SFMenu);
+  g_return_if_fail (script != NULL);
 
-  menu->script = script;
+  g_free (script->name);
+  g_free (script->blurb);
+  g_free (script->menu_path);
+  g_free (script->author);
+  g_free (script->copyright);
+  g_free (script->date);
+  g_free (script->image_types);
 
-  /*  Find the script menu path  */
-  menu->menu_path = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+  for (i = 0; i < script->n_args; i++)
+    {
+      SFArg *arg = &script->args[i];
 
-  script_menu_list = g_list_prepend (script_menu_list, menu);
+      g_free (arg->label);
 
-  return sc->NIL;
-}
+      switch (arg->type)
+        {
+        case SF_IMAGE:
+        case SF_DRAWABLE:
+        case SF_LAYER:
+        case SF_CHANNEL:
+        case SF_VECTORS:
+        case SF_DISPLAY:
+        case SF_COLOR:
+        case SF_TOGGLE:
+          break;
 
+        case SF_VALUE:
+        case SF_STRING:
+        case SF_TEXT:
+          g_free (arg->default_value.sfa_value);
+          g_free (arg->value.sfa_value);
+          break;
 
-/*  private functions  */
+        case SF_ADJUSTMENT:
+          break;
 
-static gboolean
-script_fu_run_command (const gchar  *command,
-                       GError      **error)
-{
-  GString  *output  = g_string_new ("");
-  gboolean  success = FALSE;
+        case SF_FILENAME:
+        case SF_DIRNAME:
+          g_free (arg->default_value.sfa_file.filename);
+          g_free (arg->value.sfa_file.filename);
+          break;
 
-  output = g_string_new ("");
-  ts_register_output_func (ts_gstring_output_func, output);
+        case SF_FONT:
+          g_free (arg->default_value.sfa_font);
+          g_free (arg->value.sfa_font);
+          break;
 
-  if (ts_interpret_string (command))
-    {
-      g_set_error (error, 0, 0, "%s", output->str);
-    }
-  else
-    {
-      success = TRUE;
-    }
+        case SF_PALETTE:
+          g_free (arg->default_value.sfa_palette);
+          g_free (arg->value.sfa_palette);
+          break;
 
-  g_string_free (output, TRUE);
+        case SF_PATTERN:
+          g_free (arg->default_value.sfa_pattern);
+          g_free (arg->value.sfa_pattern);
+          break;
 
-  return success;
-}
+        case SF_GRADIENT:
+          g_free (arg->default_value.sfa_gradient);
+          g_free (arg->value.sfa_gradient);
+          break;
 
-static void
-script_fu_load_script (const GimpDatafileData *file_data,
-                       gpointer                user_data)
-{
-  if (gimp_datafiles_check_extension (file_data->filename, ".scm"))
-    {
-      gchar  *escaped = script_fu_strescape (file_data->filename);
-      gchar  *command;
-      GError *error   = NULL;
+        case SF_BRUSH:
+          g_free (arg->default_value.sfa_brush.name);
+          g_free (arg->value.sfa_brush.name);
+          break;
 
-      command = g_strdup_printf ("(load \"%s\")", escaped);
-      g_free (escaped);
+        case SF_OPTION:
+          g_slist_foreach (arg->default_value.sfa_option.list,
+                           (GFunc) g_free, NULL);
+          g_slist_free (arg->default_value.sfa_option.list);
+          break;
 
-      if (! script_fu_run_command (command, &error))
-        {
-          gchar *display_name = g_filename_display_name (file_data->filename);
-          gchar *message      = g_strdup_printf (_("Error while loading %s:"),
-                                                 display_name);
-
-          g_message ("%s\n\n%s", message, error->message);
-
-          g_clear_error (&error);
-          g_free (message);
-          g_free (display_name);
+        case SF_ENUM:
+          g_free (arg->default_value.sfa_enum.type_name);
+          break;
         }
-
-#ifdef G_OS_WIN32
-      /* No, I don't know why, but this is
-       * necessary on NT 4.0.
-       */
-      Sleep (0);
-#endif
-
-      g_free (command);
     }
-}
 
-/*
- *  The following function is a GTraverseFunction.
- *  Please note that it frees the script->args structure.
- */
-static gboolean
-script_fu_install_script (gpointer  foo G_GNUC_UNUSED,
-                          GList    *scripts,
-                          gpointer  bar G_GNUC_UNUSED)
-{
-  GList *list;
+  g_free (script->args);
 
-  for (list = scripts; list; list = g_list_next (list))
-    {
-      SFScript    *script    = list->data;
-      const gchar *menu_path = NULL;
-
-      /* Allow scripts with no menus */
-      if (strncmp (script->menu_path, "<None>", 6) != 0)
-        menu_path = script->menu_path;
-
-      gimp_install_temp_proc (script->name,
-                              script->blurb,
-                              "",
-                              script->author,
-                              script->copyright,
-                              script->date,
-                              menu_path,
-                              script->img_types,
-                              GIMP_TEMPORARY,
-                              script->num_args + 1, 0,
-                              script->args, NULL,
-                              script_fu_script_proc);
-
-      g_free (script->args);
-      script->args = NULL;
-    }
-
-  return FALSE;
+  g_slice_free (SFScript, script);
 }
 
-static void
-script_fu_install_menu (SFMenu *menu)
+void
+script_fu_script_install_proc (SFScript    *script,
+                               GimpRunProc  run_proc)
 {
-  gimp_plugin_menu_register (menu->script->name, menu->menu_path);
-
-  g_free (menu->menu_path);
-  g_slice_free (SFMenu, menu);
-}
+  const gchar  *menu_path = NULL;
+  GimpParamDef *args;
+  gint          i;
 
-/*
- *  The following function is a GTraverseFunction.
- */
-static gboolean
-script_fu_remove_script (gpointer  foo G_GNUC_UNUSED,
-                         GList    *scripts,
-                         gpointer  bar G_GNUC_UNUSED)
-{
-  GList *list;
+  g_return_if_fail (script != NULL);
+  g_return_if_fail (run_proc != NULL);
 
-  for (list = scripts; list; list = g_list_next (list))
-    script_fu_free_script (list->data);
+  /* Allow scripts with no menus */
+  if (strncmp (script->menu_path, "<None>", 6) != 0)
+    menu_path = script->menu_path;
 
-  g_list_free (scripts);
+  args = g_new0 (GimpParamDef, script->n_args + 1);
 
-  return FALSE;
-}
+  args[0].type        = GIMP_PDB_INT32;
+  args[0].name        = "run-mode";
+  args[0].description = "Interactive, non-interactive";
 
-static gboolean
-script_fu_param_init (SFScript        *script,
-                      gint             nparams,
-                      const GimpParam *params,
-                      SFArgType        type,
-                      gint             n)
-{
-  if (script->num_args > n && script->arg_types[n] == type && nparams > n + 1)
+  for (i = 0; i < script->n_args; i++)
     {
-      switch (type)
+      GimpPDBArgType  type = 0;
+      const gchar    *name = NULL;
+
+      switch (script->args[i].type)
         {
         case SF_IMAGE:
-          if (params[n + 1].type == GIMP_PDB_IMAGE)
-            {
-              script->arg_values[n].sfa_image = params[n + 1].data.d_image;
-              return TRUE;
-            }
+          type = GIMP_PDB_IMAGE;
+          name = "image";
           break;
 
         case SF_DRAWABLE:
-          if (params[n + 1].type == GIMP_PDB_DRAWABLE)
-            {
-              script->arg_values[n].sfa_drawable = params[n + 1].data.d_drawable;
-              return TRUE;
-            }
+          type = GIMP_PDB_DRAWABLE;
+          name = "drawable";
           break;
 
         case SF_LAYER:
-          if (params[n + 1].type == GIMP_PDB_LAYER)
-            {
-              script->arg_values[n].sfa_layer = params[n + 1].data.d_layer;
-              return TRUE;
-            }
+          type = GIMP_PDB_LAYER;
+          name = "layer";
           break;
 
         case SF_CHANNEL:
-          if (params[n + 1].type == GIMP_PDB_CHANNEL)
-            {
-              script->arg_values[n].sfa_channel = params[n + 1].data.d_channel;
-              return TRUE;
-            }
+          type = GIMP_PDB_CHANNEL;
+          name = "channel";
           break;
 
         case SF_VECTORS:
-          if (params[n + 1].type == GIMP_PDB_VECTORS)
-            {
-              script->arg_values[n].sfa_vectors = params[n + 1].data.d_vectors;
-              return TRUE;
-            }
+          type = GIMP_PDB_VECTORS;
+          name = "vectors";
           break;
 
         case SF_DISPLAY:
-          if (params[n + 1].type == GIMP_PDB_DISPLAY)
-            {
-              script->arg_values[n].sfa_display = params[n + 1].data.d_display;
-              return TRUE;
-            }
-          break;
-
-        default:
-          break;
-        }
-    }
-
-  return FALSE;
-}
-
-static gint
-script_fu_collect_standard_args (SFScript        *script,
-                                 gint             nparams,
-                                 const GimpParam *params)
-{
-  gint params_consumed = 0;
-
-  /*  the first parameter may be a DISPLAY id  */
-  if (script_fu_param_init (script,
-                            nparams, params, SF_DISPLAY, params_consumed))
-    {
-      params_consumed++;
-    }
-
-  /*  an IMAGE id may come first or after the DISPLAY id  */
-  if (script_fu_param_init (script,
-                            nparams, params, SF_IMAGE, params_consumed))
-    {
-      params_consumed++;
-
-      /*  and may be followed by a DRAWABLE, LAYER, CHANNEL or
-       *  VECTORS id
-       */
-      if (script_fu_param_init (script,
-                                nparams, params, SF_DRAWABLE,
-                                params_consumed) ||
-          script_fu_param_init (script,
-                                nparams, params, SF_LAYER,
-                                params_consumed) ||
-          script_fu_param_init (script,
-                                nparams, params, SF_CHANNEL,
-                                params_consumed) ||
-          script_fu_param_init (script,
-                                nparams, params, SF_VECTORS,
-                                params_consumed))
-        {
-          params_consumed++;
-        }
-    }
-
-  return params_consumed;
-}
-
-static void
-script_fu_script_proc (const gchar      *name,
-                       gint              nparams,
-                       const GimpParam  *params,
-                       gint             *nreturn_vals,
-                       GimpParam       **return_vals)
-{
-  static GimpParam   values[2];
-  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
-  SFScript          *script;
-  GError            *error  = NULL;
-
-  *nreturn_vals = 1;
-  *return_vals  = values;
-
-  values[0].type = GIMP_PDB_STATUS;
-
-  script = script_fu_find_script (name);
-
-  if (! script)
-    status = GIMP_PDB_CALLING_ERROR;
-
-  if (status == GIMP_PDB_SUCCESS)
-    {
-      GimpRunMode run_mode = params[0].data.d_int32;
-
-      ts_set_run_mode (run_mode);
-
-      switch (run_mode)
-        {
-        case GIMP_RUN_INTERACTIVE:
-          {
-            gint min_args = 0;
-
-            /*  First, try to collect the standard script arguments...  */
-            min_args = script_fu_collect_standard_args (script,
-                                                        nparams, params);
-
-            /*  ...then acquire the rest of arguments (if any) with a dialog  */
-            if (script->num_args > min_args)
-              {
-                status = script_fu_interface (script, min_args);
-                break;
-              }
-            /*  otherwise (if the script takes no more arguments), skip
-             *  this part and run the script directly (fallthrough)
-             */
-          }
-
-        case GIMP_RUN_NONINTERACTIVE:
-          /*  Make sure all the arguments are there  */
-          if (nparams != (script->num_args + 1))
-            status = GIMP_PDB_CALLING_ERROR;
-
-          if (status == GIMP_PDB_SUCCESS)
-            {
-              GString *s;
-              gchar   *command;
-              gint     i;
-
-              s = g_string_new ("(");
-              g_string_append (s, script->name);
-
-              for (i = 0; i < script->num_args; i++)
-                {
-                  const GimpParam *param = &params[i + 1];
-
-                  g_string_append_c (s, ' ');
-
-                  switch (script->arg_types[i])
-                    {
-                    case SF_IMAGE:
-                    case SF_DRAWABLE:
-                    case SF_LAYER:
-                    case SF_CHANNEL:
-                    case SF_VECTORS:
-                    case SF_DISPLAY:
-                      g_string_append_printf (s, "%d", param->data.d_int32);
-                      break;
-
-                    case SF_COLOR:
-                      {
-                        guchar r, g, b;
-
-                        gimp_rgb_get_uchar (&param->data.d_color, &r, &g, &b);
-                        g_string_append_printf (s, "'(%d %d %d)",
-                                                (gint) r, (gint) g, (gint) b);
-                      }
-                      break;
-
-                    case SF_TOGGLE:
-                      g_string_append_printf (s, (param->data.d_int32 ?
-                                                  "TRUE" : "FALSE"));
-                      break;
-
-                    case SF_VALUE:
-                      g_string_append (s, param->data.d_string);
-                      break;
-
-                    case SF_STRING:
-                    case SF_TEXT:
-                    case SF_FILENAME:
-                    case SF_DIRNAME:
-                      {
-                        gchar *tmp;
-
-                        tmp = script_fu_strescape (param->data.d_string);
-                        g_string_append_printf (s, "\"%s\"", tmp);
-                        g_free (tmp);
-                      }
-                      break;
-
-                    case SF_ADJUSTMENT:
-                      {
-                        gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
-
-                        g_ascii_dtostr (buffer, sizeof (buffer),
-                                        param->data.d_float);
-                        g_string_append (s, buffer);
-                      }
-                      break;
-
-                    case SF_FONT:
-                    case SF_PALETTE:
-                    case SF_PATTERN:
-                    case SF_GRADIENT:
-                    case SF_BRUSH:
-                      g_string_append_printf (s, "\"%s\"",
-                                              param->data.d_string);
-                      break;
-
-                    case SF_OPTION:
-                    case SF_ENUM:
-                      g_string_append_printf (s, "%d", param->data.d_int32);
-                      break;
-                    }
-                }
-
-              g_string_append_c (s, ')');
-
-              command = g_string_free (s, FALSE);
-
-              /*  run the command through the interpreter  */
-              if (! script_fu_run_command (command, &error))
-                {
-                  status                  = GIMP_PDB_EXECUTION_ERROR;
-                  *nreturn_vals           = 2;
-                  values[2].data.d_string = error->message;
-                }
-
-              g_free (command);
-            }
-          break;
-
-        case GIMP_RUN_WITH_LAST_VALS:
-          {
-            GString *s;
-            gchar   *command;
-            gint     i;
-
-            /*  First, try to collect the standard script arguments  */
-            script_fu_collect_standard_args (script, nparams, params);
-
-            s = g_string_new ("(");
-            g_string_append (s, script->name);
-
-            for (i = 0; i < script->num_args; i++)
-              {
-                SFArgValue *arg_value = &script->arg_values[i];
-
-                g_string_append_c (s, ' ');
-
-                switch (script->arg_types[i])
-                  {
-                  case SF_IMAGE:
-                  case SF_DRAWABLE:
-                  case SF_LAYER:
-                  case SF_CHANNEL:
-                  case SF_VECTORS:
-                  case SF_DISPLAY:
-                    g_string_append_printf (s, "%d", arg_value->sfa_image);
-                    break;
-
-                  case SF_COLOR:
-                    {
-                      guchar r, g, b;
-
-                      gimp_rgb_get_uchar (&arg_value->sfa_color, &r, &g, &b);
-                      g_string_append_printf (s, "'(%d %d %d)",
-                                              (gint) r, (gint) g, (gint) b);
-                    }
-                    break;
-
-                  case SF_TOGGLE:
-                    g_string_append (s, arg_value->sfa_toggle ? "TRUE" : "FALSE");
-                    break;
-
-                  case SF_VALUE:
-                    g_string_append (s, arg_value->sfa_value);
-                    break;
-
-                  case SF_STRING:
-                  case SF_TEXT:
-                    {
-                      gchar *tmp;
-
-                      tmp = script_fu_strescape (arg_value->sfa_value);
-                      g_string_append_printf (s, "\"%s\"", tmp);
-                      g_free (tmp);
-                    }
-                    break;
-
-                  case SF_ADJUSTMENT:
-                    {
-                      gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
-
-                      g_ascii_dtostr (buffer, sizeof (buffer),
-                                      arg_value->sfa_adjustment.value);
-                      g_string_append (s, buffer);
-                    }
-                    break;
-
-                  case SF_FILENAME:
-                  case SF_DIRNAME:
-                    {
-                      gchar *tmp;
-
-                      tmp = script_fu_strescape (arg_value->sfa_file.filename);
-                      g_string_append_printf (s, "\"%s\"", tmp);
-                      g_free (tmp);
-                    }
-                    break;
-
-                  case SF_FONT:
-                    g_string_append_printf (s, "\"%s\"", arg_value->sfa_font);
-                    break;
-
-                  case SF_PALETTE:
-                    g_string_append_printf (s, "\"%s\"", arg_value->sfa_palette);
-                    break;
-
-                  case SF_PATTERN:
-                    g_string_append_printf (s, "\"%s\"", arg_value->sfa_pattern);
-                    break;
-
-                  case SF_GRADIENT:
-                    g_string_append_printf (s, "\"%s\"", arg_value->sfa_gradient);
-                    break;
-
-                  case SF_BRUSH:
-                    {
-                      gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
-
-                      g_ascii_dtostr (buffer, sizeof (buffer),
-                                      arg_value->sfa_brush.opacity);
-                      g_string_append_printf (s, "'(\"%s\" %s %d %d)",
-                                              arg_value->sfa_brush.name,
-                                              buffer,
-                                              arg_value->sfa_brush.spacing,
-                                              arg_value->sfa_brush.paint_mode);
-                    }
-                    break;
-
-                  case SF_OPTION:
-                    g_string_append_printf (s, "%d", arg_value->sfa_option.history);
-                    break;
-
-                  case SF_ENUM:
-                    g_string_append_printf (s, "%d", arg_value->sfa_enum.history);
-                    break;
-                  }
-              }
-
-            g_string_append_c (s, ')');
-
-            command = g_string_free (s, FALSE);
-
-            /*  run the command through the interpreter  */
-            if (! script_fu_run_command (command, &error))
-              {
-                status                  = GIMP_PDB_EXECUTION_ERROR;
-                *nreturn_vals           = 2;
-                values[2].data.d_string = error->message;
-              }
-
-            g_free (command);
-          }
+          type = GIMP_PDB_DISPLAY;
+          name = "display";
           break;
 
-        default:
+        case SF_COLOR:
+          type = GIMP_PDB_COLOR;
+          name = "color";
           break;
-        }
-    }
-
-  values[0].data.d_status = status;
-}
-
-/* this is a GTraverseFunction */
-static gboolean
-script_fu_lookup_script (gpointer      *foo G_GNUC_UNUSED,
-                         GList         *scripts,
-                         gconstpointer *name)
-{
-  GList *list;
-
-  for (list = scripts; list; list = g_list_next (list))
-    {
-      SFScript *script = list->data;
-
-      if (strcmp (script->name, *name) == 0)
-        {
-          /* store the script in the name pointer and stop the traversal */
-          *name = script;
-          return TRUE;
-        }
-    }
-
-  return FALSE;
-}
-
-static SFScript *
-script_fu_find_script (const gchar *name)
-{
-  gconstpointer script = name;
-
-  g_tree_foreach (script_tree,
-                  (GTraverseFunc) script_fu_lookup_script,
-                  &script);
-
-  if (script == name)
-    return NULL;
-
-  return (SFScript *) script;
-}
-
-static void
-script_fu_free_script (SFScript *script)
-{
-  gint i;
-
-  g_return_if_fail (script != NULL);
-
-  /*  Uninstall the temporary procedure for this script  */
-  gimp_uninstall_temp_proc (script->name);
-
-  g_free (script->name);
-  g_free (script->blurb);
-  g_free (script->menu_path);
-  g_free (script->author);
-  g_free (script->copyright);
-  g_free (script->date);
-  g_free (script->img_types);
 
-  for (i = 0; i < script->num_args; i++)
-    {
-      g_free (script->arg_labels[i]);
-      switch (script->arg_types[i])
-        {
-        case SF_IMAGE:
-        case SF_DRAWABLE:
-        case SF_LAYER:
-        case SF_CHANNEL:
-        case SF_VECTORS:
-        case SF_DISPLAY:
-        case SF_COLOR:
         case SF_TOGGLE:
+          type = GIMP_PDB_INT32;
+          name = "toggle";
           break;
 
         case SF_VALUE:
+          type = GIMP_PDB_STRING;
+          name = "value";
+          break;
+
         case SF_STRING:
         case SF_TEXT:
-          g_free (script->arg_defaults[i].sfa_value);
-          g_free (script->arg_values[i].sfa_value);
+          type = GIMP_PDB_STRING;
+          name = "string";
           break;
 
         case SF_ADJUSTMENT:
+          type = GIMP_PDB_FLOAT;
+          name = "value";
           break;
 
         case SF_FILENAME:
+          type = GIMP_PDB_STRING;
+          name = "filename";
+          break;
+
         case SF_DIRNAME:
-          g_free (script->arg_defaults[i].sfa_file.filename);
-          g_free (script->arg_values[i].sfa_file.filename);
+          type = GIMP_PDB_STRING;
+          name = "dirname";
           break;
 
         case SF_FONT:
-          g_free (script->arg_defaults[i].sfa_font);
-          g_free (script->arg_values[i].sfa_font);
+          type = GIMP_PDB_STRING;
+          name = "font";
           break;
 
         case SF_PALETTE:
-          g_free (script->arg_defaults[i].sfa_palette);
-          g_free (script->arg_values[i].sfa_palette);
+          type = GIMP_PDB_STRING;
+          name = "palette";
           break;
 
         case SF_PATTERN:
-          g_free (script->arg_defaults[i].sfa_pattern);
-          g_free (script->arg_values[i].sfa_pattern);
+          type = GIMP_PDB_STRING;
+          name = "pattern";
           break;
 
-        case SF_GRADIENT:
-          g_free (script->arg_defaults[i].sfa_gradient);
-          g_free (script->arg_values[i].sfa_gradient);
+        case SF_BRUSH:
+          type = GIMP_PDB_STRING;
+          name = "brush";
           break;
 
-        case SF_BRUSH:
-          g_free (script->arg_defaults[i].sfa_brush.name);
-          g_free (script->arg_values[i].sfa_brush.name);
+        case SF_GRADIENT:
+          type = GIMP_PDB_STRING;
+          name = "gradient";
           break;
 
         case SF_OPTION:
-          g_slist_foreach (script->arg_defaults[i].sfa_option.list,
-                           (GFunc) g_free, NULL);
-          g_slist_free (script->arg_defaults[i].sfa_option.list);
+          type = GIMP_PDB_INT32;
+          name = "option";
           break;
 
         case SF_ENUM:
-          g_free (script->arg_defaults[i].sfa_enum.type_name);
-          break;
-        }
-    }
-
-  g_free (script->arg_labels);
-  g_free (script->arg_defaults);
-  g_free (script->arg_types);
-  g_free (script->arg_values);
-
-  g_slice_free (SFScript, script);
-}
-
-static void
-script_fu_menu_map (SFScript *script)
-{
-  /*  for backward compatibility, we fiddle with some menu paths  */
-  const struct
-  {
-    const gchar *old;
-    const gchar *new;
-  } mapping[] = {
-    { "<Image>/Script-Fu/Alchemy",       "<Image>/Filters/Artistic"            },
-    { "<Image>/Script-Fu/Alpha to Logo", "<Image>/Filters/Alpha to Logo"       },
-    { "<Image>/Script-Fu/Animators",     "<Image>/Filters/Animation/Animators" },
-    { "<Image>/Script-Fu/Decor",         "<Image>/Filters/Decor"               },
-    { "<Image>/Script-Fu/Render",        "<Image>/Filters/Render"              },
-    { "<Image>/Script-Fu/Selection",     "<Image>/Select/Modify"               },
-    { "<Image>/Script-Fu/Shadow",        "<Image>/Filters/Light and Shadow/Shadow" },
-    { "<Image>/Script-Fu/Stencil Ops",   "<Image>/Filters/Decor"               }
-  };
-
-  gint i;
-
-  for (i = 0; i < G_N_ELEMENTS (mapping); i++)
-    {
-      if (g_str_has_prefix (script->menu_path, mapping[i].old))
-        {
-          const gchar *suffix = script->menu_path + strlen (mapping[i].old);
-          gchar       *tmp;
-
-          if (! *suffix == '/')
-            continue;
-
-          tmp = g_strconcat (mapping[i].new, suffix, NULL);
-
-          g_free (script->menu_path);
-          script->menu_path = tmp;
-
+          type = GIMP_PDB_INT32;
+          name = "enum";
           break;
         }
-    }
-}
-
-static gint
-script_fu_menu_compare (gconstpointer a,
-                        gconstpointer b)
-{
-  const SFMenu *menu_a = a;
-  const SFMenu *menu_b = b;
-  gint          retval = 0;
-
-  if (menu_a->menu_path && menu_b->menu_path)
-    {
-      retval = g_utf8_collate (gettext (menu_a->menu_path),
-                               gettext (menu_b->menu_path));
 
-      if (retval == 0 &&
-          menu_a->script->menu_path && menu_b->script->menu_path)
-        {
-          retval = g_utf8_collate (gettext (menu_a->script->menu_path),
-                                   gettext (menu_b->script->menu_path));
-        }
-    }
+      args[i + 1].type        = type;
+      args[i + 1].name        = (gchar *) name;
+      args[i + 1].description = script->args[i].label;
+    }
+
+  gimp_install_temp_proc (script->name,
+                          script->blurb,
+                          "",
+                          script->author,
+                          script->copyright,
+                          script->date,
+                          menu_path,
+                          script->image_types,
+                          GIMP_TEMPORARY,
+                          script->n_args + 1, 0,
+                          args, NULL,
+                          run_proc);
 
-  return retval;
+  g_free (args);
 }
 
-/*
- * Escapes the special characters '\b', '\f', '\n', '\r', '\t', '\' and '"'
- * in the string source by inserting a '\' before them.
- */
-gchar *
-script_fu_strescape (const gchar *source)
+void
+script_fu_script_uninstall_proc (SFScript *script)
 {
-  const guchar *p;
-  gchar        *dest;
-  gchar        *q;
-
-  g_return_val_if_fail (source != NULL, NULL);
-
-  p = (const guchar *) source;
-
-  /* Each source byte needs maximally two destination chars */
-  q = dest = g_malloc (strlen (source) * 2 + 1);
-
-  while (*p)
-    {
-      switch (*p)
-        {
-        case '\b':
-        case '\f':
-        case '\n':
-        case '\r':
-        case '\t':
-        case '\\':
-        case '"':
-          *q++ = '\\';
-          /* fallthrough */
-        default:
-          *q++ = *p;
-          break;
-        }
-
-      p++;
-    }
-
-  *q = 0;
+  g_return_if_fail (script != NULL);
 
-  return dest;
+  gimp_uninstall_temp_proc (script->name);
 }

Added: trunk/plug-ins/script-fu/script-fu-script.h
==============================================================================
--- (empty file)
+++ trunk/plug-ins/script-fu/script-fu-script.h	Wed Sep 17 21:39:44 2008
@@ -0,0 +1,38 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SCRIPT_FU_SCRIPT_H__
+#define __SCRIPT_FU_SCRIPT_H__
+
+
+SFScript * script_fu_script_new            (const gchar *name,
+                                            const gchar *menu_path,
+                                            const gchar *blurb,
+                                            const gchar *author,
+                                            const gchar *copyright,
+                                            const gchar *date,
+                                            const gchar *image_types,
+                                            gint         n_args);
+void       script_fu_script_free           (SFScript    *script);
+
+void       script_fu_script_install_proc   (SFScript    *script,
+                                            GimpRunProc  run_proc);
+void       script_fu_script_uninstall_proc (SFScript    *script);
+
+
+#endif /*  __SCRIPT_FU_SCRIPT__  */

Modified: trunk/plug-ins/script-fu/script-fu-scripts.c
==============================================================================
--- trunk/plug-ins/script-fu/script-fu-scripts.c	(original)
+++ trunk/plug-ins/script-fu/script-fu-scripts.c	Wed Sep 17 21:39:44 2008
@@ -37,6 +37,7 @@
 #include "script-fu-types.h"
 
 #include "script-fu-interface.h"
+#include "script-fu-script.h"
 #include "script-fu-scripts.h"
 
 #include "script-fu-intl.h"
@@ -71,7 +72,6 @@
                                            GimpParam              **return_vals);
 
 static SFScript *script_fu_find_script    (const gchar             *name);
-static void      script_fu_free_script    (SFScript                *script);
 
 static void      script_fu_menu_map       (SFScript                *script);
 static gint      script_fu_menu_compare   (gconstpointer            a,
@@ -132,488 +132,400 @@
 script_fu_add_script (scheme  *sc,
                       pointer  a)
 {
-  GimpParamDef *args;
-  SFScript     *script;
-  GType         enum_type;
-  GEnumValue   *enum_value;
-  const gchar  *val;
-  gint          i;
-  guchar        r, g, b;
-  pointer       color_list;
-  pointer       adj_list;
-  pointer       brush_list;
-  pointer       option_list;
+  SFScript    *script;
+  const gchar *name;
+  const gchar *menu_path;
+  const gchar *blurb;
+  const gchar *author;
+  const gchar *copyright;
+  const gchar *date;
+  const gchar *image_types;
+  gint         n_args;
+  gint         i;
 
   /*  Check the length of a  */
   if (sc->vptr->list_length (sc, a) < 7)
-  {
-    g_message (_("Too few arguments to 'script-fu-register' call"));
-
-    return sc->NIL;
-  }
-
-  /*  Create a new script  */
-  script = g_slice_new0 (SFScript);
+    {
+      g_message (_("Too few arguments to 'script-fu-register' call"));
+      return sc->NIL;
+    }
 
   /*  Find the script name  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->name = g_strdup (val);
+  name = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script menu_path  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->menu_path = g_strdup (val);
+  menu_path = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script blurb  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->blurb = g_strdup (val);
+  blurb = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script author  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->author = g_strdup (val);
+  author = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script copyright  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->copyright = g_strdup (val);
+  copyright = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script date  */
-  val = sc->vptr->string_value (sc->vptr->pair_car (a));
-  script->date = g_strdup (val);
+  date = sc->vptr->string_value (sc->vptr->pair_car (a));
   a = sc->vptr->pair_cdr (a);
 
   /*  Find the script image types  */
   if (sc->vptr->is_pair (a))
     {
-      val = sc->vptr->string_value (sc->vptr->pair_car (a));
+      image_types = sc->vptr->string_value (sc->vptr->pair_car (a));
       a = sc->vptr->pair_cdr (a);
     }
   else
     {
-      val = sc->vptr->string_value (a);
+      image_types = sc->vptr->string_value (a);
       a = sc->NIL;
     }
-  script->img_types = g_strdup (val);
 
   /*  Check the supplied number of arguments  */
-  script->num_args = sc->vptr->list_length (sc, a) / 3;
+  n_args = sc->vptr->list_length (sc, a) / 3;
 
-  args = g_new0 (GimpParamDef, script->num_args + 1);
+  /*  Create a new script  */
+  script = script_fu_script_new (name,
+                                 menu_path,
+                                 blurb,
+                                 author,
+                                 copyright,
+                                 date,
+                                 image_types,
+                                 n_args);
 
-  args[0].type        = GIMP_PDB_INT32;
-  args[0].name        = "run-mode";
-  args[0].description = "Interactive, non-interactive";
+  for (i = 0; i < script->n_args; i++)
+    {
+      SFArg *arg = &script->args[i];
 
-  script->arg_types    = g_new0 (SFArgType, script->num_args);
-  script->arg_labels   = g_new0 (gchar *, script->num_args);
-  script->arg_defaults = g_new0 (SFArgValue, script->num_args);
-  script->arg_values   = g_new0 (SFArgValue, script->num_args);
+      if (a != sc->NIL)
+        {
+          if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
+            return foreign_error (sc, "script-fu-register: argument types must be integer values", 0);
 
-  if (script->num_args > 0)
-    {
-      for (i = 0; i < script->num_args; i++)
+          arg->type = sc->vptr->ivalue (sc->vptr->pair_car (a));
+          a = sc->vptr->pair_cdr (a);
+        }
+      else
+        return foreign_error (sc, "script-fu-register: missing type specifier", 0);
+
+      if (a != sc->NIL)
+        {
+          if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+            return foreign_error (sc, "script-fu-register: argument labels must be strings", 0);
+
+          arg->label = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+          a = sc->vptr->pair_cdr (a);
+        }
+      else
+        return foreign_error (sc, "script-fu-register: missing arguments label", 0);
+
+      if (a != sc->NIL)
         {
-          if (a != sc->NIL)
+          switch (arg->type)
             {
+            case SF_IMAGE:
+            case SF_DRAWABLE:
+            case SF_LAYER:
+            case SF_CHANNEL:
+            case SF_VECTORS:
+            case SF_DISPLAY:
               if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                return foreign_error (sc, "script-fu-register: argument types must be integer values", 0);
-              script->arg_types[i] = sc->vptr->ivalue (sc->vptr->pair_car (a));
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            return foreign_error (sc, "script-fu-register: missing type specifier", 0);
+                return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0);
 
-          if (a != sc->NIL)
-            {
-              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                return foreign_error (sc, "script-fu-register: argument labels must be strings", 0);
-              script->arg_labels[i] = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            return foreign_error (sc, "script-fu-register: missing arguments label", 0);
+              arg->default_value.sfa_image =
+                sc->vptr->ivalue (sc->vptr->pair_car (a));
+              arg->value.sfa_image = arg->default_value.sfa_image;
+              break;
 
-          if (a != sc->NIL)
-            {
-              gchar *type_name;
+            case SF_COLOR:
+              if (sc->vptr->is_string (sc->vptr->pair_car (a)))
+                {
+                  if (! gimp_rgb_parse_css (&arg->default_value.sfa_color,
+                                            sc->vptr->string_value (sc->vptr->pair_car (a)),
+                                            -1))
+                    return foreign_error (sc, "script-fu-register: invalid default color name", 0);
 
-              switch (script->arg_types[i])
+                  gimp_rgb_set_alpha (&arg->default_value.sfa_color, 1.0);
+                }
+              else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) &&
+                       sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3)
                 {
-                case SF_IMAGE:
-                case SF_DRAWABLE:
-                case SF_LAYER:
-                case SF_CHANNEL:
-                case SF_VECTORS:
-                case SF_DISPLAY:
-                  if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0);
-                  script->arg_defaults[i].sfa_image =
-                      sc->vptr->ivalue (sc->vptr->pair_car (a));
-                  script->arg_values[i].sfa_image =
-                    script->arg_defaults[i].sfa_image;
+                  pointer color_list;
+                  guchar  r, g, b;
 
-                  switch (script->arg_types[i])
-                    {
-                    case SF_IMAGE:
-                      args[i + 1].type = GIMP_PDB_IMAGE;
-                      args[i + 1].name = "image";
-                      break;
+                  color_list = sc->vptr->pair_car (a);
+                  r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
+                  color_list = sc->vptr->pair_cdr (color_list);
+                  g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
+                  color_list = sc->vptr->pair_cdr (color_list);
+                  b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
 
-                    case SF_DRAWABLE:
-                      args[i + 1].type = GIMP_PDB_DRAWABLE;
-                      args[i + 1].name = "drawable";
-                      break;
+                  gimp_rgb_set_uchar (&arg->default_value.sfa_color, r, g, b);
+                }
+              else
+                {
+                  return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0);
+                }
 
-                    case SF_LAYER:
-                      args[i + 1].type = GIMP_PDB_LAYER;
-                      args[i + 1].name = "layer";
-                      break;
+              arg->value.sfa_color = arg->default_value.sfa_color;
+              break;
 
-                    case SF_CHANNEL:
-                      args[i + 1].type = GIMP_PDB_CHANNEL;
-                      args[i + 1].name = "channel";
-                      break;
+            case SF_TOGGLE:
+              if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0);
 
-                    case SF_VECTORS:
-                      args[i + 1].type = GIMP_PDB_VECTORS;
-                      args[i + 1].name = "vectors";
-                      break;
+              arg->default_value.sfa_toggle =
+                (sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE;
+              arg->value.sfa_toggle = arg->default_value.sfa_toggle;
+              break;
 
-                    case SF_DISPLAY:
-                      args[i + 1].type = GIMP_PDB_DISPLAY;
-                      args[i + 1].name = "display";
-                      break;
+            case SF_VALUE:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: value defaults must be string values", 0);
 
-                    default:
-                      break;
-                    }
+              arg->default_value.sfa_value =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_value = g_strdup (arg->default_value.sfa_value);
+              break;
 
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
+            case SF_STRING:
+            case SF_TEXT:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: string defaults must be string values", 0);
 
-                case SF_COLOR:
-                  if (sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    {
-                      if (! gimp_rgb_parse_css (&script->arg_defaults[i].sfa_color,
-                                                sc->vptr->string_value (sc->vptr->pair_car (a)),
-                                                -1))
-                        return foreign_error (sc, "script-fu-register: invalid default color name", 0);
-                      gimp_rgb_set_alpha (&script->arg_defaults[i].sfa_color,
-                                          1.0);
-                    }
-                  else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) &&
-                           sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3)
-                    {
-                      color_list = sc->vptr->pair_car (a);
-                      r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
-                      color_list = sc->vptr->pair_cdr (color_list);
-                      g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
-                      color_list = sc->vptr->pair_cdr (color_list);
-                      b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
+              arg->default_value.sfa_value =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_value = g_strdup (arg->default_value.sfa_value);
+              break;
 
-                      gimp_rgb_set_uchar (&script->arg_defaults[i].sfa_color, r, g, b);
-                    }
-                  else
-                    {
-                      return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0);
-                    }
+            case SF_ADJUSTMENT:
+              {
+                pointer adj_list;
 
-                  script->arg_values[i].sfa_color = script->arg_defaults[i].sfa_color;
+                if (!sc->vptr->is_list (sc, a))
+                  return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0);
 
-                  args[i + 1].type        = GIMP_PDB_COLOR;
-                  args[i + 1].name        = "color";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_TOGGLE:
-                  if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0);
-
-                  script->arg_defaults[i].sfa_toggle =
-                    (sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE;
-                  script->arg_values[i].sfa_toggle =
-                    script->arg_defaults[i].sfa_toggle;
-
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "toggle";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_VALUE:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: value defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_value =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_value =
-                    g_strdup (script->arg_defaults[i].sfa_value);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "value";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_STRING:
-                case SF_TEXT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: string defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_value =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_value =
-                    g_strdup (script->arg_defaults[i].sfa_value);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "string";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_ADJUSTMENT:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0);
-
-                  adj_list = sc->vptr->pair_car (a);
-                  script->arg_defaults[i].sfa_adjustment.value =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.lower =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.upper =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.step =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.page =
-                    sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.digits =
-                    sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
-
-                  adj_list = sc->vptr->pair_cdr (adj_list);
-                  script->arg_defaults[i].sfa_adjustment.type =
-                    sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
-
-                  script->arg_values[i].sfa_adjustment.adj = NULL;
-                  script->arg_values[i].sfa_adjustment.value =
-                    script->arg_defaults[i].sfa_adjustment.value;
-
-                  args[i + 1].type        = GIMP_PDB_FLOAT;
-                  args[i + 1].name        = "value";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_FILENAME:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0);
-                  /* fallthrough */
-
-                case SF_DIRNAME:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0);
+                adj_list = sc->vptr->pair_car (a);
+                arg->default_value.sfa_adjustment.value =
+                  sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.lower =
+                  sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.upper =
+                  sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.step =
+                  sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.page =
+                  sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.digits =
+                  sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
+
+                adj_list = sc->vptr->pair_cdr (adj_list);
+                arg->default_value.sfa_adjustment.type =
+                  sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
+
+                arg->value.sfa_adjustment.adj = NULL;
+                arg->value.sfa_adjustment.value =
+                  arg->default_value.sfa_adjustment.value;
+              }
+              break;
+
+            case SF_FILENAME:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0);
+              /* fallthrough */
+
+            case SF_DIRNAME:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0);
 
-                  script->arg_defaults[i].sfa_file.filename =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->default_value.sfa_file.filename =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
 
 #ifdef G_OS_WIN32
-                  {
-                    /* Replace POSIX slashes with Win32 backslashes. This
-                     * is just so script-fus can be written with only
-                     * POSIX directory separators.
-                     */
-                    gchar *filename = script->arg_defaults[i].sfa_file.filename;
+              {
+                /* Replace POSIX slashes with Win32 backslashes. This
+                 * is just so script-fus can be written with only
+                 * POSIX directory separators.
+                 */
+                gchar *filename = arg->default_values.sfa_file.filename;
 
-                    while (*filename)
-                      {
-                        if (*filename == '/')
-                          *filename = G_DIR_SEPARATOR;
+                while (*filename)
+                  {
+                    if (*filename == '/')
+                      *filename = G_DIR_SEPARATOR;
 
-                        filename++;
-                      }
+                    filename++;
                   }
+              }
 #endif
-                  script->arg_values[i].sfa_file.filename =
-                    g_strdup (script->arg_defaults[i].sfa_file.filename);
 
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = (script->arg_types[i] == SF_FILENAME ?
-                                             "filename" : "dirname");
-                  args[i + 1].description = script->arg_labels[i];
-                 break;
-
-                case SF_FONT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: font defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_font =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_font =
-                    g_strdup (script->arg_defaults[i].sfa_font);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "font";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_PALETTE:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_palette =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_palette =
-                    g_strdup (script->arg_defaults[i].sfa_pattern);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "palette";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_PATTERN:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_pattern =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_pattern =
-                    g_strdup (script->arg_defaults[i].sfa_pattern);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "pattern";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_BRUSH:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
-
-                  brush_list = sc->vptr->pair_car (a);
-                  script->arg_defaults[i].sfa_brush.name =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
-                  script->arg_values[i].sfa_brush.name =
-                    g_strdup (script->arg_defaults[i].sfa_brush.name);
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.opacity =
-                    sc->vptr->rvalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.opacity =
-                    script->arg_defaults[i].sfa_brush.opacity;
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.spacing =
-                    sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.spacing =
-                    script->arg_defaults[i].sfa_brush.spacing;
-
-                  brush_list = sc->vptr->pair_cdr (brush_list);
-                  script->arg_defaults[i].sfa_brush.paint_mode =
-                    sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
-                  script->arg_values[i].sfa_brush.paint_mode =
-                    script->arg_defaults[i].sfa_brush.paint_mode;
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "brush";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_GRADIENT:
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
-                    return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0);
-
-                  script->arg_defaults[i].sfa_gradient =
-                    g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
-                  script->arg_values[i].sfa_gradient =
-                    g_strdup (script->arg_defaults[i].sfa_gradient);
-
-                  args[i + 1].type        = GIMP_PDB_STRING;
-                  args[i + 1].name        = "gradient";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_OPTION:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: option defaults must be a list", 0);
-
-                  for (option_list = sc->vptr->pair_car (a);
-                       option_list != sc->NIL;
-                       option_list = sc->vptr->pair_cdr (option_list))
-                    {
-                      script->arg_defaults[i].sfa_option.list =
-                        g_slist_append (script->arg_defaults[i].sfa_option.list,
-                                        g_strdup (sc->vptr->string_value
-                                           (sc->vptr->pair_car (option_list))));
-                    }
+              arg->value.sfa_file.filename =
+                g_strdup (arg->default_value.sfa_file.filename);
+              break;
 
-                  script->arg_defaults[i].sfa_option.history = 0;
-                  script->arg_values[i].sfa_option.history = 0;
+            case SF_FONT:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: font defaults must be string values", 0);
 
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "option";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-
-                case SF_ENUM:
-                  if (!sc->vptr->is_list (sc, a))
-                    return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0);
-
-                  option_list = sc->vptr->pair_car (a);
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
-                    return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0);
-
-                  val =
-                    sc->vptr->string_value (sc->vptr->pair_car (option_list));
-
-                  if (g_str_has_prefix (val, "Gimp"))
-                    type_name = g_strdup (val);
-                  else
-                    type_name = g_strconcat ("Gimp", val, NULL);
+              arg->default_value.sfa_font =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_font = g_strdup (arg->default_value.sfa_font);
+              break;
 
-                  enum_type = g_type_from_name (type_name);
-                  if (! G_TYPE_IS_ENUM (enum_type))
-                    {
-                      g_free (type_name);
-                      return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0);
-                    }
+            case SF_PALETTE:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0);
 
-                  script->arg_defaults[i].sfa_enum.type_name = type_name;
+              arg->default_value.sfa_palette =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_palette =
+                g_strdup (arg->default_value.sfa_palette);
+              break;
 
-                  option_list = sc->vptr->pair_cdr (option_list);
-                  if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
-                    return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0);
-
-                  enum_value =
-                    g_enum_get_value_by_nick (g_type_class_peek (enum_type),
-                      sc->vptr->string_value (sc->vptr->pair_car (option_list)));
-                  if (enum_value)
-                    script->arg_defaults[i].sfa_enum.history =
-                      script->arg_values[i].sfa_enum.history = enum_value->value;
-
-                  args[i + 1].type        = GIMP_PDB_INT32;
-                  args[i + 1].name        = "enum";
-                  args[i + 1].description = script->arg_labels[i];
-                  break;
-                }
+            case SF_PATTERN:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0);
 
-              a = sc->vptr->pair_cdr (a);
-            }
-          else
-            {
-              return foreign_error (sc, "script-fu-register: missing default argument", 0);
+              arg->default_value.sfa_pattern =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_pattern =
+                g_strdup (arg->default_value.sfa_pattern);
+              break;
+
+            case SF_BRUSH:
+              {
+                pointer brush_list;
+
+                if (!sc->vptr->is_list (sc, a))
+                  return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
+
+                brush_list = sc->vptr->pair_car (a);
+                arg->default_value.sfa_brush.name =
+                  g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
+                arg->value.sfa_brush.name =
+                  g_strdup (arg->default_value.sfa_brush.name);
+
+                brush_list = sc->vptr->pair_cdr (brush_list);
+                arg->default_value.sfa_brush.opacity =
+                  sc->vptr->rvalue (sc->vptr->pair_car (brush_list));
+                arg->value.sfa_brush.opacity =
+                  arg->default_value.sfa_brush.opacity;
+
+                brush_list = sc->vptr->pair_cdr (brush_list);
+                arg->default_value.sfa_brush.spacing =
+                  sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
+                arg->value.sfa_brush.spacing =
+                  arg->default_value.sfa_brush.spacing;
+
+                brush_list = sc->vptr->pair_cdr (brush_list);
+                arg->default_value.sfa_brush.paint_mode =
+                  sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
+                arg->value.sfa_brush.paint_mode =
+                  arg->default_value.sfa_brush.paint_mode;
+              }
+              break;
+
+            case SF_GRADIENT:
+              if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
+                return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0);
+
+              arg->default_value.sfa_gradient =
+                g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
+              arg->value.sfa_gradient =
+                g_strdup (arg->default_value.sfa_gradient);
+              break;
+
+            case SF_OPTION:
+              {
+                pointer option_list;
+
+                if (!sc->vptr->is_list (sc, a))
+                  return foreign_error (sc, "script-fu-register: option defaults must be a list", 0);
+
+                for (option_list = sc->vptr->pair_car (a);
+                     option_list != sc->NIL;
+                     option_list = sc->vptr->pair_cdr (option_list))
+                  {
+                    arg->default_value.sfa_option.list =
+                      g_slist_append (arg->default_value.sfa_option.list,
+                                      g_strdup (sc->vptr->string_value
+                                                (sc->vptr->pair_car (option_list))));
+                  }
+
+                arg->default_value.sfa_option.history = 0;
+                arg->value.sfa_option.history = 0;
+              }
+              break;
+
+            case SF_ENUM:
+              {
+                pointer      option_list;
+                const gchar *val;
+                gchar       *type_name;
+                GEnumValue  *enum_value;
+                GType        enum_type;
+
+                if (!sc->vptr->is_list (sc, a))
+                  return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0);
+
+                option_list = sc->vptr->pair_car (a);
+                if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
+                  return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0);
+
+                val = sc->vptr->string_value (sc->vptr->pair_car (option_list));
+
+                if (g_str_has_prefix (val, "Gimp"))
+                  type_name = g_strdup (val);
+                else
+                  type_name = g_strconcat ("Gimp", val, NULL);
+
+                enum_type = g_type_from_name (type_name);
+                if (! G_TYPE_IS_ENUM (enum_type))
+                  {
+                    g_free (type_name);
+                    return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0);
+                  }
+
+                arg->default_value.sfa_enum.type_name = type_name;
+
+                option_list = sc->vptr->pair_cdr (option_list);
+                if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
+                  return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0);
+
+                enum_value =
+                  g_enum_get_value_by_nick (g_type_class_peek (enum_type),
+                                            sc->vptr->string_value (sc->vptr->pair_car (option_list)));
+                if (enum_value)
+                  arg->default_value.sfa_enum.history =
+                    arg->value.sfa_enum.history = enum_value->value;
+              }
+              break;
             }
+
+          a = sc->vptr->pair_cdr (a);
+        }
+      else
+        {
+          return foreign_error (sc, "script-fu-register: missing default argument", 0);
         }
     }
 
-  script->args = args;
-
   script_fu_menu_map (script);
 
   {
@@ -645,10 +557,10 @@
   script = script_fu_find_script (name);
 
   if (! script)
-  {
-    g_message ("Procedure %s in script-fu-menu-register does not exist", name);
-    return sc->NIL;
-  }
+    {
+      g_message ("Procedure %s in script-fu-menu-register does not exist", name);
+      return sc->NIL;
+    }
 
   /*  Create a new list of menus  */
   menu = g_slice_new0 (SFMenu);
@@ -729,7 +641,6 @@
 
 /*
  *  The following function is a GTraverseFunction.
- *  Please note that it frees the script->args structure.
  */
 static gboolean
 script_fu_install_script (gpointer  foo G_GNUC_UNUSED,
@@ -739,30 +650,8 @@
   GList *list;
 
   for (list = scripts; list; list = g_list_next (list))
-    {
-      SFScript    *script    = list->data;
-      const gchar *menu_path = NULL;
-
-      /* Allow scripts with no menus */
-      if (strncmp (script->menu_path, "<None>", 6) != 0)
-        menu_path = script->menu_path;
-
-      gimp_install_temp_proc (script->name,
-                              script->blurb,
-                              "",
-                              script->author,
-                              script->copyright,
-                              script->date,
-                              menu_path,
-                              script->img_types,
-                              GIMP_TEMPORARY,
-                              script->num_args + 1, 0,
-                              script->args, NULL,
-                              script_fu_script_proc);
-
-      g_free (script->args);
-      script->args = NULL;
-    }
+    script_fu_script_install_proc (list->data,
+                                   script_fu_script_proc);
 
   return FALSE;
 }
@@ -787,13 +676,19 @@
   GList *list;
 
   for (list = scripts; list; list = g_list_next (list))
-    script_fu_free_script (list->data);
+    {
+      SFScript *script = list->data;
+
+      script_fu_script_uninstall_proc (script);
+      script_fu_script_free (script);
+    }
 
   g_list_free (scripts);
 
   return FALSE;
 }
 
+
 static gboolean
 script_fu_param_init (SFScript        *script,
                       gint             nparams,
@@ -801,14 +696,16 @@
                       SFArgType        type,
                       gint             n)
 {
-  if (script->num_args > n && script->arg_types[n] == type && nparams > n + 1)
+  SFArg *arg = &script->args[n];
+
+  if (script->n_args > n && arg->type == type && nparams > n + 1)
     {
       switch (type)
         {
         case SF_IMAGE:
           if (params[n + 1].type == GIMP_PDB_IMAGE)
             {
-              script->arg_values[n].sfa_image = params[n + 1].data.d_image;
+              arg->value.sfa_image = params[n + 1].data.d_image;
               return TRUE;
             }
           break;
@@ -816,7 +713,7 @@
         case SF_DRAWABLE:
           if (params[n + 1].type == GIMP_PDB_DRAWABLE)
             {
-              script->arg_values[n].sfa_drawable = params[n + 1].data.d_drawable;
+              arg->value.sfa_drawable = params[n + 1].data.d_drawable;
               return TRUE;
             }
           break;
@@ -824,7 +721,7 @@
         case SF_LAYER:
           if (params[n + 1].type == GIMP_PDB_LAYER)
             {
-              script->arg_values[n].sfa_layer = params[n + 1].data.d_layer;
+              arg->value.sfa_layer = params[n + 1].data.d_layer;
               return TRUE;
             }
           break;
@@ -832,7 +729,7 @@
         case SF_CHANNEL:
           if (params[n + 1].type == GIMP_PDB_CHANNEL)
             {
-              script->arg_values[n].sfa_channel = params[n + 1].data.d_channel;
+              arg->value.sfa_channel = params[n + 1].data.d_channel;
               return TRUE;
             }
           break;
@@ -840,7 +737,7 @@
         case SF_VECTORS:
           if (params[n + 1].type == GIMP_PDB_VECTORS)
             {
-              script->arg_values[n].sfa_vectors = params[n + 1].data.d_vectors;
+              arg->value.sfa_vectors = params[n + 1].data.d_vectors;
               return TRUE;
             }
           break;
@@ -848,7 +745,7 @@
         case SF_DISPLAY:
           if (params[n + 1].type == GIMP_PDB_DISPLAY)
             {
-              script->arg_values[n].sfa_display = params[n + 1].data.d_display;
+              arg->value.sfa_display = params[n + 1].data.d_display;
               return TRUE;
             }
           break;
@@ -943,7 +840,7 @@
                                                         nparams, params);
 
             /*  ...then acquire the rest of arguments (if any) with a dialog  */
-            if (script->num_args > min_args)
+            if (script->n_args > min_args)
               {
                 status = script_fu_interface (script, min_args);
                 break;
@@ -955,7 +852,7 @@
 
         case GIMP_RUN_NONINTERACTIVE:
           /*  Make sure all the arguments are there  */
-          if (nparams != (script->num_args + 1))
+          if (nparams != (script->n_args + 1))
             status = GIMP_PDB_CALLING_ERROR;
 
           if (status == GIMP_PDB_SUCCESS)
@@ -967,13 +864,13 @@
               s = g_string_new ("(");
               g_string_append (s, script->name);
 
-              for (i = 0; i < script->num_args; i++)
+              for (i = 0; i < script->n_args; i++)
                 {
                   const GimpParam *param = &params[i + 1];
 
                   g_string_append_c (s, ' ');
 
-                  switch (script->arg_types[i])
+                  switch (script->args[i].type)
                     {
                     case SF_IMAGE:
                     case SF_DRAWABLE:
@@ -1070,13 +967,13 @@
             s = g_string_new ("(");
             g_string_append (s, script->name);
 
-            for (i = 0; i < script->num_args; i++)
+            for (i = 0; i < script->n_args; i++)
               {
-                SFArgValue *arg_value = &script->arg_values[i];
+                SFArgValue *arg_value = &script->args[i].value;
 
                 g_string_append_c (s, ' ');
 
-                switch (script->arg_types[i])
+                switch (script->args[i].type)
                   {
                   case SF_IMAGE:
                   case SF_DRAWABLE:
@@ -1240,100 +1137,6 @@
 }
 
 static void
-script_fu_free_script (SFScript *script)
-{
-  gint i;
-
-  g_return_if_fail (script != NULL);
-
-  /*  Uninstall the temporary procedure for this script  */
-  gimp_uninstall_temp_proc (script->name);
-
-  g_free (script->name);
-  g_free (script->blurb);
-  g_free (script->menu_path);
-  g_free (script->author);
-  g_free (script->copyright);
-  g_free (script->date);
-  g_free (script->img_types);
-
-  for (i = 0; i < script->num_args; i++)
-    {
-      g_free (script->arg_labels[i]);
-      switch (script->arg_types[i])
-        {
-        case SF_IMAGE:
-        case SF_DRAWABLE:
-        case SF_LAYER:
-        case SF_CHANNEL:
-        case SF_VECTORS:
-        case SF_DISPLAY:
-        case SF_COLOR:
-        case SF_TOGGLE:
-          break;
-
-        case SF_VALUE:
-        case SF_STRING:
-        case SF_TEXT:
-          g_free (script->arg_defaults[i].sfa_value);
-          g_free (script->arg_values[i].sfa_value);
-          break;
-
-        case SF_ADJUSTMENT:
-          break;
-
-        case SF_FILENAME:
-        case SF_DIRNAME:
-          g_free (script->arg_defaults[i].sfa_file.filename);
-          g_free (script->arg_values[i].sfa_file.filename);
-          break;
-
-        case SF_FONT:
-          g_free (script->arg_defaults[i].sfa_font);
-          g_free (script->arg_values[i].sfa_font);
-          break;
-
-        case SF_PALETTE:
-          g_free (script->arg_defaults[i].sfa_palette);
-          g_free (script->arg_values[i].sfa_palette);
-          break;
-
-        case SF_PATTERN:
-          g_free (script->arg_defaults[i].sfa_pattern);
-          g_free (script->arg_values[i].sfa_pattern);
-          break;
-
-        case SF_GRADIENT:
-          g_free (script->arg_defaults[i].sfa_gradient);
-          g_free (script->arg_values[i].sfa_gradient);
-          break;
-
-        case SF_BRUSH:
-          g_free (script->arg_defaults[i].sfa_brush.name);
-          g_free (script->arg_values[i].sfa_brush.name);
-          break;
-
-        case SF_OPTION:
-          g_slist_foreach (script->arg_defaults[i].sfa_option.list,
-                           (GFunc) g_free, NULL);
-          g_slist_free (script->arg_defaults[i].sfa_option.list);
-          break;
-
-        case SF_ENUM:
-          g_free (script->arg_defaults[i].sfa_enum.type_name);
-          break;
-        }
-    }
-
-  g_free (script->arg_labels);
-  g_free (script->arg_defaults);
-  g_free (script->arg_types);
-  g_free (script->arg_values);
-
-  g_slice_free (SFScript, script);
-}
-
-static void
 script_fu_menu_map (SFScript *script)
 {
   /*  for backward compatibility, we fiddle with some menu paths  */

Modified: trunk/plug-ins/script-fu/script-fu-types.h
==============================================================================
--- trunk/plug-ins/script-fu/script-fu-types.h	(original)
+++ trunk/plug-ins/script-fu/script-fu-types.h	Wed Sep 17 21:39:44 2008
@@ -50,14 +50,14 @@
 
 typedef struct
 {
-  GSList  *list;
-  gint     history;
+  GSList *list;
+  gint    history;
 } SFOption;
 
 typedef struct
 {
-  gchar   *type_name;
-  gint     history;
+  gchar *type_name;
+  gint   history;
 } SFEnum;
 
 typedef union
@@ -84,19 +84,24 @@
 
 typedef struct
 {
-  gchar         *name;
-  gchar         *menu_path;
-  gchar         *blurb;
-  gchar         *author;
-  gchar         *copyright;
-  gchar         *date;
-  gchar         *img_types;
-  gint           num_args;
-  SFArgType     *arg_types;
-  gchar        **arg_labels;
-  SFArgValue    *arg_defaults;
-  SFArgValue    *arg_values;
-  GimpParamDef  *args;     /*  used only temporary until installed  */
+  SFArgType   type;
+  gchar      *label;
+  SFArgValue  default_value;
+  SFArgValue  value;
+} SFArg;
+
+typedef struct
+{
+  gchar        *name;
+  gchar        *menu_path;
+  gchar        *blurb;
+  gchar        *author;
+  gchar        *copyright;
+  gchar        *date;
+  gchar        *image_types;
+
+  gint          n_args;
+  SFArg        *args;
 } SFScript;
 
 



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