diff --git a/src/post_modules/GTK2/Makefile.in b/src/post_modules/GTK2/Makefile.in
index 7ba387033eee8ec0cbf87b2c2fd47d5b5abe4901..ee768c165314cb22ce980bcc8b2f40fe237eff23 100644
--- a/src/post_modules/GTK2/Makefile.in
+++ b/src/post_modules/GTK2/Makefile.in
@@ -51,9 +51,9 @@ compile1:
 	  done; \
 	else :; fi
 	@echo "Original CFLAGS:$(CFLAGS)"
-	@echo "Modified CFLAGS:`echo ' $(CFLAGS) ' | sed -e 's/ -g[^ ]*//g' -e 's/ -W[^ ]*//g'` `echo ' $(CFLAGS) ' | sed -ne 's/.*\( -gcc-version[^ ]*\).*/\1/p'`"
+	@echo "Modified CFLAGS:`echo $(CFLAGS) | sed -e 's/-g[^ ]*//g' -e 's/-W[^ ]*//g'`"
 	@$(MAKE) OBJS="`cat files_to_compile`" \
-		 CFLAGS="`echo ' $(CFLAGS) ' | sed -e 's/ -g[^ ]*/ /g' -e 's/ -W[^ ]*/ /g'` `echo ' $(CFLAGS) ' | sed -ne 's/.*\( -gcc-version[^ ]*\).*/\1/p'`" \
+	         CFLAGS="`echo $(CFLAGS) | sed -e 's/ -g[^ ]*/ /g' -e 's/ -W[^ ]*/ /g'`" \
 	         all
 
 compile2: compile1
diff --git a/src/post_modules/GTK2/acconfig.h b/src/post_modules/GTK2/acconfig.h
index 5d3bf21a7947e7a8efb451a0dbc58a10c621ede4..88b4e5ffdc54f5bb53472bdabb98eb74138ae7bf 100644
--- a/src/post_modules/GTK2/acconfig.h
+++ b/src/post_modules/GTK2/acconfig.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: acconfig.h,v 1.7 2005/11/07 17:25:11 grubba Exp $
+|| $Id: acconfig.h,v 1.8 2006/08/02 13:42:31 ldillon Exp $
 */
 
 #undef FUNCPROTO
@@ -13,6 +13,7 @@
 #undef HAVE_GTK24
 #undef HAVE_GTK26
 #undef HAVE_GTK28
+#undef HAVE_GTK210
 #undef HAVE_ATK
 #undef HAVE_ATK18
 #undef HAVE_PANGO
diff --git a/src/post_modules/GTK2/pgtk.h b/src/post_modules/GTK2/pgtk.h
index 53877e9c6da27f081af1767b9d1a3780d9e4baa8..f46fc64679d8f62f604688ff847a04dba2bb8fb6 100644
--- a/src/post_modules/GTK2/pgtk.h
+++ b/src/post_modules/GTK2/pgtk.h
@@ -2,11 +2,13 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: pgtk.h,v 1.14 2006/02/27 12:23:15 mast Exp $
+|| $Id: pgtk.h,v 1.15 2006/08/02 13:42:31 ldillon Exp $
 */
 
 /* Sort of unnessesary, and decreases code-size with 140Kb */
+/*
 #define GTK_NO_CHECK_CASTS
+*/
 /* Also sort of unessesary, most code is autogenerated anyway. */
 #define NO_PIKE_SHORTHAND
 #include "pgtk_config.h"
@@ -125,7 +127,12 @@ void pgtk2_push_Xpseudo32bitstring(void *f, int nelems);
 int pgtk2_get_color_from_pikecolor(struct object *o, INT_TYPE *r, INT_TYPE *g, INT_TYPE *b);
 #define get_color_from_pikecolor pgtk2_get_color_from_pikecolor
 
-int pgtk2_signal_func_wrapper(struct signal_data *d, ...);
+/*int pgtk2_signal_func_wrapper(struct signal_data *d, ...); */
+void pgtk2_signal_func_wrapper(struct signal_data *d,
+			       gpointer go,
+			       guint n_params,
+			       const GValue *param_values,
+			       GValue *return_value);
 
 void pgtk2_free_signal_data(struct signal_data *s, GClosure *gcl);
 void pgtk2_free_object(struct object *o);
@@ -307,5 +314,20 @@ GObject *pgtk2_create_new_obj_with_properties(GType type, struct mapping *m);
 	get_all_args("create",args,"%m",&m);	\
 	THIS->obj=pgtk2_create_new_obj_with_properties(X,m);	\
       } while(0)
-void pgtk2_push_gvalue_r(GValue *param, GType t);
+void pgtk2_push_gvalue_r(const GValue *param, GType t);
 #define push_gvalue_r pgtk2_push_gvalue_r
+
+#ifdef HAVE_CAIRO
+/* from picairo */
+#include <cairo.h>
+struct cairo_mod_context {
+  cairo_t *ctx;
+};
+#endif
+
+void pgtk2_marshaller(GClosure *closure, GValue *return_value,
+		      guint n_param_values, const GValue *param_values,
+		      gpointer invocation_hint, gpointer marshal_data);
+
+#define pgtk2_set_value(X,Y) pgtk2_set_gvalue((X),G_VALUE_TYPE(X),Y)
+#define pgtk2_push_gvalue_rt(X) pgtk2_push_gvalue_r((X),G_VALUE_TYPE(X))
diff --git a/src/post_modules/GTK2/source/gobject.pre b/src/post_modules/GTK2/source/gobject.pre
index c6f4dd161d637c8c9ec1e2ab71cdf79bcf9b906a..df29b343d2984b7c288ebc0615319105e758f664 100644
--- a/src/post_modules/GTK2/source/gobject.pre
+++ b/src/post_modules/GTK2/source/gobject.pre
@@ -42,7 +42,9 @@ mixed get_property(string property)
   }
 }
 
+
 int signal_connect(string signal, function callback, mixed|void callback_arg)
+//! int signal_connect(string signal, function callback, mixed ... args)
 //! Connect a signal to a pike function.  The function will be called with
 //! the last argument to this function as it's first argument (defaults to 0),
 //! the second argument is always the widget, and any other arguments are the
@@ -56,6 +58,7 @@ int signal_connect(string signal, function callback, mixed|void callback_arg)
   int id;
   struct signal_data *b;
   struct svalue *tmp1,*tmp2;
+  GClosure *gc;
 
   if (args==2) {
     push_int(0);
@@ -72,22 +75,15 @@ int signal_connect(string signal, function callback, mixed|void callback_arg)
 
   b->signal_id=g_signal_lookup(a,G_TYPE_FROM_INSTANCE(THIS->obj));
   if (!b->signal_id) {
-    xfree(b);
+    g_free(b);
     Pike_error("Signal \"%s\" is not defined in the '%s' class ancestry.\n",
 		a,g_type_name(G_TYPE_FROM_INSTANCE(THIS->obj)));
   }
-
-  id=g_signal_connect_data(G_OBJECT(THIS->obj),a,
-			   G_CALLBACK(pgtk2_signal_func_wrapper),
-			   b,
-			   (GClosureNotify)pgtk2_free_signal_data,
-#ifdef HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS
-			   G_CONNECT_SWAPPED
-#else /* !HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS
-			   /* Old-style. */
-			   1 /* swapped */, 0 /* after */
-#endif /* !HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS */
-			   );
+  gc=g_cclosure_new_swap(G_CALLBACK(pgtk2_signal_func_wrapper),
+		    b,(GClosureNotify)pgtk2_free_signal_data);
+  g_closure_set_marshal(gc,pgtk2_marshaller);
+  id=g_signal_connect_closure(G_OBJECT(THIS->obj),a,
+			      gc,1);
   pgtk2_pop_n_elems(args);
   push_int(id);
 }
@@ -126,10 +122,126 @@ void signal_unblock(int signal_id)
 void signal_emit(string signal_name)
 //! Send the current named signal.
 {
-  char *s;
-  get_all_args("signal_emit",args,"%s",&s);
-  g_signal_emit_by_name(G_OBJECT(THIS->obj),s,NULL);
-  RETURN_THIS();
+  pgtk2_verify_inited();
+  {
+    char *s;
+    GQuark gq;
+    GSignalQuery _opts;
+    GSignalQuery *opts=&_opts;
+    guint signal_id;
+
+    get_all_args("signal_emit",args,"%s",&s);
+    gq=g_quark_from_string(s);
+    signal_id=g_signal_lookup(s,G_TYPE_FROM_INSTANCE(THIS->obj));
+    g_signal_query(signal_id,opts);
+    if (opts->n_params!=args-1) {
+      pgtk2_pop_n_elems(args);
+/*      Pike_error("Signal %s expects %d args, got %d.\n",s,opts->n_params,args-1); */
+      Pike_error("signal_emit:  signature mismatch for signal \"%s\" in the '%s' class ancestry.\n"
+		 "              expected %d args, got %d.\n",s,
+		 g_type_name(G_OBJECT_TYPE(THIS->obj)),opts->n_params,args-1);
+    }
+    {
+      int i;
+      GValue params[opts->n_params+1];
+      GValue rvalue={0, };
+
+      memset(params,0,sizeof(GValue)*(opts->n_params+1)); 
+      g_value_init(params+0,G_TYPE_FROM_INSTANCE(THIS->obj));
+      g_value_set_object(params+0,G_OBJECT(THIS->obj));
+      for (i=0; i<opts->n_params; i++) {
+	pgtk2_set_gvalue(params+i+1,opts->param_types[i],&Pike_sp[-args+(i+1)]);
+      }
+      if (opts->return_type!=G_TYPE_NONE)
+	g_value_init(&rvalue,opts->return_type);
+      g_signal_emitv(params,signal_id,0,&rvalue);
+      pgtk2_pop_n_elems(args);
+      if (opts->return_type!=G_TYPE_NONE) {
+	pgtk2_push_gvalue_rt(&rvalue);
+      } else {
+	push_int(0);
+      }
+      g_value_unset(params);
+      for (i=1; i<opts->n_params; i++)
+	g_value_unset(params+i);
+    }
+  }
+}
+
+int new_signal(string name, array types, string return_type)
+//! Create a new signal.
+{
+  pgtk2_verify_inited();
+  {
+    struct pike_string *t;
+    char *ret_type_name;
+    struct array *a;
+    GObject *go;
+    gchar *name;
+    guint id;
+    GType *param_types;
+    guint n_params;
+    GType return_type;
+    struct signal_data *b;
+    int i;
+
+    get_all_args("new_signal",args,"%T%A%s",&t,&a,&ret_type_name);
+    if (a->size) {
+      ref_push_string(t);
+      f_string_to_utf8(1);
+      name=g_strdup(CGSTR0(Pike_sp[-1].u.string));
+      if (name==NULL) {
+	pop_stack();
+	SIMPLE_OUT_OF_MEMORY_ERROR("new_signal",strlen(ret_type_name)*2);
+      }
+      if (!strcmp(ret_type_name,"void")) {
+	return_type=G_TYPE_NONE;
+      } else if (!strcmp(ret_type_name,"int")) {
+	return_type=G_TYPE_INT;
+      } else if (!strcmp(ret_type_name,"float")) {
+	return_type=G_TYPE_DOUBLE;
+      } else if (!strcmp(ret_type_name,"string")) {
+	return_type=G_TYPE_STRING;
+      } else if (!strcmp(ret_type_name,"object")) {
+	return_type=G_TYPE_OBJECT;
+      } else {
+	return_type=G_TYPE_POINTER;
+      }
+      param_types=xmalloc(sizeof(GType)*a->size);
+      if (param_types==NULL) {
+	g_free(name);
+	SIMPLE_OUT_OF_MEMORY_ERROR("new_signal",sizeof(GType)*a->size);
+      }
+      for (i=n_params=0; i<a->size; i++) {
+	if (ITEM(a)[i].type!=PIKE_T_STRING)
+	  continue;
+	if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"int")) {
+	  param_types[n_params]=G_TYPE_INT;
+	  n_params++;
+	} else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"float")) {
+	  param_types[n_params]=G_TYPE_DOUBLE;
+	  n_params++;
+	} else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"string")) {
+	  param_types[n_params]=G_TYPE_STRING;
+	  n_params++;
+	} else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"object")) {
+	  param_types[n_params]=G_TYPE_OBJECT;
+	  n_params++;
+	} else {
+	  param_types[n_params]=G_TYPE_POINTER;
+	  n_params++;
+	}
+
+      }
+      pgtk2_pop_n_elems(args);
+      id=g_signal_newv(name,G_TYPE_FROM_INSTANCE(THIS->obj),G_SIGNAL_RUN_LAST,
+		       NULL,NULL,NULL,pgtk2_marshaller,return_type,
+		       n_params,param_types);
+      push_int(id);
+      xfree(param_types);
+      g_free(name);
+    }
+  }
 }
 
 void notify(string property);
@@ -149,4 +261,13 @@ void accel_groups_activate(int accel_key, int accel_mods)
   RETURN_THIS();
 }
 
+require gtk210;
+/*
+object ref_sink();
+//! Increase the reference count of this object, and possibly remove the
+//! floating reference, if this object has a floating reference.
+*/
 
+int is_floating();
+//! Checks whether this object has a floating reference.
+endrequire;
diff --git a/src/post_modules/GTK2/source/support.c b/src/post_modules/GTK2/source/support.c
index 85b0d13287dc457522e6200a630b7ad4469da97e..bb6b566d3390698e1793a9698aa6b877ab364f9d 100644
--- a/src/post_modules/GTK2/source/support.c
+++ b/src/post_modules/GTK2/source/support.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: support.c,v 1.11 2006/02/27 12:23:18 mast Exp $
+|| $Id: support.c,v 1.12 2006/08/02 13:42:31 ldillon Exp $
 */
 
 #include <version.h>
@@ -474,31 +474,31 @@ static int pgtk2_push_selection_data_param( GValue *a )
 }
 */
 
-static int pgtk2_push_accel_group_param(GValue *a) {
+static int pgtk2_push_accel_group_param(const GValue *a) {
   g_object_ref(g_value_get_pointer(a));
   push_gobjectclass(g_value_get_pointer(a),pgtk2_accel_group_program);
   return PUSHED_VALUE;
 }
 
 /*
-static int pgtk2_push_ctree_node_param( GValue *a )
+static int pgtk2_push_ctree_node_param(const GValue *a )
 {
   push_pgdk2object( GTK_VALUE_POINTER(*a), pgtk2_ctree_node_program);
   return PUSHED_VALUE;
 }
 */
 
-static int pgtk2_push_gdk_drag_context_param(GValue *a) {
+static int pgtk2_push_gdk_drag_context_param(const GValue *a) {
   push_gdkobject(g_value_get_pointer(a),drag_context);
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_gdk_event_param(GValue *a) {
+static int pgtk2_push_gdk_event_param(const GValue *a) {
   push_gdk_event(g_value_get_boxed(a));
   return NEED_RETURN;
 }
 
-static int pgtk2_push_gdk_rectangle_param(GValue *a) {
+static int pgtk2_push_gdk_rectangle_param(const GValue *a) {
   GdkRectangle *r = (GdkRectangle *) g_value_get_boxed(a);
   push_text("x"); push_int(r->x);
   push_text("y"); push_int(r->y);
@@ -508,7 +508,7 @@ static int pgtk2_push_gdk_rectangle_param(GValue *a) {
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_int_param(GValue *a) {
+static int pgtk2_push_int_param(const GValue *a) {
   LONGEST retval;
   switch (G_VALUE_TYPE(a)) {
     case G_TYPE_INT:
@@ -537,7 +537,7 @@ static int pgtk2_push_int_param(GValue *a) {
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_float_param(GValue *a) {
+static int pgtk2_push_float_param(const GValue *a) {
   FLOAT_TYPE retval;
   if (G_VALUE_TYPE(a)==G_TYPE_FLOAT)
     retval=(FLOAT_TYPE)g_value_get_float(a);
@@ -547,7 +547,7 @@ static int pgtk2_push_float_param(GValue *a) {
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_string_param(GValue *a) {
+static int pgtk2_push_string_param(const GValue *a) {
   const gchar *t=g_value_get_string(a);
   if (t)
     PGTK_PUSH_GCHAR(t);
@@ -556,32 +556,33 @@ static int pgtk2_push_string_param(GValue *a) {
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_object_param(GValue *a) {
+static int pgtk2_push_object_param(const GValue *a) {
   GObject *obj=g_value_get_object(a);
   if (obj)
-    push_gobject(((void *)g_value_get_object(a)));
+/*    push_gobject(((void *)g_value_get_object(a))); */
+    push_gobject(obj);
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_pike_object_param(GValue *a) {
+static int pgtk2_push_pike_object_param(const GValue *a) {
   struct object *o=g_value_get_pointer(a);
   if (o)
     ref_push_object(o);
   return PUSHED_VALUE;
 }
 
-static int pgtk2_push_gparamspec_param(GValue *a) {
+static int pgtk2_push_gparamspec_param(const GValue *a) {
 }
 
 static struct push_callback {
-  int (*callback)(GValue *);
+  int (*callback)(const GValue *);
   GType id;
   struct push_callback *next;
 } push_callbacks[100], *push_cbtable[63];
 
 static int last_used_callback = 0;
 
-static void insert_push_callback(GType i, int (*cb)(GValue *)) {
+static void insert_push_callback(GType i, int (*cb)(const GValue *)) {
   struct push_callback *new=push_callbacks+last_used_callback++;
   struct push_callback *old=push_cbtable[i%63];
   new->id=i;
@@ -639,7 +640,7 @@ static void build_push_callbacks() {
  *   This might not be exactly what we want */
 }
 
-void push_gvalue_r(GValue *param, GType t) {
+void push_gvalue_r(const GValue *param, GType t) {
   int i;
   struct push_callback *cb=push_cbtable[t%63];
 
@@ -681,50 +682,33 @@ void push_gvalue_r(GValue *param, GType t) {
  * params[nparams] should be set to the return value. It does seem to work,
  * though.
  */
-int pgtk2_signal_func_wrapper(struct signal_data *d, ...) {
-  int i,return_value=0,j;
-  struct svalue *osp=Pike_sp;
-  GSignalQuery _opts;
-  GSignalQuery *opts=&_opts;
-  va_list ptr;
+/* This function is implement by the functions in the gobject api */
+void pgtk2_signal_func_wrapper(struct signal_data *d,
+			       gpointer go,
+			       guint n_params,
+			       const GValue *param_values,
+			       GValue *return_value) {
+  int i;
 
   if (!last_used_callback)
     build_push_callbacks();
-  g_signal_query(d->signal_id,opts);
-  va_start(ptr,d);
-  for (i=j=0; i<opts->n_params; i++) {
-    GValue v= {0, };
-    gchar *error=NULL;
-    g_value_init(&v,opts->param_types[i]);
-    G_VALUE_COLLECT(&v,ptr,G_VALUE_NOCOPY_CONTENTS,&error);
-    if (error) {
-      g_free(error);
-      continue;
-    }
-    push_gvalue_r(&v,opts->param_types[i]);
-    j++;
-  }
-  if (j /*opts->n_params*/)
-    f_aggregate(j /*opts->n_params*/);
-  {
-    GObject *obj=va_arg(ptr,GObject *);
-    push_gobject(obj);
+  push_gobject(G_OBJECT(go));
+  for (i=0; i<n_params; i++) {
+    pgtk2_push_gvalue_rt(&(param_values[i]));
   }
-  va_end(ptr);
-
-  if (j /*opts->n_params*/)
-    stack_swap();
+  if (n_params)
+    f_aggregate(n_params);
   push_svalue(&d->args);
-  if (j /*opts->n_params*/)
+  if (n_params)
     apply_svalue(&d->cb,3);
   else
     apply_svalue(&d->cb,2);
-  return_value=Pike_sp[-1].u.integer;
-  pop_stack();
-  return return_value;
+  if (return_value) {
+    pgtk2_set_value(return_value,&Pike_sp[-1]);
+    pop_stack();
+  }
 }
 
-
 void pgtk2_free_signal_data(struct signal_data *s, GClosure *gcl) {
   free_svalue(&s->cb);
   free_svalue(&s->args);
@@ -1069,8 +1053,11 @@ void pgtk2_destroy_store_data(gpointer data) {
   g_free(sd);
 }
 
+
+
 void pgtk2_set_gvalue(GValue *gv, GType gt, struct svalue *sv) {
-  g_value_init(gv,gt);
+  if (!G_IS_VALUE(gv))
+    g_value_init(gv,gt);
   if (G_TYPE_IS_ENUM(gt)) {
     g_value_set_enum(gv,(gint)PGTK_GETINT(sv));
     return;
@@ -1142,9 +1129,10 @@ void pgtk2_set_gvalue(GValue *gv, GType gt, struct svalue *sv) {
       g_value_set_double(gv,(gdouble)pgtk2_get_float(sv));
       break;
     case G_TYPE_STRING:
-      if (sv->type==PIKE_T_STRING)
-	g_value_set_string(gv,GSTR0(sv->u.string));
-      else
+      if (sv->type==PIKE_T_STRING) {
+	g_value_set_string(gv,CGSTR0(sv->u.string));
+	add_ref(sv->u.string); 
+      } else
 	g_value_set_string(gv,"");
       break;
     case G_TYPE_OBJECT:
@@ -1218,3 +1206,30 @@ GObject *pgtk2_create_new_obj_with_properties(GType type, struct mapping *m) {
   g_type_class_unref(class);
   return obj;
 }
+
+void pgtk2_marshaller(GClosure *closure,
+		      GValue *return_value,
+		      guint n_params,
+		      const GValue *param_values,
+		      gpointer invocation_hint,
+		      gpointer marshal_data) {
+  typedef void (*pgtk2_marshal_func)(gpointer data1,
+				     gpointer data2,
+				     guint n_params, 
+				     const GValue *param_values,
+				     GValue *return_value);
+  register pgtk2_marshal_func callback;
+  register GCClosure *cc=(GCClosure *)closure;
+  register gpointer data1,data2;
+
+
+  if (G_CCLOSURE_SWAP_DATA(closure)) {
+    data1=closure->data;
+    data2=g_value_peek_pointer(param_values+0);
+  } else {
+    data1=g_value_peek_pointer(param_values+0);
+    data2=closure->data;
+  }
+  callback=(pgtk2_marshal_func)(marshal_data?marshal_data:cc->callback);
+  callback(data1,data2,n_params-1,param_values+1,return_value);
+}