diff --git a/src/util.c b/src/util.c index d56f9c9..735e932 100644 --- a/src/util.c +++ b/src/util.c @@ -221,6 +221,98 @@ void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile) wm_ptrarray_free(&ws_str); } +TreeNode* wm_treenode_lmd(TreeNode *node) +{ + assert(node); + + if (node->children.size == 0) return node; + + return wm_treenode_lmd(node->children.nodes[0]); +} + +PtrArray wm_treenode_all_lmds(TreeNode *node) +{ + assert(node); + + PtrArray postorder = wm_postorder_traversal(node); + PtrArray ret = wm_ptrarray_new(); + + for (size_t i = 0; i < postorder.size; i++) { + TreeNode *lmd = wm_treenode_lmd(postorder.ptrs[i]); + + wm_ptrarray_push(&ret, (void*)lmd); + } + + wm_ptrarray_free(&postorder); + return ret; +} + +PtrArray wm_postorder_traversal(TreeNode *tree) +{ + assert(tree); + + TreeNode *root = tree; + + typedef struct { + TreeNode *node; + size_t index; + } NodeWithIndex; + + int root_index = 0; + + PtrArray stack = wm_ptrarray_new(); + PtrArray ret = wm_ptrarray_new(); + + while (root != NULL || stack.size > 0) { + if (root != NULL) { + NodeWithIndex *n = malloc(sizeof(NodeWithIndex)); + n->node = root; + n->index = root_index; + wm_ptrarray_push(&stack, n); + root_index = 0; + + if (root->children.size >= 1) + root = root->children.nodes[0]; + else root = NULL; + + continue; + } + + NodeWithIndex *nptr; + wm_ptrarray_pop(&stack, (void**)&nptr); + NodeWithIndex n = *nptr; + free(nptr); + wm_ptrarray_push(&ret, n.node); + + while (stack.size > 0 && n.index == ((NodeWithIndex**)stack.ptrs) + [stack.size-1]->node->children.size - 1) { + wm_ptrarray_pop(&stack, (void**)&nptr); + n = *nptr; + free(nptr); + + wm_ptrarray_push(&ret, n.node); + } + + if (stack.size > 0) { + root = ((NodeWithIndex**)stack.ptrs)[stack.size-1]->node + ->children.nodes[n.index + 1]; + root_index = n.index + 1; + } + } + + wm_ptrarray_free(&stack); + + return ret; +} + +bool wm_is_treenode_keyroot(TreeNode *node) +{ + assert(node); + if (!node->parent) return true; + + return wm_treenode_lmd(node) != wm_treenode_lmd(node->parent); +} + void wm_treenode_print(TreeNode *node) { char *str = wm_treenode_to_str(node); diff --git a/src/util.h b/src/util.h index d09285b..c764ac6 100644 --- a/src/util.h +++ b/src/util.h @@ -89,7 +89,6 @@ bool wm_nodearray_remove(NodeArray *arr, size_t index); void __wm_nodearray_free(NodeArray *arr); ClientArray wm_nodearray_find_clients(TreeNode *root); - PtrArray wm_ptrarray_new(); void wm_ptrarray_push(PtrArray *arr, void* ptr); bool wm_ptrarray_pop(PtrArray *arr, void **ret); @@ -103,6 +102,11 @@ TreeNode* wm_treenode_split_get_sibling(TreeNode *node); PtrArray wm_all_nodes_to_ptrarray(TreeNode *root); void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile); +TreeNode* wm_treenode_lmd(TreeNode *node); +PtrArray wm_treenode_all_lmds(TreeNode *node); +PtrArray wm_postorder_traversal(TreeNode *tree); +bool wm_is_treenode_keyroot(TreeNode *node); + ClientArray wm_clientarray_new(); void wm_clientarray_push(ClientArray *arr, Client node); bool wm_clientarray_pop(ClientArray *arr, Client *ret);