From b16590fd5a1fe99ba275f71fc6e64412d7e6c100 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Tue, 16 Sep 2025 16:48:02 +1000 Subject: [PATCH] nonbinary-tree(TM) now works in a very minimal instance --- Makefile | 4 +- cli/main.c | 26 +------- cursetree/_ncurses.h | 6 ++ cursetree/cursetree.c | 13 ++-- cursetree/dims.c | 2 +- cursetree/dims.h | 7 +-- cursetree/ncrswrap.c | 25 ++++---- cursetree/ncrswrap.h | 16 ++--- cursetree/node.c | 143 ++++++++++++------------------------------ cursetree/node.h | 21 ++++--- cursetree/nsparted.c | 11 ---- cursetree/nsparted.h | 26 -------- cursetree/surface.c | 33 +++++++++- cursetree/surface.h | 11 +++- cursetree/tree.c | 4 +- 15 files changed, 132 insertions(+), 216 deletions(-) create mode 100644 cursetree/_ncurses.h delete mode 100644 cursetree/nsparted.c delete mode 100644 cursetree/nsparted.h diff --git a/Makefile b/Makefile index 4894efc..40dc834 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ $(BUILD) $(BIN): $(BUILD)/dorne.o: $(addprefix $(CLI)/, main.c) $(call mkobj,-Icursetree) -$(BUILD)/cursetree.o: $(addprefix $(CT)/, cursetree.c ncrswrap.c) +$(BUILD)/cursetree.o: $(addprefix $(CT)/, cursetree.c tree.c node.c surface.c dims.c ncrswrap.c) $(call mkobj,) $(BUILD)/epty.o: $(addprefix $(CT)/, pty/child.c pty/epty.c pty/_pty.c) $(call mkobj,) @@ -56,4 +56,4 @@ test: clean run # === UTILITY TARGETS === .PHONY: clean clean: - - rm -rf $(BUILD) $(BIN) vgcore.* &>/dev/null + - rm -rf $(BUILD) $(BIN) vgcore.* &>/dev/null logs/ diff --git a/cli/main.c b/cli/main.c index 6c852ba..f78dee2 100644 --- a/cli/main.c +++ b/cli/main.c @@ -7,40 +7,18 @@ #include "cursetree.h" int main(int argc, char **argv) { - struct crs_tree *tree; + struct ct_tree *tree; ct_init(&tree); init_pair(1, COLOR_CYAN, COLOR_CYAN); init_pair(2, COLOR_RED, COLOR_RED); - bifurcate_window_node(&tree->root, AXIS_X, FALSE, 0.5); - // wbkgd(tree->root->child[0]->win, COLOR_PAIR(1)); - // wbkgd(tree->root->child[1]->win, COLOR_PAIR(2)); - // wrefresh(tree->root->child[0]->win); - // wrefresh(tree->root->child[1]->win); - // wbkgd(tree->root->win, COLOR_PAIR(1)); // wrefresh(tree->root->win); int i = 1; - while (1) { - /* TODO: UNCOMMENT START */ - // wclear(tree->root->child[0]->win); - // wclear(tree->root->child[1]->win); - // wbkgd(tree->root->child[0]->win, COLOR_PAIR(i)); - // wbkgd(tree->root->child[1]->win, COLOR_PAIR(3 - i)); - - // wnoutrefresh(tree->root->child[0]->win); - // wnoutrefresh(tree->root->child[1]->win); - // doupdate(); - - // wrefresh(tree->root->child[0]->win); - // wrefresh(tree->root->child[1]->win); - i = 3 - i; - /* TODO: UNCOMMENT END */ - + while (1) { ct_update(tree); - // usleep(100000); } destroy_tree(tree); diff --git a/cursetree/_ncurses.h b/cursetree/_ncurses.h new file mode 100644 index 0000000..dc92562 --- /dev/null +++ b/cursetree/_ncurses.h @@ -0,0 +1,6 @@ +/* This file exists to isolate the ncurses instance being used + * ie ncurses, ncursesw, ncursest, ncursestw + */ + +/* libncurses with wide-character support. */ +#include diff --git a/cursetree/cursetree.c b/cursetree/cursetree.c index 6d9a87e..90b1476 100644 --- a/cursetree/cursetree.c +++ b/cursetree/cursetree.c @@ -2,6 +2,7 @@ #include "ncrswrap.h" #include "tree.h" +#include "_ncurses.h" int ct_init(struct ct_tree **const tree) { /* Initialise NCurses Library & Root Node */ @@ -21,9 +22,9 @@ void ct_update(struct ct_tree *const tree) { */ switch (key) { case -1: - wclear(tree->root->child[0]->win); - mvwprintw(tree->root->child[0]->win, 0, 0, " \r-1\n"); - wrefresh(tree->root->child[0]->win); + wclear(tree->root->surface->win); + mvwprintw(tree->root->surface->win, 0, 0, " \r-1\n"); + wrefresh(tree->root->surface->win); return; case KEY_RESIZE: resize_tree(tree, termdims()); @@ -31,9 +32,9 @@ void ct_update(struct ct_tree *const tree) { doupdate(); break; default: - wclear(tree->root->child[0]->win); - mvwprintw(tree->root->child[0]->win, 0, 0, " \r%d\n", key); - wrefresh(tree->root->child[0]->win); + wclear(tree->root->surface->win); + mvwprintw(tree->root->surface->win, 0, 0, " \r%d\n", key); + wrefresh(tree->root->surface->win); break; } } diff --git a/cursetree/dims.c b/cursetree/dims.c index 7d7401e..e4073a2 100644 --- a/cursetree/dims.c +++ b/cursetree/dims.c @@ -6,7 +6,7 @@ #include "dims.h" #include "util.h" -struct ct_dims *new_dims(int x, int y, int width, int height) { +struct ct_dims *new_dims(const int x, const int y, const int width, const int height) { struct ct_dims *dims; dims = (struct ct_dims *)malloc(sizeof(struct ct_dims)); diff --git a/cursetree/dims.h b/cursetree/dims.h index ec4d5a3..25e6ccc 100644 --- a/cursetree/dims.h +++ b/cursetree/dims.h @@ -30,7 +30,7 @@ struct ct_bounds { int wmin, wmax, hmin, hmax; }; -struct ct_dims *new_dims(int x, int y, int width, int height); +struct ct_dims *new_dims(const int x, const int y, const int width, const int height); struct ct_dims *dup_dims(const struct ct_dims *const dims); struct ct_bounds *bounds_none(void); @@ -38,9 +38,4 @@ 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 c74e270..d81cc4b 100644 --- a/cursetree/ncrswrap.c +++ b/cursetree/ncrswrap.c @@ -1,8 +1,7 @@ #include #include -/* libncurses with wide-character support. */ -#include +#include "_ncurses.h" #include "ncrswrap.h" @@ -90,19 +89,19 @@ WINDOW *new_window_fs(void) { return rootwin; } -void destroy_window(WINDOW *) __attribute__((alias("delwin"))); +// 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"))); +// 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); -} +// 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. diff --git a/cursetree/ncrswrap.h b/cursetree/ncrswrap.h index 457936e..c6845e0 100644 --- a/cursetree/ncrswrap.h +++ b/cursetree/ncrswrap.h @@ -29,14 +29,14 @@ 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)) -int winposx(WINDOW *const); -int winposy(WINDOW *const); -int winwidth(WINDOW *const); -int winheight(WINDOW *const); -struct ct_dims *windims(WINDOW *win); +// #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(WINDOW *const win, const int x, const int y, const int width, const int height); diff --git a/cursetree/node.c b/cursetree/node.c index cd43598..4c5a300 100644 --- a/cursetree/node.c +++ b/cursetree/node.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -19,18 +18,13 @@ static inline struct ct_node *__alloc_node(void) { /* Returns NULL if memory allocation failed. * TODO: should dims be given as a parameter, or lazily computed in ct_update? */ -struct ct_node *new_node(struct ct_dims *const dims, - struct ct_bounds *const bounds, - struct ct_node *const parent) { +struct ct_node *__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){ - /* copy the parent's dimensions for now and request - * cursetree resize this node appropriately afterwards - * WARNING: new_node doesn't set the NFLAG_RESIZE request flag - * WARNING: that should be done by a function calling new_node - */ - .surface = new_surface(parent->surface->dims, bounds), + .surface = new_surface(dims, bounds), .flags = NFLAG_EMPTY, .parent = parent, @@ -45,6 +39,16 @@ struct ct_node *new_node(struct ct_dims *const dims, return node; } +struct ct_node *new_node(struct ct_bounds *const bounds, + struct ct_node *const parent) { + /* copy the parent's dimensions for now and request + * cursetree resize this node appropriately afterwards + * WARNING: new_node doesn't set the NFLAG_RESIZE request flag + * WARNING: that should be done by a function calling new_node + */ + return __node(parent->surface->dims, bounds, parent); +} + /* WARNING: Do NOT use __destroy_node() to destroy a node's children! * WARNING: Use the destroy_child_node() function instead. */ @@ -61,26 +65,11 @@ void __destroy_node(struct ct_node *const node) { free(node); } -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; - } - } - } -} - /* Surface Partition Dimensions */ /* TODO: can I use unsigned short instead of int? */ struct ct_spdims { // Main Axis & Orthogonal Axis Sizes int axm_size; - // int axo_size; bool fixed; int min, max; }; @@ -88,69 +77,66 @@ struct ct_spdims { /* */ int resize_node(struct ct_node *const node, struct ct_dims *const dims) { - // if (IS_PARENT_NODE(node)) { - // dims->width / node->cindex; - // } - resize_surface(node->surface, dims); + if (node->surface->bounds->wmin > dims->width || + node->surface->bounds->hmin > dims->height) { + node->flags |= NFLAG_SMALL; + return 1; + } else if (node->surface->bounds->wmax < dims->width || + node->surface->bounds->hmax < dims->height) { + node->flags |= NFLAG_LARGE; + return 1; + } + + if (!IS_PARENT_NODE(node)) + return 0; + if (node->cbounds.wmin_abs + node->cbounds.wmin_rel * dims->width > dims->width || node->cbounds.hmin_abs + node->cbounds.hmin_rel * dims->height > dims->height) { - node->flags |= NFLAG_TOOSMALL; + node->flags |= NFLAG_SMALLCHILD; return 1; } int axm_size, axm_free; - // int axo_size; size_t bounds_axm_min_offset, bounds_axm_max_offset; size_t dims_axm_pos_offset, dims_axm_size_offset; - // size_t dims_axo_pos_offset, dims_axo_size_offset; if (node->axis == AXIS_X) { axm_free = dims->width; axm_size = dims->width; - // axo_size = dims->height; - - bounds_axm_min_offset = offsetof(struct ct_bounds, wmin); - bounds_axm_max_offset = offsetof(struct ct_bounds, wmax); dims_axm_pos_offset = offsetof(struct ct_dims, x); - // dims_axo_pos_offset = offsetof(struct ct_dims, y); dims_axm_size_offset = offsetof(struct ct_dims, width); - // dims_axo_size_offset = offsetof(struct ct_dims, height); + bounds_axm_min_offset = offsetof(struct ct_bounds, wmin); + bounds_axm_max_offset = offsetof(struct ct_bounds, wmax); } else { assert(node->axis == AXIS_Y); axm_free = dims->height; axm_size = dims->height; - // axo_size = dims->width; - - bounds_axm_min_offset = offsetof(struct ct_bounds, hmin); - bounds_axm_max_offset = offsetof(struct ct_bounds, hmax); dims_axm_pos_offset = offsetof(struct ct_dims, y); - // dims_axo_pos_offset = offsetof(struct ct_dims, x); dims_axm_size_offset = offsetof(struct ct_dims, height); - // dims_axo_size_offset = offsetof(struct ct_dims, width); + bounds_axm_min_offset = offsetof(struct ct_bounds, hmin); + bounds_axm_max_offset = offsetof(struct ct_bounds, hmax); } struct ct_spdims cspdims[node->cindex]; - // struct ct_spdims *parts[node->cindex]; cindex parts_n = node->cindex; memset(cspdims, 0, sizeof(struct ct_spdims) * node->cindex); for (int i = 0; i < node->cindex; i++) { - cspdims[i].min = *(int *)(node->child[i]->surface->bounds + bounds_axm_min_offset); - cspdims[i].max = *(int *)(node->child[i]->surface->bounds + bounds_axm_max_offset); + cspdims[i].min = + *(int *)(node->child[i]->surface->bounds + bounds_axm_min_offset); + cspdims[i].max = + *(int *)(node->child[i]->surface->bounds + bounds_axm_max_offset); if (node->child[i]->surface->bounds->type == BOUND_RELATIVE) { cspdims[i].min *= axm_size; cspdims[i].max *= axm_size; } cspdims[i].axm_size = 0; - // cspdims[i].axo_size = axo_size; - - // parts[i] = &cspdims[i]; } int split, new_size; @@ -173,69 +159,18 @@ int resize_node(struct ct_node *const node, struct ct_dims *const dims) { } } - /* TODO: using axo_size this way means cspdims doesn't need an axo field!! */ - struct ct_dims * cdims = dup_dims(dims); + struct ct_dims *cdims = dup_dims(dims); /* NOTE: the statements below are done implicitly by dup_dims */ // *(int*)(cdims + dims_axm_pos_offset) = *(int*)(dims + dims_axm_pos_offset); // *(int*)(cdims + dims_axo_pos_offset) = *(int*)(dims + dims_axo_pos_offset); // *(int*)(cdims + dims_axo_size_offset) = axo_size; for (int i = 0; i < node->cindex; i++) { - *(int*)(cdims + dims_axm_size_offset) = cspdims[i].axm_size; + *(int *)(cdims + dims_axm_size_offset) = cspdims[i].axm_size; resize_node(node->child[i], dup_dims(cdims)); - *(int*)(cdims + dims_axm_pos_offset) += cspdims[i].axm_size; + *(int *)(cdims + dims_axm_pos_offset) += cspdims[i].axm_size; } free(cdims); - // int split = axm_free / node->cindex; - // for (int j = 0; j < node->cindex; j++) { - // cwhdims[j].min = *(int*)(node->child[j]->surface->bounds + - // axm_min_offset); cwhdims[j].max = *(int*)(node->child[j]->surface->bounds - // + axm_max_offset); if (node->child[j]->surface->bounds->type == - // BOUND_RELATIVE) { - // cwhdims[j].min *= axm_size; - // cwhdims[j].max *= axm_size; - // } - - // cwhdims[j].axm_size = fmax(fmin(split, cwhdims[j].max), cwhdims[j].min); - // cwhdims[j].axo_size = axo_size; - - // axm_free -= cwhdims[j].axm_size; - // } - - // int delta; - // while (axm_free) { - // if (axm_free < cunfixedn) { - // int progress = 0; - // for (int j = 0; j < node->cindex; j++) { - // if (cwhdims[j].fixed) - // continue; - // cwhdims[j].axm_size--; - // axm_free--; - // } - // } - - // // split is guaranteed to be >0 - // split = axm_free / node->cindex; - // for (int j = 0; j < node->cindex; j++) { - // if (cwhdims[j].fixed) - // continue; - - // delta = cwhdims[j].axm_size - fmax(cwhdims[j].axm_size - split, - // bounds->wmin); if (delta == 0) { - // cwhdims[j].fixed = true; - // cunfixedn++; - // continue; - // } - - // cwhdims[j].axm_size -= delta; - // axm_free -= delta; - // } - // } - - // bifurcate_dims(dims, node->axis, node->ratio, &dims0, &dims1); - - // resize_node(node->child[0], dims0); - // resize_node(node->child[1], dims1); return 0; } diff --git a/cursetree/node.h b/cursetree/node.h index 9906af0..f0341f6 100644 --- a/cursetree/node.h +++ b/cursetree/node.h @@ -13,9 +13,11 @@ typedef struct _win_st WINDOW; #define NODE_CHILDREN_GROWTH 1.5 #define CINDEX_MAX UCHAR_MAX -#define NFLAG_EMPTY (0) -#define NFLAG_RESIZE (1<<0) -#define NFLAG_TOOSMALL (1<<1) +#define NFLAG_EMPTY (0) +#define NFLAG_RESIZE (1 << 0) +#define NFLAG_SMALL (1 << 1) +#define NFLAG_SMALLCHILD (1 << 2) +#define NFLAG_LARGE (1 << 3) /* Child Index */ typedef unsigned char cindex; @@ -40,17 +42,16 @@ struct ct_node { /* === External Interface === */ #define IS_PARENT_NODE(node) (node->cindex != 0) -struct ct_node *new_node(struct ct_dims *const dims, - struct ct_bounds *const bounds, +struct ct_node *__node(struct ct_dims *const dims, + struct ct_bounds *const bounds, + struct ct_node *const parent); +struct ct_node *new_node(struct ct_bounds *const bounds, struct ct_node *const parent); -void destroy_node(struct ct_node *const node); + +void __destroy_node(struct ct_node *const node); int 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/nsparted.c b/cursetree/nsparted.c deleted file mode 100644 index 67231c3..0000000 --- a/cursetree/nsparted.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "nsparted.h" - -struct ct_nsparted init_nsparted(struct ct_node *const node, - struct ct_dims *const dims) { - struct ct_nsparted nsparted = (struct ct_nsparted) { - .node = node, - .dims = dims, - . - } -} - diff --git a/cursetree/nsparted.h b/cursetree/nsparted.h deleted file mode 100644 index c4fda2d..0000000 --- a/cursetree/nsparted.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CURSETREE_NSPARTED_H -#define CURSETREE_NSPARTED_H - -#include "node.h" - -/* Surface Partition Dimensions */ -struct ct_spdims { - // Main Axis & Orthogonal Axis Sizes - int axm_size, axo_size; - bool fixed; - int min, max; -}; - -/* Node Surface Partitioner */ -struct ct_nsparted { - struct ct_node *const node; - struct ct_dims *const dims; - - /* Child Surface Partition Dimensions */ - struct ct_spdims *const cspdims; -}; - -struct ct_nsparted *init_nsparted(struct ct_node *const node, - struct ct_dims *const dims); - -#endif /* CURSETREE_NSPARTED_H */ diff --git a/cursetree/surface.c b/cursetree/surface.c index ac1ee50..c003faa 100644 --- a/cursetree/surface.c +++ b/cursetree/surface.c @@ -2,6 +2,7 @@ #include "ncrswrap.h" #include "surface.h" +#include "_ncurses.h" static inline struct ct_surface *__surface(struct ct_dims *const dims, struct ct_bounds *const bounds, @@ -25,8 +26,8 @@ struct ct_surface *new_surface(struct ct_dims *const dims, return __surface(dims, bounds, win); } -void destroy_surface(struct ct_surface *const surface) { - destroy_window(surface->win); +void destroy_surface(const struct ct_surface *const surface) { + delwin(surface->win); free(surface->dims); } @@ -44,3 +45,31 @@ void rebind_surface(struct ct_surface *const surface, free(surface->bounds); surface->bounds = bounds; } + +void sfclear(struct ct_surface *const surface) { + wclear(surface->win); +} + +int sfwidth(const struct ct_surface *const surface) { + return getmaxx(surface->win); +} + +int sfheight(const struct ct_surface *const surface) { + return getmaxy(surface->win); +} + +int sfposx(const struct ct_surface *const surface) { + return getbegx(surface->win); +} + +int sfposy(const struct ct_surface *const surface) { + return getbegy(surface->win); +} + +struct ct_dims *sfdims(const struct ct_surface *const surface) { + int x, y, width, height; + sfpos(surface, x, y); + sfsize(surface, width, height); + return new_dims(x, y, width, height); +} + diff --git a/cursetree/surface.h b/cursetree/surface.h index b130cd7..727c489 100644 --- a/cursetree/surface.h +++ b/cursetree/surface.h @@ -16,11 +16,20 @@ struct ct_surface { struct ct_surface *new_surface(struct ct_dims *const dims, struct ct_bounds *const bounds); -void destroy_surface(struct ct_surface *const surface); +void destroy_surface(const 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); +#define sfpos(surface, x, y) (x = sfposx(surface), y = sfposy(surface)) +#define sfsize(surface, width, height) (width = sfwidth(surface), height = sfheight(surface)) + +void sclear(struct ct_surface *const surface); +int swidth(const struct ct_surface *const surface); +int sheight(const struct ct_surface *const surface); +int sposx(const struct ct_surface *const surface); +int sposy(const struct ct_surface *const surface); + #endif /* CURSETREE_SURFACE_H */ diff --git a/cursetree/tree.c b/cursetree/tree.c index b0b3b1a..4f49aff 100644 --- a/cursetree/tree.c +++ b/cursetree/tree.c @@ -6,7 +6,7 @@ /* */ static inline struct ct_node *__root_node(void) { - return new_node(termdims(), bounds_none(), NULL); + return __node(termdims(), bounds_none(), NULL); } int init_tree(struct ct_tree **const tree) { @@ -16,7 +16,7 @@ int init_tree(struct ct_tree **const tree) { } void destroy_tree(struct ct_tree *const tree) { - destroy_node(tree->root); + __destroy_node(tree->root); end_ncurses(); free(tree); }