Second batch of Win32 merge.

This commit is contained in:
Tor Lillqvist 1999-03-07 12:56:03 +00:00
parent 3152a7dbba
commit 951c92a602
112 changed files with 9272 additions and 3437 deletions

View File

@ -17,6 +17,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gtk/gtk.h>
@ -25,6 +26,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#include "about_dialog.h"
#include "interface.h"
@ -294,7 +296,8 @@ about_dialog_load_logo (GtkWidget *window)
if (logo_pixmap)
return TRUE;
g_snprintf (buf, sizeof(buf), "%s/gimp_logo.ppm", DATADIR);
g_snprintf (buf, sizeof(buf), "%s" G_DIR_SEPARATOR_S "gimp_logo.ppm",
gimp_data_directory ());
fp = fopen (buf, "rb");
if (!fp)

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -38,6 +38,7 @@
#include <gtk/gtk.h>
#include "libgimp/gimpfeatures.h"
#include "libgimp/gimpenv.h"
#include "appenv.h"
#include "app_procs.h"
@ -179,7 +180,7 @@ splash_logo_load_size (GtkWidget *window)
return TRUE;
g_snprintf (buf, sizeof(buf), "%s" G_DIR_SEPARATOR_S "gimp1_1_splash.ppm",
DATADIR);
gimp_data_directory ());
fp = fopen (buf, "rb");
if (!fp)
@ -215,7 +216,7 @@ splash_logo_load (GtkWidget *window)
return TRUE;
g_snprintf (buf, sizeof(buf), "%s" G_DIR_SEPARATOR_S "gimp1_1_splash.ppm",
DATADIR);
gimp_data_directory ());
fp = fopen (buf, "rb");
if (!fp)
@ -340,7 +341,7 @@ static GtkWidget *pbar = NULL;
static void
destroy_initialization_status_window(void)
{
if(win_initstatus)
if (win_initstatus)
{
gtk_widget_destroy(win_initstatus);
if (logo_pixmap != NULL)
@ -473,20 +474,15 @@ app_init_update_status(char *label1val,
void
app_init (void)
{
char filename[MAXPATHLEN];
char *gimp_dir;
char *path;
gchar *filename;
gchar *path;
gimp_dir = gimp_directory ();
if (gimp_dir[0] != '\000')
{
g_snprintf (filename, MAXPATHLEN, "%s" G_DIR_SEPARATOR_S "gtkrc", gimp_dir);
filename = gimp_gtkrc ();
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print (_("parsing \"%s\"\n"), filename);
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print (_("parsing \"%s\"\n"), filename);
gtk_rc_parse (filename);
}
gtk_rc_parse (filename);
if (no_interface == FALSE)
get_standard_colormaps ();
@ -555,10 +551,11 @@ app_init (void)
/* Add the swap file */
if (swap_path == NULL)
swap_path = "/tmp";
swap_path = g_get_tmp_dir ();
toast_old_temp_files ();
path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "gimpswap.%ld",
swap_path, (long)getpid ());
path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "gimpswap.%lu",
swap_path, (unsigned long) getpid ());
tile_swap_add (path, NULL, NULL);
g_free (path);

View File

@ -2,6 +2,7 @@
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

View File

@ -9,6 +9,10 @@
#include <unistd.h>
#endif
#ifdef _MSC_VER
#include <io.h>
#endif
#include "appenv.h"
#include "app_procs.h"
#include "batch.h"
@ -51,10 +55,10 @@ batch_init ()
g_print (_("reading batch commands from stdin\n"));
gdk_input_add (STDIN_FILENO, GDK_INPUT_READ, batch_read, NULL);
read_from_stdin = TRUE;
}
#else
g_error ("Batch mode from standard input not implemented on Win32");
#endif
}
}
else
{

View File

@ -20,6 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "actionarea.h"
#include "color_notebook.h"

View File

@ -35,6 +35,7 @@
#include "gimpsignal.h"
#include "libgimp/gimpintl.h"
#include "libgimp/parasite.h"
#include "layer_pvt.h"
#include "tile_manager_pvt.h"

View File

@ -15,9 +15,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include "appenv.h"
#include "actionarea.h"
@ -32,6 +34,7 @@
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define CELL_SIZE 20 /* The size of the preview cells */
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@ -212,20 +215,14 @@ devices_init (void)
void
devices_restore()
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
GList *tmp_list;
DeviceInfo *device_info;
/* Augment with information from rc file */
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("devicerc");
parse_gimprc_file (filename);
g_free (filename);
tmp_list = devices_info;
device_info = NULL;
@ -625,25 +622,19 @@ devices_write_rc_device (DeviceInfo *device_info, FILE *fp)
static void
devices_write_rc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
devices_save_current_info();
filename = gimp_personal_rc_file ("devicerc");
fp = fopen (filename, "wb");
g_free (filename);
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
if (!fp)
return;
fp = fopen (filename, "wb");
if (!fp)
return;
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
fclose (fp);
}
fclose (fp);
}
void

View File

@ -17,6 +17,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gtk/gtk.h>
@ -25,6 +26,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#include "about_dialog.h"
#include "interface.h"
@ -294,7 +296,8 @@ about_dialog_load_logo (GtkWidget *window)
if (logo_pixmap)
return TRUE;
g_snprintf (buf, sizeof(buf), "%s/gimp_logo.ppm", DATADIR);
g_snprintf (buf, sizeof(buf), "%s" G_DIR_SEPARATOR_S "gimp_logo.ppm",
gimp_data_directory ());
fp = fopen (buf, "rb");
if (!fp)

View File

@ -20,6 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "actionarea.h"
#include "color_notebook.h"

View File

@ -1,3 +1,5 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -8,8 +10,8 @@
#include "interface.h"
#include "wilber.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define TIPS_FILE_NAME "gimp_tips.txt"
@ -39,22 +41,17 @@ tips_dialog_create ()
GtkWidget *button_prev;
GtkWidget *vbox_check;
GtkWidget *button_check;
guchar * temp;
gchar * temp;
guchar * src;
guchar * dest;
gchar * gimp_data_dir;
int x;
int y;
if (tips_count == 0)
{
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_dir, TIPS_FILE_NAME);
else
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
DATADIR, TIPS_FILE_NAME);
read_tips_file ((char *)temp);
temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_directory (), TIPS_FILE_NAME);
read_tips_file (temp);
g_free (temp);
}

View File

@ -15,10 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "appenv.h"
#include "actionarea.h"
@ -26,8 +31,16 @@
#include "interface.h"
#include "gimprc.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#ifndef NATIVE_WIN32
# define USER_INSTALL "user_install"
#else
# define STRICT
# include <windows.h>
# define USER_INSTALL "user_install.bat"
#endif
static void install_run (InstallCallback);
static void install_help (InstallCallback);
@ -48,11 +61,7 @@ install_verify (InstallCallback install_callback)
struct stat stat_buf;
filename = gimp_directory ();
if ('\000' == filename[0])
{
g_message (_("No home directory--skipping GIMP user installation."));
(* install_callback) ();
}
/* gimp_directory now always returns something */
if (stat (filename, &stat_buf) != 0)
properly_installed = FALSE;
@ -373,6 +382,47 @@ help_quit_callback (GtkWidget *w,
gtk_exit (0);
}
#ifdef NATIVE_WIN32
static char *
quote_spaces (char *string)
{
int nspaces = 0;
char *p = string, *q, *new;
while (*p)
{
if (*p == ' ')
nspaces++;
p++;
}
if (nspaces == 0)
return g_strdup (string);
new = g_malloc (strlen (string) + nspaces*2 + 1);
p = string;
q = new;
while (*p)
{
if (*p == ' ')
{
*q++ = '"';
*q++ = ' ';
*q++ = '"';
}
else
*q++ = *p;
p++;
}
*q = '\0';
return new;
}
#endif
static void
install_run (InstallCallback callback)
{
@ -389,7 +439,6 @@ install_run (InstallCallback callback)
GdkFont *font;
FILE *pfp;
char buffer[2048];
char *gimp_data_dir;
struct stat stat_buf;
int err;
int executable = TRUE;
@ -430,14 +479,13 @@ install_run (InstallCallback callback)
/* Realize the text widget before inserting text strings */
gtk_widget_realize (text);
#ifndef NATIVE_WIN32
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL, _("User Installation Log\n\n"), -1);
#endif
/* Generate output */
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
g_snprintf (buffer, sizeof(buffer), "%s/user_install", gimp_data_dir);
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install", DATADIR);
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL,
gimp_data_directory ());
if ((err = stat (buffer, &stat_buf)) != 0)
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -445,6 +493,7 @@ install_run (InstallCallback callback)
_(" does not exist. Cannot install.\n"), -1);
executable = FALSE;
}
#ifdef S_IXUSR
else if (! (S_IXUSR & stat_buf.st_mode) || ! (S_IRUSR & stat_buf.st_mode))
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -452,21 +501,51 @@ install_run (InstallCallback callback)
_(" has invalid permissions.\nCannot install."), -1);
executable = FALSE;
}
#endif
if (executable == TRUE)
{
if (gimp_data_dir)
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
gimp_data_dir, gimp_data_dir, gimp_directory ());
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
DATADIR, DATADIR, gimp_directory ());
#ifdef NATIVE_WIN32
char *quoted_data_dir, *quoted_user_dir;
/* On Windows, it is common for the GIMP data directory
* to have spaces in it ("c:\Program Files\GIMP"). Put spaces in quotes.
*/
quoted_data_dir = quote_spaces (gimp_data_directory ());
quoted_user_dir = quote_spaces (gimp_directory ());
/* The Microsoft _popen doesn't work in Windows applications, sigh.
* Do the installation by calling system(). The user_install.bat
* ends with a pause command, so the user has to press enter in
* the console window to continue, and thus has a chance to read
* at the window contents.
*/
AllocConsole ();
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
quoted_data_dir, quoted_data_dir,
quoted_user_dir);
if (system (buffer) == -1)
executable = FALSE;
g_free (quoted_data_dir);
g_free (quoted_user_dir);
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL,
"Did you notice any error messages\n"
"in the console window? If not, installation\n"
"was successful! Otherwise, quit and investigate\n"
"the possible reason...\n", -1);
#else
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
gimp_data_directory (), gimp_data_directory(),
gimp_directory ());
/* urk - should really use something better than popen(), since
* we can't tell if the installation script failed --austin */
if ((pfp = popen (buffer, "r")) != NULL)
{
while (fgets (buffer, 2048, pfp))
while (fgets (buffer, sizeof (buffer), pfp))
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
pclose (pfp);
@ -476,6 +555,8 @@ install_run (InstallCallback callback)
else
executable = FALSE;
}
#endif /* !NATIVE_WIN32 */
if (executable == FALSE)
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL,
_("\nInstallation failed. Contact system administrator.\n"), -1);
@ -492,6 +573,10 @@ install_continue_callback (GtkWidget *w,
{
InstallCallback callback;
#ifdef NATIVE_WIN32
FreeConsole ();
#endif
callback = (InstallCallback) client_data;
gtk_widget_destroy (install_widget);
(* callback) ();

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "appenv.h"
#include "actionarea.h"
@ -24,6 +27,7 @@
#include "color_area.h"
#include "commands.h"
#include "devices.h"
#include "dialog_handler.h"
#include "disp_callbacks.h"
#include "errors.h"
#include "gdisplay.h"

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "appenv.h"
#include "actionarea.h"
@ -24,6 +27,7 @@
#include "color_area.h"
#include "commands.h"
#include "devices.h"
#include "dialog_handler.h"
#include "disp_callbacks.h"
#include "errors.h"
#include "gdisplay.h"

View File

@ -214,15 +214,12 @@ load_idea_manager( idea_manager *ideas )
{
FILE *fp = NULL;
gchar *desktopfile;
gchar *home_dir;
if ( ! idea_list )
{
home_dir = g_get_home_dir();
/* open persistant desktop file. */
desktopfile = append2( home_dir, FALSE, IDEAPATH, FALSE );
fp = fopen( desktopfile, "rb" );
desktopfile = gimp_personal_rc_file ("ideas");
fp = fopen( desktopfile, "r" );
g_free( desktopfile );
/* Read in persistant desktop information. */
@ -291,13 +288,10 @@ save_idea_manager( idea_manager *ideas )
{
FILE *fp;
gchar *desktopfile;
gchar *home_dir;
home_dir = g_get_home_dir();
/* open persistant desktop file. */
desktopfile = append2( home_dir, FALSE, IDEAPATH, FALSE );
fp = fopen( desktopfile, "wb" );
desktopfile = gimp_personal_rc_file ("ideas");
fp = fopen( desktopfile, "w" );
g_free( desktopfile );
if ( fp )
@ -435,13 +429,10 @@ static void idea_add_in_position_with_select( gchar *title, gint position, gbool
{
FILE *fp = NULL;
gchar *desktopfile;
gchar *home_dir;
home_dir = g_get_home_dir();
/* open persistant desktop file. */
desktopfile = append2( home_dir, FALSE, IDEAPATH, FALSE );
fp = fopen( desktopfile, "rb" );
desktopfile = gimp_personal_rc_file ("ideas");
fp = fopen( desktopfile, "r" );
g_free( desktopfile );
/* Read in persistant desktop information. */

View File

@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
#include <string.h>
#include "docindex.h"
#include "docindexif.h"

View File

@ -37,9 +37,6 @@ int getinteger( FILE *fp );
gchar *append2( gchar *string1, gboolean del1, gchar *string2, gboolean del2);
gint reset_usize( gpointer data );
#define IDEAPATH "/" GIMPDIR "/ideas"
struct bool_char_pair
{
gboolean boole;

View File

@ -71,12 +71,21 @@ fatal_error (char *fmt, ...)
va_list args;
va_start (args, fmt);
#ifndef NATIVE_WIN32
printf ("%s fatal error: ", prog_name);
vprintf (fmt, args);
printf ("\n");
#else
g_error ("%s: %s\n", prog_name, g_strdup_vprintf (fmt, args));
#endif
va_end (args);
#ifndef NATIVE_WIN32
g_on_error_query (prog_name);
#else
/* g_on_error_query unreliable on Win32 */
abort ();
#endif
app_exit (1);
}
@ -91,7 +100,9 @@ terminate (char *fmt, ...)
printf ("\n");
va_end (args);
#ifndef NATIVE_WIN32
if (use_debug_handler)
g_on_error_query (prog_name);
#endif
gdk_exit (1);
}

View File

@ -198,6 +198,13 @@ get_token (ParseInfo *info)
else if (slashed || (buffer[info->position] != '"'))
{
slashed = FALSE;
if (slashed && buffer[info->position] == 'n')
tokenbuf[tokenpos++] = '\n';
else if (slashed && buffer[info->position] == 'r')
tokenbuf[tokenpos++] = '\r';
else if (slashed && buffer[info->position] == 'z') /* ^Z */
tokenbuf[tokenpos++] = '\032';
else
tokenbuf[tokenpos++] = buffer[info->position];
info->position += 1;
}

3
app/gimp.def Normal file
View File

@ -0,0 +1,3 @@
EXPORTS
gimp_color_selector_register
gimp_color_selector_unregister

1
app/gimp.rc Normal file
View File

@ -0,0 +1 @@
wilber ICON "wilber.ico"

View File

@ -35,6 +35,7 @@
#include "gimpsignal.h"
#include "libgimp/gimpintl.h"
#include "libgimp/parasite.h"
#include "layer_pvt.h"
#include "tile_manager_pvt.h"

View File

@ -15,13 +15,21 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <glib.h>
#include "app_procs.h"
@ -37,8 +45,8 @@
#include "session.h"
#include "tools.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define ERROR 0
#define DONE 1
@ -182,7 +190,11 @@ static char* gimprc_find_token (char *token);
static void gimprc_set_token (char *token, char *value);
static Argument * gimprc_query (Argument *args);
static void add_gimp_directory_token (char *gimp_dir);
static char* open_backup_file (char *filename, FILE **fp_new, FILE **fp_old);
static char* open_backup_file (char *filename,
char *secondary_filename,
char **name_used,
FILE **fp_new,
FILE **fp_old);
static ParseInfo parse_info;
@ -281,62 +293,18 @@ static int nsession_infos = sizeof (session_infos) / sizeof (session_infos[0]);
extern char* alternate_gimprc;
extern char* alternate_system_gimprc;
#define MAX_GIMPDIR_LEN 500
#define DEFAULT_IMAGE_TITLE_FORMAT "%f-%p.%i (%t)"
char *
gimp_directory ()
static char *
gimp_system_rc_file ()
{
static char gimp_dir[MAX_GIMPDIR_LEN + 1] = "";
char *env_gimp_dir;
char *env_home_dir;
size_t len_env_home_dir = 0;
static char *value = NULL;
if (value != NULL)
return value;
if ('\000' != gimp_dir[0])
return gimp_dir;
env_gimp_dir = getenv ("GIMP_DIRECTORY");
env_home_dir = g_get_home_dir ();
if (NULL != env_home_dir)
len_env_home_dir = strlen (env_home_dir);
if (NULL != env_gimp_dir)
{
if ('/' == env_gimp_dir[0])
strncpy (gimp_dir, env_gimp_dir, MAX_GIMPDIR_LEN);
else
{
if (NULL != env_home_dir)
{
strncpy (gimp_dir, env_home_dir, MAX_GIMPDIR_LEN);
gimp_dir[len_env_home_dir] = '/';
}
else
g_message (_("warning: no home directory."));
strncpy (&gimp_dir[len_env_home_dir+1],
env_gimp_dir,
MAX_GIMPDIR_LEN - len_env_home_dir - 1);
}
}
else
{
if (NULL != env_home_dir)
{
strncpy (gimp_dir, env_home_dir, MAX_GIMPDIR_LEN);
gimp_dir[len_env_home_dir] = '/';
}
else
g_message (_("warning: no home directory."));
strncpy (&gimp_dir[len_env_home_dir+1],
GIMPDIR,
MAX_GIMPDIR_LEN - len_env_home_dir - 1);
}
gimp_dir[MAX_GIMPDIR_LEN] = '\000';
return gimp_dir;
value = g_strconcat (gimp_data_directory (), G_DIR_SEPARATOR_S, "gimprc",
NULL);
return value;
}
void
@ -344,7 +312,6 @@ parse_gimprc ()
{
char libfilename[MAXPATHLEN];
char filename[MAXPATHLEN];
char *gimp_data_dir;
char *gimp_dir;
parse_info.buffer = g_new (char, 4096);
@ -355,27 +322,20 @@ parse_gimprc ()
gimp_dir = gimp_directory ();
add_gimp_directory_token (gimp_dir);
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
g_snprintf (libfilename, MAXPATHLEN, "%s/gimprc", gimp_data_dir);
else
g_snprintf (libfilename, MAXPATHLEN, "%s/gimprc", DATADIR);
app_init_update_status(_("Resource configuration"), libfilename, -1);
strcpy (libfilename, gimp_system_rc_file ());
if (alternate_system_gimprc != NULL)
{
strncpy (libfilename, alternate_system_gimprc, 512);
}
strncpy (libfilename, alternate_system_gimprc, MAXPATHLEN);
app_init_update_status(_("Resource configuration"), libfilename, -1);
parse_gimprc_file (libfilename);
g_snprintf (filename, MAXPATHLEN, "%s/gimprc", gimp_dir);
if (strcmp (filename, libfilename) != 0)
if (alternate_gimprc != NULL)
strncpy (filename, alternate_gimprc, MAXPATHLEN);
else
strncpy (filename, gimp_personal_rc_file ("gimprc"), MAXPATHLEN);
if (filename[0] != '\0' && strcmp (filename, libfilename) != 0)
{
app_init_update_status(NULL, filename, -1);
if (alternate_gimprc != NULL)
{
strncpy (filename, alternate_gimprc, 512);
}
parse_gimprc_file (filename);
}
@ -386,19 +346,17 @@ parse_gimprc ()
void
parse_gimprc_file (char *filename)
{
static char *home_dir = NULL;
int status;
char rfilename[MAXPATHLEN];
if (filename[0] != '/')
if (!g_path_is_absolute (filename))
{
if (!home_dir)
home_dir = g_strdup (g_get_home_dir ());
g_snprintf (rfilename, MAXPATHLEN, "%s/%s", home_dir, filename);
g_snprintf (rfilename, MAXPATHLEN, "%s" G_DIR_SEPARATOR_S "%s",
g_get_home_dir (), filename);
filename = rfilename;
}
parse_info.fp = fopen (filename, "rb");
parse_info.fp = fopen (filename, "r");
if (!parse_info.fp)
return;
@ -447,8 +405,7 @@ save_gimprc (GList **updated_options,
GList **conflicting_options)
{
char timestamp[40];
char *gimp_dir;
char name[MAXPATHLEN];
char *name;
FILE *fp_new;
FILE *fp_old;
GList *option;
@ -460,10 +417,10 @@ save_gimprc (GList **updated_options,
g_assert(updated_options != NULL);
g_assert(conflicting_options != NULL);
gimp_dir = gimp_directory ();
g_snprintf (name, MAXPATHLEN, "%s/gimprc", gimp_dir);
error_msg = open_backup_file (gimp_personal_rc_file ("gimprc"),
gimp_system_rc_file (),
&name, &fp_new, &fp_old);
error_msg = open_backup_file (name, &fp_new, &fp_old);
if (error_msg != NULL)
{
g_message (error_msg);
@ -1499,7 +1456,7 @@ transform_path (char *path,
if (tmp2 == NULL)
{
/* maybe token is an environment variable */
tmp2 = getenv (token);
tmp2 = g_getenv (token);
if (tmp2 != NULL)
{
is_env = TRUE;
@ -2022,7 +1979,13 @@ static inline char *
string_to_str (gpointer val1p,
gpointer val2p)
{
return g_strdup_printf ("%c%s%c", '"', *((char **)val1p), '"');
gchar *str = g_strescape (*((char **)val1p));
gchar *retval;
retval = g_strdup_printf ("%c%s%c", '"', str, '"');
g_free (str);
return retval;
}
static inline char *
@ -2153,15 +2116,24 @@ add_gimp_directory_token (char *gimp_dir)
/* Similarly, transforming the path should be silly. */
unknown_tokens = g_list_append (unknown_tokens, ut);
/* While we're at it, also add the token gimp_install_dir */
ut = g_new (UnknownToken, 1);
ut->token = g_strdup ("gimp_install_dir");
ut->value = gimp_data_directory ();
unknown_tokens = g_list_append (unknown_tokens, ut);
}
/* Try to:
1. Open gimprc for reading.
1. Open the personal file for reading.
2. Rename gimprc to gimprc.old.
1b. If that fails, try to open the system (overriding) file
3. Open gimprc for writing.
2. If we could open the personal file, rename it to file.old.
3. Open personal file for writing.
On success, return NULL. On failure, return a string in English
explaining the problem.
@ -2169,44 +2141,67 @@ add_gimp_directory_token (char *gimp_dir)
*/
static char *
open_backup_file (char *filename,
char *secondary_filename,
char **name_used,
FILE **fp_new,
FILE **fp_old)
{
char *oldfilename;
char *oldfilename = NULL;
/*
Rename the file to *.old, open it for reading and create the new file.
*/
if ((*fp_old = fopen (filename, "rb")) == NULL)
/* Rename the file to *.old, open it for reading and create the new file. */
if ((*fp_old = fopen (filename, "r")) == NULL)
{
if (errno == EACCES)
return _("Can't open gimprc; permission problems");
if (errno == ENOENT)
return _("Can't open gimprc; file does not exist");
return _("Can't open gimprc, reason unknown");
if ((*fp_old = fopen (secondary_filename, "r")) == NULL)
{
if (errno == EACCES)
return g_strdup_printf (_("Can't open %s; permission problems"),
secondary_filename);
if (errno == ENOENT)
return g_strdup_printf (_("Can't open %s; file does not exist"),
secondary_filename);
return g_strdup_printf (_("Can't open %s; reason unknown"),
secondary_filename);
}
else
*name_used = secondary_filename;
}
else
{
*name_used = filename;
oldfilename = g_strdup_printf ("%s.old", filename);
#ifdef NATIVE_WIN32
/* Can't rename open files... */
fclose (*fp_old);
/* Also, can't rename to an existing file name */
unlink (oldfilename);
#endif
if (rename (filename, oldfilename) < 0)
{
g_free (oldfilename);
return g_strdup_printf (_("Can't rename %s to %s.old; %s"),
filename, filename, g_strerror (errno));
}
#ifdef NATIVE_WIN32
/* Can't rename open files... */
if ((*fp_old = fopen (oldfilename, "r")) == NULL)
g_error (_("Couldn't reopen %s\n"), oldfilename);
#endif
}
oldfilename = g_strdup_printf ("%s.old", filename);
if (rename (filename, oldfilename) < 0)
if ((*fp_new = fopen (filename, "w")) == NULL)
{
g_free (oldfilename);
if (errno == EACCES)
return _("Can't rename gimprc to gimprc.old; permission problems");
if (errno == EISDIR)
return _("Can't rename gimprc to gimprc.old; gimprc.old is a directory");
return _("Can't rename gimprc to gimprc.old, reason unknown");
if (oldfilename != NULL)
{
/* Undo the renaming... */
(void) rename (oldfilename, filename);
g_free (oldfilename);
}
return g_strdup_printf (_("Can't write to %s; %s"),
filename, g_strerror (errno));
}
if ((*fp_new = fopen (filename, "wb")) == NULL)
{
(void) rename (oldfilename, filename);
g_free (oldfilename);
if (errno == EACCES)
return _("Can't write to gimprc; permission problems");
return _("Can't write to gimprc, reason unknown");
}
g_free (oldfilename);
if (oldfilename != NULL)
g_free (oldfilename);
return NULL;
}

View File

@ -77,7 +77,6 @@ extern char * image_title_format;
/* function prototypes */
char * gimp_directory (void);
void parse_gimprc (void);
void parse_gimprc_file (char *filename);
void save_gimprc (GList **updated_options, GList **conflicting_options);

View File

@ -17,6 +17,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gtk/gtk.h>
@ -25,6 +26,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#include "about_dialog.h"
#include "interface.h"
@ -294,7 +296,8 @@ about_dialog_load_logo (GtkWidget *window)
if (logo_pixmap)
return TRUE;
g_snprintf (buf, sizeof(buf), "%s/gimp_logo.ppm", DATADIR);
g_snprintf (buf, sizeof(buf), "%s" G_DIR_SEPARATOR_S "gimp_logo.ppm",
gimp_data_directory ());
fp = fopen (buf, "rb");
if (!fp)

View File

@ -20,6 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "actionarea.h"
#include "color_notebook.h"

View File

@ -15,9 +15,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include "appenv.h"
#include "actionarea.h"
@ -32,6 +34,7 @@
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define CELL_SIZE 20 /* The size of the preview cells */
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@ -212,20 +215,14 @@ devices_init (void)
void
devices_restore()
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
GList *tmp_list;
DeviceInfo *device_info;
/* Augment with information from rc file */
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("devicerc");
parse_gimprc_file (filename);
g_free (filename);
tmp_list = devices_info;
device_info = NULL;
@ -625,25 +622,19 @@ devices_write_rc_device (DeviceInfo *device_info, FILE *fp)
static void
devices_write_rc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
devices_save_current_info();
filename = gimp_personal_rc_file ("devicerc");
fp = fopen (filename, "wb");
g_free (filename);
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
if (!fp)
return;
fp = fopen (filename, "wb");
if (!fp)
return;
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
fclose (fp);
}
fclose (fp);
}
void

View File

@ -15,9 +15,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include "appenv.h"
#include "actionarea.h"
@ -32,6 +34,7 @@
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define CELL_SIZE 20 /* The size of the preview cells */
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@ -212,20 +215,14 @@ devices_init (void)
void
devices_restore()
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
GList *tmp_list;
DeviceInfo *device_info;
/* Augment with information from rc file */
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("devicerc");
parse_gimprc_file (filename);
g_free (filename);
tmp_list = devices_info;
device_info = NULL;
@ -625,25 +622,19 @@ devices_write_rc_device (DeviceInfo *device_info, FILE *fp)
static void
devices_write_rc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
devices_save_current_info();
filename = gimp_personal_rc_file ("devicerc");
fp = fopen (filename, "wb");
g_free (filename);
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
if (!fp)
return;
fp = fopen (filename, "wb");
if (!fp)
return;
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
fclose (fp);
}
fclose (fp);
}
void

View File

@ -35,6 +35,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define MRU_MENU_ENTRY_SIZE (strlen (_("/File/MRU00 ")) + 1)
#define MRU_MENU_ACCEL_SIZE sizeof ("<control>0")
@ -403,7 +404,7 @@ menus_quit ()
{
gchar *filename;
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_dump_rc (filename, NULL, TRUE);
g_free (filename);
@ -635,7 +636,7 @@ menus_init ()
if (tool_info[i].menu_path)
menus_tools_create (tool_info+i);
}
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_parse_rc (filename);
g_free (filename);
}

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -38,10 +38,13 @@
Please point me into the right direction to make this work with Gnome-SM.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <sys/param.h>
#endif
#include <gtk/gtk.h>
@ -52,6 +55,7 @@
#include "session.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
static void sessionrc_write_info (SessionInfo *, FILE *);
static void session_open_dialog (SessionInfo *);
@ -107,7 +111,13 @@ session_set_window_geometry (GtkWidget *window,
if ( window == NULL || info == NULL)
return;
#ifdef WINDOWS_DISPLAY
/* We should not position windows so that no decoration is visible */
if (info->y > 0)
gtk_widget_set_uposition (window, info->x, info->y);
#else
gtk_widget_set_uposition (window, info->x, info->y);
#endif
if ( (set_size) && (info->width > 0) && (info->height > 0) )
gtk_window_set_default_size (GTK_WINDOW(window), info->width, info->height);
@ -116,51 +126,42 @@ session_set_window_geometry (GtkWidget *window,
void
save_sessionrc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/sessionrc", gimp_dir);
filename = gimp_personal_rc_file ("sessionrc");
fp = fopen (filename, "wb");
if (!fp)
return;
fp = fopen (filename, "w");
g_free (filename);
if (!fp)
return;
fprintf(fp, _("# GIMP sessionrc\n"));
fprintf(fp, _("# This file takes session-specific info (that is info,\n"));
fprintf(fp, _("# you want to keep between two gimp-sessions). You are\n"));
fprintf(fp, _("# not supposed to edit it manually, but of course you\n"));
fprintf(fp, _("# can do. This file will be entirely rewritten every time\n"));
fprintf(fp, _("# you quit the gimp. If this file isn't found, defaults\n"));
fprintf(fp, _("# are used.\n\n"));
/* save window geometries */
g_list_foreach (session_info_updates, (GFunc)sessionrc_write_info, fp);
/* save last tip shown */
fprintf(fp, "(last-tip-shown %d)\n\n", last_tip + 1);
fclose (fp);
}
fprintf(fp, _("# GIMP sessionrc\n"));
fprintf(fp, _("# This file takes session-specific info (that is info,\n"));
fprintf(fp, _("# you want to keep between two gimp-sessions). You are\n"));
fprintf(fp, _("# not supposed to edit it manually, but of course you\n"));
fprintf(fp, _("# can do. This file will be entirely rewritten every time\n"));
fprintf(fp, _("# you quit the gimp. If this file isn't found, defaults\n"));
fprintf(fp, _("# are used.\n\n"));
/* save window geometries */
g_list_foreach (session_info_updates, (GFunc)sessionrc_write_info, fp);
/* save last tip shown */
fprintf(fp, "(last-tip-shown %d)\n\n", last_tip + 1);
fclose (fp);
}
void
session_init (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/sessionrc", gimp_dir);
app_init_update_status(NULL, filename, -1);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("sessionrc");
app_init_update_status(NULL, filename, -1);
parse_gimprc_file (filename);
g_free (filename);
}
void

View File

@ -1,3 +1,5 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -8,8 +10,8 @@
#include "interface.h"
#include "wilber.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define TIPS_FILE_NAME "gimp_tips.txt"
@ -39,22 +41,17 @@ tips_dialog_create ()
GtkWidget *button_prev;
GtkWidget *vbox_check;
GtkWidget *button_check;
guchar * temp;
gchar * temp;
guchar * src;
guchar * dest;
gchar * gimp_data_dir;
int x;
int y;
if (tips_count == 0)
{
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_dir, TIPS_FILE_NAME);
else
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
DATADIR, TIPS_FILE_NAME);
read_tips_file ((char *)temp);
temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_directory (), TIPS_FILE_NAME);
read_tips_file (temp);
g_free (temp);
}

View File

@ -15,10 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "appenv.h"
#include "actionarea.h"
@ -26,8 +31,16 @@
#include "interface.h"
#include "gimprc.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#ifndef NATIVE_WIN32
# define USER_INSTALL "user_install"
#else
# define STRICT
# include <windows.h>
# define USER_INSTALL "user_install.bat"
#endif
static void install_run (InstallCallback);
static void install_help (InstallCallback);
@ -48,11 +61,7 @@ install_verify (InstallCallback install_callback)
struct stat stat_buf;
filename = gimp_directory ();
if ('\000' == filename[0])
{
g_message (_("No home directory--skipping GIMP user installation."));
(* install_callback) ();
}
/* gimp_directory now always returns something */
if (stat (filename, &stat_buf) != 0)
properly_installed = FALSE;
@ -373,6 +382,47 @@ help_quit_callback (GtkWidget *w,
gtk_exit (0);
}
#ifdef NATIVE_WIN32
static char *
quote_spaces (char *string)
{
int nspaces = 0;
char *p = string, *q, *new;
while (*p)
{
if (*p == ' ')
nspaces++;
p++;
}
if (nspaces == 0)
return g_strdup (string);
new = g_malloc (strlen (string) + nspaces*2 + 1);
p = string;
q = new;
while (*p)
{
if (*p == ' ')
{
*q++ = '"';
*q++ = ' ';
*q++ = '"';
}
else
*q++ = *p;
p++;
}
*q = '\0';
return new;
}
#endif
static void
install_run (InstallCallback callback)
{
@ -389,7 +439,6 @@ install_run (InstallCallback callback)
GdkFont *font;
FILE *pfp;
char buffer[2048];
char *gimp_data_dir;
struct stat stat_buf;
int err;
int executable = TRUE;
@ -430,14 +479,13 @@ install_run (InstallCallback callback)
/* Realize the text widget before inserting text strings */
gtk_widget_realize (text);
#ifndef NATIVE_WIN32
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL, _("User Installation Log\n\n"), -1);
#endif
/* Generate output */
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
g_snprintf (buffer, sizeof(buffer), "%s/user_install", gimp_data_dir);
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install", DATADIR);
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL,
gimp_data_directory ());
if ((err = stat (buffer, &stat_buf)) != 0)
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -445,6 +493,7 @@ install_run (InstallCallback callback)
_(" does not exist. Cannot install.\n"), -1);
executable = FALSE;
}
#ifdef S_IXUSR
else if (! (S_IXUSR & stat_buf.st_mode) || ! (S_IRUSR & stat_buf.st_mode))
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -452,21 +501,51 @@ install_run (InstallCallback callback)
_(" has invalid permissions.\nCannot install."), -1);
executable = FALSE;
}
#endif
if (executable == TRUE)
{
if (gimp_data_dir)
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
gimp_data_dir, gimp_data_dir, gimp_directory ());
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
DATADIR, DATADIR, gimp_directory ());
#ifdef NATIVE_WIN32
char *quoted_data_dir, *quoted_user_dir;
/* On Windows, it is common for the GIMP data directory
* to have spaces in it ("c:\Program Files\GIMP"). Put spaces in quotes.
*/
quoted_data_dir = quote_spaces (gimp_data_directory ());
quoted_user_dir = quote_spaces (gimp_directory ());
/* The Microsoft _popen doesn't work in Windows applications, sigh.
* Do the installation by calling system(). The user_install.bat
* ends with a pause command, so the user has to press enter in
* the console window to continue, and thus has a chance to read
* at the window contents.
*/
AllocConsole ();
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
quoted_data_dir, quoted_data_dir,
quoted_user_dir);
if (system (buffer) == -1)
executable = FALSE;
g_free (quoted_data_dir);
g_free (quoted_user_dir);
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL,
"Did you notice any error messages\n"
"in the console window? If not, installation\n"
"was successful! Otherwise, quit and investigate\n"
"the possible reason...\n", -1);
#else
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
gimp_data_directory (), gimp_data_directory(),
gimp_directory ());
/* urk - should really use something better than popen(), since
* we can't tell if the installation script failed --austin */
if ((pfp = popen (buffer, "r")) != NULL)
{
while (fgets (buffer, 2048, pfp))
while (fgets (buffer, sizeof (buffer), pfp))
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
pclose (pfp);
@ -476,6 +555,8 @@ install_run (InstallCallback callback)
else
executable = FALSE;
}
#endif /* !NATIVE_WIN32 */
if (executable == FALSE)
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL,
_("\nInstallation failed. Contact system administrator.\n"), -1);
@ -492,6 +573,10 @@ install_continue_callback (GtkWidget *w,
{
InstallCallback callback;
#ifdef NATIVE_WIN32
FreeConsole ();
#endif
callback = (InstallCallback) client_data;
gtk_widget_destroy (install_widget);
(* callback) ();

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "appenv.h"
#include "drawable.h"
#include "draw_core.h"

View File

@ -15,10 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "appenv.h"
#include "actionarea.h"
@ -26,8 +31,16 @@
#include "interface.h"
#include "gimprc.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#ifndef NATIVE_WIN32
# define USER_INSTALL "user_install"
#else
# define STRICT
# include <windows.h>
# define USER_INSTALL "user_install.bat"
#endif
static void install_run (InstallCallback);
static void install_help (InstallCallback);
@ -48,11 +61,7 @@ install_verify (InstallCallback install_callback)
struct stat stat_buf;
filename = gimp_directory ();
if ('\000' == filename[0])
{
g_message (_("No home directory--skipping GIMP user installation."));
(* install_callback) ();
}
/* gimp_directory now always returns something */
if (stat (filename, &stat_buf) != 0)
properly_installed = FALSE;
@ -373,6 +382,47 @@ help_quit_callback (GtkWidget *w,
gtk_exit (0);
}
#ifdef NATIVE_WIN32
static char *
quote_spaces (char *string)
{
int nspaces = 0;
char *p = string, *q, *new;
while (*p)
{
if (*p == ' ')
nspaces++;
p++;
}
if (nspaces == 0)
return g_strdup (string);
new = g_malloc (strlen (string) + nspaces*2 + 1);
p = string;
q = new;
while (*p)
{
if (*p == ' ')
{
*q++ = '"';
*q++ = ' ';
*q++ = '"';
}
else
*q++ = *p;
p++;
}
*q = '\0';
return new;
}
#endif
static void
install_run (InstallCallback callback)
{
@ -389,7 +439,6 @@ install_run (InstallCallback callback)
GdkFont *font;
FILE *pfp;
char buffer[2048];
char *gimp_data_dir;
struct stat stat_buf;
int err;
int executable = TRUE;
@ -430,14 +479,13 @@ install_run (InstallCallback callback)
/* Realize the text widget before inserting text strings */
gtk_widget_realize (text);
#ifndef NATIVE_WIN32
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL, _("User Installation Log\n\n"), -1);
#endif
/* Generate output */
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
g_snprintf (buffer, sizeof(buffer), "%s/user_install", gimp_data_dir);
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install", DATADIR);
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL,
gimp_data_directory ());
if ((err = stat (buffer, &stat_buf)) != 0)
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -445,6 +493,7 @@ install_run (InstallCallback callback)
_(" does not exist. Cannot install.\n"), -1);
executable = FALSE;
}
#ifdef S_IXUSR
else if (! (S_IXUSR & stat_buf.st_mode) || ! (S_IRUSR & stat_buf.st_mode))
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -452,21 +501,51 @@ install_run (InstallCallback callback)
_(" has invalid permissions.\nCannot install."), -1);
executable = FALSE;
}
#endif
if (executable == TRUE)
{
if (gimp_data_dir)
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
gimp_data_dir, gimp_data_dir, gimp_directory ());
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
DATADIR, DATADIR, gimp_directory ());
#ifdef NATIVE_WIN32
char *quoted_data_dir, *quoted_user_dir;
/* On Windows, it is common for the GIMP data directory
* to have spaces in it ("c:\Program Files\GIMP"). Put spaces in quotes.
*/
quoted_data_dir = quote_spaces (gimp_data_directory ());
quoted_user_dir = quote_spaces (gimp_directory ());
/* The Microsoft _popen doesn't work in Windows applications, sigh.
* Do the installation by calling system(). The user_install.bat
* ends with a pause command, so the user has to press enter in
* the console window to continue, and thus has a chance to read
* at the window contents.
*/
AllocConsole ();
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
quoted_data_dir, quoted_data_dir,
quoted_user_dir);
if (system (buffer) == -1)
executable = FALSE;
g_free (quoted_data_dir);
g_free (quoted_user_dir);
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL,
"Did you notice any error messages\n"
"in the console window? If not, installation\n"
"was successful! Otherwise, quit and investigate\n"
"the possible reason...\n", -1);
#else
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
gimp_data_directory (), gimp_data_directory(),
gimp_directory ());
/* urk - should really use something better than popen(), since
* we can't tell if the installation script failed --austin */
if ((pfp = popen (buffer, "r")) != NULL)
{
while (fgets (buffer, 2048, pfp))
while (fgets (buffer, sizeof (buffer), pfp))
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
pclose (pfp);
@ -476,6 +555,8 @@ install_run (InstallCallback callback)
else
executable = FALSE;
}
#endif /* !NATIVE_WIN32 */
if (executable == FALSE)
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL,
_("\nInstallation failed. Contact system administrator.\n"), -1);
@ -492,6 +573,10 @@ install_continue_callback (GtkWidget *w,
{
InstallCallback callback;
#ifdef NATIVE_WIN32
FreeConsole ();
#endif
callback = (InstallCallback) client_data;
gtk_widget_destroy (install_widget);
(* callback) ();

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "appenv.h"
#include "actionarea.h"
@ -24,6 +27,7 @@
#include "color_area.h"
#include "commands.h"
#include "devices.h"
#include "dialog_handler.h"
#include "disp_callbacks.h"
#include "errors.h"
#include "gdisplay.h"

View File

@ -35,6 +35,7 @@
#include "gimpsignal.h"
#include "libgimp/gimpintl.h"
#include "libgimp/parasite.h"
#include "layer_pvt.h"
#include "tile_manager_pvt.h"

231
app/makefile.msc Normal file
View File

@ -0,0 +1,231 @@
## Makefile for building gimp.exe with Microsoft C
## Use: nmake -f makefile.msc
# Change this to wherever you want to install gimp.exe.
BIN = D:\gimp\bin
################################################################
# Nothing much configurable below
# cl -? described the options
CC = cl -GA -G5 -GF -Ox -W3 -MD -nologo
# Change to /subsystem:console when debugging
LDFLAGS = /link /subsystem:windows /machine:ix86
INSTALL = copy
TOUCH = copy makefile.msc+nul
GIMP_VER = 1.1
GTK_VER = 1.3
GLIB_VER = 1.2
GTK = ..\..\gtk-plus
GLIB = ..\..\glib-$(GLIB_VER)
GMODULE = $(GLIB)\gmodule
CFLAGS = -DREGEX_MALLOC -DHAVE_CONFIG_H -I. -I.. -I$(GLIB) -I$(GMODULE) -I$(GTK)
GCG = ..\tools\gcg\gcg -I. -I ..\tools\gcg\gh
all : \
..\config.h \
gimpim.lib \
colormap_dialog.c \
gimp.exe
$(TOUCH) all
install : gimp.exe
$(INSTALL) gimp.exe $(BIN)
$(TOUCH) install
..\config.h : ..\config.h.win32
copy ..\config.h.win32 ..\config.h
gimpim_OBJECTS = \
gimpobject.obj \
gimpimage.obj \
gimpset.obj \
gimpsignal.obj \
gimpdrawable.obj
gimpim.lib : $(gimpim_OBJECTS)
lib /out:gimpim.lib $(gimpim_OBJECTS)
gimp_OBJECTS = \
about_dialog.obj\
actionarea.obj \
airbrush.obj \
app_procs.obj \
asupsample.obj \
batch.obj \
bezier_select.obj\
blend.obj \
blob.obj \
boundary.obj \
brightness_contrast.obj\
brush_edit.obj \
brush_select.obj\
bucket_fill.obj \
buildmenu.obj \
by_color_select.obj\
channel.obj \
channel_cmds.obj\
channels_dialog.obj\
channel_ops.obj \
clone.obj \
color_area.obj \
color_balance.obj\
color_notebook.obj\
color_panel.obj \
color_picker.obj\
color_select.obj\
color_transfer.obj\
colormaps.obj \
colormap_dialog.obj\
commands.obj \
convert.obj \
convolve.obj \
crop.obj \
cursorutil.obj \
curves.obj \
datafiles.obj \
desaturate.obj \
devices.obj \
dialog_handler.obj\
disp_callbacks.obj\
docindex.obj \
docindexif.obj \
draw_core.obj \
drawable.obj \
drawable_cmds.obj\
edit_cmds.obj \
edit_selection.obj\
ellipse_select.obj\
eraser.obj \
errorconsole.obj\
errors.obj \
equalize.obj \
fileops.obj \
flip_tool.obj \
floating_sel.obj\
floating_sel_cmds.obj\
file_new_dialog.obj\
frac.obj \
free_select.obj \
fuzzy_select.obj\
gdisplay.obj \
gdisplay_cmds.obj\
gdisplay_ops.obj\
general.obj \
gimage.obj \
gimage_cmds.obj \
gimage_mask.obj \
gimage_mask_cmds.obj\
gimpbrush.obj \
gimpbrushgenerated.obj\
gimpbrushlist.obj\
gimphistogram.obj\
gimplist.obj \
gimplut.obj \
gimpparasite.obj\
gimpprogress.obj\
gimprc.obj \
global_edit.obj \
gradient.obj \
gradient_select.obj\
gximage.obj \
histogramwidget.obj \
histogram_tool.obj\
hue_saturation.obj\
image_map.obj \
image_render.obj\
info_dialog.obj \
info_window.obj \
ink.obj \
install.obj \
interface.obj \
internal_procs.obj\
invert.obj \
iscissors.obj \
layer.obj \
layer_cmds.obj \
layer_select.obj\
layers_dialog.obj\
levels.obj \
magnify.obj \
main.obj \
menus.obj \
module_db.obj \
move.obj \
ops_buttons.obj \
palette.obj \
palette_select.obj\
paint_core.obj \
paint_funcs.obj \
paintbrush.obj \
parasite_cmds.obj\
parasitelist.obj\
paths_dialog.obj\
pattern_select.obj\
patterns.obj \
pencil.obj \
perspective_tool.obj\
pixel_region.obj\
plug_in.obj \
posterize.obj \
preferences_dialog.obj\
procedural_db.obj\
rect_select.obj \
regex.obj \
resize.obj \
rotate_tool.obj \
scale.obj \
scale_tool.obj \
scroll.obj \
selection.obj \
session.obj \
shear_tool.obj \
temp_buf.obj \
text_tool.obj \
threshold.obj \
tile.obj \
tile_cache.obj \
tile_manager.obj\
tile_swap.obj \
tips_dialog.obj \
tools.obj \
transform_core.obj\
transform_tool.obj\
undo.obj \
undo_cmds.obj \
vector2d.obj \
xcf.obj
.SUFFIXES: .gc
.gc.c:
$(GCG) -o $@ $<
gimp.res : gimp.rc wilber.ico
rc -r -fo gimp.res gimp.rc
gimp.exe : ../config.h $(gimp_OBJECTS) gimpim.lib gimp.res
$(CC) $(CFLAGS) -Fegimp.exe $(gimp_OBJECTS) gimpim.lib ..\libgimp\gimpi-$(GIMP_VER).lib $(GTK)\gtk\gtk-$(GTK_VER).lib $(GTK)\gdk\gdk-$(GTK_VER).lib $(GLIB)\glib-$(GLIB_VER).lib $(GLIB)\gmodule-$(GLIB_VER).lib $(LDFLAGS) gimp.res gdi32.lib user32.lib /def:gimp.def
# General rule for building $(gimp_OBJECTS)
.c.obj:
$(CC) $(CFLAGS) -c $<
clean:
del *.exe
del *.lib
del *.obj
del *.exp
del *.err
del *.map
del *.sym
del *.lk1
del *.mk1
del *.pdb
del *.ilk

View File

@ -35,6 +35,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define MRU_MENU_ENTRY_SIZE (strlen (_("/File/MRU00 ")) + 1)
#define MRU_MENU_ACCEL_SIZE sizeof ("<control>0")
@ -403,7 +404,7 @@ menus_quit ()
{
gchar *filename;
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_dump_rc (filename, NULL, TRUE);
g_free (filename);
@ -635,7 +636,7 @@ menus_init ()
if (tool_info[i].menu_path)
menus_tools_create (tool_info+i);
}
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_parse_rc (filename);
g_free (filename);
}

View File

@ -35,6 +35,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define MRU_MENU_ENTRY_SIZE (strlen (_("/File/MRU00 ")) + 1)
#define MRU_MENU_ACCEL_SIZE sizeof ("<control>0")
@ -403,7 +404,7 @@ menus_quit ()
{
gchar *filename;
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_dump_rc (filename, NULL, TRUE);
g_free (filename);
@ -635,7 +636,7 @@ menus_init ()
if (tool_info[i].menu_path)
menus_tools_create (tool_info+i);
}
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_parse_rc (filename);
g_free (filename);
}

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "appenv.h"
#include "drawable.h"
#include "draw_core.h"

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -15,22 +15,52 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/stat.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef WIN32
#define STRICT
#include <windows.h>
#include <process.h>
#ifdef _MSC_VER
#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
#include "regex.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h" /* ick */
#include "libgimp/gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -75,15 +105,15 @@ struct _PlugInBlocked
};
static int plug_in_write (int fd,
static int plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count);
static int plug_in_flush (int fd);
static int plug_in_flush (GIOChannel *channel);
static void plug_in_push (PlugIn *plug_in);
static void plug_in_pop (void);
static void plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond);
static gboolean plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data);
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);
@ -144,8 +174,8 @@ static GSList *blocked_plug_ins = NULL;
static GSList *plug_in_stack = NULL;
static PlugIn *current_plug_in = NULL;
static int current_readfd = 0;
static int current_writefd = 0;
static GIOChannel *current_readchannel = NULL;
static GIOChannel *current_writechannel = NULL;
static int current_write_buffer_index = 0;
static char *current_write_buffer = NULL;
static Argument *current_return_vals = NULL;
@ -156,6 +186,10 @@ static ProcRecord *last_plug_in = NULL;
static int shm_ID = -1;
static guchar *shm_addr = NULL;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static int write_pluginrc = FALSE;
static ProcArg progress_init_args[] =
@ -394,7 +428,7 @@ void
plug_in_init ()
{
extern int use_shm;
char filename[MAXPATHLEN];
char *filename;
GSList *tmp, *tmp2;
PlugInDef *plug_in_def;
PlugInProcDef *proc_def;
@ -423,22 +457,22 @@ plug_in_init ()
wire_set_writer (plug_in_write);
wire_set_flusher (plug_in_flush);
#ifdef HAVE_SHM_H
/* 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)
{
#ifdef HAVE_SHM_H
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
if (shm_ID == -1)
g_message (_("shmget failed...disabling shared memory tile transport\n"));
g_message (_("shmget failed...disabling shared memory tile transport"));
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_message (_("shmat failed...disabling shared memory tile transport\n"));
g_message (_("shmat failed...disabling shared memory tile transport"));
shm_ID = -1;
}
@ -447,22 +481,62 @@ plug_in_init ()
shmctl (shm_ID, IPC_RMID, 0);
#endif
}
}
#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
}
/* 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 */
filename = NULL;
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
if (g_path_is_absolute (pluginrc_path))
filename = g_strdup (pluginrc_path);
else
g_snprintf(filename, MAXPATHLEN, "%s/%s", gimp_directory(), pluginrc_path);
filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_directory (), pluginrc_path);
}
else
g_snprintf (filename, MAXPATHLEN, "%s/pluginrc", gimp_directory ());
filename = gimp_personal_rc_file ("pluginrc");
app_init_update_status(_("Resource configuration"), filename, -1);
parse_gimprc_file (filename);
@ -525,6 +599,8 @@ plug_in_init ()
plug_in_write_rc (filename);
}
g_free (filename);
/* add the plug-in procs to the procedure database */
plug_in_add_to_db ();
@ -582,6 +658,9 @@ plug_in_kill ()
GSList *tmp;
PlugIn *plug_in;
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
#ifndef IPC_RMID_DEFERRED_RELEASE
if (shm_ID != -1)
@ -593,6 +672,7 @@ plug_in_kill ()
if (shm_ID != -1)
shmdt ((char*) shm_addr);
#endif
#endif
#endif
tmp = open_plug_ins;
@ -787,7 +867,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
PlugInProcDef *proc_def;
char *t1, *t2;
t1 = strrchr (plug_in_def->prog, '/');
t1 = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (t1)
t1 = t1 + 1;
else
@ -819,7 +899,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
{
tplug_in_def = tmp->data;
t2 = strrchr (tplug_in_def->prog, '/');
t2 = strrchr (tplug_in_def->prog, G_DIR_SEPARATOR);
if (t2)
t2 = t2 + 1;
else
@ -827,7 +907,7 @@ plug_in_def_add (PlugInDef *plug_in_def)
if (strcmp (t1, t2) == 0)
{
if ((strcmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
(plug_in_def->mtime == tplug_in_def->mtime))
{
/* Use cached plug-in entry */
@ -895,7 +975,7 @@ plug_in_new (char *name)
PlugIn *plug_in;
char *path;
if (name[0] != '/')
if (!g_path_is_absolute (name))
{
path = search_in_path (plug_in_path, name);
if (!path)
@ -920,15 +1000,15 @@ plug_in_new (char *name)
plug_in->pid = 0;
plug_in->args[0] = g_strdup (path);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = g_new (char, 16);
plug_in->args[3] = g_new (char, 16);
plug_in->args[2] = g_new (char, 32);
plug_in->args[3] = g_new (char, 32);
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
@ -986,15 +1066,42 @@ plug_in_open (PlugIn *plug_in)
return 0;
}
plug_in->my_read = my_read[0];
plug_in->my_write = my_write[1];
plug_in->his_read = my_write[0];
plug_in->his_write = my_read[1];
#ifdef __CYGWIN32__
/* 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
/* Remember the file descriptors for the pipes.
*/
sprintf (plug_in->args[2], "%d", plug_in->his_read);
sprintf (plug_in->args[3], "%d", plug_in->his_write);
#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));
sprintf (plug_in->args[3], "%d:%ud:%d",
g_io_channel_win32_get_fd (plug_in->his_write),
GetCurrentThreadId (),
g_io_channel_win32_get_fd (plug_in->my_read));
#endif
/* Set the rest of the command line arguments.
*/
@ -1015,6 +1122,10 @@ plug_in_open (PlugIn *plug_in)
* so that we can later use it to kill the filter if
* necessary.
*/
#if defined (__CYGWIN32__) || defined (NATIVE_WIN32)
plug_in->pid = spawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
if (plug_in->pid == -1)
#else
plug_in->pid = fork ();
if (plug_in->pid == 0)
@ -1029,19 +1140,37 @@ plug_in_open (PlugIn *plug_in)
_exit (1);
}
else if (plug_in->pid == -1)
#endif
{
g_message (_("unable to run plug-in: %s\n"), plug_in->args[0]);
g_message (_("unable to run plug-in: %s"), plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
close(plug_in->his_read); plug_in->his_read = -1;
close(plug_in->his_write); plug_in->his_write = -1;
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
if (!plug_in->synchronous)
{
plug_in->input_id = gdk_input_add (plug_in->my_read,
GDK_INPUT_READ,
plug_in->input_id = g_io_add_watch (plug_in->my_read,
G_IO_IN | G_IO_PRI,
plug_in_recv_message,
plug_in);
@ -1060,7 +1189,9 @@ plug_in_close (PlugIn *plug_in,
int kill_it)
{
int status;
#ifndef NATIVE_WIN32
struct timeval tv;
#endif
if (plug_in && plug_in->open)
{
@ -1071,17 +1202,22 @@ plug_in_close (PlugIn *plug_in,
if (kill_it && plug_in->pid)
{
plug_in_push (plug_in);
gp_quit_write (current_writefd);
gp_quit_write (current_writechannel);
plug_in_pop ();
/* give the plug-in some time (10 ms) */
#ifndef NATIVE_WIN32
tv.tv_sec = 0;
tv.tv_usec = 100;
tv.tv_usec = 100; /* But this is 0.1 ms? */
select (0, NULL, NULL, NULL, &tv);
#else
Sleep (10);
#endif
}
/* If necessary, kill the filter.
*/
#ifndef NATIVE_WIN32
if (kill_it && plug_in->pid)
status = kill (plug_in->pid, SIGKILL);
@ -1090,6 +1226,10 @@ plug_in_close (PlugIn *plug_in,
*/
if (plug_in->pid)
waitpid (plug_in->pid, &status, 0);
#else
if (kill_it && plug_in->pid)
TerminateProcess ((HANDLE) plug_in->pid, 0);
#endif
/* Remove the input handler.
*/
@ -1098,14 +1238,30 @@ plug_in_close (PlugIn *plug_in,
/* Close the pipes.
*/
if (plug_in->my_read)
close (plug_in->my_read);
if (plug_in->my_write)
close (plug_in->my_write);
if (plug_in->his_read)
close (plug_in->his_read);
if (plug_in->his_write)
close (plug_in->his_write);
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;
}
wire_clear_error();
@ -1119,10 +1275,10 @@ plug_in_close (PlugIn *plug_in,
*/
plug_in->pid = 0;
plug_in->input_id = 0;
plug_in->my_read = 0;
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->my_read = NULL;
plug_in->my_write = NULL;
plug_in->his_read = NULL;
plug_in->his_write = NULL;
if (plug_in->recurse)
gtk_main_quit ();
@ -1243,9 +1399,9 @@ plug_in_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_config_write (current_writefd, &config) ||
!gp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_config_write (current_writechannel, &config) ||
!gp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;
@ -1360,17 +1516,19 @@ plug_in_set_menu_sensitivity (int base_type)
}
}
static void
plug_in_recv_message (gpointer data,
gint id,
GdkInputCondition cond)
static gboolean
plug_in_recv_message (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
WireMessage msg;
plug_in_push ((PlugIn*) data);
if (current_readchannel == NULL)
return TRUE;
memset (&msg, 0, sizeof (WireMessage));
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -1382,6 +1540,7 @@ plug_in_recv_message (gpointer data,
plug_in_destroy (current_plug_in);
else
plug_in_pop ();
return TRUE;
}
static void
@ -1393,18 +1552,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_message (_("plug_in_handle_message(): received a config message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a config message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@ -1415,7 +1574,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)\n"));
g_message (_("plug_in_handle_message(): received a temp proc run message (should not happen)"));
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@ -1431,6 +1590,13 @@ plug_in_handle_message (WireMessage *msg)
case GP_EXTENSION_ACK:
gtk_main_quit ();
break;
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;
}
}
@ -1460,14 +1626,14 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_data.data = NULL;
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1476,7 +1642,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_DATA)
{
g_message (_("expected tile data and received: %d\n"), msg.type);
g_message (_("expected tile data and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1490,7 +1656,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1498,7 +1664,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1511,7 +1677,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
if (!gp_tile_ack_write (current_writechannel))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1527,7 +1693,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!tm)
{
g_message (_("plug-in requested invalid drawable (killing)\n"));
g_message (_("plug-in requested invalid drawable (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1535,7 +1701,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
if (!tile)
{
g_message (_("plug-in requested invalid tile (killing)\n"));
g_message (_("plug-in requested invalid tile (killing)"));
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1553,7 +1719,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
tile_data.data = tile_data_pointer (tile, 0, 0);
if (!gp_tile_data_write (current_writefd, &tile_data))
if (!gp_tile_data_write (current_writechannel, &tile_data))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1562,7 +1728,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
{
g_message (_("plug_in_handle_tile_req: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1571,7 +1737,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (msg.type != GP_TILE_ACK)
{
g_message (_("expected tile ack and received: %d\n"), msg.type);
g_message (_("expected tile ack and received: %d"), msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@ -1595,7 +1761,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_message (_("PDB lookup failed on %s\n"), proc_run->name);
g_message (_("PDB lookup failed on %s"), proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@ -1617,7 +1783,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
}
if (!gp_proc_return_write (current_writefd, &proc_return))
if (!gp_proc_return_write (current_writechannel, &proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1661,7 +1827,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
if (strcmp (blocked->proc_name, proc_return->name) == 0)
{
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
if (!gp_proc_return_write (current_writechannel, proc_return))
{
g_message (_("plug_in_handle_proc_run: ERROR"));
plug_in_close (current_plug_in, TRUE);
@ -1923,9 +2089,9 @@ plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
}
static int
plug_in_write (int fd,
guint8 *buf,
gulong count)
plug_in_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
gulong bytes;
@ -1936,7 +2102,7 @@ plug_in_write (int fd,
bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
memcpy (&current_write_buffer[current_write_buffer_index], buf, bytes);
current_write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1954,8 +2120,9 @@ plug_in_write (int fd,
}
static int
plug_in_flush (int fd)
plug_in_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1965,11 +2132,13 @@ plug_in_flush (int fd)
while (count != current_write_buffer_index)
{
do {
bytes = write (fd, &current_write_buffer[count],
(current_write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &current_write_buffer[count],
(current_write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1989,15 +2158,15 @@ plug_in_push (PlugIn *plug_in)
current_plug_in = plug_in;
plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2021,16 +2190,16 @@ plug_in_pop ()
if (plug_in_stack)
{
current_plug_in = plug_in_stack->data;
current_readfd = current_plug_in->my_read;
current_writefd = current_plug_in->my_write;
current_readchannel = current_plug_in->my_read;
current_writechannel = current_plug_in->my_write;
current_write_buffer_index = current_plug_in->write_buffer_index;
current_write_buffer = current_plug_in->write_buffer;
}
else
{
current_plug_in = NULL;
current_readfd = 0;
current_writefd = 0;
current_readchannel = NULL;
current_writechannel = NULL;
current_write_buffer_index = 0;
current_write_buffer = NULL;
}
@ -2045,9 +2214,27 @@ plug_in_write_rc_string (FILE *fp,
if (str)
while (*str)
{
if ((*str == '"') || (*str == '\\'))
fputc ('\\', fp);
fputc (*str, fp);
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);
}
str += 1;
}
@ -2063,7 +2250,7 @@ plug_in_write_rc (char *filename)
GSList *tmp, *tmp2;
int i;
fp = fopen (filename, "wb");
fp = fopen (filename, "w");
if (!fp)
return;
@ -2075,10 +2262,9 @@ plug_in_write_rc (char *filename)
if (plug_in_def->proc_defs)
{
fprintf (fp, "(plug-in-def \"%s\" %ld",
plug_in_def->prog,
(long) plug_in_def->mtime);
fprintf (fp, "(plug-in-def ");
plug_in_write_rc_string (fp, plug_in_def->prog);
fprintf (fp, " %ld", (long) plug_in_def->mtime);
tmp2 = plug_in_def->proc_defs;
if (tmp2)
fprintf (fp, "\n");
@ -2161,7 +2347,7 @@ plug_in_init_file (char *filename)
char *plug_in_name;
char *name;
name = strrchr (filename, '/');
name = strrchr (filename, G_DIR_SEPARATOR);
if (name)
name = name + 1;
else
@ -2175,13 +2361,13 @@ plug_in_init_file (char *filename)
plug_in_def = tmp->data;
tmp = tmp->next;
plug_in_name = strrchr (plug_in_def->prog, '/');
plug_in_name = strrchr (plug_in_def->prog, G_DIR_SEPARATOR);
if (plug_in_name)
plug_in_name = plug_in_name + 1;
else
plug_in_name = plug_in_def->prog;
if (strcmp (name, plug_in_name) == 0)
if (g_strcasecmp (name, plug_in_name) == 0)
{
g_print (_("duplicate plug-in: \"%s\" (skipping)\n"), filename);
return;
@ -2219,7 +2405,7 @@ plug_in_query (char *filename,
while (plug_in->open)
{
if (!wire_read_msg (current_readfd, &msg))
if (!wire_read_msg (current_readchannel, &msg))
plug_in_close (current_plug_in, TRUE);
else
{
@ -2592,8 +2778,8 @@ plug_in_temp_run (ProcRecord *proc_rec,
proc_run.nparams = argc;
proc_run.params = plug_in_args_to_params (args, argc, FALSE);
if (!gp_temp_proc_run_write (current_writefd, &proc_run) ||
!wire_flush (current_writefd))
if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
!wire_flush (current_writechannel))
{
return_vals = procedural_db_return_args (proc_rec, FALSE);
goto done;

View File

@ -58,8 +58,12 @@ struct _PlugIn
pid_t pid; /* Plug-ins process id */
char *args[7]; /* Plug-ins command line arguments */
int my_read, my_write; /* Apps read and write file descriptors */
int his_read, his_write; /* Plug-ins read and write file descriptors */
GIOChannel *my_read, *my_write; /* App's read and write channels */
GIOChannel *his_read, *his_write; /* Plug-in's read and write channels */
#ifdef NATIVE_WIN32
guint his_thread_id; /* Plug-in's thread ID */
int his_read_fd; /* Plug-in's read pipe fd */
#endif
guint32 input_id; /* Id of input proc */

View File

@ -38,10 +38,13 @@
Please point me into the right direction to make this work with Gnome-SM.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <sys/param.h>
#endif
#include <gtk/gtk.h>
@ -52,6 +55,7 @@
#include "session.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
static void sessionrc_write_info (SessionInfo *, FILE *);
static void session_open_dialog (SessionInfo *);
@ -107,7 +111,13 @@ session_set_window_geometry (GtkWidget *window,
if ( window == NULL || info == NULL)
return;
#ifdef WINDOWS_DISPLAY
/* We should not position windows so that no decoration is visible */
if (info->y > 0)
gtk_widget_set_uposition (window, info->x, info->y);
#else
gtk_widget_set_uposition (window, info->x, info->y);
#endif
if ( (set_size) && (info->width > 0) && (info->height > 0) )
gtk_window_set_default_size (GTK_WINDOW(window), info->width, info->height);
@ -116,51 +126,42 @@ session_set_window_geometry (GtkWidget *window,
void
save_sessionrc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/sessionrc", gimp_dir);
filename = gimp_personal_rc_file ("sessionrc");
fp = fopen (filename, "wb");
if (!fp)
return;
fp = fopen (filename, "w");
g_free (filename);
if (!fp)
return;
fprintf(fp, _("# GIMP sessionrc\n"));
fprintf(fp, _("# This file takes session-specific info (that is info,\n"));
fprintf(fp, _("# you want to keep between two gimp-sessions). You are\n"));
fprintf(fp, _("# not supposed to edit it manually, but of course you\n"));
fprintf(fp, _("# can do. This file will be entirely rewritten every time\n"));
fprintf(fp, _("# you quit the gimp. If this file isn't found, defaults\n"));
fprintf(fp, _("# are used.\n\n"));
/* save window geometries */
g_list_foreach (session_info_updates, (GFunc)sessionrc_write_info, fp);
/* save last tip shown */
fprintf(fp, "(last-tip-shown %d)\n\n", last_tip + 1);
fclose (fp);
}
fprintf(fp, _("# GIMP sessionrc\n"));
fprintf(fp, _("# This file takes session-specific info (that is info,\n"));
fprintf(fp, _("# you want to keep between two gimp-sessions). You are\n"));
fprintf(fp, _("# not supposed to edit it manually, but of course you\n"));
fprintf(fp, _("# can do. This file will be entirely rewritten every time\n"));
fprintf(fp, _("# you quit the gimp. If this file isn't found, defaults\n"));
fprintf(fp, _("# are used.\n\n"));
/* save window geometries */
g_list_foreach (session_info_updates, (GFunc)sessionrc_write_info, fp);
/* save last tip shown */
fprintf(fp, "(last-tip-shown %d)\n\n", last_tip + 1);
fclose (fp);
}
void
session_init (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/sessionrc", gimp_dir);
app_init_update_status(NULL, filename, -1);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("sessionrc");
app_init_update_status(NULL, filename, -1);
parse_gimprc_file (filename);
g_free (filename);
}
void

View File

@ -458,9 +458,13 @@ text_gdk_image_to_region (GdkImage *image,
unsigned char * data;
scale2 = scale * scale;
#ifndef WINDOWS_DISPLAY
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
black_pixel = black.pixel;
#else
black_pixel = 0;
#endif
data = textPR->data;
for (y = 0, scaley = 0; y < textPR->h; y++, scaley += scale)
@ -591,9 +595,14 @@ text_render (GImage *gimage,
/* get black and white pixels for this gdisplay */
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
white.red = white.green = white.blue = 65535;
#ifndef WINDOWS_DISPLAY
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, FALSE, TRUE);
#else
black.pixel = 0;
white.pixel = 1;
#endif
/* Render the text into the pixmap.
* Since the pixmap may not fully bound the text (because we limit its size)

View File

@ -2,6 +2,7 @@
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

View File

@ -1,3 +1,5 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -8,8 +10,8 @@
#include "interface.h"
#include "wilber.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define TIPS_FILE_NAME "gimp_tips.txt"
@ -39,22 +41,17 @@ tips_dialog_create ()
GtkWidget *button_prev;
GtkWidget *vbox_check;
GtkWidget *button_check;
guchar * temp;
gchar * temp;
guchar * src;
guchar * dest;
gchar * gimp_data_dir;
int x;
int y;
if (tips_count == 0)
{
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_dir, TIPS_FILE_NAME);
else
temp = (char *) g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
DATADIR, TIPS_FILE_NAME);
read_tips_file ((char *)temp);
temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
gimp_data_directory (), TIPS_FILE_NAME);
read_tips_file (temp);
g_free (temp);
}

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "appenv.h"
#include "drawable.h"
#include "draw_core.h"

View File

@ -458,9 +458,13 @@ text_gdk_image_to_region (GdkImage *image,
unsigned char * data;
scale2 = scale * scale;
#ifndef WINDOWS_DISPLAY
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
black_pixel = black.pixel;
#else
black_pixel = 0;
#endif
data = textPR->data;
for (y = 0, scaley = 0; y < textPR->h; y++, scaley += scale)
@ -591,9 +595,14 @@ text_render (GImage *gimage,
/* get black and white pixels for this gdisplay */
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
white.red = white.green = white.blue = 65535;
#ifndef WINDOWS_DISPLAY
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, FALSE, TRUE);
#else
black.pixel = 0;
white.pixel = 1;
#endif
/* Render the text into the pixmap.
* Since the pixmap may not fully bound the text (because we limit its size)

View File

@ -15,6 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "appenv.h"
#include "drawable.h"
#include "draw_core.h"

View File

@ -458,9 +458,13 @@ text_gdk_image_to_region (GdkImage *image,
unsigned char * data;
scale2 = scale * scale;
#ifndef WINDOWS_DISPLAY
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
black_pixel = black.pixel;
#else
black_pixel = 0;
#endif
data = textPR->data;
for (y = 0, scaley = 0; y < textPR->h; y++, scaley += scale)
@ -591,9 +595,14 @@ text_render (GImage *gimage,
/* get black and white pixels for this gdisplay */
black.red = black.green = black.blue = 0;
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
white.red = white.green = white.blue = 65535;
#ifndef WINDOWS_DISPLAY
gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE);
gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, FALSE, TRUE);
#else
black.pixel = 0;
white.pixel = 1;
#endif
/* Render the text into the pixmap.
* Since the pixmap may not fully bound the text (because we limit its size)

View File

@ -15,10 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "appenv.h"
#include "actionarea.h"
@ -26,8 +31,16 @@
#include "interface.h"
#include "gimprc.h"
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#ifndef NATIVE_WIN32
# define USER_INSTALL "user_install"
#else
# define STRICT
# include <windows.h>
# define USER_INSTALL "user_install.bat"
#endif
static void install_run (InstallCallback);
static void install_help (InstallCallback);
@ -48,11 +61,7 @@ install_verify (InstallCallback install_callback)
struct stat stat_buf;
filename = gimp_directory ();
if ('\000' == filename[0])
{
g_message (_("No home directory--skipping GIMP user installation."));
(* install_callback) ();
}
/* gimp_directory now always returns something */
if (stat (filename, &stat_buf) != 0)
properly_installed = FALSE;
@ -373,6 +382,47 @@ help_quit_callback (GtkWidget *w,
gtk_exit (0);
}
#ifdef NATIVE_WIN32
static char *
quote_spaces (char *string)
{
int nspaces = 0;
char *p = string, *q, *new;
while (*p)
{
if (*p == ' ')
nspaces++;
p++;
}
if (nspaces == 0)
return g_strdup (string);
new = g_malloc (strlen (string) + nspaces*2 + 1);
p = string;
q = new;
while (*p)
{
if (*p == ' ')
{
*q++ = '"';
*q++ = ' ';
*q++ = '"';
}
else
*q++ = *p;
p++;
}
*q = '\0';
return new;
}
#endif
static void
install_run (InstallCallback callback)
{
@ -389,7 +439,6 @@ install_run (InstallCallback callback)
GdkFont *font;
FILE *pfp;
char buffer[2048];
char *gimp_data_dir;
struct stat stat_buf;
int err;
int executable = TRUE;
@ -430,14 +479,13 @@ install_run (InstallCallback callback)
/* Realize the text widget before inserting text strings */
gtk_widget_realize (text);
#ifndef NATIVE_WIN32
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL, _("User Installation Log\n\n"), -1);
#endif
/* Generate output */
if ((gimp_data_dir = getenv ("GIMP_DATADIR")) != NULL)
g_snprintf (buffer, sizeof(buffer), "%s/user_install", gimp_data_dir);
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install", DATADIR);
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL,
gimp_data_directory ());
if ((err = stat (buffer, &stat_buf)) != 0)
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -445,6 +493,7 @@ install_run (InstallCallback callback)
_(" does not exist. Cannot install.\n"), -1);
executable = FALSE;
}
#ifdef S_IXUSR
else if (! (S_IXUSR & stat_buf.st_mode) || ! (S_IRUSR & stat_buf.st_mode))
{
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
@ -452,21 +501,51 @@ install_run (InstallCallback callback)
_(" has invalid permissions.\nCannot install."), -1);
executable = FALSE;
}
#endif
if (executable == TRUE)
{
if (gimp_data_dir)
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
gimp_data_dir, gimp_data_dir, gimp_directory ());
else
g_snprintf (buffer, sizeof(buffer), "%s/user_install %s %s",
DATADIR, DATADIR, gimp_directory ());
#ifdef NATIVE_WIN32
char *quoted_data_dir, *quoted_user_dir;
/* On Windows, it is common for the GIMP data directory
* to have spaces in it ("c:\Program Files\GIMP"). Put spaces in quotes.
*/
quoted_data_dir = quote_spaces (gimp_data_directory ());
quoted_user_dir = quote_spaces (gimp_directory ());
/* The Microsoft _popen doesn't work in Windows applications, sigh.
* Do the installation by calling system(). The user_install.bat
* ends with a pause command, so the user has to press enter in
* the console window to continue, and thus has a chance to read
* at the window contents.
*/
AllocConsole ();
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
quoted_data_dir, quoted_data_dir,
quoted_user_dir);
if (system (buffer) == -1)
executable = FALSE;
g_free (quoted_data_dir);
g_free (quoted_user_dir);
gtk_text_insert (GTK_TEXT (text), font_strong, NULL, NULL,
"Did you notice any error messages\n"
"in the console window? If not, installation\n"
"was successful! Otherwise, quit and investigate\n"
"the possible reason...\n", -1);
#else
g_snprintf (buffer, sizeof(buffer), "%s" G_DIR_SEPARATOR_S USER_INSTALL " %s %s",
gimp_data_directory (), gimp_data_directory(),
gimp_directory ());
/* urk - should really use something better than popen(), since
* we can't tell if the installation script failed --austin */
if ((pfp = popen (buffer, "r")) != NULL)
{
while (fgets (buffer, 2048, pfp))
while (fgets (buffer, sizeof (buffer), pfp))
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, buffer, -1);
pclose (pfp);
@ -476,6 +555,8 @@ install_run (InstallCallback callback)
else
executable = FALSE;
}
#endif /* !NATIVE_WIN32 */
if (executable == FALSE)
gtk_text_insert (GTK_TEXT (text), font, NULL, NULL,
_("\nInstallation failed. Contact system administrator.\n"), -1);
@ -492,6 +573,10 @@ install_continue_callback (GtkWidget *w,
{
InstallCallback callback;
#ifdef NATIVE_WIN32
FreeConsole ();
#endif
callback = (InstallCallback) client_data;
gtk_widget_destroy (install_widget);
(* callback) ();

View File

@ -20,6 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "actionarea.h"
#include "color_notebook.h"

View File

@ -15,9 +15,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include "appenv.h"
#include "actionarea.h"
@ -32,6 +34,7 @@
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define CELL_SIZE 20 /* The size of the preview cells */
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@ -212,20 +215,14 @@ devices_init (void)
void
devices_restore()
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
GList *tmp_list;
DeviceInfo *device_info;
/* Augment with information from rc file */
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("devicerc");
parse_gimprc_file (filename);
g_free (filename);
tmp_list = devices_info;
device_info = NULL;
@ -625,25 +622,19 @@ devices_write_rc_device (DeviceInfo *device_info, FILE *fp)
static void
devices_write_rc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
devices_save_current_info();
filename = gimp_personal_rc_file ("devicerc");
fp = fopen (filename, "wb");
g_free (filename);
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
if (!fp)
return;
fp = fopen (filename, "wb");
if (!fp)
return;
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
fclose (fp);
}
fclose (fp);
}
void

View File

@ -15,9 +15,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include "appenv.h"
#include "actionarea.h"
@ -32,6 +34,7 @@
#include "dialog_handler.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define CELL_SIZE 20 /* The size of the preview cells */
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@ -212,20 +215,14 @@ devices_init (void)
void
devices_restore()
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
GList *tmp_list;
DeviceInfo *device_info;
/* Augment with information from rc file */
gimp_dir = gimp_directory ();
if (gimp_dir)
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
parse_gimprc_file (filename);
}
filename = gimp_personal_rc_file ("devicerc");
parse_gimprc_file (filename);
g_free (filename);
tmp_list = devices_info;
device_info = NULL;
@ -625,25 +622,19 @@ devices_write_rc_device (DeviceInfo *device_info, FILE *fp)
static void
devices_write_rc (void)
{
char *gimp_dir;
char filename[MAXPATHLEN];
char *filename;
FILE *fp;
devices_save_current_info();
filename = gimp_personal_rc_file ("devicerc");
fp = fopen (filename, "wb");
g_free (filename);
gimp_dir = gimp_directory ();
if ('\000' != gimp_dir[0])
{
g_snprintf (filename, MAXPATHLEN, "%s/devicerc", gimp_dir);
if (!fp)
return;
fp = fopen (filename, "wb");
if (!fp)
return;
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
g_list_foreach (devices_info, (GFunc)devices_write_rc_device, fp);
fclose (fp);
}
fclose (fp);
}
void

View File

@ -35,6 +35,7 @@
#include "config.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpenv.h"
#define MRU_MENU_ENTRY_SIZE (strlen (_("/File/MRU00 ")) + 1)
#define MRU_MENU_ACCEL_SIZE sizeof ("<control>0")
@ -403,7 +404,7 @@ menus_quit ()
{
gchar *filename;
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_dump_rc (filename, NULL, TRUE);
g_free (filename);
@ -635,7 +636,7 @@ menus_init ()
if (tool_info[i].menu_path)
menus_tools_create (tool_info+i);
}
filename = g_strconcat (gimp_directory (), "/menurc", NULL);
filename = gimp_personal_rc_file ("menurc");
gtk_item_factory_parse_rc (filename);
g_free (filename);
}

BIN
app/wilber.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -4,6 +4,7 @@ gimpincludedir = $(includedir)/libgimp
CPPFLAGS = \
-DGIMPDIR=\""$(gimpdir)"\" \
-DDATADIR=\""$(gimpdatadir)"\" \
@GIMP_THREAD_FLAGS@
INCLUDES = \
@ -21,6 +22,8 @@ lib_LTLIBRARIES = libgimp.la libgimpui.la
noinst_LIBRARIES = libgimpi.a
libgimpi_a_SOURCES = \
gimpenv.c \
gimpenv.h \
gimpchainbutton.c \
gimpchainbutton.h \
gimpmatrix.c \
@ -52,6 +55,7 @@ libgimp_la_SOURCES = \
gimpchannel.c \
gimpdisplay.c \
gimpdrawable.c \
gimpenv.c \
gimpgradient.c \
gimpimage.c \
gimplayer.c \
@ -83,6 +87,7 @@ gimpinclude_HEADERS = \
gimp.h \
gimpchainbutton.h \
gimpenums.h \
gimpenv.h \
gimpfeatures.h \
gimpmatrix.h \
gimpmenu.h \

View File

@ -25,10 +25,18 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "parasiteP.h"
#include "gimpenv.h"
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
@ -42,6 +50,14 @@
#include <sys/select.h>
#endif
#ifdef WIN32
# define STRICT
# include <windows.h>
# ifdef _MSC_VER
# include <io.h>
# endif
#endif
#include "gimp.h"
#include "gimpprotocol.h"
#include "gimpwire.h"
@ -55,8 +71,8 @@ void gimp_read_expect_msg(WireMessage *msg, int type);
static RETSIGTYPE gimp_signal (int signum);
static int gimp_write (int fd, guint8 *buf, gulong count);
static int gimp_flush (int fd);
static int gimp_write (GIOChannel *channel , guint8 *buf, gulong count);
static int gimp_flush (GIOChannel *channel );
static void gimp_loop (void);
static void gimp_config (GPConfig *config);
static void gimp_proc_run (GPProcRun *proc_run);
@ -65,14 +81,19 @@ static void gimp_message_func (char *str);
static void gimp_process_message(WireMessage *msg);
int _readfd = 0;
int _writefd = 0;
GIOChannel *_readchannel = NULL;
GIOChannel *_writechannel = NULL;
int _shm_ID = -1;
guchar *_shm_addr = NULL;
const guint gimp_major_version = GIMP_MAJOR_VERSION;
const guint gimp_minor_version = GIMP_MINOR_VERSION;
const guint gimp_micro_version = GIMP_MICRO_VERSION;
guint gimp_major_version = GIMP_MAJOR_VERSION;
guint gimp_minor_version = GIMP_MINOR_VERSION;
guint gimp_micro_version = GIMP_MICRO_VERSION;
#ifdef WIN32
static HANDLE shm_handle;
#endif
static gdouble _gamma_val;
static gint _install_cmap;
@ -86,13 +107,27 @@ static guint write_buffer_index = 0;
static GHashTable *temp_proc_ht = NULL;
#ifdef NATIVE_WIN32
static GPlugInInfo *PLUG_IN_INFO_PTR;
#define PLUG_IN_INFO (*PLUG_IN_INFO_PTR)
#else
extern GPlugInInfo PLUG_IN_INFO;
#endif
int
gimp_main (int argc,
char *argv[])
{
#ifdef NATIVE_WIN32
HMODULE handle;
char *peer, *peer_fd;
guint32 thread;
handle = GetModuleHandle (NULL);
PLUG_IN_INFO_PTR = (GPlugInInfo *) GetProcAddress (handle, "PLUG_IN_INFO");
#endif
if ((argc < 4) || (strcmp (argv[1], "-gimp") != 0))
{
g_print ("%s is a gimp plug-in and must be run by the gimp to be used\n", argv[0]);
@ -101,17 +136,37 @@ gimp_main (int argc,
progname = argv[0];
#ifdef SIGHUP
signal (SIGHUP, gimp_signal);
#endif
signal (SIGINT, gimp_signal);
#ifdef SIGQUIT
signal (SIGQUIT, gimp_signal);
#endif
#ifdef SIGBUS
signal (SIGBUS, gimp_signal);
#endif
#ifdef SIGSEGV
signal (SIGSEGV, gimp_signal);
#endif
#ifdef SIGPIPE
signal (SIGPIPE, gimp_signal);
#endif
signal (SIGTERM, gimp_signal);
#ifdef SIGFPE
signal (SIGFPE, gimp_signal);
#endif
_readfd = atoi (argv[2]);
_writefd = atoi (argv[3]);
#ifndef NATIVE_WIN32
_readchannel = g_io_channel_unix_new (atoi (argv[2]));
_writechannel = g_io_channel_unix_new (atoi (argv[3]));
#else
_readchannel = g_io_channel_win32_new_pipe (atoi (argv[2]));
peer = strchr (argv[3], ':') + 1;
peer_fd = strchr (peer, ':') + 1;
_writechannel = g_io_channel_win32_new_pipe_with_wakeups
(atoi (argv[3]), atoi (peer), atoi (peer_fd));
#endif
gp_init ();
wire_set_writer (gimp_write);
@ -125,6 +180,13 @@ gimp_main (int argc,
return 0;
}
#ifdef NATIVE_WIN32
/* Tell the GIMP our thread id */
thread = GetCurrentThreadId ();
wire_write_int32 (_writechannel, &thread, 1);
wire_flush (_writechannel);
#endif
g_set_message_handler ((GPrintFunc) gimp_message_func);
temp_proc_ht = g_hash_table_new (&g_str_hash, &g_str_equal);
@ -139,12 +201,16 @@ gimp_quit ()
if (PLUG_IN_INFO.quit_proc)
(* PLUG_IN_INFO.quit_proc) ();
#ifdef WIN32
CloseHandle (shm_handle);
#else
#ifdef HAVE_SHM_H
if ((_shm_ID != -1) && _shm_addr)
shmdt ((char*) _shm_addr);
#endif
#endif
gp_quit_write (_writefd);
gp_quit_write (_writechannel);
exit (0);
}
@ -461,7 +527,7 @@ gimp_install_procedure (char *name,
proc_install.params = (GPParamDef*) params;
proc_install.return_vals = (GPParamDef*) return_vals;
if (!gp_proc_install_write (_writefd, &proc_install))
if (!gp_proc_install_write (_writechannel, &proc_install))
gimp_quit ();
}
@ -496,7 +562,7 @@ gimp_uninstall_temp_proc (char *name)
gpointer hash_name;
proc_uninstall.name = name;
if (!gp_proc_uninstall_write (_writefd, &proc_uninstall))
if (!gp_proc_uninstall_write (_writechannel, &proc_uninstall))
gimp_quit ();
g_hash_table_lookup_extended (temp_proc_ht, name, &hash_name, NULL);
@ -740,7 +806,7 @@ gimp_run_procedure (char *name,
va_end (args);
if (!gp_proc_run_write (_writefd, &proc_run))
if (!gp_proc_run_write (_writechannel, &proc_run))
gimp_quit ();
gimp_read_expect_msg(&msg,GP_PROC_RETURN);
@ -773,7 +839,7 @@ gimp_read_expect_msg(WireMessage *msg, int type)
{
while(1)
{
if (!wire_read_msg (_readfd, msg))
if (!wire_read_msg (_readchannel, msg))
gimp_quit ();
if (msg->type != type)
@ -807,7 +873,7 @@ gimp_run_procedure2 (char *name,
proc_run.nparams = nparams;
proc_run.params = (GPParam *) params;
if (!gp_proc_run_write (_writefd, &proc_run))
if (!gp_proc_run_write (_writechannel, &proc_run))
gimp_quit ();
gimp_read_expect_msg(&msg,GP_PROC_RETURN);
@ -880,21 +946,6 @@ gimp_color_cube ()
return _color_cube;
}
gchar*
gimp_gtkrc ()
{
static char filename[MAXPATHLEN];
char *home_dir;
home_dir = g_get_home_dir ();
if (!home_dir)
return NULL;
g_snprintf (filename, MAXPATHLEN, "%s/%s/gtkrc", home_dir, GIMPDIR);
return filename;
}
static void
gimp_process_message(WireMessage *msg)
{
@ -935,7 +986,7 @@ gimp_single_message()
WireMessage msg;
/* Run a temp function */
if (!wire_read_msg (_readfd, &msg))
if (!wire_read_msg (_readchannel, &msg))
gimp_quit ();
gimp_process_message(&msg);
@ -946,6 +997,7 @@ gimp_single_message()
void
gimp_extension_process (guint timeout)
{
#ifndef NATIVE_WIN32
fd_set readfds;
int select_val;
struct timeval tv;
@ -954,14 +1006,14 @@ gimp_extension_process (guint timeout)
if (timeout)
{
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout % 1000;
tv.tv_usec = (timeout % 1000) * 1000;
tvp = &tv;
}
else
tvp = NULL;
FD_ZERO (&readfds);
FD_SET (_readfd, &readfds);
FD_SET (g_io_channel_unix_get_fd (_readchannel), &readfds);
if ((select_val = select (FD_SETSIZE, &readfds, NULL, NULL, tvp)) > 0)
{
@ -972,13 +1024,31 @@ gimp_extension_process (guint timeout)
perror ("gimp_process");
gimp_quit ();
}
#else
/* ??? */
MSG msg;
UINT timer;
static UINT message = 0;
if (message == 0)
message = RegisterWindowMessage ("g-pipe-readable");
if (timeout > 0)
timer = SetTimer (NULL, 0, timeout, NULL);
WaitMessage ();
if (timeout > 0)
KillTimer (NULL, timer);
if (PeekMessage (&msg, (HWND) -1, message, message, PM_NOREMOVE))
gimp_single_message ();
#endif
}
void
gimp_extension_ack ()
{
/* Send an extension initialization acknowledgement */
if (! gp_extension_ack_write (_writefd))
if (! gp_extension_ack_write (_writechannel))
gimp_quit ();
}
@ -988,6 +1058,12 @@ gimp_run_temp()
gimp_single_message();
}
void
gimp_request_wakeups (void)
{
if (!gp_request_wakeups_write (_writechannel))
gimp_quit ();
}
static RETSIGTYPE
gimp_signal (int signum)
@ -995,17 +1071,32 @@ gimp_signal (int signum)
static int caught_fatal_sig = 0;
if (caught_fatal_sig)
#ifdef NATIVE_WIN32
raise (signum);
#else
kill (getpid (), signum);
#endif
caught_fatal_sig = 1;
fprintf (stderr, "\n%s: %s caught\n", progname, g_strsignal (signum));
switch (signum)
{
#ifdef SIGBUS
case SIGBUS:
#endif
#ifdef SIGSEGV
case SIGSEGV:
#endif
#ifdef SIGFPE
case SIGFPE:
#endif
case 123456: /* Must have some case value... */
#ifndef NATIVE_WIN32
g_on_error_query (progname);
#else
abort ();
#endif
break;
default:
break;
@ -1015,7 +1106,7 @@ gimp_signal (int signum)
}
static int
gimp_write (int fd, guint8 *buf, gulong count)
gimp_write (GIOChannel *channel, guint8 *buf, gulong count)
{
gulong bytes;
@ -1026,7 +1117,7 @@ gimp_write (int fd, guint8 *buf, gulong count)
bytes = WRITE_BUFFER_SIZE - write_buffer_index;
memcpy (&write_buffer[write_buffer_index], buf, bytes);
write_buffer_index += bytes;
if (!wire_flush (fd))
if (!wire_flush (channel))
return FALSE;
}
else
@ -1044,8 +1135,9 @@ gimp_write (int fd, guint8 *buf, gulong count)
}
static int
gimp_flush (int fd)
gimp_flush (GIOChannel *channel)
{
GIOError error;
int count;
int bytes;
@ -1055,10 +1147,13 @@ gimp_flush (int fd)
while (count != write_buffer_index)
{
do {
bytes = write (fd, &write_buffer[count], (write_buffer_index - count));
} while ((bytes == -1) && (errno == EAGAIN));
bytes = 0;
error = g_io_channel_write (channel, &write_buffer[count],
(write_buffer_index - count),
&bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
return FALSE;
count += bytes;
@ -1077,7 +1172,7 @@ gimp_loop ()
while (1)
{
if (!wire_read_msg (_readfd, &msg))
if (!wire_read_msg (_readchannel, &msg))
gimp_quit ();
switch (msg.type)
@ -1146,15 +1241,50 @@ gimp_config (GPConfig *config)
_color_cube[3] = config->color_cube[3];
_gdisp_ID = config->gdisp_ID;
#ifdef HAVE_SHM_H
if (_shm_ID != -1)
{
#ifdef WIN32
/*
* Use Win32 shared memory mechanisms for
* transfering tile data
*/
char fileMapName[128];
int tileByteSize = _gimp_tile_width * _gimp_tile_height * 4;
/* From the id, derive the file map name */
sprintf(fileMapName, "GIMP%d.SHM", _shm_ID);
/* Open the file mapping */
shm_handle = OpenFileMapping (FILE_MAP_ALL_ACCESS,
0, 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)
{
g_warning ("MapViewOfFile error: %d... disabling shared memory transport",
GetLastError());
}
}
else
{
g_warning ("OpenFileMapping error: %d... disabling shared memory transport",
GetLastError());
}
#else
#ifdef HAVE_SHM_H
_shm_addr = (guchar*) shmat (_shm_ID, 0, 0);
if (_shm_addr == (guchar*) -1)
g_error ("could not attach to gimp shared memory segment\n");
}
#endif
#endif
}
}
static void
@ -1176,7 +1306,7 @@ gimp_proc_run (GPProcRun *proc_run)
proc_return.nparams = nreturn_vals;
proc_return.params = (GPParam*) return_vals;
if (!gp_proc_return_write (_writefd, &proc_return))
if (!gp_proc_return_write (_writechannel, &proc_return))
gimp_quit ();
}
}
@ -1203,7 +1333,7 @@ gimp_temp_proc_run (GPProcRun *proc_run)
/* proc_return.nparams = nreturn_vals; */
/* proc_return.params = (GPParam*) return_vals; */
/* if (!gp_temp_proc_return_write (_writefd, &proc_return)) */
/* if (!gp_temp_proc_return_write (_writechannel, &proc_return)) */
/* gimp_quit (); */
}
}

257
libgimp/gimp.def Normal file
View File

@ -0,0 +1,257 @@
EXPORTS
g_free_serial_description
g_deserialize
g_new_serial_description
g_new_serial_item
g_serialize
gimp_channel_copy
gimp_channel_delete
gimp_channel_get_color
gimp_channel_get_image_id
gimp_channel_get_layer_id
gimp_channel_get_name
gimp_channel_get_opacity
gimp_channel_get_show_masked
gimp_channel_get_tattoo
gimp_channel_get_visible
gimp_channel_height
gimp_channel_new
gimp_channel_set_color
gimp_channel_set_name
gimp_channel_set_opacity
gimp_channel_set_show_masked
gimp_channel_set_visible
gimp_channel_width
gimp_color_cube
gimp_data_directory
gimp_destroy_params
gimp_destroy_paramdefs
gimp_directory
gimp_display_delete
gimp_display_new
gimp_displays_flush
gimp_drawable_bpp
gimp_drawable_channel
gimp_drawable_color
gimp_drawable_delete
gimp_drawable_detach
gimp_drawable_fill
gimp_drawable_flush
gimp_drawable_get
gimp_drawable_get_tile
gimp_drawable_get_tile2
gimp_drawable_gray
gimp_drawable_has_alpha
gimp_drawable_height
gimp_drawable_image_id
gimp_drawable_indexed
gimp_drawable_layer
gimp_drawable_layer_mask
gimp_drawable_mask_bounds
gimp_drawable_merge_shadow
gimp_drawable_name
gimp_drawable_offsets
gimp_drawable_set_name
gimp_drawable_set_visible
gimp_drawable_type
gimp_drawable_update
gimp_drawable_visible
gimp_drawable_width
gimp_extension_ack
gimp_extension_process
gimp_gamma
gimp_get_data
gimp_get_data_size
gimp_gradients_get_active
gimp_gradients_get_list
gimp_gradients_sample_custom
gimp_gradients_sample_uniform
gimp_gradients_set_active
gimp_gtkrc
gimp_image_add_channel
gimp_image_add_hguide
gimp_image_add_layer
gimp_image_add_layer_mask
gimp_image_add_vguide
gimp_image_attach_parasite
gimp_image_base_type
gimp_image_clean_all
gimp_image_delete
gimp_image_delete_guide
gimp_image_detach_parasite
gimp_image_disable_undo
gimp_image_enable_undo
gimp_image_find_parasite
gimp_image_findnext_guide
gimp_image_flatten
gimp_image_floating_selection
gimp_image_get_active_channel
gimp_image_get_active_layer
gimp_image_get_channels
gimp_image_get_cmap
gimp_image_get_component_active
gimp_image_get_component_visible
gimp_image_get_filename
gimp_image_get_guide_orientation
gimp_image_get_guide_position
gimp_image_get_layers
gimp_image_get_selection
gimp_image_get_resolution
gimp_image_height
gimp_image_lower_channel
gimp_image_lower_layer
gimp_image_merge_visible_layers
gimp_image_new
gimp_image_pick_correlate_layer
gimp_image_raise_channel
gimp_image_raise_layer
gimp_image_remove_channel
gimp_image_remove_layer
gimp_image_remove_layer_mask
gimp_image_resize
gimp_image_set_active_channel
gimp_image_set_active_layer
gimp_image_set_cmap
gimp_image_set_component_active
gimp_image_set_component_visible
gimp_image_set_filename
gimp_image_set_resolution
gimp_image_width
gimp_install_cmap
gimp_install_procedure
gimp_install_temp_proc
gimp_layer_add_alpha
gimp_layer_bpp
gimp_layer_copy
gimp_layer_create_mask
gimp_layer_delete
gimp_layer_get_apply_mask
gimp_layer_get_edit_mask
gimp_layer_get_image_id
gimp_layer_get_mask_id
gimp_layer_get_mode
gimp_layer_get_name
gimp_layer_get_opacity
gimp_layer_get_preserve_transparency
gimp_layer_get_show_mask
gimp_layer_get_tattoo
gimp_layer_get_visible
gimp_layer_height
gimp_layer_is_floating_selection
gimp_layer_new
gimp_layer_resize
gimp_layer_scale
gimp_layer_set_apply_mask
gimp_layer_set_edit_mask
gimp_layer_set_mode
gimp_layer_set_name
gimp_layer_set_offsets
gimp_layer_set_opacity
gimp_layer_set_preserve_transparency
gimp_layer_set_show_mask
gimp_layer_set_visible
gimp_layer_translate
gimp_layer_type
gimp_layer_width
gimp_main
gimp_major_version
gimp_matrix_duplicate
gimp_matrix_transform_point
gimp_matrix_mult
gimp_matrix_identity
gimp_matrix_translate
gimp_matrix_scale
gimp_matrix_rotate
gimp_matrix_xshear
gimp_matrix_yshear
gimp_matrix_determinant
gimp_matrix_invert
gimp_message
gimp_micro_version
gimp_minor_version
gimp_palette_get_background
gimp_palette_get_foreground
gimp_palette_set_background
gimp_palette_set_foreground
gimp_personal_rc_file
gimp_pixel_rgn_get_col
gimp_pixel_rgn_get_pixel
gimp_pixel_rgn_get_rect
gimp_pixel_rgn_get_row
gimp_pixel_rgn_init
gimp_pixel_rgn_resize
gimp_pixel_rgn_set_col
gimp_pixel_rgn_set_pixel
gimp_pixel_rgn_set_rect
gimp_pixel_rgn_set_row
gimp_pixel_rgns_process
gimp_pixel_rgns_register
gimp_progress_init
gimp_progress_update
gimp_query_database
gimp_query_images
gimp_query_procedure
gimp_quit
gimp_register_load_handler
gimp_register_magic_load_handler
gimp_register_save_handler
gimp_request_wakeups
gimp_run_procedure
gimp_run_procedure2
gimp_run_temp
gimp_set_data
gimp_tile_cache_ntiles
gimp_tile_cache_size
gimp_tile_flush
gimp_tile_height
gimp_tile_ref
gimp_tile_ref_zero
gimp_tile_unref
gimp_tile_width
gimp_uninstall_temp_proc
gimp_use_xshm
gp_config_write
gp_extension_ack_write
gp_init
gp_proc_install_write
gp_proc_return_write
gp_proc_run_write
gp_proc_uninstall_write
gp_quit_write
gp_temp_proc_return_write
gp_temp_proc_run_write
gp_tile_ack_write
gp_tile_data_write
gp_tile_req_write
parasite_compare
parasite_copy
parasite_data
parasite_data_size
parasite_free
parasite_has_flag
parasite_is_persistent
parasite_is_type
parasite_name
parasite_new
wire_clear_error
wire_destroy
wire_error
wire_flush
wire_read
wire_read_double
wire_read_int16
wire_read_int32
wire_read_int8
wire_read_msg
wire_read_string
wire_register
wire_set_flusher
wire_set_reader
wire_set_writer
wire_write
wire_write_double
wire_write_int16
wire_write_int32
wire_write_int8
wire_write_msg
wire_write_string

View File

@ -23,19 +23,29 @@
#include <glib.h>
#include "libgimp/gimpenums.h"
#include "libgimp/gimpfeatures.h"
#include "libgimp/gimpenv.h"
#include "libgimp/parasite.h"
#include "libgimp/parasiteP.h"
#ifdef NATIVE_WIN32
# ifdef LIBGIMP_COMPILATION
# define GIMPVAR __declspec(dllexport)
# else /* !LIBGIMP_COMPILATION */
# define GIMPVAR extern __declspec(dllimport)
# endif /* !LIBGIMP_COMPILATION */
#else /* !NATIVE_WIN32 */
# define GIMPVAR extern
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern const guint gimp_major_version;
extern const guint gimp_minor_version;
extern const guint gimp_micro_version;
GIMPVAR guint gimp_major_version;
GIMPVAR guint gimp_minor_version;
GIMPVAR guint gimp_micro_version;
GIMPVAR GIOChannel *_readchannel;
typedef struct _GPlugInInfo GPlugInInfo;
typedef struct _GTile GTile;
@ -73,6 +83,14 @@ struct _GPlugInInfo
GRunProc run_proc;
};
#if defined (NATIVE_WIN32) && !defined (LIBGIMP_COMPILATION)
/* Define PLUG_IN_INFO as an exported symbol (when compiling a plug-in).
* In gimp.c, we don't declare it at all, but fetch the address
* of it with GetProcAddress.
*/
__declspec(dllexport) GPlugInInfo PLUG_IN_INFO;
#endif
struct _GTile
{
guint ewidth; /* the effective width of the tile */
@ -166,7 +184,34 @@ struct _GParam
};
#define MAIN() int main (int argc, char *argv[]) { return gimp_main (argc, argv); }
#ifdef NATIVE_WIN32
/* Define WinMain() as plug-ins are built as GUI applications. Also
* define a main() in case some plug-in still is built as a console
* application.
*/
# define MAIN() \
int _stdcall \
WinMain (int hInstance, \
int hPrevInstance, \
char *lpszCmdLine, \
int nCmdShow) \
{ \
return gimp_main (__argc, __argv); \
} \
\
int \
main (int argc, char *argv[]) \
{ \
return gimp_main (argc, argv); \
}
#else
# define MAIN() \
int \
main (int argc, char *argv[]) \
{ \
return gimp_main (argc, argv); \
}
#endif
/* The main procedure that should be called with the
@ -348,7 +393,7 @@ gdouble gimp_gamma (void);
gint gimp_install_cmap (void);
gint gimp_use_xshm (void);
guchar* gimp_color_cube (void);
gchar* gimp_gtkrc (void);
void gimp_request_wakeups (void);
/****************************************

170
libgimp/gimpenv.c Normal file
View File

@ -0,0 +1,170 @@
/* LIBGIMP - The GIMP Library
*
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
* Copyright (C) 1999 Tor Lillqvist
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include "gimpenv.h"
#include "gimpintl.h"
#ifdef NATIVE_WIN32
#define STRICT
#include <windows.h> /* For GetModuleFileName */
#endif
char *
gimp_directory ()
{
static char *gimp_dir = NULL;
char *env_gimp_dir;
char *home_dir;
if (gimp_dir != NULL)
return gimp_dir;
env_gimp_dir = g_getenv ("GIMP_DIRECTORY");
home_dir = g_get_home_dir ();
if (NULL != env_gimp_dir)
{
if (g_path_is_absolute (env_gimp_dir))
gimp_dir = g_strdup(env_gimp_dir);
else
{
if (NULL != home_dir)
{
gimp_dir = g_strconcat (home_dir,
G_DIR_SEPARATOR_S,
env_gimp_dir,
NULL);
}
else
{
gimp_dir = g_strconcat (gimp_data_directory (),
G_DIR_SEPARATOR_S,
env_gimp_dir,
NULL);
}
}
}
else
{
if (NULL != home_dir)
{
gimp_dir = g_strconcat (home_dir, G_DIR_SEPARATOR_S,
GIMPDIR, NULL);
}
else
{
g_message (_("warning: no home directory."));
gimp_dir = g_strconcat (gimp_data_directory (),
G_DIR_SEPARATOR_S,
GIMPDIR,
".",
g_get_user_name (),
NULL);
}
}
return gimp_dir;
}
char *
gimp_personal_rc_file (char *basename)
{
return g_strconcat (gimp_directory (),
G_DIR_SEPARATOR_S,
basename,
NULL);
}
char *
gimp_data_directory ()
{
static char *gimp_data_dir = NULL;
char *env_gimp_data_dir = NULL;
if (gimp_data_dir != NULL)
return gimp_data_dir;
env_gimp_data_dir = g_getenv ("GIMP_DATADIR");
if (NULL != env_gimp_data_dir)
{
if (!g_path_is_absolute (env_gimp_data_dir))
g_error ("GIMP_DATADIR environment variable should be an absolute path.");
gimp_data_dir = g_strdup (env_gimp_data_dir);
}
else
{
#ifndef NATIVE_WIN32
gimp_data_dir = DATADIR;
#else
/* Figure it out from the executable name */
char filename[MAX_PATH];
char *sep1, *sep2;
if (GetModuleFileName (NULL, filename, sizeof (filename)) == 0)
g_error ("GetModuleFilename failed\n");
/* If the executable file name is of the format <foobar>\bin\gimp.exe,
* use <foobar>. Otherwise, use the directory where the executable
* is.
*/
sep1 = strrchr (filename, G_DIR_SEPARATOR);
*sep1 = '\0';
sep2 = strrchr (filename, G_DIR_SEPARATOR);
if (sep2 != NULL)
{
if (g_strcasecmp (sep2 + 1, "bin") == 0)
*sep2 = '\0';
}
gimp_data_dir = g_strdup (filename);
#endif
}
return gimp_data_dir;
}
/* gimp_gtkrc returns the name of the GIMP's application-specific
* gtkrc file.
*
* The returned string is allocated just once, and should *NOT* be
* freed with g_free().
*/
char*
gimp_gtkrc ()
{
static char *gimp_gtkrc_filename = NULL;
if (gimp_gtkrc_filename != NULL)
return gimp_gtkrc_filename;
gimp_gtkrc_filename = g_strconcat (gimp_directory (),
G_DIR_SEPARATOR_S,
"gtkrc",
NULL);
return gimp_gtkrc_filename;
}

82
libgimp/gimpenv.h Normal file
View File

@ -0,0 +1,82 @@
/* gimpenv.h
*
* Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMPENV_H__
#define __GIMPENV_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* gimp_directory() returns the user-specific GIMP settings
* directory. If the environment variable GIMP_DIRECTORY exists, that
* is used. If it is an absolute path, it is used as is. If it is a
* relative path, it is taken to be a subdirectory of the home
* directory. If it is relative, and no home directory can be
* determined, it is taken to be a subdirectory of
* gimp_data_directory().
*
* The usual case is that no GIMP_DIRECTORY envvar exists, and then we
* use the GIMPDIR subdirectory of the home directory. If no home
* directory exists, we use a per-user subdirectory of
* gimp_data_directory().
*
* In any case, we always return some non-empty string, whether it
* corresponds to an existing directory or not.
*
* The returned string is allocated just once, and should *NOT* be
* freed with g_free().
*/
char *gimp_directory (void);
/* gimp_personal_rc_file() returns the name of a file in the
* user-specific GIMP settings directory.
*
* The returned string is allocated dynamically and *SHOULD* be freed
* with g_free() after use.
*/
char *gimp_personal_rc_file (char *basename);
/* gimp_data_directory returns the top directory for GIMP data. If
* the environment variable GIMP_DATADIR exists, that is used. It
* should be an absolute pathname.
*
* Otherwise, on Unix the compile-time defined directory is used. On
* Win32, the installation directory as deduced from the executable's
* name is used.
*
* The returned string is allocated just once, and should *NOT* be
* freed with g_free().
*/
char *gimp_data_directory (void);
/* gimp_gtkrc returns the name of the GIMP's application-specific
* gtkrc file.
*
* The returned string is allocated just once, and should *NOT* be
* freed with g_free().
*/
char *gimp_gtkrc (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMPENV_H__ */

View File

@ -0,0 +1,43 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_FEATURES_H__
#define __GIMP_FEATURES_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GIMP_MAJOR_VERSION (1)
#define GIMP_MINOR_VERSION (1)
#define GIMP_MICRO_VERSION (2)
#define GIMP_VERSION "1.1.2"
#define GIMP_HAVE_PROCEDURAL_DB_GET_DATA_SIZE 1-1-0
#define GIMP_HAVE_PARASITES 1-1-0
#define GIMP_HAVE_RESOLUTION_INFO 1-1-0
#define GIMP_HAVE_DESTROY_PARAMDEFS 1-1-0
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GIMP_FEATURES_H__ */

94
libgimp/gimpi.def Normal file
View File

@ -0,0 +1,94 @@
EXPORTS
g_free_serial_description
g_deserialize
g_new_serial_description
g_new_serial_item
g_serialize
gimp_chain_button_get_active
gimp_chain_button_get_type
gimp_chain_button_new
gimp_chain_button_set_active
gimp_data_directory
gimp_directory
gimp_gtkrc
gimp_personal_rc_file
gimp_matrix_duplicate
gimp_matrix_transform_point
gimp_matrix_mult
gimp_matrix_identity
gimp_matrix_translate
gimp_matrix_scale
gimp_matrix_rotate
gimp_matrix_xshear
gimp_matrix_yshear
gimp_matrix_determinant
gimp_matrix_invert
gimp_size_entry_attach_label
gimp_size_entry_get_refval
gimp_size_entry_get_type
gimp_size_entry_get_unit
gimp_size_entry_get_value
gimp_size_entry_new
gimp_size_entry_set_resolution
gimp_size_entry_set_refval
gimp_size_entry_set_refval_boundaries
gimp_size_entry_set_unit
gimp_size_entry_set_value
gimp_unit_get_abbreviation
gimp_unit_get_deletion_flag
gimp_unit_get_digits
gimp_unit_get_factor
gimp_unit_get_identifier
gimp_unit_get_number_of_units
gimp_unit_get_number_of_built_in_units
gimp_unit_get_plural
gimp_unit_get_singular
gimp_unit_get_symbol
gimp_unit_new
gimp_unit_set_deletion_flag
gp_config_write
gp_extension_ack_write
gp_init
gp_proc_install_write
gp_proc_return_write
gp_proc_run_write
gp_proc_uninstall_write
gp_quit_write
gp_request_wakeups_write
gp_temp_proc_return_write
gp_temp_proc_run_write
gp_tile_ack_write
gp_tile_data_write
gp_tile_req_write
parasite_compare
parasite_copy
parasite_data
parasite_data_size
parasite_free
parasite_has_flag
parasite_is_persistent
parasite_is_type
parasite_name
parasite_new
wire_clear_error
wire_destroy
wire_error
wire_flush
wire_read
wire_read_double
wire_read_int16
wire_read_int32
wire_read_int8
wire_read_msg
wire_read_string
wire_register
wire_set_flusher
wire_set_reader
wire_set_writer
wire_write
wire_write_double
wire_write_int16
wire_write_int32
wire_write_int8
wire_write_msg
wire_write_string

View File

@ -19,6 +19,7 @@
#include "gimpmatrix.h"
#include <math.h>
#include <string.h>
void
gimp_matrix_transform_point (GimpMatrix m, double x, double y,

View File

@ -79,9 +79,9 @@ static void temp_brush_invoker (char *name,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void input_callback (gpointer data,
gint source,
GdkInputCondition condition);
static gboolean input_callback (GIOChannel *channel,
GIOCondition condition,
gpointer data);
static void gimp_setup_callbacks (void);
static gchar* gen_temp_plugin_name (void);
@ -686,26 +686,30 @@ temp_gradient_invoker(char *name,
values[0].data.d_status = status;
}
static void
input_callback (gpointer data,
gint source,
GdkInputCondition condition)
static gboolean
input_callback (GIOChannel *channel,
GIOCondition condition,
gpointer data)
{
/* We have some data in the wire - read it */
/* The below will only ever run a single proc */
gimp_run_temp();
return TRUE;
}
static void
gimp_setup_callbacks (void)
{
static int first_time = TRUE;
extern int _readfd;
if(first_time)
{
/* Tie into the gdk input function */
/* only once */
gdk_input_add(_readfd,GDK_INPUT_READ,input_callback,NULL);
g_io_add_watch (_readchannel, G_IO_IN | G_IO_PRI, input_callback, NULL);
/* This needed on Win32 */
gimp_request_wakeups();
first_time = FALSE;
}
}

View File

@ -46,7 +46,13 @@ typedef struct {
* of the following type: */
typedef GimpModuleStatus (GimpModuleInitFunc) (GimpModuleInfo **);
#ifndef MODULE_COMPILATION /* On Win32 this declaration clashes with
* the definition (which uses G_MODULE_EXPORT)
* and thus should be bypassed when compiling
* the module itself.
*/
GimpModuleInitFunc module_init;
#endif
/* This function is called by the GIMP at startup, and should return
* either GIMP_MODULE_OK if it sucessfully initialised or
@ -67,7 +73,10 @@ typedef void (GimpModuleUnloadFunc) (void *shutdown_data,
void (*completed_cb)(void *),
void *completed_data);
#ifndef MODULE_COMPILATION /* The same as for module_init */
GimpModuleUnloadFunc module_unload;
#endif
/* GIMP calls this unload request function to ask a module to
* prepare itself to be unloaded. It is called with the value of

View File

@ -17,13 +17,21 @@
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "parasiteP.h"
#include "parasite.h"
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <glib.h>
#ifdef _MSC_VER
#include <process.h> /* For _getpid() */
#endif
#ifdef DEBUG
static void parasite_print(Parasite *p)
{

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,8 @@ enum {
GP_TEMP_PROC_RETURN,
GP_PROC_INSTALL,
GP_PROC_UNINSTALL,
GP_EXTENSION_ACK
GP_EXTENSION_ACK,
GP_REQUEST_WAKEUPS
};
@ -177,27 +178,28 @@ struct _GPProcUninstall
void gp_init (void);
int gp_quit_write (int fd);
int gp_config_write (int fd,
int gp_quit_write (GIOChannel *channel);
int gp_config_write (GIOChannel *channel,
GPConfig *config);
int gp_tile_req_write (int fd,
int gp_tile_req_write (GIOChannel *channel,
GPTileReq *tile_req);
int gp_tile_ack_write (int fd);
int gp_tile_data_write (int fd,
int gp_tile_ack_write (GIOChannel *channel);
int gp_tile_data_write (GIOChannel *channel,
GPTileData *tile_data);
int gp_proc_run_write (int fd,
int gp_proc_run_write (GIOChannel *channel,
GPProcRun *proc_run);
int gp_proc_return_write (int fd,
int gp_proc_return_write (GIOChannel *channel,
GPProcReturn *proc_return);
int gp_temp_proc_run_write (int fd,
int gp_temp_proc_run_write (GIOChannel *channel,
GPProcRun *proc_run);
int gp_temp_proc_return_write (int fd,
int gp_temp_proc_return_write (GIOChannel *channel,
GPProcReturn *proc_return);
int gp_proc_install_write (int fd,
int gp_proc_install_write (GIOChannel *channel,
GPProcInstall *proc_install);
int gp_proc_uninstall_write (int fd,
int gp_proc_uninstall_write (GIOChannel *channel,
GPProcUninstall *proc_uninstall);
int gp_extension_ack_write (int fd);
int gp_extension_ack_write (GIOChannel *channel);
int gp_request_wakeups_write (GIOChannel *channel);
#endif /* __GIMP_PROTOCOL_H__ */

View File

@ -138,7 +138,7 @@ gimp_tile_height ()
static void
gimp_tile_get (GTile *tile)
{
extern int _writefd;
extern GIOChannel *_writechannel;
extern guchar* _shm_addr;
GPTileReq tile_req;
@ -148,7 +148,7 @@ gimp_tile_get (GTile *tile)
tile_req.drawable_ID = tile->drawable->id;
tile_req.tile_num = tile->tile_num;
tile_req.shadow = tile->shadow;
if (!gp_tile_req_write (_writefd, &tile_req))
if (!gp_tile_req_write (_writechannel, &tile_req))
gimp_quit ();
gimp_read_expect_msg(&msg,GP_TILE_DATA);
@ -176,7 +176,7 @@ gimp_tile_get (GTile *tile)
tile_data->data = NULL;
}
if (!gp_tile_ack_write (_writefd))
if (!gp_tile_ack_write (_writechannel))
gimp_quit ();
wire_destroy (&msg);
@ -185,7 +185,7 @@ gimp_tile_get (GTile *tile)
static void
gimp_tile_put (GTile *tile)
{
extern int _writefd;
extern GIOChannel *_writechannel;
extern guchar* _shm_addr;
GPTileReq tile_req;
@ -196,7 +196,7 @@ gimp_tile_put (GTile *tile)
tile_req.drawable_ID = -1;
tile_req.tile_num = 0;
tile_req.shadow = 0;
if (!gp_tile_req_write (_writefd, &tile_req))
if (!gp_tile_req_write (_writechannel, &tile_req))
gimp_quit ();
gimp_read_expect_msg(&msg,GP_TILE_DATA);
@ -217,7 +217,7 @@ gimp_tile_put (GTile *tile)
else
tile_data.data = tile->data;
if (!gp_tile_data_write (_writefd, &tile_data))
if (!gp_tile_data_write (_writechannel, &tile_data))
gimp_quit ();
gimp_read_expect_msg(&msg,GP_TILE_ACK);

19
libgimp/gimpui.def Normal file
View File

@ -0,0 +1,19 @@
EXPORTS
gimp_brush_select_widget
gimp_brush_select_widget_close_popup
gimp_brush_select_widget_set_popup
gimp_channel_menu_new
gimp_drawable_menu_new
gimp_gradient_select_widget
gimp_gradient_select_widget_close_popup
gimp_gradient_select_widget_set_popup
gimp_image_menu_new
gimp_layer_menu_new
gimp_interactive_selection_brush
gimp_interactive_selection_pattern
gimp_pattern_close_popup
gimp_pattern_get_pattern_data
gimp_pattern_select_widget
gimp_pattern_select_widget_close_popup
gimp_pattern_select_widget_set_popup
gimp_pattern_set_popup

View File

@ -1,28 +1,41 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _MSC_VER
#include <process.h>
#include <io.h>
#endif
#include "gimpwire.h"
@ -92,39 +105,41 @@ wire_set_flusher (WireFlushFunc flush_func)
}
int
wire_read (int fd,
guint8 *buf,
gulong count)
wire_read (GIOChannel *channel,
guint8 *buf,
gulong count)
{
if (wire_read_func)
{
if (!(* wire_read_func) (fd, buf, count))
if (!(* wire_read_func) (channel, buf, count))
{
g_print ("wire_read: error\n");
g_warning ("wire_read: error");
wire_error_val = TRUE;
return FALSE;
}
}
else
{
GIOError error;
int bytes;
while (count > 0)
{
do {
bytes = read (fd, (char*) buf, count);
} while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR)));
bytes = 0;
error = g_io_channel_read (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
{
g_print ("wire_read: error\n");
g_warning ("wire_read: error");
wire_error_val = TRUE;
return FALSE;
}
if (bytes == 0)
{
g_print ("wire_read: unexpected EOF (plug-in crashed?)\n");
g_warning ("wire_read: unexpected EOF (plug-in crashed?)");
wire_error_val = TRUE;
return FALSE;
}
@ -138,32 +153,34 @@ wire_read (int fd,
}
int
wire_write (int fd,
guint8 *buf,
gulong count)
wire_write (GIOChannel *channel,
guint8 *buf,
gulong count)
{
if (wire_write_func)
{
if (!(* wire_write_func) (fd, buf, count))
if (!(* wire_write_func) (channel, buf, count))
{
g_print ("wire_write: error\n");
g_warning ("wire_write: error");
wire_error_val = TRUE;
return FALSE;
}
}
else
{
GIOError error;
int bytes;
while (count > 0)
{
do {
bytes = write (fd, (char*) buf, count);
} while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR)));
bytes = 0;
error = g_io_channel_write (channel, (char*) buf, count, &bytes);
} while (error == G_IO_ERROR_AGAIN);
if (bytes == -1)
if (error != G_IO_ERROR_NONE)
{
g_print ("wire_write: error\n");
g_warning ("wire_write: error");
wire_error_val = TRUE;
return FALSE;
}
@ -177,10 +194,10 @@ wire_write (int fd,
}
int
wire_flush (int fd)
wire_flush (GIOChannel *channel)
{
if (wire_flush_func)
return (* wire_flush_func) (fd);
return (* wire_flush_func) (channel);
return FALSE;
}
@ -197,7 +214,7 @@ wire_clear_error ()
}
int
wire_read_msg (int fd,
wire_read_msg (GIOChannel *channel,
WireMessage *msg)
{
WireHandler *handler;
@ -205,20 +222,20 @@ wire_read_msg (int fd,
if (wire_error_val)
return !wire_error_val;
if (!wire_read_int32 (fd, &msg->type, 1))
if (!wire_read_int32 (channel, &msg->type, 1))
return FALSE;
handler = g_hash_table_lookup (wire_ht, &msg->type);
if (!handler)
g_error ("could not find handler for message: %d\n", msg->type);
g_error ("could not find handler for message: %d", msg->type);
(* handler->read_func) (fd, msg);
(* handler->read_func) (channel, msg);
return !wire_error_val;
}
int
wire_write_msg (int fd,
wire_write_msg (GIOChannel *channel,
WireMessage *msg)
{
WireHandler *handler;
@ -228,12 +245,12 @@ wire_write_msg (int fd,
handler = g_hash_table_lookup (wire_ht, &msg->type);
if (!handler)
g_error ("could not find handler for message: %d\n", msg->type);
g_error ("could not find handler for message: %d", msg->type);
if (!wire_write_int32 (fd, &msg->type, 1))
if (!wire_write_int32 (channel, &msg->type, 1))
return FALSE;
(* handler->write_func) (fd, msg);
(* handler->write_func) (channel, msg);
return !wire_error_val;
}
@ -251,13 +268,13 @@ wire_destroy (WireMessage *msg)
}
int
wire_read_int32 (int fd,
guint32 *data,
gint count)
wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count)
{
if (count > 0)
{
if (!wire_read_int8 (fd, (guint8*) data, count * 4))
if (!wire_read_int8 (channel, (guint8*) data, count * 4))
return FALSE;
while (count--)
@ -271,13 +288,13 @@ wire_read_int32 (int fd,
}
int
wire_read_int16 (int fd,
guint16 *data,
gint count)
wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count)
{
if (count > 0)
{
if (!wire_read_int8 (fd, (guint8*) data, count * 2))
if (!wire_read_int8 (channel, (guint8*) data, count * 2))
return FALSE;
while (count--)
@ -291,24 +308,24 @@ wire_read_int16 (int fd,
}
int
wire_read_int8 (int fd,
guint8 *data,
gint count)
wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count)
{
return wire_read (fd, data, count);
return wire_read (channel, data, count);
}
int
wire_read_double (int fd,
gdouble *data,
gint count)
wire_read_double (GIOChannel *channel,
gdouble *data,
gint count)
{
char *str;
int i;
for (i = 0; i < count; i++)
{
if (!wire_read_string (fd, &str, 1))
if (!wire_read_string (channel, &str, 1))
return FALSE;
sscanf (str, "%le", &data[i]);
g_free (str);
@ -318,22 +335,22 @@ wire_read_double (int fd,
}
int
wire_read_string (int fd,
gchar **data,
gint count)
wire_read_string (GIOChannel *channel,
gchar **data,
gint count)
{
guint32 tmp;
int i;
for (i = 0; i < count; i++)
{
if (!wire_read_int32 (fd, &tmp, 1))
if (!wire_read_int32 (channel, &tmp, 1))
return FALSE;
if (tmp > 0)
{
data[i] = g_new (gchar, tmp);
if (!wire_read_int8 (fd, (guint8*) data[i], tmp))
if (!wire_read_int8 (channel, (guint8*) data[i], tmp))
{
g_free (data[i]);
return FALSE;
@ -349,9 +366,9 @@ wire_read_string (int fd,
}
int
wire_write_int32 (int fd,
guint32 *data,
gint count)
wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count)
{
guint32 tmp;
int i;
@ -361,7 +378,7 @@ wire_write_int32 (int fd,
for (i = 0; i < count; i++)
{
tmp = g_htonl (data[i]);
if (!wire_write_int8 (fd, (guint8*) &tmp, 4))
if (!wire_write_int8 (channel, (guint8*) &tmp, 4))
return FALSE;
}
}
@ -370,9 +387,9 @@ wire_write_int32 (int fd,
}
int
wire_write_int16 (int fd,
guint16 *data,
gint count)
wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count)
{
guint16 tmp;
int i;
@ -382,7 +399,7 @@ wire_write_int16 (int fd,
for (i = 0; i < count; i++)
{
tmp = g_htons (data[i]);
if (!wire_write_int8 (fd, (guint8*) &tmp, 2))
if (!wire_write_int8 (channel, (guint8*) &tmp, 2))
return FALSE;
}
}
@ -391,17 +408,17 @@ wire_write_int16 (int fd,
}
int
wire_write_int8 (int fd,
guint8 *data,
gint count)
wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count)
{
return wire_write (fd, data, count);
return wire_write (channel, data, count);
}
int
wire_write_double (int fd,
gdouble *data,
gint count)
wire_write_double (GIOChannel *channel,
gdouble *data,
gint count)
{
gchar *t, buf[128];
int i;
@ -410,7 +427,7 @@ wire_write_double (int fd,
for (i = 0; i < count; i++)
{
sprintf (buf, "%0.50e", data[i]);
if (!wire_write_string (fd, &t, 1))
if (!wire_write_string (channel, &t, 1))
return FALSE;
}
@ -418,9 +435,9 @@ wire_write_double (int fd,
}
int
wire_write_string (int fd,
gchar **data,
gint count)
wire_write_string (GIOChannel *channel,
gchar **data,
gint count)
{
guint32 tmp;
int i;
@ -432,10 +449,10 @@ wire_write_string (int fd,
else
tmp = 0;
if (!wire_write_int32 (fd, &tmp, 1))
if (!wire_write_int32 (channel, &tmp, 1))
return FALSE;
if (tmp > 0)
if (!wire_write_int8 (fd, (guint8*) data[i], tmp))
if (!wire_write_int8 (channel, (guint8*) data[i], tmp))
return FALSE;
}

View File

@ -1,21 +1,22 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
*/
#ifndef __GIMP_WIRE_H__
#define __GIMP_WIRE_H__
@ -25,11 +26,11 @@
typedef struct _WireMessage WireMessage;
typedef void (* WireReadFunc) (int fd, WireMessage *msg);
typedef void (* WireWriteFunc) (int fd, WireMessage *msg);
typedef void (* WireReadFunc) (GIOChannel *channel, WireMessage *msg);
typedef void (* WireWriteFunc) (GIOChannel *channel, WireMessage *msg);
typedef void (* WireDestroyFunc) (WireMessage *msg);
typedef int (* WireIOFunc) (int fd, guint8 *buf, gulong count);
typedef int (* WireFlushFunc) (int fd);
typedef int (* WireIOFunc) (GIOChannel *channel, guint8 *buf, gulong count);
typedef int (* WireFlushFunc) (GIOChannel *channel);
struct _WireMessage
@ -46,48 +47,48 @@ void wire_register (guint32 type,
void wire_set_reader (WireIOFunc read_func);
void wire_set_writer (WireIOFunc write_func);
void wire_set_flusher (WireFlushFunc flush_func);
int wire_read (int fd,
int wire_read (GIOChannel *channel,
guint8 *buf,
gulong count);
int wire_write (int fd,
int wire_write (GIOChannel *channel,
guint8 *buf,
gulong count);
int wire_flush (int fd);
int wire_flush (GIOChannel *channel);
int wire_error (void);
void wire_clear_error (void);
int wire_read_msg (int fd,
int wire_read_msg (GIOChannel *channel,
WireMessage *msg);
int wire_write_msg (int fd,
int wire_write_msg (GIOChannel *channel,
WireMessage *msg);
void wire_destroy (WireMessage *msg);
int wire_read_int32 (int fd,
int wire_read_int32 (GIOChannel *channel,
guint32 *data,
gint count);
int wire_read_int16 (int fd,
int wire_read_int16 (GIOChannel *channel,
guint16 *data,
gint count);
int wire_read_int8 (int fd,
int wire_read_int8 (GIOChannel *channel,
guint8 *data,
gint count);
int wire_read_double (int fd,
int wire_read_double (GIOChannel *channel,
gdouble *data,
gint count);
int wire_read_string (int fd,
int wire_read_string (GIOChannel *channel,
gchar **data,
gint count);
int wire_write_int32 (int fd,
int wire_write_int32 (GIOChannel *channel,
guint32 *data,
gint count);
int wire_write_int16 (int fd,
int wire_write_int16 (GIOChannel *channel,
guint16 *data,
gint count);
int wire_write_int8 (int fd,
int wire_write_int8 (GIOChannel *channel,
guint8 *data,
gint count);
int wire_write_double (int fd,
int wire_write_double (GIOChannel *channel,
gdouble *data,
gint count);
int wire_write_string (int fd,
int wire_write_string (GIOChannel *channel,
gchar **data,
gint count);

Some files were not shown because too many files have changed in this diff Show More