]> Pileus Git - ~andy/gtk/blob - gtk/gtkbuilder.c
Add GtkBubbleWindow
[~andy/gtk] / gtk / gtkbuilder.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1998-2002 James Henstridge <james@daa.com.au>
3  * Copyright (C) 2006-2007 Async Open Source,
4  *                         Johan Dahlin <jdahlin@async.com.br>,
5  *                         Henrique Romano <henrique@async.com.br>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /**
22  * SECTION:gtkbuilder
23  * @Short_description: Build an interface from an XML UI definition
24  * @Title: GtkBuilder
25  *
26  * A GtkBuilder is an auxiliary object that reads textual descriptions
27  * of a user interface and instantiates the described objects. To pass a
28  * description to a GtkBuilder, call gtk_builder_add_from_file() or
29  * gtk_builder_add_from_string(). These functions can be called multiple
30  * times; the builder merges the content of all descriptions.
31  *
32  * A GtkBuilder holds a reference to all objects that it has constructed
33  * and drops these references when it is finalized. This finalization can
34  * cause the destruction of non-widget objects or widgets which are not
35  * contained in a toplevel window. For toplevel windows constructed by a
36  * builder, it is the responsibility of the user to call gtk_widget_destroy()
37  * to get rid of them and all the widgets they contain.
38  *
39  * The functions gtk_builder_get_object() and gtk_builder_get_objects()
40  * can be used to access the widgets in the interface by the names assigned
41  * to them inside the UI description. Toplevel windows returned by these
42  * functions will stay around until the user explicitly destroys them
43  * with gtk_widget_destroy(). Other widgets will either be part of a
44  * larger hierarchy constructed by the builder (in which case you should
45  * not have to worry about their lifecycle), or without a parent, in which
46  * case they have to be added to some container to make use of them.
47  * Non-widget objects need to be reffed with g_object_ref() to keep them
48  * beyond the lifespan of the builder.
49  *
50  * The function gtk_builder_connect_signals() and variants thereof can be
51  * used to connect handlers to the named signals in the description.
52  *
53  * <refsect2 id="BUILDER-UI">
54  * <title>GtkBuilder UI Definitions</title>
55  * <para>
56  * GtkBuilder parses textual descriptions of user interfaces which are specified
57  * in an XML format which can be roughly described by the RELAX NG schema below.
58  * We refer to these descriptions as <firstterm>GtkBuilder UI definitions</firstterm>
59  * or just <firstterm>UI definitions</firstterm> if the context is clear. Do not
60  * confuse GtkBuilder UI Definitions with
61  * <link linkend="XML-UI">GtkUIManager UI Definitions</link>, which are more
62  * limited in scope. It is common to use <filename>.ui</filename> as the filename extension for files containing GtkBuilder UI definitions.
63  * </para>
64  * <programlisting>
65  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/gtkbuilder.rnc">
66  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
67  * </xi:include>
68  * </programlisting>
69  * <para>
70  * The toplevel element is &lt;interface&gt;. It optionally takes a "domain"
71  * attribute, which will make the builder look for translated strings using
72  * dgettext() in the domain specified. This can also be done by calling
73  * gtk_builder_set_translation_domain() on the builder. Objects are described by
74  * &lt;object&gt; elements, which can contain &lt;property&gt; elements to set
75  * properties, &lt;signal&gt; elements which connect signals to handlers, and
76  * &lt;child&gt; elements, which describe child objects (most often widgets
77  * inside a container, but also e.g. actions in an action group, or columns in a
78  * tree model). A &lt;child&gt; element contains an &lt;object&gt; element which
79  * describes the child object. The target toolkit version(s) are described by
80  * &lt;requires&gt; elements, the "lib" attribute specifies the widget library
81  * in question (currently the only supported value is "gtk+") and the "version"
82  * attribute specifies the target version in the form
83  * "&lt;major&gt;.&lt;minor&gt;". The builder will error out if the version
84  * requirements are not met.
85  *
86  * Typically, the specific kind of object represented by an &lt;object&gt;
87  * element is specified by the "class" attribute. If the type has not been
88  * loaded yet, GTK+ tries to find the <function>_get_type()</function> from the
89  * class name by applying heuristics. This works in most cases, but if
90  * necessary, it is possible to specify the name of the
91  * <function>_get_type()</function> explictly with the "type-func" attribute.
92  * As a special case, GtkBuilder allows to use an object that has been
93  * constructed by a #GtkUIManager in another part of the UI definition by
94  * specifying the id of the #GtkUIManager in the "constructor" attribute and the
95  * name of the object in the "id" attribute.
96  *
97  * Objects must be given a name with the "id" attribute, which allows the
98  * application to retrieve them from the builder with gtk_builder_get_object().
99  * An id is also necessary to use the object as property value in other parts of
100  * the UI definition.
101  * </para>
102  * <note><para>
103  * Prior to 2.20, GtkBuilder was setting the "name" property of constructed widgets to the
104  * "id" attribute. In GTK+ 2.20 or newer, you have to use gtk_buildable_get_name() instead
105  * of gtk_widget_get_name() to obtain the "id", or set the "name" property in your UI
106  * definition.
107  * </para></note>
108  * <para>
109  * Setting properties of objects is pretty straightforward with the
110  * &lt;property&gt; element: the "name" attribute specifies the name of the
111  * property, and the content of the element specifies the value. If the
112  * "translatable" attribute is set to a true value, GTK+ uses gettext() (or
113  * dgettext() if the builder has a translation domain set) to find a translation
114  * for the value. This happens before the value is parsed, so it can be used for
115  * properties of any type, but it is probably most useful for string properties.
116  * It is also possible to specify a context to disambiguate short strings, and
117  * comments which may help the translators.
118  *
119  * GtkBuilder can parse textual representations for the most common property
120  * types: characters, strings, integers, floating-point numbers, booleans
121  * (strings like "TRUE", "t", "yes", "y", "1" are interpreted as %TRUE, strings
122  * like "FALSE, "f", "no", "n", "0" are interpreted as %FALSE), enumerations
123  * (can be specified by their name, nick or integer value), flags (can be
124  * specified by their name, nick, integer value, optionally combined with "|",
125  * e.g. "GTK_VISIBLE|GTK_REALIZED")  and colors (in a format understood by
126  * gdk_color_parse()). Pixbufs can be specified as a filename of an image file to load. 
127  * Objects can be referred to by their name and by default refer to objects declared
128  * in the local xml fragment and objects exposed via gtk_builder_expose_object().
129  * 
130  * In general, GtkBuilder allows forward references to objects &mdash declared
131  * in the local xml; an object doesn't have to be constructed before it can be referred to. 
132  * The exception to this rule is that an object has to be constructed before 
133  * it can be used as the value of a construct-only property.
134  *
135  * Signal handlers are set up with the &lt;signal&gt; element. The "name"
136  * attribute specifies the name of the signal, and the "handler" attribute
137  * specifies the function to connect to the signal. By default, GTK+ tries to
138  * find the handler using g_module_symbol(), but this can be changed by passing
139  * a custom #GtkBuilderConnectFunc to gtk_builder_connect_signals_full(). The
140  * remaining attributes, "after", "swapped" and "object", have the same meaning
141  * as the corresponding parameters of the g_signal_connect_object() or
142  * g_signal_connect_data() functions. A "last_modification_time" attribute
143  * is also allowed, but it does not have a meaning to the builder.
144  *
145  * Sometimes it is necessary to refer to widgets which have implicitly been
146  * constructed by GTK+ as part of a composite widget, to set properties on them
147  * or to add further children (e.g. the @vbox of a #GtkDialog). This can be
148  * achieved by setting the "internal-child" propery of the &lt;child&gt; element
149  * to a true value. Note that GtkBuilder still requires an &lt;object&gt;
150  * element for the internal child, even if it has already been constructed.
151  *
152  * A number of widgets have different places where a child can be added (e.g.
153  * tabs vs. page content in notebooks). This can be reflected in a UI definition
154  * by specifying the "type" attribute on a &lt;child&gt;. The possible values
155  * for the "type" attribute are described in the sections describing the
156  * widget-specific portions of UI definitions.
157  * </para>
158  * <example>
159  * <title>A GtkBuilder UI Definition</title>
160  * <programlisting><![CDATA[
161  * <interface>
162  *   <object class="GtkDialog" id="dialog1">
163  *     <child internal-child="vbox">
164  *       <object class="GtkVBox" id="vbox1">
165  *         <property name="border-width">10</property>
166  *         <child internal-child="action_area">
167  *           <object class="GtkHButtonBox" id="hbuttonbox1">
168  *             <property name="border-width">20</property>
169  *             <child>
170  *               <object class="GtkButton" id="ok_button">
171  *                 <property name="label">gtk-ok</property>
172  *                 <property name="use-stock">TRUE</property>
173  *                 <signal name="clicked" handler="ok_button_clicked"/>
174  *               </object>
175  *             </child>
176  *           </object>
177  *         </child>
178  *       </object>
179  *     </child>
180  *   </object>
181  * </interface>
182  * ]]></programlisting>
183  * </example>
184  * <para>
185  * Beyond this general structure, several object classes define their own XML
186  * DTD fragments for filling in the ANY placeholders in the DTD above. Note that
187  * a custom element in a &lt;child&gt; element gets parsed by the custom tag
188  * handler of the parent object, while a custom element in an &lt;object&gt;
189  * element gets parsed by the custom tag handler of the object.
190  *
191  * These XML fragments are explained in the documentation of the respective
192  * objects, see
193  * <link linkend="GtkWidget-BUILDER-UI">GtkWidget</link>,
194  * <link linkend="GtkLabel-BUILDER-UI">GtkLabel</link>,
195  * <link linkend="GtkWindow-BUILDER-UI">GtkWindow</link>,
196  * <link linkend="GtkContainer-BUILDER-UI">GtkContainer</link>,
197  * <link linkend="GtkDialog-BUILDER-UI">GtkDialog</link>,
198  * <link linkend="GtkCellLayout-BUILDER-UI">GtkCellLayout</link>,
199  * <link linkend="GtkColorSelectionDialog-BUILDER-UI">GtkColorSelectionDialog</link>,
200  * <link linkend="GtkFontSelectionDialog-BUILDER-UI">GtkFontSelectionDialog</link>,
201  * <link linkend="GtkExpander-BUILDER-UI">GtkExpander</link>,
202  * <link linkend="GtkFrame-BUILDER-UI">GtkFrame</link>,
203  * <link linkend="GtkListStore-BUILDER-UI">GtkListStore</link>,
204  * <link linkend="GtkTreeStore-BUILDER-UI">GtkTreeStore</link>,
205  * <link linkend="GtkNotebook-BUILDER-UI">GtkNotebook</link>,
206  * <link linkend="GtkSizeGroup-BUILDER-UI">GtkSizeGroup</link>,
207  * <link linkend="GtkTreeView-BUILDER-UI">GtkTreeView</link>,
208  * <link linkend="GtkUIManager-BUILDER-UI">GtkUIManager</link>,
209  * <link linkend="GtkActionGroup-BUILDER-UI">GtkActionGroup</link>.
210  * <link linkend="GtkMenuItem-BUILDER-UI">GtkMenuItem</link>,
211  * <link linkend="GtkMenuToolButton-BUILDER-UI">GtkMenuToolButton</link>,
212  * <link linkend="GtkAssistant-BUILDER-UI">GtkAssistant</link>,
213  * <link linkend="GtkScale-BUILDER-UI">GtkScale</link>,
214  * <link linkend="GtkComboBoxText-BUILDER-UI">GtkComboBoxText</link>,
215  * <link linkend="GtkRecentFilter-BUILDER-UI">GtkRecentFilter</link>,
216  * <link linkend="GtkFileFilter-BUILDER-UI">GtkFileFilter</link>,
217  * <link linkend="GtkTextTagTable-BUILDER-UI">GtkTextTagTable</link>.
218  * </para>
219  * </refsect2>
220  * <refsect2>
221  * <title>Embedding other XML</title>
222  * <para>
223  * Apart from the language for UI descriptions that has been explained
224  * in the previous section, GtkBuilder can also parse XML fragments
225  * of <link linkend="gio-GMenu-Markup">GMenu markup</link>. The resulting
226  * #GMenu object and its named submenus are available via
227  * gtk_builder_get_object() like other constructed objects.
228  * </para>
229  * </refsect2>
230  */
231
232 #include "config.h"
233 #include <errno.h> /* errno */
234 #include <stdlib.h>
235 #include <string.h> /* strlen */
236
237 #include "gtkbuilder.h"
238 #include "gtkbuildable.h"
239 #include "gtkbuilderprivate.h"
240 #include "gtkdebug.h"
241 #include "gtkmain.h"
242 #include "gtkintl.h"
243 #include "gtkprivate.h"
244 #include "gtktypebuiltins.h"
245 #include "gtkwindow.h"
246 #include "gtkicontheme.h"
247 #include "gtkstock.h"
248
249
250 static void gtk_builder_class_init     (GtkBuilderClass *klass);
251 static void gtk_builder_init           (GtkBuilder      *builder);
252 static void gtk_builder_finalize       (GObject         *object);
253 static void gtk_builder_set_property   (GObject         *object,
254                                         guint            prop_id,
255                                         const GValue    *value,
256                                         GParamSpec      *pspec);
257 static void gtk_builder_get_property   (GObject         *object,
258                                         guint            prop_id,
259                                         GValue          *value,
260                                         GParamSpec      *pspec);
261 static GType gtk_builder_real_get_type_from_name (GtkBuilder  *builder,
262                                                   const gchar *type_name);
263
264 enum {
265   PROP_0,
266   PROP_TRANSLATION_DOMAIN,
267 };
268
269 struct _GtkBuilderPrivate
270 {
271   gchar *domain;
272   GHashTable *objects;
273   GSList *delayed_properties;
274   GSList *signals;
275   gchar *filename;
276   gchar *resource_prefix;
277 };
278
279 G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
280
281 static void
282 gtk_builder_class_init (GtkBuilderClass *klass)
283 {
284   GObjectClass *gobject_class;
285
286   gobject_class = G_OBJECT_CLASS (klass);
287
288   gobject_class->finalize = gtk_builder_finalize;
289   gobject_class->set_property = gtk_builder_set_property;
290   gobject_class->get_property = gtk_builder_get_property;
291
292   klass->get_type_from_name = gtk_builder_real_get_type_from_name;
293
294  /** 
295   * GtkBuilder:translation-domain:
296   *
297   * The translation domain used when translating property values that
298   * have been marked as translatable in interface descriptions.
299   * If the translation domain is %NULL, #GtkBuilder uses gettext(),
300   * otherwise g_dgettext().
301   *
302   * Since: 2.12
303   */
304   g_object_class_install_property (gobject_class,
305                                    PROP_TRANSLATION_DOMAIN,
306                                    g_param_spec_string ("translation-domain",
307                                                         P_("Translation Domain"),
308                                                         P_("The translation domain used by gettext"),
309                                                         NULL,
310                                                         GTK_PARAM_READWRITE));
311
312   g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
313 }
314
315 static void
316 gtk_builder_init (GtkBuilder *builder)
317 {
318   builder->priv = G_TYPE_INSTANCE_GET_PRIVATE (builder, GTK_TYPE_BUILDER,
319                                                GtkBuilderPrivate);
320   builder->priv->domain = NULL;
321   builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
322                                                   g_free, g_object_unref);
323 }
324
325
326 /*
327  * GObject virtual methods
328  */
329
330 static void
331 gtk_builder_finalize (GObject *object)
332 {
333   GtkBuilderPrivate *priv = GTK_BUILDER (object)->priv;
334   
335   g_free (priv->domain);
336   g_free (priv->filename);
337   g_free (priv->resource_prefix);
338   
339   g_hash_table_destroy (priv->objects);
340
341   g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
342   g_slist_free (priv->signals);
343   
344   G_OBJECT_CLASS (gtk_builder_parent_class)->finalize (object);
345 }
346
347 static void
348 gtk_builder_set_property (GObject      *object,
349                           guint         prop_id,
350                           const GValue *value,
351                           GParamSpec   *pspec)
352 {
353   GtkBuilder *builder = GTK_BUILDER (object);
354
355   switch (prop_id)
356     {
357     case PROP_TRANSLATION_DOMAIN:
358       gtk_builder_set_translation_domain (builder, g_value_get_string (value));
359       break;
360     default:
361       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
362       break;
363     }
364 }
365
366 static void
367 gtk_builder_get_property (GObject    *object,
368                           guint       prop_id,
369                           GValue     *value,
370                           GParamSpec *pspec)
371 {
372   GtkBuilder *builder = GTK_BUILDER (object);
373
374   switch (prop_id)
375     {
376     case PROP_TRANSLATION_DOMAIN:
377       g_value_set_string (value, builder->priv->domain);
378       break;
379     default:
380       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
381       break;
382     }
383 }
384
385
386 /*
387  * Try to map a type name to a _get_type function
388  * and call it, eg:
389  *
390  * GtkWindow -> gtk_window_get_type
391  * GtkHBox -> gtk_hbox_get_type
392  * GtkUIManager -> gtk_ui_manager_get_type
393  *
394  */
395 static GType
396 _gtk_builder_resolve_type_lazily (const gchar *name)
397 {
398   static GModule *module = NULL;
399   GTypeGetFunc func;
400   GString *symbol_name = g_string_new ("");
401   char c, *symbol;
402   int i;
403   GType gtype = G_TYPE_INVALID;
404
405   if (!module)
406     module = g_module_open (NULL, 0);
407   
408   for (i = 0; name[i] != '\0'; i++)
409     {
410       c = name[i];
411       /* skip if uppercase, first or previous is uppercase */
412       if ((c == g_ascii_toupper (c) &&
413            i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
414           (i > 2 && name[i]   == g_ascii_toupper (name[i]) &&
415            name[i-1] == g_ascii_toupper (name[i-1]) &&
416            name[i-2] == g_ascii_toupper (name[i-2])))
417         g_string_append_c (symbol_name, '_');
418       g_string_append_c (symbol_name, g_ascii_tolower (c));
419     }
420   g_string_append (symbol_name, "_get_type");
421   
422   symbol = g_string_free (symbol_name, FALSE);
423
424   if (g_module_symbol (module, symbol, (gpointer)&func))
425     gtype = func ();
426   
427   g_free (symbol);
428
429   return gtype;
430 }
431
432 /*
433  * GtkBuilder virtual methods
434  */
435
436 static GType
437 gtk_builder_real_get_type_from_name (GtkBuilder  *builder, 
438                                      const gchar *type_name)
439 {
440   GType gtype;
441
442   gtype = g_type_from_name (type_name);
443   if (gtype != G_TYPE_INVALID)
444     return gtype;
445
446   return _gtk_builder_resolve_type_lazily (type_name);
447 }
448
449 typedef struct
450 {
451   gchar *object;
452   gchar *name;
453   gchar *value;
454 } DelayedProperty;
455
456 static void
457 gtk_builder_get_parameters (GtkBuilder  *builder,
458                             GType        object_type,
459                             const gchar *object_name,
460                             GSList      *properties,
461                             GArray      **parameters,
462                             GArray      **construct_parameters)
463 {
464   GSList *l;
465   GParamSpec *pspec;
466   GObjectClass *oclass;
467   DelayedProperty *property;
468   GError *error = NULL;
469   
470   oclass = g_type_class_ref (object_type);
471   g_assert (oclass != NULL);
472
473   *parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
474   *construct_parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
475
476   for (l = properties; l; l = l->next)
477     {
478       PropertyInfo *prop = (PropertyInfo*)l->data;
479       GParameter parameter = { NULL };
480
481       pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
482                                             prop->name);
483       if (!pspec)
484         {
485           g_warning ("Unknown property: %s.%s",
486                      g_type_name (object_type), prop->name);
487           continue;
488         }
489
490       parameter.name = prop->name;
491
492       if (G_IS_PARAM_SPEC_OBJECT (pspec) &&
493           (G_PARAM_SPEC_VALUE_TYPE (pspec) != GDK_TYPE_PIXBUF))
494         {
495           GObject *object = gtk_builder_get_object (builder, prop->data);
496
497           if (object)
498             {
499               g_value_init (&parameter.value, G_OBJECT_TYPE (object));
500               g_value_set_object (&parameter.value, object);
501             }
502           else 
503             {
504               if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
505                 {
506                   g_warning ("Failed to get constuct only property "
507                              "%s of %s with value `%s'",
508                              prop->name, object_name, prop->data);
509                   continue;
510                 }
511               /* Delay setting property */
512               property = g_slice_new (DelayedProperty);
513               property->object = g_strdup (object_name);
514               property->name = g_strdup (prop->name);
515               property->value = g_strdup (prop->data);
516               builder->priv->delayed_properties =
517                 g_slist_prepend (builder->priv->delayed_properties, property);
518               continue;
519             }
520         }
521       else if (!gtk_builder_value_from_string (builder, pspec,
522                                                prop->data, &parameter.value, &error))
523         {
524           g_warning ("Failed to set property %s.%s to %s: %s",
525                      g_type_name (object_type), prop->name, prop->data,
526                      error->message);
527           g_error_free (error);
528           error = NULL;
529           continue;
530         }
531
532       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
533         g_array_append_val (*construct_parameters, parameter);
534       else
535         g_array_append_val (*parameters, parameter);
536     }
537
538   g_type_class_unref (oclass);
539 }
540
541 static GObject *
542 gtk_builder_get_internal_child (GtkBuilder  *builder,
543                                 ObjectInfo  *info,
544                                 const gchar *childname,
545                                 GError      **error)
546 {
547   GObject *obj = NULL;
548
549   while (!obj)
550     {
551       if (!info->parent)
552         break;
553
554       info = (ObjectInfo*)((ChildInfo*)info->parent)->parent;
555       if (!info)
556         break;
557
558       GTK_NOTE (BUILDER,
559                 g_print ("Trying to get internal child %s from %s\n",
560                          childname,
561                          gtk_buildable_get_name (GTK_BUILDABLE (info->object))));
562
563       if (GTK_IS_BUILDABLE (info->object))
564           obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
565                                                   builder,
566                                                   childname);
567     };
568
569   if (!obj)
570     {
571       g_set_error (error,
572                    GTK_BUILDER_ERROR,
573                    GTK_BUILDER_ERROR_INVALID_VALUE,
574                    "Unknown internal child: %s", childname);
575     }
576   return obj;
577 }
578
579 static inline void
580 object_set_name (GObject *object, const gchar *name)
581 {
582   if (GTK_IS_BUILDABLE (object))
583     gtk_buildable_set_name (GTK_BUILDABLE (object), name);
584   else
585     g_object_set_data_full (object, "gtk-builder-name", g_strdup (name), g_free);
586 }
587
588 void
589 _gtk_builder_add_object (GtkBuilder  *builder,
590                          const gchar *id,
591                          GObject     *object)
592 {
593   object_set_name (object, id);
594   g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object));
595 }
596
597 GObject *
598 _gtk_builder_construct (GtkBuilder *builder,
599                         ObjectInfo *info,
600                         GError **error)
601 {
602   GArray *parameters, *construct_parameters;
603   GType object_type;
604   GObject *obj;
605   int i;
606   GtkBuildableIface *iface;
607   gboolean custom_set_property;
608   GtkBuildable *buildable;
609
610   g_assert (info->class_name != NULL);
611   object_type = gtk_builder_get_type_from_name (builder, info->class_name);
612   if (object_type == G_TYPE_INVALID)
613     {
614       g_set_error (error,
615                    GTK_BUILDER_ERROR,
616                    GTK_BUILDER_ERROR_INVALID_VALUE,
617                    "Invalid object type `%s'",
618                    info->class_name);
619       return NULL;
620     }
621
622   gtk_builder_get_parameters (builder, object_type,
623                               info->id,
624                               info->properties,
625                               &parameters,
626                               &construct_parameters);
627
628   if (info->constructor)
629     {
630       GObject *constructor;
631
632       constructor = gtk_builder_get_object (builder, info->constructor);
633       if (constructor == NULL)
634         {
635           g_set_error (error,
636                        GTK_BUILDER_ERROR,
637                        GTK_BUILDER_ERROR_INVALID_VALUE,
638                        "Unknown object constructor for %s: %s",
639                        info->id,
640                        info->constructor);
641           g_array_free (parameters, TRUE);
642           g_array_free (construct_parameters, TRUE);
643           return NULL;
644         }
645       obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
646                                            builder,
647                                            info->id);
648       g_assert (obj != NULL);
649       if (construct_parameters->len)
650         g_warning ("Can't pass in construct-only parameters to %s", info->id);
651     }
652   else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
653     {
654       gchar *childname = ((ChildInfo*)info->parent)->internal_child;
655       obj = gtk_builder_get_internal_child (builder, info, childname, error);
656       if (!obj)
657         {
658           g_array_free (parameters, TRUE);
659           g_array_free (construct_parameters, TRUE);
660           return NULL;
661         }
662       if (construct_parameters->len)
663         g_warning ("Can't pass in construct-only parameters to %s", childname);
664       g_object_ref (obj);
665     }
666   else
667     {
668       obj = g_object_newv (object_type,
669                            construct_parameters->len,
670                            (GParameter *)construct_parameters->data);
671
672       /* No matter what, make sure we have a reference.
673        *
674        * If it's an initially unowned object, sink it.
675        * If it's not initially unowned then we have the reference already.
676        *
677        * In the case that this is a window it will be sunk already and
678        * this is effectively a call to g_object_ref().  That's what
679        * we want.
680        */
681       if (G_IS_INITIALLY_UNOWNED (obj))
682         g_object_ref_sink (obj);
683
684       GTK_NOTE (BUILDER,
685                 g_print ("created %s of type %s\n", info->id, info->class_name));
686
687       for (i = 0; i < construct_parameters->len; i++)
688         {
689           GParameter *param = &g_array_index (construct_parameters,
690                                               GParameter, i);
691           g_value_unset (&param->value);
692         }
693     }
694   g_array_free (construct_parameters, TRUE);
695
696   custom_set_property = FALSE;
697   buildable = NULL;
698   iface = NULL;
699   if (GTK_IS_BUILDABLE (obj))
700     {
701       buildable = GTK_BUILDABLE (obj);
702       iface = GTK_BUILDABLE_GET_IFACE (obj);
703       if (iface->set_buildable_property)
704         custom_set_property = TRUE;
705     }
706
707   for (i = 0; i < parameters->len; i++)
708     {
709       GParameter *param = &g_array_index (parameters, GParameter, i);
710       if (custom_set_property)
711         iface->set_buildable_property (buildable, builder, param->name, &param->value);
712       else
713         g_object_set_property (obj, param->name, &param->value);
714
715 #if G_ENABLE_DEBUG
716       if (gtk_get_debug_flags () & GTK_DEBUG_BUILDER)
717         {
718           gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
719           g_print ("set %s: %s = %s\n", info->id, param->name, str);
720           g_free (str);
721         }
722 #endif      
723       g_value_unset (&param->value);
724     }
725   g_array_free (parameters, TRUE);
726
727   /* put it in the hash table. */
728   _gtk_builder_add_object (builder, info->id, obj);
729   
730   /* we already own a reference to obj. */ 
731   g_object_unref (obj);
732   
733   return obj;
734 }
735
736 void
737 _gtk_builder_add (GtkBuilder *builder,
738                   ChildInfo  *child_info)
739 {
740   GObject *object;
741   GObject *parent;
742
743   /* Internal children are already added
744    * Also prevent us from being called twice.
745    */
746   if (!child_info ||
747       child_info->internal_child ||
748       child_info->added)
749     return;
750
751   object = child_info->object;
752   if (!object)
753     return;
754
755   if (!child_info->parent)
756     {
757       g_warning ("%s: Not adding, No parent",
758                  gtk_buildable_get_name (GTK_BUILDABLE (object)));
759       return;
760     }
761
762   g_assert (object != NULL);
763
764   parent = ((ObjectInfo*)child_info->parent)->object;
765   g_assert (GTK_IS_BUILDABLE (parent));
766
767   GTK_NOTE (BUILDER,
768             g_print ("adding %s to %s\n",
769                      gtk_buildable_get_name (GTK_BUILDABLE (object)),
770                      gtk_buildable_get_name (GTK_BUILDABLE (parent))));
771   
772   gtk_buildable_add_child (GTK_BUILDABLE (parent), builder, object,
773                            child_info->type);
774
775   child_info->added = TRUE;
776 }
777
778 void
779 _gtk_builder_add_signals (GtkBuilder *builder,
780                           GSList     *signals)
781 {
782   builder->priv->signals = g_slist_concat (builder->priv->signals,
783                                            g_slist_copy (signals));
784 }
785
786 static void
787 gtk_builder_apply_delayed_properties (GtkBuilder *builder)
788 {
789   GSList *l, *props;
790   DelayedProperty *property;
791   GObject *object;
792   GType object_type;
793   GObjectClass *oclass;
794   GParamSpec *pspec;
795
796   /* take the list over from the builder->priv.
797    *
798    * g_slist_reverse does not copy the list, so the list now
799    * belongs to us (and we free it at the end of this function).
800    */
801   props = g_slist_reverse (builder->priv->delayed_properties);
802   builder->priv->delayed_properties = NULL;
803
804   for (l = props; l; l = l->next)
805     {
806       property = (DelayedProperty*)l->data;
807       object = g_hash_table_lookup (builder->priv->objects, property->object);
808       g_assert (object != NULL);
809
810       object_type = G_OBJECT_TYPE (object);
811       g_assert (object_type != G_TYPE_INVALID);
812
813       oclass = g_type_class_ref (object_type);
814       g_assert (oclass != NULL);
815
816       pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
817                                             property->name);
818       if (!pspec)
819         g_warning ("Unknown property: %s.%s", g_type_name (object_type),
820                    property->name);
821       else
822         {
823           GObject *obj;
824
825           obj = g_hash_table_lookup (builder->priv->objects, property->value);
826           if (!obj)
827             g_warning ("No object called: %s", property->value);
828           else
829             g_object_set (object, property->name, obj, NULL);
830         }
831       g_free (property->value);
832       g_free (property->object);
833       g_free (property->name);
834       g_slice_free (DelayedProperty, property);
835       g_type_class_unref (oclass);
836     }
837   g_slist_free (props);
838 }
839
840 void
841 _gtk_builder_finish (GtkBuilder *builder)
842 {
843   gtk_builder_apply_delayed_properties (builder);
844 }
845
846 /**
847  * gtk_builder_new:
848  *
849  * Creates a new builder object.
850  *
851  * Return value: a new #GtkBuilder object
852  *
853  * Since: 2.12
854  **/
855 GtkBuilder *
856 gtk_builder_new (void)
857 {
858   return g_object_new (GTK_TYPE_BUILDER, NULL);
859 }
860
861 /**
862  * gtk_builder_add_from_file:
863  * @builder: a #GtkBuilder
864  * @filename: the name of the file to parse
865  * @error: (allow-none): return location for an error, or %NULL
866  *
867  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
868  * UI definition</link> and merges it with the current contents of @builder. 
869  * 
870  * Upon errors 0 will be returned and @error will be assigned a
871  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
872  * domain.
873  *
874  * Returns: A positive value on success, 0 if an error occurred
875  *
876  * Since: 2.12
877  **/
878 guint
879 gtk_builder_add_from_file (GtkBuilder   *builder,
880                            const gchar  *filename,
881                            GError      **error)
882 {
883   gchar *buffer;
884   gsize length;
885   GError *tmp_error;
886
887   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
888   g_return_val_if_fail (filename != NULL, 0);
889   g_return_val_if_fail (error == NULL || *error == NULL, 0);
890
891   tmp_error = NULL;
892
893   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
894     {
895       g_propagate_error (error, tmp_error);
896       return 0;
897     }
898   
899   g_free (builder->priv->filename);
900   g_free (builder->priv->resource_prefix);
901   builder->priv->filename = g_strdup (filename);
902   builder->priv->resource_prefix = NULL;
903
904   _gtk_builder_parser_parse_buffer (builder, filename,
905                                     buffer, length,
906                                     NULL,
907                                     &tmp_error);
908
909   g_free (buffer);
910
911   if (tmp_error != NULL)
912     {
913       g_propagate_error (error, tmp_error);
914       return 0;
915     }
916
917   return 1;
918 }
919
920 /**
921  * gtk_builder_add_objects_from_file:
922  * @builder: a #GtkBuilder
923  * @filename: the name of the file to parse
924  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
925  * @error: (allow-none): return location for an error, or %NULL
926  *
927  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
928  * UI definition</link> building only the requested objects and merges
929  * them with the current contents of @builder. 
930  *
931  * Upon errors 0 will be returned and @error will be assigned a
932  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
933  * domain.
934  *
935  * <note><para>
936  * If you are adding an object that depends on an object that is not 
937  * its child (for instance a #GtkTreeView that depends on its
938  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
939  * </para></note>
940  *
941  * Returns: A positive value on success, 0 if an error occurred
942  *
943  * Since: 2.14
944  **/
945 guint
946 gtk_builder_add_objects_from_file (GtkBuilder   *builder,
947                                    const gchar  *filename,
948                                    gchar       **object_ids,
949                                    GError      **error)
950 {
951   gchar *buffer;
952   gsize length;
953   GError *tmp_error;
954
955   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
956   g_return_val_if_fail (filename != NULL, 0);
957   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
958   g_return_val_if_fail (error == NULL || *error == NULL, 0);
959
960   tmp_error = NULL;
961
962   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
963     {
964       g_propagate_error (error, tmp_error);
965       return 0;
966     }
967   
968   g_free (builder->priv->filename);
969   g_free (builder->priv->resource_prefix);
970   builder->priv->filename = g_strdup (filename);
971   builder->priv->resource_prefix = NULL;
972
973   _gtk_builder_parser_parse_buffer (builder, filename,
974                                     buffer, length,
975                                     object_ids,
976                                     &tmp_error);
977
978   g_free (buffer);
979
980   if (tmp_error != NULL)
981     {
982       g_propagate_error (error, tmp_error);
983       return 0;
984     }
985
986   return 1;
987 }
988
989 /**
990  * gtk_builder_add_from_resource:
991  * @builder: a #GtkBuilder
992  * @resource_path: the path of the resource file to parse
993  * @error: (allow-none): return location for an error, or %NULL
994  *
995  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
996  * UI definition</link> and merges it with the current contents of @builder.
997  *
998  * Upon errors 0 will be returned and @error will be assigned a
999  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1000  * domain.
1001  *
1002  * Returns: A positive value on success, 0 if an error occurred
1003  *
1004  * Since: 3.4
1005  **/
1006 guint
1007 gtk_builder_add_from_resource (GtkBuilder   *builder,
1008                                const gchar  *resource_path,
1009                                GError      **error)
1010 {
1011   GError *tmp_error;
1012   GBytes *data;
1013   char *filename_for_errors;
1014   char *slash;
1015
1016   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1017   g_return_val_if_fail (resource_path != NULL, 0);
1018   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1019
1020   tmp_error = NULL;
1021
1022   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1023   if (data == NULL)
1024     {
1025       g_propagate_error (error, tmp_error);
1026       return 0;
1027     }
1028
1029   g_free (builder->priv->filename);
1030   g_free (builder->priv->resource_prefix);
1031   builder->priv->filename = g_strdup (".");
1032
1033   slash = strrchr (resource_path, '/');
1034   if (slash != NULL)
1035     builder->priv->resource_prefix =
1036       g_strndup (resource_path, slash - resource_path + 1);
1037   else
1038     builder->priv->resource_prefix =
1039       g_strdup ("/");
1040
1041   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1042
1043   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1044                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1045                                     NULL,
1046                                     &tmp_error);
1047
1048   g_free (filename_for_errors);
1049   g_bytes_unref (data);
1050
1051   if (tmp_error != NULL)
1052     {
1053       g_propagate_error (error, tmp_error);
1054       return 0;
1055     }
1056
1057   return 1;
1058 }
1059
1060 /**
1061  * gtk_builder_add_objects_from_resource:
1062  * @builder: a #GtkBuilder
1063  * @resource_path: the path of the resource file to parse
1064  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1065  * @error: (allow-none): return location for an error, or %NULL
1066  *
1067  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
1068  * UI definition</link> building only the requested objects and merges
1069  * them with the current contents of @builder.
1070  *
1071  * Upon errors 0 will be returned and @error will be assigned a
1072  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1073  * domain.
1074  *
1075  * <note><para>
1076  * If you are adding an object that depends on an object that is not
1077  * its child (for instance a #GtkTreeView that depends on its
1078  * #GtkTreeModel), you have to explicitely list all of them in @object_ids.
1079  * </para></note>
1080  *
1081  * Returns: A positive value on success, 0 if an error occurred
1082  *
1083  * Since: 3.4
1084  **/
1085 guint
1086 gtk_builder_add_objects_from_resource (GtkBuilder   *builder,
1087                                        const gchar  *resource_path,
1088                                        gchar       **object_ids,
1089                                        GError      **error)
1090 {
1091   GError *tmp_error;
1092   GBytes *data;
1093   char *filename_for_errors;
1094   char *slash;
1095
1096   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1097   g_return_val_if_fail (resource_path != NULL, 0);
1098   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1099   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1100
1101   tmp_error = NULL;
1102
1103   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1104   if (data == NULL)
1105     {
1106       g_propagate_error (error, tmp_error);
1107       return 0;
1108     }
1109
1110   g_free (builder->priv->filename);
1111   g_free (builder->priv->resource_prefix);
1112   builder->priv->filename = g_strdup (".");
1113
1114   slash = strrchr (resource_path, '/');
1115   if (slash != NULL)
1116     builder->priv->resource_prefix =
1117       g_strndup (resource_path, slash - resource_path + 1);
1118   else
1119     builder->priv->resource_prefix =
1120       g_strdup ("/");
1121
1122   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1123
1124   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1125                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1126                                     object_ids,
1127                                     &tmp_error);
1128   g_free (filename_for_errors);
1129   g_bytes_unref (data);
1130
1131   if (tmp_error != NULL)
1132     {
1133       g_propagate_error (error, tmp_error);
1134       return 0;
1135     }
1136
1137   return 1;
1138 }
1139
1140 /**
1141  * gtk_builder_add_from_string:
1142  * @builder: a #GtkBuilder
1143  * @buffer: the string to parse
1144  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1145  * @error: (allow-none): return location for an error, or %NULL
1146  *
1147  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1148  * UI definition</link> and merges it with the current contents of @builder. 
1149  *
1150  * Upon errors 0 will be returned and @error will be assigned a
1151  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1152  *
1153  * Returns: A positive value on success, 0 if an error occurred
1154  *
1155  * Since: 2.12
1156  **/
1157 guint
1158 gtk_builder_add_from_string (GtkBuilder   *builder,
1159                              const gchar  *buffer,
1160                              gsize         length,
1161                              GError      **error)
1162 {
1163   GError *tmp_error;
1164
1165   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1166   g_return_val_if_fail (buffer != NULL, 0);
1167   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1168
1169   tmp_error = NULL;
1170
1171   g_free (builder->priv->filename);
1172   g_free (builder->priv->resource_prefix);
1173   builder->priv->filename = g_strdup (".");
1174   builder->priv->resource_prefix = NULL;
1175
1176   _gtk_builder_parser_parse_buffer (builder, "<input>",
1177                                     buffer, length,
1178                                     NULL,
1179                                     &tmp_error);
1180   if (tmp_error != NULL)
1181     {
1182       g_propagate_error (error, tmp_error);
1183       return 0;
1184     }
1185
1186   return 1;
1187 }
1188
1189 /**
1190  * gtk_builder_add_objects_from_string:
1191  * @builder: a #GtkBuilder
1192  * @buffer: the string to parse
1193  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1194  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1195  * @error: (allow-none): return location for an error, or %NULL
1196  *
1197  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1198  * UI definition</link> building only the requested objects and merges
1199  * them with the current contents of @builder. 
1200  *
1201  * Upon errors 0 will be returned and @error will be assigned a
1202  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1203  * 
1204  * <note><para>
1205  * If you are adding an object that depends on an object that is not 
1206  * its child (for instance a #GtkTreeView that depends on its
1207  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
1208  * </para></note>
1209  *
1210  * Returns: A positive value on success, 0 if an error occurred
1211  *
1212  * Since: 2.14
1213  **/
1214 guint
1215 gtk_builder_add_objects_from_string (GtkBuilder   *builder,
1216                                      const gchar  *buffer,
1217                                      gsize         length,
1218                                      gchar       **object_ids,
1219                                      GError      **error)
1220 {
1221   GError *tmp_error;
1222
1223   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1224   g_return_val_if_fail (buffer != NULL, 0);
1225   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1226   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1227
1228   tmp_error = NULL;
1229
1230   g_free (builder->priv->filename);
1231   g_free (builder->priv->resource_prefix);
1232   builder->priv->filename = g_strdup (".");
1233   builder->priv->resource_prefix = NULL;
1234
1235   _gtk_builder_parser_parse_buffer (builder, "<input>",
1236                                     buffer, length,
1237                                     object_ids,
1238                                     &tmp_error);
1239
1240   if (tmp_error != NULL)
1241     {
1242       g_propagate_error (error, tmp_error);
1243       return 0;
1244     }
1245
1246   return 1;
1247 }
1248
1249 /**
1250  * gtk_builder_get_object:
1251  * @builder: a #GtkBuilder
1252  * @name: name of object to get
1253  *
1254  * Gets the object named @name. Note that this function does not
1255  * increment the reference count of the returned object. 
1256  *
1257  * Return value: (transfer none): the object named @name or %NULL if
1258  *    it could not be found in the object tree.
1259  *
1260  * Since: 2.12
1261  **/
1262 GObject *
1263 gtk_builder_get_object (GtkBuilder  *builder,
1264                         const gchar *name)
1265 {
1266   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1267   g_return_val_if_fail (name != NULL, NULL);
1268
1269   return g_hash_table_lookup (builder->priv->objects, name);
1270 }
1271
1272 static void
1273 object_add_to_list (gchar    *object_id,
1274                     GObject  *object,
1275                     GSList  **list)
1276 {
1277   *list = g_slist_prepend (*list, object);
1278 }
1279
1280 /**
1281  * gtk_builder_get_objects:
1282  * @builder: a #GtkBuilder
1283  *
1284  * Gets all objects that have been constructed by @builder. Note that 
1285  * this function does not increment the reference counts of the returned
1286  * objects.
1287  *
1288  * Return value: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects
1289  *   constructed by the #GtkBuilder instance. It should be freed by
1290  *   g_slist_free()
1291  *
1292  * Since: 2.12
1293  **/
1294 GSList *
1295 gtk_builder_get_objects (GtkBuilder *builder)
1296 {
1297   GSList *objects = NULL;
1298
1299   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1300
1301   g_hash_table_foreach (builder->priv->objects, (GHFunc)object_add_to_list, &objects);
1302
1303   return g_slist_reverse (objects);
1304 }
1305
1306 /**
1307  * gtk_builder_set_translation_domain:
1308  * @builder: a #GtkBuilder
1309  * @domain: (allow-none): the translation domain or %NULL
1310  *
1311  * Sets the translation domain of @builder. 
1312  * See #GtkBuilder:translation-domain.
1313  *
1314  * Since: 2.12
1315  **/
1316 void
1317 gtk_builder_set_translation_domain (GtkBuilder  *builder,
1318                                     const gchar *domain)
1319 {
1320   gchar *new_domain;
1321     
1322   g_return_if_fail (GTK_IS_BUILDER (builder));
1323
1324   new_domain = g_strdup (domain);
1325   g_free (builder->priv->domain);
1326   builder->priv->domain = new_domain;
1327
1328   g_object_notify (G_OBJECT (builder), "translation-domain");
1329 }
1330
1331 /**
1332  * gtk_builder_get_translation_domain:
1333  * @builder: a #GtkBuilder
1334  *
1335  * Gets the translation domain of @builder.
1336  *
1337  * Return value: the translation domain. This string is owned
1338  * by the builder object and must not be modified or freed.
1339  *
1340  * Since: 2.12
1341  **/
1342 const gchar *
1343 gtk_builder_get_translation_domain (GtkBuilder *builder)
1344 {
1345   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1346
1347   return builder->priv->domain;
1348 }
1349
1350 /**
1351  * gtk_builder_expose_object:
1352  * @builder: a #GtkBuilder
1353  * @name: the name of the object exposed to the builder
1354  * @object: the object to expose
1355  *
1356  * Add @object to the @builder object pool so it can be referenced just like any
1357  * other object built by builder.
1358  *
1359  * To make this function even more useful a new special entry point element
1360  * &lt;external-object&gt; is defined. It is similar to &lt;object&gt; but has 
1361  * to reference an external object exposed with this function.
1362  * This way you can change properties and even add children to an
1363  * external object using builder, not just reference it.
1364  * 
1365  * Since: 3.8
1366  **/
1367 void
1368 gtk_builder_expose_object (GtkBuilder    *builder,
1369                            const gchar   *name,
1370                            GObject       *object)
1371 {
1372   g_return_if_fail (GTK_IS_BUILDER (builder));
1373   g_return_if_fail (name && name[0]);
1374   g_return_if_fail (gtk_builder_get_object (builder, name) == NULL);
1375
1376   object_set_name (object, name);
1377   g_hash_table_insert (builder->priv->objects,
1378                        g_strdup (name),
1379                        g_object_ref (object));
1380 }
1381
1382
1383 typedef struct {
1384   GModule *module;
1385   gpointer data;
1386 } connect_args;
1387
1388 static void
1389 gtk_builder_connect_signals_default (GtkBuilder    *builder,
1390                                      GObject       *object,
1391                                      const gchar   *signal_name,
1392                                      const gchar   *handler_name,
1393                                      GObject       *connect_object,
1394                                      GConnectFlags  flags,
1395                                      gpointer       user_data)
1396 {
1397   GCallback func;
1398   connect_args *args = (connect_args*)user_data;
1399   
1400   if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
1401     {
1402       g_warning ("Could not find signal handler '%s'", handler_name);
1403       return;
1404     }
1405
1406   if (connect_object)
1407     g_signal_connect_object (object, signal_name, func, connect_object, flags);
1408   else
1409     g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
1410 }
1411
1412
1413 /**
1414  * gtk_builder_connect_signals:
1415  * @builder: a #GtkBuilder
1416  * @user_data: a pointer to a structure sent in as user data to all signals
1417  *
1418  * This method is a simpler variation of gtk_builder_connect_signals_full().
1419  * It uses #GModule's introspective features (by opening the module %NULL) 
1420  * to look at the application's symbol table. From here it tries to match
1421  * the signal handler names given in the interface description with
1422  * symbols in the application and connects the signals. Note that this
1423  * function can only be called once, subsequent calls will do nothing.
1424  * 
1425  * Note that this function will not work correctly if #GModule is not
1426  * supported on the platform.
1427  *
1428  * When compiling applications for Windows, you must declare signal callbacks
1429  * with #G_MODULE_EXPORT, or they will not be put in the symbol table.
1430  * On Linux and Unices, this is not necessary; applications should instead
1431  * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
1432  * gmodule-export-2.0.
1433  *
1434  * Since: 2.12
1435  **/
1436 void
1437 gtk_builder_connect_signals (GtkBuilder *builder,
1438                              gpointer    user_data)
1439 {
1440   connect_args *args;
1441   
1442   g_return_if_fail (GTK_IS_BUILDER (builder));
1443   
1444   if (!g_module_supported ())
1445     g_error ("gtk_builder_connect_signals() requires working GModule");
1446
1447   args = g_slice_new0 (connect_args);
1448   args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
1449   args->data = user_data;
1450   
1451   gtk_builder_connect_signals_full (builder,
1452                                     gtk_builder_connect_signals_default,
1453                                     args);
1454   g_module_close (args->module);
1455
1456   g_slice_free (connect_args, args);
1457 }
1458
1459 /**
1460  * GtkBuilderConnectFunc:
1461  * @builder: a #GtkBuilder
1462  * @object: object to connect a signal to
1463  * @signal_name: name of the signal
1464  * @handler_name: name of the handler
1465  * @connect_object: a #GObject, if non-%NULL, use g_signal_connect_object()
1466  * @flags: #GConnectFlags to use
1467  * @user_data: user data
1468  *
1469  * This is the signature of a function used to connect signals.  It is used
1470  * by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
1471  * methods.  It is mainly intended for interpreted language bindings, but
1472  * could be useful where the programmer wants more control over the signal
1473  * connection process. Note that this function can only be called once,
1474  * subsequent calls will do nothing.
1475  *
1476  * Since: 2.12
1477  */
1478
1479 /**
1480  * gtk_builder_connect_signals_full:
1481  * @builder: a #GtkBuilder
1482  * @func: (scope call): the function used to connect the signals
1483  * @user_data: arbitrary data that will be passed to the connection function
1484  *
1485  * This function can be thought of the interpreted language binding
1486  * version of gtk_builder_connect_signals(), except that it does not
1487  * require GModule to function correctly.
1488  *
1489  * Since: 2.12
1490  */
1491 void
1492 gtk_builder_connect_signals_full (GtkBuilder            *builder,
1493                                   GtkBuilderConnectFunc  func,
1494                                   gpointer               user_data)
1495 {
1496   GSList *l;
1497   GObject *object;
1498   GObject *connect_object;
1499   
1500   g_return_if_fail (GTK_IS_BUILDER (builder));
1501   g_return_if_fail (func != NULL);
1502   
1503   if (!builder->priv->signals)
1504     return;
1505
1506   builder->priv->signals = g_slist_reverse (builder->priv->signals);
1507   for (l = builder->priv->signals; l; l = l->next)
1508     {
1509       SignalInfo *signal = (SignalInfo*)l->data;
1510
1511       g_assert (signal != NULL);
1512       g_assert (signal->name != NULL);
1513
1514       object = g_hash_table_lookup (builder->priv->objects,
1515                                     signal->object_name);
1516       g_assert (object != NULL);
1517
1518       connect_object = NULL;
1519       
1520       if (signal->connect_object_name)
1521         {
1522           connect_object = g_hash_table_lookup (builder->priv->objects,
1523                                                 signal->connect_object_name);
1524           if (!connect_object)
1525               g_warning ("Could not lookup object %s on signal %s of object %s",
1526                          signal->connect_object_name, signal->name,
1527                          signal->object_name);
1528         }
1529                                                   
1530       func (builder, object, signal->name, signal->handler, 
1531             connect_object, signal->flags, user_data);
1532     }
1533
1534   g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
1535   g_slist_free (builder->priv->signals);
1536   builder->priv->signals = NULL;
1537 }
1538
1539 /**
1540  * gtk_builder_value_from_string:
1541  * @builder: a #GtkBuilder
1542  * @pspec: the #GParamSpec for the property
1543  * @string: the string representation of the value
1544  * @value: (out): the #GValue to store the result in
1545  * @error: (allow-none): return location for an error, or %NULL
1546  *
1547  * This function demarshals a value from a string. This function
1548  * calls g_value_init() on the @value argument, so it need not be
1549  * initialised beforehand.
1550  *
1551  * This function can handle char, uchar, boolean, int, uint, long,
1552  * ulong, enum, flags, float, double, string, #GdkColor, #GdkRGBA and
1553  * #GtkAdjustment type values. Support for #GtkWidget type values is
1554  * still to come.
1555  *
1556  * Upon errors %FALSE will be returned and @error will be assigned a
1557  * #GError from the #GTK_BUILDER_ERROR domain.
1558  *
1559  * Returns: %TRUE on success
1560  *
1561  * Since: 2.12
1562  */
1563 gboolean
1564 gtk_builder_value_from_string (GtkBuilder   *builder,
1565                                GParamSpec   *pspec,
1566                                const gchar  *string,
1567                                GValue       *value,
1568                                GError      **error)
1569 {
1570   g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
1571   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1572   g_return_val_if_fail (string != NULL, FALSE);
1573   g_return_val_if_fail (value != NULL, FALSE);
1574   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1575
1576   /*
1577    * GParamSpecUnichar has the internal type G_TYPE_UINT,
1578    * so we cannot handle this in the switch, do it separately
1579    */
1580   if (G_IS_PARAM_SPEC_UNICHAR (pspec))
1581     {
1582       gunichar c;
1583       g_value_init (value, G_TYPE_UINT);
1584       c = g_utf8_get_char_validated (string, strlen (string));
1585       if (c > 0)
1586         g_value_set_uint (value, c);
1587       return TRUE;
1588     }
1589
1590   /*
1591    * GParamSpecVariant can specify a GVariantType which can help with
1592    * parsing, so we need to take care of that here.
1593    */
1594   if (G_IS_PARAM_SPEC_VARIANT (pspec))
1595     {
1596       GParamSpecVariant *variant_pspec = G_PARAM_SPEC_VARIANT (pspec);
1597       const GVariantType *type;
1598       GVariant *variant;
1599
1600       g_value_init (value, G_TYPE_VARIANT);
1601
1602       /* The GVariant parser doesn't deal with indefinite types */
1603       if (g_variant_type_is_definite (variant_pspec->type))
1604         type = variant_pspec->type;
1605       else
1606         type = NULL;
1607
1608       variant = g_variant_parse (type, string, NULL, NULL, error);
1609       if (variant == NULL)
1610         return FALSE;
1611       g_value_take_variant (value, variant);
1612       return TRUE;
1613     }
1614
1615   return gtk_builder_value_from_string_type (builder,
1616                                              G_PARAM_SPEC_VALUE_TYPE (pspec),
1617                                              string, value, error);
1618 }
1619
1620 /**
1621  * gtk_builder_value_from_string_type:
1622  * @builder: a #GtkBuilder
1623  * @type: the #GType of the value
1624  * @string: the string representation of the value
1625  * @value: (out): the #GValue to store the result in
1626  * @error: (allow-none): return location for an error, or %NULL
1627  *
1628  * Like gtk_builder_value_from_string(), this function demarshals 
1629  * a value from a string, but takes a #GType instead of #GParamSpec.
1630  * This function calls g_value_init() on the @value argument, so it 
1631  * need not be initialised beforehand.
1632  *
1633  * Upon errors %FALSE will be returned and @error will be assigned a
1634  * #GError from the #GTK_BUILDER_ERROR domain.
1635  *
1636  * Returns: %TRUE on success
1637  *
1638  * Since: 2.12
1639  */
1640 gboolean
1641 gtk_builder_value_from_string_type (GtkBuilder   *builder,
1642                                     GType         type,
1643                                     const gchar  *string,
1644                                     GValue       *value,
1645                                     GError      **error)
1646 {
1647   gboolean ret = TRUE;
1648
1649   g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
1650   g_return_val_if_fail (string != NULL, FALSE);
1651   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1652
1653   g_value_init (value, type);
1654
1655   switch (G_TYPE_FUNDAMENTAL (type))
1656     {
1657     case G_TYPE_CHAR:
1658       g_value_set_schar (value, string[0]);
1659       break;
1660     case G_TYPE_UCHAR:
1661       g_value_set_uchar (value, (guchar)string[0]);
1662       break;
1663     case G_TYPE_BOOLEAN:
1664       {
1665         gboolean b;
1666
1667         if (!_gtk_builder_boolean_from_string (string, &b, error))
1668           {
1669             ret = FALSE;
1670             break;
1671           }
1672         g_value_set_boolean (value, b);
1673         break;
1674       }
1675     case G_TYPE_INT:
1676     case G_TYPE_LONG:
1677       {
1678         long l;
1679         gchar *endptr = NULL;
1680         errno = 0;
1681         l = g_ascii_strtoll (string, &endptr, 0);
1682         if (errno || endptr == string)
1683           {
1684             g_set_error (error,
1685                          GTK_BUILDER_ERROR,
1686                          GTK_BUILDER_ERROR_INVALID_VALUE,
1687                          "Could not parse integer `%s'",
1688                          string);
1689             ret = FALSE;
1690             break;
1691           }
1692         if (G_VALUE_HOLDS_INT (value))
1693           g_value_set_int (value, l);
1694         else
1695           g_value_set_long (value, l);
1696         break;
1697       }
1698     case G_TYPE_UINT:
1699     case G_TYPE_ULONG:
1700       {
1701         gulong ul;
1702         gchar *endptr = NULL;
1703         errno = 0;
1704         ul = g_ascii_strtoull (string, &endptr, 0);
1705         if (errno || endptr == string)
1706           {
1707             g_set_error (error,
1708                          GTK_BUILDER_ERROR,
1709                          GTK_BUILDER_ERROR_INVALID_VALUE,
1710                          "Could not parse unsigned integer `%s'",
1711                          string);
1712             ret = FALSE;
1713             break;
1714           }
1715         if (G_VALUE_HOLDS_UINT (value))
1716           g_value_set_uint (value, ul);
1717         else 
1718           g_value_set_ulong (value, ul);
1719         break;
1720       }
1721     case G_TYPE_ENUM:
1722       {
1723         gint enum_value;
1724         if (!_gtk_builder_enum_from_string (type, string, &enum_value, error))
1725           {
1726             ret = FALSE;
1727             break;
1728           }
1729         g_value_set_enum (value, enum_value);
1730         break;
1731       }
1732     case G_TYPE_FLAGS:
1733       {
1734         guint flags_value;
1735
1736         if (!_gtk_builder_flags_from_string (type, string, &flags_value, error))
1737           {
1738             ret = FALSE;
1739             break;
1740           }
1741         g_value_set_flags (value, flags_value);
1742         break;
1743       }
1744     case G_TYPE_FLOAT:
1745     case G_TYPE_DOUBLE:
1746       {
1747         gdouble d;
1748         gchar *endptr = NULL;
1749         errno = 0;
1750         d = g_ascii_strtod (string, &endptr);
1751         if (errno || endptr == string)
1752           {
1753             g_set_error (error,
1754                          GTK_BUILDER_ERROR,
1755                          GTK_BUILDER_ERROR_INVALID_VALUE,
1756                          "Could not parse double `%s'",
1757                          string);
1758             ret = FALSE;
1759             break;
1760           }
1761         if (G_VALUE_HOLDS_FLOAT (value))
1762           g_value_set_float (value, d);
1763         else
1764           g_value_set_double (value, d);
1765         break;
1766       }
1767     case G_TYPE_STRING:
1768       g_value_set_string (value, string);
1769       break;
1770     case G_TYPE_VARIANT:
1771       {
1772         GVariant *variant;
1773
1774         variant = g_variant_parse (NULL, string, NULL, NULL, error);
1775         if (value != NULL)
1776           g_value_take_variant (value, variant);
1777         else
1778           ret = FALSE;
1779       }
1780       break;
1781     case G_TYPE_BOXED:
1782       if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
1783         {
1784           GdkColor color = { 0, };
1785
1786           if (gdk_color_parse (string, &color))
1787             g_value_set_boxed (value, &color);
1788           else
1789             {
1790               g_set_error (error,
1791                            GTK_BUILDER_ERROR,
1792                            GTK_BUILDER_ERROR_INVALID_VALUE,
1793                            "Could not parse color `%s'",
1794                            string);
1795               ret = FALSE;
1796             }
1797         }
1798       else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
1799         {
1800           GdkRGBA rgba = { 0 };
1801
1802           if (gdk_rgba_parse (&rgba, string))
1803             g_value_set_boxed (value, &rgba);
1804           else
1805             {
1806               g_set_error (error,
1807                            GTK_BUILDER_ERROR,
1808                            GTK_BUILDER_ERROR_INVALID_VALUE,
1809                            "Could not parse RGBA color '%s'",
1810                            string);
1811               ret = FALSE;
1812             }
1813         }
1814       else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
1815         {
1816           gchar **vector = g_strsplit (string, "\n", 0);
1817           g_value_take_boxed (value, vector);
1818         }
1819       else
1820         {
1821           g_set_error (error,
1822                        GTK_BUILDER_ERROR,
1823                        GTK_BUILDER_ERROR_INVALID_VALUE,
1824                        "Could not parse '%s' as a %s",
1825                        string, G_VALUE_TYPE_NAME (value));
1826           ret = FALSE;
1827         }
1828       break;
1829     case G_TYPE_OBJECT:
1830       if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
1831         {
1832           gchar *filename;
1833           GError *tmp_error = NULL;
1834           GdkPixbuf *pixbuf = NULL;
1835        
1836           if (gtk_builder_get_object (builder, string))
1837             {
1838               g_set_error (error,
1839                            GTK_BUILDER_ERROR,
1840                            GTK_BUILDER_ERROR_INVALID_VALUE,
1841                            "Could not load image '%s': "
1842                            " '%s' is already used as object id",
1843                            string, string);
1844               return FALSE;
1845             }
1846
1847           filename = _gtk_builder_get_resource_path (builder, string);
1848           if (filename != NULL)
1849             {
1850               GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error);
1851               if (stream != NULL)
1852                 {
1853                   pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &tmp_error);
1854                   g_object_unref (stream);
1855                 }
1856             }
1857           else
1858             {
1859               filename = _gtk_builder_get_absolute_filename (builder, string);
1860               pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error);
1861             }
1862
1863           if (pixbuf == NULL)
1864             {
1865               GtkIconTheme *theme;
1866
1867               g_warning ("Could not load image '%s': %s", 
1868                          string, tmp_error->message);
1869               g_error_free (tmp_error);
1870
1871               /* fall back to a missing image */
1872               theme = gtk_icon_theme_get_default ();
1873               pixbuf = gtk_icon_theme_load_icon (theme, 
1874                                                  GTK_STOCK_MISSING_IMAGE,
1875                                                  16,
1876                                                  GTK_ICON_LOOKUP_USE_BUILTIN,
1877                                                  NULL);
1878             }
1879  
1880           if (pixbuf)
1881             {
1882               g_value_set_object (value, pixbuf);
1883               g_object_unref (G_OBJECT (pixbuf));
1884             }
1885
1886           g_free (filename);
1887
1888           ret = TRUE;
1889         }
1890       else
1891         ret = FALSE;
1892       break;
1893     default:
1894       ret = FALSE;
1895       break;
1896     }
1897  
1898   /* Catch unassigned error for object types as well as any unsupported types.
1899    * While parsing GtkBuilder; object types are deserialized
1900    * without calling gtk_builder_value_from_string_type().
1901    */
1902   if (!ret && error && *error == NULL) 
1903     g_set_error (error,
1904                  GTK_BUILDER_ERROR,
1905                  GTK_BUILDER_ERROR_INVALID_VALUE,
1906                  "Unsupported GType `%s'", g_type_name (type));
1907
1908   return ret;
1909 }
1910
1911 gboolean
1912 _gtk_builder_enum_from_string (GType         type, 
1913                                const gchar  *string,
1914                                gint         *enum_value,
1915                                GError      **error)
1916 {
1917   GEnumClass *eclass;
1918   GEnumValue *ev;
1919   gchar *endptr;
1920   gint value;
1921   gboolean ret;
1922   
1923   g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE);
1924   g_return_val_if_fail (string != NULL, FALSE);
1925   
1926   ret = TRUE;
1927
1928   endptr = NULL;
1929   errno = 0;
1930   value = g_ascii_strtoull (string, &endptr, 0);
1931   if (errno == 0 && endptr != string) /* parsed a number */
1932     *enum_value = value;
1933   else
1934     {
1935       eclass = g_type_class_ref (type);
1936       ev = g_enum_get_value_by_name (eclass, string);
1937       if (!ev)
1938         ev = g_enum_get_value_by_nick (eclass, string);
1939
1940       if (ev)
1941         *enum_value = ev->value;
1942       else
1943         {
1944           g_set_error (error,
1945                        GTK_BUILDER_ERROR,
1946                        GTK_BUILDER_ERROR_INVALID_VALUE,
1947                        "Could not parse enum: `%s'",
1948                        string);
1949           ret = FALSE;
1950         }
1951       
1952       g_type_class_unref (eclass);
1953     }
1954   
1955   return ret;
1956 }
1957
1958 gboolean
1959 _gtk_builder_flags_from_string (GType         type, 
1960                                 const gchar  *string,
1961                                 guint        *flags_value,
1962                                 GError      **error)
1963 {
1964   GFlagsClass *fclass;
1965   gchar *endptr, *prevptr;
1966   guint i, j, value;
1967   gchar *flagstr;
1968   GFlagsValue *fv;
1969   const gchar *flag;
1970   gunichar ch;
1971   gboolean eos, ret;
1972
1973   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE);
1974   g_return_val_if_fail (string != 0, FALSE);
1975
1976   ret = TRUE;
1977
1978   endptr = NULL;
1979   errno = 0;
1980   value = g_ascii_strtoull (string, &endptr, 0);
1981   if (errno == 0 && endptr != string) /* parsed a number */
1982     *flags_value = value;
1983   else
1984     {
1985       fclass = g_type_class_ref (type);
1986
1987       flagstr = g_strdup (string);
1988       for (value = i = j = 0; ; i++)
1989         {
1990           
1991           eos = flagstr[i] == '\0';
1992           
1993           if (!eos && flagstr[i] != '|')
1994             continue;
1995           
1996           flag = &flagstr[j];
1997           endptr = &flagstr[i];
1998           
1999           if (!eos)
2000             {
2001               flagstr[i++] = '\0';
2002               j = i;
2003             }
2004           
2005           /* trim spaces */
2006           for (;;)
2007             {
2008               ch = g_utf8_get_char (flag);
2009               if (!g_unichar_isspace (ch))
2010                 break;
2011               flag = g_utf8_next_char (flag);
2012             }
2013           
2014           while (endptr > flag)
2015             {
2016               prevptr = g_utf8_prev_char (endptr);
2017               ch = g_utf8_get_char (prevptr);
2018               if (!g_unichar_isspace (ch))
2019                 break;
2020               endptr = prevptr;
2021             }
2022           
2023           if (endptr > flag)
2024             {
2025               *endptr = '\0';
2026               fv = g_flags_get_value_by_name (fclass, flag);
2027               
2028               if (!fv)
2029                 fv = g_flags_get_value_by_nick (fclass, flag);
2030               
2031               if (fv)
2032                 value |= fv->value;
2033               else
2034                 {
2035                   g_set_error (error,
2036                                GTK_BUILDER_ERROR,
2037                                GTK_BUILDER_ERROR_INVALID_VALUE,
2038                                "Unknown flag: `%s'",
2039                                flag);
2040                   ret = FALSE;
2041                   break;
2042                 }
2043             }
2044           
2045           if (eos)
2046             {
2047               *flags_value = value;
2048               break;
2049             }
2050         }
2051       
2052       g_free (flagstr);
2053       
2054       g_type_class_unref (fclass);
2055     }
2056
2057   return ret;
2058 }
2059
2060 /**
2061  * gtk_builder_get_type_from_name:
2062  * @builder: a #GtkBuilder
2063  * @type_name: type name to lookup
2064  *
2065  * Looks up a type by name, using the virtual function that 
2066  * #GtkBuilder has for that purpose. This is mainly used when
2067  * implementing the #GtkBuildable interface on a type.
2068  *
2069  * Returns: the #GType found for @type_name or #G_TYPE_INVALID 
2070  *   if no type was found
2071  *
2072  * Since: 2.12
2073  */
2074 GType
2075 gtk_builder_get_type_from_name (GtkBuilder  *builder, 
2076                                 const gchar *type_name)
2077 {
2078   g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
2079   g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2080
2081   return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, type_name);
2082 }
2083
2084 GQuark
2085 gtk_builder_error_quark (void)
2086 {
2087   return g_quark_from_static_string ("gtk-builder-error-quark");
2088 }
2089
2090 gchar *
2091 _gtk_builder_get_resource_path (GtkBuilder *builder, const gchar *string)
2092 {
2093   if (g_str_has_prefix (string, "resource:///"))
2094     return g_uri_unescape_string (string + 11, "/");
2095
2096   if (g_path_is_absolute (string) ||
2097       builder->priv->resource_prefix == NULL)
2098     return NULL;
2099
2100   return g_build_path ("/", builder->priv->resource_prefix, string, NULL);
2101 }
2102
2103 gchar *
2104 _gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string)
2105 {
2106   gchar *filename;
2107   gchar *dirname = NULL;
2108   
2109   if (g_path_is_absolute (string))
2110     return g_strdup (string);
2111
2112   if (builder->priv->filename &&
2113       strcmp (builder->priv->filename, ".") != 0) 
2114     {
2115       dirname = g_path_get_dirname (builder->priv->filename);
2116
2117       if (strcmp (dirname, ".") == 0)
2118         {
2119           g_free (dirname);
2120           dirname = g_get_current_dir ();
2121         }
2122     }
2123   else
2124     dirname = g_get_current_dir ();
2125     
2126   filename = g_build_filename (dirname, string, NULL);
2127   g_free (dirname);
2128   
2129   return filename;
2130 }