ref: 1890aeca379976e46deabb0ce844aefc8be1a2c5
dir: /nate_construct.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "nate_construct.h"
typedef struct NCelem NCelem;
struct NCelem {
Nelem* elem;
NCelem* next;
};
static NCelem* nc_stack = nil;
void
nc_init()
{
nc_stack = nil;
}
void
nc_push(Nelem* nelem)
{
NCelem *n;
if (!nc_stack) {
nc_stack = malloc(sizeof(NCelem));
assert(nc_stack);
nc_stack->next = nil;
nc_stack->elem = nelem;
} else {
n = malloc(sizeof(NCelem));
assert(n);
n->next = nc_stack;
n->elem = nelem;
nc_stack = n;
}
}
void
nc_pop()
{
if (!nc_stack)
return;
NCelem *nc = nc_stack;
nc_stack = nc->next;
free(nc);
}
Nelem*
nc_get()
{
return nc_stack ? nc_stack->elem : nil;
}
typedef struct chparams chparams;
struct chparams {
Nelem *retelem;
Image *screen;
Mouse mouse;
};
static void
fe_checkhit(Nelem* elem, int, void *aux)
{
chparams *p = (chparams*)aux;
Rectangle r;
Nelem* e;
if (p->retelem)
return;
border(p->screen, r, 1, ncolor.green, ZP);
if (!ptinrect(p->mouse.xy, elem->r))
return;
e = ncallcheckhit(elem, p->screen, p->mouse);
nctracehitlevel--;
if (e) {
p->retelem = e;
}
}
Nelem*
nd_checkhit(Nelem* nelem, Image* screen, Mouse m)
{
chparams params;
Nlist* l = ncallgetchildren(nelem);
if (!l)
return nil;
params.retelem = nil;
params.screen = screen;
params.mouse = m;
lforeach(l, fe_checkhit, ¶ms);
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, int nchildren)
{
Nelem *nel = mallocz(size, 1);
if (!nel)
sysfatal("oom: creating nelem %s", type);
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;
void
nctracehit(Nelem *el, int pt)
{
char *name;
if (natedebugfd < 0)
return;
if (nctracehitlevel < 0)
return;
if (el->funcs && el->funcs->getname)
name = el->funcs->getname(el);
else
name = el->name;
fprint(natedebugfd, "HIT: %*s%c%s%c %c%s%c\n",
nctracehitlevel * 3, nctracehitlevel?"↘":"", /* indent */
pt ? '(' : ' ', el->type, pt ? ')' : ' ', /* Nelem type */
name?'\"':' ', name ? name : "", name?'\"':' '); /* name */
}