Support for custom plug-in interpreters, independent of OS support.

2005-02-20  Manish Singh  <yosh@gimp.org>

        Support for custom plug-in interpreters, independent of OS support.

        * app/core/Makefile.am
        * app/core/core-types.h
        * app/core/gimpinterpreterdb.[ch]: implemented GimpInterpreterDB,
        which handles registering and resolving custom plug-in interpreters.

        * app/core/gimp.[ch]: keep a GimpInterpreterDB around.

        * app/config/gimpcoreconfig.[ch]
        * app/config/gimprc-blurbs.h
        * app/dialogs/preferences-dialog.c
        * app/dialogs/user-install-dialog.c
        * app/widgets/gimphelp-ids.h: interpreter-path config stuff.

        * app/plug-in/plug-in.c: use registered interpreters when running
        plug-ins.

        * themes/Default/images/preferences/Makefile.am
        * themes/Default/images/preferences/folders-interp.png: just copied
        folders-plug-ins.png here, need a better one.

        * data/interpreters/Makefile.am: creates system interpreter directory.

        * data/interpreters/default.interp: sample interpreter file info.

        * data/Makefile.am
        * configure.in: add data/interpreters directory.

        * plug-ins/pygimp/Makefile.am: install pygimp.interp, which configures
        the python interpreter to point to the python we were built with. Also
        register the .py extension.

        * etc/gimprc
        * docs/gimprc.5.in: regenerated
This commit is contained in:
Manish Singh 2005-02-21 02:56:29 +00:00 committed by Manish Singh
parent fd809bfe92
commit 9706fce0a3
26 changed files with 1875 additions and 32 deletions

View File

@ -1,3 +1,41 @@
2005-02-20 Manish Singh <yosh@gimp.org>
Support for custom plug-in interpreters, independent of OS support.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpinterpreterdb.[ch]: implemented GimpInterpreterDB,
which handles registering and resolving custom plug-in interpreters.
* app/core/gimp.[ch]: keep a GimpInterpreterDB around.
* app/config/gimpcoreconfig.[ch]
* app/config/gimprc-blurbs.h
* app/dialogs/preferences-dialog.c
* app/dialogs/user-install-dialog.c
* app/widgets/gimphelp-ids.h: interpreter-path config stuff.
* app/plug-in/plug-in.c: use registered interpreters when running
plug-ins.
* themes/Default/images/preferences/Makefile.am
* themes/Default/images/preferences/folders-interp.png: just copied
folders-plug-ins.png here, need a better one.
* data/interpreters/Makefile.am: creates system interpreter directory.
* data/interpreters/default.interp: sample interpreter file info.
* data/Makefile.am
* configure.in: add data/interpreters directory.
* plug-ins/pygimp/Makefile.am: install pygimp.interp, which configures
the python interpreter to point to the python we were built with. Also
register the .py extension.
* etc/gimprc
* docs/gimprc.5.in: regenerated
2005-02-20 Jay Cox <jaycox@gimp.org>
* plug-ins/common/psd.c: Fix layer mask support. Addresses bug

View File

@ -73,6 +73,7 @@ enum
PROP_INTERPOLATION_TYPE,
PROP_PLUG_IN_PATH,
PROP_MODULE_PATH,
PROP_INTERPRETER_PATH,
PROP_ENVIRON_PATH,
PROP_BRUSH_PATH,
PROP_BRUSH_PATH_WRITABLE,
@ -169,6 +170,11 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
GIMP_CONFIG_PATH_DIR_LIST,
gimp_config_build_plug_in_path ("modules"),
GIMP_CONFIG_PARAM_RESTART);
GIMP_CONFIG_INSTALL_PROP_PATH (object_class, PROP_INTERPRETER_PATH,
"interpreter-path", INTERPRETER_PATH_BLURB,
GIMP_CONFIG_PATH_DIR_LIST,
gimp_config_build_plug_in_path ("interpreters"),
GIMP_CONFIG_PARAM_RESTART);
GIMP_CONFIG_INSTALL_PROP_PATH (object_class, PROP_ENVIRON_PATH,
"environ-path", ENVIRON_PATH_BLURB,
GIMP_CONFIG_PATH_DIR_LIST,
@ -357,6 +363,7 @@ gimp_core_config_finalize (GObject *object)
g_free (core_config->plug_in_path);
g_free (core_config->module_path);
g_free (core_config->interpreter_path);
g_free (core_config->environ_path);
g_free (core_config->brush_path);
g_free (core_config->brush_path_writable);
@ -408,6 +415,10 @@ gimp_core_config_set_property (GObject *object,
g_free (core_config->module_path);
core_config->module_path = g_value_dup_string (value);
break;
case PROP_INTERPRETER_PATH:
g_free (core_config->interpreter_path);
core_config->interpreter_path = g_value_dup_string (value);
break;
case PROP_ENVIRON_PATH:
g_free (core_config->environ_path);
core_config->environ_path = g_value_dup_string (value);
@ -559,6 +570,9 @@ gimp_core_config_get_property (GObject *object,
case PROP_MODULE_PATH:
g_value_set_string (value, core_config->module_path);
break;
case PROP_INTERPRETER_PATH:
g_value_set_string (value, core_config->interpreter_path);
break;
case PROP_ENVIRON_PATH:
g_value_set_string (value, core_config->environ_path);
break;

View File

@ -43,6 +43,7 @@ struct _GimpCoreConfig
GimpInterpolationType interpolation_type;
gchar *plug_in_path;
gchar *module_path;
gchar *interpreter_path;
gchar *environ_path;
gchar *brush_path;
gchar *brush_path_writable;

View File

@ -173,6 +173,9 @@ N_("Install a private colormap; might be useful on 8-bit (256 colors) displays."
N_("Sets the level of interpolation used for scaling and other " \
"transformations.")
#define INTERPRETER_PATH_BLURB \
"Sets the interpreter search path."
#define LAST_OPENED_SIZE_BLURB \
N_("How many recently opened image filenames to keep on the File menu.")

View File

@ -158,6 +158,8 @@ libappcore_a_sources = \
gimpimagefile.h \
gimpimagemap.c \
gimpimagemap.h \
gimpinterpreterdb.c \
gimpinterpreterdb.h \
gimpitem.c \
gimpitem.h \
gimpitem-linked.c \

View File

@ -113,6 +113,7 @@ typedef struct _GimpEnvironTable GimpEnvironTable;
/* typedef struct _GimpGrid GimpGrid; in config-types.h */
typedef struct _GimpImagefile GimpImagefile;
typedef struct _GimpImageMap GimpImageMap;
typedef struct _GimpInterpreterDB GimpInterpreterDB;
typedef struct _GimpParasiteList GimpParasiteList;
typedef struct _GimpPdbProgress GimpPdbProgress;
typedef struct _GimpProjection GimpProjection;

View File

@ -59,6 +59,7 @@
#include "gimpgradient-load.h"
#include "gimpimage.h"
#include "gimpimagefile.h"
#include "gimpinterpreterdb.h"
#include "gimplist.h"
#include "gimpmarshal.h"
#include "gimppalette.h"
@ -230,6 +231,7 @@ gimp_init (Gimp *gimp)
gimp_modules_init (gimp);
gimp->interpreter_db = gimp_interpreter_db_new ();
gimp->environ_table = gimp_environ_table_new ();
gimp->plug_in_debug = NULL;
@ -432,6 +434,12 @@ gimp_finalize (GObject *object)
gimp->environ_table = NULL;
}
if (gimp->interpreter_db)
{
g_object_unref (gimp->interpreter_db);
gimp->interpreter_db = NULL;
}
if (gimp->module_db)
gimp_modules_exit (gimp);
@ -635,6 +643,12 @@ gimp_real_initialize (Gimp *gimp,
(* status_callback) (_("Procedural Database"), NULL, -1);
procedural_db_init_procs (gimp, status_callback);
(* status_callback) (_("Plug-In Interpreters"), "", -1);
path = gimp_config_path_expand (gimp->config->interpreter_path, TRUE, NULL);
gimp_interpreter_db_load (gimp->interpreter_db, path);
g_free (path);
(* status_callback) (_("Plug-In Environment"), "", -1);
path = gimp_config_path_expand (gimp->config->environ_path, TRUE, NULL);

View File

@ -81,6 +81,7 @@ struct _Gimp
PlugInProcDef *last_plug_in;
PlugInShm *plug_in_shm;
GimpInterpreterDB *interpreter_db;
GimpEnvironTable *environ_table;
GimpPlugInDebug *plug_in_debug;

View File

@ -0,0 +1,767 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpinterpreterdb.c
* (C) 2005 Manish Singh <yosh@gimp.org>
*
* 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.
*/
/*
* The binfmt_misc bits are derived from linux/fs/binfmt_misc.c
* Copyright (C) 1997 Richard Günther
*/
/*
* The sh-bang code is derived from linux/fs/binfmt_script.c
* Copyright (C) 1996 Martin von Löwis
* original #!-checking implemented by tytso.
*/
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <glib-object.h>
#include <glib/gstdio.h>
#ifdef G_OS_WIN32
#include <io.h>
#endif
#ifndef _O_BINARY
#define _O_BINARY 0
#endif
#include "libgimpbase/gimpbase.h"
#include "core-types.h"
#include "gimpinterpreterdb.h"
#include "gimp-intl.h"
#define BUFSIZE 4096
typedef struct _GimpInterpreterMagic GimpInterpreterMagic;
struct _GimpInterpreterMagic
{
gulong offset;
gchar *magic;
gchar *mask;
guint size;
gchar *program;
};
static void gimp_interpreter_db_class_init (GimpInterpreterDBClass *class);
static void gimp_interpreter_db_init (GimpInterpreterDB *db);
static void gimp_interpreter_db_finalize (GObject *object);
static void gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
gpointer user_data);
static void gimp_interpreter_db_add_program (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer);
static void gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer);
static gboolean gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
gchar **tokens);
static gboolean gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
gchar **tokens);
static void gimp_interpreter_db_clear_magics (GimpInterpreterDB *db);
static void gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db);
static GObjectClass *parent_class = NULL;
GType
gimp_interpreter_db_get_type (void)
{
static GType interpreter_db_type = 0;
if (! interpreter_db_type)
{
static const GTypeInfo interpreter_db_info =
{
sizeof (GimpInterpreterDBClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gimp_interpreter_db_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GimpInterpreterDB),
0, /* n_preallocs */
(GInstanceInitFunc) gimp_interpreter_db_init,
};
interpreter_db_type = g_type_register_static (G_TYPE_OBJECT,
"GimpInterpreterDB",
&interpreter_db_info, 0);
}
return interpreter_db_type;
}
static void
gimp_interpreter_db_class_init (GimpInterpreterDBClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
object_class->finalize = gimp_interpreter_db_finalize;
}
static void
gimp_interpreter_db_init (GimpInterpreterDB *db)
{
db->programs = NULL;
db->magics = NULL;
db->magic_names = NULL;
db->extensions = NULL;
db->extension_names = NULL;
}
static void
gimp_interpreter_db_finalize (GObject *object)
{
GimpInterpreterDB *db;
db = GIMP_INTERPRETER_DB (object);
gimp_interpreter_db_clear (db);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GimpInterpreterDB *
gimp_interpreter_db_new (void)
{
return g_object_new (GIMP_TYPE_INTERPRETER_DB, NULL);
}
void
gimp_interpreter_db_load (GimpInterpreterDB *db,
const gchar *interp_path)
{
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
gimp_interpreter_db_clear (db);
db->programs = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
db->magic_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
db->extension_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
gimp_datafiles_read_directories (interp_path,
G_FILE_TEST_EXISTS,
gimp_interpreter_db_load_interp_file,
db);
gimp_interpreter_db_resolve_programs (db);
}
void
gimp_interpreter_db_clear (GimpInterpreterDB *db)
{
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
if (db->magic_names)
{
g_hash_table_destroy (db->magic_names);
db->magic_names = NULL;
}
if (db->extension_names)
{
g_hash_table_destroy (db->extension_names);
db->extension_names = NULL;
}
if (db->programs)
{
g_hash_table_destroy (db->programs);
db->programs = NULL;
}
if (db->extensions)
{
g_hash_table_destroy (db->extensions);
db->extensions = NULL;
}
gimp_interpreter_db_clear_magics (db);
}
static void
gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
gpointer user_data)
{
GimpInterpreterDB *db;
FILE *interp_file;
gchar buffer[4096];
gsize len;
db = GIMP_INTERPRETER_DB (user_data);
interp_file = g_fopen (file_data->filename, "r");
if (! interp_file)
return;
while (fgets (buffer, sizeof (buffer), interp_file))
{
/* Skip comments */
if (buffer[0] == '#')
continue;
len = strlen (buffer) - 1;
/* Skip too long lines */
if (buffer[len] != '\n')
continue;
buffer[len] = '\0';
if (g_ascii_isalnum (buffer[0]) || (buffer[0] == '/'))
gimp_interpreter_db_add_program (db, file_data, buffer);
else if (! g_ascii_isspace (buffer[0]) && (buffer[0] != '\0'))
gimp_interpreter_db_add_binfmt_misc (db, file_data, buffer);
}
fclose (interp_file);
}
static void
gimp_interpreter_db_add_program (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer)
{
gchar *name, *program, *p;
p = strchr (buffer, '=');
if (! p)
return;
*p = '\0';
name = buffer;
program = p + 1;
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
{
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
gimp_filename_to_utf8 (file_data->filename),
gimp_filename_to_utf8 (program));
return;
}
if (! g_hash_table_lookup (db->programs, name))
g_hash_table_insert (db->programs, g_strdup (name), g_strdup (program));
}
static void
gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer)
{
gchar **tokens = NULL;
gchar *name, *type, *program;
gsize count;
gchar del[2];
count = strlen (buffer);
if ((count < 10) || (count > 255))
goto bail;
del[0] = *buffer;
del[1] = '\0';
memset (buffer + count, del[0], 8);
tokens = g_strsplit (buffer + 1, del, -1);
name = tokens[0];
type = tokens[1];
program = tokens[5];
if (name[0] == '\0' || program == '\0' || type[0] == '\0' || type[1] != '\0')
goto bail;
switch (type[0])
{
case 'E':
if (! gimp_interpreter_db_add_extension (db, tokens))
goto bail;
break;
case 'M':
if (! gimp_interpreter_db_add_magic (db, tokens))
goto bail;
break;
default:
goto bail;
}
goto out;
bail:
g_message (_("Bad binary format string in interpreter file %s"),
gimp_filename_to_utf8 (file_data->filename));
out:
g_strfreev (tokens);
}
static gboolean
gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
gchar **tokens)
{
gchar *name, *extension, *program;
name = tokens[0];
extension = tokens[3];
program = tokens[5];
if (! g_hash_table_lookup (db->extension_names, name))
{
if (extension[0] == '\0' || extension[0] == '/')
return FALSE;
program = g_strdup (program);
g_hash_table_insert (db->extensions, g_strdup (extension), program);
g_hash_table_insert (db->extension_names, g_strdup (name), program);
}
return TRUE;
}
static gboolean
scanarg (gchar *s)
{
gchar c;
while ((c = *s++) != '\0')
{
if (c == '\\' && *s == 'x')
{
s++;
if (! g_ascii_isxdigit (*s++))
return FALSE;
if (! g_ascii_isxdigit (*s++))
return FALSE;
}
}
return TRUE;
}
static guint
unquote (gchar *from)
{
gchar c, *s = from, *p = from;
while ((c = *s++) != '\0')
{
if (c == '\\' && *s == 'x')
{
s++;
*p = g_ascii_xdigit_value (*s++) << 4;
*p++ |= g_ascii_xdigit_value (*s++);
continue;
}
*p++ = c;
}
return p - from;
}
static gboolean
gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
gchar **tokens)
{
GimpInterpreterMagic *interp_magic;
gchar *name, *num, *magic, *mask, *program;
gulong offset;
guint size;
name = tokens[0];
num = tokens[2];
magic = tokens[3];
mask = tokens[4];
program = tokens[5];
if (! g_hash_table_lookup (db->magic_names, name))
{
if (num[0] != '\0')
{
offset = strtoul (num, &num, 10);
if (num[0] != '\0')
return FALSE;
if (offset > (BUFSIZE / 4))
return FALSE;
}
else
offset = 0;
if (! scanarg (magic))
return FALSE;
if (! scanarg (mask))
return FALSE;
size = unquote (magic);
if ((size + offset) > (BUFSIZE / 2))
return FALSE;
if (mask[0] == '\0')
mask = NULL;
else if (unquote (mask) != size)
return FALSE;
interp_magic = g_new (GimpInterpreterMagic, 1);
interp_magic->offset = offset;
interp_magic->magic = g_memdup (magic, size);
interp_magic->mask = g_memdup (mask, size);
interp_magic->size = size;
interp_magic->program = g_strdup (program);
db->magics = g_slist_append (db->magics, interp_magic);
g_hash_table_insert (db->magic_names, g_strdup (name), interp_magic);
}
return TRUE;
}
static void
gimp_interpreter_db_clear_magics (GimpInterpreterDB *db)
{
GimpInterpreterMagic *magic;
GSList *list, *last;
list = db->magics;
db->magics = NULL;
while (list)
{
magic = list->data;
g_free (magic->magic);
g_free (magic->mask);
g_free (magic->program);
g_free (magic);
last = list;
list = list->next;
g_slist_free_1 (last);
}
}
#ifdef INTERP_DEBUG
static void
print_kv (gpointer key,
gpointer value,
gpointer user_data)
{
g_print ("%s: %s\n", (gchar *) key, (gchar *) value);
}
static gchar *
quote (gchar *s,
guint size)
{
GString *d;
guint i;
if (s == NULL)
return "(null)";
d = g_string_sized_new (size * 4);
for (i = 0; i < size; i++)
g_string_append_printf (d, "\\x%02x", ((guint) s[i]) & 0xff);
return g_string_free (d, FALSE);
}
#endif
static gboolean
resolve_program (gpointer key,
gpointer value,
gpointer user_data)
{
GimpInterpreterDB *db = user_data;
gchar *program;
program = g_hash_table_lookup (db->programs, value);
if (program != NULL)
{
g_free (value);
value = g_strdup (program);
}
g_hash_table_insert (db->extensions, key, value);
return TRUE;
}
static void
gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db)
{
GSList *list;
gchar *program;
GimpInterpreterMagic *magic;
GHashTable *extensions;
list = db->magics;
while (list)
{
magic = list->data;
program = g_hash_table_lookup (db->programs, magic->program);
if (program != NULL)
{
g_free (magic->program);
magic->program = g_strdup (program);
}
list = list->next;
}
extensions = db->extensions;
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
g_hash_table_foreach_steal (extensions, resolve_program, db);
g_hash_table_destroy (extensions);
#ifdef INTERP_DEBUG
g_print ("Programs:\n");
g_hash_table_foreach (db->programs, print_kv, NULL);
g_print ("\nExtensions:\n");
g_hash_table_foreach (db->extensions, print_kv, NULL);
g_print ("\nMagics:\n");
list = db->magics;
while (list)
{
GimpInterpreterMagic *magic;
magic = list->data;
g_print ("program: %s, offset: %lu, magic: %s, mask: %s\n",
magic->program, magic->offset,
quote (magic->magic, magic->size),
quote (magic->mask, magic->size));
list = list->next;
}
g_print ("\n");
#endif
}
static gchar *
resolve_extension (GimpInterpreterDB *db,
const gchar *program_path)
{
gchar *filename, *p, *program;
filename = g_path_get_basename (program_path);
p = strrchr (filename, '.');
if (! p)
return NULL;
program = g_hash_table_lookup (db->extensions, p + 1);
return g_strdup (program);
}
static gchar *
resolve_sh_bang (GimpInterpreterDB *db,
const gchar *program_path,
gchar *buffer,
gssize len,
gchar **interp_arg)
{
gchar *cp, *name, *program;
cp = strchr (buffer, '\n');
if (! cp)
cp = buffer + len - 1;
*cp = '\0';
while (cp > buffer)
{
cp--;
if ((*cp == ' ') || (*cp == '\t'))
*cp = '\0';
else
break;
}
for (cp = buffer + 2; (*cp == ' ') || (*cp == '\t'); cp++);
if (*cp == '\0')
return NULL;
name = cp;
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
/* nothing */ ;
while ((*cp == ' ') || (*cp == '\t'))
*cp++ = '\0';
if (*cp)
{
if (strcmp ("/usr/bin/env", name) == 0)
{
program = g_hash_table_lookup (db->programs, cp);
if (program)
return g_strdup (program);
}
*interp_arg = g_strdup (cp);
}
program = g_hash_table_lookup (db->programs, name);
if (! program)
program = name;
return g_strdup (program);
}
static gchar *
resolve_magic (GimpInterpreterDB *db,
const gchar *program_path,
gchar *buffer)
{
GSList *list;
GimpInterpreterMagic *magic;
gchar *s;
guint i;
list = db->magics;
while (list)
{
magic = list->data;
s = buffer + magic->offset;
if (magic->mask)
{
for (i = 0; i < magic->size; i++)
if ((*s++ ^ magic->magic[i]) & magic->mask[i])
break;
}
else
{
for (i = 0; i < magic->size; i++)
if ((*s++ ^ magic->magic[i]))
break;
}
if (i == magic->size)
return g_strdup (magic->program);
list = list->next;
}
return resolve_extension (db, program_path);
}
gchar *
gimp_interpreter_db_resolve (GimpInterpreterDB *db,
const gchar *program_path,
gchar **interp_arg)
{
gint fd;
gssize len;
gchar buffer[BUFSIZE];
*interp_arg = NULL;
fd = g_open (program_path, O_RDONLY | _O_BINARY, 0);
if (fd == -1)
return resolve_extension (db, program_path);
memset (buffer, 0, sizeof (buffer));
len = read (fd, buffer, sizeof (buffer));
close (fd);
if (len <= 0)
return resolve_extension (db, program_path);
if (len > 3 && buffer[0] == '#' && buffer[1] == '!')
return resolve_sh_bang (db, program_path, buffer, len, interp_arg);
return resolve_magic (db, program_path, buffer);
}

View File

@ -0,0 +1,68 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpinterpreterdb.h
* (C) 2005 Manish Singh <yosh@gimp.org>
*
* 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.
*/
#ifndef __GIMP_INTERPRETER_DB_H__
#define __GIMP_INTERPRETER_DB_H__
#define GIMP_TYPE_INTERPRETER_DB (gimp_interpreter_db_get_type ())
#define GIMP_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDB))
#define GIMP_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
#define GIMP_IS_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INTERPRETER_DB))
#define GIMP_IS_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INTERPRETER_DB))
#define GIMP_INTERPRETER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
typedef struct _GimpInterpreterDBClass GimpInterpreterDBClass;
struct _GimpInterpreterDB
{
GObject parent_instance;
GHashTable *programs;
GSList *magics;
GHashTable *magic_names;
GHashTable *extensions;
GHashTable *extension_names;
};
struct _GimpInterpreterDBClass
{
GObjectClass parent_class;
};
GType gimp_interpreter_db_get_type (void) G_GNUC_CONST;
GimpInterpreterDB * gimp_interpreter_db_new (void);
void gimp_interpreter_db_load (GimpInterpreterDB *db,
const gchar *interp_path);
void gimp_interpreter_db_clear (GimpInterpreterDB *db);
gchar * gimp_interpreter_db_resolve (GimpInterpreterDB *db,
const gchar *program_path,
gchar **interp_arg);
#endif /* __GIMP_INTERPRETER_DB_H__ */

View File

@ -2396,6 +2396,10 @@ prefs_dialog_new (Gimp *gimp,
GIMP_HELP_PREFS_FOLDERS_MODULES,
N_("Select Module Folders"),
"module-path", NULL },
{ N_("Interpreters"), N_("Interpreter Folders"), "folders-interp.png",
GIMP_HELP_PREFS_FOLDERS_INTERPRETERS,
N_("Select Interpreter Folders"),
"interpreter-path", NULL },
{ N_("Environment"), N_("Environment Folders"), "folders-environ.png",
GIMP_HELP_PREFS_FOLDERS_ENVIRONMENT,
N_("Select Environment Folders"),

View File

@ -243,6 +243,16 @@ tree_items[] =
"during initialization."),
TREE_ITEM_MKDIR
},
{
TRUE, "interpreters",
N_("This folder is used to store configuration for user "
"created, temporary, or otherwise non-system-supported "
"plug-in interpreters. The GIMP checks this folder in "
"addition to the system-wide GIMP interpreters folder "
"when searching for plug-in interpreter configuration "
"files."),
TREE_ITEM_MKDIR
},
{
TRUE, "environ",
N_("This folder is used to store user created, temporary, "

View File

@ -0,0 +1,767 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpinterpreterdb.c
* (C) 2005 Manish Singh <yosh@gimp.org>
*
* 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.
*/
/*
* The binfmt_misc bits are derived from linux/fs/binfmt_misc.c
* Copyright (C) 1997 Richard Günther
*/
/*
* The sh-bang code is derived from linux/fs/binfmt_script.c
* Copyright (C) 1996 Martin von Löwis
* original #!-checking implemented by tytso.
*/
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <glib-object.h>
#include <glib/gstdio.h>
#ifdef G_OS_WIN32
#include <io.h>
#endif
#ifndef _O_BINARY
#define _O_BINARY 0
#endif
#include "libgimpbase/gimpbase.h"
#include "core-types.h"
#include "gimpinterpreterdb.h"
#include "gimp-intl.h"
#define BUFSIZE 4096
typedef struct _GimpInterpreterMagic GimpInterpreterMagic;
struct _GimpInterpreterMagic
{
gulong offset;
gchar *magic;
gchar *mask;
guint size;
gchar *program;
};
static void gimp_interpreter_db_class_init (GimpInterpreterDBClass *class);
static void gimp_interpreter_db_init (GimpInterpreterDB *db);
static void gimp_interpreter_db_finalize (GObject *object);
static void gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
gpointer user_data);
static void gimp_interpreter_db_add_program (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer);
static void gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer);
static gboolean gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
gchar **tokens);
static gboolean gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
gchar **tokens);
static void gimp_interpreter_db_clear_magics (GimpInterpreterDB *db);
static void gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db);
static GObjectClass *parent_class = NULL;
GType
gimp_interpreter_db_get_type (void)
{
static GType interpreter_db_type = 0;
if (! interpreter_db_type)
{
static const GTypeInfo interpreter_db_info =
{
sizeof (GimpInterpreterDBClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gimp_interpreter_db_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GimpInterpreterDB),
0, /* n_preallocs */
(GInstanceInitFunc) gimp_interpreter_db_init,
};
interpreter_db_type = g_type_register_static (G_TYPE_OBJECT,
"GimpInterpreterDB",
&interpreter_db_info, 0);
}
return interpreter_db_type;
}
static void
gimp_interpreter_db_class_init (GimpInterpreterDBClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
object_class->finalize = gimp_interpreter_db_finalize;
}
static void
gimp_interpreter_db_init (GimpInterpreterDB *db)
{
db->programs = NULL;
db->magics = NULL;
db->magic_names = NULL;
db->extensions = NULL;
db->extension_names = NULL;
}
static void
gimp_interpreter_db_finalize (GObject *object)
{
GimpInterpreterDB *db;
db = GIMP_INTERPRETER_DB (object);
gimp_interpreter_db_clear (db);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GimpInterpreterDB *
gimp_interpreter_db_new (void)
{
return g_object_new (GIMP_TYPE_INTERPRETER_DB, NULL);
}
void
gimp_interpreter_db_load (GimpInterpreterDB *db,
const gchar *interp_path)
{
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
gimp_interpreter_db_clear (db);
db->programs = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
db->magic_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
db->extension_names = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
gimp_datafiles_read_directories (interp_path,
G_FILE_TEST_EXISTS,
gimp_interpreter_db_load_interp_file,
db);
gimp_interpreter_db_resolve_programs (db);
}
void
gimp_interpreter_db_clear (GimpInterpreterDB *db)
{
g_return_if_fail (GIMP_IS_INTERPRETER_DB (db));
if (db->magic_names)
{
g_hash_table_destroy (db->magic_names);
db->magic_names = NULL;
}
if (db->extension_names)
{
g_hash_table_destroy (db->extension_names);
db->extension_names = NULL;
}
if (db->programs)
{
g_hash_table_destroy (db->programs);
db->programs = NULL;
}
if (db->extensions)
{
g_hash_table_destroy (db->extensions);
db->extensions = NULL;
}
gimp_interpreter_db_clear_magics (db);
}
static void
gimp_interpreter_db_load_interp_file (const GimpDatafileData *file_data,
gpointer user_data)
{
GimpInterpreterDB *db;
FILE *interp_file;
gchar buffer[4096];
gsize len;
db = GIMP_INTERPRETER_DB (user_data);
interp_file = g_fopen (file_data->filename, "r");
if (! interp_file)
return;
while (fgets (buffer, sizeof (buffer), interp_file))
{
/* Skip comments */
if (buffer[0] == '#')
continue;
len = strlen (buffer) - 1;
/* Skip too long lines */
if (buffer[len] != '\n')
continue;
buffer[len] = '\0';
if (g_ascii_isalnum (buffer[0]) || (buffer[0] == '/'))
gimp_interpreter_db_add_program (db, file_data, buffer);
else if (! g_ascii_isspace (buffer[0]) && (buffer[0] != '\0'))
gimp_interpreter_db_add_binfmt_misc (db, file_data, buffer);
}
fclose (interp_file);
}
static void
gimp_interpreter_db_add_program (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer)
{
gchar *name, *program, *p;
p = strchr (buffer, '=');
if (! p)
return;
*p = '\0';
name = buffer;
program = p + 1;
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
{
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
gimp_filename_to_utf8 (file_data->filename),
gimp_filename_to_utf8 (program));
return;
}
if (! g_hash_table_lookup (db->programs, name))
g_hash_table_insert (db->programs, g_strdup (name), g_strdup (program));
}
static void
gimp_interpreter_db_add_binfmt_misc (GimpInterpreterDB *db,
const GimpDatafileData *file_data,
gchar *buffer)
{
gchar **tokens = NULL;
gchar *name, *type, *program;
gsize count;
gchar del[2];
count = strlen (buffer);
if ((count < 10) || (count > 255))
goto bail;
del[0] = *buffer;
del[1] = '\0';
memset (buffer + count, del[0], 8);
tokens = g_strsplit (buffer + 1, del, -1);
name = tokens[0];
type = tokens[1];
program = tokens[5];
if (name[0] == '\0' || program == '\0' || type[0] == '\0' || type[1] != '\0')
goto bail;
switch (type[0])
{
case 'E':
if (! gimp_interpreter_db_add_extension (db, tokens))
goto bail;
break;
case 'M':
if (! gimp_interpreter_db_add_magic (db, tokens))
goto bail;
break;
default:
goto bail;
}
goto out;
bail:
g_message (_("Bad binary format string in interpreter file %s"),
gimp_filename_to_utf8 (file_data->filename));
out:
g_strfreev (tokens);
}
static gboolean
gimp_interpreter_db_add_extension (GimpInterpreterDB *db,
gchar **tokens)
{
gchar *name, *extension, *program;
name = tokens[0];
extension = tokens[3];
program = tokens[5];
if (! g_hash_table_lookup (db->extension_names, name))
{
if (extension[0] == '\0' || extension[0] == '/')
return FALSE;
program = g_strdup (program);
g_hash_table_insert (db->extensions, g_strdup (extension), program);
g_hash_table_insert (db->extension_names, g_strdup (name), program);
}
return TRUE;
}
static gboolean
scanarg (gchar *s)
{
gchar c;
while ((c = *s++) != '\0')
{
if (c == '\\' && *s == 'x')
{
s++;
if (! g_ascii_isxdigit (*s++))
return FALSE;
if (! g_ascii_isxdigit (*s++))
return FALSE;
}
}
return TRUE;
}
static guint
unquote (gchar *from)
{
gchar c, *s = from, *p = from;
while ((c = *s++) != '\0')
{
if (c == '\\' && *s == 'x')
{
s++;
*p = g_ascii_xdigit_value (*s++) << 4;
*p++ |= g_ascii_xdigit_value (*s++);
continue;
}
*p++ = c;
}
return p - from;
}
static gboolean
gimp_interpreter_db_add_magic (GimpInterpreterDB *db,
gchar **tokens)
{
GimpInterpreterMagic *interp_magic;
gchar *name, *num, *magic, *mask, *program;
gulong offset;
guint size;
name = tokens[0];
num = tokens[2];
magic = tokens[3];
mask = tokens[4];
program = tokens[5];
if (! g_hash_table_lookup (db->magic_names, name))
{
if (num[0] != '\0')
{
offset = strtoul (num, &num, 10);
if (num[0] != '\0')
return FALSE;
if (offset > (BUFSIZE / 4))
return FALSE;
}
else
offset = 0;
if (! scanarg (magic))
return FALSE;
if (! scanarg (mask))
return FALSE;
size = unquote (magic);
if ((size + offset) > (BUFSIZE / 2))
return FALSE;
if (mask[0] == '\0')
mask = NULL;
else if (unquote (mask) != size)
return FALSE;
interp_magic = g_new (GimpInterpreterMagic, 1);
interp_magic->offset = offset;
interp_magic->magic = g_memdup (magic, size);
interp_magic->mask = g_memdup (mask, size);
interp_magic->size = size;
interp_magic->program = g_strdup (program);
db->magics = g_slist_append (db->magics, interp_magic);
g_hash_table_insert (db->magic_names, g_strdup (name), interp_magic);
}
return TRUE;
}
static void
gimp_interpreter_db_clear_magics (GimpInterpreterDB *db)
{
GimpInterpreterMagic *magic;
GSList *list, *last;
list = db->magics;
db->magics = NULL;
while (list)
{
magic = list->data;
g_free (magic->magic);
g_free (magic->mask);
g_free (magic->program);
g_free (magic);
last = list;
list = list->next;
g_slist_free_1 (last);
}
}
#ifdef INTERP_DEBUG
static void
print_kv (gpointer key,
gpointer value,
gpointer user_data)
{
g_print ("%s: %s\n", (gchar *) key, (gchar *) value);
}
static gchar *
quote (gchar *s,
guint size)
{
GString *d;
guint i;
if (s == NULL)
return "(null)";
d = g_string_sized_new (size * 4);
for (i = 0; i < size; i++)
g_string_append_printf (d, "\\x%02x", ((guint) s[i]) & 0xff);
return g_string_free (d, FALSE);
}
#endif
static gboolean
resolve_program (gpointer key,
gpointer value,
gpointer user_data)
{
GimpInterpreterDB *db = user_data;
gchar *program;
program = g_hash_table_lookup (db->programs, value);
if (program != NULL)
{
g_free (value);
value = g_strdup (program);
}
g_hash_table_insert (db->extensions, key, value);
return TRUE;
}
static void
gimp_interpreter_db_resolve_programs (GimpInterpreterDB *db)
{
GSList *list;
gchar *program;
GimpInterpreterMagic *magic;
GHashTable *extensions;
list = db->magics;
while (list)
{
magic = list->data;
program = g_hash_table_lookup (db->programs, magic->program);
if (program != NULL)
{
g_free (magic->program);
magic->program = g_strdup (program);
}
list = list->next;
}
extensions = db->extensions;
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
g_hash_table_foreach_steal (extensions, resolve_program, db);
g_hash_table_destroy (extensions);
#ifdef INTERP_DEBUG
g_print ("Programs:\n");
g_hash_table_foreach (db->programs, print_kv, NULL);
g_print ("\nExtensions:\n");
g_hash_table_foreach (db->extensions, print_kv, NULL);
g_print ("\nMagics:\n");
list = db->magics;
while (list)
{
GimpInterpreterMagic *magic;
magic = list->data;
g_print ("program: %s, offset: %lu, magic: %s, mask: %s\n",
magic->program, magic->offset,
quote (magic->magic, magic->size),
quote (magic->mask, magic->size));
list = list->next;
}
g_print ("\n");
#endif
}
static gchar *
resolve_extension (GimpInterpreterDB *db,
const gchar *program_path)
{
gchar *filename, *p, *program;
filename = g_path_get_basename (program_path);
p = strrchr (filename, '.');
if (! p)
return NULL;
program = g_hash_table_lookup (db->extensions, p + 1);
return g_strdup (program);
}
static gchar *
resolve_sh_bang (GimpInterpreterDB *db,
const gchar *program_path,
gchar *buffer,
gssize len,
gchar **interp_arg)
{
gchar *cp, *name, *program;
cp = strchr (buffer, '\n');
if (! cp)
cp = buffer + len - 1;
*cp = '\0';
while (cp > buffer)
{
cp--;
if ((*cp == ' ') || (*cp == '\t'))
*cp = '\0';
else
break;
}
for (cp = buffer + 2; (*cp == ' ') || (*cp == '\t'); cp++);
if (*cp == '\0')
return NULL;
name = cp;
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
/* nothing */ ;
while ((*cp == ' ') || (*cp == '\t'))
*cp++ = '\0';
if (*cp)
{
if (strcmp ("/usr/bin/env", name) == 0)
{
program = g_hash_table_lookup (db->programs, cp);
if (program)
return g_strdup (program);
}
*interp_arg = g_strdup (cp);
}
program = g_hash_table_lookup (db->programs, name);
if (! program)
program = name;
return g_strdup (program);
}
static gchar *
resolve_magic (GimpInterpreterDB *db,
const gchar *program_path,
gchar *buffer)
{
GSList *list;
GimpInterpreterMagic *magic;
gchar *s;
guint i;
list = db->magics;
while (list)
{
magic = list->data;
s = buffer + magic->offset;
if (magic->mask)
{
for (i = 0; i < magic->size; i++)
if ((*s++ ^ magic->magic[i]) & magic->mask[i])
break;
}
else
{
for (i = 0; i < magic->size; i++)
if ((*s++ ^ magic->magic[i]))
break;
}
if (i == magic->size)
return g_strdup (magic->program);
list = list->next;
}
return resolve_extension (db, program_path);
}
gchar *
gimp_interpreter_db_resolve (GimpInterpreterDB *db,
const gchar *program_path,
gchar **interp_arg)
{
gint fd;
gssize len;
gchar buffer[BUFSIZE];
*interp_arg = NULL;
fd = g_open (program_path, O_RDONLY | _O_BINARY, 0);
if (fd == -1)
return resolve_extension (db, program_path);
memset (buffer, 0, sizeof (buffer));
len = read (fd, buffer, sizeof (buffer));
close (fd);
if (len <= 0)
return resolve_extension (db, program_path);
if (len > 3 && buffer[0] == '#' && buffer[1] == '!')
return resolve_sh_bang (db, program_path, buffer, len, interp_arg);
return resolve_magic (db, program_path, buffer);
}

View File

@ -0,0 +1,68 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpinterpreterdb.h
* (C) 2005 Manish Singh <yosh@gimp.org>
*
* 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.
*/
#ifndef __GIMP_INTERPRETER_DB_H__
#define __GIMP_INTERPRETER_DB_H__
#define GIMP_TYPE_INTERPRETER_DB (gimp_interpreter_db_get_type ())
#define GIMP_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDB))
#define GIMP_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
#define GIMP_IS_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_INTERPRETER_DB))
#define GIMP_IS_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_INTERPRETER_DB))
#define GIMP_INTERPRETER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_INTERPRETER_DB, GimpInterpreterDBClass))
typedef struct _GimpInterpreterDBClass GimpInterpreterDBClass;
struct _GimpInterpreterDB
{
GObject parent_instance;
GHashTable *programs;
GSList *magics;
GHashTable *magic_names;
GHashTable *extensions;
GHashTable *extension_names;
};
struct _GimpInterpreterDBClass
{
GObjectClass parent_class;
};
GType gimp_interpreter_db_get_type (void) G_GNUC_CONST;
GimpInterpreterDB * gimp_interpreter_db_new (void);
void gimp_interpreter_db_load (GimpInterpreterDB *db,
const gchar *interp_path);
void gimp_interpreter_db_clear (GimpInterpreterDB *db);
gchar * gimp_interpreter_db_resolve (GimpInterpreterDB *db,
const gchar *program_path,
gchar **interp_arg);
#endif /* __GIMP_INTERPRETER_DB_H__ */

View File

@ -73,6 +73,7 @@
#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpenvirontable.h"
#include "core/gimpinterpreterdb.h"
#include "core/gimpprogress.h"
#include "plug-in.h"
@ -337,7 +338,9 @@ plug_in_open (PlugIn *plug_in)
gint my_read[2];
gint my_write[2];
gchar **envp;
gchar *args[7], **argv, **debug_argv;
gchar *args[9], **argv, **debug_argv;
gint argc;
gchar *interp, *interp_arg;
gchar *read_fd, *write_fd;
gchar *mode, *stm;
GError *error = NULL;
@ -417,13 +420,23 @@ plug_in_open (PlugIn *plug_in)
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
args[0] = plug_in->prog;
args[1] = "-gimp";
args[2] = read_fd;
args[3] = write_fd;
args[4] = mode;
args[5] = stm;
args[6] = NULL;
interp = gimp_interpreter_db_resolve (plug_in->gimp->interpreter_db,
plug_in->prog, &interp_arg);
argc = 0;
if (interp)
args[argc++] = interp;
if (interp_arg)
args[argc++] = interp_arg;
args[argc++] = plug_in->prog;
args[argc++] = "-gimp";
args[argc++] = read_fd;
args[argc++] = write_fd;
args[argc++] = mode;
args[argc++] = stm;
args[argc++] = NULL;
argv = args;
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
@ -497,6 +510,9 @@ cleanup:
g_free (write_fd);
g_free (stm);
g_free (interp);
g_free (interp_arg);
return plug_in->open;
}

View File

@ -73,6 +73,7 @@
#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpenvirontable.h"
#include "core/gimpinterpreterdb.h"
#include "core/gimpprogress.h"
#include "plug-in.h"
@ -337,7 +338,9 @@ plug_in_open (PlugIn *plug_in)
gint my_read[2];
gint my_write[2];
gchar **envp;
gchar *args[7], **argv, **debug_argv;
gchar *args[9], **argv, **debug_argv;
gint argc;
gchar *interp, *interp_arg;
gchar *read_fd, *write_fd;
gchar *mode, *stm;
GError *error = NULL;
@ -417,13 +420,23 @@ plug_in_open (PlugIn *plug_in)
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
args[0] = plug_in->prog;
args[1] = "-gimp";
args[2] = read_fd;
args[3] = write_fd;
args[4] = mode;
args[5] = stm;
args[6] = NULL;
interp = gimp_interpreter_db_resolve (plug_in->gimp->interpreter_db,
plug_in->prog, &interp_arg);
argc = 0;
if (interp)
args[argc++] = interp;
if (interp_arg)
args[argc++] = interp_arg;
args[argc++] = plug_in->prog;
args[argc++] = "-gimp";
args[argc++] = read_fd;
args[argc++] = write_fd;
args[argc++] = mode;
args[argc++] = stm;
args[argc++] = NULL;
argv = args;
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
@ -497,6 +510,9 @@ cleanup:
g_free (write_fd);
g_free (stm);
g_free (interp);
g_free (interp_arg);
return plug_in->open;
}

View File

@ -399,6 +399,7 @@
#define GIMP_HELP_PREFS_FOLDERS_PLUG_INS "gimp-prefs-folders-plug-ins"
#define GIMP_HELP_PREFS_FOLDERS_SCRIPTS "gimp-prefs-folders-scripts"
#define GIMP_HELP_PREFS_FOLDERS_MODULES "gimp-prefs-folders-modules"
#define GIMP_HELP_PREFS_FOLDERS_INTERPRETERS "gimp-prefs-folders-interpreters"
#define GIMP_HELP_PREFS_FOLDERS_ENVIRONMENT "gimp-prefs-folders-environment"
#define GIMP_HELP_PREFS_FOLDERS_THEMES "gimp-prefs-folders-themes"

View File

@ -1647,6 +1647,7 @@ themes/Default/images/Makefile
themes/Default/images/preferences/Makefile
themes/Small/Makefile
data/Makefile
data/interpreters/Makefile
data/environ/Makefile
data/misc/Makefile
data/misc/gimp.desktop.in

View File

@ -1,6 +1,6 @@
## Makefile.am for gimp/data
SUBDIRS = environ misc images brushes gradients palettes patterns
SUBDIRS = interpreters environ misc images brushes gradients palettes patterns
EXTRA_DIST = \
AUTHORS \

View File

@ -0,0 +1,2 @@
Makefile.in
Makefile

View File

@ -0,0 +1,7 @@
## Makefile.am for gimp/data/interpreters
interpretersdir = $(gimpplugindir)/interpreters
interpreters_DATA = default.interp
EXTRA_DIST = $(interpreters_DATA)

View File

@ -0,0 +1,15 @@
# Example entries in files like these
# This registers an interpreter name with a binary
# It is matched against #! syntax and the binfmt_misc syntax
#scm=/path/to/scm
# The following is the same syntax as Linux binfmt_misc
# See Documentation/binfmt_misc.txt in the Linux kernel sources for
# detailed information. (Right now, "flags" are noops)
# Register an extension
#:Scheme-ext:E::scm::/path/to/scm:
# Register a magic
#:Scheme-magic:M::\x3b\x20GIMP Scheme::scm:

View File

@ -61,14 +61,14 @@ GIMP opts for speed over memory. However, if memory is a big issue, try to
enable this setting. Possible values are yes and no.
.TP
(num-processors 1)
(num-processors 2)
On multiprocessor machines, if GIMP has been compiled with --enable-mp this
sets how many processors GIMP should use simultaneously. This is an integer
value.
.TP
(tile-cache-size 128M)
(tile-cache-size 256M)
The tile cache is used to make sure the GIMP doesn't thrash tiles between
memory and disk. Setting this value higher will cause the GIMP to use less
@ -83,7 +83,7 @@ kilobytes.
(interpolation-type linear)
Sets the level of interpolation used for scaling and other transformations.
Possible values are none, linear and cubic.
Possible values are none, linear, cubic and lanczos.
.TP
(plug-in-path "${gimp_dir}/plug-ins:${gimp_plug_in_dir}/plug-ins")
@ -97,6 +97,12 @@ search.
Sets the module search path. This is a colon-separated list of folders to
search.
.TP
(interpreter-path "${gimp_dir}/interpreters:${gimp_plug_in_dir}/interpreters")
Sets the interpreter search path. This is a colon-separated list of folders
to search.
.TP
(environ-path "${gimp_dir}/environ:${gimp_plug_in_dir}/environ")
@ -219,8 +225,8 @@ are yes and no.
.TP
(default-image
(width 420)
(height 300)
(width 377)
(height 233)
(unit pixels)
(xresolution 72.000000)
(yresolution 72.000000)
@ -236,8 +242,8 @@ Sets the default image in the "File/New" dialog. This is a parameter list.
(style intersections)
(fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
(bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
(xspacing 10.000000)
(yspacing 10.000000)
(xspacing 32.000000)
(yspacing 32.000000)
(spacing-unit inches)
(xoffset 0.000000)
(yoffset 0.000000)
@ -315,6 +321,14 @@ Possible values are yes and no.
Generally only a concern for 8-bit displays, this sets the minimum number of
system colors allocated for the GIMP. This is an integer value.
.TP
(color-management
(mode display)
(display-rendering-intent perceptual)
(simulation-rendering-intent perceptual))
Defines the color management behavior. This is a parameter list.
.TP
(transparency-size medium-checks)

View File

@ -39,7 +39,7 @@
# sets how many processors GIMP should use simultaneously. This is an
# integer value.
#
# (num-processors 1)
# (num-processors 2)
# The tile cache is used to make sure the GIMP doesn't thrash tiles between
# memory and disk. Setting this value higher will cause the GIMP to use less
@ -50,10 +50,10 @@
# or gigabytes. If no suffix is specified the size defaults to being
# specified in kilobytes.
#
# (tile-cache-size 128M)
# (tile-cache-size 256M)
# Sets the level of interpolation used for scaling and other transformations.
# Possible values are none, linear and cubic.
# Possible values are none, linear, cubic and lanczos.
#
# (interpolation-type linear)
@ -67,6 +67,11 @@
#
# (module-path "${gimp_dir}/modules:${gimp_plug_in_dir}/modules")
# Sets the interpreter search path. This is a colon-separated list of
# folders to search.
#
# (interpreter-path "${gimp_dir}/interpreters:${gimp_plug_in_dir}/interpreters")
# Sets the environ search path. This is a colon-separated list of folders to
# search.
#
@ -170,8 +175,8 @@
# Sets the default image in the "File/New" dialog. This is a parameter list.
#
# (default-image
# (width 420)
# (height 300)
# (width 377)
# (height 233)
# (unit pixels)
# (xresolution 72.000000)
# (yresolution 72.000000)
@ -186,8 +191,8 @@
# (style intersections)
# (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
# (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
# (xspacing 10.000000)
# (yspacing 10.000000)
# (xspacing 32.000000)
# (yspacing 32.000000)
# (spacing-unit inches)
# (xoffset 0.000000)
# (yoffset 0.000000)
@ -254,6 +259,13 @@
#
# (min-colors 144)
# Defines the color management behavior. This is a parameter list.
#
# (color-management
# (mode display)
# (display-rendering-intent perceptual)
# (simulation-rendering-intent perceptual))
# Sets the size of the checkerboard used to display transparency. Possible
# values are small-checks, medium-checks and large-checks.
#

View File

@ -11,10 +11,11 @@ PREFS_IMAGES = \
environment.png \
folders.png \
folders-brushes.png \
folders-environ.png \
folders-fonts.png \
folders-gradients.png \
folders-interp.png \
folders-modules.png \
folders-environ.png \
folders-palettes.png \
folders-patterns.png \
folders-plug-ins.png \

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB