Index: gtk/gtkaction.c
===================================================================
--- gtk/gtkaction.c	(revisão 18111)
+++ gtk/gtkaction.c	(cópia de trabalho)
@@ -46,6 +46,7 @@
 #include "gtktoolbutton.h"
 #include "gtktoolbar.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 
@@ -107,14 +108,22 @@ enum 
   PROP_ACTION_GROUP
 };
 
+/* GtkBuildable */
+static void gtk_action_buildable_init             (GtkBuildableIface *iface);
+static void gtk_action_buildable_set_name         (GtkBuildable *buildable,
+						   const gchar  *name);
+static const gchar* gtk_action_buildable_get_name (GtkBuildable *buildable);
+
+G_DEFINE_TYPE_WITH_CODE (GtkAction, gtk_action, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_action_buildable_init))
+
 
 static GQuark      accel_path_id  = 0;
 static GQuark      quark_gtk_action_proxy  = 0;
 static const gchar accel_path_key[] = "GtkAction::accel_path";
 static const gchar gtk_action_proxy_key[] = "gtk-action";
 
-G_DEFINE_TYPE (GtkAction, gtk_action, G_TYPE_OBJECT)
-
 static void gtk_action_finalize     (GObject *object);
 static void gtk_action_set_property (GObject         *object,
 				     guint            prop_id,
@@ -378,6 +387,33 @@ gtk_action_init (GtkAction *action)
   action->private_data->proxies = NULL;
 }
 
+static void
+gtk_action_buildable_init (GtkBuildableIface *iface)
+{
+  iface->set_name = gtk_action_buildable_set_name;
+  iface->get_name = gtk_action_buildable_get_name;
+}
+
+static void
+gtk_action_buildable_set_name (GtkBuildable *buildable,
+			       const gchar  *name)
+{
+  gchar *tmp;
+  GtkAction *action = GTK_ACTION (buildable);
+
+  tmp = action->private_data->name;
+  action->private_data->name = g_strdup (name);
+  g_free (tmp);
+}
+
+static const gchar *
+gtk_action_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkAction *action = GTK_ACTION (buildable);
+
+  return action->private_data->name;
+}
+
 /**
  * gtk_action_new:
  * @name: A unique name for the action
Index: gtk/gtkactiongroup.c
===================================================================
--- gtk/gtkactiongroup.c	(revisão 18111)
+++ gtk/gtkactiongroup.c	(cópia de trabalho)
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include "gtkactiongroup.h"
+#include "gtkbuildable.h"
 #include "gtkiconfactory.h"
 #include "gtkicontheme.h"
 #include "gtkstock.h"
@@ -87,6 +88,15 @@ static void       gtk_action_group_get_p
 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup      *self,
 						    const gchar         *name);
 
+/* GtkBuildable */
+static void gtk_action_group_buildable_init (GtkBuildableIface *iface);
+static void gtk_action_group_buildable_add (GtkBuildable  *buildable,
+					    GtkBuilder    *builder,
+					    GObject       *child,
+					    const gchar   *type);
+static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+						 const gchar  *name);
+static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable);
 
 GType
 gtk_action_group_get_type (void)
@@ -108,10 +118,20 @@ gtk_action_group_get_type (void)
         (GInstanceInitFunc) gtk_action_group_init,
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+	(GInterfaceInitFunc) gtk_action_group_buildable_init,
+	NULL,
+	NULL
+      };
+
       type = g_type_register_static (G_TYPE_OBJECT, I_("GtkActionGroup"),
 				     &type_info, 0);
-    }
 
+      g_type_add_interface_static (type,
+				   GTK_TYPE_BUILDABLE,
+				   &buildable_info);
+    }
   return type;
 }
 
@@ -272,6 +292,39 @@ gtk_action_group_init (GtkActionGroup *s
   self->private_data->translate_notify = NULL;
 }
 
+static void
+gtk_action_group_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_action_group_buildable_add;
+  iface->set_name = gtk_action_group_buildable_set_name;
+  iface->get_name = gtk_action_group_buildable_get_name;
+}
+
+static void
+gtk_action_group_buildable_add (GtkBuildable  *buildable,
+				GtkBuilder    *builder,
+				GObject       *child,
+				const gchar   *type)
+{
+  gtk_action_group_add_action (GTK_ACTION_GROUP (buildable),
+			       GTK_ACTION (child));
+}
+
+static void
+gtk_action_group_buildable_set_name (GtkBuildable *buildable,
+				     const gchar  *name)
+{
+  GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+  self->private_data->name = g_strdup (name);
+}
+
+static const gchar *
+gtk_action_group_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
+  return self->private_data->name;
+}
+
 /**
  * gtk_action_group_new:
  * @name: the name of the action group.
Index: gtk/gtkbuildable.c
===================================================================
--- gtk/gtkbuildable.c	(revisão 0)
+++ gtk/gtkbuildable.c	(revisão 0)
@@ -0,0 +1,372 @@
+/* gtkbuildable.c
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include "gtkbuildable.h"
+#include "gtktypeutils.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+GType
+gtk_buildable_get_type (void)
+{
+  static GType buildable_type = 0;
+
+  if (!buildable_type)
+    buildable_type =
+      g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkBuildable"),
+				     sizeof (GtkBuildableIface),
+				     NULL, 0, NULL, 0);
+
+  return buildable_type;
+}
+
+/**
+ * gtk_buildable_set_name:
+ * @buildable: a #GtkBuildable
+ * @name: name to set
+ *
+ * Sets the name of the buildable object, it's used to synchronize the name
+ * if the object already has it's own concept of name.
+ *
+ * #GtkWidget implements this to map the buildable name to the widget name
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_set_name (GtkBuildable *buildable,
+                        const gchar  *name)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (name != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  if (iface->set_name)
+    (* iface->set_name) (buildable, name);
+  else
+    g_object_set_data_full (G_OBJECT (buildable),
+			    "gtk-builder-name",
+			    g_strdup (name),
+			    g_free);
+}
+
+/**
+ * gtk_buildable_get_name:
+ * @buildable: a #GtkBuildable
+ *
+ * Returns: the buildable name, the name which was set in
+ * the <link linkend="BUILDER-UI">GtkBuilder UI definition</link> used to
+ * construct the @buildable.
+ *
+ * #GtkWidget implements this to map the buildable name to the widget name
+ *
+ * Since: 2.12
+ **/
+const gchar *
+gtk_buildable_get_name (GtkBuildable *buildable)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+
+  if (iface->get_name)
+    return (* iface->get_name) (buildable);
+  else
+    return (const gchar*)g_object_get_data (G_OBJECT (buildable),
+					    "gtk-builder-name");
+}
+
+/**
+ * gtk_buildable_add:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @child: child to add
+ * @type: kind of child or %NULL
+ *
+ * Add a child to a buildable. type is an optional string
+ * describing how the child should be added.
+ *
+ * #GtkContainer implements this to be able to add a child widget
+ * to the container. #GtkNotebook uses the @type to distinguish between
+ * page labels (@type = "page-label") and normal children.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_add (GtkBuildable *buildable,
+                   GtkBuilder   *builder,
+                   GObject      *child,
+                   const gchar  *type)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_if_fail (iface->add != NULL);
+
+  (* iface->add) (buildable, builder, child, type);
+}
+
+/**
+ * gtk_buildable_set_property:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @name: name of property
+ * @value: value of property
+ *
+ * Sets the property name @name to @value on the buildable object @buildable
+ * which is created by the @builder.
+ *
+ * This is optional to implement and is normally not neeeded.
+ * g_object_set_property() is used as a fallback.
+ *
+ * #GtkWindow implements this to delay showing (::visible) itself until
+ * the whole interface is fully created.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_set_property (GtkBuildable *buildable,
+                            GtkBuilder   *builder,
+                            const gchar  *name,
+                            const GValue *value)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (value != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->set_property)
+    (* iface->set_property) (buildable, builder, name, value);
+  else
+    g_object_set_property (G_OBJECT (buildable), name, value);
+}
+
+/**
+ * gtk_buildable_parser_finished:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ *
+ * Finish the parsing of a <link linkend="BUILDER-UI">GtkBuilder UI definition</link>
+ * snippet. Note that this will be called once for each time gtk_builder_add_from_file or
+ * gtk_builder_add_from_string is called on a builder.
+ *
+ * #GtkWindow implements this to delay showing (::visible) itself until
+ * the whole interface is fully created.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_parser_finished (GtkBuildable *buildable,
+			       GtkBuilder   *builder)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->parser_finished)
+    (* iface->parser_finished) (buildable, builder);
+}
+
+/**
+ * gtk_buildable_construct_child
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @name: name of child to construct
+ *
+ * Construct a child of @buildable with the name @name.
+ *
+ * #GtkUIManager implements this to reference to a widget created in a <ui> tag
+ * which is outsideof the normal <link linkend="BUILDER-UI">GtkBuilder UI definition</link>
+ * object hierarchy.
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_buildable_construct_child (GtkBuildable *buildable,
+                               GtkBuilder   *builder,
+                               const gchar  *name)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_val_if_fail (iface->construct_child != NULL, NULL);
+
+  return (* iface->construct_child) (buildable, builder, name);
+}
+
+/**
+ * gtk_buildable_custom_tag_start
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder used to construct this object
+ * @child: child object or %NULL for non-child tags
+ * @tagname: name of tag
+ * @parser: a #GMarkupParser structure
+ * @data: user data that will be passed in to parser functions
+ *
+ * This is called when an unknown tag under <child> tag is found.
+ * 
+ * Called when an unknown tag is present under a a <child> tag.
+ * If the buildable implementation wishes to handle the tag it should
+ * return %TRUE and fill in the @parser structure. Remember to either
+ * implement custom_tag_end or custom_tag_finish to free
+ * the user data allocated here.
+ *
+ * #GtkWidget implements this and parsers all <accelerator> tags to
+ * keyboard accelerators.
+ * #GtkContainer implements this to map properties defined under <packing>
+ * tag to child properties.
+ *
+ * Returns: %TRUE if a object has a custom implementation, %FALSE
+ *          if it doesn't.
+ *
+ * Since: 2.12
+ **/
+gboolean
+gtk_buildable_custom_tag_start (GtkBuildable  *buildable,
+                                GtkBuilder    *builder,
+                                GObject       *child,
+                                const gchar   *tagname,
+                                GMarkupParser *parser,
+                                gpointer      *data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), FALSE);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), FALSE);
+  g_return_val_if_fail (tagname != NULL, FALSE);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  g_return_val_if_fail (iface->custom_tag_start != NULL, FALSE);
+
+  return (* iface->custom_tag_start) (buildable, builder, child,
+                                      tagname, parser, data);
+}
+
+/**
+ * gtk_buildable_custom_tag_end
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @child: child object or %NULL for non-child tags
+ * @tagname: name of tag
+ * @data: user data that will be passed in to parser functions
+ *
+ * This is called for each custom tag handled by the buildable.
+ * It will be called when the end of the tag is reached.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_buildable_custom_tag_end (GtkBuildable  *buildable,
+                              GtkBuilder    *builder,
+                              GObject       *child,
+                              const gchar   *tagname,
+                              gpointer      *data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (tagname != NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->custom_tag_end)
+    (* iface->custom_tag_end) (buildable, builder, child, tagname, data);
+}
+
+/**
+ * gtk_buildable_custom_finished:
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @child: child object or %NULL for non-child tags
+ * @tagname: the name of the tag
+ * @data: user data created in custom_tag_start
+ *
+ * This is similar to gtk_buildable_parser_finished() but is
+ * called once for each custom tag handled by the @buildable.
+ * 
+ * Since: 2.12
+ **/
+void
+gtk_buildable_custom_finished (GtkBuildable  *buildable,
+			       GtkBuilder    *builder,
+			       GObject       *child,
+			       const gchar   *tagname,
+			       gpointer       data)
+{
+  GtkBuildableIface *iface;
+
+  g_return_if_fail (GTK_IS_BUILDABLE (buildable));
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (iface->custom_finished)
+    (* iface->custom_finished) (buildable, builder, child, tagname, data);
+}
+
+/**
+ * gtk_buildable_get_internal_child
+ * @buildable: a #GtkBuildable
+ * @builder: a #GtkBuilder
+ * @childname: name of child
+ *
+ * Get the internal child called @child of the @buildable object.
+ *
+ * Return: the internal child of the buildable object
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_buildable_get_internal_child (GtkBuildable *buildable,
+                                  GtkBuilder   *builder,
+                                  const gchar  *childname)
+{
+  GtkBuildableIface *iface;
+
+  g_return_val_if_fail (GTK_IS_BUILDABLE (buildable), NULL);
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (childname != NULL, NULL);
+
+  iface = GTK_BUILDABLE_GET_IFACE (buildable);
+  if (!iface->get_internal_child)
+    return NULL;
+
+  return (* iface->get_internal_child) (buildable, builder, childname);
+}
+
+#define __GTK_BUILDABLE_C__
+#include "gtkaliasdef.c"
Index: gtk/gtkbuildable.h
===================================================================
--- gtk/gtkbuildable.h	(revisão 0)
+++ gtk/gtkbuildable.h	(revisão 0)
@@ -0,0 +1,123 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDABLE_H__
+#define __GTK_BUILDABLE_H__
+
+#include <glib/gmarkup.h>
+#include <gtk/gtkbuilder.h>
+#include <gtk/gtktypeutils.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDABLE            (gtk_buildable_get_type ())
+#define GTK_BUILDABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildable))
+#define GTK_BUILDABLE_CLASS(obj)      (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+#define GTK_IS_BUILDABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDABLE))
+#define GTK_BUILDABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_BUILDABLE, GtkBuildableIface))
+
+typedef struct _GtkBuildable      GtkBuildable; /* Dummy typedef */
+typedef struct _GtkBuildableIface GtkBuildableIface;
+
+struct _GtkBuildableIface
+{
+  GTypeInterface g_iface;
+
+  /* virtual table */
+  void          (* set_name)            (GtkBuildable  *buildable,
+                                         const gchar   *name);
+  const gchar * (* get_name)            (GtkBuildable  *buildable);
+  void          (* add)                 (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *type);
+  void          (* set_property)        (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *name,
+                                         const GValue  *value);
+  GObject *     (* construct_child)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *name);
+  gboolean      (* custom_tag_start)    (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         GMarkupParser *parser,
+                                         gpointer      *data);
+  void          (* custom_tag_end)      (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         gpointer      *data);
+  void          (* custom_finished)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         GObject       *child,
+                                         const gchar   *tagname,
+                                         gpointer       data);
+  void          (* parser_finished)     (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder);
+
+  GObject *    (* get_internal_child)   (GtkBuildable  *buildable,
+                                         GtkBuilder    *builder,
+                                         const gchar   *childname);
+};
+
+
+GType     gtk_buildable_get_type           (void) G_GNUC_CONST;
+
+void      gtk_buildable_set_name           (GtkBuildable        *buildable,
+                                            const gchar         *name);
+const gchar * gtk_buildable_get_name       (GtkBuildable        *buildable);
+void      gtk_buildable_add                (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *type);
+void      gtk_buildable_set_property       (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *name,
+                                            const GValue        *value);
+GObject * gtk_buildable_construct_child    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *name);
+gboolean  gtk_buildable_custom_tag_start   (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            GMarkupParser       *parser,
+                                            gpointer            *data);
+void      gtk_buildable_custom_tag_end     (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            gpointer            *data);
+void      gtk_buildable_custom_finished    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            GObject             *child,
+                                            const gchar         *tagname,
+                                            gpointer             data);
+void      gtk_buildable_parser_finished    (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder);
+GObject * gtk_buildable_get_internal_child (GtkBuildable        *buildable,
+                                            GtkBuilder          *builder,
+                                            const gchar         *childname);
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDABLE_H__ */
Index: gtk/gtkbuilder.c
===================================================================
--- gtk/gtkbuilder.c	(revisão 0)
+++ gtk/gtkbuilder.c	(revisão 0)
@@ -0,0 +1,1272 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <ctype.h> /* tolower, toupper */
+#include <errno.h> /* errno */
+#include <stdlib.h> /* strtol, strtoul */
+#include <string.h> /* strlen */
+
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkbuilderprivate.h"
+#include "gtkmain.h"
+#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtktypebuiltins.h"
+#include "gtkalias.h"
+
+static void gtk_builder_class_init     (GtkBuilderClass *klass);
+static void gtk_builder_init           (GtkBuilder      *builder);
+static void gtk_builder_finalize       (GObject         *object);
+static void gtk_builder_set_property   (GObject         *object,
+                                        guint            prop_id,
+                                        const GValue    *value,
+                                        GParamSpec      *pspec);
+static void gtk_builder_get_property   (GObject         *object,
+                                        guint            prop_id,
+                                        GValue          *value,
+                                        GParamSpec      *pspec);
+static GType gtk_builder_real_get_type_from_name   (GtkBuilder      *builder,
+                                                    const char      *typename);
+
+
+enum {
+  PROP_0,
+  PROP_TRANSLATION_DOMAIN,
+};
+
+struct _GtkBuilderPrivate
+{
+  gchar *domain;
+  GHashTable *objects;
+  GHashTable *delayed_properties;
+  GSList *signals;
+  gchar *current_toplevel;
+};
+
+G_DEFINE_TYPE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
+
+static void
+gtk_builder_class_init (GtkBuilderClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gtk_builder_finalize;
+  gobject_class->set_property = gtk_builder_set_property;
+  gobject_class->get_property = gtk_builder_get_property;
+
+  klass->get_type_from_name = gtk_builder_real_get_type_from_name;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TRANSLATION_DOMAIN,
+                                   g_param_spec_string ("translation-domain",
+                                                        P_("Translation Domain"),
+                                                        P_("The translation domain used by gettext"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+
+  g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
+}
+
+static void
+gtk_builder_init (GtkBuilder *builder)
+{
+  builder->priv = G_TYPE_INSTANCE_GET_PRIVATE (builder, GTK_TYPE_BUILDER,
+                                               GtkBuilderPrivate);
+  builder->priv->domain = NULL;
+  builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  g_free, NULL);
+  builder->priv->delayed_properties = g_hash_table_new_full (g_str_hash,
+                                                             g_str_equal,
+                                                             g_free, NULL);
+}
+
+
+/*
+ * GObject virtual methods
+ */
+
+static void
+gtk_builder_finalize (GObject *object)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+  
+  g_free (builder->priv->domain);
+
+  g_free (builder->priv->current_toplevel);
+  g_hash_table_destroy (builder->priv->delayed_properties);
+  builder->priv->delayed_properties = NULL;
+  g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (builder->priv->signals);
+  g_hash_table_destroy (builder->priv->objects);
+}
+
+static void
+gtk_builder_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TRANSLATION_DOMAIN:
+      gtk_builder_set_translation_domain (builder, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_builder_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  GtkBuilder *builder = GTK_BUILDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TRANSLATION_DOMAIN:
+      g_value_set_string (value, builder->priv->domain);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+/*
+ * Try to map a type name to a _get_type function
+ * and call it, eg:
+ *
+ * GtkWindow -> gtk_window_get_type
+ * GtkHBox -> gtk_hbox_get_type
+ * GtkUIManager -> gtk_ui_manager_get_type
+ *
+ */
+static GType
+_gtk_builder_resolve_type_lazily (const gchar *name)
+{
+  static GModule *module = NULL;
+  GTypeGetFunc func;
+  GString *symbol_name = g_string_new ("");
+  char c, *symbol;
+  int i;
+  GType gtype = G_TYPE_INVALID;
+
+  if (!module)
+    module = g_module_open (NULL, 0);
+  
+  for (i = 0; name[i] != '\0'; i++)
+    {
+      c = name[i];
+      /* skip if uppercase, first or previous is uppercase */
+      if ((c == toupper (c) &&
+           i > 0 && name[i-1] != toupper (name[i-1])) ||
+          (i > 2 && name[i]   == toupper (name[i]) &&
+           name[i-1] == toupper (name[i-1]) &&
+           name[i-2] == toupper (name[i-2])))
+        g_string_append_c (symbol_name, '_');
+      g_string_append_c (symbol_name, tolower (c));
+    }
+  g_string_append (symbol_name, "_get_type");
+  
+  symbol = g_string_free (symbol_name, FALSE);
+
+  if (g_module_symbol (module, symbol, (gpointer)&func))
+    gtype = func ();
+  
+  g_free (symbol);
+
+  return gtype;
+}
+
+/*
+ * GtkBuilder virtual methods
+ */
+
+static GType
+gtk_builder_real_get_type_from_name (GtkBuilder *builder, const char *typename)
+{
+  GType gtype;
+
+  gtype = g_type_from_name (typename);
+  if (gtype != G_TYPE_INVALID)
+    return gtype;
+
+  return _gtk_builder_resolve_type_lazily (typename);
+}
+
+typedef struct
+{
+  gchar *object;
+  gchar *name;
+  gchar *value;
+} DelayedProperty;
+
+static void
+gtk_builder_get_parameters (GtkBuilder  *builder,
+                            GType        object_type,
+                            const gchar *object_name,
+                            GSList      *properties,
+                            GArray      **parameters,
+                            GArray      **construct_parameters)
+{
+  GSList *l;
+  GParamSpec *pspec;
+  GObjectClass *oclass;
+  DelayedProperty *property;
+
+  oclass = g_type_class_ref (object_type);
+  g_assert (oclass != NULL);
+
+  *parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
+  *construct_parameters = g_array_new (FALSE, FALSE, sizeof (GParameter));
+
+  for (l = properties; l; l = l->next)
+    {
+      PropertyInfo *prop = (PropertyInfo*)l->data;
+      GParameter parameter = { NULL };
+
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
+                                            prop->name);
+      if (!pspec)
+        {
+          g_warning ("Unknown property: %s.%s\n",
+                     g_type_name (object_type), prop->name);
+          continue;
+        }
+
+      parameter.name = prop->name;
+
+      if (G_IS_PARAM_SPEC_OBJECT (pspec))
+        {
+          if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+            {
+              GObject *object;
+              object = gtk_builder_get_object (builder, prop->data);
+              if (!object)
+                {
+                  g_warning ("failed to get constuct only property %s of %s "
+                             "with value `%s'",
+                             prop->name, object_name, prop->data);
+                  continue;
+                }
+              g_value_init (&parameter.value, G_OBJECT_TYPE (object));
+              g_value_set_object (&parameter.value, g_object_ref (object));
+            }
+          else
+            {
+              GSList *delayed_properties;
+              
+              delayed_properties = g_hash_table_lookup (builder->priv->delayed_properties,
+                                                        builder->priv->current_toplevel);
+              property = g_slice_new (DelayedProperty);
+              property->object = g_strdup (object_name);
+              property->name = g_strdup (prop->name);
+              property->value = g_strdup (prop->data);
+              delayed_properties = g_slist_prepend (delayed_properties, property);
+              g_hash_table_insert (builder->priv->delayed_properties,
+                                   g_strdup (builder->priv->current_toplevel),
+                                   delayed_properties);
+              continue;
+            }
+        }
+      else if (!gtk_builder_value_from_string (pspec, prop->data, &parameter.value))
+        {
+          g_warning ("failed to set property %s.%s to %s",
+                     g_type_name (object_type), prop->name, prop->data);
+          continue;
+        }
+
+      if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
+        g_array_append_val (*construct_parameters, parameter);
+      else
+        g_array_append_val (*parameters, parameter);
+    }
+
+  g_type_class_unref (oclass);
+}
+
+static GObject *
+gtk_builder_get_internal_child (GtkBuilder  *builder,
+                                ObjectInfo  *info,
+                                const gchar *childname)
+{
+  GObject *obj = NULL;
+
+  while (!obj)
+    {
+      if (!info->parent)
+        break;
+
+      info = (ObjectInfo*)((ChildInfo*)info->parent)->parent;
+      if (!info)
+        break;
+
+      GTK_NOTE (BUILDER,
+                g_print ("Trying to get internal child %s from %s\n",
+                         childname,
+                         gtk_buildable_get_name (GTK_BUILDABLE (info->object))));
+
+      if (GTK_IS_BUILDABLE (info->object))
+          obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
+                                                  builder,
+                                                  childname);
+    };
+
+  if (!obj)
+    g_error ("Unknown internal child: %s\n", childname);
+
+  return obj;
+}
+
+GObject *
+_gtk_builder_construct (GtkBuilder *builder,
+                        ObjectInfo *info)
+{
+  GArray *parameters, *construct_parameters;
+  GType object_type;
+  GObject *obj;
+  int i;
+  GtkBuildableIface *iface;
+  gboolean custom_set_property;
+  GtkBuildable *buildable;
+
+  g_assert (info->class_name != NULL);
+  object_type = gtk_builder_get_type_from_name (builder, info->class_name);
+  if (object_type == G_TYPE_INVALID)
+    g_error ("Invalid type: %s", info->class_name);
+
+  gtk_builder_get_parameters (builder, object_type,
+                              info->id,
+                              info->properties,
+                              &parameters,
+                              &construct_parameters);
+
+  if (info->constructor)
+    {
+      GObject *constructor;
+
+      constructor = gtk_builder_get_object (builder, info->constructor);
+      if (constructor == NULL)
+        g_error ("Unknown constructor for %s: %s\n", info->id,
+                 info->constructor);
+
+      obj = gtk_buildable_construct_child (GTK_BUILDABLE (constructor),
+                                           builder,
+                                           info->id);
+      g_assert (obj != NULL);
+      if (construct_parameters->len)
+        g_warning ("Can't pass in construct-only parameters to %s", info->id);
+
+    }
+  else if (info->parent && ((ChildInfo*)info->parent)->internal_child != NULL)
+    {
+      gchar *childname = ((ChildInfo*)info->parent)->internal_child;
+      obj = gtk_builder_get_internal_child (builder, info, childname);
+      if (construct_parameters->len)
+        g_warning ("Can't pass in construct-only parameters to %s", childname);
+    }
+  else
+    {
+      obj = g_object_newv (object_type,
+                           construct_parameters->len,
+                           (GParameter *)construct_parameters->data);
+
+      GTK_NOTE (BUILDER,
+                g_print ("created %s of type %s\n", info->id, info->class_name));
+
+      for (i = 0; i < construct_parameters->len; i++)
+        {
+          GParameter *param = &g_array_index (construct_parameters,
+                                              GParameter, i);
+          g_value_unset (&param->value);
+        }
+    }
+  g_array_free (construct_parameters, TRUE);
+
+  custom_set_property = FALSE;
+  buildable = NULL;
+  iface = NULL;
+  if (GTK_IS_BUILDABLE (obj))
+    {
+      buildable = GTK_BUILDABLE (obj);
+      iface = GTK_BUILDABLE_GET_IFACE (obj);
+      if (iface->set_property)
+        custom_set_property = TRUE;
+    }
+
+  for (i = 0; i < parameters->len; i++)
+    {
+      GParameter *param = &g_array_index (parameters, GParameter, i);
+      if (custom_set_property)
+        iface->set_property (buildable, builder, param->name, &param->value);
+      else
+        g_object_set_property (obj, param->name, &param->value);
+
+#if G_ENABLE_DEBUG
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+        {
+          gchar *str = g_strdup_value_contents ((const GValue*)&param->value);
+          g_print ("set %s: %s = %s\n", info->id, param->name, str);
+          g_free (str);
+        }
+#endif      
+      g_value_unset (&param->value);
+    }
+  g_array_free (parameters, TRUE);
+  
+  if (GTK_IS_BUILDABLE (obj))
+    gtk_buildable_set_name (buildable, info->id);
+  else
+    g_object_set_data_full (obj,
+                            "gtk-builder-name",
+                            g_strdup (info->id),
+                            g_free);
+
+  if (!info->parent)
+    {
+      g_free (builder->priv->current_toplevel);
+      builder->priv->current_toplevel = g_strdup (info->id);
+    }
+  g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
+  
+  builder->priv->signals = g_slist_concat (builder->priv->signals,
+                                           g_slist_copy (info->signals));
+  return obj;
+}
+
+
+void
+_gtk_builder_add (GtkBuilder *builder,
+                  ChildInfo  *child_info)
+{
+  GObject *object;
+  GObject *parent;
+
+  /* Internal children are already added
+   * Also prevent us from being called twice.
+   */
+  if (!child_info ||
+      child_info->internal_child ||
+      child_info->added)
+    return;
+
+  object = child_info->object;
+  if (!object)
+    return;
+
+  if (!child_info->parent)
+    {
+      g_warning ("%s: Not adding, No parent\n",
+                 gtk_buildable_get_name (GTK_BUILDABLE (object)));
+      return;
+    }
+
+  g_assert (object != NULL);
+
+  parent = ((ObjectInfo*)child_info->parent)->object;
+  g_assert (GTK_IS_BUILDABLE (parent));
+
+  GTK_NOTE (BUILDER,
+            g_print ("adding %s to %s\n",
+                     gtk_buildable_get_name (GTK_BUILDABLE (object)),
+                     gtk_buildable_get_name (GTK_BUILDABLE (parent))));
+  
+  gtk_buildable_add (GTK_BUILDABLE (parent), builder, object,
+                     child_info->type);
+
+  child_info->added = TRUE;
+}
+
+static void
+apply_delayed_properties (const gchar *window_name,
+                          GSList      *props,
+                          GtkBuilder  *builder)
+{
+  GSList *l;
+  DelayedProperty *property;
+  GObject *object;
+  GType object_type;
+  GObjectClass *oclass;
+  GParamSpec *pspec;
+
+  g_assert (props != NULL);
+  props = g_slist_reverse (props);
+  for (l = props; l; l = l->next)
+    {
+      property = (DelayedProperty*)l->data;
+      object = g_hash_table_lookup (builder->priv->objects, property->object);
+      g_assert (object != NULL);
+
+      object_type = G_OBJECT_TYPE (object);
+      g_assert (object_type != G_TYPE_INVALID);
+
+      oclass = g_type_class_ref (object_type);
+      g_assert (oclass != NULL);
+
+      pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass),
+                                            property->name);
+      if (!pspec)
+        g_warning ("Unknown property: %s.%s\n", g_type_name (object_type),
+                   property->name);
+      else
+        {
+          GObject *obj;
+
+          obj = g_hash_table_lookup (builder->priv->objects, property->value);
+          if (!obj)
+            g_warning ("No object called: %s\n", property->object);
+          else
+            g_object_set (object, property->name, obj, NULL);
+        }
+      g_free (property->value);
+      g_free (property->object);
+      g_free (property->name);
+      g_slice_free (DelayedProperty, property);
+      g_type_class_unref (oclass);
+    }
+  g_slist_free (props);
+}
+
+void
+_gtk_builder_finish (GtkBuilder  *builder)
+{
+  if (builder->priv->delayed_properties)
+    g_hash_table_foreach (builder->priv->delayed_properties,
+                          (GHFunc)apply_delayed_properties, builder);
+}
+
+/**
+ * gtk_builder_new:
+ *
+ * Creates a new builder object.
+ *
+ * Return value: a new builder object.
+ *
+ * Since: 2.12
+ **/
+GtkBuilder *
+gtk_builder_new (void)
+{
+  return g_object_new (GTK_TYPE_BUILDER, NULL);
+}
+
+/**
+ * gtk_builder_add_from_file:
+ * @buildable: a #GtkBuilder
+ * @filename: the name of the file to parse
+ * @error: return location for an error
+ *
+ * Parses a string containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and 
+ * merges it with the current contents of @builder. 
+ * 
+ * Returns: 1 on success, 0 if an error occurred
+ *
+ * Since: 2.12
+ **/
+guint
+gtk_builder_add_from_file (GtkBuilder   *builder,
+                           const gchar  *filename,
+                           GError      **error)
+{
+  char *buffer;
+  unsigned length;
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (filename != NULL, 0);
+
+  tmp_error = NULL;
+
+  if (!g_file_get_contents (filename, &buffer, &length, &tmp_error))
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+  
+  _gtk_builder_parser_parse_buffer (builder, filename,
+                                    buffer, length,
+                                    &tmp_error);
+
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  g_free (buffer);
+
+  return 1;
+}
+
+/**
+ * gtk_builder_add_from_string:
+ * @builder: a #GtkBuilder
+ * @buffer: the string to parse
+ * @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
+ * @error: return location for an error
+ *
+ * Parses a file containing a <link linkend="BUILDER-UI">GtkBuilder UI definition</link> and 
+ * merges it with the current contents of @builder. 
+ * 
+ * Returns: 1 on success, 0 if an error occurred
+ *
+ * Since: 2.12
+ **/
+guint
+gtk_builder_add_from_string (GtkBuilder   *builder,
+                             const gchar  *buffer,
+                             gsize         length,
+                             GError      **error)
+{
+  GError *tmp_error;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
+  g_return_val_if_fail (buffer != NULL, 0);
+
+  tmp_error = NULL;
+
+  _gtk_builder_parser_parse_buffer (builder, "<input>",
+                                    buffer, length,
+                                    &tmp_error);
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return 0;
+    }
+
+  return 1;
+}
+
+/**
+ * gtk_builder_get_object:
+ * @builder: a #GtkBuilder
+ * @name: name of object to get
+ *
+ * Return value: GObject or %NULL if it could not be found in the object tree.
+ *
+ * Since: 2.12
+ **/
+GObject *
+gtk_builder_get_object (GtkBuilder  *builder,
+                        const gchar *name)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  return g_hash_table_lookup (builder->priv->objects, name);
+}
+
+static void
+object_add_to_list (gchar *object_id,
+                    GObject *object,
+                    GSList **list)
+{
+  *list = g_slist_prepend (*list, object);
+}
+
+/**
+ * gtk_builder_get_objects:
+ * @builder: a #GtkBuilder
+ *
+ * Return value: a newly-allocated #GSList containing all the objects
+ *   constructed by GtkBuilder instance.
+ *
+ * Since: 2.12
+ **/
+GSList *
+gtk_builder_get_objects (GtkBuilder *builder)
+{
+  GSList *objects = NULL;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  g_hash_table_foreach (builder->priv->objects, (GHFunc)object_add_to_list, &objects);
+
+  return g_slist_reverse (objects);
+}
+
+/**
+ * gtk_builder_set_translation_domain:
+ * @builder: a #GtkBuilder
+ * @domain: the translation domain or %NULL
+ *
+ * Sets the translation domain and uses dgettext() for translating the
+ * property values marked as translatable from an interface description.
+ * You can also pass in %NULL to this method to use gettext() instead of
+ * dgettext().
+ *
+ * Since: 2.12
+ **/
+void
+gtk_builder_set_translation_domain (GtkBuilder  *builder,
+                                    const gchar *domain)
+{
+  gchar *new_domain;
+    
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  new_domain = g_strdup (domain);
+  g_free (builder->priv->domain);
+  builder->priv->domain = new_domain;
+
+  g_object_notify (G_OBJECT (builder), "translation-domain");
+}
+
+/**
+ * gtk_builder_get_translation_domain:
+ * @builder: a #GtkBuilder
+ *
+ * Return value : the translation domain. This string is owned
+ * by the builder object and must not be modified or freed.
+ *
+ * Since: 2.12
+ **/
+const gchar *
+gtk_builder_get_translation_domain (GtkBuilder *builder)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  return builder->priv->domain;
+}
+
+static void
+gtk_builder_connect_signals_default (GtkBuilder  *builder,
+                                     const gchar *handler_name,
+                                     GObject     *object,
+                                     const gchar *signal_name,
+                                     GObject     *connect_object,
+                                     gboolean     after,
+                                     gpointer     user_data)
+{
+  GConnectFlags flags = 0;
+  GCallback func;
+  GModule *module = (GModule*)user_data;
+  
+  if (!g_module_symbol (module, handler_name, (gpointer)&func))
+    {
+      g_warning ("could not find signal handler '%s'", handler_name);
+      return;
+    }
+  
+  if (after)
+    flags |= G_CONNECT_AFTER;
+  
+  if (connect_object)
+    flags |= G_CONNECT_SWAPPED;
+  
+  g_signal_connect_data (object, signal_name, func, connect_object, NULL, flags);
+}
+
+
+/**
+ * gtk_builder_connect_signals:
+ * @builder: a #GtkBuilder
+ *
+ * This method is a simpler variation of gtk_builder_connect_signals_full().
+ * It uses #GModule's introspective features (by opening the module %NULL) to
+ * look at the application's symbol table.  From here it tries to match
+ * the signal handler names given in the interface description with
+ * symbols in the application and connects the signals.
+ * 
+ * Note that this function will not work correctly if #GModule is not
+ * supported on the platform.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_builder_connect_signals (GtkBuilder *builder)
+{
+  GModule *module;
+
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  
+  if (!g_module_supported ())
+    g_error ("gtk_builder_connect_signals requires working GModule");
+
+  module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+
+  gtk_builder_connect_signals_full (builder,
+                                    gtk_builder_connect_signals_default,
+                                    module);
+}
+
+/**
+ * GtkBuilderConnectFunc:
+ * @builder: a #GtkBuilder
+ * @object: a GObject subclass to connect a signal to
+ * @handler: name of the handler
+ * @object: GObject, if non NULL, use g_signal_connect_object.
+ * @after: if %TRUE use with g_signal_connect_after.
+ * @data: user data
+ *
+ * This is the signature of a function used to connect signals.  It is used
+ * by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
+ * methods.  It is mainly intented for interpreted language bindings, but
+ * could be useful where the programmer wants more control over the signal
+ * connection process.
+ *
+ * Since: 2.12
+ */
+
+/**
+ * gtk_builder_connect_signals_full:
+ * @builder: a #GtkBuilder
+ * @func: the function used to connect the signals.
+ * @user_data: arbitrary data that will be passed to the connection function.
+ *
+ * This function can be thought of the interpeted language binding
+ * version of gtk_builder_signal_autoconnect(), except that it does not
+ * require gmodule to function correctly.
+ *
+ * Since: 2.12
+ */
+void
+gtk_builder_connect_signals_full (GtkBuilder            *builder,
+                                  GtkBuilderConnectFunc  func,
+                                  gpointer               data)
+{
+  GSList *l;
+  GObject *object;
+  GObject *other;
+
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (func != NULL);
+  
+  if (!builder->priv->signals)
+    return;
+
+  builder->priv->signals = g_slist_reverse (builder->priv->signals);
+  for (l = builder->priv->signals; l; l = l->next)
+    {
+      SignalInfo *signal = (SignalInfo*)l->data;
+
+      g_assert (signal != NULL);
+      g_assert (signal->name != NULL);
+
+      object = g_hash_table_lookup (builder->priv->objects, signal->object_name);
+      g_assert (object != NULL);
+
+      if (signal->object)
+        other = g_hash_table_lookup (builder->priv->objects, signal->object);
+      else
+        other = NULL;
+
+      func (builder, signal->handler, object, signal->name, other,
+            signal->after, data);
+    }
+
+  g_slist_foreach (builder->priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (builder->priv->signals);
+  builder->priv->signals = NULL;
+}
+
+/**
+ * gtk_builder_value_from_string
+ * @pspec: the GParamSpec for the property
+ * @string: the string representation of the value.
+ * @value: the GValue to store the result in.
+ *
+ * This function demarshals a value from a string.  This function
+ * calls g_value_init() on the @value argument, so it need not be
+ * initialised beforehand.
+ *
+ * This function can handle char, uchar, boolean, int, uint, long,
+ * ulong, enum, flags, float, double, string, GdkColor and
+ * GtkAdjustment type values.  Support for GtkWidget type values is
+ * still to come.
+ *
+ * Returns: %TRUE on success.
+ *
+ * Since: 2.12
+ */
+gboolean
+gtk_builder_value_from_string (GParamSpec  *pspec,
+                               const gchar *string,
+                               GValue      *value)
+{
+  /*
+   * GParamSpecUnichar has the internal type G_TYPE_UINT,
+   * so we cannot handle this in the switch, do it separately
+   */
+  if (G_IS_PARAM_SPEC_UNICHAR (pspec))
+    {
+      gunichar c;
+      g_value_init (value, G_TYPE_UINT);
+      c = g_utf8_get_char_validated (string, strlen (string));
+      if (c > 0)
+        g_value_set_uint (value, c);
+      return TRUE;
+    }
+
+  return gtk_builder_value_from_string_type (G_PARAM_SPEC_VALUE_TYPE (pspec),
+                                             string, value);
+}
+
+/**
+ * gtk_builder_value_from_string_type
+ * @type: the GType of the value
+ * @string: the string representation of the value.
+ * @value: the GValue to store the result in.
+ *
+ * Like gtk_builder_value_from_string(), but takes a #GType instead of #GParamSpec.
+ *
+ * Returns: %TRUE on success.
+ *
+ * Since: 2.12
+ */
+gboolean
+gtk_builder_value_from_string_type (GType        type,
+                                    const gchar *string,
+                                    GValue      *value)
+{
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (type != G_TYPE_INVALID, FALSE);
+  g_return_val_if_fail (string != NULL, FALSE);
+
+  g_value_init (value, type);
+
+  switch (G_TYPE_FUNDAMENTAL (type))
+    {
+    case G_TYPE_CHAR:
+      g_value_set_char (value, string[0]);
+      break;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (value, (guchar)string[0]);
+      break;
+    case G_TYPE_BOOLEAN:
+      {
+        gboolean b;
+
+        if (g_ascii_tolower (string[0]) == 't')
+          b = TRUE;
+        else if (g_ascii_tolower (string[0]) == 'y')
+          b = FALSE;
+        else {
+          errno = 0;
+          b = strtol (string, NULL, 0);
+          if (errno) {
+            g_warning ("could not parse int `%s'", string);
+            break;
+          }
+        }
+        g_value_set_boolean (value, b);
+        break;
+      }
+    case G_TYPE_INT:
+    case G_TYPE_LONG:
+      {
+        long l;
+        errno = 0;
+        l = strtol (string, NULL, 0);
+        if (errno) {
+          g_warning ("could not parse long `%s'", string);
+          break;
+        }
+        if (G_VALUE_HOLDS_INT (value))
+          g_value_set_int (value, l);
+        else
+          g_value_set_long (value, l);
+        break;
+      }
+    case G_TYPE_UINT:
+    case G_TYPE_ULONG:
+      {
+        ulong ul;
+        errno = 0;
+        ul = strtoul (string, NULL, 0);
+        if (errno)
+          {
+            g_warning ("could not parse ulong `%s'", string);
+            break;
+          }
+        if (G_VALUE_HOLDS_UINT (value))
+          g_value_set_uint (value, strtoul (string, NULL, 0));
+        else 
+          g_value_set_ulong (value, strtoul (string, NULL, 0));
+        break;
+      }
+    case G_TYPE_ENUM:
+      g_value_set_enum (value, gtk_builder_enum_from_string (type, string));
+      break;
+    case G_TYPE_FLAGS:
+      g_value_set_flags (value, gtk_builder_flags_from_string (type, string));
+      break;
+    case G_TYPE_FLOAT:
+    case G_TYPE_DOUBLE:
+      {
+        double d;
+        errno = 0;
+        d = g_ascii_strtod (string, NULL);
+        if (errno)
+          {
+            g_warning ("could not parse double `%s'", string);
+            break;
+          }
+        if (G_VALUE_HOLDS_FLOAT (value))
+          g_value_set_float (value, d);
+        else
+          g_value_set_double (value, d);
+        break;
+      }
+    case G_TYPE_STRING:
+      g_value_set_string (value, string);
+      break;
+    case G_TYPE_BOXED:
+      if (G_VALUE_HOLDS (value, GDK_TYPE_COLOR))
+        {
+          GdkColor colour = { 0, };
+
+          if (gdk_color_parse (string, &colour) &&
+              gdk_colormap_alloc_color (gtk_widget_get_default_colormap (),
+                                        &colour, FALSE, TRUE))
+            g_value_set_boxed (value, &colour);
+          else
+            {
+              g_warning ("could not parse colour name `%s'", string);
+              ret = FALSE;
+            }
+        }
+      else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        {
+          char **vector = g_strsplit (string, "\n", 0);
+          g_value_take_boxed (value, vector);
+        }
+      else
+        ret = FALSE;
+      break;
+    case G_TYPE_OBJECT:
+#if 0
+        if (G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF))
+      {
+        gchar *filename;
+        GError *error = NULL;
+        GdkPixbuf *pixbuf;
+
+        filename = gtk_xml_relative_file (xml, string);
+        pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+        if (pixbuf)
+          {
+            g_value_set_object (value, pixbuf);
+            g_object_unref (G_OBJECT (pixbuf));
+          }
+        else
+          {
+            g_warning ("Error loading image: %s", error->message);
+            g_error_free (error);
+            ret = FALSE;
+          }
+        g_free (filename);
+      }
+        else
+#endif
+          ret = FALSE;
+      break;
+    default:
+      ret = FALSE;
+      break;
+    }
+
+  return ret;
+}
+
+/**
+ * gtk_builder_enum_from_string:
+ * @type: a #GType
+ * @string: string containing an enum
+ *
+ * This function is used to convert a string to a enum value. You can use the
+ * enums nick or blurb representations to convert from.
+ *
+ * Return value: converted enum value
+ *
+ * Since: 2.12
+ */
+gint
+gtk_builder_enum_from_string (GType type, const char *string)
+{
+  GEnumClass *eclass;
+  GEnumValue *ev;
+  gchar *endptr;
+  gint ret = 0;
+
+  g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0);
+  g_return_val_if_fail (string != NULL, 0);
+  
+  ret = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  eclass = g_type_class_ref (type);
+  ev = g_enum_get_value_by_name (eclass, string);
+  if (!ev)
+    ev = g_enum_get_value_by_nick (eclass, string);
+
+  if (ev)
+    ret = ev->value;
+
+  g_type_class_unref (eclass);
+
+  return ret;
+}
+
+/**
+ * gtk_builder_flags_from_string:
+ * @type: a #GType
+ * @string: string containing a flag
+ *
+ * This function is used to convert a string to a flags value. You can use the
+ * flags' nick or blurb representations to convert from. Multiple values must be
+ * separated by a pipe character (|), space(s) are allowed before and after.
+ *
+ * Return value: converted flags value
+ *
+ * Since: 2.12
+ */
+guint
+gtk_builder_flags_from_string (GType type, const char *string)
+{
+  GFlagsClass *fclass;
+  gchar *endptr, *prevptr;
+  guint i, j, ret;
+  char *flagstr;
+  GFlagsValue *fv;
+  const char  *flag;
+  gunichar ch;
+  gboolean eos;
+
+  g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0);
+  g_return_val_if_fail (string != 0, 0);
+
+  ret = strtoul (string, &endptr, 0);
+  if (endptr != string) /* parsed a number */
+    return ret;
+
+  fclass = g_type_class_ref (type);
+
+  flagstr = g_strdup (string);
+  for (ret = i = j = 0; ; i++)
+    {
+
+      eos = flagstr[i] == '\0';
+
+      if (!eos && flagstr[i] != '|')
+        continue;
+
+      flag = &flagstr[j];
+      endptr = &flagstr[i];
+
+      if (!eos)
+        {
+          flagstr[i++] = '\0';
+          j = i;
+        }
+
+      /* trim spaces */
+      for (;;)
+        {
+          ch = g_utf8_get_char (flag);
+          if (!g_unichar_isspace (ch))
+            break;
+          flag = g_utf8_next_char (flag);
+        }
+
+      while (endptr > flag)
+        {
+          prevptr = g_utf8_prev_char (endptr);
+          ch = g_utf8_get_char (prevptr);
+          if (!g_unichar_isspace (ch))
+            break;
+          endptr = prevptr;
+        }
+
+      if (endptr > flag)
+        {
+          *endptr = '\0';
+          fv = g_flags_get_value_by_name (fclass, flag);
+
+          if (!fv)
+            fv = g_flags_get_value_by_nick (fclass, flag);
+
+          if (fv)
+            ret |= fv->value;
+          else
+            g_warning ("Unknown flag: '%s'", flag);
+        }
+
+      if (eos)
+        break;
+    }
+
+  g_free (flagstr);
+
+  g_type_class_unref (fclass);
+
+  return ret;
+}
+
+/**
+ * gtk_builder_get_type_from_name:
+ * @builder: a #GtkBuilder
+ * @typename: Type name to lookup.
+ *
+ * This method is used to lookup a type. It can be implemented in a subclass to
+ * override the #GType of an object created by the builder.
+ *
+ * Since 2.12
+ */
+GType
+gtk_builder_get_type_from_name (GtkBuilder *builder, const gchar *typename)
+{
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
+  g_return_val_if_fail (typename != NULL, G_TYPE_INVALID);
+
+  return GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, typename);
+}
+
+/**
+ * gtk_builder_error_quark:
+ *
+ * Registers an error quark for #GtkBuilder if necessary.
+ * 
+ * Return value: The error quark used for #GtkBuilder errors.
+ *
+ * Since: 2.12
+ **/
+GQuark
+gtk_builder_error_quark (void)
+{
+  return g_quark_from_static_string ("gtk-builder-error-quark");
+}
+
+
+#define __GTK_BUILDER_C__
+#include "gtkaliasdef.c"
Index: gtk/gtkbuilder.h
===================================================================
--- gtk/gtkbuilder.h	(revisão 0)
+++ gtk/gtkbuilder.h	(revisão 0)
@@ -0,0 +1,115 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_BUILDER_H__
+#define __GTK_BUILDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BUILDER                 (gtk_builder_get_type ())
+#define GTK_BUILDER(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BUILDER, GtkBuilder))
+#define GTK_BUILDER_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_BUILDER, GtkBuilderClass))
+#define GTK_IS_BUILDER(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BUILDER))
+#define GTK_IS_BUILDER_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_BUILDER))
+#define GTK_BUILDER_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_BUILDER, GtkBuilderClass))
+
+#define GTK_BUILDER_ERROR                (gtk_builder_error_quark ())
+
+typedef struct _GtkBuilder        GtkBuilder;
+typedef struct _GtkBuilderClass   GtkBuilderClass;
+typedef struct _GtkBuilderPrivate GtkBuilderPrivate;
+
+typedef enum
+{
+  GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION
+} GtkBuilderError;
+
+GQuark gtk_builder_error_quark (void);
+
+struct _GtkBuilder
+{
+  GObject parent;
+
+  GtkBuilderPrivate *priv;
+};
+
+struct _GtkBuilderClass
+{
+  GObjectClass parent_class;
+  
+  GType (* get_type_from_name) (GtkBuilder *builder,
+                                const char *typename);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+typedef void (*GtkBuilderConnectFunc) (GtkBuilder  *builder,
+                                       const gchar *handler_name,
+                                       GObject     *object,
+                                       const gchar *signal_name,
+                                       GObject     *connect_object,
+                                       gboolean     after,
+                                       gpointer     user_data);
+
+GType        gtk_builder_get_type                (void) G_GNUC_CONST;
+GtkBuilder*  gtk_builder_new                     (void);
+
+guint        gtk_builder_add_from_file           (GtkBuilder   *builder,
+                                                  const gchar  *filename,
+                                                  GError      **error);
+guint        gtk_builder_add_from_string         (GtkBuilder   *builder,
+                                                  const gchar  *buffer,
+                                                  gsize         length,
+                                                  GError      **error);
+GObject*     gtk_builder_get_object              (GtkBuilder   *builder,
+                                                  const gchar  *name);
+GSList*      gtk_builder_get_objects             (GtkBuilder   *builder);
+void         gtk_builder_connect_signals         (GtkBuilder   *builder);
+void         gtk_builder_connect_signals_full    (GtkBuilder   *builder,
+                                                  GtkBuilderConnectFunc func,
+                                                  gpointer      user_data);
+void         gtk_builder_set_translation_domain  (GtkBuilder   *builder,
+                                                  const gchar  *domain);
+const gchar* gtk_builder_get_translation_domain  (GtkBuilder   *builder);
+GType        gtk_builder_get_type_from_name      (GtkBuilder   *builder,
+                                                  const char   *typename);
+
+gboolean     gtk_builder_value_from_string       (GParamSpec   *pspec,
+                                                  const gchar  *string,
+                                                  GValue       *value);
+gboolean     gtk_builder_value_from_string_type  (GType         type,
+                                                  const gchar  *string,
+                                                  GValue       *value);
+guint        gtk_builder_flags_from_string       (GType         type,
+                                                  const char   *string);
+gint         gtk_builder_enum_from_string        (GType         type,
+                                                  const char   *string);
+
+#define GTK_BUILDER_WARN_INVALID_CHILD_TYPE(object, type) \
+  g_warning ("%s is not a valid child type of %s", type, g_type_name (G_OBJECT_TYPE (type)))
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDER_H__ */
Index: gtk/gtkbuilderparser.c
===================================================================
--- gtk/gtkbuilderparser.c	(revisão 0)
+++ gtk/gtkbuilderparser.c	(revisão 0)
@@ -0,0 +1,694 @@
+/* gtkbuilderparser.c
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gfileutils.h>
+#include <glib/gi18n.h>
+#include <glib/gmacros.h>
+#include <glib/gmessages.h>
+#include <glib/gslist.h>
+#include <glib/gstrfuncs.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <gdk/gdkenumtypes.h>
+#include <gdk/gdkkeys.h>
+#include <gtk/gtktypeutils.h>
+#include "gtkbuilderprivate.h"
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkdebug.h"
+#include "gtktypeutils.h"
+#include "gtkalias.h"
+
+static void free_property_info (PropertyInfo *info,
+                                gpointer      user_data);
+
+static inline void
+state_push (ParserData *data, gpointer info)
+{
+  data->stack = g_slist_prepend (data->stack, info);
+}
+
+static inline gpointer
+state_peek (ParserData *data)
+{
+  if (!data->stack)
+    return NULL;
+
+  return data->stack->data;
+}
+
+static inline gpointer
+state_pop (ParserData *data)
+{
+  gpointer old = NULL;
+
+  if (!data->stack)
+    return NULL;
+
+  old = data->stack->data;
+  data->stack = g_slist_delete_link (data->stack, data->stack);
+  return old;
+}
+#define state_peek_info(data, st) ((st*)state_peek(data))
+#define state_pop_info(data, st) ((st*)state_pop(data))
+
+static void
+error_missing_attribute (ParserData *data,
+                         gchar *tag,
+                         gchar *attribute,
+                         GError **error)
+{
+  gint line_number, char_number;
+
+  g_markup_parse_context_get_position (data->ctx,
+                                       &line_number,
+                                       &char_number);
+
+  g_set_error (error,
+               G_MARKUP_ERROR,
+               G_MARKUP_ERROR_INVALID_CONTENT,
+               "%s:%d:%d <%s> requires attribute \"%s\"",
+               data->filename,
+               line_number, char_number, tag, attribute);
+}
+
+static ObjectInfo *
+parse_object (ParserData   *data,
+              const gchar  *element_name,
+              const gchar **names,
+              const gchar **values,
+              GError      **error)
+{
+  int i;
+  gchar *object_class = NULL;
+  gchar *object_id = NULL;
+  gchar *constructor = NULL;
+  ObjectInfo *info;
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "class") == 0)
+        object_class = g_strdup (values[i]);
+      else if (strcmp (names[i], "id") == 0)
+        object_id = g_strdup (values[i]);
+      else if (strcmp (names[i], "constructor") == 0)
+        constructor = g_strdup (values[i]);
+    }
+
+  if (!object_class)
+    error_missing_attribute (data, "object", "class", error);
+
+  if (!object_id)
+    error_missing_attribute (data, "object", "id", error);
+
+  info = g_slice_new0 (ObjectInfo);
+  info->class_name = object_class;
+  info->id = object_id;
+  info->constructor = constructor;
+  state_push (data, info);
+  g_assert (state_peek (data) != NULL);
+  info->tag.name = element_name;
+
+  return info;
+}
+
+static void
+free_object_info (ObjectInfo *info)
+{
+  /* Do not free the signal items, which GtkBuilder takes ownership of */
+  g_slist_free (info->signals);
+  g_slist_foreach (info->properties,
+                   (GFunc)free_property_info, NULL);
+  g_slist_free (info->properties);
+  g_free (info->constructor);
+  g_free (info->class_name);
+  g_free (info->id);
+  g_slice_free (ObjectInfo, info);
+}
+
+static gchar *
+_get_type_by_symbol (const gchar* symbol)
+{
+  static GModule *module = NULL;
+  GTypeGetFunc func;
+  GType type;
+  
+  if (!module)
+    module = g_module_open (NULL, 0);
+
+  if (!g_module_symbol (module, symbol, (gpointer)&func))
+    return NULL;
+  
+  type = func ();
+  if (type == G_TYPE_INVALID)
+    return NULL;
+
+  return g_strdup (g_type_name (type));
+}
+
+
+static ChildInfo *
+parse_child (ParserData   *data,
+             const gchar  *element_name,
+             const gchar **names,
+             const gchar **values,
+             GError      **error)
+
+{
+  ChildInfo *info;
+  guint i;
+
+  info = g_slice_new0 (ChildInfo);
+  state_push (data, info);
+  g_assert (state_peek (data) != NULL);
+  info->tag.name = element_name;
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "type") == 0)
+        info->type = g_strdup (values[i]);
+      else if (strcmp (names[i], "internal-child") == 0)
+        info->internal_child = g_strdup (values[i]);
+      else if (strcmp (names[i], "type-func") == 0)
+        {
+          info->type = _get_type_by_symbol (values[i]);
+          if (!info->type)
+            {
+              g_set_error (error, GTK_BUILDER_ERROR, 
+                           GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION,
+                           _("Invalid type function: `%s'"),
+                           values[i]);
+              return NULL;
+            }
+        }
+    }
+  return info;
+}
+
+static void
+free_child_info (ChildInfo *info)
+{
+  g_free (info->type);
+  g_free (info->internal_child);
+  g_slice_free (ChildInfo, info);
+}
+
+static void
+parse_property (ParserData   *data,
+                const gchar  *element_name,
+                const gchar **names,
+                const gchar **values,
+                GError      **error)
+{
+  PropertyInfo *info;
+  gchar *name = NULL;
+  gboolean translatable = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "name") == 0)
+        name = g_strdelimit (g_strdup (values[i]), "_", '-');
+      else if (strcmp (names[i], "translatable") == 0)
+        translatable = strcmp (values[i], "yes") == 0;
+    }
+
+  if (!name)
+    error_missing_attribute (data, "property", "name", error);
+
+  info = g_slice_new0 (PropertyInfo);
+  info->name = name;
+  info->translatable = translatable;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+static void
+free_property_info (PropertyInfo *info,
+                    gpointer user_data)
+{
+  g_free (info->data);
+  g_free (info->name);
+  g_slice_free (PropertyInfo, info);
+}
+
+static void
+parse_signal (ParserData   *data,
+              const gchar  *element_name,
+              const gchar **names,
+              const gchar **values,
+              GError      **error)
+{
+  SignalInfo *info;
+  gchar *name = NULL;
+  gchar *handler = NULL;
+  gchar *object = NULL;
+  gboolean after = FALSE;
+  int i;
+
+  g_assert (data->stack != NULL);
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "name") == 0)
+        name = g_strdup (values[i]);
+      else if (strcmp (names[i], "handler") == 0)
+        handler = g_strdup (values[i]);
+      else if (strcmp (names[i], "object") == 0)
+        object = g_strdup (values[i]);
+      else if (strcmp (names[i], "after") == 0)
+        after = strcmp (values[i], "yes") == 0;
+    }
+
+  if (!name)
+    error_missing_attribute (data, "signal", "name", error);
+
+  if (!handler)
+    error_missing_attribute (data, "signal", "handler", error);
+
+  info = g_slice_new0 (SignalInfo);
+  info->name = name;
+  info->handler = handler;
+  info->object = object;
+  info->after = after;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
+/* Called by GtkBuilder */
+void
+_free_signal_info (SignalInfo *info,
+                   gpointer user_data)
+{
+  g_free (info->name);
+  g_free (info->handler);
+  g_free (info->object);
+  g_free (info->object_name);
+  g_slice_free (SignalInfo, info);
+}
+
+
+static GObject *
+builder_construct (ParserData *data,
+                   ObjectInfo *object_info)
+{
+  GObject *object;
+
+  g_assert (object_info != NULL);
+
+  if (object_info->object)
+    return object_info->object;
+
+  object_info->properties = g_slist_reverse (object_info->properties);
+
+  object = _gtk_builder_construct (data->builder, object_info);
+  g_assert (G_IS_OBJECT (object));
+
+  object_info->object = object;
+
+  return object;
+}
+
+static void
+start_element (GMarkupParseContext *context,
+               const gchar         *element_name,
+               const gchar        **names,
+               const gchar        **values,
+               gpointer             user_data,
+               GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+
+#ifdef GTK_ENABLE_DEBUG
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    {
+      GString *tags = g_string_new ("");
+      int i;
+      for (i = 0; names[i]; i++)
+        g_string_append_printf (tags, "%s=\"%s\" ", names[i], values[i]);
+
+      if (i)
+        {
+          g_string_insert_c (tags, 0, ' ');
+          g_string_truncate (tags, tags->len - 1);
+        }
+      g_print ("<%s%s>\n", element_name, tags->str);
+      g_string_free (tags, TRUE);
+    }
+#endif
+
+  if (data->subparser)
+    {
+      if (!data->subparser->start &&
+          strcmp (element_name, data->subparser->tagname) == 0)
+        data->subparser->start = element_name;
+
+      if (data->subparser->start)
+        {
+          if (data->subparser->parser->start_element)
+            data->subparser->parser->start_element (context,
+                                                    element_name, names, values,
+                                                    data->subparser->data, error);
+          return;
+        }
+    }
+
+  if (strcmp (element_name, "object") == 0)
+    {
+      ChildInfo* child_info = state_peek_info (data, ChildInfo);
+      ObjectInfo *object_info;
+
+      object_info = parse_object (data, element_name, names, values, error);
+
+      if (child_info)
+        object_info->parent = (CommonInfo*)child_info;
+
+    }
+  else if (strcmp (element_name, "child") == 0)
+    {
+      ChildInfo* child_info;
+      ObjectInfo* object_info = state_peek_info (data, ObjectInfo);
+
+      child_info = parse_child (data, element_name, names, values, error);
+      child_info->parent = (CommonInfo*)object_info;
+
+      object_info->object = builder_construct (data, object_info);
+    }
+  else if (strcmp (element_name, "property") == 0)
+    parse_property (data, element_name, names, values, error);
+  else if (strcmp (element_name, "signal") == 0)
+    parse_signal (data, element_name, names, values, error);
+  else if (strcmp (element_name, "interface") == 0)
+    {
+      int i;
+
+      for (i = 0; names[i] != NULL; i++)
+        if (strcmp (names[i], "domain") == 0 && !data->domain)
+          {
+            data->domain = g_strdup (values[i]);
+            break;
+          }
+    }
+  else if (strcmp (element_name, "placeholder") == 0)
+    {
+      /* placeholder has no special treatmeant, but it needs an
+       * if clause to avoid an error below.
+       */
+    }
+  else
+    {
+      CommonInfo* info = state_peek_info (data, CommonInfo);
+
+      if (!info)
+        goto unhandled;
+
+      if (strcmp (info->tag.name, "object") == 0 ||
+          strcmp (info->tag.name, "child") == 0)
+        {
+          GMarkupParser parser;
+          SubParser *subparser;
+          gpointer *subparser_data;
+          GObject *object;
+          GObject *child;
+
+          if (strcmp (info->tag.name, "object") == 0)
+            {
+              ObjectInfo* object_info = (ObjectInfo*)info;
+              if (!object_info->object)
+                object_info->object = _gtk_builder_construct (data->builder,
+                                                              object_info);
+              g_assert (object_info->object);
+              object = object_info->object;
+              child = NULL;
+            }
+
+          else if (strcmp (info->tag.name, "child") == 0)
+            {
+              ChildInfo* child_info = (ChildInfo*)info;
+
+              _gtk_builder_add (data->builder, child_info);
+
+              object = ((ObjectInfo*)child_info->parent)->object;
+              child  = child_info->object;
+            }
+          else
+            goto unhandled;
+
+          if (!gtk_buildable_custom_tag_start (GTK_BUILDABLE (object),
+                                               data->builder,
+                                               child,
+                                               element_name,
+                                               &parser,
+                                               (gpointer*)&subparser_data))
+            goto unhandled;
+
+          subparser = g_slice_new0 (SubParser);
+          subparser->object = object;
+          subparser->child = child;
+          subparser->tagname = g_strdup (element_name);
+          subparser->start = element_name;
+          subparser->parser = g_memdup (&parser, sizeof (GMarkupParser));
+          subparser->data = subparser_data;
+          data->subparser = subparser;
+
+          if (parser.start_element)
+              parser.start_element (context,
+                                    element_name, names, values,
+                                    subparser_data, error);
+          return;
+        }
+
+    unhandled:
+      g_warning ("unhandled tag: %s\n", element_name);
+    }
+}
+
+/* Called for close tags </foo> */
+static void
+end_element (GMarkupParseContext *context,
+             const gchar         *element_name,
+             gpointer             user_data,
+             GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+
+  GTK_NOTE (BUILDER, g_print ("</%s>\n", element_name));
+
+  if (data->subparser && data->subparser->start)
+    {
+      if (data->subparser->parser->end_element)
+        data->subparser->parser->end_element (context, element_name,
+                                              data->subparser->data, error);
+
+      if (strcmp (data->subparser->start, element_name) == 0)
+        {
+          gtk_buildable_custom_tag_end (GTK_BUILDABLE (data->subparser->object),
+                                        data->builder,
+                                        data->subparser->child,
+                                        element_name,
+                                        data->subparser->data);
+          g_free (data->subparser->parser);
+          if (GTK_BUILDABLE_GET_IFACE (data->subparser->object)->custom_finished)
+            data->custom_finalizers = g_slist_prepend (data->custom_finalizers,
+                                                       data->subparser);
+          else
+            {
+              g_free (data->subparser->tagname);
+              g_slice_free (SubParser, data->subparser);
+            }
+            
+          data->subparser = NULL;
+        }
+      return;
+    }
+
+  if (strcmp (element_name, "object") == 0)
+    {
+      ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
+      ChildInfo* child_info = state_peek_info (data, ChildInfo);
+
+      object_info->object = builder_construct (data, object_info);
+
+      if (child_info)
+        child_info->object = object_info->object;
+
+      if (GTK_IS_BUILDABLE (object_info->object) &&
+          GTK_BUILDABLE_GET_IFACE (object_info->object)->parser_finished)
+        data->finalizers = g_slist_prepend (data->finalizers, object_info->object);
+      free_object_info (object_info);
+    }
+  else if (strcmp (element_name, "property") == 0)
+    {
+      PropertyInfo *prop_info = state_pop_info (data, PropertyInfo);
+      CommonInfo *info = state_peek_info (data, CommonInfo);
+
+      /* Normal properties */
+      if (strcmp (info->tag.name, "object") == 0)
+        {
+          ObjectInfo *object_info = (ObjectInfo*)info;
+          object_info->properties =
+            g_slist_prepend (object_info->properties, prop_info);
+        }
+      else
+        g_assert_not_reached ();
+    }
+  else if (strcmp (element_name, "child") == 0)
+    {
+      ChildInfo *child_info = state_pop_info (data, ChildInfo);
+
+      _gtk_builder_add (data->builder, child_info);
+
+      free_child_info (child_info);
+    }
+  else if (strcmp (element_name, "signal") == 0)
+    {
+      SignalInfo *signal_info = state_pop_info (data, SignalInfo);
+      ObjectInfo *object_info = (ObjectInfo*)state_peek_info (data, CommonInfo);
+      signal_info->object_name = g_strdup (object_info->id);
+      object_info->signals =
+        g_slist_prepend (object_info->signals, signal_info);
+    }
+  else if (strcmp (element_name, "interface") == 0)
+    {
+    }
+  else if (strcmp (element_name, "placeholder") == 0)
+    {
+    }
+}
+
+/* Called for character data */
+/* text is not nul-terminated */
+static void
+text (GMarkupParseContext *context,
+      const gchar         *text,
+      gsize                text_len,
+      gpointer             user_data,
+      GError             **error)
+{
+  ParserData *data = (ParserData*)user_data;
+  CommonInfo *info;
+
+  if (data->subparser && data->subparser->start)
+    {
+      if (data->subparser->parser->text)
+        data->subparser->parser->text (context, text, text_len,
+                                       data->subparser->data, error);
+      return;
+    }
+
+  if (!data->stack)
+    return;
+
+  info = state_peek_info (data, CommonInfo);
+  g_assert (info != NULL);
+
+  if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
+    {
+      PropertyInfo *prop_info = (PropertyInfo*)info;
+
+      if (prop_info->translatable && text_len)
+        {
+          if (data->domain)
+            text = dgettext (text, data->domain);
+          else
+            text = gettext (text);
+        }
+      prop_info->data = g_strndup (text, text_len);
+    }
+}
+
+static void
+error (GMarkupParseContext *context,
+       GError              *error,
+       gpointer             user_data)
+{
+  g_message ("error: '%s'", error->message);
+}
+
+
+static const GMarkupParser parser = {
+  start_element,
+  end_element,
+  text,
+  NULL,
+  error
+};
+
+void
+_gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
+                                  const gchar  *filename,
+                                  const gchar  *buffer,
+                                  gsize         length,
+                                  GError      **error)
+{
+  ParserData *data;
+  GSList *l;
+  
+  data = g_new0 (ParserData, 1);
+  data->builder = builder;
+  data->filename = filename;
+  data->domain = g_strdup (gtk_builder_get_translation_domain (builder));
+
+  data->ctx = g_markup_parse_context_new (
+                  &parser, G_MARKUP_TREAT_CDATA_AS_TEXT, data, NULL);
+
+  if (!g_markup_parse_context_parse (data->ctx, buffer, length, error))
+    goto out;
+  
+  gtk_builder_set_translation_domain (data->builder, data->domain);
+  _gtk_builder_finish (builder);
+
+  /* Custom parser_finished */
+  data->custom_finalizers = g_slist_reverse (data->custom_finalizers);
+  for (l = data->custom_finalizers; l; l = l->next)
+    {
+      SubParser *sub = (SubParser*)l->data;
+      
+      gtk_buildable_custom_finished (GTK_BUILDABLE (sub->object),
+                                     builder,
+                                     sub->child,
+                                     sub->tagname,
+                                     sub->data);
+      g_free (sub->tagname);
+      g_slice_free (SubParser, sub);
+    }
+  
+  /* Common parser_finished, for all created objects */
+  data->finalizers = g_slist_reverse (data->finalizers);
+  for (l = data->finalizers; l; l = l->next)
+    {
+      GtkBuildable *buildable = (GtkBuildable*)l->data;
+      gtk_buildable_parser_finished (GTK_BUILDABLE (buildable), builder);
+    }
+
+ out:
+  g_markup_parse_context_free (data->ctx);
+
+  g_slist_free (data->stack);
+  g_slist_free (data->custom_finalizers);
+  g_slist_free (data->finalizers);
+  g_free (data->domain);
+  g_free (data);
+}
Index: gtk/gtkbuilderprivate.h
===================================================================
--- gtk/gtkbuilderprivate.h	(revisão 0)
+++ gtk/gtkbuilderprivate.h	(revisão 0)
@@ -0,0 +1,110 @@
+/* gtkbuilderprivate.h
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_BUILDER_PRIVATE_H__
+#define __GTK_BUILDER_PRIVATE_H__
+
+#include <glib/gmarkup.h>
+#include <glib/gslist.h>
+
+#include <glib-object.h>
+#include "gtkbuilder.h"
+
+typedef struct {
+  const gchar *name;
+} TagInfo;
+
+typedef struct {
+  TagInfo tag;
+} CommonInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *class_name;
+  gchar *id;
+  gchar *constructor;
+  GSList *properties;
+  GSList *signals;
+  GObject *object;
+  CommonInfo *parent;
+} ObjectInfo;
+
+typedef struct {
+  TagInfo tag;
+  GSList *packing_properties;
+  GObject *object;
+  CommonInfo *parent;
+  gchar *type;
+  gchar *internal_child;
+  gboolean added;
+} ChildInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *name;
+  gchar *data;
+  gboolean translatable;
+} PropertyInfo;
+
+typedef struct {
+  TagInfo tag;
+  gchar *name;
+  gchar *handler;
+  gchar *object;
+  gboolean after;
+  gchar *object_name;
+} SignalInfo;
+
+typedef struct {
+  GMarkupParser *parser;
+  gchar *tagname;
+  const gchar *start;
+  gpointer data;
+  GObject *object;
+  GObject *child;
+} SubParser;
+
+typedef struct {
+  GtkBuilder *builder;
+  gchar *domain;
+  GSList *stack;
+  SubParser *subparser;
+  GMarkupParseContext *ctx;
+  const gchar *filename;
+  GSList *finalizers;
+  GSList *custom_finalizers;
+} ParserData;
+
+typedef GType (*GTypeGetFunc) (void);
+
+void _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
+                                       const gchar *filename,
+                                       const gchar *buffer,
+                                       gsize length,
+                                       GError **error);
+GObject * _gtk_builder_construct (GtkBuilder *builder,
+                                  ObjectInfo *info);
+void      _gtk_builder_add (GtkBuilder *builder,
+                            ChildInfo *child_info);
+void      _gtk_builder_finish (GtkBuilder *builder);
+void _free_signal_info (SignalInfo *info,
+                        gpointer user_data);
+
+#endif /* __GTK_BUILDER_PRIVATE_H__ */
Index: gtk/gtkcelllayout.c
===================================================================
--- gtk/gtkcelllayout.c	(revisão 18111)
+++ gtk/gtkcelllayout.c	(cópia de trabalho)
@@ -17,6 +17,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <string.h>
+#include <stdlib.h>
 #include <config.h>
 #include "gtkcelllayout.h"
 #include "gtkintl.h"
@@ -309,5 +311,115 @@ gtk_cell_layout_get_cells (GtkCellLayout
   return NULL;
 }
 
+typedef struct {
+  GtkCellLayout   *cell_layout;
+  GtkCellRenderer *renderer;
+  gchar           *attr_name;
+} AttributesSubParserData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer             user_data,
+			  GError             **error)
+{
+  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "attribute") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+	parser_data->attr_name = g_strdup (values[i]);
+  else if (strcmp (element_name, "attributes") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+			 const gchar         *text,
+			 gsize                text_len,
+			 gpointer             user_data,
+			 GError             **error)
+{
+  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
+
+  if (!parser_data->attr_name)
+    return;
+  gtk_cell_layout_add_attribute (parser_data->cell_layout,
+				 parser_data->renderer,
+				 parser_data->attr_name, atoi (text));
+  g_free (parser_data->attr_name);
+  parser_data->attr_name = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+gboolean
+_gtk_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
+					     GtkBuilder    *builder,
+					     GObject       *child,
+					     const gchar   *tagname,
+					     GMarkupParser *parser,
+					     gpointer      *data)
+{
+  AttributesSubParserData *parser_data;
+
+  if (!child)
+    return FALSE;
+
+  if (strcmp (tagname, "attributes") == 0)
+    {
+      parser_data = g_slice_new0 (AttributesSubParserData);
+      parser_data->cell_layout = GTK_CELL_LAYOUT (buildable);
+      parser_data->renderer = GTK_CELL_RENDERER (child);
+      parser_data->attr_name = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+void
+_gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
+					   GtkBuilder   *builder,
+					   GObject      *child,
+					   const gchar  *tagname,
+					   gpointer     *data)
+{
+  AttributesSubParserData *parser_data;
+
+  parser_data = (AttributesSubParserData*)data;
+  g_assert (!parser_data->attr_name);
+  g_slice_free (AttributesSubParserData, parser_data);
+}
+
+void
+_gtk_cell_layout_buildable_add (GtkBuildable      *buildable,
+				GtkBuilder        *builder,
+				GObject           *child,
+				const gchar       *type)
+{
+  GtkCellLayoutIface *iface;
+  
+  g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (child));
+
+  iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
+  g_return_if_fail (iface->pack_end != NULL);
+  iface->pack_end (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);
+}
+
 #define __GTK_CELL_LAYOUT_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkcelllayout.h
===================================================================
--- gtk/gtkcelllayout.h	(revisão 18111)
+++ gtk/gtkcelllayout.h	(cópia de trabalho)
@@ -24,6 +24,8 @@
 
 #include <gtk/gtkcellrenderer.h>
 #include <gtk/gtktreeviewcolumn.h>
+#include <gtk/gtkbuildable.h>
+#include <gtk/gtkbuilder.h>
 
 G_BEGIN_DECLS
 
@@ -97,7 +99,21 @@
 void  gtk_cell_layout_reorder            (GtkCellLayout         *cell_layout,
                                           GtkCellRenderer       *cell,
                                           gint                   position);
-
+gboolean _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
+						      GtkBuilder    *builder,
+						      GObject       *child,
+						      const gchar   *tagname,
+						      GMarkupParser *parser,
+						      gpointer      *data);
+void _gtk_cell_layout_buildable_custom_tag_end       (GtkBuildable  *buildable,
+						      GtkBuilder    *builder,
+						      GObject       *child,
+						      const gchar   *tagname,
+						      gpointer      *data);
+void _gtk_cell_layout_buildable_add                  (GtkBuildable  *buildable,
+						      GtkBuilder    *builder,
+						      GObject       *child,
+						      const gchar   *type);
 
 G_END_DECLS
 
Index: gtk/gtkcellrenderer.c
===================================================================
--- gtk/gtkcellrenderer.c	(revisão 18111)
+++ gtk/gtkcellrenderer.c	(cópia de trabalho)
@@ -23,6 +23,7 @@
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
 #include "gtktreeprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 static void gtk_cell_renderer_get_property  (GObject              *object,
@@ -35,6 +36,7 @@ static void gtk_cell_renderer_set_proper
 					     GParamSpec           *pspec);
 static void set_cell_bg_color               (GtkCellRenderer      *cell,
 					     GdkColor             *color);
+static void gtk_cell_renderer_buildable_init  (GtkBuildableIface *iface);
 
 
 #define GTK_CELL_RENDERER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_RENDERER, GtkCellRendererPrivate))
@@ -73,7 +75,9 @@ enum {
 
 static guint cell_renderer_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_ABSTRACT_TYPE (GtkCellRenderer, gtk_cell_renderer, GTK_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkCellRenderer, gtk_cell_renderer, GTK_TYPE_OBJECT,
+				  G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+							 gtk_cell_renderer_buildable_init))
 
 static void
 gtk_cell_renderer_init (GtkCellRenderer *cell)
@@ -299,6 +303,12 @@ gtk_cell_renderer_class_init (GtkCellRen
 }
 
 static void
+gtk_cell_renderer_buildable_init  (GtkBuildableIface *iface)
+{
+
+}
+
+static void
 gtk_cell_renderer_get_property (GObject     *object,
 				guint        param_id,
 				GValue      *value,
Index: gtk/gtkcellview.c
===================================================================
--- gtk/gtkcellview.c	(revisão 18111)
+++ gtk/gtkcellview.c	(cópia de trabalho)
@@ -18,6 +18,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcellview.h"
 #include "gtkcelllayout.h"
 #include "gtkintl.h"
@@ -26,6 +27,7 @@
 #include "gtkcellrendererpixbuf.h"
 #include "gtkprivate.h"
 #include <gobject/gmarshal.h>
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
@@ -105,6 +107,22 @@ static void       gtk_cell_view_cell_lay
                                                                 gint                   position);
 static GList *    gtk_cell_view_cell_layout_get_cells          (GtkCellLayout         *layout);
 
+/* buildable */
+static void       gtk_cell_view_buildable_init                 (GtkBuildableIface     *iface);
+static gboolean   gtk_cell_view_buildable_custom_tag_start     (GtkBuildable  	      *buildable,
+								GtkBuilder    	      *builder,
+								GObject       	      *child,
+								const gchar   	      *tagname,
+								GMarkupParser 	      *parser,
+								gpointer      	      *data);
+static void       gtk_cell_view_buildable_custom_tag_end       (GtkBuildable  	      *buildable,
+								GtkBuilder    	      *builder,
+								GObject       	      *child,
+								const gchar   	      *tagname,
+								gpointer      	      *data);
+
+static GtkBuildableIface *parent_buildable_iface;
+
 #define GTK_CELL_VIEW_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_VIEW, GtkCellViewPrivate))
 
 enum
@@ -118,7 +136,9 @@ enum
 
 G_DEFINE_TYPE_WITH_CODE (GtkCellView, gtk_cell_view, GTK_TYPE_WIDGET, 
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-						gtk_cell_view_cell_layout_init))
+						gtk_cell_view_cell_layout_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_cell_view_buildable_init))
 
 static void
 gtk_cell_view_class_init (GtkCellViewClass *klass)
@@ -175,6 +195,15 @@ gtk_cell_view_class_init (GtkCellViewCla
 }
 
 static void
+gtk_cell_view_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_cell_view_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_cell_view_buildable_custom_tag_end;
+}
+
+static void
 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
   iface->pack_start = gtk_cell_view_cell_layout_pack_start;
@@ -1068,5 +1097,37 @@ gtk_cell_view_cell_layout_get_cells (Gtk
 }
 
 
+static gboolean
+gtk_cell_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *tagname,
+					  GMarkupParser *parser,
+					  gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+						tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+						      tagname, parser, data);
+}
+
+static void
+gtk_cell_view_buildable_custom_tag_end (GtkBuildable *buildable,
+					GtkBuilder   *builder,
+					GObject      *child,
+					const gchar  *tagname,
+					gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+					       data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+					    data);
+}
+
+
 #define __GTK_CELL_VIEW_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkcolorseldialog.c
===================================================================
--- gtk/gtkcolorseldialog.c	(revisão 18111)
+++ gtk/gtkcolorseldialog.c	(cópia de trabalho)
@@ -24,6 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 #include <config.h>
+#include <string.h>
 #include <glib.h>
 #include "gtkcolorseldialog.h"
 #include "gtkframe.h"
@@ -31,6 +32,7 @@
 #include "gtkbutton.h"
 #include "gtkstock.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 
@@ -38,7 +40,17 @@
 /* GtkColorSelectionDialog */
 /***************************/
 
-G_DEFINE_TYPE (GtkColorSelectionDialog, gtk_color_selection_dialog, GTK_TYPE_DIALOG)
+static void gtk_color_selection_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_color_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+									  GtkBuilder   *builder,
+									  const gchar  *childname);
+
+G_DEFINE_TYPE_WITH_CODE (GtkColorSelectionDialog, gtk_color_selection_dialog,
+           GTK_TYPE_DIALOG,
+           G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                      gtk_color_selection_dialog_buildable_interface_init))
+
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
 gtk_color_selection_dialog_class_init (GtkColorSelectionDialogClass *klass)
@@ -106,5 +118,30 @@ gtk_color_selection_dialog_new (const gc
   return GTK_WIDGET (colorseldiag);
 }
 
+static void
+gtk_color_selection_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = gtk_color_selection_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_color_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+							 GtkBuilder   *builder,
+							 const gchar  *childname)
+{
+    if (strcmp(childname, "ok_button") == 0)
+	return G_OBJECT (GTK_COLOR_SELECTION_DIALOG (buildable)->ok_button);
+    else if (strcmp(childname, "cancel_button") == 0)
+	return G_OBJECT (GTK_COLOR_SELECTION_DIALOG (buildable)->cancel_button);
+    else if (strcmp(childname, "help_button") == 0)
+	return G_OBJECT (GTK_COLOR_SELECTION_DIALOG(buildable)->help_button);
+    else if (strcmp(childname, "color_selection") == 0)
+	return G_OBJECT (GTK_COLOR_SELECTION_DIALOG(buildable)->colorsel);
+
+    return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+
 #define __GTK_COLOR_SELECTION_DIALOG_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkcombobox.c
===================================================================
--- gtk/gtkcombobox.c	(revisão 18111)
+++ gtk/gtkcombobox.c	(cópia de trabalho)
@@ -443,6 +443,21 @@ static void     gtk_combo_box_child_show
 static void     gtk_combo_box_child_hide                     (GtkWidget       *widget,
 							      GtkComboBox     *combo_box);
 
+/* GtkBuildable method implementation */
+static GtkBuildableIface *parent_buildable_iface;
+
+static void     gtk_combo_box_buildable_init                 (GtkBuildableIface *iface);
+static gboolean gtk_combo_box_buildable_custom_tag_start     (GtkBuildable  *buildable,
+							      GtkBuilder    *builder,
+							      GObject       *child,
+							      const gchar   *tagname,
+							      GMarkupParser *parser,
+							      gpointer      *data);
+static void     gtk_combo_box_buildable_custom_tag_end       (GtkBuildable  *buildable,
+							      GtkBuilder    *builder,
+							      GObject       *child,
+							      const gchar   *tagname,
+							      gpointer      *data);
 
 /* GtkCellEditable method implementations */
 static void gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
@@ -453,7 +468,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkComboBox, gt
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
 						gtk_combo_box_cell_layout_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
-						gtk_combo_box_cell_editable_init))
+						gtk_combo_box_cell_editable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_combo_box_buildable_init))
+
 
 /* common */
 static void
@@ -819,6 +837,15 @@ gtk_combo_box_class_init (GtkComboBoxCla
 }
 
 static void
+gtk_combo_box_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_combo_box_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_combo_box_buildable_custom_tag_end;
+}
+
+static void
 gtk_combo_box_cell_layout_init (GtkCellLayoutIface *iface)
 {
   iface->pack_start = gtk_combo_box_cell_layout_pack_start;
@@ -5605,5 +5632,36 @@ gtk_combo_box_get_focus_on_click (GtkCom
 }
 
 
+static gboolean
+gtk_combo_box_buildable_custom_tag_start (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *tagname,
+					  GMarkupParser *parser,
+					  gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+						tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+						      tagname, parser, data);
+}
+
+static void
+gtk_combo_box_buildable_custom_tag_end (GtkBuildable *buildable,
+					GtkBuilder   *builder,
+					GObject      *child,
+					const gchar  *tagname,
+					gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+					       data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+					    data);
+}
+
 #define __GTK_COMBO_BOX_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkcomboboxentry.c
===================================================================
--- gtk/gtkcomboboxentry.c	(revisão 18111)
+++ gtk/gtkcomboboxentry.c	(cópia de trabalho)
@@ -18,6 +18,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcomboboxentry.h"
 #include "gtkcelllayout.h"
 
@@ -26,6 +27,7 @@
 
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GTK_COMBO_BOX_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_COMBO_BOX_ENTRY, GtkComboBoxEntryPrivate))
@@ -60,6 +62,10 @@ static void gtk_combo_box_entry_grab_foc
 static void has_frame_changed                    (GtkComboBoxEntry      *entry_box,
 						  GParamSpec            *pspec,
 						  gpointer               data);
+static void gtk_combo_box_entry_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_combo_box_entry_buildable_get_internal_child (GtkBuildable *buildable,
+						     GtkBuilder   *builder,
+						     const gchar  *childname);
 
 enum
 {
@@ -67,7 +73,9 @@ enum
   PROP_TEXT_COLUMN
 };
 
-G_DEFINE_TYPE (GtkComboBoxEntry, gtk_combo_box_entry, GTK_TYPE_COMBO_BOX)
+G_DEFINE_TYPE_WITH_CODE (GtkComboBoxEntry, gtk_combo_box_entry, GTK_TYPE_COMBO_BOX,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_combo_box_entry_buildable_interface_init))
 
 static void
 gtk_combo_box_entry_class_init (GtkComboBoxEntryClass *klass)
@@ -130,6 +138,23 @@ gtk_combo_box_entry_init (GtkComboBoxEnt
 }
 
 static void
+gtk_combo_box_entry_buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->get_internal_child = gtk_combo_box_entry_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_combo_box_entry_buildable_get_internal_child (GtkBuildable *buildable,
+						  GtkBuilder   *builder,
+						  const gchar  *childname)
+{
+    if (strcmp (childname, "entry") == 0)
+      return G_OBJECT (gtk_bin_get_child (GTK_BIN (buildable)));
+
+    return NULL;
+}
+
+static void
 gtk_combo_box_entry_set_property (GObject      *object,
                                   guint         prop_id,
                                   const GValue *value,
Index: gtk/gtkcontainer.c
===================================================================
--- gtk/gtkcontainer.c	(revisão 18111)
+++ gtk/gtkcontainer.c	(cópia de trabalho)
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 
 #include "gtkcontainer.h"
+#include "gtkbuildable.h"
 #include "gtkprivate.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
@@ -99,6 +100,24 @@ static void     gtk_container_unmap     
 static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
 							  GtkWidget    *child);
 
+/* GtkBuildable */
+static void gtk_container_buildable_init           (GtkBuildableIface *iface);
+static void gtk_container_buildable_add            (GtkBuildable *buildable,
+						    GtkBuilder   *builder,
+						    GObject      *child,
+						    const gchar  *type);
+static gboolean gtk_container_buildable_custom_tag_start (GtkBuildable  *buildable,
+							  GtkBuilder    *builder,
+							  GObject       *child,
+							  const gchar   *tagname,
+							  GMarkupParser *parser,
+							  gpointer      *data);
+static void    gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
+						       GtkBuilder   *builder,
+						       GObject      *child,
+						       const gchar  *tagname,
+						       gpointer     *data);
+
 
 /* --- variables --- */
 static const gchar           vadjustment_key[] = "gtk-vadjustment";
@@ -110,6 +129,7 @@ static guint                 container_s
 static GtkWidgetClass       *parent_class = NULL;
 extern GParamSpecPool       *_gtk_widget_child_property_pool;
 extern GObjectNotifyContext *_gtk_widget_child_property_notify_context;
+static GtkBuildableIface    *parent_buildable_iface;
 
 
 /* --- functions --- */
@@ -134,9 +154,21 @@ gtk_container_get_type (void)
 	NULL,       /* value_table */
       };
 
+      static const GInterfaceInfo buildable_info =
+      {
+	(GInterfaceInitFunc) gtk_container_buildable_init,
+	NULL,
+	NULL
+      };
+
       container_type =
 	g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"), 
 				&container_info, G_TYPE_FLAG_ABSTRACT);
+
+      g_type_add_interface_static (container_type,
+				   GTK_TYPE_BUILDABLE,
+				   &buildable_info);
+
     }
 
   return container_type;
@@ -260,6 +292,164 @@ gtk_container_class_init (GtkContainerCl
 		  GTK_TYPE_WIDGET);
 }
 
+static void
+gtk_container_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = gtk_container_buildable_add;
+  iface->custom_tag_start = gtk_container_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_container_buildable_custom_tag_end;
+}
+
+static void
+gtk_container_buildable_add (GtkBuildable  *buildable,
+			     GtkBuilder    *builder,
+			     GObject       *child,
+			     const gchar   *type)
+{
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+}
+
+static void
+gtk_container_buildable_set_child_property (GtkContainer *container,
+					    GtkWidget    *child,
+					    gchar        *name,
+					    const gchar  *value)
+{
+  GParamSpec *pspec;
+  GValue gvalue = { 0, };
+
+  pspec = gtk_container_class_find_child_property
+    (G_OBJECT_GET_CLASS (container), name);
+  if (!pspec)
+    {
+      g_warning ("%s does not have a property called %s",
+		 g_type_name (G_OBJECT_TYPE (container)), name);
+      return;
+    }
+
+  if (!gtk_builder_value_from_string (pspec, value, &gvalue))
+    {
+      g_warning ("Could not read property %s:%s with value %s of type %s",
+		 g_type_name (G_OBJECT_TYPE (container)),
+		 name,
+		 value,
+		 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+      return;
+    }
+
+  gtk_container_child_set_property (container, child, name, &gvalue);
+  g_value_unset (&gvalue);
+}
+
+typedef struct {
+  GtkBuilder   *builder;
+  GtkContainer *container;
+  GtkWidget    *child;
+  gchar        *child_prop_name;
+} PackingPropertiesData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer             user_data,
+			  GError             **error)
+{
+  PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "property") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+	parser_data->child_prop_name = g_strdup (values[i]);
+  else if (strcmp (element_name, "packing") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkContainer: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+			 const gchar         *text,
+			 gsize                text_len,
+			 gpointer             user_data,
+			 GError             **error)
+{
+  PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data;
+
+  if (!parser_data->child_prop_name)
+    return;
+
+  gtk_container_buildable_set_child_property (parser_data->container,
+					      parser_data->child,
+					      parser_data->child_prop_name,
+					      text);
+
+  g_free (parser_data->child_prop_name);
+  parser_data->child_prop_name = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+static gboolean
+gtk_container_buildable_custom_tag_start (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *tagname,
+					  GMarkupParser *parser,
+					  gpointer      *data)
+{
+  PackingPropertiesData *parser_data;
+
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+						tagname, parser, data))
+    return TRUE;
+
+  if (child && strcmp (tagname, "packing") == 0)
+    {
+      parser_data = g_slice_new0 (PackingPropertiesData);
+      parser_data->builder = builder;
+      parser_data->container = GTK_CONTAINER (buildable);
+      parser_data->child = GTK_WIDGET (child);
+      parser_data->child_prop_name = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_container_buildable_custom_tag_end (GtkBuildable *buildable,
+					GtkBuilder   *builder,
+					GObject      *child,
+					const gchar  *tagname,
+					gpointer     *data)
+{
+  if (strcmp (tagname, "packing") == 0)
+    {
+      g_slice_free (PackingPropertiesData, data);
+      return;
+
+    }
+
+  if (parent_buildable_iface->custom_tag_end)
+    parent_buildable_iface->custom_tag_end (buildable, builder,
+					    child, tagname, data);
+
+}
+
 /**
  * gtk_container_child_type: 
  * @container: a #GtkContainer
Index: gtk/gtkdebug.h
===================================================================
--- gtk/gtkdebug.h	(revisão 18111)
+++ gtk/gtkdebug.h	(cópia de trabalho)
@@ -42,7 +42,8 @@
   GTK_DEBUG_MODULES     = 1 << 7,
   GTK_DEBUG_GEOMETRY    = 1 << 8,
   GTK_DEBUG_ICONTHEME   = 1 << 9,
-  GTK_DEBUG_PRINTING	= 1 << 10
+  GTK_DEBUG_PRINTING	= 1 << 10,
+  GTK_DEBUG_BUILDER	= 1 << 11
 } GtkDebugFlag;
 
 #ifdef G_ENABLE_DEBUG
Index: gtk/gtkdialog.c
===================================================================
--- gtk/gtkdialog.c	(revisão 18111)
+++ gtk/gtkdialog.c	(cópia de trabalho)
@@ -24,6 +24,8 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <stdlib.h>
+#include <string.h>
 #include <config.h>
 #include "gtkbutton.h"
 #include "gtkdialog.h"
@@ -37,6 +39,7 @@
 #include "gtkintl.h"
 #include "gtkbindings.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_DIALOG, GtkDialogPrivate))
@@ -76,6 +79,22 @@ static void gtk_dialog_close            
 
 static ResponseData* get_response_data   (GtkWidget        *widget,
 					  gboolean          create);
+static void gtk_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+						     GtkBuilder   *builder,
+						     const gchar  *childname);
+static gboolean gtk_dialog_buildable_custom_tag_start (GtkBuildable  *buildable,
+						       GtkBuilder    *builder,
+						       GObject       *child,
+						       const gchar   *tagname,
+						       GMarkupParser *parser,
+						       gpointer      *data);
+static void gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
+						  GtkBuilder   *builder,
+						  GObject       *child,
+						  const gchar   *tagname,
+						  gpointer      user_data);
+
 
 enum {
   PROP_0,
@@ -90,7 +109,9 @@ enum {
 
 static guint dialog_signals[LAST_SIGNAL];
 
-G_DEFINE_TYPE (GtkDialog, gtk_dialog, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE_WITH_CODE (GtkDialog, gtk_dialog, GTK_TYPE_WINDOW,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_dialog_buildable_interface_init))
 
 static void
 gtk_dialog_class_init (GtkDialogClass *class)
@@ -235,6 +256,26 @@ gtk_dialog_init (GtkDialog *dialog)
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
 }
 
+static void
+gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  iface->get_internal_child = gtk_dialog_buildable_get_internal_child;
+  iface->custom_tag_start = gtk_dialog_buildable_custom_tag_start;
+  iface->custom_finished = gtk_dialog_buildable_custom_finished;
+}
+
+static GObject *
+gtk_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+					 GtkBuilder   *builder,
+					 const gchar  *childname)
+{
+    if (strcmp (childname, "vbox") == 0)
+      return G_OBJECT (GTK_DIALOG (buildable)->vbox);
+    else if (strcmp (childname, "action_area") == 0)
+      return G_OBJECT (GTK_DIALOG (buildable)->action_area);
+
+    return NULL;
+}
 
 static void 
 gtk_dialog_set_property (GObject      *object,
@@ -1216,5 +1257,134 @@ gtk_dialog_set_alternative_button_order_
     }
 }
 
+typedef struct {
+  gchar *widget_name;
+  gchar *response_id;
+} ActionWidgetInfo;
+
+typedef struct {
+  GtkDialog *dialog;
+  GtkBuilder *builder;
+  GSList *items;
+  gchar *response;
+} ActionWidgetsSubParserData;
+
+static void
+attributes_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer             user_data,
+			  GError             **error)
+{
+  ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
+  guint i;
+
+  if (strcmp (element_name, "action-widget") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "response") == 0)
+	parser_data->response = g_strdup (values[i]);
+  else if (strcmp (element_name, "action-widgets") == 0)
+    return;
+  else
+    g_warning ("Unsupported tag for GtkDialog: %s\n", element_name);
+}
+
+static void
+attributes_text_element (GMarkupParseContext *context,
+			 const gchar         *text,
+			 gsize                text_len,
+			 gpointer             user_data,
+			 GError             **error)
+{
+  ActionWidgetsSubParserData *parser_data = (ActionWidgetsSubParserData*)user_data;
+  ActionWidgetInfo *item;
+
+  if (!parser_data->response)
+    return;
+
+  item = g_new (ActionWidgetInfo, 1);
+  item->widget_name = g_strndup (text, text_len);
+  item->response_id = parser_data->response;
+  parser_data->items = g_slist_prepend (parser_data->items, item);
+  parser_data->response = NULL;
+}
+
+static const GMarkupParser attributes_parser =
+  {
+    attributes_start_element,
+    NULL,
+    attributes_text_element,
+  };
+
+gboolean
+gtk_dialog_buildable_custom_tag_start (GtkBuildable  *buildable,
+				       GtkBuilder    *builder,
+				       GObject       *child,
+				       const gchar   *tagname,
+				       GMarkupParser *parser,
+				       gpointer      *data)
+{
+  ActionWidgetsSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "action-widgets") == 0)
+    {
+      parser_data = g_slice_new0 (ActionWidgetsSubParserData);
+      parser_data->dialog = GTK_DIALOG (buildable);
+      parser_data->items = NULL;
+
+      *parser = attributes_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
+				      GtkBuilder   *builder,
+				      GObject      *child,
+				      const gchar  *tagname,
+				      gpointer      user_data)
+{
+  GSList *l;
+  ActionWidgetsSubParserData *parser_data;
+  GObject *object;
+  ResponseData* data;
+
+  if (strcmp (tagname, "action-widgets"))
+    return;
+
+  parser_data = (ActionWidgetsSubParserData*)user_data;
+  parser_data->items = g_slist_reverse (parser_data->items);
+
+  for (l = parser_data->items; l; l = l->next)
+    {
+      ActionWidgetInfo *item = l->data;
+
+      object = gtk_builder_get_object (builder, item->widget_name);
+      if (!object)
+	{
+	  g_warning ("Unknown object %s specified in action-widgets %s",
+		     item->widget_name,
+		     gtk_buildable_get_name (GTK_BUILDABLE (object)));
+	  continue;
+	}
+
+      data = get_response_data (GTK_WIDGET (object), TRUE);
+      data->response_id = atoi (item->response_id);
+
+      g_free (item->widget_name);
+      g_free (item->response_id);
+      g_free (item);
+    }
+  g_slist_free (parser_data->items);
+  g_slice_free (ActionWidgetsSubParserData, parser_data);
+}
+
 #define __GTK_DIALOG_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkentrycompletion.c
===================================================================
--- gtk/gtkentrycompletion.c	(revisão 18111)
+++ gtk/gtkentrycompletion.c	(cópia de trabalho)
@@ -149,9 +149,15 @@ static void     gtk_entry_completion_ins
 
 static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
 
+/* GtkBuildable */
+static void     gtk_entry_completion_buildable_init      (GtkBuildableIface  *iface);
+
 G_DEFINE_TYPE_WITH_CODE (GtkEntryCompletion, gtk_entry_completion, G_TYPE_OBJECT,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-						gtk_entry_completion_cell_layout_init))
+						gtk_entry_completion_cell_layout_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_entry_completion_buildable_init))
+
 
 static void
 gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
@@ -387,6 +393,14 @@ gtk_entry_completion_class_init (GtkEntr
 }
 
 static void
+gtk_entry_completion_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
+  iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
+}
+
+static void
 gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface)
 {
   iface->pack_start = gtk_entry_completion_pack_start;
Index: gtk/gtkexpander.c
===================================================================
--- gtk/gtkexpander.c	(revisão 18111)
+++ gtk/gtkexpander.c	(cópia de trabalho)
@@ -22,10 +22,11 @@
  */
 
 #include <config.h>
-
+#include <string.h>
 #include "gtkexpander.h"
 
 #include "gtklabel.h"
+#include "gtkbuildable.h"
 #include "gtkcontainer.h"
 #include "gtkmarshalers.h"
 #include "gtkmain.h"
@@ -126,7 +127,16 @@ static void gtk_expander_activate (GtkEx
 static void get_expander_bounds (GtkExpander  *expander,
 				 GdkRectangle *rect);
 
-G_DEFINE_TYPE (GtkExpander, gtk_expander, GTK_TYPE_BIN)
+/* GtkBuildable */
+static void gtk_expander_buildable_init           (GtkBuildableIface *iface);
+static void gtk_expander_buildable_add            (GtkBuildable *buildable,
+						   GtkBuilder   *builder,
+						   GObject      *child,
+						   const gchar  *type);
+
+G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_expander_buildable_init))
 
 static void
 gtk_expander_class_init (GtkExpanderClass *klass)
@@ -278,6 +288,26 @@ gtk_expander_init (GtkExpander *expander
 }
 
 static void
+gtk_expander_buildable_add (GtkBuildable  *buildable,
+			    GtkBuilder    *builder,
+			    GObject       *child,
+			    const gchar   *type)
+{
+  if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else if (strcmp (type, "label") == 0)
+    gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_EXPANDER (buildable), type);
+}
+
+static void
+gtk_expander_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_expander_buildable_add;
+}
+
+static void
 gtk_expander_set_property (GObject      *object,
 			   guint         prop_id,
 			   const GValue *value,
Index: gtk/gtkfontsel.c
===================================================================
--- gtk/gtkfontsel.c	(revisão 18111)
+++ gtk/gtkfontsel.c	(cópia de trabalho)
@@ -59,6 +59,7 @@
 #include "gtkintl.h"
 #include "gtkaccessible.h"
 #include "gtkprivate.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 /* We don't enable the font and style entries because they don't add
@@ -1291,7 +1292,17 @@ gtk_font_selection_set_preview_text  (Gt
  * GtkFontSelectionDialog
  *****************************************************************************/
 
-G_DEFINE_TYPE (GtkFontSelectionDialog, gtk_font_selection_dialog, GTK_TYPE_DIALOG);
+static void gtk_font_selection_dialog_buildable_interface_init     (GtkBuildableIface *iface);
+static GObject * gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+									  GtkBuilder   *builder,
+									  const gchar  *childname);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFontSelectionDialog, gtk_font_selection_dialog,
+			 GTK_TYPE_DIALOG,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_font_selection_dialog_buildable_interface_init))
+
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
 gtk_font_selection_dialog_class_init (GtkFontSelectionDialogClass *klass)
@@ -1365,6 +1376,30 @@ gtk_font_selection_dialog_new (const gch
   return GTK_WIDGET (fontseldiag);
 }
 
+static void
+gtk_font_selection_dialog_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = gtk_font_selection_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_font_selection_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+							GtkBuilder   *builder,
+							const gchar  *childname)
+{
+    if (strcmp(childname, "ok_button") == 0)
+	return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->ok_button);
+    else if (strcmp(childname, "cancel_button") == 0)
+	return G_OBJECT (GTK_FONT_SELECTION_DIALOG (buildable)->cancel_button);
+    else if (strcmp(childname, "apply_button") == 0)
+	return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->apply_button);
+    else if (strcmp(childname, "font_selection") == 0)
+	return G_OBJECT (GTK_FONT_SELECTION_DIALOG(buildable)->fontsel);
+
+    return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
 /**
  * gtk_font_selection_dialog_get_font_name:
  * @fsd: a #GtkFontSelectionDialog
Index: gtk/gtkframe.c
===================================================================
--- gtk/gtkframe.c	(revisão 18111)
+++ gtk/gtkframe.c	(cópia de trabalho)
@@ -30,6 +30,7 @@
 #include "gtklabel.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define LABEL_PAD 1
@@ -73,7 +74,16 @@ static void gtk_frame_compute_child_allo
 static void gtk_frame_real_compute_child_allocation (GtkFrame      *frame,
 						     GtkAllocation *child_allocation);
 
-G_DEFINE_TYPE (GtkFrame, gtk_frame, GTK_TYPE_BIN)
+/* GtkBuildable */
+static void gtk_frame_buildable_init                (GtkBuildableIface *iface);
+static void gtk_frame_buildable_add                 (GtkBuildable *buildable,
+						     GtkBuilder   *builder,
+						     GObject      *child,
+						     const gchar  *type);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_frame_buildable_init))
 
 static void
 gtk_frame_class_init (GtkFrameClass *class)
@@ -150,6 +160,26 @@ gtk_frame_class_init (GtkFrameClass *cla
 }
 
 static void
+gtk_frame_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_frame_buildable_add;
+}
+
+static void
+gtk_frame_buildable_add (GtkBuildable *buildable,
+			 GtkBuilder   *builder,
+			 GObject      *child,
+			 const gchar  *type)
+{
+  if (type && strcmp (type, "label") == 0)
+    gtk_frame_set_label_widget (GTK_FRAME (buildable), GTK_WIDGET (child));
+  else if (!type)
+    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_FRAME (buildable), type);
+}
+
+static void
 gtk_frame_init (GtkFrame *frame)
 {
   frame->label_widget = NULL;
Index: gtk/gtk.h
===================================================================
--- gtk/gtk.h	(revisão 18111)
+++ gtk/gtk.h	(cópia de trabalho)
@@ -45,6 +45,7 @@
 #include <gtk/gtkbin.h>
 #include <gtk/gtkbindings.h>
 #include <gtk/gtkbox.h>
+#include <gtk/gtkbuildable.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkcalendar.h>
 #include <gtk/gtkcelllayout.h>
Index: gtk/gtkiconview.c
===================================================================
--- gtk/gtkiconview.c	(revisão 18111)
+++ gtk/gtkiconview.c	(cópia de trabalho)
@@ -450,11 +450,28 @@ static void     clear_source_info       
 static void     adjust_wrap_width                (GtkIconView     *icon_view,
 						  GtkIconViewItem *item);
 
+/* GtkBuildable */
+static GtkBuildableIface *parent_buildable_iface;
+static void     gtk_icon_view_buildable_init             (GtkBuildableIface *iface);
+static gboolean gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+							  GtkBuilder    *builder,
+							  GObject       *child,
+							  const gchar   *tagname,
+							  GMarkupParser *parser,
+							  gpointer      *data);
+static void     gtk_icon_view_buildable_custom_tag_end   (GtkBuildable  *buildable,
+							  GtkBuilder    *builder,
+							  GObject       *child,
+							  const gchar   *tagname,
+							  gpointer      *data);
+
 static guint icon_view_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-						gtk_icon_view_cell_layout_init))
+						gtk_icon_view_cell_layout_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_icon_view_buildable_init))
 
 static void
 gtk_icon_view_class_init (GtkIconViewClass *klass)
@@ -896,6 +913,15 @@ gtk_icon_view_class_init (GtkIconViewCla
 }
 
 static void
+gtk_icon_view_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = gtk_icon_view_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_icon_view_buildable_custom_tag_end;
+}
+
+static void
 gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface)
 {
   iface->pack_start = gtk_icon_view_cell_layout_pack_start;
@@ -9236,5 +9262,38 @@ gtk_icon_view_get_accessible (GtkWidget 
   return (* GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->get_accessible) (widget);
 }
 
+static gboolean
+gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *tagname,
+					  GMarkupParser *parser,
+					  gpointer      *data)
+{
+  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+						tagname, parser, data))
+    return TRUE;
+
+  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
+						      tagname, parser, data);
+}
+
+static void
+gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable,
+					GtkBuilder   *builder,
+					GObject      *child,
+					const gchar  *tagname,
+					gpointer     *data)
+{
+  if (strcmp (tagname, "attributes") == 0)
+    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
+					       data);
+  else
+    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
+					    data);
+}
+
+
+
 #define __GTK_ICON_VIEW_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkliststore.c
===================================================================
--- gtk/gtkliststore.c	(revisão 18111)
+++ gtk/gtkliststore.c	(cópia de trabalho)
@@ -18,6 +18,8 @@
  */
 
 #include <config.h>
+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <gobject/gvaluecollector.h>
 #include "gtktreemodel.h"
@@ -25,6 +27,7 @@
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
 #include "gtkintl.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID)
@@ -34,6 +37,7 @@ static void         gtk_list_store_tree_
 static void         gtk_list_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_list_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_list_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_list_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_list_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_list_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_list_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -114,6 +118,19 @@ static void     gtk_list_store_set_defau
 static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable        *sortable);
 
 
+/* buildable */
+static gboolean gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+							   GtkBuilder    *builder,
+							   GObject       *child,
+							   const gchar   *tagname,
+							   GMarkupParser *parser,
+							   gpointer      *data);
+static void     gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
+							 GtkBuilder   *builder,
+							 GObject      *child,
+							 const gchar  *tagname,
+							 gpointer     *data);
+
 G_DEFINE_TYPE_WITH_CODE (GtkListStore, gtk_list_store, G_TYPE_OBJECT,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
 						gtk_list_store_tree_model_init)
@@ -122,7 +139,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkListStore, g
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
 						gtk_list_store_drag_dest_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-						gtk_list_store_sortable_init))
+						gtk_list_store_sortable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_list_store_buildable_init))
+
 
 static void
 gtk_list_store_class_init (GtkListStoreClass *class)
@@ -176,6 +196,13 @@ gtk_list_store_sortable_init (GtkTreeSor
   iface->has_default_sort_func = gtk_list_store_has_default_sort_func;
 }
 
+void
+gtk_list_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_list_store_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_list_store_buildable_custom_tag_end;
+}
+
 static void
 gtk_list_store_init (GtkListStore *list_store)
 {
@@ -2008,5 +2035,252 @@ gtk_list_store_insert_with_valuesv (GtkL
   gtk_tree_path_free (path);
 }
 
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GtkBuilder *builder;
+  GObject *object;
+  GSList *column_type_names;
+  GType *column_types;
+  GValue *values;
+  gint *columns;
+  gint last_row;
+  gint n_columns;
+  gint row_column;
+  GQuark error_quark;
+  gboolean is_data;
+} SubParserData;
+
+static void
+list_store_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer             user_data,
+			  GError             **error)
+{
+  guint i;
+  SubParserData *data = (SubParserData*)user_data;
+
+  if (strcmp (element_name, "col") == 0)
+    {
+      int i, id = -1;
+
+      if (data->row_column >= data->n_columns)
+	g_set_error (error, data->error_quark, 0,
+		     "Too many columns, maximum is %d\n", data->n_columns - 1);
+
+      for (i = 0; names[i]; i++)
+	if (strcmp (names[i], "id") == 0)
+	  {
+	    errno = 0;
+	    id = atoi (values[i]);
+	    if (errno)
+	      g_set_error (error, data->error_quark, 0,
+			   "the id tag %s could not be converted to an integer", values[i]);
+	  }
+
+      if (id == -1)
+	g_set_error (error, data->error_quark, 0,
+		     "<col> needs an id attribute");
+
+      data->columns[data->row_column] = id;
+      data->row_column++;
+      data->is_data = TRUE;
+    }
+  else if (strcmp (element_name, "row") == 0)
+    ;
+  else if (strcmp (element_name, "column") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "type") == 0)
+	data->column_type_names = g_slist_prepend (data->column_type_names,
+						   g_strdup (values[i]));
+  else if (strcmp (element_name, "columns") == 0)
+    ;
+  else if (strcmp (element_name, "data") == 0)
+    ;
+  else
+    g_set_error (error, data->error_quark, 0,
+		 "Unknown start tag: %s", element_name);
+}
+
+static void
+list_store_end_element (GMarkupParseContext *context,
+			const gchar         *element_name,
+			gpointer             user_data,
+			GError             **error)
+{
+  SubParserData *data = (SubParserData*)user_data;
+
+  g_assert (data->builder);
+  
+  if (strcmp (element_name, "row") == 0)
+    {
+      GtkTreeIter iter;
+      int i;
+
+      gtk_list_store_insert_with_valuesv (GTK_LIST_STORE (data->object),
+					  &iter,
+					  data->last_row,
+					  data->columns,
+					  data->values,
+					  data->row_column);
+      for (i = 0; i < data->row_column; i++)
+	g_value_unset (&data->values[i]);
+      g_free (data->values);
+      data->values = g_new0 (GValue, data->n_columns);
+      data->last_row++;
+      data->row_column = 0;
+    }
+  else if (strcmp (element_name, "columns") == 0)
+    {
+      GType *column_types;
+      GSList *l;
+      int i;
+      GType type;
+
+      data->column_type_names = g_slist_reverse (data->column_type_names);
+      column_types = g_new0 (GType, g_slist_length (data->column_type_names));
+
+      for (l = data->column_type_names, i = 0; l; l = l->next, i++)
+	{
+	  type = gtk_builder_get_type_from_name (data->builder, l->data);
+	  if (type == G_TYPE_INVALID)
+	    {
+	      g_warning ("Unknown type %s specified in treemodel %s",
+			 (const gchar*)l->data,
+			 gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	      continue;
+	    }
+	  column_types[i] = type;
+
+	  g_free (l->data);
+	}
+
+      gtk_list_store_set_column_types (GTK_LIST_STORE (data->object), i,
+				       column_types);
+
+      g_free (column_types);
+    }
+  else if (strcmp (element_name, "col") == 0)
+    data->is_data = FALSE;
+  else if (strcmp (element_name, "data") == 0)
+    ;
+  else if (strcmp (element_name, "column") == 0)
+    ;
+  else
+    g_set_error (error, data->error_quark, 0,
+		 "Unknown end tag: %s", element_name);
+}
+
+static void
+list_store_text (GMarkupParseContext *context,
+		 const gchar         *text,
+		 gsize                text_len,
+		 gpointer             user_data,
+		 GError             **error)
+{
+  SubParserData *data = (SubParserData*)user_data;
+  gint i;
+
+  if (!data->is_data)
+    return;
+
+  i = data->row_column - 1;
+
+  if (!gtk_builder_value_from_string_type (data->column_types[i],
+					   text,
+					   &data->values[i]))
+    g_error ("Could not convert '%s' to type %s\n",
+	     text, g_type_name (data->column_types[i]));
+}
+
+static const GMarkupParser list_store_parser =
+  {
+    list_store_start_element,
+    list_store_end_element,
+    list_store_text
+  };
+
+static gboolean
+gtk_list_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+					   GtkBuilder    *builder,
+					   GObject       *child,
+					   const gchar   *tagname,
+					   GMarkupParser *parser,
+					   gpointer      *data)
+{
+  SubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "columns") == 0)
+    {
+
+      parser_data = g_slice_new0 (SubParserData);
+      parser_data->builder = builder;
+      parser_data->object = G_OBJECT (buildable);
+      parser_data->column_type_names = NULL;
+
+      *parser = list_store_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  else if (strcmp (tagname, "data") == 0)
+    {
+      gint n_columns = gtk_list_store_get_n_columns (GTK_TREE_MODEL (buildable));
+      if (n_columns == 0)
+	g_error ("Cannot append data to an empty model");
+
+      parser_data = g_slice_new0 (SubParserData);
+      parser_data->builder = builder;
+      parser_data->object = G_OBJECT (buildable);
+      parser_data->values = g_new0 (GValue, n_columns);
+      parser_data->columns = g_new0 (gint, n_columns);
+      parser_data->column_types = GTK_LIST_STORE (buildable)->column_headers;
+      parser_data->n_columns = n_columns;
+      parser_data->last_row = 0;
+      parser_data->error_quark = g_quark_from_static_string ("GtkListStore");
+      
+      *parser = list_store_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  else
+    g_warning ("Unknown custom list store tag: %s", tagname);
+  
+  return FALSE;
+}
+
+static void
+gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable,
+					 GtkBuilder   *builder,
+					 GObject      *child,
+					 const gchar  *tagname,
+					 gpointer     *data)
+{
+  SubParserData *sub = (SubParserData*)data;
+  
+  if (strcmp (tagname, "columns") == 0)
+    {
+      g_slist_free (sub->column_type_names);
+      g_slice_free (SubParserData, sub);
+    }
+  else if (strcmp (tagname, "data") == 0)
+    {
+      g_free (sub->columns);
+      g_free (sub->values);
+      g_slice_free (SubParserData, sub);
+    }
+  else
+    g_warning ("Unknown custom list store tag: %s", tagname);
+}
+
 #define __GTK_LIST_STORE_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkmain.c
===================================================================
--- gtk/gtkmain.c	(revisão 18111)
+++ gtk/gtkmain.c	(cópia de trabalho)
@@ -162,7 +162,8 @@ static const GDebugKey gtk_debug_keys[] 
   {"modules", GTK_DEBUG_MODULES},
   {"geometry", GTK_DEBUG_GEOMETRY},
   {"icontheme", GTK_DEBUG_ICONTHEME},
-  {"printing", GTK_DEBUG_PRINTING}
+  {"printing", GTK_DEBUG_PRINTING},
+  {"builder", GTK_DEBUG_BUILDER}
 };
 #endif /* G_ENABLE_DEBUG */
 
@@ -658,7 +659,7 @@ do_post_parse_initialization (int    *ar
   }
 
   gtk_type_init (0);
-  _gtk_accel_map_init ();  
+ _gtk_accel_map_init ();  
   _gtk_rc_init ();
 
   /* Set the 'initialized' flag.
Index: gtk/gtknotebook.c
===================================================================
--- gtk/gtknotebook.c	(revisão 18111)
+++ gtk/gtknotebook.c	(cópia de trabalho)
@@ -26,6 +26,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtknotebook.h"
 #include "gtkmain.h"
 #include "gtkmenu.h"
@@ -38,6 +39,7 @@
 #include "gtkbindings.h"
 #include "gtkprivate.h"
 #include "gtkdnd.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define SCROLL_DELAY_FACTOR   5
@@ -421,6 +423,12 @@ static void do_detach_tab  (GtkNotebook 
 			    gint         x,
 			    gint         y);
 
+/* GtkBuildable */
+static void gtk_notebook_buildable_init           (GtkBuildableIface *iface);
+static void gtk_notebook_buildable_add            (GtkBuildable *buildable,
+						   GtkBuilder   *builder,
+						   GObject      *child,
+						   const gchar  *type);
 
 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
 static gpointer window_creation_hook_data;
@@ -428,7 +436,9 @@ static GDestroyNotify window_creation_ho
 
 static guint notebook_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_notebook_buildable_init))
 
 static void
 add_tab_bindings (GtkBindingSet    *binding_set,
@@ -1095,6 +1105,36 @@ gtk_notebook_init (GtkNotebook *notebook
   gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
 }
 
+static void
+gtk_notebook_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_notebook_buildable_add;
+}
+
+static void
+gtk_notebook_buildable_add (GtkBuildable  *buildable,
+			    GtkBuilder    *builder,
+			    GObject       *child,
+			    const gchar   *type)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (buildable);
+
+  if (type && strcmp (type, "tab") == 0)
+    {
+      GtkWidget * page;
+
+      page = gtk_notebook_get_nth_page (notebook, -1);
+      /* To set the tab label widget, we must have already a child
+       * inside the tab container. */
+      g_assert (page != NULL);
+      gtk_notebook_set_tab_label (notebook, page, GTK_WIDGET (child));
+    }
+  else if (!type)
+    gtk_notebook_append_page (notebook, GTK_WIDGET (child), NULL);
+  else
+    GTK_BUILDER_WARN_INVALID_CHILD_TYPE (notebook, type);
+}
+
 static gboolean
 gtk_notebook_select_page (GtkNotebook *notebook,
                           gboolean     move_focus)
Index: gtk/gtksizegroup.c
===================================================================
--- gtk/gtksizegroup.c	(revisão 18111)
+++ gtk/gtksizegroup.c	(cópia de trabalho)
@@ -19,10 +19,12 @@
  */
 
 #include <config.h>
+#include <string.h>
 #include "gtkcontainer.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtksizegroup.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 enum {
@@ -49,6 +51,20 @@ static void add_widget_to_closure (GtkWi
 				   GSList           **groups,
 				   GSList           **widgets);
 
+/* GtkBuildable */
+static void gtk_size_group_buildable_init (GtkBuildableIface *iface);
+static gboolean gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+							   GtkBuilder    *builder,
+							   GObject       *child,
+							   const gchar   *tagname,
+							   GMarkupParser *parser,
+							   gpointer      *data);
+static void gtk_size_group_buildable_custom_finished (GtkBuildable  *buildable,
+						      GtkBuilder    *builder,
+						      GObject       *child,
+						      const gchar   *tagname,
+						      gpointer       user_data);
+
 static GQuark size_groups_quark;
 static const gchar size_groups_tag[] = "gtk-size-groups";
 
@@ -310,7 +326,16 @@ gtk_size_group_init (GtkSizeGroup *size_
   size_group->ignore_hidden = 0;
 }
 
-G_DEFINE_TYPE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT)
+static void
+gtk_size_group_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_size_group_buildable_custom_tag_start;
+  iface->custom_finished = gtk_size_group_buildable_custom_finished;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkSizeGroup, gtk_size_group, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_size_group_buildable_init))
 
 static void
 gtk_size_group_set_property (GObject      *object,
@@ -813,5 +838,101 @@ _gtk_size_group_queue_resize (GtkWidget 
   queue_resize_on_widget (widget, TRUE);
 }
 
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+size_group_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer            user_data,
+			  GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  if (strcmp (element_name, "widget") == 0)
+    for (i = 0; names[i]; i++)
+      if (strcmp (names[i], "name") == 0)
+	data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+  else if (strcmp (element_name, "widgets") == 0)
+    return;
+  else
+    g_warning ("Unsupported type tag for GtkSizeGroup: %s\n",
+	       element_name);
+
+}
+
+static const GMarkupParser size_group_parser =
+  {
+    size_group_start_element
+  };
+
+static gboolean
+gtk_size_group_buildable_custom_tag_start (GtkBuildable  *buildable,
+					   GtkBuilder    *builder,
+					   GObject       *child,
+					   const gchar   *tagname,
+					   GMarkupParser *parser,
+					   gpointer      *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "widgets") == 0)
+    {
+      parser_data = g_slice_new0 (GSListSubParserData);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+
+      *parser = size_group_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_size_group_buildable_custom_finished (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *tagname,
+					  gpointer       user_data)
+{
+  GSList *l;
+  GSListSubParserData *data;
+  GObject *object;
+
+  if (strcmp (tagname, "widgets"))
+    return;
+  
+  data = (GSListSubParserData*)user_data;
+  data->items = g_slist_reverse (data->items);
+
+  for (l = data->items; l; l = l->next)
+    {
+      object = gtk_builder_get_object (builder, l->data);
+      if (!object)
+	{
+	  g_warning ("Unknown object %s specified in sizegroup %s",
+		     (const gchar*)l->data,
+		     gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	  continue;
+	}
+      gtk_size_group_add_widget (GTK_SIZE_GROUP (data->object),
+				 GTK_WIDGET (object));
+      g_free (l->data);
+    }
+  g_slist_free (data->items);
+  g_slice_free (GSListSubParserData, data);
+}
+
+
 #define __GTK_SIZE_GROUP_C__
 #include "gtkaliasdef.c"
Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revisão 18111)
+++ gtk/gtk.symbols	(cópia de trabalho)
@@ -254,6 +254,7 @@
 gtk_arrow_type_get_type G_GNUC_CONST
 gtk_assistant_page_type_get_type G_GNUC_CONST
 gtk_attach_options_get_type G_GNUC_CONST
+gtk_builder_error_get_type G_GNUC_CONST
 gtk_button_action_get_type G_GNUC_CONST
 gtk_buttons_type_get_type G_GNUC_CONST
 gtk_calendar_display_options_get_type G_GNUC_CONST
@@ -420,6 +421,43 @@
 #endif
 #endif
 
+#if IN_HEADER(__GTK_BUILDABLE_H__)
+#if IN_FILE(__GTK_BUILDABLE_C__)
+gtk_buildable_add
+gtk_buildable_construct_child
+gtk_buildable_custom_tag_start
+gtk_buildable_custom_tag_end
+gtk_buildable_custom_finished
+gtk_buildable_get_internal_child
+gtk_buildable_get_name
+gtk_buildable_get_type G_GNUC_CONST
+gtk_buildable_parser_finished
+gtk_buildable_set_name
+gtk_buildable_set_property
+#endif
+#endif
+
+#if IN_HEADER(__GTK_BUILDER_H__)
+#if IN_FILE(__GTK_BUILDER_C__)
+gtk_builder_add_from_file
+gtk_builder_add_from_string
+gtk_builder_enum_from_string
+gtk_builder_error_quark
+gtk_builder_flags_from_string
+gtk_builder_get_object
+gtk_builder_get_objects
+gtk_builder_get_translation_domain
+gtk_builder_get_type G_GNUC_CONST
+gtk_builder_get_type_from_name
+gtk_builder_new
+gtk_builder_set_translation_domain
+gtk_builder_connect_signals
+gtk_builder_connect_signals_full
+gtk_builder_value_from_string
+gtk_builder_value_from_string_type
+#endif
+#endif
+
 #if IN_HEADER(__GTK_BUTTON_BOX_H__)
 #if IN_FILE(__GTK_BUTTON_BOX_C__)
 #ifndef GTK_DISABLE_DEPRECATED
Index: gtk/gtktreestore.c
===================================================================
--- gtk/gtktreestore.c	(revisão 18111)
+++ gtk/gtktreestore.c	(cópia de trabalho)
@@ -24,6 +24,7 @@
 #include "gtktreestore.h"
 #include "gtktreedatalist.h"
 #include "gtktreednd.h"
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -35,6 +36,7 @@ static void         gtk_tree_store_tree_
 static void         gtk_tree_store_drag_source_init(GtkTreeDragSourceIface *iface);
 static void         gtk_tree_store_drag_dest_init  (GtkTreeDragDestIface   *iface);
 static void         gtk_tree_store_sortable_init   (GtkTreeSortableIface   *iface);
+static void         gtk_tree_store_buildable_init  (GtkBuildableIface      *iface);
 static void         gtk_tree_store_finalize        (GObject           *object);
 static GtkTreeModelFlags gtk_tree_store_get_flags  (GtkTreeModel      *tree_model);
 static gint         gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
@@ -115,6 +117,21 @@ static void     gtk_tree_store_set_defau
 							GtkDestroyNotify        destroy);
 static gboolean gtk_tree_store_has_default_sort_func   (GtkTreeSortable        *sortable);
 
+
+/* buildable */
+
+static gboolean gtk_tree_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+							   GtkBuilder    *builder,
+							   GObject       *child,
+							   const gchar   *tagname,
+							   GMarkupParser *parser,
+							   gpointer      *data);
+static void     gtk_tree_store_buildable_custom_finished (GtkBuildable 	 *buildable,
+							  GtkBuilder   	 *builder,
+							  GObject      	 *child,
+							  const gchar  	 *tagname,
+							  gpointer     	  user_data);
+
 static void     validate_gnode                         (GNode *node);
 
 static void     gtk_tree_store_move                    (GtkTreeStore           *tree_store,
@@ -142,7 +159,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeStore, g
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
 						gtk_tree_store_drag_dest_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-						gtk_tree_store_sortable_init))
+						gtk_tree_store_sortable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_tree_store_buildable_init))
 
 static void
 gtk_tree_store_class_init (GtkTreeStoreClass *class)
@@ -196,6 +215,13 @@ gtk_tree_store_sortable_init (GtkTreeSor
   iface->has_default_sort_func = gtk_tree_store_has_default_sort_func;
 }
 
+void
+gtk_tree_store_buildable_init (GtkBuildableIface *iface)
+{
+  iface->custom_tag_start = gtk_tree_store_buildable_custom_tag_start;
+  iface->custom_finished = gtk_tree_store_buildable_custom_finished;
+}
+
 static void
 gtk_tree_store_init (GtkTreeStore *tree_store)
 {
@@ -3173,5 +3199,110 @@ validate_gnode (GNode* node)
     }
 }
 
+/* GtkBuildable custom tag implementation
+ *
+ * <columns>
+ *   <column type="..."/>
+ *   <column type="..."/>
+ * </columns>
+ */
+typedef struct {
+  GObject *object;
+  GSList *items;
+} GSListSubParserData;
+
+static void
+tree_model_start_element (GMarkupParseContext *context,
+			  const gchar         *element_name,
+			  const gchar        **names,
+			  const gchar        **values,
+			  gpointer            user_data,
+			  GError            **error)
+{
+  guint i;
+  GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "type") == 0)
+	data->items = g_slist_prepend (data->items, g_strdup (values[i]));
+    }
+}
+
+static const GMarkupParser tree_model_parser =
+  {
+    tree_model_start_element
+  };
+
+
+static gboolean
+gtk_tree_store_buildable_custom_tag_start (GtkBuildable  *buildable,
+					   GtkBuilder    *builder,
+					   GObject       *child,
+					   const gchar   *tagname,
+					   GMarkupParser *parser,
+					   gpointer      *data)
+{
+  GSListSubParserData *parser_data;
+
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "columns") == 0)
+    {
+      parser_data = g_slice_new0 (GSListSubParserData);
+      parser_data->items = NULL;
+      parser_data->object = G_OBJECT (buildable);
+
+      *parser = tree_model_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_tree_store_buildable_custom_finished (GtkBuildable *buildable,
+					  GtkBuilder   *builder,
+					  GObject      *child,
+					  const gchar  *tagname,
+					  gpointer      user_data)
+{
+  GSList *l;
+  GSListSubParserData *data;
+  GType *types;
+  int i;
+  GType type;
+
+  if (strcmp (tagname, "columns"))
+    return;
+
+  data = (GSListSubParserData*)user_data;
+  data->items = g_slist_reverse (data->items);
+  types = g_new0 (GType, g_slist_length (data->items));
+
+  for (l = data->items, i = 0; l; l = l->next, i++)
+    {
+      type = gtk_builder_get_type_from_name (builder, l->data);
+      if (type == G_TYPE_INVALID)
+	{
+	  g_warning ("Unknown type %s specified in treemodel %s",
+		     (const gchar*)l->data,
+		     gtk_buildable_get_name (GTK_BUILDABLE (data->object)));
+	  continue;
+	}
+      types[i] = type;
+
+      g_free (l->data);
+    }
+
+  gtk_tree_store_set_column_types (GTK_TREE_STORE (data->object), i, types);
+
+  g_free (types);
+  g_slist_free (data->items);
+  g_slice_free (GSListSubParserData, data);
+}
+
 #define __GTK_TREE_STORE_C__
 #include "gtkaliasdef.c"
Index: gtk/gtktreeview.c
===================================================================
--- gtk/gtktreeview.c	(revisão 18111)
+++ gtk/gtktreeview.c	(cópia de trabalho)
@@ -29,6 +29,7 @@
 #include "gtkcellrenderer.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
+#include "gtkbuildable.h"
 #include "gtkbutton.h"
 #include "gtkalignment.h"
 #include "gtklabel.h"
@@ -462,6 +463,13 @@ static void gtk_tree_view_tree_window_to
 						      gint         wy,
 						      gint        *tx,
 						      gint        *ty);
+/* GtkBuildable */
+static void gtk_tree_view_buildable_add (GtkBuildable *tree_view,
+					 GtkBuilder  *builder,
+					 GObject     *child,
+					 const gchar *type);
+static void gtk_tree_view_buildable_init (GtkBuildableIface *iface);
+
 
 static gboolean scroll_row_timeout                   (gpointer     data);
 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
@@ -474,7 +482,9 @@ static guint tree_view_signals [LAST_SIG
 /* GType Methods
  */
 
-G_DEFINE_TYPE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_tree_view_buildable_init))
 
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
@@ -1285,6 +1295,12 @@ gtk_tree_view_class_init (GtkTreeViewCla
 }
 
 static void
+gtk_tree_view_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_tree_view_buildable_add;
+}
+
+static void
 gtk_tree_view_init (GtkTreeView *tree_view)
 {
   tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, GTK_TYPE_TREE_VIEW, GtkTreeViewPrivate);
@@ -1492,6 +1508,15 @@ gtk_tree_view_finalize (GObject *object)
 
 
 
+static void
+gtk_tree_view_buildable_add (GtkBuildable *tree_view,
+			     GtkBuilder  *builder,
+			     GObject     *child,
+			     const gchar *type)
+{
+  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (child));
+}
+
 /* GtkObject Methods
  */
 
Index: gtk/gtktreeviewcolumn.c
===================================================================
--- gtk/gtktreeviewcolumn.c	(revisão 18111)
+++ gtk/gtktreeviewcolumn.c	(cópia de trabalho)
@@ -151,12 +151,17 @@ static GList *gtk_tree_view_column_cell_
 								GList                  *current);
 static void gtk_tree_view_column_clear_attributes_by_info      (GtkTreeViewColumn      *tree_column,
 					                        GtkTreeViewColumnCellInfo *info);
+/* GtkBuildable implementation */
+static void gtk_tree_view_column_buildable_init                 (GtkBuildableIface     *iface);
 
 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
-						gtk_tree_view_column_cell_layout_init))
+						gtk_tree_view_column_cell_layout_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_tree_view_column_buildable_init))
+
 
 static void
 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
@@ -324,6 +329,14 @@ gtk_tree_view_column_class_init (GtkTree
 }
 
 static void
+gtk_tree_view_column_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = _gtk_cell_layout_buildable_add;
+  iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
+  iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
+}
+
+static void
 gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
 {
   iface->pack_start = gtk_tree_view_column_cell_layout_pack_start;
Index: gtk/gtkuimanager.c
===================================================================
--- gtk/gtkuimanager.c	(revisão 18111)
+++ gtk/gtkuimanager.c	(cópia de trabalho)
@@ -31,6 +31,7 @@
 #include <config.h>
 
 #include <string.h>
+#include "gtkbuildable.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkmenu.h"
@@ -142,6 +143,28 @@ static void        node_prepend_ui_refer
 static void        node_remove_ui_reference       (GNode             *node,
                                                    guint              merge_id);
 
+/* GtkBuildable */
+static void gtk_ui_manager_buildable_init (GtkBuildableIface *iface);
+static void gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+					  GtkBuilder    *builder,
+					  GObject       *child,
+					  const gchar   *type);
+static GObject* gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+							  GtkBuilder   *builder,
+							  const gchar  *name);
+static gboolean gtk_ui_manager_buildable_custom_tag_start (GtkBuildable  *buildable,
+							   GtkBuilder    *builder,
+							   GObject       *child,
+							   const gchar   *tagname,
+							   GMarkupParser *parser,
+							   gpointer      *data);
+static void     gtk_ui_manager_buildable_custom_tag_end (GtkBuildable 	 *buildable,
+							 GtkBuilder   	 *builder,
+							 GObject      	 *child,
+							 const gchar  	 *tagname,
+							 gpointer     	 *data);
+
+
 
 enum 
 {
@@ -163,7 +186,9 @@ enum
 
 static guint ui_manager_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkUIManager, gtk_ui_manager, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (GtkUIManager, gtk_ui_manager, GTK_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_ui_manager_buildable_init))
 
 static void
 gtk_ui_manager_class_init (GtkUIManagerClass *klass)
@@ -401,6 +426,52 @@ gtk_ui_manager_finalize (GObject *object
 }
 
 static void
+gtk_ui_manager_buildable_init (GtkBuildableIface *iface)
+{
+  iface->add = gtk_ui_manager_buildable_add;
+  iface->construct_child = gtk_ui_manager_buildable_construct_child;
+  iface->custom_tag_start = gtk_ui_manager_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_ui_manager_buildable_custom_tag_end;
+}
+
+static void
+gtk_ui_manager_buildable_add (GtkBuildable  *buildable,
+			      GtkBuilder    *builder,
+			      GObject       *child,
+			      const gchar   *type)
+{
+  GtkUIManager *self = GTK_UI_MANAGER (buildable);
+  guint pos;
+
+  g_return_if_fail (GTK_IS_ACTION_GROUP (child));
+
+  pos = g_list_length (self->private_data->action_groups);
+
+  g_object_ref (child);
+  gtk_ui_manager_insert_action_group (self,
+				      GTK_ACTION_GROUP (child),
+				      pos);
+}
+
+static GObject *
+gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
+					  GtkBuilder   *builder,
+					  const gchar  *id)
+{
+  GtkWidget *widget;
+  char *name;
+
+  name = g_strdup_printf ("ui/%s", id);
+  widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name);
+  if (!widget)
+    g_error ("Unknown ui manager child: %s\n", name);
+
+  g_free (name);
+
+  return G_OBJECT (widget);
+}
+
+static void
 gtk_ui_manager_set_property (GObject         *object,
 			     guint            prop_id,
 			     const GValue    *value,
@@ -1479,7 +1550,7 @@ add_ui_from_string (GtkUIManager *self,
 
   queue_update (self);
 
-  g_object_notify (G_OBJECT (self), "ui");      
+  g_object_notify (G_OBJECT (self), "ui");
 
   return ctx.merge_id;
 
@@ -2818,6 +2889,49 @@ print_node (GtkUIManager *self,
     g_string_append_printf (buffer, close_fmt, indent_level, "");
 }
 
+static gboolean
+gtk_ui_manager_buildable_custom_tag_start (GtkBuildable  *buildable,
+					   GtkBuilder    *builder,
+					   GObject       *child,
+					   const gchar   *tagname,
+					   GMarkupParser *parser,
+					   gpointer      *data)
+{
+  if (child)
+    return FALSE;
+
+  if (strcmp (tagname, "ui") == 0)
+    {
+      ParseContext *ctx;
+
+      ctx = g_new0 (ParseContext, 1);
+      ctx->state = STATE_START;
+      ctx->self = GTK_UI_MANAGER (buildable);
+      ctx->current = NULL;
+      ctx->merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (buildable));
+
+      *data = ctx;
+      *parser = ui_parser;
+
+      return TRUE;
+    }
+
+  return FALSE;
+
+}
+
+static void
+gtk_ui_manager_buildable_custom_tag_end (GtkBuildable *buildable,
+					 GtkBuilder   *builder,
+					 GObject      *child,
+					 const gchar  *tagname,
+					 gpointer     *data)
+{
+  queue_update (GTK_UI_MANAGER (buildable));
+  g_object_notify (G_OBJECT (buildable), "ui");
+  g_free (data);
+}
+
 /**
  * gtk_ui_manager_get_ui:
  * @self: a #GtkUIManager
Index: gtk/gtkwidget.c
===================================================================
--- gtk/gtkwidget.c	(revisão 18111)
+++ gtk/gtkwidget.c	(cópia de trabalho)
@@ -52,6 +52,7 @@
 #include "gtktooltips.h"
 #include "gtktooltip.h"
 #include "gtkinvisible.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #define WIDGET_CLASS(w)	 GTK_WIDGET_GET_CLASS (w)
@@ -245,6 +246,28 @@ static gboolean         gtk_widget_real_
 static void             gtk_widget_set_has_tooltip              (GtkWidget *widget,
 								 gboolean   has_tooltip,
 								 gboolean   force);
+static void             gtk_widget_buildable_interface_init     (GtkBuildableIface *iface);
+static void             gtk_widget_buildable_set_name           (GtkBuildable     *buildable,
+                                                                 const gchar      *name);
+static const gchar *    gtk_widget_buildable_get_name           (GtkBuildable     *buildable);
+static void             gtk_widget_buildable_set_property       (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 const gchar      *name,
+                                                                 const GValue     *value);
+static gboolean         gtk_widget_buildable_custom_tag_start   (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 GObject          *child,
+                                                                 const gchar      *tagname,
+                                                                 GMarkupParser    *parser,
+                                                                 gpointer         *data);
+static void             gtk_widget_buildable_custom_finshed     (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder,
+                                                                 GObject          *child,
+                                                                 const gchar      *tagname,
+                                                                 gpointer          data);
+static void             gtk_widget_buildable_parser_finshed     (GtkBuildable     *buildable,
+                                                                 GtkBuilder       *builder);
+
      
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
 					   gint       width,
@@ -311,11 +334,20 @@ gtk_widget_get_type (void)
 	NULL /* interface data */
       };
 
+      const GInterfaceInfo buildable_info =
+      {
+	(GInterfaceInitFunc) gtk_widget_buildable_interface_init,
+	(GInterfaceFinalizeFunc) NULL,
+	NULL /* interface data */
+      };
+
       widget_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkWidget",
                                            &widget_info, G_TYPE_FLAG_ABSTRACT);
 
       g_type_add_interface_static (widget_type, ATK_TYPE_IMPLEMENTOR,
                                    &accessibility_info) ;
+      g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
+                                   &buildable_info) ;
 
     }
 
@@ -8366,6 +8398,176 @@ gtk_widget_ref_accessible (AtkImplemento
   return accessible;
 }
 
+/*
+ * GtkBuildable implementation
+ */
+static GQuark		quark_builder_has_default = 0;
+static GQuark		quark_builder_has_focus = 0;
+
+static void
+gtk_widget_buildable_interface_init (GtkBuildableIface *iface)
+{
+  quark_builder_has_default = g_quark_from_static_string ("gtk-builder-has-default");
+  quark_builder_has_focus = g_quark_from_static_string ("gtk-builder-has-focus");
+
+  iface->set_name = gtk_widget_buildable_set_name;
+  iface->get_name = gtk_widget_buildable_get_name;
+  iface->set_property = gtk_widget_buildable_set_property;
+  iface->parser_finished = gtk_widget_buildable_parser_finshed;
+  iface->custom_tag_start = gtk_widget_buildable_custom_tag_start;
+  iface->custom_finished = gtk_widget_buildable_custom_finshed;
+}
+
+static void
+gtk_widget_buildable_set_name (GtkBuildable *buildable,
+			       const gchar  *name)
+{
+  gtk_widget_set_name (GTK_WIDGET (buildable), name);
+}
+
+static const gchar *
+gtk_widget_buildable_get_name (GtkBuildable *buildable)
+{
+  return gtk_widget_get_name (GTK_WIDGET (buildable));
+}
+
+static void
+gtk_widget_buildable_set_property (GtkBuildable *buildable,
+				   GtkBuilder   *builder,
+				   const gchar  *name,
+				   const GValue *value)
+{
+  if (strcmp (name, "has-default") == 0 && g_value_get_boolean (value))
+      g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_default,
+			  GINT_TO_POINTER (TRUE));
+  else if (strcmp (name, "has-focus") == 0 && g_value_get_boolean (value))
+      g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_focus,
+			  GINT_TO_POINTER (TRUE));
+  else
+    g_object_set_property (G_OBJECT (buildable), name, value);
+}
+
+static void
+gtk_widget_buildable_parser_finshed (GtkBuildable *buildable,
+				     GtkBuilder   *builder)
+{
+  if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_default))
+    gtk_widget_grab_default (GTK_WIDGET (buildable));
+  if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_focus))
+    gtk_widget_grab_focus (GTK_WIDGET (buildable));
+}
+
+typedef struct {
+  GObject *object;
+  guint    key;
+  guint    modifiers;
+  gchar   *signal;
+} AccelGroupParserData;
+
+static void
+accel_group_start_element (GMarkupParseContext *context,
+			   const gchar         *element_name,
+			   const gchar        **names,
+			   const gchar        **values,
+			   gpointer             user_data,
+			   GError             **error)
+{
+  gint i;
+  guint key = 0;
+  guint modifiers = 0;
+  gchar *signal = NULL;
+  AccelGroupParserData *parser_data = (AccelGroupParserData*)user_data;
+
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "key") == 0)
+	key = gdk_keyval_from_name (values[i]);
+      else if (strcmp (names[i], "modifiers") == 0)
+	modifiers = gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, values[i]);
+      else if (strcmp (names[i], "signal") == 0)
+	signal = g_strdup (values[i]);
+    }
+
+  if (key == 0 || signal == NULL)
+    {
+      g_warning ("<accelerator> requires a key or signal attribute");
+      return;
+    }
+  parser_data->key = key;
+  parser_data->modifiers = modifiers;
+  parser_data->signal = signal;
+}
+
+static const GMarkupParser accel_group_parser =
+  {
+    accel_group_start_element,
+  };
+
+static gboolean
+gtk_widget_buildable_custom_tag_start (GtkBuildable     *buildable,
+				       GtkBuilder       *builder,
+				       GObject          *child,
+				       const gchar      *tagname,
+				       GMarkupParser    *parser,
+				       gpointer         *data)
+{
+  AccelGroupParserData *parser_data;
+
+  g_assert (buildable);
+
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      parser_data = g_new0 (AccelGroupParserData, 1);
+      parser_data->object = g_object_ref (buildable);
+      *parser = accel_group_parser;
+      *data = parser_data;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static void
+gtk_widget_buildable_custom_finshed (GtkBuildable *buildable,
+				     GtkBuilder   *builder,
+				     GObject      *child,
+				     const gchar  *tagname,
+				     gpointer      user_data)
+{
+  AccelGroupParserData *data;
+  GtkWidget *toplevel;
+  GSList *accel_groups;
+  GtkAccelGroup *accel_group;
+
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      data = (AccelGroupParserData*)user_data;
+      g_assert (data->object);
+
+      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (data->object));
+      accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
+      if (g_slist_length (accel_groups) == 0)
+	{
+	  accel_group = gtk_accel_group_new ();
+	  gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
+	}
+      else
+	{
+	  g_assert (g_slist_length (accel_groups) == 1);
+	  accel_group = g_slist_nth_data (accel_groups, 0);
+	}
+      gtk_widget_add_accelerator (GTK_WIDGET(data->object),
+				  data->signal,
+				  accel_group,
+				  data->key,
+				  data->modifiers,
+				  GTK_ACCEL_VISIBLE);
+      g_object_unref (data->object);
+      g_free (data->signal);
+      g_slice_free (AccelGroupParserData, data);
+    }
+}
+
+
 /**
  * gtk_widget_get_clipboard:
  * @widget: a #GtkWidget
Index: gtk/gtkwindow.c
===================================================================
--- gtk/gtkwindow.c	(revisão 18111)
+++ gtk/gtkwindow.c	(cópia de trabalho)
@@ -46,6 +46,7 @@
 #include "gtkicontheme.h"
 #include "gtkmarshalers.h"
 #include "gtkplug.h"
+#include "gtkbuildable.h"
 #include "gtkalias.h"
 
 #ifdef GDK_WINDOWING_X11
@@ -182,6 +183,7 @@ struct _GtkWindowPrivate
 
   guint reset_type_hint : 1;
   guint opacity_set : 1;
+  guint builder_visible : 1;
 
   GdkWindowTypeHint type_hint;
 
@@ -309,6 +311,8 @@ static GQuark       quark_gtk_window_key
 static GQuark       quark_gtk_window_default_icon_pixmap = 0;
 static GQuark       quark_gtk_window_icon_info = 0;
 
+static GtkBuildableIface *parent_buildable_iface;
+
 static void gtk_window_set_property (GObject         *object,
 				     guint            prop_id,
 				     const GValue    *value,
@@ -318,8 +322,19 @@ static void gtk_window_get_property (GOb
 				     GValue          *value,
 				     GParamSpec      *pspec);
 
+/* GtkBuildable */
+static void gtk_window_buildable_interface_init  (GtkBuildableIface *iface);
+static void gtk_window_buildable_set_property    (GtkBuildable        *buildable,
+						  GtkBuilder          *builder,
+						  const gchar         *name,
+						  const GValue        *value);
+static void gtk_window_buildable_parser_finished (GtkBuildable     *buildable,
+						  GtkBuilder       *builder);
 
-G_DEFINE_TYPE (GtkWindow, gtk_window, GTK_TYPE_BIN)
+
+G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+						gtk_window_buildable_interface_init))
 
 static void
 add_tab_bindings (GtkBindingSet    *binding_set,
@@ -1114,6 +1129,39 @@ gtk_window_get_property (GObject      *o
     }
 }
 
+static void
+gtk_window_buildable_interface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->set_property = gtk_window_buildable_set_property;
+  iface->parser_finished = gtk_window_buildable_parser_finished;
+
+}
+
+static void
+gtk_window_buildable_set_property (GtkBuildable        *buildable,
+				   GtkBuilder          *builder,
+				   const gchar         *name,
+				   const GValue        *value)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
+
+  if (strcmp (name, "visible") == 0 && g_value_get_boolean (value))
+    priv->builder_visible = TRUE;
+  else
+    parent_buildable_iface->set_property (buildable, builder, name, value);
+}
+
+static void
+gtk_window_buildable_parser_finished (GtkBuildable *buildable,
+				      GtkBuilder   *builder)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable);
+
+  if (priv->builder_visible)
+    gtk_widget_show (GTK_WIDGET (buildable));
+}
+
 /**
  * gtk_window_new:
  * @type: type of window
Index: gtk/Makefile.am
===================================================================
--- gtk/Makefile.am	(revisão 18111)
+++ gtk/Makefile.am	(cópia de trabalho)
@@ -143,6 +143,9 @@
 	gtkbin.h		\
 	gtkbindings.h		\
 	gtkbox.h		\
+	gtkbuilder.h		\
+	gtkbuildable.h		\
+	gtkbuilderprivate.h 	\
 	gtkbutton.h		\
 	gtkcalendar.h		\
 	gtkcelleditable.h	\
@@ -405,6 +408,9 @@
 	gtkbin.c		\
 	gtkbindings.c		\
 	gtkbox.c		\
+	gtkbuildable.c		\
+	gtkbuilder.c		\
+	gtkbuilderparser.c	\
 	gtkbutton.c		\
 	gtkcalendar.c		\
 	gtkcelleditable.c	\
Index: tests/builderdemo.c
===================================================================
--- tests/builderdemo.c	(revisão 0)
+++ tests/builderdemo.c	(revisão 0)
@@ -0,0 +1,59 @@
+/* demo.c
+ * Copyright (C) 2006 Async Open Source
+ * Author: Henrique Romano
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+void
+quit_activate (GtkAction *action)
+{
+  gtk_main_quit ();
+}
+
+void
+about_activate (GtkAction *action)
+{
+  GtkWidget *about_dlg;
+
+  about_dlg = gtk_about_dialog_new ();
+  gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (about_dlg), "GtkBuilder demo");
+  gtk_dialog_run (GTK_DIALOG (about_dlg));
+  gtk_widget_destroy (about_dlg);
+
+  g_message ("about clicked");
+}
+
+int
+main (int argc, char **argv)
+{
+  GtkBuilder *builder;
+  GObject *widget;
+  
+  gtk_init (&argc, &argv);
+  builder = gtk_builder_new ();
+  gtk_builder_add_from_file (builder, "demo.glade", NULL);
+  widget = gtk_builder_get_object (builder, "window1");
+  gtk_widget_show (GTK_WIDGET (widget));
+  gtk_builder_connect_signals (builder);
+
+  gtk_main ();
+  g_object_unref (builder);
+  
+  return 0;
+}
Index: tests/buildertest.c
===================================================================
--- tests/buildertest.c	(revisão 0)
+++ tests/buildertest.c	(revisão 0)
@@ -0,0 +1,1420 @@
+/* buildertest.c
+ * Copyright (C) 2006-2007 Async Open Source
+ * Authors: Johan Dahlin
+ *          Henrique Romano
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkprintjob.h>
+
+static GtkBuilder *
+builder_new_from_string (const gchar *buffer,
+                         gsize length,
+                         gchar *domain)
+{
+  GtkBuilder *builder;
+  builder = gtk_builder_new ();
+  if (domain)
+    gtk_builder_set_translation_domain (builder, domain);
+  gtk_builder_add_from_string (builder, buffer, length, NULL);
+  return builder;
+}
+
+int normal;
+int after;
+int object;
+int object_after;
+
+void
+signal_normal (GtkWindow *window, GParamSpec spec)
+{
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (normal == 0);
+  g_assert (after == 0);
+
+  normal++;
+}
+                    
+void
+signal_after (GtkWindow *window, GParamSpec spec)
+{
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (normal == 1);
+  g_assert (after == 0);
+  
+  after++;
+}
+
+void
+signal_object (GtkButton *button, GParamSpec spec)
+{
+  g_assert (GTK_IS_BUTTON (button));
+  g_assert (object == 0);
+  g_assert (object_after == 0);
+
+  object++;
+}
+
+void
+signal_object_after (GtkButton *button, GParamSpec spec)
+{
+  g_assert (GTK_IS_BUTTON (button));
+  g_assert (object == 1);
+  g_assert (object_after == 0);
+
+  object_after++;
+}
+
+void
+signal_first (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 0);
+  normal = 10;
+}
+
+void
+signal_second (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 10);
+  normal = 20;
+}
+
+void
+signal_extra (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 20);
+  normal = 30;
+}
+
+void
+signal_extra2 (GtkButton *button, GParamSpec spec)
+{
+  g_assert (normal == 30);
+  normal = 40;
+}
+
+gboolean test_connect_signals (void)
+{
+  GtkBuilder *builder;
+  GObject *window;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkButton\" id=\"button\"/>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <signal name=\"notify::title\" handler=\"signal_normal\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_after\" after=\"yes\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_object\" object=\"button\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_object_after\" object=\"button\" after=\"yes\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_order[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <signal name=\"notify::title\" handler=\"signal_first\"/>"
+    "    <signal name=\"notify::title\" handler=\"signal_second\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_extra[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window2\">"
+    "    <signal name=\"notify::title\" handler=\"signal_extra\"/>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer_extra2[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window3\">"
+    "    <signal name=\"notify::title\" handler=\"signal_extra2\"/>"
+    "  </object>"
+    "</interface>";
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  gtk_builder_connect_signals (builder);
+
+  window = gtk_builder_get_object (builder, "window1");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+
+  g_return_val_if_fail (normal == 1, FALSE);
+  g_return_val_if_fail (after == 1, FALSE);
+  g_return_val_if_fail (object == 1, FALSE);
+  g_return_val_if_fail (object_after == 1, FALSE);
+  
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer_order, -1, NULL);
+  gtk_builder_connect_signals (builder);
+  window = gtk_builder_get_object (builder, "window1");
+  normal = 0;
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 20);
+
+  gtk_builder_add_from_string (builder, buffer_extra,
+			       strlen (buffer_extra), NULL);
+  gtk_builder_add_from_string (builder, buffer_extra2,
+			       strlen (buffer_extra2), NULL);
+  gtk_builder_connect_signals (builder);
+  window = gtk_builder_get_object (builder, "window2");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 30);
+  window = gtk_builder_get_object (builder, "window3");
+  gtk_window_set_title (GTK_WINDOW (window), "test");
+  g_assert (normal == 40);
+
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_uimanager_simple (void)
+{
+  GtkBuilder *builder;
+  GObject *uimgr, *menubar;
+  GObject *menu, *label;
+  GList *children;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkUIManager\" id=\"uimgr1\"/>"
+    "</interface>";
+    
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkUIManager\" id=\"uimgr1\">"
+    "    <child>"
+    "      <object class=\"GtkActionGroup\" id=\"ag1\">"
+    "        <child>"
+    "          <object class=\"GtkAction\" id=\"file\">"
+    "            <property name=\"label\">_File</property>"
+    "          </object>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "    <ui>"
+    "      <menubar name=\"menubar1\">"
+    "        <menu action=\"file\">"
+    "        </menu>"
+    "      </menubar>"
+    "    </ui>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkMenuBar\" id=\"menubar1\" constructor=\"uimgr1\"/>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+
+  uimgr = gtk_builder_get_object (builder, "uimgr1");
+  g_return_val_if_fail (uimgr != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_UI_MANAGER (uimgr), FALSE);
+
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+
+  menubar = gtk_builder_get_object (builder, "menubar1");
+  g_return_val_if_fail (menubar != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_MENU_BAR (menubar), FALSE);
+
+  children = gtk_container_get_children (GTK_CONTAINER (menubar));
+  menu = children->data;
+  g_return_val_if_fail (menu != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_MENU_ITEM (menu), FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (menu)->name, "file") == 0, FALSE);
+  g_list_free (children);
+  
+  label = G_OBJECT (GTK_BIN (menu)->child);
+  g_return_val_if_fail (label != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail
+    (strcmp (gtk_label_get_text (GTK_LABEL (label)), "File") == 0, FALSE);
+  
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_domain (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer1[] = "<interface/>";
+  const gchar buffer2[] = "<interface domain=\"domain\"/>";
+  const gchar *domain;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain == NULL);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer1, -1, "domain-1");
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain-1") == 0);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain") == 0);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, "domain-1");
+  domain = gtk_builder_get_translation_domain (builder);
+  g_assert (domain);
+  g_assert (strcmp (domain, "domain-1") == 0);
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+#if 0
+gboolean test_translation (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label\">"
+    "        <property name=\"label\" translatable=\"yes\">File</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GtkLabel *label;
+
+  setlocale (LC_ALL, "sv_SE");
+  textdomain ("builder");
+  bindtextdomain ("builder", "tests");
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  label = GTK_LABEL (gtk_builder_get_object (builder, "label"));
+  g_assert (strcmp (gtk_label_get_text (label), "Arkiv") == 0);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+#endif
+
+gboolean test_sizegroup (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkVBox\" id=\"vbox1\">"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "    </widgets>"
+    "   </object>"
+    "</interface>";
+  const gchar buffer3[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup1\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup2\">"
+    "    <property name=\"mode\">GTK_SIZE_GROUP_HORIZONTAL</property>"
+    "    <widgets>"
+    "      <widget name=\"radio1\"/>"
+    "      <widget name=\"radio2\"/>"
+    "    </widgets>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkVBox\" id=\"vbox1\">"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio1\"/>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkRadioButton\" id=\"radio2\"/>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *sizegroup;
+  GSList *widgets;
+
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 0, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer3, -1, NULL);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup1");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  sizegroup = gtk_builder_get_object (builder, "sizegroup2");
+  widgets = gtk_size_group_get_widgets (GTK_SIZE_GROUP (sizegroup));
+  g_return_val_if_fail (g_slist_length (widgets) == 2, FALSE);
+  g_slist_free (widgets);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_list_store (void)
+{
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"guint\"/>"
+    "    </columns>"
+    "  </object>"
+    "</interface>";
+  const char buffer2[] = 
+    "<object class=\"GtkListStore\" id=\"liststore1\">"
+    "  <columns>"
+    "    <column type=\"gchararray\"/>"
+    "    <column type=\"gchararray\"/>"
+    "    <column type=\"gint\"/>"
+    "  </columns>"
+    "  <data>"
+    "    <row>"
+    "      <col id=\"0\">John</col>"
+    "      <col id=\"1\">Doe</col>"
+    "      <col id=\"2\">25</col>"
+    "    </row>"
+    "    <row>"
+    "      <col id=\"0\">Johan</col>"
+    "      <col id=\"1\">Dole</col>"
+    "      <col id=\"2\">50</col>"
+    "    </row>"
+    "  </data>"
+    "</object>";
+  GtkBuilder *builder;
+  GObject *store;
+  GtkTreeIter iter;
+  gchar *surname, *lastname;
+  int age;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  store = gtk_builder_get_object (builder, "liststore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT, FALSE);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  store = gtk_builder_get_object (builder, "liststore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 3, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 2) == G_TYPE_INT, FALSE);
+  
+  g_return_val_if_fail (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == TRUE, FALSE);
+  gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                      0, &surname,
+                      1, &lastname,
+                      2, &age,
+                      -1);
+  g_assert (surname != NULL);
+  g_return_val_if_fail (strcmp (surname, "John") == 0, FALSE);
+  g_free (surname);
+  g_assert (lastname != NULL);
+  g_return_val_if_fail (strcmp (lastname, "Doe") == 0, FALSE);
+  g_free (lastname);
+  g_return_val_if_fail (age == 25, FALSE);
+  g_return_val_if_fail (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == TRUE, FALSE);
+  
+  gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                      0, &surname,
+                      1, &lastname,
+                      2, &age,
+                      -1);
+  g_assert (surname != NULL);
+  g_return_val_if_fail (strcmp (surname, "Johan") == 0, FALSE);
+  g_free (surname);
+  g_assert (lastname != NULL);
+  g_return_val_if_fail (strcmp (lastname, "Dole") == 0, FALSE);
+  g_free (lastname);
+  g_return_val_if_fail (age == 50, FALSE);
+  g_return_val_if_fail (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter) == FALSE, FALSE);
+  
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_tree_store (void)
+{
+  const gchar buffer[] =
+    "<interface domain=\"test\">"
+    "  <object class=\"GtkTreeStore\" id=\"treestore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"guint\"/>"
+    "    </columns>"
+    "  </object>"
+    "</interface>";
+  GtkBuilder *builder;
+  GObject *store;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  store = gtk_builder_get_object (builder, "treestore1");
+  g_return_val_if_fail (gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)) == 2, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 0) == G_TYPE_STRING, FALSE);
+  g_return_val_if_fail (gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), 1) == G_TYPE_UINT, FALSE);
+  
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_types (void)
+{
+  const gchar buffer[] = 
+    "<interface>"
+    "  <object class=\"GtkAction\" id=\"action\"/>"
+    "  <object class=\"GtkActionGroup\" id=\"actiongroup\"/>"
+    "  <object class=\"GtkAlignment\" id=\"alignment\"/>"
+    "  <object class=\"GtkArrow\" id=\"arrow\"/>"
+    "  <object class=\"GtkButton\" id=\"button\"/>"
+    "  <object class=\"GtkCheckButton\" id=\"checkbutton\"/>"
+    "  <object class=\"GtkDialog\" id=\"dialog\"/>"
+    "  <object class=\"GtkDrawingArea\" id=\"drawingarea\"/>"
+    "  <object class=\"GtkEventBox\" id=\"eventbox\"/>"
+    "  <object class=\"GtkEntry\" id=\"entry\"/>"
+    "  <object class=\"GtkFontButton\" id=\"fontbutton\"/>"
+    "  <object class=\"GtkHButtonBox\" id=\"hbuttonbox\"/>"
+    "  <object class=\"GtkHBox\" id=\"hbox\"/>"
+    "  <object class=\"GtkHPaned\" id=\"hpaned\"/>"
+    "  <object class=\"GtkHRuler\" id=\"hruler\"/>"
+    "  <object class=\"GtkHScale\" id=\"hscale\"/>"
+    "  <object class=\"GtkHScrollbar\" id=\"hscrollbar\"/>"
+    "  <object class=\"GtkHSeparator\" id=\"hseparator\"/>"
+    "  <object class=\"GtkImage\" id=\"image\"/>"
+    "  <object class=\"GtkLabel\" id=\"label\"/>"
+    "  <object class=\"GtkListStore\" id=\"liststore\"/>"
+    "  <object class=\"GtkMenuBar\" id=\"menubar\"/>"
+    "  <object class=\"GtkNotebook\" id=\"notebook\"/>"
+    "  <object class=\"GtkProgressBar\" id=\"progressbar\"/>"
+    "  <object class=\"GtkRadioButton\" id=\"radiobutton\"/>"
+    "  <object class=\"GtkSizeGroup\" id=\"sizegroup\"/>"
+    "  <object class=\"GtkScrolledWindow\" id=\"scrolledwindow\"/>"
+    "  <object class=\"GtkSpinButton\" id=\"spinbutton\"/>"
+    "  <object class=\"GtkStatusbar\" id=\"statusbar\"/>"
+    "  <object class=\"GtkTextView\" id=\"textview\"/>"
+    "  <object class=\"GtkToggleAction\" id=\"toggleaction\"/>"
+    "  <object class=\"GtkToggleButton\" id=\"togglebutton\"/>"
+    "  <object class=\"GtkToolbar\" id=\"toolbar\"/>"
+    "  <object class=\"GtkTreeStore\" id=\"treestore\"/>"
+    "  <object class=\"GtkTreeView\" id=\"treeview\"/>"
+    "  <object class=\"GtkTable\" id=\"table\"/>"
+    "  <object class=\"GtkVBox\" id=\"vbox\"/>"
+    "  <object class=\"GtkVButtonBox\" id=\"vbuttonbox\"/>"
+    "  <object class=\"GtkVScrollbar\" id=\"vscrollbar\"/>"
+    "  <object class=\"GtkVSeparator\" id=\"vseparator\"/>"
+    "  <object class=\"GtkViewport\" id=\"viewport\"/>"
+    "  <object class=\"GtkVRuler\" id=\"vruler\"/>"
+    "  <object class=\"GtkVPaned\" id=\"vpaned\"/>"
+    "  <object class=\"GtkVScale\" id=\"vscale\"/>"
+    "  <object class=\"GtkWindow\" id=\"window\"/>"
+    "  <object class=\"GtkUIManager\" id=\"uimanager\"/>"
+    "</interface>";
+  GtkBuilder *builder;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_spin_button (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "<object class=\"GtkAdjustment\" id=\"adjustment1\">"
+    "<property name=\"lower\">0</property>"
+    "<property name=\"upper\">10</property>"
+    "<property name=\"step-increment\">2</property>"
+    "<property name=\"page-increment\">3</property>"
+    "<property name=\"page-size\">5</property>"
+    "<property name=\"value\">1</property>"
+    "</object>"
+    "<object class=\"GtkSpinButton\" id=\"spinbutton1\">"
+    "<property name=\"visible\">True</property>"
+    "<property name=\"adjustment\">adjustment1</property>"
+    "</object>"
+    "</interface>";
+  GObject *object;
+  GtkAdjustment *adjustment;
+  gdouble value;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  object = gtk_builder_get_object (builder, "spinbutton1");
+  g_assert (GTK_IS_SPIN_BUTTON (object));
+  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (object));
+  g_assert (GTK_IS_ADJUSTMENT (adjustment));
+  g_object_get (adjustment, "value", &value, NULL);
+  g_return_val_if_fail (value == 1, FALSE);
+  g_object_get (adjustment, "lower", &value, NULL);
+  g_return_val_if_fail (value == 0, FALSE);
+  g_object_get (adjustment, "upper", &value, NULL);
+  g_return_val_if_fail (value == 10, FALSE);
+  g_object_get (adjustment, "step-increment", &value, NULL);
+  g_return_val_if_fail (value == 2, FALSE);
+  g_object_get (adjustment, "page-increment", &value, NULL);
+  g_return_val_if_fail (value == 3, FALSE);
+  g_object_get (adjustment, "page-size", &value, NULL);
+  g_return_val_if_fail (value == 5, FALSE);
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_notebook (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkNotebook\" id=\"notebook1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label1\">"
+    "        <property name=\"label\">label1</property>"
+    "      </object>"
+    "    </child>"
+    "    <child type=\"tab\">"
+    "      <object class=\"GtkLabel\" id=\"tablabel1\">"
+    "        <property name=\"label\">tab_label1</property>"
+    "      </object>"
+    "    </child>"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label2\">"
+    "        <property name=\"label\">label2</property>"
+    "      </object>"
+    "    </child>"
+    "    <child type=\"tab\">"
+    "      <object class=\"GtkLabel\" id=\"tablabel2\">"
+    "        <property name=\"label\">tab_label2</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *notebook;
+  GtkWidget *label;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  notebook = gtk_builder_get_object (builder, "notebook1");
+  g_assert (notebook != NULL);
+  g_return_val_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) == 2,
+                        FALSE);
+
+  label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                                "label1") == 0, FALSE);
+  label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+				"tab_label1") == 0, FALSE);
+
+  label = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+                                "label2") == 0, FALSE);
+  label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), label);
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  g_return_val_if_fail (strcmp (gtk_label_get_label (GTK_LABEL (label)),
+				"tab_label2") == 0, FALSE);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_construct_only_property (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <property name=\"type\">GTK_WINDOW_POPUP</property>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkTextTagTable\" id=\"tagtable1\"/>"
+    "  <object class=\"GtkTextBuffer\" id=\"textbuffer1\">"
+    "    <property name=\"tag-table\">tagtable1</property>"
+    "  </object>"
+    "</interface>";
+  GObject *widget, *tagtable, *textbuffer;
+  GtkWindowType type;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  widget = gtk_builder_get_object (builder, "window1");
+  g_object_get (widget, "type", &type, NULL);
+  g_return_val_if_fail (type == GTK_WINDOW_POPUP, FALSE);
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  textbuffer = gtk_builder_get_object (builder, "textbuffer1");
+  g_return_val_if_fail (textbuffer != NULL, FALSE);
+  g_object_get (textbuffer, "tag-table", &tagtable, NULL);
+  g_return_val_if_fail (tagtable == gtk_builder_get_object (builder, "tagtable1"), FALSE);
+  g_object_unref (builder);
+
+  return TRUE;
+}
+
+gboolean test_children (void)
+{
+  GtkBuilder * builder;
+  GList *children;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "        <property name=\"label\">Hello</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  const gchar buffer2[] =
+    "<interface>"
+    "  <object class=\"GtkDialog\" id=\"dialog1\">"
+    "    <child internal-child=\"vbox\">"
+    "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
+    "        <property name=\"border-width\">10</property>"
+    "          <child internal-child=\"action_area\">"
+    "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
+    "              <property name=\"border-width\">20</property>"
+    "            </object>"
+    "          </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  GObject *window, *button;
+  GObject *dialog, *vbox, *action_area;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  window = gtk_builder_get_object (builder, "window1");
+  g_return_val_if_fail (window != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  button = gtk_builder_get_object (builder, "button1");
+  g_return_val_if_fail (button != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_WIDGET (button)->parent)->name, "window1") == 0, FALSE);
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  dialog = gtk_builder_get_object (builder, "dialog1");
+  g_return_val_if_fail (dialog != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_DIALOG (dialog), FALSE);
+  children = gtk_container_get_children (GTK_CONTAINER (dialog));
+  g_return_val_if_fail (g_list_length (children) == 1, FALSE);
+  g_list_free (children);
+  
+  vbox = gtk_builder_get_object (builder, "dialog1-vbox");
+  g_return_val_if_fail (vbox != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_VBOX (vbox), FALSE);
+  g_return_val_if_fail (GTK_WIDGET (vbox)->parent != NULL, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_WIDGET (vbox)->parent)->name, "dialog1") == 0, FALSE);
+  g_return_val_if_fail (GTK_CONTAINER (vbox)->border_width == 10, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_DIALOG (dialog)->vbox)->name,
+				"dialog1-vbox") == 0, FALSE);
+
+  action_area = gtk_builder_get_object (builder, "dialog1-action_area");
+  g_return_val_if_fail (action_area != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_HBUTTON_BOX (action_area), FALSE);
+  g_return_val_if_fail (GTK_WIDGET (action_area)->parent != NULL, FALSE);
+  g_return_val_if_fail (GTK_CONTAINER (action_area)->border_width == 20, FALSE);
+  g_return_val_if_fail (GTK_DIALOG (dialog)->action_area != NULL, FALSE);
+  g_return_val_if_fail (GTK_WIDGET (GTK_DIALOG (dialog)->action_area)->name != NULL, FALSE);
+  g_return_val_if_fail (strcmp (GTK_WIDGET (GTK_DIALOG (dialog)->action_area)->name,
+				"dialog1-action_area") == 0, FALSE);
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_child_properties (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkVBox\" id=\"vbox1\">"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label1\"/>"
+    "      <packing>"
+    "        <property name=\"pack-type\">start</property>"
+    "      </packing>"
+    "    </child>"
+    "    <child>"
+    "      <object class=\"GtkLabel\" id=\"label2\"/>"
+    "      <packing>"
+    "        <property name=\"pack-type\">end</property>"
+    "      </packing>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+
+  GObject *label, *vbox;
+  GtkPackType pack_type;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  vbox = gtk_builder_get_object (builder, "vbox1");
+  g_return_val_if_fail (GTK_IS_VBOX (vbox), FALSE);
+
+  label = gtk_builder_get_object (builder, "label1");
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  gtk_container_child_get (GTK_CONTAINER (vbox),
+                           GTK_WIDGET (label),
+                           "pack-type",
+                           &pack_type,
+                           NULL);
+  g_return_val_if_fail (pack_type == GTK_PACK_START, FALSE);
+  
+  label = gtk_builder_get_object (builder, "label2");
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  gtk_container_child_get (GTK_CONTAINER (vbox),
+                           GTK_WIDGET (label),
+                           "pack-type",
+                           &pack_type,
+                           NULL);
+  g_return_val_if_fail (pack_type == GTK_PACK_END, FALSE);
+
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_treeview_column (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "<object class=\"GtkListStore\" id=\"liststore1\">"
+    "  <columns>"
+    "    <column type=\"gchararray\"/>"
+    "    <column type=\"guint\"/>"
+    "  </columns>"
+    "  <data>"
+    "    <row>"
+    "      <col id=\"0\">John</col>"
+    "      <col id=\"1\">25</col>"
+    "    </row>"
+    "  </data>"
+    "</object>"
+    "<object class=\"GtkWindow\" id=\"window1\">"
+    "  <child>"
+    "    <object class=\"GtkTreeView\" id=\"treeview1\">"
+    "      <property name=\"visible\">True</property>"
+    "      <property name=\"model\">liststore1</property>"
+    "      <child>"
+    "        <object class=\"GtkTreeViewColumn\" id=\"column1\">"
+    "          <property name=\"title\">Test</property>"
+    "          <child>"
+    "            <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "          </child>"
+    "        </object>"
+    "      </child>"
+    "      <child>"
+    "        <object class=\"GtkTreeViewColumn\" id=\"column2\">"
+    "          <property name=\"title\">Number</property>"
+    "          <child>"
+    "            <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "          </child>"
+    "        </object>"
+    "      </child>"
+    "    </object>"
+    "  </child>"
+    "</object>"
+    "</interface>";
+  GObject *treeview;
+  GtkTreeViewColumn *column;
+  GList *renderers;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  treeview = gtk_builder_get_object (builder, "treeview1");
+  g_return_val_if_fail (treeview, FALSE);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
+  column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 0);
+  g_return_val_if_fail (strcmp (gtk_tree_view_column_get_title (column),
+				"Test") == 0, FALSE);
+
+  renderers = gtk_tree_view_column_get_cell_renderers (column);
+  g_return_val_if_fail (g_list_length (renderers) == 1, FALSE);
+  renderer = g_list_nth_data (renderers, 0);
+  g_return_val_if_fail (renderer, FALSE);
+  g_return_val_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer), FALSE);
+  g_list_free (renderers);
+
+  gtk_widget_realize (GTK_WIDGET (treeview));
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "25") == 0, FALSE);
+  g_free (text);
+  
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "John") == 0, FALSE);
+  g_free (text);
+
+  gtk_widget_unrealize (GTK_WIDGET (treeview));
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_icon_view (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "      <column type=\"GdkPixbuf\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">test</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkIconView\" id=\"iconview1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"text-column\">0</property>"
+    "        <property name=\"pixbuf-column\">1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "          <attributes>"
+    "            <attribute name=\"text\">0</attribute>"
+    "          </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *iconview;
+  GObject *renderer;
+  gchar *text;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  iconview = gtk_builder_get_object (builder, "iconview1");
+  g_return_val_if_fail (iconview, FALSE);
+  g_return_val_if_fail (GTK_IS_ICON_VIEW (iconview), FALSE);
+
+  gtk_widget_realize (GTK_WIDGET (iconview));
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "test") == 0, FALSE);
+  g_free (text);
+    
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_combo_box (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"guint\"/>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">1</col>"
+    "        <col id=\"1\">Foo</col>"
+    "      </row>"
+    "      <row>"
+    "        <col id=\"0\">2</col>"
+    "        <col id=\"1\">Bar</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkComboBox\" id=\"combobox1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *combobox;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  combobox = gtk_builder_get_object (builder, "combobox1");
+  g_return_val_if_fail (combobox, FALSE);
+  gtk_widget_realize (GTK_WIDGET (combobox));
+
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "Bar") == 0, FALSE);
+  g_free (text);
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "2") == 0, FALSE);
+  g_free (text);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_combo_box_entry (void)
+{
+  GtkBuilder *builder;
+  const gchar buffer[] =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"guint\"/>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">1</col>"
+    "        <col id=\"1\">Foo</col>"
+    "      </row>"
+    "      <row>"
+    "        <col id=\"0\">2</col>"
+    "        <col id=\"1\">Bar</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkComboBoxEntry\" id=\"comboboxentry1\">"
+    "        <property name=\"model\">liststore1</property>"
+    "        <property name=\"visible\">True</property>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">0</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "        <child>"
+    "          <object class=\"GtkCellRendererText\" id=\"renderer2\"/>"
+    "            <attributes>"
+    "              <attribute name=\"text\">1</attribute>"
+    "            </attributes>"
+    "        </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *combobox;
+  GObject *renderer;
+  gchar *text;
+
+  builder = builder_new_from_string (buffer, -1, NULL);
+  combobox = gtk_builder_get_object (builder, "comboboxentry1");
+  g_return_val_if_fail (combobox, FALSE);
+
+  renderer = gtk_builder_get_object (builder, "renderer2");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "Bar") == 0, FALSE);
+  g_free (text);
+
+  renderer = gtk_builder_get_object (builder, "renderer1");
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_assert (text);
+  g_return_val_if_fail (strcmp (text, "2") == 0, FALSE);
+  g_free (text);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_cell_view (void)
+{
+  GtkBuilder *builder;
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkListStore\" id=\"liststore1\">"
+    "    <columns>"
+    "      <column type=\"gchararray\"/>"
+    "    </columns>"
+    "    <data>"
+    "      <row>"
+    "        <col id=\"0\">test</col>"
+    "      </row>"
+    "    </data>"
+    "  </object>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkCellView\" id=\"cellview1\">"
+    "   <property name=\"visible\">True</property>"
+    "   <property name=\"model\">liststore1</property>"
+    "   <child>"
+    "     <object class=\"GtkCellRendererText\" id=\"renderer1\"/>"
+    "     <attributes>"
+    "       <attribute name=\"text\">0</attribute>"
+    "     </attributes>"
+    "   </child>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *cellview;
+  GObject *model;
+  GtkTreePath *path;
+  GList *renderers;
+  GObject *renderer;
+  gchar *text;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  g_assert (builder);
+  cellview = gtk_builder_get_object (builder, "cellview1");
+  g_assert (cellview);
+  g_return_val_if_fail (GTK_IS_CELL_VIEW (cellview), FALSE);
+  g_object_get (cellview, "model", &model, NULL);
+  g_assert (model);
+  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+  path = gtk_tree_path_new_first ();
+  gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (cellview), path);
+  
+  renderers = gtk_cell_view_get_cell_renderers (GTK_CELL_VIEW (cellview));
+  g_assert (renderers);
+  g_return_val_if_fail (g_list_length (renderers) == 1, FALSE);
+  
+  gtk_widget_realize (GTK_WIDGET (cellview));
+
+  renderer = g_list_nth_data (renderers, 0);
+  g_list_free (renderers);
+  g_assert (renderer);
+  g_object_get (renderer, "text", &text, NULL);
+  g_return_val_if_fail (strcmp (text, "test") == 0, FALSE);
+  g_free (text);
+  gtk_tree_path_free (path);
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_dialog (void)
+{
+  GtkBuilder * builder;
+  const gchar buffer1[] =
+    "<interface>"
+    "  <object class=\"GtkDialog\" id=\"dialog1\">"
+    "    <child internal-child=\"vbox\">"
+    "      <object class=\"GtkVBox\" id=\"dialog1-vbox\">"
+    "          <child internal-child=\"action_area\">"
+    "            <object class=\"GtkHButtonBox\" id=\"dialog1-action_area\">"
+    "              <child>"
+    "                <object class=\"GtkButton\" id=\"button_cancel\"/>"
+    "              </child>"
+    "              <child>"
+    "                <object class=\"GtkButton\" id=\"button_ok\"/>"
+    "              </child>"
+    "            </object>"
+    "          </child>"
+    "      </object>"
+    "    </child>"
+    "    <action-widgets>"
+    "      <action-widget response=\"3\">button_ok</action-widget>"
+    "      <action-widget response=\"-5\">button_cancel</action-widget>"
+    "    </action-widgets>"
+    "  </object>"
+    "</interface>";
+
+  GObject *dialog1;
+  GObject *button_ok;
+  GObject *button_cancel;
+  
+  builder = builder_new_from_string (buffer1, -1, NULL);
+  dialog1 = gtk_builder_get_object (builder, "dialog1");
+  button_ok = gtk_builder_get_object (builder, "button_ok");
+  g_return_val_if_fail (gtk_dialog_get_response_for_widget
+                        (GTK_DIALOG (dialog1),
+                         GTK_WIDGET (button_ok)) == 3, FALSE);
+  button_cancel = gtk_builder_get_object (builder, "button_cancel");
+  g_return_val_if_fail (gtk_dialog_get_response_for_widget
+                        (GTK_DIALOG (dialog1),
+                         GTK_WIDGET (button_cancel)) == -5, FALSE);
+  
+  g_object_unref (builder);
+  
+  return TRUE;
+}
+
+gboolean test_accelerators (void)
+{
+  GtkBuilder *builder;
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "        <accelerator key=\"q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"clicked\"/>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  gchar *buffer2 =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkTreeView\" id=\"treeview1\">"
+    "        <signal name=\"cursor-changed\" handler=\"gtk_main_quit\"/>"
+    "        <accelerator key=\"f\" modifiers=\"GDK_CONTROL_MASK\" signal=\"grab_focus\"/>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+    "</interface>";
+  GObject *window1;
+  GSList *accel_groups;
+  GObject *accel_group;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_return_val_if_fail (g_slist_length (accel_groups) == 1, FALSE);
+  accel_group = g_slist_nth_data (accel_groups, 0);
+  g_assert (accel_group);
+
+  g_object_unref (builder);
+
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  window1 = gtk_builder_get_object (builder, "window1");
+  g_assert (window1);
+  g_assert (GTK_IS_WINDOW (window1));
+
+  accel_groups = gtk_accel_groups_from_object (window1);
+  g_return_val_if_fail (g_slist_length (accel_groups) == 1, FALSE);
+  accel_group = g_slist_nth_data (accel_groups, 0);
+  g_assert (accel_group);
+
+  g_object_unref (builder);
+  return TRUE;
+}
+
+gboolean test_widget (void)
+{
+  gchar *buffer =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "         <property name=\"can-focus\">True</property>"
+    "         <property name=\"has-focus\">True</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+   "</interface>";
+  gchar *buffer2 =
+    "<interface>"
+    "  <object class=\"GtkWindow\" id=\"window1\">"
+    "    <child>"
+    "      <object class=\"GtkButton\" id=\"button1\">"
+    "         <property name=\"can-default\">True</property>"
+    "         <property name=\"has-default\">True</property>"
+    "      </object>"
+    "    </child>"
+    "  </object>"
+   "</interface>";
+  GtkBuilder *builder;
+  GObject *button1;
+  
+  builder = builder_new_from_string (buffer, -1, NULL);
+  button1 = gtk_builder_get_object (builder, "button1");
+
+#if 0
+  g_return_val_if_fail (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (button1)), FALSE);
+#endif
+  g_object_unref (builder);
+  
+  builder = builder_new_from_string (buffer2, -1, NULL);
+  button1 = gtk_builder_get_object (builder, "button1");
+
+  g_return_val_if_fail (GTK_WIDGET_RECEIVES_DEFAULT (GTK_WIDGET (button1)), FALSE);
+  
+  g_object_unref (builder);
+  return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+  gtk_init (&argc, &argv);
+
+  g_print ("Testing types\n");
+  if (!test_types ())
+    g_error ("test_types failed");
+
+  g_print ("Testing construct-only property\n");
+  if (!test_construct_only_property ())
+    g_error ("test_construct_only_property failed");
+  
+  g_print ("Testing children\n");
+  if (!test_children ())
+    g_error ("test_children failed");
+
+  g_print ("Testing child properties\n");
+  if (!test_child_properties ())
+    g_error ("test_child_properties failed");
+
+  g_print ("Testing notebook\n");
+  if (!test_notebook ())
+    g_error ("test_notebook failed");
+
+  g_print ("Testing domain\n");
+  if (!test_domain ())
+    g_error ("test_domain failed");
+
+  g_print ("Testing signal autoconnect\n");
+  if (!test_connect_signals ())
+    g_error ("test_connect_signals failed");
+
+  g_print ("Testing uimanager simple\n");
+  if (!test_uimanager_simple ())
+    g_error ("test_uimanager_simple failed");
+
+  g_print ("Testing spin button\n");
+  if (!test_spin_button ())
+    g_error ("test_spin_button failed");
+
+  g_print ("Testing sizegroup\n");
+  if (!test_sizegroup ())
+    g_error ("test_sizegroup failed");
+  
+  g_print ("Testing list store\n");
+  if (!test_list_store ())
+    g_error ("test_list_store failed");
+  
+  g_print ("Testing tree store\n");
+  if (!test_tree_store ())
+    g_error ("test_tree_store failed");
+
+  g_print ("Testing treeview column\n");
+  if (!test_treeview_column ())
+    g_error ("test_treeview_column failed");
+
+  g_print ("Testing iconview\n");
+  if (!test_icon_view ())
+    g_error ("test_icon_view failed");
+
+  g_print ("Testing combobox\n");
+  if (!test_combo_box ())
+    g_error ("test_combo_box failed");
+
+  g_print ("Testing combobox entry\n");
+  if (!test_combo_box_entry ())
+    g_error ("test_combo_box_entry failed");
+
+  g_print ("Testing cell view\n");
+  if (!test_cell_view ())
+    g_error ("test_cell_view failed");
+  
+  g_print ("Testing dialog\n");
+  if (!test_dialog ())
+    g_error ("test_dialog failed");
+
+  g_print ("Testing accelerators\n");
+  if (!test_accelerators ())
+    g_error ("test_accelerators failed");
+
+  g_print ("Testing widget\n");
+  if (!test_widget ())
+    g_error ("test_widget failed");
+
+  return 0;
+}
Index: tests/demo.glade
===================================================================
--- tests/demo.glade	(revisão 0)
+++ tests/demo.glade	(revisão 0)
@@ -0,0 +1,175 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<interface>
+    <object class="GtkUIManager" id="uimanager">
+        <child>
+            <object class="GtkActionGroup" id="DefaultActions">
+                <child>
+                    <object class="GtkAction" id="Copy">
+                        <property name="name">Copy</property>
+                        <property name="tooltip" translatable="yes">Copy selected object into the clipboard</property>
+                        <property name="stock_id">gtk-copy</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Cut">
+                        <property name="name">Cut</property>
+                        <property name="tooltip" translatable="yes">Cut selected object into the clipboard</property>
+                        <property name="stock_id">gtk-cut</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="EditMenu">
+                        <property name="name">EditMenu</property>
+                        <property name="label" translatable="yes">_Edit</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="FileMenu">
+                        <property name="name">FileMenu</property>
+                        <property name="label" translatable="yes">_File</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="New">
+                        <property name="name">New</property>
+                        <property name="tooltip" translatable="yes">Create a new file</property>
+                        <property name="stock_id">gtk-new</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Open">
+                        <property name="name">Open</property>
+                        <property name="tooltip" translatable="yes">Open a file</property>
+                        <property name="stock_id">gtk-open</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Paste">
+                        <property name="name">Paste</property>
+                        <property name="tooltip" translatable="yes">Paste object from the Clipboard</property>
+                        <property name="stock_id">gtk-paste</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Quit">
+                        <property name="name">Quit</property>
+                        <property name="tooltip" translatable="yes">Quit the program</property>
+                        <property name="stock_id">gtk-quit</property>
+                        <signal handler="quit_activate" name="activate"/>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="Save">
+                        <property name="name">Save</property>
+                        <property name="is_important">True</property>
+                        <property name="tooltip" translatable="yes">Save a file</property>
+                        <property name="stock_id">gtk-save</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="SaveAs">
+                        <property name="name">SaveAs</property>
+                        <property name="tooltip" translatable="yes">Save with a different name</property>
+                        <property name="stock_id">gtk-save-as</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="HelpMenu">
+                        <property name="name">Help</property>
+                        <property name="label" translatable="yes">_Help</property>
+                    </object>
+                </child>
+                <child>
+                    <object class="GtkAction" id="About">
+                        <property name="name">About</property>
+                        <property name="stock_id">gtk-about</property>
+                        <signal handler="about_activate" name="activate"/>
+                    </object>
+                </child>
+            </object>
+        </child>
+        <ui>
+          <menubar name="menubar1">
+            <menu action="FileMenu" name="FileMenu">
+              <menuitem action="New" name="New"/>
+              <menuitem action="Open" name="Open"/>
+              <menuitem action="Save" name="Save"/>
+              <menuitem action="SaveAs" name="SaveAs"/>
+              <separator/>
+              <menuitem action="Quit" name="Quit"/>
+            </menu>
+            <menu action="EditMenu">
+              <menuitem action="Copy" name="Copy"/>
+              <menuitem action="Cut" name="Cut"/>
+              <menuitem action="Paste" name="Paste"/>
+            </menu>
+            <menu action="HelpMenu" name="HelpMenu">
+              <menuitem action="About" name="About"/>
+            </menu>
+          </menubar>
+          <toolbar name="toolbar1">
+            <toolitem action="New" name="New"/>
+            <toolitem action="Open" name="Open"/>
+            <toolitem action="Save" name="Save"/>
+            <separator/>
+            <toolitem action="Copy" name="Copy"/>
+            <toolitem action="Cut" name="Cut"/>
+            <toolitem action="Paste" name="Paste"/>
+          </toolbar>
+        </ui>
+    </object>
+
+    <object class="GtkWindow" id="window1">
+        <property name="default_height">250</property>
+        <property name="default_width">440</property>
+        <signal handler="gtk_main_quit" name="delete-event"/>
+        <child>
+            <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <child>
+                    <object constructor="uimanager" class="GtkMenuBar" id="menubar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                    </packing>
+                </child>
+                <child>
+                    <object constructor="uimanager" class="GtkToolbar" id="toolbar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                        <property name="position">1</property>
+                    </packing>
+                </child>
+                <child>
+                    <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <property name="visible">True</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <child>
+                            <object class="GtkTextView" id="textview1">
+                                <property name="is_focus">True</property>
+                                <property name="visible">True</property>
+                            </object>
+                        </child>
+                    </object>
+                    <packing>
+                        <property name="position">2</property>
+                    </packing>
+                </child>
+                <child>
+                    <object class="GtkStatusbar" id="statusbar1">
+                        <property name="visible">True</property>
+                    </object>
+                    <packing>
+                        <property name="expand">False</property>
+                        <property name="position">3</property>
+                    </packing>
+                </child>
+            </object>
+        </child>
+    </object>
+</interface>
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revisão 18111)
+++ tests/Makefile.am	(cópia de trabalho)
@@ -24,11 +24,13 @@
 testsocket_programs = testsocket testsocket_child
 endif
 
-TESTS = floatingtest
+TESTS = floatingtest buildertest
 
 noinst_PROGRAMS =			\
 	autotestfilechooser		\
 	floatingtest			\
+	buildertest			\
+	builderdemo			\
 	simple				\
 	print-editor			\
 	testaccel			\
@@ -91,6 +93,8 @@
 autotestfilechooser_DEPENDENCIES = $(TEST_DEPS)
 simple_DEPENDENCIES = $(TEST_DEPS)
 floatingtest_DEPENDENCIES = $(TEST_DEPS)
+buildertest_DEPENDENCIES = $(TEST_DEPS)
+builderdemo_DEPENDENCIES = $(TEST_DEPS)
 print_editor_DEPENDENCIES = $(TEST_DEPS)
 testicontheme_DEPENDENCIES = $(TEST_DEPS)
 testiconview_DEPENDENCIES = $(TEST_DEPS)
@@ -146,6 +150,8 @@
 autotestfilechooser_LDADD = $(LDADDS)
 simple_LDADD = $(LDADDS)
 floatingtest_LDADD = $(LDADDS)
+buildertest_LDADD = $(LDADDS)
+builderdemo_LDADD = $(LDADDS)
 print_editor_LDADD = $(LDADDS)
 testaccel_LDADD = $(LDADDS)
 testassistant_LDADD = $(LDADDS)
@@ -205,6 +211,10 @@
 testtooltips_LDADD = $(LDADDS)
 testvolumebutton_LDADD = $(LDADDS)
 
+# XXX: Hack
+buildertest_LDFLAGS = -Wl,--export-dynamic
+builderdemo_LDFLAGS = -Wl,--export-dynamic
+
 autotestfilechooser_SOURCES =	\
 	autotestfilechooser.c
 
