diff --git a/ChangeLog b/ChangeLog index 123c21c885..64e04cd97f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +Mon Jan 18 23:36:57 1999 Austin Donnelly + + * app/menus.c: include module browser, plus re-instate the 'swap + colors' and other options that got killed by mistake. Clean + up the odd extra separator too. + + * app/color_notebook.c: hide newly created colour selectors so we + know the GIMP one will be the default page. + + * app/module_db.[ch]: NEW FILEs: module database / browser. + * app/Makefile.am: add module_db.[ch] stuff + * app/app_procs.c: initialise the module_db + * app/commands.[ch]: callback to create a module browser. + * app/plug_in.c: move module loading out to module_db.c + * libgimp/gimpmodule.h: API change: module_init() should return + additonal info (author, purpose, date, etc.) Also optional + module_unload() function. + * modules/colorsel_gtk.c: add module info, plus an unload function + + * modules/Makefile.am: build triangle colour selector module + * modules/colorsel_triangle.c: NEW FILE: colour selector from + Simon Budig . + + * MAINTAINERS: changed my email address + Mon Jan 18 22:55:19 GMT 1999 Adam D. Moss * app/gimpimage.c app/gimpimage.h: diff --git a/MAINTAINERS b/MAINTAINERS index a7b661fb98..c48f047540 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -31,10 +31,10 @@ current work: once the Windows port needs less attention, would love commit access: no Name: Austin Donnelly -Email: austin@greenend.org.uk +Email: austin@gimp.org url: http://www.cl.cam.ac.uk/~and1000/ ircnick: austin -expertise: resolution stuff, fonts +expertise: resolution stuff, modules, colour selectors, fonts current work: random bug fixes, resolution commit access: yes diff --git a/app/Makefile.am b/app/Makefile.am index 6a6f3f44a8..c94d286943 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -245,6 +245,8 @@ gimp_SOURCES = \ marching_ants.h \ menus.c \ menus.h \ + module_db.c \ + module_db.h \ move.c \ move.h \ ops_buttons.c \ diff --git a/app/actions/help-commands.c b/app/actions/help-commands.c index 0d0cb2f17d..e33aacb1a4 100644 --- a/app/actions/help-commands.c +++ b/app/actions/help-commands.c @@ -57,6 +57,7 @@ #include "layers_dialog.h" #include "layer_select.h" #include "levels.h" +#include "module_db.h" #include "palette.h" #include "patterns.h" #include "plug_in.h" @@ -1105,6 +1106,16 @@ tips_dialog_cmd_callback (GtkWidget *widget, tips_dialog_create (); } +void +dialogs_module_browser_cmd_callback (GtkWidget *widget, + gpointer client_data) +{ + GtkWidget *w; + + w = module_db_browser_new (); + gtk_widget_show (w); +} + /****************************************************/ /** LOCAL FUNCTIONS **/ diff --git a/app/actions/help-commands.h b/app/actions/help-commands.h index 0d0215d1d4..028893fa33 100644 --- a/app/actions/help-commands.h +++ b/app/actions/help-commands.h @@ -95,5 +95,6 @@ void dialogs_device_status_cmd_callback (GtkWidget *, gpointer); void dialogs_error_console_cmd_callback (GtkWidget *, gpointer); void about_dialog_cmd_callback (GtkWidget *, gpointer); void tips_dialog_cmd_callback (GtkWidget *, gpointer); +void dialogs_module_browser_cmd_callback (GtkWidget *, gpointer); #endif /* __COMMANDS_H__ */ diff --git a/app/actions/plug-in-commands.c b/app/actions/plug-in-commands.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/actions/plug-in-commands.c +++ b/app/actions/plug-in-commands.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/app_procs.c b/app/app_procs.c index 49a8fb771c..b1d8dd15c7 100644 --- a/app/app_procs.c +++ b/app/app_procs.c @@ -55,6 +55,7 @@ #include "palette.h" #include "patterns.h" #include "plug_in.h" +#include "module_db.h" #include "procedural_db.h" #include "session.h" #include "temp_buf.h" @@ -526,6 +527,7 @@ app_init (void) app_init_update_status (NULL, NULL, 1.00); plug_in_init (); /* initialize the plug in structures */ + module_db_init (); /* load any modules we need */ RESET_BAR(); file_ops_post_init (); /* post-initialize the file types */ diff --git a/app/color_notebook.c b/app/color_notebook.c index 438e92d989..7ee36087ee 100644 --- a/app/color_notebook.c +++ b/app/color_notebook.c @@ -147,6 +147,8 @@ color_notebook_new (int r, { label = gtk_label_new (info->name); gtk_widget_show (label); + /* hide the frame, so it doesn't get selected by mistake */ + gtk_widget_hide (csel->frame); gtk_notebook_append_page (GTK_NOTEBOOK (cnp->notebook), csel->frame, label); } diff --git a/app/commands.c b/app/commands.c index 0d0cb2f17d..e33aacb1a4 100644 --- a/app/commands.c +++ b/app/commands.c @@ -57,6 +57,7 @@ #include "layers_dialog.h" #include "layer_select.h" #include "levels.h" +#include "module_db.h" #include "palette.h" #include "patterns.h" #include "plug_in.h" @@ -1105,6 +1106,16 @@ tips_dialog_cmd_callback (GtkWidget *widget, tips_dialog_create (); } +void +dialogs_module_browser_cmd_callback (GtkWidget *widget, + gpointer client_data) +{ + GtkWidget *w; + + w = module_db_browser_new (); + gtk_widget_show (w); +} + /****************************************************/ /** LOCAL FUNCTIONS **/ diff --git a/app/commands.h b/app/commands.h index 0d0215d1d4..028893fa33 100644 --- a/app/commands.h +++ b/app/commands.h @@ -95,5 +95,6 @@ void dialogs_device_status_cmd_callback (GtkWidget *, gpointer); void dialogs_error_console_cmd_callback (GtkWidget *, gpointer); void about_dialog_cmd_callback (GtkWidget *, gpointer); void tips_dialog_cmd_callback (GtkWidget *, gpointer); +void dialogs_module_browser_cmd_callback (GtkWidget *, gpointer); #endif /* __COMMANDS_H__ */ diff --git a/app/dialogs/color-dialog.c b/app/dialogs/color-dialog.c index 438e92d989..7ee36087ee 100644 --- a/app/dialogs/color-dialog.c +++ b/app/dialogs/color-dialog.c @@ -147,6 +147,8 @@ color_notebook_new (int r, { label = gtk_label_new (info->name); gtk_widget_show (label); + /* hide the frame, so it doesn't get selected by mistake */ + gtk_widget_hide (csel->frame); gtk_notebook_append_page (GTK_NOTEBOOK (cnp->notebook), csel->frame, label); } diff --git a/app/dialogs/module-dialog.c b/app/dialogs/module-dialog.c new file mode 100644 index 0000000000..95f8c49dd8 --- /dev/null +++ b/app/dialogs/module-dialog.c @@ -0,0 +1,518 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.c (C) 1999 Austin Donnelly + * + * 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 +#include + +#include "appenv.h" +#include "module_db.h" +#include "gimprc.h" +#include "datafiles.h" +#include "actionarea.h" +#include "libgimp/gimpintl.h" + +#include "libgimp/gimpmodule.h" + + +typedef enum { + ST_MODULE_ERROR, /* missing module_load function or other error */ + ST_LOADED_OK, /* happy and running (normal state of affairs) */ + ST_LOAD_FAILED, /* module_load returned GIMP_MODULE_UNLOAD */ + ST_UNLOAD_REQUESTED, /* sent unload request, waiting for callback */ + ST_UNLOADED_OK /* callback arrived, module not in memory anymore */ +} module_state; + +static const char * const statename[] = { + "ST_MODULE_ERROR", + "ST_LOADED_OK", + "ST_LOAD_FAILED", + "ST_UNLOAD_REQUESTED", + "ST_UNLOADED_OK" +}; + + +/* one of these is kept per-module */ +typedef struct { + gchar *fullpath; /* path to the module */ + module_state state; /* what's happened to the module */ + /* stuff from now on may be NULL depending on the state the module is in */ + GimpModuleInfo *info; /* returned values from module_init */ + GModule *module; /* handle on the module */ + gchar *last_module_error; + GimpModuleInitFunc *init; + GimpModuleUnloadFunc *unload; +} module_info; + +#define NUM_INFO_LINES 6 + +typedef struct { + GtkWidget *table; + GtkWidget *label[NUM_INFO_LINES]; + GtkWidget *button_label; + module_info *last_update; + GtkWidget *button; +} browser_st; + +/* global list of module_info */ +static GSList *modules = NULL; + + +/*#define DUMP_DB*/ + + +/* prototypes */ +static void module_initialize (char *filename); +static void mod_load (module_info *mod, gboolean verbose); +static void mod_unload (module_info *mod, gboolean verbose); +#ifdef DUMP_DB +static void print_module_info (gpointer data, gpointer user_data); +#endif + +static void browser_popdown_callback (GtkWidget *w, gpointer client_data); +static void browser_info_update (browser_st *st, module_info *mod); +static void browser_info_init (GtkWidget *table); +static void browser_select_callback (GtkWidget *widget, GtkWidget *child); +static void browser_load_unload_callback (GtkWidget *widget, gpointer data); + + +/**************************************************************/ +/* Exported functions */ + +void +module_db_init (void) +{ + /* Load and initialize gimp modules */ + + if (g_module_supported ()) + datafiles_read_directories (module_path, + module_initialize, 0 /* no flags */); + +#ifdef DUMP_DB + g_slist_foreach (modules, print_module_info, NULL); +#endif +} + + +GtkWidget * +module_db_browser_new (void) +{ + GtkWidget *shell; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *listbox; + GtkWidget *list; + GtkWidget *list_item; + GSList *here; + module_info *info; + browser_st *st; + ActionAreaItem action_items[] = + { + { N_("OK"), browser_popdown_callback, NULL, NULL } + }; + + + shell = gtk_dialog_new (); + gtk_window_set_wmclass (GTK_WINDOW (shell), "module_db_dialog", "Gimp"); + gtk_window_set_title (GTK_WINDOW (shell), _("Module DB")); + + hbox = gtk_hbox_new (FALSE, 5); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 1); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (shell)->vbox), hbox, TRUE, TRUE, 0); + gtk_widget_show (hbox); + + listbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (hbox), listbox, TRUE, TRUE, 0); + gtk_widget_set_usize (listbox, 125, 100); + gtk_widget_show (listbox); + + list = gtk_list_new (); + gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (listbox), list); + + st = g_new0 (browser_st, 1); + + here = modules; + while (here) + { + info = here->data; + here = g_slist_next (here); + + if (!st->last_update) + st->last_update = info; + + list_item = gtk_list_item_new_with_label (info->fullpath); + gtk_container_add (GTK_CONTAINER (list), list_item); + gtk_widget_show (list_item); + gtk_object_set_user_data (GTK_OBJECT (list_item), info); + } + + gtk_widget_show (list); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + st->table = gtk_table_new (2, NUM_INFO_LINES, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), st->table, TRUE, TRUE, 0); + gtk_widget_show (st->table); + + st->button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox), st->button, TRUE, TRUE, 0); + gtk_widget_show (st->button); + gtk_signal_connect (GTK_OBJECT (st->button), "clicked", + browser_load_unload_callback, st); + + browser_info_init (st->table); + browser_info_update (st, modules->data); + + gtk_object_set_user_data (GTK_OBJECT (list), st); + + gtk_signal_connect (GTK_OBJECT (list), "select_child", + browser_select_callback, NULL); + + action_items[0].user_data = shell; + build_action_area (GTK_DIALOG (shell), + action_items, + sizeof( action_items)/sizeof( ActionAreaItem), + 0); + + return shell; +} + + +/**************************************************************/ +/* helper functions */ + + +/* name must be of the form lib*.so */ +/* TODO: need support for WIN32-style dll names. Maybe this function + * should live in libgmodule? */ +static gboolean +valid_module_name (const char *filename) +{ + const char *basename; + int len; + + basename = strrchr (filename, '/'); + if (basename) + basename++; + else + basename = filename; + + len = strlen (basename); + + if (len < 3 + 1 + 3) + return FALSE; + + if (strncmp (basename, "lib", 3)) + return FALSE; + + if (strcmp (basename + len - 3, ".so")) + return FALSE; + + return TRUE; +} + + + +static void +module_initialize (char *filename) +{ + module_info *mod; + + if (!valid_module_name (filename)) + return; + + mod = g_new0 (module_info, 1); + modules = g_slist_append (modules, mod); + + mod->fullpath = g_strdup (filename); + + if ((be_verbose == TRUE) || (no_splash == TRUE)) + g_print (_("load module: \"%s\"\n"), filename); + + mod_load (mod, TRUE); +} + +static void +mod_load (module_info *mod, gboolean verbose) +{ + gpointer symbol; + + g_return_if_fail (mod->module == NULL); + + mod->module = g_module_open (mod->fullpath, G_MODULE_BIND_LAZY); + if (!mod->module) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (g_module_error ()); + + if (verbose) + g_warning (_("module load error: %s: %s"), + mod->fullpath, mod->last_module_error); + return; + } + + /* find the module_init symbol */ + if (!g_module_symbol (mod->module, "module_init", &symbol)) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (_("missing module_init() symbol")); + + if (verbose) + g_warning (_("%s: module_init() symbol not found"), mod->fullpath); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* run module's initialisation */ + mod->init = symbol; + mod->info = NULL; + if (mod->init (&mod->info) == GIMP_MODULE_UNLOAD) + { + mod->state = ST_LOAD_FAILED; + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* module is now happy */ + mod->state = ST_LOADED_OK; + + /* do we have an unload function? */ + if (g_module_symbol (mod->module, "module_unload", &symbol)) + mod->unload = symbol; + else + mod->unload = NULL; +} + + +static void +mod_unload_completed_callback (void *data) +{ + module_info *mod = data; + + g_return_if_fail (mod->state == ST_UNLOAD_REQUESTED); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + + mod->state = ST_UNLOADED_OK; +} + +static void +mod_unload (module_info *mod, gboolean verbose) +{ + g_return_if_fail (mod->module != NULL); + g_return_if_fail (mod->unload != NULL); + + if (mod->state == ST_UNLOAD_REQUESTED) + return; + + mod->state = ST_UNLOAD_REQUESTED; + + /* send the unload request */ + mod->unload (mod->info->shutdown_data, mod_unload_completed_callback, mod); +} + + + +#ifdef DUMP_DB +static void +print_module_info (gpointer data, gpointer user_data) +{ + module_info *i = data; + + printf ("\n%s: %s\n", + i->fullpath, statename[i->state]); + printf (" module:%p lasterr:%s init:%p unload:%p\n", + i->module, i->last_module_error? i->last_module_error : "NONE", + i->init, i->unload); + if (i->info) + { + printf (" shutdown_data: %p\n" + " purpose: %s\n" + " author: %s\n" + " version: %s\n" + " copyright: %s\n" + " date: %s\n", + i->info->shutdown_data, + i->info->purpose, i->info->author, i->info->version, + i->info->copyright, i->info->date); + } +} +#endif + + + +/**************************************************************/ +/* UI functions */ + +static void +browser_popdown_callback (GtkWidget *w, gpointer client_data) +{ + gtk_widget_destroy (GTK_WIDGET (client_data)); +} + + +static void +browser_info_update (browser_st *st, module_info *mod) +{ + int i; + const char *text[NUM_INFO_LINES]; + + if (mod->info) + { + text[0] = mod->info->purpose; + text[1] = mod->info->author; + text[2] = mod->info->version; + text[3] = mod->info->copyright; + text[4] = mod->info->date; + } + else + { + text[0] = "--"; + text[1] = "--"; + text[2] = "--"; + text[3] = "--"; + text[4] = "--"; + } + + if (mod->state == ST_MODULE_ERROR && mod->last_module_error) + { + text[5] = g_malloc (strlen (statename[mod->state]) + 2 + + strlen (mod->last_module_error) + 2); + sprintf(text[5], "%s (%s)", statename[mod->state], mod->last_module_error); + } + else + { + text[5] = g_strdup (statename[mod->state]); + } + + for (i=0; i < NUM_INFO_LINES; i++) + { + if (st->label[i]) + gtk_container_remove (GTK_CONTAINER (st->table), st->label[i]); + st->label[i] = gtk_label_new (text[i]); + gtk_misc_set_alignment (GTK_MISC (st->label[i]), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (st->table), st->label[i], 1, 2, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (st->label[i]); + } + + g_free (text[5]); + + /* work out what the button should do (if anything) */ + switch (mod->state) { + case ST_MODULE_ERROR: + case ST_LOAD_FAILED: + case ST_UNLOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Load")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), TRUE); + break; + + case ST_UNLOAD_REQUESTED: + gtk_widget_set_sensitive (GTK_WIDGET (st->button), FALSE); + break; + + case ST_LOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Unload")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), + mod->unload? TRUE : FALSE); + break; + } +} + +static void +browser_info_init (GtkWidget *table) +{ + GtkWidget *label; + int i; + char *text[] = { + N_("Purpose: "), + N_("Author: "), + N_("Verson: "), + N_("Copyright: "), + N_("Date: "), + N_("State: ") + }; + + for (i=0; i < sizeof(text) / sizeof(char *); i++) + { + label = gtk_label_new (gettext (text[i])); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (label); + } +} + +static void +browser_select_callback (GtkWidget *widget, GtkWidget *child) +{ + module_info *i; + browser_st *st; + + i = gtk_object_get_user_data (GTK_OBJECT (child)); + st = gtk_object_get_user_data (GTK_OBJECT (widget)); + + if (st->last_update == i) + return; + + st->last_update = i; + + browser_info_update (st, i); +} + + +static void +browser_load_unload_callback (GtkWidget *widget, gpointer data) +{ + browser_st *st = data; + + if (st->last_update->state == ST_LOADED_OK) + mod_unload (st->last_update, FALSE); + else + mod_load (st->last_update, FALSE); + + browser_info_update (st, st->last_update); +} diff --git a/app/dialogs/module-dialog.h b/app/dialogs/module-dialog.h new file mode 100644 index 0000000000..c8d4a1dbe1 --- /dev/null +++ b/app/dialogs/module-dialog.h @@ -0,0 +1,29 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.h (C) 1999 Austin Donnelly + * + * 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 __MODULE_DB_H__ + +/* Load any modules we find on the module-path set in the gimprc */ +void module_db_init (void); + +GtkWidget *module_db_browser_new (void); + + +#endif /* __MODULE_DB_H__ */ diff --git a/app/gui/color-notebook.c b/app/gui/color-notebook.c index 438e92d989..7ee36087ee 100644 --- a/app/gui/color-notebook.c +++ b/app/gui/color-notebook.c @@ -147,6 +147,8 @@ color_notebook_new (int r, { label = gtk_label_new (info->name); gtk_widget_show (label); + /* hide the frame, so it doesn't get selected by mistake */ + gtk_widget_hide (csel->frame); gtk_notebook_append_page (GTK_NOTEBOOK (cnp->notebook), csel->frame, label); } diff --git a/app/gui/commands.c b/app/gui/commands.c index 0d0cb2f17d..e33aacb1a4 100644 --- a/app/gui/commands.c +++ b/app/gui/commands.c @@ -57,6 +57,7 @@ #include "layers_dialog.h" #include "layer_select.h" #include "levels.h" +#include "module_db.h" #include "palette.h" #include "patterns.h" #include "plug_in.h" @@ -1105,6 +1106,16 @@ tips_dialog_cmd_callback (GtkWidget *widget, tips_dialog_create (); } +void +dialogs_module_browser_cmd_callback (GtkWidget *widget, + gpointer client_data) +{ + GtkWidget *w; + + w = module_db_browser_new (); + gtk_widget_show (w); +} + /****************************************************/ /** LOCAL FUNCTIONS **/ diff --git a/app/gui/commands.h b/app/gui/commands.h index 0d0215d1d4..028893fa33 100644 --- a/app/gui/commands.h +++ b/app/gui/commands.h @@ -95,5 +95,6 @@ void dialogs_device_status_cmd_callback (GtkWidget *, gpointer); void dialogs_error_console_cmd_callback (GtkWidget *, gpointer); void about_dialog_cmd_callback (GtkWidget *, gpointer); void tips_dialog_cmd_callback (GtkWidget *, gpointer); +void dialogs_module_browser_cmd_callback (GtkWidget *, gpointer); #endif /* __COMMANDS_H__ */ diff --git a/app/gui/help-commands.c b/app/gui/help-commands.c index 0d0cb2f17d..e33aacb1a4 100644 --- a/app/gui/help-commands.c +++ b/app/gui/help-commands.c @@ -57,6 +57,7 @@ #include "layers_dialog.h" #include "layer_select.h" #include "levels.h" +#include "module_db.h" #include "palette.h" #include "patterns.h" #include "plug_in.h" @@ -1105,6 +1106,16 @@ tips_dialog_cmd_callback (GtkWidget *widget, tips_dialog_create (); } +void +dialogs_module_browser_cmd_callback (GtkWidget *widget, + gpointer client_data) +{ + GtkWidget *w; + + w = module_db_browser_new (); + gtk_widget_show (w); +} + /****************************************************/ /** LOCAL FUNCTIONS **/ diff --git a/app/gui/help-commands.h b/app/gui/help-commands.h index 0d0215d1d4..028893fa33 100644 --- a/app/gui/help-commands.h +++ b/app/gui/help-commands.h @@ -95,5 +95,6 @@ void dialogs_device_status_cmd_callback (GtkWidget *, gpointer); void dialogs_error_console_cmd_callback (GtkWidget *, gpointer); void about_dialog_cmd_callback (GtkWidget *, gpointer); void tips_dialog_cmd_callback (GtkWidget *, gpointer); +void dialogs_module_browser_cmd_callback (GtkWidget *, gpointer); #endif /* __COMMANDS_H__ */ diff --git a/app/gui/menus.c b/app/gui/menus.c index 0075cfd210..5abfe7e3b2 100644 --- a/app/gui/menus.c +++ b/app/gui/menus.c @@ -62,6 +62,7 @@ static const GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Device Status..."), NULL, dialogs_device_status_cmd_callback, 0 }, { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, + { N_("/File/Dialogs/Module Browser..."), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, }; static guint n_toolbox_entries = sizeof (toolbox_entries) / sizeof (toolbox_entries[0]); @@ -148,7 +149,6 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Image/Resize"), NULL, image_resize_cmd_callback, 0 }, { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Image/---"), NULL, NULL, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, { N_("/Layers/Raise Layer"), "F", layers_raise_cmd_callback, 0 }, @@ -191,7 +191,11 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, */ - { N_("/Filters/"), NULL, NULL, 0 }, + { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, + { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, + { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, + { N_("/Tools/---"), NULL, NULL, 0, "" }, + { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, @@ -297,7 +301,7 @@ void menus_tools_create (ToolInfo *tool_info) { GtkItemFactoryEntry entry; - + entry.path = gettext(tool_info->menu_path); entry.accelerator = tool_info->menu_accel; entry.callback = tools_select_cmd_callback; diff --git a/app/gui/module-browser.c b/app/gui/module-browser.c new file mode 100644 index 0000000000..95f8c49dd8 --- /dev/null +++ b/app/gui/module-browser.c @@ -0,0 +1,518 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.c (C) 1999 Austin Donnelly + * + * 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 +#include + +#include "appenv.h" +#include "module_db.h" +#include "gimprc.h" +#include "datafiles.h" +#include "actionarea.h" +#include "libgimp/gimpintl.h" + +#include "libgimp/gimpmodule.h" + + +typedef enum { + ST_MODULE_ERROR, /* missing module_load function or other error */ + ST_LOADED_OK, /* happy and running (normal state of affairs) */ + ST_LOAD_FAILED, /* module_load returned GIMP_MODULE_UNLOAD */ + ST_UNLOAD_REQUESTED, /* sent unload request, waiting for callback */ + ST_UNLOADED_OK /* callback arrived, module not in memory anymore */ +} module_state; + +static const char * const statename[] = { + "ST_MODULE_ERROR", + "ST_LOADED_OK", + "ST_LOAD_FAILED", + "ST_UNLOAD_REQUESTED", + "ST_UNLOADED_OK" +}; + + +/* one of these is kept per-module */ +typedef struct { + gchar *fullpath; /* path to the module */ + module_state state; /* what's happened to the module */ + /* stuff from now on may be NULL depending on the state the module is in */ + GimpModuleInfo *info; /* returned values from module_init */ + GModule *module; /* handle on the module */ + gchar *last_module_error; + GimpModuleInitFunc *init; + GimpModuleUnloadFunc *unload; +} module_info; + +#define NUM_INFO_LINES 6 + +typedef struct { + GtkWidget *table; + GtkWidget *label[NUM_INFO_LINES]; + GtkWidget *button_label; + module_info *last_update; + GtkWidget *button; +} browser_st; + +/* global list of module_info */ +static GSList *modules = NULL; + + +/*#define DUMP_DB*/ + + +/* prototypes */ +static void module_initialize (char *filename); +static void mod_load (module_info *mod, gboolean verbose); +static void mod_unload (module_info *mod, gboolean verbose); +#ifdef DUMP_DB +static void print_module_info (gpointer data, gpointer user_data); +#endif + +static void browser_popdown_callback (GtkWidget *w, gpointer client_data); +static void browser_info_update (browser_st *st, module_info *mod); +static void browser_info_init (GtkWidget *table); +static void browser_select_callback (GtkWidget *widget, GtkWidget *child); +static void browser_load_unload_callback (GtkWidget *widget, gpointer data); + + +/**************************************************************/ +/* Exported functions */ + +void +module_db_init (void) +{ + /* Load and initialize gimp modules */ + + if (g_module_supported ()) + datafiles_read_directories (module_path, + module_initialize, 0 /* no flags */); + +#ifdef DUMP_DB + g_slist_foreach (modules, print_module_info, NULL); +#endif +} + + +GtkWidget * +module_db_browser_new (void) +{ + GtkWidget *shell; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *listbox; + GtkWidget *list; + GtkWidget *list_item; + GSList *here; + module_info *info; + browser_st *st; + ActionAreaItem action_items[] = + { + { N_("OK"), browser_popdown_callback, NULL, NULL } + }; + + + shell = gtk_dialog_new (); + gtk_window_set_wmclass (GTK_WINDOW (shell), "module_db_dialog", "Gimp"); + gtk_window_set_title (GTK_WINDOW (shell), _("Module DB")); + + hbox = gtk_hbox_new (FALSE, 5); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 1); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (shell)->vbox), hbox, TRUE, TRUE, 0); + gtk_widget_show (hbox); + + listbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (hbox), listbox, TRUE, TRUE, 0); + gtk_widget_set_usize (listbox, 125, 100); + gtk_widget_show (listbox); + + list = gtk_list_new (); + gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (listbox), list); + + st = g_new0 (browser_st, 1); + + here = modules; + while (here) + { + info = here->data; + here = g_slist_next (here); + + if (!st->last_update) + st->last_update = info; + + list_item = gtk_list_item_new_with_label (info->fullpath); + gtk_container_add (GTK_CONTAINER (list), list_item); + gtk_widget_show (list_item); + gtk_object_set_user_data (GTK_OBJECT (list_item), info); + } + + gtk_widget_show (list); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + st->table = gtk_table_new (2, NUM_INFO_LINES, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), st->table, TRUE, TRUE, 0); + gtk_widget_show (st->table); + + st->button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox), st->button, TRUE, TRUE, 0); + gtk_widget_show (st->button); + gtk_signal_connect (GTK_OBJECT (st->button), "clicked", + browser_load_unload_callback, st); + + browser_info_init (st->table); + browser_info_update (st, modules->data); + + gtk_object_set_user_data (GTK_OBJECT (list), st); + + gtk_signal_connect (GTK_OBJECT (list), "select_child", + browser_select_callback, NULL); + + action_items[0].user_data = shell; + build_action_area (GTK_DIALOG (shell), + action_items, + sizeof( action_items)/sizeof( ActionAreaItem), + 0); + + return shell; +} + + +/**************************************************************/ +/* helper functions */ + + +/* name must be of the form lib*.so */ +/* TODO: need support for WIN32-style dll names. Maybe this function + * should live in libgmodule? */ +static gboolean +valid_module_name (const char *filename) +{ + const char *basename; + int len; + + basename = strrchr (filename, '/'); + if (basename) + basename++; + else + basename = filename; + + len = strlen (basename); + + if (len < 3 + 1 + 3) + return FALSE; + + if (strncmp (basename, "lib", 3)) + return FALSE; + + if (strcmp (basename + len - 3, ".so")) + return FALSE; + + return TRUE; +} + + + +static void +module_initialize (char *filename) +{ + module_info *mod; + + if (!valid_module_name (filename)) + return; + + mod = g_new0 (module_info, 1); + modules = g_slist_append (modules, mod); + + mod->fullpath = g_strdup (filename); + + if ((be_verbose == TRUE) || (no_splash == TRUE)) + g_print (_("load module: \"%s\"\n"), filename); + + mod_load (mod, TRUE); +} + +static void +mod_load (module_info *mod, gboolean verbose) +{ + gpointer symbol; + + g_return_if_fail (mod->module == NULL); + + mod->module = g_module_open (mod->fullpath, G_MODULE_BIND_LAZY); + if (!mod->module) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (g_module_error ()); + + if (verbose) + g_warning (_("module load error: %s: %s"), + mod->fullpath, mod->last_module_error); + return; + } + + /* find the module_init symbol */ + if (!g_module_symbol (mod->module, "module_init", &symbol)) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (_("missing module_init() symbol")); + + if (verbose) + g_warning (_("%s: module_init() symbol not found"), mod->fullpath); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* run module's initialisation */ + mod->init = symbol; + mod->info = NULL; + if (mod->init (&mod->info) == GIMP_MODULE_UNLOAD) + { + mod->state = ST_LOAD_FAILED; + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* module is now happy */ + mod->state = ST_LOADED_OK; + + /* do we have an unload function? */ + if (g_module_symbol (mod->module, "module_unload", &symbol)) + mod->unload = symbol; + else + mod->unload = NULL; +} + + +static void +mod_unload_completed_callback (void *data) +{ + module_info *mod = data; + + g_return_if_fail (mod->state == ST_UNLOAD_REQUESTED); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + + mod->state = ST_UNLOADED_OK; +} + +static void +mod_unload (module_info *mod, gboolean verbose) +{ + g_return_if_fail (mod->module != NULL); + g_return_if_fail (mod->unload != NULL); + + if (mod->state == ST_UNLOAD_REQUESTED) + return; + + mod->state = ST_UNLOAD_REQUESTED; + + /* send the unload request */ + mod->unload (mod->info->shutdown_data, mod_unload_completed_callback, mod); +} + + + +#ifdef DUMP_DB +static void +print_module_info (gpointer data, gpointer user_data) +{ + module_info *i = data; + + printf ("\n%s: %s\n", + i->fullpath, statename[i->state]); + printf (" module:%p lasterr:%s init:%p unload:%p\n", + i->module, i->last_module_error? i->last_module_error : "NONE", + i->init, i->unload); + if (i->info) + { + printf (" shutdown_data: %p\n" + " purpose: %s\n" + " author: %s\n" + " version: %s\n" + " copyright: %s\n" + " date: %s\n", + i->info->shutdown_data, + i->info->purpose, i->info->author, i->info->version, + i->info->copyright, i->info->date); + } +} +#endif + + + +/**************************************************************/ +/* UI functions */ + +static void +browser_popdown_callback (GtkWidget *w, gpointer client_data) +{ + gtk_widget_destroy (GTK_WIDGET (client_data)); +} + + +static void +browser_info_update (browser_st *st, module_info *mod) +{ + int i; + const char *text[NUM_INFO_LINES]; + + if (mod->info) + { + text[0] = mod->info->purpose; + text[1] = mod->info->author; + text[2] = mod->info->version; + text[3] = mod->info->copyright; + text[4] = mod->info->date; + } + else + { + text[0] = "--"; + text[1] = "--"; + text[2] = "--"; + text[3] = "--"; + text[4] = "--"; + } + + if (mod->state == ST_MODULE_ERROR && mod->last_module_error) + { + text[5] = g_malloc (strlen (statename[mod->state]) + 2 + + strlen (mod->last_module_error) + 2); + sprintf(text[5], "%s (%s)", statename[mod->state], mod->last_module_error); + } + else + { + text[5] = g_strdup (statename[mod->state]); + } + + for (i=0; i < NUM_INFO_LINES; i++) + { + if (st->label[i]) + gtk_container_remove (GTK_CONTAINER (st->table), st->label[i]); + st->label[i] = gtk_label_new (text[i]); + gtk_misc_set_alignment (GTK_MISC (st->label[i]), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (st->table), st->label[i], 1, 2, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (st->label[i]); + } + + g_free (text[5]); + + /* work out what the button should do (if anything) */ + switch (mod->state) { + case ST_MODULE_ERROR: + case ST_LOAD_FAILED: + case ST_UNLOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Load")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), TRUE); + break; + + case ST_UNLOAD_REQUESTED: + gtk_widget_set_sensitive (GTK_WIDGET (st->button), FALSE); + break; + + case ST_LOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Unload")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), + mod->unload? TRUE : FALSE); + break; + } +} + +static void +browser_info_init (GtkWidget *table) +{ + GtkWidget *label; + int i; + char *text[] = { + N_("Purpose: "), + N_("Author: "), + N_("Verson: "), + N_("Copyright: "), + N_("Date: "), + N_("State: ") + }; + + for (i=0; i < sizeof(text) / sizeof(char *); i++) + { + label = gtk_label_new (gettext (text[i])); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (label); + } +} + +static void +browser_select_callback (GtkWidget *widget, GtkWidget *child) +{ + module_info *i; + browser_st *st; + + i = gtk_object_get_user_data (GTK_OBJECT (child)); + st = gtk_object_get_user_data (GTK_OBJECT (widget)); + + if (st->last_update == i) + return; + + st->last_update = i; + + browser_info_update (st, i); +} + + +static void +browser_load_unload_callback (GtkWidget *widget, gpointer data) +{ + browser_st *st = data; + + if (st->last_update->state == ST_LOADED_OK) + mod_unload (st->last_update, FALSE); + else + mod_load (st->last_update, FALSE); + + browser_info_update (st, st->last_update); +} diff --git a/app/gui/module-browser.h b/app/gui/module-browser.h new file mode 100644 index 0000000000..c8d4a1dbe1 --- /dev/null +++ b/app/gui/module-browser.h @@ -0,0 +1,29 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.h (C) 1999 Austin Donnelly + * + * 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 __MODULE_DB_H__ + +/* Load any modules we find on the module-path set in the gimprc */ +void module_db_init (void); + +GtkWidget *module_db_browser_new (void); + + +#endif /* __MODULE_DB_H__ */ diff --git a/app/gui/plug-in-commands.c b/app/gui/plug-in-commands.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/gui/plug-in-commands.c +++ b/app/gui/plug-in-commands.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/gui/plug-in-menus.c b/app/gui/plug-in-menus.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/gui/plug-in-menus.c +++ b/app/gui/plug-in-menus.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/menus.c b/app/menus.c index 0075cfd210..5abfe7e3b2 100644 --- a/app/menus.c +++ b/app/menus.c @@ -62,6 +62,7 @@ static const GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Device Status..."), NULL, dialogs_device_status_cmd_callback, 0 }, { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, + { N_("/File/Dialogs/Module Browser..."), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, }; static guint n_toolbox_entries = sizeof (toolbox_entries) / sizeof (toolbox_entries[0]); @@ -148,7 +149,6 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Image/Resize"), NULL, image_resize_cmd_callback, 0 }, { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Image/---"), NULL, NULL, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, { N_("/Layers/Raise Layer"), "F", layers_raise_cmd_callback, 0 }, @@ -191,7 +191,11 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, */ - { N_("/Filters/"), NULL, NULL, 0 }, + { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, + { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, + { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, + { N_("/Tools/---"), NULL, NULL, 0, "" }, + { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, @@ -297,7 +301,7 @@ void menus_tools_create (ToolInfo *tool_info) { GtkItemFactoryEntry entry; - + entry.path = gettext(tool_info->menu_path); entry.accelerator = tool_info->menu_accel; entry.callback = tools_select_cmd_callback; diff --git a/app/menus/menus.c b/app/menus/menus.c index 0075cfd210..5abfe7e3b2 100644 --- a/app/menus/menus.c +++ b/app/menus/menus.c @@ -62,6 +62,7 @@ static const GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Device Status..."), NULL, dialogs_device_status_cmd_callback, 0 }, { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, + { N_("/File/Dialogs/Module Browser..."), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, }; static guint n_toolbox_entries = sizeof (toolbox_entries) / sizeof (toolbox_entries[0]); @@ -148,7 +149,6 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Image/Resize"), NULL, image_resize_cmd_callback, 0 }, { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Image/---"), NULL, NULL, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, { N_("/Layers/Raise Layer"), "F", layers_raise_cmd_callback, 0 }, @@ -191,7 +191,11 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, */ - { N_("/Filters/"), NULL, NULL, 0 }, + { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, + { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, + { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, + { N_("/Tools/---"), NULL, NULL, 0, "" }, + { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, @@ -297,7 +301,7 @@ void menus_tools_create (ToolInfo *tool_info) { GtkItemFactoryEntry entry; - + entry.path = gettext(tool_info->menu_path); entry.accelerator = tool_info->menu_accel; entry.callback = tools_select_cmd_callback; diff --git a/app/menus/plug-in-menus.c b/app/menus/plug-in-menus.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/menus/plug-in-menus.c +++ b/app/menus/plug-in-menus.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/module_db.c b/app/module_db.c new file mode 100644 index 0000000000..95f8c49dd8 --- /dev/null +++ b/app/module_db.c @@ -0,0 +1,518 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.c (C) 1999 Austin Donnelly + * + * 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 +#include + +#include "appenv.h" +#include "module_db.h" +#include "gimprc.h" +#include "datafiles.h" +#include "actionarea.h" +#include "libgimp/gimpintl.h" + +#include "libgimp/gimpmodule.h" + + +typedef enum { + ST_MODULE_ERROR, /* missing module_load function or other error */ + ST_LOADED_OK, /* happy and running (normal state of affairs) */ + ST_LOAD_FAILED, /* module_load returned GIMP_MODULE_UNLOAD */ + ST_UNLOAD_REQUESTED, /* sent unload request, waiting for callback */ + ST_UNLOADED_OK /* callback arrived, module not in memory anymore */ +} module_state; + +static const char * const statename[] = { + "ST_MODULE_ERROR", + "ST_LOADED_OK", + "ST_LOAD_FAILED", + "ST_UNLOAD_REQUESTED", + "ST_UNLOADED_OK" +}; + + +/* one of these is kept per-module */ +typedef struct { + gchar *fullpath; /* path to the module */ + module_state state; /* what's happened to the module */ + /* stuff from now on may be NULL depending on the state the module is in */ + GimpModuleInfo *info; /* returned values from module_init */ + GModule *module; /* handle on the module */ + gchar *last_module_error; + GimpModuleInitFunc *init; + GimpModuleUnloadFunc *unload; +} module_info; + +#define NUM_INFO_LINES 6 + +typedef struct { + GtkWidget *table; + GtkWidget *label[NUM_INFO_LINES]; + GtkWidget *button_label; + module_info *last_update; + GtkWidget *button; +} browser_st; + +/* global list of module_info */ +static GSList *modules = NULL; + + +/*#define DUMP_DB*/ + + +/* prototypes */ +static void module_initialize (char *filename); +static void mod_load (module_info *mod, gboolean verbose); +static void mod_unload (module_info *mod, gboolean verbose); +#ifdef DUMP_DB +static void print_module_info (gpointer data, gpointer user_data); +#endif + +static void browser_popdown_callback (GtkWidget *w, gpointer client_data); +static void browser_info_update (browser_st *st, module_info *mod); +static void browser_info_init (GtkWidget *table); +static void browser_select_callback (GtkWidget *widget, GtkWidget *child); +static void browser_load_unload_callback (GtkWidget *widget, gpointer data); + + +/**************************************************************/ +/* Exported functions */ + +void +module_db_init (void) +{ + /* Load and initialize gimp modules */ + + if (g_module_supported ()) + datafiles_read_directories (module_path, + module_initialize, 0 /* no flags */); + +#ifdef DUMP_DB + g_slist_foreach (modules, print_module_info, NULL); +#endif +} + + +GtkWidget * +module_db_browser_new (void) +{ + GtkWidget *shell; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *listbox; + GtkWidget *list; + GtkWidget *list_item; + GSList *here; + module_info *info; + browser_st *st; + ActionAreaItem action_items[] = + { + { N_("OK"), browser_popdown_callback, NULL, NULL } + }; + + + shell = gtk_dialog_new (); + gtk_window_set_wmclass (GTK_WINDOW (shell), "module_db_dialog", "Gimp"); + gtk_window_set_title (GTK_WINDOW (shell), _("Module DB")); + + hbox = gtk_hbox_new (FALSE, 5); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 1); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (shell)->vbox), hbox, TRUE, TRUE, 0); + gtk_widget_show (hbox); + + listbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (hbox), listbox, TRUE, TRUE, 0); + gtk_widget_set_usize (listbox, 125, 100); + gtk_widget_show (listbox); + + list = gtk_list_new (); + gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (listbox), list); + + st = g_new0 (browser_st, 1); + + here = modules; + while (here) + { + info = here->data; + here = g_slist_next (here); + + if (!st->last_update) + st->last_update = info; + + list_item = gtk_list_item_new_with_label (info->fullpath); + gtk_container_add (GTK_CONTAINER (list), list_item); + gtk_widget_show (list_item); + gtk_object_set_user_data (GTK_OBJECT (list_item), info); + } + + gtk_widget_show (list); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + st->table = gtk_table_new (2, NUM_INFO_LINES, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), st->table, TRUE, TRUE, 0); + gtk_widget_show (st->table); + + st->button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox), st->button, TRUE, TRUE, 0); + gtk_widget_show (st->button); + gtk_signal_connect (GTK_OBJECT (st->button), "clicked", + browser_load_unload_callback, st); + + browser_info_init (st->table); + browser_info_update (st, modules->data); + + gtk_object_set_user_data (GTK_OBJECT (list), st); + + gtk_signal_connect (GTK_OBJECT (list), "select_child", + browser_select_callback, NULL); + + action_items[0].user_data = shell; + build_action_area (GTK_DIALOG (shell), + action_items, + sizeof( action_items)/sizeof( ActionAreaItem), + 0); + + return shell; +} + + +/**************************************************************/ +/* helper functions */ + + +/* name must be of the form lib*.so */ +/* TODO: need support for WIN32-style dll names. Maybe this function + * should live in libgmodule? */ +static gboolean +valid_module_name (const char *filename) +{ + const char *basename; + int len; + + basename = strrchr (filename, '/'); + if (basename) + basename++; + else + basename = filename; + + len = strlen (basename); + + if (len < 3 + 1 + 3) + return FALSE; + + if (strncmp (basename, "lib", 3)) + return FALSE; + + if (strcmp (basename + len - 3, ".so")) + return FALSE; + + return TRUE; +} + + + +static void +module_initialize (char *filename) +{ + module_info *mod; + + if (!valid_module_name (filename)) + return; + + mod = g_new0 (module_info, 1); + modules = g_slist_append (modules, mod); + + mod->fullpath = g_strdup (filename); + + if ((be_verbose == TRUE) || (no_splash == TRUE)) + g_print (_("load module: \"%s\"\n"), filename); + + mod_load (mod, TRUE); +} + +static void +mod_load (module_info *mod, gboolean verbose) +{ + gpointer symbol; + + g_return_if_fail (mod->module == NULL); + + mod->module = g_module_open (mod->fullpath, G_MODULE_BIND_LAZY); + if (!mod->module) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (g_module_error ()); + + if (verbose) + g_warning (_("module load error: %s: %s"), + mod->fullpath, mod->last_module_error); + return; + } + + /* find the module_init symbol */ + if (!g_module_symbol (mod->module, "module_init", &symbol)) + { + mod->state = ST_MODULE_ERROR; + + if (mod->last_module_error) + g_free (mod->last_module_error); + mod->last_module_error = g_strdup (_("missing module_init() symbol")); + + if (verbose) + g_warning (_("%s: module_init() symbol not found"), mod->fullpath); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* run module's initialisation */ + mod->init = symbol; + mod->info = NULL; + if (mod->init (&mod->info) == GIMP_MODULE_UNLOAD) + { + mod->state = ST_LOAD_FAILED; + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + return; + } + + /* module is now happy */ + mod->state = ST_LOADED_OK; + + /* do we have an unload function? */ + if (g_module_symbol (mod->module, "module_unload", &symbol)) + mod->unload = symbol; + else + mod->unload = NULL; +} + + +static void +mod_unload_completed_callback (void *data) +{ + module_info *mod = data; + + g_return_if_fail (mod->state == ST_UNLOAD_REQUESTED); + + g_module_close (mod->module); + mod->module = NULL; + mod->info = NULL; + + mod->state = ST_UNLOADED_OK; +} + +static void +mod_unload (module_info *mod, gboolean verbose) +{ + g_return_if_fail (mod->module != NULL); + g_return_if_fail (mod->unload != NULL); + + if (mod->state == ST_UNLOAD_REQUESTED) + return; + + mod->state = ST_UNLOAD_REQUESTED; + + /* send the unload request */ + mod->unload (mod->info->shutdown_data, mod_unload_completed_callback, mod); +} + + + +#ifdef DUMP_DB +static void +print_module_info (gpointer data, gpointer user_data) +{ + module_info *i = data; + + printf ("\n%s: %s\n", + i->fullpath, statename[i->state]); + printf (" module:%p lasterr:%s init:%p unload:%p\n", + i->module, i->last_module_error? i->last_module_error : "NONE", + i->init, i->unload); + if (i->info) + { + printf (" shutdown_data: %p\n" + " purpose: %s\n" + " author: %s\n" + " version: %s\n" + " copyright: %s\n" + " date: %s\n", + i->info->shutdown_data, + i->info->purpose, i->info->author, i->info->version, + i->info->copyright, i->info->date); + } +} +#endif + + + +/**************************************************************/ +/* UI functions */ + +static void +browser_popdown_callback (GtkWidget *w, gpointer client_data) +{ + gtk_widget_destroy (GTK_WIDGET (client_data)); +} + + +static void +browser_info_update (browser_st *st, module_info *mod) +{ + int i; + const char *text[NUM_INFO_LINES]; + + if (mod->info) + { + text[0] = mod->info->purpose; + text[1] = mod->info->author; + text[2] = mod->info->version; + text[3] = mod->info->copyright; + text[4] = mod->info->date; + } + else + { + text[0] = "--"; + text[1] = "--"; + text[2] = "--"; + text[3] = "--"; + text[4] = "--"; + } + + if (mod->state == ST_MODULE_ERROR && mod->last_module_error) + { + text[5] = g_malloc (strlen (statename[mod->state]) + 2 + + strlen (mod->last_module_error) + 2); + sprintf(text[5], "%s (%s)", statename[mod->state], mod->last_module_error); + } + else + { + text[5] = g_strdup (statename[mod->state]); + } + + for (i=0; i < NUM_INFO_LINES; i++) + { + if (st->label[i]) + gtk_container_remove (GTK_CONTAINER (st->table), st->label[i]); + st->label[i] = gtk_label_new (text[i]); + gtk_misc_set_alignment (GTK_MISC (st->label[i]), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (st->table), st->label[i], 1, 2, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (st->label[i]); + } + + g_free (text[5]); + + /* work out what the button should do (if anything) */ + switch (mod->state) { + case ST_MODULE_ERROR: + case ST_LOAD_FAILED: + case ST_UNLOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Load")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), TRUE); + break; + + case ST_UNLOAD_REQUESTED: + gtk_widget_set_sensitive (GTK_WIDGET (st->button), FALSE); + break; + + case ST_LOADED_OK: + if (st->button_label) + gtk_container_remove (GTK_CONTAINER (st->button), st->button_label); + st->button_label = gtk_label_new (_("Unload")); + gtk_widget_show (st->button_label); + gtk_container_add (GTK_CONTAINER (st->button), st->button_label); + gtk_widget_set_sensitive (GTK_WIDGET (st->button), + mod->unload? TRUE : FALSE); + break; + } +} + +static void +browser_info_init (GtkWidget *table) +{ + GtkWidget *label; + int i; + char *text[] = { + N_("Purpose: "), + N_("Author: "), + N_("Verson: "), + N_("Copyright: "), + N_("Date: "), + N_("State: ") + }; + + for (i=0; i < sizeof(text) / sizeof(char *); i++) + { + label = gtk_label_new (gettext (text[i])); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i+1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 2); + gtk_widget_show (label); + } +} + +static void +browser_select_callback (GtkWidget *widget, GtkWidget *child) +{ + module_info *i; + browser_st *st; + + i = gtk_object_get_user_data (GTK_OBJECT (child)); + st = gtk_object_get_user_data (GTK_OBJECT (widget)); + + if (st->last_update == i) + return; + + st->last_update = i; + + browser_info_update (st, i); +} + + +static void +browser_load_unload_callback (GtkWidget *widget, gpointer data) +{ + browser_st *st = data; + + if (st->last_update->state == ST_LOADED_OK) + mod_unload (st->last_update, FALSE); + else + mod_load (st->last_update, FALSE); + + browser_info_update (st, st->last_update); +} diff --git a/app/module_db.h b/app/module_db.h new file mode 100644 index 0000000000..c8d4a1dbe1 --- /dev/null +++ b/app/module_db.h @@ -0,0 +1,29 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * module_db.h (C) 1999 Austin Donnelly + * + * 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 __MODULE_DB_H__ + +/* Load any modules we find on the module-path set in the gimprc */ +void module_db_init (void); + +GtkWidget *module_db_browser_new (void); + + +#endif /* __MODULE_DB_H__ */ diff --git a/app/plug-in/gimpplugin-message.c b/app/plug-in/gimpplugin-message.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimpplugin-message.c +++ b/app/plug-in/gimpplugin-message.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimpplugin-progress.c b/app/plug-in/gimpplugin-progress.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimpplugin-progress.c +++ b/app/plug-in/gimpplugin-progress.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimpplugin.c b/app/plug-in/gimpplugin.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimpplugin.c +++ b/app/plug-in/gimpplugin.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimppluginmanager-call.c b/app/plug-in/gimppluginmanager-call.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimppluginmanager-call.c +++ b/app/plug-in/gimppluginmanager-call.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimppluginmanager-run.c b/app/plug-in/gimppluginmanager-run.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimppluginmanager-run.c +++ b/app/plug-in/gimppluginmanager-run.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimppluginmanager.c b/app/plug-in/gimppluginmanager.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimppluginmanager.c +++ b/app/plug-in/gimppluginmanager.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/gimppluginshm.c b/app/plug-in/gimppluginshm.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/gimppluginshm.c +++ b/app/plug-in/gimppluginshm.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-def.c b/app/plug-in/plug-in-def.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-def.c +++ b/app/plug-in/plug-in-def.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-message.c b/app/plug-in/plug-in-message.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-message.c +++ b/app/plug-in/plug-in-message.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-params.c b/app/plug-in/plug-in-params.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-params.c +++ b/app/plug-in/plug-in-params.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-progress.c b/app/plug-in/plug-in-progress.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-progress.c +++ b/app/plug-in/plug-in-progress.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-run.c b/app/plug-in/plug-in-run.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-run.c +++ b/app/plug-in/plug-in-run.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in-shm.c b/app/plug-in/plug-in-shm.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in-shm.c +++ b/app/plug-in/plug-in-shm.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-in.c b/app/plug-in/plug-in.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-in.c +++ b/app/plug-in/plug-in.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug-in/plug-ins.c b/app/plug-in/plug-ins.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug-in/plug-ins.c +++ b/app/plug-in/plug-ins.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/plug_in.c b/app/plug_in.c index 8a5482c0e0..381c7e26d9 100644 --- a/app/plug_in.c +++ b/app/plug_in.c @@ -30,7 +30,6 @@ #include #include "libgimp/parasite.h" #include "libgimp/parasiteP.h" /* ick */ -#include "libgimp/gimpmodule.h" #ifdef HAVE_IPC_H #include @@ -137,7 +136,6 @@ static Argument* message_handler_set_invoker (Argument *args); static Argument* plugin_temp_PDB_name_invoker (Argument *args); -static void module_initialize (char *filename); static GSList *plug_in_defs = NULL; @@ -484,76 +482,9 @@ plug_in_init () g_slist_free (plug_in_defs); - /* Load and initialize gimp modules */ - - if (g_module_supported ()) - datafiles_read_directories (module_path, - module_initialize, 0 /* no flags */); } -/* name must be of the form lib*.so */ -/* TODO: need support for WIN32-style dll names. Maybe this function - * should live in libgmodule? */ -static gboolean -valid_module_name (const char *filename) -{ - const char *basename; - int len; - - basename = strrchr (filename, '/'); - if (basename) - basename++; - else - basename = filename; - - len = strlen (basename); - - if (len < 3 + 1 + 3) - return FALSE; - - if (strncmp (basename, "lib", 3)) - return FALSE; - - if (strcmp (basename + len - 3, ".so")) - return FALSE; - - return TRUE; -} - -static void -module_initialize (char *filename) -{ - GModule *mod; - GimpModuleInitFunc init; - gpointer symbol; - - if (!valid_module_name (filename)) - return; - - if ((be_verbose == TRUE) || (no_splash == TRUE)) - g_print (_("load module: \"%s\"\n"), filename); - - mod = g_module_open (filename, G_MODULE_BIND_LAZY); - if (!mod) - { - g_warning (_("module load error: %s: %s"), filename, g_module_error ()); - return; - } - - if (g_module_symbol (mod, "module_init", &symbol)) - { - init = symbol; - if (init () == GIMP_MODULE_UNLOAD) - g_module_close (mod); - } - else - { - g_warning (_("%s: module_init() symbol not found"), filename); - g_module_close (mod); - } -} - void plug_in_kill () diff --git a/app/widgets/gimpcolordialog.c b/app/widgets/gimpcolordialog.c index 438e92d989..7ee36087ee 100644 --- a/app/widgets/gimpcolordialog.c +++ b/app/widgets/gimpcolordialog.c @@ -147,6 +147,8 @@ color_notebook_new (int r, { label = gtk_label_new (info->name); gtk_widget_show (label); + /* hide the frame, so it doesn't get selected by mistake */ + gtk_widget_hide (csel->frame); gtk_notebook_append_page (GTK_NOTEBOOK (cnp->notebook), csel->frame, label); } diff --git a/app/widgets/gimpitemfactory.c b/app/widgets/gimpitemfactory.c index 0075cfd210..5abfe7e3b2 100644 --- a/app/widgets/gimpitemfactory.c +++ b/app/widgets/gimpitemfactory.c @@ -62,6 +62,7 @@ static const GtkItemFactoryEntry toolbox_entries[] = { N_("/File/Dialogs/Device Status..."), NULL, dialogs_device_status_cmd_callback, 0 }, { N_("/File/Dialogs/Document Index..."), NULL, raise_idea_callback, 0 }, { N_("/File/Dialogs/Error Console..."), NULL, dialogs_error_console_cmd_callback, 0 }, + { N_("/File/Dialogs/Module Browser..."), NULL, dialogs_module_browser_cmd_callback, 0 }, { N_("/File/---"), NULL, NULL, 0, "" }, }; static guint n_toolbox_entries = sizeof (toolbox_entries) / sizeof (toolbox_entries[0]); @@ -148,7 +149,6 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Image/Resize"), NULL, image_resize_cmd_callback, 0 }, { N_("/Image/Scale"), NULL, image_scale_cmd_callback, 0 }, { N_("/Image/---"), NULL, NULL, 0, "" }, - { N_("/Image/---"), NULL, NULL, 0, "" }, { N_("/Layers/Layers & Channels..."), "L", dialogs_lc_cmd_callback, 0 }, { N_("/Layers/Raise Layer"), "F", layers_raise_cmd_callback, 0 }, @@ -191,7 +191,11 @@ static const GtkItemFactoryEntry image_entries[] = { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, */ - { N_("/Filters/"), NULL, NULL, 0 }, + { N_("/Tools/Toolbox"), NULL, toolbox_raise_callback, 0 }, + { N_("/Tools/Default Colors"), "D", tools_default_colors_cmd_callback, 0 }, + { N_("/Tools/Swap Colors"), "X", tools_swap_colors_cmd_callback, 0 }, + { N_("/Tools/---"), NULL, NULL, 0, "" }, + { N_("/Filters/Repeat last"), "F", filters_repeat_cmd_callback, 0x0 }, { N_("/Filters/Re-show last"), "F", filters_repeat_cmd_callback, 0x1 }, { N_("/Filters/---"), NULL, NULL, 0, "" }, @@ -297,7 +301,7 @@ void menus_tools_create (ToolInfo *tool_info) { GtkItemFactoryEntry entry; - + entry.path = gettext(tool_info->menu_path); entry.accelerator = tool_info->menu_accel; entry.callback = tools_select_cmd_callback; diff --git a/libgimp/gimpmodule.h b/libgimp/gimpmodule.h index 685083c445..a5736c51d3 100644 --- a/libgimp/gimpmodule.h +++ b/libgimp/gimpmodule.h @@ -30,15 +30,54 @@ typedef enum { } GimpModuleStatus; + +typedef struct { + void *shutdown_data; + const char *purpose; + const char *author; + const char *version; + const char *copyright; + const char *date; +} GimpModuleInfo; + + + /* GIMP modules should G_MODULE_EXPORT a function named "module_init" * of the following type: */ -typedef GimpModuleStatus (*GimpModuleInitFunc) (void); +typedef GimpModuleStatus (GimpModuleInitFunc) (GimpModuleInfo **); + +GimpModuleInitFunc module_init; /* This function is called by the GIMP at startup, and should return * either GIMP_MODULE_OK if it sucessfully initialised or * GIMP_MODULE_UNLOAD if the module failed to hook whatever functions * it wanted. GIMP_MODULE_UNLOAD causes the module to be closed, so * the module must not have registered any internal functions or given - * out pointers to its data to anyone. */ + * out pointers to its data to anyone. + * + * If the module returns GIMP_MODULE_OK, it should also return a + * GimpModuleInfo structure describing itself. + */ + + +/* If GIMP modules want to allow themselves to be unloaded, they + * should G_MODULE_EXPORT a function named "module_unload" with the + * following type: */ +typedef void (GimpModuleUnloadFunc) (void *shutdown_data, + void (*completed_cb)(void *), + void *completed_data); + +GimpModuleUnloadFunc module_unload; + +/* GIMP calls this unload request function to ask a module to + * prepare itself to be unloaded. It is called with the value of + * shutdown_data supplied in the GimpModuleInfo struct. The module + * should ensure that none of its code or data are being used, and + * then call the supplied "completed_cb" callback function with the + * data provided. Typically the shutdown request function will queue + * de-registration activities then return. Only when the + * de-registration has finished should the completed_cb be invoked. */ + + #endif /* __GIMPMODULE_H__ */ diff --git a/modules/Makefile.am b/modules/Makefile.am index b1d014465b..d48a67f19f 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -8,7 +8,9 @@ INCLUDES = \ $(GTK_CFLAGS) \ -I$(includedir) -module_LTLIBRARIES = libcolorsel_gtk.la +module_LTLIBRARIES = libcolorsel_gtk.la libcolorsel_triangle.la libcolorsel_gtk_la_SOURCES = colorsel_gtk.c +libcolorsel_triangle_la_SOURCES = colorsel_triangle.c + diff --git a/modules/colorsel_gtk.c b/modules/colorsel_gtk.c index 6e174842eb..86398a1fdc 100644 --- a/modules/colorsel_gtk.c +++ b/modules/colorsel_gtk.c @@ -40,18 +40,47 @@ static GimpColorSelectorMethods methods = colorsel_gtk_setcolor }; +static GimpModuleInfo info = { + NULL, + "GTK colour selector as a pluggable colour selector", + "Austin Donnelly ", + "v0.02", + "(c) 1999, released under the GPL", + "17 Jan 1999" +}; + /* globaly exported init function */ G_MODULE_EXPORT GimpModuleStatus -module_init (void) +module_init (GimpModuleInfo **inforet) { - if (gimp_color_selector_register ("GTK", &methods)) + GimpColorSelectorID id; + + id = gimp_color_selector_register ("GTK", &methods); + + if (id) + { + info.shutdown_data = id; + *inforet = &info; return GIMP_MODULE_OK; + } else + { return GIMP_MODULE_UNLOAD; + } } +G_MODULE_EXPORT void +module_unload (void *shutdown_data, + void (*completed_cb)(void *), + void *completed_data) +{ + gimp_color_selector_unregister (shutdown_data, completed_cb, completed_data); +} + + + /**************************************************************/ /* GTK colour selector methods */ diff --git a/modules/colorsel_triangle.c b/modules/colorsel_triangle.c new file mode 100644 index 0000000000..b1d5840569 --- /dev/null +++ b/modules/colorsel_triangle.c @@ -0,0 +1,665 @@ +/* + * colorsel_triangle module (C) 1999 Simon Budig + * http://www.home.unix-ag.org/simon/gimp/colorsel.html + * + * 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. + * + * Ported to loadable colour selector interface by Austin Donnelly + * + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* prototypes */ +static GtkWidget * colorsel_triangle_new (int, int, int, + GimpColorSelector_Callback, void *, + void **); +static void colorsel_triangle_free (void *); +static void colorsel_triangle_setcolor (void *, int, int, int, int); + + + +/* local methods */ +static GimpColorSelectorMethods methods = +{ + colorsel_triangle_new, + colorsel_triangle_free, + colorsel_triangle_setcolor +}; + + +static GimpModuleInfo info = { + NULL /* no shutdown data needed */, + "Painter-style colour selector as a pluggable colour selector", + "Simon Budig ", + "v0.01", + "(c) 1999, released under the GPL", + "17 Jan 1999" +}; + + + +#define COLORWHEELRADIUS 100 +#define COLORTRIANGLERADIUS 80 +#define PREVIEWSIZE (2*COLORWHEELRADIUS+1) +#define INTENSITY(r,g,b) (r * 0.30 + g * 0.59 + b * 0.11 + 0.001) + +#define BGCOLOR 180 + +#define PREVIEW_MASK GDK_EXPOSURE_MASK | \ + GDK_BUTTON_PRESS_MASK | \ + GDK_BUTTON_RELEASE_MASK | \ + GDK_BUTTON_MOTION_MASK + +typedef enum { + HUE = 0, + SATURATION, + VALUE, + RED, + GREEN, + BLUE, + HUE_SATURATION, + HUE_VALUE, + SATURATION_VALUE, + RED_GREEN, + RED_BLUE, + GREEN_BLUE +} ColorSelectFillType; + +typedef struct _ColorSelect _ColorSelect, *ColorSelectP; + +struct _ColorSelect { + gint values[6]; + gfloat oldsat; + gfloat oldval; + gint mode; + GtkWidget *preview; + GimpColorSelector_Callback callback; + void *data; +}; + + +static GtkWidget * create_color_preview (ColorSelectP); +static void color_select_update_rgb_values (ColorSelectP); +static void update_color_preview (ColorSelectP, GtkWidget *, gint); +static void color_select_update_hsv_values (ColorSelectP); + + +/*************************************************************/ + +/* globaly exported init function */ +G_MODULE_EXPORT GimpModuleStatus +module_init (GimpModuleInfo **inforet) +{ + if (gimp_color_selector_register ("Triangle", &methods)) + { + *inforet = &info; + return GIMP_MODULE_OK; + } + else + { + return GIMP_MODULE_UNLOAD; + } +} + + +/*************************************************************/ +/* methods */ + +static GtkWidget * colorsel_triangle_new (int r, int g, int b, + GimpColorSelector_Callback callback, + void *callback_data, + /* RETURNS: */ + void **selector_data) +{ + ColorSelectP coldata; + GtkWidget *frame; + + coldata = g_malloc (sizeof (_ColorSelect)); + coldata->values[RED] = r; + coldata->values[GREEN] = g; + coldata->values[BLUE] = b; + color_select_update_hsv_values(coldata); + + coldata->oldsat = 0; + coldata->oldval = 0; + + coldata->mode = 0; + + coldata->callback = callback; + coldata->data = callback_data; + + /* gtk_rc_parse ("colorselrc"); */ + + frame = create_color_preview (coldata); + coldata->preview = frame; + + *selector_data = coldata; + return frame; +} + + +static void +colorsel_triangle_free (void *selector_data) +{ + /* anything else needed to go? */ + g_free (selector_data); +} + + +static void +colorsel_triangle_setcolor (void *selector_data, int r, int g, int b, + int set_current) +{ + ColorSelectP coldata; + + coldata = selector_data; + + coldata->values[RED] = r; + coldata->values[GREEN] = g; + coldata->values[BLUE] = b; + color_select_update_hsv_values(coldata); + update_color_preview(coldata, coldata->preview, 1); +} + + + + +/*************************************************************/ +/* helper functions */ + + +/* Conversion hsv->rgb */ + +static void color_hsv_to_rgb (gfloat hue, gfloat sat, gfloat val, guchar* red, guchar *green, guchar *blue) { + gfloat f, p, q, t; + + if (sat == 0) { + *red = val * 255; + *green = val * 255; + *blue = val * 255; + } else { + while (hue < 0) + hue += 360; + while (hue >= 360) + hue -= 360; + + hue /= 60; + f = hue - (int) hue; + p = val * (1 - sat); + q = val * (1 - (sat * f)); + t = val * (1 - (sat * (1 - f))); + + switch ((int) hue) { + case 0: + *red = val * 255; + *green = t * 255; + *blue = p * 255; + break; + case 1: + *red = q * 255; + *green = val * 255; + *blue = p * 255; + break; + case 2: + *red = p * 255; + *green = val * 255; + *blue = t * 255; + break; + case 3: + *red = p * 255; + *green = q * 255; + *blue = val * 255; + break; + case 4: + *red = t * 255; + *green = p * 255; + *blue = val * 255; + break; + case 5: + *red = val * 255; + *green = p * 255; + *blue = q * 255; + break; + default: + break; + } + } +} + + +static void color_select_update_rgb_values (ColorSelectP csp) { + gfloat h, s, v; + gfloat f, p, q, t; + + if (csp) + { + h = csp->values[HUE]; + s = csp->values[SATURATION] / 100.0; + v = csp->values[VALUE] / 100.0; + + if (s == 0) + { + csp->values[RED] = v * 255; + csp->values[GREEN] = v * 255; + csp->values[BLUE] = v * 255; + } + else + { + if (h == 360) + h = 0; + + h /= 60; + f = h - (int) h; + p = v * (1 - s); + q = v * (1 - (s * f)); + t = v * (1 - (s * (1 - f))); + + switch ((int) h) + { + case 0: + csp->values[RED] = v * 255; + csp->values[GREEN] = t * 255; + csp->values[BLUE] = p * 255; + break; + case 1: + csp->values[RED] = q * 255; + csp->values[GREEN] = v * 255; + csp->values[BLUE] = p * 255; + break; + case 2: + csp->values[RED] = p * 255; + csp->values[GREEN] = v * 255; + csp->values[BLUE] = t * 255; + break; + case 3: + csp->values[RED] = p * 255; + csp->values[GREEN] = q * 255; + csp->values[BLUE] = v * 255; + break; + case 4: + csp->values[RED] = t * 255; + csp->values[GREEN] = p * 255; + csp->values[BLUE] = v * 255; + break; + case 5: + csp->values[RED] = v * 255; + csp->values[GREEN] = p * 255; + csp->values[BLUE] = q * 255; + break; + } + } + } +} + +static void +color_select_update_hsv_values (ColorSelectP csp) +{ + int r, g, b; + float h, s, v; + int min, max; + int delta; + + if (csp) + { + r = csp->values[RED]; + g = csp->values[GREEN]; + b = csp->values[BLUE]; + + if (r > g) + { + if (r > b) + max = r; + else + max = b; + + if (g < b) + min = g; + else + min = b; + } + else + { + if (g > b) + max = g; + else + max = b; + + if (r < b) + min = r; + else + min = b; + } + + v = max; + + if (max != 0) + s = (max - min) / (float) max; + else + s = 0; + + if (s == 0) + h = 0; + else + { + h = 0; + delta = max - min; + if (r == max) + h = (g - b) / (float) delta; + else if (g == max) + h = 2 + (b - r) / (float) delta; + else if (b == max) + h = 4 + (r - g) / (float) delta; + h *= 60; + + if (h < 0) + h += 360; + } + + csp->values[HUE] = h; + csp->values[SATURATION] = s * 100; + csp->values[VALUE] = v * 100 / 255; + } +} + + + +static void update_color_preview (ColorSelectP coldata, + GtkWidget *preview, gint hue_changed) { + guchar buf[3*PREVIEWSIZE]; + gint x, y, k, r2, dx, col; + gint x0, y0; + gfloat hue, sat, val, s, v; + gint hx,hy, sx,sy, vx,vy; + + hue = (float) coldata->values[HUE] * M_PI / 180; + + hx = sin(hue) * COLORTRIANGLERADIUS; + hy = cos(hue) * COLORTRIANGLERADIUS; + + sx = sin(hue - 2*M_PI/3) * COLORTRIANGLERADIUS; + sy = cos(hue - 2*M_PI/3) * COLORTRIANGLERADIUS; + + vx = sin(hue + 2*M_PI/3) * COLORTRIANGLERADIUS; + vy = cos(hue + 2*M_PI/3) * COLORTRIANGLERADIUS; + + hue = (float) coldata->values[HUE]; + + if (hue_changed) { + for (y = COLORWHEELRADIUS; y > -COLORWHEELRADIUS; y--) { + dx = (int) sqrt((float) abs((COLORWHEELRADIUS)*(COLORWHEELRADIUS)-y*y)); + for (x = -dx, k=0; x <= dx; x++) { + buf[k]=buf[k+1]=buf[k+2]=BGCOLOR; + r2 = (x*x)+(y*y); + if ( r2 <= COLORWHEELRADIUS * COLORWHEELRADIUS) { + if (r2 > COLORTRIANGLERADIUS * COLORTRIANGLERADIUS) { + color_hsv_to_rgb (atan2 (x,y) / M_PI * 180, 1, 1, &buf[k], &buf[k+1], &buf[k+2]); + } else { + val = (float) ((x-sx)*(hy-vy)-(y-sy)*(hx-vx)) / (float) ((vx-sx)*(hy-vy)-(vy-sy)*(hx-vx)); + if (val>0 && val<=1) { // eigentlich val>=0, aber dann Grafikfehler... + sat = (val==0?0: ((float) (y-sy-val*(vy-sy)) / (val * (float) (hy-vy)))); + if (sat >= 0 && sat <= 1) + color_hsv_to_rgb (hue, sat, val, &buf[k], &buf[k+1], &buf[k+2]); + } + } + } + k += 3; + } + /* gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, COLORWHEELRADIUS - y - 1, PREVIEWSIZE); */ + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, COLORWHEELRADIUS - dx, COLORWHEELRADIUS - y - 1, 2*dx+1); + } + + // Marker im aeusseren Ring + + x0 = (gint) (sin(hue*M_PI/180) * ((float) (COLORWHEELRADIUS - COLORTRIANGLERADIUS + 1)/2 + COLORTRIANGLERADIUS) + 0.5); + y0 = (gint) (cos(hue*M_PI/180) * ((float) (COLORWHEELRADIUS - COLORTRIANGLERADIUS + 1)/2 + COLORTRIANGLERADIUS) + 0.5); + color_hsv_to_rgb (atan2 (x0,y0) / M_PI * 180, 1, 1, &buf[0], &buf[1], &buf[2]); + col = INTENSITY(buf[0], buf[1], buf[2]) > 127 ? 0 : 255 ; + + for (y = y0 - 4 ; y <= y0 + 4 ; y++) { + for (x = x0 - 4, k=0 ; x <= x0 + 4 ; x++) { + r2 = (x-x0)*(x-x0)+(y-y0)*(y-y0); + if (r2 <= 20 && r2 >= 6) + buf[k]=buf[k+1]=buf[k+2]=col; + else + color_hsv_to_rgb (atan2 (x,y) / M_PI * 180, 1, 1, &buf[k], &buf[k+1], &buf[k+2]); + k += 3; + } + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, COLORWHEELRADIUS + x0-4, COLORWHEELRADIUS - 1 - y, 9); + } + + + } else { + // Marker im Dreieck loeschen + + s = coldata->oldsat; + v = coldata->oldval; + x0 = (gint) (sx + (vx - sx)*v + (hx - vx) * s * v); + y0 = (gint) (sy + (vy - sy)*v + (hy - vy) * s * v); + for (y = y0 - 4 ; y <= y0 + 4 ; y++) { + for (x = x0 - 4, k=0 ; x <= x0 + 4 ; x++) { + buf[k]=buf[k+1]=buf[k+2]=BGCOLOR; + r2 = (x-x0)*(x-x0)+(y-y0)*(y-y0); + if (x*x+y*y > COLORTRIANGLERADIUS * COLORTRIANGLERADIUS) { + color_hsv_to_rgb (atan2 (x,y) / M_PI * 180, 1, 1, &buf[k], &buf[k+1], &buf[k+2]); + } else { + val = (float) ((x-sx)*(hy-vy)-(y-sy)*(hx-vx)) / (float) ((vx-sx)*(hy-vy)-(vy-sy)*(hx-vx)); + if (val>0 && val<=1) { // eigentlich val>=0, aber dann Grafikfehler... + sat = (val==0?0: ((float) (y-sy-val*(vy-sy)) / (val * (float) (hy-vy)))); + if (sat >= 0 && sat <= 1) + color_hsv_to_rgb (hue, sat, val, &buf[k], &buf[k+1], &buf[k+2]); + } + } + k += 3; + } + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, COLORWHEELRADIUS + x0-4, COLORWHEELRADIUS - 1 - y, 9); + } + + coldata->oldsat = coldata->values[SATURATION] / 100.0; + coldata->oldval = coldata->values[VALUE] / 100.0; + } + + // Marker im Dreieck + + col = INTENSITY(coldata->values[RED], coldata->values[GREEN], + coldata->values[BLUE]) > 127 ? 0 : 255 ; + + s = coldata->values[SATURATION] / 100.0; + v = coldata->values[VALUE] / 100.0; + coldata->oldsat=s; + coldata->oldval=v; + x0 = (gint) (sx + (vx - sx)*v + (hx - vx) * s * v); + y0 = (gint) (sy + (vy - sy)*v + (hy - vy) * s * v); + for (y = y0 - 4 ; y <= y0 + 4 ; y++) { + for (x = x0 - 4, k=0 ; x <= x0 + 4 ; x++) { + buf[k]=buf[k+1]=buf[k+2]=BGCOLOR; + r2 = (x-x0)*(x-x0)+(y-y0)*(y-y0); + if (r2 <= 20 && r2 >= 6) + buf[k]=buf[k+1]=buf[k+2]=col; + else { + if (x*x+y*y > COLORTRIANGLERADIUS * COLORTRIANGLERADIUS) { + color_hsv_to_rgb (atan2 (x,y) / M_PI * 180, 1, 1, &buf[k], &buf[k+1], &buf[k+2]); + } else { + val = (float) ((x-sx)*(hy-vy)-(y-sy)*(hx-vx)) / (float) ((vx-sx)*(hy-vy)-(vy-sy)*(hx-vx)); + if (val>0 && val<=1) { // eigentlich val>=0, aber dann Grafikfehler... + sat = (val==0?0: ((float) (y-sy-val*(vy-sy)) / (val * (float) (hy-vy)))); + if (sat >= 0 && sat <= 1) + color_hsv_to_rgb (hue, sat, val, &buf[k], &buf[k+1], &buf[k+2]); + } + } + } + k += 3; + } + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, COLORWHEELRADIUS + x0-4, COLORWHEELRADIUS - 1 - y, 9); + } + + for (k=0; k < (PREVIEWSIZE * 3); k+=3) { + buf[k]=coldata->values[RED]; + buf[k+1]=coldata->values[GREEN]; + buf[k+2]=coldata->values[BLUE]; + } + for (y=0; y < 30; y++) { + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, y+PREVIEWSIZE, PREVIEWSIZE); + } + + gtk_widget_draw (preview, NULL); + +} + +static void +init_color_preview (GtkWidget *preview) +{ + guchar buf[3*PREVIEWSIZE]; + gint i; + for (i=0; i < 3*PREVIEWSIZE; i+=3) + buf[i]=buf[i+1]=buf[i+2]=BGCOLOR; + for (i=0; i < PREVIEWSIZE; i++) + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, PREVIEWSIZE); + gtk_widget_draw (preview, NULL); +} + +/* + * Color Preview + */ + +static gint +color_selection_callback(GtkWidget *widget, GdkEvent *event) +{ + ColorSelectP coldata; + gint x,y, mousex, mousey; + gfloat r; + gfloat hue, sat, val; + gint hx,hy, sx,sy, vx,vy; + + coldata = gtk_object_get_user_data (GTK_OBJECT (widget)); + + switch (event->type) { + case GDK_BUTTON_PRESS: + x = event->button.x - COLORWHEELRADIUS - 1; + y = - event->button.y + COLORWHEELRADIUS + 1; + r = sqrt((float) (x*x+y*y)); + if ( /* r <= COLORWHEELRADIUS && */ r > COLORTRIANGLERADIUS) + coldata->mode = 1; // Dragging in the Ring + else + coldata->mode = 2; // Dragging in the Triangle + break; + + case GDK_MOTION_NOTIFY: + x = event->motion.x - COLORWHEELRADIUS - 1; + y = - event->motion.y + COLORWHEELRADIUS + 1; + break; + + case GDK_BUTTON_RELEASE: + coldata->mode = 0; + break; + + default: + gtk_widget_get_pointer(widget, &x, &y); + x = x - COLORWHEELRADIUS - 1; + y = - y + COLORWHEELRADIUS + 1; + break; + } + + gtk_widget_get_pointer(widget, &mousex, &mousey); + if ((event->type == GDK_MOTION_NOTIFY && + (mousex != event->motion.x || mousey != event->motion.y))) + return FALSE; + + if (coldata->mode == 1) { + coldata->values[HUE] = ( (int) (atan2 (x, y) / M_PI * 180) + 360 ) %360; + color_select_update_rgb_values(coldata); + update_color_preview(coldata, widget, 1); + } + if (coldata->mode == 2) { + hue = (float) coldata->values[HUE] * M_PI / 180; + hx = sin(hue) * COLORTRIANGLERADIUS; + hy = cos(hue) * COLORTRIANGLERADIUS; + sx = sin(hue - 2*M_PI/3) * COLORTRIANGLERADIUS; + sy = cos(hue - 2*M_PI/3) * COLORTRIANGLERADIUS; + vx = sin(hue + 2*M_PI/3) * COLORTRIANGLERADIUS; + vy = cos(hue + 2*M_PI/3) * COLORTRIANGLERADIUS; + hue = (float) coldata->values[HUE]; + if ((x-sx)*vx+(y-sy)*vy < 0) { + sat = 1; + val = ((float) ((x-sx)*(hx-sx)+(y-sy)*(hy-sy)))/((hx-sx)*(hx-sx)+(hy-sy)*(hy-sy)); + if (val<0) val=0; else if (val>1) val=1; + } else if ((x-sx)*hx+(y-sy)*hy < 0) { + sat = 0; + val = ((float) ((x-sx)*(vx-sx)+(y-sy)*(vy-sy)))/((vx-sx)*(vx-sx)+(vy-sy)*(vy-sy)); + if (val<0) val=0; else if (val>1) val=1; + } else if ((x-hx)*sx+(y-hy)*sy < 0) { + val = 1; + sat = ((float) ((x-vx)*(hx-vx)+(y-vy)*(hy-vy)))/((hx-vx)*(hx-vx)+(hy-vy)*(hy-vy)); + if (sat<0) sat=0; else if (sat>1) sat=1; + } else { + val = (float) ((x-sx)*(hy-vy)-(y-sy)*(hx-vx)) / (float) ((vx-sx)*(hy-vy)-(vy-sy)*(hx-vx)); + if (val<=0) { + val=0; + sat=0; + } else { + if (val>1) val=1; + sat = (float) (y-sy-val*(vy-sy)) / (val * (float) (hy-vy)); + if (sat<0) sat=0; else if (sat>1) sat=1; + } + } + + coldata->values[SATURATION]=100*sat+0.5; + coldata->values[VALUE]=100*val+0.5; + color_select_update_rgb_values(coldata); + update_color_preview(coldata, widget, 0); + + } + + /* callback the user */ + (*coldata->callback) (coldata->data, + coldata->values[RED], + coldata->values[GREEN], + coldata->values[BLUE]); + + return FALSE; +} + +static GtkWidget * +create_color_preview (ColorSelectP coldata) +{ + GtkWidget *preview; + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_widget_set_events( GTK_WIDGET(preview), PREVIEW_MASK ); + gtk_preview_size (GTK_PREVIEW (preview), PREVIEWSIZE, PREVIEWSIZE + 30 /* BAD! */); + + gtk_object_set_user_data (GTK_OBJECT (preview), coldata); + + gtk_signal_connect (GTK_OBJECT(preview), "motion_notify_event", + GTK_SIGNAL_FUNC(color_selection_callback), NULL); + gtk_signal_connect (GTK_OBJECT(preview), "button_press_event", + GTK_SIGNAL_FUNC(color_selection_callback), NULL); + gtk_signal_connect (GTK_OBJECT(preview), "button_release_event", + GTK_SIGNAL_FUNC(color_selection_callback), NULL); + init_color_preview (preview); + update_color_preview (coldata, preview, 1); + + return preview; +} + +