+void tui_add_widget(struct tui_widget *par, struct tui_widget *w)
+{
+ if(w->par == par) return;
+
+ w->next = par->child;
+ par->child = w;
+ w->par = par;
+}
+
+void tui_remove_widget(struct tui_widget *par, struct tui_widget *w)
+{
+ struct tui_widget *iter, dummy;
+
+ if(w->par != par) {
+ fprintf(stderr, "failed to remove widget %p from %p\n", (void*)w, (void*)par);
+ return;
+ }
+
+ dummy.next = par->child;
+ iter = &dummy;
+ while(iter->next) {
+ if(iter->next == w) {
+ iter->next = w->next;
+ break;
+ }
+ iter = iter->next;
+ }
+ par->child = dummy.next;
+
+ w->next = 0;
+ w->par = 0;
+}
+
+struct tui_widget *tui_parent(struct tui_widget *w)
+{
+ return w->par;
+}
+
+int tui_isdirty(struct tui_widget *w)
+{
+ return w->dirty;
+}
+
+void tui_draw(struct tui_widget *w)
+{
+ struct tui_widget *iter;
+
+ if(w->cbfunc[TUI_DRAW]) {
+ w->cbfunc[TUI_DRAW](w, 0);
+ }
+ w->dirty = 0;
+
+ iter = w->child;
+ while(iter) {
+ tui_draw(iter);
+ iter = iter->next;
+ }
+
+ tg_redraw();
+}
+