[gimp] plug-ins: port file-xmc to GimpPlugIn and new API objects



commit e146e4747ad317d21c52d65f3d686f68107652bb
Author: Michael Natterer <mitch gimp org>
Date:   Wed Aug 21 17:18:23 2019 +0200

    plug-ins: port file-xmc to GimpPlugIn and new API objects

 plug-ins/common/Makefile.am    |    2 -
 plug-ins/common/file-xmc.c     | 1053 +++++++++++++++++++++-------------------
 plug-ins/common/plugin-defs.pl |    2 +-
 3 files changed, 560 insertions(+), 497 deletions(-)
---
diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index 03bf6a3f79..83c076940f 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -1197,8 +1197,6 @@ file_xbm_LDADD = \
        $(INTLLIBS)             \
        $(file_xbm_RC)
 
-file_xmc_CPPFLAGS = $(AM_CPPFLAGS) -DGIMP_DEPRECATED_REPLACE_NEW_API
-
 file_xmc_SOURCES = \
        file-xmc.c
 
diff --git a/plug-ins/common/file-xmc.c b/plug-ins/common/file-xmc.c
index 7c6342730b..885206aeed 100644
--- a/plug-ins/common/file-xmc.c
+++ b/plug-ins/common/file-xmc.c
@@ -130,12 +130,9 @@
 #define CURSOR_MINIMUM_DELAY    5
 
 #define div_255(x)       (((x) + 0x80 + (((x) + 0x80) >> 8)) >> 8)
-#define READ32(f, e)     read32 ((f), (e)); if (*(e)) return -1;
+#define READ32(f, e)     read32 ((f), (e)); if (*(e)) return NULL;
 #define DISPLAY_DIGIT(x) ((x) > 100) ? 3 : ((x) > 10) ? 2 : 1
 
-/*
- * Structures...
- */
 
 typedef struct
 {
@@ -146,107 +143,132 @@ typedef struct
   gboolean    delay_replace;
 } XmcSaveVals;
 
-/*
- * Local functions...
- */
 
-static void      query                     (void);
+typedef struct _Xmc      Xmc;
+typedef struct _XmcClass XmcClass;
 
-static void      run                       (const gchar      *name,
-                                            gint              nparams,
-                                            const GimpParam  *param,
-                                            gint             *nreturn_vals,
-                                            GimpParam       **return_vals);
+struct _Xmc
+{
+  GimpPlugIn      parent_instance;
+};
 
-static gint32    load_image                (const gchar      *filename,
-                                            GError          **error);
+struct _XmcClass
+{
+  GimpPlugInClass parent_class;
+};
 
-static gint32    load_thumbnail            (const gchar      *filename,
-                                            gint32            thumb_size,
-                                            gint32           *width,
-                                            gint32           *height,
-                                            gint32           *num_layers,
-                                            GError          **error);
 
-static guint32   read32                    (FILE             *f,
-                                            GError          **error);
+#define XMC_TYPE  (xmc_get_type ())
+#define XMC (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XMC_TYPE, Xmc))
 
-static gboolean  save_image                (const gchar      *filename,
-                                            gint32            image_ID,
-                                            gint32            drawable_ID,
-                                            gint32            orig_image_ID,
-                                            GError          **error);
+GType                   xmc_get_type         (void) G_GNUC_CONST;
 
-static gboolean  save_dialog               (const gint32      image_ID,
-                                            GeglRectangle    *hotspotRange);
+static GList          * xmc_query_procedures (GimpPlugIn           *plug_in);
+static GimpProcedure  * xmc_create_procedure (GimpPlugIn           *plug_in,
+                                              const gchar          *name);
 
-static void      comment_entry_callback    (GtkWidget        *widget,
-                                            gchar           **commentp);
+static GimpValueArray * xmc_load             (GimpProcedure        *procedure,
+                                              GimpRunMode           run_mode,
+                                              GFile                *file,
+                                              const GimpValueArray *args,
+                                              gpointer              run_data);
+static GimpValueArray * xmc_load_thumb       (GimpProcedure        *procedure,
+                                              GFile                *file,
+                                              gint                  size,
+                                              const GimpValueArray *args,
+                                              gpointer              run_data);
+static GimpValueArray * xmc_save             (GimpProcedure        *procedure,
+                                              GimpRunMode           run_mode,
+                                              GimpImage            *image,
+                                              GimpDrawable         *drawable,
+                                              GFile                *file,
+                                              const GimpValueArray *args,
+                                              gpointer              run_data);
 
-static void      text_view_callback        (GtkTextBuffer    *buffer,
-                                            gchar           **commentp);
+static GimpImage      * load_image           (const gchar      *filename,
+                                              GError          **error);
 
-static gboolean  load_default_hotspot      (const gint32      image_ID,
-                                            GeglRectangle    *hotspotRange);
+static GimpImage      * load_thumbnail       (const gchar      *filename,
+                                              gint32            thumb_size,
+                                              gint32           *width,
+                                              gint32           *height,
+                                              gint32           *num_layers,
+                                              GError          **error);
 
-static inline guint32   separate_alpha     (guint32           pixel);
+static guint32          read32               (FILE             *f,
+                                              GError          **error);
 
-static inline guint32   premultiply_alpha  (guint32           pixel);
+static gboolean         save_image           (const gchar      *filename,
+                                              GimpImage        *image,
+                                              GimpDrawable     *drawable,
+                                              GimpImage        *orig_image,
+                                              GError          **error);
 
-static XcursorComments *set_cursor_comments (void);
+static gboolean         save_dialog          (GimpImage        *image,
+                                              GeglRectangle    *hotspotRange);
 
-static void      load_comments             (const gint32      image_ID);
+static void             comment_entry_callback (GtkWidget      *widget,
+                                                gchar         **commentp);
 
-static gboolean  set_comment_to_pname      (const gint32      image_ID,
-                                            const gchar      *content,
-                                            const gchar      *pname);
+static void             text_view_callback   (GtkTextBuffer    *buffer,
+                                              gchar           **commentp);
 
-static gchar    *get_comment_from_pname    (const gint32      image_ID,
-                                            const gchar       *pname);
+static gboolean         load_default_hotspot (GimpImage        *image,
+                                              GeglRectangle    *hotspotRange);
 
-static gboolean  set_hotspot_to_parasite   (gint32            image_ID);
+static inline guint32   separate_alpha       (guint32           pixel);
 
-static gboolean  get_hotspot_from_parasite (gint32            image_ID);
+static inline guint32   premultiply_alpha    (guint32           pixel);
 
-static void      set_size_and_delay        (const gchar       *framename,
-                                            guint32           *sizep,
-                                            guint32           *delayp,
-                                            GRegex            *re,
-                                            gboolean          *size_warnp);
+static XcursorComments *set_cursor_comments  (void);
 
-static gchar    *make_framename            (guint32            size,
-                                            guint32            delay,
-                                            guint              indent,
-                                            GError           **errorp);
+static void             load_comments        (GimpImage        *image);
 
-static void      get_cropped_region        (GeglRectangle     *retrun_rgn,
-                                            GeglBuffer        *buffer);
+static gboolean         set_comment_to_pname (GimpImage        *image,
+                                              const gchar      *content,
+                                              const gchar      *pname);
 
-static inline gboolean pix_is_opaque       (guint32            pix);
+static gchar          * get_comment_from_pname (GimpImage      *image,
+                                                const gchar    *pname);
 
-static GeglRectangle * get_intersection_of_frames (gint32      image_ID);
+static gboolean         set_hotspot_to_parasite (GimpImage     *image);
 
-static gboolean   pix_in_region            (gint32             x,
-                                            gint32             y,
-                                            GeglRectangle     *xmcrp);
+static gboolean         get_hotspot_from_parasite (GimpImage  *image);
 
-static void find_hotspots_and_dimensions   (XcursorImages     *xcIs,
-                                            gint32            *xhot,
-                                            gint32            *yhot,
-                                            gint32            *width,
-                                            gint32            *height);
+static void             set_size_and_delay   (const gchar      *framename,
+                                              guint32          *sizep,
+                                              guint32          *delayp,
+                                              GRegex           *re,
+                                              gboolean         *size_warnp);
 
-/*
- * Globals...
- */
+static gchar          * make_framename       (guint32           size,
+                                              guint32           delay,
+                                              guint             indent,
+                                              GError          **errorp);
+
+static void             get_cropped_region   (GeglRectangle    *retrun_rgn,
+                                              GeglBuffer       *buffer);
+
+static inline gboolean  pix_is_opaque        (guint32           pix);
+
+static GeglRectangle  * get_intersection_of_frames (GimpImage  *image);
+
+static gboolean         pix_in_region        (gint32            x,
+                                              gint32            y,
+                                              GeglRectangle    *xmcrp);
+
+static void             find_hotspots_and_dimensions
+                                             (XcursorImages    *xcIs,
+                                              gint32           *xhot,
+                                              gint32           *yhot,
+                                              gint32           *width,
+                                              gint32           *height);
+
+
+G_DEFINE_TYPE (Xmc, xmc, GIMP_TYPE_PLUG_IN)
+
+GIMP_MAIN (XMC_TYPE)
 
-const GimpPlugInInfo PLUG_IN_INFO =
-{
-  NULL,
-  NULL,
-  query,
-  run
-};
 
 static XmcSaveVals xmcvals =
 {
@@ -271,390 +293,418 @@ static const gchar *parasiteName[3] = { "xmc-copyright",
                                         "xmc-license",
                                         "gimp-comment" };
 
-/*
- * 'main()' - Main entry - just call gimp_main()...
- */
-
-MAIN ()
 
+static void
+xmc_class_init (XmcClass *klass)
+{
+  GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
 
-/*
- * 'query()' - Respond to a plug-in query...
- */
+  plug_in_class->query_procedures = xmc_query_procedures;
+  plug_in_class->create_procedure = xmc_create_procedure;
+}
 
 static void
-query (void)
+xmc_init (Xmc *xmc)
 {
-  static const GimpParamDef load_args[] =
-    {
-      { GIMP_PDB_INT32,  "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
-      { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
-      { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
-    };
-  static const GimpParamDef load_return_vals[] =
-    {
-      { GIMP_PDB_IMAGE, "image", "Output image" }
-    };
+}
+
+static GList *
+xmc_query_procedures (GimpPlugIn *plug_in)
+{
+  GList *list = NULL;
 
-  static const GimpParamDef thumb_args[] =
+  list = g_list_append (list, g_strdup (LOAD_PROC));
+  list = g_list_append (list, g_strdup (LOAD_THUMB_PROC));
+  list = g_list_append (list, g_strdup (SAVE_PROC));
+
+  return list;
+}
+
+static GimpProcedure *
+xmc_create_procedure (GimpPlugIn  *plug_in,
+                      const gchar *name)
+{
+  GimpProcedure *procedure = NULL;
+
+  if (! strcmp (name, LOAD_PROC))
     {
-      { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
-      { GIMP_PDB_INT32,  "thumb-size",   "Preferred thumbnail size"     }
-    };
-  static const GimpParamDef thumb_return_vals[] =
+      procedure = gimp_load_procedure_new (plug_in, name, GIMP_PLUGIN,
+                                           xmc_load, NULL, NULL);
+
+      gimp_procedure_set_menu_label (procedure, N_("X11 Mouse Cursor"));
+
+      gimp_procedure_set_documentation (procedure,
+                                        "Loads files of X11 Mouse Cursor "
+                                        "file format",
+                                        "This plug-in loads X11 Mouse Cursor "
+                                        "(XMC) files.",
+                                        name);
+      gimp_procedure_set_attribution (procedure,
+                                      "Takeshi Matsuyama <tksmashiw gmail com>",
+                                      "Takeshi Matsuyama",
+                                      "26 May 2009");
+
+      gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
+                                          XCURSOR_MIME_TYPE);
+      gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
+                                          XCURSOR_EXTENSION);
+      gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
+                                      "0,string,Xcur");
+
+      gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure),
+                                                LOAD_THUMB_PROC);
+    }
+  else if (! strcmp (name, LOAD_THUMB_PROC))
     {
-      { GIMP_PDB_IMAGE,   "image",            "Thumbnail image"        },
-      { GIMP_PDB_INT32,   "image-width",      "The width of image"     },
-      { GIMP_PDB_INT32,   "image-height",     "The height of image"    },
-      { GIMP_PDB_INT32,   "image-type",       "The color type of image"},
-      { GIMP_PDB_INT32,   "image-num-layers", "The number of layeres"  }
-    };
-
-  static const GimpParamDef save_args[] =
+      procedure = gimp_thumbnail_procedure_new (plug_in, name, GIMP_PLUGIN,
+                                                xmc_load_thumb, NULL, NULL);
+
+      gimp_procedure_set_documentation (procedure,
+                                        "Loads only first frame of X11 Mouse "
+                                        "Cursor's animation sequence which "
+                                        "nominal size is the closest of "
+                                        "thumb-size to be used as a thumbnail",
+                                        "",
+                                        name);
+      gimp_procedure_set_attribution (procedure,
+                                      "Takeshi Matsuyama <tksmashiw gmail com>",
+                                      "Takeshi Matsuyama",
+                                      "26 May 2009");
+    }
+  else if (! strcmp (name, SAVE_PROC))
     {
-      { GIMP_PDB_INT32,    "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
-      { GIMP_PDB_IMAGE,    "image",        "Input image"                  },
-      { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to export"           },
-      { GIMP_PDB_STRING,   "filename",     "The name of the file to export the image in" },
-      { GIMP_PDB_STRING,   "raw-filename", "The name entered" },
-      /* following elements are XMC specific options */
-      { GIMP_PDB_INT32,    "x_hot",        "X-coordinate of hot spot"       },
-      { GIMP_PDB_INT32,    "y_hot",        "Y-coordinate of hot spot\n"
-                                           "Use (-1, -1) to keep original hot spot."},
-      { GIMP_PDB_INT32,    "crop",         "Auto-crop or not"              },
-      { GIMP_PDB_INT32,    "size",         "Default nominal size"          },
-      { GIMP_PDB_INT32,    "size_replace", "Replace existent size or not." },
-      { GIMP_PDB_INT32,    "delay",        "Default delay"                 },
-      { GIMP_PDB_INT32,    "delay_replace","Replace existent delay or not."},
-      { GIMP_PDB_STRING,   "copyright",    "Copyright information."        },
-      { GIMP_PDB_STRING,   "license",      "License information."          },
-      { GIMP_PDB_STRING,   "other",        "Other comment.(taken from "
-                                           "\"gimp-comment\" parasite)"    }
-    };
-
-  gimp_install_procedure (LOAD_PROC,
-                          "Loads files of X11 Mouse Cursor file format",
-                          "This plug-in loads X11 Mouse Cursor (XMC) files.",
-                          "Takeshi Matsuyama <tksmashiw gmail com>",
-                          "Takeshi Matsuyama",
-                          "26 May 2009",
-                          N_("X11 Mouse Cursor"),
-                          NULL,
-                          GIMP_PLUGIN,
-                          G_N_ELEMENTS (load_args),
-                          G_N_ELEMENTS (load_return_vals),
-                          load_args,
-                          load_return_vals);
-
-  gimp_register_file_handler_mime (LOAD_PROC, XCURSOR_MIME_TYPE);
-  gimp_register_magic_load_handler (LOAD_PROC,
-                                    XCURSOR_EXTENSION,
-                                    "",
-                                    "0,string,Xcur");
-
-  gimp_install_procedure (LOAD_THUMB_PROC,
-                          "Loads only first frame of X11 Mouse Cursor's "
-                          "animation sequence which nominal size is the closest "
-                          "of thumb-size to be used as a thumbnail",
-                          "",
-                          "Takeshi Matsuyama <tksmashiw gmail com>",
-                          "Takeshi Matsuyama",
-                          "26 May 2009",
-                          NULL,
-                          NULL,
-                          GIMP_PLUGIN,
-                          G_N_ELEMENTS (thumb_args),
-                          G_N_ELEMENTS (thumb_return_vals),
-                          thumb_args,
-                          thumb_return_vals);
-
-  gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC);
-
-  gimp_install_procedure (SAVE_PROC,
-                          "Exports files of X11 cursor file",
-                          "This plug-in exports X11 Mouse Cursor (XMC) files",
-                          "Takeshi Matsuyama <tksmashiw gmail com>",
-                          "Takeshi Matsuyama",
-                          "26 May 2009",
-                          N_("X11 Mouse Cursor"),
-                          "RGBA",
-                          GIMP_PLUGIN,
-                          G_N_ELEMENTS (save_args), 0,
-                          save_args, NULL);
-
-  gimp_register_file_handler_mime (SAVE_PROC, XCURSOR_MIME_TYPE);
-  gimp_register_save_handler (SAVE_PROC, XCURSOR_EXTENSION, "");
-}
+      procedure = gimp_save_procedure_new (plug_in, name, GIMP_PLUGIN,
+                                           xmc_save, NULL, NULL);
+
+      gimp_procedure_set_image_types (procedure, "RGBA");
+
+      gimp_procedure_set_menu_label (procedure, N_("X11 Mouse Cursor"));
+
+      gimp_procedure_set_documentation (procedure,
+                                        "Exports files of X11 cursor file",
+                                        "This plug-in exports X11 Mouse Cursor "
+                                        "(XMC) files",
+                                        name);
+      gimp_procedure_set_attribution (procedure,
+                                      "Takeshi Matsuyama <tksmashiw gmail com>",
+                                      "Takeshi Matsuyama",
+                                      "26 May 2009");
+
+      gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
+                                          XCURSOR_MIME_TYPE);
+      gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
+                                          XCURSOR_EXTENSION);
+
+      GIMP_PROC_ARG_INT (procedure, "x-hot",
+                         "X hot",
+                         "X-coordinate of hot spot",
+                         -1, GIMP_MAX_IMAGE_SIZE, -1,
+                         G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_INT (procedure, "y-hot",
+                         "Y hot",
+                         "Y-coordinate of hot spot "
+                         "(use -1, -1 to keep original hot spot",
+                         -1, GIMP_MAX_IMAGE_SIZE, -1,
+                         G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_BOOLEAN (procedure, "crop",
+                             "Crop",
+                             "Auto-crop or not",
+                             FALSE,
+                             G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_INT (procedure, "size",
+                         "Size",
+                         "Default nominal size",
+                         1, G_MAXINT, 32,
+                         G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_BOOLEAN (procedure, "size-replace",
+                             "Size replace",
+                             "Replace existent size or not",
+                             FALSE,
+                             G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_INT (procedure, "delay",
+                         "Delay",
+                         "Default delay",
+                         0, G_MAXINT, CURSOR_DEFAULT_DELAY,
+                         G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_BOOLEAN (procedure, "delay-replace",
+                             "Delay replace",
+                             "Replace existent delay or not",
+                             FALSE,
+                             G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_STRING (procedure, "copyright",
+                            "Copyright",
+                            "Copyright information",
+                            NULL,
+                            G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_STRING (procedure, "license",
+                            "License",
+                            "License information",
+                            NULL,
+                            G_PARAM_READWRITE);
+
+      GIMP_PROC_ARG_STRING (procedure, "other",
+                            "Other",
+                            "Other comment (taken from 'gimp-comment' parasite",
+                            NULL,
+                            G_PARAM_READWRITE);
 
-/*
- * 'run()' - Run the plug-in...
- */
+    }
 
-static void
-run (const gchar      *name,
-     gint              nparams,
-     const GimpParam  *param,
-     gint             *nreturn_vals,
-     GimpParam       **return_vals)
+  return procedure;
+}
+
+static GimpValueArray *
+xmc_load (GimpProcedure        *procedure,
+          GimpRunMode           run_mode,
+          GFile                *file,
+          const GimpValueArray *args,
+          gpointer              run_data)
 {
-  static GimpParam  values[6];
-  GimpRunMode       run_mode;
-  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
-  gint32            image_ID;
-  gint32            drawable_ID;
-  gint32            orig_image_ID;
-  GimpExportReturn  export = GIMP_EXPORT_CANCEL;
-  GeglRectangle    *hotspotRange = NULL;
-  gint32            width, height;
-  gint32            num_layers;
-  GError           *error = NULL;
-  gint              i;
+  GimpValueArray *return_vals;
+  gchar          *filename;
+  GimpImage      *image;
+  GError         *error = NULL;
 
   INIT_I18N ();
   gegl_init (NULL, NULL);
 
-  DM_XMC ("run: start.\n");
-  *nreturn_vals = 1;
-  *return_vals  = values;
+  filename = g_file_get_path (file);
 
-  values[0].type          = GIMP_PDB_STATUS;
-  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
+  image = load_image (filename, &error);
 
-  if (strcmp (name, LOAD_PROC) == 0)
-    {
-      GFile *file = g_file_new_for_uri (param[1].data.d_string);
+  g_free (filename);
 
-      DM_XMC ("Starting to load file.\tparam.data=%s\n",
-              gimp_file_get_utf8_name (file));
+  if (! image)
+    return gimp_procedure_new_return_values (procedure,
+                                             GIMP_PDB_EXECUTION_ERROR,
+                                             error);
 
-      image_ID = load_image (g_file_get_path (file), &error);
+  return_vals = gimp_procedure_new_return_values (procedure,
+                                                  GIMP_PDB_SUCCESS,
+                                                  NULL);
 
-      if (image_ID != -1)
-        {
-          *nreturn_vals = 2;
-          values[1].type = GIMP_PDB_IMAGE;
-          values[1].data.d_image = image_ID;
-          DM_XMC ("LOAD_PROC successfully load image. image_ID=%i\n", image_ID);
-        }
-      else
-        {
-          status = GIMP_PDB_EXECUTION_ERROR;
-        }
-    }
-  else if (strcmp (name, LOAD_THUMB_PROC) == 0)
-    {
-      GFile *file = g_file_new_for_uri (param[0].data.d_string);
+  GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
 
-      DM_XMC ("Starting to load thumbnail.\tfilename=%s\tthumb-size=%d\n",
-              gimp_file_get_utf8_name (file), param[1].data.d_int32);
+  return return_vals;
+}
 
-      image_ID = load_thumbnail (g_file_get_path (file),
-                                 param[1].data.d_int32,
-                                 &width,
-                                 &height,
-                                 &num_layers,
-                                 &error);
+static GimpValueArray *
+xmc_load_thumb (GimpProcedure        *procedure,
+                GFile                *file,
+                gint                  size,
+                const GimpValueArray *args,
+                gpointer              run_data)
+{
+  GimpValueArray *return_vals;
+  gchar          *filename;
+  gint            width;
+  gint            height;
+  gint            num_layers;
+  GimpImage      *image;
+  GError         *error = NULL;
 
-      if (image_ID != -1)
-        {
-          *nreturn_vals = 6;
-          values[1].type = GIMP_PDB_IMAGE;
-          values[1].data.d_image = image_ID;
-          values[2].type = GIMP_PDB_INT32;
-          values[2].data.d_int32 = width;            /* width */
-          values[3].type = GIMP_PDB_INT32;
-          values[3].data.d_int32 = height;           /* height */
-          /* This will not work on GIMP 2.6, but not harmful. */
-          values[4].type = GIMP_PDB_INT32;
-          values[4].data.d_int32 = GIMP_RGBA_IMAGE;  /* type */
-          values[5].type = GIMP_PDB_INT32;
-          values[5].data.d_int32 = num_layers;       /* num_layers */
-
-          DM_XMC ("LOAD_THUMB_PROC successfully load image. image_ID=%i\n", image_ID);
-        }
-      else
-        {
-          status = GIMP_PDB_EXECUTION_ERROR;
-        }
-    }
-  else if (strcmp (name, SAVE_PROC) == 0)
-    {
-      GFile *file = g_file_new_for_uri (param[3].data.d_string);
+  INIT_I18N ();
+  gegl_init (NULL, NULL);
 
-      DM_XMC ("run: exprort %s\n", name);
+  filename = g_file_get_path (file);
 
-      run_mode    = param[0].data.d_int32;
-      image_ID    = orig_image_ID = param[1].data.d_int32;
-      drawable_ID = param[2].data.d_int32;
-      hotspotRange = get_intersection_of_frames (image_ID);
+  image = load_thumbnail (filename, size,
+                          &width,
+                          &height,
+                          &num_layers,
+                          &error);
 
-      if (! hotspotRange)
-        {
-          g_set_error (&error, 0, 0,
-                       _("Cannot set the hot spot!\n"
-                         "You must arrange layers so that all of them have "
-                         "an intersection."));
+  g_free (filename);
 
-          *nreturn_vals = 2;
-          values[1].type          = GIMP_PDB_STRING;
-          values[1].data.d_string = error->message;
-          values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
+  if (! image)
+    return gimp_procedure_new_return_values (procedure,
+                                             GIMP_PDB_EXECUTION_ERROR,
+                                             error);
 
-          return;
-        }
+  return_vals = gimp_procedure_new_return_values (procedure,
+                                                  GIMP_PDB_SUCCESS,
+                                                  NULL);
 
-      /*  eventually export the image */
-      switch (run_mode)
-        {
-        case GIMP_RUN_INTERACTIVE:
-        case GIMP_RUN_WITH_LAST_VALS:
-          gimp_ui_init (PLUG_IN_BINARY, FALSE);
+  GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
+  GIMP_VALUES_SET_INT   (return_vals, 2, width);
+  GIMP_VALUES_SET_INT   (return_vals, 3, height);
+  GIMP_VALUES_SET_ENUM  (return_vals, 4, GIMP_RGBA_IMAGE);
+  GIMP_VALUES_SET_INT   (return_vals, 5, num_layers);
 
-          export = gimp_export_image (&image_ID, &drawable_ID, "XMC",
-                                      GIMP_EXPORT_CAN_HANDLE_RGB    |
-                                      GIMP_EXPORT_CAN_HANDLE_ALPHA  |
-                                      GIMP_EXPORT_CAN_HANDLE_LAYERS |
-                                      GIMP_EXPORT_NEEDS_ALPHA);
+  return return_vals;
+}
 
-          if (export == GIMP_EXPORT_CANCEL)
-            {
-              *nreturn_vals = 1;
-              values[0].data.d_status = GIMP_PDB_CANCEL;
+static GimpValueArray *
+xmc_save (GimpProcedure        *procedure,
+          GimpRunMode           run_mode,
+          GimpImage            *image,
+          GimpDrawable         *drawable,
+          GFile                *file,
+          const GimpValueArray *args,
+          gpointer              run_data)
+{
+  GimpPDBStatusType  status       = GIMP_PDB_SUCCESS;
+  gchar             *filename;
+  GimpImage         *orig_image;
+  GimpExportReturn   export       = GIMP_EXPORT_CANCEL;
+  GeglRectangle     *hotspotRange = NULL;
+  GError            *error        = NULL;
+  gint               i;
 
-              return;
-            }
-          break;
+  INIT_I18N ();
+  gegl_init (NULL, NULL);
 
-        default:
-          break;
-        }
-      switch (run_mode)
-        {
-        case GIMP_RUN_INTERACTIVE:
-          /*
-           * Possibly retrieve data...
-           */
-          gimp_get_data (SAVE_PROC, &xmcvals);
-          load_comments (image_ID);
+  orig_image = image;
 
-          load_default_hotspot (image_ID, hotspotRange);
+  filename = g_file_get_path (file);
 
-          if (! save_dialog (image_ID, hotspotRange))
-              status = GIMP_PDB_CANCEL;
-          break;
+  hotspotRange = get_intersection_of_frames (image);
 
-        case GIMP_RUN_NONINTERACTIVE:
-          /*
-           * Make sure all the arguments are there!
-           */
-          if (nparams != 15)
-            {
-              status = GIMP_PDB_CALLING_ERROR;
-            }
-          else
-            {
-              if (pix_in_region (param[5].data.d_int32, param[6].data.d_int32,
-                                 hotspotRange))
-                { /* if passed hotspot is acceptable, use that ones. */
-                  xmcparas.x = param[5].data.d_int32;
-                  xmcparas.y = param[6].data.d_int32;
-                }
-              else
-                {
-                  load_default_hotspot (image_ID, hotspotRange);
-                  /* you can purposely choose non acceptable values for hotspot
-                     to use cursor's original values. */
-                }
-              xmcvals.crop          = param[7].data.d_int32;
-              xmcvals.size          = param[8].data.d_int32;
-              xmcvals.size_replace  = param[9].data.d_int32;
-              /* load delay */
-              if (param[10].data.d_int32 < CURSOR_MINIMUM_DELAY)
-                {
-                  xmcvals.delay = CURSOR_DEFAULT_DELAY;
-                }
-              else
-                {
-                  xmcvals.delay = param[10].data.d_int32;
-                }
-              xmcvals.delay_replace = param[11].data.d_int32;
-              load_comments (image_ID);
-              for (i = 0; i < 3; ++i)
-                {
-                  if (param[i + 12].data.d_string &&
-                      g_utf8_validate (param[i + 12].data.d_string, -1, NULL))
-                    {
-                      xmcparas.comments[i] = g_strdup (param[i + 12].data.d_string);
-                    }
-                }
-            }
-          break;
+  if (! hotspotRange)
+    {
+      g_set_error (&error, 0, 0,
+                   _("Cannot set the hot spot!\n"
+                     "You must arrange layers so that all of them have "
+                     "an intersection."));
+
+      return gimp_procedure_new_return_values (procedure,
+                                               GIMP_PDB_EXECUTION_ERROR,
+                                               error);
+    }
 
-        case GIMP_RUN_WITH_LAST_VALS:
-          /* Possibly retrieve data... */
-          gimp_get_data (SAVE_PROC, &xmcvals);
-          load_comments (image_ID);
-          load_default_hotspot (image_ID, hotspotRange);
-          break;
+  switch (run_mode)
+    {
+    case GIMP_RUN_INTERACTIVE:
+    case GIMP_RUN_WITH_LAST_VALS:
+      gimp_ui_init (PLUG_IN_BINARY, FALSE);
+
+      export = gimp_export_image (&image, &drawable, "XMC",
+                                  GIMP_EXPORT_CAN_HANDLE_RGB    |
+                                  GIMP_EXPORT_CAN_HANDLE_ALPHA  |
+                                  GIMP_EXPORT_CAN_HANDLE_LAYERS |
+                                  GIMP_EXPORT_NEEDS_ALPHA);
+
+      if (export == GIMP_EXPORT_CANCEL)
+        return gimp_procedure_new_return_values (procedure,
+                                                 GIMP_PDB_CANCEL,
+                                                 NULL);
+      break;
+
+    default:
+      break;
+    }
 
-        default:
-          break;
+  switch (run_mode)
+    {
+    case GIMP_RUN_INTERACTIVE:
+      gimp_get_data (SAVE_PROC, &xmcvals);
+      load_comments (image);
+
+      load_default_hotspot (image, hotspotRange);
+
+      if (! save_dialog (image, hotspotRange))
+        return gimp_procedure_new_return_values (procedure,
+                                                 GIMP_PDB_CANCEL,
+                                                 NULL);
+      break;
+
+    case GIMP_RUN_NONINTERACTIVE:
+      if (pix_in_region (GIMP_VALUES_GET_INT (args, 0),
+                         GIMP_VALUES_GET_INT (args, 1),
+                         hotspotRange))
+        {
+          /* if passed hotspot is acceptable, use that ones. */
+          xmcparas.x = GIMP_VALUES_GET_INT (args, 0);
+          xmcparas.y = GIMP_VALUES_GET_INT (args, 1);
+        }
+      else
+        {
+          /* you can purposely choose non acceptable values for hotspot
+           * to use cursor's original values.
+           */
+          load_default_hotspot (image, hotspotRange);
         }
+      xmcvals.crop          = GIMP_VALUES_GET_BOOLEAN (args, 2);
+      xmcvals.size          = GIMP_VALUES_GET_INT     (args, 3);
+      xmcvals.size_replace  = GIMP_VALUES_GET_BOOLEAN (args, 4);
 
-      if (status == GIMP_PDB_SUCCESS)
+      if (GIMP_VALUES_GET_INT (args, 5) < CURSOR_MINIMUM_DELAY)
         {
-          if (save_image (g_file_get_path (file),
-                          image_ID, drawable_ID, orig_image_ID,
-                          &error))
-            {
-              gimp_set_data (SAVE_PROC, &xmcvals, sizeof (XmcSaveVals));
-            }
-          else
+          xmcvals.delay = CURSOR_DEFAULT_DELAY;
+        }
+      else
+        {
+          xmcvals.delay = GIMP_VALUES_GET_INT (args, 5);
+        }
+
+      xmcvals.delay_replace = GIMP_VALUES_GET_BOOLEAN (args, 6);
+      load_comments (image);
+
+      for (i = 0; i < 3; ++i)
+        {
+          if (GIMP_VALUES_GET_STRING (args, 7 + i))
             {
-              status = GIMP_PDB_EXECUTION_ERROR;
+              xmcparas.comments[i] = GIMP_VALUES_DUP_STRING (args, 7 + i);
             }
         }
+      break;
 
-      if (export == GIMP_EXPORT_EXPORT)
-        gimp_image_delete (image_ID);
+    case GIMP_RUN_WITH_LAST_VALS:
+      gimp_get_data (SAVE_PROC, &xmcvals);
+      load_comments (image);
+      load_default_hotspot (image, hotspotRange);
+      break;
 
-      g_free (hotspotRange);
+    default:
+      break;
+    }
 
-      for (i = 0; i < 3 ; ++i)
-        {
-          g_free (xmcparas.comments[i]);
-          xmcparas.comments[i] = NULL;
-        }
+  if (save_image (g_file_get_path (file),
+                  image, drawable, orig_image,
+                  &error))
+    {
+      gimp_set_data (SAVE_PROC, &xmcvals, sizeof (XmcSaveVals));
     }
   else
     {
-      DM_XMC ("name=%s\n", name);
-      status = GIMP_PDB_CALLING_ERROR;
+      status = GIMP_PDB_EXECUTION_ERROR;
     }
 
-   if (status != GIMP_PDB_SUCCESS && error)
-     {
-       *nreturn_vals = 2;
-       values[1].type          = GIMP_PDB_STRING;
-       values[1].data.d_string = error->message;
-     }
+  if (export == GIMP_EXPORT_EXPORT)
+    gimp_image_delete (image);
 
-  values[0].data.d_status = status;
-  DM_XMC ("run: finish\n");
-}
+  g_free (hotspotRange);
+
+  for (i = 0; i < 3 ; ++i)
+    {
+      g_free (xmcparas.comments[i]);
+      xmcparas.comments[i] = NULL;
+    }
 
+  g_free (filename);
+
+  return gimp_procedure_new_return_values (procedure, status, error);
+}
 
 /*
  * 'load_image()' - Load a X cursor image into a new image window.
  */
 
-static gint32
+static GimpImage *
 load_image (const gchar  *filename,
             GError      **error)
 {
   FILE            *fp;
-  gint32           image_ID;
-  gint32           layer_ID;
+  GimpImage       *image;
+  GimpLayer       *layer;
   GeglBuffer      *buffer;
   XcursorComments *commentsp; /* pointer to comments */
   XcursorImages   *imagesp;   /* pointer to images*/
@@ -677,7 +727,7 @@ load_image (const gchar  *filename,
       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                    _("Could not open '%s' for reading: %s"),
                    gimp_filename_to_utf8 (filename), g_strerror (errno));
-      return -1;
+      return NULL;
     }
 
   if (! XcursorFileLoad (fp, &commentsp, &imagesp))
@@ -685,7 +735,7 @@ load_image (const gchar  *filename,
       g_set_error (error, 0, 0, _("'%s' is not a valid X cursor."),
                    gimp_filename_to_utf8 (filename));
       fclose (fp);
-      return -1;
+      return NULL;
     }
 
   /* check dimension is valid. */
@@ -698,7 +748,7 @@ load_image (const gchar  *filename,
                        _("Frame %d of '%s' is too wide for an X cursor."),
                        i + 1, gimp_filename_to_utf8 (filename));
           fclose (fp);
-          return -1;
+          return NULL;
         }
       if (imagesp->images[i]->height > MAX_LOAD_DIMENSION)
         {
@@ -706,7 +756,7 @@ load_image (const gchar  *filename,
                        _("Frame %d of '%s' is too high for an X cursor."),
                        i + 1, gimp_filename_to_utf8 (filename));
           fclose (fp);
-          return -1;
+          return NULL;
         }
     }
 
@@ -717,14 +767,14 @@ load_image (const gchar  *filename,
   DM_XMC ("xhot=%i,\tyhot=%i,\timg_width=%i,\timg_height=%i\n",
           xmcparas.x, xmcparas.y, img_width, img_height);
 
-  image_ID = gimp_image_new (img_width, img_height, GIMP_RGB);
+  image = gimp_image_new (img_width, img_height, GIMP_RGB);
 
-  gimp_image_set_filename (image_ID, filename);
+  gimp_image_set_filename (image, filename);
 
-  if (! set_hotspot_to_parasite (image_ID))
+  if (! set_hotspot_to_parasite (image))
     {
       fclose (fp);
-      return -1;
+      return NULL;
     }
 
   /* Temporary buffer */
@@ -751,17 +801,17 @@ load_image (const gchar  *filename,
       if (! framename)
         {
           fclose (fp);
-          return -1;
+          return NULL;
         }
 
-      layer_ID = gimp_layer_new (image_ID, framename, width, height,
-                                 GIMP_RGBA_IMAGE,
-                                 100,
-                                 gimp_image_get_default_new_layer_mode (image_ID));
-      gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
+      layer = gimp_layer_new (image, framename, width, height,
+                              GIMP_RGBA_IMAGE,
+                              100,
+                              gimp_image_get_default_new_layer_mode (image));
+      gimp_image_insert_layer (image, layer, NULL, 0);
 
       /* Adjust layer position to let hotspot sit on the same point. */
-      gimp_item_transform_translate (layer_ID,
+      gimp_item_transform_translate (GIMP_ITEM (layer),
                                      xmcparas.x - imagesp->images[i]->xhot,
                                      xmcparas.y - imagesp->images[i]->yhot);
 
@@ -769,7 +819,7 @@ load_image (const gchar  *filename,
 
       /* Get the buffer for our load... */
 
-      buffer = gimp_drawable_get_buffer (layer_ID);
+      buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
 
       /* set color to each pixel */
       for (j = 0; j < width * height; j++)
@@ -799,13 +849,13 @@ load_image (const gchar  *filename,
           DM_XMC ("comment type=%d\tcomment=%s\n",
                   commentsp->comments[i]->comment_type,
                   commentsp->comments[i]->comment);
-          if (! set_comment_to_pname (image_ID,
+          if (! set_comment_to_pname (image,
                                       commentsp->comments[i]->comment,
                                       parasiteName[commentsp->comments[i]->comment_type -1]))
             {
               DM_XMC ("Failed to write %ith comment.\n", i);
               fclose (fp);
-              return -1;
+              return NULL;
             }
         }
     }
@@ -817,14 +867,14 @@ load_image (const gchar  *filename,
 
   gimp_progress_end ();
 
-  return image_ID;
+  return image;
 }
 
 /*
  * load_thumbnail
  */
 
-static gint32
+static GimpImage *
 load_thumbnail (const gchar *filename,
                 gint32       thumb_size,
                 gint32      *thumb_width,
@@ -844,9 +894,9 @@ load_thumbnail (const gchar *filename,
   guint32        diff;         /* difference between thumb_size and current size */
   guint32        min_diff = XCURSOR_IMAGE_MAX_SIZE; /* minimum value of diff */
   guint32        type;         /* chunk type */
-  FILE          *fp = NULL;
-  gint32         image_ID = -1;
-  gint32         layer_ID;
+  FILE          *fp    = NULL;
+  GimpImage     *image = NULL;
+  GimpLayer     *layer;
   GeglBuffer    *buffer;
   guint32       *tmppixel;     /* pixel data (guchar * bpp = guint32) */
   guint32        ntoc = 0;     /* the number of table of contents */
@@ -855,9 +905,9 @@ load_thumbnail (const gchar *filename,
   gint           height;
   gint           i;
 
-  g_return_val_if_fail (thumb_width, -1);
-  g_return_val_if_fail (thumb_height, -1);
-  g_return_val_if_fail (thumb_num_layers, -1);
+  g_return_val_if_fail (thumb_width, NULL);
+  g_return_val_if_fail (thumb_height, NULL);
+  g_return_val_if_fail (thumb_num_layers, NULL);
 
   *thumb_width      = 0;
   *thumb_height     = 0;
@@ -870,7 +920,7 @@ load_thumbnail (const gchar *filename,
       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                    _("Could not open '%s' for reading: %s"),
                    gimp_filename_to_utf8 (filename), g_strerror (errno));
-      return -1;
+      return NULL;
     }
 
   /* From this line, we make a XcursorImages struct so that we can find out the
@@ -892,7 +942,7 @@ load_thumbnail (const gchar *filename,
                    "'%s' seems to have an incorrect toc size.",
                    gimp_filename_to_utf8 (filename));
       fclose (fp);
-      return -1;
+      return NULL;
     }
   positions = g_malloc (ntoc * sizeof (guint32));
 
@@ -931,7 +981,7 @@ load_thumbnail (const gchar *filename,
                    _("there is no image chunk in \"%s\"."),
                    gimp_filename_to_utf8 (filename));
       fclose (fp);
-      return -1;
+      return NULL;
     }
 
   /* get width and height of entire image */
@@ -972,7 +1022,7 @@ load_thumbnail (const gchar *filename,
                    _("'%s' is too wide for an X cursor."),
                    gimp_filename_to_utf8 (filename));
       fclose (fp);
-      return -1;
+      return NULL;
     }
 
   if (*thumb_height > MAX_LOAD_DIMENSION)
@@ -981,7 +1031,7 @@ load_thumbnail (const gchar *filename,
                    _("'%s' is too high for an X cursor."),
                    gimp_filename_to_utf8 (filename));
       fclose (fp);
-      return -1;
+      return NULL;
     }
 
   /*  create new image! */
@@ -989,20 +1039,20 @@ load_thumbnail (const gchar *filename,
   width  = xcIs->images[sel_num]->width;
   height = xcIs->images[sel_num]->height;
 
-  image_ID = gimp_image_new (width, height, GIMP_RGB);
+  image = gimp_image_new (width, height, GIMP_RGB);
 
-  layer_ID = gimp_layer_new (image_ID, NULL, width, height,
-                             GIMP_RGBA_IMAGE,
-                             100,
-                             gimp_image_get_default_new_layer_mode (image_ID));
+  layer = gimp_layer_new (image, NULL, width, height,
+                          GIMP_RGBA_IMAGE,
+                          100,
+                          gimp_image_get_default_new_layer_mode (image));
 
-  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
+  gimp_image_insert_layer (image, layer, NULL, 0);
 
   /*
    * Get the drawable and set the pixel region for our load...
    */
 
-  buffer = gimp_drawable_get_buffer (layer_ID);
+  buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
 
   /* Temporary buffer */
   tmppixel = g_new (guint32, width * height);
@@ -1029,7 +1079,7 @@ load_thumbnail (const gchar *filename,
 
   g_object_unref (buffer);
 
-  return image_ID;
+  return image;
 }
 
 /* read guint32 value from f despite of host's byte order. */
@@ -1062,7 +1112,7 @@ read32 (FILE    *f,
 /* 'save_dialog ()'
  */
 static gboolean
-save_dialog (const gint32   image_ID,
+save_dialog (GimpImage     *image,
              GeglRectangle *hotspotRange)
 {
   GtkWidget      *dialog;
@@ -1434,14 +1484,14 @@ text_view_callback (GtkTextBuffer  *buffer,
  * Set default hotspot based on hotspotRange.
 **/
 static gboolean
-load_default_hotspot (const gint32   image_ID,
+load_default_hotspot (GimpImage     *image,
                       GeglRectangle *hotspotRange)
 {
 
   g_return_val_if_fail (hotspotRange, FALSE);
 
   if ( /* if we cannot load hotspot correctly */
-      ! get_hotspot_from_parasite (image_ID) ||
+      ! get_hotspot_from_parasite (image) ||
      /* ,or hostspot is out of range */
       ! pix_in_region (xmcparas.x, xmcparas.y, hotspotRange))
     {
@@ -1458,11 +1508,11 @@ load_default_hotspot (const gint32   image_ID,
  */
 
 static gboolean
-save_image (const gchar *filename,
-            gint32       image_ID,
-            gint32       drawable_ID,
-            gint32       orig_image_ID,
-            GError     **error)
+save_image (const gchar  *filename,
+            GimpImage    *image,
+            GimpDrawable *drawable,
+            GimpImage    *orig_image,
+            GError      **error)
 {
   FILE            *fp;                     /* File pointer */
   gboolean         dimension_warn = FALSE; /* become TRUE if even one
@@ -1479,9 +1529,10 @@ save_image (const gchar *filename,
                                             * framename */
   XcursorComments *commentsp;              /* pointer to comments */
   XcursorImages   *imagesp;                /* pointer to images */
-  gint32          *layers;                 /* Array of layer */
-  gint32          *orig_layers;            /* Array of layer of orig_image */
-  gint             nlayers;                /* Number of layers */
+  GList           *layers;                 /* Array of layer */
+  GList           *orig_layers;            /* Array of layer of orig_image */
+  GList           *list;
+  GList           *orig_list;
   gchar           *framename;              /* framename of a layer */
   GeglRectangle    save_rgn;               /* region to save */
   gint             layer_xoffset, layer_yoffset;
@@ -1515,18 +1566,18 @@ save_image (const gchar *filename,
     }
 
   /* get layers */
-  orig_layers = gimp_image_get_layers (orig_image_ID, &nlayers);
-  layers = gimp_image_get_layers (image_ID, &nlayers);
+  orig_layers = gimp_image_get_layers (orig_image);
+  layers      = gimp_image_get_layers (image);
 
   /* create new XcursorImages. */
-  imagesp = XcursorImagesCreate (nlayers);
+  imagesp = XcursorImagesCreate (g_list_length (layers));
   if (!imagesp)
     {
       DM_XMC ("Failed to XcursorImagesCreate!\n");
       fclose (fp);
       return FALSE;
     }
-  imagesp->nimage = nlayers;
+  imagesp->nimage = g_list_length (layers);
 
   /* XcursorImages also have `name' member but it is not used as long as I know.
      We leave it NULL here. */
@@ -1534,14 +1585,19 @@ save_image (const gchar *filename,
   /*
    *  Now we start to convert each layer to a XcurosrImage one by one.
    */
-  for (i = 0; i < nlayers; i++)
+  for (list = g_list_last (layers),
+         orig_list = g_list_last (orig_layers), i = 0;
+       list && orig_list;
+       list = g_list_previous (layers),
+         orig_list = g_list_previous (orig_list), i++)
     {
-      GeglBuffer *buffer;
-      const Babl *format;
-      gint        width;
-      gint        height;
+      GimpDrawable *drawable = list->data;
+      GeglBuffer   *buffer;
+      const Babl   *format;
+      gint          width;
+      gint          height;
 
-      buffer = gimp_drawable_get_buffer (layers[nlayers - 1 - i]);
+      buffer = gimp_drawable_get_buffer (drawable);
 
       width  = gegl_buffer_get_width  (buffer);
       height = gegl_buffer_get_height (buffer);
@@ -1549,9 +1605,9 @@ save_image (const gchar *filename,
       format = babl_format ("R'G'B'A u8");
 
       /* get framename of this layer */
-      framename = gimp_item_get_name (layers[nlayers - 1 - i]);
+      framename = gimp_item_get_name (GIMP_ITEM (drawable));
       /* get offset of this layer. */
-      gimp_drawable_offsets (layers[nlayers - 1 - i], &layer_xoffset, &layer_yoffset);
+      gimp_drawable_offsets (drawable, &layer_xoffset, &layer_yoffset);
 
       /*
        * layer dimension check.
@@ -1721,7 +1777,7 @@ save_image (const gchar *filename,
           return FALSE;
         }
 
-      gimp_item_set_name (orig_layers[nlayers - 1 - i], framename);
+      gimp_item_set_name (orig_list->data, framename);
       g_free (framename);
 
       g_object_unref (buffer);
@@ -1729,6 +1785,9 @@ save_image (const gchar *filename,
       gimp_progress_update ((i + 1) / imagesp->nimage);
     }
 
+  g_list_free (list);
+  g_list_free (orig_list);
+
   gimp_progress_update (1.0);
 
   /*
@@ -1826,11 +1885,11 @@ save_image (const gchar *filename,
   /* Save the comment back to the original image */
   for (i = 0; i < 3; i++)
     {
-      gimp_image_detach_parasite (orig_image_ID, parasiteName[i]);
+      gimp_image_detach_parasite (orig_image, parasiteName[i]);
 
       if (xmcparas.comments[i])
         {
-          if (! set_comment_to_pname (orig_image_ID,
+          if (! set_comment_to_pname (orig_image,
                                       xmcparas.comments[i], parasiteName[i]))
             {
               DM_XMC ("Failed to write back %ith comment to orig_image.\n", i);
@@ -1838,7 +1897,7 @@ save_image (const gchar *filename,
         }
     }
   /* Save hotspot back to the original image */
-  set_hotspot_to_parasite (orig_image_ID);
+  set_hotspot_to_parasite (orig_image);
 
   return TRUE;
 }
@@ -1968,32 +2027,32 @@ set_cursor_comments (void)
  * Don't forget to g_free each element of xmcparas.comments later.
  */
 static void
-load_comments (const gint32 image_ID)
+load_comments (GimpImage *image)
 {
   gint i;
 
-  g_return_if_fail (image_ID != -1);
+  g_return_if_fail (GIMP_IS_IMAGE (image));
 
   for (i = 0; i < 3; ++i)
-    xmcparas.comments[i] = get_comment_from_pname (image_ID, parasiteName[i]);
+    xmcparas.comments[i] = get_comment_from_pname (image, parasiteName[i]);
 }
 
 /* Set content to a parasite named as pname. if parasite already
  * exists, append the new one to the old one with "\n"
  */
 static gboolean
-set_comment_to_pname (const gint32  image_ID,
-                      const gchar  *content,
-                      const gchar  *pname)
+set_comment_to_pname (GimpImage   *image,
+                      const gchar *content,
+                      const gchar *pname)
 {
   gboolean      ret = FALSE;
   gchar        *tmpstring, *joind;
   GimpParasite *parasite;
 
-  g_return_val_if_fail (image_ID != -1, FALSE);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
   g_return_val_if_fail (content, FALSE);
 
-  parasite = gimp_image_get_parasite (image_ID, pname);
+  parasite = gimp_image_get_parasite (image, pname);
   if (! parasite)
     {
       parasite = gimp_parasite_new (pname, GIMP_PARASITE_PERSISTENT,
@@ -2013,7 +2072,7 @@ set_comment_to_pname (const gint32  image_ID,
 
   if (parasite)
     {
-      ret = gimp_image_attach_parasite (image_ID, parasite);
+      ret = gimp_image_attach_parasite (image, parasite);
       gimp_parasite_free (parasite);
     }
 
@@ -2024,16 +2083,16 @@ set_comment_to_pname (const gint32  image_ID,
  * g_free(returned pointer) later
  */
 static gchar *
-get_comment_from_pname (const gint32  image_ID,
+get_comment_from_pname (GimpImage   *image,
                         const gchar  *pname)
 {
   gchar        *string = NULL;
   GimpParasite *parasite;
   glong         length;
 
-  g_return_val_if_fail (image_ID != -1, NULL);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
 
-  parasite = gimp_image_get_parasite (image_ID, pname);
+  parasite = gimp_image_get_parasite (image, pname);
   length = gimp_parasite_data_size (parasite);
 
   if (parasite)
@@ -2057,13 +2116,13 @@ get_comment_from_pname (const gint32  image_ID,
  * of file-xbm.
  */
 static gboolean
-set_hotspot_to_parasite (gint32 image_ID)
+set_hotspot_to_parasite (GimpImage *image)
 {
   gboolean      ret = FALSE;
   gchar        *tmpstr;
   GimpParasite *parasite;
 
-  g_return_val_if_fail (image_ID != -1, FALSE);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
 
   tmpstr = g_strdup_printf ("%d %d", xmcparas.x, xmcparas.y);
   parasite = gimp_parasite_new ("hot-spot",
@@ -2074,7 +2133,7 @@ set_hotspot_to_parasite (gint32 image_ID)
 
   if (parasite)
     {
-      ret = gimp_image_attach_parasite (image_ID, parasite);
+      ret = gimp_image_attach_parasite (image, parasite);
       gimp_parasite_free (parasite);
     }
 
@@ -2087,15 +2146,15 @@ set_hotspot_to_parasite (gint32 image_ID)
  * If "hot-spot" is not found or broken, return FALSE.
  */
 static gboolean
-get_hotspot_from_parasite (gint32 image_ID)
+get_hotspot_from_parasite (GimpImage *image)
 {
   GimpParasite *parasite;
 
-  g_return_val_if_fail (image_ID != -1, FALSE);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
 
   DM_XMC ("function: getHotsopt\n");
 
-  parasite = gimp_image_get_parasite (image_ID, "hot-spot");
+  parasite = gimp_image_get_parasite (image, "hot-spot");
   if (!parasite)  /* cannot find a parasite named "hot-spot". */
     {
       return FALSE;
@@ -2398,36 +2457,42 @@ pix_is_opaque (guint32 pix)
   return ((pix >> 24) != 0);
 }
 
-/* Get the intersection of the all layers of the image specified by image_ID.
+/* Get the intersection of the all layers of the image specified by image.
  * if the intersection is empty return NULL.
  * don't forget to g_free returned pointer later.
  */
 static GeglRectangle *
-get_intersection_of_frames (gint32 image_ID)
+get_intersection_of_frames (GimpImage *image)
 {
   GeglRectangle *iregion;
-  gint           i;
   gint32         x1 = G_MININT32, x2 = G_MAXINT32;
   gint32         y1 = G_MININT32, y2 = G_MAXINT32;
   gint32         x_off, y_off;
-  gint           nlayers;
-  gint          *layers;
+  GList         *layers;
+  GList         *list;
 
-  g_return_val_if_fail (image_ID != -1, FALSE);
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
 
-  layers = gimp_image_get_layers (image_ID, &nlayers);
+  layers = gimp_image_get_layers (image);
 
-  for (i = 0; i < nlayers; ++i)
+  for (list = layers; list; list = g_list_next (list))
     {
-      if (! gimp_drawable_offsets (layers[i], &x_off, &y_off))
-        return NULL;
+      GimpDrawable *drawable = list->data;
+
+      if (! gimp_drawable_offsets (drawable, &x_off, &y_off))
+        {
+          g_list_free (layers);
+          return NULL;
+        }
 
       x1 = MAX (x1, x_off);
       y1 = MAX (y1, y_off);
-      x2 = MIN (x2, x_off + gimp_drawable_width  (layers[i]) - 1);
-      y2 = MIN (y2, y_off + gimp_drawable_height (layers[i]) - 1);
+      x2 = MIN (x2, x_off + gimp_drawable_width  (drawable) - 1);
+      y2 = MIN (y2, y_off + gimp_drawable_height (drawable) - 1);
     }
 
+  g_list_free (layers);
+
   if (x1 > x2 || y1 > y2)
     return NULL;
 
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index 6e81ff777c..bfc43208b9 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -48,7 +48,7 @@
     'file-tga' => { ui => 1, gegl => 1, old_api => 1 },
     'file-wmf' => { ui => 1, gegl => 1, optional => 1, libs => 'WMF_LIBS', cflags => 'WMF_CFLAGS', old_api 
=> 1 },
     'file-xbm' => { ui => 1, gegl => 1, old_api => 1 },
-    'file-xmc' => { ui => 1, gegl => 1, optional => 1, libs => 'XMC_LIBS', old_api => 1 },
+    'file-xmc' => { ui => 1, gegl => 1, optional => 1, libs => 'XMC_LIBS' },
     'file-xpm' => { ui => 1, gegl => 1, optional => 1, libs => 'XPM_LIBS', old_api => 1 },
     'file-xwd' => {  ui => 1, gegl => 1, old_api => 1 },
     'film' => { ui => 1, gegl => 1 },


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