changeset 1884:71780cf68aa2

More container and tree changes on all platforms regarding memory. This should fix GTK3 memory leaks I wasn't previously aware of... but it will cause all platforms to leak memory if strings returned from dw_container_query_start(), dw_container_query_next() and dw_tree_get_title() are not freed with dw_free() when using version 3.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 28 Aug 2013 23:47:40 +0000
parents 0fecaedb83fa
children 0768bbcf67e5
files dwtest.c gtk/dw.c gtk3/dw.c os2/dw.c readme.txt win/dw.c
diffstat 6 files changed, 127 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/dwtest.c	Thu Aug 15 18:51:56 2013 +0000
+++ b/dwtest.c	Wed Aug 28 23:47:40 2013 +0000
@@ -802,6 +802,7 @@
     {
         sprintf(buf,"Selected: %s\r\n", str);
         mle_point = dw_mle_import( container_mle, buf, mle_point);
+        dw_free(str);
         str = dw_container_query_next(container, DW_CRA_SELECTED);
     }
     /* Make the last inserted point the cursor location */
--- a/gtk/dw.c	Thu Aug 15 18:51:56 2013 +0000
+++ b/gtk/dw.c	Wed Aug 28 23:47:40 2013 +0000
@@ -6573,6 +6573,12 @@
    if(tree && GTK_IS_TREE_VIEW(tree) &&
       (store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
       gtk_tree_model_get(store, (GtkTreeIter *)item, 0, &text, -1);
+   if(text)
+   {
+      char *temp = text;
+      text = strdup(temp);
+      g_free(temp);
+   }
 #else
    text = (char *)gtk_object_get_data(GTK_OBJECT(item), "_dw_text");
 #endif
@@ -7881,7 +7887,7 @@
    void *retval = NULL;
    int _locked_by_me = FALSE;
    int type = _DW_DATA_TYPE_STRING;
-   void **params;
+   void **params = NULL;
 
    if(flags & DW_CR_RETDATA)
        type = _DW_DATA_TYPE_POINTER;
@@ -7892,7 +7898,7 @@
    if(!clist)
    {
       DW_MUTEX_UNLOCK;
-      return NULL;
+      return retval;
    }
 
    /* These should be separate but right now this will work */
@@ -7904,19 +7910,23 @@
       {
          gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", GINT_TO_POINTER(1));
          params = (void **)gtk_clist_get_row_data(GTK_CLIST(clist), GPOINTER_TO_UINT(list->data));
-         retval = params ? params[type] : NULL;
       }
    }
    else if(flags & DW_CRA_CURSORED)
    {
       params = (void **)gtk_clist_get_row_data(GTK_CLIST(clist), GTK_CLIST(clist)->focus_row);
-      retval = params ? params[type] : NULL;
    }
    else
    {
       params = (void **)gtk_clist_get_row_data(GTK_CLIST(clist), 0);
       gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", GINT_TO_POINTER(1));
-      retval = params ? params[type] : NULL;
+   }
+   if(params)
+   {
+      if(type == _DW_DATA_TYPE_STRING && params[type])
+         retval = strdup((char *)params[type]);
+      else
+         retval = (char *)params[type];
    }
    DW_MUTEX_UNLOCK;
    return retval;
@@ -7937,7 +7947,7 @@
    void *retval = NULL;
    int _locked_by_me = FALSE;
    int type = _DW_DATA_TYPE_STRING;
-   void **params;
+   void **params = NULL;
    
    if(flags & DW_CR_RETDATA)
        type = _DW_DATA_TYPE_POINTER;
@@ -7948,7 +7958,7 @@
    if(!clist)
    {
       DW_MUTEX_UNLOCK;
-      return NULL;
+      return retval;
    }
 
    /* These should be separate but right now this will work */
@@ -7968,10 +7978,7 @@
          }
 
          if(list)
-         {
             params = (void **)gtk_clist_get_row_data(GTK_CLIST(clist), GPOINTER_TO_UINT(list->data));
-            retval = params ? params[type] : NULL;
-         }
       }
    }
    else if(flags & DW_CRA_CURSORED)
@@ -7987,7 +7994,13 @@
 
       params = (void **)gtk_clist_get_row_data(GTK_CLIST(clist), pos);
       gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", GINT_TO_POINTER(pos+1));
-      retval = params ? params[type] : NULL;
+   }
+   if(params)
+   {
+      if(type == _DW_DATA_TYPE_STRING && params[type])
+         retval = strdup((char *)params[type]);
+      else
+         retval = (char *)params[type];
    }
    DW_MUTEX_UNLOCK;
    return retval;
--- a/gtk3/dw.c	Thu Aug 15 18:51:56 2013 +0000
+++ b/gtk3/dw.c	Wed Aug 28 23:47:40 2013 +0000
@@ -1382,6 +1382,9 @@
    return retval;
 }
 
+#define _DW_DATA_TYPE_STRING  0
+#define _DW_DATA_TYPE_POINTER 1
+
 static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
 {
    SignalHandler work = _get_signal_handler(data);
@@ -1406,11 +1409,11 @@
             {
                if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_TREE))
                {
-                  gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, -1);
+                  gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, 2, &itemdata, -1);
                }
                else
                {
-                  gtk_tree_model_get(store, &iter, 0, &text, -1);
+                  gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, -1);
                }
             }
             else
@@ -1426,11 +1429,11 @@
                   {
                      if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_TREE))
                      {
-                        gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, -1);
+                        gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, 2, &itemdata, -1);
                      }
                      else
                      {
-                        gtk_tree_model_get(store, &iter, 0, &text, -1);
+                        gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, -1);
                      }
                   }
                   gtk_tree_path_free(path);
@@ -1439,6 +1442,8 @@
          }
 
          retval = contextfunc(work.window, text, event->x, event->y, work.data, itemdata);
+         if(text)
+            g_free(text);
       }
    }
    return retval;
@@ -1472,12 +1477,12 @@
          {
             if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_TREE))
             {
-               gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, 3, &item, -1);
+               gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, 2, &itemdata, 3, &item, -1);
                retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
             }
             else if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_CONTAINER))
             {
-               gtk_tree_model_get(store, &iter, 0, &text, 1, &itemdata, -1);
+               gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, _DW_DATA_TYPE_POINTER, &itemdata, -1);
                retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
             }
             else
@@ -1511,12 +1516,12 @@
                {
                   if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_TREE))
                   {
-                     gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, 3, &item, -1);
+                     gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, 2, &itemdata, 3, &item, -1);
                      retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
                   }
                   else if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_CONTAINER))
                   {
-                     gtk_tree_model_get(store, &iter, 0, &text, 1, &itemdata, -1);
+                     gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, _DW_DATA_TYPE_POINTER, &itemdata, -1);
                      retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
                   }
                   else
@@ -1534,6 +1539,8 @@
                gtk_tree_path_free(path);
             }
          }
+         if(text)
+            g_free(text);
       }
    }
    return retval;
@@ -1590,8 +1597,10 @@
                {
                   if(g_object_get_data(G_OBJECT(widget), "_dw_tree_type") == GINT_TO_POINTER(_DW_TREE_TYPE_CONTAINER))
                   {
-                     gtk_tree_model_get(store, &iter, 0, &text, 1, &data, -1);
+                     gtk_tree_model_get(store, &iter, _DW_DATA_TYPE_STRING, &text, _DW_DATA_TYPE_POINTER, &data, -1);
                      retval = contextfunc(work.window, text, work.data, data);
+                     if(text)
+                        g_free(text);
                   }
                }
                gtk_tree_path_free(path);
@@ -5260,7 +5269,13 @@
 
    if(tree && GTK_IS_TREE_VIEW(tree) &&
       (store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
-      gtk_tree_model_get(store, (GtkTreeIter *)item, 0, &text, -1);
+      gtk_tree_model_get(store, (GtkTreeIter *)item, _DW_DATA_TYPE_STRING, &text, -1);
+   if(text)
+   {
+      char *temp = text;
+      text = strdup(temp);
+      g_free(temp);
+   }
    DW_MUTEX_UNLOCK;
    return text;
 }
@@ -6141,9 +6156,6 @@
 }
 
 /* Internal version for both */
-#define _DW_DATA_TYPE_STRING  0
-#define _DW_DATA_TYPE_POINTER 1
-
 void _dw_container_set_row_data(HWND handle, void *pointer, int row, int type, void *data)
 {
    GtkWidget *cont = handle;
@@ -6393,6 +6405,7 @@
    GtkListStore *store = NULL;
    char *retval = NULL;
    int _locked_by_me = FALSE;
+   int type = flags & DW_CR_RETDATA ? _DW_DATA_TYPE_POINTER : _DW_DATA_TYPE_STRING;
 
    DW_MUTEX_LOCK;
    cont = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
@@ -6422,7 +6435,7 @@
 
                   if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, indices[0]))
                   {
-                     gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &retval, -1);
+                     gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, type, &retval, -1);
                      g_object_set_data(G_OBJECT(cont), "_dw_querypos", GINT_TO_POINTER(1));
                   }
                }
@@ -6442,7 +6455,7 @@
 
             if(gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
             {
-               gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &retval, -1);
+               gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, type, &retval, -1);
             }
             gtk_tree_path_free(path);
          }
@@ -6453,11 +6466,18 @@
 
          if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, 0))
          {
-            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &retval, -1);
+            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, type, &retval, -1);
             g_object_set_data(G_OBJECT(cont), "_dw_querypos", GINT_TO_POINTER(1));
          }
       }
    }
+   /* If there is a title, duplicate it and free the temporary copy */
+   if(retval && type == _DW_DATA_TYPE_STRING)
+   {
+      char *temp = retval;
+      retval = strdup(temp);
+      g_free(temp);
+   }
    DW_MUTEX_UNLOCK;
    return retval;
 }
@@ -6476,6 +6496,7 @@
    GtkListStore *store = NULL;
    char *retval = NULL;
    int _locked_by_me = FALSE;
+   int type = flags & DW_CR_RETDATA ? _DW_DATA_TYPE_POINTER : _DW_DATA_TYPE_STRING;
 
    DW_MUTEX_LOCK;
    cont = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
@@ -6509,7 +6530,7 @@
 
                   if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, indices[0]))
                   {
-                     gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &retval, -1);
+                     gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, type, &retval, -1);
                      g_object_set_data(G_OBJECT(cont), "_dw_querypos", GINT_TO_POINTER(pos+1));
                   }
                }
@@ -6531,11 +6552,18 @@
 
          if(pos < count && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, pos))
          {
-            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &retval, -1);
+            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, type, &retval, -1);
             g_object_set_data(G_OBJECT(cont), "_dw_querypos", GINT_TO_POINTER(pos+1));
          }
       }
    }
+   /* If there is a title, duplicate it and free the temporary copy */
+   if(retval && type == _DW_DATA_TYPE_STRING)
+   {
+      char *temp = retval;
+      retval = strdup(temp);
+      g_free(temp);
+   }
    DW_MUTEX_UNLOCK;
    return retval;
 }
@@ -6544,20 +6572,24 @@
 {
    int z, rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
    void *thisdata;
+   int retval = FALSE;
 
    for(z=0;z<rows;z++)
    {
       if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), iter, NULL, z))
       {
          /* Get either string from position 0 or pointer from position 1 */
-         gtk_tree_model_get(GTK_TREE_MODEL(store), iter, textcomp ? 0 : 1, &thisdata, -1);
+         gtk_tree_model_get(GTK_TREE_MODEL(store), iter, textcomp ? _DW_DATA_TYPE_STRING : _DW_DATA_TYPE_POINTER, &thisdata, -1);
          if((textcomp && thisdata && strcmp((char *)thisdata, (char *)data) == 0) || (!textcomp && thisdata == data))
          {
-            return TRUE;
+            retval = TRUE;
+            z = rows;
          }
-      }
-   }
-   return FALSE;
+         if(textcomp && thisdata)
+            g_free(thisdata);
+      }
+   }
+   return retval;
 }
 
 void _dw_container_cursor(HWND handle, void *data, int textcomp)
@@ -9990,8 +10022,12 @@
          {
             /* Get the text */
             gchar *text;
-            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &text, -1);
-            strncpy(buffer, text, length);
+            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, _DW_DATA_TYPE_STRING, &text, -1);
+            if(text)
+            {
+               strncpy(buffer, text, length);
+               g_free(text);
+            }
             DW_MUTEX_UNLOCK;
             return;
          }
--- a/os2/dw.c	Thu Aug 15 18:51:56 2013 +0000
+++ b/os2/dw.c	Wed Aug 28 23:47:40 2013 +0000
@@ -9182,8 +9182,8 @@
    PCNRITEM pci = (PCNRITEM)item;
 
    handle = handle; /* keep compiler happy */
-   if(pci)
-      return (char *)pci->rc.pszIcon;
+   if(pci && pci->rc.pszIcon)
+      return strdup((char *)pci->rc.pszIcon);
    return NULL;
 }
 
@@ -10288,7 +10288,9 @@
             if(pCore->flRecordAttr & flags)
             {
                dw_window_set_data(handle, "_dw_pcore", (void *)pCore);
-               return flags & DW_CR_RETDATA ? (char *)pCore->pszText : (char *)pCore->pszIcon;
+               if(flags & DW_CR_RETDATA)
+                  return (char *)pCore->pszText;
+               return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL;
             }
             pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
          }
@@ -10296,7 +10298,9 @@
       else
       {
          dw_window_set_data(handle, "_dw_pcore", (void *)pCore);
-         return flags & DW_CR_RETDATA ? (char *)pCore->pszText : (char *)pCore->pszIcon;
+         if(flags & DW_CR_RETDATA)
+            return (char *)pCore->pszText;
+         return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL;
       }
    }
    return NULL;
@@ -10325,7 +10329,9 @@
             if(pCore->flRecordAttr & flags)
             {
                dw_window_set_data(handle, "_dw_pcore", (void *)pCore);
-               return flags & DW_CR_RETDATA ? (char *)pCore->pszText : (char *)pCore->pszIcon;
+               if(flags & DW_CR_RETDATA)
+                  return (char *)pCore->pszText;
+               return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL;
             }
 
             pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
@@ -10334,7 +10340,9 @@
       else
       {
          dw_window_set_data(handle, "_dw_pcore", (void *)pCore);
-         return flags & DW_CR_RETDATA ? (char *)pCore->pszText : (char *)pCore->pszIcon;
+         if(flags & DW_CR_RETDATA)
+            return (char *)pCore->pszText;
+         return pCore->pszIcon ? strdup((char *)pCore->pszIcon) : NULL;
       }
    }
     return NULL;
--- a/readme.txt	Thu Aug 15 18:51:56 2013 +0000
+++ b/readme.txt	Wed Aug 28 23:47:40 2013 +0000
@@ -1,4 +1,4 @@
-This is a pre-release of Dynamic Windows version 2.6.
+This is a pre-release of Dynamic Windows version 3.0.
 
 The current Dynamic Windows source base is considered stable on:
 OS/2, Mac, Windows, Linux, FreeBSD and Solaris.
@@ -46,6 +46,10 @@
 Added DW_CR_RETDATA flag to dw_container_query_*() functions to return the
    data pointer instead of the string pointer, this may change in the future.
 Fixed some memory leaks.
+WARNING: Changed how tree and container titles are returned, they are now duplicated 
+   and need to be freed with dw_free().  This affects the following functions:
+   dw_tree_get_title(), dw_container_query_start() and dw_container_query_next()
+   You should audit any code using these functions for leaks if using verison 3.
 
 Dynamic Windows Documentation is available at:
 
--- a/win/dw.c	Thu Aug 15 18:51:56 2013 +0000
+++ b/win/dw.c	Wed Aug 28 23:47:40 2013 +0000
@@ -9644,9 +9644,10 @@
    int _index = ListView_GetNextItem(handle, -1, flags);
    void **params;
    int type = _DW_DATA_TYPE_STRING;
+   char *retval = NULL;
 
    if(_index == -1)
-      return NULL;
+      return retval;
       
    if(flags & DW_CR_RETDATA)
       type = _DW_DATA_TYPE_POINTER;
@@ -9658,9 +9659,17 @@
 
    ListView_GetItem(handle, &lvi);
    params = (void **)lvi.lParam;
+   
+   if(params)
+   {
+      if(type == _DW_DATA_TYPE_STRING && params[type])
+         retval = _strdup((char *)params[type]);
+      else
+         retval = (char *)params[type];
+   }
 
    dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER(_index));
-   return params ? (char *)params[type] : NULL;
+   return retval;
 }
 
 /*
@@ -9677,11 +9686,12 @@
    int _index = DW_POINTER_TO_INT(dw_window_get_data(handle, "_dw_index"));
    void **params;
    int type = _DW_DATA_TYPE_STRING;
+   char *retval = NULL;
 
    _index = ListView_GetNextItem(handle, _index, flags);
 
    if(_index == -1)
-      return NULL;
+      return retval;
 
    if(flags & DW_CR_RETDATA)
       type = _DW_DATA_TYPE_POINTER;
@@ -9694,8 +9704,16 @@
    ListView_GetItem(handle, &lvi);
    params = (void **)lvi.lParam;
 
+   if(params)
+   {
+      if(type == _DW_DATA_TYPE_STRING && params[type])
+         retval = _strdup((char *)params[type]);
+      else
+         retval = (char *)params[type];
+   }
+
    dw_window_set_data(handle, "_dw_index", DW_INT_TO_POINTER(_index));
-   return params ? (char *)params[type] : NULL;
+   return retval;
 }
 
 /*