Index: gtk/gtktypeutils.h
===================================================================
--- gtk/gtktypeutils.h	(revisão 18022)
+++ gtk/gtktypeutils.h	(cópia de trabalho)
@@ -229,8 +229,15 @@
 
 #endif /* GTK_DISABLE_DEPRECATED */
 
+typedef GType (*GTypeGetFunc) (void);
+
 gpointer	gtk_type_class	(GtkType	 type);
 
+void            _gtk_type_table_init     (void);
+void            gtk_type_register        (const gchar  *name,
+                                          GTypeGetFunc  func);
+GType           gtk_registered_type_from_name (const gchar  *name);
+
 #ifndef GTK_DISABLE_DEPRECATED
 
 GtkType		gtk_type_unique	(GtkType	   parent_type,
Index: gtk/gtktypeutils.c
===================================================================
--- gtk/gtktypeutils.c	(revisão 18022)
+++ gtk/gtktypeutils.c	(cópia de trabalho)
@@ -28,10 +28,13 @@
 
 #include <config.h>
 #include <string.h> /* strcmp */
+#include <ctype.h> /* toupper */
+#include <stdlib.h> /* strtol, strtoul */
 
 #include "gtktypeutils.h"
 #include "gtkobject.h"
 #include "gtkintl.h"
+#include "gtkuimanager.h"
 #include "gtkalias.h"
 
 
@@ -199,6 +202,107 @@ gtk_type_flags_find_value (GtkType      
   return value;
 }
 
+static GHashTable* type_table;
+
+/*
+ * 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
+ *
+ */
+static GType
+_gtk_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])) {
+      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;
+}
+
+/**
+ * gtk_registered_type_from_name
+ * @name: a type name
+ *
+ * Like g_type_from_name, but takes into account the types registered
+ * using the gtk_type_register function.
+ *
+ * Since: 2.12
+ */
+GType
+gtk_registered_type_from_name (const gchar *name)
+{
+  GType gtype;
+  GTypeGetFunc func;
+  
+  gtype = g_type_from_name (name);
+  if (gtype != G_TYPE_INVALID)
+    return gtype;
+
+  func = g_hash_table_lookup (type_table, name);
+  if (func)
+    gtype = func ();
+  if (gtype != G_TYPE_INVALID)
+    return gtype;
+
+  return _gtk_resolve_type_lazily (name);
+}
+
+/**
+ * gtk_type_register
+ * @name: a type name
+ * @func: a #GTypeGetFunc
+ *
+ * Registers a type registration function for a type name.
+ * This is used by GtkBuilder to be able to register a type on demand.
+ *
+ * You can call this in a your library to map a type name to a function
+ * which will register a GType, it's useful for libraries defining
+ * #GtkBuildable types.
+ *
+ * Since: 2.12
+ */
+void
+gtk_type_register (const gchar *name, GTypeGetFunc func)
+{
+  g_return_if_fail (g_hash_table_lookup (type_table, name) == NULL);
+
+  g_hash_table_insert (type_table, g_strdup (name), func);
+}
+
+void
+_gtk_type_table_init (void)
+{
+  type_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+  g_hash_table_insert (type_table, "GtkUIManager", gtk_ui_manager_get_type);
+}
 
 #define __GTK_TYPE_UTILS_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkmain.c
===================================================================
--- gtk/gtkmain.c	(revisão 18022)
+++ 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,6 +659,7 @@ do_post_parse_initialization (int    *ar
   }
 
   gtk_type_init (0);
+  _gtk_type_table_init ();
   _gtk_accel_map_init ();  
   _gtk_rc_init ();
 
Index: tests/typeutilstest.c
===================================================================
--- tests/typeutilstest.c	(revisão 0)
+++ tests/typeutilstest.c	(revisão 0)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 Johan Dahlin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+
+int main(int   argc,
+         char *argv[])
+{
+  int i;
+  char *names[] = {
+    "GdkPixbuf", "GtkAboutDialog", "GtkAccelLabel", "GtkAction",
+    "GtkActionGroup", "GtkAdjustment", "GtkAlignment", "GtkArrow",
+    "GtkAspectFrame", "GtkAssistant", "GtkButton", "GtkCalendar",
+    "GtkCheckButton", "GtkCellRenderer", "GtkCellRendererText", "GtkCellView",
+    "GtkColorButton", "GtkColorSelection", "GtkColorSelectionDialog",
+    "GtkComboBox", "GtkComboBoxEntry", "GtkCurve", "GtkDialog",
+    "GtkDrawingArea", "GtkEventBox", "GtkEntry", "GtkEntryCompletion",
+    "GtkFileChooser", "GtkFileChooserDialog", "GtkFileChooserButton",
+    "GtkFileSelection", "GtkFixed", "GtkFontSelection",
+    "GtkFontSelectionDialog", "GtkFrame", "GtkExpander", "GtkFontButton",
+    "GtkGammaCurve", "GtkHandleBox", "GtkHButtonBox", "GtkHBox", "GtkHPaned",
+    "GtkHRuler", "GtkHScale", "GtkHScrollbar", "GtkHSeparator", "GtkIconView",
+    "GtkImage", "GtkInputDialog", "GtkLabel", "GtkLayout", "GtkLinkButton",
+    "GtkListStore", "GtkMenu", "GtkMenuBar", "GtkMessageDialog", "GtkNotebook",
+    "GtkProgressBar", "GtkRadioAction", "GtkRadioButton",
+    "GtkRecentChooserDialog", "GtkSizeGroup", "GtkScrolledWindow",
+    "GtkSpinButton", "GtkStatusbar", "GtkTextBuffer", "GtkTextView",
+    "GtkToggleAction", "GtkToggleButton", "GtkToolbar", "GtkTooltips",
+    "GtkTreeModelFilter", "GtkTreeModelSort", "GtkTreeStore", "GtkTreeView",
+    "GtkTreeViewColumn", "GtkTable", "GtkVBox", "GtkVButtonBox",
+    "GtkVScrollbar", "GtkVSeparator", "GtkViewport", "GtkVRuler", "GtkVPaned",
+    "GtkVScale", "GtkWindow", "GtkUIManager", NULL };
+
+  gtk_init (&argc, &argv);
+
+  for (i = 0; i < g_strv_length (names); i++) {
+    GType type = gtk_registered_type_from_name (names[i]);
+    g_assert (type != G_TYPE_INVALID);
+
+    if (strcmp (g_type_name (type), names[i]) != 0) {
+      g_print("%s != %s\n", g_type_name (type), names[i]);
+      return 1;
+    }
+  }
+ 
+  return(0);
+}
