gimp-pdb.c 20.1 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
 */
Sven Neumann's avatar
Sven Neumann committed
18

19 20
#include "config.h"

Elliot Lee's avatar
Elliot Lee committed
21 22
#include <stdarg.h>
#include <string.h>
23
#include <sys/types.h>
24

25
#include <glib-object.h>
Sven Neumann's avatar
Sven Neumann committed
26

27 28
#include "libgimpbase/gimpbase.h"

29
#include "pdb-types.h"
Sven Neumann's avatar
Sven Neumann committed
30

31
#include "core/gimp.h"
32
#include "core/gimpcontext.h"
33
#include "core/gimpprogress.h"
34

35
#include "plug-in/plug-in-run.h"
Michael Natterer's avatar
Michael Natterer committed
36

37
#include "internal_procs.h"
Elliot Lee's avatar
Elliot Lee committed
38
#include "procedural_db.h"
39

40
#include "gimp-intl.h"
41

42

Michael Natterer's avatar
Michael Natterer committed
43 44 45 46 47 48 49 50 51 52
typedef struct _PDBData PDBData;

struct _PDBData
{
  gchar  *identifier;
  gint32  bytes;
  guint8 *data;
};


53 54 55 56 57 58 59
/*  local function prototypes  */

gchar * procedural_db_type_name (GimpPDBArgType type);


/*  public functions  */

Elliot Lee's avatar
Elliot Lee committed
60
void
61
procedural_db_init (Gimp *gimp)
Elliot Lee's avatar
Elliot Lee committed
62
{
63
  g_return_if_fail (GIMP_IS_GIMP (gimp));
64

Michael Natterer's avatar
Michael Natterer committed
65
  gimp->procedural_ht           = g_hash_table_new (g_str_hash, g_str_equal);
66
  gimp->procedural_compat_ht    = g_hash_table_new (g_str_hash, g_str_equal);
Michael Natterer's avatar
Michael Natterer committed
67
  gimp->procedural_db_data_list = NULL;
Elliot Lee's avatar
Elliot Lee committed
68 69
}

70
static void
71
procedural_db_free_entry (gpointer key,
Manish Singh's avatar
Manish Singh committed
72 73
                          gpointer value,
                          gpointer user_data)
74 75 76 77 78
{
  if (value)
    g_list_free (value);
}

Elliot Lee's avatar
Elliot Lee committed
79
void
80
procedural_db_free (Gimp *gimp)
Elliot Lee's avatar
Elliot Lee committed
81
{
Michael Natterer's avatar
Michael Natterer committed
82 83
  g_return_if_fail (GIMP_IS_GIMP (gimp));

84
  if (gimp->procedural_ht)
85
    {
86
      g_hash_table_foreach (gimp->procedural_ht,
87
                            procedural_db_free_entry, NULL);
88 89 90
      g_hash_table_destroy (gimp->procedural_ht);
      gimp->procedural_ht = NULL;
    }
Michael Natterer's avatar
Michael Natterer committed
91

92 93 94 95 96 97
  if (gimp->procedural_compat_ht)
    {
      g_hash_table_destroy (gimp->procedural_compat_ht);
      gimp->procedural_compat_ht = NULL;
    }

98
  procedural_db_free_data (gimp);
Elliot Lee's avatar
Elliot Lee committed
99 100
}

101
void
102
procedural_db_init_procs (Gimp *gimp)
103 104 105 106 107 108 109 110
{
  static const struct
  {
    const gchar *old_name;
    const gchar *new_name;
  }
  compat_procs[] =
  {
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
    { "gimp-blend",                      "gimp-edit-blend"                 },
    { "gimp-brushes-list",               "gimp-brushes-get-list"           },
    { "gimp-bucket-fill",                "gimp-edit-bucket-fill"           },
    { "gimp-channel-delete",             "gimp-drawable-delete"            },
    { "gimp-channel-get-name",           "gimp-drawable-get-name"          },
    { "gimp-channel-get-tattoo",         "gimp-drawable-get-tattoo"        },
    { "gimp-channel-get-visible",        "gimp-drawable-get-visible"       },
    { "gimp-channel-set-name",           "gimp-drawable-set-name"          },
    { "gimp-channel-set-tattoo",         "gimp-drawable-set-tattoo"        },
    { "gimp-channel-set-visible",        "gimp-drawable-set-visible"       },
    { "gimp-color-picker",               "gimp-image-pick-color"           },
    { "gimp-convert-grayscale",          "gimp-image-convert-grayscale"    },
    { "gimp-convert-indexed",            "gimp-image-convert-indexed"      },
    { "gimp-convert-rgb",                "gimp-image-convert-rgb"          },
    { "gimp-crop",                       "gimp-image-crop"                 },
    { "gimp-drawable-bytes",             "gimp-drawable-bpp"               },
    { "gimp-drawable-image",             "gimp-drawable-get-image"         },
    { "gimp-image-active-drawable",      "gimp-image-get-active-drawable"  },
    { "gimp-image-floating-selection",   "gimp-image-get-floating-sel"     },
    { "gimp-layer-delete",               "gimp-drawable-delete"            },
    { "gimp-layer-get-linked",           "gimp-drawable-get-linked"        },
    { "gimp-layer-get-name",             "gimp-drawable-get-name"          },
    { "gimp-layer-get-tattoo",           "gimp-drawable-get-tattoo"        },
    { "gimp-layer-get-visible",          "gimp-drawable-get-visible"       },
    { "gimp-layer-mask",                 "gimp-layer-get-mask"             },
    { "gimp-layer-set-linked",           "gimp-drawable-set-linked"        },
    { "gimp-layer-set-name",             "gimp-drawable-set-name"          },
    { "gimp-layer-set-tattoo",           "gimp-drawable-set-tattoo"        },
    { "gimp-layer-set-visible",          "gimp-drawable-set-visible"       },
    { "gimp-palette-refresh",            "gimp-palettes-refresh"           },
    { "gimp-patterns-list",              "gimp-patterns-get-list"          },
    { "gimp-temp-PDB-name",              "gimp-procedural-db-temp-name"    },
    { "gimp-undo-push-group-end",        "gimp-image-undo-group-end"       },
    { "gimp-undo-push-group-start",      "gimp-image-undo-group-start"     },
145 146

    /*  deprecations since 2.0  */
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    { "gimp-brushes-get-opacity",        "gimp-context-get-opacity"        },
    { "gimp-brushes-get-paint-mode",     "gimp-context-get-paint-mode"     },
    { "gimp-brushes-set-brush",          "gimp-context-set-brush"          },
    { "gimp-brushes-set-opacity",        "gimp-context-set-opacity"        },
    { "gimp-brushes-set-paint-mode",     "gimp-context-set-paint-mode"     },
    { "gimp-channel-ops-duplicate",      "gimp-image-duplicate"            },
    { "gimp-channel-ops-offset",         "gimp-drawable-offset"            },
    { "gimp-gradients-get-active",       "gimp-context-get-gradient"       },
    { "gimp-gradients-get-gradient",     "gimp-context-get-gradient"       },
    { "gimp-gradients-set-active",       "gimp-context-set-gradient"       },
    { "gimp-gradients-set-gradient",     "gimp-context-set-gradient"       },
    { "gimp-image-get-cmap",             "gimp-image-get-colormap"         },
    { "gimp-image-set-cmap",             "gimp-image-set-colormap"         },
    { "gimp-palette-get-background",     "gimp-context-get-background"     },
    { "gimp-palette-get-foreground",     "gimp-context-get-foreground"     },
    { "gimp-palette-set-background",     "gimp-context-set-background"     },
    { "gimp-palette-set-default-colors", "gimp-context-set-default-colors" },
    { "gimp-palette-set-foreground",     "gimp-context-set-foreground"     },
    { "gimp-palette-swap-colors",        "gimp-context-swap-colors"        },
    { "gimp-palettes-set-palette",       "gimp-context-set-palette"        },
    { "gimp-patterns-set-pattern",       "gimp-context-set-pattern"        },
    { "gimp-selection-clear",            "gimp-selection-none"             },
169

170
    /*  deprecations since 2.2  */
171 172
    { "gimp-layer-get-preserve-trans",   "gimp-drawable-get-lock-alpha"    },
    { "gimp-layer-set-preserve-trans",   "gimp-drawable-set-lock-alpha"    }
173 174 175 176
  };

  g_return_if_fail (GIMP_IS_GIMP (gimp));

177
  internal_procs_init (gimp);
178

179 180 181 182 183 184 185 186 187
  if (gimp->pdb_compat_mode != GIMP_PDB_COMPAT_OFF)
    {
      gint i;

      for (i = 0; i < G_N_ELEMENTS (compat_procs); i++)
        g_hash_table_insert (gimp->procedural_compat_ht,
                             (gpointer) compat_procs[i].old_name,
                             (gpointer) compat_procs[i].new_name);
    }
188 189
}

Elliot Lee's avatar
Elliot Lee committed
190
void
191
procedural_db_register (Gimp       *gimp,
Manish Singh's avatar
Manish Singh committed
192
                        ProcRecord *procedure)
Elliot Lee's avatar
Elliot Lee committed
193 194 195
{
  GList *list;

Michael Natterer's avatar
Michael Natterer committed
196 197 198
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (procedure != NULL);

199
  list = g_hash_table_lookup (gimp->procedural_ht, procedure->name);
Elliot Lee's avatar
Elliot Lee committed
200

201
  g_hash_table_insert (gimp->procedural_ht,
202 203
                       procedure->name,
                       g_list_prepend (list, procedure));
Elliot Lee's avatar
Elliot Lee committed
204 205 206
}

void
207
procedural_db_unregister (Gimp        *gimp,
Manish Singh's avatar
Manish Singh committed
208
                          const gchar *name)
Elliot Lee's avatar
Elliot Lee committed
209 210 211
{
  GList *list;

Michael Natterer's avatar
Michael Natterer committed
212 213 214
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (name != NULL);

215
  list = g_hash_table_lookup (gimp->procedural_ht, name);
216

Elliot Lee's avatar
Elliot Lee committed
217 218 219 220 221
  if (list)
    {
      list = g_list_remove (list, list->data);

      if (list)
Manish Singh's avatar
Manish Singh committed
222
        g_hash_table_insert (gimp->procedural_ht, (gpointer) name, list);
223
      else
Manish Singh's avatar
Manish Singh committed
224
        g_hash_table_remove (gimp->procedural_ht, name);
Elliot Lee's avatar
Elliot Lee committed
225 226 227 228
    }
}

ProcRecord *
229
procedural_db_lookup (Gimp        *gimp,
Manish Singh's avatar
Manish Singh committed
230
                      const gchar *name)
Elliot Lee's avatar
Elliot Lee committed
231
{
232
  GList *list;
Elliot Lee's avatar
Elliot Lee committed
233

Michael Natterer's avatar
Michael Natterer committed
234 235 236
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (name != NULL, NULL);

237
  list = g_hash_table_lookup (gimp->procedural_ht, name);
Elliot Lee's avatar
Elliot Lee committed
238

239
  if (list)
240
    return list->data;
241 242
  else
    return NULL;
Elliot Lee's avatar
Elliot Lee committed
243 244 245
}

Argument *
246 247 248 249 250
procedural_db_execute (Gimp         *gimp,
                       GimpContext  *context,
                       GimpProgress *progress,
                       const gchar  *name,
                       Argument     *args)
Elliot Lee's avatar
Elliot Lee committed
251
{
252 253
  Argument *return_args = NULL;
  GList    *list;
Elliot Lee's avatar
Elliot Lee committed
254

Michael Natterer's avatar
Michael Natterer committed
255
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
256
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
257
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
Michael Natterer's avatar
Michael Natterer committed
258 259
  g_return_val_if_fail (name != NULL, NULL);

260
  list = g_hash_table_lookup (gimp->procedural_ht, name);
Elliot Lee's avatar
Elliot Lee committed
261

262 263
  if (list == NULL)
    {
264
      g_message (_("PDB calling error:\nprocedure '%s' not found"), name);
265

266
      return_args = g_new (Argument, 1);
267
      return_args->arg_type      = GIMP_PDB_STATUS;
268
      return_args->value.pdb_int = GIMP_PDB_CALLING_ERROR;
269

270 271
      return return_args;
    }
272

273
  for (; list; list = g_list_next (list))
Elliot Lee's avatar
Elliot Lee committed
274
    {
275
      ProcRecord *procedure = list->data;
276 277 278
      gint        i;

      g_return_val_if_fail (procedure != NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
279 280 281

      /*  check the arguments  */
      for (i = 0; i < procedure->num_args; i++)
Manish Singh's avatar
Manish Singh committed
282 283 284
        {
          if (args[i].arg_type != procedure->args[i].arg_type)
            {
285 286 287 288 289 290
              gchar *expected;
              gchar *got;

              expected = procedural_db_type_name (procedure->args[i].arg_type);
              got      = procedural_db_type_name (args[i].arg_type);

Manish Singh's avatar
Manish Singh committed
291
              g_message (_("PDB calling error for procedure '%s':\n"
292
                           "Argument #%d type mismatch (expected %s, got %s)"),
293 294 295 296
                         procedure->name, i + 1, expected, got);

              g_free (expected);
              g_free (got);
297

Manish Singh's avatar
Manish Singh committed
298 299 300
              return_args = g_new (Argument, 1);
              return_args->arg_type      = GIMP_PDB_STATUS;
              return_args->value.pdb_int = GIMP_PDB_CALLING_ERROR;
Elliot Lee's avatar
Elliot Lee committed
301

Manish Singh's avatar
Manish Singh committed
302 303 304
              return return_args;
            }
        }
Elliot Lee's avatar
Elliot Lee committed
305 306 307

      /*  call the procedure  */
      switch (procedure->proc_type)
Manish Singh's avatar
Manish Singh committed
308 309 310
        {
        case GIMP_INTERNAL:
          return_args =
311
            (* procedure->exec_method.internal.marshal_func) (gimp, context,
312
                                                              progress,
313
                                                              args);
Manish Singh's avatar
Manish Singh committed
314
          break;
Elliot Lee's avatar
Elliot Lee committed
315

Manish Singh's avatar
Manish Singh committed
316 317 318
        case GIMP_PLUGIN:
        case GIMP_EXTENSION:
        case GIMP_TEMPORARY:
319
          return_args = plug_in_run (gimp, context, progress, procedure,
320
                                     args, procedure->num_args,
321
                                     TRUE, FALSE, -1);
322 323 324 325 326 327

          /*  If there are no return arguments, assume
           *  an execution error and fall through.
           */
          if (return_args)
            break;
Elliot Lee's avatar
Elliot Lee committed
328

Manish Singh's avatar
Manish Singh committed
329 330 331 332
        default:
          return_args = g_new (Argument, 1);
          return_args->arg_type      = GIMP_PDB_STATUS;
          return_args->value.pdb_int = GIMP_PDB_EXECUTION_ERROR;
333 334

          return return_args;
Manish Singh's avatar
Manish Singh committed
335
        }
Elliot Lee's avatar
Elliot Lee committed
336

337 338
      if (return_args[0].value.pdb_int != GIMP_PDB_SUCCESS      &&
          return_args[0].value.pdb_int != GIMP_PDB_PASS_THROUGH &&
Manish Singh's avatar
Manish Singh committed
339
          procedure->num_values > 0)
340
        {
341 342
          memset (&return_args[1],
                  0, sizeof (Argument) * procedure->num_values);
343
        }
Elliot Lee's avatar
Elliot Lee committed
344

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
      if (return_args[0].value.pdb_int == GIMP_PDB_PASS_THROUGH)
        {
          /*  If the return value is GIMP_PDB_PASS_THROUGH and there is
           *  a next procedure in the list, destroy the return values
           *  and run the next procedure.
           */
          if (g_list_next (list))
            procedural_db_destroy_args (return_args, procedure->num_values);
        }
      else
        {
          /*  No GIMP_PDB_PASS_THROUGH, break out of the list of
           *  procedures and return the current return values.
           */
          break;
        }
Elliot Lee's avatar
Elliot Lee committed
361 362 363 364 365 366
    }

  return return_args;
}

Argument *
367 368 369 370 371
procedural_db_run_proc (Gimp         *gimp,
                        GimpContext  *context,
                        GimpProgress *progress,
                        const gchar  *name,
                        gint         *nreturn_vals,
Manish Singh's avatar
Manish Singh committed
372
                        ...)
Elliot Lee's avatar
Elliot Lee committed
373 374
{
  ProcRecord *proc;
375 376 377 378
  Argument   *params;
  Argument   *return_vals;
  va_list     args;
  gint        i;
Elliot Lee's avatar
Elliot Lee committed
379

Michael Natterer's avatar
Michael Natterer committed
380
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
381
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
382
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
Michael Natterer's avatar
Michael Natterer committed
383
  g_return_val_if_fail (name != NULL, NULL);
Sven Neumann's avatar
Sven Neumann committed
384
  g_return_val_if_fail (nreturn_vals != NULL, NULL);
Michael Natterer's avatar
Michael Natterer committed
385

386 387 388
  proc = procedural_db_lookup (gimp, name);

  if (proc == NULL)
Elliot Lee's avatar
Elliot Lee committed
389
    {
Sven Neumann's avatar
Sven Neumann committed
390 391
      *nreturn_vals = 1;

392
      return_vals = g_new (Argument, 1);
393
      return_vals->arg_type      = GIMP_PDB_STATUS;
394
      return_vals->value.pdb_int = GIMP_PDB_CALLING_ERROR;
395

Elliot Lee's avatar
Elliot Lee committed
396 397 398 399 400 401 402 403 404 405
      return return_vals;
    }

  /*  allocate the parameter array  */
  params = g_new (Argument, proc->num_args);

  va_start (args, nreturn_vals);

  for (i = 0; i < proc->num_args; i++)
    {
406 407 408
      params[i].arg_type = va_arg (args, GimpPDBArgType);

      if (proc->args[i].arg_type != params[i].arg_type)
Manish Singh's avatar
Manish Singh committed
409
        {
410 411 412 413 414 415
          gchar *expected;
          gchar *got;

          expected = procedural_db_type_name (proc->args[i].arg_type);
          got      = procedural_db_type_name (params[i].arg_type);

Manish Singh's avatar
Manish Singh committed
416
          g_free (params);
Sven Neumann's avatar
Sven Neumann committed
417

418 419 420 421 422 423 424
         g_message (_("PDB calling error for procedure '%s':\n"
                       "Argument #%d type mismatch (expected %s, got %s)"),
                    proc->name, i + 1, expected, got);

          g_free (expected);
          g_free (got);

Sven Neumann's avatar
Sven Neumann committed
425
          *nreturn_vals = 0;
Manish Singh's avatar
Manish Singh committed
426 427
          return NULL;
        }
Elliot Lee's avatar
Elliot Lee committed
428 429

      switch (proc->args[i].arg_type)
Manish Singh's avatar
Manish Singh committed
430 431 432 433
        {
        case GIMP_PDB_INT32:
        case GIMP_PDB_INT16:
        case GIMP_PDB_INT8:
434
        case GIMP_PDB_DISPLAY:
Manish Singh's avatar
Manish Singh committed
435 436
          params[i].value.pdb_int = (gint32) va_arg (args, gint);
          break;
437

438
        case GIMP_PDB_FLOAT:
439
          params[i].value.pdb_float = (gdouble) va_arg (args, gdouble);
Elliot Lee's avatar
Elliot Lee committed
440
          break;
441

442 443 444 445 446 447
        case GIMP_PDB_STRING:
        case GIMP_PDB_INT32ARRAY:
        case GIMP_PDB_INT16ARRAY:
        case GIMP_PDB_INT8ARRAY:
        case GIMP_PDB_FLOATARRAY:
        case GIMP_PDB_STRINGARRAY:
448 449
          params[i].value.pdb_pointer = va_arg (args, gpointer);
          break;
450

451
        case GIMP_PDB_COLOR:
Manish Singh's avatar
Manish Singh committed
452
          params[i].value.pdb_color = va_arg (args, GimpRGB);
Elliot Lee's avatar
Elliot Lee committed
453
          break;
454

455
        case GIMP_PDB_REGION:
Elliot Lee's avatar
Elliot Lee committed
456
          break;
457

458 459 460 461 462 463 464
        case GIMP_PDB_IMAGE:
        case GIMP_PDB_LAYER:
        case GIMP_PDB_CHANNEL:
        case GIMP_PDB_DRAWABLE:
        case GIMP_PDB_SELECTION:
        case GIMP_PDB_BOUNDARY:
        case GIMP_PDB_PATH:
Manish Singh's avatar
Manish Singh committed
465 466
          params[i].value.pdb_int = (gint32) va_arg (args, gint);
          break;
467

468
        case GIMP_PDB_PARASITE:
469
          params[i].value.pdb_pointer = va_arg (args, gpointer);
470
          break;
471

472
        case GIMP_PDB_STATUS:
Manish Singh's avatar
Manish Singh committed
473 474
          params[i].value.pdb_int = (gint32) va_arg (args, gint);
          break;
475

Manish Singh's avatar
Manish Singh committed
476 477 478
        case GIMP_PDB_END:
          break;
        }
Elliot Lee's avatar
Elliot Lee committed
479 480 481 482 483 484
    }

  va_end (args);

  *nreturn_vals = proc->num_values;

485
  return_vals = procedural_db_execute (gimp, context, progress, name, params);
Elliot Lee's avatar
Elliot Lee committed
486 487 488 489 490 491 492 493

  g_free (params);

  return return_vals;
}

Argument *
procedural_db_return_args (ProcRecord *procedure,
Manish Singh's avatar
Manish Singh committed
494
                           gboolean    success)
Elliot Lee's avatar
Elliot Lee committed
495 496
{
  Argument *return_args;
497
  gint      i;
Elliot Lee's avatar
Elliot Lee committed
498

Michael Natterer's avatar
Michael Natterer committed
499 500
  g_return_val_if_fail (procedure != NULL, NULL);

501 502 503
  return_args = g_new0 (Argument, procedure->num_values + 1);

  return_args[0].arg_type = GIMP_PDB_STATUS;
Elliot Lee's avatar
Elliot Lee committed
504 505

  if (success)
506
    return_args[0].value.pdb_int = GIMP_PDB_SUCCESS;
Elliot Lee's avatar
Elliot Lee committed
507
  else
508
    return_args[0].value.pdb_int = GIMP_PDB_EXECUTION_ERROR;
Elliot Lee's avatar
Elliot Lee committed
509 510 511

  /*  Set the arg types for the return values  */
  for (i = 0; i < procedure->num_values; i++)
512
    return_args[i + 1].arg_type = procedure->values[i].arg_type;
Elliot Lee's avatar
Elliot Lee committed
513 514 515 516 517 518

  return return_args;
}

void
procedural_db_destroy_args (Argument *args,
Manish Singh's avatar
Manish Singh committed
519
                            gint      nargs)
Elliot Lee's avatar
Elliot Lee committed
520
{
521
  gint i;
Elliot Lee's avatar
Elliot Lee committed
522

523
  if (! args)
524
    return;
525

Elliot Lee's avatar
Elliot Lee committed
526 527 528
  for (i = 0; i < nargs; i++)
    {
      switch (args[i].arg_type)
Manish Singh's avatar
Manish Singh committed
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
        {
        case GIMP_PDB_INT32:
        case GIMP_PDB_INT16:
        case GIMP_PDB_INT8:
        case GIMP_PDB_FLOAT:
          break;

        case GIMP_PDB_STRING:
        case GIMP_PDB_INT32ARRAY:
        case GIMP_PDB_INT16ARRAY:
        case GIMP_PDB_INT8ARRAY:
        case GIMP_PDB_FLOATARRAY:
          g_free (args[i].value.pdb_pointer);
          break;

        case GIMP_PDB_STRINGARRAY:
545 546 547 548
          {
            gchar **stringarray;
            gint    count;
            gint    j;
549

550 551 552 553 554 555 556 557 558 559
            count       = args[i - 1].value.pdb_int;
            stringarray = args[i].value.pdb_pointer;

            for (j = 0; j < count; j++)
              g_free (stringarray[j]);

            g_free (args[i].value.pdb_pointer);
          }
          break;

Manish Singh's avatar
Manish Singh committed
560 561 562 563 564 565 566 567 568 569 570 571 572
        case GIMP_PDB_COLOR:
        case GIMP_PDB_REGION:
        case GIMP_PDB_DISPLAY:
        case GIMP_PDB_IMAGE:
        case GIMP_PDB_LAYER:
        case GIMP_PDB_CHANNEL:
        case GIMP_PDB_DRAWABLE:
        case GIMP_PDB_SELECTION:
        case GIMP_PDB_BOUNDARY:
        case GIMP_PDB_PATH:
          break;

        case GIMP_PDB_PARASITE:
573
          gimp_parasite_free (args[i].value.pdb_pointer);
574 575
          break;

Manish Singh's avatar
Manish Singh committed
576 577 578 579
        case GIMP_PDB_STATUS:
        case GIMP_PDB_END:
          break;
        }
Elliot Lee's avatar
Elliot Lee committed
580 581 582 583
    }

  g_free (args);
}
Michael Natterer's avatar
Michael Natterer committed
584

585 586 587 588 589 590 591
void
procedural_db_free_data (Gimp *gimp)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));

  if (gimp->procedural_db_data_list)
    {
592
      GList *list;
593 594 595 596 597

      for (list = gimp->procedural_db_data_list;
           list;
           list = g_list_next (list))
        {
598
          PDBData *data = list->data;
599 600 601 602 603 604 605 606 607 608 609

          g_free (data->identifier);
          g_free (data->data);
          g_free (data);
        }

      g_list_free (gimp->procedural_db_data_list);
      gimp->procedural_db_data_list = NULL;
    }
}

Michael Natterer's avatar
Michael Natterer committed
610
void
611
procedural_db_set_data (Gimp         *gimp,
Michael Natterer's avatar
Michael Natterer committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625
                        const gchar  *identifier,
                        gint32        bytes,
                        const guint8 *data)
{
  GList   *list;
  PDBData *pdb_data;

  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (identifier != NULL);
  g_return_if_fail (bytes > 0);
  g_return_if_fail (data != NULL);

  for (list = gimp->procedural_db_data_list; list; list = g_list_next (list))
    {
626
      pdb_data = list->data;
Michael Natterer's avatar
Michael Natterer committed
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654

      if (! strcmp (pdb_data->identifier, identifier))
        break;
    }

  /* If there isn't already data with the specified identifier, create one */
  if (list == NULL)
    {
      pdb_data = g_new0 (PDBData, 1);
      pdb_data->identifier = g_strdup (identifier);

      gimp->procedural_db_data_list =
        g_list_prepend (gimp->procedural_db_data_list, pdb_data);
    }
  else
    {
      g_free (pdb_data->data);
    }

  pdb_data->bytes = bytes;
  pdb_data->data  = g_memdup (data, bytes);
}

const guint8 *
procedural_db_get_data (Gimp        *gimp,
                        const gchar *identifier,
                        gint32      *bytes)
{
655
  GList *list;
Michael Natterer's avatar
Michael Natterer committed
656 657 658 659 660 661 662 663 664

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (identifier != NULL, NULL);
  g_return_val_if_fail (bytes != NULL, NULL);

  *bytes = 0;

  for (list = gimp->procedural_db_data_list; list; list = g_list_next (list))
    {
665
      PDBData *pdb_data = list->data;
Michael Natterer's avatar
Michael Natterer committed
666 667 668 669 670 671 672 673 674 675

      if (! strcmp (pdb_data->identifier, identifier))
        {
          *bytes = pdb_data->bytes;
          return pdb_data->data;
        }
    }

  return NULL;
}
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692


/*  private functions  */

gchar *
procedural_db_type_name (GimpPDBArgType type)
{
  const gchar *name;

  if (! gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, type,
                             &name, NULL, NULL, NULL))
    {
      return  g_strdup_printf ("(PDB type %d unknown)", type);
    }

  return g_strdup (name);
}