home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / plug_in.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  89.0 KB  |  3,524 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #ifdef HAVE_SYS_PARAM_H
  22. #include <sys/param.h>
  23. #endif
  24.  
  25. #include <glib.h>
  26.  
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #ifdef HAVE_SYS_WAIT_H
  33. #include <sys/wait.h>
  34. #endif
  35. #ifdef HAVE_SYS_TIME_H
  36. #include <sys/time.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <time.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44.  
  45. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  46. #define STRICT
  47. #include <windows.h>
  48. #include <process.h>
  49.  
  50. #ifdef G_OS_WIN32
  51. #include <fcntl.h>
  52. #include <io.h>
  53. #endif
  54.  
  55. #ifdef G_WITH_CYGWIN
  56. #define O_TEXT        0x0100    /* text file */
  57. #define _O_TEXT        0x0100    /* text file */
  58. #define O_BINARY    0x0200    /* binary file */
  59. #define _O_BINARY    0x0200    /* binary file */
  60. #endif
  61.  
  62. #endif
  63.  
  64. #ifdef __EMX__
  65. #include <fcntl.h>
  66. #include <process.h>
  67. #define _O_BINARY O_BINARY
  68. #define _P_NOWAIT P_NOWAIT
  69. #define xspawnv spawnv
  70. #endif
  71.  
  72. #ifdef HAVE_IPC_H
  73. #include <sys/ipc.h>
  74. #endif
  75.  
  76. #ifdef HAVE_SHM_H
  77. #include <sys/shm.h>
  78. #endif
  79.  
  80. #include "apptypes.h"
  81.  
  82. #include "app_procs.h"
  83. #include "appenv.h"
  84. #include "brush_select.h"  /* Need for closing dialogs */
  85. #include "drawable.h"
  86. #include "datafiles.h"
  87. #include "errors.h"
  88. #include "gdisplay.h"
  89. #include "general.h"
  90. #include "gimage.h"
  91. #include "gimprc.h"
  92. #include "gradient_select.h"
  93. #include "menus.h"
  94. #include "pattern_select.h"   /* Needed for closing pattern dialogs */
  95. #include "plug_in.h"
  96.  
  97. #include "tile.h"            /* ick. */
  98.  
  99. #include "libgimp/gimpenv.h"
  100. #include "libgimp/gimpprotocol.h"
  101. #include "libgimp/gimpwire.h"
  102. #include "libgimp/gimpparasite.h"
  103.  
  104. #include "libgimp/gimpintl.h"
  105.  
  106.  
  107. typedef struct _PlugInBlocked PlugInBlocked;
  108.  
  109. struct _PlugInBlocked
  110. {
  111.   PlugIn *plug_in;
  112.   gchar  *proc_name;
  113. };
  114.  
  115.  
  116. typedef struct _PlugInMenuEntry PlugInMenuEntry;
  117.  
  118. struct _PlugInMenuEntry
  119. {
  120.   PlugInProcDef *proc_def;
  121.   gchar         *domain;
  122.   gchar         *help_path;
  123. };
  124.  
  125.  
  126. typedef struct _PlugInHelpPathDef PlugInHelpPathDef;
  127.  
  128. struct _PlugInHelpPathDef
  129. {
  130.   gchar *prog_name;
  131.   gchar *help_path;
  132. };
  133.  
  134.  
  135. static gboolean plug_in_write             (GIOChannel         *channel,
  136.                        guint8            *buf,
  137.                            gulong             count);
  138. static gboolean plug_in_flush             (GIOChannel        *channel);
  139. static void     plug_in_push              (PlugIn            *plug_in);
  140. static void     plug_in_pop               (void);
  141. static gboolean plug_in_recv_message      (GIOChannel         *channel,
  142.                        GIOCondition          cond,
  143.                        gpointer          data);
  144. static void plug_in_handle_message        (WireMessage       *msg);
  145. static void plug_in_handle_quit           (void);
  146. static void plug_in_handle_tile_req       (GPTileReq         *tile_req);
  147. static void plug_in_handle_proc_run       (GPProcRun         *proc_run);
  148. static void plug_in_handle_proc_return    (GPProcReturn      *proc_return);
  149. static void plug_in_handle_proc_install   (GPProcInstall     *proc_install);
  150. static void plug_in_handle_proc_uninstall (GPProcUninstall   *proc_uninstall);
  151. static void plug_in_write_rc              (gchar             *filename);
  152. static void plug_in_init_file             (gchar             *filename);
  153. static void plug_in_query                 (PlugInDef         *plug_in_def);
  154. static void plug_in_add_to_db             (void);
  155. static void plug_in_make_menu             (void);
  156. static gint plug_in_make_menu_entry       (gpointer           foo,
  157.                        PlugInMenuEntry   *menu_entry,
  158.                        gpointer           bar);
  159. static void plug_in_callback              (GtkWidget         *widget,
  160.                        gpointer           client_data);
  161. static void plug_in_proc_def_insert       (PlugInProcDef     *proc_def,
  162.                        void (* superceed_fn) (void *));
  163. static void plug_in_proc_def_dead         (void              *freed_proc_def);
  164. static void plug_in_proc_def_remove       (PlugInProcDef     *proc_def);
  165. static void plug_in_proc_def_destroy      (PlugInProcDef     *proc_def,
  166.                        gboolean           data_only);
  167.  
  168. static Argument * plug_in_temp_run       (ProcRecord *proc_rec,
  169.                       Argument   *args,
  170.                       gint        argc);
  171. static Argument * plug_in_params_to_args (GPParam    *params,
  172.                       gint        nparams,
  173.                       gboolean    full_copy);
  174. static GPParam  * plug_in_args_to_params (Argument   *args,
  175.                       gint        nargs,
  176.                       gboolean    full_copy);
  177. static void       plug_in_params_destroy (GPParam    *params,
  178.                       gint        nparams,
  179.                       gboolean    full_destroy);
  180. static void       plug_in_args_destroy   (Argument   *args,
  181.                       gint        nargs,
  182.                       gboolean    full_destroy);
  183. static void       plug_in_init_shm       (void);
  184.  
  185.  
  186. PlugIn *current_plug_in = NULL;
  187. GSList *proc_defs       = NULL;
  188.  
  189. static GSList *plug_in_defs     = NULL;
  190. static GSList *gimprc_proc_defs = NULL;
  191. static GSList *open_plug_ins    = NULL;
  192. static GSList *blocked_plug_ins = NULL;
  193.  
  194. static GSList *help_path_defs = NULL;
  195.  
  196. static GSList     *plug_in_stack              = NULL;
  197. static GIOChannel *current_readchannel        = NULL;
  198. static GIOChannel *current_writechannel       = NULL;
  199. static gint        current_write_buffer_index = 0;
  200. static gchar      *current_write_buffer       = NULL;
  201. static Argument   *current_return_vals        = NULL;
  202. static gint        current_return_nvals       = 0;
  203.  
  204. static ProcRecord *last_plug_in = NULL;
  205.  
  206. static gint    shm_ID = -1;
  207. static guchar *shm_addr = NULL;
  208.  
  209. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  210. static HANDLE shm_handle;
  211. #endif
  212.  
  213. static gboolean write_pluginrc = FALSE;
  214.  
  215. static gchar *std_plugins_domain = "gimp-std-plugins";
  216.  
  217.  
  218. static void
  219. plug_in_init_shm (void)
  220. {
  221.   /* allocate a piece of shared memory for use in transporting tiles
  222.    *  to plug-ins. if we can't allocate a piece of shared memory then
  223.    *  we'll fall back on sending the data over the pipe.
  224.    */
  225.   
  226. #ifdef HAVE_SHM_H
  227.   shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
  228.   
  229.   if (shm_ID == -1)
  230.     g_message ("shmget() failed: Disabling shared memory tile transport.");
  231.   else
  232.     {
  233.       shm_addr = (guchar *) shmat (shm_ID, NULL, 0);
  234.       if (shm_addr == (guchar *) -1)
  235.     {
  236.       g_message ("shmat() failed: Disabling shared memory tile transport.");
  237.       shmctl (shm_ID, IPC_RMID, NULL);
  238.       shm_ID = -1;
  239.     }
  240.       
  241. #ifdef    IPC_RMID_DEFERRED_RELEASE
  242.       if (shm_addr != (guchar *) -1)
  243.     shmctl (shm_ID, IPC_RMID, NULL);
  244. #endif
  245.     }
  246. #else
  247. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  248.   /* Use Win32 shared memory mechanisms for
  249.    * transfering tile data.
  250.    */
  251.   gint  pid;
  252.   gchar fileMapName[MAX_PATH];
  253.   gint  tileByteSize = TILE_WIDTH * TILE_HEIGHT * 4;
  254.   
  255.   /* Our shared memory id will be our process ID */
  256.   pid = GetCurrentProcessId ();
  257.   
  258.   /* From the id, derive the file map name */
  259.   g_snprintf (fileMapName, sizeof (fileMapName), "GIMP%d.SHM", pid);
  260.  
  261.   /* Create the file mapping into paging space */
  262.   shm_handle = CreateFileMapping ((HANDLE) 0xFFFFFFFF, NULL,
  263.                   PAGE_READWRITE, 0,
  264.                   tileByteSize, fileMapName);
  265.   
  266.   if (shm_handle)
  267.     {
  268.       /* Map the shared memory into our address space for use */
  269.       shm_addr = (guchar *) MapViewOfFile(shm_handle,
  270.                       FILE_MAP_ALL_ACCESS,
  271.                       0, 0, tileByteSize);
  272.       
  273.       /* Verify that we mapped our view */
  274.       if (shm_addr)
  275.     shm_ID = pid;
  276.       else
  277.     {
  278.       g_warning ("MapViewOfFile error: %d... disabling shared memory transport\n", GetLastError());
  279.     }
  280.     }
  281.   else
  282.     {
  283.       g_warning ("CreateFileMapping error: %d... disabling shared memory transport\n", GetLastError());
  284.     }
  285. #endif
  286. #endif
  287. }
  288.  
  289. void
  290. plug_in_init (void)
  291. {
  292.   extern gboolean use_shm;
  293.  
  294.   gchar         *filename;
  295.   GSList        *tmp;
  296.   GSList        *tmp2;
  297.   PlugInDef     *plug_in_def;
  298.   PlugInProcDef *proc_def;
  299.   gfloat         nplugins;
  300.   gfloat         nth;
  301.  
  302.   /* initialize the gimp protocol library and set the read and
  303.    *  write handlers.
  304.    */
  305.   gp_init ();
  306.   wire_set_writer (plug_in_write);
  307.   wire_set_flusher (plug_in_flush);
  308.  
  309.   /* allocate a piece of shared memory for use in transporting tiles
  310.    *  to plug-ins. if we can't allocate a piece of shared memory then
  311.    *  we'll fall back on sending the data over the pipe.
  312.    */
  313.   if (use_shm)
  314.     plug_in_init_shm ();
  315.  
  316.   /* search for binaries in the plug-in directory path */
  317.   datafiles_read_directories (plug_in_path, plug_in_init_file, MODE_EXECUTABLE);
  318.  
  319.   /* read the pluginrc file for cached data */
  320.   filename = NULL;
  321.   if (pluginrc_path)
  322.     {
  323.       if (g_path_is_absolute (pluginrc_path))
  324.         filename = g_strdup (pluginrc_path);
  325.       else
  326.         filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
  327.                     gimp_directory (), pluginrc_path);
  328.     }
  329.   else
  330.     filename = gimp_personal_rc_file ("pluginrc");
  331.  
  332.   app_init_update_status (_("Resource configuration"), filename, -1);
  333.   parse_gimprc_file (filename);
  334.  
  335.   /* query any plug-ins that have changed since we last wrote out
  336.    *  the pluginrc file.
  337.    */
  338.   tmp = plug_in_defs;
  339.   app_init_update_status (_("Plug-ins"), "", 0);
  340.   nplugins = g_slist_length (tmp);
  341.   nth = 0;
  342.   while (tmp)
  343.     {
  344.       plug_in_def = tmp->data;
  345.       tmp = tmp->next;
  346.  
  347.       if (plug_in_def->query)
  348.     {
  349.       write_pluginrc = TRUE;
  350.  
  351.       if (be_verbose)
  352.         g_print (_("query plug-in: \"%s\"\n"), plug_in_def->prog);
  353.  
  354.       plug_in_query (plug_in_def);
  355.     }
  356.  
  357.       app_init_update_status (NULL, plug_in_def->prog, nth / nplugins);
  358.       nth++;
  359.     }
  360.  
  361.   /* insert the proc defs */
  362.   for (tmp = gimprc_proc_defs; tmp; tmp = g_slist_next (tmp))
  363.     {
  364.       proc_def = g_new (PlugInProcDef, 1);
  365.       *proc_def = *((PlugInProcDef*) tmp->data);
  366.       plug_in_proc_def_insert (proc_def, NULL);
  367.     }
  368.  
  369.   tmp = plug_in_defs;
  370.   while (tmp)
  371.     {
  372.       plug_in_def = tmp->data;
  373.       tmp = tmp->next;
  374.  
  375.       tmp2 = plug_in_def->proc_defs;
  376.       while (tmp2)
  377.     {
  378.       proc_def = tmp2->data;
  379.       tmp2 = tmp2->next;
  380.  
  381.        proc_def->mtime = plug_in_def->mtime; 
  382.       plug_in_proc_def_insert (proc_def, plug_in_proc_def_dead);
  383.     }
  384.     }
  385.  
  386.   /* write the pluginrc file if necessary */
  387.   if (write_pluginrc)
  388.     {
  389.       if (be_verbose)
  390.     g_print (_("writing \"%s\"\n"), filename);
  391.  
  392.       plug_in_write_rc (filename);
  393.     }
  394.  
  395.   g_free (filename);
  396.  
  397.   /* add the plug-in procs to the procedure database */
  398.   plug_in_add_to_db ();
  399.  
  400.   /* make the menu */
  401.   plug_in_make_menu ();
  402.  
  403.   /* run the available extensions */
  404.   if (be_verbose)
  405.     g_print (_("Starting extensions: "));
  406.  
  407.   app_init_update_status (_("Extensions"), "", 0);
  408.  
  409.   tmp = proc_defs;
  410.   nplugins = g_slist_length (tmp); nth = 0;
  411.  
  412.   while (tmp)
  413.     {
  414.       proc_def = tmp->data;
  415.       tmp = tmp->next;
  416.  
  417.       if (proc_def->prog &&
  418.       (proc_def->db_info.num_args == 0) &&
  419.       (proc_def->db_info.proc_type == PDB_EXTENSION))
  420.     {
  421.       if (be_verbose)
  422.         g_print ("%s ", proc_def->db_info.name);
  423.  
  424.       app_init_update_status (NULL, proc_def->db_info.name,
  425.                   nth / nplugins);
  426.  
  427.       plug_in_run (&proc_def->db_info, NULL, 0, FALSE, TRUE, -1);
  428.     }
  429.     }
  430.  
  431.   if (be_verbose)
  432.     g_print ("\n");
  433.  
  434.   /* create help path list and free up stuff */
  435.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  436.     {
  437.       plug_in_def = tmp->data;
  438.  
  439.       if (plug_in_def->help_path)
  440.     {
  441.       PlugInHelpPathDef *help_path_def;
  442.  
  443.       help_path_def = g_new (PlugInHelpPathDef, 1);
  444.  
  445.       help_path_def->prog_name = g_strdup (plug_in_def->prog);
  446.       help_path_def->help_path = g_strdup (plug_in_def->help_path);
  447.  
  448.       help_path_defs = g_slist_prepend (help_path_defs, help_path_def);
  449.     }
  450.  
  451.       plug_in_def_free (plug_in_def, FALSE);
  452.     }
  453.  
  454.   g_slist_free (plug_in_defs);
  455.   plug_in_defs = NULL;
  456. }
  457.  
  458.  
  459. void
  460. plug_in_kill (void)
  461. {
  462.   GSList *tmp;
  463.   PlugIn *plug_in;
  464.   
  465. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  466.   CloseHandle (shm_handle);
  467. #else
  468. #ifdef HAVE_SHM_H
  469. #ifndef    IPC_RMID_DEFERRED_RELEASE
  470.   if (shm_ID != -1)
  471.     {
  472.       shmdt ((gchar *) shm_addr);
  473.       shmctl (shm_ID, IPC_RMID, NULL);
  474.     }
  475. #else    /* IPC_RMID_DEFERRED_RELEASE */
  476.   if (shm_ID != -1)
  477.     shmdt ((gchar *) shm_addr);
  478. #endif
  479. #endif
  480. #endif
  481.  
  482.   tmp = open_plug_ins;
  483.   while (tmp)
  484.     {
  485.       plug_in = tmp->data;
  486.       tmp = tmp->next;
  487.  
  488.       plug_in_destroy (plug_in);
  489.     }
  490. }
  491.  
  492. void
  493. plug_in_add (gchar *prog,
  494.          gchar *menu_path,
  495.          gchar *accelerator)
  496. {
  497.   PlugInProcDef *proc_def;
  498.   GSList        *tmp;
  499.  
  500.   if (strncmp ("plug_in_", prog, 8) != 0)
  501.     {
  502.       gchar *t = g_strdup_printf ("plug_in_%s", prog);
  503.       g_free (prog);
  504.       prog = t;
  505.     }
  506.  
  507.   tmp = gimprc_proc_defs;
  508.   while (tmp)
  509.     {
  510.       proc_def = tmp->data;
  511.       tmp = tmp->next;
  512.  
  513.       if (strcmp (proc_def->db_info.name, prog) == 0)
  514.     {
  515.       if (proc_def->db_info.name)
  516.         g_free (proc_def->db_info.name);
  517.       if (proc_def->menu_path)
  518.         g_free (proc_def->menu_path);
  519.       if (proc_def->accelerator)
  520.         g_free (proc_def->accelerator);
  521.       if (proc_def->extensions)
  522.         g_free (proc_def->extensions);
  523.       if (proc_def->prefixes)
  524.         g_free (proc_def->prefixes);
  525.       if (proc_def->magics)
  526.         g_free (proc_def->magics);
  527.       if (proc_def->image_types)
  528.         g_free (proc_def->image_types);
  529.  
  530.       proc_def->db_info.name = prog;
  531.       proc_def->menu_path    = menu_path;
  532.       proc_def->accelerator  = accelerator;
  533.       proc_def->prefixes     = NULL;
  534.       proc_def->extensions   = NULL;
  535.       proc_def->magics       = NULL;
  536.       proc_def->image_types  = NULL;
  537.       return;
  538.     }
  539.     }
  540.  
  541.   proc_def = g_new0 (PlugInProcDef, 1);
  542.   proc_def->db_info.name = prog;
  543.   proc_def->menu_path    = menu_path;
  544.   proc_def->accelerator  = accelerator;
  545.  
  546.   gimprc_proc_defs = g_slist_prepend (gimprc_proc_defs, proc_def);
  547. }
  548.  
  549. gchar *
  550. plug_in_image_types (gchar *name)
  551. {
  552.   PlugInDef     *plug_in_def;
  553.   PlugInProcDef *proc_def;
  554.   GSList        *tmp;
  555.  
  556.   if (current_plug_in)
  557.     {
  558.       plug_in_def = current_plug_in->user_data;
  559.       tmp = plug_in_def->proc_defs;
  560.     }
  561.   else
  562.     {
  563.       tmp = proc_defs;
  564.     }
  565.  
  566.   while (tmp)
  567.     {
  568.       proc_def = tmp->data;
  569.       tmp = tmp->next;
  570.  
  571.       if (strcmp (proc_def->db_info.name, name) == 0)
  572.     return proc_def->image_types;
  573.     }
  574.  
  575.   return NULL;
  576. }
  577.  
  578. GSList *
  579. plug_in_extensions_parse (gchar *extensions)
  580. {
  581.   GSList *list;
  582.   gchar  *extension;
  583.   gchar  *next_token;
  584.  
  585.   list = NULL;
  586.  
  587.   /* EXTENSIONS can be NULL.  Avoid calling strtok if it is.  */
  588.   if (extensions)
  589.     {
  590.       extensions = g_strdup (extensions);
  591.       next_token = extensions;
  592.       extension = strtok (next_token, " \t,");
  593.       while (extension)
  594.     {
  595.       list = g_slist_prepend (list, g_strdup (extension));
  596.       extension = strtok (NULL, " \t,");
  597.     }
  598.       g_free (extensions);
  599.     }
  600.  
  601.   return g_slist_reverse (list);
  602. }
  603.  
  604. void
  605. plug_in_add_internal (PlugInProcDef *proc_def)
  606. {
  607.   proc_defs = g_slist_prepend (proc_defs, proc_def);
  608. }
  609.  
  610. PlugInProcDef *
  611. plug_in_file_handler (gchar *name,
  612.               gchar *extensions,
  613.               gchar *prefixes,
  614.               gchar *magics)
  615. {
  616.   PlugInDef     *plug_in_def;
  617.   PlugInProcDef *proc_def;
  618.   GSList        *tmp;
  619.  
  620.   if (current_plug_in)
  621.     {
  622.       plug_in_def = current_plug_in->user_data;
  623.       tmp = plug_in_def->proc_defs;
  624.     }
  625.   else
  626.     {
  627.       tmp = proc_defs;
  628.     }
  629.  
  630.   while (tmp)
  631.     {
  632.       proc_def = tmp->data;
  633.       tmp = tmp->next;
  634.  
  635.       if (strcmp (proc_def->db_info.name, name) == 0)
  636.     {
  637.       /* EXTENSIONS can be proc_def->extensions  */
  638.       if (proc_def->extensions != extensions)
  639.         {
  640.           if (proc_def->extensions)
  641.         g_free (proc_def->extensions);
  642.           proc_def->extensions = g_strdup (extensions);
  643.         }
  644.       proc_def->extensions_list = plug_in_extensions_parse (proc_def->extensions);
  645.  
  646.       /* PREFIXES can be proc_def->prefixes  */
  647.       if (proc_def->prefixes != prefixes)
  648.         {
  649.           if (proc_def->prefixes)
  650.         g_free (proc_def->prefixes);
  651.           proc_def->prefixes = g_strdup (prefixes);
  652.         }
  653.       proc_def->prefixes_list = plug_in_extensions_parse (proc_def->prefixes);
  654.  
  655.       /* MAGICS can be proc_def->magics  */
  656.       if (proc_def->magics != magics)
  657.         {
  658.           if (proc_def->magics)
  659.         g_free (proc_def->magics);
  660.           proc_def->magics = g_strdup (magics);
  661.         }
  662.       proc_def->magics_list = plug_in_extensions_parse (proc_def->magics);
  663.       return proc_def;
  664.     }
  665.     }
  666.  
  667.   return NULL;
  668. }
  669.  
  670.  
  671. PlugInDef *
  672. plug_in_def_new (gchar *prog)
  673. {
  674.   PlugInDef *plug_in_def;
  675.  
  676.   g_return_val_if_fail (prog != NULL, NULL);
  677.  
  678.   plug_in_def = g_new (PlugInDef, 1);
  679.  
  680.   plug_in_def->prog          = g_strdup (prog);
  681.   plug_in_def->proc_defs     = NULL;
  682.   plug_in_def->locale_domain = NULL;
  683.   plug_in_def->locale_path   = NULL;
  684.   plug_in_def->help_path     = NULL;
  685.   plug_in_def->mtime         = 0;
  686.   plug_in_def->query         = FALSE;
  687.   
  688.   return plug_in_def;
  689. }
  690.  
  691.  
  692. void
  693. plug_in_def_free (PlugInDef *plug_in_def,
  694.           gboolean   free_proc_defs)
  695. {
  696.   GSList *list;
  697.  
  698.   g_free (plug_in_def->prog);
  699.   if (plug_in_def->locale_domain)
  700.     g_free (plug_in_def->locale_domain);
  701.   if (plug_in_def->locale_path)
  702.     g_free (plug_in_def->locale_path);
  703.   if (plug_in_def->help_path)
  704.     g_free (plug_in_def->help_path);
  705.  
  706.   if (free_proc_defs)
  707.     {
  708.       for (list = plug_in_def->proc_defs; list; list = list->next)
  709.     plug_in_proc_def_destroy ((PlugInProcDef *)(list->data), FALSE);
  710.     }
  711.  
  712.   if (plug_in_def->proc_defs)
  713.     g_slist_free (plug_in_def->proc_defs);
  714.  
  715.   g_free (plug_in_def);
  716. }
  717.  
  718.  
  719. void
  720. plug_in_def_add (PlugInDef *plug_in_def)
  721. {
  722.   PlugInDef     *tplug_in_def;
  723.   PlugInProcDef *proc_def;
  724.   GSList *tmp;
  725.   gchar  *t1, *t2;
  726.  
  727.   t1 = g_basename (plug_in_def->prog);
  728.  
  729.   /*  If this is a file load or save plugin, make sure we have
  730.    *  something for one of the extensions, prefixes, or magic number.
  731.    *  Other bits of code rely on detecting file plugins by the presence
  732.    *  of one of these things, but Nick Lamb's alien/unknown format
  733.    *  loader needs to be able to register no extensions, prefixes or
  734.    *  magics. -- austin 13/Feb/99
  735.    */
  736.   for (tmp = plug_in_def->proc_defs; tmp; tmp = g_slist_next (tmp))
  737.     {
  738.       proc_def = tmp->data;
  739.  
  740.       if (!proc_def->extensions && !proc_def->prefixes && !proc_def->magics &&
  741.       proc_def->menu_path &&
  742.       (!strncmp (proc_def->menu_path, "<Load>", 6) ||
  743.        !strncmp (proc_def->menu_path, "<Save>", 6)))
  744.     {
  745.       proc_def->extensions = g_strdup ("");
  746.     }
  747.     }
  748.  
  749.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  750.     {
  751.       tplug_in_def = tmp->data;
  752.  
  753.       t2 = g_basename (tplug_in_def->prog);
  754.  
  755.       if (strcmp (t1, t2) == 0)
  756.     {
  757.       if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
  758.           (plug_in_def->mtime == tplug_in_def->mtime))
  759.         {
  760.           /* Use cached plug-in entry */
  761.           tmp->data = plug_in_def;
  762.           plug_in_def_free (tplug_in_def, TRUE);
  763.         }
  764.       else
  765.         {
  766.           plug_in_def_free (plug_in_def, TRUE);    
  767.         }
  768.       
  769.       return;
  770.     }
  771.     }
  772.  
  773.   write_pluginrc = TRUE;
  774.   g_print ("\"%s\" executable not found\n", plug_in_def->prog);
  775.   plug_in_def_free (plug_in_def, FALSE);
  776. }
  777.  
  778. gchar *
  779. plug_in_menu_path (gchar *name)
  780. {
  781.   PlugInDef *plug_in_def;
  782.   PlugInProcDef *proc_def;
  783.   GSList *tmp, *tmp2;
  784.  
  785.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  786.     {
  787.       plug_in_def = tmp->data;
  788.  
  789.       for (tmp2 = plug_in_def->proc_defs; tmp2; tmp2 = g_slist_next (tmp2))
  790.     {
  791.       proc_def = tmp2->data;
  792.  
  793.       if (strcmp (proc_def->db_info.name, name) == 0)
  794.         return proc_def->menu_path;
  795.     }
  796.     }
  797.  
  798.   for (tmp = proc_defs; tmp; tmp = g_slist_next (tmp))
  799.     {
  800.       proc_def = tmp->data;
  801.  
  802.       if (strcmp (proc_def->db_info.name, name) == 0)
  803.     return proc_def->menu_path;
  804.     }
  805.  
  806.   return NULL;
  807. }
  808.  
  809. gchar *
  810. plug_in_help_path (gchar *prog_name)
  811. {
  812.   PlugInHelpPathDef *help_path_def;
  813.   GSList *list;
  814.  
  815.   if (!prog_name || !strlen (prog_name))
  816.     return NULL;
  817.  
  818.   for (list = help_path_defs; list; list = g_slist_next (list))
  819.     {
  820.       help_path_def = (PlugInHelpPathDef *) list->data;
  821.  
  822.       if (help_path_def &&
  823.       help_path_def->prog_name &&
  824.       strcmp (help_path_def->prog_name, prog_name) == 0)
  825.     return help_path_def->help_path;
  826.     }
  827.  
  828.   return NULL;
  829. }
  830.  
  831. PlugIn *
  832. plug_in_new (gchar *name)
  833. {
  834.   PlugIn *plug_in;
  835.   gchar  *path;
  836.  
  837.   if (!g_path_is_absolute (name))
  838.     {
  839.       path = search_in_path (plug_in_path, name);
  840.       if (!path)
  841.     {
  842.       g_message (_("Unable to locate Plug-In: \"%s\""), name);
  843.       return NULL;
  844.     }
  845.     }
  846.   else
  847.     {
  848.       path = name;
  849.     }
  850.  
  851.   plug_in = g_new (PlugIn, 1);
  852.  
  853.   plug_in->open               = FALSE;
  854.   plug_in->destroy            = FALSE;
  855.   plug_in->query              = FALSE;
  856.   plug_in->synchronous        = FALSE;
  857.   plug_in->recurse            = FALSE;
  858.   plug_in->busy               = FALSE;
  859.   plug_in->pid                = 0;
  860.   plug_in->args[0]            = g_strdup (path);
  861.   plug_in->args[1]            = g_strdup ("-gimp");
  862.   plug_in->args[2]            = NULL;
  863.   plug_in->args[3]            = NULL;
  864.   plug_in->args[4]            = NULL;
  865.   plug_in->args[5]            = NULL;
  866.   plug_in->args[6]            = NULL;
  867.   plug_in->my_read            = NULL;
  868.   plug_in->my_write           = NULL;
  869.   plug_in->his_read           = NULL;
  870.   plug_in->his_write          = NULL;
  871.   plug_in->input_id           = 0;
  872.   plug_in->write_buffer_index = 0;
  873.   plug_in->temp_proc_defs     = NULL;
  874.   plug_in->progress           = NULL;
  875.   plug_in->user_data          = NULL;
  876.  
  877.   return plug_in;
  878. }
  879.  
  880. void
  881. plug_in_destroy (PlugIn *plug_in)
  882. {
  883.   if (plug_in)
  884.     {
  885.       plug_in_close (plug_in, TRUE);
  886.  
  887.       if (plug_in->args[0])
  888.     g_free (plug_in->args[0]);
  889.       if (plug_in->args[1])
  890.     g_free (plug_in->args[1]);
  891.       if (plug_in->args[2])
  892.     g_free (plug_in->args[2]);
  893.       if (plug_in->args[3])
  894.     g_free (plug_in->args[3]);
  895.       if (plug_in->args[4])
  896.     g_free (plug_in->args[4]);
  897.       if (plug_in->args[5])
  898.     g_free (plug_in->args[5]);
  899.  
  900.       if (plug_in->progress)
  901.     progress_end (plug_in->progress);
  902.       plug_in->progress = NULL;
  903.  
  904.       if (plug_in == current_plug_in)
  905.     plug_in_pop ();
  906.  
  907.       if (!plug_in->destroy)
  908.     g_free (plug_in);
  909.     }
  910. }
  911.  
  912. #ifdef G_OS_WIN32
  913. /* The Microsoft _spawnv() does not allow to run scripts. But
  914.  * this is essential to get scripting extension up and running.
  915.  * Following the replacement function xspawnv().
  916.  */
  917. gint
  918. xspawnv (gint                mode,
  919.      const gchar        *cmdname,
  920.      const gchar *const *argv)
  921. {
  922.   gchar sExecutable[_MAX_PATH*2];
  923.   gchar** sArgsList;
  924.   gchar sCmndLine[1024];
  925.   gchar* sPath;
  926.   HINSTANCE hInst;
  927.   gint i;
  928.   gint pid;
  929.  
  930.   /* only use it if _spawnv fails */
  931.   pid = _spawnv (mode, cmdname, argv);
  932.   if (pid != -1) return pid;
  933.  
  934.   /* stuff parameters into one cmndline */
  935.   sCmndLine[0] = 0;
  936.   for (i = 1; argv[i] != NULL; i++)
  937.     {
  938.        strcat (sCmndLine, argv[i]);
  939.        strcat (sCmndLine, " ");
  940.     }
  941.   /* remove last blank */
  942.   sCmndLine[strlen (sCmndLine)-1] = 0;
  943.  
  944.   /* do we really need _spawnv (ShelExecute seems not to do it)*/
  945.   if (32 <= (int) FindExecutable (cmdname, 
  946.                   gimp_directory (),
  947.                   sExecutable))
  948.     {
  949.       /* g_print("_spawnlp %s %s %s", sExecutable, cmdname, sCmndLine); */
  950.       
  951.       pid = _spawnlp (mode, sExecutable, "-c", cmdname, sCmndLine, NULL);
  952.     }
  953.   else
  954.     {
  955.       g_warning ("Execution error for: %s", cmdname);
  956.       return -1;
  957.     }
  958.   return pid;
  959. }
  960.  
  961. #endif /* G_OS_WIN32 */
  962.  
  963. gboolean
  964. plug_in_open (PlugIn *plug_in)
  965. {
  966.   gint my_read[2];
  967.   gint my_write[2];
  968.  
  969.   if (plug_in)
  970.     {
  971.       /* Open two pipes. (Bidirectional communication).
  972.        */
  973.       if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
  974.     {
  975.       g_message ("pipe() failed: Unable to start Plug-In \"%s\"\n(%s)",
  976.              g_basename (plug_in->args[0]), plug_in->args[0]);
  977.       return FALSE;
  978.     }
  979.  
  980. #if defined(G_WITH_CYGWIN) || defined(__EMX__)
  981.       /* Set to binary mode */
  982.       setmode (my_read[0], _O_BINARY);
  983.       setmode (my_write[0], _O_BINARY);
  984.       setmode (my_read[1], _O_BINARY);
  985.       setmode (my_write[1], _O_BINARY);
  986. #endif
  987.  
  988.       plug_in->my_read   = g_io_channel_unix_new (my_read[0]);
  989.       plug_in->my_write  = g_io_channel_unix_new (my_write[1]);
  990.       plug_in->his_read  = g_io_channel_unix_new (my_write[0]);
  991.       plug_in->his_write = g_io_channel_unix_new (my_read[1]);
  992.  
  993.       /* Remember the file descriptors for the pipes.
  994.        */
  995.       plug_in->args[2] =
  996.     g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read));
  997.       plug_in->args[3] =
  998.     g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write));
  999.  
  1000.       /* Set the rest of the command line arguments.
  1001.        */
  1002.       if (plug_in->query)
  1003.     {
  1004.       plug_in->args[4] = g_strdup ("-query");
  1005.     }
  1006.       else
  1007.     {
  1008.       plug_in->args[4] = g_strdup ("-run");
  1009.     }
  1010.  
  1011.       plug_in->args[5] = g_strdup_printf ("%d", (gint) stack_trace_mode);
  1012.  
  1013.       /* Fork another process. We'll remember the process id
  1014.        *  so that we can later use it to kill the filter if
  1015.        *  necessary.
  1016.        */
  1017. #ifdef __EMX__
  1018.       fcntl (my_read[0], F_SETFD, 1);
  1019.       fcntl (my_write[1], F_SETFD, 1);
  1020. #endif
  1021. #if defined(G_OS_WIN32) || defined (G_WITH_CYGWIN) || defined(__EMX__)
  1022.       plug_in->pid = xspawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
  1023.       if (plug_in->pid == -1)
  1024. #else
  1025.       plug_in->pid = fork ();
  1026.  
  1027.       if (plug_in->pid == 0)
  1028.     {
  1029.       g_io_channel_close (plug_in->my_read);
  1030.       g_io_channel_unref (plug_in->my_read);
  1031.       plug_in->my_read  = NULL;
  1032.       g_io_channel_close (plug_in->my_write);
  1033.       g_io_channel_unref (plug_in->my_write);
  1034.       plug_in->my_write  = NULL;
  1035.  
  1036.           /* Execute the filter. The "_exit" call should never
  1037.            *  be reached, unless some strange error condition
  1038.            *  exists.
  1039.            */
  1040.           execvp (plug_in->args[0], plug_in->args);
  1041.           _exit (1);
  1042.     }
  1043.       else if (plug_in->pid == -1)
  1044. #endif
  1045.     {
  1046.           g_message ("fork() failed: Unable to run Plug-In: \"%s\"\n(%s)",
  1047.              g_basename (plug_in->args[0]), plug_in->args[0]);
  1048.           plug_in_destroy (plug_in);
  1049.           return FALSE;
  1050.     }
  1051.  
  1052.       g_io_channel_close (plug_in->his_read);
  1053.       g_io_channel_unref (plug_in->his_read);
  1054.       plug_in->his_read  = NULL;
  1055.       g_io_channel_close (plug_in->his_write);
  1056.       g_io_channel_unref (plug_in->his_write);
  1057.       plug_in->his_write = NULL;
  1058.  
  1059.       if (!plug_in->synchronous)
  1060.     {
  1061.       plug_in->input_id =
  1062.         g_io_add_watch (plug_in->my_read,
  1063.                 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
  1064.                 plug_in_recv_message,
  1065.                 plug_in);
  1066.  
  1067.       open_plug_ins = g_slist_prepend (open_plug_ins, plug_in);
  1068.     }
  1069.  
  1070.       plug_in->open = TRUE;
  1071.       return TRUE;
  1072.     }
  1073.  
  1074.   return FALSE;
  1075. }
  1076.  
  1077. void
  1078. plug_in_close (PlugIn   *plug_in,
  1079.            gboolean  kill_it)
  1080. {
  1081.   gint status;
  1082. #ifndef G_OS_WIN32
  1083.   struct timeval tv;
  1084. #endif
  1085.  
  1086.   if (plug_in && plug_in->open)
  1087.     {
  1088.       plug_in->open = FALSE;
  1089.  
  1090.       /* Ask the filter to exit gracefully
  1091.        */
  1092.       if (kill_it && plug_in->pid)
  1093.     {
  1094.       plug_in_push (plug_in);
  1095.       gp_quit_write (current_writechannel);
  1096.       plug_in_pop ();
  1097.  
  1098.       /*  give the plug-in some time (10 ms)  */
  1099. #ifndef G_OS_WIN32
  1100.       tv.tv_sec = 0;
  1101.       tv.tv_usec = 100;    /* But this is 0.1 ms? */
  1102.       select (0, NULL, NULL, NULL, &tv);
  1103. #else
  1104.       Sleep (10);
  1105. #endif
  1106.     }
  1107.  
  1108.       /* If necessary, kill the filter. */
  1109. #ifndef G_OS_WIN32
  1110.       if (kill_it && plug_in->pid)
  1111.     status = kill (plug_in->pid, SIGKILL);
  1112.  
  1113.       /* Wait for the process to exit. This will happen
  1114.        *  immediately if it was just killed.
  1115.        */
  1116.       if (plug_in->pid)
  1117.         waitpid (plug_in->pid, &status, 0);
  1118. #else
  1119.       if (kill_it && plug_in->pid)
  1120.     {
  1121.       /* Trying to avoid TerminateProcess (does mostly work).
  1122.        * Otherwise some of our needed DLLs may get into an unstable state
  1123.        * (see Win32 API docs).
  1124.        */
  1125.       DWORD dwExitCode = STILL_ACTIVE;
  1126.       DWORD dwTries  = 10;
  1127.       while ((STILL_ACTIVE == dwExitCode)
  1128.          && GetExitCodeProcess((HANDLE) plug_in->pid, &dwExitCode)
  1129.          && (dwTries > 0))
  1130.         {
  1131.           Sleep(10);
  1132.           dwTries--;
  1133.         }
  1134.       if (STILL_ACTIVE == dwExitCode)
  1135.         {
  1136.           g_warning("Terminating %s ...", plug_in->args[0]);
  1137.           TerminateProcess ((HANDLE) plug_in->pid, 0);
  1138.         }
  1139.     }
  1140. #endif
  1141.  
  1142.       /* Remove the input handler. */
  1143.       if (plug_in->input_id)
  1144.         gdk_input_remove (plug_in->input_id);
  1145.  
  1146.       /* Close the pipes. */
  1147.       if (plug_in->my_read != NULL)
  1148.     {
  1149.       g_io_channel_close (plug_in->my_read);
  1150.       g_io_channel_unref (plug_in->my_read);
  1151.       plug_in->my_read = NULL;
  1152.     }
  1153.       if (plug_in->my_write != NULL)
  1154.     {
  1155.       g_io_channel_close (plug_in->my_write);
  1156.       g_io_channel_unref (plug_in->my_write);
  1157.       plug_in->my_write = NULL;
  1158.     }
  1159.       if (plug_in->his_read != NULL)
  1160.     {
  1161.       g_io_channel_close (plug_in->his_read);
  1162.       g_io_channel_unref (plug_in->his_read);
  1163.       plug_in->his_read = NULL;
  1164.     }
  1165.       if (plug_in->his_write != NULL)
  1166.     {
  1167.       g_io_channel_close (plug_in->his_write);
  1168.       g_io_channel_unref (plug_in->his_write);
  1169.       plug_in->his_write = NULL;
  1170.     }
  1171.  
  1172.       wire_clear_error ();
  1173.  
  1174.       /* Destroy the progress dialog if it exists. */
  1175.       if (plug_in->progress)
  1176.     progress_end (plug_in->progress);
  1177.       plug_in->progress = NULL;
  1178.  
  1179.       /* Set the fields to null values. */
  1180.       plug_in->pid = 0;
  1181.       plug_in->input_id = 0;
  1182.       plug_in->my_read = NULL;
  1183.       plug_in->my_write = NULL;
  1184.       plug_in->his_read = NULL;
  1185.       plug_in->his_write = NULL;
  1186.  
  1187.       if (plug_in->recurse)
  1188.     gtk_main_quit ();
  1189.  
  1190.       plug_in->synchronous = FALSE;
  1191.       plug_in->recurse     = FALSE;
  1192.  
  1193.       /* Unregister any temporary procedures. */
  1194.       if (plug_in->temp_proc_defs)
  1195.     {
  1196.       GSList        *list;
  1197.       PlugInProcDef *proc_def;
  1198.  
  1199.       for (list = plug_in->temp_proc_defs; list; list = g_slist_next (list))
  1200.         {
  1201.           proc_def = (PlugInProcDef *) list->data;
  1202.           plug_in_proc_def_remove (proc_def);
  1203.         }
  1204.  
  1205.       g_slist_free (plug_in->temp_proc_defs);
  1206.       plug_in->temp_proc_defs = NULL;
  1207.     }
  1208.  
  1209.       /* Close any dialogs that this plugin might have opened */
  1210.       brushes_check_dialogs ();
  1211.       patterns_check_dialogs ();
  1212.       gradients_check_dialogs ();
  1213.  
  1214.       open_plug_ins = g_slist_remove (open_plug_ins, plug_in);
  1215.     }
  1216. }
  1217.  
  1218. static Argument *
  1219. plug_in_get_current_return_vals (ProcRecord *proc_rec)
  1220. {
  1221.   Argument *return_vals;
  1222.   gint      nargs;
  1223.  
  1224.   /* Return the status code plus the current return values. */
  1225.   nargs = proc_rec->num_values + 1;
  1226.   if (current_return_vals && current_return_nvals == nargs)
  1227.     {
  1228.       return_vals = current_return_vals;
  1229.     }
  1230.   else if (current_return_vals)
  1231.     {
  1232.       /* Allocate new return values of the correct size. */
  1233.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  1234.  
  1235.       /* Copy all of the arguments we can. */
  1236.       memcpy (return_vals, current_return_vals,
  1237.           sizeof (Argument) * MIN (current_return_nvals, nargs));
  1238.  
  1239.       /* Free the old argument pointer.  This will cause a memory leak
  1240.      only if there were more values returned than we need (which
  1241.      shouldn't ever happen). */
  1242.       g_free (current_return_vals);
  1243.     }
  1244.   else
  1245.     {
  1246.       /* Just return a dummy set of values. */
  1247.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  1248.     }
  1249.  
  1250.   /* We have consumed any saved values, so clear them. */
  1251.   current_return_nvals = 0;
  1252.   current_return_vals  = NULL;
  1253.  
  1254.   return return_vals;
  1255. }
  1256.  
  1257. Argument *
  1258. plug_in_run (ProcRecord *proc_rec,
  1259.          Argument   *args,
  1260.          gint        argc,
  1261.          gboolean    synchronous,   
  1262.          gboolean    destroy_values,
  1263.          gint        gdisp_ID)
  1264. {
  1265.   GPConfig   config;
  1266.   GPProcRun  proc_run;
  1267.   Argument  *return_vals;
  1268.   PlugIn    *plug_in;
  1269.  
  1270.   return_vals = NULL;
  1271.  
  1272.   if (proc_rec->proc_type == PDB_TEMPORARY)
  1273.     {
  1274.       return_vals = plug_in_temp_run (proc_rec, args, argc);
  1275.       goto done;
  1276.     }
  1277.  
  1278.   plug_in = plug_in_new (proc_rec->exec_method.plug_in.filename);
  1279.  
  1280.   if (plug_in)
  1281.     {
  1282.       if (plug_in_open (plug_in))
  1283.     {
  1284.       plug_in->recurse = synchronous;
  1285.  
  1286.       plug_in_push (plug_in);
  1287.  
  1288.       config.version      = GP_VERSION;
  1289.       config.tile_width   = TILE_WIDTH;
  1290.       config.tile_height  = TILE_HEIGHT;
  1291.       config.shm_ID       = shm_ID;
  1292.       config.gamma        = gamma_val;
  1293.       config.install_cmap = install_cmap;
  1294.       config.use_xshm     = gdk_get_use_xshm ();
  1295.       config.gdisp_ID     = gdisp_ID;
  1296.  
  1297.       if (gtk_check_version (1, 2, 8))
  1298.         config.min_colors = CLAMP (min_colors, 27, 216);
  1299.       else
  1300.         config.min_colors = CLAMP (min_colors, 27, 256);
  1301.  
  1302.       proc_run.name    = proc_rec->name;
  1303.       proc_run.nparams = argc;
  1304.       proc_run.params  = plug_in_args_to_params (args, argc, FALSE);
  1305.  
  1306.       if (!gp_config_write (current_writechannel, &config) ||
  1307.           !gp_proc_run_write (current_writechannel, &proc_run) ||
  1308.           !wire_flush (current_writechannel))
  1309.         {
  1310.           return_vals = procedural_db_return_args (proc_rec, FALSE);
  1311.           goto done;
  1312.         }
  1313.  
  1314.       plug_in_pop ();
  1315.  
  1316.       plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
  1317.  
  1318.       /*  If this is an automatically installed extension, wait for an
  1319.        *  installation-confirmation message
  1320.        */
  1321.       if ((proc_rec->proc_type == PDB_EXTENSION) &&
  1322.           (proc_rec->num_args == 0))
  1323.         gtk_main ();
  1324.  
  1325.       if (plug_in->recurse)
  1326.         {
  1327.           gtk_main ();
  1328.           return_vals = plug_in_get_current_return_vals (proc_rec);
  1329.         }
  1330.     }
  1331.     }
  1332.  
  1333.  done:
  1334.   if (return_vals && destroy_values)
  1335.     {
  1336.       procedural_db_destroy_args (return_vals, proc_rec->num_values);
  1337.       return_vals = NULL;
  1338.     }
  1339.   return return_vals;
  1340. }
  1341.  
  1342. void
  1343. plug_in_repeat (gboolean with_interface)
  1344. {
  1345.   GDisplay *gdisplay;
  1346.   Argument *args;
  1347.   gint i;
  1348.  
  1349.   if (last_plug_in)
  1350.     {
  1351.       gdisplay = gdisplay_active ();
  1352.       if (!gdisplay) return;
  1353.  
  1354.       /* construct the procedures arguments */
  1355.       args = g_new (Argument, 3);
  1356.  
  1357.       /* initialize the first three argument types */
  1358.       for (i = 0; i < 3; i++)
  1359.     args[i].arg_type = last_plug_in->args[i].arg_type;
  1360.  
  1361.       /* initialize the first three plug-in arguments  */
  1362.       args[0].value.pdb_int = (with_interface ? RUN_INTERACTIVE : RUN_WITH_LAST_VALS);
  1363.       args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  1364.       args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  1365.  
  1366.       /* run the plug-in procedure */
  1367.       plug_in_run (last_plug_in, args, 3, FALSE, TRUE, gdisplay->ID);
  1368.  
  1369.       g_free (args);
  1370.     }
  1371. }
  1372.  
  1373. void
  1374. plug_in_set_menu_sensitivity (GimpImageType type)
  1375. {
  1376.   PlugInProcDef *proc_def;
  1377.   GSList        *tmp;
  1378.   gboolean       sensitive = FALSE;
  1379.  
  1380.   for (tmp = proc_defs; tmp; tmp = g_slist_next (tmp))
  1381.     {
  1382.       proc_def = tmp->data;
  1383.  
  1384.       if (proc_def->image_types_val && proc_def->menu_path)
  1385.     {
  1386.       switch (type)
  1387.         {
  1388.         case RGB_GIMAGE:
  1389.           sensitive = proc_def->image_types_val & PLUG_IN_RGB_IMAGE;
  1390.           break;
  1391.         case RGBA_GIMAGE:
  1392.           sensitive = proc_def->image_types_val & PLUG_IN_RGBA_IMAGE;
  1393.           break;
  1394.         case GRAY_GIMAGE:
  1395.           sensitive = proc_def->image_types_val & PLUG_IN_GRAY_IMAGE;
  1396.           break;
  1397.         case GRAYA_GIMAGE:
  1398.           sensitive = proc_def->image_types_val & PLUG_IN_GRAYA_IMAGE;
  1399.           break;
  1400.         case INDEXED_GIMAGE:
  1401.           sensitive = proc_def->image_types_val & PLUG_IN_INDEXED_IMAGE;
  1402.           break;
  1403.         case INDEXEDA_GIMAGE:
  1404.           sensitive = proc_def->image_types_val & PLUG_IN_INDEXEDA_IMAGE;
  1405.           break;
  1406.         default:
  1407.           sensitive = FALSE;
  1408.           break;
  1409.         }
  1410.  
  1411.       menus_set_sensitive (proc_def->menu_path, sensitive);
  1412.  
  1413.           if (last_plug_in && (last_plug_in == &(proc_def->db_info)))
  1414.         {
  1415.           menus_set_sensitive ("<Image>/Filters/Repeat Last", sensitive);
  1416.           menus_set_sensitive ("<Image>/Filters/Re-Show Last", sensitive);
  1417.         }
  1418.     }
  1419.     }
  1420.  
  1421.   if (!last_plug_in)
  1422.     {
  1423.       menus_set_sensitive ("<Image>/Filters/Repeat Last", FALSE);
  1424.       menus_set_sensitive ("<Image>/Filters/Re-Show Last", FALSE);
  1425.     }
  1426. }
  1427.  
  1428. static gboolean
  1429. plug_in_recv_message (GIOChannel   *channel,
  1430.               GIOCondition  cond,
  1431.               gpointer        data)
  1432. {
  1433.   gboolean got_message = FALSE;
  1434.  
  1435.   if ((PlugIn *) data != current_plug_in)
  1436.     plug_in_push ((PlugIn *) data);
  1437.  
  1438.   if (current_readchannel == NULL)
  1439.     return TRUE;
  1440.  
  1441.   if (cond & (G_IO_IN | G_IO_PRI))
  1442.     {
  1443.       WireMessage msg;
  1444.  
  1445.       memset (&msg, 0, sizeof (WireMessage));
  1446.  
  1447.       if (!wire_read_msg (current_readchannel, &msg))
  1448.     {
  1449.       plug_in_close (current_plug_in, TRUE);
  1450.     }
  1451.       else 
  1452.     {
  1453.       plug_in_handle_message (&msg);
  1454.       wire_destroy (&msg);
  1455.       got_message = TRUE;
  1456.     }
  1457.  
  1458.     }
  1459.  
  1460.   if (cond & (G_IO_ERR | G_IO_HUP))
  1461.     {
  1462.       if (current_plug_in->open)
  1463.     {
  1464.       plug_in_close (current_plug_in, TRUE);
  1465.     }
  1466.     }
  1467.  
  1468.   if (!got_message)
  1469.     g_message (_("Plug-In crashed: \"%s\"\n(%s)\n\n"
  1470.          "The dying Plug-In may have messed up GIMP's internal state.\n"
  1471.          "You may want to save your images and restart GIMP\n"
  1472.          "to be on the safe side."),
  1473.            g_basename (current_plug_in->args[0]),
  1474.            current_plug_in->args[0]);
  1475.  
  1476.   if (!current_plug_in->open)
  1477.     plug_in_destroy (current_plug_in);
  1478.   else
  1479.     plug_in_pop ();
  1480.  
  1481.   return TRUE;
  1482. }
  1483.  
  1484. static void
  1485. plug_in_handle_message (WireMessage *msg)
  1486. {
  1487.   switch (msg->type)
  1488.     {
  1489.     case GP_QUIT:
  1490.       plug_in_handle_quit ();
  1491.       break;
  1492.     case GP_CONFIG:
  1493.       g_warning ("plug_in_handle_message(): "
  1494.          "received a config message (should not happen)");
  1495.       plug_in_close (current_plug_in, TRUE);
  1496.       break;
  1497.     case GP_TILE_REQ:
  1498.       plug_in_handle_tile_req (msg->data);
  1499.       break;
  1500.     case GP_TILE_ACK:
  1501.       g_warning ("plug_in_handle_message(): "
  1502.          "received a tile ack message (should not happen)");
  1503.       plug_in_close (current_plug_in, TRUE);
  1504.       break;
  1505.     case GP_TILE_DATA:
  1506.       g_warning ("plug_in_handle_message(): "
  1507.          "received a tile data message (should not happen)");
  1508.       plug_in_close (current_plug_in, TRUE);
  1509.       break;
  1510.     case GP_PROC_RUN:
  1511.       plug_in_handle_proc_run (msg->data);
  1512.       break;
  1513.     case GP_PROC_RETURN:
  1514.       plug_in_handle_proc_return (msg->data);
  1515.       plug_in_close (current_plug_in, FALSE);
  1516.       break;
  1517.     case GP_TEMP_PROC_RUN:
  1518.       g_warning ("plug_in_handle_message(): "
  1519.          "received a temp proc run message (should not happen)");
  1520.       plug_in_close (current_plug_in, TRUE);
  1521.       break;
  1522.     case GP_TEMP_PROC_RETURN:
  1523.       plug_in_handle_proc_return (msg->data);
  1524.       gtk_main_quit ();
  1525.       break;
  1526.     case GP_PROC_INSTALL:
  1527.       plug_in_handle_proc_install (msg->data);
  1528.       break;
  1529.     case GP_PROC_UNINSTALL:
  1530.       plug_in_handle_proc_uninstall (msg->data);
  1531.       break;
  1532.     case GP_EXTENSION_ACK:
  1533.       gtk_main_quit ();
  1534.       break;
  1535.     }
  1536. }
  1537.  
  1538. static void
  1539. plug_in_handle_quit (void)
  1540. {
  1541.   plug_in_close (current_plug_in, FALSE);
  1542. }
  1543.  
  1544. static void
  1545. plug_in_handle_tile_req (GPTileReq *tile_req)
  1546. {
  1547.   GPTileData   tile_data;
  1548.   GPTileData  *tile_info;
  1549.   WireMessage  msg;
  1550.   TileManager *tm;
  1551.   Tile        *tile;
  1552.  
  1553.   if (tile_req->drawable_ID == -1)
  1554.     {
  1555.       tile_data.drawable_ID = -1;
  1556.       tile_data.tile_num    = 0;
  1557.       tile_data.shadow      = 0;
  1558.       tile_data.bpp         = 0;
  1559.       tile_data.width       = 0;
  1560.       tile_data.height      = 0;
  1561.       tile_data.use_shm     = (shm_ID == -1) ? FALSE : TRUE;
  1562.       tile_data.data        = NULL;
  1563.  
  1564.       if (!gp_tile_data_write (current_writechannel, &tile_data))
  1565.     {
  1566.       g_warning ("plug_in_handle_tile_req: ERROR");
  1567.       plug_in_close (current_plug_in, TRUE);
  1568.       return;
  1569.     }
  1570.  
  1571.       if (!wire_read_msg (current_readchannel, &msg))
  1572.     {
  1573.       g_warning ("plug_in_handle_tile_req: ERROR");
  1574.       plug_in_close (current_plug_in, TRUE);
  1575.       return;
  1576.     }
  1577.  
  1578.       if (msg.type != GP_TILE_DATA)
  1579.     {
  1580.       g_warning ("expected tile data and received: %d", msg.type);
  1581.       plug_in_close (current_plug_in, TRUE);
  1582.       return;
  1583.     }
  1584.  
  1585.       tile_info = msg.data;
  1586.  
  1587.       if (tile_info->shadow)
  1588.     tm = drawable_shadow (drawable_get_ID (tile_info->drawable_ID));
  1589.       else
  1590.     tm = drawable_data (drawable_get_ID (tile_info->drawable_ID));
  1591.  
  1592.       if (!tm)
  1593.     {
  1594.       g_warning ("plug-in requested invalid drawable (killing)");
  1595.       plug_in_close (current_plug_in, TRUE);
  1596.       return;
  1597.     }
  1598.  
  1599.       tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
  1600.       if (!tile)
  1601.     {
  1602.       g_warning ("plug-in requested invalid tile (killing)");
  1603.       plug_in_close (current_plug_in, TRUE);
  1604.       return;
  1605.     }
  1606.  
  1607.       if (tile_data.use_shm)
  1608.     memcpy (tile_data_pointer (tile, 0, 0), shm_addr, tile_size (tile));
  1609.       else
  1610.     memcpy (tile_data_pointer (tile, 0, 0), tile_info->data, tile_size (tile));
  1611.  
  1612.       tile_release (tile, TRUE);
  1613.  
  1614.       wire_destroy (&msg);
  1615.       if (!gp_tile_ack_write (current_writechannel))
  1616.     {
  1617.       g_warning ("plug_in_handle_tile_req: ERROR");
  1618.       plug_in_close (current_plug_in, TRUE);
  1619.       return;
  1620.     }
  1621.     }
  1622.   else
  1623.     {
  1624.       if (tile_req->shadow)
  1625.     tm = drawable_shadow (drawable_get_ID (tile_req->drawable_ID));
  1626.       else
  1627.     tm = drawable_data (drawable_get_ID (tile_req->drawable_ID));
  1628.  
  1629.       if (!tm)
  1630.     {
  1631.       g_warning ("plug-in requested invalid drawable (killing)");
  1632.       plug_in_close (current_plug_in, TRUE);
  1633.       return;
  1634.     }
  1635.  
  1636.       tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
  1637.       if (!tile)
  1638.     {
  1639.       g_warning ("plug-in requested invalid tile (killing)");
  1640.       plug_in_close (current_plug_in, TRUE);
  1641.       return;
  1642.     }
  1643.  
  1644.       tile_data.drawable_ID = tile_req->drawable_ID;
  1645.       tile_data.tile_num    = tile_req->tile_num;
  1646.       tile_data.shadow      = tile_req->shadow;
  1647.       tile_data.bpp         = tile_bpp (tile);
  1648.       tile_data.width       = tile_ewidth (tile);
  1649.       tile_data.height      = tile_eheight (tile);
  1650.       tile_data.use_shm     = (shm_ID == -1) ? FALSE : TRUE;
  1651.  
  1652.       if (tile_data.use_shm)
  1653.     memcpy (shm_addr, tile_data_pointer (tile, 0, 0), tile_size (tile));
  1654.       else
  1655.     tile_data.data = tile_data_pointer (tile, 0, 0);
  1656.  
  1657.       if (!gp_tile_data_write (current_writechannel, &tile_data))
  1658.     {
  1659.       g_message ("plug_in_handle_tile_req: ERROR");
  1660.       plug_in_close (current_plug_in, TRUE);
  1661.       return;
  1662.     }
  1663.  
  1664.       tile_release (tile, FALSE);
  1665.  
  1666.       if (!wire_read_msg (current_readchannel, &msg))
  1667.     {
  1668.       g_message ("plug_in_handle_tile_req: ERROR");
  1669.       plug_in_close (current_plug_in, TRUE);
  1670.       return;
  1671.     }
  1672.  
  1673.       if (msg.type != GP_TILE_ACK)
  1674.     {
  1675.       g_warning ("expected tile ack and received: %d", msg.type);
  1676.       plug_in_close (current_plug_in, TRUE);
  1677.       return;
  1678.     }
  1679.  
  1680.       wire_destroy (&msg);
  1681.     }
  1682. }
  1683.  
  1684. static void
  1685. plug_in_handle_proc_run (GPProcRun *proc_run)
  1686. {
  1687.   GPProcReturn   proc_return;
  1688.   ProcRecord    *proc_rec;
  1689.   Argument      *args;
  1690.   Argument      *return_vals;
  1691.   PlugInBlocked *blocked;
  1692.  
  1693.   args = plug_in_params_to_args (proc_run->params, proc_run->nparams, FALSE);
  1694.   proc_rec = procedural_db_lookup (proc_run->name);
  1695.  
  1696.   if (proc_rec)
  1697.     {
  1698.       return_vals = procedural_db_execute (proc_run->name, args);
  1699.     }
  1700.   else
  1701.     {
  1702.       /*  if the name lookup failed, construct a 
  1703.        *  dummy "executiuon error" return value --Michael
  1704.        */
  1705.       return_vals = g_new (Argument, 1);
  1706.       return_vals[0].arg_type = PDB_STATUS;
  1707.       return_vals[0].value.pdb_int = PDB_EXECUTION_ERROR;
  1708.     }
  1709.  
  1710.   if (return_vals)
  1711.     {
  1712.       proc_return.name = proc_run->name;
  1713.  
  1714.       if (proc_rec)
  1715.     {
  1716.       proc_return.nparams = proc_rec->num_values + 1;
  1717.       proc_return.params = plug_in_args_to_params (return_vals, proc_rec->num_values + 1, FALSE);
  1718.     }
  1719.       else
  1720.     {
  1721.       proc_return.nparams = 1;
  1722.       proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
  1723.     }
  1724.  
  1725.       if (!gp_proc_return_write (current_writechannel, &proc_return))
  1726.     {
  1727.       g_warning ("plug_in_handle_proc_run: ERROR");
  1728.       plug_in_close (current_plug_in, TRUE);
  1729.       return;
  1730.     }
  1731.  
  1732.       plug_in_args_destroy (args, proc_run->nparams, FALSE);
  1733.       plug_in_args_destroy (return_vals, (proc_rec ? (proc_rec->num_values + 1) : 1), TRUE);
  1734.       plug_in_params_destroy (proc_return.params, proc_return.nparams, FALSE);
  1735.     }
  1736.   else
  1737.     {
  1738.       blocked = g_new (PlugInBlocked, 1);
  1739.       blocked->plug_in = current_plug_in;
  1740.       blocked->proc_name = g_strdup (proc_run->name);
  1741.       blocked_plug_ins = g_slist_prepend (blocked_plug_ins, blocked);
  1742.     }
  1743. }
  1744.  
  1745. static void
  1746. plug_in_handle_proc_return (GPProcReturn *proc_return)
  1747. {
  1748.   PlugInBlocked *blocked;
  1749.   GSList        *tmp;
  1750.  
  1751.   if (current_plug_in->recurse)
  1752.     {
  1753.       current_return_vals = plug_in_params_to_args (proc_return->params,
  1754.                             proc_return->nparams,
  1755.                             TRUE);
  1756.       current_return_nvals = proc_return->nparams;
  1757.     }
  1758.   else
  1759.     {
  1760.       tmp = blocked_plug_ins;
  1761.       while (tmp)
  1762.     {
  1763.       blocked = tmp->data;
  1764.       tmp = tmp->next;
  1765.  
  1766.       if (strcmp (blocked->proc_name, proc_return->name) == 0)
  1767.         {
  1768.           plug_in_push (blocked->plug_in);
  1769.           if (!gp_proc_return_write (current_writechannel, proc_return))
  1770.         {
  1771.           g_message ("plug_in_handle_proc_run: ERROR");
  1772.           plug_in_close (current_plug_in, TRUE);
  1773.           return;
  1774.         }
  1775.           plug_in_pop ();
  1776.  
  1777.           blocked_plug_ins = g_slist_remove (blocked_plug_ins, blocked);
  1778.           g_free (blocked->proc_name);
  1779.           g_free (blocked);
  1780.           break;
  1781.         }
  1782.     }
  1783.     }
  1784. }
  1785.  
  1786. static void
  1787. plug_in_handle_proc_install (GPProcInstall *proc_install)
  1788. {
  1789.   PlugInDef       *plug_in_def = NULL;
  1790.   PlugInProcDef   *proc_def;
  1791.   ProcRecord      *proc = NULL;
  1792.   PlugInMenuEntry *menu_entry;
  1793.   GSList          *tmp = NULL;
  1794.   gchar           *prog = NULL;
  1795.   gboolean         add_proc_def;
  1796.   gint i;
  1797.  
  1798.   /*  Argument checking
  1799.    *   --only sanity check arguments when the procedure requests a menu path
  1800.    */
  1801.  
  1802.   if (proc_install->menu_path)
  1803.     {
  1804.       if (strncmp (proc_install->menu_path, "<Toolbox>", 9) == 0)
  1805.     {
  1806.       if ((proc_install->nparams < 1) ||
  1807.           (proc_install->params[0].type != PDB_INT32))
  1808.         {
  1809.           g_message ("Plug-In \"%s\"\n(%s)\n"
  1810.              "attempted to install procedure \"%s\"\n"
  1811.              "which does not take the standard Plug-In args.",
  1812.              g_basename (current_plug_in->args[0]),
  1813.              current_plug_in->args[0],
  1814.              proc_install->name);
  1815.           return;
  1816.         }
  1817.     }
  1818.       else if (strncmp (proc_install->menu_path, "<Image>", 7) == 0)
  1819.     {
  1820.       if ((proc_install->nparams < 3) ||
  1821.           (proc_install->params[0].type != PDB_INT32) ||
  1822.           (proc_install->params[1].type != PDB_IMAGE) ||
  1823.           (proc_install->params[2].type != PDB_DRAWABLE))
  1824.         {
  1825.           g_message ("Plug-In \"%s\"\n(%s)\n"
  1826.              "attempted to install procedure \"%s\"\n"
  1827.              "which does not take the standard Plug-In args.",
  1828.              g_basename (current_plug_in->args[0]),
  1829.              current_plug_in->args[0],
  1830.              proc_install->name);
  1831.           return;
  1832.         }
  1833.     }
  1834.       else if (strncmp (proc_install->menu_path, "<Load>", 6) == 0)
  1835.     {
  1836.       if ((proc_install->nparams < 3) ||
  1837.           (proc_install->params[0].type != PDB_INT32) ||
  1838.           (proc_install->params[1].type != PDB_STRING) ||
  1839.           (proc_install->params[2].type != PDB_STRING))
  1840.         {
  1841.           g_message ("Plug-In \"%s\"\n(%s)\n"
  1842.              "attempted to install procedure \"%s\"\n"
  1843.              "which does not take the standard Plug-In args.",
  1844.              g_basename (current_plug_in->args[0]),
  1845.              current_plug_in->args[0],
  1846.              proc_install->name);
  1847.           return;
  1848.         }
  1849.     }
  1850.       else if (strncmp (proc_install->menu_path, "<Save>", 6) == 0)
  1851.     {
  1852.       if ((proc_install->nparams < 5) ||
  1853.           (proc_install->params[0].type != PDB_INT32) ||
  1854.           (proc_install->params[1].type != PDB_IMAGE) ||
  1855.           (proc_install->params[2].type != PDB_DRAWABLE) ||
  1856.           (proc_install->params[3].type != PDB_STRING) ||
  1857.           (proc_install->params[4].type != PDB_STRING))
  1858.         {
  1859.           g_message ("Plug-In \"%s\"\n(%s)\n"
  1860.              "attempted to install procedure \"%s\"\n"
  1861.              "which does not take the standard Plug-In args.",
  1862.              g_basename (current_plug_in->args[0]),
  1863.              current_plug_in->args[0],
  1864.              proc_install->name);
  1865.           return;
  1866.         }
  1867.     }
  1868.       else
  1869.     {
  1870.       g_message ("Plug-In \"%s\"\n(%s)\n"
  1871.              "attempted to install procedure \"%s\"\n"
  1872.              "in an invalid menu location.\n"
  1873.              "Use either \"<Toolbox>\", \"<Image>\", "
  1874.              "\"<Load>\", or \"<Save>\".",
  1875.              g_basename (current_plug_in->args[0]),
  1876.              current_plug_in->args[0],
  1877.              proc_install->name);
  1878.       return;
  1879.     }
  1880.     }
  1881.  
  1882.   /*  Sanity check for array arguments  */
  1883.  
  1884.   for (i = 1; i < proc_install->nparams; i++) 
  1885.     {
  1886.       if ((proc_install->params[i].type == PDB_INT32ARRAY ||
  1887.        proc_install->params[i].type == PDB_INT8ARRAY ||
  1888.        proc_install->params[i].type == PDB_FLOATARRAY ||
  1889.        proc_install->params[i].type == PDB_STRINGARRAY) &&
  1890.       proc_install->params[i-1].type != PDB_INT32) 
  1891.     {
  1892.       g_message ("Plug-In \"%s\"\n(%s)\n"
  1893.              "attempted to install procedure \"%s\"\n"
  1894.              "which fails to comply with the array parameter\n"
  1895.              "passing standard.  Argument %d is noncompliant.", 
  1896.              g_basename (current_plug_in->args[0]),
  1897.              current_plug_in->args[0],
  1898.              proc_install->name, i);
  1899.       return;
  1900.     }
  1901.     }
  1902.   
  1903.  
  1904.   /*  Initialization  */
  1905.  
  1906.   proc_def = NULL;
  1907.  
  1908.   switch (proc_install->type)
  1909.     {
  1910.     case PDB_PLUGIN:
  1911.     case PDB_EXTENSION:
  1912.       plug_in_def = current_plug_in->user_data;
  1913.       prog = plug_in_def->prog;
  1914.  
  1915.       tmp = plug_in_def->proc_defs;
  1916.       break;
  1917.  
  1918.     case PDB_TEMPORARY:
  1919.       prog = "none";
  1920.  
  1921.       tmp = current_plug_in->temp_proc_defs;
  1922.       break;
  1923.     }
  1924.  
  1925.   while (tmp)
  1926.     {
  1927.       proc_def = tmp->data;
  1928.       tmp = tmp->next;
  1929.  
  1930.       if (strcmp (proc_def->db_info.name, proc_install->name) == 0)
  1931.     {
  1932.       if (proc_install->type == PDB_TEMPORARY)
  1933.         plug_in_proc_def_remove (proc_def);
  1934.       else
  1935.         plug_in_proc_def_destroy (proc_def, TRUE);  /* destroys data_only */ 
  1936.  
  1937.       break;
  1938.     }
  1939.  
  1940.       proc_def = NULL;
  1941.     }
  1942.  
  1943.   add_proc_def = FALSE;
  1944.   if (!proc_def)
  1945.     {
  1946.       add_proc_def = TRUE;
  1947.       proc_def = g_new (PlugInProcDef, 1);
  1948.     }
  1949.  
  1950.   proc_def->prog = g_strdup (prog);
  1951.  
  1952.   proc_def->menu_path       = g_strdup (proc_install->menu_path);
  1953.   proc_def->accelerator     = NULL;
  1954.   proc_def->extensions      = NULL;
  1955.   proc_def->prefixes        = NULL;
  1956.   proc_def->magics          = NULL;
  1957.   proc_def->image_types     = g_strdup (proc_install->image_types);
  1958.   proc_def->image_types_val = plug_in_image_types_parse (proc_def->image_types);
  1959.   /* Install temp one use todays time */
  1960.   proc_def->mtime           = time (NULL);
  1961.  
  1962.   proc = &proc_def->db_info;
  1963.  
  1964.   /*  The procedural database procedure  */
  1965.  
  1966.   proc->name      = g_strdup (proc_install->name);
  1967.   proc->blurb     = g_strdup (proc_install->blurb);
  1968.   proc->help      = g_strdup (proc_install->help);
  1969.   proc->author    = g_strdup (proc_install->author);
  1970.   proc->copyright = g_strdup (proc_install->copyright);
  1971.   proc->date      = g_strdup (proc_install->date);
  1972.   proc->proc_type = proc_install->type;
  1973.  
  1974.   proc->num_args   = proc_install->nparams;
  1975.   proc->num_values = proc_install->nreturn_vals;
  1976.  
  1977.   proc->args   = g_new (ProcArg, proc->num_args);
  1978.   proc->values = g_new (ProcArg, proc->num_values);
  1979.  
  1980.   for (i = 0; i < proc->num_args; i++)
  1981.     {
  1982.       proc->args[i].arg_type    = proc_install->params[i].type;
  1983.       proc->args[i].name        = g_strdup (proc_install->params[i].name);
  1984.       proc->args[i].description = g_strdup (proc_install->params[i].description);
  1985.     }
  1986.  
  1987.   for (i = 0; i < proc->num_values; i++)
  1988.     {
  1989.       proc->values[i].arg_type    = proc_install->return_vals[i].type;
  1990.       proc->values[i].name        = g_strdup (proc_install->return_vals[i].name);
  1991.       proc->values[i].description = g_strdup (proc_install->return_vals[i].description);
  1992.     }
  1993.  
  1994.   switch (proc_install->type)
  1995.     {
  1996.     case PDB_PLUGIN:
  1997.     case PDB_EXTENSION:
  1998.       if (add_proc_def)
  1999.     plug_in_def->proc_defs = g_slist_prepend (plug_in_def->proc_defs, proc_def);
  2000.       break;
  2001.  
  2002.     case PDB_TEMPORARY:
  2003.       if (add_proc_def)
  2004.     current_plug_in->temp_proc_defs = 
  2005.       g_slist_prepend (current_plug_in->temp_proc_defs, proc_def);
  2006.  
  2007.       proc_defs = g_slist_append (proc_defs, proc_def);
  2008.       proc->exec_method.temporary.plug_in = (void *) current_plug_in;
  2009.       procedural_db_register (proc);
  2010.  
  2011.       /*  If there is a menu path specified, create a menu entry  */
  2012.       if (proc_install->menu_path)
  2013.     {
  2014.       menu_entry = g_new (PlugInMenuEntry, 1);
  2015.       menu_entry->proc_def = proc_def;
  2016.  
  2017.       /*  Below we use a hack to allow translations of Script-Fu paths.
  2018.            *  Would be nice if we could solve this properly, but I haven't 
  2019.            *  found a way yet ...  (Sven)
  2020.        */
  2021.       if (plug_in_def && plug_in_def->locale_domain)
  2022.         menu_entry->domain = plug_in_def->locale_domain;
  2023.       else if (strncmp (proc_def->db_info.name, "script_fu", 9) == 0)
  2024.         menu_entry->domain = "gimp-script-fu";
  2025.       else
  2026.         menu_entry->domain = std_plugins_domain;
  2027.  
  2028.       if (plug_in_def)
  2029.         menu_entry->help_path = plug_in_def->help_path;
  2030.       else
  2031.         menu_entry->help_path = NULL;
  2032.  
  2033.       /* plug_in_make_menu_entry frees the menu_entry for us */
  2034.       plug_in_make_menu_entry (NULL, menu_entry, NULL);  
  2035.     }
  2036.       break;
  2037.     }
  2038. }
  2039.  
  2040. static void
  2041. plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
  2042. {
  2043.   PlugInProcDef *proc_def;
  2044.   GSList        *tmp;
  2045.  
  2046.   tmp = current_plug_in->temp_proc_defs;
  2047.   while (tmp)
  2048.     {
  2049.       proc_def = tmp->data;
  2050.       tmp = tmp->next;
  2051.  
  2052.       if (strcmp (proc_def->db_info.name, proc_uninstall->name) == 0)
  2053.     {
  2054.       current_plug_in->temp_proc_defs = g_slist_remove (current_plug_in->temp_proc_defs, proc_def);
  2055.       plug_in_proc_def_remove (proc_def);
  2056.       break;
  2057.     }
  2058.     }
  2059. }
  2060.  
  2061. static gboolean
  2062. plug_in_write (GIOChannel *channel,
  2063.            guint8      *buf,
  2064.            gulong       count)
  2065. {
  2066.   gulong bytes;
  2067.  
  2068.   while (count > 0)
  2069.     {
  2070.       if ((current_write_buffer_index + count) >= WRITE_BUFFER_SIZE)
  2071.     {
  2072.       bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
  2073.       memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
  2074.       current_write_buffer_index += bytes;
  2075.       if (!wire_flush (channel))
  2076.         return FALSE;
  2077.     }
  2078.       else
  2079.     {
  2080.       bytes = count;
  2081.       memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
  2082.       current_write_buffer_index += bytes;
  2083.     }
  2084.  
  2085.       buf += bytes;
  2086.       count -= bytes;
  2087.     }
  2088.  
  2089.   return TRUE;
  2090. }
  2091.  
  2092. static gboolean
  2093. plug_in_flush (GIOChannel *channel)
  2094. {
  2095.   GIOError error;
  2096.   gint     count;
  2097.   guint    bytes;
  2098.  
  2099.   if (current_write_buffer_index > 0)
  2100.     {
  2101.       count = 0;
  2102.       while (count != current_write_buffer_index)
  2103.         {
  2104.       do {
  2105.         bytes = 0;
  2106.         error = g_io_channel_write (channel, ¤t_write_buffer[count],
  2107.                     (current_write_buffer_index - count),
  2108.                     &bytes);
  2109.       } while (error == G_IO_ERROR_AGAIN);
  2110.  
  2111.       if (error != G_IO_ERROR_NONE)
  2112.         return FALSE;
  2113.  
  2114.           count += bytes;
  2115.         }
  2116.  
  2117.       current_write_buffer_index = 0;
  2118.     }
  2119.  
  2120.   return TRUE;
  2121. }
  2122.  
  2123. static void
  2124. plug_in_push (PlugIn *plug_in)
  2125. {
  2126.   if (plug_in)
  2127.     {
  2128.       current_plug_in = plug_in;
  2129.       plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
  2130.  
  2131.       current_readchannel        = current_plug_in->my_read;
  2132.       current_writechannel       = current_plug_in->my_write;
  2133.       current_write_buffer_index = current_plug_in->write_buffer_index;
  2134.       current_write_buffer       = current_plug_in->write_buffer;
  2135.     }
  2136.   else
  2137.     {
  2138.       current_readchannel        = NULL;
  2139.       current_writechannel       = NULL;
  2140.       current_write_buffer_index = 0;
  2141.       current_write_buffer       = NULL;
  2142.     }
  2143. }
  2144.  
  2145. static void
  2146. plug_in_pop (void)
  2147. {
  2148.   GSList *tmp;
  2149.  
  2150.   if (current_plug_in)
  2151.     {
  2152.       current_plug_in->write_buffer_index = current_write_buffer_index;
  2153.  
  2154.       tmp = plug_in_stack;
  2155.       plug_in_stack = plug_in_stack->next;
  2156.       tmp->next = NULL;
  2157.       g_slist_free (tmp);
  2158.     }
  2159.  
  2160.   if (plug_in_stack)
  2161.     {
  2162.       current_plug_in            = plug_in_stack->data;
  2163.       current_readchannel        = current_plug_in->my_read;
  2164.       current_writechannel       = current_plug_in->my_write;
  2165.       current_write_buffer_index = current_plug_in->write_buffer_index;
  2166.       current_write_buffer       = current_plug_in->write_buffer;
  2167.     }
  2168.   else
  2169.     {
  2170.       current_plug_in            = NULL;
  2171.       current_readchannel        = NULL;
  2172.       current_writechannel       = NULL;
  2173.       current_write_buffer_index = 0;
  2174.       current_write_buffer        = NULL;
  2175.     }
  2176. }
  2177.  
  2178. static void
  2179. plug_in_write_rc_string (FILE  *fp,
  2180.              gchar *str)
  2181. {
  2182.   fputc ('"', fp);
  2183.  
  2184.   if (str)
  2185.     while (*str)
  2186.       {
  2187.     if (*str == '\n')
  2188.       {
  2189.         fputc ('\\', fp);
  2190.         fputc ('n', fp);
  2191.       }
  2192.     else if (*str == '\r')
  2193.       {
  2194.         fputc ('\\', fp);
  2195.         fputc ('r', fp);
  2196.       }
  2197.     else if (*str == '\032') /* ^Z is problematic on Windows */
  2198.       {
  2199.         fputc ('\\', fp);
  2200.         fputc ('z', fp);
  2201.       }
  2202.     else
  2203.       {
  2204.         if ((*str == '"') || (*str == '\\'))
  2205.           fputc ('\\', fp);
  2206.         fputc (*str, fp);
  2207.       }
  2208.     str += 1;
  2209.       }
  2210.  
  2211.   fputc ('"', fp);
  2212. }
  2213.  
  2214. static void
  2215. plug_in_write_rc (gchar *filename)
  2216. {
  2217.   FILE          *fp;
  2218.   PlugInDef     *plug_in_def;
  2219.   PlugInProcDef *proc_def;
  2220.   GSList        *tmp;
  2221.   GSList        *tmp2;
  2222.   gint i;
  2223.  
  2224.   fp = fopen (filename, "w");
  2225.   if (!fp)
  2226.     return;
  2227.  
  2228.   tmp = plug_in_defs;
  2229.   while (tmp)
  2230.     {
  2231.       plug_in_def = tmp->data;
  2232.       tmp = tmp->next;
  2233.  
  2234.       if (plug_in_def->proc_defs)
  2235.     {
  2236.       fprintf (fp, "(plug-in-def ");
  2237.       plug_in_write_rc_string (fp, plug_in_def->prog);
  2238.       fprintf (fp, " %ld", (long) plug_in_def->mtime);
  2239.       tmp2 = plug_in_def->proc_defs;
  2240.       if (tmp2)
  2241.         fprintf (fp, "\n");
  2242.  
  2243.       while (tmp2)
  2244.         {
  2245.           proc_def = tmp2->data;
  2246.           tmp2 = tmp2->next;
  2247.  
  2248.           fprintf (fp, "\t(proc-def \"%s\" %d\n",
  2249.                proc_def->db_info.name, proc_def->db_info.proc_type);
  2250.           fprintf (fp, "\t\t");
  2251.           plug_in_write_rc_string (fp, proc_def->db_info.blurb);
  2252.           fprintf (fp, "\n\t\t");
  2253.           plug_in_write_rc_string (fp, proc_def->db_info.help);
  2254.           fprintf (fp, "\n\t\t");
  2255.           plug_in_write_rc_string (fp, proc_def->db_info.author);
  2256.           fprintf (fp, "\n\t\t");
  2257.           plug_in_write_rc_string (fp, proc_def->db_info.copyright);
  2258.           fprintf (fp, "\n\t\t");
  2259.           plug_in_write_rc_string (fp, proc_def->db_info.date);
  2260.           fprintf (fp, "\n\t\t");
  2261.           plug_in_write_rc_string (fp, proc_def->menu_path);
  2262.           fprintf (fp, "\n\t\t");
  2263.           plug_in_write_rc_string (fp, proc_def->extensions);
  2264.           fprintf (fp, "\n\t\t");
  2265.           plug_in_write_rc_string (fp, proc_def->prefixes);
  2266.           fprintf (fp, "\n\t\t");
  2267.           plug_in_write_rc_string (fp, proc_def->magics);
  2268.           fprintf (fp, "\n\t\t");
  2269.           plug_in_write_rc_string (fp, proc_def->image_types);
  2270.           fprintf (fp, "\n\t\t%d %d\n",
  2271.                proc_def->db_info.num_args, proc_def->db_info.num_values);
  2272.  
  2273.           for (i = 0; i < proc_def->db_info.num_args; i++)
  2274.         {
  2275.           fprintf (fp, "\t\t(proc-arg %d ",
  2276.                proc_def->db_info.args[i].arg_type);
  2277.  
  2278.           plug_in_write_rc_string (fp, proc_def->db_info.args[i].name);
  2279.           plug_in_write_rc_string (fp, proc_def->db_info.args[i].description);
  2280.  
  2281.           fprintf (fp, ")%s",
  2282.                (proc_def->db_info.num_values ||
  2283.                 (i < (proc_def->db_info.num_args - 1))) ? "\n" : "");
  2284.         }
  2285.  
  2286.           for (i = 0; i < proc_def->db_info.num_values; i++)
  2287.         {
  2288.           fprintf (fp, "\t\t(proc-arg %d ",
  2289.                proc_def->db_info.values[i].arg_type);
  2290.  
  2291.           plug_in_write_rc_string (fp, proc_def->db_info.values[i].name);
  2292.           plug_in_write_rc_string (fp, proc_def->db_info.values[i].description);
  2293.  
  2294.           fprintf (fp, ")%s", (i < (proc_def->db_info.num_values - 1)) ? "\n" : "");
  2295.         }
  2296.  
  2297.           fprintf (fp, ")");
  2298.  
  2299.           if (tmp2)
  2300.         fprintf (fp, "\n");
  2301.         }
  2302.       
  2303.       if (plug_in_def->locale_domain)
  2304.         {
  2305.           fprintf (fp, "\n\t(locale-def \"%s\"", plug_in_def->locale_domain);
  2306.           if (plug_in_def->locale_path)
  2307.         fprintf (fp, " \"%s\")", plug_in_def->locale_path);
  2308.           else
  2309.         fprintf (fp, ")");
  2310.         }
  2311.  
  2312.       if (plug_in_def->help_path)
  2313.         {
  2314.           fprintf (fp, "\n\t(help-def \"%s\")", plug_in_def->help_path);
  2315.         }
  2316.  
  2317.       fprintf (fp, ")\n");
  2318.  
  2319.       if (tmp)
  2320.         fprintf (fp, "\n");
  2321.     }
  2322.       
  2323.     }
  2324.  
  2325.   fclose (fp);
  2326. }
  2327.  
  2328. static void
  2329. plug_in_init_file (gchar *filename)
  2330. {
  2331.   GSList    *tmp;
  2332.   PlugInDef *plug_in_def;
  2333.   gchar     *plug_in_name;
  2334.   gchar     *name;
  2335.  
  2336.   name = g_basename (filename);
  2337.  
  2338.   plug_in_def = NULL;
  2339.   tmp = plug_in_defs;
  2340.  
  2341.   while (tmp)
  2342.     {
  2343.       plug_in_def = tmp->data;
  2344.       tmp = tmp->next;
  2345.  
  2346.       plug_in_name = g_basename (plug_in_def->prog);
  2347.  
  2348.       if (g_strcasecmp (name, plug_in_name) == 0)
  2349.     {
  2350.       g_print ("duplicate plug-in: \"%s\" (skipping)\n", filename);
  2351.       return;
  2352.     }
  2353.  
  2354.       plug_in_def = NULL;
  2355.     }
  2356.  
  2357.   plug_in_def = plug_in_def_new (filename);
  2358.   plug_in_def->mtime = datafile_mtime ();
  2359.   plug_in_def->query = TRUE;
  2360.  
  2361.   plug_in_defs = g_slist_append (plug_in_defs, plug_in_def);
  2362. }
  2363.  
  2364. static void
  2365. plug_in_query (PlugInDef *plug_in_def)
  2366. {
  2367.   PlugIn      *plug_in;
  2368.   WireMessage  msg;
  2369.  
  2370.   plug_in = plug_in_new (plug_in_def->prog);
  2371.   if (plug_in)
  2372.     {
  2373.       plug_in->query       = TRUE;
  2374.       plug_in->synchronous = TRUE;
  2375.       plug_in->user_data   = plug_in_def;
  2376.  
  2377.       if (plug_in_open (plug_in))
  2378.     {
  2379.       plug_in_push (plug_in);
  2380.  
  2381.       while (plug_in->open)
  2382.         {
  2383.           if (!wire_read_msg (current_readchannel, &msg))
  2384.         plug_in_close (current_plug_in, TRUE);
  2385.           else 
  2386.         {
  2387.           plug_in_handle_message (&msg);
  2388.           wire_destroy (&msg);
  2389.         }
  2390.         }
  2391.  
  2392.       plug_in_pop ();
  2393.       plug_in_destroy (plug_in);
  2394.     }
  2395.     }
  2396. }
  2397.  
  2398. static void
  2399. plug_in_add_to_db (void)
  2400. {
  2401.   PlugInProcDef *proc_def;
  2402.   Argument       args[4];
  2403.   Argument      *return_vals;
  2404.   GSList        *tmp;
  2405.  
  2406.   tmp = proc_defs;
  2407.  
  2408.   while (tmp)
  2409.     {
  2410.       proc_def = tmp->data;
  2411.       tmp = tmp->next;
  2412.  
  2413.       if (proc_def->prog && (proc_def->db_info.proc_type != PDB_INTERNAL))
  2414.     {
  2415.       proc_def->db_info.exec_method.plug_in.filename = proc_def->prog;
  2416.       procedural_db_register (&proc_def->db_info);
  2417.     }
  2418.     }
  2419.  
  2420.   for (tmp = proc_defs; tmp; tmp = tmp->next)
  2421.     {
  2422.       proc_def = tmp->data;
  2423.  
  2424.       if (proc_def->extensions || proc_def->prefixes || proc_def->magics)
  2425.         {
  2426.           args[0].arg_type          = PDB_STRING;
  2427.           args[0].value.pdb_pointer = proc_def->db_info.name;
  2428.  
  2429.           args[1].arg_type          = PDB_STRING;
  2430.           args[1].value.pdb_pointer = proc_def->extensions;
  2431.  
  2432.       args[2].arg_type          = PDB_STRING;
  2433.       args[2].value.pdb_pointer = proc_def->prefixes;
  2434.  
  2435.       args[3].arg_type          = PDB_STRING;
  2436.       args[3].value.pdb_pointer = proc_def->magics;
  2437.  
  2438.           if (proc_def->image_types)
  2439.             {
  2440.               return_vals = procedural_db_execute ("gimp_register_save_handler", args);
  2441.               g_free (return_vals);
  2442.             }
  2443.           else
  2444.             {
  2445.               return_vals = procedural_db_execute ("gimp_register_magic_load_handler", args);
  2446.               g_free (return_vals);
  2447.             }
  2448.     }
  2449.     }
  2450. }
  2451.  
  2452. /*  The following function has to be a GTraverseFunction, 
  2453.  *  but is also called directly. Please note that it frees the
  2454.  *  menu_entry strcuture.                --Sven 
  2455.  */ 
  2456. static gint
  2457. plug_in_make_menu_entry (gpointer         foo,
  2458.              PlugInMenuEntry *menu_entry,
  2459.              gpointer         bar)
  2460. {
  2461.   GimpItemFactoryEntry  entry;
  2462.   gchar                *help_page;
  2463.   
  2464.   if (menu_entry->help_path)
  2465.     {
  2466.       help_page = g_strconcat (menu_entry->help_path,
  2467.                    "@",   /* HACK: locale subdir */
  2468.                    g_basename (menu_entry->proc_def->prog),
  2469.                    ".html",
  2470.                    NULL);
  2471.     }
  2472.   else
  2473.     {
  2474.       help_page = g_strconcat ("filters/",  /* _not_ G_DIR_SEPARATOR_S */
  2475.                    g_basename (menu_entry->proc_def->prog),
  2476.                    ".html",
  2477.                    NULL);
  2478.     }
  2479.  
  2480.   g_strdown (help_page);
  2481.   
  2482.   entry.entry.path            = menu_entry->proc_def->menu_path;
  2483.   entry.entry.accelerator     = menu_entry->proc_def->accelerator;
  2484.   entry.entry.callback        = plug_in_callback;
  2485.   entry.entry.callback_action = 0;
  2486.   entry.entry.item_type       = NULL;
  2487.   entry.help_page             = help_page;
  2488.   entry.description           = NULL;
  2489.  
  2490.   menus_create_item_from_full_path (&entry, 
  2491.                     menu_entry->domain, 
  2492.                     &menu_entry->proc_def->db_info);
  2493.   g_free (menu_entry);
  2494.   
  2495.   return FALSE;
  2496. }
  2497.  
  2498. static void
  2499. plug_in_make_menu (void)
  2500. {
  2501.   PlugInDef       *plug_in_def;
  2502.   PlugInProcDef   *proc_def;
  2503.   PlugInMenuEntry *menu_entry;
  2504.   GSList *domains = NULL;
  2505.   GSList *procs;
  2506.   GSList *tmp;
  2507.   GTree  *menu_entries;
  2508.  
  2509. #ifdef ENABLE_NLS
  2510.   bindtextdomain (std_plugins_domain, LOCALEDIR);
  2511.   domains = g_slist_append (domains, std_plugins_domain);
  2512. #endif
  2513.  
  2514. #ifdef ENABLE_NLS
  2515.   menu_entries = g_tree_new ((GCompareFunc)strcoll);
  2516. #else
  2517.   menu_entries = g_tree_new ((GCompareFunc)strcmp);
  2518. #endif
  2519.  
  2520.   tmp = plug_in_defs;
  2521.   while (tmp)
  2522.     {
  2523.       plug_in_def = tmp->data;
  2524.       tmp = tmp->next;
  2525.  
  2526.       procs = plug_in_def->proc_defs;
  2527.  
  2528.       if (!procs)
  2529.     continue;
  2530.  
  2531. #ifdef ENABLE_NLS
  2532.       {
  2533.     gchar    *domain;
  2534.     GSList   *list;
  2535.     gboolean  found = FALSE;
  2536.  
  2537.     if (plug_in_def->locale_domain)
  2538.       {
  2539.         domain = plug_in_def->locale_domain;
  2540.         for (list = domains; list && !found; list = list->next)
  2541.           {
  2542.         if (strcmp (domain, (gchar*)(list->data)) == 0)
  2543.           found = TRUE;
  2544.           }
  2545.         if (!found)
  2546.           {
  2547.         domains = g_slist_append (domains, domain);
  2548.         if (plug_in_def->locale_path)
  2549.           bindtextdomain (domain, plug_in_def->locale_path);
  2550.         else
  2551.           bindtextdomain (domain, LOCALEDIR);
  2552.           }
  2553.       }
  2554.       }
  2555. #endif  /*  ENABLE_NLS  */
  2556.  
  2557.       while (procs)
  2558.     {
  2559.       proc_def = procs->data;
  2560.       procs = procs->next;
  2561.  
  2562.       if (proc_def->prog && proc_def->menu_path && (!proc_def->extensions &&
  2563.                             !proc_def->prefixes &&
  2564.                             !proc_def->magics))
  2565.         {
  2566.           menu_entry = g_new (PlugInMenuEntry, 1);
  2567.           menu_entry->proc_def = proc_def;
  2568.           menu_entry->domain   = plug_in_def->locale_domain ? 
  2569.         plug_in_def->locale_domain : std_plugins_domain;
  2570.           menu_entry->help_path = plug_in_def->help_path;
  2571.  
  2572.           g_tree_insert (menu_entries, 
  2573.                  dgettext (menu_entry->domain, proc_def->menu_path),
  2574.                  menu_entry);
  2575.         }
  2576.     }
  2577.     }
  2578.  
  2579.   g_tree_traverse (menu_entries, 
  2580.            (GTraverseFunc)plug_in_make_menu_entry, G_IN_ORDER, NULL);
  2581.   g_tree_destroy (menu_entries);
  2582.  
  2583.   g_slist_free (domains);
  2584. }
  2585.  
  2586.  
  2587. static void
  2588. plug_in_callback (GtkWidget *widget,
  2589.           gpointer   client_data)
  2590. {
  2591.   GDisplay   *gdisplay;
  2592.   ProcRecord *proc_rec;
  2593.   Argument   *args;
  2594.   gint i;
  2595.   gint gdisp_ID = -1;
  2596.   gint argc = 0; /* calm down a gcc warning.  */
  2597.  
  2598.   /* get the active gdisplay */
  2599.   gdisplay = gdisplay_active ();
  2600.  
  2601.   proc_rec = (ProcRecord *) client_data;
  2602.  
  2603.   /* construct the procedures arguments */
  2604.   args = g_new0 (Argument, proc_rec->num_args);
  2605.  
  2606.   /* initialize the argument types */
  2607.   for (i = 0; i < proc_rec->num_args; i++)
  2608.     args[i].arg_type = proc_rec->args[i].arg_type;
  2609.  
  2610.   switch (proc_rec->proc_type)
  2611.     {
  2612.     case PDB_EXTENSION:
  2613.       /* initialize the first argument  */
  2614.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2615.       argc = 1;
  2616.       break;
  2617.  
  2618.     case PDB_PLUGIN:
  2619.       if (gdisplay)
  2620.     {
  2621.       gdisp_ID = gdisplay->ID;
  2622.  
  2623.       /* initialize the first 3 plug-in arguments  */
  2624.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2625.       args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  2626.       args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  2627.       argc = 3;
  2628.     }
  2629.       else
  2630.     {
  2631.       g_warning ("Uh-oh, no active gdisplay for the plug-in!");
  2632.       g_free (args);
  2633.       return;
  2634.     }
  2635.       break;
  2636.  
  2637.     case PDB_TEMPORARY:
  2638.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2639.       argc = 1;
  2640.       if (proc_rec->num_args >= 3 &&
  2641.       proc_rec->args[1].arg_type == PDB_IMAGE &&
  2642.       proc_rec->args[2].arg_type == PDB_DRAWABLE)
  2643.     {
  2644.       if (gdisplay)
  2645.         {
  2646.           gdisp_ID = gdisplay->ID;
  2647.  
  2648.           args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  2649.           args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  2650.           argc = 3;
  2651.         }
  2652.       else
  2653.         {
  2654.           g_warning ("Uh-oh, no active gdisplay for the temporary procedure!");
  2655.           g_free (args);
  2656.           return;
  2657.         }
  2658.     }
  2659.       break;
  2660.  
  2661.     default:
  2662.       g_error ("Unknown procedure type.");
  2663.       g_free (args);
  2664.       return;
  2665.     }
  2666.  
  2667.   /* run the plug-in procedure */
  2668.   plug_in_run (proc_rec, args, argc, FALSE, TRUE, gdisp_ID);
  2669.  
  2670.   if (proc_rec->proc_type == PDB_PLUGIN)
  2671.     last_plug_in = proc_rec;
  2672.  
  2673.   g_free (args);
  2674. }
  2675.  
  2676. static void
  2677. plug_in_proc_def_insert (PlugInProcDef *proc_def,
  2678.              void (*superceed_fn)(void*))
  2679. {
  2680.   PlugInProcDef *tmp_proc_def;
  2681.   GSList *tmp;
  2682.   GSList *prev;
  2683.   GSList *list;
  2684.  
  2685.   prev = NULL;
  2686.   tmp  = proc_defs;
  2687.  
  2688.   while (tmp)
  2689.     {
  2690.       tmp_proc_def = tmp->data;
  2691.  
  2692.       if (strcmp (proc_def->db_info.name, tmp_proc_def->db_info.name) == 0)
  2693.     {
  2694.       tmp->data = proc_def;
  2695.  
  2696.       if (proc_def->menu_path)
  2697.         g_free (proc_def->menu_path);
  2698.       if (proc_def->accelerator)
  2699.         g_free (proc_def->accelerator);
  2700.  
  2701.       proc_def->menu_path   = tmp_proc_def->menu_path;
  2702.       proc_def->accelerator = tmp_proc_def->accelerator;
  2703.  
  2704.       tmp_proc_def->menu_path   = NULL;
  2705.       tmp_proc_def->accelerator = NULL;
  2706.  
  2707.       if (superceed_fn)
  2708.         (* superceed_fn) (tmp_proc_def);
  2709.  
  2710.       plug_in_proc_def_destroy (tmp_proc_def, FALSE);
  2711.       return;
  2712.     }
  2713.       else if (!proc_def->menu_path ||
  2714.            (tmp_proc_def->menu_path &&
  2715.         (strcmp (proc_def->menu_path, tmp_proc_def->menu_path) < 0)))
  2716.     {
  2717.       list = g_slist_alloc ();
  2718.       list->data = proc_def;
  2719.  
  2720.       list->next = tmp;
  2721.       if (prev)
  2722.         prev->next = list;
  2723.       else
  2724.         proc_defs = list;
  2725.       return;
  2726.     }
  2727.  
  2728.       prev = tmp;
  2729.       tmp = tmp->next;
  2730.     }
  2731.  
  2732.   proc_defs = g_slist_append (proc_defs, proc_def);
  2733. }
  2734.  
  2735. /* called when plug_in_proc_def_insert causes a proc_def to be
  2736.  * overridden and thus g_free()d.
  2737.  */
  2738. static void
  2739. plug_in_proc_def_dead (void *freed_proc_def)
  2740. {
  2741.   GSList        *tmp;
  2742.   PlugInDef     *plug_in_def;
  2743.   PlugInProcDef *proc_def = freed_proc_def;
  2744.  
  2745.   g_warning ("removing duplicate PDB procedure \"%s\"",
  2746.          proc_def->db_info.name);
  2747.  
  2748.   /* search the plugin list to see if any plugins had references to 
  2749.    * the recently freed proc_def.
  2750.    */
  2751.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  2752.     {
  2753.       plug_in_def = tmp->data;
  2754.  
  2755.       plug_in_def->proc_defs = g_slist_remove (plug_in_def->proc_defs,
  2756.                            freed_proc_def);
  2757.     }
  2758. }
  2759.  
  2760. static void
  2761. plug_in_proc_def_remove (PlugInProcDef *proc_def)
  2762. {
  2763.   /*  Destroy the menu item  */
  2764.   if (proc_def->menu_path)
  2765.     menus_destroy (proc_def->menu_path);
  2766.  
  2767.   /*  Unregister the procedural database entry  */
  2768.   procedural_db_unregister (proc_def->db_info.name);
  2769.  
  2770.   /*  Remove the defintion from the global list  */
  2771.   proc_defs = g_slist_remove (proc_defs, proc_def);
  2772.  
  2773.   /*  Destroy the definition  */
  2774.   plug_in_proc_def_destroy (proc_def, TRUE);
  2775. }
  2776.  
  2777. static void
  2778. plug_in_proc_def_destroy (PlugInProcDef *proc_def,
  2779.               gboolean       data_only)
  2780. {
  2781.   gint i;
  2782.  
  2783.   if (proc_def->prog)
  2784.     g_free (proc_def->prog);
  2785.   if (proc_def->menu_path)
  2786.     g_free (proc_def->menu_path);
  2787.   if (proc_def->accelerator)
  2788.     g_free (proc_def->accelerator);
  2789.   if (proc_def->extensions)
  2790.     g_free (proc_def->extensions);
  2791.   if (proc_def->prefixes)
  2792.     g_free (proc_def->prefixes);
  2793.   if (proc_def->magics)
  2794.     g_free (proc_def->magics);
  2795.   if (proc_def->image_types)
  2796.     g_free (proc_def->image_types);
  2797.   if (proc_def->db_info.name)
  2798.     g_free (proc_def->db_info.name);
  2799.   if (proc_def->db_info.blurb)
  2800.     g_free (proc_def->db_info.blurb);
  2801.   if (proc_def->db_info.help)
  2802.     g_free (proc_def->db_info.help);
  2803.   if (proc_def->db_info.author)
  2804.     g_free (proc_def->db_info.author);
  2805.   if (proc_def->db_info.copyright)
  2806.     g_free (proc_def->db_info.copyright);
  2807.   if (proc_def->db_info.date)
  2808.     g_free (proc_def->db_info.date);
  2809.  
  2810.   for (i = 0; i < proc_def->db_info.num_args; i++)
  2811.     {
  2812.       if (proc_def->db_info.args[i].name)
  2813.     g_free (proc_def->db_info.args[i].name);
  2814.       if (proc_def->db_info.args[i].description)
  2815.     g_free (proc_def->db_info.args[i].description);
  2816.     }
  2817.  
  2818.   for (i = 0; i < proc_def->db_info.num_values; i++)
  2819.     {
  2820.       if (proc_def->db_info.values[i].name)
  2821.     g_free (proc_def->db_info.values[i].name);
  2822.       if (proc_def->db_info.values[i].description)
  2823.     g_free (proc_def->db_info.values[i].description);
  2824.     }
  2825.  
  2826.   if (proc_def->db_info.args)
  2827.     g_free (proc_def->db_info.args);
  2828.   if (proc_def->db_info.values)
  2829.     g_free (proc_def->db_info.values);
  2830.  
  2831.   if (!data_only)
  2832.     g_free (proc_def);
  2833. }
  2834.  
  2835. static Argument *
  2836. plug_in_temp_run (ProcRecord *proc_rec,
  2837.           Argument   *args,
  2838.           gint        argc)
  2839. {
  2840.   Argument  *return_vals;
  2841.   PlugIn    *plug_in;
  2842.   GPProcRun  proc_run;
  2843.   gint       old_recurse;
  2844.  
  2845.   return_vals = NULL;
  2846.  
  2847.   plug_in = (PlugIn *) proc_rec->exec_method.temporary.plug_in;
  2848.  
  2849.   if (plug_in)
  2850.     {
  2851.       if (plug_in->busy)
  2852.     {
  2853.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  2854.       goto done;
  2855.     }
  2856.  
  2857.       plug_in->busy = TRUE;
  2858.       plug_in_push (plug_in);
  2859.  
  2860.       proc_run.name    = proc_rec->name;
  2861.       proc_run.nparams = argc;
  2862.       proc_run.params  = plug_in_args_to_params (args, argc, FALSE);
  2863.  
  2864.       if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
  2865.       !wire_flush (current_writechannel))
  2866.     {
  2867.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  2868.       goto done;
  2869.     }
  2870.  
  2871.       plug_in_pop ();
  2872.  
  2873.       plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
  2874.  
  2875.       old_recurse = plug_in->recurse;
  2876.       plug_in->recurse = TRUE;
  2877.  
  2878. /*       gtk_main (); */
  2879.       
  2880. /*       return_vals = plug_in_get_current_return_vals (proc_rec); */
  2881.       return_vals = procedural_db_return_args (proc_rec, TRUE);
  2882.       plug_in->recurse = old_recurse;
  2883.       plug_in->busy = FALSE;
  2884.     }
  2885.  
  2886. done:
  2887.   return return_vals;
  2888. }
  2889.  
  2890. static Argument*
  2891. plug_in_params_to_args (GPParam *params,
  2892.             gint     nparams,
  2893.             gboolean full_copy)
  2894. {
  2895.   Argument  *args;
  2896.   gchar    **stringarray;
  2897.   guchar    *colorarray;
  2898.   gint count;
  2899.   gint i, j;
  2900.  
  2901.   if (nparams == 0)
  2902.     return NULL;
  2903.  
  2904.   args = g_new (Argument, nparams);
  2905.  
  2906.   for (i = 0; i < nparams; i++)
  2907.     {
  2908.       args[i].arg_type = params[i].type;
  2909.  
  2910.       switch (args[i].arg_type)
  2911.     {
  2912.     case PDB_INT32:
  2913.       args[i].value.pdb_int = params[i].data.d_int32;
  2914.       break;
  2915.     case PDB_INT16:
  2916.       args[i].value.pdb_int = params[i].data.d_int16;
  2917.       break;
  2918.     case PDB_INT8:
  2919.       args[i].value.pdb_int = params[i].data.d_int8;
  2920.       break;
  2921.     case PDB_FLOAT:
  2922.       args[i].value.pdb_float = params[i].data.d_float;
  2923.       break;
  2924.     case PDB_STRING:
  2925.       if (full_copy)
  2926.         args[i].value.pdb_pointer = g_strdup (params[i].data.d_string);
  2927.       else
  2928.         args[i].value.pdb_pointer = params[i].data.d_string;
  2929.       break;
  2930.     case PDB_INT32ARRAY:
  2931.       if (full_copy)
  2932.         {
  2933.           count = args[i-1].value.pdb_int;
  2934.           args[i].value.pdb_pointer = g_new (gint32, count);
  2935.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int32array, count * 4);
  2936.         }
  2937.       else
  2938.         {
  2939.           args[i].value.pdb_pointer = params[i].data.d_int32array;
  2940.         }
  2941.       break;
  2942.     case PDB_INT16ARRAY:
  2943.       if (full_copy)
  2944.         {
  2945.           count = args[i-1].value.pdb_int;
  2946.           args[i].value.pdb_pointer = g_new (gint16, count);
  2947.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int16array, count * 2);
  2948.         }
  2949.       else
  2950.         {
  2951.           args[i].value.pdb_pointer = params[i].data.d_int16array;
  2952.         }
  2953.       break;
  2954.     case PDB_INT8ARRAY:
  2955.       if (full_copy)
  2956.         {
  2957.           count = args[i-1].value.pdb_int;
  2958.           args[i].value.pdb_pointer = g_new (gint8, count);
  2959.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int8array, count);
  2960.         }
  2961.       else
  2962.         {
  2963.           args[i].value.pdb_pointer = params[i].data.d_int8array;
  2964.         }
  2965.       break;
  2966.     case PDB_FLOATARRAY:
  2967.       if (full_copy)
  2968.         {
  2969.           count = args[i-1].value.pdb_int;
  2970.           args[i].value.pdb_pointer = g_new (gdouble, count);
  2971.           memcpy (args[i].value.pdb_pointer, params[i].data.d_floatarray, count * 8);
  2972.         }
  2973.       else
  2974.         {
  2975.           args[i].value.pdb_pointer = params[i].data.d_floatarray;
  2976.         }
  2977.       break;
  2978.     case PDB_STRINGARRAY:
  2979.       if (full_copy)
  2980.         {
  2981.           args[i].value.pdb_pointer = g_new (gchar*, args[i-1].value.pdb_int);
  2982.           stringarray = args[i].value.pdb_pointer;
  2983.  
  2984.           for (j = 0; j < args[i-1].value.pdb_int; j++)
  2985.         stringarray[j] = g_strdup (params[i].data.d_stringarray[j]);
  2986.         }
  2987.       else
  2988.         {
  2989.           args[i].value.pdb_pointer = params[i].data.d_stringarray;
  2990.         }
  2991.       break;
  2992.     case PDB_COLOR:
  2993.       args[i].value.pdb_pointer = g_new (guchar, 3);
  2994.       colorarray    = args[i].value.pdb_pointer;
  2995.       colorarray[0] = params[i].data.d_color.red;
  2996.       colorarray[1] = params[i].data.d_color.green;
  2997.       colorarray[2] = params[i].data.d_color.blue;
  2998.       break;
  2999.     case PDB_REGION:
  3000.       g_message ("the \"region\" arg type is not currently supported");
  3001.       break;
  3002.     case PDB_DISPLAY:
  3003.       args[i].value.pdb_int = params[i].data.d_display;
  3004.       break;
  3005.     case PDB_IMAGE:
  3006.       args[i].value.pdb_int = params[i].data.d_image;
  3007.       break;
  3008.     case PDB_LAYER:
  3009.       args[i].value.pdb_int = params[i].data.d_layer;
  3010.       break;
  3011.     case PDB_CHANNEL:
  3012.       args[i].value.pdb_int = params[i].data.d_channel;
  3013.       break;
  3014.     case PDB_DRAWABLE:
  3015.       args[i].value.pdb_int = params[i].data.d_drawable;
  3016.       break;
  3017.     case PDB_SELECTION:
  3018.       args[i].value.pdb_int = params[i].data.d_selection;
  3019.       break;
  3020.     case PDB_BOUNDARY:
  3021.       args[i].value.pdb_int = params[i].data.d_boundary;
  3022.       break;
  3023.     case PDB_PATH:
  3024.       args[i].value.pdb_int = params[i].data.d_path;
  3025.       break;
  3026.     case PDB_PARASITE:
  3027.       if (full_copy)
  3028.         args[i].value.pdb_pointer =
  3029.           gimp_parasite_copy ((GimpParasite *) &(params[i].data.d_parasite));
  3030.       else
  3031.         args[i].value.pdb_pointer = (void *)&(params[i].data.d_parasite);
  3032.       break;
  3033.     case PDB_STATUS:
  3034.       args[i].value.pdb_int = params[i].data.d_status;
  3035.       break;
  3036.     case PDB_END:
  3037.       break;
  3038.     }
  3039.     }
  3040.  
  3041.   return args;
  3042. }
  3043.  
  3044. static GPParam*
  3045. plug_in_args_to_params (Argument *args,
  3046.             gint      nargs,
  3047.             gboolean  full_copy)
  3048. {
  3049.   GPParam  *params;
  3050.   gchar   **stringarray;
  3051.   guchar   *colorarray;
  3052.   gint i, j;
  3053.  
  3054.   if (nargs == 0)
  3055.     return NULL;
  3056.  
  3057.   params = g_new (GPParam, nargs);
  3058.  
  3059.   for (i = 0; i < nargs; i++)
  3060.     {
  3061.       params[i].type = args[i].arg_type;
  3062.  
  3063.       switch (args[i].arg_type)
  3064.     {
  3065.     case PDB_INT32:
  3066.       params[i].data.d_int32 = args[i].value.pdb_int;
  3067.       break;
  3068.     case PDB_INT16:
  3069.       params[i].data.d_int16 = args[i].value.pdb_int;
  3070.       break;
  3071.     case PDB_INT8:
  3072.       params[i].data.d_int8 = args[i].value.pdb_int;
  3073.       break;
  3074.     case PDB_FLOAT:
  3075.       params[i].data.d_float = args[i].value.pdb_float;
  3076.       break;
  3077.     case PDB_STRING:
  3078.       if (full_copy)
  3079.         params[i].data.d_string = g_strdup (args[i].value.pdb_pointer);
  3080.       else
  3081.         params[i].data.d_string = args[i].value.pdb_pointer;
  3082.       break;
  3083.     case PDB_INT32ARRAY:
  3084.       if (full_copy)
  3085.         {
  3086.           params[i].data.d_int32array = g_new (gint32, params[i-1].data.d_int32);
  3087.           memcpy (params[i].data.d_int32array,
  3088.               args[i].value.pdb_pointer,
  3089.               params[i-1].data.d_int32 * 4);
  3090.         }
  3091.       else
  3092.         {
  3093.           params[i].data.d_int32array = args[i].value.pdb_pointer;
  3094.         }
  3095.       break;
  3096.     case PDB_INT16ARRAY:
  3097.       if (full_copy)
  3098.         {
  3099.           params[i].data.d_int16array = g_new (gint16, params[i-1].data.d_int32);
  3100.           memcpy (params[i].data.d_int16array,
  3101.               args[i].value.pdb_pointer,
  3102.               params[i-1].data.d_int32 * 2);
  3103.         }
  3104.       else
  3105.         {
  3106.           params[i].data.d_int16array = args[i].value.pdb_pointer;
  3107.         }
  3108.       break;
  3109.     case PDB_INT8ARRAY:
  3110.       if (full_copy)
  3111.         {
  3112.           params[i].data.d_int8array = g_new (gint8, params[i-1].data.d_int32);
  3113.           memcpy (params[i].data.d_int8array,
  3114.               args[i].value.pdb_pointer,
  3115.               params[i-1].data.d_int32);
  3116.         }
  3117.       else
  3118.         {
  3119.           params[i].data.d_int8array = args[i].value.pdb_pointer;
  3120.         }
  3121.       break;
  3122.     case PDB_FLOATARRAY:
  3123.       if (full_copy)
  3124.         {
  3125.           params[i].data.d_floatarray = g_new (gdouble, params[i-1].data.d_int32);
  3126.           memcpy (params[i].data.d_floatarray,
  3127.               args[i].value.pdb_pointer,
  3128.               params[i-1].data.d_int32 * 8);
  3129.         }
  3130.       else
  3131.         {
  3132.           params[i].data.d_floatarray = args[i].value.pdb_pointer;
  3133.         }
  3134.       break;
  3135.     case PDB_STRINGARRAY:
  3136.       if (full_copy)
  3137.         {
  3138.           params[i].data.d_stringarray = g_new (gchar*, params[i-1].data.d_int32);
  3139.           stringarray = args[i].value.pdb_pointer;
  3140.  
  3141.           for (j = 0; j < params[i-1].data.d_int32; j++)
  3142.         params[i].data.d_stringarray[j] = g_strdup (stringarray[j]);
  3143.         }
  3144.       else
  3145.         {
  3146.           params[i].data.d_stringarray = args[i].value.pdb_pointer;
  3147.         }
  3148.       break;
  3149.     case PDB_COLOR:
  3150.       colorarray = args[i].value.pdb_pointer;
  3151.       if( colorarray )
  3152.         {
  3153.           params[i].data.d_color.red   = colorarray[0];
  3154.           params[i].data.d_color.green = colorarray[1];
  3155.           params[i].data.d_color.blue  = colorarray[2];
  3156.         }
  3157.       else
  3158.         {
  3159.           params[i].data.d_color.red   = 0;
  3160.           params[i].data.d_color.green = 0;
  3161.           params[i].data.d_color.blue  = 0;
  3162.         }
  3163.       break;
  3164.     case PDB_REGION:
  3165.       g_message ("the \"region\" arg type is not currently supported");
  3166.       break;
  3167.     case PDB_DISPLAY:
  3168.       params[i].data.d_display = args[i].value.pdb_int;
  3169.       break;
  3170.     case PDB_IMAGE:
  3171.       params[i].data.d_image = args[i].value.pdb_int;
  3172.       break;
  3173.     case PDB_LAYER:
  3174.       params[i].data.d_layer = args[i].value.pdb_int;
  3175.       break;
  3176.     case PDB_CHANNEL:
  3177.       params[i].data.d_channel = args[i].value.pdb_int;
  3178.       break;
  3179.     case PDB_DRAWABLE:
  3180.       params[i].data.d_drawable = args[i].value.pdb_int;
  3181.       break;
  3182.     case PDB_SELECTION:
  3183.       params[i].data.d_selection = args[i].value.pdb_int;
  3184.       break;
  3185.     case PDB_BOUNDARY:
  3186.       params[i].data.d_boundary = args[i].value.pdb_int;
  3187.       break;
  3188.     case PDB_PATH:
  3189.       params[i].data.d_path = args[i].value.pdb_int;
  3190.       break;
  3191.     case PDB_PARASITE:
  3192.       if (full_copy)
  3193.         {
  3194.           GimpParasite *tmp;
  3195.  
  3196.           tmp = gimp_parasite_copy (args[i].value.pdb_pointer);
  3197.           if (tmp == NULL)
  3198.         {
  3199.           params[i].data.d_parasite.name  = 0;
  3200.           params[i].data.d_parasite.flags = 0;
  3201.           params[i].data.d_parasite.size  = 0;
  3202.           params[i].data.d_parasite.data  = 0;
  3203.         }
  3204.           else
  3205.         {
  3206.           memcpy (¶ms[i].data.d_parasite, tmp,
  3207.               sizeof (GimpParasite));
  3208.           g_free (tmp);
  3209.         }
  3210.         }
  3211.       else
  3212.         {
  3213.           if (args[i].value.pdb_pointer == NULL)
  3214.         {
  3215.           params[i].data.d_parasite.name  = 0;
  3216.           params[i].data.d_parasite.flags = 0;
  3217.           params[i].data.d_parasite.size  = 0;
  3218.           params[i].data.d_parasite.data  = 0;
  3219.         }
  3220.           else
  3221.         memcpy (¶ms[i].data.d_parasite,
  3222.             (GimpParasite *) (args[i].value.pdb_pointer),
  3223.             sizeof (GimpParasite));
  3224.         }
  3225.       break;
  3226.     case PDB_STATUS:
  3227.       params[i].data.d_status = args[i].value.pdb_int;
  3228.       break;
  3229.     case PDB_END:
  3230.       break;
  3231.     }
  3232.     }
  3233.  
  3234.   return params;
  3235. }
  3236.  
  3237. static void
  3238. plug_in_params_destroy (GPParam *params,
  3239.             gint      nparams,
  3240.             gboolean  full_destroy)
  3241. {
  3242.   gint i, j;
  3243.  
  3244.   for (i = 0; i < nparams; i++)
  3245.     {
  3246.       switch (params[i].type)
  3247.     {
  3248.     case PDB_INT32:
  3249.     case PDB_INT16:
  3250.     case PDB_INT8:
  3251.     case PDB_FLOAT:
  3252.       break;
  3253.     case PDB_STRING:
  3254.       if (full_destroy)
  3255.         g_free (params[i].data.d_string);
  3256.       break;
  3257.     case PDB_INT32ARRAY:
  3258.       if (full_destroy)
  3259.         g_free (params[i].data.d_int32array);
  3260.       break;
  3261.     case PDB_INT16ARRAY:
  3262.       if (full_destroy)
  3263.         g_free (params[i].data.d_int16array);
  3264.       break;
  3265.     case PDB_INT8ARRAY:
  3266.       if (full_destroy)
  3267.         g_free (params[i].data.d_int8array);
  3268.       break;
  3269.     case PDB_FLOATARRAY:
  3270.       if (full_destroy)
  3271.         g_free (params[i].data.d_floatarray);
  3272.       break;
  3273.     case PDB_STRINGARRAY:
  3274.       if (full_destroy)
  3275.         {
  3276.           for (j = 0; j < params[i-1].data.d_int32; j++)
  3277.         g_free (params[i].data.d_stringarray[j]);
  3278.           g_free (params[i].data.d_stringarray);
  3279.         }
  3280.       break;
  3281.     case PDB_COLOR:
  3282.       break;
  3283.     case PDB_REGION:
  3284.       g_message ("the \"region\" arg type is not currently supported");
  3285.       break;
  3286.     case PDB_DISPLAY:
  3287.     case PDB_IMAGE:
  3288.     case PDB_LAYER:
  3289.     case PDB_CHANNEL:
  3290.     case PDB_DRAWABLE:
  3291.     case PDB_SELECTION:
  3292.     case PDB_BOUNDARY:
  3293.     case PDB_PATH:
  3294.       break;
  3295.     case PDB_PARASITE:
  3296.       if (full_destroy)
  3297.         if (params[i].data.d_parasite.data)
  3298.         {
  3299.           g_free (params[i].data.d_parasite.name);
  3300.           g_free (params[i].data.d_parasite.data);
  3301.           params[i].data.d_parasite.name = 0;
  3302.           params[i].data.d_parasite.data = 0;
  3303.         }
  3304.       break;
  3305.     case PDB_STATUS:
  3306.       break;
  3307.     case PDB_END:
  3308.       break;
  3309.     }
  3310.     }
  3311.  
  3312.   g_free (params);
  3313. }
  3314.  
  3315. static void
  3316. plug_in_args_destroy (Argument *args,
  3317.               gint       nargs,
  3318.               gboolean   full_destroy)
  3319. {
  3320.   gchar **stringarray;
  3321.   gint    count;
  3322.   gint    i, j;
  3323.  
  3324.   for (i = 0; i < nargs; i++)
  3325.     {
  3326.       switch (args[i].arg_type)
  3327.     {
  3328.     case PDB_INT32:
  3329.     case PDB_INT16:
  3330.     case PDB_INT8:
  3331.     case PDB_FLOAT:
  3332.       break;
  3333.     case PDB_STRING:
  3334.       if (full_destroy)
  3335.         g_free (args[i].value.pdb_pointer);
  3336.       break;
  3337.     case PDB_INT32ARRAY:
  3338.       if (full_destroy)
  3339.         g_free (args[i].value.pdb_pointer);
  3340.       break;
  3341.     case PDB_INT16ARRAY:
  3342.       if (full_destroy)
  3343.         g_free (args[i].value.pdb_pointer);
  3344.       break;
  3345.     case PDB_INT8ARRAY:
  3346.       if (full_destroy)
  3347.         g_free (args[i].value.pdb_pointer);
  3348.       break;
  3349.     case PDB_FLOATARRAY:
  3350.       if (full_destroy)
  3351.         g_free (args[i].value.pdb_pointer);
  3352.       break;
  3353.     case PDB_STRINGARRAY:
  3354.       if (full_destroy)
  3355.         {
  3356.           count = args[i-1].value.pdb_int;
  3357.           stringarray = args[i].value.pdb_pointer;
  3358.  
  3359.           for (j = 0; j < count; j++)
  3360.         g_free (stringarray[j]);
  3361.  
  3362.           g_free (args[i].value.pdb_pointer);
  3363.         }
  3364.       break;
  3365.     case PDB_COLOR:
  3366.       g_free (args[i].value.pdb_pointer);
  3367.       break;
  3368.     case PDB_REGION:
  3369.       g_message ("the \"region\" arg type is not currently supported");
  3370.       break;
  3371.     case PDB_DISPLAY:
  3372.     case PDB_IMAGE:
  3373.     case PDB_LAYER:
  3374.     case PDB_CHANNEL:
  3375.     case PDB_DRAWABLE:
  3376.     case PDB_SELECTION:
  3377.     case PDB_BOUNDARY:
  3378.     case PDB_PATH:
  3379.       break;
  3380.     case PDB_PARASITE:
  3381.       if (full_destroy)
  3382.         {
  3383.           gimp_parasite_free ((GimpParasite *) (args[i].value.pdb_pointer));
  3384.           args[i].value.pdb_pointer = NULL;
  3385.         }
  3386.       break;
  3387.     case PDB_STATUS:
  3388.       break;
  3389.     case PDB_END:
  3390.       break;
  3391.     }
  3392.     }
  3393.  
  3394.   g_free (args);
  3395. }
  3396.  
  3397. gint
  3398. plug_in_image_types_parse (gchar *image_types)
  3399. {
  3400.   gchar *type_spec = image_types;
  3401.   gint   types = 0;
  3402.  
  3403.   /* 
  3404.    *  If the plug_in registers with image_type == NULL or "", return 0
  3405.    *  By doing so it won't be touched by plug_in_set_menu_sensitivity() 
  3406.    */
  3407.   if (!image_types)
  3408.     return types;
  3409.  
  3410.   while (*image_types)
  3411.     {
  3412.       while (*image_types &&
  3413.          ((*image_types == ' ') ||
  3414.           (*image_types == '\t') ||
  3415.           (*image_types == ',')))
  3416.     image_types++;
  3417.  
  3418.       if (*image_types)
  3419.     {
  3420.       if (strncmp (image_types, "RGBA", 4) == 0)
  3421.         {
  3422.           types |= PLUG_IN_RGBA_IMAGE;
  3423.           image_types += 4;
  3424.         }
  3425.       else if (strncmp (image_types, "RGB*", 4) == 0)
  3426.         {
  3427.           types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE;
  3428.           image_types += 4;
  3429.         }
  3430.       else if (strncmp (image_types, "RGB", 3) == 0)
  3431.         {
  3432.           types |= PLUG_IN_RGB_IMAGE;
  3433.           image_types += 3;
  3434.         }
  3435.       else if (strncmp (image_types, "GRAYA", 5) == 0)
  3436.         {
  3437.           types |= PLUG_IN_GRAYA_IMAGE;
  3438.           image_types += 5;
  3439.         }
  3440.       else if (strncmp (image_types, "GRAY*", 5) == 0)
  3441.         {
  3442.           types |= PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE;
  3443.           image_types += 5;
  3444.         }
  3445.       else if (strncmp (image_types, "GRAY", 4) == 0)
  3446.         {
  3447.           types |= PLUG_IN_GRAY_IMAGE;
  3448.           image_types += 4;
  3449.         }
  3450.       else if (strncmp (image_types, "INDEXEDA", 8) == 0)
  3451.         {
  3452.           types |= PLUG_IN_INDEXEDA_IMAGE;
  3453.           image_types += 8;
  3454.         }
  3455.       else if (strncmp (image_types, "INDEXED*", 8) == 0)
  3456.         {
  3457.           types |= PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
  3458.           image_types += 8;
  3459.         }
  3460.       else if (strncmp (image_types, "INDEXED", 7) == 0)
  3461.         {
  3462.           types |= PLUG_IN_INDEXED_IMAGE;
  3463.           image_types += 7;
  3464.         }
  3465.       else if (strncmp (image_types, "*", 1) == 0)
  3466.         {
  3467.           types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE
  3468.                  | PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE
  3469.                  | PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
  3470.           image_types += 1;
  3471.         }
  3472.       else
  3473.         {
  3474.               g_warning ("image_type contains unrecognizable parts: '%s'", type_spec);
  3475.           while (*image_types &&
  3476.                      ((*image_types != ' ') ||
  3477.                       (*image_types != '\t') ||
  3478.                       (*image_types != ',')))
  3479.         image_types++;
  3480.         }
  3481.     }
  3482.     }
  3483.  
  3484.   return types;
  3485. }
  3486.  
  3487. static void
  3488. plug_in_progress_cancel (GtkWidget *widget,
  3489.              PlugIn    *plug_in)
  3490. {
  3491.   plug_in_destroy (plug_in);
  3492. }
  3493.  
  3494. void
  3495. plug_in_progress_init (PlugIn *plug_in,
  3496.                gchar  *message,
  3497.                gint    gdisp_ID)
  3498. {
  3499.   GDisplay *gdisp = NULL;
  3500.  
  3501.   if (!message)
  3502.     message = plug_in->args[0];
  3503.  
  3504.   if (gdisp_ID > 0) 
  3505.       gdisp = gdisplay_get_ID(gdisp_ID);
  3506.  
  3507.   if (plug_in->progress)
  3508.     plug_in->progress = progress_restart (plug_in->progress, message,
  3509.                       plug_in_progress_cancel, plug_in);
  3510.   else
  3511.     plug_in->progress = progress_start (gdisp, message, TRUE,
  3512.                     plug_in_progress_cancel, plug_in);
  3513. }
  3514.  
  3515. void
  3516. plug_in_progress_update (PlugIn  *plug_in,
  3517.              gdouble  percentage)
  3518. {
  3519.   if (!plug_in->progress)
  3520.     plug_in_progress_init (plug_in, NULL, -1);
  3521.   
  3522.   progress_update (plug_in->progress, percentage);
  3523. }
  3524.