ref: c04fd4ce67a03c04b342c38185523bb834f4e0b7
dir: /nate.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include "nate_construct.h" 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)) { lforeach(&rootchain, f); } 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)) { Nlistelem* l = list->first; for (int i = 0; l; i++) { f(l->item, i); 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); } Point ncallcalcsize(Nelem* nelem, Image* dst) { assert(nelem); if (nelem->funcs && nelem->funcs->calcsize) return nelem->funcs->calcsize(nelem, dst); return Pt(0,0); } void ncalldraw(Nelem* nelem, Image* dst, Rectangle r) { assert(nelem); if (nelem->funcs && nelem->funcs->draw) nelem->funcs->draw(nelem, dst, r); } Nelem* ncallcheckhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m) { assert(nelem); if (nelem->funcs && nelem->funcs->checkhit) return nelem->funcs->checkhit(nelem, screen, r, m); return nil; } 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(); } void nateredraw() { if (!rootelem) return; ncalldraw(rootelem, screen, screen->r); } int natemouseevent(Mouse m) { Nelem* el; Point s; Rectangle r; if (!rootelem) return 0; s = ncallcalcsize(rootelem, screen); r.min = screen->r.min; r.max = addpt(r.min, s); if (!ptinrect(m.xy, r)) return 0; el = ncallcheckhit(rootelem, screen, screen->r, m); if (!el) return 0; return ncallhit(el, m); }