1997-11-25 06:05:25 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
1999-03-07 20:56:03 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "config.h"
|
1999-03-07 20:56:03 +08:00
|
|
|
|
1999-06-22 04:04:04 +08:00
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
|
|
#include <sys/param.h>
|
|
|
|
#endif
|
|
|
|
|
1999-06-15 06:18:02 +08:00
|
|
|
#include <glib.h>
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <sys/wait.h>
|
1999-03-07 20:56:03 +08:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <sys/time.h>
|
1999-03-07 21:23:06 +08:00
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <time.h>
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifdef HAVE_UNISTD_H
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <unistd.h>
|
1999-03-07 20:56:03 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#define STRICT
|
|
|
|
#include <windows.h>
|
|
|
|
#include <process.h>
|
|
|
|
|
Win32 portability changes:
* config.h.win32, README.win32: Small changes.
* tools/pdbgen/pdb/*.pdb: Include <string.h>.
* app/*_cmds.c: Autogenerated files reflect above changes.
* libgimp/makefile.msc app/makefile.msc: Various updates,
including new object files. Gtk+ directory now should be called
gtk+ (not gtk-plus). Use win32-specific gdk subdir. Glib directory
now should be called just glib.
* libgimp/gimp.def: Updates.
* libgimp/gimpfeatures.h.win32: Made current with
gimpfeatures.h.in.
* libgimp/gimpfileselection.c: Define S_ISDIR and S_ISREG if
necessary.
* tools/pdbgen/pdb/fileops.pdb: Must have a
statement (even an empty one) after a label.
* app/fileops_cmds.c: Autogenerated file reflects above changes.
* app/crop.c: Include <string.h>.
* app/{app_procs,batch,fileops,datafiles,errorconsole,general,
plug_in,temp_buf,tile_swap}.c: Test NATIVE_WIN32, not
_MSC_VER. (NATIVE_WIN32 means we are using the Microsoft C
runtime, even if we might be compiling with gcc.)
* app/fileops.c: Don't include <process.h> here.
* app/fileops.h: Do include <process.h> here.
* app/gimpparasite.c: Include config.h, guard inclusion of
<unistd.h>. (Is the inclusion of unistd.h in source files all over
the place really necessary?)
* app/ink.c: MSC doesn't handle conversion from unsigned __int64
to double, so cast to signed.
* app/lut_funcs.c: Include config.h, and define rint() if necessary.
* app/pixel_processor.c: Include config.h without "..", like in
all the other places. Include <string.h>
* app/text_tool.c: Guard the "POINTS" identifier that clashes with
<windows.h>, sigh.
1999-05-05 05:32:17 +08:00
|
|
|
#ifdef NATIVE_WIN32
|
1999-03-07 20:56:03 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __CYGWIN32__
|
|
|
|
#define O_TEXT 0x0100 /* text file */
|
|
|
|
#define _O_TEXT 0x0100 /* text file */
|
|
|
|
#define O_BINARY 0x0200 /* binary file */
|
|
|
|
#define _O_BINARY 0x0200 /* binary file */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
1999-04-25 03:12:12 +08:00
|
|
|
#ifdef __EMX__
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <process.h>
|
|
|
|
#define _O_BINARY O_BINARY
|
|
|
|
#define _P_NOWAIT P_NOWAIT
|
|
|
|
#endif
|
|
|
|
|
1999-01-31 09:08:26 +08:00
|
|
|
#include "regex.h"
|
1998-10-14 10:54:02 +08:00
|
|
|
#include "libgimp/parasite.h"
|
|
|
|
#include "libgimp/parasiteP.h" /* ick */
|
1999-03-07 20:56:03 +08:00
|
|
|
#include "libgimp/gimpenv.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-08-29 07:01:46 +08:00
|
|
|
#ifdef HAVE_IPC_H
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SHM_H
|
|
|
|
#include <sys/shm.h>
|
|
|
|
#endif
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "libgimp/gimpprotocol.h"
|
|
|
|
#include "libgimp/gimpwire.h"
|
|
|
|
|
1998-01-20 08:12:21 +08:00
|
|
|
#include "app_procs.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "appenv.h"
|
1998-09-19 08:40:27 +08:00
|
|
|
#include "brush_select.h" /* Need for closing dialogs */
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "drawable.h"
|
|
|
|
#include "datafiles.h"
|
|
|
|
#include "errors.h"
|
|
|
|
#include "gdisplay.h"
|
|
|
|
#include "general.h"
|
|
|
|
#include "gimage.h"
|
|
|
|
#include "gimprc.h"
|
1998-11-01 00:22:37 +08:00
|
|
|
#include "gradient.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "interface.h"
|
|
|
|
#include "menus.h"
|
1998-10-02 06:09:01 +08:00
|
|
|
#include "pattern_select.h" /* Needed for closing pattern dialogs */
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "plug_in.h"
|
|
|
|
|
1998-08-12 01:35:34 +08:00
|
|
|
#include "tile.h" /* ick. */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
typedef struct _PlugInBlocked PlugInBlocked;
|
|
|
|
|
|
|
|
struct _PlugInBlocked
|
|
|
|
{
|
|
|
|
PlugIn *plug_in;
|
|
|
|
char *proc_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
static int plug_in_write (GIOChannel *channel,
|
1997-11-25 06:05:25 +08:00
|
|
|
guint8 *buf,
|
|
|
|
gulong count);
|
1999-03-07 20:56:03 +08:00
|
|
|
static int plug_in_flush (GIOChannel *channel);
|
1997-11-25 06:05:25 +08:00
|
|
|
static void plug_in_push (PlugIn *plug_in);
|
|
|
|
static void plug_in_pop (void);
|
1999-03-07 20:56:03 +08:00
|
|
|
static gboolean plug_in_recv_message (GIOChannel *channel,
|
|
|
|
GIOCondition cond,
|
|
|
|
gpointer data);
|
1997-11-25 06:05:25 +08:00
|
|
|
static void plug_in_handle_message (WireMessage *msg);
|
|
|
|
static void plug_in_handle_quit (void);
|
|
|
|
static void plug_in_handle_tile_req (GPTileReq *tile_req);
|
|
|
|
static void plug_in_handle_proc_run (GPProcRun *proc_run);
|
|
|
|
static void plug_in_handle_proc_return (GPProcReturn *proc_return);
|
|
|
|
static void plug_in_handle_proc_install (GPProcInstall *proc_install);
|
|
|
|
static void plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall);
|
|
|
|
static void plug_in_write_rc (char *filename);
|
|
|
|
static void plug_in_init_file (char *filename);
|
|
|
|
static void plug_in_query (char *filename,
|
|
|
|
PlugInDef *plug_in_def);
|
|
|
|
static void plug_in_add_to_db (void);
|
|
|
|
static void plug_in_make_menu (void);
|
|
|
|
static void plug_in_callback (GtkWidget *widget,
|
|
|
|
gpointer client_data);
|
1999-02-14 09:53:23 +08:00
|
|
|
static void plug_in_proc_def_insert (PlugInProcDef *proc_def,
|
|
|
|
void (*superceed_fn)(void *));
|
|
|
|
static void plug_in_proc_def_dead (void *freed_proc_def);
|
1997-11-25 06:05:25 +08:00
|
|
|
static void plug_in_proc_def_remove (PlugInProcDef *proc_def);
|
|
|
|
static void plug_in_proc_def_destroy (PlugInProcDef *proc_def,
|
|
|
|
int data_only);
|
|
|
|
|
|
|
|
static Argument* plug_in_temp_run (ProcRecord *proc_rec,
|
1998-10-22 03:10:14 +08:00
|
|
|
Argument *args,
|
|
|
|
int argc);
|
1997-11-25 06:05:25 +08:00
|
|
|
static Argument* plug_in_params_to_args (GPParam *params,
|
|
|
|
int nparams,
|
|
|
|
int full_copy);
|
|
|
|
static GPParam* plug_in_args_to_params (Argument *args,
|
|
|
|
int nargs,
|
|
|
|
int full_copy);
|
|
|
|
static void plug_in_params_destroy (GPParam *params,
|
|
|
|
int nparams,
|
|
|
|
int full_destroy);
|
|
|
|
static void plug_in_args_destroy (Argument *args,
|
|
|
|
int nargs,
|
|
|
|
int full_destroy);
|
1999-05-07 04:56:07 +08:00
|
|
|
static void plug_in_init_shm (void);
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
|
1999-05-04 03:22:58 +08:00
|
|
|
PlugIn *current_plug_in = NULL;
|
|
|
|
GSList *proc_defs = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
static GSList *plug_in_defs = NULL;
|
|
|
|
static GSList *gimprc_proc_defs = NULL;
|
|
|
|
static GSList *open_plug_ins = NULL;
|
|
|
|
static GSList *blocked_plug_ins = NULL;
|
|
|
|
|
|
|
|
static GSList *plug_in_stack = NULL;
|
1999-03-07 20:56:03 +08:00
|
|
|
static GIOChannel *current_readchannel = NULL;
|
|
|
|
static GIOChannel *current_writechannel = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
static int current_write_buffer_index = 0;
|
|
|
|
static char *current_write_buffer = NULL;
|
|
|
|
static Argument *current_return_vals = NULL;
|
|
|
|
static int current_return_nvals = 0;
|
|
|
|
|
|
|
|
static ProcRecord *last_plug_in = NULL;
|
|
|
|
|
|
|
|
static int shm_ID = -1;
|
|
|
|
static guchar *shm_addr = NULL;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifdef WIN32
|
|
|
|
static HANDLE shm_handle;
|
|
|
|
#endif
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static int write_pluginrc = FALSE;
|
|
|
|
|
1999-02-14 09:53:23 +08:00
|
|
|
|
1999-05-07 04:56:07 +08:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_init_shm (void)
|
|
|
|
{
|
|
|
|
/* allocate a piece of shared memory for use in transporting tiles
|
|
|
|
* to plug-ins. if we can't allocate a piece of shared memory then
|
|
|
|
* we'll fall back on sending the data over the pipe.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_SHM_H
|
|
|
|
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
|
|
|
|
|
|
|
|
if (shm_ID == -1)
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("shmget failed...disabling shared memory tile transport");
|
1999-05-07 04:56:07 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
|
|
|
|
if (shm_addr == (guchar*) -1)
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("shmat failed...disabling shared memory tile transport");
|
1999-05-07 04:56:07 +08:00
|
|
|
shm_ID = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef IPC_RMID_DEFERRED_RELEASE
|
|
|
|
if (shm_addr != (guchar*) -1)
|
|
|
|
shmctl (shm_ID, IPC_RMID, 0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
|
|
|
/* Use Win32 shared memory mechanisms for
|
|
|
|
* transfering tile data.
|
|
|
|
*/
|
|
|
|
int pid;
|
|
|
|
char fileMapName[MAX_PATH];
|
|
|
|
int tileByteSize = TILE_WIDTH * TILE_HEIGHT * 4;
|
|
|
|
|
|
|
|
/* Our shared memory id will be our process ID */
|
|
|
|
pid = GetCurrentProcessId ();
|
|
|
|
|
|
|
|
/* From the id, derive the file map name */
|
|
|
|
sprintf (fileMapName, "GIMP%d.SHM", pid);
|
|
|
|
|
|
|
|
/* Create the file mapping into paging space */
|
|
|
|
shm_handle = CreateFileMapping ((HANDLE) 0xFFFFFFFF, NULL,
|
|
|
|
PAGE_READWRITE, 0,
|
|
|
|
tileByteSize, fileMapName);
|
|
|
|
|
|
|
|
if (shm_handle)
|
|
|
|
{
|
|
|
|
/* Map the shared memory into our address space for use */
|
|
|
|
shm_addr = (guchar *) MapViewOfFile(shm_handle,
|
|
|
|
FILE_MAP_ALL_ACCESS,
|
|
|
|
0, 0, tileByteSize);
|
|
|
|
|
|
|
|
/* Verify that we mapped our view */
|
|
|
|
if (shm_addr)
|
|
|
|
shm_ID = pid;
|
|
|
|
else {
|
|
|
|
g_warning ("MapViewOfFile error: %d... disabling shared memory transport\n", GetLastError());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("CreateFileMapping error: %d... disabling shared memory transport\n", GetLastError());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_init (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
extern int use_shm;
|
1999-03-07 20:56:03 +08:00
|
|
|
char *filename;
|
1997-11-25 06:05:25 +08:00
|
|
|
GSList *tmp, *tmp2;
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def;
|
1998-01-20 08:12:21 +08:00
|
|
|
gfloat nplugins, nth;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* initialize the gimp protocol library and set the read and
|
|
|
|
* write handlers.
|
|
|
|
*/
|
|
|
|
gp_init ();
|
|
|
|
wire_set_writer (plug_in_write);
|
|
|
|
wire_set_flusher (plug_in_flush);
|
|
|
|
|
|
|
|
/* allocate a piece of shared memory for use in transporting tiles
|
|
|
|
* to plug-ins. if we can't allocate a piece of shared memory then
|
|
|
|
* we'll fall back on sending the data over the pipe.
|
|
|
|
*/
|
|
|
|
if (use_shm)
|
1999-05-07 04:56:07 +08:00
|
|
|
{
|
|
|
|
plug_in_init_shm();
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
/* search for binaries in the plug-in directory path */
|
|
|
|
datafiles_read_directories (plug_in_path, plug_in_init_file, MODE_EXECUTABLE);
|
|
|
|
|
|
|
|
/* read the pluginrc file for cached data */
|
1999-03-07 20:56:03 +08:00
|
|
|
filename = NULL;
|
1998-04-11 13:07:52 +08:00
|
|
|
if (pluginrc_path)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
if (g_path_is_absolute (pluginrc_path))
|
|
|
|
filename = g_strdup (pluginrc_path);
|
1998-04-11 13:07:52 +08:00
|
|
|
else
|
1999-03-07 20:56:03 +08:00
|
|
|
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
|
|
|
|
gimp_directory (), pluginrc_path);
|
1998-04-11 13:07:52 +08:00
|
|
|
}
|
|
|
|
else
|
1999-03-07 20:56:03 +08:00
|
|
|
filename = gimp_personal_rc_file ("pluginrc");
|
1998-04-11 13:07:52 +08:00
|
|
|
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
app_init_update_status(_("Resource configuration"), filename, -1);
|
1997-11-25 06:05:25 +08:00
|
|
|
parse_gimprc_file (filename);
|
|
|
|
|
|
|
|
/* query any plug-ins that have changed since we last wrote out
|
|
|
|
* the pluginrc file.
|
|
|
|
*/
|
|
|
|
tmp = plug_in_defs;
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
app_init_update_status(_("Plug-ins"), "", 0);
|
1998-01-20 08:12:21 +08:00
|
|
|
nplugins = g_slist_length(tmp);
|
|
|
|
nth = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (plug_in_def->query)
|
|
|
|
{
|
|
|
|
write_pluginrc = TRUE;
|
1998-03-26 05:36:59 +08:00
|
|
|
if ((be_verbose == TRUE) || (no_splash == TRUE))
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
g_print (_("query plug-in: \"%s\"\n"), plug_in_def->prog);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_query (plug_in_def->prog, plug_in_def);
|
|
|
|
}
|
1998-01-20 08:12:21 +08:00
|
|
|
app_init_update_status(NULL, plug_in_def->prog, nth/nplugins);
|
|
|
|
nth++;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* insert the proc defs */
|
|
|
|
tmp = gimprc_proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = g_new (PlugInProcDef, 1);
|
|
|
|
*proc_def = *((PlugInProcDef*) tmp->data);
|
1999-02-14 09:53:23 +08:00
|
|
|
plug_in_proc_def_insert (proc_def, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
tmp2 = plug_in_def->proc_defs;
|
|
|
|
while (tmp2)
|
|
|
|
{
|
|
|
|
proc_def = tmp2->data;
|
|
|
|
tmp2 = tmp2->next;
|
|
|
|
|
1999-01-31 09:08:26 +08:00
|
|
|
proc_def->mtime = plug_in_def->mtime;
|
1999-02-14 09:53:23 +08:00
|
|
|
plug_in_proc_def_insert (proc_def, plug_in_proc_def_dead);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write the pluginrc file if necessary */
|
|
|
|
if (write_pluginrc)
|
|
|
|
{
|
1998-03-26 05:36:59 +08:00
|
|
|
if ((be_verbose == TRUE) || (no_splash == TRUE))
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
g_print (_("writing \"%s\"\n"), filename);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_write_rc (filename);
|
|
|
|
}
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
g_free (filename);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* add the plug-in procs to the procedure database */
|
|
|
|
plug_in_add_to_db ();
|
|
|
|
|
|
|
|
/* make the menu */
|
|
|
|
plug_in_make_menu ();
|
|
|
|
|
|
|
|
/* run the available extensions */
|
|
|
|
tmp = proc_defs;
|
1998-03-26 05:36:59 +08:00
|
|
|
if ((be_verbose == TRUE) || (no_splash == TRUE))
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
g_print (_("Starting extensions: "));
|
|
|
|
app_init_update_status(_("Extensions"), "", 0);
|
1998-01-20 08:12:21 +08:00
|
|
|
nplugins = g_slist_length(tmp); nth = 0;
|
1998-01-26 06:13:00 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (proc_def->prog &&
|
|
|
|
(proc_def->db_info.num_args == 0) &&
|
|
|
|
(proc_def->db_info.proc_type == PDB_EXTENSION))
|
|
|
|
{
|
1998-03-26 05:36:59 +08:00
|
|
|
if ((be_verbose == TRUE) || (no_splash == TRUE))
|
|
|
|
g_print ("%s ", proc_def->db_info.name);
|
1998-01-20 08:12:21 +08:00
|
|
|
app_init_update_status(NULL, proc_def->db_info.name,
|
|
|
|
nth/nplugins);
|
1998-01-26 06:13:00 +08:00
|
|
|
|
1998-10-22 03:10:14 +08:00
|
|
|
plug_in_run (&proc_def->db_info, NULL, 0, FALSE, TRUE, -1);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
1998-03-26 05:36:59 +08:00
|
|
|
if ((be_verbose == TRUE) || (no_splash == TRUE))
|
|
|
|
g_print ("\n");
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* free up stuff */
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
g_slist_free (plug_in_def->proc_defs);
|
|
|
|
g_free (plug_in_def->prog);
|
|
|
|
g_free (plug_in_def);
|
|
|
|
}
|
|
|
|
g_slist_free (plug_in_defs);
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_kill (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
PlugIn *plug_in;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifdef WIN32
|
|
|
|
CloseHandle (shm_handle);
|
|
|
|
#else
|
1998-08-29 07:01:46 +08:00
|
|
|
#ifdef HAVE_SHM_H
|
1997-11-25 06:05:25 +08:00
|
|
|
#ifndef IPC_RMID_DEFERRED_RELEASE
|
|
|
|
if (shm_ID != -1)
|
|
|
|
{
|
|
|
|
shmdt ((char*) shm_addr);
|
|
|
|
shmctl (shm_ID, IPC_RMID, 0);
|
|
|
|
}
|
|
|
|
#else /* IPC_RMID_DEFERRED_RELEASE */
|
|
|
|
if (shm_ID != -1)
|
|
|
|
shmdt ((char*) shm_addr);
|
|
|
|
#endif
|
1999-03-07 20:56:03 +08:00
|
|
|
#endif
|
1998-08-29 07:01:46 +08:00
|
|
|
#endif
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tmp = open_plug_ins;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
plug_in_destroy (plug_in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_add (char *prog,
|
|
|
|
char *menu_path,
|
|
|
|
char *accelerator)
|
|
|
|
{
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (strncmp ("plug_in_", prog, 8) != 0)
|
|
|
|
{
|
1998-12-26 02:22:01 +08:00
|
|
|
char *t = g_strdup_printf ("plug_in_%s", prog);
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (prog);
|
|
|
|
prog = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = gimprc_proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, prog) == 0)
|
|
|
|
{
|
|
|
|
if (proc_def->db_info.name)
|
|
|
|
g_free (proc_def->db_info.name);
|
|
|
|
if (proc_def->menu_path)
|
|
|
|
g_free (proc_def->menu_path);
|
|
|
|
if (proc_def->accelerator)
|
|
|
|
g_free (proc_def->accelerator);
|
|
|
|
if (proc_def->extensions)
|
|
|
|
g_free (proc_def->extensions);
|
|
|
|
if (proc_def->prefixes)
|
|
|
|
g_free (proc_def->prefixes);
|
|
|
|
if (proc_def->magics)
|
|
|
|
g_free (proc_def->magics);
|
|
|
|
if (proc_def->image_types)
|
|
|
|
g_free (proc_def->image_types);
|
|
|
|
|
|
|
|
proc_def->db_info.name = prog;
|
|
|
|
proc_def->menu_path = menu_path;
|
|
|
|
proc_def->accelerator = accelerator;
|
|
|
|
proc_def->prefixes = NULL;
|
|
|
|
proc_def->extensions = NULL;
|
|
|
|
proc_def->magics = NULL;
|
|
|
|
proc_def->image_types = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
proc_def = g_new0 (PlugInProcDef, 1);
|
|
|
|
proc_def->db_info.name = prog;
|
|
|
|
proc_def->menu_path = menu_path;
|
|
|
|
proc_def->accelerator = accelerator;
|
|
|
|
|
|
|
|
gimprc_proc_defs = g_slist_prepend (gimprc_proc_defs, proc_def);
|
|
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
|
|
plug_in_image_types (char *name)
|
|
|
|
{
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (current_plug_in)
|
|
|
|
{
|
|
|
|
plug_in_def = current_plug_in->user_data;
|
|
|
|
tmp = plug_in_def->proc_defs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp = proc_defs;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, name) == 0)
|
|
|
|
return proc_def->image_types;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GSList*
|
|
|
|
plug_in_extensions_parse (char *extensions)
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
char *extension;
|
|
|
|
list = NULL;
|
|
|
|
/* EXTENSIONS can be NULL. Avoid calling strtok if it is. */
|
|
|
|
if (extensions)
|
|
|
|
{
|
|
|
|
extensions = g_strdup (extensions);
|
|
|
|
extension = strtok (extensions, " \t,");
|
|
|
|
while (extension)
|
|
|
|
{
|
|
|
|
list = g_slist_prepend (list, g_strdup (extension));
|
|
|
|
extension = strtok (NULL, " \t,");
|
|
|
|
}
|
|
|
|
g_free (extensions);
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_add_internal (PlugInProcDef *proc_def)
|
|
|
|
{
|
|
|
|
proc_defs = g_slist_prepend (proc_defs, proc_def);
|
|
|
|
}
|
|
|
|
|
|
|
|
PlugInProcDef*
|
|
|
|
plug_in_file_handler (char *name,
|
|
|
|
char *extensions,
|
|
|
|
char *prefixes,
|
|
|
|
char *magics)
|
|
|
|
{
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (current_plug_in)
|
|
|
|
{
|
|
|
|
plug_in_def = current_plug_in->user_data;
|
|
|
|
tmp = plug_in_def->proc_defs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp = proc_defs;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, name) == 0)
|
|
|
|
{
|
|
|
|
/* EXTENSIONS can be proc_def->extensions */
|
|
|
|
if (proc_def->extensions != extensions)
|
|
|
|
{
|
|
|
|
if (proc_def->extensions)
|
|
|
|
g_free (proc_def->extensions);
|
|
|
|
proc_def->extensions = g_strdup (extensions);
|
|
|
|
}
|
|
|
|
proc_def->extensions_list = plug_in_extensions_parse (proc_def->extensions);
|
|
|
|
|
|
|
|
/* PREFIXES can be proc_def->prefixes */
|
|
|
|
if (proc_def->prefixes != prefixes)
|
|
|
|
{
|
|
|
|
if (proc_def->prefixes)
|
|
|
|
g_free (proc_def->prefixes);
|
|
|
|
proc_def->prefixes = g_strdup (prefixes);
|
|
|
|
}
|
|
|
|
proc_def->prefixes_list = plug_in_extensions_parse (proc_def->prefixes);
|
|
|
|
|
1998-05-16 14:37:14 +08:00
|
|
|
/* MAGICS can be proc_def->magics */
|
1997-11-25 06:05:25 +08:00
|
|
|
if (proc_def->magics != magics)
|
|
|
|
{
|
|
|
|
if (proc_def->magics)
|
|
|
|
g_free (proc_def->magics);
|
|
|
|
proc_def->magics = g_strdup (magics);
|
|
|
|
}
|
|
|
|
proc_def->magics_list = plug_in_extensions_parse (proc_def->magics);
|
|
|
|
return proc_def;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_def_add (PlugInDef *plug_in_def)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
PlugInDef *tplug_in_def;
|
1999-02-14 09:53:23 +08:00
|
|
|
PlugInProcDef *proc_def;
|
1997-11-25 06:05:25 +08:00
|
|
|
char *t1, *t2;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (t1)
|
|
|
|
t1 = t1 + 1;
|
|
|
|
else
|
|
|
|
t1 = plug_in_def->prog;
|
|
|
|
|
1999-02-14 09:53:23 +08:00
|
|
|
/* If this is a file load or save plugin, make sure we have
|
|
|
|
* something for one of the extensions, prefixes, or magic number.
|
|
|
|
* Other bits of code rely on detecting file plugins by the presence
|
|
|
|
* of one of these things, but Nick Lamb's alien/unknown format
|
|
|
|
* loader needs to be able to register no extensions, prefixes or
|
|
|
|
* magics. -- austin 13/Feb/99 */
|
|
|
|
tmp = plug_in_def->proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
if (!proc_def->extensions && !proc_def->prefixes && !proc_def->magics &&
|
|
|
|
proc_def->menu_path &&
|
|
|
|
(!strncmp (proc_def->menu_path, "<Load>", 6) ||
|
|
|
|
!strncmp (proc_def->menu_path, "<Save>", 6)))
|
|
|
|
{
|
|
|
|
proc_def->extensions = g_strdup("");
|
|
|
|
}
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
tplug_in_def = tmp->data;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (t2)
|
|
|
|
t2 = t2 + 1;
|
|
|
|
else
|
|
|
|
t2 = tplug_in_def->prog;
|
|
|
|
|
|
|
|
if (strcmp (t1, t2) == 0)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
|
1997-11-25 06:05:25 +08:00
|
|
|
(plug_in_def->mtime == tplug_in_def->mtime))
|
|
|
|
{
|
|
|
|
/* Use cached plug-in entry */
|
|
|
|
tmp->data = plug_in_def;
|
|
|
|
g_free (tplug_in_def->prog);
|
|
|
|
g_free (tplug_in_def);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_free (plug_in_def->prog);
|
|
|
|
g_free (plug_in_def);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_pluginrc = TRUE;
|
1999-09-23 19:49:16 +08:00
|
|
|
g_print ("\"%s\" executable not found\n", plug_in_def->prog);
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (plug_in_def->prog);
|
|
|
|
g_free (plug_in_def);
|
|
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
|
|
plug_in_menu_path (char *name)
|
|
|
|
{
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp, *tmp2;
|
|
|
|
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
tmp2 = plug_in_def->proc_defs;
|
|
|
|
while (tmp2)
|
|
|
|
{
|
|
|
|
proc_def = tmp2->data;
|
|
|
|
tmp2 = tmp2->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, name) == 0)
|
|
|
|
return proc_def->menu_path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, name) == 0)
|
|
|
|
return proc_def->menu_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlugIn*
|
|
|
|
plug_in_new (char *name)
|
|
|
|
{
|
|
|
|
PlugIn *plug_in;
|
|
|
|
char *path;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!g_path_is_absolute (name))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
path = search_in_path (plug_in_path, name);
|
|
|
|
if (!path)
|
|
|
|
{
|
Lots of ii8n stuff here and some additions to the de.po. Applied
Wed Oct 14 17:46:15 EDT 1998 Adrian Likins <adrian@gimp.org>
* app/*, po/de.po, de/POTFILES.in, libgimp/gimpintl.h:
Lots of ii8n stuff here and some additions to the de.po.
Applied gimp-egger-981005-1 ,gimp-egger-981006-1,
gimp-egger-981007-1, gimp-egger-981008-1,
gimp-egger-981009-1.patch, gimp-egger-981010-1.patch
* plug-in/guillotine/guillotine.c: added the coordinates
of the split images from the original image to the title.
ie foo.jpg (0,0) for the image in the topleft.
* plug-in/script-fu/scripts/neon-logo.scm,
perspective-shadow.scm, predator.scm,rendermap.scm,
ripply-anim.scm, select_to_image.scm,swirltile.scm,
xach-effect.scm: updated scripts to use new script-fu stuff
wooo boy! a big un!
in testing this, it looks like some of the po files are busted.
but the code stuff seems okay.
-adrian
1998-10-15 07:23:52 +08:00
|
|
|
g_message (_("unable to locate plug-in: \"%s\""), name);
|
1997-11-25 06:05:25 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in = g_new (PlugIn, 1);
|
|
|
|
|
|
|
|
plug_in->open = FALSE;
|
|
|
|
plug_in->destroy = FALSE;
|
|
|
|
plug_in->query = FALSE;
|
|
|
|
plug_in->synchronous = FALSE;
|
|
|
|
plug_in->recurse = FALSE;
|
|
|
|
plug_in->busy = FALSE;
|
|
|
|
plug_in->pid = 0;
|
|
|
|
plug_in->args[0] = g_strdup (path);
|
|
|
|
plug_in->args[1] = g_strdup ("-gimp");
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in->args[2] = g_new (char, 32);
|
|
|
|
plug_in->args[3] = g_new (char, 32);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in->args[4] = NULL;
|
|
|
|
plug_in->args[5] = NULL;
|
|
|
|
plug_in->args[6] = NULL;
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in->my_read = NULL;
|
|
|
|
plug_in->my_write = NULL;
|
|
|
|
plug_in->his_read = NULL;
|
|
|
|
plug_in->his_write = NULL;
|
1998-03-31 14:08:08 +08:00
|
|
|
plug_in->input_id = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in->write_buffer_index = 0;
|
|
|
|
plug_in->temp_proc_defs = NULL;
|
|
|
|
plug_in->progress = NULL;
|
|
|
|
plug_in->user_data = NULL;
|
|
|
|
|
|
|
|
return plug_in;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_destroy (PlugIn *plug_in)
|
|
|
|
{
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
plug_in_close (plug_in, TRUE);
|
|
|
|
|
|
|
|
if (plug_in->args[0])
|
|
|
|
g_free (plug_in->args[0]);
|
|
|
|
if (plug_in->args[1])
|
|
|
|
g_free (plug_in->args[1]);
|
|
|
|
if (plug_in->args[2])
|
|
|
|
g_free (plug_in->args[2]);
|
|
|
|
if (plug_in->args[3])
|
|
|
|
g_free (plug_in->args[3]);
|
|
|
|
if (plug_in->args[4])
|
|
|
|
g_free (plug_in->args[4]);
|
|
|
|
if (plug_in->args[5])
|
|
|
|
g_free (plug_in->args[5]);
|
|
|
|
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
if (plug_in->progress)
|
|
|
|
progress_end (plug_in->progress);
|
|
|
|
plug_in->progress = NULL;
|
1998-06-15 10:25:27 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (plug_in == current_plug_in)
|
|
|
|
plug_in_pop ();
|
|
|
|
|
|
|
|
if (!plug_in->destroy)
|
|
|
|
g_free (plug_in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
plug_in_open (PlugIn *plug_in)
|
|
|
|
{
|
|
|
|
int my_read[2];
|
|
|
|
int my_write[2];
|
|
|
|
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
/* Open two pipes. (Bidirectional communication).
|
|
|
|
*/
|
|
|
|
if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("unable to open pipe");
|
1997-11-25 06:05:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-04-25 03:12:12 +08:00
|
|
|
#if defined(__CYGWIN32__) || defined(__EMX__)
|
1999-03-07 20:56:03 +08:00
|
|
|
/* Set to binary mode */
|
|
|
|
setmode(my_read[0], _O_BINARY);
|
|
|
|
setmode(my_write[0], _O_BINARY);
|
|
|
|
setmode(my_read[1], _O_BINARY);
|
|
|
|
setmode(my_write[1], _O_BINARY);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef NATIVE_WIN32
|
|
|
|
plug_in->my_read = g_io_channel_unix_new (my_read[0]);
|
|
|
|
plug_in->my_write = g_io_channel_unix_new (my_write[1]);
|
|
|
|
plug_in->his_read = g_io_channel_unix_new (my_write[0]);
|
|
|
|
plug_in->his_write = g_io_channel_unix_new (my_read[1]);
|
|
|
|
#else
|
|
|
|
plug_in->my_read = g_io_channel_win32_new_pipe (my_read[0]);
|
|
|
|
plug_in->his_read = g_io_channel_win32_new_pipe (my_write[0]);
|
|
|
|
plug_in->his_read_fd = my_write[0];
|
|
|
|
plug_in->my_write = g_io_channel_win32_new_pipe (my_write[1]);
|
|
|
|
plug_in->his_write = g_io_channel_win32_new_pipe (my_read[1]);
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Remember the file descriptors for the pipes.
|
|
|
|
*/
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifndef NATIVE_WIN32
|
|
|
|
sprintf (plug_in->args[2], "%d",
|
|
|
|
g_io_channel_unix_get_fd (plug_in->his_read));
|
|
|
|
sprintf (plug_in->args[3], "%d",
|
|
|
|
g_io_channel_unix_get_fd (plug_in->his_write));
|
|
|
|
#else
|
|
|
|
sprintf (plug_in->args[2], "%d",
|
|
|
|
g_io_channel_win32_get_fd (plug_in->his_read));
|
1999-08-29 01:00:33 +08:00
|
|
|
sprintf (plug_in->args[3], "%d:%u:%d",
|
1999-03-07 20:56:03 +08:00
|
|
|
g_io_channel_win32_get_fd (plug_in->his_write),
|
|
|
|
GetCurrentThreadId (),
|
|
|
|
g_io_channel_win32_get_fd (plug_in->my_read));
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set the rest of the command line arguments.
|
|
|
|
*/
|
|
|
|
if (plug_in->query)
|
|
|
|
{
|
|
|
|
plug_in->args[4] = g_strdup ("-query");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
plug_in->args[4] = g_new (char, 16);
|
|
|
|
plug_in->args[5] = g_new (char, 16);
|
|
|
|
|
|
|
|
sprintf (plug_in->args[4], "%d", TILE_WIDTH);
|
|
|
|
sprintf (plug_in->args[5], "%d", TILE_WIDTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fork another process. We'll remember the process id
|
|
|
|
* so that we can later use it to kill the filter if
|
|
|
|
* necessary.
|
|
|
|
*/
|
1999-04-25 03:12:12 +08:00
|
|
|
#ifdef __EMX__
|
|
|
|
fcntl(my_read[0], F_SETFD, 1);
|
|
|
|
fcntl(my_write[1], F_SETFD, 1);
|
|
|
|
#endif
|
|
|
|
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32) || defined(__EMX__)
|
Check for mmap.
* configure.in: Check for mmap.
* app/makefile.msc: Depend on gimpi.lib.
* app/app_procs.c (app_init): Fix gccism: Allocate filenames (an
array with non-constant size) dynamically.
* app/{datafiles,fileops,general,install,module_db,temp_buf}.c:
Include glib.h before standard headers, because of certain obscure
details related to compiling with gcc on Win32.
(If you really want to know: glib.h defines he names of POSIXish
(but non-ANSI) functions as prefixed with underscore, because
that's how they are named in the msvcrt runtime C library we want
to use. However, defining stat as _stat causes some problems if
done after including the mingw32 <sys/stat.h>. So, it's easiest to
include <glib.h> early.)
* app/main.c: Use _stdcall and __argc, __argv with MSC, but
__attribute__((stdcall)) and _argc, _argv with gcc. Don't print
the "Passed serialization test" message on Win32. (It would open
up an otherwise unnecessary console window.)
* app/paint_funcs.c (gaussian_blur_region): Don't use variable sum
until initialized.
* app/{bezier_select,paths_dialog}.c: Include config.h and define
rint() if necessary.
* app/plug_in.c: Use _spawnv, not spawnv, on Win32 and OS/2.
1999-05-29 01:47:17 +08:00
|
|
|
plug_in->pid = _spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
|
1999-03-07 20:56:03 +08:00
|
|
|
if (plug_in->pid == -1)
|
|
|
|
#else
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in->pid = fork ();
|
|
|
|
|
|
|
|
if (plug_in->pid == 0)
|
|
|
|
{
|
1999-03-08 18:27:52 +08:00
|
|
|
g_io_channel_close (plug_in->my_read);
|
|
|
|
g_io_channel_unref (plug_in->my_read);
|
|
|
|
plug_in->my_read = NULL;
|
|
|
|
g_io_channel_close (plug_in->my_write);
|
|
|
|
g_io_channel_unref (plug_in->my_write);
|
|
|
|
plug_in->my_write = NULL;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Execute the filter. The "_exit" call should never
|
|
|
|
* be reached, unless some strange error condition
|
|
|
|
* exists.
|
|
|
|
*/
|
|
|
|
execvp (plug_in->args[0], plug_in->args);
|
|
|
|
_exit (1);
|
|
|
|
}
|
|
|
|
else if (plug_in->pid == -1)
|
1999-03-07 20:56:03 +08:00
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("unable to run plug-in: %s", plug_in->args[0]);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_destroy (plug_in);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
g_io_channel_close (plug_in->his_read);
|
|
|
|
g_io_channel_unref (plug_in->his_read);
|
|
|
|
plug_in->his_read = NULL;
|
|
|
|
g_io_channel_close (plug_in->his_write);
|
|
|
|
g_io_channel_unref (plug_in->his_write);
|
|
|
|
plug_in->his_write = NULL;
|
|
|
|
|
|
|
|
#ifdef NATIVE_WIN32
|
|
|
|
/* The plug-in tells us its thread id */
|
|
|
|
if (!plug_in->query)
|
|
|
|
{
|
|
|
|
if (!wire_read_int32 (plug_in->my_read, &plug_in->his_thread_id, 1))
|
|
|
|
{
|
|
|
|
g_message ("unable to read plug-ins's thread id");
|
|
|
|
plug_in_destroy (plug_in);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (!plug_in->synchronous)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in->input_id = g_io_add_watch (plug_in->my_read,
|
|
|
|
G_IO_IN | G_IO_PRI,
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_recv_message,
|
|
|
|
plug_in);
|
|
|
|
|
|
|
|
open_plug_ins = g_slist_prepend (open_plug_ins, plug_in);
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in->open = TRUE;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_close (PlugIn *plug_in,
|
|
|
|
int kill_it)
|
|
|
|
{
|
|
|
|
int status;
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifndef NATIVE_WIN32
|
1997-11-25 06:05:25 +08:00
|
|
|
struct timeval tv;
|
1999-03-07 20:56:03 +08:00
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (plug_in && plug_in->open)
|
|
|
|
{
|
|
|
|
plug_in->open = FALSE;
|
|
|
|
|
|
|
|
/* Ask the filter to exit gracefully
|
|
|
|
*/
|
|
|
|
if (kill_it && plug_in->pid)
|
|
|
|
{
|
|
|
|
plug_in_push (plug_in);
|
1999-03-07 20:56:03 +08:00
|
|
|
gp_quit_write (current_writechannel);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_pop ();
|
|
|
|
|
|
|
|
/* give the plug-in some time (10 ms) */
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifndef NATIVE_WIN32
|
1997-11-25 06:05:25 +08:00
|
|
|
tv.tv_sec = 0;
|
1999-03-07 20:56:03 +08:00
|
|
|
tv.tv_usec = 100; /* But this is 0.1 ms? */
|
1997-11-25 06:05:25 +08:00
|
|
|
select (0, NULL, NULL, NULL, &tv);
|
1999-03-07 20:56:03 +08:00
|
|
|
#else
|
|
|
|
Sleep (10);
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If necessary, kill the filter.
|
|
|
|
*/
|
1999-03-07 20:56:03 +08:00
|
|
|
#ifndef NATIVE_WIN32
|
1997-11-25 06:05:25 +08:00
|
|
|
if (kill_it && plug_in->pid)
|
|
|
|
status = kill (plug_in->pid, SIGKILL);
|
|
|
|
|
|
|
|
/* Wait for the process to exit. This will happen
|
|
|
|
* immediately if it was just killed.
|
|
|
|
*/
|
|
|
|
if (plug_in->pid)
|
|
|
|
waitpid (plug_in->pid, &status, 0);
|
1999-03-07 20:56:03 +08:00
|
|
|
#else
|
|
|
|
if (kill_it && plug_in->pid)
|
|
|
|
TerminateProcess ((HANDLE) plug_in->pid, 0);
|
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Remove the input handler.
|
|
|
|
*/
|
|
|
|
if (plug_in->input_id)
|
|
|
|
gdk_input_remove (plug_in->input_id);
|
|
|
|
|
|
|
|
/* Close the pipes.
|
|
|
|
*/
|
1999-03-07 20:56:03 +08:00
|
|
|
if (plug_in->my_read != NULL)
|
|
|
|
{
|
|
|
|
g_io_channel_close (plug_in->my_read);
|
|
|
|
g_io_channel_unref (plug_in->my_read);
|
|
|
|
plug_in->my_read = NULL;
|
|
|
|
}
|
|
|
|
if (plug_in->my_write != NULL)
|
|
|
|
{
|
|
|
|
g_io_channel_close (plug_in->my_write);
|
|
|
|
g_io_channel_unref (plug_in->my_write);
|
|
|
|
plug_in->my_write = NULL;
|
|
|
|
}
|
|
|
|
if (plug_in->his_read != NULL)
|
|
|
|
{
|
|
|
|
g_io_channel_close (plug_in->his_read);
|
|
|
|
g_io_channel_unref (plug_in->his_read);
|
|
|
|
plug_in->his_read = NULL;
|
|
|
|
}
|
|
|
|
if (plug_in->his_write != NULL)
|
|
|
|
{
|
|
|
|
g_io_channel_close (plug_in->his_write);
|
|
|
|
g_io_channel_unref (plug_in->his_write);
|
|
|
|
plug_in->his_write = NULL;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
wire_clear_error();
|
|
|
|
|
|
|
|
/* Destroy the progress dialog if it exists
|
|
|
|
*/
|
|
|
|
if (plug_in->progress)
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
progress_end (plug_in->progress);
|
|
|
|
plug_in->progress = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set the fields to null values.
|
|
|
|
*/
|
|
|
|
plug_in->pid = 0;
|
|
|
|
plug_in->input_id = 0;
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in->my_read = NULL;
|
|
|
|
plug_in->my_write = NULL;
|
|
|
|
plug_in->his_read = NULL;
|
|
|
|
plug_in->his_write = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (plug_in->recurse)
|
|
|
|
gtk_main_quit ();
|
|
|
|
|
|
|
|
plug_in->synchronous = FALSE;
|
|
|
|
plug_in->recurse = FALSE;
|
|
|
|
|
|
|
|
/* Unregister any temporary procedures
|
|
|
|
*/
|
|
|
|
if (plug_in->temp_proc_defs)
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
|
|
|
|
list = plug_in->temp_proc_defs;
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
proc_def = (PlugInProcDef *) list->data;
|
|
|
|
plug_in_proc_def_remove (proc_def);
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free (plug_in->temp_proc_defs);
|
|
|
|
plug_in->temp_proc_defs = NULL;
|
|
|
|
}
|
|
|
|
|
1998-09-19 08:40:27 +08:00
|
|
|
/* Close any dialogs that this plugin might have opened */
|
|
|
|
brushes_check_dialogs();
|
1998-10-02 06:09:01 +08:00
|
|
|
patterns_check_dialogs();
|
1998-11-01 00:22:37 +08:00
|
|
|
gradients_check_dialogs();
|
1998-09-19 08:40:27 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
open_plug_ins = g_slist_remove (open_plug_ins, plug_in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Argument *
|
|
|
|
plug_in_get_current_return_vals (ProcRecord *proc_rec)
|
|
|
|
{
|
|
|
|
Argument *return_vals;
|
|
|
|
int nargs;
|
|
|
|
|
|
|
|
/* Return the status code plus the current return values. */
|
|
|
|
nargs = proc_rec->num_values + 1;
|
|
|
|
if (current_return_vals && current_return_nvals == nargs)
|
|
|
|
return_vals = current_return_vals;
|
|
|
|
else if (current_return_vals)
|
|
|
|
{
|
|
|
|
/* Allocate new return values of the correct size. */
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, FALSE);
|
|
|
|
|
|
|
|
/* Copy all of the arguments we can. */
|
|
|
|
memcpy (return_vals, current_return_vals,
|
|
|
|
sizeof (Argument) * MIN (current_return_nvals, nargs));
|
|
|
|
|
|
|
|
/* Free the old argument pointer. This will cause a memory leak
|
|
|
|
only if there were more values returned than we need (which
|
|
|
|
shouldn't ever happen). */
|
|
|
|
g_free (current_return_vals);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Just return a dummy set of values. */
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We have consumed any saved values, so clear them. */
|
|
|
|
current_return_nvals = 0;
|
|
|
|
current_return_vals = NULL;
|
|
|
|
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
Argument*
|
|
|
|
plug_in_run (ProcRecord *proc_rec,
|
|
|
|
Argument *args,
|
1998-10-22 03:10:14 +08:00
|
|
|
int argc,
|
1997-11-25 06:05:25 +08:00
|
|
|
int synchronous,
|
1998-06-14 12:33:27 +08:00
|
|
|
int destroy_values,
|
|
|
|
int gdisp_ID)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GPConfig config;
|
|
|
|
GPProcRun proc_run;
|
|
|
|
Argument *return_vals;
|
|
|
|
PlugIn *plug_in;
|
|
|
|
|
|
|
|
return_vals = NULL;
|
|
|
|
|
|
|
|
if (proc_rec->proc_type == PDB_TEMPORARY)
|
|
|
|
{
|
1998-10-22 03:10:14 +08:00
|
|
|
return_vals = plug_in_temp_run (proc_rec, args, argc);
|
1997-11-25 06:05:25 +08:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in = plug_in_new (proc_rec->exec_method.plug_in.filename);
|
|
|
|
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
if (plug_in_open (plug_in))
|
|
|
|
{
|
|
|
|
plug_in->recurse = synchronous;
|
|
|
|
|
|
|
|
plug_in_push (plug_in);
|
|
|
|
|
|
|
|
config.version = GP_VERSION;
|
|
|
|
config.tile_width = TILE_WIDTH;
|
|
|
|
config.tile_height = TILE_HEIGHT;
|
|
|
|
config.shm_ID = shm_ID;
|
|
|
|
config.gamma = gamma_val;
|
|
|
|
config.install_cmap = install_cmap;
|
|
|
|
config.use_xshm = gdk_get_use_xshm ();
|
|
|
|
config.color_cube[0] = color_cube_shades[0];
|
|
|
|
config.color_cube[1] = color_cube_shades[1];
|
|
|
|
config.color_cube[2] = color_cube_shades[2];
|
|
|
|
config.color_cube[3] = color_cube_shades[3];
|
1998-06-14 12:33:27 +08:00
|
|
|
config.gdisp_ID = gdisp_ID;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
proc_run.name = proc_rec->name;
|
1998-10-22 03:10:14 +08:00
|
|
|
proc_run.nparams = argc;
|
|
|
|
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_config_write (current_writechannel, &config) ||
|
|
|
|
!gp_proc_run_write (current_writechannel, &proc_run) ||
|
|
|
|
!wire_flush (current_writechannel))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, FALSE);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in_pop ();
|
|
|
|
|
|
|
|
plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is an automatically installed extension, wait for an
|
|
|
|
* installation-confirmation message
|
|
|
|
*/
|
|
|
|
if ((proc_rec->proc_type == PDB_EXTENSION) && (proc_rec->num_args == 0))
|
|
|
|
gtk_main ();
|
|
|
|
|
|
|
|
if (plug_in->recurse)
|
|
|
|
{
|
|
|
|
gtk_main ();
|
|
|
|
|
|
|
|
return_vals = plug_in_get_current_return_vals (proc_rec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (return_vals && destroy_values)
|
|
|
|
{
|
|
|
|
procedural_db_destroy_args (return_vals, proc_rec->num_values);
|
|
|
|
return_vals = NULL;
|
|
|
|
}
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
plug_in_repeat (int with_interface)
|
|
|
|
{
|
|
|
|
GDisplay *gdisplay;
|
|
|
|
Argument *args;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (last_plug_in)
|
|
|
|
{
|
|
|
|
gdisplay = gdisplay_active ();
|
1999-06-22 06:12:07 +08:00
|
|
|
if (!gdisplay) return;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* construct the procedures arguments */
|
1998-10-22 03:10:14 +08:00
|
|
|
args = g_new (Argument, 3);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-10-22 03:10:14 +08:00
|
|
|
/* initialize the first three argument types */
|
|
|
|
for (i = 0; i < 3; i++)
|
1997-11-25 06:05:25 +08:00
|
|
|
args[i].arg_type = last_plug_in->args[i].arg_type;
|
|
|
|
|
1998-10-22 03:10:14 +08:00
|
|
|
/* initialize the first three plug-in arguments */
|
1997-11-25 06:05:25 +08:00
|
|
|
args[0].value.pdb_int = (with_interface ? RUN_INTERACTIVE : RUN_WITH_LAST_VALS);
|
1998-06-30 23:31:32 +08:00
|
|
|
args[1].value.pdb_int = pdb_image_to_id(gdisplay->gimage);
|
1998-01-22 15:02:57 +08:00
|
|
|
args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* run the plug-in procedure */
|
1998-10-22 03:10:14 +08:00
|
|
|
plug_in_run (last_plug_in, args, 3, FALSE, TRUE, gdisplay->ID);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
g_free (args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
plug_in_set_menu_sensitivity (GimpImageType type)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
1998-05-05 10:38:10 +08:00
|
|
|
int sensitive = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
tmp = proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (proc_def->image_types_val && proc_def->menu_path)
|
1998-05-05 10:38:10 +08:00
|
|
|
{
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
switch (type)
|
1998-05-05 10:38:10 +08:00
|
|
|
{
|
|
|
|
case RGB_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & RGB_IMAGE;
|
|
|
|
break;
|
|
|
|
case RGBA_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & RGBA_IMAGE;
|
|
|
|
break;
|
|
|
|
case GRAY_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & GRAY_IMAGE;
|
|
|
|
break;
|
|
|
|
case GRAYA_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & GRAYA_IMAGE;
|
|
|
|
break;
|
|
|
|
case INDEXED_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & INDEXED_IMAGE;
|
|
|
|
break;
|
|
|
|
case INDEXEDA_GIMAGE:
|
|
|
|
sensitive = proc_def->image_types_val & INDEXEDA_IMAGE;
|
|
|
|
break;
|
1999-09-26 17:57:32 +08:00
|
|
|
default:
|
|
|
|
sensitive = FALSE;
|
|
|
|
break;
|
1998-05-05 10:38:10 +08:00
|
|
|
}
|
|
|
|
|
1999-06-07 05:13:03 +08:00
|
|
|
menus_set_sensitive (proc_def->menu_path, sensitive);
|
1998-05-05 10:38:10 +08:00
|
|
|
if (last_plug_in && (last_plug_in == &(proc_def->db_info)))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
menus_set_sensitive_glue ("<Image>", N_("/Filters/Repeat last"), sensitive);
|
|
|
|
menus_set_sensitive_glue ("<Image>", N_("/Filters/Re-show last"), sensitive);
|
1998-05-05 10:38:10 +08:00
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
static gboolean
|
|
|
|
plug_in_recv_message (GIOChannel *channel,
|
|
|
|
GIOCondition cond,
|
|
|
|
gpointer data)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
WireMessage msg;
|
|
|
|
|
|
|
|
plug_in_push ((PlugIn*) data);
|
1999-03-07 20:56:03 +08:00
|
|
|
if (current_readchannel == NULL)
|
|
|
|
return TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
memset (&msg, 0, sizeof (WireMessage));
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!wire_read_msg (current_readchannel, &msg))
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
plug_in_handle_message (&msg);
|
|
|
|
wire_destroy (&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!current_plug_in->open)
|
|
|
|
plug_in_destroy (current_plug_in);
|
|
|
|
else
|
|
|
|
plug_in_pop ();
|
1999-03-07 20:56:03 +08:00
|
|
|
return TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_handle_message (WireMessage *msg)
|
|
|
|
{
|
|
|
|
switch (msg->type)
|
|
|
|
{
|
|
|
|
case GP_QUIT:
|
|
|
|
plug_in_handle_quit ();
|
|
|
|
break;
|
|
|
|
case GP_CONFIG:
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_message(): received a config message (should not happen)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
break;
|
|
|
|
case GP_TILE_REQ:
|
|
|
|
plug_in_handle_tile_req (msg->data);
|
|
|
|
break;
|
|
|
|
case GP_TILE_ACK:
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_message(): received a config message (should not happen)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
break;
|
|
|
|
case GP_TILE_DATA:
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_message(): received a config message (should not happen)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
break;
|
|
|
|
case GP_PROC_RUN:
|
|
|
|
plug_in_handle_proc_run (msg->data);
|
|
|
|
break;
|
|
|
|
case GP_PROC_RETURN:
|
|
|
|
plug_in_handle_proc_return (msg->data);
|
|
|
|
plug_in_close (current_plug_in, FALSE);
|
|
|
|
break;
|
|
|
|
case GP_TEMP_PROC_RUN:
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_message(): received a temp proc run message (should not happen)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
break;
|
|
|
|
case GP_TEMP_PROC_RETURN:
|
|
|
|
plug_in_handle_proc_return (msg->data);
|
|
|
|
gtk_main_quit ();
|
|
|
|
break;
|
|
|
|
case GP_PROC_INSTALL:
|
|
|
|
plug_in_handle_proc_install (msg->data);
|
|
|
|
break;
|
|
|
|
case GP_PROC_UNINSTALL:
|
|
|
|
plug_in_handle_proc_uninstall (msg->data);
|
|
|
|
break;
|
|
|
|
case GP_EXTENSION_ACK:
|
|
|
|
gtk_main_quit ();
|
|
|
|
break;
|
1999-03-07 20:56:03 +08:00
|
|
|
case GP_REQUEST_WAKEUPS:
|
|
|
|
#ifdef NATIVE_WIN32
|
|
|
|
g_io_channel_win32_pipe_request_wakeups (current_plug_in->my_write,
|
|
|
|
current_plug_in->his_thread_id,
|
|
|
|
current_plug_in->his_read_fd);
|
|
|
|
#endif
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_handle_quit (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
plug_in_close (current_plug_in, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_handle_tile_req (GPTileReq *tile_req)
|
|
|
|
{
|
|
|
|
GPTileData tile_data;
|
|
|
|
GPTileData *tile_info;
|
|
|
|
WireMessage msg;
|
|
|
|
TileManager *tm;
|
|
|
|
Tile *tile;
|
|
|
|
|
|
|
|
if (tile_req->drawable_ID == -1)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_tile_data_write (current_writechannel, &tile_data))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!wire_read_msg (current_readchannel, &msg))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.type != GP_TILE_DATA)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("expected tile data and received: %d", msg.type);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tile_info = msg.data;
|
|
|
|
|
|
|
|
if (tile_info->shadow)
|
1998-01-22 15:02:57 +08:00
|
|
|
tm = drawable_shadow (drawable_get_ID (tile_info->drawable_ID));
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
1998-01-22 15:02:57 +08:00
|
|
|
tm = drawable_data (drawable_get_ID (tile_info->drawable_ID));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (!tm)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug-in requested invalid drawable (killing)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-08-16 03:17:36 +08:00
|
|
|
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (!tile)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug-in requested invalid tile (killing)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile_data.use_shm)
|
1998-08-12 01:35:34 +08:00
|
|
|
memcpy (tile_data_pointer (tile, 0, 0), shm_addr, tile_size (tile));
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
1998-08-12 01:35:34 +08:00
|
|
|
memcpy (tile_data_pointer (tile, 0, 0), tile_info->data, tile_size (tile));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (tile, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
wire_destroy (&msg);
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_tile_ack_write (current_writechannel))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_tile_req: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (tile_req->shadow)
|
1998-01-22 15:02:57 +08:00
|
|
|
tm = drawable_shadow (drawable_get_ID (tile_req->drawable_ID));
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
1998-01-22 15:02:57 +08:00
|
|
|
tm = drawable_data (drawable_get_ID (tile_req->drawable_ID));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (!tm)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug-in requested invalid drawable (killing)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-08-16 03:17:36 +08:00
|
|
|
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (!tile)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug-in requested invalid tile (killing)");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_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;
|
1998-08-12 01:35:34 +08:00
|
|
|
tile_data.bpp = tile_bpp(tile);
|
|
|
|
tile_data.width = tile_ewidth(tile);
|
|
|
|
tile_data.height = tile_eheight(tile);
|
1997-11-25 06:05:25 +08:00
|
|
|
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
|
|
|
|
|
|
|
|
if (tile_data.use_shm)
|
1998-08-12 01:35:34 +08:00
|
|
|
memcpy (shm_addr, tile_data_pointer (tile, 0, 0), tile_size (tile));
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
1998-08-12 01:35:34 +08:00
|
|
|
tile_data.data = tile_data_pointer (tile, 0, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_tile_data_write (current_writechannel, &tile_data))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_message ("plug_in_handle_tile_req: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (tile, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!wire_read_msg (current_readchannel, &msg))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_message ("plug_in_handle_tile_req: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.type != GP_TILE_ACK)
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("expected tile ack and received: %d", msg.type);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wire_destroy (&msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_handle_proc_run (GPProcRun *proc_run)
|
|
|
|
{
|
|
|
|
GPProcReturn proc_return;
|
|
|
|
ProcRecord *proc_rec;
|
|
|
|
Argument *args;
|
|
|
|
Argument *return_vals;
|
|
|
|
PlugInBlocked *blocked;
|
|
|
|
|
|
|
|
args = plug_in_params_to_args (proc_run->params, proc_run->nparams, FALSE);
|
|
|
|
proc_rec = procedural_db_lookup (proc_run->name);
|
|
|
|
|
1999-06-28 21:28:37 +08:00
|
|
|
if (proc_rec)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-28 21:28:37 +08:00
|
|
|
return_vals = procedural_db_execute (proc_run->name, args);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* if the name lookup failed, construct a
|
|
|
|
* dummy "executiuon error" return value --Michael
|
|
|
|
*/
|
|
|
|
return_vals = g_new (Argument, 1);
|
|
|
|
return_vals[0].arg_type = PDB_INT32;
|
|
|
|
return_vals[0].value.pdb_int = PDB_EXECUTION_ERROR;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (return_vals)
|
|
|
|
{
|
|
|
|
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_rec->num_values + 1, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
proc_return.nparams = 1;
|
|
|
|
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
|
|
|
|
}
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_proc_return_write (current_writechannel, &proc_return))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("plug_in_handle_proc_run: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in_args_destroy (args, proc_run->nparams, FALSE);
|
|
|
|
plug_in_args_destroy (return_vals, (proc_rec ? (proc_rec->num_values + 1) : 1), TRUE);
|
|
|
|
plug_in_params_destroy (proc_return.params, proc_return.nparams, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
blocked = g_new (PlugInBlocked, 1);
|
|
|
|
blocked->plug_in = current_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 (GPProcReturn *proc_return)
|
|
|
|
{
|
|
|
|
PlugInBlocked *blocked;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (current_plug_in->recurse)
|
|
|
|
{
|
|
|
|
current_return_vals = plug_in_params_to_args (proc_return->params,
|
|
|
|
proc_return->nparams,
|
|
|
|
TRUE);
|
|
|
|
current_return_nvals = proc_return->nparams;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp = blocked_plug_ins;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
blocked = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (blocked->proc_name, proc_return->name) == 0)
|
|
|
|
{
|
|
|
|
plug_in_push (blocked->plug_in);
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_proc_return_write (current_writechannel, proc_return))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_message ("plug_in_handle_proc_run: ERROR");
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
plug_in_pop ();
|
|
|
|
|
|
|
|
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_install (GPProcInstall *proc_install)
|
|
|
|
{
|
|
|
|
PlugInDef *plug_in_def = NULL;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
ProcRecord *proc = NULL;
|
|
|
|
GSList *tmp = NULL;
|
|
|
|
GtkMenuEntry entry;
|
|
|
|
char *prog = NULL;
|
|
|
|
int add_proc_def;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Argument checking
|
|
|
|
* --only sanity check arguments when the procedure requests a menu path
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (proc_install->menu_path)
|
|
|
|
{
|
|
|
|
if (strncmp (proc_install->menu_path, "<Toolbox>", 9) == 0)
|
|
|
|
{
|
|
|
|
if ((proc_install->nparams < 1) ||
|
|
|
|
(proc_install->params[0].type != PDB_INT32))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
|
|
|
|
"does not take the standard plug-in args",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strncmp (proc_install->menu_path, "<Image>", 7) == 0)
|
|
|
|
{
|
|
|
|
if ((proc_install->nparams < 3) ||
|
|
|
|
(proc_install->params[0].type != PDB_INT32) ||
|
|
|
|
(proc_install->params[1].type != PDB_IMAGE) ||
|
|
|
|
(proc_install->params[2].type != PDB_DRAWABLE))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
|
|
|
|
"does not take the standard plug-in args",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strncmp (proc_install->menu_path, "<Load>", 6) == 0)
|
|
|
|
{
|
|
|
|
if ((proc_install->nparams < 3) ||
|
|
|
|
(proc_install->params[0].type != PDB_INT32) ||
|
|
|
|
(proc_install->params[1].type != PDB_STRING) ||
|
|
|
|
(proc_install->params[2].type != PDB_STRING))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
|
|
|
|
"does not take the standard plug-in args",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strncmp (proc_install->menu_path, "<Save>", 6) == 0)
|
|
|
|
{
|
|
|
|
if ((proc_install->nparams < 5) ||
|
|
|
|
(proc_install->params[0].type != PDB_INT32) ||
|
|
|
|
(proc_install->params[1].type != PDB_IMAGE) ||
|
|
|
|
(proc_install->params[2].type != PDB_DRAWABLE) ||
|
|
|
|
(proc_install->params[3].type != PDB_STRING) ||
|
|
|
|
(proc_install->params[4].type != PDB_STRING))
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
|
|
|
|
"does not take the standard plug-in args",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" in "
|
1997-11-25 06:05:25 +08:00
|
|
|
"an invalid menu location. Use either \"<Toolbox>\", \"<Image>\", "
|
1999-09-23 19:49:16 +08:00
|
|
|
"\"<Load>\", or \"<Save>\".",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sanity check for array arguments
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = 1; i < proc_install->nparams; i++)
|
|
|
|
{
|
|
|
|
if ((proc_install->params[i].type == PDB_INT32ARRAY ||
|
|
|
|
proc_install->params[i].type == PDB_INT8ARRAY ||
|
|
|
|
proc_install->params[i].type == PDB_FLOATARRAY ||
|
|
|
|
proc_install->params[i].type == PDB_STRINGARRAY) &&
|
|
|
|
proc_install->params[i-1].type != PDB_INT32)
|
|
|
|
{
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("plug_in \"%s\" attempted to install procedure \"%s\" "
|
1997-11-25 06:05:25 +08:00
|
|
|
"which fails to comply with the array parameter "
|
1999-09-23 19:49:16 +08:00
|
|
|
"passing standard. Argument %d is noncompliant.",
|
1997-11-25 06:05:25 +08:00
|
|
|
current_plug_in->args[0], proc_install->name, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialization
|
|
|
|
*/
|
|
|
|
proc_def = NULL;
|
|
|
|
|
|
|
|
switch (proc_install->type)
|
|
|
|
{
|
|
|
|
case PDB_PLUGIN:
|
|
|
|
case PDB_EXTENSION:
|
|
|
|
plug_in_def = current_plug_in->user_data;
|
|
|
|
prog = plug_in_def->prog;
|
|
|
|
|
|
|
|
tmp = plug_in_def->proc_defs;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDB_TEMPORARY:
|
1998-03-01 09:18:45 +08:00
|
|
|
prog = "none";
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
tmp = current_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)
|
|
|
|
{
|
|
|
|
if (proc_install->type == PDB_TEMPORARY)
|
|
|
|
plug_in_proc_def_remove (proc_def);
|
|
|
|
else
|
|
|
|
plug_in_proc_def_destroy (proc_def, TRUE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc_def = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_proc_def = FALSE;
|
|
|
|
if (!proc_def)
|
|
|
|
{
|
|
|
|
add_proc_def = TRUE;
|
|
|
|
proc_def = g_new (PlugInProcDef, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
proc_def->prog = g_strdup (prog);
|
|
|
|
|
|
|
|
proc_def->menu_path = g_strdup (proc_install->menu_path);
|
|
|
|
proc_def->accelerator = NULL;
|
|
|
|
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_in_image_types_parse (proc_def->image_types);
|
1999-01-31 09:08:26 +08:00
|
|
|
/* Install temp one use todays time */
|
|
|
|
proc_def->mtime = time(NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
proc = &proc_def->db_info;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The procedural database procedure
|
|
|
|
*/
|
|
|
|
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_new (ProcArg, proc->num_args);
|
|
|
|
proc->values = g_new (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 PDB_PLUGIN:
|
|
|
|
case PDB_EXTENSION:
|
|
|
|
if (add_proc_def)
|
|
|
|
plug_in_def->proc_defs = g_slist_prepend (plug_in_def->proc_defs, proc_def);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDB_TEMPORARY:
|
|
|
|
if (add_proc_def)
|
|
|
|
current_plug_in->temp_proc_defs = g_slist_prepend (current_plug_in->temp_proc_defs, proc_def);
|
|
|
|
|
|
|
|
proc_defs = g_slist_append (proc_defs, proc_def);
|
|
|
|
proc->exec_method.temporary.plug_in = (void *) current_plug_in;
|
|
|
|
procedural_db_register (proc);
|
|
|
|
|
|
|
|
/* If there is a menu path specified, create a menu entry */
|
|
|
|
if (proc_install->menu_path)
|
|
|
|
{
|
1998-03-01 09:18:45 +08:00
|
|
|
entry.path = proc_install->menu_path;
|
1997-11-25 06:05:25 +08:00
|
|
|
entry.accelerator = NULL;
|
|
|
|
entry.callback = plug_in_callback;
|
|
|
|
entry.callback_data = proc;
|
|
|
|
|
|
|
|
menus_create (&entry, 1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
|
|
|
|
{
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = current_plug_in->temp_proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, proc_uninstall->name) == 0)
|
|
|
|
{
|
|
|
|
current_plug_in->temp_proc_defs = g_slist_remove (current_plug_in->temp_proc_defs, proc_def);
|
|
|
|
plug_in_proc_def_remove (proc_def);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in_write (GIOChannel *channel,
|
|
|
|
guint8 *buf,
|
|
|
|
gulong count)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
gulong bytes;
|
|
|
|
|
|
|
|
while (count > 0)
|
|
|
|
{
|
|
|
|
if ((current_write_buffer_index + count) >= WRITE_BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
|
|
|
|
memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
|
|
|
|
current_write_buffer_index += bytes;
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!wire_flush (channel))
|
1997-11-25 06:05:25 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bytes = count;
|
|
|
|
memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
|
|
|
|
current_write_buffer_index += bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf += bytes;
|
|
|
|
count -= bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in_flush (GIOChannel *channel)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
GIOError error;
|
1997-11-25 06:05:25 +08:00
|
|
|
int count;
|
1999-04-23 14:07:09 +08:00
|
|
|
guint bytes;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (current_write_buffer_index > 0)
|
|
|
|
{
|
|
|
|
count = 0;
|
|
|
|
while (count != current_write_buffer_index)
|
|
|
|
{
|
|
|
|
do {
|
1999-03-07 20:56:03 +08:00
|
|
|
bytes = 0;
|
|
|
|
error = g_io_channel_write (channel, ¤t_write_buffer[count],
|
|
|
|
(current_write_buffer_index - count),
|
|
|
|
&bytes);
|
|
|
|
} while (error == G_IO_ERROR_AGAIN);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (error != G_IO_ERROR_NONE)
|
1997-11-25 06:05:25 +08:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
count += bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_write_buffer_index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_push (PlugIn *plug_in)
|
|
|
|
{
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
current_plug_in = plug_in;
|
|
|
|
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
current_readchannel = current_plug_in->my_read;
|
|
|
|
current_writechannel = current_plug_in->my_write;
|
1997-11-25 06:05:25 +08:00
|
|
|
current_write_buffer_index = current_plug_in->write_buffer_index;
|
|
|
|
current_write_buffer = current_plug_in->write_buffer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
current_readchannel = NULL;
|
|
|
|
current_writechannel = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
current_write_buffer_index = 0;
|
|
|
|
current_write_buffer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_pop (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
if (current_plug_in)
|
|
|
|
{
|
|
|
|
current_plug_in->write_buffer_index = current_write_buffer_index;
|
|
|
|
|
|
|
|
tmp = plug_in_stack;
|
|
|
|
plug_in_stack = plug_in_stack->next;
|
|
|
|
tmp->next = NULL;
|
|
|
|
g_slist_free (tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (plug_in_stack)
|
|
|
|
{
|
|
|
|
current_plug_in = plug_in_stack->data;
|
1999-03-07 20:56:03 +08:00
|
|
|
current_readchannel = current_plug_in->my_read;
|
|
|
|
current_writechannel = current_plug_in->my_write;
|
1997-11-25 06:05:25 +08:00
|
|
|
current_write_buffer_index = current_plug_in->write_buffer_index;
|
|
|
|
current_write_buffer = current_plug_in->write_buffer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
current_plug_in = NULL;
|
1999-03-07 20:56:03 +08:00
|
|
|
current_readchannel = NULL;
|
|
|
|
current_writechannel = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
current_write_buffer_index = 0;
|
|
|
|
current_write_buffer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_write_rc_string (FILE *fp,
|
|
|
|
char *str)
|
|
|
|
{
|
|
|
|
fputc ('"', fp);
|
|
|
|
|
|
|
|
if (str)
|
|
|
|
while (*str)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
if (*str == '\n')
|
|
|
|
{
|
|
|
|
fputc ('\\', fp);
|
|
|
|
fputc ('n', fp);
|
|
|
|
}
|
|
|
|
else if (*str == '\r')
|
|
|
|
{
|
|
|
|
fputc ('\\', fp);
|
|
|
|
fputc ('r', fp);
|
|
|
|
}
|
|
|
|
else if (*str == '\032') /* ^Z is problematic on Windows */
|
|
|
|
{
|
|
|
|
fputc ('\\', fp);
|
|
|
|
fputc ('z', fp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((*str == '"') || (*str == '\\'))
|
|
|
|
fputc ('\\', fp);
|
|
|
|
fputc (*str, fp);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
str += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fputc ('"', fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_write_rc (char *filename)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp, *tmp2;
|
|
|
|
int i;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
fp = fopen (filename, "w");
|
1997-11-25 06:05:25 +08:00
|
|
|
if (!fp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (plug_in_def->proc_defs)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
fprintf (fp, "(plug-in-def ");
|
|
|
|
plug_in_write_rc_string (fp, plug_in_def->prog);
|
|
|
|
fprintf (fp, " %ld", (long) plug_in_def->mtime);
|
1997-11-25 06:05:25 +08:00
|
|
|
tmp2 = plug_in_def->proc_defs;
|
|
|
|
if (tmp2)
|
|
|
|
fprintf (fp, "\n");
|
|
|
|
|
|
|
|
while (tmp2)
|
|
|
|
{
|
|
|
|
proc_def = tmp2->data;
|
|
|
|
tmp2 = tmp2->next;
|
|
|
|
|
|
|
|
fprintf (fp, " (proc-def \"%s\" %d\n",
|
|
|
|
proc_def->db_info.name, proc_def->db_info.proc_type);
|
|
|
|
fprintf (fp, " ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.blurb);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.help);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.author);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.copyright);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.date);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->menu_path);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->extensions);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->prefixes);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->magics);
|
|
|
|
fprintf (fp, "\n ");
|
|
|
|
plug_in_write_rc_string (fp, proc_def->image_types);
|
|
|
|
fprintf (fp, "\n %d %d\n",
|
|
|
|
proc_def->db_info.num_args, proc_def->db_info.num_values);
|
|
|
|
|
|
|
|
for (i = 0; i < proc_def->db_info.num_args; i++)
|
|
|
|
{
|
|
|
|
fprintf (fp, " (proc-arg %d ",
|
|
|
|
proc_def->db_info.args[i].arg_type);
|
|
|
|
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.args[i].name);
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.args[i].description);
|
|
|
|
|
|
|
|
fprintf (fp, ")%s",
|
|
|
|
(proc_def->db_info.num_values ||
|
|
|
|
(i < (proc_def->db_info.num_args - 1))) ? "\n" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < proc_def->db_info.num_values; i++)
|
|
|
|
{
|
|
|
|
fprintf (fp, " (proc-arg %d ",
|
|
|
|
proc_def->db_info.values[i].arg_type);
|
|
|
|
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.values[i].name);
|
|
|
|
plug_in_write_rc_string (fp, proc_def->db_info.values[i].description);
|
|
|
|
|
|
|
|
fprintf (fp, ")%s", (i < (proc_def->db_info.num_values - 1)) ? "\n" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf (fp, ")");
|
|
|
|
|
|
|
|
if (tmp2)
|
|
|
|
fprintf (fp, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf (fp, ")\n");
|
|
|
|
|
|
|
|
if (tmp)
|
|
|
|
fprintf (fp, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose (fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_init_file (char *filename)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
char *plug_in_name;
|
|
|
|
char *name;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
name = strrchr (filename, G_DIR_SEPARATOR);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (name)
|
|
|
|
name = name + 1;
|
|
|
|
else
|
|
|
|
name = filename;
|
|
|
|
|
|
|
|
plug_in_def = NULL;
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
|
1997-11-25 06:05:25 +08:00
|
|
|
if (plug_in_name)
|
|
|
|
plug_in_name = plug_in_name + 1;
|
|
|
|
else
|
|
|
|
plug_in_name = plug_in_def->prog;
|
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (g_strcasecmp (name, plug_in_name) == 0)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-09-26 17:57:32 +08:00
|
|
|
g_print ("duplicate plug-in: \"%s\" (skipping)\n", filename);
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in_def = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in_def = g_new (PlugInDef, 1);
|
|
|
|
plug_in_def->prog = g_strdup (filename);
|
|
|
|
plug_in_def->proc_defs = NULL;
|
|
|
|
plug_in_def->mtime = datafile_mtime ();
|
|
|
|
plug_in_def->query = TRUE;
|
|
|
|
|
|
|
|
plug_in_defs = g_slist_append (plug_in_defs, plug_in_def);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_query (char *filename,
|
|
|
|
PlugInDef *plug_in_def)
|
|
|
|
{
|
|
|
|
PlugIn *plug_in;
|
|
|
|
WireMessage msg;
|
|
|
|
|
|
|
|
plug_in = plug_in_new (filename);
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
plug_in->query = TRUE;
|
|
|
|
plug_in->synchronous = TRUE;
|
|
|
|
plug_in->user_data = plug_in_def;
|
|
|
|
|
|
|
|
if (plug_in_open (plug_in))
|
|
|
|
{
|
|
|
|
plug_in_push (plug_in);
|
|
|
|
|
|
|
|
while (plug_in->open)
|
|
|
|
{
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!wire_read_msg (current_readchannel, &msg))
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_close (current_plug_in, TRUE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
plug_in_handle_message (&msg);
|
|
|
|
wire_destroy (&msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in_pop ();
|
1998-01-25 09:24:46 +08:00
|
|
|
plug_in_destroy (plug_in);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_add_to_db (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
Argument args[4];
|
|
|
|
Argument *return_vals;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = proc_defs;
|
|
|
|
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (proc_def->prog && (proc_def->db_info.proc_type != PDB_INTERNAL))
|
|
|
|
{
|
|
|
|
proc_def->db_info.exec_method.plug_in.filename = proc_def->prog;
|
|
|
|
procedural_db_register (&proc_def->db_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (tmp = proc_defs; tmp; tmp = tmp->next)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
|
|
|
|
if (proc_def->extensions || proc_def->prefixes || proc_def->magics)
|
|
|
|
{
|
|
|
|
args[0].arg_type = PDB_STRING;
|
|
|
|
args[0].value.pdb_pointer = proc_def->db_info.name;
|
|
|
|
|
|
|
|
args[1].arg_type = PDB_STRING;
|
|
|
|
args[1].value.pdb_pointer = proc_def->extensions;
|
|
|
|
|
|
|
|
args[2].arg_type = PDB_STRING;
|
|
|
|
args[2].value.pdb_pointer = proc_def->prefixes;
|
|
|
|
|
|
|
|
args[3].arg_type = PDB_STRING;
|
|
|
|
args[3].value.pdb_pointer = proc_def->magics;
|
|
|
|
|
|
|
|
if (proc_def->image_types)
|
|
|
|
{
|
|
|
|
return_vals = procedural_db_execute ("gimp_register_save_handler", args);
|
|
|
|
g_free (return_vals);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return_vals = procedural_db_execute ("gimp_register_magic_load_handler", args);
|
|
|
|
g_free (return_vals);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-05-04 03:22:58 +08:00
|
|
|
plug_in_make_menu (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GtkMenuEntry entry;
|
|
|
|
PlugInProcDef *proc_def;
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
tmp = proc_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
proc_def = tmp->data;
|
|
|
|
tmp = tmp->next;
|
|
|
|
|
|
|
|
if (proc_def->prog && proc_def->menu_path && (!proc_def->extensions &&
|
|
|
|
!proc_def->prefixes &&
|
|
|
|
!proc_def->magics))
|
|
|
|
{
|
|
|
|
entry.path = proc_def->menu_path;
|
|
|
|
entry.accelerator = proc_def->accelerator;
|
|
|
|
entry.callback = plug_in_callback;
|
|
|
|
entry.callback_data = &proc_def->db_info;
|
|
|
|
|
|
|
|
menus_create (&entry, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_callback (GtkWidget *widget,
|
|
|
|
gpointer client_data)
|
|
|
|
{
|
|
|
|
GDisplay *gdisplay;
|
|
|
|
ProcRecord *proc_rec;
|
|
|
|
Argument *args;
|
|
|
|
int i;
|
1998-06-14 12:33:27 +08:00
|
|
|
int gdisp_ID = -1;
|
1998-10-22 03:10:14 +08:00
|
|
|
int argc = 0; /* calm down a gcc warning. */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* get the active gdisplay */
|
|
|
|
gdisplay = gdisplay_active ();
|
|
|
|
|
|
|
|
proc_rec = (ProcRecord*) client_data;
|
|
|
|
|
|
|
|
/* construct the procedures arguments */
|
|
|
|
args = g_new (Argument, proc_rec->num_args);
|
|
|
|
memset (args, 0, (sizeof (Argument) * proc_rec->num_args));
|
|
|
|
|
|
|
|
/* initialize the argument types */
|
|
|
|
for (i = 0; i < proc_rec->num_args; i++)
|
|
|
|
args[i].arg_type = proc_rec->args[i].arg_type;
|
|
|
|
|
|
|
|
switch (proc_rec->proc_type)
|
|
|
|
{
|
|
|
|
case PDB_EXTENSION:
|
|
|
|
/* initialize the first argument */
|
|
|
|
args[0].value.pdb_int = RUN_INTERACTIVE;
|
1998-10-22 03:10:14 +08:00
|
|
|
argc = 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PDB_PLUGIN:
|
|
|
|
if (gdisplay)
|
|
|
|
{
|
1998-06-14 12:33:27 +08:00
|
|
|
gdisp_ID = gdisplay->ID;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* initialize the first 3 plug-in arguments */
|
|
|
|
args[0].value.pdb_int = RUN_INTERACTIVE;
|
1998-06-30 23:31:32 +08:00
|
|
|
args[1].value.pdb_int = pdb_image_to_id(gdisplay->gimage);
|
1998-01-22 15:02:57 +08:00
|
|
|
args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
|
1998-10-22 03:10:14 +08:00
|
|
|
argc = 3;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("Uh-oh, no active gdisplay for the plug-in!");
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (args);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDB_TEMPORARY:
|
|
|
|
args[0].value.pdb_int = RUN_INTERACTIVE;
|
1998-10-25 04:11:17 +08:00
|
|
|
argc = 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
if (proc_rec->num_args >= 3 &&
|
|
|
|
proc_rec->args[1].arg_type == PDB_IMAGE &&
|
|
|
|
proc_rec->args[2].arg_type == PDB_DRAWABLE)
|
|
|
|
{
|
|
|
|
if (gdisplay)
|
|
|
|
{
|
1998-06-14 12:33:27 +08:00
|
|
|
gdisp_ID = gdisplay->ID;
|
|
|
|
|
1998-06-30 23:31:32 +08:00
|
|
|
args[1].value.pdb_int = pdb_image_to_id(gdisplay->gimage);
|
1998-01-22 15:02:57 +08:00
|
|
|
args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
|
1998-10-22 03:10:14 +08:00
|
|
|
argc = 3;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-06-06 07:41:45 +08:00
|
|
|
g_warning ("Uh-oh, no active gdisplay for the temporary procedure!");
|
1997-11-25 06:05:25 +08:00
|
|
|
g_free (args);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1999-09-23 19:49:16 +08:00
|
|
|
g_error ("Unknown procedure type.");
|
1998-10-22 03:10:14 +08:00
|
|
|
g_free (args);
|
|
|
|
return;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* run the plug-in procedure */
|
1998-10-22 03:10:14 +08:00
|
|
|
plug_in_run (proc_rec, args, argc, FALSE, TRUE, gdisp_ID);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (proc_rec->proc_type == PDB_PLUGIN)
|
|
|
|
last_plug_in = proc_rec;
|
|
|
|
|
|
|
|
g_free (args);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-02-14 09:53:23 +08:00
|
|
|
plug_in_proc_def_insert (PlugInProcDef *proc_def,
|
|
|
|
void (*superceed_fn)(void*))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PlugInProcDef *tmp_proc_def;
|
|
|
|
GSList *tmp, *prev;
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
prev = NULL;
|
|
|
|
tmp = proc_defs;
|
|
|
|
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
tmp_proc_def = tmp->data;
|
|
|
|
|
|
|
|
if (strcmp (proc_def->db_info.name, tmp_proc_def->db_info.name) == 0)
|
|
|
|
{
|
|
|
|
tmp->data = proc_def;
|
|
|
|
|
|
|
|
if (proc_def->menu_path)
|
|
|
|
g_free (proc_def->menu_path);
|
|
|
|
if (proc_def->accelerator)
|
|
|
|
g_free (proc_def->accelerator);
|
|
|
|
|
|
|
|
proc_def->menu_path = tmp_proc_def->menu_path;
|
|
|
|
proc_def->accelerator = tmp_proc_def->accelerator;
|
|
|
|
|
|
|
|
tmp_proc_def->menu_path = NULL;
|
|
|
|
tmp_proc_def->accelerator = NULL;
|
|
|
|
|
1999-02-14 09:53:23 +08:00
|
|
|
if (superceed_fn)
|
|
|
|
(*superceed_fn) (tmp_proc_def);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_proc_def_destroy (tmp_proc_def, FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (!proc_def->menu_path ||
|
|
|
|
(tmp_proc_def->menu_path &&
|
|
|
|
(strcmp (proc_def->menu_path, tmp_proc_def->menu_path) < 0)))
|
|
|
|
{
|
|
|
|
list = g_slist_alloc ();
|
|
|
|
list->data = proc_def;
|
|
|
|
|
|
|
|
list->next = tmp;
|
|
|
|
if (prev)
|
|
|
|
prev->next = list;
|
|
|
|
else
|
|
|
|
proc_defs = list;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = tmp;
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc_defs = g_slist_append (proc_defs, proc_def);
|
|
|
|
}
|
|
|
|
|
1999-02-14 09:53:23 +08:00
|
|
|
/* called when plug_in_proc_def_insert causes a proc_def to be
|
|
|
|
* overridden and thus g_free()d. */
|
|
|
|
static void
|
|
|
|
plug_in_proc_def_dead (void *freed_proc_def)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
PlugInDef *plug_in_def;
|
|
|
|
PlugInProcDef *proc_def = freed_proc_def;
|
|
|
|
|
1999-09-23 19:49:16 +08:00
|
|
|
g_warning ("removing duplicate PDB procedure \"%s\"",
|
1999-02-14 09:53:23 +08:00
|
|
|
proc_def->db_info.name);
|
|
|
|
|
|
|
|
/* search the plugin list to see if any plugins had references to
|
|
|
|
* the recently freed proc_def. */
|
|
|
|
tmp = plug_in_defs;
|
|
|
|
while (tmp)
|
|
|
|
{
|
|
|
|
plug_in_def = tmp->data;
|
|
|
|
|
|
|
|
plug_in_def->proc_defs = g_slist_remove (plug_in_def->proc_defs,
|
|
|
|
freed_proc_def);
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
|
|
|
plug_in_proc_def_remove (PlugInProcDef *proc_def)
|
|
|
|
{
|
|
|
|
/* Destroy the menu item */
|
|
|
|
if (proc_def->menu_path)
|
1998-12-26 02:22:01 +08:00
|
|
|
menus_destroy (gettext(proc_def->menu_path));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Unregister the procedural database entry */
|
|
|
|
procedural_db_unregister (proc_def->db_info.name);
|
|
|
|
|
|
|
|
/* Remove the defintion from the global list */
|
|
|
|
proc_defs = g_slist_remove (proc_defs, proc_def);
|
|
|
|
|
|
|
|
/* Destroy the definition */
|
|
|
|
plug_in_proc_def_destroy (proc_def, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_proc_def_destroy (PlugInProcDef *proc_def,
|
|
|
|
int data_only)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (proc_def->prog)
|
|
|
|
g_free (proc_def->prog);
|
|
|
|
if (proc_def->menu_path)
|
|
|
|
g_free (proc_def->menu_path);
|
|
|
|
if (proc_def->accelerator)
|
|
|
|
g_free (proc_def->accelerator);
|
|
|
|
if (proc_def->extensions)
|
|
|
|
g_free (proc_def->extensions);
|
|
|
|
if (proc_def->prefixes)
|
|
|
|
g_free (proc_def->prefixes);
|
|
|
|
if (proc_def->magics)
|
|
|
|
g_free (proc_def->magics);
|
|
|
|
if (proc_def->image_types)
|
|
|
|
g_free (proc_def->image_types);
|
|
|
|
if (proc_def->db_info.name)
|
|
|
|
g_free (proc_def->db_info.name);
|
|
|
|
if (proc_def->db_info.blurb)
|
|
|
|
g_free (proc_def->db_info.blurb);
|
|
|
|
if (proc_def->db_info.help)
|
|
|
|
g_free (proc_def->db_info.help);
|
|
|
|
if (proc_def->db_info.author)
|
|
|
|
g_free (proc_def->db_info.author);
|
|
|
|
if (proc_def->db_info.copyright)
|
|
|
|
g_free (proc_def->db_info.copyright);
|
|
|
|
if (proc_def->db_info.date)
|
|
|
|
g_free (proc_def->db_info.date);
|
|
|
|
|
|
|
|
for (i = 0; i < proc_def->db_info.num_args; i++)
|
|
|
|
{
|
|
|
|
if (proc_def->db_info.args[i].name)
|
|
|
|
g_free (proc_def->db_info.args[i].name);
|
|
|
|
if (proc_def->db_info.args[i].description)
|
|
|
|
g_free (proc_def->db_info.args[i].description);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < proc_def->db_info.num_values; i++)
|
|
|
|
{
|
|
|
|
if (proc_def->db_info.values[i].name)
|
|
|
|
g_free (proc_def->db_info.values[i].name);
|
|
|
|
if (proc_def->db_info.values[i].description)
|
|
|
|
g_free (proc_def->db_info.values[i].description);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (proc_def->db_info.args)
|
|
|
|
g_free (proc_def->db_info.args);
|
|
|
|
if (proc_def->db_info.values)
|
|
|
|
g_free (proc_def->db_info.values);
|
|
|
|
|
|
|
|
if (!data_only)
|
|
|
|
g_free (proc_def);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Argument *
|
|
|
|
plug_in_temp_run (ProcRecord *proc_rec,
|
1998-10-22 03:10:14 +08:00
|
|
|
Argument *args,
|
|
|
|
int argc)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
Argument *return_vals;
|
|
|
|
PlugIn *plug_in;
|
|
|
|
GPProcRun proc_run;
|
|
|
|
gint old_recurse;
|
|
|
|
|
|
|
|
return_vals = NULL;
|
|
|
|
|
|
|
|
plug_in = (PlugIn *) proc_rec->exec_method.temporary.plug_in;
|
|
|
|
|
|
|
|
if (plug_in)
|
|
|
|
{
|
|
|
|
if (plug_in->busy)
|
|
|
|
{
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, FALSE);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
plug_in->busy = TRUE;
|
|
|
|
plug_in_push (plug_in);
|
|
|
|
|
|
|
|
proc_run.name = proc_rec->name;
|
1998-10-22 03:10:14 +08:00
|
|
|
proc_run.nparams = argc;
|
|
|
|
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-03-07 20:56:03 +08:00
|
|
|
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
|
|
|
|
!wire_flush (current_writechannel))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, FALSE);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
1998-09-19 08:40:27 +08:00
|
|
|
/* plug_in_pop (); */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
|
|
|
|
|
|
|
|
old_recurse = plug_in->recurse;
|
|
|
|
plug_in->recurse = TRUE;
|
|
|
|
|
1998-09-19 08:40:27 +08:00
|
|
|
/* gtk_main (); */
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-09-19 08:40:27 +08:00
|
|
|
/* return_vals = plug_in_get_current_return_vals (proc_rec); */
|
|
|
|
return_vals = procedural_db_return_args (proc_rec, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in->recurse = old_recurse;
|
|
|
|
plug_in->busy = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
return return_vals;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Argument*
|
|
|
|
plug_in_params_to_args (GPParam *params,
|
|
|
|
int nparams,
|
|
|
|
int full_copy)
|
|
|
|
{
|
|
|
|
Argument *args;
|
|
|
|
gchar **stringarray;
|
|
|
|
guchar *colorarray;
|
|
|
|
int count;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (nparams == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
args = g_new (Argument, nparams);
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++)
|
|
|
|
{
|
|
|
|
args[i].arg_type = params[i].type;
|
|
|
|
|
|
|
|
switch (args[i].arg_type)
|
|
|
|
{
|
|
|
|
case PDB_INT32:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_int32;
|
|
|
|
break;
|
|
|
|
case PDB_INT16:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_int16;
|
|
|
|
break;
|
|
|
|
case PDB_INT8:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_int8;
|
|
|
|
break;
|
|
|
|
case PDB_FLOAT:
|
|
|
|
args[i].value.pdb_float = params[i].data.d_float;
|
|
|
|
break;
|
|
|
|
case PDB_STRING:
|
|
|
|
if (full_copy)
|
|
|
|
args[i].value.pdb_pointer = g_strdup (params[i].data.d_string);
|
|
|
|
else
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_string;
|
|
|
|
break;
|
|
|
|
case PDB_INT32ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
count = args[i-1].value.pdb_int;
|
|
|
|
args[i].value.pdb_pointer = g_new (gint32, count);
|
|
|
|
memcpy (args[i].value.pdb_pointer, params[i].data.d_int32array, count * 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_int32array;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_INT16ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
count = args[i-1].value.pdb_int;
|
|
|
|
args[i].value.pdb_pointer = g_new (gint16, count);
|
|
|
|
memcpy (args[i].value.pdb_pointer, params[i].data.d_int16array, count * 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_int16array;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_INT8ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
count = args[i-1].value.pdb_int;
|
|
|
|
args[i].value.pdb_pointer = g_new (gint8, count);
|
|
|
|
memcpy (args[i].value.pdb_pointer, params[i].data.d_int8array, count);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_int8array;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_FLOATARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
count = args[i-1].value.pdb_int;
|
|
|
|
args[i].value.pdb_pointer = g_new (gdouble, count);
|
|
|
|
memcpy (args[i].value.pdb_pointer, params[i].data.d_floatarray, count * 8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_floatarray;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_STRINGARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = g_new (gchar*, args[i-1].value.pdb_int);
|
|
|
|
stringarray = args[i].value.pdb_pointer;
|
|
|
|
|
|
|
|
for (j = 0; j < args[i-1].value.pdb_int; j++)
|
|
|
|
stringarray[j] = g_strdup (params[i].data.d_stringarray[j]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args[i].value.pdb_pointer = params[i].data.d_stringarray;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_COLOR:
|
|
|
|
args[i].value.pdb_pointer = g_new (guchar, 3);
|
|
|
|
colorarray = args[i].value.pdb_pointer;
|
|
|
|
colorarray[0] = params[i].data.d_color.red;
|
|
|
|
colorarray[1] = params[i].data.d_color.green;
|
|
|
|
colorarray[2] = params[i].data.d_color.blue;
|
|
|
|
break;
|
|
|
|
case PDB_REGION:
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("the \"region\" arg type is not currently supported");
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
case PDB_DISPLAY:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_display;
|
|
|
|
break;
|
|
|
|
case PDB_IMAGE:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_image;
|
|
|
|
break;
|
|
|
|
case PDB_LAYER:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_layer;
|
|
|
|
break;
|
|
|
|
case PDB_CHANNEL:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_channel;
|
|
|
|
break;
|
|
|
|
case PDB_DRAWABLE:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_drawable;
|
|
|
|
break;
|
|
|
|
case PDB_SELECTION:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_selection;
|
|
|
|
break;
|
|
|
|
case PDB_BOUNDARY:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_boundary;
|
|
|
|
break;
|
|
|
|
case PDB_PATH:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_path;
|
|
|
|
break;
|
1998-10-08 16:15:21 +08:00
|
|
|
case PDB_PARASITE:
|
|
|
|
if (full_copy)
|
|
|
|
args[i].value.pdb_pointer = parasite_copy ((Parasite *)
|
|
|
|
&(params[i].data.d_parasite));
|
|
|
|
else
|
|
|
|
args[i].value.pdb_pointer = (void *)&(params[i].data.d_parasite);
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
case PDB_STATUS:
|
|
|
|
args[i].value.pdb_int = params[i].data.d_status;
|
|
|
|
break;
|
|
|
|
case PDB_END:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GPParam*
|
|
|
|
plug_in_args_to_params (Argument *args,
|
|
|
|
int nargs,
|
|
|
|
int full_copy)
|
|
|
|
{
|
|
|
|
GPParam *params;
|
|
|
|
gchar **stringarray;
|
|
|
|
guchar *colorarray;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (nargs == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
params = g_new (GPParam, nargs);
|
|
|
|
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
|
|
|
params[i].type = args[i].arg_type;
|
|
|
|
|
|
|
|
switch (args[i].arg_type)
|
|
|
|
{
|
|
|
|
case PDB_INT32:
|
|
|
|
params[i].data.d_int32 = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_INT16:
|
|
|
|
params[i].data.d_int16 = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_INT8:
|
|
|
|
params[i].data.d_int8 = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_FLOAT:
|
|
|
|
params[i].data.d_float = args[i].value.pdb_float;
|
|
|
|
break;
|
|
|
|
case PDB_STRING:
|
|
|
|
if (full_copy)
|
|
|
|
params[i].data.d_string = g_strdup (args[i].value.pdb_pointer);
|
|
|
|
else
|
|
|
|
params[i].data.d_string = args[i].value.pdb_pointer;
|
|
|
|
break;
|
|
|
|
case PDB_INT32ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
params[i].data.d_int32array = g_new (gint32, params[i-1].data.d_int32);
|
|
|
|
memcpy (params[i].data.d_int32array,
|
|
|
|
args[i].value.pdb_pointer,
|
|
|
|
params[i-1].data.d_int32 * 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_int32array = args[i].value.pdb_pointer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_INT16ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
params[i].data.d_int16array = g_new (gint16, params[i-1].data.d_int32);
|
|
|
|
memcpy (params[i].data.d_int16array,
|
|
|
|
args[i].value.pdb_pointer,
|
|
|
|
params[i-1].data.d_int32 * 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_int16array = args[i].value.pdb_pointer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_INT8ARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
params[i].data.d_int8array = g_new (gint8, params[i-1].data.d_int32);
|
|
|
|
memcpy (params[i].data.d_int8array,
|
|
|
|
args[i].value.pdb_pointer,
|
|
|
|
params[i-1].data.d_int32);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_int8array = args[i].value.pdb_pointer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_FLOATARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
params[i].data.d_floatarray = g_new (gdouble, params[i-1].data.d_int32);
|
|
|
|
memcpy (params[i].data.d_floatarray,
|
|
|
|
args[i].value.pdb_pointer,
|
|
|
|
params[i-1].data.d_int32 * 8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_floatarray = args[i].value.pdb_pointer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_STRINGARRAY:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
params[i].data.d_stringarray = g_new (gchar*, params[i-1].data.d_int32);
|
|
|
|
stringarray = args[i].value.pdb_pointer;
|
|
|
|
|
|
|
|
for (j = 0; j < params[i-1].data.d_int32; j++)
|
|
|
|
params[i].data.d_stringarray[j] = g_strdup (stringarray[j]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_stringarray = args[i].value.pdb_pointer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_COLOR:
|
|
|
|
colorarray = args[i].value.pdb_pointer;
|
|
|
|
if( colorarray )
|
|
|
|
{
|
|
|
|
params[i].data.d_color.red = colorarray[0];
|
|
|
|
params[i].data.d_color.green = colorarray[1];
|
|
|
|
params[i].data.d_color.blue = colorarray[2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
params[i].data.d_color.red = 0;
|
|
|
|
params[i].data.d_color.green = 0;
|
|
|
|
params[i].data.d_color.blue = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_REGION:
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("the \"region\" arg type is not currently supported");
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
case PDB_DISPLAY:
|
|
|
|
params[i].data.d_display = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_IMAGE:
|
|
|
|
params[i].data.d_image = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_LAYER:
|
|
|
|
params[i].data.d_layer = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_CHANNEL:
|
|
|
|
params[i].data.d_channel = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_DRAWABLE:
|
|
|
|
params[i].data.d_drawable = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_SELECTION:
|
|
|
|
params[i].data.d_selection = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_BOUNDARY:
|
|
|
|
params[i].data.d_boundary = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_PATH:
|
|
|
|
params[i].data.d_path = args[i].value.pdb_int;
|
|
|
|
break;
|
1998-10-08 16:15:21 +08:00
|
|
|
case PDB_PARASITE:
|
|
|
|
if (full_copy)
|
|
|
|
{
|
|
|
|
Parasite *tmp;
|
|
|
|
tmp = parasite_copy (args[i].value.pdb_pointer);
|
|
|
|
if (tmp == NULL)
|
|
|
|
{
|
1998-10-14 10:54:02 +08:00
|
|
|
params[i].data.d_parasite.name = 0;
|
|
|
|
params[i].data.d_parasite.flags = 0;
|
1998-10-08 16:15:21 +08:00
|
|
|
params[i].data.d_parasite.size = 0;
|
|
|
|
params[i].data.d_parasite.data = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (¶ms[i].data.d_parasite, tmp, sizeof(Parasite));
|
|
|
|
g_free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (args[i].value.pdb_pointer == NULL)
|
|
|
|
{
|
1998-10-14 10:54:02 +08:00
|
|
|
params[i].data.d_parasite.name = 0;
|
|
|
|
params[i].data.d_parasite.flags = 0;
|
1998-10-08 16:15:21 +08:00
|
|
|
params[i].data.d_parasite.size = 0;
|
|
|
|
params[i].data.d_parasite.data = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
memcpy (¶ms[i].data.d_parasite,
|
|
|
|
(Parasite *)(args[i].value.pdb_pointer),
|
|
|
|
sizeof(Parasite));
|
|
|
|
}
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
case PDB_STATUS:
|
|
|
|
params[i].data.d_status = args[i].value.pdb_int;
|
|
|
|
break;
|
|
|
|
case PDB_END:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_params_destroy (GPParam *params,
|
|
|
|
int nparams,
|
|
|
|
int full_destroy)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++)
|
|
|
|
{
|
|
|
|
switch (params[i].type)
|
|
|
|
{
|
|
|
|
case PDB_INT32:
|
|
|
|
case PDB_INT16:
|
|
|
|
case PDB_INT8:
|
|
|
|
case PDB_FLOAT:
|
|
|
|
break;
|
|
|
|
case PDB_STRING:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (params[i].data.d_string);
|
|
|
|
break;
|
|
|
|
case PDB_INT32ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (params[i].data.d_int32array);
|
|
|
|
break;
|
|
|
|
case PDB_INT16ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (params[i].data.d_int16array);
|
|
|
|
break;
|
|
|
|
case PDB_INT8ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (params[i].data.d_int8array);
|
|
|
|
break;
|
|
|
|
case PDB_FLOATARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (params[i].data.d_floatarray);
|
|
|
|
break;
|
|
|
|
case PDB_STRINGARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
{
|
|
|
|
for (j = 0; j < params[i-1].data.d_int32; j++)
|
|
|
|
g_free (params[i].data.d_stringarray[j]);
|
|
|
|
g_free (params[i].data.d_stringarray);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_COLOR:
|
|
|
|
break;
|
|
|
|
case PDB_REGION:
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("the \"region\" arg type is not currently supported");
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
case PDB_DISPLAY:
|
|
|
|
case PDB_IMAGE:
|
|
|
|
case PDB_LAYER:
|
|
|
|
case PDB_CHANNEL:
|
|
|
|
case PDB_DRAWABLE:
|
|
|
|
case PDB_SELECTION:
|
|
|
|
case PDB_BOUNDARY:
|
|
|
|
case PDB_PATH:
|
1998-10-08 16:15:21 +08:00
|
|
|
break;
|
|
|
|
case PDB_PARASITE:
|
|
|
|
if (full_destroy)
|
|
|
|
if (params[i].data.d_parasite.data)
|
|
|
|
{
|
1998-10-14 10:54:02 +08:00
|
|
|
g_free (params[i].data.d_parasite.name);
|
1998-10-08 16:15:21 +08:00
|
|
|
g_free (params[i].data.d_parasite.data);
|
1998-10-14 10:54:02 +08:00
|
|
|
params[i].data.d_parasite.name = 0;
|
1998-10-08 16:15:21 +08:00
|
|
|
params[i].data.d_parasite.data = 0;
|
|
|
|
}
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
case PDB_STATUS:
|
|
|
|
break;
|
|
|
|
case PDB_END:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (params);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_args_destroy (Argument *args,
|
|
|
|
int nargs,
|
|
|
|
int full_destroy)
|
|
|
|
{
|
|
|
|
gchar **stringarray;
|
|
|
|
int count;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
|
|
|
switch (args[i].arg_type)
|
|
|
|
{
|
|
|
|
case PDB_INT32:
|
|
|
|
case PDB_INT16:
|
|
|
|
case PDB_INT8:
|
|
|
|
case PDB_FLOAT:
|
|
|
|
break;
|
|
|
|
case PDB_STRING:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_INT32ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_INT16ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_INT8ARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_FLOATARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_STRINGARRAY:
|
|
|
|
if (full_destroy)
|
|
|
|
{
|
|
|
|
count = args[i-1].value.pdb_int;
|
|
|
|
stringarray = args[i].value.pdb_pointer;
|
|
|
|
|
|
|
|
for (j = 0; j < count; j++)
|
|
|
|
g_free (stringarray[j]);
|
|
|
|
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PDB_COLOR:
|
|
|
|
g_free (args[i].value.pdb_pointer);
|
|
|
|
break;
|
|
|
|
case PDB_REGION:
|
1999-09-23 19:49:16 +08:00
|
|
|
g_message ("the \"region\" arg type is not currently supported");
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
case PDB_DISPLAY:
|
|
|
|
case PDB_IMAGE:
|
|
|
|
case PDB_LAYER:
|
|
|
|
case PDB_CHANNEL:
|
|
|
|
case PDB_DRAWABLE:
|
|
|
|
case PDB_SELECTION:
|
|
|
|
case PDB_BOUNDARY:
|
|
|
|
case PDB_PATH:
|
1998-10-08 16:15:21 +08:00
|
|
|
break;
|
|
|
|
case PDB_PARASITE:
|
|
|
|
if (full_destroy)
|
|
|
|
{
|
1998-10-30 18:21:33 +08:00
|
|
|
parasite_free ((Parasite *)(args[i].value.pdb_pointer));
|
|
|
|
args[i].value.pdb_pointer = NULL;
|
1998-10-08 16:15:21 +08:00
|
|
|
}
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
case PDB_STATUS:
|
|
|
|
break;
|
|
|
|
case PDB_END:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (args);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
plug_in_image_types_parse (char *image_types)
|
|
|
|
{
|
|
|
|
int types;
|
|
|
|
|
|
|
|
if (!image_types)
|
|
|
|
return (RGB_IMAGE | GRAY_IMAGE | INDEXED_IMAGE);
|
|
|
|
|
|
|
|
types = 0;
|
|
|
|
|
|
|
|
while (*image_types)
|
|
|
|
{
|
|
|
|
while (*image_types &&
|
|
|
|
((*image_types == ' ') ||
|
|
|
|
(*image_types == '\t') ||
|
|
|
|
(*image_types == ',')))
|
|
|
|
image_types++;
|
|
|
|
|
|
|
|
if (*image_types)
|
|
|
|
{
|
|
|
|
if (strncmp (image_types, "RGBA", 4) == 0)
|
|
|
|
{
|
|
|
|
types |= RGBA_IMAGE;
|
|
|
|
image_types += 4;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "RGB*", 4) == 0)
|
|
|
|
{
|
|
|
|
types |= RGB_IMAGE | RGBA_IMAGE;
|
|
|
|
image_types += 4;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "RGB", 3) == 0)
|
|
|
|
{
|
|
|
|
types |= RGB_IMAGE;
|
|
|
|
image_types += 3;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "GRAYA", 5) == 0)
|
|
|
|
{
|
|
|
|
types |= GRAYA_IMAGE;
|
|
|
|
image_types += 5;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "GRAY*", 5) == 0)
|
|
|
|
{
|
|
|
|
types |= GRAY_IMAGE | GRAYA_IMAGE;
|
|
|
|
image_types += 5;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "GRAY", 4) == 0)
|
|
|
|
{
|
|
|
|
types |= GRAY_IMAGE;
|
|
|
|
image_types += 4;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "INDEXEDA", 8) == 0)
|
|
|
|
{
|
|
|
|
types |= INDEXEDA_IMAGE;
|
|
|
|
image_types += 8;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "INDEXED*", 8) == 0)
|
|
|
|
{
|
|
|
|
types |= INDEXED_IMAGE | INDEXEDA_IMAGE;
|
|
|
|
image_types += 8;
|
|
|
|
}
|
|
|
|
else if (strncmp (image_types, "INDEXED", 7) == 0)
|
|
|
|
{
|
|
|
|
types |= INDEXED_IMAGE;
|
|
|
|
image_types += 7;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (*image_types &&
|
|
|
|
(*image_types != 'R') &&
|
|
|
|
(*image_types != 'G') &&
|
|
|
|
(*image_types != 'I'))
|
|
|
|
image_types++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return types;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
plug_in_progress_cancel (GtkWidget *widget,
|
|
|
|
PlugIn *plug_in)
|
|
|
|
{
|
|
|
|
plug_in_destroy (plug_in);
|
|
|
|
}
|
|
|
|
|
1999-05-04 03:22:58 +08:00
|
|
|
void
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_progress_init (PlugIn *plug_in,
|
1998-06-15 10:25:27 +08:00
|
|
|
char *message,
|
|
|
|
gint gdisp_ID)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-06-15 12:46:32 +08:00
|
|
|
GDisplay *gdisp = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (!message)
|
|
|
|
message = plug_in->args[0];
|
|
|
|
|
1998-06-15 10:25:27 +08:00
|
|
|
if (gdisp_ID > 0)
|
|
|
|
gdisp = gdisplay_get_ID(gdisp_ID);
|
|
|
|
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
if (plug_in->progress)
|
|
|
|
plug_in->progress = progress_restart (plug_in->progress, message,
|
|
|
|
plug_in_progress_cancel, plug_in);
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
plug_in->progress = progress_start (gdisp, message, TRUE,
|
|
|
|
plug_in_progress_cancel, plug_in);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1999-05-04 03:22:58 +08:00
|
|
|
void
|
1997-11-25 06:05:25 +08:00
|
|
|
plug_in_progress_update (PlugIn *plug_in,
|
|
|
|
double percentage)
|
|
|
|
{
|
Bit of a large checkin this - it's basically three things: 1 - GimpModules
Sun Jan 11 00:24:21 GMT 1999 Austin Donnelly <austin@greenend.org.uk>
Bit of a large checkin this - it's basically three things:
1 - GimpModules using gmodules to dynamically load and
initialise modules at gimp start of day.
2 - Color selectors now register themselves with a color
notebook.
3 - progress bars have been cleaned up a bit, so now have
progress indictations on all transform tool and gradient
fill operations. Not done bucket fill, but that seems to
be the next candidate.
New directories:
* modules/: new directory for dynamically loadable modules.
New files:
* modules/.cvsignore
* modules/Makefile.am
* modules/colorsel_gtk.c: GTK color selector wrapped up as a
color selector the gimp can use.
* app/gimpprogress.[ch]: progress bars within gimp core, either as
popups, or in the status bar. This is mainly code moved out
of plug-in.c
* app/color_notebook.[ch]: color selector notebook, implementing
very similar interface to color_select.h so it can be used as
a drop-in replacement for it.
* libgimp/color_selector.h: API color selectors need to implement
to become a page in the color_notebook.
* libgimp/gimpmodule.h: API gimp modules need to implement to be
initialised by gimp at start of day.
Modified files:
* Makefile.am: add modules/ to SUBDIRS
* libgimp/Makefile.am: install gimpmodule.h and color_selector.h
* app/gimprc.[ch]: recognise module-path variable.
* gimprc.in: set module-path variable to something sensible
(currently "${gimp_dir}/modules:${gimp_plugin_dir}/modules").
* app/Makefile.am: build color notebook and gimpprogress
* app/app_procs.c: register internal GIMP color selector with
color notebook.
* app/asupsample.c: call progress function less frequently for
better performance.
* app/asupsample.h: progress_func_t typedef moved to gimpprogress.h
* app/blend.c: make callbacks to a progress function
* app/color_area.c: use a color notebook rather than a color selector
* app/color_panel.c: ditto
* app/color_select.c: export color selector interface for notebook
* app/color_select.h: color_select_init() prototype
* app/flip_tool.c: flip the image every time, rather than every
second click.
* app/interface.c: move progress bar stuff out to
gimpprogress.c. Make the code actually work while we're at it.
* app/interface.h: move prototypes for progress functions out to
gimpprogress.h
* app/plug_in.c: load and initialise modules (if possible). Move
progress bar handling code out to gimpprogress.c
* app/plug_in.h: keep only a gimp_progress * for each plugin, not
a whole bunch of GtkWidgets.
* app/scale_tool.c
* app/rotate_tool.c
* app/shear_tool.c
* app/perspective_tool.c: progress bar during operation.
De-sensitise the dialog to discourage the user from running
two transforms in parallel.
* app/transform_core.c: recalculate grid coords when bounding box
changes. Only initialise the action area of the dialog once,
to avoid multiple "ok" / "reset" buttons appearing. Undraw
transform tool with correct matrix to get rid of handle
remains on screen. Call a progress function as we apply the
transform matrix. A few new i18n markups. Invalidate
floating selection marching ants after applying matrix.
* app/transform_core.h: transform_core_do() takes an optional
progress callback argument (and data).
* plug-ins/oilify/oilify.c: send progress bar updates after every
pixel region, not only if they processed a multiple of 5
pixels (which was quite unlikely, and therefore gave a jerky
progress indication).
1999-01-11 08:57:33 +08:00
|
|
|
if (!plug_in->progress)
|
|
|
|
plug_in_progress_init (plug_in, NULL, -1);
|
|
|
|
|
|
|
|
progress_update (plug_in->progress, percentage);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|