--- gtk/gtkbuilderprivate.h	(.../tags/start)	(revision 0)
+++ gtk/gtkbuilderprivate.h	(.../trunk)	(revision 313)
@@ -0,0 +1,112 @@
+/* gtkbuilderprivate.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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;
+
+  /* For GtkUIManager */
+  const GMarkupParser *ui_parser;
+  gpointer ui_parser_data;
+} 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;
+  const 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;
+} ParserData;
+
+#define state_peek_info(data, st) ((st*)state_peek(data))
+#define state_pop_info(data, st) ((st*)state_pop(data))
+
+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_finish (GtkBuilder *builder);
+void      _gtk_builder_add (GtkBuilder *builder,
+			    ChildInfo *child_info);
+void _free_signal_info (SignalInfo *info,
+			gpointer user_data);
+
+#endif /* __GTK_BUILDER_PRIVATE_H__ */
--- gtk/gtkbuilder.c	(.../tags/start)	(revision 0)
+++ gtk/gtkbuilder.c	(.../trunk)	(revision 313)
@@ -0,0 +1,948 @@
+/* gtkbuilder.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+#include "gtkbuilder.h"
+#include "gtkbuildable.h"
+#include "gtkbuilderprivate.h"
+#include "gtkmain.h"
+#include "gtkintl.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);
+
+enum {
+  PROP_0,
+  PROP_DOMAIN,
+};
+
+enum {
+  FINISH,
+  NUM_SIGNALS,
+};
+
+static guint gtk_builder_signals[NUM_SIGNALS] = { 0 };
+
+#define GTK_BUILDER_GET_PRIVATE(o)       (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUILDER, GtkBuilderPrivate))
+typedef struct _GtkBuilderPrivate GtkBuilderPrivate;
+
+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;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_DOMAIN,
+                                   g_param_spec_string ("domain",
+                                                        P_("Domain"),
+                                                        P_("Translation domain"),
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+
+  g_type_class_add_private (gobject_class, sizeof (GtkBuilderPrivate));
+
+  gtk_builder_signals[FINISH] = g_signal_new ("finish",
+					      G_TYPE_FROM_CLASS (klass),
+					      G_SIGNAL_RUN_LAST,
+					      G_STRUCT_OFFSET (GtkBuilderClass,
+							       finish),
+					      NULL, NULL,
+					      g_cclosure_marshal_VOID__VOID,
+					      G_TYPE_NONE, 0);
+}
+
+static void
+gtk_builder_init (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  priv->domain = NULL;
+  priv->objects = g_hash_table_new (g_str_hash, g_str_equal);
+  priv->delayed_properties = g_hash_table_new_full (g_str_hash, g_str_equal,
+						    g_free, NULL);
+}
+
+static void
+gtk_builder_finalize (GObject *object)
+{
+  GtkBuilderPrivate *priv;
+
+  priv = GTK_BUILDER_GET_PRIVATE (object);
+  g_free (priv->domain);
+  
+  g_slist_foreach (priv->signals, (GFunc)_free_signal_info, NULL);
+  g_slist_free (priv->signals);
+  g_hash_table_foreach (priv->objects, (GHFunc)g_free, NULL);
+  g_hash_table_destroy (priv->objects);
+}
+
+static void
+gtk_builder_set_property (GObject      *object,
+			  guint         prop_id,
+			  const GValue *value,
+			  GParamSpec   *pspec)
+{
+  GtkBuilderPrivate *priv;
+
+  priv = GTK_BUILDER_GET_PRIVATE (object);
+  switch (prop_id)
+    {
+    case PROP_DOMAIN:
+      g_free (priv->domain);
+      priv->domain = g_value_dup_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)
+{
+  GtkBuilderPrivate *priv;
+
+  priv = GTK_BUILDER_GET_PRIVATE (object);
+  switch (prop_id)
+    {
+    case PROP_DOMAIN:
+      g_value_set_string (value, priv->domain);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+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)
+{
+  GtkBuilderPrivate *priv;
+  GSList *l;
+  GParamSpec *pspec;
+  GObjectClass *oclass;
+  DelayedProperty *property;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  
+  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_print ("Unknown property: %s.%s\n",
+		   g_type_name (object_type), prop->name);
+	  continue;
+	}
+      if (G_IS_PARAM_SPEC_OBJECT (pspec))
+	{
+	  GSList *delayed_properties;
+
+	  delayed_properties = g_hash_table_lookup (priv->delayed_properties,
+						    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 (priv->delayed_properties,
+			       g_strdup (priv->current_toplevel),
+			       delayed_properties);
+	  continue;
+	}
+      
+      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;
+	}
+
+      parameter.name = prop->name;
+      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;
+
+      if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+	g_print ("Trying to get internal child %s from %s\n",
+		 childname,
+		 gtk_builder_get_object_name (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;
+  GtkBuilderPrivate *priv;
+  int i;
+  GSList *l;
+  GtkBuildableIface *iface;
+  gboolean custom_set_property;
+  GtkBuildable *buildable;
+  
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+
+  g_assert (info->class_name != NULL);
+  object_type = gtk_lazy_type_from_name (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);
+    }
+  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);
+    }
+  else
+    {
+      obj = g_object_newv (object_type,
+			   construct_parameters->len,
+			   (GParameter *)construct_parameters->data);
+
+      if (gtk_debug_flags & GTK_DEBUG_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 (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);
+	}
+      g_value_unset (&param->value);
+    }
+  g_array_free (parameters, TRUE);
+
+  if (GTK_IS_BUILDABLE (obj))
+    gtk_buildable_set_name (buildable, info->id);
+  
+  g_object_set_data_full (obj,
+			  "gtk-builder-name",
+			  g_strdup (info->id),
+			  g_free);
+
+  if (!info->parent)
+    {
+      g_free (priv->current_toplevel);
+      priv->current_toplevel = g_strdup (info->id);
+    }
+  g_hash_table_insert (priv->objects, g_strdup (info->id), obj);
+
+  for (l = info->signals; l; l = l->next)
+    {
+      priv->signals = g_slist_prepend (priv->signals, l->data);
+    }
+  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_print ("%s: Not adding, No parent\n",
+	       gtk_builder_get_object_name (object));
+      return;
+    }
+  
+  g_assert (object != NULL);
+
+  parent = ((ObjectInfo*)child_info->parent)->object;
+  g_assert (parent != NULL);
+  g_assert (GTK_IS_BUILDABLE (parent));
+
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    g_print ("adding %s to %s\n",
+	     gtk_builder_get_object_name (object),
+	     gtk_builder_get_object_name (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;
+  GtkBuilderPrivate *priv;
+  GType object_type;
+  GObjectClass *oclass;
+  GParamSpec *pspec;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  
+  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 (priv->objects, property->object);
+      g_assert (object != NULL);
+
+      object_type = gtk_lazy_type_from_name (G_OBJECT_TYPE_NAME (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 (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)
+{
+  GtkBuilderPrivate *priv;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  if (priv->delayed_properties)
+    {
+      g_hash_table_foreach (priv->delayed_properties,
+			    (GHFunc)apply_delayed_properties, builder);
+      g_hash_table_destroy (priv->delayed_properties);
+      priv->delayed_properties = NULL;
+    }
+  g_free (priv->current_toplevel);
+  g_signal_emit (G_OBJECT (builder), gtk_builder_signals[FINISH], 0);
+}
+
+/**
+ * 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.
+ */
+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
+ * @pspec: the GParamSpec for the property
+ * @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.
+ */
+gboolean
+gtk_builder_value_from_string_type (GType type,
+				    const gchar *string,
+				    GValue *value)
+{
+  gboolean ret = TRUE;
+
+  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:
+      g_value_set_boolean (value, 
+			   g_ascii_tolower (string[0]) == 't'
+			   || g_ascii_tolower (string[0]) == 'y'
+			   || strtol (string, NULL, 0));
+      break;
+    case G_TYPE_INT:
+      g_value_set_int (value, strtol (string, NULL, 0));
+      break;
+    case G_TYPE_UINT:
+      g_value_set_uint (value, strtoul (string, NULL, 0));
+      break;
+    case G_TYPE_LONG:
+      g_value_set_long (value, strtol (string, NULL, 0));
+      break;
+    case G_TYPE_ULONG:
+      g_value_set_ulong (value, strtoul (string, NULL, 0));
+      break; 
+    case G_TYPE_ENUM:
+      g_value_set_enum (value, gtk_enum_from_string (type, string));
+      break;
+    case G_TYPE_FLAGS:
+      g_value_set_flags (value, gtk_flags_from_string (type, string));
+      break;
+    case G_TYPE_FLOAT:
+      g_value_set_float (value, g_strtod (string, NULL));
+      break;
+    case G_TYPE_DOUBLE:
+      g_value_set_double (value, g_strtod (string, NULL));
+      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_new:
+ *
+ * Creates a new ui manager object.
+ * 
+ * Return value: a new ui manager object.
+ *
+ * Since: 2.10
+ **/
+GtkBuilder *
+gtk_builder_new (void)
+{
+  return g_object_new (GTK_TYPE_BUILDER, NULL);
+}
+
+/**
+ * gtk_builder_parse_filename:
+ * @buildable: a #GtkBuilder
+ * @filename: the name of the file to parse
+ * @error: return location for an error
+ *
+ * Since: 2.10
+ **/
+void
+gtk_builder_parse_filename (GtkBuilder   *builder,
+			    const gchar  *filename,
+			    GError      **error)
+{
+  char *buffer;
+  unsigned length;
+  
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (filename != NULL);
+  
+  if (g_file_get_contents (filename, &buffer, &length, error))
+    _gtk_builder_parser_parse_buffer (builder, filename,
+				      buffer, length,
+				      error);
+  
+  g_free (buffer);
+}
+
+/**
+ * gtk_builder_parse_buffer:
+ * @buildable: 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
+ *
+ * Since: 2.10
+ **/
+void
+gtk_builder_parse_buffer (GtkBuilder  *builder,
+			  const gchar *buffer,
+			  gsize        length,
+			  GError     **error)
+{
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (buffer != NULL);
+
+  _gtk_builder_parser_parse_buffer (builder, "<input>",
+				    buffer, length,
+				    error);
+}
+
+/**
+ * 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.10
+ **/
+GObject *
+gtk_builder_get_object (GtkBuilder  *builder,
+			const gchar *name)
+{
+  GtkBuilderPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+  
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  return g_hash_table_lookup (priv->objects, name);
+}
+
+static void
+object_add_to_list (gchar *object_id,
+		    GObject *object,
+		    GSList **list)
+{
+  *list = g_slist_append (*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.10
+ **/
+GSList *
+gtk_builder_get_objects (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv;
+  GSList *objects = NULL;
+
+  g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  g_hash_table_foreach (priv->objects, (GHFunc)object_add_to_list, &objects);
+
+  return objects;
+}
+
+/**
+ * gtk_builder_get_object_name:
+ * @object: a GObject
+ *
+ * Return value: the name of the object, or %NULL if it was not constructed
+ *   by a GtkBuilder
+ *
+ * Since: 2.10
+ **/
+const gchar *
+gtk_builder_get_object_name (GObject *object)
+{
+  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+  return (const gchar*)g_object_get_data (G_OBJECT (object),
+					  "gtk-builder-name");
+}
+
+/**
+ * gtk_builder_set_translation_domain:
+ * @builder: a #GtkBuilder
+ * @domain: the translation domain to use for dgettext() calls
+ * 
+ * Sets the translation domain and uses dgettext() for translating the 
+ * property values marked as translatable from an interface description.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_builder_set_translation_domain (GtkBuilder   *builder,
+				    const gchar  *domain)
+{
+  GtkBuilderPrivate *priv;
+
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  g_free (priv->domain);
+  if (domain)
+    priv->domain = g_strdup (domain);
+}
+
+/**
+ * gtk_builder_signal_autoconnect:
+ * @buildable: a #GtkBuilder
+ *
+ * Return value: 
+ *
+ * Since: 2.10
+ **/
+void
+gtk_builder_signal_autoconnect (GtkBuilder *builder)
+{
+  GtkBuilderPrivate *priv;
+  GSList *l;
+  GObject *object;
+  GObject *other;
+  GModule *module;
+  GCallback func;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  if (!priv->signals)
+    return;
+
+  module = g_module_open (NULL, 0);
+
+  for (l = priv->signals; l; l = l->next)
+    {
+      SignalInfo *signal = (SignalInfo*)l->data;
+      GConnectFlags flags = 0;
+
+      g_assert (signal != NULL);
+      g_assert (signal->name != NULL);
+
+      object = g_hash_table_lookup (priv->objects, signal->object_name);
+      g_assert (object != NULL);
+      
+      if (signal->object)
+	other = g_hash_table_lookup (priv->objects, signal->object);
+      else
+	other = NULL;
+
+      if (!g_module_symbol (module, signal->handler, (gpointer)&func))
+	{
+	  g_warning ("could not find signal handler '%s'",
+		     signal->handler);
+	  continue;
+	}
+
+      if (signal->after)
+	flags |= G_CONNECT_AFTER;
+
+      if (signal->object)
+	flags |= G_CONNECT_SWAPPED;
+
+      g_signal_connect_data (object, signal->name, func, other, NULL, flags);
+    }
+}
+
+/**
+ * GtkBuilderConnectFunc:
+ * @builder: the GtkBuilder object
+ * @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 glade_xml_signal_connect_full and glade_xml_signal_autoconnect_full
+ * functions.  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.10
+ */
+
+/**
+ * gtk_builder_signal_autoconnect_full
+ * @self: the GtkBuilder object.
+ * @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.10
+ */
+void
+gtk_builder_signal_autoconnect_full (GtkBuilder            *builder,
+				     GtkBuilderConnectFunc  func,
+				     gpointer               data)
+{
+  GtkBuilderPrivate *priv;
+  GSList *l;
+  GObject *object;
+  GObject *other;
+
+  priv = GTK_BUILDER_GET_PRIVATE (builder);
+  if (!priv->signals)
+    return;
+
+  for (l = 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 (priv->objects, signal->object_name);
+      g_assert (object != NULL);
+      
+      if (signal->object)
+	other = g_hash_table_lookup (priv->objects, signal->object);
+      else
+	other = NULL;
+
+      func (builder, signal->handler, object, signal->name, other,
+	    signal->after, data);
+    }
+}
+
+#define __GTK_BUILDER_C__
+#include "gtkaliasdef.c"
--- gtk/gtkbuilder.h	(.../tags/start)	(revision 0)
+++ gtk/gtkbuilder.h	(.../trunk)	(revision 313)
@@ -0,0 +1,94 @@
+/* gtkbuilder.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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))
+
+typedef struct _GtkBuilder        GtkBuilder;
+typedef struct _GtkBuilderClass   GtkBuilderClass;
+
+struct _GtkBuilder
+{
+  GObject parent;
+};
+
+struct _GtkBuilderClass
+{
+  GObjectClass        parent_class;
+  
+
+  void (*finish) (GtkBuilder *builder);
+
+  /* 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);
+
+void        gtk_builder_parse_filename     (GtkBuilder   *builder,
+					    const gchar  *filename,
+					    GError      **error);
+void        gtk_builder_parse_buffer       (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_signal_autoconnect (GtkBuilder   *builder);
+void        gtk_builder_signal_autoconnect_full (GtkBuilder *builder,
+						 GtkBuilderConnectFunc func,
+						 gpointer user_data);
+void        gtk_builder_set_translation_domain (GtkBuilder   *builder,
+                                                const gchar  *domain);
+
+const gchar*   gtk_builder_get_object_name (GObject *object);
+
+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);
+
+G_END_DECLS
+
+#endif /* __GTK_BUILDER_H__ */
--- gtk/gtk.h	(.../tags/start)	(revision 313)
+++ gtk/gtk.h	(.../trunk)	(revision 313)
@@ -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>
--- gtk/gtkbuilderparser.c	(.../tags/start)	(revision 0)
+++ gtk/gtkbuilderparser.c	(.../trunk)	(revision 313)
@@ -0,0 +1,627 @@
+/* gtkbuilderparser.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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 <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"
+
+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;
+}
+
+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"))
+	object_class = g_strdup (values[i]);
+      else if (!strcmp (names[i], "id"))
+	object_id = g_strdup (values[i]);
+      else if (!strcmp (names[i], "constructor"))
+	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 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"))
+	info->type = g_strdup (values[i]);
+      else if (!strcmp (names[i], "internal-child"))
+	info->internal_child = g_strdup (values[i]);
+    }
+  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"))
+	name = g_strdelimit (g_strdup (values[i]), "_", '-');
+      else if (!strcmp (names[i], "translatable"))
+	translatable = !strcmp (values[i], "yes");
+    }
+
+  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"))
+	name = g_strdup (values[i]);
+      else if (!strcmp (names[i], "handler"))
+	handler = g_strdup (values[i]);
+      else if (!strcmp (names[i], "object"))
+	object = g_strdup (values[i]);
+      else if (!strcmp (names[i], "after"))
+	after = !strcmp (values[i], "yes");
+    }
+
+  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 (object != NULL);
+  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))
+	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"))
+    {
+      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"))
+    {
+      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"))
+    {
+      parse_property (data, element_name, names, values, error);
+    }
+  else if (!strcmp (element_name, "signal"))
+    {
+      parse_signal (data, element_name, names, values, error);
+    }
+  else if (!strcmp (element_name, "glade-interface"))
+    {
+      int i;
+      
+      for (i = 0; names[i] != NULL; i++)
+	{
+	  if (!strcmp (names[i], "domain") && !data->domain)
+	    {
+	      data->domain = g_strdup (values[i]);
+	      break;
+	    }
+	}
+    }
+  else if (!strcmp (element_name, "placeholder"))
+    {
+    }
+  else
+    {
+      CommonInfo* info = state_peek_info (data, CommonInfo);
+      
+      if (!info)
+	goto unhandled;
+      
+      if (!strcmp (info->tag.name, "object") ||
+	  !strcmp (info->tag.name, "child"))
+	{
+	  GMarkupParser parser;
+	  SubParser *subparser;
+	  gpointer *subparser_data;
+	  GObject *object;
+	  GObject *child;
+
+	  if (!strcmp (info->tag.name, "object"))
+	    {
+	      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"))
+	    {
+	      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 = 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;
+  
+#ifdef GTK_ENABLE_DEBUG
+  if (gtk_debug_flags & GTK_DEBUG_BUILDER)
+    g_print ("</%s>\n", element_name);
+#endif
+  
+  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))
+	{
+	  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);
+	  g_slice_free (SubParser, data->subparser);
+	  data->subparser = NULL;
+	}
+      return;
+    }
+
+  if (!strcmp (element_name, "object"))
+    {
+      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;
+
+      free_object_info (object_info);
+    }
+  else if (!strcmp (element_name, "property"))
+    {
+      PropertyInfo *prop_info = state_pop_info (data, PropertyInfo);
+      CommonInfo *info = state_peek_info (data, CommonInfo);
+
+      /* Normal properties */
+      if (!strcmp (info->tag.name, "object"))
+	{
+	  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"))
+    {
+      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"))
+    {
+      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, "glade-interface"))
+    {
+    }
+  else if (!strcmp (element_name, "placeholder"))
+    {
+    }
+}
+
+/* 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"))
+    {
+      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;
+
+  data = g_new0 (ParserData, 1);
+  data->builder = builder;
+  data->filename = filename;
+  
+  g_object_get (builder, "domain", &data->domain, NULL);
+  
+  data->ctx = g_markup_parse_context_new (&parser, 0, data, NULL);
+  
+  if (g_markup_parse_context_parse (data->ctx, buffer, length, error))
+    {
+      g_object_set (data->builder, "domain", data->domain, NULL);
+      _gtk_builder_finish (builder);
+    }
+
+  g_markup_parse_context_free (data->ctx);
+  
+  g_free (data->domain);
+  g_free (data);
+}
--- gtk/gtkbuildable.c	(.../tags/start)	(revision 0)
+++ gtk/gtkbuildable.c	(.../trunk)	(revision 313)
@@ -0,0 +1,292 @@
+/* gtkbuildable.c
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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)
+    {
+      static const GTypeInfo buildable_info =
+      {
+	sizeof (GtkBuildableIface) /* class_size */
+      };
+
+      buildable_type =
+	g_type_register_static (G_TYPE_INTERFACE, I_("GtkBuildable"),
+				&buildable_info, 0);
+
+    }
+
+  return buildable_type;
+}
+
+/**
+ * gtk_buildable_set_name:
+ * @buildable: A #GtkBuildable
+ * @name: name to set
+ *
+ * Sets the name of the builder, it's mainly used to synchronize the name
+ * if the object already has it's own concept of name. #GtkWidget for instance,
+ * implements this and calls gtk_widget_set_name internally.
+ * 
+ **/
+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);
+  
+  g_object_set_data_full (G_OBJECT (buildable),
+			  "gtk-buildable-name",
+			  g_strdup (name),
+			  g_free);
+}
+
+/**
+ * gtk_buildable_get_name:
+ * @buildable: A #GtkBuildable
+ *
+ * Returns: the buildable name or %NULL if the object was not
+ *          constructed by a #GtkBuilder.
+ **/
+const gchar *
+gtk_buildable_get_name (GtkBuildable *buildable)
+{
+  return gtk_builder_get_object_name (G_OBJECT (buildable));
+}
+
+/**
+ * gtk_buildable_add:
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @child: child to add
+ * @type: kind of child or #NULL
+ *
+ * Adds a child to a buildable. type is an optional string
+ * describing how the child should be added. #GtkNotebook uses the
+ * type to distinguish between page labels and normal children.
+ **/
+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 != NULL);
+  g_return_if_fail (iface->add != NULL);
+  
+  (* iface->add) (buildable, builder, child, type);
+}
+
+/**
+ * gtk_buildable_set_property:
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @name: name of property
+ * @value: value of property
+ *
+ * This method is called for each normal property that is set.
+ * It's optional to implement, g_object_set_property is used as
+ * a fallback if it's not implemented.
+ * 
+ **/
+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);
+
+  g_return_if_fail (iface != NULL);
+
+  if (iface->set_property)
+    (* iface->set_property) (buildable, builder, name, value);
+  else
+    g_object_set_property (G_OBJECT (buildable), name, value);
+}
+
+/**
+ * gtk_buildable_construct_child
+ * @buildable: A #GtkBuildable
+ * @builder: #GtkBuilder used to construct this object
+ * @name: name of child to construct
+ *
+ * This method is used to construct children specified by
+ * the constructor tag in the object. It's used by #GtkUIManager
+ * to reference to a widget created in a <ui> tag which is outside
+ * of the normal hierarchy.
+ **/
+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 != NULL, NULL);
+  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: #GtkBuilder used to construct this object
+ * @child: if a child tag, the child instance, otherwise %NULL
+ * @tagname: name of tag
+ * @parser: a #GMarkupParser structure
+ * @data: user data that will be passed in to parser functions
+ *
+ * This method can be implemented if the object wants to implement
+ * a custom tag not present in the GtkBuilder.
+ * Keyboard accelerators for #GtkWidget is implemented using this
+ * custom tag.
+ * If child is not %NULL the tag is found under <child> tag and child
+ * will represent the child itself. If it's %NULL the tag is present
+ * under the <object> tag.
+ *
+ * Returns: %TRUE if a object has a custom implementation, %FALSE
+ *          if it doesn't.
+ **/
+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 != NULL, FALSE);
+  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: if a child tag, the child instance, otherwise %NULL
+ * @tagname: name of tag
+ * @data: user data that will be passed in to parser functions
+ *
+ **/
+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);
+
+  g_return_if_fail (iface != NULL);
+  g_return_if_fail (iface->custom_tag_end != NULL);
+
+  (* iface->custom_tag_end) (buildable, builder, child, tagname, data);
+}
+
+/**
+ * gtk_buildable_get_internal_child
+ * @buildable: A #GtkBuildable
+ * @builder: A #GtkBuilder instance
+ * @childname: name of child
+ *
+ * This method can be implemented to map an attribute name to a child
+ * which is not part of the ordinary hierarchy. It's mainly used by
+ * #GtkDialog to be able to access widgets such as action_area.
+ * 
+ **/
+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);
+
+  g_return_val_if_fail (iface != NULL, NULL);
+  
+  if (!iface->get_internal_child)
+    return NULL;
+
+  return (* iface->get_internal_child) (buildable, builder, childname);
+}
+
+#define __GTK_BUILDABLE_C__
+#include "gtkaliasdef.c"
--- gtk/gtkbuildable.h	(.../tags/start)	(revision 0)
+++ gtk/gtkbuildable.h	(.../trunk)	(revision 313)
@@ -0,0 +1,106 @@
+/* gtkbuildable.h
+ * Copyright (C) 2006 Async Open Source
+ *
+ * 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);
+  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);
+  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);
+GObject * gtk_buildable_get_internal_child    (GtkBuildable        *buildable,
+					       GtkBuilder          *builder,
+					       const gchar         *childname);
+						  
+G_END_DECLS
+
+#endif /* __GTK_BUILDABLE_H__ */
