? myauto.sh
? doc/libglade-docs.sgml
? doc/version.xml
? glade/glade-parser.c.backup
? macros/codeset.m4
? macros/gettext.m4
? macros/glibc21.m4
? macros/iconv.m4
? macros/lcmessage.m4
? macros/progtest.m4
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libglade/ChangeLog,v
retrieving revision 1.329
diff -u -p -r1.329 ChangeLog
--- ChangeLog	29 Nov 2004 11:05:16 -0000	1.329
+++ ChangeLog	2 Jan 2005 22:14:40 -0000
@@ -1,3 +1,19 @@
+2004-12-21  Tristan Van Berkom <tvb@cvs.gnome.org>
+	* glade-init.c: Fix for applications to load properly under win32
+	  (Ivan Wong <email@ivanwong.info>)
+
+	* glade-parser.[ch]: 
+	  - Implement loading of glade files for glade-3 
+	    (Ivan Wong <email@ivanwong.info>)
+	  - Fine grained error handling on dump (Ivan and Myself)
+	
+	* glade-xml.c: Non widget fix (This implements non-widgets cleanly
+	  but does not change function signatures and variable names library wide
+	  from "GtkWidget *widget" to "GObject *object").
+
+	* glade-private.h,glade-xml.c: Implementation of g_module_lookup for
+	  signal handler user_data arguments.
+	
 2004-11-29  James Henstridge  <james@jamesh.id.au>
 
 	* configure.in: require ATK 1.9.0
Index: doc/tmpl/glade-parser.sgml
===================================================================
RCS file: /cvs/gnome/libglade/doc/tmpl/glade-parser.sgml,v
retrieving revision 1.5
diff -u -p -r1.5 glade-parser.sgml
--- doc/tmpl/glade-parser.sgml	26 Apr 2002 14:55:30 -0000	1.5
+++ doc/tmpl/glade-parser.sgml	2 Jan 2005 22:14:40 -0000
@@ -66,14 +66,6 @@ these functions and structures.
 @child: 
 @internal_child: 
 
-<!-- ##### STRUCT GladeProperty ##### -->
-<para>
-
-</para>
-
-@name: 
-@value: 
-
 <!-- ##### STRUCT GladeSignalInfo ##### -->
 <para>
 
@@ -83,6 +75,7 @@ these functions and structures.
 @handler: 
 @object: 
 @after: 
+@lookup: 
 
 <!-- ##### STRUCT GladeAccelInfo ##### -->
 <para>
Index: doc/tmpl/libglade-unused.sgml
===================================================================
RCS file: /cvs/gnome/libglade/doc/tmpl/libglade-unused.sgml,v
retrieving revision 1.16
diff -u -p -r1.16 libglade-unused.sgml
--- doc/tmpl/libglade-unused.sgml	7 Feb 2002 05:40:02 -0000	1.16
+++ doc/tmpl/libglade-unused.sgml	2 Jan 2005 22:14:40 -0000
@@ -107,6 +107,14 @@ Libglade Initialisation
 @name: 
 @value: 
 
+<!-- ##### STRUCT GladeProperty ##### -->
+<para>
+
+</para>
+
+@name: 
+@value: 
+
 <!-- ##### STRUCT GladeSignalData ##### -->
 <para>
 
Index: glade/glade-init.c
===================================================================
RCS file: /cvs/gnome/libglade/glade/glade-init.c,v
retrieving revision 1.19
diff -u -p -r1.19 glade-init.c
--- glade/glade-init.c	19 Aug 2002 13:39:23 -0000	1.19
+++ glade/glade-init.c	2 Jan 2005 22:14:40 -0000
@@ -100,7 +100,13 @@ get_module_path (void)
     if (exe_prefix)
 	default_dir = g_build_filename (exe_prefix, "lib", "libglade", "2.0", NULL);
     else
-	default_dir = g_build_filename (GLADE_LIBDIR, "libglade", "2.0", NULL);
+#ifndef G_OS_WIN32
+        default_dir = g_build_filename (GLADE_LIBDIR, "libglade", "2.0", NULL);
+#else
+        default_dir = g_win32_get_package_installation_subdirectory (NULL,
+                                                                     "libglade-2.0-0.dll",
+                                                                     "/lib/libglade/2.0");
+#endif
     
     module_path = g_strconcat (module_path_env ? module_path_env : "",
 			       module_path_env ? G_SEARCHPATH_SEPARATOR_S : "",
Index: glade/glade-parser.c
===================================================================
RCS file: /cvs/gnome/libglade/glade/glade-parser.c,v
retrieving revision 1.32
diff -u -p -r1.32 glade-parser.c
--- glade/glade-parser.c	11 Nov 2004 08:46:29 -0000	1.32
+++ glade/glade-parser.c	2 Jan 2005 22:14:40 -0000
@@ -1,3 +1,4 @@
+
 /* -*- Mode: C; c-basic-offset: 4 -*-
  * libglade - a library for building interfaces from XML files at runtime
  * Copyright (C) 1998-2002  James Henstridge <james@daa.com.au>
@@ -24,8 +25,20 @@
 #endif
 
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#ifdef G_OS_WIN32
+#  include <io.h>
+#endif
 
 #ifdef ENABLE_NLS
 #  include <libintl.h>
@@ -39,6 +52,34 @@
 #include "glade-parser.h"
 #include "glade-private.h"
 
+#define GETTEXT_PACKAGE "libglade"
+#include <glib/gi18n-lib.h>
+
+#ifdef _MSC_VER
+#  define open     _open
+#  define fdopen   _fdopen
+#  define O_CREAT  _O_CREAT
+#  define O_TRUNC  _O_TRUNC
+#  define O_WRONLY _O_WRONLY
+#  define O_BINARY _O_BINARY
+#  define S_IRUSR  _S_IREAD
+#  define S_IWUSR  _S_IWRITE
+#endif
+
+#ifndef G_OS_WIN32
+#  define GLADE_CREATE_PERMS    (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#else
+#  define GLADE_CREATE_PERMS    (S_IRUSR|S_IWUSR)
+#endif
+
+
+/* O_BINARY useful on Cygwin */
+#ifndef O_BINARY
+#  define O_BINARY 0
+#endif
+extern FILE *fdopen (int, const char *);
+
+
 typedef enum {
     PARSER_START,
     PARSER_GLADE_INTERFACE,
@@ -183,14 +224,14 @@ flush_properties(GladeParseState *state)
     case PROP_WIDGET:
 	if (state->widget->properties)
 	    g_warning("we already read all the props for this key.  Leaking");
-	state->widget->properties = (GladeProperty *)state->props->data;
+	state->widget->properties = (GladePropInfo *)state->props->data;
 	state->widget->n_properties = state->props->len;
 	g_array_free(state->props, FALSE);
 	break;
     case PROP_ATK:
 	if (state->widget->atk_props)
 	    g_warning("we already read all the ATK props for this key.  Leaking");
-	state->widget->atk_props = (GladeProperty *)state->props->data;
+	state->widget->atk_props = (GladePropInfo *)state->props->data;
 	state->widget->n_atk_props = state->props->len;
 	g_array_free(state->props, FALSE);
 	break;
@@ -203,7 +244,7 @@ flush_properties(GladeParseState *state)
 						state->widget->n_children-1];
 	    if (info->properties)
 		g_warning("we already read all the child props for this key.  Leaking");
-	    info->properties = (GladeProperty *)state->props->data;
+	    info->properties = (GladePropInfo *)state->props->data;
 	    info->n_properties = state->props->len;
 	    g_array_free(state->props, FALSE);
 	}
@@ -327,6 +368,8 @@ handle_signal(GladeParseState *state, co
 	    info.handler = alloc_string(state->interface, attrs[i+1]);
 	else if (!strcmp(attrs[i], "after"))
 	    info.after = attrs[i+1][0] == 'y';
+	else if (!strcmp(attrs[i], "lookup"))
+	    info.lookup = attrs[i+1][0] == 'y';
 	else if (!strcmp(attrs[i], "object"))
 	    info.object = alloc_string(state->interface, attrs[i+1]);
 	else if (!strcmp(attrs[i], "last_modification_time"))
@@ -868,7 +911,7 @@ glade_parser_start_element(GladeParseSta
 static void
 glade_parser_end_element(GladeParseState *state, const xmlChar *name)
 {
-    GladeProperty prop;
+    GladePropInfo prop;
 
     GLADE_NOTE(PARSER, g_message("</%s> in state %s",
 				 name, state_names[state->state]));
@@ -911,7 +954,7 @@ glade_parser_end_element(GladeParseState
 	if (strcmp(name, "property") != 0)
 	    g_warning("should find </property> here.  Found </%s>", name);
 	if (!state->props)
-	    state->props = g_array_new(FALSE, FALSE, sizeof(GladeProperty));
+	    state->props = g_array_new(FALSE, FALSE, sizeof(GladePropInfo));
 	prop.name = state->prop_name;
  	if (state->translate_prop && state->content->str[0] != '\0') {
 	    if (state->context_prop) 
@@ -938,7 +981,7 @@ glade_parser_end_element(GladeParseState
 	if (strcmp(name, "atkproperty") != 0)
 	    g_warning("should find </atkproperty> here.  Found </%s>", name);
 	if (!state->props)
-	    state->props = g_array_new(FALSE, FALSE, sizeof(GladeProperty));
+	    state->props = g_array_new(FALSE, FALSE, sizeof(GladePropInfo));
 	prop.name = state->prop_name;
  	if (state->translate_prop && state->content->str[0] != '\0') {
 	    if (state->context_prop) 
@@ -1005,7 +1048,7 @@ glade_parser_end_element(GladeParseState
 	if (strcmp(name, "property") != 0)
 	    g_warning("should find </property> here.  Found </%s>", name);
 	if (!state->props)
-	    state->props = g_array_new(FALSE, FALSE, sizeof(GladeProperty));
+	    state->props = g_array_new(FALSE, FALSE, sizeof(GladePropInfo));
 	prop.name = state->prop_name;
  	if (state->translate_prop && state->content->str[0] != '\0') {
 	    if (state->context_prop) 
@@ -1322,6 +1365,8 @@ dump_widget(xmlNode *parent, GladeWidget
 	xmlSetProp(node, "handler", info->signals[i].handler);
 	if (info->signals[i].after)
 	    xmlSetProp(node, "after", "yes");
+	if (info->signals[i].lookup)
+	    xmlSetProp(node, "lookup", "yes");
 	if (info->signals[i].object)
 	    xmlSetProp(node, "object", info->signals[i].object);
 	xmlAddChild(widget, node);
@@ -1343,7 +1388,7 @@ dump_widget(xmlNode *parent, GladeWidget
     }
 
     for (i = 0; i < info->n_children; i++) {
-	xmlNode *child;
+	xmlNode *child, *packing;
 	GladeChildInfo *childinfo = &info->children[i];
 	gint k;
 
@@ -1357,22 +1402,36 @@ dump_widget(xmlNode *parent, GladeWidget
 	xmlNodeAddContent(widget, "\n");
 	xmlNodeAddContent(child, "\n");
 
-	for (k = 0; k < childinfo->n_properties; k++) { 
-	    xmlNode *node;
+	for (j = 0; j < indent + 2; j++)
+	    xmlNodeAddContent(child, "  ");
+	dump_widget(child, childinfo->child, indent + 2);
+	xmlNodeAddContent(child, "\n");
 
+	if (childinfo->n_properties) {
 	    for (j = 0; j < indent + 2; j++)
 		xmlNodeAddContent(child, "  ");
-	    node = xmlNewNode(NULL, "property");
-	    xmlSetProp(node, "name", childinfo->properties[i].name);
-	    xmlNodeSetContent(node, childinfo->properties[i].value);
-	    xmlAddChild(child, node);
-	    xmlNodeAddContent(child, "\n");
+	    packing = xmlNewNode(NULL, "packing");
+	    xmlAddChild(child, packing);
+	    xmlNodeAddContent(packing, "\n");
+
+	    for (k = 0; k < childinfo->n_properties; k++) { 
+		xmlNode *node;
+
+		for (j = 0; j < indent + 3; j++)
+		    xmlNodeAddContent(packing, "  ");
+		node = xmlNewNode(NULL, "property");
+		xmlSetProp(node, "name", childinfo->properties[k].name);
+		xmlNodeSetContent(node, childinfo->properties[k].value);
+		xmlAddChild(packing, node);
+		xmlNodeAddContent(packing, "\n");
+	    }
 	}
 
-	for (j = 0; j < indent + 2; j++)
-	    xmlNodeAddContent(child, "  ");
-	dump_widget(child, childinfo->child, indent + 2);
-	xmlNodeAddContent(child, "\n");
+	if (childinfo->n_properties) {
+	    for (j = 0; j < indent + 2; j++)
+		xmlNodeAddContent(packing, "  ");
+	    xmlNodeAddContent(child, "\n");
+	}
 
 	for (j = 0; j < indent + 1; j++)
 	    xmlNodeAddContent(child, "  ");
@@ -1382,16 +1441,8 @@ dump_widget(xmlNode *parent, GladeWidget
 	xmlNodeAddContent(widget, "  ");
 }
 
-/**
- * glade_interface_dump
- * @interface: the GladeInterface
- * @filename: the filename to write the interface data to.
- *
- * This function dumps the contents of a GladeInterface into a file as
- * XML.  It is intended mainly as a debugging tool.
- */
-void
-glade_interface_dump(GladeInterface *interface, const gchar *filename)
+static xmlDoc *
+glade_interface_make_doc (GladeInterface *interface)
 {
     xmlDoc *doc;
     xmlNode *root;
@@ -1421,11 +1472,144 @@ glade_interface_dump(GladeInterface *int
 	dump_widget(root, interface->toplevels[i], 1);
 	xmlNodeAddContent(root, "\n");
     }
+    return doc;
+}
 
-    /* output */
-    
-    xmlSaveFileEnc(filename, doc, "UTF-8");
+static void
+glade_interface_buffer (GladeInterface  *interface,
+			gpointer        *buffer,
+			gint            *size)
+{
+    xmlDoc *doc;
+    g_return_if_fail (interface != NULL);
+    g_return_if_fail (buffer    != NULL);
+    g_return_if_fail (size      != NULL);
+
+    doc = glade_interface_make_doc (interface);
+    xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)buffer,
+			      size, "UTF-8",  TRUE);
     xmlFreeDoc(doc);
+}
+
+static gboolean
+write_buffer_contents_stdio (const gchar *display_filename, FILE *f, 
+			     gchar *buffer, gint size, GError **error)
+{
+    gint bytes_written = 0, rv;
+
+    /* write buffer */
+    do {
+	if ((rv = fwrite
+	     (buffer + bytes_written, sizeof (gchar),
+	      (size - bytes_written), f)) != (size - bytes_written) && 
+	    errno != EINTR)
+	    break;
+	if (rv >= 0)
+	    bytes_written += rv;
+    } while (bytes_written < size);
+
+    /* handle error */
+    if (rv == 0 && error) {
+	g_set_error (error,
+		     G_FILE_ERROR,
+		     g_file_error_from_errno (errno),
+		     _("Failed to write to file '%s': %s"),
+		     display_filename, 
+		     g_strerror (errno));
+    }
+    return (rv > 0) ? TRUE : FALSE;
+}
+
+static gboolean
+write_buffer_contents (const gchar  *filename,
+		       gchar        *buffer,
+		       gsize         size,
+		       GError      **error)
+{
+    FILE     *f;
+    gint      fd;
+    gchar    *display_filename;
+    gchar    *disk_filename;
+    gboolean  retval = FALSE;
+
+    display_filename = g_filename_display_name (filename);
+    disk_filename    = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+
+    /* O_BINARY useful on Cygwin */
+    if ((fd = open (disk_filename, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,
+		    GLADE_CREATE_PERMS)) >= 0) {
+
+	if ((f = fdopen (fd, "w")) != NULL) {
+	    retval = 
+		write_buffer_contents_stdio (display_filename, f, 
+					     buffer, size, error);
+	    fclose (f);
+	} else if (error) {
+	    g_set_error (error,
+			 G_FILE_ERROR,
+			 g_file_error_from_errno (errno),
+			 _("Failed to open file '%s': fdopen() failed: %s"),
+			 display_filename, 
+			 g_strerror (errno));
+	}
+	close (fd);
+    } else if (error) {
+	g_set_error (error,
+		     G_FILE_ERROR,
+		     g_file_error_from_errno (errno),
+		     _("Failed to create file '%s': %s"),
+		     display_filename, 
+		     g_strerror (errno));
+    }
+    g_free (display_filename);
+    g_free (disk_filename);
+
+    return retval;
+}
+
+/**
+ * glade_interface_dump_full
+ * @interface: the GladeInterface
+ * @filename: the filename to write the interface data to.
+ * @error: a #GError for error handleing.
+ *
+ * This function dumps the contents of a GladeInterface into a file as
+ * XML.  It is used by glade to write glade files.
+ *
+ * Returns whether the write was successfull or not.
+ */
+gboolean
+glade_interface_dump_full(GladeInterface *interface, const gchar *filename, GError **error)
+{
+    gpointer buffer;
+    gint     size;
+
+    glade_interface_buffer (interface, &buffer, &size);
+
+    if (buffer) {
+	return write_buffer_contents (filename, buffer, size, error);
+	xmlFree (buffer);
+    } else if (error) {
+	g_set_error (error,
+		     G_FILE_ERROR,
+		     G_FILE_ERROR_NOMEM,
+		     _("Could not allocate memory for interface"));
+    }
+    return FALSE;
+}
+
+/**
+ * glade_interface_dump
+ * @interface: the GladeInterface
+ * @filename: the filename to write the interface data to.
+ *
+ * This function dumps the contents of a GladeInterface into a file as
+ * XML.  It was originaly intended as a debugging tool.
+ */
+void
+glade_interface_dump(GladeInterface *interface, const gchar *filename)
+{
+    glade_interface_dump_full(interface, filename, NULL);
 }
 
 #if 0
Index: glade/glade-parser.h
===================================================================
RCS file: /cvs/gnome/libglade/glade/glade-parser.h,v
retrieving revision 1.8
diff -u -p -r1.8 glade-parser.h
--- glade/glade-parser.h	25 Apr 2002 15:49:30 -0000	1.8
+++ glade/glade-parser.h	2 Jan 2005 22:14:40 -0000
@@ -28,8 +28,8 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GladeProperty GladeProperty;
-struct _GladeProperty {
+typedef struct _GladePropInfo GladePropInfo;
+struct _GladePropInfo {
     gchar *name;
     gchar *value;
 };
@@ -38,8 +38,10 @@ typedef struct _GladeSignalInfo GladeSig
 struct _GladeSignalInfo {
     gchar *name;
     gchar *handler;
-    gchar *object; /* NULL if this isn't a connect_object signal */
+    gchar *object; /* represents userdata, if lookup is FALSE, then do connect_object with a
+                    * widget looked up by name, otherwise g_module_lookup() */
     guint after : 1;
+    guint lookup : 1;
 };
 
 typedef struct _GladeAtkActionInfo GladeAtkActionInfo;
@@ -70,10 +72,10 @@ struct _GladeWidgetInfo {
     gchar *classname;
     gchar *name;
 
-    GladeProperty *properties;
+    GladePropInfo *properties;
     guint n_properties;
 
-    GladeProperty *atk_props;
+    GladePropInfo *atk_props;
     guint n_atk_props;
 
     GladeSignalInfo *signals;
@@ -93,7 +95,7 @@ struct _GladeWidgetInfo {
 };
 
 struct _GladeChildInfo {
-    GladeProperty *properties;
+    GladePropInfo *properties;
     guint n_properties;
 
     GladeWidgetInfo *child;
@@ -118,10 +120,12 @@ GladeInterface *glade_parser_parse_file 
 					   const gchar *domain);
 GladeInterface *glade_parser_parse_buffer (const gchar *buffer, gint len,
 					   const gchar *domain);
-void            glade_interface_destroy   (GladeInterface *interface);
-
-void            glade_interface_dump      (GladeInterface *interface,
-					   const gchar *filename);
+void            glade_interface_destroy   (GladeInterface  *interface);
+void            glade_interface_dump      (GladeInterface  *interface,
+					   const gchar     *filename);
+gboolean        glade_interface_dump_full (GladeInterface  *interface, 
+					   const gchar     *filename,
+					   GError         **error);
 
 G_END_DECLS
 
Index: glade/glade-private.h
===================================================================
RCS file: /cvs/gnome/libglade/glade/glade-private.h,v
retrieving revision 1.23
diff -u -p -r1.23 glade-private.h
--- glade/glade-private.h	5 Feb 2002 23:26:52 -0000	1.23
+++ glade/glade-private.h	2 Jan 2005 22:14:40 -0000
@@ -64,6 +64,7 @@ struct _GladeSignalData {
     GObject *signal_object;
     char *signal_name;
     char *connect_object; /* or NULL if there is none */
+    gboolean lookup_userdata;
     gboolean signal_after;
 };
 
Index: glade/glade-xml.c
===================================================================
RCS file: /cvs/gnome/libglade/glade/glade-xml.c,v
retrieving revision 1.111
diff -u -p -r1.111 glade-xml.c
--- glade/glade-xml.c	29 Nov 2004 11:05:16 -0000	1.111
+++ glade/glade-xml.c	2 Jan 2005 22:14:41 -0000
@@ -48,6 +48,11 @@ static GQuark       glade_xml_name_id   
 static const gchar *glade_xml_tooltips_key = "GladeXML::tooltips";
 static GQuark       glade_xml_tooltips_id  = 0;
 
+/* Used for bookkeeping on the name hash */
+typedef struct {
+    gchar    *name;
+    GladeXML *xml;
+} DestroyData;
 
 static void glade_xml_init(GladeXML *xml);
 static void glade_xml_class_init(GladeXMLClass *class);
@@ -277,31 +282,45 @@ autoconnect_foreach(const char *signal_h
 {
     GCallback func;
 
-    if (!g_module_symbol(allsymbols, signal_handler, (gpointer)&func))
-	g_warning("could not find signal handler '%s'.", signal_handler);
+    if (!g_module_symbol(allsymbols,
+                         signal_handler,
+                         ((gpointer *) &func)))
+        g_warning("could not find signal handler '%s'.", signal_handler);
     else
-	for (; signals != NULL; signals = signals->next) {
-	    GladeSignalData *data = signals->data;
-	    if (data->connect_object) {
-		GladeXML *self = glade_get_widget_tree(
-					GTK_WIDGET(data->signal_object));
-		GObject *other = g_hash_table_lookup(self->priv->name_hash,
-						       data->connect_object);
-
-		g_signal_connect_object(data->signal_object, data->signal_name,
-			func, other, (data->signal_after ? G_CONNECT_AFTER : 0)
-					| G_CONNECT_SWAPPED);
-	    } else {
-		/* the signal_data argument is just a string, but may
-		 * be helpful for someone */
-		if (data->signal_after)
-		    g_signal_connect_after(data->signal_object,
-					   data->signal_name, func, NULL);
-		else
-		    g_signal_connect(data->signal_object, data->signal_name,
-				     func, NULL);
-	    }
-	}
+        for (; signals != NULL; signals = signals->next) {
+            GladeSignalData *data = signals->data;
+            if (data->connect_object && !data->lookup_userdata) {
+                GladeXML *self = glade_get_widget_tree
+                    (GTK_WIDGET(data->signal_object));
+                GObject *other = g_hash_table_lookup(self->priv->name_hash,
+                                                     data->connect_object);
+ 
+                g_signal_connect_object(data->signal_object, data->signal_name,
+                                        func, other, (data->signal_after ? G_CONNECT_AFTER : 0)
+                                        | G_CONNECT_SWAPPED);
+            } else if (data->connect_object && data->lookup_userdata) {
+                gpointer userdata;
+ 
+                if (!g_module_symbol(allsymbols, data->connect_object, &userdata))
+                    g_warning("could not find user data '%s' for signal handler '%s'.",
+                              data->connect_object, signal_handler);
+                else if (data->signal_after)
+                    g_signal_connect_after(data->signal_object,
+                                           data->signal_name, func, userdata);
+                else
+                    g_signal_connect(data->signal_object, data->signal_name,
+                                     func, userdata);
+            } else {
+                /* the signal_data argument is just a string, but may
+                 * be helpful for someone */
+                if (data->signal_after)
+                    g_signal_connect_after(data->signal_object,
+                                           data->signal_name, func, NULL);
+                else
+                    g_signal_connect(data->signal_object, data->signal_name,
+                                     func, NULL);
+            }
+        }
 }
 
 /**
@@ -727,8 +746,9 @@ glade_xml_add_signals(GladeXML *xml, Gtk
 	data->signal_object = G_OBJECT(w);
 	data->signal_name = sig->name;
 	data->connect_object = sig->object;
+        data->lookup_userdata = sig->lookup;
 	data->signal_after = sig->after;
-
+    
 	list = g_hash_table_lookup(xml->priv->signals, sig->handler);
 	list = g_list_prepend(list, data);
 	g_hash_table_insert(xml->priv->signals, sig->handler, list);
@@ -1213,7 +1233,7 @@ glade_register_widget(GType type,
     GladeWidgetBuildData *data;
     gpointer old_data;
 
-    g_return_if_fail(g_type_is_a(type, GTK_TYPE_WIDGET));
+    g_return_if_fail(g_type_is_a(type, G_TYPE_OBJECT));
 
     if (glade_build_data_id == 0)
 	glade_build_data_id = g_quark_from_static_string(glade_build_data_key);
@@ -1566,7 +1586,7 @@ glade_xml_set_value_from_string (GladeXM
 typedef struct _CustomPropData CustomPropData;
 struct _CustomPropData {
     GladeApplyCustomPropFunc apply_prop;
-    GladeProperty *prop;
+    GladePropInfo *prop;
 };
 
 /**
@@ -1669,7 +1689,7 @@ glade_standard_build_widget(GladeXML *xm
 
     /* handle deferred properties */
     for (tmp = deferred_props; tmp; tmp = tmp->next) {
-	GladeProperty *prop = tmp->data;
+	GladePropInfo *prop = tmp->data;
 
 	glade_xml_handle_widget_prop(xml, widget, prop->name, prop->value);
     }
@@ -1973,21 +1993,14 @@ glade_xml_handle_internal_child(GladeXML
     glade_xml_set_common_params(self, child, child_info->child);
 }
 
-
 static void
-glade_xml_widget_destroy(GtkObject *object, GladeXML *xml)
+glade_xml_finalize_notify (DestroyData *dd, GObject *was_an_object)
 {
-    gchar *name;
-
-    g_return_if_fail(GTK_IS_OBJECT(object));
-    g_return_if_fail(GLADE_IS_XML(xml));
-
-    name = g_object_get_qdata(G_OBJECT(object), glade_xml_name_id);
-
-    if (!name) return;
-    g_hash_table_remove(xml->priv->name_hash, name);
-    g_object_set_qdata(G_OBJECT(object), glade_xml_tree_id, NULL);
-    g_object_set_qdata(G_OBJECT(object), glade_xml_name_id, NULL);
+    if (dd->xml) {
+        g_hash_table_remove(dd->xml->priv->name_hash, dd->name);
+    }
+    g_free (dd->name);
+    g_free (dd);
 }
 
 /**
@@ -2007,16 +2020,19 @@ glade_xml_set_common_params(GladeXML *se
 			    GladeWidgetInfo *info)
 {
     GList *tmp;
+    DestroyData *dd;
     const GladeWidgetBuildData *data;
     static GQuark visible_id = 0;
-
+    
     /* get the build data */
     data = get_build_data(G_OBJECT_TYPE(widget));
     glade_xml_add_signals(self, widget, info);
     glade_xml_add_accels(self, widget, info);
 
-    gtk_widget_set_name(widget, info->name);
-    glade_xml_add_accessibility_info(self, widget, info);
+    if (GTK_IS_WIDGET (widget)) {
+        gtk_widget_set_name(widget, info->name);
+        glade_xml_add_accessibility_info(self, widget, info);
+    }
 
     /* store this information as data of the widget. */
     g_object_set_qdata(G_OBJECT(widget), glade_xml_tree_id, self);
@@ -2024,13 +2040,15 @@ glade_xml_set_common_params(GladeXML *se
     /* store widgets in hash table, for easy lookup */
     g_hash_table_insert(self->priv->name_hash, info->name, widget);
 
-    /* set up function to remove widget from GladeXML object's
-     * name_hash on destruction. Use connect_object so the handler is
-     * automatically removed on finalization of the GladeXML
-     * object. */
-    g_signal_connect_object(G_OBJECT(widget), "destroy",
-			    G_CALLBACK(glade_xml_widget_destroy),
-			    G_OBJECT(self), 0);
+    /* set up function to remove object from GladeXML object's
+     * name_hash on destruction. Use a weak pointer to ensure
+     * that the GladeXML object isn't accessed after its destruction.
+     */
+    dd        = g_new (DestroyData, 1);
+    dd->name  = g_strdup (info->name);
+    dd->xml   = self;
+    g_object_weak_ref (G_OBJECT (widget), (GWeakNotify)glade_xml_finalize_notify, dd);
+    g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&(dd->xml));
 
     /* handle any deferred properties using this widget */
     tmp = self->priv->deferred_props;
@@ -2068,18 +2086,16 @@ glade_xml_set_common_params(GladeXML *se
     }
 
     if (data && data->build_children && info->children) {
-	if (GTK_IS_CONTAINER (widget))
-	    data->build_children(self, widget, info);
-	else
-	    g_warning ("widget %s (%s) has children, but is not a GtkContainer.",
-		       info->name, g_type_name (G_TYPE_FROM_INSTANCE (widget)));
+        data->build_children(self, widget, info);
     }
 
-    if (visible_id == 0)
-	visible_id = g_quark_from_static_string("Libglade::visible");
+    if (GTK_IS_WIDGET (widget)) {
+        if (visible_id == 0)
+            visible_id = g_quark_from_static_string("Libglade::visible");
 
-    if (g_object_get_qdata(G_OBJECT(widget), visible_id))
-	gtk_widget_show(widget);
+        if (g_object_get_qdata(G_OBJECT(widget), visible_id))
+            gtk_widget_show(widget);
+    }
 }
 
 /**
