mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 12:28:22 +01:00
Finished the generic tree node data type
This commit is contained in:
@@ -582,23 +582,37 @@ WMTreeNode* WMCreateTreeNodeWithDestructor(void *data, WMFreeDataProc *destructo
|
||||
|
||||
WMTreeNode* WMInsertItemInTree(WMTreeNode *parent, int index, void *item);
|
||||
|
||||
WMTreeNode* WMAddItemToTree(WMTreeNode *parent, void *item);
|
||||
#define WMAddItemToTree(parent, item) WMInsertItemInTree(parent, -1, item)
|
||||
|
||||
WMTreeNode* WMInsertNodeInTree(WMTreeNode *parent, int index, WMTreeNode *node);
|
||||
WMTreeNode* WMInsertNodeInTree(WMTreeNode *parent, int index, WMTreeNode *aNode);
|
||||
|
||||
WMTreeNode* WMAddNodeToTree(WMTreeNode *parent, WMTreeNode *node);
|
||||
#define WMAddNodeToTree(parent, aNode) WMInsertNodeInTree(parent, -1, aNode)
|
||||
|
||||
int WMGetTreeNodeDepth(WMTreeNode *node);
|
||||
void WMDestroyTreeNode(WMTreeNode *aNode);
|
||||
|
||||
void WMDestroyTreeNode(WMTreeNode *node);
|
||||
void WMDeleteLeafForTreeNode(WMTreeNode *aNode, int index);
|
||||
|
||||
void* WMGetDataForTreeNode(WMTreeNode *node);
|
||||
void WMRemoveLeafForTreeNode(WMTreeNode *aNode, void *leaf);
|
||||
|
||||
WMTreeNode* WMGetParentForTreeNode(WMTreeNode *node);
|
||||
void* WMReplaceDataForTreeNode(WMTreeNode *aNode, void *newData);
|
||||
|
||||
void WMSortLeavesForTreeNode(WMTreeNode *node, WMCompareDataProc *comparer);
|
||||
void* WMGetDataForTreeNode(WMTreeNode *aNode);
|
||||
|
||||
void WMSortTree(WMTreeNode *root, WMCompareDataProc *comparer);
|
||||
int WMGetTreeNodeDepth(WMTreeNode *aNode);
|
||||
|
||||
WMTreeNode* WMGetParentForTreeNode(WMTreeNode *aNode);
|
||||
|
||||
/* Sort only the leaves of the passed node */
|
||||
void WMSortLeavesForTreeNode(WMTreeNode *aNode, WMCompareDataProc *comparer);
|
||||
|
||||
/* Sort all tree recursively starting from the passed node */
|
||||
void WMSortTree(WMTreeNode *aNode, WMCompareDataProc *comparer);
|
||||
|
||||
/* Returns the first node which matches node's data with cdata by 'match' */
|
||||
WMTreeNode* WMFindInTree(WMTreeNode *aTree, WMMatchDataProc *match, void *cdata);
|
||||
|
||||
/* Returns first tree node that has data == cdata */
|
||||
#define WMGetFirstInTree(aTree, cdata) WMFindInTree(atree, NULL, cdata)
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
252
WINGs/tree.c
252
WINGs/tree.c
@@ -22,18 +22,19 @@ typedef struct W_TreeNode {
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
destroyNode(void *data)
|
||||
{
|
||||
WMTreeNode *node = (WMTreeNode*) data;
|
||||
WMTreeNode *aNode = (WMTreeNode*) data;
|
||||
|
||||
if (node->destructor) {
|
||||
(*node->destructor)(node->data);
|
||||
if (aNode->destructor) {
|
||||
(*aNode->destructor)(aNode->data);
|
||||
}
|
||||
if (node->leaves) {
|
||||
WMFreeArray(node->leaves);
|
||||
if (aNode->leaves) {
|
||||
WMFreeArray(aNode->leaves);
|
||||
}
|
||||
wfree(node);
|
||||
wfree(aNode);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,157 +48,232 @@ WMCreateTreeNode(void *data)
|
||||
WMTreeNode*
|
||||
WMCreateTreeNodeWithDestructor(void *data, WMFreeDataProc *destructor)
|
||||
{
|
||||
WMTreeNode *node;
|
||||
WMTreeNode *aNode;
|
||||
|
||||
node = (WMTreeNode*) wmalloc(sizeof(W_TreeNode));
|
||||
memset(node, 0, sizeof(W_TreeNode));
|
||||
aNode = (WMTreeNode*) wmalloc(sizeof(W_TreeNode));
|
||||
memset(aNode, 0, sizeof(W_TreeNode));
|
||||
|
||||
node->destructor = destructor;
|
||||
aNode->destructor = destructor;
|
||||
|
||||
node->data = data;
|
||||
node->parent = NULL;
|
||||
node->depth = 0;
|
||||
node->leaves = WMCreateArrayWithDestructor(1, destroyNode);
|
||||
aNode->data = data;
|
||||
aNode->parent = NULL;
|
||||
aNode->depth = 0;
|
||||
aNode->leaves = NULL;
|
||||
/*aNode->leaves = WMCreateArrayWithDestructor(1, destroyNode);*/
|
||||
|
||||
return node;
|
||||
return aNode;
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMInsertItemInTree(WMTreeNode *parent, int index, void *item)
|
||||
{
|
||||
WMTreeNode *node;
|
||||
WMTreeNode *aNode;
|
||||
|
||||
wassertrv(parent!=NULL, NULL);
|
||||
|
||||
node = WMCreateTreeNodeWithDestructor(item, parent->destructor);
|
||||
node->parent = parent;
|
||||
node->depth = parent->depth+1;
|
||||
if (index < 0 || index > WMGetArrayItemCount(parent->leaves)) {
|
||||
WMAddToArray(parent->leaves, node);
|
||||
aNode = WMCreateTreeNodeWithDestructor(item, parent->destructor);
|
||||
aNode->parent = parent;
|
||||
aNode->depth = parent->depth+1;
|
||||
if (!parent->leaves) {
|
||||
parent->leaves = WMCreateArrayWithDestructor(1, destroyNode);
|
||||
}
|
||||
if (index < 0) {
|
||||
WMAddToArray(parent->leaves, aNode);
|
||||
} else {
|
||||
WMInsertInArray(parent->leaves, index, node);
|
||||
WMInsertInArray(parent->leaves, index, aNode);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMAddItemToTree(WMTreeNode *parent, void *item)
|
||||
{
|
||||
WMTreeNode *node;
|
||||
|
||||
wassertrv(parent!=NULL, NULL);
|
||||
|
||||
node = WMCreateTreeNodeWithDestructor(item, parent->destructor);
|
||||
node->parent = parent;
|
||||
node->depth = parent->depth+1;
|
||||
WMAddToArray(parent->leaves, node);
|
||||
|
||||
return node;
|
||||
return aNode;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
updateNodeDepth(WMTreeNode *node, int depth)
|
||||
updateNodeDepth(WMTreeNode *aNode, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
node->depth = depth;
|
||||
for (i=0; i<WMGetArrayItemCount(node->leaves); i++) {
|
||||
updateNodeDepth(WMGetFromArray(node->leaves, i), depth+1);
|
||||
aNode->depth = depth;
|
||||
|
||||
if (aNode->leaves) {
|
||||
for (i=0; i<WMGetArrayItemCount(aNode->leaves); i++) {
|
||||
updateNodeDepth(WMGetFromArray(aNode->leaves, i), depth+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMInsertNodeInTree(WMTreeNode *parent, int index, WMTreeNode *node)
|
||||
WMInsertNodeInTree(WMTreeNode *parent, int index, WMTreeNode *aNode)
|
||||
{
|
||||
wassertrv(parent!=NULL, NULL);
|
||||
wassertrv(node!=NULL, NULL);
|
||||
wassertrv(aNode!=NULL, NULL);
|
||||
|
||||
node->parent = parent;
|
||||
updateNodeDepth(node, parent->depth+1);
|
||||
if (index < 0 || index > WMGetArrayItemCount(parent->leaves)) {
|
||||
WMAddToArray(parent->leaves, node);
|
||||
aNode->parent = parent;
|
||||
updateNodeDepth(aNode, parent->depth+1);
|
||||
if (!parent->leaves) {
|
||||
parent->leaves = WMCreateArrayWithDestructor(1, destroyNode);
|
||||
}
|
||||
if (index < 0) {
|
||||
WMAddToArray(parent->leaves, aNode);
|
||||
} else {
|
||||
WMInsertInArray(parent->leaves, index, node);
|
||||
WMInsertInArray(parent->leaves, index, aNode);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMAddNodeToTree(WMTreeNode *parent, WMTreeNode *node)
|
||||
{
|
||||
wassertrv(parent!=NULL, NULL);
|
||||
wassertrv(node!=NULL, NULL);
|
||||
|
||||
node->parent = parent;
|
||||
updateNodeDepth(node, parent->depth+1);
|
||||
WMAddToArray(parent->leaves, node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetTreeNodeDepth(WMTreeNode *node)
|
||||
{
|
||||
return node->depth;
|
||||
return aNode;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDestroyTreeNode(WMTreeNode *node)
|
||||
WMDestroyTreeNode(WMTreeNode *aNode)
|
||||
{
|
||||
destroyNode(node);
|
||||
wassertr(aNode!=NULL);
|
||||
|
||||
if (aNode->parent && aNode->parent->leaves) {
|
||||
WMRemoveFromArray(aNode->parent->leaves, aNode);
|
||||
} else {
|
||||
destroyNode(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDeleteLeafForTreeNode(WMTreeNode *aNode, int index)
|
||||
{
|
||||
wassertr(aNode!=NULL);
|
||||
wassertr(aNode->leaves!=NULL);
|
||||
|
||||
WMDeleteFromArray(aNode->leaves, index);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sameData(void *item, void *data)
|
||||
{
|
||||
return (((WMTreeNode*)item)->data == data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemoveLeafForTreeNode(WMTreeNode *aNode, void *leaf)
|
||||
{
|
||||
int index;
|
||||
|
||||
wassertr(aNode!=NULL);
|
||||
wassertr(aNode->leaves!=NULL);
|
||||
|
||||
index = WMFindInArray(aNode->leaves, sameData, leaf);
|
||||
if (index != WANotFound) {
|
||||
WMDeleteFromArray(aNode->leaves, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
WMGetDataForTreeNode(WMTreeNode *node)
|
||||
WMReplaceDataForTreeNode(WMTreeNode *aNode, void *newData)
|
||||
{
|
||||
return node->data;
|
||||
void *old;
|
||||
|
||||
wassertrv(aNode!=NULL, NULL);
|
||||
|
||||
old = aNode->data;
|
||||
aNode->data = newData;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
WMGetDataForTreeNode(WMTreeNode *aNode)
|
||||
{
|
||||
return aNode->data;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetTreeNodeDepth(WMTreeNode *aNode)
|
||||
{
|
||||
return aNode->depth;
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMGetParentForTreeNode(WMTreeNode *node)
|
||||
WMGetParentForTreeNode(WMTreeNode *aNode)
|
||||
{
|
||||
return node->parent;
|
||||
return aNode->parent;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSortLeavesForTreeNode(WMTreeNode *node, WMCompareDataProc *comparer)
|
||||
WMSortLeavesForTreeNode(WMTreeNode *aNode, WMCompareDataProc *comparer)
|
||||
{
|
||||
wassertr(node!=NULL);
|
||||
wassertr(aNode!=NULL);
|
||||
|
||||
WMSortArray(node->leaves, comparer);
|
||||
if (aNode->leaves) {
|
||||
WMSortArray(aNode->leaves, comparer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sortLeavesForNode(WMTreeNode *node, WMCompareDataProc *comparer)
|
||||
sortLeavesForNode(WMTreeNode *aNode, WMCompareDataProc *comparer)
|
||||
{
|
||||
int i;
|
||||
|
||||
WMSortArray(node->leaves, comparer);
|
||||
for (i=0; i<WMGetArrayItemCount(node->leaves); i++) {
|
||||
sortLeavesForNode(WMGetFromArray(node->leaves, i), comparer);
|
||||
if (!aNode->leaves)
|
||||
return;
|
||||
|
||||
WMSortArray(aNode->leaves, comparer);
|
||||
for (i=0; i<WMGetArrayItemCount(aNode->leaves); i++) {
|
||||
sortLeavesForNode(WMGetFromArray(aNode->leaves, i), comparer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSortTree(WMTreeNode *root, WMCompareDataProc *comparer)
|
||||
WMSortTree(WMTreeNode *aNode, WMCompareDataProc *comparer)
|
||||
{
|
||||
wassertr(root!=NULL);
|
||||
wassertr(aNode!=NULL);
|
||||
|
||||
sortLeavesForNode(root, comparer);
|
||||
sortLeavesForNode(aNode, comparer);
|
||||
}
|
||||
|
||||
|
||||
static WMTreeNode*
|
||||
findNodeInTree(WMTreeNode *aNode, WMMatchDataProc *match, void *cdata)
|
||||
{
|
||||
if (match==NULL) {
|
||||
if (aNode->data == cdata) {
|
||||
return aNode;
|
||||
}
|
||||
} else {
|
||||
if ((*match)(aNode->data, cdata)) {
|
||||
return aNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (aNode->leaves) {
|
||||
WMTreeNode *leaf;
|
||||
int i;
|
||||
|
||||
for (i=0; i<WMGetArrayItemCount(aNode->leaves); i++) {
|
||||
leaf = findNodeInTree(WMGetFromArray(aNode->leaves, i), match, cdata);
|
||||
if (leaf) {
|
||||
return leaf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
WMTreeNode*
|
||||
WMFindInTree(WMTreeNode *aTree, WMMatchDataProc *match, void *cdata)
|
||||
{
|
||||
wassertrv(aTree!=NULL, NULL);
|
||||
|
||||
return findNodeInTree(aTree, match, cdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user