shithub: libnate

Download patch

ref: 7d7806db6cd48b8ebd565f636eebc59939e72c53
parent: 794e2ee40b0345746539fbd41ad0eda122f8603e
author: sirjofri <sirjofri@sirjofri.de>
date: Sun Feb 9 16:30:56 EST 2025

generalizes free and getchildren function
 M n_box.c
 M n_box.h
 M n_button.c
 M n_hbox.c
 M n_hbox.h
 M n_image.c
 M n_label.c
 M n_vbox.c
 M n_vbox.h
 M n_window.c
 M n_window.h
 M nate.c
 M nate.h
 M nate_construct.c
 M nate_construct.h
 M test/ntest.c

--- a/n_box.c
+++ b/n_box.c
@@ -13,19 +13,20 @@
 {
 	NBox* b = (NBox*)nelem;
 	GUARD(b);
+	Nelem *child = lgetfirst(&b->children);
 	if (!b->sizetocontent) {
 		r.max = addpt(r.min, b->size);
 		/* tell child its size (important!) */
-		ncallcalcsize(lgetfirst(&b->child), screen, r);
+		ncallcalcsize(child, screen, r);
 		b->r = r;
 		return r;
 	}
-	if (!lgetfirst(&b->child)) {
+	if (!child) {
 		/* greedy */
 		b->r = r;
 		return r;
 	}
-	Rectangle csize = ncallcalcsize(lgetfirst(&b->child), screen, r);
+	Rectangle csize = ncallcalcsize(child, screen, r);
 	b->r = insetrect(csize, b->borderwidth);
 	return b->r;
 }
@@ -37,7 +38,7 @@
 	Rectangle r;
 	NBox* b = (NBox*)nelem;
 	GUARD(b);
-	f = lgetfirst(&b->child);
+	f = lgetfirst(&b->children);
 	if (!f)
 		return;
 
@@ -102,27 +103,6 @@
 	return 1;
 }
 
-static void
-box_free(Nelem* nelem)
-{
-	Nelem* ch;
-	NBox* b = (NBox*)nelem;
-	if (nisroot(b))
-		return;
-	
-	if ((ch = lgetfirst(&b->child)))
-		ncallfree(ch);
-	free(b);
-}
-
-static Nlist*
-box_getchildren(Nelem* nelem)
-{
-	NBox* b = (NBox*)nelem;
-	GUARD(b);
-	return &b->child;
-}
-
 static char*
 box_getname(Nelem *nelem)
 {
@@ -129,7 +109,7 @@
 	Nelem *ch;
 	NBox *b = (NBox*)nelem;
 	GUARD(b);
-	ch = lgetfirst(&b->child);
+	ch = lgetfirst(&b->children);
 	if (!(ch && ch->funcs && ch->funcs->getname))
 		return b->name;
 	return ch->funcs->getname(ch);
@@ -140,23 +120,10 @@
 	.draw = box_draw,
 	.checkhit = box_checkhit,
 	.hit = box_hit,
-	.free = box_free,
-	.getchildren = box_getchildren,
 	.getname = box_getname,
 };
 
-static NBox*
-box_slot(Nelem* child)
-{
-	if (child == nc_get()) {
-		nc_pop();
-	}
-	NBox* b = (NBox*)nc_get();
-	GUARD(b);
-	// TODO: potential leak!
-	lsetfirst(&b->child, child);
-	return b;
-}
+DEF_SLOTFUNC(NBox, box_slot);
 
 DEF_ACCESSOR_TwoParams(NBox, box_border, int, borderwidth, Image*, bordercolor);
 DEF_ACCESSOR_OneParam(NBox, box_sizetocontent, int, sizetocontent);
@@ -167,7 +134,7 @@
 NBox*
 New_Box(char *name)
 {
-	NBox *b = MakeNelem(NBox, NBox_Type, &Nboxfunctions, name);
+	NBox *b = MakeNelem(NBox, NBox_Type, &Nboxfunctions, name, 1);
 	
 	b->Slot = box_slot;
 	b->Border = box_border;
@@ -176,7 +143,6 @@
 	b->OnClick = box_onclick;
 	b->Padding = box_padding;
 	
-	linit(&b->child);
 	b->sizetocontent = 0;
 	b->size = ZP;
 	b->hitfunc = nil;
--- a/n_box.h
+++ b/n_box.h
@@ -11,7 +11,6 @@
 	DECL_ACCESSOR_OneParam(NBox, Padding, Nmargin);
 	
 	// private members
-	Nlist child;
 	Point size;
 	int sizetocontent;
 	int borderwidth;
--- a/n_button.c
+++ b/n_button.c
@@ -51,7 +51,7 @@
 {
 	NButton *b = (NButton*)nelem;
 	GUARD(b);
-	return &b->box->child;
+	return ncallgetchildren(b->box);
 }
 
 static Nelemfunctions Nbuttonfunctions = {
@@ -133,7 +133,7 @@
 NButton*
 New_Button(char *name)
 {
-	NButton *b = MakeNelem(NButton, NButton_Type, &Nbuttonfunctions, name);
+	NButton *b = MakeNelem(NButton, NButton_Type, &Nbuttonfunctions, name, 0);
 	
 	b->box = New_Box(name)
 		->Slot(NAssign(NLabel, &b->label, New_Label(nil)));
--- a/n_hbox.c
+++ b/n_hbox.c
@@ -62,44 +62,12 @@
 	}
 }
 
-static void
-hbox_free(Nelem* nelem)
-{
-	NHBox* b = (NHBox*)nelem;
-	if (nisroot(b))
-		return;
-	
-	lfreelist(&b->children);
-	free(b);
-}
-
-static Nlist*
-hbox_getchildren(Nelem* nelem)
-{
-	NHBox* b = (NHBox*)nelem;
-	GUARD(b);
-	return &b->children;
-}
-
 static Nelemfunctions Nhboxfunctions = {
 	.calcsize = hbox_calcsize,
 	.draw = hbox_draw,
-	.free = hbox_free,
-	.getchildren = hbox_getchildren,
 };
 
-static NHBox*
-hbox_slot(Nelem* child)
-{
-	if (child == nc_get()) {
-		nc_pop();
-	}
-	NHBox* b = (NHBox*)nc_get();
-	GUARD(b);
-	
-	ladd(&b->children, child);
-	return b;
-}
+DEF_SLOTFUNC(NHBox, hbox_slot);
 
 DEF_ACCESSOR_OneParam(NHBox, hbox_sizetocontent, int, sizetocontent);
 
@@ -106,7 +74,7 @@
 NHBox*
 New_HBox(char *name)
 {
-	NHBox *b = MakeNelem(NHBox, NHBox_Type, &Nhboxfunctions, name);
+	NHBox *b = MakeNelem(NHBox, NHBox_Type, &Nhboxfunctions, name, -1);
 	
 	b->Slot = hbox_slot;
 	b->SizeToContent = hbox_sizetocontent;
--- a/n_hbox.h
+++ b/n_hbox.h
@@ -7,7 +7,6 @@
 	DECL_ACCESSOR_OneParam(NHBox, SizeToContent, int);
 	
 	// private members
-	Nlist children;
 	int sizetocontent;
 };
 
--- a/n_image.c
+++ b/n_image.c
@@ -41,26 +41,9 @@
 	draw(img, i->r, i->image, nil, i->offset);
 }
 
-static void
-image_free(Nelem *nelem)
-{
-	GUARD(nelem);
-	if (nisroot(nelem))
-		return;
-	free(nelem);
-}
-
-static Nlist*
-image_getchildren(Nelem*)
-{
-	return nil;
-}
-
 static Nelemfunctions Nimagefunctions = {
 	.calcsize = image_calcsize,
 	.draw = image_draw,
-	.free = image_free,
-	.getchildren = image_getchildren,
 };
 
 DEF_ACCESSOR_OneParam(NImage, image_image, Image*, image);
@@ -70,7 +53,7 @@
 NImage*
 New_Image(char *name)
 {
-	NImage *i = MakeNelem(NImage, NImage_Type, &Nimagefunctions, name);
+	NImage *i = MakeNelem(NImage, NImage_Type, &Nimagefunctions, name, 0);
 	
 	i->image = nil;
 	i->offset = ZP;
--- a/n_label.c
+++ b/n_label.c
@@ -53,21 +53,6 @@
 	}
 }
 
-static void
-label_free(Nelem* nelem)
-{
-	GUARD(nelem);
-	if (nisroot(nelem))
-		return;
-	free(nelem);
-}
-
-static Nlist*
-label_getchildren(Nelem* nelem)
-{
-	return nil;
-}
-
 static char*
 label_getname(Nelem *nelem)
 {
@@ -79,8 +64,6 @@
 static Nelemfunctions Nlabelfunctions = {
 	.calcsize = label_calcsize,
 	.draw = label_draw,
-	.free = label_free,
-	.getchildren = label_getchildren,
 	.getname = label_getname,
 };
 
@@ -93,7 +76,7 @@
 NLabel*
 New_Label(char *name)
 {
-	NLabel *e = MakeNelem(NLabel, NLabel_Type, &Nlabelfunctions, name);
+	NLabel *e = MakeNelem(NLabel, NLabel_Type, &Nlabelfunctions, name, 0);
 	
 	e->Label = label;
 	e->LabelFunc = labelfunc;
--- a/n_vbox.c
+++ b/n_vbox.c
@@ -57,44 +57,12 @@
 	lforeach(&b->children, vbox_childdraw, img);
 }
 
-static void
-vbox_free(Nelem* nelem)
-{
-	NVBox* b = (NVBox*)nelem;
-	if (nisroot(b))
-		return;
-	
-	lfreelist(&b->children);
-	free(b);
-}
-
-static Nlist*
-vbox_getchildren(Nelem* nelem)
-{
-	NVBox* b = (NVBox*)nelem;
-	GUARD(b);
-	return &b->children;
-}
-
 static Nelemfunctions Nvboxfunctions = {
 	.calcsize = vbox_calcsize,
 	.draw = vbox_draw,
-	.free = vbox_free,
-	.getchildren = vbox_getchildren,
 };
 
-static NVBox*
-vbox_slot(Nelem* child)
-{
-	if (child == nc_get()) {
-		nc_pop();
-	}
-	NVBox* b = (NVBox*)nc_get();
-	GUARD(b);
-	
-	ladd(&b->children, child);
-	return b;
-}
+DEF_SLOTFUNC(NVBox, vbox_slot);
 
 DEF_ACCESSOR_OneParam(NVBox, vbox_sizetocontent, int, sizetocontent);
 
@@ -101,7 +69,7 @@
 NVBox*
 New_VBox(char *name)
 {
-	NVBox *b = MakeNelem(NVBox, NVBox_Type, &Nvboxfunctions, name);
+	NVBox *b = MakeNelem(NVBox, NVBox_Type, &Nvboxfunctions, name, -1);
 	
 	b->Slot = vbox_slot;
 	b->SizeToContent = vbox_sizetocontent;
--- a/n_vbox.h
+++ b/n_vbox.h
@@ -7,7 +7,6 @@
 	DECL_ACCESSOR_OneParam(NVBox, SizeToContent, int);
 	
 	// private members
-	Nlist children;
 	int sizetocontent;
 };
 
--- a/n_window.c
+++ b/n_window.c
@@ -14,7 +14,7 @@
 	Nelem *f;
 	NWindow *w = (NWindow*)nelem;
 	GUARD(w);
-	f = lgetfirst(&w->child);
+	f = lgetfirst(&w->children);
 	if (f)
 		ncallcalcsize(f, screen, screen->r);
 	nelem->r = r;
@@ -27,53 +27,26 @@
 	Nelem *f;
 	NWindow *w = (NWindow*)nelem;
 	GUARD(w);
-	f = lgetfirst(&w->child);
+	f = lgetfirst(&w->children);
 	if (f)
 		ncalldraw(f, img);
 }
 
+/* could be removed completely, but leave here as an example */
 static void
 wfree(Nelem* nelem)
 {
-	Nelem* f;
-	NWindow* w = (NWindow*)nelem;
-	if (nisroot(w))
-		return;
-	
-	if ((f = lgetfirst(&w->child)))
-		ncallfree(f);
-	free(w);
+	nd_free(nelem);
 }
 
-static Nlist*
-wgetchildren(Nelem* nelem)
-{
-	NWindow* w = (NWindow*)nelem;
-	GUARD(w);
-	return &w->child;
-}
-
 static Nelemfunctions Nwindowfunctions = {
 	.calcsize = wcalcsize,
 	.draw = wdraw,
 	.checkhit = nd_checkhit,
-	.hit = nil,
 	.free = wfree,
-	.getchildren = wgetchildren,
 };
 
-static NWindow*
-slot(Nelem* child)
-{
-	if (child == nc_get()) {
-		nc_pop();
-	}
-	NWindow* w = (NWindow*)nc_get();
-	GUARD(w);
-	// old child is potential leak!
-	lsetfirst(&w->child, child);
-	return w;
-}
+DEF_SLOTFUNC(NWindow, wslot);
 
 static NWindow*
 makeroot(void)
@@ -87,12 +60,11 @@
 NWindow*
 New_Window(char *name)
 {
-	NWindow *e = MakeNelem(NWindow, NWindow_Type, &Nwindowfunctions, name);
+	NWindow *e = MakeNelem(NWindow, NWindow_Type, &Nwindowfunctions, name, 1);
 	
-	e->Slot = slot;
+	e->Slot = wslot;
 	e->MakeRoot = makeroot;
 	
-	linit(&e->child);
 	nc_push(e);
 	return e;
 }
--- a/n_window.h
+++ b/n_window.h
@@ -5,9 +5,6 @@
 	Nelem;
 	DECL_ACCESSOR_OneParam(NWindow, Slot, Nelem*);
 	DECL_ACCESSOR(NWindow, MakeRoot);
-	
-	// private members
-	Nlist child;
 };
 
 NWindow* New_Window(char*);
--- a/nate.c
+++ b/nate.c
@@ -57,6 +57,7 @@
 linit(Nlist* list)
 {
 	list->first = nil;
+	list->num = 0;
 }
 
 int
@@ -80,6 +81,7 @@
 		assert(list->first);
 		list->first->item = item;
 		list->first->next = nil;
+		list->num++;
 		return;
 	}
 	
@@ -91,6 +93,7 @@
 	assert(l->next);
 	l->next->item = item;
 	l->next->next = nil;
+	list->num++;
 }
 
 void
@@ -107,6 +110,7 @@
 	a = l->next;
 	l->next = a->next;
 	free(a);
+	list->num--;
 }
 
 void
@@ -120,6 +124,7 @@
 	l->next = malloc(sizeof(Nlist));
 	l->next->next = a;
 	l->next->item = item;
+	list->num++;
 }
 
 void
@@ -140,7 +145,7 @@
 	while (l) {
 		a = l->next;
 		if (l->item)
-			free(l->item);
+			ncallfree(l->item);
 		free(l);
 		l = a;
 	}
@@ -240,6 +245,8 @@
 	
 	if (nelem->funcs && nelem->funcs->getchildren)
 		return nelem->funcs->getchildren(nelem);
+	if (nelem->children.num)
+		return &nelem->children;
 	return nil;
 }
 
--- a/nate.h
+++ b/nate.h
@@ -3,11 +3,25 @@
 typedef struct Nelem Nelem;
 typedef struct Nelemfunctions Nelemfunctions;
 typedef struct Nlist Nlist;
+typedef struct Nlistelem Nlistelem;
 
+/**************/
+/* list types */
+/**************/
 
-/* common types
- *****************/
+struct Nlist {
+	Nlistelem* first;
+	int num;
+};
+struct Nlistelem {
+	Nelem* item;
+	Nlistelem* next;
+};
 
+/****************/
+/* common types */
+/****************/
+
 typedef int (*OnclickHandler)(Mouse, Nelem*, void*);
 typedef char* (*StringGetter)(void);
 
@@ -23,8 +37,9 @@
 #define NMargin(l, t, r, b) ((Nmargin){l, t, r, b})
 #define NMargin2(x, y) ((Nmargin){x, y, x, y})
 
-/* user functions
- ******************/
+/******************/
+/* user functions */
+/******************/
 
 void nateinit(void);
 void nateredraw(int all);
@@ -46,13 +61,16 @@
 } ncolor;
 
 
-/* end user functions
- *********************/
+/**********************/
+/* end user functions */
+/**********************/
 
 struct Nelem {
 	char *type;
 	char *name;
 	Rectangle r;
+	Nlist children;
+	int nchildren; /* -1=inf, 0=none, n otherwise */
 	Nelemfunctions* funcs;
 };
 struct Nelemfunctions {
@@ -67,18 +85,10 @@
 	char* (*getname)(Nelem*);
 };
 
-/* nlist functions
- ******************/
+/*******************/
+/* nlist functions */
+/*******************/
 
-typedef struct Nlistelem Nlistelem;
-struct Nlist {
-	Nlistelem* first;
-};
-struct Nlistelem {
-	Nelem* item;
-	Nlistelem* next;
-};
-
 void linit(Nlist* list);
 int  lhas(Nlist* list, Nelem* item);
 void ladd(Nlist* list, Nelem* item);
@@ -92,8 +102,9 @@
 Nelem* lsetfirst(Nlist* list, Nelem* item);
 
 
-/* helper functions
- ********************/
+/********************/
+/* helper functions */
+/********************/
 
 // calls on Nelem
 Rectangle ncallcalcsize(Nelem*, Image*, Rectangle);
@@ -104,8 +115,9 @@
 Nlist* ncallgetchildren(Nelem*);
 
 
-/* root set management
- ***********************/
+/***********************/
+/* root set management */
+/***********************/
 
 // register Nelem as root
 void nregister(Nelem*);
@@ -118,8 +130,9 @@
 void nregroot(Nelem*);
 
 
-/* more syntactic sugar
- ***********************/
+/************************/
+/* more syntactic sugar */
+/************************/
 
 #define DECL_ACCESSOR(Type, Acc) Type* (*Acc)(void)
 #define DECL_ACCESSOR_OneParam(Type, Acc, T1) Type* (*Acc)(T1)
--- a/nate_construct.c
+++ b/nate_construct.c
@@ -98,8 +98,17 @@
 	return params.retelem;
 }
 
+void
+nd_free(Nelem *el)
+{
+	if (nisroot(el))
+		return;
+	lfreelist(&el->children);
+	free(el);
+}
+
 Nelem*
-makenelem(long size, char *type, Nelemfunctions *funcs, char *name)
+makenelem(long size, char *type, Nelemfunctions *funcs, char *name, int nchildren)
 {
 	Nelem *nel = mallocz(size, 1);
 	if (!nel)
@@ -107,7 +116,27 @@
 	nel->type = type;
 	nel->name = name;
 	nel->funcs = funcs;
+	nel->nchildren = nchildren;
+	linit(&nel->children);
 	return nel;
+}
+
+void
+nc_addchild(Nelem *parent, Nelem *child)
+{
+	if (parent->nchildren < 0)
+		goto Add;
+	
+	if (!parent->nchildren) {
+		sysfatal("invalid add to parent: %s is leaf", parent->type);
+	}
+	
+	if (parent->children.num + 1 > parent->nchildren) {
+		sysfatal("children count exhausted: parent %s supports %d children", parent->type, parent->nchildren);
+	}
+	
+Add:
+	ladd(&parent->children, child);
 }
 
 int nctracehitlevel = 0;
--- a/nate_construct.h
+++ b/nate_construct.h
@@ -9,9 +9,10 @@
 #define GUARD(N) assert(COND(N))
 
 // create with benefits
-Nelem *makenelem(long size, char *type, Nelemfunctions *funcs, char *name);
-#define MakeNelem(Type, Char, F, N) ((Type*)makenelem(sizeof(Type), Char, F, N));
+Nelem *makenelem(long size, char *type, Nelemfunctions *funcs, char *name, int nchildren);
+#define MakeNelem(Type, Char, F, N, NUM) ((Type*)makenelem(sizeof(Type), Char, F, N, NUM));
 
+void nc_addchild(Nelem*, Nelem*);
 
 // internal stuff
 void nc_init(void);
@@ -22,6 +23,20 @@
 
 // default functionality
 Nelem* nd_checkhit(Nelem* nelem, Image* screen, Mouse m);
+void nd_free(Nelem *nelem);
+
+// syntactic sugar: default slot
+#define DEF_SLOTFUNC(Type, Func) \
+	static Type* \
+	Func(Nelem *el) \
+	{ \
+		if (el == nc_get()) \
+			nc_pop(); \
+		Type *b = (Type*)nc_get(); \
+		GUARD(b); \
+		nc_addchild(b, el); \
+		return b; \
+	}
 
 // syntactic sugar: default accessors
 #define DEF_ACCESSOR_OneParam(Type, Func, T1, N1) \
--- a/test/ntest.c
+++ b/test/ntest.c
@@ -52,19 +52,21 @@
 		sysfatal("initdraw: %r");
 	
 	/* send 2 output to /srv/ntest */
-	int p[2];
-	pipe(p);
-	dup(p[0], 2);
-	int fd = create("/srv/ntest", OWRITE|ORCLOSE, 0666);
-	if (fd < 0)
-		sysfatal("create: %r");
-	fprint(fd, "%d\n", p[1]);
-	close(p[1]);
+	if (1) {
+		int p[2];
+		pipe(p);
+		dup(p[0], 2);
+		int fd = create("/srv/ntest", OWRITE|ORCLOSE, 0666);
+		if (fd < 0)
+			sysfatal("create: %r");
+		fprint(fd, "%d\n", p[1]);
+		close(p[1]);
+	}
 	
 	/* debug nate */
 	nateborders = 1;
-	//natetracehit = 1;
-	//natetracedraw = 1;
+	natetracehit = 1;
+	natetracedraw = 1;
 	natedebugfd = 2;
 	
 	einit(Emouse);