Index: hid_dad.h
===================================================================
--- hid_dad.h	(revision 34137)
+++ hid_dad.h	(working copy)
@@ -82,7 +82,7 @@
 		long lng;
 		double dbl;
 	} user_data2;
-	char *cell[1];   /* each cell is a char *; the true length of the array is the value of the len field; the array is allocated together with the struct */
+	char *cell[1];   /* each cell is an strdup'd char *; the true length of the array is the value of the len field; the array is allocated together with the struct */
 } rnd_hid_row_t;
 
 typedef struct {
@@ -93,7 +93,7 @@
 
 	/* optional callbacks the user set after widget creation */
 	void *user_ctx;
-	void (*user_free_cb)(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row);
+	void (*user_free_cb)(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row); /* should free user data; cells are free'd */
 	void (*user_selected_cb)(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row);
 	int (*user_browse_activate_cb)(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row); /* returns non-zero if the row should auto-activate while browsing (e.g. stepping with arrow keys) */
 	const char *(*user_copy_to_clip_cb)(rnd_hid_attribute_t *attrib, void *hid_ctx, rnd_hid_row_t *row); /* returns the string to copy to clipboard for the given row (if unset, first column text is used) */
Index: hid_dad_tree.c
===================================================================
--- hid_dad_tree.c	(revision 34137)
+++ hid_dad_tree.c	(working copy)
@@ -38,17 +38,7 @@
 	while((r = gdl_first(list)) != NULL) {
 		gdl_remove(list, r, link);
 		rnd_dad_tree_free_rowlist(attr, &r->children);
-
-		if (tree->hid_free_cb != NULL)
-			tree->hid_free_cb(tree->attrib, tree->hid_wdata, r);
-
-		if (tree->user_free_cb != NULL)
-			tree->user_free_cb(tree->attrib, tree->hid_wdata, r);
-
-		if (attr->rnd_hatt_flags & RND_HATF_TREE_COL)
-			free(r->path);
-
-		free(r);
+		rnd_dad_tree_free_row(tree, r);
 	}
 }
 
Index: hid_dad_tree.h
===================================================================
--- hid_dad_tree.h	(revision 34137)
+++ hid_dad_tree.h	(working copy)
@@ -44,7 +44,7 @@
 
 /* Recursively create the node and all parents in a tree. If cells is not NULL,
    the target path row is created with these cells, else only the first col
-   is filled in. Temporarily modifies path (but changes it back) */
+   is copied for path. Temporarily modifies path (but changes it back) */
 rnd_hid_row_t *rnd_dad_tree_mkdirp(rnd_hid_tree_t *tree, char *path, char **cells);
 
 /* Internal: Allocate a new row and load the cells (but do not insert it anywhere) */
@@ -65,20 +65,21 @@
 
 RND_INLINE void rnd_dad_tree_free_row(rnd_hid_tree_t *tree, rnd_hid_row_t *row)
 {
-	int do_free_path = 0;
-	/* do this before the user callback just in case row->path == row->cell[0]
-	   and the user callback free's it */
-	if (row->path != NULL) {
+	int n;
+
+	if (row->path != NULL)
 		htsp_pop(&tree->paths, row->path);
-		do_free_path = (row->path != row->cell[0]); /* user_free_cb may set row->cell[0] to NULL */
-	}
 
+	if (tree->hid_free_cb != NULL)
+		tree->hid_free_cb(tree->attrib, tree->hid_wdata, row);
+
 	if (tree->user_free_cb != NULL)
 		tree->user_free_cb(tree->attrib, tree->hid_wdata, row);
 
-	if (do_free_path)
-		free(row->path);
+	for(n = 0; n < row->cols; n++)
+		free(row->cell[n]);
 
+	free(row->path);
 	free(row);
 }
 
@@ -126,7 +127,7 @@
 		row->path = path.array;
 	}
 	else
-		row->path = row->cell[0];
+		row->path = rnd_strdup(row->cell[0]);
 	htsp_set(&tree->paths, row->path, row);
 }
 
@@ -271,6 +272,7 @@
 		row->path = NULL;
 	}
 
+	free(row->cell[col]);
 	row->cell[col] = new_val;
 
 	if (col == 0)
