changeset 1853:4790589f52a9

Initial commit for new dw_signal_connect_data() function... Same as dw_signal_connect() but it has an additional callback parameter that gets called when the callback is being removed. This allows me to free memory allocated for the data parameter and prevent memory leaks in godwindows... Tested GTK and Mac.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 27 Feb 2013 19:14:22 +0000
parents 5f0e4ca14dcd
children dcd6181223a9
files dw.h gtk/dw.c gtk3/dw.c mac/dw.m os2/dw.c win/dw.c
diffstat 6 files changed, 430 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/dw.h	Fri Feb 15 09:22:56 2013 +0000
+++ b/dw.h	Wed Feb 27 19:14:22 2013 +0000
@@ -1719,6 +1719,7 @@
 int API dw_timer_connect(int interval, void *sigfunc, void *data);
 void API dw_timer_disconnect(int id);
 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data);
+void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data);
 void API dw_signal_disconnect_by_window(HWND window);
 void API dw_signal_disconnect_by_data(HWND window, void *data);
 void API dw_signal_disconnect_by_name(HWND window, char *signame);
--- a/gtk/dw.c	Fri Feb 15 09:22:56 2013 +0000
+++ b/gtk/dw.c	Wed Feb 27 19:14:22 2013 +0000
@@ -3,7 +3,7 @@
  *          A GTK like cross-platform GUI
  *          GTK forwarder module for portabilty.
  *
- * (C) 2000-2012 Brian Smith <brian@dbsoft.org>
+ * (C) 2000-2013 Brian Smith <brian@dbsoft.org>
  * (C) 2003-2011 Mark Hessling <mark@rexx.org>
  * (C) 2002 Nickolay V. Shmyrev <shmyrev@yandex.ru>
  */
@@ -177,6 +177,7 @@
 #endif
 static gint _switch_page_event(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data);
 static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data);
+static void _dw_signal_disconnect(gpointer data, GClosure *closure);
 
 /* Embedable Mozilla functions*/
 #ifdef USE_GTKMOZEMBED
@@ -1223,23 +1224,28 @@
    return NULL;
 }
 
-static SignalHandler _get_signal_handler(GtkWidget *widget, gpointer data)
-{
-   int counter = GPOINTER_TO_INT(data);
-   SignalHandler sh;
-   char text[101] = {0};
-
-   snprintf(text, 100, "_dw_sigwindow%d", counter);
-   sh.window = (HWND)gtk_object_get_data(GTK_OBJECT(widget), text);
-   snprintf(text, 100, "_dw_sigfunc%d", counter);
-   sh.func = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
-   snprintf(text, 100, "_dw_intfunc%d", counter);
-   sh.intfunc = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
-   snprintf(text, 100, "_dw_sigdata%d", counter);
-   sh.data = gtk_object_get_data(GTK_OBJECT(widget), text);
-   snprintf(text, 100, "_dw_sigcid%d", counter);
-   sh.cid = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(widget), text));
-
+static SignalHandler _get_signal_handler(gpointer data)
+{
+   SignalHandler sh = {0};
+   
+   if(data)
+   {
+      void **params = (void **)data;
+      int counter = GPOINTER_TO_INT(params[0]);
+      GtkWidget *widget = (GtkWidget *)params[2];
+      char text[101] = {0};
+
+      snprintf(text, 100, "_dw_sigwindow%d", counter);
+      sh.window = (HWND)gtk_object_get_data(GTK_OBJECT(widget), text);
+      snprintf(text, 100, "_dw_sigfunc%d", counter);
+      sh.func = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
+      snprintf(text, 100, "_dw_intfunc%d", counter);
+      sh.intfunc = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
+      snprintf(text, 100, "_dw_sigdata%d", counter);
+      sh.data = gtk_object_get_data(GTK_OBJECT(widget), text);
+      snprintf(text, 100, "_dw_sigcid%d", counter);
+      sh.cid = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(widget), text));
+   }
    return sh;
 }
 
@@ -1292,7 +1298,7 @@
 
 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)window, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1307,7 +1313,7 @@
 
 static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1328,7 +1334,7 @@
 
 static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1349,7 +1355,7 @@
 
 static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1382,7 +1388,7 @@
 
 static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1397,7 +1403,7 @@
 
 static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1417,7 +1423,7 @@
 
 static gint _generic_event(GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1432,7 +1438,7 @@
 
 static gint _activate_event(GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1448,7 +1454,7 @@
 
 static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1463,7 +1469,7 @@
 
 static gint _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1483,7 +1489,7 @@
 
 static gint _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    static int _dw_recursing = 0;
    int retval = FALSE;
 
@@ -1528,7 +1534,7 @@
 
 static gint _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1551,7 +1557,7 @@
 
 static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1614,7 +1620,7 @@
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
    if(widget)
    {
-      SignalHandler work = _get_signal_handler(widget, data);
+      SignalHandler work = _get_signal_handler(data);
 
       if(work.window)
       {
@@ -1636,7 +1642,7 @@
 
 static gint _tree_expand_event(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1650,7 +1656,7 @@
 #else
 static gint _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)tree, data);
+   SignalHandler work = _get_signal_handler(data);
    GtkWidget *treeroot = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(child), "_dw_tree");
    int retval = FALSE;
 
@@ -1675,7 +1681,7 @@
 
 static gint _tree_expand_event(GtkTreeItem *treeitem, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)treeitem, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1690,7 +1696,7 @@
 
 static gint _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1714,7 +1720,7 @@
 
 static gint _container_enter_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1750,7 +1756,7 @@
 
 static gint _switch_page_event(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)notebook, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1764,7 +1770,7 @@
 
 static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
@@ -1778,7 +1784,7 @@
 
 static gint _container_select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    char *rowdata = gtk_clist_get_row_data(GTK_CLIST(widget), row);
    int (*contextfunc)(HWND, HWND, char *, void *, void *) = work.func;
 
@@ -1819,7 +1825,7 @@
 
    if (slider || spinbutton || scrollbar)
    {
-      SignalHandler work = _get_signal_handler((GtkWidget *)adjustment, data);
+      SignalHandler work = _get_signal_handler(data);
 
       if (work.window)
       {
@@ -6212,14 +6218,24 @@
    {
       void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_item_expand_func");
       void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_item_expand_data");
-      SignalHandler work = _get_signal_handler(tree, mydata);
+      void **params = calloc(sizeof(void *), 3):
+      SignalHandler work;
+      
+      params[0] = mydata;
+      params[2] = (void *)tree;
+      work = _get_signal_handler(mydata);
 
       if(thisfunc && work.window)
       {
-         int sigid = _set_signal_handler(newitem, work.window, work.func, work.data, thisfunc);
-         gint cid =gtk_signal_connect(GTK_OBJECT(newitem), "expand", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+         gint sigid = _set_signal_handler(newitem, work.window, work.func, work.data, thisfunc);
+         pointer[0] = GINT_TO_POINTER(sigid);
+         gint cid = g_signal_connect_data(G_OBJECT(newitem), "expand", G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
          _set_signal_handler_id(newitem, sigid, cid);
       }
+      else
+      {
+         free(params);
+      }
    }
 
    _dw_ignore_expand = 1;
@@ -6230,7 +6246,7 @@
       {
          void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_func");
          void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_data");
-         SignalHandler work = _get_signal_handler(tree, mydata);
+         SignalHandler work = _get_signal_handler(mydata);
 
          subtree = gtk_tree_new();
 
@@ -6243,7 +6259,7 @@
 
          thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_func");
          mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_data");
-         work = _get_signal_handler(tree, mydata);
+         work = _get_signal_handler(mydata);
 
          if(thisfunc && work.window)
          {
@@ -6358,12 +6374,18 @@
    {
       void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_item_expand_func");
       void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_item_expand_data");
-      SignalHandler work = _get_signal_handler(tree, mydata);
+      void **params = calloc(sizeof(void *), 3):
+      SignalHandler work;
+      
+      params[0] = mydata;
+      params[2] = (void *)tree;
+      work = _get_signal_handler(mydata);
 
       if(thisfunc && work.window)
       {
-         int sigid = _set_signal_handler(item, work.window, work.func, work.data, thisfunc);
-         gint cid =gtk_signal_connect(GTK_OBJECT(item), "expand", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+         gint sigid = _set_signal_handler(item, work.window, work.func, work.data, thisfunc);
+         params[0] = GINT_TO_POINTER(sigid);
+         gint cid = g_signal_connect_data(G_OBJECT(item), "expand", G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
          _set_signal_handler_id(item, sigid, cid);
       }
    }
@@ -6376,7 +6398,7 @@
       {
          void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_func");
          void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_data");
-         SignalHandler work = _get_signal_handler(tree, mydata);
+         SignalHandler work = _get_signal_handler(mydata);
 
          subtree = gtk_tree_new();
 
@@ -6389,7 +6411,7 @@
 
          thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_func");
          mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_data");
-         work = _get_signal_handler(tree, mydata);
+         work = _get_signal_handler(mydata);
 
          if(thisfunc && work.window)
          {
@@ -13466,6 +13488,29 @@
    return thiswindow;
 }
 
+/* Internal function to free any allocated signal data..
+ * and call any required function to free additional memory.
+ */
+static void _dw_signal_disconnect(gpointer data, GClosure *closure)
+{
+   if(data)
+   {
+      void **params = (void **)data;
+      void (*discfunc)(HWND, void *) = params[1];
+
+      if(discfunc)
+      {
+         SignalHandler work = _get_signal_handler(data);
+         
+         if(work.window)
+         {
+            discfunc(work.window, work.data);
+         }
+      }
+      free(data);
+   }
+}
+
 /*
  * Add a callback to a window event.
  * Parameters:
@@ -13476,12 +13521,30 @@
  */
 void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
+   dw_signal_connect_data(window, signame, sigfunc, NULL, data);
+}
+
+/*
+ * Add a callback to a window event with a closure callback.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       discfunc: The pointer to the function called when this handler is removed.
+ *       data: User data to be passed to the handler function.
+ */
+void dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data)
+{
    void *thisfunc  = _findsigfunc(signame);
    char *thisname = signame;
    HWND thiswindow = window;
    int sigid, _locked_by_me = FALSE;
+   void **params = calloc(3, sizeof(void *));
    gint cid;
 
+   /* Save the disconnect function pointer */
+   params[1] = discfunc;
+
    DW_MUTEX_LOCK;
    /*
     * If the window we are setting the signal on is a scrolled window we need to get
@@ -13508,7 +13571,7 @@
       thisfunc = _findsigfunc("tree-context");
 
       sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
-      cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), GINT_TO_POINTER(sigid));
+      cid = g_signal_connect_data(G_OBJECT(thiswindow), "button_press_event", G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
       _set_signal_handler_id(thiswindow, sigid, cid);
 
 #if 0
@@ -13528,7 +13591,9 @@
       thisname = "changed";
 
       sigid = _set_signal_handler(treeview, window, sigfunc, data, thisfunc);
-      cid = g_signal_connect(G_OBJECT(thiswindow), thisname, (GCallback)thisfunc, GINT_TO_POINTER(sigid));
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
+      cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, (GCallback)thisfunc, params, _dw_signal_disconnect, 0);
       _set_signal_handler_id(treeview, sigid, cid);
       DW_MUTEX_UNLOCK;
       return;
@@ -13542,13 +13607,18 @@
    {
       thisfunc = _findsigfunc("tree-context");
       sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
-
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
       gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_container_context_func", (gpointer)thisfunc);
-      gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_container_context_data", GINT_TO_POINTER(sigid));
-      cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), GINT_TO_POINTER(sigid));
+      gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_container_context_data", params);
+      cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), params);
       _set_signal_handler_id(thiswindow, sigid, cid);
+      
+      params = calloc(sizeof(void *), 3);
       sigid = _set_signal_handler(window, window, sigfunc, data, thisfunc);
-      cid = gtk_signal_connect(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), GINT_TO_POINTER(sigid));
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
+      cid = gtk_signal_connect(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), params);
       _set_signal_handler_id(window, sigid, cid);
       DW_MUTEX_UNLOCK;
       return;
@@ -13558,6 +13628,7 @@
       if(thisfunc)
       {
          sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+         params[0] = GINT_TO_POINTER(sigid);
          gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_select_child_func", (gpointer)thisfunc);
          gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_select_child_data", GINT_TO_POINTER(sigid));
       }
@@ -13578,7 +13649,9 @@
    else if (GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_ENTER) == 0)
    {
       sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event);
-      cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "key_press_event", GTK_SIGNAL_FUNC(_container_enter_event), GINT_TO_POINTER(sigid));
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
+      cid = g_signal_connect_data(G_OBJECT(thiswindow), "key_press_event", G_CALLBACK(_container_enter_event), params, _dw_signal_disconnect, 0);
       _set_signal_handler_id(thiswindow, sigid, cid);
 
       thisname = "button_press_event";
@@ -13634,7 +13707,9 @@
    }
 
    sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
-   cid = gtk_signal_connect(GTK_OBJECT(thiswindow), thisname, GTK_SIGNAL_FUNC(thisfunc),GINT_TO_POINTER(sigid));
+   params[0] = GINT_TO_POINTER(sigid);
+   params[2] = (void *)thiswindow;
+   cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
    _set_signal_handler_id(thiswindow, sigid, cid);
    DW_MUTEX_UNLOCK;
 }
@@ -13646,22 +13721,25 @@
  */
 void dw_signal_disconnect_by_name(HWND window, char *signame)
 {
-   HWND thiswindow;
    int z, count;
    void *thisfunc;
    int _locked_by_me = FALSE;
-
-   DW_MUTEX_LOCK;
-   thiswindow = _find_signal_window(window, signame);
-   count = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_sigcounter"));
-   thisfunc  = _findsigfunc(signame);
+   void **params = alloca(sizeof(void *) * 3);
+
+   DW_MUTEX_LOCK;
+   params[2] = _find_signal_window(window, signame);
+   count = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(params[2]), "_dw_sigcounter"));
+   thisfunc = _findsigfunc(signame);
 
    for(z=0;z<count;z++)
    {
-      SignalHandler sh = _get_signal_handler(thiswindow, GINT_TO_POINTER(z));
+      SignalHandler sh;
+      
+      params[0] = GINT_TO_POINTER(z);
+      sh = _get_signal_handler(params);
 
       if(sh.intfunc == thisfunc)
-         _remove_signal_handler(thiswindow, z);
+         _remove_signal_handler((HWND)params[2], z);
    }
    DW_MUTEX_UNLOCK;
 }
@@ -13695,20 +13773,23 @@
  */
 void dw_signal_disconnect_by_data(HWND window, void *data)
 {
-   HWND thiswindow;
    int z, count;
    int _locked_by_me = FALSE;
-
-   DW_MUTEX_LOCK;
-   thiswindow = _find_signal_window(window, NULL);
-   count = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_sigcounter"));
+   void **params = alloca(sizeof(void *) * 3);
+
+   DW_MUTEX_LOCK;
+   params[2] = _find_signal_window(window, NULL);
+   count = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(params[2]), "_dw_sigcounter"));
 
    for(z=0;z<count;z++)
    {
-      SignalHandler sh = _get_signal_handler(thiswindow, GINT_TO_POINTER(z));
+      SignalHandler sh;
+      
+      params[0] = GINT_TO_POINTER(z);
+      sh = _get_signal_handler(params);
 
       if(sh.data == data)
-         _remove_signal_handler(thiswindow, z);
+         _remove_signal_handler((HWND)params[2], z);
    }
    DW_MUTEX_UNLOCK;
 }
--- a/gtk3/dw.c	Fri Feb 15 09:22:56 2013 +0000
+++ b/gtk3/dw.c	Wed Feb 27 19:14:22 2013 +0000
@@ -3,7 +3,7 @@
  *          A GTK like cross-platform GUI
  *          GTK3 forwarder module for portabilty.
  *
- * (C) 2000-2012 Brian Smith <brian@dbsoft.org>
+ * (C) 2000-2013 Brian Smith <brian@dbsoft.org>
  * (C) 2003-2011 Mark Hessling <mark@rexx.org>
  * (C) 2002 Nickolay V. Shmyrev <shmyrev@yandex.ru>
  */
@@ -152,6 +152,8 @@
 static gint _tree_expand_event(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer data);
 static gint _switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data);
 static gint _column_click_event(GtkWidget *widget, gpointer data);
+static void _dw_signal_disconnect(gpointer data, GClosure *closure);
+
 
 #ifdef USE_WEBKIT
 /*
@@ -1083,23 +1085,28 @@
    return NULL;
 }
 
-static SignalHandler _get_signal_handler(GtkWidget *widget, gpointer data)
-{
-   int counter = GPOINTER_TO_INT(data);
-   SignalHandler sh;
-   char text[100];
-
-   sprintf(text, "_dw_sigwindow%d", counter);
-   sh.window = (HWND)g_object_get_data(G_OBJECT(widget), text);
-   sprintf(text, "_dw_sigfunc%d", counter);
-   sh.func = (void *)g_object_get_data(G_OBJECT(widget), text);
-   sprintf(text, "_dw_intfunc%d", counter);
-   sh.intfunc = (void *)g_object_get_data(G_OBJECT(widget), text);
-   sprintf(text, "_dw_sigdata%d", counter);
-   sh.data = g_object_get_data(G_OBJECT(widget), text);
-   sprintf(text, "_dw_sigcid%d", counter);
-   sh.cid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), text));
-
+static SignalHandler _get_signal_handler(gpointer data)
+{
+   SignalHandler sh = {0};
+   
+   if(data)
+   {
+      void **params = (void **)data;
+      int counter = GPOINTER_TO_INT(params[0]);
+      GtkWidget *widget = (GtkWidget *)params[2];
+      char text[100];
+
+      sprintf(text, "_dw_sigwindow%d", counter);
+      sh.window = (HWND)g_object_get_data(G_OBJECT(widget), text);
+      sprintf(text, "_dw_sigfunc%d", counter);
+      sh.func = (void *)g_object_get_data(G_OBJECT(widget), text);
+      sprintf(text, "_dw_intfunc%d", counter);
+      sh.intfunc = (void *)g_object_get_data(G_OBJECT(widget), text);
+      sprintf(text, "_dw_sigdata%d", counter);
+      sh.data = g_object_get_data(G_OBJECT(widget), text);
+      sprintf(text, "_dw_sigcid%d", counter);
+      sh.cid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), text));
+   }
    return sh;
 }
 
@@ -1122,7 +1129,7 @@
    g_object_set_data(G_OBJECT(widget), text, NULL);
 }
 
-static int _set_signal_handler(GtkWidget *widget, HWND window, void *func, gpointer data, void *intfunc)
+static int _set_signal_handler(GtkWidget *widget, HWND window, void *func, gpointer data, void *intfunc, void *discfunc)
 {
    int counter = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "_dw_sigcounter"));
    char text[100];
@@ -1133,6 +1140,8 @@
    g_object_set_data(G_OBJECT(widget), text, (gpointer)func);
    sprintf(text, "_dw_intfunc%d", counter);
    g_object_set_data(G_OBJECT(widget), text, (gpointer)intfunc);
+   sprintf(text, "_dw_discfunc%d", counter);
+   g_object_set_data(G_OBJECT(widget), text, (gpointer)discfunc);
    sprintf(text, "_dw_sigdata%d", counter);
    g_object_set_data(G_OBJECT(widget), text, (gpointer)data);
 
@@ -1152,7 +1161,7 @@
 
 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)window, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1166,7 +1175,7 @@
 
 static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1186,7 +1195,7 @@
 
 static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1206,7 +1215,7 @@
 
 static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1238,7 +1247,7 @@
 
 static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1252,7 +1261,7 @@
 
 static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1271,7 +1280,7 @@
 
 static gint _generic_event(GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1285,7 +1294,7 @@
 
 static gint _activate_event(GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window && !_dw_ignore_click)
@@ -1300,7 +1309,7 @@
 
 static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1314,7 +1323,7 @@
 
 static gint _expose_event(GtkWidget *widget, cairo_t *cr, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1332,7 +1341,7 @@
 
 static gint _combobox_select_event(GtkWidget *widget, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(g_object_get_data(G_OBJECT(widget), "_dw_recursing"))
@@ -1375,7 +1384,7 @@
 
 static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1442,7 +1451,7 @@
 
    if(widget)
    {
-      SignalHandler work = _get_signal_handler(widget, data);
+      SignalHandler work = _get_signal_handler(data);
 
       if(work.window)
       {
@@ -1532,7 +1541,7 @@
 
 static gint _tree_expand_event(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)widget, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(!_dw_ignore_expand && work.window)
@@ -1545,7 +1554,7 @@
 
 static gint _container_enter_event(GtkWidget *widget, GdkEventAny *event, gpointer data)
 {
-   SignalHandler work = _get_signal_handler(widget, data);
+   SignalHandler work = _get_signal_handler(data);
    GdkEventKey *keyevent = (GdkEventKey *)event;
    GdkEventButton *buttonevent = (GdkEventButton *)event;
    int retval = FALSE;
@@ -1613,7 +1622,7 @@
 
 static gint _switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data)
 {
-   SignalHandler work = _get_signal_handler((GtkWidget *)notebook, data);
+   SignalHandler work = _get_signal_handler(data);
    int retval = FALSE;
 
    if(work.window)
@@ -1626,20 +1635,27 @@
 
 static gint _column_click_event(GtkWidget *widget, gpointer data)
 {
-   GtkWidget *tree = data;
-   gint handlerdata = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tree), "_dw_column_click_id"));
-   SignalHandler work;
+   void **params = data;
    int retval = FALSE;
-
-   if(handlerdata)
-   {
-      work = _get_signal_handler(tree, GINT_TO_POINTER(handlerdata-1));
-
-      if(work.window)
-      {
-         int column_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "_dw_column"));
-         int (*clickcolumnfunc)(HWND, int, void *) = work.func;
-         retval = clickcolumnfunc(work.window, column_num, work.data);
+   
+   if(params && params[2])
+   {
+      GtkWidget *tree = (GtkWidget *)params[2];
+      gint handlerdata = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tree), "_dw_column_click_id"));
+
+      if(handlerdata)
+      {
+         SignalHandler work;
+         
+         params[0] = GINT_TO_POINTER(handlerdata-1);
+         work = _get_signal_handler(params);
+
+         if(work.window)
+         {
+            int column_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "_dw_column"));
+            int (*clickcolumnfunc)(HWND, int, void *) = work.func;
+            retval = clickcolumnfunc(work.window, column_num, work.data);
+         }
       }
    }
    return retval;
@@ -1676,7 +1692,7 @@
 
    if (slider || spinbutton || scrollbar)
    {
-      SignalHandler work = _get_signal_handler(widget, data);
+      SignalHandler work = _get_signal_handler(data);
 
       if (work.window)
       {
@@ -5526,6 +5542,7 @@
       g_object_set_data(G_OBJECT(tree), numbuf, GINT_TO_POINTER(flags[z]));
       col = gtk_tree_view_column_new();
       rend = NULL;
+      void **params = calloc(sizeof(void *), 3);
 
       if(z == 0 && flags[z] & DW_CFA_STRINGANDICON)
       {
@@ -5571,7 +5588,8 @@
          gtk_tree_view_column_set_resizable(col, TRUE);
       }
       g_object_set_data(G_OBJECT(col), "_dw_column", GINT_TO_POINTER(z));
-      g_signal_connect(G_OBJECT(col), "clicked", G_CALLBACK(_column_click_event), (gpointer)tree);
+      params[2] = tree;
+      g_signal_connect_data(G_OBJECT(col), "clicked", G_CALLBACK(_column_click_event), (gpointer)params, _dw_signal_disconnect, 0);
       gtk_tree_view_column_set_title(col, titles[z]);
       if(flags[z] & DW_CFA_RIGHT)
       {
@@ -11191,11 +11209,52 @@
  */
 void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
+   dw_signal_connect_data(window, signame, sigfunc, NULL, data); 
+}
+
+/* Internal function to free any allocated signal data..
+ * and call any required function to free additional memory.
+ */
+static void _dw_signal_disconnect(gpointer data, GClosure *closure)
+{
+   if(data)
+   {
+      void **params = (void **)data;
+      void (*discfunc)(HWND, void *) = params[1];
+
+      if(discfunc)
+      {
+         SignalHandler work = _get_signal_handler(data);
+         
+         if(work.window)
+         {
+            discfunc(work.window, work.data);
+         }
+      }
+      free(data);
+   }
+}
+
+/*
+ * Add a callback to a window event with a closure callback.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       discfunc: The pointer to the function called when this handler is removed.
+ *       data: User data to be passed to the handler function.
+ */
+void dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data)
+{
    void *thisfunc  = _findsigfunc(signame);
    char *thisname = signame;
    HWND thiswindow = window;
    int sigid, _locked_by_me = FALSE;
+   void **params = calloc(3, sizeof(void *));
    gint cid;
+   
+   /* Save the disconnect function pointer */
+   params[1] = discfunc;
 
    DW_MUTEX_LOCK;
    /*
@@ -11218,8 +11277,10 @@
    }
    else if (GTK_IS_TREE_VIEW(thiswindow)  && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
    {
-      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
-      cid = g_signal_connect(G_OBJECT(thiswindow), "button_press_event", G_CALLBACK(thisfunc), GINT_TO_POINTER(sigid));
+      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc, discfunc);
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
+      cid = g_signal_connect_data(G_OBJECT(thiswindow), "button_press_event", G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
       _set_signal_handler_id(thiswindow, sigid, cid);
 
       DW_MUTEX_UNLOCK;
@@ -11232,15 +11293,17 @@
 
       thisname = "changed";
 
-      sigid = _set_signal_handler(widget, window, sigfunc, data, thisfunc);
+      sigid = _set_signal_handler(widget, window, sigfunc, data, thisfunc, discfunc);
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
       if(GTK_IS_TREE_VIEW(thiswindow))
       {
          thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow));
-         cid = g_signal_connect(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), GINT_TO_POINTER(sigid));
+         cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
       }
       else
       {
-         cid = g_signal_connect(G_OBJECT(thiswindow), thisname, G_CALLBACK(_combobox_select_event), GINT_TO_POINTER(sigid));
+         cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(_combobox_select_event), params, _dw_signal_disconnect, 0);
       }
       _set_signal_handler_id(widget, sigid, cid);
 
@@ -11253,9 +11316,13 @@
    }
    else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_ENTER) == 0)
    {
-      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event);
-      cid = g_signal_connect(G_OBJECT(thiswindow), "key_press_event", G_CALLBACK(_container_enter_event), GINT_TO_POINTER(sigid));
+      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event, discfunc);
+      params[0] = GINT_TO_POINTER(sigid);
+      params[2] = (void *)thiswindow;
+      cid = g_signal_connect_data(G_OBJECT(thiswindow), "key_press_event", G_CALLBACK(_container_enter_event), params, _dw_signal_disconnect, 0);
       _set_signal_handler_id(thiswindow, sigid, cid);
+      
+      params = calloc(sizeof(void *), 3);
 
       thisname = "button_press_event";
       thisfunc = _findsigfunc(DW_SIGNAL_ITEM_ENTER);
@@ -11265,7 +11332,7 @@
       /* We don't actually need a signal handler here... just need to assign the handler ID
        * Since the handlers for the columns were already created in _dw_container_setup()
        */
-      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _column_click_event);
+      sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _column_click_event, discfunc);
       g_object_set_data(G_OBJECT(thiswindow), "_dw_column_click_id", GINT_TO_POINTER(sigid+1));
       DW_MUTEX_UNLOCK;
       return;
@@ -11295,12 +11362,15 @@
 
    if (!thisfunc || !thiswindow)
    {
+      free(params);
       DW_MUTEX_UNLOCK;
       return;
    }
 
-   sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
-   cid = g_signal_connect(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc),GINT_TO_POINTER(sigid));
+   sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc, discfunc);
+   params[0] = GINT_TO_POINTER(sigid);
+   params[2] = (void *)thiswindow;
+   cid = g_signal_connect_data(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc), params, _dw_signal_disconnect, 0);
    _set_signal_handler_id(thiswindow, sigid, cid);
    DW_MUTEX_UNLOCK;
 }
@@ -11312,22 +11382,25 @@
  */
 void dw_signal_disconnect_by_name(HWND window, char *signame)
 {
-   HWND thiswindow;
    int z, count;
    void *thisfunc;
    int _locked_by_me = FALSE;
-
-   DW_MUTEX_LOCK;
-   thiswindow = _find_signal_window(window, signame);
-   count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(thiswindow), "_dw_sigcounter"));
-   thisfunc  = _findsigfunc(signame);
+   void **params = alloca(sizeof(void *) * 3);
+
+   DW_MUTEX_LOCK;
+   params[2] = _find_signal_window(window, signame);
+   count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(params[2]), "_dw_sigcounter"));
+   thisfunc = _findsigfunc(signame);
 
    for(z=0;z<count;z++)
    {
-      SignalHandler sh = _get_signal_handler(thiswindow, GINT_TO_POINTER(z));
+      SignalHandler sh;
+      
+      params[0] = GINT_TO_POINTER(z);
+      sh = _get_signal_handler(params);
 
       if(sh.intfunc == thisfunc)
-         _remove_signal_handler(thiswindow, z);
+         _remove_signal_handler((HWND)params[2], z);
    }
    DW_MUTEX_UNLOCK;
 }
@@ -11361,20 +11434,23 @@
  */
 void dw_signal_disconnect_by_data(HWND window, void *data)
 {
-   HWND thiswindow;
    int z, count;
    int _locked_by_me = FALSE;
-
-   DW_MUTEX_LOCK;
-   thiswindow = _find_signal_window(window, NULL);
-   count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(thiswindow), "_dw_sigcounter"));
+   void **params = alloca(sizeof(void *) * 3);
+
+   DW_MUTEX_LOCK;
+   params[2] = _find_signal_window(window, NULL);
+   count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(params[2]), "_dw_sigcounter"));
 
    for(z=0;z<count;z++)
    {
-      SignalHandler sh = _get_signal_handler(thiswindow, GINT_TO_POINTER(z));
+      SignalHandler sh;
+      
+      params[0] = GINT_TO_POINTER(z);
+      sh = _get_signal_handler(params);
 
       if(sh.data == data)
-         _remove_signal_handler(thiswindow, z);
+         _remove_signal_handler((HWND)params[2], z);
    }
    DW_MUTEX_UNLOCK;
 }
--- a/mac/dw.m	Fri Feb 15 09:22:56 2013 +0000
+++ b/mac/dw.m	Wed Feb 27 19:14:22 2013 +0000
@@ -2,7 +2,7 @@
  * Dynamic Windows:
  *          A GTK like implementation of the MacOS GUI using Cocoa
  *
- * (C) 2011-2012 Brian Smith <brian@dbsoft.org>
+ * (C) 2011-2013 Brian Smith <brian@dbsoft.org>
  * (C) 2011 Mark Hessling <mark@rexx.org>
  *
  * Requires 10.5 or later.
@@ -145,6 +145,7 @@
     HWND window;
     int id;
     void *signalfunction;
+    void *discfunction;
     void *data;
 
 } SignalHandler;
@@ -2627,7 +2628,7 @@
 
 /* This function adds a signal handler callback into the linked list.
  */
-void _new_signal(ULONG message, HWND window, int msgid, void *signalfunction, void *data)
+void _new_signal(ULONG message, HWND window, int msgid, void *signalfunction, void *discfunc, void *data)
 {
     SignalHandler *new = malloc(sizeof(SignalHandler));
 
@@ -2635,6 +2636,7 @@
     new->window = window;
     new->id = msgid;
     new->signalfunction = signalfunction;
+    new->discfunction = discfunc;
     new->data = data;
     new->next = NULL;
 
@@ -9854,7 +9856,7 @@
     {
         NSTimeInterval seconds = (double)interval / 1000.0;
         NSTimer *thistimer = DWTimers[z] = [NSTimer scheduledTimerWithTimeInterval:seconds target:DWHandler selector:@selector(runTimer:) userInfo:nil repeats:YES];
-        _new_signal(0, thistimer, z+1, sigfunc, data);
+        _new_signal(0, thistimer, z+1, sigfunc, NULL, data);
         return z+1;
     }
     return 0;
@@ -9914,6 +9916,20 @@
  */
 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
+    dw_signal_connect_data(window, signame, sigfunc, NULL, data);
+}
+
+/*
+ * Add a callback to a window event with a closure callback.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       discfunc: The pointer to the function called when this handler is removed.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data)
+{
     ULONG message = 0, msgid = 0;
     
     /* Handle special case of application delete signal */
@@ -9926,7 +9942,7 @@
     {
         if((message = _findsigmessage(signame)) != 0)
         {
-            _new_signal(message, window, (int)msgid, sigfunc, data);
+            _new_signal(message, window, (int)msgid, sigfunc, discfunc, data);
         }
     }
 }
@@ -9948,6 +9964,13 @@
     {
         if(tmp->window == window && tmp->message == message)
         {
+            void (*discfunc)(HWND, void *) = tmp->discfunction;
+            
+            if(discfunc)
+            {
+                discfunc(tmp->window, tmp->data);
+            }
+            
             if(prev)
             {
                 prev->next = tmp->next;
@@ -9982,6 +10005,13 @@
     {
         if(tmp->window == window)
         {
+            void (*discfunc)(HWND, void *) = tmp->discfunction;
+            
+            if(discfunc)
+            {
+                discfunc(tmp->window, tmp->data);
+            }
+            
             if(prev)
             {
                 prev->next = tmp->next;
@@ -10017,6 +10047,13 @@
     {
         if(tmp->window == window && tmp->data == data)
         {
+            void (*discfunc)(HWND, void *) = tmp->discfunction;
+            
+            if(discfunc)
+            {
+                discfunc(tmp->window, tmp->data);
+            }
+            
             if(prev)
             {
                 prev->next = tmp->next;
--- a/os2/dw.c	Fri Feb 15 09:22:56 2013 +0000
+++ b/os2/dw.c	Wed Feb 27 19:14:22 2013 +0000
@@ -166,6 +166,7 @@
    HWND window;
    int id;
    void *signalfunction;
+   void *discfunction;
    void *data;
 
 } SignalHandler;
@@ -216,7 +217,7 @@
 
 /* This function adds a signal handler callback into the linked list.
  */
-void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
+void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data)
 {
    SignalHandler *new = malloc(sizeof(SignalHandler));
 
@@ -224,6 +225,7 @@
    new->window = window;
    new->id = id;
    new->signalfunction = signalfunction;
+   new->discfunction = discfunc;
    new->data = data;
    new->next = NULL;
 
@@ -13210,7 +13212,7 @@
 
       if(timerid)
       {
-         _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data);
+         _new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, NULL, data);
          return timerid;
       }
    }
@@ -13267,6 +13269,20 @@
  */
 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
+    dw_signal_connect_data(window, signame, sigfunc, NULL, data);
+}
+
+/*
+ * Add a callback to a window event with a closure callback.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       discfunc: The pointer to the function called when this handler is removed.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data)
+{
    ULONG message = 0, id = 0;
 
    if(window && signame && sigfunc)
@@ -13291,7 +13307,7 @@
                window = owner;
             }
          }
-         _new_signal(message, window, id, sigfunc, data);
+         _new_signal(message, window, id, sigfunc, discfunc, data);
       }
    }
 }
@@ -13313,6 +13329,13 @@
    {
       if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->message == message)
       {
+         void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
          if(prev)
          {
             prev->next = tmp->next;
@@ -13347,6 +13370,13 @@
    {
       if((window < 65536 && tmp->id == window) || tmp->window == window)
       {
+         void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
          if(prev)
          {
             prev->next = tmp->next;
@@ -13382,6 +13412,13 @@
    {
       if(((window < 65536 && tmp->id == window) || tmp->window == window) && tmp->data == data)
       {
+         void (API_FUNC discfunc)(HWND, void *) = (void (API_FUNC)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
          if(prev)
          {
             prev->next = tmp->next;
--- a/win/dw.c	Fri Feb 15 09:22:56 2013 +0000
+++ b/win/dw.c	Wed Feb 27 19:14:22 2013 +0000
@@ -2,7 +2,7 @@
  * Dynamic Windows:
  *          A GTK like implementation of the Win32 GUI
  *
- * (C) 2000-2012 Brian Smith <brian@dbsoft.org>
+ * (C) 2000-2013 Brian Smith <brian@dbsoft.org>
  * (C) 2003-2011 Mark Hessling <mark@rexx.org>
  *
  */
@@ -336,6 +336,7 @@
    HWND window;
    int id;
    void *signalfunction;
+   void *discfunction;
    void *data;
 
 } SignalHandler;
@@ -667,7 +668,7 @@
 
 /* This function adds a signal handler callback into the linked list.
  */
-void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
+void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *discfunc, void *data)
 {
    SignalHandler *new = malloc(sizeof(SignalHandler));
 
@@ -675,6 +676,7 @@
    new->window = window;
    new->id = id;
    new->signalfunction = signalfunction;
+   new->discfunction = discfunc;
    new->data = data;
    new->next = NULL;
 
@@ -12250,7 +12252,7 @@
 
       if(timerid)
       {
-         _new_signal(WM_TIMER, NULL, timerid, sigfunc, data);
+         _new_signal(WM_TIMER, NULL, timerid, sigfunc, NULL, data);
          return timerid;
       }
    }
@@ -12307,6 +12309,20 @@
  */
 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
+    dw_signal_connect_data(window, signame, sigfunc, NULL, data);
+}
+
+/*
+ * Add a callback to a window event with a closure callback.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       discfunc: The pointer to the function called when this handler is removed.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_signal_connect_data(HWND window, char *signame, void *sigfunc, void *discfunc, void *data)
+{
    ULONG message = 0, id = 0;
 
    if (window && signame && sigfunc)
@@ -12334,7 +12350,7 @@
                window = owner;
             }
          }
-         _new_signal(message, window, id, sigfunc, data);
+         _new_signal(message, window, id, sigfunc, discfunc, data);
       }
    }
 }
@@ -12356,7 +12372,14 @@
    {
       if(((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window) && tmp->message == message)
       {
-        if(prev)
+         void (*discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
+         if(prev)
          {
             prev->next = tmp->next;
             free(tmp);
@@ -12390,6 +12413,13 @@
    {
       if((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window)
       {
+         void (*discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
          if(prev)
          {
             prev->next = tmp->next;
@@ -12425,6 +12455,13 @@
    {
       if(((window < (HWND)65536 && (int)(intptr_t)window == tmp->id) || tmp->window == window) && tmp->data == data)
       {
+         void (*discfunc)(HWND, void *) = (void (*)(HWND, void *))tmp->discfunction;
+            
+         if(discfunc)
+         {
+             discfunc(tmp->window, tmp->data);
+         }
+         
         if(prev)
          {
             prev->next = tmp->next;