# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1377733660 0 # Node ID 71780cf68aa2e4392dadb2d44796475e2ca033a0 # Parent 0fecaedb83fad1d3eee1cc632a4e43db60d332b7 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. diff -r 0fecaedb83fa -r 71780cf68aa2 dwtest.c --- 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 */ diff -r 0fecaedb83fa -r 71780cf68aa2 gtk/dw.c --- 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; diff -r 0fecaedb83fa -r 71780cf68aa2 gtk3/dw.c --- 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;zrc.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; diff -r 0fecaedb83fa -r 71780cf68aa2 readme.txt --- 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: diff -r 0fecaedb83fa -r 71780cf68aa2 win/dw.c --- 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; } /*