gimppluginmanager.c 25.7 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
 */
18

Elliot Lee's avatar
Elliot Lee committed
19
#include "config.h"
Tor Lillqvist's avatar
Tor Lillqvist committed
20

21
#include "string.h"
Manish Singh's avatar
Manish Singh committed
22

23
#include <glib-object.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
24

25 26 27
#include "libgimpbase/gimpbase.h"
#include "libgimpbase/gimpprotocol.h"
#include "libgimpbase/gimpwire.h"
28

29
#include "plug-in-types.h"
30

31
#include "config/gimpcoreconfig.h"
32
#include "config/gimpconfig-error.h"
33
#include "config/gimpconfig-path.h"
34

35
#include "core/gimp.h"
36
#include "core/gimpcontext.h"
37 38
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
39

40
#include "plug-in.h"
41 42 43
#include "plug-ins.h"
#include "plug-in-def.h"
#include "plug-in-params.h"
44
#include "plug-in-proc.h"
45
#include "plug-in-progress.h"
46
#include "plug-in-rc.h"
47
#include "plug-in-run.h"
48

49
#include "gimp-intl.h"
50

51

52
#define STD_PLUGINS_DOMAIN  GETTEXT_PACKAGE "-std-plug-ins"
53 54 55


typedef struct _PlugInLocaleDomainDef PlugInLocaleDomainDef;
56
typedef struct _PlugInHelpDomainDef   PlugInHelpDomainDef;
57 58 59 60

struct _PlugInLocaleDomainDef
{
  gchar *prog_name;
61 62
  gchar *domain_name;
  gchar *domain_path;
63
};
64

65
struct _PlugInHelpDomainDef
66 67
{
  gchar *prog_name;
68 69
  gchar *domain_name;
  gchar *domain_uri;
70 71 72
};


73 74
static void            plug_ins_init_file (const GimpDatafileData *file_data,
                                           gpointer                user_data);
75 76
static void            plug_ins_add_to_db       (Gimp             *gimp,
                                                 GimpContext      *context);
77 78
static PlugInProcDef * plug_ins_proc_def_insert (Gimp             *gimp,
                                                 PlugInProcDef    *proc_def);
79

80

81 82
/*  public functions  */

Elliot Lee's avatar
Elliot Lee committed
83
void
84 85
plug_ins_init (Gimp               *gimp,
               GimpInitStatusFunc  status_callback)
Elliot Lee's avatar
Elliot Lee committed
86
{
87 88 89 90
  GimpContext *context;
  gchar       *filename;
  gchar       *basename;
  gchar       *path;
91
  GSList      *list;
92 93 94 95 96
  GList       *extensions = NULL;
  gdouble      n_plugins;
  gdouble      n_extensions;
  gdouble      nth;
  GError      *error = NULL;
Elliot Lee's avatar
Elliot Lee committed
97

98 99 100
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (status_callback != NULL);

101 102
  context = gimp_context_new (gimp, "temp", NULL);

103
  plug_in_init (gimp);
104

Elliot Lee's avatar
Elliot Lee committed
105
  /* search for binaries in the plug-in directory path */
106 107 108
  path = gimp_config_path_expand (gimp->config->plug_in_path, TRUE, NULL);

  gimp_datafiles_read_directories (path,
109
                                   G_FILE_TEST_IS_EXECUTABLE,
110 111
				   plug_ins_init_file,
                                   &gimp->plug_in_defs);
Elliot Lee's avatar
Elliot Lee committed
112

113 114
  g_free (path);

115

Elliot Lee's avatar
Elliot Lee committed
116
  /* read the pluginrc file for cached data */
117
  if (gimp->config->plug_in_rc_path)
118
    {
119 120 121
      filename = gimp_config_path_expand (gimp->config->plug_in_rc_path,
                                          TRUE, NULL);

122
      if (! g_path_is_absolute (filename))
123
        {
124
          gchar *str = g_build_filename (gimp_directory (), filename, NULL);
125

126
          g_free (filename);
127
          filename = str;
128
        }
129 130
    }
  else
131 132 133
    {
      filename = gimp_personal_rc_file ("pluginrc");
    }
134

135
  (* status_callback) (_("Resource configuration"),
136
		       gimp_filename_to_utf8 (filename), -1);
137 138 139

  if (! plug_in_rc_parse (gimp, filename, &error))
    {
140 141 142
      if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
        g_message (error->message);

143
      g_clear_error (&error);
144
    }
Elliot Lee's avatar
Elliot Lee committed
145

146
  /*  Query any plug-ins that have changed since we last wrote out
Elliot Lee's avatar
Elliot Lee committed
147 148
   *  the pluginrc file.
   */
149
  (* status_callback) (_("Querying new Plug-ins"), "", 0);
150
  n_plugins = g_slist_length (gimp->plug_in_defs);
151

152
  for (list = gimp->plug_in_defs, nth = 0; list; list = list->next, nth++)
Elliot Lee's avatar
Elliot Lee committed
153
    {
154
      PlugInDef *plug_in_def = list->data;
Elliot Lee's avatar
Elliot Lee committed
155

156
      basename = g_path_get_basename (plug_in_def->prog);
157
      (* status_callback) (NULL, gimp_filename_to_utf8 (basename),
158
			   nth / n_plugins);
159 160
      g_free (basename);

161
      if (plug_in_def->needs_query)
Elliot Lee's avatar
Elliot Lee committed
162
	{
163
	  gimp->write_pluginrc = TRUE;
164

165
	  if (gimp->be_verbose)
166
	    g_print (_("Querying plug-in: '%s'\n"),
167
		     gimp_filename_to_utf8 (plug_in_def->prog));
168

169
	  plug_in_call_query (gimp, context, plug_in_def);
Elliot Lee's avatar
Elliot Lee committed
170 171 172
	}
    }

173 174
  (* status_callback) (NULL, NULL, 1.0);

175 176 177
  /* initialize the plug-ins */
  (* status_callback) (_("Initializing Plug-ins"), "", 0);

178
  for (list = gimp->plug_in_defs, nth = 0; list; list = list->next, nth++)
179
    {
180
      PlugInDef *plug_in_def = list->data;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

      basename = g_path_get_basename (plug_in_def->prog);
      (* status_callback) (NULL, gimp_filename_to_utf8 (basename),
			   nth / n_plugins);
      g_free (basename);

      if (plug_in_def->has_init)
	{
	  if (gimp->be_verbose)
	    g_print (_("Initializing plug-in: '%s'\n"),
                     gimp_filename_to_utf8 (plug_in_def->prog));

	  plug_in_call_init (gimp, context, plug_in_def);
	}
    }

  (* status_callback) (NULL, NULL, 1.0);

Elliot Lee's avatar
Elliot Lee committed
199
  /* insert the proc defs */
200
  for (list = gimp->plug_in_defs; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
201
    {
202 203
      PlugInDef *plug_in_def = list->data;
      GSList    *list2;
Elliot Lee's avatar
Elliot Lee committed
204

205
      for (list2 = plug_in_def->proc_defs; list2; list2 = list2->next)
Elliot Lee's avatar
Elliot Lee committed
206
	{
207
	  PlugInProcDef *proc_def = list2->data;
208 209
          PlugInProcDef *overridden_proc_def;

210
 	  proc_def->mtime = plug_in_def->mtime;
211

212
	  overridden_proc_def = plug_ins_proc_def_insert (gimp, proc_def);
213 214 215

          if (overridden_proc_def)
            {
216
              GSList *list3;
217

218 219 220 221
              g_printerr ("removing duplicate PDB procedure \"%s\" "
                          "registered by '%s'\n",
                          overridden_proc_def->db_info.name,
                          gimp_filename_to_utf8 (overridden_proc_def->prog));
222

223
              /* search the plugin list to see if any plugins had references to
224 225
               * the overridden_proc_def.
               */
226
              for (list3 = gimp->plug_in_defs; list3; list3 = list3->next)
227
                {
228
                  PlugInDef *plug_in_def2 = list3->data;
229 230 231 232 233 234

                  plug_in_def2->proc_defs =
                    g_slist_remove (plug_in_def2->proc_defs,
                                    overridden_proc_def);
                }

235 236 237 238 239 240
              /* also remove it from the lists of load and save procs */
              gimp->load_procs = g_slist_remove (gimp->load_procs,
                                                 overridden_proc_def);
              gimp->save_procs = g_slist_remove (gimp->save_procs,
                                                 overridden_proc_def);

241 242
              plug_in_proc_def_free (overridden_proc_def);
            }
Elliot Lee's avatar
Elliot Lee committed
243 244 245 246
	}
    }

  /* write the pluginrc file if necessary */
247
  if (gimp->write_pluginrc)
Elliot Lee's avatar
Elliot Lee committed
248
    {
249
      if (gimp->be_verbose)
250
	g_print (_("Writing '%s'\n"),
251
		 gimp_filename_to_utf8 (filename));
252

253 254 255
      if (! plug_in_rc_write (gimp->plug_in_defs, filename, &error))
        {
          g_message ("%s", error->message);
256
          g_clear_error (&error);
257 258
        }

259
      gimp->write_pluginrc = FALSE;
Elliot Lee's avatar
Elliot Lee committed
260 261
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
262 263
  g_free (filename);

Elliot Lee's avatar
Elliot Lee committed
264
  /* add the plug-in procs to the procedure database */
265
  plug_ins_add_to_db (gimp, context);
Elliot Lee's avatar
Elliot Lee committed
266

267
  /* create help_path and locale_domain lists */
268
  for (list = gimp->plug_in_defs; list; list = list->next)
269
    {
270
      PlugInDef *plug_in_def = list->data;
271

272
      if (plug_in_def->locale_domain_name)
273
	{
274
	  PlugInLocaleDomainDef *def;
275

276
	  def = g_new (PlugInLocaleDomainDef, 1);
277

278 279 280
	  def->prog_name   = g_strdup (plug_in_def->prog);
	  def->domain_name = g_strdup (plug_in_def->locale_domain_name);
          def->domain_path = g_strdup (plug_in_def->locale_domain_path);
281

282
	  gimp->plug_in_locale_domains =
283 284
            g_slist_prepend (gimp->plug_in_locale_domains, def);

Sven Neumann's avatar
Sven Neumann committed
285
#ifdef VERBOSE
286
          g_print ("added locale domain \"%s\" for path \"%s\"\n",
287
                   def->domain_name ? def->domain_name : "(null)",
288 289
                   def->domain_path ?
                   gimp_filename_to_utf8 (def->domain_path) : "(null)");
Sven Neumann's avatar
Sven Neumann committed
290
#endif
291 292
	}

293
      if (plug_in_def->help_domain_name)
294
	{
295 296 297
	  PlugInHelpDomainDef *def;

	  def = g_new (PlugInHelpDomainDef, 1);
298

299 300 301
	  def->prog_name   = g_strdup (plug_in_def->prog);
	  def->domain_name = g_strdup (plug_in_def->help_domain_name);
	  def->domain_uri  = g_strdup (plug_in_def->help_domain_uri);
302

303 304
	  gimp->plug_in_help_domains =
            g_slist_prepend (gimp->plug_in_help_domains, def);
305

Sven Neumann's avatar
Sven Neumann committed
306
#ifdef VERBOSE
307
          g_print ("added help domain \"%s\" for base uri \"%s\"\n",
Sven Neumann's avatar
Sven Neumann committed
308 309 310
                   def->domain_name ? def->domain_name : "(null)",
                   def->domain_uri  ? def->domain_uri  : "(null)");
#endif
311 312 313
	}
    }

314
  if (! gimp->no_interface)
315
    gimp_menus_init (gimp, gimp->plug_in_defs, STD_PLUGINS_DOMAIN);
Elliot Lee's avatar
Elliot Lee committed
316

317
  /* build list of automatically started extensions */
318
  for (list = gimp->plug_in_proc_defs, nth = 0; list; list = list->next, nth++)
Elliot Lee's avatar
Elliot Lee committed
319
    {
320
      PlugInProcDef *proc_def = list->data;
Elliot Lee's avatar
Elliot Lee committed
321

322 323 324
      if (proc_def->prog                                &&
	  proc_def->db_info.proc_type == GIMP_EXTENSION &&
	  proc_def->db_info.num_args  == 0)
Elliot Lee's avatar
Elliot Lee committed
325
	{
326 327 328 329 330 331 332 333 334 335
          extensions = g_list_prepend (extensions, proc_def);
        }
    }

  extensions   = g_list_reverse (extensions);
  n_extensions = g_list_length (extensions);

  /* run the available extensions */
  if (extensions)
    {
336 337
      GList *list;

338 339
      (* status_callback) (_("Starting Extensions"), "", 0);

340
      for (list = extensions, nth = 0; list; list = g_list_next (list), nth++)
341
        {
342
          PlugInProcDef *proc_def = list->data;
343

344
	  if (gimp->be_verbose)
345
	    g_print (_("Starting extension: '%s'\n"), proc_def->db_info.name);
346

347
	  (* status_callback) (NULL, proc_def->db_info.name, nth / n_plugins);
348

349 350
	  plug_in_run (gimp, context, &proc_def->db_info,
                       NULL, 0, FALSE, TRUE, -1);
Elliot Lee's avatar
Elliot Lee committed
351
	}
352 353 354 355

      (* status_callback) (NULL, NULL, 1.0);

      g_list_free (extensions);
Elliot Lee's avatar
Elliot Lee committed
356
    }
357

358
  /* free up stuff */
359 360
  for (list = gimp->plug_in_defs; list; list = list->next)
    plug_in_def_free (list->data, FALSE);
361

362 363
  g_slist_free (gimp->plug_in_defs);
  gimp->plug_in_defs = NULL;
364 365

  g_object_unref (context);
Elliot Lee's avatar
Elliot Lee committed
366 367 368
}

void
369
plug_ins_exit (Gimp *gimp)
Elliot Lee's avatar
Elliot Lee committed
370
{
371
  GSList *list;
Elliot Lee's avatar
Elliot Lee committed
372

373
  plug_in_exit (gimp);
Sven Neumann's avatar
Sven Neumann committed
374

375
  for (list = gimp->plug_in_locale_domains; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
376
    {
377
      PlugInLocaleDomainDef *def = list->data;
Elliot Lee's avatar
Elliot Lee committed
378

379 380 381 382
      g_free (def->prog_name);
      g_free (def->domain_name);
      g_free (def->domain_path);
      g_free (def);
Elliot Lee's avatar
Elliot Lee committed
383 384
    }

385 386
  g_slist_free (gimp->plug_in_locale_domains);
  gimp->plug_in_locale_domains = NULL;
Elliot Lee's avatar
Elliot Lee committed
387

388
  for (list = gimp->plug_in_help_domains; list; list = list->next)
389
    {
390
      PlugInHelpDomainDef *def = list->data;
391

392 393 394 395
      g_free (def->prog_name);
      g_free (def->domain_name);
      g_free (def->domain_uri);
      g_free (def);
Elliot Lee's avatar
Elliot Lee committed
396 397
    }

398 399
  g_slist_free (gimp->plug_in_help_domains);
  gimp->plug_in_help_domains = NULL;
Elliot Lee's avatar
Elliot Lee committed
400 401 402
}

void
403 404
plug_ins_add_internal (Gimp          *gimp,
                       PlugInProcDef *proc_def)
Elliot Lee's avatar
Elliot Lee committed
405
{
406
  g_return_if_fail (GIMP_IS_GIMP (gimp));
407 408
  g_return_if_fail (proc_def != NULL);

409 410
  gimp->plug_in_proc_defs = g_slist_prepend (gimp->plug_in_proc_defs,
                                             proc_def);
Elliot Lee's avatar
Elliot Lee committed
411 412
}

413
PlugInProcDef *
414 415 416 417 418
plug_ins_file_register_magic (Gimp        *gimp,
                              const gchar *name,
                              const gchar *extensions,
                              const gchar *prefixes,
                              const gchar *magics)
Elliot Lee's avatar
Elliot Lee committed
419
{
420
  GSList *list;
Elliot Lee's avatar
Elliot Lee committed
421

422
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
Sven Neumann's avatar
Sven Neumann committed
423 424
  g_return_val_if_fail (name != NULL, NULL);

425 426
  if (gimp->current_plug_in)
    list = gimp->current_plug_in->plug_in_def->proc_defs;
Elliot Lee's avatar
Elliot Lee committed
427
  else
428
    list = gimp->plug_in_proc_defs;
Elliot Lee's avatar
Elliot Lee committed
429

430
  for (; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
431
    {
432
      PlugInProcDef *proc_def = list->data;
Elliot Lee's avatar
Elliot Lee committed
433 434 435 436 437

      if (strcmp (proc_def->db_info.name, name) == 0)
	{
	  if (proc_def->extensions != extensions)
	    {
438 439
              if (proc_def->extensions)
                g_free (proc_def->extensions);
Elliot Lee's avatar
Elliot Lee committed
440 441
	      proc_def->extensions = g_strdup (extensions);
	    }
442 443 444

	  proc_def->extensions_list =
            plug_ins_extensions_parse (proc_def->extensions);
Elliot Lee's avatar
Elliot Lee committed
445 446 447

	  if (proc_def->prefixes != prefixes)
	    {
448 449
              if (proc_def->prefixes)
                g_free (proc_def->prefixes);
Elliot Lee's avatar
Elliot Lee committed
450 451
	      proc_def->prefixes = g_strdup (prefixes);
	    }
452 453 454

	  proc_def->prefixes_list =
            plug_ins_extensions_parse (proc_def->prefixes);
Elliot Lee's avatar
Elliot Lee committed
455 456 457

	  if (proc_def->magics != magics)
	    {
458 459
              if (proc_def->magics)
                g_free (proc_def->magics);
Elliot Lee's avatar
Elliot Lee committed
460 461
	      proc_def->magics = g_strdup (magics);
	    }
462 463 464 465

	  proc_def->magics_list =
            plug_ins_extensions_parse (proc_def->magics);

Elliot Lee's avatar
Elliot Lee committed
466 467 468 469 470 471 472
	  return proc_def;
	}
    }

  return NULL;
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
PlugInProcDef *
plug_ins_file_register_mime (Gimp        *gimp,
                             const gchar *name,
                             const gchar *mime_type)
{
  GSList *list;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (mime_type != NULL, NULL);

  if (gimp->current_plug_in)
    list = gimp->current_plug_in->plug_in_def->proc_defs;
  else
    list = gimp->plug_in_proc_defs;

  for (; list; list = list->next)
    {
      PlugInProcDef *proc_def = list->data;

      if (strcmp (proc_def->db_info.name, name) == 0)
	{
          if (proc_def->mime_type)
            g_free (proc_def->mime_type);
          proc_def->mime_type = g_strdup (mime_type);
        }

      return proc_def;
    }

  return NULL;
}

Elliot Lee's avatar
Elliot Lee committed
506
void
507 508
plug_ins_def_add_from_rc (Gimp      *gimp,
                          PlugInDef *plug_in_def)
Elliot Lee's avatar
Elliot Lee committed
509
{
510
  GSList *list;
511
  gchar  *basename1;
512

513
  g_return_if_fail (GIMP_IS_GIMP (gimp));
514 515 516 517 518 519 520 521 522
  g_return_if_fail (plug_in_def != NULL);
  g_return_if_fail (plug_in_def->prog != NULL);

  if (! g_path_is_absolute (plug_in_def->prog))
    {
      g_warning ("plug_ins_def_add_from_rc: filename not absolute (skipping)");
      plug_in_def_free (plug_in_def, TRUE);
      return;
    }
Elliot Lee's avatar
Elliot Lee committed
523

524
  basename1 = g_path_get_basename (plug_in_def->prog);
Elliot Lee's avatar
Elliot Lee committed
525

526 527 528 529 530 531 532
  /*  If this is a file load or save plugin, make sure we have
   *  something for one of the extensions, prefixes, or magic number.
   *  Other bits of code rely on detecting file plugins by the presence
   *  of one of these things, but Nick Lamb's alien/unknown format
   *  loader needs to be able to register no extensions, prefixes or
   *  magics. -- austin 13/Feb/99
   */
533
  for (list = plug_in_def->proc_defs; list; list = list->next)
534
    {
535 536
      PlugInProcDef *proc_def;

537
      proc_def = (PlugInProcDef *) list->data;
538

539 540 541
      if (! proc_def->extensions &&
          ! proc_def->prefixes   &&
          ! proc_def->magics     &&
542 543 544
	  proc_def->menu_paths   &&
	  (! strncmp (proc_def->menu_paths->data, "<Load>", 6) ||
	   ! strncmp (proc_def->menu_paths->data, "<Save>", 6)))
545
	{
546
	  proc_def->extensions = g_strdup ("");
547 548
	}
    }
549

550 551 552
  /*  Check if the entry mentioned in pluginrc matches an executable
   *  found in the plug_in_path.
   */
553
  for (list = gimp->plug_in_defs; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
554
    {
555
      PlugInDef *ondisk_plug_in_def;
556
      gchar     *basename2;
Elliot Lee's avatar
Elliot Lee committed
557

558
      ondisk_plug_in_def = (PlugInDef *) list->data;
Elliot Lee's avatar
Elliot Lee committed
559

560 561 562
      basename2 = g_path_get_basename (ondisk_plug_in_def->prog);

      if (! strcmp (basename1, basename2))
Elliot Lee's avatar
Elliot Lee committed
563
	{
564 565 566
	  if (! g_ascii_strcasecmp (plug_in_def->prog,
                                    ondisk_plug_in_def->prog) &&
	      (plug_in_def->mtime == ondisk_plug_in_def->mtime))
Elliot Lee's avatar
Elliot Lee committed
567
	    {
568
	      /* Use pluginrc entry, deleting ondisk entry */
569
	      list->data = plug_in_def;
570
	      plug_in_def_free (ondisk_plug_in_def, TRUE);
Elliot Lee's avatar
Elliot Lee committed
571 572 573
	    }
	  else
	    {
574 575
              /* Use ondisk entry, deleting pluginrc entry */
	      plug_in_def_free (plug_in_def, TRUE);
Elliot Lee's avatar
Elliot Lee committed
576
	    }
577 578

	  g_free (basename2);
579
	  g_free (basename1);
580

Elliot Lee's avatar
Elliot Lee committed
581 582
	  return;
	}
583 584

      g_free (basename2);
Elliot Lee's avatar
Elliot Lee committed
585 586
    }

587 588
  g_free (basename1);

589
  gimp->write_pluginrc = TRUE;
590 591
  g_printerr ("executable not found: '%s'\n",
              gimp_filename_to_utf8 (plug_in_def->prog));
592
  plug_in_def_free (plug_in_def, FALSE);
Elliot Lee's avatar
Elliot Lee committed
593 594
}

595 596
void
plug_ins_temp_proc_def_add (Gimp          *gimp,
597
                            PlugInProcDef *proc_def)
Elliot Lee's avatar
Elliot Lee committed
598
{
599 600
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (proc_def != NULL);
Sven Neumann's avatar
Sven Neumann committed
601

602
  if (! gimp->no_interface)
Elliot Lee's avatar
Elliot Lee committed
603
    {
604
      if (proc_def->menu_paths)
605
        gimp_menus_create_entry (gimp, proc_def);
Elliot Lee's avatar
Elliot Lee committed
606 607
    }

608 609
  /*  Register the procedural database entry  */
  procedural_db_register (gimp, &proc_def->db_info);
Elliot Lee's avatar
Elliot Lee committed
610

611
  /*  Add the definition to the global list  */
612
  gimp->plug_in_proc_defs = g_slist_append (gimp->plug_in_proc_defs, proc_def);
613 614 615 616 617 618 619 620 621 622 623
}

void
plug_ins_temp_proc_def_remove (Gimp          *gimp,
                               PlugInProcDef *proc_def)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (proc_def != NULL);

  if (! gimp->no_interface)
    {
624
      if (proc_def->menu_paths)
625
        gimp_menus_delete_entry (gimp, proc_def);
Elliot Lee's avatar
Elliot Lee committed
626 627
    }

628 629 630 631
  /*  Unregister the procedural database entry  */
  procedural_db_unregister (gimp, proc_def->db_info.name);

  /*  Remove the definition from the global list  */
632
  gimp->plug_in_proc_defs = g_slist_remove (gimp->plug_in_proc_defs, proc_def);
633 634 635

  /*  Destroy the definition  */
  plug_in_proc_def_free (proc_def);
Elliot Lee's avatar
Elliot Lee committed
636 637
}

638
const gchar *
639 640
plug_ins_locale_domain (Gimp         *gimp,
                        const gchar  *prog_name,
641
                        const gchar **domain_path)
642
{
643
  GSList *list;
644

645
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
646

647 648
  if (domain_path)
    *domain_path = gimp_locale_directory ();
649

650 651 652 653
  /*  A NULL prog_name is GIMP itself, return the default domain  */
  if (! prog_name)
    return NULL;

654
  for (list = gimp->plug_in_locale_domains; list; list = list->next)
655
    {
656
      PlugInLocaleDomainDef *def = list->data;
657

658
      if (def && def->prog_name && ! strcmp (def->prog_name, prog_name))
659
        {
660 661
          if (domain_path && def->domain_path)
            *domain_path = def->domain_path;
662

663
          return def->domain_name;
664 665 666 667 668 669 670
        }
    }

  return STD_PLUGINS_DOMAIN;
}

const gchar *
671 672 673
plug_ins_help_domain (Gimp         *gimp,
                      const gchar  *prog_name,
                      const gchar **domain_uri)
674
{
675
  GSList *list;
676

677
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
678

679 680 681
  if (domain_uri)
    *domain_uri = NULL;

682 683 684 685
  /*  A NULL prog_name is GIMP itself, return the default domain  */
  if (! prog_name)
    return NULL;

686
  for (list = gimp->plug_in_help_domains; list; list = list->next)
687
    {
688 689 690 691 692 693
      PlugInHelpDomainDef *def = list->data;

      if (def && def->prog_name && ! strcmp (def->prog_name, prog_name))
        {
          if (domain_uri && def->domain_uri)
            *domain_uri = def->domain_uri;
694

695 696
          return def->domain_name;
        }
697 698 699 700 701
    }

  return NULL;
}

702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
gint
plug_ins_help_domains (Gimp    *gimp,
                       gchar ***help_domains,
                       gchar ***help_uris)
{
  GSList *list;
  gint    n_domains;
  gint    i;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), 0);
  g_return_val_if_fail (help_domains != NULL, 0);
  g_return_val_if_fail (help_uris != NULL, 0);

  n_domains = g_slist_length (gimp->plug_in_help_domains);

  *help_domains = g_new0 (gchar *, n_domains);
  *help_uris    = g_new0 (gchar *, n_domains);

720
  for (list = gimp->plug_in_help_domains, i = 0; list; list = list->next, i++)
721 722 723
    {
      PlugInHelpDomainDef *def = list->data;

724 725
      (*help_domains)[i] = g_strdup (def->domain_name);
      (*help_uris)[i]    = g_strdup (def->domain_uri);
726 727 728 729 730
    }

  return n_domains;
}

731 732 733 734 735 736 737 738 739
PlugInProcDef *
plug_ins_proc_def_find (Gimp       *gimp,
                        ProcRecord *proc_rec)
{
  GSList *list;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (proc_rec != NULL, NULL);

740
  for (list = gimp->plug_in_proc_defs; list; list = list->next)
741 742 743 744 745 746 747 748 749 750 751 752
    {
      PlugInProcDef *proc_def;

      proc_def = (PlugInProcDef *) list->data;

      if (proc_rec == &proc_def->db_info)
        return proc_def;
    }

  return NULL;
}

753 754 755
GSList *
plug_ins_extensions_parse (gchar *extensions)
{
756
  GSList *list = NULL;
757 758 759 760

  /* EXTENSIONS can be NULL.  Avoid calling strtok if it is.  */
  if (extensions)
    {
761 762 763
      gchar *extension;
      gchar *next_token;

764
      extensions = g_strdup (extensions);
765

766 767
      next_token = extensions;
      extension = strtok (next_token, " \t,");
768

769 770 771 772 773
      while (extension)
	{
	  list = g_slist_prepend (list, g_strdup (extension));
	  extension = strtok (NULL, " \t,");
	}
774

775 776 777 778 779 780 781 782 783 784 785 786
      g_free (extensions);
    }

  return g_slist_reverse (list);
}

PlugInImageType
plug_ins_image_types_parse (gchar *image_types)
{
  gchar           *type_spec = image_types;
  PlugInImageType  types     = 0;

787
  /*  If the plug_in registers with image_type == NULL or "", return 0
788
   *  By doing so it won't be touched by plug_in_set_menu_sensitivity()
789
   */
790
  if (! image_types)
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
    return types;

  while (*image_types)
    {
      while (*image_types &&
	     ((*image_types == ' ') ||
	      (*image_types == '\t') ||
	      (*image_types == ',')))
	image_types++;

      if (*image_types)
	{
	  if (strncmp (image_types, "RGBA", 4) == 0)
	    {
	      types |= PLUG_IN_RGBA_IMAGE;
	      image_types += 4;
	    }
	  else if (strncmp (image_types, "RGB*", 4) == 0)
	    {
	      types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE;
	      image_types += 4;
	    }
	  else if (strncmp (image_types, "RGB", 3) == 0)
	    {
	      types |= PLUG_IN_RGB_IMAGE;
	      image_types += 3;
	    }
	  else if (strncmp (image_types, "GRAYA", 5) == 0)
	    {
	      types |= PLUG_IN_GRAYA_IMAGE;
	      image_types += 5;
	    }
	  else if (strncmp (image_types, "GRAY*", 5) == 0)
	    {
	      types |= PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE;
	      image_types += 5;
	    }
	  else if (strncmp (image_types, "GRAY", 4) == 0)
	    {
	      types |= PLUG_IN_GRAY_IMAGE;
	      image_types += 4;
	    }
	  else if (strncmp (image_types, "INDEXEDA", 8) == 0)
	    {
	      types |= PLUG_IN_INDEXEDA_IMAGE;
	      image_types += 8;
	    }
	  else if (strncmp (image_types, "INDEXED*", 8) == 0)
	    {
	      types |= PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
	      image_types += 8;
	    }
	  else if (strncmp (image_types, "INDEXED", 7) == 0)
	    {
	      types |= PLUG_IN_INDEXED_IMAGE;
	      image_types += 7;
	    }
	  else if (strncmp (image_types, "*", 1) == 0)
	    {
	      types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE
	             | PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE
	             | PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
	      image_types += 1;
	    }
	  else
	    {
857 858
              g_printerr ("image_type contains unrecognizable parts: '%s'\n",
                          type_spec);
859

860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
	      while (*image_types &&
                     ((*image_types != ' ') ||
                      (*image_types != '\t') ||
                      (*image_types != ',')))
		image_types++;
	    }
	}
    }

  return types;
}


/*  private functions  */

875
static void
876 877
plug_ins_init_file (const GimpDatafileData *file_data,
                    gpointer                user_data)
Elliot Lee's avatar
Elliot Lee committed
878
{
879
  PlugInDef  *plug_in_def;
880 881
  GSList    **plug_in_defs;
  GSList     *list;
882

883
  plug_in_defs = (GSList **) user_data;
884

885
  for (list = *plug_in_defs; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
886
    {
887 888 889
      gchar *plug_in_name;

      plug_in_def = (PlugInDef *) list->data;
890

891 892
      plug_in_name = g_path_get_basename (plug_in_def->prog);

893
      if (g_ascii_strcasecmp (file_data->basename, plug_in_name) == 0)
Elliot Lee's avatar
Elliot Lee committed
894
	{
Sven Neumann's avatar
Sven Neumann committed
895
	  g_printerr ("skipping duplicate plug-in: '%s'\n",
896
                      gimp_filename_to_utf8 (file_data->filename));
897 898 899

          g_free (plug_in_name);

900
	  return;
Elliot Lee's avatar
Elliot Lee committed
901 902
	}

903
      g_free (plug_in_name);
Elliot Lee's avatar
Elliot Lee committed
904 905
    }

906 907 908 909
  plug_in_def = plug_in_def_new (file_data->filename);

  plug_in_def_set_mtime (plug_in_def, file_data->mtime);
  plug_in_def_set_needs_query (plug_in_def, TRUE);
Tor Lillqvist's avatar
Tor Lillqvist committed
910

911
  *plug_in_defs = g_slist_append (*plug_in_defs, plug_in_def);
912
}
Tor Lillqvist's avatar
Tor Lillqvist committed
913

914
static void
915 916
plug_ins_add_to_db (Gimp        *gimp,
                    GimpContext *context)
Elliot Lee's avatar
Elliot Lee committed
917
{
918
  PlugInProcDef *proc_def;
919
  GSList        *list;
920

921
  for (list = gimp->plug_in_proc_defs; list; list = list->next)
Elliot Lee's avatar
Elliot Lee committed
922
    {
923
      proc_def = list->data;
Elliot Lee's avatar
Elliot Lee committed
924

925
      if (proc_def->prog && (proc_def->db_info.proc_type != GIMP_INTERNAL))
Elliot Lee's avatar
Elliot Lee committed
926
	{
927 928
	  proc_def->db_info.exec_method.plug_in.filename = proc_def->prog;
	  procedural_db_register (gimp, &proc_def->db_info);
Elliot Lee's avatar
Elliot Lee committed
929
	}
930
    }
Elliot Lee's avatar
Elliot Lee committed
931

932
  for (list = gimp->plug_in_proc_defs; list; list = list->next)
933
    {
934
      proc_def = list->data;
935 936 937

      if (proc_def->extensions || proc_def->prefixes || proc_def->magics)
        {
938
          Argument args[4];
939

940 941
          args[0].arg_type          = GIMP_PDB_STRING;
          args[0].value.pdb_pointer = proc_def->db_info.name;
Elliot Lee's avatar
Elliot Lee committed
942

943 944
          args[1].arg_type          = GIMP_PDB_STRING;
          args[1].value.pdb_pointer = proc_def->extensions;
945

946 947
	  args[2].arg_type          = GIMP_PDB_STRING;
	  args[2].value.pdb_pointer = proc_def->prefixes;
Tor Lillqvist's avatar
Tor Lillqvist committed
948

949 950
	  args[3].arg_type          = GIMP_PDB_STRING;
	  args[3].value.pdb_pointer = proc_def->magics;
Elliot Lee's avatar
Elliot Lee committed
951

952 953 954 955 956
          g_free (procedural_db_execute (gimp, context,
                                         proc_def->image_types ?
                                         "gimp_register_save_handler" :
                                         "gimp_register_magic_load_handler",
                                         args));
Elliot Lee's avatar
Elliot Lee committed
957 958 959 960
	}
    }
}

961
static PlugInProcDef *
962 963
plug_ins_proc_def_insert (Gimp          *gimp,
                          PlugInProcDef *proc_def)
Elliot Lee's avatar
Elliot Lee committed
964
{
965
  GSList *list;
Elliot Lee's avatar
Elliot Lee committed
966

967
  for (list = gimp->plug_in_proc_defs; list; list = list->next)
968
    {
969
      PlugInProcDef *tmp_proc_def = list->data;
Elliot Lee's avatar
Elliot Lee committed
970

971
      if (strcmp (proc_def->db_info.name, tmp_proc_def->db_info.name) == 0)
Tor Lillqvist's avatar
Tor Lillqvist committed
972
	{
973