diff --git a/cli/tree.c b/cli/tree.c new file mode 100644 index 0000000..04922e6 --- /dev/null +++ b/cli/tree.c @@ -0,0 +1,116 @@ +#include +#include + +#include "curse.h" +#include "tree.h" + +/* Internal allocator method for crs_node structures. + */ +static inline struct crs_node *__alloc_node(const enum crs_nodetype type) { + struct crs_node *node = (struct crs_node *)malloc(sizeof(struct crs_node)); + node->type = type; + return node; +} + +/* Construct a new window node (crs_node of type NODE_WIN). + */ +static struct crs_node *init_node_window(WINDOW *win) { + struct crs_node *node = __alloc_node(NODE_WINDOW); + node->win = win; + + return node; +} + +static struct crs_node *init_node_abstract(struct crs_node *node1, + struct crs_node *node2, + float ratio) { + struct crs_node *node = __alloc_node(NODE_ABSTRACT); + node->ratio = ratio; + + node->child[0] = node1; + node->child[1] = node2; + return node; +} + +static void destroy_node(struct crs_node *node) { + if (node->type == NODE_WINDOW) { + /* Window Node */ + delwin(node->win); + goto end; + } + /* Abstract Node */ + destroy_node(node->child[0]); + destroy_node(node->child[1]); + +end: + free(node); +} + +/* Subdivide a window node's allocated region into two window nodes + * replacing the original node with an abstract node. + * Parameters: + * axis - controls which direction the subdivision occurs + * invert - invert index of the original node in the new abstract node + */ +static void bifurcate_window_node(struct crs_node **node, enum crs_axis axis, + int invert, float ratio) { + assert((*node)->type == NODE_ABSTRACT); + + struct crs_node *original_node = *node; + struct crs_node *bi_node = init_node_window(); // WARNING: TODO + + if (!invert) { + /* Inverted Bifurcation */ + *node = init_node_abstract(bi_node, original_node, ratio); + } else { + /* Non-Inverted Bifurcation */ + *node = init_node_abstract(original_node, bi_node, ratio); + } + + resize_abstract_node(*node); +} + +/* Collapse an abstract node, killing one child node and resizing + * the other to take its place. + */ +static void collapse_abstract_node(struct crs_node **node, + const int collapse_i) { + assert((*node)->type == NODE_ABSTRACT); + assert(0 <= collapse_i && collapse_i < NODE_CHILD_N); + + // WARNING: only works for NODE_CHILD_N=2 (binary trees) + destroy_node((*node)->child[!collapse_i]); + + struct crs_node *collapse_target = (*node)->child[collapse_i]; + free(*node); + *node = collapse_target; +} + +/* + */ +static struct crs_node *init_root_node(void) { + WINDOW *rootwin = newwin(0, 0, 0, 0); + return init_node_window(rootwin); +} + +int init_tree(struct crs_tree **tree) { + *tree = (struct crs_tree *)malloc(sizeof(struct crs_tree)); + + /* Initialise NCurses Library & Standard Screen */ + crs_init(&(*tree)->stdscr); + + /* */ + (*tree)->root = init_root_node(); + + // (*tree)->root = __alloc_node(NODE_WINDOW); + // crs_init(&(*tree)->root->win); + + return EXIT_SUCCESS; +} + +void destroy_tree(struct crs_tree *tree) { + /* WARNING: is it ok to delwin(stdscr) ?? */ + destroy_node(tree->root); + + endwin(); +} diff --git a/cli/tree.h b/cli/tree.h new file mode 100644 index 0000000..d5ba171 --- /dev/null +++ b/cli/tree.h @@ -0,0 +1,58 @@ +#ifndef DORNE_TREE_H +#define DORNE_TREE_H + +# ifndef __NCURSES_H +typedef struct _win_st WINDOW; +# endif /* __NCURSES_H */ + +#define NODE_CHILD_N 2 + +/* MACRO: + * void NODEDIMS(struct crs_node *node, struct crs_nodedims dims); + */ +#define NODEDIMS(node, dims) (getbegyx(dims.y, dims.x); getmaxyx(dims.y, dims.x)) + +enum crs_nodetype { + NODE_WINDOW, + NODE_ABSTRACT, +}; + +/* Stores a node's starting x,y coordinates, width, & height. + * NOTE: Intended for interfunction communication. + */ +struct crs_nodedims { + int x, y, width, height; +}; + +enum crs_axis { + AXIS_X, + AXIS_Y, +}; + +struct crs_node { + enum crs_nodetype type; + // union value depends on crs_node.type + union { + WINDOW *win; + struct { + float ratio; + struct crs_node *child[NODE_CHILD_N]; + }; + }; +}; + +struct crs_tree { + WINDOW *stdscr; + struct crs_node *root; +}; + +/* === External Interface === */ +// struct crs_node *init_node_window(void); +// struct crs_node *init_node_abstract(void); +// void destroy_node(struct crs_node *node); + +int init_tree(struct crs_tree **tree); +void update_tree(struct crs_tree *tree); +void destroy_tree(struct crs_tree *tree); + +#endif /* DORNE_TREE_H */