]> Pileus Git - ~andy/gtk/blob - gtk/gtkitemfactory.c
Use g_object_new instead of gtk_widget_new
[~andy/gtk] / gtk / gtkitemfactory.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GtkItemFactory: Flexible item factory with automatic rc handling
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GTK+ Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
28  */
29
30 #include        <config.h>
31
32 #undef GTK_DISABLE_DEPRECATED
33 #include        "gtkitemfactory.h"
34 #include        "gtkoptionmenu.h"
35 #include        "gtkmenubar.h"
36 #include        "gtkmenu.h"
37 #include        "gtkmenuitem.h"
38 #include        "gtkradiomenuitem.h"
39 #include        "gtkcheckmenuitem.h"
40 #include        "gtkimagemenuitem.h"
41 #include        "gtktearoffmenuitem.h"
42 #include        "gtkaccelmap.h"
43 #include        "gtkaccellabel.h"
44 #include        "gdk/gdkkeysyms.h"
45 #include        "gtkimage.h"
46 #include        "gtkstock.h"
47 #include        "gtkiconfactory.h"
48 #include        "gtkintl.h"
49 #include        <string.h>
50 #include        <fcntl.h>
51 #ifdef HAVE_UNISTD_H
52 #include        <unistd.h>
53 #endif
54 #include        <stdio.h>
55
56 #include "gtkalias.h"
57
58 /* --- defines --- */
59 #define         ITEM_FACTORY_STRING     ((gchar*) item_factory_string)
60 #define         ITEM_BLOCK_SIZE         (128)
61
62
63 /* --- structures --- */
64 typedef struct  _GtkIFCBData            GtkIFCBData;
65 typedef struct  _GtkIFDumpData          GtkIFDumpData;
66 struct _GtkIFCBData
67 {
68   GtkItemFactoryCallback  func;
69   guint                   callback_type;
70   gpointer                func_data;
71   guint                   callback_action;
72 };
73
74
75 /* --- prototypes --- */
76 static void     gtk_item_factory_destroy                (GtkObject            *object);
77 static void     gtk_item_factory_finalize               (GObject              *object);
78
79
80 /* --- static variables --- */
81 static const gchar       item_factory_string[] = "Gtk-<ItemFactory>";
82 static GQuark            quark_popup_data = 0;
83 static GQuark            quark_if_menu_pos = 0;
84 static GQuark            quark_item_factory = 0;
85 static GQuark            quark_item_path = 0;
86 static GQuark            quark_action = 0;
87 static GQuark            quark_accel_group = 0;
88 static GQuark            quark_type_item = 0;
89 static GQuark            quark_type_title = 0;
90 static GQuark            quark_type_radio_item = 0;
91 static GQuark            quark_type_check_item = 0;
92 static GQuark            quark_type_toggle_item = 0;
93 static GQuark            quark_type_image_item = 0;
94 static GQuark            quark_type_stock_item = 0;
95 static GQuark            quark_type_tearoff_item = 0;
96 static GQuark            quark_type_separator_item = 0;
97 static GQuark            quark_type_branch = 0;
98 static GQuark            quark_type_last_branch = 0;
99
100 G_DEFINE_TYPE (GtkItemFactory, gtk_item_factory, GTK_TYPE_OBJECT)
101
102 /* --- functions --- */
103 static void
104 gtk_item_factory_class_init (GtkItemFactoryClass  *class)
105 {
106   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
107   GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
108
109   gobject_class->finalize = gtk_item_factory_finalize;
110
111   object_class->destroy = gtk_item_factory_destroy;
112
113   class->item_ht = g_hash_table_new (g_str_hash, g_str_equal);
114
115   quark_popup_data              = g_quark_from_static_string ("GtkItemFactory-popup-data");
116   quark_if_menu_pos             = g_quark_from_static_string ("GtkItemFactory-menu-position");
117   quark_item_factory            = g_quark_from_static_string ("GtkItemFactory");
118   quark_item_path               = g_quark_from_static_string ("GtkItemFactory-path");
119   quark_action                  = g_quark_from_static_string ("GtkItemFactory-action");
120   quark_accel_group             = g_quark_from_static_string ("GtkAccelGroup");
121   quark_type_item               = g_quark_from_static_string ("<Item>");
122   quark_type_title              = g_quark_from_static_string ("<Title>");
123   quark_type_radio_item         = g_quark_from_static_string ("<RadioItem>");
124   quark_type_check_item         = g_quark_from_static_string ("<CheckItem>");
125   quark_type_toggle_item        = g_quark_from_static_string ("<ToggleItem>");
126   quark_type_image_item         = g_quark_from_static_string ("<ImageItem>");
127   quark_type_stock_item         = g_quark_from_static_string ("<StockItem>");
128   quark_type_separator_item     = g_quark_from_static_string ("<Separator>");
129   quark_type_tearoff_item       = g_quark_from_static_string ("<Tearoff>");
130   quark_type_branch             = g_quark_from_static_string ("<Branch>");
131   quark_type_last_branch        = g_quark_from_static_string ("<LastBranch>");
132 }
133
134 static void
135 gtk_item_factory_init (GtkItemFactory       *ifactory)
136 {
137   ifactory->path = NULL;
138   ifactory->accel_group = NULL;
139   ifactory->widget = NULL;
140   ifactory->items = NULL;
141   ifactory->translate_func = NULL;
142   ifactory->translate_data = NULL;
143   ifactory->translate_notify = NULL;
144 }
145
146 /**
147  * gtk_item_factory_new:
148  * @container_type: the kind of menu to create; can be
149  *    #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
150  * @path: the factory path of the new item factory, a string of the form 
151  *    <literal>"&lt;name&gt;"</literal>
152  * @accel_group: a #GtkAccelGroup to which the accelerators for the
153  *    menu items will be added, or %NULL to create a new one
154  * @returns: a new #GtkItemFactory
155  * 
156  * Creates a new #GtkItemFactory.
157  *
158  * Beware that the returned object does not have a floating reference.
159  *
160  * Deprecated: 2.4:     
161  */
162 GtkItemFactory*
163 gtk_item_factory_new (GType          container_type,
164                       const gchar   *path,
165                       GtkAccelGroup *accel_group)
166 {
167   GtkItemFactory *ifactory;
168
169   g_return_val_if_fail (path != NULL, NULL);
170
171   ifactory = g_object_new (GTK_TYPE_ITEM_FACTORY, NULL);
172   gtk_item_factory_construct (ifactory, container_type, path, accel_group);
173
174   return ifactory;
175 }
176
177 static void
178 gtk_item_factory_callback_marshal (GtkWidget *widget,
179                                    gpointer   func_data)
180 {
181   GtkIFCBData *data;
182
183   data = func_data;
184
185   if (data->callback_type == 1)
186     {
187       GtkItemFactoryCallback1 func1 = (GtkItemFactoryCallback1) data->func;
188       func1 (data->func_data, data->callback_action, widget);
189     }
190   else if (data->callback_type == 2)
191     {
192       GtkItemFactoryCallback2 func2 = (GtkItemFactoryCallback2) data->func;
193       func2 (widget, data->func_data, data->callback_action);
194     }
195 }
196
197 static void
198 gtk_item_factory_item_remove_widget (GtkWidget          *widget,
199                                      GtkItemFactoryItem *item)
200 {
201   item->widgets = g_slist_remove (item->widgets, widget);
202   g_object_set_qdata (G_OBJECT (widget), quark_item_factory, NULL);
203   g_object_set_qdata (G_OBJECT (widget), quark_item_path, NULL);
204 }
205
206 /**
207  * gtk_item_factory_add_foreign:
208  * @accel_widget:     widget to install an accelerator on 
209  * @full_path:        the full path for the @accel_widget 
210  * @accel_group:      the accelerator group to install the accelerator in
211  * @keyval:           key value of the accelerator
212  * @modifiers:        modifier combination of the accelerator
213  *
214  * Installs an accelerator for @accel_widget in @accel_group, that causes
215  * the ::activate signal to be emitted if the accelerator is activated.
216  * 
217  * This function can be used to make widgets participate in the accel
218  * saving/restoring functionality provided by gtk_accel_map_save() and
219  * gtk_accel_map_load(), even if they haven't been created by an item
220  * factory. 
221  *
222  * Deprecated: 2.4: The recommended API for this purpose are the functions 
223  * gtk_menu_item_set_accel_path() and gtk_widget_set_accel_path(); don't 
224  * use gtk_item_factory_add_foreign() in new code, since it is likely to
225  * be removed in the future.
226  */
227 void
228 gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
229                               const gchar    *full_path,
230                               GtkAccelGroup  *accel_group,
231                               guint           keyval,
232                               GdkModifierType modifiers)
233 {
234   GtkItemFactoryClass *class;
235   GtkItemFactoryItem *item;
236
237   g_return_if_fail (GTK_IS_WIDGET (accel_widget));
238   g_return_if_fail (full_path != NULL);
239
240   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
241
242   keyval = keyval != GDK_VoidSymbol ? keyval : 0;
243
244   item = g_hash_table_lookup (class->item_ht, full_path);
245   if (!item)
246     {
247       item = g_slice_new (GtkItemFactoryItem);
248
249       item->path = g_strdup (full_path);
250       item->widgets = NULL;
251       
252       g_hash_table_insert (class->item_ht, item->path, item);
253     }
254
255   item->widgets = g_slist_prepend (item->widgets, accel_widget);
256   g_signal_connect (accel_widget,
257                     "destroy",
258                     G_CALLBACK (gtk_item_factory_item_remove_widget),
259                     item);
260
261   /* set the item path for the widget
262    */
263   g_object_set_qdata (G_OBJECT (accel_widget), quark_item_path, item->path);
264   gtk_widget_set_name (accel_widget, item->path);
265   if (accel_group)
266     {
267       g_object_ref (accel_group);
268       g_object_set_qdata_full (G_OBJECT (accel_widget),
269                                quark_accel_group,
270                                accel_group,
271                                g_object_unref);
272     }
273   else
274     g_object_set_qdata (G_OBJECT (accel_widget), quark_accel_group, NULL);
275
276   /* install defined accelerators
277    */
278   if (g_signal_lookup ("activate", G_TYPE_FROM_INSTANCE (accel_widget)))
279     {
280       if (accel_group)
281         {
282           gtk_accel_map_add_entry (full_path, keyval, modifiers);
283           gtk_widget_set_accel_path (accel_widget, full_path, accel_group);
284         }
285     }
286 }
287
288 static void
289 ifactory_cb_data_free (gpointer mem)
290 {
291   g_slice_free (GtkIFCBData, mem);
292 }
293
294 static void
295 gtk_item_factory_add_item (GtkItemFactory               *ifactory,
296                            const gchar                  *path,
297                            const gchar                  *accelerator,
298                            GtkItemFactoryCallback       callback,
299                            guint                        callback_action,
300                            gpointer                     callback_data,
301                            guint                        callback_type,
302                            gchar                        *item_type,
303                            GtkWidget                    *widget)
304 {
305   GtkItemFactoryClass *class;
306   GtkItemFactoryItem *item;
307   gchar *fpath;
308   guint keyval;
309   GdkModifierType mods;
310   
311   g_return_if_fail (widget != NULL);
312   g_return_if_fail (item_type != NULL);
313
314   class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
315
316   /* set accelerator group on menu widgets
317    */
318   if (GTK_IS_MENU (widget))
319     gtk_menu_set_accel_group ((GtkMenu*) widget, ifactory->accel_group);
320
321   /* connect callback if necessary
322    */
323   if (callback)
324     {
325       GtkIFCBData *data;
326
327       data = g_slice_new (GtkIFCBData);
328       data->func = callback;
329       data->callback_type = callback_type;
330       data->func_data = callback_data;
331       data->callback_action = callback_action;
332
333       g_object_weak_ref (G_OBJECT (widget),
334                          (GWeakNotify) ifactory_cb_data_free,
335                          data);
336       g_signal_connect (widget,
337                         "activate",
338                         G_CALLBACK (gtk_item_factory_callback_marshal),
339                         data);
340     }
341
342   /* link the widget into its item-entry
343    * and keep back pointer on both the item factory and the widget
344    */
345   g_object_set_qdata (G_OBJECT (widget), quark_action, GUINT_TO_POINTER (callback_action));
346   g_object_set_qdata (G_OBJECT (widget), quark_item_factory, ifactory);
347   if (accelerator)
348     gtk_accelerator_parse (accelerator, &keyval, &mods);
349   else
350     {
351       keyval = 0;
352       mods = 0;
353     }
354   fpath = g_strconcat (ifactory->path, path, NULL);
355   gtk_item_factory_add_foreign (widget, fpath, ifactory->accel_group, keyval, mods);
356   item = g_hash_table_lookup (class->item_ht, fpath);
357   g_free (fpath);
358
359   g_return_if_fail (item != NULL);
360
361   if (!g_slist_find (ifactory->items, item))
362     ifactory->items = g_slist_prepend (ifactory->items, item);
363 }
364
365 /**
366  * gtk_item_factory_construct:
367  * @ifactory: a #GtkItemFactory
368  * @container_type: the kind of menu to create; can be
369  *    #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
370  * @path: the factory path of @ifactory, a string of the form 
371  *    <literal>"&lt;name&gt;"</literal>
372  * @accel_group: a #GtkAccelGroup to which the accelerators for the
373  *    menu items will be added, or %NULL to create a new one
374  * 
375  * Initializes an item factory.
376  *
377  * Deprecated: 2.4:
378  */  
379 void
380 gtk_item_factory_construct (GtkItemFactory      *ifactory,
381                             GType                container_type,
382                             const gchar         *path,
383                             GtkAccelGroup       *accel_group)
384 {
385   guint len;
386
387   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
388   g_return_if_fail (ifactory->accel_group == NULL);
389   g_return_if_fail (path != NULL);
390   if (!g_type_is_a (container_type, GTK_TYPE_OPTION_MENU))
391     g_return_if_fail (g_type_is_a (container_type, GTK_TYPE_MENU_SHELL));
392
393   len = strlen (path);
394
395   if (path[0] != '<' && path[len - 1] != '>')
396     {
397       g_warning ("GtkItemFactory: invalid factory path `%s'", path);
398       return;
399     }
400
401   if (accel_group)
402     {
403       ifactory->accel_group = accel_group;
404       g_object_ref (ifactory->accel_group);
405     }
406   else
407     ifactory->accel_group = gtk_accel_group_new ();
408
409   ifactory->path = g_strdup (path);
410   ifactory->widget = g_object_connect (g_object_new (container_type, NULL),
411                                        "signal::destroy", gtk_widget_destroyed, &ifactory->widget,
412                                        NULL);
413   g_object_ref_sink (ifactory);
414
415   gtk_item_factory_add_item (ifactory,
416                              "", NULL,
417                              NULL, 0, NULL, 0,
418                              ITEM_FACTORY_STRING,
419                              ifactory->widget);
420 }
421
422 /**
423  * gtk_item_factory_from_path:
424  * @path: a string starting with a factory path of the form 
425  *   <literal>"&lt;name&gt;"</literal>
426  * @returns: the #GtkItemFactory created for the given factory path, or %NULL 
427  *
428  * Finds an item factory which has been constructed using the 
429  * <literal>"&lt;name&gt;"</literal> prefix of @path as the @path argument 
430  * for gtk_item_factory_new().
431  *
432  * Deprecated: 2.4:
433  */
434 GtkItemFactory*
435 gtk_item_factory_from_path (const gchar      *path)
436 {
437   GtkItemFactoryClass *class;
438   GtkItemFactoryItem *item;
439   gchar *fname;
440   guint i;
441
442   g_return_val_if_fail (path != NULL, NULL);
443   g_return_val_if_fail (path[0] == '<', NULL);
444
445   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
446
447   i = 0;
448   while (path[i] && path[i] != '>')
449     i++;
450   if (path[i] != '>')
451     {
452       g_warning ("gtk_item_factory_from_path(): invalid factory path \"%s\"",
453                  path);
454       return NULL;
455     }
456   fname = g_new (gchar, i + 2);
457   g_memmove (fname, path, i + 1);
458   fname[i + 1] = 0;
459
460   item = g_hash_table_lookup (class->item_ht, fname);
461
462   g_free (fname);
463
464   if (item && item->widgets)
465     return gtk_item_factory_from_widget (item->widgets->data);
466
467   return NULL;
468 }
469
470 static void
471 gtk_item_factory_destroy (GtkObject *object)
472 {
473   GtkItemFactory *ifactory = (GtkItemFactory*) object;
474   GSList *slist;
475
476   if (ifactory->widget)
477     {
478       GtkObject *dobj;
479
480       dobj = GTK_OBJECT (ifactory->widget);
481
482       g_object_ref_sink (dobj);
483       gtk_object_destroy (dobj);
484       g_object_unref (dobj);
485
486       ifactory->widget = NULL;
487     }
488
489   for (slist = ifactory->items; slist; slist = slist->next)
490     {
491       GtkItemFactoryItem *item = slist->data;
492       GSList *link;
493       
494       for (link = item->widgets; link; link = link->next)
495         if (g_object_get_qdata (link->data, quark_item_factory) == ifactory)
496           g_object_set_qdata (link->data, quark_item_factory, NULL);
497     }
498   g_slist_free (ifactory->items);
499   ifactory->items = NULL;
500
501   GTK_OBJECT_CLASS (gtk_item_factory_parent_class)->destroy (object);
502 }
503
504 static void
505 gtk_item_factory_finalize (GObject *object)
506 {
507   GtkItemFactory *ifactory = GTK_ITEM_FACTORY (object);
508
509   if (ifactory->accel_group)
510     g_object_unref (ifactory->accel_group);
511
512   g_free (ifactory->path);
513   g_assert (ifactory->widget == NULL);
514
515   if (ifactory->translate_notify)
516     ifactory->translate_notify (ifactory->translate_data);
517   
518   G_OBJECT_CLASS (gtk_item_factory_parent_class)->finalize (object);
519 }
520
521 /**
522  * gtk_item_factory_from_widget:
523  * @widget: a widget
524  * @returns: the item factory from which @widget was created, or %NULL
525  *
526  * Obtains the item factory from which a widget was created.
527  *
528  * Deprecated: 2.4
529  */
530 GtkItemFactory*
531 gtk_item_factory_from_widget (GtkWidget        *widget)
532 {
533   GtkItemFactory *ifactory;
534
535   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
536
537   ifactory = g_object_get_qdata (G_OBJECT (widget), quark_item_factory);
538
539   if (ifactory == NULL && GTK_IS_MENU_ITEM (widget) &&
540       GTK_MENU_ITEM (widget)->submenu != NULL) 
541     {
542       GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
543       ifactory = g_object_get_qdata (G_OBJECT (menu), quark_item_factory);
544     }
545
546   return ifactory;
547 }
548
549 /**
550  * gtk_item_factory_path_from_widget:
551  * @widget: a widget
552  * @returns: the full path to @widget if it has been created by an item
553  *   factory, %NULL otherwise. This value is owned by GTK+ and must not be
554  *   modified or freed.
555  * 
556  * If @widget has been created by an item factory, returns the full path
557  * to it. (The full path of a widget is the concatenation of the factory 
558  * path specified in gtk_item_factory_new() with the path specified in the 
559  * #GtkItemFactoryEntry from which the widget was created.)
560  *
561  * Deprecated: 2.4:
562  */
563 G_CONST_RETURN gchar*
564 gtk_item_factory_path_from_widget (GtkWidget        *widget)
565 {
566   gchar* path;
567
568   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
569
570   path = g_object_get_qdata (G_OBJECT (widget), quark_item_path);
571
572   if (path == NULL && GTK_IS_MENU_ITEM (widget) &&
573       GTK_MENU_ITEM (widget)->submenu != NULL) 
574     {
575       GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
576       path = g_object_get_qdata (G_OBJECT (menu), quark_item_path);
577     }
578
579   return path;
580 }
581
582 /**
583  * gtk_item_factory_create_items:
584  * @ifactory: a #GtkItemFactory
585  * @n_entries: the length of @entries
586  * @entries: an array of #GtkItemFactoryEntry<!-- -->s whose @callback members
587  *    must by of type #GtkItemFactoryCallback1
588  * @callback_data: data passed to the callback functions of all entries
589  *
590  * Creates the menu items from the @entries.
591  *
592  * Deprecated: 2.4:
593  */
594 void
595 gtk_item_factory_create_items (GtkItemFactory      *ifactory,
596                                guint                n_entries,
597                                GtkItemFactoryEntry *entries,
598                                gpointer             callback_data)
599 {
600   gtk_item_factory_create_items_ac (ifactory, n_entries, entries, callback_data, 1);
601 }
602
603 /**
604  * gtk_item_factory_create_items_ac:
605  * @ifactory: a #GtkItemFactory
606  * @n_entries: the length of @entries
607  * @entries: an array of #GtkItemFactoryEntry<!-- -->s 
608  * @callback_data: data passed to the callback functions of all entries
609  * @callback_type: 1 if the callback functions in @entries are of type
610  *    #GtkItemFactoryCallback1, 2 if they are of type #GtkItemFactoryCallback2 
611  *
612  * Creates the menu items from the @entries.
613  *
614  * Deprecated: 2.4:
615  */
616 void
617 gtk_item_factory_create_items_ac (GtkItemFactory      *ifactory,
618                                   guint                n_entries,
619                                   GtkItemFactoryEntry *entries,
620                                   gpointer             callback_data,
621                                   guint                callback_type)
622 {
623   guint i;
624
625   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
626   g_return_if_fail (callback_type >= 1 && callback_type <= 2);
627
628   if (n_entries == 0)
629     return;
630
631   g_return_if_fail (entries != NULL);
632
633   for (i = 0; i < n_entries; i++)
634     gtk_item_factory_create_item (ifactory, entries + i, callback_data, callback_type);
635 }
636
637 /**
638  * gtk_item_factory_get_widget:
639  * @ifactory: a #GtkItemFactory
640  * @path: the path to the widget
641  * @returns: the widget for the given path, or %NULL if @path doesn't lead
642  *   to a widget
643  *
644  * Obtains the widget which corresponds to @path. 
645  *
646  * If the widget corresponding to @path is a menu item which opens a 
647  * submenu, then the submenu is returned. If you are interested in the menu 
648  * item, use gtk_item_factory_get_item() instead.
649  *
650  * Deprecated: 2.4:
651  */
652 GtkWidget*
653 gtk_item_factory_get_widget (GtkItemFactory *ifactory,
654                              const gchar    *path)
655 {
656   GtkItemFactoryClass *class;
657   GtkItemFactoryItem *item;
658
659   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
660   g_return_val_if_fail (path != NULL, NULL);
661
662   class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
663
664   if (path[0] == '<')
665     item = g_hash_table_lookup (class->item_ht, (gpointer) path);
666   else
667     {
668       gchar *fpath;
669
670       fpath = g_strconcat (ifactory->path, path, NULL);
671       item = g_hash_table_lookup (class->item_ht, fpath);
672       g_free (fpath);
673     }
674
675   if (item)
676     {
677       GSList *slist;
678
679       for (slist = item->widgets; slist; slist = slist->next)
680         {
681           if (gtk_item_factory_from_widget (slist->data) == ifactory)
682             return slist->data;
683         }
684     }
685
686   return NULL;
687 }
688
689 /**
690  * gtk_item_factory_get_widget_by_action:
691  * @ifactory: a #GtkItemFactory
692  * @action: an action as specified in the @callback_action field
693  *   of #GtkItemFactoryEntry
694  * @returns: the widget which corresponds to the given action, or %NULL
695  *   if no widget was found
696  *
697  * Obtains the widget which was constructed from the #GtkItemFactoryEntry
698  * with the given @action.
699  *
700  * If there are multiple items with the same action, the result is 
701  * undefined.
702  *
703  * Deprecated: 2.4:
704  */
705 GtkWidget*
706 gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
707                                        guint           action)
708 {
709   GSList *slist;
710
711   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
712
713   for (slist = ifactory->items; slist; slist = slist->next)
714     {
715       GtkItemFactoryItem *item = slist->data;
716       GSList *link;
717
718       for (link = item->widgets; link; link = link->next)
719         if (g_object_get_qdata (link->data, quark_item_factory) == ifactory &&
720             g_object_get_qdata (link->data, quark_action) == GUINT_TO_POINTER (action))
721           return link->data;
722     }
723
724   return NULL;
725 }
726
727 /** 
728  * gtk_item_factory_get_item:
729  * @ifactory: a #GtkItemFactory
730  * @path: the path to the menu item
731  * @returns: the menu item for the given path, or %NULL if @path doesn't
732  *   lead to a menu item
733  *
734  * Obtains the menu item which corresponds to @path. 
735  *
736  * If the widget corresponding to @path is a menu item which opens a 
737  * submenu, then the item is returned. If you are interested in the submenu, 
738  * use gtk_item_factory_get_widget() instead.
739  *
740  * Deprecated: 2.4:
741  */
742 GtkWidget*
743 gtk_item_factory_get_item (GtkItemFactory *ifactory,
744                            const gchar    *path)
745 {
746   GtkWidget *widget;
747
748   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
749   g_return_val_if_fail (path != NULL, NULL);
750
751   widget = gtk_item_factory_get_widget (ifactory, path);
752
753   if (GTK_IS_MENU (widget))
754     widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
755
756   return GTK_IS_ITEM (widget) ? widget : NULL;
757 }
758
759
760 /**
761  * gtk_item_factory_get_item_by_action:
762  * @ifactory: a #GtkItemFactory
763  * @action: an action as specified in the @callback_action field
764  *   of #GtkItemFactoryEntry
765  * @returns: the menu item which corresponds to the given action, or %NULL
766  *   if no menu item was found
767  *
768  * Obtains the menu item which was constructed from the first 
769  * #GtkItemFactoryEntry with the given @action.
770  *
771  * Deprecated: 2.4:
772  */
773 GtkWidget*
774 gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory,
775                                      guint           action)
776 {
777   GtkWidget *widget;
778
779   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
780
781   widget = gtk_item_factory_get_widget_by_action (ifactory, action);
782
783   if (GTK_IS_MENU (widget))
784     widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
785
786   return GTK_IS_ITEM (widget) ? widget : NULL;
787 }
788
789 static char *
790 item_factory_find_separator_r (char *path)
791 {
792   gchar *result = NULL;
793   gboolean escaped = FALSE;
794
795   while (*path)
796     {
797       if (escaped)
798         escaped = FALSE;
799       else
800         {
801           if (*path == '\\')
802             escaped = TRUE;
803           else if (*path == '/')
804             result = path;
805         }
806       
807       path++;
808     }
809
810   return result;
811 }
812
813 static char *
814 item_factory_unescape_label (const char *label)
815 {
816   char *new = g_malloc (strlen (label) + 1);
817   char *p = new;
818   gboolean escaped = FALSE;
819   
820   while (*label)
821     {
822       if (escaped)
823         {
824           *p++ = *label;
825           escaped = FALSE;
826         }
827       else
828         {
829           if (*label == '\\')
830             escaped = TRUE;
831           else
832             *p++ = *label;
833         }
834       
835       label++;
836     }
837
838   *p = '\0';
839
840   return new;
841 }
842
843 static gboolean
844 gtk_item_factory_parse_path (GtkItemFactory *ifactory,
845                              gchar          *str,
846                              gchar         **path,
847                              gchar         **parent_path,
848                              gchar         **item)
849 {
850   gchar *translation;
851   gchar *p, *q;
852   
853   *path = g_strdup (str);
854
855   p = q = *path;
856   while (*p)
857     {
858       if (*p == '_')
859         {
860           if (p[1] == '_')
861             {
862               p++;
863               *q++ = '_';
864             }
865         }
866       else
867         {
868           *q++ = *p;
869         }
870       p++;
871     }
872   *q = 0;
873
874   *parent_path = g_strdup (*path);
875   p = item_factory_find_separator_r (*parent_path);
876   if (!p)
877     {
878       g_warning ("GtkItemFactory: invalid entry path `%s'", str);
879       return FALSE;
880     }
881   *p = 0;
882
883   if (ifactory->translate_func)
884     translation = ifactory->translate_func (str, ifactory->translate_data);
885   else
886     translation = str;
887                               
888   p = item_factory_find_separator_r (translation);
889   if (p)
890     p++;
891   else
892     p = translation;
893
894   *item = item_factory_unescape_label (p);
895
896   return TRUE;
897 }
898
899 /**
900  * gtk_item_factory_create_item:
901  * @ifactory: a #GtkItemFactory
902  * @entry: the #GtkItemFactoryEntry to create an item for
903  * @callback_data: data passed to the callback function of @entry
904  * @callback_type: 1 if the callback function of @entry is of type
905  *    #GtkItemFactoryCallback1, 2 if it is of type #GtkItemFactoryCallback2 
906  *
907  * Creates an item for @entry.
908  *
909  * Deprecated: 2.4:
910  */
911 void
912 gtk_item_factory_create_item (GtkItemFactory         *ifactory,
913                               GtkItemFactoryEntry    *entry,
914                               gpointer                callback_data,
915                               guint                   callback_type)
916 {
917   GtkOptionMenu *option_menu = NULL;
918   GtkWidget *parent;
919   GtkWidget *widget;
920   GtkWidget *image;
921   GSList *radio_group;
922   gchar *name;
923   gchar *parent_path;
924   gchar *path;
925   gchar *accelerator;
926   guint type_id;
927   GType type;
928   gchar *item_type_path;
929   GtkStockItem stock_item;
930       
931   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
932   g_return_if_fail (entry != NULL);
933   g_return_if_fail (entry->path != NULL);
934   g_return_if_fail (entry->path[0] == '/');
935   g_return_if_fail (callback_type >= 1 && callback_type <= 2);
936
937   if (!entry->item_type ||
938       entry->item_type[0] == 0)
939     {
940       item_type_path = "<Item>";
941       type_id = quark_type_item;
942     }
943   else
944     {
945       item_type_path = entry->item_type;
946       type_id = g_quark_try_string (item_type_path);
947     }
948
949   radio_group = NULL;
950   if (type_id == quark_type_item)
951     type = GTK_TYPE_MENU_ITEM;
952   else if (type_id == quark_type_title)
953     type = GTK_TYPE_MENU_ITEM;
954   else if (type_id == quark_type_radio_item)
955     type = GTK_TYPE_RADIO_MENU_ITEM;
956   else if (type_id == quark_type_check_item)
957     type = GTK_TYPE_CHECK_MENU_ITEM;
958   else if (type_id == quark_type_image_item)
959     type = GTK_TYPE_IMAGE_MENU_ITEM;
960   else if (type_id == quark_type_stock_item)
961     type = GTK_TYPE_IMAGE_MENU_ITEM;
962   else if (type_id == quark_type_tearoff_item)
963     type = GTK_TYPE_TEAROFF_MENU_ITEM;
964   else if (type_id == quark_type_toggle_item)
965     type = GTK_TYPE_CHECK_MENU_ITEM;
966   else if (type_id == quark_type_separator_item)
967     type = GTK_TYPE_MENU_ITEM;
968   else if (type_id == quark_type_branch)
969     type = GTK_TYPE_MENU_ITEM;
970   else if (type_id == quark_type_last_branch)
971     type = GTK_TYPE_MENU_ITEM;
972   else
973     {
974       GtkWidget *radio_link;
975
976       radio_link = gtk_item_factory_get_widget (ifactory, item_type_path);
977       if (radio_link && GTK_IS_RADIO_MENU_ITEM (radio_link))
978         {
979           type = GTK_TYPE_RADIO_MENU_ITEM;
980           radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radio_link));
981         }
982       else
983         {
984           g_warning ("GtkItemFactory: entry path `%s' has invalid type `%s'",
985                      entry->path,
986                      item_type_path);
987           return;
988         }
989     }
990
991   if (!gtk_item_factory_parse_path (ifactory, entry->path, 
992                                     &path, &parent_path, &name))
993     return;
994
995   parent = gtk_item_factory_get_widget (ifactory, parent_path);
996   if (!parent)
997     {
998       GtkItemFactoryEntry pentry;
999       gchar *ppath, *p;
1000
1001       ppath = g_strdup (entry->path);
1002       p = item_factory_find_separator_r (ppath);
1003       g_return_if_fail (p != NULL);
1004       *p = 0;
1005       pentry.path = ppath;
1006       pentry.accelerator = NULL;
1007       pentry.callback = NULL;
1008       pentry.callback_action = 0;
1009       pentry.item_type = "<Branch>";
1010
1011       gtk_item_factory_create_item (ifactory, &pentry, NULL, 1);
1012       g_free (ppath);
1013
1014       parent = gtk_item_factory_get_widget (ifactory, parent_path);
1015       g_return_if_fail (parent != NULL);
1016     }
1017
1018   if (GTK_IS_OPTION_MENU (parent))
1019     {
1020       option_menu = GTK_OPTION_MENU (parent);
1021       if (!option_menu->menu)
1022         {
1023           GtkWidget *menu = g_object_new (GTK_TYPE_MENU, NULL);
1024           gchar *p = g_strconcat (ifactory->path, parent_path, NULL);
1025
1026           gtk_menu_set_accel_path (GTK_MENU (menu), p);
1027           g_free (p);
1028           gtk_option_menu_set_menu (option_menu, menu);
1029         }
1030       parent = option_menu->menu;
1031     }
1032   g_free (parent_path);
1033                               
1034   g_return_if_fail (GTK_IS_CONTAINER (parent));
1035
1036   accelerator = entry->accelerator;
1037   
1038   widget = g_object_new (type,
1039                            "visible", TRUE,
1040                            "sensitive", (type_id != quark_type_separator_item &&
1041                                          type_id != quark_type_title),
1042                            "parent", parent,
1043                            NULL);
1044   if (option_menu && !option_menu->menu_item)
1045     gtk_option_menu_set_history (option_menu, 0);
1046
1047   if (GTK_IS_RADIO_MENU_ITEM (widget))
1048     gtk_radio_menu_item_set_group (GTK_RADIO_MENU_ITEM (widget), radio_group);
1049   if (type_id == quark_type_image_item)
1050     {
1051       GdkPixbuf *pixbuf = NULL;
1052       image = NULL;
1053       if (entry->extra_data)
1054         {
1055           pixbuf = gdk_pixbuf_new_from_inline (-1,
1056                                                entry->extra_data,
1057                                                FALSE,
1058                                                NULL);
1059           if (pixbuf)
1060             image = gtk_image_new_from_pixbuf (pixbuf);
1061         }
1062       if (image)
1063         {
1064           gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
1065           gtk_widget_show (image);
1066         }
1067       if (pixbuf)
1068         g_object_unref (pixbuf);
1069     }
1070   if (type_id == quark_type_stock_item)
1071     {
1072       image = gtk_image_new_from_stock (entry->extra_data, GTK_ICON_SIZE_MENU);
1073       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
1074       gtk_widget_show (image);
1075
1076       if (gtk_stock_lookup (entry->extra_data, &stock_item))
1077         {
1078           if (!accelerator)
1079             accelerator = gtk_accelerator_name (stock_item.keyval, stock_item.modifier);
1080         }
1081     }
1082
1083   /* install underline accelerators for this item
1084    */
1085   if (type_id != quark_type_separator_item && 
1086       type_id != quark_type_tearoff_item &&
1087       *name)
1088     {
1089       GtkWidget *label;
1090       
1091       label = g_object_new (GTK_TYPE_ACCEL_LABEL,
1092                               "visible", TRUE,
1093                               "parent", widget,
1094                               "accel-widget", widget,
1095                               "xalign", 0.0,
1096                               NULL);
1097       gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
1098     }
1099   
1100   g_free (name);
1101   
1102   if (type_id == quark_type_branch ||
1103       type_id == quark_type_last_branch)
1104     {
1105       gchar *p;
1106
1107       if (entry->callback)
1108         g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"",
1109                    entry->path);
1110       if (type_id == quark_type_last_branch)
1111         gtk_menu_item_set_right_justified (GTK_MENU_ITEM (widget), TRUE);
1112       
1113       parent = widget;
1114       widget = g_object_new (GTK_TYPE_MENU, NULL);
1115       p = g_strconcat (ifactory->path, path, NULL);
1116       gtk_menu_set_accel_path (GTK_MENU (widget), p);
1117       g_free (p);
1118       
1119       gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget);
1120     }      
1121   
1122   gtk_item_factory_add_item (ifactory,
1123                              path, accelerator,
1124                              (type_id == quark_type_branch ||
1125                               type_id == quark_type_last_branch) ?
1126                               (GtkItemFactoryCallback) NULL : entry->callback,
1127                              entry->callback_action, callback_data,
1128                              callback_type,
1129                              item_type_path,
1130                              widget);
1131   if (accelerator != entry->accelerator)
1132     g_free (accelerator);
1133   g_free (path);
1134 }
1135
1136 /**
1137  * gtk_item_factory_create_menu_entries:
1138  * @n_entries: the length of @entries
1139  * @entries: an array of #GtkMenuEntry<!-- -->s 
1140  *
1141  * Creates the menu items from the @entries.
1142  *
1143  * Deprecated: 2.4:
1144  */
1145 void
1146 gtk_item_factory_create_menu_entries (guint              n_entries,
1147                                       GtkMenuEntry      *entries)
1148 {
1149   static GPatternSpec *pspec_separator = NULL;
1150   static GPatternSpec *pspec_check = NULL;
1151   guint i;
1152
1153   if (!n_entries)
1154     return;
1155   g_return_if_fail (entries != NULL);
1156
1157   if (!pspec_separator)
1158     {
1159       pspec_separator = g_pattern_spec_new ("*<separator>*");
1160       pspec_check = g_pattern_spec_new ("*<check>*");
1161     }
1162
1163   for (i = 0; i < n_entries; i++)
1164     {
1165       GtkItemFactory *ifactory;
1166       GtkItemFactoryEntry entry;
1167       gchar *path;
1168       gchar *cpath;
1169
1170       path = entries[i].path;
1171       ifactory = gtk_item_factory_from_path (path);
1172       if (!ifactory)
1173         {
1174           g_warning ("gtk_item_factory_create_menu_entries(): "
1175                      "entry[%u] refers to unknown item factory: \"%s\"",
1176                      i, entries[i].path);
1177           continue;
1178         }
1179
1180       while (*path != '>')
1181         path++;
1182       path++;
1183       cpath = NULL;
1184
1185       entry.path = path;
1186       entry.accelerator = entries[i].accelerator;
1187       entry.callback = entries[i].callback;
1188       entry.callback_action = 0;
1189       if (g_pattern_match_string (pspec_separator, path))
1190         entry.item_type = "<Separator>";
1191       else if (!g_pattern_match_string (pspec_check, path))
1192         entry.item_type = NULL;
1193       else
1194         {
1195           gboolean in_brace = FALSE;
1196           gchar *c;
1197           
1198           cpath = g_new (gchar, strlen (path));
1199           c = cpath;
1200           while (*path != 0)
1201             {
1202               if (*path == '<')
1203                 in_brace = TRUE;
1204               else if (*path == '>')
1205                 in_brace = FALSE;
1206               else if (!in_brace)
1207                 *(c++) = *path;
1208               path++;
1209             }
1210           *c = 0;
1211           entry.item_type = "<ToggleItem>";
1212           entry.path = cpath;
1213         }
1214       
1215       gtk_item_factory_create_item (ifactory, &entry, entries[i].callback_data, 2);
1216       entries[i].widget = gtk_item_factory_get_widget (ifactory, entries[i].path);
1217       g_free (cpath);
1218     }
1219 }
1220
1221 /**
1222  * gtk_item_factories_path_delete:
1223  * @ifactory_path: a factory path to prepend to @path. May be %NULL if @path
1224  *   starts with a factory path
1225  * @path: a path 
1226  * 
1227  * Deletes all widgets constructed from the specified path.
1228  *
1229  * Deprecated: 2.4:
1230  */
1231 void
1232 gtk_item_factories_path_delete (const gchar *ifactory_path,
1233                                 const gchar *path)
1234 {
1235   GtkItemFactoryClass *class;
1236   GtkItemFactoryItem *item;
1237
1238   g_return_if_fail (path != NULL);
1239
1240   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
1241
1242   if (path[0] == '<')
1243     item = g_hash_table_lookup (class->item_ht, (gpointer) path);
1244   else
1245     {
1246       gchar *fpath;
1247
1248       g_return_if_fail (ifactory_path != NULL);
1249       
1250       fpath = g_strconcat (ifactory_path, path, NULL);
1251       item = g_hash_table_lookup (class->item_ht, fpath);
1252       g_free (fpath);
1253     }
1254   
1255   if (item)
1256     {
1257       GSList *widget_list;
1258       GSList *slist;
1259
1260       widget_list = NULL;
1261       for (slist = item->widgets; slist; slist = slist->next)
1262         {
1263           GtkWidget *widget;
1264
1265           widget = slist->data;
1266           widget_list = g_slist_prepend (widget_list, widget);
1267           g_object_ref (widget);
1268         }
1269
1270       for (slist = widget_list; slist; slist = slist->next)
1271         {
1272           GtkWidget *widget;
1273
1274           widget = slist->data;
1275           gtk_widget_destroy (widget);
1276           g_object_unref (widget);
1277         }
1278       g_slist_free (widget_list);
1279     }
1280 }
1281
1282 /**
1283  * gtk_item_factory_delete_item:
1284  * @ifactory: a #GtkItemFactory
1285  * @path: a path
1286  *
1287  * Deletes the menu item which was created for @path by the given
1288  * item factory.
1289  *
1290  * Deprecated: 2.4:
1291  */
1292 void
1293 gtk_item_factory_delete_item (GtkItemFactory         *ifactory,
1294                               const gchar            *path)
1295 {
1296   GtkWidget *widget;
1297
1298   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1299   g_return_if_fail (path != NULL);
1300
1301   widget = gtk_item_factory_get_widget (ifactory, path);
1302
1303   if (widget)
1304     {
1305       if (GTK_IS_MENU (widget))
1306         widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
1307
1308       gtk_widget_destroy (widget);
1309     }
1310 }
1311
1312 /**
1313  * gtk_item_factory_delete_entry:
1314  * @ifactory: a #GtkItemFactory
1315  * @entry: a #GtkItemFactoryEntry
1316  *
1317  * Deletes the menu item which was created from @entry by the given
1318  * item factory.
1319  *
1320  * Deprecated: 2.4:
1321  */
1322 void
1323 gtk_item_factory_delete_entry (GtkItemFactory         *ifactory,
1324                                GtkItemFactoryEntry    *entry)
1325 {
1326   gchar *path;
1327   gchar *parent_path;
1328   gchar *name;
1329
1330   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1331   g_return_if_fail (entry != NULL);
1332   g_return_if_fail (entry->path != NULL);
1333   g_return_if_fail (entry->path[0] == '/');
1334
1335   if (!gtk_item_factory_parse_path (ifactory, entry->path, 
1336                                     &path, &parent_path, &name))
1337     return;
1338   
1339   gtk_item_factory_delete_item (ifactory, path);
1340
1341   g_free (path);
1342   g_free (parent_path);
1343   g_free (name);
1344 }
1345
1346 /**
1347  * gtk_item_factory_delete_entries:
1348  * @ifactory: a #GtkItemFactory
1349  * @n_entries: the length of @entries
1350  * @entries: an array of #GtkItemFactoryEntry<!-- -->s 
1351  *
1352  * Deletes the menu items which were created from the @entries by the given
1353  * item factory.
1354  *
1355  * Deprecated: 2.4:
1356  */
1357 void
1358 gtk_item_factory_delete_entries (GtkItemFactory         *ifactory,
1359                                  guint                   n_entries,
1360                                  GtkItemFactoryEntry    *entries)
1361 {
1362   guint i;
1363
1364   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1365   if (n_entries > 0)
1366     g_return_if_fail (entries != NULL);
1367
1368   for (i = 0; i < n_entries; i++)
1369     gtk_item_factory_delete_entry (ifactory, entries + i);
1370 }
1371
1372 typedef struct
1373 {
1374   guint x;
1375   guint y;
1376 } MenuPos;
1377
1378 static void
1379 gtk_item_factory_menu_pos (GtkMenu  *menu,
1380                            gint     *x,
1381                            gint     *y,
1382                            gboolean *push_in,
1383                            gpointer  func_data)
1384 {
1385   MenuPos *mpos = func_data;
1386
1387   *x = mpos->x;
1388   *y = mpos->y;
1389 }
1390
1391 /**
1392  * gtk_item_factory_popup_data_from_widget:
1393  * @widget: a widget
1394  * @returns: @popup_data associated with the item factory from
1395  *   which @widget was created, or %NULL if @widget wasn't created
1396  *   by an item factory
1397  *
1398  * Obtains the @popup_data which was passed to 
1399  * gtk_item_factory_popup_with_data(). This data is available until the menu
1400  * is popped down again.
1401  *
1402  * Deprecated: 2.4:
1403  */
1404 gpointer
1405 gtk_item_factory_popup_data_from_widget (GtkWidget *widget)
1406 {
1407   GtkItemFactory *ifactory;
1408   
1409   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1410
1411   ifactory = gtk_item_factory_from_widget (widget);
1412   if (ifactory)
1413     return g_object_get_qdata (G_OBJECT (ifactory), quark_popup_data);
1414
1415   return NULL;
1416 }
1417
1418 /**
1419  * gtk_item_factory_popup_data:
1420  * @ifactory: a #GtkItemFactory
1421  * @returns: @popup_data associated with @ifactory
1422  *
1423  * Obtains the @popup_data which was passed to 
1424  * gtk_item_factory_popup_with_data(). This data is available until the menu
1425  * is popped down again.
1426  *
1427  * Deprecated: 2.4:
1428  */
1429 gpointer
1430 gtk_item_factory_popup_data (GtkItemFactory *ifactory)
1431 {
1432   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
1433
1434   return g_object_get_qdata (G_OBJECT (ifactory), quark_popup_data);
1435 }
1436
1437 static void
1438 ifactory_delete_popup_data (GtkObject      *object,
1439                             GtkItemFactory *ifactory)
1440 {
1441   g_signal_handlers_disconnect_by_func (object,
1442                                         ifactory_delete_popup_data,
1443                                         ifactory);
1444   g_object_set_qdata (G_OBJECT (ifactory), quark_popup_data, NULL);
1445 }
1446
1447 /**
1448  * gtk_item_factory_popup:
1449  * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
1450  * @x: the x position 
1451  * @y: the y position
1452  * @mouse_button: the mouse button which was pressed to initiate the popup
1453  * @time_: the time at which the activation event occurred
1454  *
1455  * Pops up the menu constructed from the item factory at (@x, @y).
1456  *
1457  * The @mouse_button parameter should be the mouse button pressed to initiate
1458  * the menu popup. If the menu popup was initiated by something other than
1459  * a mouse button press, such as a mouse button release or a keypress,
1460  * @mouse_button should be 0.
1461  *
1462  * The @time_ parameter should be the time stamp of the event that
1463  * initiated the popup. If such an event is not available, use
1464  * gtk_get_current_event_time() instead.
1465  *
1466  * The operation of the @mouse_button and the @time_ parameter is the same
1467  * as the @button and @activation_time parameters for gtk_menu_popup().
1468  *
1469  * Deprecated: 2.4:
1470  */
1471 void
1472 gtk_item_factory_popup (GtkItemFactory          *ifactory,
1473                         guint                    x,
1474                         guint                    y,
1475                         guint                    mouse_button,
1476                         guint32                  time)
1477 {
1478   gtk_item_factory_popup_with_data (ifactory, NULL, NULL, x, y, mouse_button, time);
1479 }
1480
1481 /**
1482  * gtk_item_factory_popup_with_data:
1483  * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
1484  * @popup_data: data available for callbacks while the menu is posted
1485  * @destroy: a #GtkDestroyNotify function to be called on @popup_data when
1486  *  the menu is unposted
1487  * @x: the x position 
1488  * @y: the y position
1489  * @mouse_button: the mouse button which was pressed to initiate the popup
1490  * @time_: the time at which the activation event occurred
1491  *
1492  * Pops up the menu constructed from the item factory at (@x, @y). Callbacks
1493  * can access the @popup_data while the menu is posted via 
1494  * gtk_item_factory_popup_data() and gtk_item_factory_popup_data_from_widget().
1495  *
1496  * The @mouse_button parameter should be the mouse button pressed to initiate
1497  * the menu popup. If the menu popup was initiated by something other than
1498  * a mouse button press, such as a mouse button release or a keypress,
1499  * @mouse_button should be 0.
1500  *
1501  * The @time_ parameter should be the time stamp of the event that
1502  * initiated the popup. If such an event is not available, use
1503  * gtk_get_current_event_time() instead.
1504  *
1505  * The operation of the @mouse_button and the @time_ parameters is the same
1506  * as the @button and @activation_time parameters for gtk_menu_popup().
1507  *
1508  * Deprecated: 2.4:
1509  */
1510 void
1511 gtk_item_factory_popup_with_data (GtkItemFactory        *ifactory,
1512                                   gpointer               popup_data,
1513                                   GtkDestroyNotify       destroy,
1514                                   guint                  x,
1515                                   guint                  y,
1516                                   guint                  mouse_button,
1517                                   guint32                time)
1518 {
1519   MenuPos *mpos;
1520
1521   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1522   g_return_if_fail (GTK_IS_MENU (ifactory->widget));
1523   
1524   mpos = g_object_get_qdata (G_OBJECT (ifactory->widget), quark_if_menu_pos);
1525   
1526   if (!mpos)
1527     {
1528       mpos = g_new0 (MenuPos, 1);
1529       g_object_set_qdata_full (G_OBJECT (ifactory->widget),
1530                                quark_if_menu_pos,
1531                                mpos,
1532                                g_free);
1533     }
1534   
1535   mpos->x = x;
1536   mpos->y = y;
1537   
1538   if (popup_data != NULL)
1539     {
1540       g_object_set_qdata_full (G_OBJECT (ifactory),
1541                                quark_popup_data,
1542                                popup_data,
1543                                destroy);
1544       g_signal_connect (ifactory->widget,
1545                         "selection-done",
1546                         G_CALLBACK (ifactory_delete_popup_data),
1547                         ifactory);
1548     }
1549   
1550   gtk_menu_popup (GTK_MENU (ifactory->widget),
1551                   NULL, NULL,
1552                   gtk_item_factory_menu_pos, mpos,
1553                   mouse_button, time);
1554 }
1555
1556 /**
1557  * gtk_item_factory_set_translate_func:
1558  * @ifactory: a #GtkItemFactory
1559  * @func: the #GtkTranslateFunc function to be used to translate path elements 
1560  * @data: data to pass to @func and @notify
1561  * @notify: a #GtkDestroyNotify function to be called when @ifactory is 
1562  *   destroyed and when the translation function is changed again
1563  * 
1564  * Sets a function to be used for translating the path elements before they
1565  * are displayed. 
1566  *
1567  * Deprecated: 2.4:
1568  */ 
1569 void
1570 gtk_item_factory_set_translate_func (GtkItemFactory      *ifactory,
1571                                      GtkTranslateFunc     func,
1572                                      gpointer             data,
1573                                      GtkDestroyNotify     notify)
1574 {
1575   g_return_if_fail (ifactory != NULL);
1576   
1577   if (ifactory->translate_notify)
1578     ifactory->translate_notify (ifactory->translate_data);
1579       
1580   ifactory->translate_func = func;
1581   ifactory->translate_data = data;
1582   ifactory->translate_notify = notify;
1583 }
1584
1585 #define __GTK_ITEM_FACTORY_C__
1586 #include "gtkaliasdef.c"