diff options
author | treectrl <treectrl> | 2006-10-30 23:03:22 (GMT) |
---|---|---|
committer | treectrl <treectrl> | 2006-10-30 23:03:22 (GMT) |
commit | edb84a8f80c44169df95b5b73b8db1d01722a1d1 (patch) | |
tree | 9f44b1f286fcc1314272d7477b33422b779c0bfc | |
parent | 944fbd178e18c860c178858548d1f1185fbac89a (diff) | |
download | tktreectrl-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.c | 65 | ||||
-rw-r--r-- | generic/tkTreeCtrl.h | 6 | ||||
-rw-r--r-- | generic/tkTreeItem.c | 118 |
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); |