/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995-2003 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 3 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, see <https://www.gnu.org/licenses/>.
 */

/* NOTE: This file is auto-generated by pdbgen.pl. */

#include "config.h"

#include "stamp-pdbgen.h"

#include <gegl.h>

#include <gdk-pixbuf/gdk-pixbuf.h>

#include "libpikaconfig/pikaconfig.h"

#include "libpikabase/pikabase.h"

#include "pdb-types.h"

#include "core/pika-edit.h"
#include "core/pika.h"
#include "core/pikabuffer.h"
#include "core/pikadrawable-edit.h"
#include "core/pikadrawable.h"
#include "core/pikaimage.h"
#include "core/pikalayer.h"
#include "core/pikaparamspecs.h"
#include "core/pikaprogress.h"

#include "pikapdb.h"
#include "pikapdb-utils.h"
#include "pikapdbcontext.h"
#include "pikaprocedure.h"
#include "internal-procs.h"

#include "pika-intl.h"


static PikaValueArray *
edit_cut_invoker (PikaProcedure         *procedure,
                  Pika                  *pika,
                  PikaContext           *context,
                  PikaProgress          *progress,
                  const PikaValueArray  *args,
                  GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint num_drawables;
  const PikaItem **drawables;
  gboolean non_empty = FALSE;

  num_drawables = g_value_get_int (pika_value_array_index (args, 0));
  drawables = (const PikaItem **) pika_value_get_object_array (pika_value_array_index (args, 1));

  if (success)
    {
      PikaImage *image         = NULL;
      GList     *drawable_list = NULL;
      gint       i;

      for (i = 0; i < num_drawables; i++)
        {
          if (! pika_pdb_item_is_attached (PIKA_ITEM (drawables[i]), NULL,
                                           PIKA_PDB_ITEM_CONTENT, error) ||
              pika_pdb_item_is_group (PIKA_ITEM (drawables[i]), error))
            {
              success = FALSE;
              break;
            }

          if (! image)
            {
              image = pika_item_get_image (PIKA_ITEM (drawables[i]));
            }
          else if (image != pika_item_get_image (PIKA_ITEM (drawables[i])))
            {
              success = FALSE;
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    _("All specified drawables must belong to the same image."));
              break;
            }

          drawable_list = g_list_prepend (drawable_list, (gpointer) drawables[i]);
        }

      if (success && image)
        {
          GError *my_error = NULL;

          non_empty = pika_edit_cut (image, drawable_list, context, &my_error) != NULL;

          if (! non_empty)
            {
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        {
          success = FALSE;
        }
      g_list_free (drawable_list);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), non_empty);

  return return_vals;
}

static PikaValueArray *
edit_copy_invoker (PikaProcedure         *procedure,
                   Pika                  *pika,
                   PikaContext           *context,
                   PikaProgress          *progress,
                   const PikaValueArray  *args,
                   GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint num_drawables;
  const PikaItem **drawables;
  gboolean non_empty = FALSE;

  num_drawables = g_value_get_int (pika_value_array_index (args, 0));
  drawables = (const PikaItem **) pika_value_get_object_array (pika_value_array_index (args, 1));

  if (success)
    {
      PikaImage *image          = NULL;
      GList     *drawables_list = NULL;
      gint       i;

      for (i = 0; i < num_drawables; i++)
        {
          if (! pika_pdb_item_is_attached (PIKA_ITEM (drawables[i]), NULL, 0, error))
            {
              success = FALSE;
              break;
            }
          if (image == NULL)
            {
              image = pika_item_get_image (PIKA_ITEM (drawables[i]));
            }
          else if (image != pika_item_get_image (PIKA_ITEM (drawables[i])))
            {
              success = FALSE;
              break;
            }
          drawables_list = g_list_prepend (drawables_list, (gpointer) drawables[i]);
        }

      if (success && num_drawables > 0)
        {
          GError *my_error = NULL;

          non_empty = pika_edit_copy (image, drawables_list, context, &my_error) != NULL;

          if (! non_empty)
            {
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        success = FALSE;

      g_list_free (drawables_list);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), non_empty);

  return return_vals;
}

static PikaValueArray *
edit_copy_visible_invoker (PikaProcedure         *procedure,
                           Pika                  *pika,
                           PikaContext           *context,
                           PikaProgress          *progress,
                           const PikaValueArray  *args,
                           GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  gboolean non_empty = FALSE;

  image = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      GError *my_error = NULL;

      non_empty = pika_edit_copy_visible (image, context, &my_error) != NULL;

      if (! non_empty)
        {
          pika_message_literal (pika,
                                G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                my_error->message);
          g_clear_error (&my_error);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_boolean (pika_value_array_index (return_vals, 1), non_empty);

  return return_vals;
}

static PikaValueArray *
edit_paste_invoker (PikaProcedure         *procedure,
                    Pika                  *pika,
                    PikaContext           *context,
                    PikaProgress          *progress,
                    const PikaValueArray  *args,
                    GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaDrawable *drawable;
  gboolean paste_into;
  gint num_layers = 0;
  PikaLayer **layers = NULL;

  drawable = g_value_get_object (pika_value_array_index (args, 0));
  paste_into = g_value_get_boolean (pika_value_array_index (args, 1));

  if (success)
    {
      PikaObject *paste = pika_get_clipboard_object (pika);

      if (paste &&
          pika_pdb_item_is_attached (PIKA_ITEM (drawable), NULL,
                                     PIKA_PDB_ITEM_CONTENT, error) &&
          pika_pdb_item_is_not_group (PIKA_ITEM (drawable), error))
        {
          GList *drawables = NULL;
          GList *list;
          gint   i;

          if (drawable != NULL)
            drawables = g_list_prepend (drawables, drawable);

          list = pika_edit_paste (pika_item_get_image (PIKA_ITEM (drawable)),
                                  drawables, paste,
                                  paste_into ?
                                  PIKA_PASTE_TYPE_FLOATING_INTO :
                                  PIKA_PASTE_TYPE_FLOATING,
                                  context, FALSE,
                                  -1, -1, -1, -1);
          g_list_free (drawables);

          if (! list)
            success = FALSE;

          num_layers = g_list_length (list);
          layers = g_new (PikaLayer *, num_layers);

          for (i = 0; i < num_layers; i++, list = g_list_next (list))
            layers[i] = g_object_ref (list->data);

          g_list_free (list);
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_layers);
      pika_value_take_object_array (pika_value_array_index (return_vals, 2), PIKA_TYPE_LAYER, (GObject **) layers, num_layers);
    }

  return return_vals;
}

static PikaValueArray *
edit_paste_as_new_image_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image = NULL;

  PikaObject *paste = pika_get_clipboard_object (pika);

  if (paste)
    {
      image = pika_edit_paste_as_new_image (pika, paste, context);

      if (! image)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), image);

  return return_vals;
}

static PikaValueArray *
edit_named_cut_invoker (PikaProcedure         *procedure,
                        Pika                  *pika,
                        PikaContext           *context,
                        PikaProgress          *progress,
                        const PikaValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint num_drawables;
  const PikaItem **drawables;
  const gchar *buffer_name;
  gchar *real_name = NULL;

  num_drawables = g_value_get_int (pika_value_array_index (args, 0));
  drawables = (const PikaItem **) pika_value_get_object_array (pika_value_array_index (args, 1));
  buffer_name = g_value_get_string (pika_value_array_index (args, 2));

  if (success)
    {
      PikaImage *image         = NULL;
      GList     *drawable_list = NULL;
      gint       i;

      for (i = 0; i < num_drawables; i++)
        {
          if (! pika_pdb_item_is_attached (PIKA_ITEM (drawables[i]), NULL,
                                           PIKA_PDB_ITEM_CONTENT, error) ||
              pika_pdb_item_is_group (PIKA_ITEM (drawables[i]), error))
            {
              success = FALSE;
              break;
            }

          if (! image)
            {
              image = pika_item_get_image (PIKA_ITEM (drawables[i]));
            }
          else if (image != pika_item_get_image (PIKA_ITEM (drawables[i])))
            {
              success = FALSE;
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    _("All specified drawables must belong to the same image."));
              break;
            }

          drawable_list = g_list_prepend (drawable_list, (gpointer) drawables[i]);
        }

      if (success && image)
        {
          GError *my_error = NULL;

          real_name = (gchar *) pika_edit_named_cut (image, buffer_name,
                                                     drawable_list, context, &my_error);

          if (real_name)
            {
              real_name = g_strdup (real_name);
            }
          else
            {
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        {
          success = FALSE;
        }
      g_list_free (drawable_list);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (pika_value_array_index (return_vals, 1), real_name);

  return return_vals;
}

static PikaValueArray *
edit_named_copy_invoker (PikaProcedure         *procedure,
                         Pika                  *pika,
                         PikaContext           *context,
                         PikaProgress          *progress,
                         const PikaValueArray  *args,
                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  gint num_drawables;
  const PikaItem **drawables;
  const gchar *buffer_name;
  gchar *real_name = NULL;

  num_drawables = g_value_get_int (pika_value_array_index (args, 0));
  drawables = (const PikaItem **) pika_value_get_object_array (pika_value_array_index (args, 1));
  buffer_name = g_value_get_string (pika_value_array_index (args, 2));

  if (success)
    {
      PikaImage *image         = NULL;
      GList     *drawable_list = NULL;
      gint       i;

      for (i = 0; i < num_drawables; i++)
        {
          if (! pika_pdb_item_is_attached (PIKA_ITEM (drawables[i]), NULL,
                                           0, error))
            {
              success = FALSE;
              break;
            }

          if (! image)
            {
              image = pika_item_get_image (PIKA_ITEM (drawables[i]));
            }
          else if (image != pika_item_get_image (PIKA_ITEM (drawables[i])))
            {
              success = FALSE;
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    _("All specified drawables must belong to the same image."));
              break;
            }

          drawable_list = g_list_prepend (drawable_list, (gpointer) drawables[i]);
        }

      if (success && image)
        {
          GError *my_error = NULL;

          real_name = (gchar *) pika_edit_named_copy (image, buffer_name,
                                                      drawable_list, context, &my_error);

          if (real_name)
            {
              real_name = g_strdup (real_name);
            }
          else
            {
              pika_message_literal (pika,
                                    G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                    my_error->message);
              g_clear_error (&my_error);
            }
        }
      else
        {
          success = FALSE;
        }
      g_list_free (drawable_list);
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (pika_value_array_index (return_vals, 1), real_name);

  return return_vals;
}

static PikaValueArray *
edit_named_copy_visible_invoker (PikaProcedure         *procedure,
                                 Pika                  *pika,
                                 PikaContext           *context,
                                 PikaProgress          *progress,
                                 const PikaValueArray  *args,
                                 GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaImage *image;
  const gchar *buffer_name;
  gchar *real_name = NULL;

  image = g_value_get_object (pika_value_array_index (args, 0));
  buffer_name = g_value_get_string (pika_value_array_index (args, 1));

  if (success)
    {
      GError *my_error = NULL;

      real_name = (gchar *) pika_edit_named_copy_visible (image, buffer_name,
                                                          context, &my_error);

      if (real_name)
        {
          real_name = g_strdup (real_name);
        }
      else
        {
          pika_message_literal (pika,
                                G_OBJECT (progress), PIKA_MESSAGE_WARNING,
                                my_error->message);
          g_clear_error (&my_error);
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (pika_value_array_index (return_vals, 1), real_name);

  return return_vals;
}

static PikaValueArray *
edit_named_paste_invoker (PikaProcedure         *procedure,
                          Pika                  *pika,
                          PikaContext           *context,
                          PikaProgress          *progress,
                          const PikaValueArray  *args,
                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaDrawable *drawable;
  const gchar *buffer_name;
  gboolean paste_into;
  PikaLayer *floating_sel = NULL;

  drawable = g_value_get_object (pika_value_array_index (args, 0));
  buffer_name = g_value_get_string (pika_value_array_index (args, 1));
  paste_into = g_value_get_boolean (pika_value_array_index (args, 2));

  if (success)
    {
      PikaBuffer *buffer = pika_pdb_get_buffer (pika, buffer_name, error);

      if (buffer &&
          pika_pdb_item_is_attached (PIKA_ITEM (drawable), NULL,
                                     PIKA_PDB_ITEM_CONTENT, error) &&
          pika_pdb_item_is_not_group (PIKA_ITEM (drawable), error))
        {
          GList *drawables = NULL;
          GList *layers;

          if (drawable != NULL)
            drawables = g_list_prepend (drawables, drawable);

          layers = pika_edit_paste (pika_item_get_image (PIKA_ITEM (drawable)),
                                    drawables, PIKA_OBJECT (buffer),
                                    paste_into ?
                                    PIKA_PASTE_TYPE_FLOATING_INTO :
                                    PIKA_PASTE_TYPE_FLOATING,
                                    context, FALSE,
                                    -1, -1, -1, -1);
          g_list_free (drawables);

          if (! layers)
            success = FALSE;
          else
            floating_sel = layers->data;

          g_list_free (layers);
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), floating_sel);

  return return_vals;
}

static PikaValueArray *
edit_named_paste_as_new_image_invoker (PikaProcedure         *procedure,
                                       Pika                  *pika,
                                       PikaContext           *context,
                                       PikaProgress          *progress,
                                       const PikaValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  const gchar *buffer_name;
  PikaImage *image = NULL;

  buffer_name = g_value_get_string (pika_value_array_index (args, 0));

  if (success)
    {
      PikaBuffer *buffer = pika_pdb_get_buffer (pika, buffer_name, error);

      if (buffer)
        {
          image = pika_edit_paste_as_new_image (pika, PIKA_OBJECT (buffer), context);

          if (! image)
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), image);

  return return_vals;
}

void
register_edit_procs (PikaPDB *pdb)
{
  PikaProcedure *procedure;

  /*
   * pika-edit-cut
   */
  procedure = pika_procedure_new (edit_cut_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-cut");
  pika_procedure_set_static_help (procedure,
                                  "Cut from the specified drawables.",
                                  "If there is a selection in the image, then the area specified by the selection is cut from the specified drawables and placed in an internal PIKA edit buffer. It can subsequently be retrieved using the 'pika-edit-paste' command. If there is no selection and only one specified drawable, then the specified drawable will be removed and its contents stored in the internal PIKA edit buffer. This procedure will fail if the selected area lies completely outside the bounds of the current drawables and there is nothing to cut from.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-drawables",
                                                 "num drawables",
                                                 "The number of drawables",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("drawables",
                                                             "drawables",
                                                             "The drawables to cut from",
                                                             PIKA_TYPE_ITEM,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("non-empty",
                                                         "non empty",
                                                         "TRUE if the cut was successful, FALSE if there was nothing to copy from",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-copy
   */
  procedure = pika_procedure_new (edit_copy_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-copy");
  pika_procedure_set_static_help (procedure,
                                  "Copy from the specified drawables.",
                                  "If there is a selection in the image, then the area specified by the selection is copied from the specified drawables and placed in an internal PIKA edit buffer. It can subsequently be retrieved using the 'pika-edit-paste' command. If there is no selection, then the specified drawables' contents will be stored in the internal PIKA edit buffer. This procedure will fail if the selected area lies completely outside the bounds of the current drawables and there is nothing to copy from. All the drawables must belong to the same image.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-drawables",
                                                 "num drawables",
                                                 "The number of drawables to save",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("drawables",
                                                             "drawables",
                                                             "Drawables to copy from",
                                                             PIKA_TYPE_ITEM,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("non-empty",
                                                         "non empty",
                                                         "TRUE if the cut was successful, FALSE if there was nothing to copy from",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-copy-visible
   */
  procedure = pika_procedure_new (edit_copy_visible_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-copy-visible");
  pika_procedure_set_static_help (procedure,
                                  "Copy from the projection.",
                                  "If there is a selection in the image, then the area specified by the selection is copied from the projection and placed in an internal PIKA edit buffer. It can subsequently be retrieved using the 'pika-edit-paste' command. If there is no selection, then the projection's contents will be stored in the internal PIKA edit buffer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2004");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image to copy from",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_boolean ("non-empty",
                                                         "non empty",
                                                         "TRUE if the copy was successful",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-paste
   */
  procedure = pika_procedure_new (edit_paste_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-paste");
  pika_procedure_set_static_help (procedure,
                                  "Paste buffer to the specified drawable.",
                                  "This procedure pastes a copy of the internal PIKA edit buffer to the specified drawable. The PIKA edit buffer will be empty unless a call was previously made to either 'pika-edit-cut' or 'pika-edit-copy'. The \"paste_into\" option specifies whether to clear the current image selection, or to paste the buffer \"behind\" the selection. This allows the selection to act as a mask for the pasted buffer. Anywhere that the selection mask is non-zero, the pasted buffer will show through. The pasted data may be a floating selection when relevant, layers otherwise. If the image has a floating selection at the time of pasting, the old floating selection will be anchored to its drawable before the new floating selection is added.\n"
                                  "This procedure returns the new layers (floating or not). If the result is a floating selection, it will already be attached to the specified drawable, and a subsequent call to floating_sel_attach is not needed.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Spencer Kimball & Peter Mattis",
                                         "Spencer Kimball & Peter Mattis",
                                         "1995-1996");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_drawable ("drawable",
                                                         "drawable",
                                                         "The drawable to paste to",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("paste-into",
                                                     "paste into",
                                                     "Clear selection, or paste behind it?",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-layers",
                                                     "num layers",
                                                     "The newly pasted layers",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_object_array ("layers",
                                                                 "layers",
                                                                 "The list of pasted layers.",
                                                                 PIKA_TYPE_LAYER,
                                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-paste-as-new-image
   */
  procedure = pika_procedure_new (edit_paste_as_new_image_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-paste-as-new-image");
  pika_procedure_set_static_help (procedure,
                                  "Paste buffer to a new image.",
                                  "This procedure pastes a copy of the internal PIKA edit buffer to a new image. The PIKA edit buffer will be empty unless a call was previously made to either 'pika-edit-cut' or 'pika-edit-copy'. This procedure returns the new image or -1 if the edit buffer was empty.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_image ("image",
                                                          "image",
                                                          "The new image",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-named-cut
   */
  procedure = pika_procedure_new (edit_named_cut_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-named-cut");
  pika_procedure_set_static_help (procedure,
                                  "Cut into a named buffer.",
                                  "This procedure works like 'pika-edit-cut', but additionally stores the cut buffer into a named buffer that will stay available for later pasting, regardless of any intermediate copy or cut operations.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-drawables",
                                                 "num drawables",
                                                 "The number of drawables",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("drawables",
                                                             "drawables",
                                                             "The drawables to cut from",
                                                             PIKA_TYPE_ITEM,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("buffer-name",
                                                       "buffer name",
                                                       "The name of the buffer to create",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_string ("real-name",
                                                           "real name",
                                                           "The real name given to the buffer, or NULL if the cut failed",
                                                           FALSE, FALSE, FALSE,
                                                           NULL,
                                                           PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-named-copy
   */
  procedure = pika_procedure_new (edit_named_copy_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-named-copy");
  pika_procedure_set_static_help (procedure,
                                  "Copy into a named buffer.",
                                  "This procedure works like 'pika-edit-copy', but additionally stores the copied buffer into a named buffer that will stay available for later pasting, regardless of any intermediate copy or cut operations.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-drawables",
                                                 "num drawables",
                                                 "The number of drawables",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_object_array ("drawables",
                                                             "drawables",
                                                             "The drawables to copy from",
                                                             PIKA_TYPE_ITEM,
                                                             PIKA_PARAM_READWRITE | PIKA_PARAM_NO_VALIDATE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("buffer-name",
                                                       "buffer name",
                                                       "The name of the buffer to create",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_string ("real-name",
                                                           "real name",
                                                           "The real name given to the buffer, or NULL if the copy failed",
                                                           FALSE, FALSE, FALSE,
                                                           NULL,
                                                           PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-named-copy-visible
   */
  procedure = pika_procedure_new (edit_named_copy_visible_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-named-copy-visible");
  pika_procedure_set_static_help (procedure,
                                  "Copy from the projection into a named buffer.",
                                  "This procedure works like 'pika-edit-copy-visible', but additionally stores the copied buffer into a named buffer that will stay available for later pasting, regardless of any intermediate copy or cut operations.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_image ("image",
                                                      "image",
                                                      "The image to copy from",
                                                      FALSE,
                                                      PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("buffer-name",
                                                       "buffer name",
                                                       "The name of the buffer to create",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_string ("real-name",
                                                           "real name",
                                                           "The real name given to the buffer, or NULL if the copy failed",
                                                           FALSE, FALSE, FALSE,
                                                           NULL,
                                                           PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-named-paste
   */
  procedure = pika_procedure_new (edit_named_paste_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-named-paste");
  pika_procedure_set_static_help (procedure,
                                  "Paste named buffer to the specified drawable.",
                                  "This procedure works like 'pika-edit-paste' but pastes a named buffer instead of the global buffer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_drawable ("drawable",
                                                         "drawable",
                                                         "The drawable to paste to",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("buffer-name",
                                                       "buffer name",
                                                       "The name of the buffer to paste",
                                                       FALSE, FALSE, FALSE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("paste-into",
                                                     "paste into",
                                                     "Clear selection, or paste behind it?",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_layer ("floating-sel",
                                                          "floating sel",
                                                          "The new floating selection",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-edit-named-paste-as-new-image
   */
  procedure = pika_procedure_new (edit_named_paste_as_new_image_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-edit-named-paste-as-new-image");
  pika_procedure_set_static_help (procedure,
                                  "Paste named buffer to a new image.",
                                  "This procedure works like 'pika-edit-paste-as-new-image' but pastes a named buffer instead of the global buffer.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2005");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("buffer-name",
                                                       "buffer name",
                                                       "The name of the buffer to paste",
                                                       FALSE, FALSE, FALSE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_image ("image",
                                                          "image",
                                                          "The new image",
                                                          FALSE,
                                                          PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);
}
