/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "string.h" #include #include #include "libgimpbase/gimpbase.h" #include "libgimpwidgets/gimpwidgets.h" #include "widgets-types.h" #include "config/gimpguiconfig.h" #include "core/gimp.h" #include "gimphelp-ids.h" #include "gimpitemfactory.h" #include "gimpwidgets-utils.h" #include "gimphelp.h" #include "gimp-intl.h" /* local function prototypes */ static void gimp_item_factory_class_init (GimpItemFactoryClass *klass); static void gimp_item_factory_init (GimpItemFactory *factory); static void gimp_item_factory_finalize (GObject *object); static void gimp_item_factory_destroy (GtkObject *object); static void gimp_item_factory_create_branches (GimpItemFactory *factory, GimpItemFactoryEntry *entry, const gchar *textdomain); static void gimp_item_factory_item_realize (GtkWidget *widget, GimpItemFactory *factory); static gboolean gimp_item_factory_item_key_press (GtkWidget *widget, GdkEventKey *kevent, GimpItemFactory *factory); static void gimp_item_factory_menu_position (GtkMenu *menu, gint *x, gint *y, gpointer data); static gchar * gimp_item_factory_translate (const gchar *path, gpointer data); static GtkItemFactoryClass *parent_class = NULL; GType gimp_item_factory_get_type (void) { static GType factory_type = 0; if (! factory_type) { static const GTypeInfo factory_info = { sizeof (GimpItemFactoryClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gimp_item_factory_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GimpItemFactory), 0, /* n_preallocs */ (GInstanceInitFunc) gimp_item_factory_init, }; factory_type = g_type_register_static (GTK_TYPE_ITEM_FACTORY, "GimpItemFactory", &factory_info, 0); } return factory_type; } static void gimp_item_factory_class_init (GimpItemFactoryClass *klass) { GObjectClass *object_class; GtkObjectClass *gtk_object_class; object_class = G_OBJECT_CLASS (klass); gtk_object_class = GTK_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gimp_item_factory_finalize; gtk_object_class->destroy = gimp_item_factory_destroy; klass->factories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void gimp_item_factory_init (GimpItemFactory *factory) { factory->gimp = NULL; factory->update_func = NULL; factory->update_on_popup = FALSE; factory->title = NULL; factory->help_id = NULL; factory->translation_trash = NULL; } static void gimp_item_factory_finalize (GObject *object) { GimpItemFactory *factory; factory = GIMP_ITEM_FACTORY (object); if (factory->title) { g_free (factory->title); factory->title = NULL; } if (factory->help_id) { g_free (factory->help_id); factory->help_id = NULL; } G_OBJECT_CLASS (parent_class)->finalize (object); } static void gimp_item_factory_destroy (GtkObject *object) { GimpItemFactory *factory; gchar *factory_path; factory = GIMP_ITEM_FACTORY (object); factory_path = GTK_ITEM_FACTORY (object)->path; if (factory_path) { GimpItemFactoryClass *factory_class; GList *list; factory_class = GIMP_ITEM_FACTORY_GET_CLASS (factory); list = g_hash_table_lookup (factory_class->factories, factory_path); if (list) { list = g_list_remove (list, factory); if (list) g_hash_table_replace (factory_class->factories, g_strdup (factory_path), list); else g_hash_table_remove (factory_class->factories, factory_path); } } GTK_OBJECT_CLASS (parent_class)->destroy (object); if (GTK_ITEM_FACTORY (factory)->widget) g_object_unref (GTK_ITEM_FACTORY (factory)->widget); } /* public functions */ GimpItemFactory * gimp_item_factory_new (Gimp *gimp, GType container_type, const gchar *factory_path, const gchar *title, const gchar *help_id, GimpItemFactoryUpdateFunc update_func, gboolean update_on_popup, guint n_entries, GimpItemFactoryEntry *entries, gpointer callback_data, gboolean create_tearoff) { GimpItemFactoryClass *factory_class; GimpItemFactory *factory; GList *list; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (factory_path != NULL, NULL); g_return_val_if_fail (title != NULL, NULL); g_return_val_if_fail (help_id != NULL, NULL); g_return_val_if_fail (factory_path[0] == '<', NULL); g_return_val_if_fail (factory_path[strlen (factory_path) - 1] == '>', NULL); factory_class = g_type_class_ref (GIMP_TYPE_ITEM_FACTORY); factory = g_object_new (GIMP_TYPE_ITEM_FACTORY, NULL); gtk_item_factory_construct (GTK_ITEM_FACTORY (factory), container_type, factory_path, NULL); gtk_item_factory_set_translate_func (GTK_ITEM_FACTORY (factory), gimp_item_factory_translate, factory, NULL); factory->gimp = gimp; factory->update_func = update_func; factory->update_on_popup = update_on_popup; factory->create_tearoff = create_tearoff; factory->title = g_strdup (title); factory->help_id = g_strdup (help_id); list = g_hash_table_lookup (factory_class->factories, factory_path); list = g_list_append (list, factory); g_hash_table_replace (factory_class->factories, g_strdup (factory_path), list); gimp_item_factory_create_items (factory, n_entries, entries, callback_data, 2, TRUE); g_type_class_unref (factory_class); if (GTK_ITEM_FACTORY (factory)->widget) g_object_ref (GTK_ITEM_FACTORY (factory)->widget); return factory; } GimpItemFactory * gimp_item_factory_from_path (const gchar *path) { GList *list; list = gimp_item_factories_from_path (path); if (list) return list->data; return NULL; } GList * gimp_item_factories_from_path (const gchar *path) { GimpItemFactoryClass *factory_class; GList *list; gchar *base_path; gchar *p; g_return_val_if_fail (path != NULL, NULL); base_path = g_strdup (path); p = strchr (base_path, '>'); if (p) p[1] = '\0'; factory_class = g_type_class_ref (GIMP_TYPE_ITEM_FACTORY); list = g_hash_table_lookup (factory_class->factories, base_path); g_type_class_unref (factory_class); g_free (base_path); return list; } void gimp_item_factory_create_item (GimpItemFactory *item_factory, GimpItemFactoryEntry *entry, const gchar *textdomain, gpointer callback_data, guint callback_type, gboolean static_entry) { GtkWidget *menu_item; gchar *menu_path; gboolean tearoffs; g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory)); g_return_if_fail (entry != NULL); tearoffs = GIMP_GUI_CONFIG (item_factory->gimp->config)->tearoff_menus; if (! (strstr (entry->entry.path, "tearoff"))) { if (tearoffs && item_factory->create_tearoff) { gimp_item_factory_create_branches (item_factory, entry, textdomain); } } else if (! tearoffs || ! item_factory->create_tearoff) { return; } if (entry->quark_string) { GQuark quark; if (static_entry) quark = g_quark_from_static_string (entry->quark_string); else quark = g_quark_from_string (entry->quark_string); entry->entry.callback_action = (guint) quark; } if (textdomain) g_object_set_data (G_OBJECT (item_factory), "textdomain", (gpointer) textdomain); gtk_item_factory_create_item (GTK_ITEM_FACTORY (item_factory), (GtkItemFactoryEntry *) entry, callback_data, callback_type); if (textdomain) g_object_set_data (G_OBJECT (item_factory), "textdomain", NULL); if (item_factory->translation_trash) { g_list_foreach (item_factory->translation_trash, (GFunc) g_free, NULL); g_list_free (item_factory->translation_trash); item_factory->translation_trash = NULL; } menu_path = gimp_strip_uline (((GtkItemFactoryEntry *) entry)->path); menu_item = gtk_item_factory_get_item (GTK_ITEM_FACTORY (item_factory), menu_path); g_free (menu_path); if (menu_item) { g_signal_connect_after (menu_item, "realize", G_CALLBACK (gimp_item_factory_item_realize), item_factory); if (entry->help_id) { if (static_entry) g_object_set_data (G_OBJECT (menu_item), "gimp-help-id", (gpointer) entry->help_id); else g_object_set_data_full (G_OBJECT (menu_item), "gimp-help-id", g_strdup (entry->help_id), g_free); } } } void gimp_item_factory_create_items (GimpItemFactory *item_factory, guint n_entries, GimpItemFactoryEntry *entries, gpointer callback_data, guint callback_type, gboolean static_entries) { gint i; for (i = 0; i < n_entries; i++) { gimp_item_factory_create_item (item_factory, entries + i, NULL, callback_data, callback_type, static_entries); } } void gimp_item_factory_update (GimpItemFactory *item_factory, gpointer popup_data) { g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory)); if (item_factory->update_func) item_factory->update_func (GTK_ITEM_FACTORY (item_factory), popup_data); } void gimp_item_factory_popup_with_data (GimpItemFactory *item_factory, gpointer popup_data, GtkWidget *parent, GimpMenuPositionFunc position_func, gpointer position_data, GtkDestroyNotify popdown_func) { GdkEvent *current_event; gint x, y; guint button; guint32 activate_time; g_return_if_fail (GIMP_IS_ITEM_FACTORY (item_factory)); g_return_if_fail (GTK_IS_WIDGET (parent)); if (item_factory->update_on_popup) gimp_item_factory_update (item_factory, popup_data); if (! position_func) { position_func = gimp_item_factory_menu_position; position_data = parent; } (* position_func) (GTK_MENU (GTK_ITEM_FACTORY (item_factory)->widget), &x, &y, position_data); current_event = gtk_get_current_event (); if (current_event && current_event->type == GDK_BUTTON_PRESS) { GdkEventButton *bevent; bevent = (GdkEventButton *) current_event; button = bevent->button; activate_time = bevent->time; } else { button = 0; activate_time = 0; } gtk_item_factory_popup_with_data (GTK_ITEM_FACTORY (item_factory), popup_data, popdown_func, x, y, button, activate_time); } void gimp_item_factory_set_active (GtkItemFactory *factory, const gchar *path, gboolean active) { GtkWidget *widget; g_return_if_fail (GTK_IS_ITEM_FACTORY (factory)); g_return_if_fail (path != NULL); widget = gtk_item_factory_get_widget (factory, path); if (widget) { if (GTK_IS_CHECK_MENU_ITEM (widget)) { gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), active); } else { g_warning ("%s: Unable to set \"active\" for menu item " "of type \"%s\": %s", G_STRFUNC, g_type_name (G_TYPE_FROM_INSTANCE (widget)), path); } } else if (! strstr (path, "Script-Fu")) { g_warning ("%s: Unable to set \"active\" for menu item " "which doesn't exist: %s", G_STRFUNC, path); } } void gimp_item_factories_set_active (const gchar *factory_path, const gchar *path, gboolean active) { GList *list; g_return_if_fail (factory_path != NULL); g_return_if_fail (path != NULL); for (list = gimp_item_factories_from_path (factory_path); list; list = g_list_next (list)) { gimp_item_factory_set_active (GTK_ITEM_FACTORY (list->data), path, active); } } void gimp_item_factory_set_color (GtkItemFactory *factory, const gchar *path, const GimpRGB *color, gboolean set_label) { GtkWidget *widget; GtkWidget *area = NULL; GtkWidget *label = NULL; GdkScreen *screen; g_return_if_fail (GTK_IS_ITEM_FACTORY (factory)); g_return_if_fail (path != NULL); g_return_if_fail (color != NULL); widget = gtk_item_factory_get_widget (factory, path); if (! widget) { g_warning ("%s: Unable to set color of menu item " "which doesn't exist: %s", G_STRFUNC, path); return; } if (GTK_IS_HBOX (GTK_BIN (widget)->child)) { area = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), "color_area"); label = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), "label"); } else if (GTK_IS_LABEL (GTK_BIN (widget)->child)) { GtkWidget *hbox; gint width, height; label = GTK_BIN (widget)->child; g_object_ref (label); gtk_container_remove (GTK_CONTAINER (widget), label); hbox = gtk_hbox_new (FALSE, 4); gtk_container_add (GTK_CONTAINER (widget), hbox); gtk_widget_show (hbox); area = gimp_color_area_new (color, GIMP_COLOR_AREA_SMALL_CHECKS, 0); gimp_color_area_set_draw_border (GIMP_COLOR_AREA (area), TRUE); screen = gtk_widget_get_screen (area); gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen), GTK_ICON_SIZE_MENU, &width, &height); gtk_widget_set_size_request (area, width, height); gtk_box_pack_start (GTK_BOX (hbox), area, FALSE, FALSE, 0); gtk_widget_show (area); gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); gtk_widget_show (label); g_object_unref (label); g_object_set_data (G_OBJECT (hbox), "color_area", area); g_object_set_data (G_OBJECT (hbox), "label", label); } if (area) gimp_color_area_set_color (GIMP_COLOR_AREA (area), color); if (label && set_label) { gchar *str; str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), color->r, color->g, color->b, color->a); gtk_label_set_text (GTK_LABEL (label), str); g_free (str); } } void gimp_item_factories_set_color (const gchar *factory_path, const gchar *path, const GimpRGB *color, gboolean set_label) { GList *list; g_return_if_fail (factory_path != NULL); g_return_if_fail (path != NULL); g_return_if_fail (color != NULL); for (list = gimp_item_factories_from_path (factory_path); list; list = g_list_next (list)) { gimp_item_factory_set_color (GTK_ITEM_FACTORY (list->data), path, color, set_label); } } void gimp_item_factory_set_label (GtkItemFactory *factory, const gchar *path, const gchar *label) { GtkWidget *widget; g_return_if_fail (GTK_IS_ITEM_FACTORY (factory)); g_return_if_fail (path != NULL); g_return_if_fail (label != NULL); widget = gtk_item_factory_get_widget (factory, path); if (widget) { if (GTK_IS_MENU (widget)) widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); if (GTK_IS_LABEL (GTK_BIN (widget)->child)) gtk_label_set_text_with_mnemonic (GTK_LABEL (GTK_BIN (widget)->child), label); } else { g_warning ("%s: Unable to set label of menu item " "which doesn't exist: %s", G_STRFUNC, path); } } void gimp_item_factories_set_label (const gchar *factory_path, const gchar *path, const gchar *label) { GList *list; g_return_if_fail (factory_path != NULL); g_return_if_fail (path != NULL); g_return_if_fail (label != NULL); for (list = gimp_item_factories_from_path (factory_path); list; list = g_list_next (list)) { gimp_item_factory_set_label (GTK_ITEM_FACTORY (list->data), path, label); } } void gimp_item_factory_set_sensitive (GtkItemFactory *factory, const gchar *path, gboolean sensitive) { GtkWidget *widget; g_return_if_fail (GTK_IS_ITEM_FACTORY (factory)); g_return_if_fail (path != NULL); widget = gtk_item_factory_get_widget (factory, path); if (widget) { gtk_widget_set_sensitive (widget, sensitive); } else if (! strstr (path, "Script-Fu")) { g_warning ("%s: Unable to set sensitivity of menu item " "which doesn't exist: %s", G_STRFUNC, path); } } void gimp_item_factories_set_sensitive (const gchar *factory_path, const gchar *path, gboolean sensitive) { GList *list; g_return_if_fail (factory_path != NULL); g_return_if_fail (path != NULL); for (list = gimp_item_factories_from_path (factory_path); list; list = g_list_next (list)) { gimp_item_factory_set_sensitive (GTK_ITEM_FACTORY (list->data), path, sensitive); } } void gimp_item_factory_set_visible (GtkItemFactory *factory, const gchar *path, gboolean visible) { GtkWidget *widget; g_return_if_fail (GTK_IS_ITEM_FACTORY (factory)); g_return_if_fail (path != NULL); widget = gtk_item_factory_get_widget (factory, path); if (widget) { if (GTK_IS_MENU (widget)) widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); if (visible) gtk_widget_show (widget); else gtk_widget_hide (widget); } else { g_warning ("%s: Unable to set visibility of menu item " "which doesn't exist: %s", G_STRFUNC, path); } } void gimp_item_factories_set_visible (const gchar *factory_path, const gchar *path, gboolean visible) { GList *list; g_return_if_fail (factory_path != NULL); g_return_if_fail (path != NULL); for (list = gimp_item_factories_from_path (factory_path); list; list = g_list_next (list)) { gimp_item_factory_set_visible (GTK_ITEM_FACTORY (list->data), path, visible); } } void gimp_item_factory_tearoff_callback (GtkWidget *widget, gpointer data, guint action) { if (GTK_IS_TEAROFF_MENU_ITEM (widget)) { GtkTearoffMenuItem *tomi = (GtkTearoffMenuItem *) widget; if (tomi->torn_off) { GtkWidget *toplevel; toplevel = gtk_widget_get_toplevel (widget); if (! GTK_IS_WINDOW (toplevel)) { g_warning ("%s: tearoff menu not in top level window", G_STRFUNC); } else { #ifdef __GNUC__ #warning FIXME: register tearoffs #endif g_object_set_data (G_OBJECT (widget), "tearoff-menu-toplevel", toplevel); } } else { GtkWidget *toplevel; toplevel = (GtkWidget *) g_object_get_data (G_OBJECT (widget), "tearoff-menu-toplevel"); if (! toplevel) { g_warning ("%s: can't unregister tearoff menu top level window", G_STRFUNC); } else { #ifdef __GNUC__ #warning FIXME: unregister tearoffs #endif } } } } /* private functions */ static void gimp_item_factory_create_branches (GimpItemFactory *factory, GimpItemFactoryEntry *entry, const gchar *textdomain) { GString *tearoff_path; gint factory_length; gchar *p; if (! entry->entry.path) return; tearoff_path = g_string_new (""); p = strchr (entry->entry.path, '/'); factory_length = p - entry->entry.path; /* skip the first slash */ if (p) p = strchr (p + 1, '/'); while (p) { g_string_assign (tearoff_path, entry->entry.path + factory_length); g_string_truncate (tearoff_path, p - entry->entry.path - factory_length); if (! gtk_item_factory_get_widget (GTK_ITEM_FACTORY (factory), tearoff_path->str)) { GimpItemFactoryEntry branch_entry = { { NULL, NULL, NULL, 0, "" }, NULL, NULL }; branch_entry.entry.path = tearoff_path->str; g_object_set_data (G_OBJECT (factory), "complete", entry->entry.path); gimp_item_factory_create_item (factory, &branch_entry, textdomain, NULL, 2, TRUE); g_object_set_data (G_OBJECT (factory), "complete", NULL); } g_string_append (tearoff_path, "/tearoff"); if (! gtk_item_factory_get_widget (GTK_ITEM_FACTORY (factory), tearoff_path->str)) { GimpItemFactoryEntry tearoff_entry = { { NULL, NULL, gimp_item_factory_tearoff_callback, 0, "" }, NULL, NULL, NULL }; tearoff_entry.entry.path = tearoff_path->str; gimp_item_factory_create_item (factory, &tearoff_entry, textdomain, NULL, 2, TRUE); } p = strchr (p + 1, '/'); } g_string_free (tearoff_path, TRUE); } static void gimp_item_factory_item_realize (GtkWidget *widget, GimpItemFactory *item_factory) { if (GTK_IS_MENU_SHELL (widget->parent)) { static GQuark quark_key_press_connected = 0; if (! quark_key_press_connected) quark_key_press_connected = g_quark_from_static_string ("gimp-menu-item-key-press-connected"); if (! GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget->parent), quark_key_press_connected))) { g_signal_connect (widget->parent, "key_press_event", G_CALLBACK (gimp_item_factory_item_key_press), item_factory); g_object_set_qdata (G_OBJECT (widget->parent), quark_key_press_connected, GINT_TO_POINTER (TRUE)); } } } static gboolean gimp_item_factory_item_key_press (GtkWidget *widget, GdkEventKey *kevent, GimpItemFactory *item_factory) { GtkWidget *active_menu_item; gchar *help_id = NULL; active_menu_item = GTK_MENU_SHELL (widget)->active_menu_item; /* first, get the help page from the item */ if (active_menu_item) { help_id = g_object_get_data (G_OBJECT (active_menu_item), "gimp-help-id"); if (help_id && ! strlen (help_id)) help_id = NULL; } /* For any valid accelerator key except F1, continue with the * standard GtkItemFactory callback and assign a new shortcut, but * don't assign a shortcut to the help menu entries ... */ if (kevent->keyval != GDK_F1) { if (help_id && gtk_accelerator_valid (kevent->keyval, 0) && (strcmp (help_id, GIMP_HELP_HELP) == 0 || strcmp (help_id, GIMP_HELP_HELP_CONTEXT) == 0)) { return TRUE; } return FALSE; } /* ...finally, if F1 was pressed over any menu, show it's help page... */ if (! help_id) help_id = item_factory->help_id; { gchar *help_domain = NULL; gchar *help_string = NULL; gchar *domain_separator; help_id = g_strdup (help_id); domain_separator = strchr (help_id, '?'); if (domain_separator) { *domain_separator = '\0'; help_domain = g_strdup (help_id); help_string = g_strdup (domain_separator + 1); } else { help_string = g_strdup (help_id); } gimp_help (item_factory->gimp, help_domain, help_string); g_free (help_domain); g_free (help_string); g_free (help_id); } return TRUE; } static void gimp_item_factory_menu_position (GtkMenu *menu, gint *x, gint *y, gpointer data) { GdkScreen *screen; GtkRequisition requisition; GdkRectangle rect; gint monitor; gint pointer_x; gint pointer_y; g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); g_return_if_fail (GTK_IS_WIDGET (data)); gdk_display_get_pointer (gtk_widget_get_display (GTK_WIDGET (data)), &screen, &pointer_x, &pointer_y, NULL); monitor = gdk_screen_get_monitor_at_point (screen, pointer_x, pointer_y); gdk_screen_get_monitor_geometry (screen, monitor, &rect); gtk_menu_set_screen (menu, screen); gtk_widget_size_request (GTK_WIDGET (menu), &requisition); if (gtk_widget_get_direction (GTK_WIDGET (menu)) == GTK_TEXT_DIR_RTL) { *x = pointer_x - 2 - requisition.width; if (*x < rect.x) *x = pointer_x + 2; } else { *x = pointer_x + 2; if (*x + requisition.width > rect.x + rect.width) *x = pointer_x - 2 - requisition.width; } *y = pointer_y + 2; if (*y + requisition.height > rect.y + rect.height) *y = pointer_y - 2 - requisition.height; if (*x < rect.x) *x = rect.x; if (*y < rect.y) *y = rect.y; } static gchar * gimp_item_factory_translate (const gchar *path, gpointer data) { GtkItemFactory *item_factory; GimpItemFactory *gimp_factory; const gchar *retval; gchar *translation; gchar *domain = NULL; gchar *complete = NULL; gchar *p, *t; item_factory = GTK_ITEM_FACTORY (data); gimp_factory = GIMP_ITEM_FACTORY (data); if (strstr (path, "tearoff") || strstr (path, "/---") || strstr (path, "/MRU")) { return (gchar *) path; } domain = g_object_get_data (G_OBJECT (item_factory), "textdomain"); complete = g_object_get_data (G_OBJECT (item_factory), "complete"); if (domain) /* use the plugin textdomain */ { gchar *full_path; full_path = g_strconcat (item_factory->path, path, NULL); if (complete) { /* This is a branch, use the complete path for translation, * then strip off entries from the end until it matches. */ complete = g_strconcat (item_factory->path, complete, NULL); translation = g_strdup (dgettext (domain, complete)); while (*complete && *translation && strcmp (complete, full_path)) { p = strrchr (complete, '/'); t = strrchr (translation, '/'); if (p && t) { *p = '\0'; *t = '\0'; } else break; } g_free (complete); /* DON'T set complete to NULL here */ } else { translation = g_strdup (dgettext (domain, full_path)); } gimp_factory->translation_trash = g_list_prepend (gimp_factory->translation_trash, translation); if (strncmp (item_factory->path, translation, strlen (item_factory->path)) == 0) { retval = translation + strlen (item_factory->path); } else { g_warning ("%s: bad translation for menupath: %s", G_STRFUNC, full_path); retval = path; } g_free (full_path); } else /* use the gimp textdomain */ { if (complete) { /* This is a branch, use the complete path for translation, * then strip off entries from the end until it matches. */ complete = g_strdup (complete); translation = g_strdup (gettext (complete)); gimp_factory->translation_trash = g_list_prepend (gimp_factory->translation_trash, translation); while (*complete && *translation && strcmp (complete, path)) { p = strrchr (complete, '/'); t = strrchr (translation, '/'); if (p && t) { *p = '\0'; *t = '\0'; } else break; } g_free (complete); /* DON'T set complete to NULL here */ } else { translation = gettext (path); } if (*translation == '/') { retval = translation; } else { g_warning ("%s: bad translation for menupath: %s", G_STRFUNC, path); retval = path; } } return (gchar *) retval; }