diff --git a/cursetree/dims.c b/cursetree/dims.c index beaf2d9..4fa4895 100644 --- a/cursetree/dims.c +++ b/cursetree/dims.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -25,35 +26,97 @@ struct ct_dims *dup_dims(const struct ct_dims *const dims) { return dup; } +static struct ct_bounds *__bounds(const enum ct_boundtype type, const int wmin, + const int wmax, const int hmin, + const int hmax) { + struct ct_bounds *bounds; + + bounds = (struct ct_bounds *)malloc(sizeof(struct ct_bounds)); + *bounds = (struct ct_bounds){ + .type = type, + .wmin = wmin, + .wmax = wmax, + .hmin = hmin, + .hmax = hmax, + }; + return bounds; +} + +static inline void clamp(int *const val, const int min, const int max, + const int do_ceiling) { + if (*val == __BOUND_UNLIMITED) + *val = do_ceiling ? max : min; + else if (*val > max) + *val = max; + else if (*val < min) + *val = min; +} +#define CLAMP_ABS(val, is_max) \ + (clamp(&val, __BOUND_ABS_MIN, __BOUND_ABS_MAX, is_max)) +#define CLAMP_REL(val, is_max) \ + (clamp(&val, __BOUND_REL_MIN, __BOUND_REL_MAX, is_max)) + +struct ct_bounds *bounds_none(void) { + return __bounds(BOUND_NONE, __BOUND_ABS_MIN, __BOUND_ABS_MAX, __BOUND_ABS_MIN, + __BOUND_ABS_MAX); +} + +struct ct_bounds *bounds_absolute(int wmin, int wmax, + int hmin, int hmax) { + CLAMP_ABS(wmin, false); + CLAMP_ABS(wmax, true); + CLAMP_ABS(hmin, false); + CLAMP_ABS(hmax, true); + return __bounds(BOUND_ABSOLUTE, wmin, wmax, hmin, hmax); +} + +struct ct_bounds *bounds_relative(int wmin, int wmax, + int hmin, int hmax) { + CLAMP_REL(wmin, false); + CLAMP_REL(wmax, true); + CLAMP_REL(hmin, false); + CLAMP_REL(hmax, true); + return __bounds(BOUND_RELATIVE, wmin, wmax, hmin, hmax); +} + +struct ct_bounds *dup_bounds(const struct ct_bounds *const bounds) { + struct ct_bounds *dup; + dup = (struct ct_bounds *)malloc(sizeof(struct ct_bounds)); + memcpy(dup, bounds, sizeof(struct ct_bounds)); + + return dup; +} + /* Calculate the dimensions for nodes resulting from a bifurcation. * Returns 0 on success, and 1 on failure if any width/height are 0 characters. * WARNING: This function does not guarantee the x,y positions returned * WARNING: are valid screen coordinates. */ -int bifurcate_dims(const struct ct_dims *const parent_dims, - const enum ct_axis axis, const float ratio, - struct ct_dims **const dims0, struct ct_dims **const dims1) { - assert(0 < ratio && ratio < 1); - struct ct_dims *_dims0, *_dims1; +// int bifurcate_dims(const struct ct_dims *const parent_dims, +// const enum ct_axis axis, const float ratio, +// struct ct_dims **const dims0, struct ct_dims **const +// dims1) { +// assert(0 < ratio && ratio < 1); +// struct ct_dims *_dims0, *_dims1; - _dims0 = dup_dims(parent_dims); - _dims1 = dup_dims(parent_dims); +// _dims0 = dup_dims(parent_dims); +// _dims1 = dup_dims(parent_dims); - if (axis == AXIS_X) { - _dims0->width *= ratio; - _dims1->width -= _dims0->width; - _dims1->x += _dims0->width; - } else { - _dims0->height *= ratio; - _dims1->height -= _dims0->height; - _dims1->y += _dims0->height; - } +// if (axis == AXIS_X) { +// _dims0->width *= ratio; +// _dims1->width -= _dims0->width; +// _dims1->x += _dims0->width; +// } else { +// _dims0->height *= ratio; +// _dims1->height -= _dims0->height; +// _dims1->y += _dims0->height; +// } - if (!_dims0->width || !_dims0->height || !_dims1->width || !_dims1->height) - return 1; +// if (!_dims0->width || !_dims0->height || !_dims1->width || !_dims1->height) +// return 1; - // propagate bifurcated dimensions - *dims0 = _dims0; - *dims1 = _dims1; - return 0; -} +// // propagate bifurcated dimensions +// *dims0 = _dims0; +// *dims1 = _dims1; +// return 0; +// } diff --git a/cursetree/dims.h b/cursetree/dims.h index 9ad42eb..ec4d5a3 100644 --- a/cursetree/dims.h +++ b/cursetree/dims.h @@ -1,11 +1,23 @@ #ifndef CURSETREE_DIMS_H #define CURSETREE_DIMS_H +#define __BOUND_UNLIMITED (-1) +#define __BOUND_ABS_MIN (1) +#define __BOUND_ABS_MAX (INT_MAX) +#define __BOUND_REL_MIN ((float)0) +#define __BOUND_REL_MAX ((float)1) + enum ct_axis { AXIS_X, AXIS_Y, }; +enum ct_boundtype { + BOUND_NONE, + BOUND_ABSOLUTE, + BOUND_RELATIVE, +}; + /* Stores a node's starting x,y coordinates, width, & height. * NOTE: Intended for interfunction communication. */ @@ -13,11 +25,22 @@ struct ct_dims { int x, y, width, height; }; +struct ct_bounds { + enum ct_boundtype type; + int wmin, wmax, hmin, hmax; +}; + struct ct_dims *new_dims(int x, int y, int width, int height); struct ct_dims *dup_dims(const struct ct_dims *const dims); -int bifurcate_dims(const struct ct_dims *const parent_dims, - const enum ct_axis axis, const float ratio, - struct ct_dims **const dims0, struct ct_dims **const dims1); +struct ct_bounds *bounds_none(void); +struct ct_bounds *bounds_absolute(int wmin, int wmax, int hmin, int hmax); +struct ct_bounds *bounds_relative(int wmin, int wmax, int hmin, int hmax); +struct ct_bounds *dup_bounds(const struct ct_bounds *const bounds); + +// int bifurcate_dims(const struct ct_dims *const parent_dims, +// const enum ct_axis axis, const float ratio, +// struct ct_dims **const dims0, struct ct_dims **const +// dims1); #endif /* CURSETREE_DIMS_H */ diff --git a/cursetree/ncrswrap.c b/cursetree/ncrswrap.c index d3b89c8..c74e270 100644 --- a/cursetree/ncrswrap.c +++ b/cursetree/ncrswrap.c @@ -68,6 +68,10 @@ void init_ncurses(void) { curs_set(0); // hide cursor } +void end_ncurses(void) { + endwin(); +} + /* Initialise (with default IO configuration) a new ncurses WINDOW. */ WINDOW *new_window(const int x, const int y, const int width, @@ -105,7 +109,7 @@ struct ct_dims *windims(WINDOW *win) { * NOTE: Failure occurs if width or height <= 0, * NOTE: or if the x,y coordinate is outside the screen bounds. */ -int resizemv_window(const int x, const int y, const int width, const int height, - WINDOW *const win) { +int resizemv_window(WINDOW *const win, const int x, const int y, + const int width, const int height) { return wresize(win, height, width) || mvwin(win, y, x); } diff --git a/cursetree/ncrswrap.h b/cursetree/ncrswrap.h index 900a914..457936e 100644 --- a/cursetree/ncrswrap.h +++ b/cursetree/ncrswrap.h @@ -3,9 +3,9 @@ #include "dims.h" -# ifndef __NCURSES_H +#ifndef __NCURSES_H typedef struct _win_st WINDOW; -# endif /* __NCURSES_H */ +#endif /* __NCURSES_H */ enum crs_termmode { /* tty cbreak mode */ @@ -20,22 +20,25 @@ enum crs_termmode { int termmode(const enum crs_termmode mode); void termsize(int *const width, int *const height); +struct ct_dims *termdims(void); void init_ncurses(void); +void end_ncurses(void); WINDOW *new_window(const int x, const int y, const int width, const int height); WINDOW *new_window_fs(void); void destroy_window(WINDOW *); #define winpos(win, x, y) (x = winposx(win), y = winposy(win)) -#define winsize(win, width, height) (width = winwidth(win), height=winheight(win)) +#define winsize(win, width, height) \ + (width = winwidth(win), height = winheight(win)) int winposx(WINDOW *const); int winposy(WINDOW *const); int winwidth(WINDOW *const); int winheight(WINDOW *const); struct ct_dims *windims(WINDOW *win); -int resizemv_window(const int x, const int y, const int width, const int height, - WINDOW *const win); +int resizemv_window(WINDOW *const win, const int x, const int y, + const int width, const int height); #endif /* CURSETREE_NCRSWRAP_H */ diff --git a/cursetree/node.c b/cursetree/node.c index 3a91945..f7d786a 100644 --- a/cursetree/node.c +++ b/cursetree/node.c @@ -1,153 +1,259 @@ #include #include -#include -#include "ncrswrap.h" +#include "dims.h" #include "node.h" +#include "surface.h" /* Internal allocator method for ct_node structures. */ -static inline struct ct_node *__alloc_node(const enum ct_nodetype type) { +static inline struct ct_node *__alloc_node(void) { struct ct_node *node = (struct ct_node *)malloc(sizeof(struct ct_node)); - node->type = type; return node; } -/* Construct a new window node (ct_node of type NODE_WIN). +/* Returns NULL if memory allocation failed. */ -struct ct_node *init_window_node(WINDOW *const win) { - struct ct_node *node = __alloc_node(NODE_WINDOW); - node->win = win; +struct ct_node *new_node(struct ct_dims *const dims, + struct ct_bounds *const bounds, + struct ct_node *const parent) { + struct ct_node *node = __alloc_node(); + if (node == NULL) { + *node = (struct ct_node){ + .surface = new_surface(dims, bounds), - return node; -} - -static struct ct_node * -auto_window_node(const struct ct_dims *const dims) { - WINDOW *win = new_window(dims->x, dims->y, dims->width, dims->height); - return init_window_node(win); -} - -static struct ct_node *init_abstract_node(struct ct_node *const node0, - struct ct_node *const node1, - const enum ct_axis axis, - const float ratio, - struct ct_dims *const dims) { - struct ct_node *node = __alloc_node(NODE_ABSTRACT); - node->axis = axis; - node->ratio = ratio; - node->dims = dims; - - node->child[0] = node0; - node->child[1] = node1; - return node; -} - -void destroy_node(struct ct_node *const node) { - if (node->type == NODE_WINDOW) { - /* Window Node */ - destroy_window(node->win); - goto end; + .parent = parent, + .child = (struct ct_node **)malloc(NODE_INIT_CHILDREN * + sizeof(struct ct_node *)), + .csize = NODE_INIT_CHILDREN, + .cindex = 0, + .axis = AXIS_X, + .ratio = 0, + }; } - /* Abstract Node */ - assert(node->type == NODE_ABSTRACT); - destroy_node(node->child[0]); - destroy_node(node->child[1]); - free(node->dims); -end: + return node; +} + +/* WARNING: Do NOT use __destroy_node() to destroy a node's children! + * WARNING: Use the destroy_child_node() function instead. + */ +void __destroy_node(struct ct_node *const node) { + if (node == NULL) + return; + + // destroy children first + for (int j = 0; j < node->cindex; j++) { + __destroy_node(node->child[j]); + } + + destroy_surface(node->surface); free(node); } -static inline struct ct_dims *nodedims(const struct ct_node *const node) { - struct ct_dims *dims; - if (node->type == NODE_WINDOW) { - /* Window Node */ - dims = windims(node->win); - } else { - /* Abstract Node */ - assert(node->type == NODE_ABSTRACT); - dims = dup_dims(node->dims); +void satisfy_node(struct ct_node *const node, struct ct_dims *const dims) { + double axismax; + if (IS_PARENT_NODE(node)) { + for (int i = 0; i < node->cindex; i++) { + if (node->axis == AXIS_X) { + axismax += dims->width * node->child[i]->surface->bounds->wmax; + } else { + assert(node->axis == AXIS_Y); + axismax += dims->width * node->child[i]->surface->bounds->hmax; + } + } } - - return dims; } -/* NOTE: resize_node calls wnoutrefresh(3x), which expects - * NOTE: a call doupdate(3x) call afterwards to flush ncurses - * NOTE: virtual screen to the physical screen. +/* */ -void resize_node(struct ct_node *const node, - struct ct_dims *const new_dims) { - if (node->type == NODE_WINDOW) { - /* Window Node */ - resizemv_window(new_dims->x, new_dims->y, new_dims->width, new_dims->height, - node->win); - free(new_dims); +void resize_node(struct ct_node *const node, struct ct_dims *const dims) { + int cwidth, cheight; // child dimensions - wnoutrefresh(node->win); + if (IS_PARENT_NODE(node)) { + dims->width / node->cindex; + } + + resize_surface(node->surface, dims); + + for (int j = 0; j < node->cindex; j++) { + /* TODO */ + resize_node(node->child[j], TODO); + } + // bifurcate_dims(dims, node->axis, node->ratio, &dims0, &dims1); + + // resize_node(node->child[0], dims0); + // resize_node(node->child[1], dims1); +} + +static int __set_cbounds(struct ct_node *const parent, + const struct ct_node *const child, + const bool additive) { + /* child and parent w/h min aliases */ + int c_wmin, c_hmin; + int p_wmin_rel, p_hmin_rel; + + c_wmin = child->surface->bounds->wmin; + c_hmin = child->surface->bounds->hmin; + + if (!additive) { + c_wmin *= -1; + c_hmin *= -1; + } + + if (child->surface->bounds->type == BOUND_RELATIVE) { + parent->cbounds.wmin_abs++; + parent->cbounds.hmin_abs++; + + p_wmin_rel = parent->cbounds.wmin_rel + c_wmin; + p_hmin_rel = parent->cbounds.hmin_rel + c_wmin; + if (p_wmin_rel > __BOUND_REL_MAX || p_hmin_rel >= __BOUND_REL_MAX) + return 1; + + parent->cbounds.wmin_rel = p_wmin_rel; + parent->cbounds.hmin_rel = p_hmin_rel; + assert(parent->cbounds.wmin_rel > __BOUND_REL_MIN); + assert(parent->cbounds.hmin_rel > __BOUND_REL_MIN); } else { - /* Abstract Node */ - assert(node->type == NODE_ABSTRACT); - struct ct_dims *dims0, *dims1; - - free(node->dims); - node->dims = new_dims; - bifurcate_dims(new_dims, node->axis, node->ratio, &dims0, &dims1); - - resize_node(node->child[0], dims0); - resize_node(node->child[1], dims1); + parent->cbounds.wmin_abs += c_wmin; + parent->cbounds.hmin_abs += c_hmin; + assert(parent->cbounds.wmin_abs > __BOUND_ABS_MIN); + assert(parent->cbounds.hmin_abs > __BOUND_ABS_MIN); } + return 0; } -/* 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_axis - invert index of the original node in the new abstract node +/* Returns: + * 0 -> success + * 1 -> failed (max child limit reached) + * 2 -> failed (cumulative relative bounds surpasses 100%) */ -static void __bifurcate_window_node(struct ct_node **const node, - const enum ct_axis axis, const int invert_axis, - const float ratio) { - assert((*node)->type == NODE_WINDOW); - struct ct_dims *dims0, *dims1; - struct ct_node *node0, *node1; +int insert_child_node(struct ct_node *const parent, struct ct_node *const child, + const cindex i) { + if (parent->cindex == CINDEX_MAX) + return 1; + else if (__set_cbounds(parent, child, true)) + return 2; + else if (parent->cindex == parent->csize) { + // grow child array size and clamp maximum + parent->csize *= NODE_CHILDREN_GROWTH; + if (parent->csize > CINDEX_MAX) + parent->csize = CINDEX_MAX; - struct ct_dims *original_dims = nodedims(*node); - if (bifurcate_dims(original_dims, axis, ratio, &dims0, &dims1)) { - /* TODO: handle this error properly */ - free(original_dims); - exit(1); - return; + parent->child = + reallocarray(parent->child, parent->csize, sizeof(struct ct_node *)); } - if (invert_axis) { - /* Inverted Bifurcation */ - node0 = auto_window_node(dims0); - node1 = *node; - resize_node(node1, dims1); + // shift all children up for insertion + for (int j = parent->cindex; j > i; j--) { + parent->child[j] = parent->child[j - 1]; + } + // do insertion + parent->child[i] = child; + parent->cindex++; + return EXIT_SUCCESS; +} + +/* Returns: + * 0 -> success + * 1 -> failed (max child limit reached) + * 2 -> failed (cumulative relative bounds surpasses 100%) + */ +int append_child_node(struct ct_node *const parent, + struct ct_node *const child) { + return insert_child_node(parent, child, parent->cindex); +} + +/* Remove a child node from a parent node by index. + * Returns NULL if an invalid index was provided, otherwise returns + * a pointer to the child node removed. + * NOTE: This does NOT destroy the child node and should be + * NOTE: used when moving the child somewhere else. + * NOTE: Otherwise use destroy_child_node() instead. + */ +struct ct_node *remove_child_node(struct ct_node *const parent, + const cindex i) { + struct ct_node *child; + + if (i >= parent->cindex) + return NULL; + else if (parent->cindex <= parent->csize / NODE_CHILDREN_GROWTH) { + // shrink child array to avoid memory bloat + parent->csize /= NODE_CHILDREN_GROWTH; + parent->child = + reallocarray(parent->child, parent->csize, sizeof(struct ct_node *)); + } + + child = &parent[i]; + // shift all children down to fill removal + for (int j = i; j < parent->cindex; j++) { + parent->child[j] = parent->child[j + 1]; + } + parent->cindex--; + __set_cbounds(parent, child, false); + return child; +} + +/* Remove and destroy a child node by index. + * Returns 1 on failure (invalid index provided), and 0 on success. + * NOTE: Use remove_child_node() instead if the child should live. + */ +int destroy_child_node(struct ct_node *const parent, const cindex i) { + struct ct_node *child = remove_child_node(parent, i); + __destroy_node(child); + return (child == NULL); +} + +/* + * Returns: + * 0 -> success + * 1 -> failed (node has no parent) + * 2 -> failed (parent has no reference to node, CRITICAL) + */ +static int __index_as_child(const struct ct_node *const node, + int *const index) { + if (node->parent == NULL) + return 1; + + for (int i = 0; i < node->parent->cindex; i++) { + if (node->parent->child[i] == node) { + *index = i; + return 0; + } + } + + return 2; +} + +/* + * If preserve_bounds is set then upon collapse the new node maintains the + * original node's bounds struct. Otherwise the bounds of the child collapsed + * onto are used. + */ +void collapse_node(struct ct_node **const node, const int i, + const bool preserve_bounds) { + assert(0 <= i && i < (*node)->cindex); + int parent_index; + struct ct_node *const parent = (*node)->parent; + struct ct_node *collapse_target = remove_child_node(*node, i); + struct ct_dims *dims = dup_dims((*node)->surface->dims); + struct ct_bounds *bounds; + + if (preserve_bounds) { + bounds = dup_bounds((*node)->surface->bounds); + rebind_surface(collapse_target->surface, bounds); + } + + /* Destroy original node and point to the collapse_target */ + if (__index_as_child(*node, &parent_index)) { + /* __index_as_child fails (typically) because + * the *node is cursetree's root node. */ + __destroy_node(*node); + *node = collapse_target; } else { - /* Non-Inverted Bifurcation */ - node0 = *node; - node1 = auto_window_node(dims1); - resize_node(node0, dims0); + destroy_child_node(parent, parent_index); + insert_child_node(parent, collapse_target, parent_index); } - *node = init_abstract_node(node0, node1, axis, ratio, original_dims); -} - -/* Collapse an abstract node, killing one child node and resizing - * the other to take its place. - */ -static void collapse_abstract_node(struct ct_node **const 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 ct_node *collapse_target = (*node)->child[collapse_i]; - free(*node); - *node = collapse_target; + resize_node(collapse_target, dims); } diff --git a/cursetree/node.h b/cursetree/node.h index f10b70c..9f713e7 100644 --- a/cursetree/node.h +++ b/cursetree/node.h @@ -2,48 +2,52 @@ #define CURSETREE_NODE_H #include "dims.h" +#include "limits.h" +#include "surface.h" -# ifndef __NCURSES_H +#ifndef __NCURSES_H typedef struct _win_st WINDOW; -# endif /* __NCURSES_H */ +#endif /* __NCURSES_H */ -#define NODE_CHILD_N 2 +#define NODE_INIT_CHILDREN 4 +#define NODE_CHILDREN_GROWTH 1.5 +#define CINDEX_MAX UCHAR_MAX -/* MACRO: - * Get widnow node start x,y coordinates, width, & height. - * void NODEDIMS(struct ct_node *node, struct ct_dims dims); - */ -#define GET_WNODEDIMS(dims, node) \ - (getbegyx((node)->win, dims.y, dims.x)); \ - getmaxyx((node)->win, dims.y, dims.x) - -enum ct_nodetype { - NODE_WINDOW, - NODE_ABSTRACT, -}; +/* Child Index */ +typedef unsigned char cindex; struct ct_node { - enum ct_nodetype type; - // union value depends on ct_node.type - union { - WINDOW *win; - struct { - enum ct_axis axis; - float ratio; - struct ct_dims *dims; - struct ct_node *child[NODE_CHILD_N]; - }; - }; + struct ct_surface *surface; + + struct ct_node *parent; + enum ct_axis axis; + struct ct_node **child; + cindex csize, cindex; + /* child imposed minimum bounds */ + struct { + int wmin_abs; + int hmin_abs; + int wmin_rel; + int hmin_rel; + } cbounds; + + float ratio; }; /* === External Interface === */ -struct ct_node *init_window_node(WINDOW *const win); -void destroy_node(struct ct_node *const node); -void resize_node(struct ct_node *const node, - struct ct_dims *const new_dims); +#define IS_PARENT_NODE(node) (node->cindex != 0) -void bifurcate_window_node(struct ct_node **const node, - const enum ct_axis axis, const int invert_axis, - const float ratio); +struct ct_node *new_node(struct ct_dims *const dims, + struct ct_bounds *const bounds, + struct ct_node *const parent); +void destroy_node(struct ct_node *const node); +void resize_node(struct ct_node *const node, struct ct_dims *const new_dims); + +void collapse_node(struct ct_node **const node, const int i, + const bool preserve_bounds); + +// void bifurcate_window_node(struct ct_node **const node, const enum ct_axis +// axis, +// const int invert_axis, const float ratio); #endif /* CURSETREE_NODE_H */ diff --git a/cursetree/surface.c b/cursetree/surface.c new file mode 100644 index 0000000..ac1ee50 --- /dev/null +++ b/cursetree/surface.c @@ -0,0 +1,46 @@ +#include + +#include "ncrswrap.h" +#include "surface.h" + +static inline struct ct_surface *__surface(struct ct_dims *const dims, + struct ct_bounds *const bounds, + WINDOW *const win) { + struct ct_surface *surface; + + surface = (struct ct_surface *)malloc(sizeof(struct ct_surface)); + *surface = (struct ct_surface){ + .dims = dims, + .bounds = bounds, + .win = win, + .updatereq = true, + }; + + return surface; +} + +struct ct_surface *new_surface(struct ct_dims *const dims, + struct ct_bounds *const bounds) { + WINDOW *const win = new_window(dims->x, dims->y, dims->width, dims->height); + return __surface(dims, bounds, win); +} + +void destroy_surface(struct ct_surface *const surface) { + destroy_window(surface->win); + free(surface->dims); +} + +void resize_surface(struct ct_surface *const surface, + struct ct_dims *const dims) { + free(surface->dims); + surface->dims = dims; + surface->updatereq = true; + + resizemv_window(surface->win, dims->x, dims->y, dims->width, dims->height); +} + +void rebind_surface(struct ct_surface *const surface, + struct ct_bounds *const bounds) { + free(surface->bounds); + surface->bounds = bounds; +} diff --git a/cursetree/surface.h b/cursetree/surface.h new file mode 100644 index 0000000..b130cd7 --- /dev/null +++ b/cursetree/surface.h @@ -0,0 +1,26 @@ +#ifndef CURSETREE_SURFACE_H +#define CURSETREE_SURFACE_H + +#include "dims.h" + +#ifndef __NCURSES_H +typedef struct _win_st WINDOW; +#endif /* __NCURSES_H */ + +struct ct_surface { + struct ct_dims *dims; + struct ct_bounds *bounds; + WINDOW *win; + unsigned char updatereq; +}; + +struct ct_surface *new_surface(struct ct_dims *const dims, + struct ct_bounds *const bounds); +void destroy_surface(struct ct_surface *const surface); + +void resize_surface(struct ct_surface *const surface, + struct ct_dims *const dims); +void rebind_surface(struct ct_surface *const surface, + struct ct_bounds *const bounds); + +#endif /* CURSETREE_SURFACE_H */ diff --git a/cursetree/tree.c b/cursetree/tree.c index 26175c3..6a91937 100644 --- a/cursetree/tree.c +++ b/cursetree/tree.c @@ -5,22 +5,19 @@ /* */ -static struct ct_node *init_root_node(void) { - WINDOW *rootwin; - - rootwin = new_window_fs(); - return init_window_node(rootwin); +static inline struct ct_node *__root_node(void) { + return new_node(termdims(), NULL); } int init_tree(struct ct_tree **const tree) { - *tree = (struct ct_tree *)malloc(sizeof(struct ct_tree)); - (*tree)->root = init_root_node(); -return EXIT_SUCCESS; + *tree = (struct ct_tree *)malloc(sizeof(struct ct_tree)); + (*tree)->root = __root_node(); + return EXIT_SUCCESS; } void destroy_tree(struct ct_tree *const tree) { destroy_node(tree->root); - endwin(); + end_ncurses(); free(tree); } @@ -28,3 +25,14 @@ void resize_tree(struct ct_tree *const tree, struct ct_dims *const dims) { resize_node(tree->root, dims); } +void switch_nodes(struct ct_node **const node0, struct ct_node **const node1) { + struct ct_node *const node0ptr = *node0; + struct ct_dims *const node0dims = dup_dims((*node0)->dims); + struct ct_dims *const node1dims = dup_dims((*node1)->dims); + + *node0 = *node1; + resize_node(*node0, node1dims); + + *node1 = node0ptr; + resize_node(*node1, node0dims); +}