summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortreectrl <treectrl>2006-10-30 23:03:22 (GMT)
committertreectrl <treectrl>2006-10-30 23:03:22 (GMT)
commitedb84a8f80c44169df95b5b73b8db1d01722a1d1 (patch)
tree9f44b1f286fcc1314272d7477b33422b779c0bfc
parent944fbd178e18c860c178858548d1f1185fbac89a (diff)
downloadtktreectrl-edb84a8f80c44169df95b5b73b8db1d01722a1d1.zip
tktreectrl-edb84a8f80c44169df95b5b73b8db1d01722a1d1.tar.gz
tktreectrl-edb84a8f80c44169df95b5b73b8db1d01722a1d1.tar.bz2
Changed handling of deleted items (again) so that the item is removed from the heirarchy of known items but the record is not freed until it is not in use.
-rw-r--r--generic/tkTreeCtrl.c65
-rw-r--r--generic/tkTreeCtrl.h6
-rw-r--r--generic/tkTreeItem.c118
3 files changed, 145 insertions, 44 deletions
diff --git a/generic/tkTreeCtrl.c b/generic/tkTreeCtrl.c
index 001f756..bb6250f 100644
--- a/generic/tkTreeCtrl.c
+++ b/generic/tkTreeCtrl.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2003 Christian Krone
* Copyright (c) 2003-2005 ActiveState, a division of Sophos
*
- * RCS: @(#) $Id: tkTreeCtrl.c,v 1.76 2006/10/30 02:41:55 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeCtrl.c,v 1.77 2006/10/30 23:03:22 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -538,7 +538,7 @@ static int TreeWidgetCmd(
switch (index) {
case COMMAND_ACTIVATE:
{
- TreeItem item;
+ TreeItem active, item;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "item");
@@ -550,8 +550,8 @@ static int TreeWidgetCmd(
if (item != tree->activeItem) {
int x, y, w, h;
- TreeNotify_ActiveItem(tree, tree->activeItem, item);
- TreeItem_ChangeState(tree, tree->activeItem, STATE_ACTIVE, 0);
+ active = tree->activeItem;
+ TreeItem_ChangeState(tree, active, STATE_ACTIVE, 0);
tree->activeItem = item;
TreeItem_ChangeState(tree, tree->activeItem, 0, STATE_ACTIVE);
#ifdef COLUMN_LOCK
@@ -563,6 +563,7 @@ static int TreeWidgetCmd(
Tk_SetCaretPos(tree->tkwin, x - tree->xOrigin,
y - tree->yOrigin, h);
}
+ TreeNotify_ActiveItem(tree, active, item);
}
break;
}
@@ -697,7 +698,7 @@ static int TreeWidgetCmd(
count = TreeItemList_Count(&item2s);
for (j = 0; j < count; j++) {
_item = TreeItemList_Nth(&item2s, j);
- TreeItem_OpenClose(tree, _item, mode, FALSE);
+ TreeItem_OpenClose(tree, _item, mode);
}
TreeItemList_Free(&items);
TreeItemList_Free(&item2s);
@@ -1688,7 +1689,7 @@ TreeDestroy(
TreeItem item;
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- int i;
+ int i, count;
hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search);
while (hPtr != NULL) {
@@ -1698,6 +1699,11 @@ TreeDestroy(
}
Tcl_DeleteHashTable(&tree->itemHash);
+ count = TreeItemList_Count(&tree->preserveItemList);
+ for (i = 0; i < count; i++) {
+ item = TreeItemList_Nth(&tree->preserveItemList, i);
+ TreeItem_Release(tree, item);
+ }
TreeItemList_Free(&tree->preserveItemList);
TreeStyle_Free(tree);
@@ -3374,14 +3380,49 @@ TreeDebugCmd(
return TCL_OK;
}
-void Tree_PreserveItems(
+/*
+ *--------------------------------------------------------------
+ *
+ * Tree_PreserveItems --
+ *
+ * Increment tree->preserveItemRefCnt.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tree_PreserveItems(
TreeCtrl *tree
)
{
tree->preserveItemRefCnt++;
}
-void Tree_ReleaseItems(
+/*
+ *--------------------------------------------------------------
+ *
+ * Tree_ReleaseItems --
+ *
+ * Decrement tree->preserveItemRefCnt. If it reaches zero,
+ * release the storage of items marked as deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tree_ReleaseItems(
TreeCtrl *tree
)
{
@@ -3397,13 +3438,7 @@ void Tree_ReleaseItems(
count = TreeItemList_Count(&tree->preserveItemList);
for (i = 0; i < count; i++) {
item = TreeItemList_Nth(&tree->preserveItemList, i);
- /* if (!TreeItem_Deleted(tree, item)) panic(""); */
- TreeItem_RemoveFromParent(tree, item);
- }
- for (i = 0; i < count; i++) {
- item = TreeItemList_Nth(&tree->preserveItemList, i);
- /* if (TreeItem_NumChildren(tree, item) > 0) panic(""); */
- TreeItem_Delete(tree, item);
+ TreeItem_Release(tree, item);
}
TreeItemList_Free(&tree->preserveItemList);
diff --git a/generic/tkTreeCtrl.h b/generic/tkTreeCtrl.h
index 95386b8..70d18eb 100644
--- a/generic/tkTreeCtrl.h
+++ b/generic/tkTreeCtrl.h
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2003 Christian Krone
* Copyright (c) 2003 ActiveState Corporation
*
- * RCS: @(#) $Id: tkTreeCtrl.h,v 1.60 2006/10/29 02:37:54 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeCtrl.h,v 1.61 2006/10/30 23:03:22 treectrl Exp $
*/
#include "tkPort.h"
@@ -464,8 +464,9 @@ extern void Tree_Debug(TreeCtrl *tree);
extern int TreeItem_Init(TreeCtrl *tree);
extern int TreeItem_Debug(TreeCtrl *tree, TreeItem item);
-extern void TreeItem_OpenClose(TreeCtrl *tree, TreeItem item, int mode, int recurse);
+extern void TreeItem_OpenClose(TreeCtrl *tree, TreeItem item, int mode);
extern void TreeItem_Delete(TreeCtrl *tree, TreeItem item);
+extern int TreeItem_Deleted(TreeCtrl *tree, TreeItem item);
#define STATE_OPEN 0x0001
#define STATE_SELECTED 0x0002
@@ -512,6 +513,7 @@ extern void TreeItem_DrawLines(TreeCtrl *tree, TreeItem self, int x, int y, int
extern void TreeItem_DrawButton(TreeCtrl *tree, TreeItem self, int x, int y, int width, int height, Drawable drawable);
extern int TreeItem_ReallyVisible(TreeCtrl *tree, TreeItem self);
extern void TreeItem_FreeResources(TreeCtrl *tree, TreeItem self);
+extern void TreeItem_Release(TreeCtrl *tree, TreeItem item);
extern TreeItem TreeItem_RootAncestor(TreeCtrl *tree, TreeItem item_);
extern int TreeItem_IsAncestor(TreeCtrl *tree, TreeItem item1, TreeItem item2);
extern Tcl_Obj *TreeItem_ToObj(TreeCtrl *tree, TreeItem item);
diff --git a/generic/tkTreeItem.c b/generic/tkTreeItem.c
index ce22ad6..199aff5 100644
--- a/generic/tkTreeItem.c
+++ b/generic/tkTreeItem.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeItem.c,v 1.73 2006/10/29 02:33:02 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeItem.c,v 1.74 2006/10/30 23:03:22 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -63,7 +63,7 @@ static CONST char *ItemUid = "Item", *ItemColumnUid = "ItemColumn";
#define IS_ALL(i) (((TreeItem) i) == ITEM_ALL)
-#define IS_DELETED(i) (((i)->flags & ITEM_FLAG_DELETED) != 0)
+#define IS_DELETED(i) ((((Item *) i)->flags & ITEM_FLAG_DELETED) != 0)
/*
* Flags returned by Tk_SetOptions() (see itemOptionSpecs below).
@@ -1691,6 +1691,7 @@ Qualifiers_Free(
* "ID MODIFIERS"
* -- returning multiple items --
* all QUALIFIERS
+ * QUALIFIERS (like "all QUALIFIERS")
* list listOfItemDescs
* range QUALIFIERS
* tag tagExpr QUALIFIERS
@@ -1723,9 +1724,9 @@ Qualifiers_Free(
* QUALIFIERS:
* depth integer
* state stateList
+ * tag tagExpr
* visible
* !visible
- * tag tagExpr
*
* Examples:
* $T item id "first visible firstchild"
@@ -1759,7 +1760,7 @@ TreeItemList_FromObj(
Tcl_Obj **objv, *elemPtr;
Item *item = NULL;
Qualifiers q;
- int qualArgsTotal = 0;
+ int qualArgsTotal;
static CONST char *indexName[] = {
"active", "all", "anchor", "end", "first", "last", "list",
@@ -2539,7 +2540,7 @@ Item_ToggleOpen(
*
* TreeItem_OpenClose --
*
- * Inverts the STATE_OPEN flag of an Item, possibly recursively.
+ * Inverts the STATE_OPEN flag of an Item.
*
* Results:
* Items may be displayed/undisplayed.
@@ -2555,17 +2556,18 @@ void
TreeItem_OpenClose(
TreeCtrl *tree, /* Widget info. */
TreeItem item_, /* Item token. */
- int mode, /* -1: toggle
+ int mode /* -1: toggle
* 0: close
* 1: open */
- int recurse /* TRUE to perform same op on descendants,
- * FALSE to only affect given item. */
)
{
Item *item = (Item *) item_;
- Item *child;
int stateOff = 0, stateOn = 0;
+ /* When processing a list of items, any <Expand> or <Collapse> event
+ * may result in items being deleted. */
+ if (IS_DELETED(item_)) return;
+
if (mode == -1) {
if (item->state & STATE_OPEN)
stateOff = STATE_OPEN;
@@ -2578,13 +2580,10 @@ TreeItem_OpenClose(
if (stateOff != stateOn) {
TreeNotify_OpenClose(tree, item_, stateOn, TRUE);
+ if (IS_DELETED(item_)) return;
Item_ToggleOpen(tree, item, stateOff, stateOn);
TreeNotify_OpenClose(tree, item_, stateOn, FALSE);
}
- if (recurse) {
- for (child = item->firstChild; child != NULL; child = child->nextSibling)
- TreeItem_OpenClose(tree, (TreeItem) child, mode, recurse);
- }
}
/*
@@ -2637,6 +2636,31 @@ TreeItem_Delete(
/*
*----------------------------------------------------------------------
*
+ * TreeItem_Deleted --
+ *
+ * Return 1 if the given item is deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TreeItem_Deleted(
+ TreeCtrl *tree, /* Widget info. */
+ TreeItem item_ /* Item token. */
+ )
+{
+ return IS_DELETED(item_);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TreeItem_FirstAndLast --
*
* Determine the order of two items and swap them if needed.
@@ -3173,10 +3197,37 @@ TreeItem_FreeResources(
if (self->rInfo != NULL)
Tree_FreeItemRInfo(tree, item_);
Tk_FreeConfigOptions((char *) self, tree->itemOptionTable, tree->tkwin);
+
+ /* Add the item record to the "preserved" list. It will be freed later. */
+ TreeItemList_Append(&tree->preserveItemList, item_);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TreeItem_Release --
+ *
+ * Finally free an item record when it is no longer needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TreeItem_Release(
+ TreeCtrl *tree, /* Widget info. */
+ TreeItem item_ /* Item token. */
+ )
+{
#ifdef ALLOC_HAX
- AllocHax_Free(tree->allocData, ItemUid, (char *) self, sizeof(Item));
+ AllocHax_Free(tree->allocData, ItemUid, (char *) item_, sizeof(Item));
#else
- WFREE(self, Item);
+ WFREE(item_, Item);
#endif
}
@@ -7233,8 +7284,9 @@ TreeItemCmd(
ItemForEach iter;
if (numArgs == 2) {
- char *s = Tcl_GetString(objv[4]);
- if (strcmp(s, "-recurse")) {
+ int len;
+ char *s = Tcl_GetStringFromObj(objv[4], &len);
+ if (strncmp(s, "-recurse", len)) {
FormatResult(interp, "bad option \"%s\": must be -recurse",
s);
goto errorExit;
@@ -7262,7 +7314,7 @@ TreeItemCmd(
count = TreeItemList_Count(&items);
for (i = 0; i < count; i++) {
_item = TreeItemList_Nth(&items, i);
- TreeItem_OpenClose(tree, _item, mode, FALSE);
+ TreeItem_OpenClose(tree, _item, mode);
}
TreeItemList_Free(&items);
#ifdef SELECTION_VISIBLE
@@ -7462,9 +7514,9 @@ TreeItemCmd(
if (IS_DELETED(item))
continue;
item->flags |= ITEM_FLAG_DELETED;
- TreeItemList_Append(&deleted, (TreeItem) item);
- if (TreeItem_GetSelected(tree, (TreeItem) item))
- TreeItemList_Append(&selected, (TreeItem) item);
+ TreeItemList_Append(&deleted, _item);
+ if (TreeItem_GetSelected(tree, _item))
+ TreeItemList_Append(&selected, _item);
if (iter.all)
continue;
/* Check every descendant. */
@@ -7475,15 +7527,16 @@ TreeItemCmd(
item2 = item2->lastChild;
item = item->firstChild;
while (1) {
+ _item = (TreeItem) item;
if (IS_DELETED(item)) {
/* Skip all descendants (they are already flagged). */
while (item->lastChild != NULL)
item = item->lastChild;
} else {
item->flags |= ITEM_FLAG_DELETED;
- TreeItemList_Append(&deleted, (TreeItem) item);
- if (TreeItem_GetSelected(tree, (TreeItem) item))
- TreeItemList_Append(&selected, (TreeItem) item);
+ TreeItemList_Append(&deleted, _item);
+ if (TreeItem_GetSelected(tree, _item))
+ TreeItemList_Append(&selected, _item);
}
if (item == item2)
break;
@@ -7506,9 +7559,20 @@ TreeItemCmd(
/* Generate <ItemDelete> event for items being deleted. */
TreeNotify_ItemDeleted(tree, &deleted);
- /* Add deleted items to the preserved list so they can be
- * freed when no longer in use. */
- TreeItemList_Concat(&tree->preserveItemList, &deleted);
+ /* Remove every item from its parent. Needed because items
+ * are deleted recursively. */
+ for (i = 0; i < count; i++) {
+ _item = TreeItemList_Nth(&deleted, i);
+ TreeItem_RemoveFromParent(tree, _item);
+ }
+
+ /* Delete the items. The item record will be freed when no
+ * longer in use; however, the item cannot be referred to
+ * by commands from this point on. */
+ for (i = 0; i < count; i++) {
+ _item = TreeItemList_Nth(&deleted, i);
+ TreeItem_Delete(tree, _item);
+ }
}
TreeItemList_Free(&selected);