ref: 8e9b3935e13faea2d4304b0f557754c43290a266
dir: /nate.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "nate_construct.h"
int nateborders = 0;
int natetracehit = 0;
int natedebugfd = -1;
static Nlist rootchain = { nil };
static Nelem* rootelem = nil;
void
nregroot(Nelem* nelem)
{
assert(nelem);
// root must be inside rootchain
nregister(nelem);
if (rootelem)
ncallfree(rootelem);
rootelem = nelem;
}
void
nregister(Nelem* nelem)
{
if (lhas(&rootchain, nelem))
return;
ladd(&rootchain, nelem);
}
void
nderegister(Nelem* nelem)
{
ldel(&rootchain, nelem);
}
void
nforeachroot(void (*f)(Nelem*, int, void*), void *aux)
{
lforeach(&rootchain, f, aux);
}
int
nisroot(Nelem* nelem)
{
return lhas(&rootchain, nelem);
}
void
linit(Nlist* list)
{
list->first = nil;
}
int
lhas(Nlist* list, Nelem* item)
{
Nlistelem* l = list->first;
while (l) {
if (l->item == item)
return 1;
l = l->next;
}
return 0;
}
void
ladd(Nlist* list, Nelem* item)
{
Nlistelem* l;
if (!list->first) {
list->first = malloc(sizeof(Nlist));
assert(list->first);
list->first->item = item;
list->first->next = nil;
return;
}
l = list->first;
while (l->next)
l = l->next;
l->next = malloc(sizeof(Nlist));
assert(l->next);
l->next->item = item;
l->next->next = nil;
}
void
ldel(Nlist* list, Nelem* item)
{
Nlistelem* l, *a;
if (!list->first)
return;
l = list->first;
while (l->next && l->next->item != item)
l = l->next;
a = l->next;
l->next = a->next;
free(a);
}
void
linsert(Nlist* list, Nelem* before, Nelem* item)
{
Nlistelem* l = list->first, *a;
while (l->next && l->item != before)
l = l->next;
a = l->next;
l->next = malloc(sizeof(Nlist));
l->next->next = a;
l->next->item = item;
}
void
lforeach(Nlist* list, void (*f)(Nelem*, int, void*), void *aux)
{
Nlistelem* l = list->first;
for (int i = 0; l; i++) {
f(l->item, i, aux);
l = l->next;
}
}
void
lfreelist(Nlist* list)
{
Nlistelem* a;
Nlistelem* l = list->first;
while (l) {
a = l->next;
if (l->item)
free(l->item);
free(l);
l = a;
}
}
Nelem*
lgetfirst(Nlist* list)
{
return list->first ? list->first->item : nil;
}
Nelem*
lsetfirst(Nlist* list, Nelem* item)
{
Nelem* f = lgetfirst(list);
if (list->first) {
list->first->item = item;
return f;
}
list->first = malloc(sizeof(Nlistelem));
list->first->next = nil;
list->first->item = item;
return f;
}
void
ncallfree(Nelem* nelem)
{
assert(nelem);
if (nisroot(nelem))
return;
if (nelem->funcs && nelem->funcs->free)
nelem->funcs->free(nelem);
}
Rectangle
ncallcalcsize(Nelem* nelem, Image* dst, Rectangle r)
{
assert(nelem);
if (nelem->funcs && nelem->funcs->calcsize) {
r = nelem->funcs->calcsize(nelem, dst, r);
//fprint(2, "calcsize %s: %R\n", nelem->type, r);
return r;
}
return r;
}
void
ncalldraw(Nelem* nelem, Image* dst)
{
Rectangle or;
assert(nelem);
if (nelem->funcs && nelem->funcs->draw) {
if (natedebugfd >= 0)
fprint(natedebugfd, "DRAW: %s\n", nelem->type);
or = dst->clipr;
//replclipr(dst, 0, nelem->r);
nelem->funcs->draw(nelem, dst);
//replclipr(dst, 0, or);
}
}
Nelem*
ncallcheckhit(Nelem* nelem, Image* screen, Mouse m)
{
assert(nelem);
nctracehit(nelem, !nelem->funcs->hit);
nctracehitlevel++;
if (nelem->funcs && nelem->funcs->checkhit) {
return nelem->funcs->checkhit(nelem, screen, m);
}
return nd_checkhit(nelem, screen, m);
}
int
ncallhit(Nelem* nelem, Mouse m)
{
assert(nelem);
if (nelem->funcs && nelem->funcs->hit)
return nelem->funcs->hit(nelem, m);
return 0;
}
Nlist*
ncallgetchildren(Nelem* nelem)
{
assert(nelem);
if (nelem->funcs && nelem->funcs->getchildren)
return nelem->funcs->getchildren(nelem);
return nil;
}
Nelem*
nassign(Nelem** dst, Nelem* src)
{
assert(dst && src);
*dst = src;
return src;
}
void
nateinit()
{
nc_init();
#define A(col) allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, col)
ncolor.red = A(DRed);
ncolor.green = A(DGreen);
ncolor.blue = A(DBlue);
#undef A
}
void
nateredraw(int all)
{
if (!rootelem)
return;
if (all)
ncallcalcsize(rootelem, screen, screen->r);
ncalldraw(rootelem, screen);
}
int
natemouseevent(Mouse m)
{
Nelem* el;
Rectangle r;
if (!rootelem)
return 0;
r = ncallcalcsize(rootelem, screen, screen->r);
if (!ptinrect(m.xy, r))
return 0;
nctracehitlevel = natetracehit - 1;
el = ncallcheckhit(rootelem, screen, m);
if (!el)
return 0;
return ncallhit(el, m);
}