2004-12-14 Michael Natterer <mitch@gimp.org> * app/plug-in/plug-in-proc-frame.[ch]: added "gint ref_count" to the PlugInProcFrame struct. Added new functions plug_in_proc_frame_ref/unref(). (plug_in_proc_frame_new): set the ref_count to 1. * app/plug-in/plug-in.[ch] (plug_in_proc_frame_push): return the new proc_frame. (plug_in_proc_frame_pop): use unref() instead of free(). * app/plug-in/plug-in-run.c (plug_in_temp_run): ref the proc_frame while running its main loop. Removed the call to plug_in_proc_frame_pop(). * app/plug-in/plug-in-message.c (plug_in_handle_temp_proc_return): call plug_in_proc_frame_pop() immediately after plug_in_main_loop_quit() so the proc_frame goes away from the stack and can't be used accidentially if the core is too busy to return to the main loop before the next command arrives on the wire. Really fixes bug #161114 this time.
847 lines
25 KiB
C
847 lines
25 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* plug-in-message.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib-object.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpbase/gimpprotocol.h"
|
|
#include "libgimpbase/gimpwire.h"
|
|
|
|
#include "plug-in-types.h"
|
|
|
|
#include "base/tile.h"
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpdrawable.h"
|
|
|
|
#include "plug-in.h"
|
|
#include "plug-ins.h"
|
|
#include "plug-in-def.h"
|
|
#include "plug-in-params.h"
|
|
#include "plug-in-proc-def.h"
|
|
#include "plug-in-shm.h"
|
|
|
|
|
|
typedef struct _PlugInBlocked PlugInBlocked;
|
|
|
|
struct _PlugInBlocked
|
|
{
|
|
PlugIn *plug_in;
|
|
gchar *proc_name;
|
|
};
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void plug_in_handle_quit (PlugIn *plug_in);
|
|
static void plug_in_handle_tile_req (PlugIn *plug_in,
|
|
GPTileReq *tile_req);
|
|
static void plug_in_handle_proc_run (PlugIn *plug_in,
|
|
GPProcRun *proc_run);
|
|
static void plug_in_handle_proc_return_priv (PlugIn *plug_in,
|
|
GPProcReturn *proc_return,
|
|
gboolean temp_proc);
|
|
static void plug_in_handle_proc_return (PlugIn *plug_in,
|
|
GPProcReturn *proc_return);
|
|
static void plug_in_handle_temp_proc_return (PlugIn *plug_in,
|
|
GPProcReturn *proc_return);
|
|
static void plug_in_handle_proc_install (PlugIn *plug_in,
|
|
GPProcInstall *proc_install);
|
|
static void plug_in_handle_proc_uninstall (PlugIn *plug_in,
|
|
GPProcUninstall *proc_uninstall);
|
|
static void plug_in_handle_extension_ack (PlugIn *plug_in);
|
|
static void plug_in_handle_has_init (PlugIn *plug_in);
|
|
|
|
|
|
/* private variables */
|
|
|
|
static GSList *blocked_plug_ins = NULL;
|
|
|
|
|
|
/* public functions */
|
|
|
|
void
|
|
plug_in_handle_message (PlugIn *plug_in,
|
|
WireMessage *msg)
|
|
{
|
|
switch (msg->type)
|
|
{
|
|
case GP_QUIT:
|
|
plug_in_handle_quit (plug_in);
|
|
break;
|
|
|
|
case GP_CONFIG:
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent a CONFIG message (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
break;
|
|
|
|
case GP_TILE_REQ:
|
|
plug_in_handle_tile_req (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_TILE_ACK:
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent a TILE_ACK message (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
break;
|
|
|
|
case GP_TILE_DATA:
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent a TILE_DATA message (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
break;
|
|
|
|
case GP_PROC_RUN:
|
|
plug_in_handle_proc_run (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_PROC_RETURN:
|
|
plug_in_handle_proc_return (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_TEMP_PROC_RUN:
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent a TEMP_PROC_RUN message (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
break;
|
|
|
|
case GP_TEMP_PROC_RETURN:
|
|
plug_in_handle_temp_proc_return (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_PROC_INSTALL:
|
|
plug_in_handle_proc_install (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_PROC_UNINSTALL:
|
|
plug_in_handle_proc_uninstall (plug_in, msg->data);
|
|
break;
|
|
|
|
case GP_EXTENSION_ACK:
|
|
plug_in_handle_extension_ack (plug_in);
|
|
break;
|
|
|
|
case GP_HAS_INIT:
|
|
plug_in_handle_has_init (plug_in);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static void
|
|
plug_in_handle_quit (PlugIn *plug_in)
|
|
{
|
|
plug_in_close (plug_in, FALSE);
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_tile_req (PlugIn *plug_in,
|
|
GPTileReq *tile_req)
|
|
{
|
|
GPTileData tile_data;
|
|
GPTileData *tile_info;
|
|
WireMessage msg;
|
|
GimpDrawable *drawable;
|
|
TileManager *tm;
|
|
Tile *tile;
|
|
gint shm_ID;
|
|
|
|
shm_ID = plug_in_shm_get_ID (plug_in->gimp);
|
|
|
|
if (tile_req->drawable_ID == -1)
|
|
{
|
|
/* this branch communicates with libgimp/gimptile.c:gimp_tile_put() */
|
|
|
|
tile_data.drawable_ID = -1;
|
|
tile_data.tile_num = 0;
|
|
tile_data.shadow = 0;
|
|
tile_data.bpp = 0;
|
|
tile_data.width = 0;
|
|
tile_data.height = 0;
|
|
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
|
|
tile_data.data = NULL;
|
|
|
|
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
|
|
{
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (! wire_read_msg (plug_in->my_read, &msg, plug_in))
|
|
{
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (msg.type != GP_TILE_DATA)
|
|
{
|
|
g_warning ("expected tile data and received: %d", msg.type);
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
tile_info = msg.data;
|
|
|
|
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->gimp,
|
|
tile_info->drawable_ID);
|
|
|
|
if (! drawable)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"requested invalid drawable (killing)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (tile_info->shadow)
|
|
tm = gimp_drawable_shadow (drawable);
|
|
else
|
|
tm = gimp_drawable_data (drawable);
|
|
|
|
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
|
|
|
|
if (! tile)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"requested invalid tile (killing)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (tile_data.use_shm)
|
|
memcpy (tile_data_pointer (tile, 0, 0),
|
|
plug_in_shm_get_addr (plug_in->gimp),
|
|
tile_size (tile));
|
|
else
|
|
memcpy (tile_data_pointer (tile, 0, 0),
|
|
tile_info->data,
|
|
tile_size (tile));
|
|
|
|
tile_release (tile, TRUE);
|
|
|
|
wire_destroy (&msg);
|
|
if (! gp_tile_ack_write (plug_in->my_write, plug_in))
|
|
{
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* this branch communicates with libgimp/gimptile.c:gimp_tile_get() */
|
|
|
|
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->gimp,
|
|
tile_req->drawable_ID);
|
|
|
|
if (! drawable)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"requested invalid drawable (killing)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (tile_req->shadow)
|
|
tm = gimp_drawable_shadow (drawable);
|
|
else
|
|
tm = gimp_drawable_data (drawable);
|
|
|
|
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
|
|
|
|
if (! tile)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"requested invalid tile (killing)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
tile_data.drawable_ID = tile_req->drawable_ID;
|
|
tile_data.tile_num = tile_req->tile_num;
|
|
tile_data.shadow = tile_req->shadow;
|
|
tile_data.bpp = tile_bpp (tile);
|
|
tile_data.width = tile_ewidth (tile);
|
|
tile_data.height = tile_eheight (tile);
|
|
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
|
|
|
|
if (tile_data.use_shm)
|
|
memcpy (plug_in_shm_get_addr (plug_in->gimp),
|
|
tile_data_pointer (tile, 0, 0),
|
|
tile_size (tile));
|
|
else
|
|
tile_data.data = tile_data_pointer (tile, 0, 0);
|
|
|
|
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
|
|
{
|
|
g_message ("plug_in_handle_tile_req: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
tile_release (tile, FALSE);
|
|
|
|
if (! wire_read_msg (plug_in->my_read, &msg, plug_in))
|
|
{
|
|
g_message ("plug_in_handle_tile_req: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
if (msg.type != GP_TILE_ACK)
|
|
{
|
|
g_warning ("expected tile ack and received: %d", msg.type);
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
wire_destroy (&msg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_proc_run (PlugIn *plug_in,
|
|
GPProcRun *proc_run)
|
|
{
|
|
PlugInProcFrame *proc_frame;
|
|
const gchar *proc_name = NULL;
|
|
ProcRecord *proc_rec;
|
|
Argument *args;
|
|
Argument *return_vals;
|
|
|
|
proc_frame = plug_in_get_proc_frame (plug_in);
|
|
|
|
proc_rec = procedural_db_lookup (plug_in->gimp, proc_run->name);
|
|
|
|
if (! proc_rec)
|
|
{
|
|
proc_name = g_hash_table_lookup (plug_in->gimp->procedural_compat_ht,
|
|
proc_run->name);
|
|
|
|
if (proc_name)
|
|
{
|
|
proc_rec = procedural_db_lookup (plug_in->gimp, proc_name);
|
|
|
|
if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
|
|
{
|
|
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
|
|
"called deprecated procedure '%s'.\n"
|
|
"It should call '%s' instead!",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog),
|
|
proc_run->name, proc_name);
|
|
}
|
|
}
|
|
}
|
|
else if (proc_rec->deprecated)
|
|
{
|
|
if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
|
|
{
|
|
if (! strcmp (proc_rec->deprecated, "NONE"))
|
|
{
|
|
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
|
|
"called deprecated procedure '%s'.",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog),
|
|
proc_run->name);
|
|
}
|
|
else
|
|
{
|
|
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
|
|
"called deprecated procedure '%s'.\n"
|
|
"It should call '%s' instead!",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog),
|
|
proc_run->name, proc_rec->deprecated);
|
|
}
|
|
}
|
|
else if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_OFF)
|
|
{
|
|
proc_rec = NULL;
|
|
}
|
|
}
|
|
|
|
if (! proc_name)
|
|
proc_name = proc_run->name;
|
|
|
|
args = plug_in_params_to_args (proc_run->params, proc_run->nparams, FALSE);
|
|
|
|
plug_in_push (plug_in->gimp, plug_in);
|
|
|
|
/* Execute the procedure even if procedural_db_lookup() returned NULL,
|
|
* procedural_db_execute() will return appropriate error return_vals.
|
|
*/
|
|
return_vals = procedural_db_execute (plug_in->gimp,
|
|
proc_frame->context_stack ?
|
|
proc_frame->context_stack->data :
|
|
proc_frame->main_context,
|
|
proc_frame->progress,
|
|
proc_name, args);
|
|
|
|
plug_in_pop (plug_in->gimp);
|
|
|
|
if (return_vals)
|
|
{
|
|
GPProcReturn proc_return;
|
|
|
|
/* Return the name we got called with, *not* proc_name, since
|
|
* proc_name may have been remapped by gimp->procedural_compat_ht
|
|
*/
|
|
proc_return.name = proc_run->name;
|
|
|
|
if (proc_rec)
|
|
{
|
|
proc_return.nparams = proc_rec->num_values + 1;
|
|
proc_return.params = plug_in_args_to_params (return_vals,
|
|
proc_return.nparams,
|
|
FALSE);
|
|
}
|
|
else
|
|
{
|
|
proc_return.nparams = 1;
|
|
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
|
|
}
|
|
|
|
if (! gp_proc_return_write (plug_in->my_write, &proc_return, plug_in))
|
|
{
|
|
g_warning ("plug_in_handle_proc_run: ERROR");
|
|
plug_in_close (plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
plug_in_args_destroy (args, proc_run->nparams, FALSE);
|
|
|
|
if (proc_rec)
|
|
plug_in_args_destroy (return_vals, proc_rec->num_values + 1, TRUE);
|
|
else
|
|
plug_in_args_destroy (return_vals, 1, TRUE);
|
|
|
|
plug_in_params_destroy (proc_return.params, proc_return.nparams, FALSE);
|
|
}
|
|
else
|
|
{
|
|
PlugInBlocked *blocked;
|
|
|
|
g_warning ("%s: EEEEEEEEEK! \n"
|
|
"You managed to trigger a code path that \n"
|
|
"should be dead. Please report this to bugs.gimp.org.",
|
|
G_STRFUNC);
|
|
|
|
blocked = g_new0 (PlugInBlocked, 1);
|
|
|
|
blocked->plug_in = plug_in;
|
|
blocked->proc_name = g_strdup (proc_run->name);
|
|
|
|
blocked_plug_ins = g_slist_prepend (blocked_plug_ins, blocked);
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_proc_return_priv (PlugIn *plug_in,
|
|
GPProcReturn *proc_return,
|
|
gboolean temp_proc)
|
|
{
|
|
PlugInProcFrame *proc_frame;
|
|
|
|
if (temp_proc)
|
|
proc_frame = plug_in->temp_proc_frames->data;
|
|
else
|
|
proc_frame = &plug_in->main_proc_frame;
|
|
|
|
if (proc_frame->main_loop)
|
|
{
|
|
proc_frame->return_vals = plug_in_params_to_args (proc_return->params,
|
|
proc_return->nparams,
|
|
TRUE);
|
|
proc_frame->n_return_vals = proc_return->nparams;
|
|
}
|
|
else
|
|
{
|
|
GSList *list;
|
|
|
|
for (list = blocked_plug_ins; list; list = g_slist_next (list))
|
|
{
|
|
PlugInBlocked *blocked;
|
|
|
|
blocked = (PlugInBlocked *) list->data;
|
|
|
|
if (blocked->proc_name && proc_return->name &&
|
|
strcmp (blocked->proc_name, proc_return->name) == 0)
|
|
{
|
|
if (! gp_proc_return_write (blocked->plug_in->my_write,
|
|
proc_return,
|
|
blocked->plug_in))
|
|
{
|
|
g_message ("plug_in_handle_proc_run: ERROR");
|
|
plug_in_close (blocked->plug_in, TRUE);
|
|
return;
|
|
}
|
|
|
|
blocked_plug_ins = g_slist_remove (blocked_plug_ins, blocked);
|
|
g_free (blocked->proc_name);
|
|
g_free (blocked);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_proc_return (PlugIn *plug_in,
|
|
GPProcReturn *proc_return)
|
|
{
|
|
plug_in_handle_proc_return_priv (plug_in, proc_return, FALSE);
|
|
|
|
if (plug_in->main_proc_frame.main_loop)
|
|
g_main_loop_quit (plug_in->main_proc_frame.main_loop);
|
|
|
|
plug_in_close (plug_in, FALSE);
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_temp_proc_return (PlugIn *plug_in,
|
|
GPProcReturn *proc_return)
|
|
{
|
|
if (plug_in->temp_proc_frames)
|
|
{
|
|
plug_in_handle_proc_return_priv (plug_in, proc_return, TRUE);
|
|
|
|
plug_in_main_loop_quit (plug_in);
|
|
plug_in_proc_frame_pop (plug_in);
|
|
}
|
|
else
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent a TEMP_PROC_RETURN message while not running "
|
|
"a temp proc (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_proc_install (PlugIn *plug_in,
|
|
GPProcInstall *proc_install)
|
|
{
|
|
PlugInDef *plug_in_def = NULL;
|
|
PlugInProcDef *proc_def = NULL;
|
|
ProcRecord *proc = NULL;
|
|
GSList *tmp = NULL;
|
|
gchar *prog = NULL;
|
|
gboolean valid_utf8 = FALSE;
|
|
gint i;
|
|
|
|
/* Argument checking
|
|
* --only sanity check arguments when the procedure requests a menu path
|
|
*/
|
|
|
|
if (proc_install->menu_path && proc_install->menu_path[0] == '<')
|
|
{
|
|
GError *error = NULL;
|
|
|
|
if (! plug_in_param_defs_check (plug_in->name,
|
|
plug_in->prog,
|
|
proc_install->name,
|
|
proc_install->menu_path,
|
|
proc_install->params,
|
|
proc_install->nparams,
|
|
proc_install->return_vals,
|
|
proc_install->nreturn_vals,
|
|
&error))
|
|
{
|
|
g_message (error->message);
|
|
g_clear_error (&error);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Sanity check for array arguments */
|
|
|
|
for (i = 1; i < proc_install->nparams; i++)
|
|
{
|
|
if ((proc_install->params[i].type == GIMP_PDB_INT32ARRAY ||
|
|
proc_install->params[i].type == GIMP_PDB_INT8ARRAY ||
|
|
proc_install->params[i].type == GIMP_PDB_FLOATARRAY ||
|
|
proc_install->params[i].type == GIMP_PDB_STRINGARRAY)
|
|
&&
|
|
proc_install->params[i-1].type != GIMP_PDB_INT32)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"attempted to install procedure \"%s\" "
|
|
"which fails to comply with the array parameter "
|
|
"passing standard. Argument %d is noncompliant.",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog),
|
|
proc_install->name, i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Sanity check strings for UTF-8 validity */
|
|
|
|
if ((proc_install->menu_path == NULL ||
|
|
g_utf8_validate (proc_install->menu_path, -1, NULL)) &&
|
|
(g_utf8_validate (proc_install->name, -1, NULL)) &&
|
|
(proc_install->blurb == NULL ||
|
|
g_utf8_validate (proc_install->blurb, -1, NULL)) &&
|
|
(proc_install->help == NULL ||
|
|
g_utf8_validate (proc_install->help, -1, NULL)) &&
|
|
(proc_install->author == NULL ||
|
|
g_utf8_validate (proc_install->author, -1, NULL)) &&
|
|
(proc_install->copyright == NULL ||
|
|
g_utf8_validate (proc_install->copyright, -1, NULL)) &&
|
|
(proc_install->date == NULL ||
|
|
g_utf8_validate (proc_install->date, -1, NULL)))
|
|
{
|
|
valid_utf8 = TRUE;
|
|
|
|
for (i = 0; i < proc_install->nparams && valid_utf8; i++)
|
|
{
|
|
if (! (g_utf8_validate (proc_install->params[i].name, -1, NULL) &&
|
|
(proc_install->params[i].description == NULL ||
|
|
g_utf8_validate (proc_install->params[i].description, -1, NULL))))
|
|
valid_utf8 = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < proc_install->nreturn_vals && valid_utf8; i++)
|
|
{
|
|
if (! (g_utf8_validate (proc_install->return_vals[i].name, -1, NULL) &&
|
|
(proc_install->return_vals[i].description == NULL ||
|
|
g_utf8_validate (proc_install->return_vals[i].description, -1, NULL))))
|
|
valid_utf8 = FALSE;
|
|
}
|
|
}
|
|
|
|
if (! valid_utf8)
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"attempted to install a procedure with invalid UTF-8 strings.",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
return;
|
|
}
|
|
|
|
/* Initialization */
|
|
|
|
switch (proc_install->type)
|
|
{
|
|
case GIMP_PLUGIN:
|
|
case GIMP_EXTENSION:
|
|
plug_in_def = plug_in->plug_in_def;
|
|
prog = plug_in_def->prog;
|
|
|
|
tmp = plug_in_def->proc_defs;
|
|
break;
|
|
|
|
case GIMP_TEMPORARY:
|
|
plug_in_def = NULL;
|
|
prog = "none";
|
|
|
|
tmp = plug_in->temp_proc_defs;
|
|
break;
|
|
}
|
|
|
|
while (tmp)
|
|
{
|
|
proc_def = tmp->data;
|
|
tmp = tmp->next;
|
|
|
|
if (strcmp (proc_def->db_info.name, proc_install->name) == 0)
|
|
{
|
|
switch (proc_install->type)
|
|
{
|
|
case GIMP_PLUGIN:
|
|
case GIMP_EXTENSION:
|
|
plug_in_def->proc_defs = g_slist_remove (plug_in_def->proc_defs,
|
|
proc_def);
|
|
plug_in_proc_def_free (proc_def);
|
|
break;
|
|
|
|
case GIMP_TEMPORARY:
|
|
plug_in->temp_proc_defs = g_slist_remove (plug_in->temp_proc_defs,
|
|
proc_def);
|
|
plug_ins_temp_proc_def_remove (plug_in->gimp, proc_def);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
proc_def = plug_in_proc_def_new ();
|
|
|
|
if (proc_install->menu_path)
|
|
{
|
|
if (proc_install->menu_path[0] == '<')
|
|
proc_def->menu_paths =
|
|
g_list_append (proc_def->menu_paths,
|
|
g_strdup (proc_install->menu_path));
|
|
else
|
|
proc_def->menu_label = g_strdup (proc_install->menu_path);
|
|
}
|
|
|
|
proc_def->prog = g_strdup (prog);
|
|
proc_def->extensions = NULL;
|
|
proc_def->prefixes = NULL;
|
|
proc_def->magics = NULL;
|
|
proc_def->image_types = g_strdup (proc_install->image_types);
|
|
proc_def->image_types_val = plug_ins_image_types_parse (proc_def->image_types);
|
|
/* Install temp one use todays time */
|
|
proc_def->mtime = time (NULL);
|
|
|
|
/* Remember if this proc was installed while initing a plug-in */
|
|
proc_def->installed_during_init = plug_in->init;
|
|
|
|
/* The procedural database procedure */
|
|
|
|
proc = &proc_def->db_info;
|
|
|
|
proc->name = g_strdup (proc_install->name);
|
|
proc->blurb = g_strdup (proc_install->blurb);
|
|
proc->help = g_strdup (proc_install->help);
|
|
proc->author = g_strdup (proc_install->author);
|
|
proc->copyright = g_strdup (proc_install->copyright);
|
|
proc->date = g_strdup (proc_install->date);
|
|
proc->proc_type = proc_install->type;
|
|
|
|
proc->num_args = proc_install->nparams;
|
|
proc->num_values = proc_install->nreturn_vals;
|
|
|
|
proc->args = g_new0 (ProcArg, proc->num_args);
|
|
proc->values = g_new0 (ProcArg, proc->num_values);
|
|
|
|
for (i = 0; i < proc->num_args; i++)
|
|
{
|
|
proc->args[i].arg_type = proc_install->params[i].type;
|
|
proc->args[i].name = g_strdup (proc_install->params[i].name);
|
|
proc->args[i].description = g_strdup (proc_install->params[i].description);
|
|
}
|
|
|
|
for (i = 0; i < proc->num_values; i++)
|
|
{
|
|
proc->values[i].arg_type = proc_install->return_vals[i].type;
|
|
proc->values[i].name = g_strdup (proc_install->return_vals[i].name);
|
|
proc->values[i].description = g_strdup (proc_install->return_vals[i].description);
|
|
}
|
|
|
|
switch (proc_install->type)
|
|
{
|
|
case GIMP_PLUGIN:
|
|
case GIMP_EXTENSION:
|
|
plug_in_def->proc_defs = g_slist_prepend (plug_in_def->proc_defs,
|
|
proc_def);
|
|
break;
|
|
|
|
case GIMP_TEMPORARY:
|
|
plug_in->temp_proc_defs = g_slist_prepend (plug_in->temp_proc_defs,
|
|
proc_def);
|
|
|
|
proc->exec_method.temporary.plug_in = plug_in;
|
|
|
|
plug_ins_temp_proc_def_add (plug_in->gimp, proc_def);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_proc_uninstall (PlugIn *plug_in,
|
|
GPProcUninstall *proc_uninstall)
|
|
{
|
|
GSList *tmp;
|
|
|
|
for (tmp = plug_in->temp_proc_defs; tmp; tmp = g_slist_next (tmp))
|
|
{
|
|
PlugInProcDef *proc_def;
|
|
|
|
proc_def = tmp->data;
|
|
|
|
if (! strcmp (proc_def->db_info.name, proc_uninstall->name))
|
|
{
|
|
plug_in->temp_proc_defs = g_slist_remove (plug_in->temp_proc_defs,
|
|
proc_def);
|
|
plug_ins_temp_proc_def_remove (plug_in->gimp, proc_def);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_extension_ack (PlugIn *plug_in)
|
|
{
|
|
if (plug_in->ext_main_loop)
|
|
{
|
|
g_main_loop_quit (plug_in->ext_main_loop);
|
|
}
|
|
else
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent an EXTENSION_ACK message while not being started "
|
|
"as extension (should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
plug_in_handle_has_init (PlugIn *plug_in)
|
|
{
|
|
if (plug_in->query)
|
|
{
|
|
plug_in_def_set_has_init (plug_in->plug_in_def, TRUE);
|
|
}
|
|
else
|
|
{
|
|
g_message ("Plug-In \"%s\"\n(%s)\n\n"
|
|
"sent an HAS_INIT message while not in query() "
|
|
"(should not happen)",
|
|
gimp_filename_to_utf8 (plug_in->name),
|
|
gimp_filename_to_utf8 (plug_in->prog));
|
|
plug_in_close (plug_in, TRUE);
|
|
}
|
|
}
|