nonbinary-tree(TM) now works in a very minimal instance

This commit is contained in:
Emile Clark-Boman 2025-09-16 16:48:02 +10:00
parent 330755591b
commit b16590fd5a
15 changed files with 132 additions and 216 deletions

View file

@ -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/

View file

@ -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);

6
cursetree/_ncurses.h Normal file
View file

@ -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 <ncursesw/ncurses.h>

View file

@ -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;
}
}

View file

@ -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));

View file

@ -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 */

View file

@ -1,8 +1,7 @@
#include <locale.h>
#include <unistd.h>
/* libncurses with wide-character support. */
#include <ncursesw/ncurses.h>
#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.

View file

@ -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);

View file

@ -1,5 +1,4 @@
#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -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;
}

View file

@ -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 */

View file

@ -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,
.
}
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);
}