#include "../include/xcv_license.h" //"GL/glui.h" //PCH namespace Widgets95 {//-. //<-' /*************************** xcv_sort_node() *******/ void node::_sort(const less::ref &pred, int depth) { if(--depth<0||!_child_head) return; enum{ ISIZE=32 }; node *stackbuf[ISIZE]; size_t bufsz = ISIZE; node **buf = stackbuf; size_t i = 0; node *p = _child_head; for(;;) { for(;inext()) { buf[i++] = p; if(depth) p->_sort(pred,depth); } if(!p) break; // else make a bigger buf, try again bufsz*=2; if(buf==stackbuf) { buf = (node**)malloc(sizeof(node*)*bufsz); } else buf = (node**)realloc(buf,sizeof(node*)*bufsz); } if(i==1) { //This is in case users don't want to implement a //recursive walk of the tree so to systematically //initialize the ui. pred(buf[0],buf[0]); } else { //std::sort(buf,buf+i,pred); std::stable_sort(buf,buf+i,pred); _child_head = buf[0]; _child_tail = buf[--i]; buf[i]->_next_sibling = nullptr; for(;i-->0;) { buf[i]->_next_sibling = buf[i+1]; buf[i+1]->_prev_sibling = buf[i]; } buf[0]->_prev_sibling = nullptr; } if(buf!=stackbuf) free(buf); } /*************************** WIDGETS_95_Node::link_this_to_parent_last() *******/ /* Links as last child of parent */ bool node::_link(node *p, int how) { if(!p) return false; //ins_item for first item? if(this==p) return false; //tab::_set_parent(_row)? if(_parent_node) { _unlink(); //NEW } else //Siblings implies parents? { assert(!_prev_sibling&&!_next_sibling); } if(how<2) { if(!p->_child_tail) /* parent has no children */ { p->_child_head = this; p->_child_tail = this; } else if(0==how) /* parent has children */ { //link_this_to_parent_last p->_child_tail->_next_sibling = this; _prev_sibling = p->_child_tail; p->_child_tail = this; } else //UNUSED { assert(1==how); //link_this_to_parent_first p->_child_head->_prev_sibling = this; _next_sibling = p->_child_head; p->_child_head = this; } _parent_node = p; } else //UNUSED { if(how==2) //UNUSED { //link_this_to_sibling_next if(!p->_next_sibling) //node has no next parent { p->_next_sibling = this; _prev_sibling = p; //This was the parent's last child, so update that as well if(p->_parent_node) { p->_parent_node->_child_tail = this; } else assert(0); } else //node already has a next parent { p->_next_sibling->_prev_sibling = this; _next_sibling = p->_next_sibling; p->_next_sibling = this; _prev_sibling = p; } } else //UNUSED { assert(3==how); //_link_this_to_sibling_prev if(!p->_prev_sibling) //node has no prev parent { p->_prev_sibling = this; _next_sibling = p; //This was the parent's first child, so update that as well if(p->_parent_node) { p->_parent_node->_child_head = this; } else assert(0); } else //node already has a prev parent { p->_prev_sibling->_next_sibling = this; _prev_sibling = p->_prev_sibling; p->_prev_sibling = this; _next_sibling = p; } } _parent_node = p->_parent_node; } return true; } /**************************************** WIDGETS_95_Node::_unlink() **************/ void node::_unlink() { node *p = _parent_node; if(_prev_sibling) /* Unlink from prev sibling */ { _prev_sibling->_next_sibling = _next_sibling; } else /* No prev sibling: this was parent's first child */ { if(p) p->_child_head = _next_sibling; } if(_next_sibling) /* Unlink from next sibling */ { _next_sibling->_prev_sibling = _prev_sibling; } else /* No next sibling: this was parent's last child */ { if(p) p->_child_tail = _prev_sibling; } _parent_node = _next_sibling = _prev_sibling = nullptr; } /**************************************** WIDGETS_95_Node::_dump() **************/ #ifdef WIDGETS_95_DEBUG_STDOUT FILE *node::_dump_FILE = stdout; void node::_dump(const char *name) { fprintf(_dump_FILE,"WIDGETS_95_node: %s\n",name); fprintf(_dump_FILE," parent: %p _child_head: %p _child_tail: %p\n",_parent_node,_child_head,_child_tail); fprintf(_dump_FILE," next: %p prev: %p\n",_next_sibling,_prev_sibling); } #endif //---. }//<-'