plug-in-menus.c 87 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

Manish Singh's avatar
Manish Singh committed
21 22 23 24
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif

25
#include <gtk/gtk.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
26

Elliot Lee's avatar
Elliot Lee committed
27 28 29 30 31
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
32
#ifdef HAVE_SYS_WAIT_H
Elliot Lee's avatar
Elliot Lee committed
33
#include <sys/wait.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
34 35
#endif
#ifdef HAVE_SYS_TIME_H
Elliot Lee's avatar
Elliot Lee committed
36
#include <sys/time.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
37
#endif
Elliot Lee's avatar
Elliot Lee committed
38 39 40
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
41
#ifdef HAVE_UNISTD_H
Elliot Lee's avatar
Elliot Lee committed
42
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
43 44
#endif

Manish Singh's avatar
Manish Singh committed
45
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
Tor Lillqvist's avatar
Tor Lillqvist committed
46 47 48 49
#define STRICT
#include <windows.h>
#include <process.h>

50
#ifdef G_OS_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
51 52
#include <fcntl.h>
#include <io.h>
53 54 55
#ifndef S_ISREG
#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
Tor Lillqvist's avatar
Tor Lillqvist committed
56 57
#endif

Manish Singh's avatar
Manish Singh committed
58
#ifdef G_WITH_CYGWIN
Tor Lillqvist's avatar
Tor Lillqvist committed
59 60 61 62 63 64 65 66
#define O_TEXT		0x0100	/* text file */
#define _O_TEXT		0x0100	/* text file */
#define O_BINARY	0x0200	/* binary file */
#define _O_BINARY	0x0200	/* binary file */
#endif

#endif

Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
67 68 69 70 71
#ifdef __EMX__
#include <fcntl.h>
#include <process.h>
#define _O_BINARY O_BINARY
#define _P_NOWAIT P_NOWAIT
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
72
#define xspawnv spawnv
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
73 74
#endif

75 76 77 78 79 80 81 82
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
#endif

#ifdef HAVE_SHM_H
#include <sys/shm.h>
#endif

83 84 85
#include "libgimpbase/gimpbase.h"
#include "libgimpbase/gimpprotocol.h"
#include "libgimpbase/gimpwire.h"
86

87 88
#include "core/core-types.h"

Michael Natterer's avatar
Michael Natterer committed
89 90 91
#include "base/tile.h"
#include "base/tile-manager.h"

92 93
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
94 95 96 97 98 99 100

#include "gui/brush-select.h"
#include "gui/gradient-select.h"
#include "gui/menus.h"
#include "gui/pattern-select.h"
#include "gdisplay.h"

101
#include "app_procs.h"
Elliot Lee's avatar
Elliot Lee committed
102 103
#include "appenv.h"
#include "datafiles.h"
104
#include "errors.h"
105
#include "gimpprogress.h"
Elliot Lee's avatar
Elliot Lee committed
106 107 108
#include "gimprc.h"
#include "plug_in.h"

109 110
#include "libgimp/gimpintl.h"

111

112
typedef struct _PlugInBlocked PlugInBlocked;
Elliot Lee's avatar
Elliot Lee committed
113 114 115 116

struct _PlugInBlocked
{
  PlugIn *plug_in;
117
  gchar  *proc_name;
Elliot Lee's avatar
Elliot Lee committed
118 119 120
};


121 122 123 124 125 126
typedef struct _PlugInMenuEntry PlugInMenuEntry;

struct _PlugInMenuEntry
{
  PlugInProcDef *proc_def;
  gchar         *domain;
127 128 129 130 131 132 133 134 135 136
  gchar         *help_path;
};


typedef struct _PlugInHelpPathDef PlugInHelpPathDef;

struct _PlugInHelpPathDef
{
  gchar *prog_name;
  gchar *help_path;
137 138 139
};


140
static gboolean plug_in_write             (GIOChannel	     *channel,
Elliot Lee's avatar
Elliot Lee committed
141 142
					   guint8            *buf,
				           gulong             count);
143 144 145
static gboolean plug_in_flush             (GIOChannel        *channel);
static void     plug_in_push              (PlugIn            *plug_in);
static void     plug_in_pop               (void);
Tor Lillqvist's avatar
Tor Lillqvist committed
146 147 148
static gboolean plug_in_recv_message	  (GIOChannel	     *channel,
					   GIOCondition	      cond,
					   gpointer	      data);
Elliot Lee's avatar
Elliot Lee committed
149 150 151 152 153 154 155
static void plug_in_handle_message        (WireMessage       *msg);
static void plug_in_handle_quit           (void);
static void plug_in_handle_tile_req       (GPTileReq         *tile_req);
static void plug_in_handle_proc_run       (GPProcRun         *proc_run);
static void plug_in_handle_proc_return    (GPProcReturn      *proc_return);
static void plug_in_handle_proc_install   (GPProcInstall     *proc_install);
static void plug_in_handle_proc_uninstall (GPProcUninstall   *proc_uninstall);
156
static void plug_in_write_rc              (const gchar       *filename);
157 158
static void plug_in_init_file             (const gchar       *filename,
					   gpointer           loader_data);
159
static void plug_in_query                 (PlugInDef         *plug_in_def);
Elliot Lee's avatar
Elliot Lee committed
160 161
static void plug_in_add_to_db             (void);
static void plug_in_make_menu             (void);
162 163 164
static gint plug_in_make_menu_entry       (gpointer           foo,
					   PlugInMenuEntry   *menu_entry,
					   gpointer           bar);
Elliot Lee's avatar
Elliot Lee committed
165 166
static void plug_in_callback              (GtkWidget         *widget,
					   gpointer           client_data);
167
static void plug_in_proc_def_insert       (PlugInProcDef     *proc_def,
168 169
					   void (* superceed_fn) (void *));
static void plug_in_proc_def_dead         (void              *freed_proc_def);
Elliot Lee's avatar
Elliot Lee committed
170 171
static void plug_in_proc_def_remove       (PlugInProcDef     *proc_def);
static void plug_in_proc_def_destroy      (PlugInProcDef     *proc_def,
172
					   gboolean           data_only);
Elliot Lee's avatar
Elliot Lee committed
173

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
static Argument * plug_in_temp_run       (ProcRecord *proc_rec,
					  Argument   *args,
					  gint        argc);
static Argument * plug_in_params_to_args (GPParam    *params,
					  gint        nparams,
					  gboolean    full_copy);
static GPParam  * plug_in_args_to_params (Argument   *args,
					  gint        nargs,
					  gboolean    full_copy);
static void       plug_in_params_destroy (GPParam    *params,
					  gint        nparams,
					  gboolean    full_destroy);
static void       plug_in_args_destroy   (Argument   *args,
					  gint        nargs,
					  gboolean    full_destroy);
static void       plug_in_init_shm       (void);

191 192
static gchar    * plug_in_search_in_path (gchar      *search_path,
					  gchar      *filename);
193

194
PlugIn *current_plug_in = NULL;
195
GSList *proc_defs       = NULL;
Elliot Lee's avatar
Elliot Lee committed
196

197
static GSList *plug_in_defs     = NULL;
Elliot Lee's avatar
Elliot Lee committed
198
static GSList *gimprc_proc_defs = NULL;
199
static GSList *open_plug_ins    = NULL;
Elliot Lee's avatar
Elliot Lee committed
200 201
static GSList *blocked_plug_ins = NULL;

202 203 204 205 206
static GSList *help_path_defs = NULL;

static GSList     *plug_in_stack              = NULL;
static GIOChannel *current_readchannel        = NULL;
static GIOChannel *current_writechannel       = NULL;
207
static gint        current_write_buffer_index = 0;
208 209 210
static gchar      *current_write_buffer       = NULL;
static Argument   *current_return_vals        = NULL;
static gint        current_return_nvals       = 0;
Elliot Lee's avatar
Elliot Lee committed
211 212 213

static ProcRecord *last_plug_in = NULL;

214
static gint    shm_ID = -1;
Elliot Lee's avatar
Elliot Lee committed
215 216
static guchar *shm_addr = NULL;

Manish Singh's avatar
Manish Singh committed
217
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
Tor Lillqvist's avatar
Tor Lillqvist committed
218 219 220
static HANDLE shm_handle;
#endif

221
static gboolean write_pluginrc = FALSE;
Elliot Lee's avatar
Elliot Lee committed
222

223
static gchar *std_plugins_domain = "gimp-std-plugins";
224 225 226 227 228 229 230 231 232 233 234 235 236 237


static void
plug_in_init_shm (void)
{
  /* allocate a piece of shared memory for use in transporting tiles
   *  to plug-ins. if we can't allocate a piece of shared memory then
   *  we'll fall back on sending the data over the pipe.
   */
  
#ifdef HAVE_SHM_H
  shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
  
  if (shm_ID == -1)
238
    g_message ("shmget() failed: Disabling shared memory tile transport.");
239 240
  else
    {
241 242
      shm_addr = (guchar *) shmat (shm_ID, NULL, 0);
      if (shm_addr == (guchar *) -1)
243
	{
244
	  g_message ("shmat() failed: Disabling shared memory tile transport.");
245
	  shmctl (shm_ID, IPC_RMID, NULL);
246 247 248 249
	  shm_ID = -1;
	}
      
#ifdef	IPC_RMID_DEFERRED_RELEASE
250 251
      if (shm_addr != (guchar *) -1)
	shmctl (shm_ID, IPC_RMID, NULL);
252 253 254
#endif
    }
#else
Manish Singh's avatar
Manish Singh committed
255
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
256 257 258
  /* Use Win32 shared memory mechanisms for
   * transfering tile data.
   */
259 260 261
  gint  pid;
  gchar fileMapName[MAX_PATH];
  gint  tileByteSize = TILE_WIDTH * TILE_HEIGHT * 4;
262 263 264 265 266
  
  /* Our shared memory id will be our process ID */
  pid = GetCurrentProcessId ();
  
  /* From the id, derive the file map name */
267 268
  g_snprintf (fileMapName, sizeof (fileMapName), "GIMP%d.SHM", pid);

269 270 271 272 273 274 275 276 277
  /* Create the file mapping into paging space */
  shm_handle = CreateFileMapping ((HANDLE) 0xFFFFFFFF, NULL,
				  PAGE_READWRITE, 0,
				  tileByteSize, fileMapName);
  
  if (shm_handle)
    {
      /* Map the shared memory into our address space for use */
      shm_addr = (guchar *) MapViewOfFile(shm_handle,
278
					  FILE_MAP_ALL_ACCESS,
279 280 281 282 283
					  0, 0, tileByteSize);
      
      /* Verify that we mapped our view */
      if (shm_addr)
	shm_ID = pid;
284 285 286 287
      else
	{
	  g_warning ("MapViewOfFile error: %d... disabling shared memory transport\n", GetLastError());
	}
288 289 290 291 292 293 294 295 296
    }
  else
    {
      g_warning ("CreateFileMapping error: %d... disabling shared memory transport\n", GetLastError());
    }
#endif
#endif
}

Elliot Lee's avatar
Elliot Lee committed
297
void
298
plug_in_init (void)
Elliot Lee's avatar
Elliot Lee committed
299
{
300
  extern gboolean use_shm;
301 302 303 304

  gchar         *filename;
  GSList        *tmp;
  GSList        *tmp2;
305
  PlugInDef     *plug_in_def;
Elliot Lee's avatar
Elliot Lee committed
306
  PlugInProcDef *proc_def;
307 308
  gfloat         nplugins;
  gfloat         nth;
Elliot Lee's avatar
Elliot Lee committed
309 310 311 312 313 314 315 316 317 318 319 320 321

  /* initialize the gimp protocol library and set the read and
   *  write handlers.
   */
  gp_init ();
  wire_set_writer (plug_in_write);
  wire_set_flusher (plug_in_flush);

  /* allocate a piece of shared memory for use in transporting tiles
   *  to plug-ins. if we can't allocate a piece of shared memory then
   *  we'll fall back on sending the data over the pipe.
   */
  if (use_shm)
322 323
    plug_in_init_shm ();

Elliot Lee's avatar
Elliot Lee committed
324
  /* search for binaries in the plug-in directory path */
Michael Natterer's avatar
Michael Natterer committed
325 326
  gimp_datafiles_read_directories (plug_in_path, MODE_EXECUTABLE,
				   plug_in_init_file, NULL);
Elliot Lee's avatar
Elliot Lee committed
327 328

  /* read the pluginrc file for cached data */
Tor Lillqvist's avatar
Tor Lillqvist committed
329
  filename = NULL;
330 331
  if (pluginrc_path)
    {
Tor Lillqvist's avatar
Tor Lillqvist committed
332 333
      if (g_path_is_absolute (pluginrc_path))
        filename = g_strdup (pluginrc_path);
334
      else
Tor Lillqvist's avatar
Tor Lillqvist committed
335 336
        filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
				    gimp_directory (), pluginrc_path);
337 338
    }
  else
Tor Lillqvist's avatar
Tor Lillqvist committed
339
    filename = gimp_personal_rc_file ("pluginrc");
340

341
  app_init_update_status (_("Resource configuration"), filename, -1);
Elliot Lee's avatar
Elliot Lee committed
342 343 344 345 346 347
  parse_gimprc_file (filename);

  /* query any plug-ins that have changed since we last wrote out
   *  the pluginrc file.
   */
  tmp = plug_in_defs;
348 349
  app_init_update_status (_("Plug-ins"), "", 0);
  nplugins = g_slist_length (tmp);
350
  nth = 0;
Elliot Lee's avatar
Elliot Lee committed
351 352 353 354 355 356 357 358
  while (tmp)
    {
      plug_in_def = tmp->data;
      tmp = tmp->next;

      if (plug_in_def->query)
	{
	  write_pluginrc = TRUE;
359 360

	  if (be_verbose)
361
	    g_print (_("query plug-in: \"%s\"\n"), plug_in_def->prog);
362

363
	  plug_in_query (plug_in_def);
Elliot Lee's avatar
Elliot Lee committed
364
	}
365

366
      app_init_update_status (NULL, plug_in_def->prog, nth / nplugins);
367
      nth++;
Elliot Lee's avatar
Elliot Lee committed
368 369 370
    }

  /* insert the proc defs */
371
  for (tmp = gimprc_proc_defs; tmp; tmp = g_slist_next (tmp))
Elliot Lee's avatar
Elliot Lee committed
372 373 374
    {
      proc_def = g_new (PlugInProcDef, 1);
      *proc_def = *((PlugInProcDef*) tmp->data);
375
      plug_in_proc_def_insert (proc_def, NULL);
Elliot Lee's avatar
Elliot Lee committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389
    }

  tmp = plug_in_defs;
  while (tmp)
    {
      plug_in_def = tmp->data;
      tmp = tmp->next;

      tmp2 = plug_in_def->proc_defs;
      while (tmp2)
	{
	  proc_def = tmp2->data;
	  tmp2 = tmp2->next;

GMT 1999 Andy Thomas's avatar
GMT 1999 Andy Thomas committed
390
 	  proc_def->mtime = plug_in_def->mtime; 
391
	  plug_in_proc_def_insert (proc_def, plug_in_proc_def_dead);
Elliot Lee's avatar
Elliot Lee committed
392 393 394 395 396 397
	}
    }

  /* write the pluginrc file if necessary */
  if (write_pluginrc)
    {
398
      if (be_verbose)
399
	g_print (_("writing \"%s\"\n"), filename);
400

Elliot Lee's avatar
Elliot Lee committed
401 402 403
      plug_in_write_rc (filename);
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
404 405
  g_free (filename);

Elliot Lee's avatar
Elliot Lee committed
406 407 408 409 410 411 412
  /* add the plug-in procs to the procedure database */
  plug_in_add_to_db ();

  /* make the menu */
  plug_in_make_menu ();

  /* run the available extensions */
413
  if (be_verbose)
414
    g_print (_("Starting extensions: "));
415

416
  app_init_update_status (_("Extensions"), "", 0);
417 418

  tmp = proc_defs;
419
  nplugins = g_slist_length (tmp); nth = 0;
420

Elliot Lee's avatar
Elliot Lee committed
421 422 423 424 425 426 427
  while (tmp)
    {
      proc_def = tmp->data;
      tmp = tmp->next;

      if (proc_def->prog &&
	  (proc_def->db_info.num_args == 0) &&
428
	  (proc_def->db_info.proc_type == GIMP_EXTENSION))
Elliot Lee's avatar
Elliot Lee committed
429
	{
430
	  if (be_verbose)
431
	    g_print ("%s ", proc_def->db_info.name);
432

433 434
	  app_init_update_status (NULL, proc_def->db_info.name,
				  nth / nplugins);
435

436
	  plug_in_run (&proc_def->db_info, NULL, 0, FALSE, TRUE, -1);
Elliot Lee's avatar
Elliot Lee committed
437 438
	}
    }
439 440

  if (be_verbose)
441
    g_print ("\n");
Elliot Lee's avatar
Elliot Lee committed
442

443
  /* create help path list and free up stuff */
444
  for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
Elliot Lee's avatar
Elliot Lee committed
445 446 447
    {
      plug_in_def = tmp->data;

448 449 450 451 452 453 454 455 456 457 458 459
      if (plug_in_def->help_path)
	{
	  PlugInHelpPathDef *help_path_def;

	  help_path_def = g_new (PlugInHelpPathDef, 1);

	  help_path_def->prog_name = g_strdup (plug_in_def->prog);
	  help_path_def->help_path = g_strdup (plug_in_def->help_path);

	  help_path_defs = g_slist_prepend (help_path_defs, help_path_def);
	}

Sven Neumann's avatar
Sven Neumann committed
460
      plug_in_def_free (plug_in_def, FALSE);
Elliot Lee's avatar
Elliot Lee committed
461
    }
462

Elliot Lee's avatar
Elliot Lee committed
463
  g_slist_free (plug_in_defs);
464
  plug_in_defs = NULL;
Elliot Lee's avatar
Elliot Lee committed
465 466
}

467

Elliot Lee's avatar
Elliot Lee committed
468
void
469
plug_in_kill (void)
Elliot Lee's avatar
Elliot Lee committed
470 471 472 473
{
  GSList *tmp;
  PlugIn *plug_in;
  
Manish Singh's avatar
Manish Singh committed
474
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
Tor Lillqvist's avatar
Tor Lillqvist committed
475 476
  CloseHandle (shm_handle);
#else
477
#ifdef HAVE_SHM_H
Elliot Lee's avatar
Elliot Lee committed
478 479 480
#ifndef	IPC_RMID_DEFERRED_RELEASE
  if (shm_ID != -1)
    {
481 482
      shmdt ((gchar *) shm_addr);
      shmctl (shm_ID, IPC_RMID, NULL);
Elliot Lee's avatar
Elliot Lee committed
483 484 485
    }
#else	/* IPC_RMID_DEFERRED_RELEASE */
  if (shm_ID != -1)
486
    shmdt ((gchar *) shm_addr);
Elliot Lee's avatar
Elliot Lee committed
487
#endif
Tor Lillqvist's avatar
Tor Lillqvist committed
488
#endif
489 490
#endif
 
Elliot Lee's avatar
Elliot Lee committed
491 492 493 494 495 496 497 498 499 500 501
  tmp = open_plug_ins;
  while (tmp)
    {
      plug_in = tmp->data;
      tmp = tmp->next;

      plug_in_destroy (plug_in);
    }
}

void
502 503 504
plug_in_add (gchar *prog,
	     gchar *menu_path,
	     gchar *accelerator)
Elliot Lee's avatar
Elliot Lee committed
505 506
{
  PlugInProcDef *proc_def;
507
  GSList        *tmp;
Elliot Lee's avatar
Elliot Lee committed
508

Sven Neumann's avatar
Sven Neumann committed
509 510
  g_return_if_fail (prog != NULL);

Elliot Lee's avatar
Elliot Lee committed
511 512
  if (strncmp ("plug_in_", prog, 8) != 0)
    {
513
      gchar *t = g_strdup_printf ("plug_in_%s", prog);
Elliot Lee's avatar
Elliot Lee committed
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
      g_free (prog);
      prog = t;
    }

  tmp = gimprc_proc_defs;
  while (tmp)
    {
      proc_def = tmp->data;
      tmp = tmp->next;

      if (strcmp (proc_def->db_info.name, prog) == 0)
	{
	  if (proc_def->db_info.name)
	    g_free (proc_def->db_info.name);
	  if (proc_def->menu_path)
	    g_free (proc_def->menu_path);
	  if (proc_def->accelerator)
	    g_free (proc_def->accelerator);
	  if (proc_def->extensions)
	    g_free (proc_def->extensions);
	  if (proc_def->prefixes)
	    g_free (proc_def->prefixes);
	  if (proc_def->magics)
	    g_free (proc_def->magics);
	  if (proc_def->image_types)
	    g_free (proc_def->image_types);

	  proc_def->db_info.name = prog;
542 543 544 545 546 547
	  proc_def->menu_path    = menu_path;
	  proc_def->accelerator  = accelerator;
	  proc_def->prefixes     = NULL;
	  proc_def->extensions   = NULL;
	  proc_def->magics       = NULL;
	  proc_def->image_types  = NULL;
Elliot Lee's avatar
Elliot Lee committed
548 549 550 551 552 553
	  return;
	}
    }

  proc_def = g_new0 (PlugInProcDef, 1);
  proc_def->db_info.name = prog;
554 555
  proc_def->menu_path    = menu_path;
  proc_def->accelerator  = accelerator;
Elliot Lee's avatar
Elliot Lee committed
556 557 558 559

  gimprc_proc_defs = g_slist_prepend (gimprc_proc_defs, proc_def);
}

560
gchar *
561
plug_in_image_types (gchar *name)
Elliot Lee's avatar
Elliot Lee committed
562
{
563
  PlugInDef     *plug_in_def;
Elliot Lee's avatar
Elliot Lee committed
564
  PlugInProcDef *proc_def;
565
  GSList        *tmp;
Elliot Lee's avatar
Elliot Lee committed
566

Sven Neumann's avatar
Sven Neumann committed
567 568
  g_return_val_if_fail (name != NULL, NULL);

Elliot Lee's avatar
Elliot Lee committed
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
  if (current_plug_in)
    {
      plug_in_def = current_plug_in->user_data;
      tmp = plug_in_def->proc_defs;
    }
  else
    {
      tmp = proc_defs;
    }

  while (tmp)
    {
      proc_def = tmp->data;
      tmp = tmp->next;

      if (strcmp (proc_def->db_info.name, name) == 0)
	return proc_def->image_types;
    }

  return NULL;
}

591
GSList *
592
plug_in_extensions_parse (gchar *extensions)
Elliot Lee's avatar
Elliot Lee committed
593 594
{
  GSList *list;
595 596 597
  gchar  *extension;
  gchar  *next_token;

Elliot Lee's avatar
Elliot Lee committed
598
  list = NULL;
599

Elliot Lee's avatar
Elliot Lee committed
600 601 602 603
  /* EXTENSIONS can be NULL.  Avoid calling strtok if it is.  */
  if (extensions)
    {
      extensions = g_strdup (extensions);
604 605
      next_token = extensions;
      extension = strtok (next_token, " \t,");
Elliot Lee's avatar
Elliot Lee committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
      while (extension)
	{
	  list = g_slist_prepend (list, g_strdup (extension));
	  extension = strtok (NULL, " \t,");
	}
      g_free (extensions);
    }

  return g_slist_reverse (list);
}

void
plug_in_add_internal (PlugInProcDef *proc_def)
{
  proc_defs = g_slist_prepend (proc_defs, proc_def);
}

623
PlugInProcDef *
624 625 626 627
plug_in_file_handler (gchar *name,
		      gchar *extensions,
		      gchar *prefixes,
		      gchar *magics)
Elliot Lee's avatar
Elliot Lee committed
628
{
629
  PlugInDef     *plug_in_def;
Elliot Lee's avatar
Elliot Lee committed
630
  PlugInProcDef *proc_def;
631
  GSList        *tmp;
Elliot Lee's avatar
Elliot Lee committed
632

Sven Neumann's avatar
Sven Neumann committed
633 634
  g_return_val_if_fail (name != NULL, NULL);

Elliot Lee's avatar
Elliot Lee committed
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
  if (current_plug_in)
    {
      plug_in_def = current_plug_in->user_data;
      tmp = plug_in_def->proc_defs;
    }
  else
    {
      tmp = proc_defs;
    }

  while (tmp)
    {
      proc_def = tmp->data;
      tmp = tmp->next;

      if (strcmp (proc_def->db_info.name, name) == 0)
	{
	  /* EXTENSIONS can be proc_def->extensions  */
	  if (proc_def->extensions != extensions)
	    {
	      if (proc_def->extensions)
		g_free (proc_def->extensions);
	      proc_def->extensions = g_strdup (extensions);
	    }
	  proc_def->extensions_list = plug_in_extensions_parse (proc_def->extensions);

	  /* PREFIXES can be proc_def->prefixes  */
	  if (proc_def->prefixes != prefixes)
	    {
	      if (proc_def->prefixes)
		g_free (proc_def->prefixes);
	      proc_def->prefixes = g_strdup (prefixes);
	    }
	  proc_def->prefixes_list = plug_in_extensions_parse (proc_def->prefixes);

670
	  /* MAGICS can be proc_def->magics  */
Elliot Lee's avatar
Elliot Lee committed
671 672 673 674 675 676 677 678 679 680 681 682 683 684
	  if (proc_def->magics != magics)
	    {
	      if (proc_def->magics)
		g_free (proc_def->magics);
	      proc_def->magics = g_strdup (magics);
	    }
	  proc_def->magics_list = plug_in_extensions_parse (proc_def->magics);
	  return proc_def;
	}
    }

  return NULL;
}

685 686

PlugInDef *
687
plug_in_def_new (const gchar *prog)
688 689 690 691 692 693 694
{
  PlugInDef *plug_in_def;

  g_return_val_if_fail (prog != NULL, NULL);

  plug_in_def = g_new (PlugInDef, 1);

695 696
  plug_in_def->prog          = g_strdup (prog);
  plug_in_def->proc_defs     = NULL;
697
  plug_in_def->locale_domain = NULL;
698 699 700 701
  plug_in_def->locale_path   = NULL;
  plug_in_def->help_path     = NULL;
  plug_in_def->mtime         = 0;
  plug_in_def->query         = FALSE;
702 703 704 705 706 707 708 709 710 711 712 713
  
  return plug_in_def;
}


void
plug_in_def_free (PlugInDef *plug_in_def,
		  gboolean   free_proc_defs)
{
  GSList *list;

  g_free (plug_in_def->prog);
714 715 716 717 718 719
  if (plug_in_def->locale_domain)
    g_free (plug_in_def->locale_domain);
  if (plug_in_def->locale_path)
    g_free (plug_in_def->locale_path);
  if (plug_in_def->help_path)
    g_free (plug_in_def->help_path);
720

Sven Neumann's avatar
Sven Neumann committed
721
  if (free_proc_defs)
722 723
    {
      for (list = plug_in_def->proc_defs; list; list = list->next)
Sven Neumann's avatar
Sven Neumann committed
724
	plug_in_proc_def_destroy ((PlugInProcDef *)(list->data), FALSE);
725 726
    }

Sven Neumann's avatar
Sven Neumann committed
727 728 729
  if (plug_in_def->proc_defs)
    g_slist_free (plug_in_def->proc_defs);

730 731 732 733
  g_free (plug_in_def);
}


Elliot Lee's avatar
Elliot Lee committed
734 735 736
void
plug_in_def_add (PlugInDef *plug_in_def)
{
737
  PlugInDef     *tplug_in_def;
738
  PlugInProcDef *proc_def;
739 740
  GSList *tmp;
  gchar  *t1, *t2;
Elliot Lee's avatar
Elliot Lee committed
741

742
  t1 = g_basename (plug_in_def->prog);
Elliot Lee's avatar
Elliot Lee committed
743

744 745 746 747 748 749 750
  /*  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
   */
751
  for (tmp = plug_in_def->proc_defs; tmp; tmp = g_slist_next (tmp))
752
    {
753
      proc_def = tmp->data;
754

755 756 757 758 759
      if (!proc_def->extensions && !proc_def->prefixes && !proc_def->magics &&
	  proc_def->menu_path &&
	  (!strncmp (proc_def->menu_path, "<Load>", 6) ||
	   !strncmp (proc_def->menu_path, "<Save>", 6)))
	{
760
	  proc_def->extensions = g_strdup ("");
761 762
	}
    }
763

764
  for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
Elliot Lee's avatar
Elliot Lee committed
765 766 767
    {
      tplug_in_def = tmp->data;

768
      t2 = g_basename (tplug_in_def->prog);
Elliot Lee's avatar
Elliot Lee committed
769 770 771

      if (strcmp (t1, t2) == 0)
	{
Tor Lillqvist's avatar
Tor Lillqvist committed
772
	  if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
Elliot Lee's avatar
Elliot Lee committed
773 774 775 776
	      (plug_in_def->mtime == tplug_in_def->mtime))
	    {
	      /* Use cached plug-in entry */
	      tmp->data = plug_in_def;
Sven Neumann's avatar
Sven Neumann committed
777
	      plug_in_def_free (tplug_in_def, TRUE);
Elliot Lee's avatar
Elliot Lee committed
778 779 780
	    }
	  else
	    {
Sven Neumann's avatar
Sven Neumann committed
781
	      plug_in_def_free (plug_in_def, TRUE);    
Elliot Lee's avatar
Elliot Lee committed
782
	    }
783
	  
Elliot Lee's avatar
Elliot Lee committed
784 785 786 787 788
	  return;
	}
    }

  write_pluginrc = TRUE;
Sven Neumann's avatar
Sven Neumann committed
789
  g_print ("\"%s\" executable not found\n", plug_in_def->prog);
790
  plug_in_def_free (plug_in_def, FALSE);
Elliot Lee's avatar
Elliot Lee committed
791 792
}

793 794
gchar *
plug_in_menu_path (gchar *name)
Elliot Lee's avatar
Elliot Lee committed
795 796 797 798 799
{
  PlugInDef *plug_in_def;
  PlugInProcDef *proc_def;
  GSList *tmp, *tmp2;

Sven Neumann's avatar
Sven Neumann committed
800 801
  g_return_val_if_fail (name != NULL, NULL);

802
  for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
Elliot Lee's avatar
Elliot Lee committed
803 804 805
    {
      plug_in_def = tmp->data;

806
      for (tmp2 = plug_in_def->proc_defs; tmp2; tmp2 = g_slist_next (tmp2))
Elliot Lee's avatar
Elliot Lee committed
807 808 809 810 811 812 813 814
	{
	  proc_def = tmp2->data;

	  if (strcmp (proc_def->db_info.name, name) == 0)
	    return proc_def->menu_path;
	}
    }

815
  for (tmp = proc_defs; tmp; tmp = g_slist_next (tmp))
Elliot Lee's avatar
Elliot Lee committed
816 817 818 819 820 821 822 823 824 825
    {
      proc_def = tmp->data;

      if (strcmp (proc_def->db_info.name, name) == 0)
	return proc_def->menu_path;
    }

  return NULL;
}

826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
gchar *
plug_in_help_path (gchar *prog_name)
{
  PlugInHelpPathDef *help_path_def;
  GSList *list;

  if (!prog_name || !strlen (prog_name))
    return NULL;

  for (list = help_path_defs; list; list = g_slist_next (list))
    {
      help_path_def = (PlugInHelpPathDef *) list->data;

      if (help_path_def &&
	  help_path_def->prog_name &&
	  strcmp (help_path_def->prog_name, prog_name) == 0)
	return help_path_def->help_path;
    }

  return NULL;
}

848
PlugIn *
849
plug_in_new (gchar *name)
Elliot Lee's avatar
Elliot Lee committed
850 851
{
  PlugIn *plug_in;
852
  gchar  *path;
Elliot Lee's avatar
Elliot Lee committed
853

854
  if (! g_path_is_absolute (name))
Elliot Lee's avatar
Elliot Lee committed
855
    {
856 857 858
      path = plug_in_search_in_path (plug_in_path, name);

      if (! path)
Elliot Lee's avatar
Elliot Lee committed
859
	{
860
	  g_message (_("Unable to locate Plug-In: \"%s\""), name);
Elliot Lee's avatar
Elliot Lee committed
861 862 863 864 865 866 867 868 869 870
	  return NULL;
	}
    }
  else
    {
      path = name;
    }

  plug_in = g_new (PlugIn, 1);

871 872 873 874 875 876 877 878 879
  plug_in->open               = FALSE;
  plug_in->destroy            = FALSE;
  plug_in->query              = FALSE;
  plug_in->synchronous        = FALSE;
  plug_in->recurse            = FALSE;
  plug_in->busy               = FALSE;
  plug_in->pid                = 0;
  plug_in->args[0]            = g_strdup (path);
  plug_in->args[1]            = g_strdup ("-gimp");
880 881
  plug_in->args[2]            = NULL;
  plug_in->args[3]            = NULL;
882 883 884 885 886 887 888 889
  plug_in->args[4]            = NULL;
  plug_in->args[5]            = NULL;
  plug_in->args[6]            = NULL;
  plug_in->my_read            = NULL;
  plug_in->my_write           = NULL;
  plug_in->his_read           = NULL;
  plug_in->his_write          = NULL;
  plug_in->input_id           = 0;
Elliot Lee's avatar
Elliot Lee committed
890
  plug_in->write_buffer_index = 0;
891 892 893
  plug_in->temp_proc_defs     = NULL;
  plug_in->progress           = NULL;
  plug_in->user_data          = NULL;
Elliot Lee's avatar
Elliot Lee committed
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917

  return plug_in;
}

void
plug_in_destroy (PlugIn *plug_in)
{
  if (plug_in)
    {
      plug_in_close (plug_in, TRUE);

      if (plug_in->args[0])
	g_free (plug_in->args[0]);
      if (plug_in->args[1])
	g_free (plug_in->args[1]);
      if (plug_in->args[2])
	g_free (plug_in->args[2]);
      if (plug_in->args[3])
	g_free (plug_in->args[3]);
      if (plug_in->args[4])
	g_free (plug_in->args[4]);
      if (plug_in->args[5])
	g_free (plug_in->args[5]);

918 919 920
      if (plug_in->progress)
	progress_end (plug_in->progress);
      plug_in->progress = NULL;
921

Elliot Lee's avatar
Elliot Lee committed
922 923 924 925 926 927 928 929
      if (plug_in == current_plug_in)
	plug_in_pop ();

      if (!plug_in->destroy)
	g_free (plug_in);
    }
}

Tor Lillqvist's avatar
Tor Lillqvist committed
930 931 932 933 934
#ifdef G_OS_WIN32
/* The Microsoft _spawnv() does not allow to run scripts. But
 * this is essential to get scripting extension up and running.
 * Following the replacement function xspawnv().
 */
935 936 937
gint
xspawnv (gint                mode,
	 const gchar        *cmdname,
938
	 const gchar *const *argv)
Tor Lillqvist's avatar
Tor Lillqvist committed
939
{
940 941 942 943
  gchar sExecutable[_MAX_PATH*2];
  gchar** sArgsList;
  gchar sCmndLine[1024];
  gchar* sPath;
Tor Lillqvist's avatar
Tor Lillqvist committed
944
  HINSTANCE hInst;
945 946
  gint i;
  gint pid;
Tor Lillqvist's avatar
Tor Lillqvist committed
947 948

  /* only use it if _spawnv fails */
949
  pid = _spawnv (mode, cmdname, argv);
Tor Lillqvist's avatar
Tor Lillqvist committed
950 951 952 953 954 955
  if (pid != -1) return pid;

  /* stuff parameters into one cmndline */
  sCmndLine[0] = 0;
  for (i = 1; argv[i] != NULL; i++)
    {
956 957
       strcat (sCmndLine, argv[i]);
       strcat (sCmndLine, " ");
Tor Lillqvist's avatar
Tor Lillqvist committed
958 959
    }
  /* remove last blank */
960
  sCmndLine[strlen (sCmndLine)-1] = 0;
Tor Lillqvist's avatar
Tor Lillqvist committed
961 962

  /* do we really need _spawnv (ShelExecute seems not to do it)*/
963 964 965
  if (32 <= (int) FindExecutable (cmdname, 
				  gimp_directory (),
				  sExecutable))
Tor Lillqvist's avatar
Tor Lillqvist committed
966
    {
967
      /* g_print("_spawnlp %s %s %s", sExecutable, cmdname, sCmndLine); */
Tor Lillqvist's avatar
Tor Lillqvist committed
968
      
969
      pid = _spawnlp (mode, sExecutable, "-c", cmdname, sCmndLine, NULL);
Tor Lillqvist's avatar
Tor Lillqvist committed
970 971 972
    }
  else
    {
973
      g_warning ("Execution error for: %s", cmdname);
Tor Lillqvist's avatar
Tor Lillqvist committed
974 975 976 977 978 979 980
      return -1;
    }
  return pid;
}

#endif /* G_OS_WIN32 */

981
gboolean
Elliot Lee's avatar
Elliot Lee committed
982 983
plug_in_open (PlugIn *plug_in)
{
984 985
  gint my_read[2];
  gint my_write[2];
Elliot Lee's avatar
Elliot Lee committed
986 987 988 989 990 991 992

  if (plug_in)
    {
      /* Open two pipes. (Bidirectional communication).
       */
      if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
	{
993 994
	  g_message ("pipe() failed: Unable to start Plug-In \"%s\"\n(%s)",
		     g_basename (plug_in->args[0]), plug_in->args[0]);
995
	  return FALSE;
Elliot Lee's avatar
Elliot Lee committed
996 997
	}

Manish Singh's avatar
Manish Singh committed
998
#if defined(G_WITH_CYGWIN) || defined(__EMX__)
Tor Lillqvist's avatar
Tor Lillqvist committed
999
      /* Set to binary mode */
1000 1001 1002 1003
      setmode (my_read[0], _O_BINARY);
      setmode (my_write[0], _O_BINARY);
      setmode (my_read[1], _O_BINARY);
      setmode (my_write[1], _O_BINARY);
Tor Lillqvist's avatar
Tor Lillqvist committed
1004 1005
#endif

1006 1007 1008
      plug_in->my_read   = g_io_channel_unix_new (my_read[0]);
      plug_in->my_write  = g_io_channel_unix_new (my_write[1]);
      plug_in->his_read  = g_io_channel_unix_new (my_write[0]);
Tor Lillqvist's avatar
Tor Lillqvist committed
1009
      plug_in->his_write = g_io_channel_unix_new (my_read[1]);
Elliot Lee's avatar
Elliot Lee committed
1010 1011 1012

      /* Remember the file descriptors for the pipes.
       */
1013 1014 1015 1016
      plug_in->args[2] =
	g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read));
      plug_in->args[3] =
	g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write));
Elliot Lee's avatar
Elliot Lee committed
1017 1018 1019 1020 1021 1022 1023 1024 1025

      /* Set the rest of the command line arguments.
       */
      if (plug_in->query)
	{
	  plug_in->args[4] = g_strdup ("-query");
	}
      else
	{
1026
	  plug_in->args[4] = g_strdup ("-run");
Elliot Lee's avatar
Elliot Lee committed
1027 1028
	}