From b04f0b4aa3cd91342ca62dbfc981362096e1a137 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Sat, 13 Sep 2025 12:44:58 +1000 Subject: [PATCH] hide behind ncrswrap.* isolate ct_dims implementation to dims.* --- cursetree/cursetree.c | 6 +-- cursetree/dims.c | 59 ++++++++++++++++++++++++++++ cursetree/dims.h | 23 +++++++++++ cursetree/ncrswrap.c | 36 +++++++++++++++-- cursetree/ncrswrap.h | 22 ++++++++--- cursetree/node.c | 89 +++---------------------------------------- cursetree/node.h | 18 ++------- cursetree/tree.c | 2 +- 8 files changed, 142 insertions(+), 113 deletions(-) create mode 100644 cursetree/dims.c create mode 100644 cursetree/dims.h diff --git a/cursetree/cursetree.c b/cursetree/cursetree.c index 4e7befd..6d9a87e 100644 --- a/cursetree/cursetree.c +++ b/cursetree/cursetree.c @@ -13,8 +13,6 @@ int ct_init(struct ct_tree **const tree) { void ct_update(struct ct_tree *const tree) { - struct ct_dims * term_dims; - int term_width, term_height; const int key = wgetch(curscr); /* ncurses binds a SIGWINCH handler if SIGWINCH has SIG_DFL disposition @@ -28,9 +26,7 @@ void ct_update(struct ct_tree *const tree) { wrefresh(tree->root->child[0]->win); return; case KEY_RESIZE: - termsize(term_width, term_height); - term_dims = __alloc_dims(0, 0, term_width, term_height); - resize_tree(tree, term_dims); + resize_tree(tree, termdims()); // flush ncurses virtual screen -> physical screen doupdate(); break; diff --git a/cursetree/dims.c b/cursetree/dims.c new file mode 100644 index 0000000..beaf2d9 --- /dev/null +++ b/cursetree/dims.c @@ -0,0 +1,59 @@ +#include +#include +#include + +#include "dims.h" + +struct ct_dims *new_dims(int x, int y, int width, int height) { + struct ct_dims *dims; + + dims = (struct ct_dims *)malloc(sizeof(struct ct_dims)); + *dims = (struct ct_dims){ + .x = x, + .y = y, + .width = width, + .height = height, + }; + return dims; +} + +struct ct_dims *dup_dims(const struct ct_dims *const dims) { + struct ct_dims *dup; + dup = (struct ct_dims *)malloc(sizeof(struct ct_dims)); + memcpy(dup, dims, sizeof(struct ct_dims)); + + 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; + + _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 (!_dims0->width || !_dims0->height || !_dims1->width || !_dims1->height) + return 1; + + // propagate bifurcated dimensions + *dims0 = _dims0; + *dims1 = _dims1; + return 0; +} diff --git a/cursetree/dims.h b/cursetree/dims.h new file mode 100644 index 0000000..9ad42eb --- /dev/null +++ b/cursetree/dims.h @@ -0,0 +1,23 @@ +#ifndef CURSETREE_DIMS_H +#define CURSETREE_DIMS_H + +enum ct_axis { + AXIS_X, + AXIS_Y, +}; + +/* Stores a node's starting x,y coordinates, width, & height. + * NOTE: Intended for interfunction communication. + */ +struct ct_dims { + int x, y, width, height; +}; + +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); + +#endif /* CURSETREE_DIMS_H */ diff --git a/cursetree/ncrswrap.c b/cursetree/ncrswrap.c index 9623447..d3b89c8 100644 --- a/cursetree/ncrswrap.c +++ b/cursetree/ncrswrap.c @@ -1,6 +1,9 @@ #include #include +/* libncurses with wide-character support. */ +#include + #include "ncrswrap.h" #define CRS_LOCALE "en_US.UTF-8" @@ -24,6 +27,18 @@ int termmode(const enum crs_termmode mode) { } } +void termsize(int *const width, int *const height) { + *width = COLS; + *height = LINES; +} + +struct ct_dims *termdims(void) { + struct ct_dims *dims = new_dims(0, 0, 0, 0); + termsize(&dims->width, &dims->height); + + return dims; +} + /* Apply a default IO configuration for an ncurses WINDOW. */ static inline void __conf_window(WINDOW *const win) { @@ -40,7 +55,7 @@ void init_ncurses(void) { // ncurses expects a locale for consistent behaviour setlocale(LC_ALL, CRS_LOCALE); - /* NCurses Init */ + /* NCurses Initialisation */ initscr(); /* WARNING: no you shouldn't delwin(stdscr) it breaks everything... */ __conf_window(stdscr); @@ -63,15 +78,28 @@ WINDOW *new_window(const int x, const int y, const int width, return win; } -/* Initialise (with default IO configuration) the root ncurses WINDOW. - * NOTE: This is typically done via initscr(3x) and called "stdscr". +/* Initialise (with default IO configuration) a fullscreen ncurses WINDOW. */ -WINDOW *root_window(void) { +WINDOW *new_window_fs(void) { WINDOW *rootwin = new_window(0, 0, COLS, LINES); __conf_window(rootwin); return rootwin; } +void destroy_window(WINDOW *) __attribute__((alias("delwin"))); + +int winposx(WINDOW *) __attribute__((alias("getbegy"))); +int winposy(WINDOW *) __attribute__((alias("getbegy"))); +int winwidth(WINDOW *) __attribute__((alias("getmaxx"))); +int winheight(WINDOW *) __attribute__((alias("getmaxy"))); + +struct ct_dims *windims(WINDOW *win) { + int x, y, width, height; + winpos(win, x, y); + winsize(win, width, height); + return new_dims(x, y, width, height); +} + /* Resize and move (if resized successfully) an ncurses WINDOW. * Returns ERR (1) on fail, and OK (0) on success. * NOTE: Failure occurs if width or height <= 0, diff --git a/cursetree/ncrswrap.h b/cursetree/ncrswrap.h index b73f4b5..900a914 100644 --- a/cursetree/ncrswrap.h +++ b/cursetree/ncrswrap.h @@ -1,8 +1,11 @@ #ifndef CURSETREE_NCRSWRAP_H #define CURSETREE_NCRSWRAP_H -/* libncurses with wide-character support. */ -#include +#include "dims.h" + +# ifndef __NCURSES_H +typedef struct _win_st WINDOW; +# endif /* __NCURSES_H */ enum crs_termmode { /* tty cbreak mode */ @@ -15,13 +18,22 @@ enum crs_termmode { TMODE_NORAW, }; -#define termsize(width, height) (width=COLS); (height=LINES) - int termmode(const enum crs_termmode mode); +void termsize(int *const width, int *const height); void init_ncurses(void); + WINDOW *new_window(const int x, const int y, const int width, const int height); -WINDOW *root_window(void); +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)) +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); diff --git a/cursetree/node.c b/cursetree/node.c index 282b363..3a91945 100644 --- a/cursetree/node.c +++ b/cursetree/node.c @@ -24,7 +24,7 @@ struct ct_node *init_window_node(WINDOW *const win) { static struct ct_node * auto_window_node(const struct ct_dims *const dims) { - WINDOW *win = newwin(dims->height, dims->width, dims->y, dims->x); + WINDOW *win = new_window(dims->x, dims->y, dims->width, dims->height); return init_window_node(win); } @@ -46,7 +46,7 @@ static struct ct_node *init_abstract_node(struct ct_node *const node0, void destroy_node(struct ct_node *const node) { if (node->type == NODE_WINDOW) { /* Window Node */ - delwin(node->win); + destroy_window(node->win); goto end; } /* Abstract Node */ @@ -59,99 +59,20 @@ end: free(node); } -static inline struct ct_dims *__alloc_dims(int x, int y, int width, - int height) { - struct ct_dims *dims; - - dims = (struct ct_dims *)malloc(sizeof(struct ct_dims)); - *dims = (struct ct_dims){ - .x = x, - .y = y, - .width = width, - .height = height, - }; - return dims; -} - -static inline struct ct_dims * -__dup_dims(const struct ct_dims *const dims) { - struct ct_dims *dup; - dup = (struct ct_dims *)malloc(sizeof(struct ct_dims)); - memcpy(dup, dims, sizeof(struct ct_dims)); - - return dup; -} - -static inline struct ct_dims *termdims(void) { - struct ct_dims *dims = __alloc_dims(0, 0, 0, 0); - termsize(dims->width, dims->height); - - return dims; -} - -static inline void nodesize(const struct ct_node *const node, int *const width, - int *const height) { - if (node->type == NODE_WINDOW) { - /* Window Node */ - getmaxyx(node->win, *height, *width); - } else { - /* Abstract Node */ - assert(node->type == NODE_ABSTRACT); - *width = node->dims->width; - *height = node->dims->height; - } -} - static inline struct ct_dims *nodedims(const struct ct_node *const node) { struct ct_dims *dims; if (node->type == NODE_WINDOW) { /* Window Node */ - dims = (struct ct_dims *)malloc(sizeof(struct ct_dims)); - getbegyx(node->win, dims->y, dims->x); - getmaxyx(node->win, dims->height, dims->width); + dims = windims(node->win); } else { /* Abstract Node */ assert(node->type == NODE_ABSTRACT); - dims = __dup_dims(node->dims); + dims = dup_dims(node->dims); } return dims; } -/* 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. - */ -static 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); - - 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; - - // propagate bifurcated dimensions - *dims0 = _dims0; - *dims1 = _dims1; - return 0; -} - /* 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. @@ -185,7 +106,7 @@ void resize_node(struct ct_node *const node, * axis - controls which direction the subdivision occurs * invert_axis - invert index of the original node in the new abstract node */ -void bifurcate_window_node(struct ct_node **const node, +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); diff --git a/cursetree/node.h b/cursetree/node.h index 439d452..f10b70c 100644 --- a/cursetree/node.h +++ b/cursetree/node.h @@ -1,9 +1,11 @@ #ifndef CURSETREE_NODE_H #define CURSETREE_NODE_H -#ifndef __NCURSES_H +#include "dims.h" + +# ifndef __NCURSES_H typedef struct _win_st WINDOW; -#endif /* __NCURSES_H */ +# endif /* __NCURSES_H */ #define NODE_CHILD_N 2 @@ -20,18 +22,6 @@ enum ct_nodetype { NODE_ABSTRACT, }; -/* Stores a node's starting x,y coordinates, width, & height. - * NOTE: Intended for interfunction communication. - */ -struct ct_dims { - int x, y, width, height; -}; - -enum ct_axis { - AXIS_X, - AXIS_Y, -}; - struct ct_node { enum ct_nodetype type; // union value depends on ct_node.type diff --git a/cursetree/tree.c b/cursetree/tree.c index acb2a25..26175c3 100644 --- a/cursetree/tree.c +++ b/cursetree/tree.c @@ -8,7 +8,7 @@ static struct ct_node *init_root_node(void) { WINDOW *rootwin; - rootwin = root_window(); + rootwin = new_window_fs(); return init_window_node(rootwin); }