]> Pileus Git - ~andy/gtk/blob - gtk/gtkbuilder.c
1f9d6e47384fea7ab143ab793fa4bf2381169842
[~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, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gtkbuilder
25  * @Short_description: Build an interface from an XML UI definition
26  * @Title: GtkBuilder
27  *
28  * A GtkBuilder is an auxiliary object that reads textual descriptions
29  * of a user interface and instantiates the described objects. To pass a
30  * description to a GtkBuilder, call gtk_builder_add_from_file() or
31  * gtk_builder_add_from_string(). These functions can be called multiple
32  * times; the builder merges the content of all descriptions.
33  *
34  * A GtkBuilder holds a reference to all objects that it has constructed
35  * and drops these references when it is finalized. This finalization can
36  * cause the destruction of non-widget objects or widgets which are not
37  * contained in a toplevel window. For toplevel windows constructed by a
38  * builder, it is the responsibility of the user to call gtk_widget_destroy()
39  * to get rid of them and all the widgets they contain.
40  *
41  * The functions gtk_builder_get_object() and gtk_builder_get_objects()
42  * can be used to access the widgets in the interface by the names assigned
43  * to them inside the UI description. Toplevel windows returned by these
44  * functions will stay around until the user explicitly destroys them
45  * with gtk_widget_destroy(). Other widgets will either be part of a
46  * larger hierarchy constructed by the builder (in which case you should
47  * not have to worry about their lifecycle), or without a parent, in which
48  * case they have to be added to some container to make use of them.
49  * Non-widget objects need to be reffed with g_object_ref() to keep them
50  * beyond the lifespan of the builder.
51  *
52  * The function gtk_builder_connect_signals() and variants thereof can be
53  * used to connect handlers to the named signals in the description.
54  *
55  * <refsect2 id="BUILDER-UI">
56  * <title>GtkBuilder UI Definitions</title>
57  * <para>
58  * GtkBuilder parses textual descriptions of user interfaces which are specified
59  * in an XML format which can be roughly described by the RELAX NG schema below.
60  * We refer to these descriptions as <firstterm>GtkBuilder UI definitions</firstterm>
61  * or just <firstterm>UI definitions</firstterm> if the context is clear. Do not
62  * confuse GtkBuilder UI Definitions with
63  * <link linkend="XML-UI">GtkUIManager UI Definitions</link>, which are more
64  * limited in scope.
65  * </para>
66  * <programlisting>
67  * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gtk/gtkbuilder.rnc">
68  *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
69  * </xi:include>
70  * </programlisting>
71  * <para>
72  * The toplevel element is &lt;interface&gt;. It optionally takes a "domain"
73  * attribute, which will make the builder look for translated strings using
74  * dgettext() in the domain specified. This can also be done by calling
75  * gtk_builder_set_translation_domain() on the builder. Objects are described by
76  * &lt;object&gt; elements, which can contain &lt;property&gt; elements to set
77  * properties, &lt;signal&gt; elements which connect signals to handlers, and
78  * &lt;child&gt; elements, which describe child objects (most often widgets
79  * inside a container, but also e.g. actions in an action group, or columns in a
80  * tree model). A &lt;child&gt; element contains an &lt;object&gt; element which
81  * describes the child object. The target toolkit version(s) are described by
82  * &lt;requires&gt; elements, the "lib" attribute specifies the widget library
83  * in question (currently the only supported value is "gtk+") and the "version"
84  * attribute specifies the target version in the form
85  * "&lt;major&gt;.&lt;minor&gt;". The builder will error out if the version
86  * requirements are not met.
87  *
88  * Typically, the specific kind of object represented by an &lt;object&gt;
89  * element is specified by the "class" attribute. If the type has not been
90  * loaded yet, GTK+ tries to find the <function>_get_type()</function> from the
91  * class name by applying heuristics. This works in most cases, but if
92  * necessary, it is possible to specify the name of the
93  * <function>_get_type()</function> explictly with the "type-func" attribute.
94  * As a special case, GtkBuilder allows to use an object that has been
95  * constructed by a #GtkUIManager in another part of the UI definition by
96  * specifying the id of the #GtkUIManager in the "constructor" attribute and the
97  * name of the object in the "id" attribute.
98  *
99  * Objects must be given a name with the "id" attribute, which allows the
100  * application to retrieve them from the builder with gtk_builder_get_object().
101  * An id is also necessary to use the object as property value in other parts of
102  * the UI definition.
103  * </para>
104  * <note><para>
105  * Prior to 2.20, GtkBuilder was setting the "name" property of constructed widgets to the
106  * "id" attribute. In GTK+ 2.20 or newer, you have to use gtk_buildable_get_name() instead
107  * of gtk_widget_get_name() to obtain the "id", or set the "name" property in your UI
108  * definition.
109  * </para></note>
110  * <para>
111  * Setting properties of objects is pretty straightforward with the
112  * &lt;property&gt; element: the "name" attribute specifies the name of the
113  * property, and the content of the element specifies the value. If the
114  * "translatable" attribute is set to a true value, GTK+ uses gettext() (or
115  * dgettext() if the builder has a translation domain set) to find a translation
116  * for the value. This happens before the value is parsed, so it can be used for
117  * properties of any type, but it is probably most useful for string properties.
118  * It is also possible to specify a context to disambiguate short strings, and
119  * comments which may help the translators.
120  *
121  * GtkBuilder can parse textual representations for the most common property
122  * types: characters, strings, integers, floating-point numbers, booleans
123  * (strings like "TRUE", "t", "yes", "y", "1" are interpreted as %TRUE, strings
124  * like "FALSE, "f", "no", "n", "0" are interpreted as %FALSE), enumerations
125  * (can be specified by their name, nick or integer value), flags (can be
126  * specified by their name, nick, integer value, optionally combined with "|",
127  * e.g. "GTK_VISIBLE|GTK_REALIZED")  and colors (in a format understood by
128  * gdk_color_parse()). Objects can be referred to by their name. Pixbufs can be
129  * specified as a filename of an image file to load. In general, GtkBuilder
130  * allows forward references to objects &mdash; an object doesn't have to be
131  * constructed before it can be referred to. The exception to this rule is that
132  * an object has to be constructed before it can be used as the value of a
133  * 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 GObject *
580 _gtk_builder_construct (GtkBuilder *builder,
581                         ObjectInfo *info,
582                         GError **error)
583 {
584   GArray *parameters, *construct_parameters;
585   GType object_type;
586   GObject *obj;
587   int i;
588   GtkBuildableIface *iface;
589   gboolean custom_set_property;
590   GtkBuildable *buildable;
591
592   g_assert (info->class_name != NULL);
593   object_type = gtk_builder_get_type_from_name (builder, info->class_name);
594   if (object_type == G_TYPE_INVALID)
595     {
596       g_set_error (error,
597                    GTK_BUILDER_ERROR,
598                    GTK_BUILDER_ERROR_INVALID_VALUE,
599                    "Invalid object type `%s'",
600                    info->class_name);
601       return NULL;
602     }
603
604   gtk_builder_get_parameters (builder, object_type,
605                               info->id,
606                               info->properties,
607                               &parameters,
608                               &construct_parameters);
609
610   if (info->constructor)
611     {
612       GObject *constructor;
613
614       constructor = gtk_builder_get_object (builder, info->constructor);
615       if (constructor == NULL)
616         {
617           g_set_error (error,
618                        GTK_BUILDER_ERROR,
619                        GTK_BUILDER_ERROR_INVALID_VALUE,
620                        "Unknown object constructor for %s: %s",
621                        info->id,
622                        info->constructor);
623           g_array_free (parameters, TRUE);
624           g_array_free (construct_parameters, TRUE);
625           return NULL;
626         }
627       obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
628                                            builder,
629                                            info->id);
630       g_assert (obj != NULL);
631       if (construct_parameters->len)
632         g_warning ("Can't pass in construct-only parameters to %s", info->id);
633     }
634   else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
635     {
636       gchar *childname = ((ChildInfo*)info->parent)->internal_child;
637       obj = gtk_builder_get_internal_child (builder, info, childname, error);
638       if (!obj)
639         {
640           g_array_free (parameters, TRUE);
641           g_array_free (construct_parameters, TRUE);
642           return NULL;
643         }
644       if (construct_parameters->len)
645         g_warning ("Can't pass in construct-only parameters to %s", childname);
646       g_object_ref (obj);
647     }
648   else
649     {
650       obj = g_object_newv (object_type,
651                            construct_parameters->len,
652                            (GParameter *)construct_parameters->data);
653
654       /* No matter what, make sure we have a reference.
655        *
656        * If it's an initially unowned object, sink it.
657        * If it's not initially unowned then we have the reference already.
658        *
659        * In the case that this is a window it will be sunk already and
660        * this is effectively a call to g_object_ref().  That's what
661        * we want.
662        */
663       if (G_IS_INITIALLY_UNOWNED (obj))
664         g_object_ref_sink (obj);
665
666       GTK_NOTE (BUILDER,
667                 g_print ("created %s of type %s\n", info->id, info->class_name));
668
669       for (i = 0; i < construct_parameters->len; i++)
670         {
671           GParameter *param = &g_array_index (construct_parameters,
672                                               GParameter, i);
673           g_value_unset (&param->value);
674         }
675     }
676   g_array_free (construct_parameters, TRUE);
677
678   custom_set_property = FALSE;
679   buildable = NULL;
680   iface = NULL;
681   if (GTK_IS_BUILDABLE (obj))
682     {
683       buildable = GTK_BUILDABLE (obj);
684       iface = GTK_BUILDABLE_GET_IFACE (obj);
685       if (iface->set_buildable_property)
686         custom_set_property = TRUE;
687     }
688
689   for (i = 0; i < parameters->len; i++)
690     {
691       GParameter *param = &g_array_index (parameters, GParameter, i);
692       if (custom_set_property)
693         iface->set_buildable_property (buildable, builder, param->name, &param->value);
694       else
695         g_object_set_property (obj, param->name, &param->value);
696
697 #if G_ENABLE_DEBUG
698       if (gtk_get_debug_flags () & GTK_DEBUG_BUILDER)
699         {
700           gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
701           g_print ("set %s: %s = %s\n", info->id, param->name, str);
702           g_free (str);
703         }
704 #endif      
705       g_value_unset (&param->value);
706     }
707   g_array_free (parameters, TRUE);
708   
709   if (GTK_IS_BUILDABLE (obj))
710     gtk_buildable_set_name (buildable, info->id);
711   else
712     g_object_set_data_full (obj,
713                             "gtk-builder-name",
714                             g_strdup (info->id),
715                             g_free);
716
717   /* we already own a reference to obj.  put it in the hash table. */
718   g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
719   
720   return obj;
721 }
722
723 void
724 _gtk_builder_add_object (GtkBuilder  *builder,
725                          const gchar *id,
726                          GObject     *object)
727 {
728   g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object));
729 }
730
731 void
732 _gtk_builder_add (GtkBuilder *builder,
733                   ChildInfo  *child_info)
734 {
735   GObject *object;
736   GObject *parent;
737
738   /* Internal children are already added
739    * Also prevent us from being called twice.
740    */
741   if (!child_info ||
742       child_info->internal_child ||
743       child_info->added)
744     return;
745
746   object = child_info->object;
747   if (!object)
748     return;
749
750   if (!child_info->parent)
751     {
752       g_warning ("%s: Not adding, No parent",
753                  gtk_buildable_get_name (GTK_BUILDABLE (object)));
754       return;
755     }
756
757   g_assert (object != NULL);
758
759   parent = ((ObjectInfo*)child_info->parent)->object;
760   g_assert (GTK_IS_BUILDABLE (parent));
761
762   GTK_NOTE (BUILDER,
763             g_print ("adding %s to %s\n",
764                      gtk_buildable_get_name (GTK_BUILDABLE (object)),
765                      gtk_buildable_get_name (GTK_BUILDABLE (parent))));
766   
767   gtk_buildable_add_child (GTK_BUILDABLE (parent), builder, object,
768                            child_info->type);
769
770   child_info->added = TRUE;
771 }
772
773 void
774 _gtk_builder_add_signals (GtkBuilder *builder,
775                           GSList     *signals)
776 {
777   builder->priv->signals = g_slist_concat (builder->priv->signals,
778                                            g_slist_copy (signals));
779 }
780
781 static void
782 gtk_builder_apply_delayed_properties (GtkBuilder *builder)
783 {
784   GSList *l, *props;
785   DelayedProperty *property;
786   GObject *object;
787   GType object_type;
788   GObjectClass *oclass;
789   GParamSpec *pspec;
790
791   /* take the list over from the builder->priv.
792    *
793    * g_slist_reverse does not copy the list, so the list now
794    * belongs to us (and we free it at the end of this function).
795    */
796   props = g_slist_reverse (builder->priv->delayed_properties);
797   builder->priv->delayed_properties = NULL;
798
799   for (l = props; l; l = l->next)
800     {
801       property = (DelayedProperty*)l->data;
802       object = g_hash_table_lookup (builder->priv->objects, property->object);
803       g_assert (object != NULL);
804
805       object_type = G_OBJECT_TYPE (object);
806       g_assert (object_type != G_TYPE_INVALID);
807
808       oclass = g_type_class_ref (object_type);
809       g_assert (oclass != NULL);
810
811       pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
812                                             property->name);
813       if (!pspec)
814         g_warning ("Unknown property: %s.%s", g_type_name (object_type),
815                    property->name);
816       else
817         {
818           GObject *obj;
819
820           obj = g_hash_table_lookup (builder->priv->objects, property->value);
821           if (!obj)
822             g_warning ("No object called: %s", property->value);
823           else
824             g_object_set (object, property->name, obj, NULL);
825         }
826       g_free (property->value);
827       g_free (property->object);
828       g_free (property->name);
829       g_slice_free (DelayedProperty, property);
830       g_type_class_unref (oclass);
831     }
832   g_slist_free (props);
833 }
834
835 void
836 _gtk_builder_finish (GtkBuilder *builder)
837 {
838   gtk_builder_apply_delayed_properties (builder);
839 }
840
841 /**
842  * gtk_builder_new:
843  *
844  * Creates a new builder object.
845  *
846  * Return value: a new #GtkBuilder object
847  *
848  * Since: 2.12
849  **/
850 GtkBuilder *
851 gtk_builder_new (void)
852 {
853   return g_object_new (GTK_TYPE_BUILDER, NULL);
854 }
855
856 /**
857  * gtk_builder_add_from_file:
858  * @builder: a #GtkBuilder
859  * @filename: the name of the file to parse
860  * @error: (allow-none): return location for an error, or %NULL
861  *
862  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
863  * UI definition</link> and merges it with the current contents of @builder. 
864  * 
865  * Upon errors 0 will be returned and @error will be assigned a
866  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
867  * domain.
868  *
869  * Returns: A positive value on success, 0 if an error occurred
870  *
871  * Since: 2.12
872  **/
873 guint
874 gtk_builder_add_from_file (GtkBuilder   *builder,
875                            const gchar  *filename,
876                            GError      **error)
877 {
878   gchar *buffer;
879   gsize length;
880   GError *tmp_error;
881
882   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
883   g_return_val_if_fail (filename != NULL, 0);
884   g_return_val_if_fail (error == NULL || *error == NULL, 0);
885
886   tmp_error = NULL;
887
888   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
889     {
890       g_propagate_error (error, tmp_error);
891       return 0;
892     }
893   
894   g_free (builder->priv->filename);
895   g_free (builder->priv->resource_prefix);
896   builder->priv->filename = g_strdup (filename);
897   builder->priv->resource_prefix = NULL;
898
899   _gtk_builder_parser_parse_buffer (builder, filename,
900                                     buffer, length,
901                                     NULL,
902                                     &tmp_error);
903
904   g_free (buffer);
905
906   if (tmp_error != NULL)
907     {
908       g_propagate_error (error, tmp_error);
909       return 0;
910     }
911
912   return 1;
913 }
914
915 /**
916  * gtk_builder_add_objects_from_file:
917  * @builder: a #GtkBuilder
918  * @filename: the name of the file to parse
919  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
920  * @error: (allow-none): return location for an error, or %NULL
921  *
922  * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder 
923  * UI definition</link> building only the requested objects and merges
924  * them with the current contents of @builder. 
925  *
926  * Upon errors 0 will be returned and @error will be assigned a
927  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_FILE_ERROR 
928  * domain.
929  *
930  * <note><para>
931  * If you are adding an object that depends on an object that is not 
932  * its child (for instance a #GtkTreeView that depends on its
933  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
934  * </para></note>
935  *
936  * Returns: A positive value on success, 0 if an error occurred
937  *
938  * Since: 2.14
939  **/
940 guint
941 gtk_builder_add_objects_from_file (GtkBuilder   *builder,
942                                    const gchar  *filename,
943                                    gchar       **object_ids,
944                                    GError      **error)
945 {
946   gchar *buffer;
947   gsize length;
948   GError *tmp_error;
949
950   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
951   g_return_val_if_fail (filename != NULL, 0);
952   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
953   g_return_val_if_fail (error == NULL || *error == NULL, 0);
954
955   tmp_error = NULL;
956
957   if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
958     {
959       g_propagate_error (error, tmp_error);
960       return 0;
961     }
962   
963   g_free (builder->priv->filename);
964   g_free (builder->priv->resource_prefix);
965   builder->priv->filename = g_strdup (filename);
966   builder->priv->resource_prefix = NULL;
967
968   _gtk_builder_parser_parse_buffer (builder, filename,
969                                     buffer, length,
970                                     object_ids,
971                                     &tmp_error);
972
973   g_free (buffer);
974
975   if (tmp_error != NULL)
976     {
977       g_propagate_error (error, tmp_error);
978       return 0;
979     }
980
981   return 1;
982 }
983
984 /**
985  * gtk_builder_add_from_resource:
986  * @builder: a #GtkBuilder
987  * @resource_path: the path of the resource file to parse
988  * @error: (allow-none): return location for an error, or %NULL
989  *
990  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
991  * UI definition</link> and merges it with the current contents of @builder.
992  *
993  * Upon errors 0 will be returned and @error will be assigned a
994  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
995  * domain.
996  *
997  * Returns: A positive value on success, 0 if an error occurred
998  *
999  * Since: 3.4
1000  **/
1001 guint
1002 gtk_builder_add_from_resource (GtkBuilder   *builder,
1003                                const gchar  *resource_path,
1004                                GError      **error)
1005 {
1006   GError *tmp_error;
1007   GBytes *data;
1008   char *filename_for_errors;
1009   char *slash;
1010
1011   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1012   g_return_val_if_fail (resource_path != NULL, 0);
1013   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1014
1015   tmp_error = NULL;
1016
1017   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1018   if (data == NULL)
1019     {
1020       g_propagate_error (error, tmp_error);
1021       return 0;
1022     }
1023
1024   g_free (builder->priv->filename);
1025   g_free (builder->priv->resource_prefix);
1026   builder->priv->filename = g_strdup (".");
1027
1028   slash = strrchr (resource_path, '/');
1029   if (slash != NULL)
1030     builder->priv->resource_prefix =
1031       g_strndup (resource_path, slash - resource_path + 1);
1032   else
1033     builder->priv->resource_prefix =
1034       g_strdup ("/");
1035
1036   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1037
1038   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1039                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1040                                     NULL,
1041                                     &tmp_error);
1042
1043   g_free (filename_for_errors);
1044   g_bytes_unref (data);
1045
1046   if (tmp_error != NULL)
1047     {
1048       g_propagate_error (error, tmp_error);
1049       return 0;
1050     }
1051
1052   return 1;
1053 }
1054
1055 /**
1056  * gtk_builder_add_objects_from_resource:
1057  * @builder: a #GtkBuilder
1058  * @resource_path: the path of the resource file to parse
1059  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1060  * @error: (allow-none): return location for an error, or %NULL
1061  *
1062  * Parses a resource file containing a <link linkend="BUILDER-UI">GtkBuilder
1063  * UI definition</link> building only the requested objects and merges
1064  * them with the current contents of @builder.
1065  *
1066  * Upon errors 0 will be returned and @error will be assigned a
1067  * #GError from the #GTK_BUILDER_ERROR, #G_MARKUP_ERROR or #G_RESOURCE_ERROR
1068  * domain.
1069  *
1070  * <note><para>
1071  * If you are adding an object that depends on an object that is not
1072  * its child (for instance a #GtkTreeView that depends on its
1073  * #GtkTreeModel), you have to explicitely list all of them in @object_ids.
1074  * </para></note>
1075  *
1076  * Returns: A positive value on success, 0 if an error occurred
1077  *
1078  * Since: 3.4
1079  **/
1080 guint
1081 gtk_builder_add_objects_from_resource (GtkBuilder   *builder,
1082                                        const gchar  *resource_path,
1083                                        gchar       **object_ids,
1084                                        GError      **error)
1085 {
1086   GError *tmp_error;
1087   GBytes *data;
1088   char *filename_for_errors;
1089   char *slash;
1090
1091   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1092   g_return_val_if_fail (resource_path != NULL, 0);
1093   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1094   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1095
1096   tmp_error = NULL;
1097
1098   data = g_resources_lookup_data (resource_path, 0, &tmp_error);
1099   if (data == NULL)
1100     {
1101       g_propagate_error (error, tmp_error);
1102       return 0;
1103     }
1104
1105   g_free (builder->priv->filename);
1106   g_free (builder->priv->resource_prefix);
1107   builder->priv->filename = g_strdup (".");
1108
1109   slash = strrchr (resource_path, '/');
1110   if (slash != NULL)
1111     builder->priv->resource_prefix =
1112       g_strndup (resource_path, slash - resource_path + 1);
1113   else
1114     builder->priv->resource_prefix =
1115       g_strdup ("/");
1116
1117   filename_for_errors = g_strconcat ("<resource>", resource_path, NULL);
1118
1119   _gtk_builder_parser_parse_buffer (builder, filename_for_errors,
1120                                     g_bytes_get_data (data, NULL), g_bytes_get_size (data),
1121                                     object_ids,
1122                                     &tmp_error);
1123   g_free (filename_for_errors);
1124   g_bytes_unref (data);
1125
1126   if (tmp_error != NULL)
1127     {
1128       g_propagate_error (error, tmp_error);
1129       return 0;
1130     }
1131
1132   return 1;
1133 }
1134
1135 /**
1136  * gtk_builder_add_from_string:
1137  * @builder: a #GtkBuilder
1138  * @buffer: the string to parse
1139  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1140  * @error: (allow-none): return location for an error, or %NULL
1141  *
1142  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1143  * UI definition</link> and merges it with the current contents of @builder. 
1144  *
1145  * Upon errors 0 will be returned and @error will be assigned a
1146  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1147  *
1148  * Returns: A positive value on success, 0 if an error occurred
1149  *
1150  * Since: 2.12
1151  **/
1152 guint
1153 gtk_builder_add_from_string (GtkBuilder   *builder,
1154                              const gchar  *buffer,
1155                              gsize         length,
1156                              GError      **error)
1157 {
1158   GError *tmp_error;
1159
1160   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1161   g_return_val_if_fail (buffer != NULL, 0);
1162   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1163
1164   tmp_error = NULL;
1165
1166   g_free (builder->priv->filename);
1167   g_free (builder->priv->resource_prefix);
1168   builder->priv->filename = g_strdup (".");
1169   builder->priv->resource_prefix = NULL;
1170
1171   _gtk_builder_parser_parse_buffer (builder, "<input>",
1172                                     buffer, length,
1173                                     NULL,
1174                                     &tmp_error);
1175   if (tmp_error != NULL)
1176     {
1177       g_propagate_error (error, tmp_error);
1178       return 0;
1179     }
1180
1181   return 1;
1182 }
1183
1184 /**
1185  * gtk_builder_add_objects_from_string:
1186  * @builder: a #GtkBuilder
1187  * @buffer: the string to parse
1188  * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
1189  * @object_ids: (array zero-terminated=1) (element-type utf8): nul-terminated array of objects to build
1190  * @error: (allow-none): return location for an error, or %NULL
1191  *
1192  * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder 
1193  * UI definition</link> building only the requested objects and merges
1194  * them with the current contents of @builder. 
1195  *
1196  * Upon errors 0 will be returned and @error will be assigned a
1197  * #GError from the #GTK_BUILDER_ERROR or #G_MARKUP_ERROR domain.
1198  * 
1199  * <note><para>
1200  * If you are adding an object that depends on an object that is not 
1201  * its child (for instance a #GtkTreeView that depends on its
1202  * #GtkTreeModel), you have to explicitely list all of them in @object_ids. 
1203  * </para></note>
1204  *
1205  * Returns: A positive value on success, 0 if an error occurred
1206  *
1207  * Since: 2.14
1208  **/
1209 guint
1210 gtk_builder_add_objects_from_string (GtkBuilder   *builder,
1211                                      const gchar  *buffer,
1212                                      gsize         length,
1213                                      gchar       **object_ids,
1214                                      GError      **error)
1215 {
1216   GError *tmp_error;
1217
1218   g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
1219   g_return_val_if_fail (buffer != NULL, 0);
1220   g_return_val_if_fail (object_ids != NULL && object_ids[0] != NULL, 0);
1221   g_return_val_if_fail (error == NULL || *error == NULL, 0);
1222
1223   tmp_error = NULL;
1224
1225   g_free (builder->priv->filename);
1226   g_free (builder->priv->resource_prefix);
1227   builder->priv->filename = g_strdup (".");
1228   builder->priv->resource_prefix = NULL;
1229
1230   _gtk_builder_parser_parse_buffer (builder, "<input>",
1231                                     buffer, length,
1232                                     object_ids,
1233                                     &tmp_error);
1234
1235   if (tmp_error != NULL)
1236     {
1237       g_propagate_error (error, tmp_error);
1238       return 0;
1239     }
1240
1241   return 1;
1242 }
1243
1244 /**
1245  * gtk_builder_get_object:
1246  * @builder: a #GtkBuilder
1247  * @name: name of object to get
1248  *
1249  * Gets the object named @name. Note that this function does not
1250  * increment the reference count of the returned object. 
1251  *
1252  * Return value: (transfer none): the object named @name or %NULL if
1253  *    it could not be found in the object tree.
1254  *
1255  * Since: 2.12
1256  **/
1257 GObject *
1258 gtk_builder_get_object (GtkBuilder  *builder,
1259                         const gchar *name)
1260 {
1261   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1262   g_return_val_if_fail (name != NULL, NULL);
1263
1264   return g_hash_table_lookup (builder->priv->objects, name);
1265 }
1266
1267 static void
1268 object_add_to_list (gchar    *object_id,
1269                     GObject  *object,
1270                     GSList  **list)
1271 {
1272   *list = g_slist_prepend (*list, object);
1273 }
1274
1275 /**
1276  * gtk_builder_get_objects:
1277  * @builder: a #GtkBuilder
1278  *
1279  * Gets all objects that have been constructed by @builder. Note that 
1280  * this function does not increment the reference counts of the returned
1281  * objects.
1282  *
1283  * Return value: (element-type GObject) (transfer container): a newly-allocated #GSList containing all the objects
1284  *   constructed by the #GtkBuilder instance. It should be freed by
1285  *   g_slist_free()
1286  *
1287  * Since: 2.12
1288  **/
1289 GSList *
1290 gtk_builder_get_objects (GtkBuilder *builder)
1291 {
1292   GSList *objects = NULL;
1293
1294   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1295
1296   g_hash_table_foreach (builder->priv->objects, (GHFunc)object_add_to_list, &objects);
1297
1298   return g_slist_reverse (objects);
1299 }
1300
1301 /**
1302  * gtk_builder_set_translation_domain:
1303  * @builder: a #GtkBuilder
1304  * @domain: (allow-none): the translation domain or %NULL
1305  *
1306  * Sets the translation domain of @builder. 
1307  * See #GtkBuilder:translation-domain.
1308  *
1309  * Since: 2.12
1310  **/
1311 void
1312 gtk_builder_set_translation_domain (GtkBuilder  *builder,
1313                                     const gchar *domain)
1314 {
1315   gchar *new_domain;
1316     
1317   g_return_if_fail (GTK_IS_BUILDER (builder));
1318
1319   new_domain = g_strdup (domain);
1320   g_free (builder->priv->domain);
1321   builder->priv->domain = new_domain;
1322
1323   g_object_notify (G_OBJECT (builder), "translation-domain");
1324 }
1325
1326 /**
1327  * gtk_builder_get_translation_domain:
1328  * @builder: a #GtkBuilder
1329  *
1330  * Gets the translation domain of @builder.
1331  *
1332  * Return value: the translation domain. This string is owned
1333  * by the builder object and must not be modified or freed.
1334  *
1335  * Since: 2.12
1336  **/
1337 const gchar *
1338 gtk_builder_get_translation_domain (GtkBuilder *builder)
1339 {
1340   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
1341
1342   return builder->priv->domain;
1343 }
1344
1345 typedef struct {
1346   GModule *module;
1347   gpointer data;
1348 } connect_args;
1349
1350 static void
1351 gtk_builder_connect_signals_default (GtkBuilder    *builder,
1352                                      GObject       *object,
1353                                      const gchar   *signal_name,
1354                                      const gchar   *handler_name,
1355                                      GObject       *connect_object,
1356                                      GConnectFlags  flags,
1357                                      gpointer       user_data)
1358 {
1359   GCallback func;
1360   connect_args *args = (connect_args*)user_data;
1361   
1362   if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
1363     {
1364       g_warning ("Could not find signal handler '%s'", handler_name);
1365       return;
1366     }
1367
1368   if (connect_object)
1369     g_signal_connect_object (object, signal_name, func, connect_object, flags);
1370   else
1371     g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
1372 }
1373
1374
1375 /**
1376  * gtk_builder_connect_signals:
1377  * @builder: a #GtkBuilder
1378  * @user_data: a pointer to a structure sent in as user data to all signals
1379  *
1380  * This method is a simpler variation of gtk_builder_connect_signals_full().
1381  * It uses #GModule's introspective features (by opening the module %NULL) 
1382  * to look at the application's symbol table. From here it tries to match
1383  * the signal handler names given in the interface description with
1384  * symbols in the application and connects the signals. Note that this
1385  * function can only be called once, subsequent calls will do nothing.
1386  * 
1387  * Note that this function will not work correctly if #GModule is not
1388  * supported on the platform.
1389  *
1390  * When compiling applications for Windows, you must declare signal callbacks
1391  * with #G_MODULE_EXPORT, or they will not be put in the symbol table.
1392  * On Linux and Unices, this is not necessary; applications should instead
1393  * be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
1394  * gmodule-export-2.0.
1395  *
1396  * Since: 2.12
1397  **/
1398 void
1399 gtk_builder_connect_signals (GtkBuilder *builder,
1400                              gpointer    user_data)
1401 {
1402   connect_args *args;
1403   
1404   g_return_if_fail (GTK_IS_BUILDER (builder));
1405   
1406   if (!g_module_supported ())
1407     g_error ("gtk_builder_connect_signals() requires working GModule");
1408
1409   args = g_slice_new0 (connect_args);
1410   args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
1411   args->data = user_data;
1412   
1413   gtk_builder_connect_signals_full (builder,
1414                                     gtk_builder_connect_signals_default,
1415                                     args);
1416   g_module_close (args->module);
1417
1418   g_slice_free (connect_args, args);
1419 }
1420
1421 /**
1422  * GtkBuilderConnectFunc:
1423  * @builder: a #GtkBuilder
1424  * @object: object to connect a signal to
1425  * @signal_name: name of the signal
1426  * @handler_name: name of the handler
1427  * @connect_object: a #GObject, if non-%NULL, use g_signal_connect_object()
1428  * @flags: #GConnectFlags to use
1429  * @user_data: user data
1430  *
1431  * This is the signature of a function used to connect signals.  It is used
1432  * by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
1433  * methods.  It is mainly intended for interpreted language bindings, but
1434  * could be useful where the programmer wants more control over the signal
1435  * connection process. Note that this function can only be called once,
1436  * subsequent calls will do nothing.
1437  *
1438  * Since: 2.12
1439  */
1440
1441 /**
1442  * gtk_builder_connect_signals_full:
1443  * @builder: a #GtkBuilder
1444  * @func: (scope call): the function used to connect the signals
1445  * @user_data: arbitrary data that will be passed to the connection function
1446  *
1447  * This function can be thought of the interpreted language binding
1448  * version of gtk_builder_connect_signals(), except that it does not
1449  * require GModule to function correctly.
1450  *
1451  * Since: 2.12
1452  */
1453 void
1454 gtk_builder_connect_signals_full (GtkBuilder            *builder,
1455                                   GtkBuilderConnectFunc  func,
1456                                   gpointer               user_data)
1457 {
1458   GSList *l;
1459   GObject *object;
1460   GObject *connect_object;
1461   
1462   g_return_if_fail (GTK_IS_BUILDER (builder));
1463   g_return_if_fail (func != NULL);
1464   
1465   if (!builder->priv->signals)
1466     return;
1467
1468   builder->priv->signals = g_slist_reverse (builder->priv->signals);
1469   for (l = builder->priv->signals; l; l = l->next)
1470     {
1471       SignalInfo *signal = (SignalInfo*)l->data;
1472
1473       g_assert (signal != NULL);
1474       g_assert (signal->name != NULL);
1475
1476       object = g_hash_table_lookup (builder->priv->objects,
1477                                     signal->object_name);
1478       g_assert (object != NULL);
1479
1480       connect_object = NULL;
1481       
1482       if (signal->connect_object_name)
1483         {
1484           connect_object = g_hash_table_lookup (builder->priv->objects,
1485                                                 signal->connect_object_name);
1486           if (!connect_object)
1487               g_warning ("Could not lookup object %s on signal %s of object %s",
1488                          signal->connect_object_name, signal->name,
1489                          signal->object_name);
1490         }
1491                                                   
1492       func (builder, object, signal->name, signal->handler, 
1493             connect_object, signal->flags, user_data);
1494     }
1495
1496   g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
1497   g_slist_free (builder->priv->signals);
1498   builder->priv->signals = NULL;
1499 }
1500
1501 /**
1502  * gtk_builder_value_from_string:
1503  * @builder: a #GtkBuilder
1504  * @pspec: the #GParamSpec for the property
1505  * @string: the string representation of the value
1506  * @value: (out): the #GValue to store the result in
1507  * @error: (allow-none): return location for an error, or %NULL
1508  *
1509  * This function demarshals a value from a string. This function
1510  * calls g_value_init() on the @value argument, so it need not be
1511  * initialised beforehand.
1512  *
1513  * This function can handle char, uchar, boolean, int, uint, long,
1514  * ulong, enum, flags, float, double, string, #GdkColor, #GdkRGBA and
1515  * #GtkAdjustment type values. Support for #GtkWidget type values is
1516  * still to come.
1517  *
1518  * Upon errors %FALSE will be returned and @error will be assigned a
1519  * #GError from the #GTK_BUILDER_ERROR domain.
1520  *
1521  * Returns: %TRUE on success
1522  *
1523  * Since: 2.12
1524  */
1525 gboolean
1526 gtk_builder_value_from_string (GtkBuilder   *builder,
1527                                GParamSpec   *pspec,
1528                                const gchar  *string,
1529                                GValue       *value,
1530                                GError      **error)
1531 {
1532   g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
1533   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1534   g_return_val_if_fail (string != NULL, FALSE);
1535   g_return_val_if_fail (value != NULL, FALSE);
1536   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1537
1538   /*
1539    * GParamSpecUnichar has the internal type G_TYPE_UINT,
1540    * so we cannot handle this in the switch, do it separately
1541    */
1542   if (G_IS_PARAM_SPEC_UNICHAR (pspec))
1543     {
1544       gunichar c;
1545       g_value_init (value, G_TYPE_UINT);
1546       c = g_utf8_get_char_validated (string, strlen (string));
1547       if (c > 0)
1548         g_value_set_uint (value, c);
1549       return TRUE;
1550     }
1551
1552   /*
1553    * GParamSpecVariant can specify a GVariantType which can help with
1554    * parsing, so we need to take care of that here.
1555    */
1556   if (G_IS_PARAM_SPEC_VARIANT (pspec))
1557     {
1558       GParamSpecVariant *variant_pspec = G_PARAM_SPEC_VARIANT (pspec);
1559       const GVariantType *type;
1560       GVariant *variant;
1561
1562       g_value_init (value, G_TYPE_VARIANT);
1563
1564       /* The GVariant parser doesn't deal with indefinite types */
1565       if (g_variant_type_is_definite (variant_pspec->type))
1566         type = variant_pspec->type;
1567       else
1568         type = NULL;
1569
1570       variant = g_variant_parse (type, string, NULL, NULL, error);
1571       if (variant == NULL)
1572         return FALSE;
1573       g_value_take_variant (value, variant);
1574       return TRUE;
1575     }
1576
1577   return gtk_builder_value_from_string_type (builder,
1578                                              G_PARAM_SPEC_VALUE_TYPE (pspec),
1579                                              string, value, error);
1580 }
1581
1582 /**
1583  * gtk_builder_value_from_string_type:
1584  * @builder: a #GtkBuilder
1585  * @type: the #GType of the value
1586  * @string: the string representation of the value
1587  * @value: (out): the #GValue to store the result in
1588  * @error: (allow-none): return location for an error, or %NULL
1589  *
1590  * Like gtk_builder_value_from_string(), this function demarshals 
1591  * a value from a string, but takes a #GType instead of #GParamSpec.
1592  * This function calls g_value_init() on the @value argument, so it 
1593  * need not be initialised beforehand.
1594  *
1595  * Upon errors %FALSE will be returned and @error will be assigned a
1596  * #GError from the #GTK_BUILDER_ERROR domain.
1597  *
1598  * Returns: %TRUE on success
1599  *
1600  * Since: 2.12
1601  */
1602 gboolean
1603 gtk_builder_value_from_string_type (GtkBuilder   *builder,
1604                                     GType         type,
1605                                     const gchar  *string,
1606                                     GValue       *value,
1607                                     GError      **error)
1608 {
1609   gboolean ret = TRUE;
1610
1611   g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
1612   g_return_val_if_fail (string != NULL, FALSE);
1613   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1614
1615   g_value_init (value, type);
1616
1617   switch (G_TYPE_FUNDAMENTAL (type))
1618     {
1619     case G_TYPE_CHAR:
1620       g_value_set_schar (value, string[0]);
1621       break;
1622     case G_TYPE_UCHAR:
1623       g_value_set_uchar (value, (guchar)string[0]);
1624       break;
1625     case G_TYPE_BOOLEAN:
1626       {
1627         gboolean b;
1628
1629         if (!_gtk_builder_boolean_from_string (string, &b, error))
1630           {
1631             ret = FALSE;
1632             break;
1633           }
1634         g_value_set_boolean (value, b);
1635         break;
1636       }
1637     case G_TYPE_INT:
1638     case G_TYPE_LONG:
1639       {
1640         long l;
1641         gchar *endptr = NULL;
1642         errno = 0;
1643         l = g_ascii_strtoll (string, &endptr, 0);
1644         if (errno || endptr == string)
1645           {
1646             g_set_error (error,
1647                          GTK_BUILDER_ERROR,
1648                          GTK_BUILDER_ERROR_INVALID_VALUE,
1649                          "Could not parse integer `%s'",
1650                          string);
1651             ret = FALSE;
1652             break;
1653           }
1654         if (G_VALUE_HOLDS_INT (value))
1655           g_value_set_int (value, l);
1656         else
1657           g_value_set_long (value, l);
1658         break;
1659       }
1660     case G_TYPE_UINT:
1661     case G_TYPE_ULONG:
1662       {
1663         gulong ul;
1664         gchar *endptr = NULL;
1665         errno = 0;
1666         ul = g_ascii_strtoull (string, &endptr, 0);
1667         if (errno || endptr == string)
1668           {
1669             g_set_error (error,
1670                          GTK_BUILDER_ERROR,
1671                          GTK_BUILDER_ERROR_INVALID_VALUE,
1672                          "Could not parse unsigned integer `%s'",
1673                          string);
1674             ret = FALSE;
1675             break;
1676           }
1677         if (G_VALUE_HOLDS_UINT (value))
1678           g_value_set_uint (value, ul);
1679         else 
1680           g_value_set_ulong (value, ul);
1681         break;
1682       }
1683     case G_TYPE_ENUM:
1684       {
1685         gint enum_value;
1686         if (!_gtk_builder_enum_from_string (type, string, &enum_value, error))
1687           {
1688             ret = FALSE;
1689             break;
1690           }
1691         g_value_set_enum (value, enum_value);
1692         break;
1693       }
1694     case G_TYPE_FLAGS:
1695       {
1696         guint flags_value;
1697
1698         if (!_gtk_builder_flags_from_string (type, string, &flags_value, error))
1699           {
1700             ret = FALSE;
1701             break;
1702           }
1703         g_value_set_flags (value, flags_value);
1704         break;
1705       }
1706     case G_TYPE_FLOAT:
1707     case G_TYPE_DOUBLE:
1708       {
1709         gdouble d;
1710         gchar *endptr = NULL;
1711         errno = 0;
1712         d = g_ascii_strtod (string, &endptr);
1713         if (errno || endptr == string)
1714           {
1715             g_set_error (error,
1716                          GTK_BUILDER_ERROR,
1717                          GTK_BUILDER_ERROR_INVALID_VALUE,
1718                          "Could not parse double `%s'",
1719                          string);
1720             ret = FALSE;
1721             break;
1722           }
1723         if (G_VALUE_HOLDS_FLOAT (value))
1724           g_value_set_float (value, d);
1725         else
1726           g_value_set_double (value, d);
1727         break;
1728       }
1729     case G_TYPE_STRING:
1730       g_value_set_string (value, string);
1731       break;
1732     case G_TYPE_VARIANT:
1733       {
1734         GVariant *variant;
1735
1736         variant = g_variant_parse (NULL, string, NULL, NULL, error);
1737         if (value != NULL)
1738           g_value_take_variant (value, variant);
1739         else
1740           ret = FALSE;
1741       }
1742       break;
1743     case G_TYPE_BOXED:
1744       if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
1745         {
1746           GdkColor color = { 0, };
1747
1748           if (gdk_color_parse (string, &color))
1749             g_value_set_boxed (value, &color);
1750           else
1751             {
1752               g_set_error (error,
1753                            GTK_BUILDER_ERROR,
1754                            GTK_BUILDER_ERROR_INVALID_VALUE,
1755                            "Could not parse color `%s'",
1756                            string);
1757               ret = FALSE;
1758             }
1759         }
1760       else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
1761         {
1762           GdkRGBA rgba = { 0 };
1763
1764           if (gdk_rgba_parse (&rgba, string))
1765             g_value_set_boxed (value, &rgba);
1766           else
1767             {
1768               g_set_error (error,
1769                            GTK_BUILDER_ERROR,
1770                            GTK_BUILDER_ERROR_INVALID_VALUE,
1771                            "Could not parse RGBA color '%s'",
1772                            string);
1773               ret = FALSE;
1774             }
1775         }
1776       else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
1777         {
1778           gchar **vector = g_strsplit (string, "\n", 0);
1779           g_value_take_boxed (value, vector);
1780         }
1781       else
1782         {
1783           g_set_error (error,
1784                        GTK_BUILDER_ERROR,
1785                        GTK_BUILDER_ERROR_INVALID_VALUE,
1786                        "Could not parse '%s' as a %s",
1787                        string, G_VALUE_TYPE_NAME (value));
1788           ret = FALSE;
1789         }
1790       break;
1791     case G_TYPE_OBJECT:
1792       if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
1793         {
1794           gchar *filename;
1795           GError *tmp_error = NULL;
1796           GdkPixbuf *pixbuf = NULL;
1797        
1798           if (gtk_builder_get_object (builder, string))
1799             {
1800               g_set_error (error,
1801                            GTK_BUILDER_ERROR,
1802                            GTK_BUILDER_ERROR_INVALID_VALUE,
1803                            "Could not load image '%s': "
1804                            " '%s' is already used as object id",
1805                            string, string);
1806               return FALSE;
1807             }
1808
1809           filename = _gtk_builder_get_resource_path (builder, string);
1810           if (filename != NULL)
1811             {
1812               GInputStream *stream = g_resources_open_stream (filename, 0, &tmp_error);
1813               if (stream != NULL)
1814                 {
1815                   pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &tmp_error);
1816                   g_object_unref (stream);
1817                 }
1818             }
1819           else
1820             {
1821               filename = _gtk_builder_get_absolute_filename (builder, string);
1822               pixbuf = gdk_pixbuf_new_from_file (filename, &tmp_error);
1823             }
1824
1825           if (pixbuf == NULL)
1826             {
1827               GtkIconTheme *theme;
1828
1829               g_warning ("Could not load image '%s': %s", 
1830                          string, tmp_error->message);
1831               g_error_free (tmp_error);
1832
1833               /* fall back to a missing image */
1834               theme = gtk_icon_theme_get_default ();
1835               pixbuf = gtk_icon_theme_load_icon (theme, 
1836                                                  GTK_STOCK_MISSING_IMAGE,
1837                                                  16,
1838                                                  GTK_ICON_LOOKUP_USE_BUILTIN,
1839                                                  NULL);
1840             }
1841  
1842           if (pixbuf)
1843             {
1844               g_value_set_object (value, pixbuf);
1845               g_object_unref (G_OBJECT (pixbuf));
1846             }
1847
1848           g_free (filename);
1849
1850           ret = TRUE;
1851         }
1852       else
1853         ret = FALSE;
1854       break;
1855     default:
1856       ret = FALSE;
1857       break;
1858     }
1859  
1860   /* Catch unassigned error for object types as well as any unsupported types.
1861    * While parsing GtkBuilder; object types are deserialized
1862    * without calling gtk_builder_value_from_string_type().
1863    */
1864   if (!ret && error && *error == NULL) 
1865     g_set_error (error,
1866                  GTK_BUILDER_ERROR,
1867                  GTK_BUILDER_ERROR_INVALID_VALUE,
1868                  "Unsupported GType `%s'", g_type_name (type));
1869
1870   return ret;
1871 }
1872
1873 gboolean
1874 _gtk_builder_enum_from_string (GType         type, 
1875                                const gchar  *string,
1876                                gint         *enum_value,
1877                                GError      **error)
1878 {
1879   GEnumClass *eclass;
1880   GEnumValue *ev;
1881   gchar *endptr;
1882   gint value;
1883   gboolean ret;
1884   
1885   g_return_val_if_fail (G_TYPE_IS_ENUM (type), FALSE);
1886   g_return_val_if_fail (string != NULL, FALSE);
1887   
1888   ret = TRUE;
1889
1890   endptr = NULL;
1891   errno = 0;
1892   value = g_ascii_strtoull (string, &endptr, 0);
1893   if (errno == 0 && endptr != string) /* parsed a number */
1894     *enum_value = value;
1895   else
1896     {
1897       eclass = g_type_class_ref (type);
1898       ev = g_enum_get_value_by_name (eclass, string);
1899       if (!ev)
1900         ev = g_enum_get_value_by_nick (eclass, string);
1901
1902       if (ev)
1903         *enum_value = ev->value;
1904       else
1905         {
1906           g_set_error (error,
1907                        GTK_BUILDER_ERROR,
1908                        GTK_BUILDER_ERROR_INVALID_VALUE,
1909                        "Could not parse enum: `%s'",
1910                        string);
1911           ret = FALSE;
1912         }
1913       
1914       g_type_class_unref (eclass);
1915     }
1916   
1917   return ret;
1918 }
1919
1920 gboolean
1921 _gtk_builder_flags_from_string (GType         type, 
1922                                 const gchar  *string,
1923                                 guint        *flags_value,
1924                                 GError      **error)
1925 {
1926   GFlagsClass *fclass;
1927   gchar *endptr, *prevptr;
1928   guint i, j, value;
1929   gchar *flagstr;
1930   GFlagsValue *fv;
1931   const gchar *flag;
1932   gunichar ch;
1933   gboolean eos, ret;
1934
1935   g_return_val_if_fail (G_TYPE_IS_FLAGS (type), FALSE);
1936   g_return_val_if_fail (string != 0, FALSE);
1937
1938   ret = TRUE;
1939
1940   endptr = NULL;
1941   errno = 0;
1942   value = g_ascii_strtoull (string, &endptr, 0);
1943   if (errno == 0 && endptr != string) /* parsed a number */
1944     *flags_value = value;
1945   else
1946     {
1947       fclass = g_type_class_ref (type);
1948
1949       flagstr = g_strdup (string);
1950       for (value = i = j = 0; ; i++)
1951         {
1952           
1953           eos = flagstr[i] == '\0';
1954           
1955           if (!eos && flagstr[i] != '|')
1956             continue;
1957           
1958           flag = &flagstr[j];
1959           endptr = &flagstr[i];
1960           
1961           if (!eos)
1962             {
1963               flagstr[i++] = '\0';
1964               j = i;
1965             }
1966           
1967           /* trim spaces */
1968           for (;;)
1969             {
1970               ch = g_utf8_get_char (flag);
1971               if (!g_unichar_isspace (ch))
1972                 break;
1973               flag = g_utf8_next_char (flag);
1974             }
1975           
1976           while (endptr > flag)
1977             {
1978               prevptr = g_utf8_prev_char (endptr);
1979               ch = g_utf8_get_char (prevptr);
1980               if (!g_unichar_isspace (ch))
1981                 break;
1982               endptr = prevptr;
1983             }
1984           
1985           if (endptr > flag)
1986             {
1987               *endptr = '\0';
1988               fv = g_flags_get_value_by_name (fclass, flag);
1989               
1990               if (!fv)
1991                 fv = g_flags_get_value_by_nick (fclass, flag);
1992               
1993               if (fv)
1994                 value |= fv->value;
1995               else
1996                 {
1997                   g_set_error (error,
1998                                GTK_BUILDER_ERROR,
1999                                GTK_BUILDER_ERROR_INVALID_VALUE,
2000                                "Unknown flag: `%s'",
2001                                flag);
2002                   ret = FALSE;
2003                   break;
2004                 }
2005             }
2006           
2007           if (eos)
2008             {
2009               *flags_value = value;
2010               break;
2011             }
2012         }
2013       
2014       g_free (flagstr);
2015       
2016       g_type_class_unref (fclass);
2017     }
2018
2019   return ret;
2020 }
2021
2022 /**
2023  * gtk_builder_get_type_from_name:
2024  * @builder: a #GtkBuilder
2025  * @type_name: type name to lookup
2026  *
2027  * Looks up a type by name, using the virtual function that 
2028  * #GtkBuilder has for that purpose. This is mainly used when
2029  * implementing the #GtkBuildable interface on a type.
2030  *
2031  * Returns: the #GType found for @type_name or #G_TYPE_INVALID 
2032  *   if no type was found
2033  *
2034  * Since: 2.12
2035  */
2036 GType
2037 gtk_builder_get_type_from_name (GtkBuilder  *builder, 
2038                                 const gchar *type_name)
2039 {
2040   g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
2041   g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2042
2043   return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, type_name);
2044 }
2045
2046 GQuark
2047 gtk_builder_error_quark (void)
2048 {
2049   return g_quark_from_static_string ("gtk-builder-error-quark");
2050 }
2051
2052 gchar *
2053 _gtk_builder_get_resource_path (GtkBuilder *builder, const gchar *string)
2054 {
2055   if (g_str_has_prefix (string, "resource:///"))
2056     return g_uri_unescape_string (string + 11, "/");
2057
2058   if (g_path_is_absolute (string) ||
2059       builder->priv->resource_prefix == NULL)
2060     return NULL;
2061
2062   return g_build_path ("/", builder->priv->resource_prefix, string, NULL);
2063 }
2064
2065 gchar *
2066 _gtk_builder_get_absolute_filename (GtkBuilder *builder, const gchar *string)
2067 {
2068   gchar *filename;
2069   gchar *dirname = NULL;
2070   
2071   if (g_path_is_absolute (string))
2072     return g_strdup (string);
2073
2074   if (builder->priv->filename &&
2075       strcmp (builder->priv->filename, ".") != 0) 
2076     {
2077       dirname = g_path_get_dirname (builder->priv->filename);
2078
2079       if (strcmp (dirname, ".") == 0)
2080         {
2081           g_free (dirname);
2082           dirname = g_get_current_dir ();
2083         }
2084     }
2085   else
2086     dirname = g_get_current_dir ();
2087     
2088   filename = g_build_filename (dirname, string, NULL);
2089   g_free (dirname);
2090   
2091   return filename;
2092 }