--- /work/glib/glib-2.11.0orig/./gobject/gtype.c	2006-04-23 07:21:08.000000000 +0300
+++ ./gobject/gtype.c	2006-05-19 16:44:28.000000000 +0300
@@ -158,6 +158,7 @@ static void                             
                                                                          TypeNode               *node);
 static gboolean				type_node_is_a_L		(TypeNode		*node,
 									 TypeNode		*iface_node);
+static GType				type_from_name_L		(const gchar *name);
 
 
 /* --- enumeration --- */
@@ -603,11 +604,6 @@ check_type_name_I (const gchar *type_nam
       g_warning ("type name `%s' contains invalid characters", type_name);
       return FALSE;
     }
-  if (g_type_from_name (type_name))
-    {
-      g_warning ("cannot register existing type `%s'", type_name);
-      return FALSE;
-    }
   
   return TRUE;
 }
@@ -828,7 +824,9 @@ find_conforming_child_type_L (TypeNode *
 
 static gboolean
 check_add_interface_L (GType instance_type,
-		       GType iface_type)
+		       GType iface_type,
+		       const GInterfaceInfo *info,
+		       GTypePlugin *plugin)
 {
   TypeNode *node = lookup_type_node_I (instance_type);
   TypeNode *iface = lookup_type_node_I (iface_type);
@@ -871,6 +869,25 @@ check_add_interface_L (GType instance_ty
        */
       return TRUE;
     }
+  if (entry)
+    {
+      IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
+      if (iholder)
+	{
+	  /* the interface has already been added, so skip the warning if iholder
+	   * details are the same
+	   */
+	  if (iholder->info && info)
+	    {
+	      if (iholder->info->interface_init     == info->interface_init &&
+		  iholder->info->interface_finalize == info->interface_finalize &&
+		  iholder->info->interface_data     == info->interface_data)
+		return FALSE;
+	    }
+	  else if (!iholder->info && !info && iholder->plugin == plugin)
+	    return FALSE;
+	}
+    }
   /* check whether one of our children already conforms (or whether the interface
    * got added to this node already)
    */
@@ -1044,6 +1061,210 @@ type_data_make_W (TypeNode              
   g_assert (node->data->common.value_table != NULL); /* paranoid */
 }
 
+static gboolean
+type_data_match_I (const TypeNode        *node,
+		   const GTypeInfo       *info,
+		   const GTypeValueTable *value_table)
+{
+  gboolean match;
+  const TypeData *data;
+  const GTypeValueTable *vtable1, *vtable2;
+  const GTypeValueTable zero_vtable = { NULL, };
+
+  if (!node || !node->data)
+    return FALSE;
+
+  match = TRUE;
+
+  data = node->data;
+
+  if (node->is_instantiatable)
+    {
+      match = (data->instance.class_size          == info->class_size    ) ? match : FALSE;
+      match = (data->instance.class_init_base     == info->base_init     ) ? match : FALSE;
+      match = (data->instance.class_finalize_base == info->base_finalize ) ? match : FALSE;
+      match = (data->instance.class_init          == info->class_init    ) ? match : FALSE;
+      match = (data->instance.class_finalize      == info->class_finalize) ? match : FALSE;
+      match = (data->instance.class_data          == info->class_data    ) ? match : FALSE;
+      match = (data->instance.instance_size       == info->instance_size ) ? match : FALSE;
+      match = (data->instance.instance_init       == info->instance_init ) ? match : FALSE;
+    }
+  else if (node->is_classed)
+    {
+      match = (data->class.class_size             == info->class_size    ) ? match : FALSE;
+      match = (data->class.class_init_base        == info->base_init     ) ? match : FALSE;
+      match = (data->class.class_finalize_base    == info->base_finalize ) ? match : FALSE;
+      match = (data->class.class_init             == info->class_init    ) ? match : FALSE;
+      match = (data->class.class_finalize         == info->class_finalize) ? match : FALSE;
+      match = (data->class.class_data             == info->class_data    ) ? match : FALSE;
+    }
+  else if (NODE_IS_IFACE (node))
+    {
+      match = (data->iface.vtable_size            == info->class_size    ) ? match : FALSE;
+      match = (data->iface.vtable_init_base       == info->base_init     ) ? match : FALSE;
+      match = (data->iface.vtable_finalize_base   == info->base_finalize ) ? match : FALSE;
+      match = (data->iface.dflt_init              == info->class_init    ) ? match : FALSE;
+      match = (data->iface.dflt_finalize          == info->class_finalize) ? match : FALSE;
+      match = (data->iface.dflt_data              == info->class_data    ) ? match : FALSE;
+    }
+
+  vtable1 = value_table;
+
+  if (!vtable1)
+    {
+      TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
+      if (pnode)
+	vtable1 = pnode->data->common.value_table;
+      else
+	vtable1 = &zero_vtable;
+    }
+
+  vtable2 = data->common.value_table;
+
+  if (vtable1 != vtable2)
+    {
+      gchar empty_string[1] = { 0, }, *str1, *str2;
+      if (!vtable1 || !vtable2)
+        return FALSE;
+      match = (vtable1->value_init         == vtable2->value_init        ) ? match : FALSE;
+      match = (vtable1->value_free         == vtable2->value_free        ) ? match : FALSE;
+      match = (vtable1->value_copy         == vtable2->value_copy        ) ? match : FALSE;
+      match = (vtable1->value_peek_pointer == vtable2->value_peek_pointer) ? match : FALSE;
+      match = (vtable1->collect_value      == vtable2->collect_value     ) ? match : FALSE;
+      match = (vtable1->lcopy_value        == vtable2->lcopy_value       ) ? match : FALSE;
+      str1 = vtable1->collect_format ? vtable1->collect_format : empty_string;
+      str2 = vtable2->collect_format ? vtable2->collect_format : empty_string;
+      match = (strcmp(str1,str2) == 0) ? match : FALSE;
+      str1 = vtable1->lcopy_format ? vtable1->lcopy_format : empty_string;
+      str2 = vtable2->lcopy_format ? vtable2->lcopy_format : empty_string;
+      match = (strcmp(str1,str2) == 0) ? match : FALSE;
+    }
+
+  return match;
+}
+
+static GType
+type_already_registered_fundamental_L (GType                       type_id,
+				       const gchar                *type_name,
+				       const GTypeInfo            *info,
+				       const GTypeFundamentalInfo *finfo,
+				       GTypeFlags		   flags)
+{
+  GType type;
+  TypeNode *node;
+  guint dflags;
+  const GTypeValueTable *value_table;
+
+  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_return_val_if_fail (type_id > 0, 0);
+  g_return_val_if_fail (type_name != NULL, 0);
+  g_return_val_if_fail (info != NULL, 0);
+  g_return_val_if_fail (finfo != NULL, 0);
+
+  type = type_from_name_L (type_name);
+  if (type == 0 || type != type_id || type > G_TYPE_FUNDAMENTAL_MAX)
+    return 0;
+
+  node = lookup_type_node_I (type);
+  if (!node || node->plugin)
+    return 0;
+
+  const GTypeFundamentalInfo *node_finfo;
+  node_finfo = type_node_fundamental_info_I (node);
+  if ((finfo->type_flags & TYPE_FUNDAMENTAL_FLAG_MASK) != node_finfo->type_flags)
+    return 0;
+
+  dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
+  if ((flags & ~TYPE_FLAG_MASK) == 0 && (dflags & flags) != flags)
+    return 0;
+
+  if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
+    {
+      value_table = check_value_table_I (type_name, info->value_table) ? info->value_table : NULL;
+      if (!type_data_match_I (node, info, value_table))
+	return 0;
+    }
+
+  return type;
+}
+
+static GType
+type_already_registered_static_L (GType            parent_type,
+				  const gchar     *type_name,
+				  const GTypeInfo *info,
+				  GTypeFlags	   flags)
+{
+  GType type, ptype;
+  TypeNode *node, *pnode;
+  guint dflags;
+  const GTypeValueTable *value_table;
+
+  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_return_val_if_fail (parent_type > 0, 0);
+  g_return_val_if_fail (type_name != NULL, 0);
+  g_return_val_if_fail (info != NULL, 0);
+
+  type = type_from_name_L (type_name);
+  if (type == 0)
+    return 0;
+
+  ptype = g_type_parent (type);
+  if (ptype != parent_type)
+    return 0;
+
+  node = lookup_type_node_I (type);
+  if (!node || !node->data || node->plugin)
+    return 0;
+
+  pnode = lookup_type_node_I (parent_type);
+  if (!check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
+    return 0;
+
+  dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
+  if ((flags & ~TYPE_FLAG_MASK) == 0 && (dflags & flags) != flags)
+    return 0;
+
+  value_table = check_value_table_I (type_name, info->value_table) ? info->value_table : NULL;
+  if (!type_data_match_I (node, info, value_table))
+    return 0;
+
+  return type;
+}
+
+static GType
+type_already_registered_dynamic_L (GType        parent_type,
+				   const gchar *type_name,
+				   GTypePlugin *plugin,
+				   GTypeFlags   flags)
+{
+  GType type, ptype;
+  TypeNode *node;
+  guint dflags;
+
+  g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
+  g_return_val_if_fail (parent_type > 0, 0);
+  g_return_val_if_fail (type_name != NULL, 0);
+  g_return_val_if_fail (plugin != NULL, 0);
+
+  type = type_from_name_L (type_name);
+  if (type == 0)
+    return 0;
+
+  ptype = g_type_parent (type);
+  if (ptype != parent_type)
+    return 0;
+
+  node = lookup_type_node_I (type);
+  if (!node || node->plugin != plugin)
+    return 0;
+
+  dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
+  if ((flags & ~TYPE_FLAG_MASK) == 0 && (dflags & flags) != flags)
+    return 0;
+
+  return type;
+}
+
 static inline void
 type_data_ref_Wm (TypeNode *node)
 {
@@ -2158,6 +2379,7 @@ g_type_register_fundamental (GType      
 			     const GTypeFundamentalInfo *finfo,
 			     GTypeFlags			 flags)
 {
+  GType type;
   TypeNode *node;
   
   g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
@@ -2183,15 +2405,24 @@ g_type_register_fundamental (GType      
 		 type_name);
       return 0;
     }
-  if (lookup_type_node_I (type_id))
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  if (type_from_name_L (type_name))
+    {
+      type = type_already_registered_fundamental_L (type_id, type_name, info, finfo, flags);
+      G_WRITE_UNLOCK (&type_rw_lock);
+      if (type == 0)
+	g_warning ("cannot register existing type `%s'", type_name);
+      return type;
+    }
+  else if (lookup_type_node_I (type_id))
     {
+      G_WRITE_UNLOCK (&type_rw_lock);
       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
 		 type_descriptive_name_I (type_id),
 		 type_name);
       return 0;
     }
-  
-  G_WRITE_LOCK (&type_rw_lock);
   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
   type_add_flags_W (node, flags);
   
@@ -2254,6 +2485,14 @@ g_type_register_static (GType           
   
   pnode = lookup_type_node_I (parent_type);
   G_WRITE_LOCK (&type_rw_lock);
+  if (type_from_name_L (type_name))
+    {
+      type = type_already_registered_static_L (parent_type, type_name, info, flags);
+      G_WRITE_UNLOCK (&type_rw_lock);
+      if (type == 0)
+	g_warning ("cannot register existing type `%s'", type_name);
+      return type;
+    }
   type_data_ref_Wm (pnode);
   if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
     {
@@ -2288,6 +2527,14 @@ g_type_register_dynamic (GType        pa
     return 0;
   
   G_WRITE_LOCK (&type_rw_lock);
+  if (type_from_name_L (type_name))
+    {
+      type = type_already_registered_dynamic_L (parent_type, type_name, plugin, flags);
+      G_WRITE_UNLOCK (&type_rw_lock);
+      if (type == 0)
+	g_warning ("cannot register existing type `%s'", type_name);
+      return type;
+    }
   pnode = lookup_type_node_I (parent_type);
   node = type_node_new_W (pnode, type_name, plugin);
   type_add_flags_W (node, flags);
@@ -2305,9 +2552,10 @@ g_type_add_interface_static (GType      
   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
+  g_return_if_fail (info != NULL);
   
   G_WRITE_LOCK (&type_rw_lock);
-  if (check_add_interface_L (instance_type, interface_type))
+  if (check_add_interface_L (instance_type, interface_type, info, NULL))
     {
       TypeNode *node = lookup_type_node_I (instance_type);
       TypeNode *iface = lookup_type_node_I (interface_type);
@@ -2334,7 +2582,7 @@ g_type_add_interface_dynamic (GType     
     return;
   
   G_WRITE_LOCK (&type_rw_lock);
-  if (check_add_interface_L (instance_type, interface_type))
+  if (check_add_interface_L (instance_type, interface_type, NULL, plugin))
     {
       TypeNode *iface = lookup_type_node_I (interface_type);
       
@@ -2660,6 +2908,21 @@ g_type_from_name (const gchar *name)
   return type;
 }
 
+static GType
+type_from_name_L (const gchar *name)
+{
+  GType type = 0;
+  GQuark quark;
+  
+  g_return_val_if_fail (name != NULL, 0);
+  
+  quark = g_quark_try_string (name);
+  if (quark)
+    type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));
+  
+  return type;
+}
+
 GType
 g_type_parent (GType type)
 {
