577159c75e
git-svn-id: svn://10.65.10.50/branches/R_10_00@22884 c028cbd2-c16b-5b4b-a496-9718f37d4682
855 lines
17 KiB
C++
Executable File
855 lines
17 KiB
C++
Executable File
#include <colors.h>
|
|
#include <image.h>
|
|
#include <tree.h>
|
|
#include <urldefid.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Callbacks
|
|
///////////////////////////////////////////////////////////
|
|
|
|
HIDDEN bool callback_compare_node(TTree& node, void* jolly, word /*when*/)
|
|
{
|
|
const TString& id = *((TString*)jolly);
|
|
TString cur_id; node.curr_id(cur_id);
|
|
return id == cur_id;
|
|
}
|
|
|
|
HIDDEN bool callback_expand_node(TTree& node, void* jolly, word when)
|
|
{
|
|
if (when == SCAN_PRE_ORDER)
|
|
node.expand();
|
|
return false;
|
|
}
|
|
|
|
HIDDEN bool callback_find_father(TTree& node, void* jolly, word when)
|
|
{
|
|
TString_array& father_and_son = *(TString_array*)jolly;
|
|
TString myself; node.curr_id(myself);
|
|
|
|
if (when == SCAN_PRE_ORDER)
|
|
{
|
|
if (myself == father_and_son.row(1))
|
|
father_and_son.add(myself, 0);
|
|
}
|
|
else
|
|
{
|
|
if (father_and_son.objptr(0))
|
|
{
|
|
father_and_son.add(myself, 0);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
HIDDEN bool callback_find_brother(TTree& node, void* jolly, word when)
|
|
{
|
|
TString_array& brother_and_sister = *(TString_array*)jolly;
|
|
TString myself; node.curr_id(myself);
|
|
|
|
if (when == SCAN_PRE_ORDER)
|
|
{
|
|
if (myself == brother_and_sister.row(1))
|
|
brother_and_sister.add(myself, 0);
|
|
}
|
|
else
|
|
{
|
|
if (brother_and_sister.objptr(0))
|
|
{
|
|
brother_and_sister.add(myself, 0);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TTtree
|
|
///////////////////////////////////////////////////////////
|
|
|
|
bool TTree::scan_depth_first(NODE_HANDLER nh, void* jolly, word flags)
|
|
{
|
|
if ((flags & 0x7) == 0)
|
|
flags |= SCAN_PRE_ORDER;
|
|
|
|
bool test_myself = true;
|
|
if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
|
|
test_myself = false;
|
|
|
|
TString myself;
|
|
curr_id(myself);
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
|
|
return true;
|
|
|
|
const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
|
|
if (!stop && goto_firstson())
|
|
{
|
|
if (scan_depth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_node(myself);
|
|
}
|
|
|
|
if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
|
|
return true;
|
|
}
|
|
|
|
if (goto_rbrother())
|
|
{
|
|
if (scan_depth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_node(myself);
|
|
}
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool TTree::scan_breadth_first(NODE_HANDLER nh, void* jolly, word flags)
|
|
{
|
|
if ((flags & 0x7) == 0)
|
|
flags |= SCAN_PRE_ORDER;
|
|
|
|
bool test_myself = true;
|
|
if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
|
|
test_myself = false;
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
|
|
return true;
|
|
}
|
|
|
|
TString myself;
|
|
curr_id(myself);
|
|
|
|
if (goto_rbrother())
|
|
{
|
|
if (scan_breadth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_node(myself);
|
|
}
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
|
|
return true;
|
|
|
|
const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
|
|
if (!stop && goto_firstson())
|
|
{
|
|
if (scan_breadth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_node(myself);
|
|
}
|
|
if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int TTree::curr_depth() const
|
|
{
|
|
int n = -1;
|
|
if (has_root())
|
|
{
|
|
TString myself; curr_id(myself);
|
|
for (n = 0; ((TTree*)this)->goto_father(); n++);
|
|
((TTree*)this)->goto_node(myself);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
bool TTree::has_root() const
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = ((TTree*)this)->goto_root();
|
|
if (ok)
|
|
((TTree*)this)->goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::has_father() const
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = ((TTree*)this)->goto_father();
|
|
if (ok)
|
|
((TTree*)this)->goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::goto_father()
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = goto_root();
|
|
if (ok)
|
|
{
|
|
TString_array father_and_son;
|
|
father_and_son.add(myself, 1);
|
|
ok = scan_breadth_first(callback_find_father, &father_and_son,
|
|
SCAN_PRE_ORDER | SCAN_IN_ORDER);
|
|
}
|
|
if (!ok)
|
|
goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::has_lbrother() const
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = ((TTree*)this)->goto_lbrother();
|
|
if (ok)
|
|
((TTree*)this)->goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::goto_lbrother()
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = goto_root();
|
|
if (ok)
|
|
{
|
|
TString_array brother_and_sister;
|
|
brother_and_sister.add(myself, 1);
|
|
ok = scan_depth_first(callback_find_brother, &brother_and_sister,
|
|
SCAN_PRE_ORDER | SCAN_POST_ORDER);
|
|
}
|
|
if (!ok)
|
|
goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::has_rbrother() const
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = ((TTree*)this)->goto_rbrother();
|
|
if (ok)
|
|
((TTree*)this)->goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::could_have_son() const
|
|
{ return has_son(); }
|
|
|
|
bool TTree::has_son() const
|
|
{
|
|
TString myself; curr_id(myself);
|
|
bool ok = ((TTree*)this)->goto_firstson();
|
|
if (ok)
|
|
((TTree*)this)->goto_node(myself);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::expanded() const
|
|
{
|
|
TString str; curr_id(str);
|
|
bool yes = _expanded.is_key(str);
|
|
return yes;
|
|
}
|
|
|
|
bool TTree::expand()
|
|
{
|
|
bool ok = enabled() && has_son();
|
|
if (ok)
|
|
{
|
|
TString str; curr_id(str);
|
|
ok = !_expanded.is_key(str);
|
|
if (ok)
|
|
_expanded.add(str);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::shrink()
|
|
{
|
|
TString str; curr_id(str);
|
|
bool ok = _expanded.is_key(str);
|
|
if (ok)
|
|
_expanded.remove(str);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::expand_all()
|
|
{
|
|
bool ok = goto_root();
|
|
if (ok)
|
|
scan_breadth_first(callback_expand_node, NULL);
|
|
return ok;
|
|
}
|
|
|
|
bool TTree::shrink_all()
|
|
{
|
|
_expanded.destroy();
|
|
return goto_root();
|
|
}
|
|
|
|
TImage* TTree::get_res_image(short bmp_id) const
|
|
{
|
|
TImage* bmp = (TImage*)_image.objptr(bmp_id);
|
|
if (bmp == NULL)
|
|
{
|
|
bmp = new TImage(bmp_id);
|
|
if (bmp->ok())
|
|
{
|
|
bmp->convert_transparent_color(NORMAL_BACK_COLOR);
|
|
((TTree*)this)->_image.add(bmp, bmp_id);
|
|
}
|
|
else
|
|
{
|
|
delete bmp;
|
|
bmp = NULL;
|
|
}
|
|
}
|
|
return bmp;
|
|
}
|
|
|
|
TImage* TTree::get_res_icon(short icon_id) const
|
|
{
|
|
const int id = 100000 + icon_id;
|
|
TImage* bmp = (TImage*)_image.objptr(id);
|
|
if (bmp == NULL)
|
|
{
|
|
TImage ico(icon_id, true);
|
|
if (ico.ok())
|
|
{
|
|
const TImage* def = get_res_image(BMP_FILE);
|
|
int w = 16, h = 16;
|
|
if (def != NULL)
|
|
{
|
|
w = def->width();
|
|
h = def->height();
|
|
}
|
|
ico.convert_transparent_color(NORMAL_BACK_COLOR);
|
|
bmp = new TImage(ico, w, h);
|
|
((TTree*)this)->_image.add(bmp, id);
|
|
}
|
|
}
|
|
return bmp;
|
|
}
|
|
|
|
TImage* TTree::image(bool selected) const
|
|
{
|
|
short bmp_id = BMP_FILE;
|
|
if (could_have_son())
|
|
bmp_id = selected ? BMP_DIRDN : BMP_DIR;
|
|
return get_res_image(bmp_id);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TBidirectional_tree
|
|
///////////////////////////////////////////////////////////
|
|
|
|
bool TBidirectional_tree::scan_depth_first(NODE_HANDLER nh, void* jolly, word flags)
|
|
{
|
|
if ((flags & 0x7) == 0)
|
|
flags |= SCAN_PRE_ORDER;
|
|
|
|
bool test_myself = true;
|
|
if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
|
|
test_myself = false;
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
|
|
return true;
|
|
|
|
const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
|
|
if (!stop && goto_firstson())
|
|
{
|
|
if (scan_depth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_father();
|
|
}
|
|
|
|
if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
|
|
return true;
|
|
}
|
|
|
|
if (goto_rbrother())
|
|
{
|
|
if (scan_depth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_lbrother();
|
|
}
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool TBidirectional_tree::scan_breadth_first(NODE_HANDLER nh, void* jolly, word flags)
|
|
{
|
|
if ((flags & 0x7) == 0)
|
|
flags |= SCAN_PRE_ORDER;
|
|
|
|
bool test_myself = true;
|
|
if ((flags & SCAN_IGNORING_LEAVES) && !has_son())
|
|
test_myself = false;
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_PRE_ORDER) && nh(*this, jolly, SCAN_PRE_ORDER))
|
|
return true;
|
|
}
|
|
|
|
if (goto_rbrother())
|
|
{
|
|
if (scan_breadth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_lbrother();
|
|
}
|
|
|
|
if (test_myself)
|
|
{
|
|
if ((flags & SCAN_IN_ORDER) && nh(*this, jolly, SCAN_IN_ORDER))
|
|
return true;
|
|
const bool stop = (flags & SCAN_IGNORING_UNEXPANDED) && !expanded();
|
|
if (!stop && goto_firstson())
|
|
{
|
|
if (scan_breadth_first(nh, jolly, flags))
|
|
return true;
|
|
goto_father();
|
|
}
|
|
if ((flags & SCAN_POST_ORDER) && nh(*this, jolly, SCAN_POST_ORDER))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool TBidirectional_tree::goto_node(const TString &id)
|
|
{
|
|
bool ok = goto_root();
|
|
if (ok && id.not_empty())
|
|
ok = scan_breadth_first(callback_compare_node, (void *)&id);
|
|
return ok;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TObject tree
|
|
///////////////////////////////////////////////////////////
|
|
|
|
bool TObject_tree::expanded() const
|
|
{
|
|
bool ok = _current && _current->_expanded;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::expand()
|
|
{
|
|
bool ok = _current && _current->_son && !_current->_expanded && enabled();
|
|
if (ok)
|
|
_current->_expanded = true;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::shrink()
|
|
{
|
|
bool ok = _current && _current->_expanded;
|
|
if (ok)
|
|
_current->_expanded = false;
|
|
return ok;
|
|
}
|
|
|
|
void TObject_tree::node2id(const TObject* node, TString& id) const
|
|
{
|
|
id.format("%p", (const void*)node);
|
|
}
|
|
|
|
bool TObject_tree::goto_node(const TString& node)
|
|
{
|
|
bool ok = goto_root();
|
|
if (node.full())
|
|
{
|
|
#ifdef DBG_TREE
|
|
if (!_expanded.is_key(node)) // Usa l'assoc array per testare i nodi validi!
|
|
{
|
|
NFCHECK("Invalid node: %s", (const char*)node);
|
|
return false;
|
|
}
|
|
#endif
|
|
ok = scan_depth_first(callback_compare_node, (void*)&node);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::goto_root()
|
|
{
|
|
_current = _root;
|
|
return _root != NULL;
|
|
}
|
|
|
|
bool TObject_tree::goto_firstson()
|
|
{
|
|
TTree_node* n = _current ? _current->_son : NULL;
|
|
if (n) _current = n;
|
|
return n != NULL;
|
|
}
|
|
|
|
bool TObject_tree::goto_rbrother()
|
|
{
|
|
TTree_node* n = _current ? _current->_rbrother : NULL;
|
|
if (n) _current = n;
|
|
return n != NULL;
|
|
}
|
|
|
|
bool TObject_tree::goto_father()
|
|
{
|
|
TTree_node* n = _current ? _current->_father : NULL;
|
|
if (n) _current = n;
|
|
return n != NULL;
|
|
}
|
|
|
|
bool TObject_tree::goto_lbrother()
|
|
{
|
|
TTree_node* n = _current ? _current->_lbrother : NULL;
|
|
if (n) _current = n;
|
|
return n != NULL;
|
|
}
|
|
|
|
bool TObject_tree::set_object(TObject* obj)
|
|
{
|
|
if (_current && _current->_obj != obj)
|
|
{
|
|
#ifdef DBG_TREE
|
|
TString str; curr_id(str);
|
|
_expanded.add(str); // Usa l'assoc array per memorizzare i nodi validi!
|
|
#endif
|
|
delete detach_object();
|
|
_current->_obj = obj;
|
|
}
|
|
return _current != NULL;
|
|
}
|
|
|
|
bool TObject_tree::set_object(const TObject& obj)
|
|
{
|
|
bool ok = false;
|
|
if (_current)
|
|
{
|
|
TObject* ptr = obj.dup();
|
|
ok = set_object(ptr);
|
|
if (!ok)
|
|
delete ptr;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
TObject* TObject_tree::detach_object()
|
|
{
|
|
TObject* o = NULL;
|
|
if (_current && _current->_obj)
|
|
{
|
|
o = _current->_obj;
|
|
_current->_obj = NULL;
|
|
}
|
|
return o;
|
|
}
|
|
|
|
#define swap_obj(o1, o2) { auto o0 = o1; o1 = o2; o2 = o0; }
|
|
|
|
void TObject_tree::reparent(TObject_tree::TTree_node* son, TObject_tree::TTree_node* father)
|
|
{
|
|
while (son)
|
|
{
|
|
son->_father = father;
|
|
son = son->_rbrother;
|
|
}
|
|
}
|
|
|
|
bool TObject_tree::swap_left()
|
|
{
|
|
const bool ok = goto_lbrother();
|
|
if (ok)
|
|
{
|
|
reparent(_current->_rbrother->_son, _current);
|
|
reparent(_current->_son, _current->_rbrother);
|
|
swap_obj(_current->_son, _current->_rbrother->_son);
|
|
swap_obj(_current->_obj, _current->_rbrother->_obj);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::swap_right()
|
|
{
|
|
const bool ok = goto_rbrother();
|
|
if (ok)
|
|
{
|
|
reparent(_current->_lbrother->_son, _current);
|
|
reparent(_current->_son, _current->_lbrother);
|
|
swap_obj(_current->_son, _current->_lbrother->_son);
|
|
swap_obj(_current->_obj, _current->_lbrother->_obj);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::push_down()
|
|
{
|
|
bool ok = _current != NULL;
|
|
if (ok)
|
|
{
|
|
TObject* obj = detach_object();
|
|
set_object(obj->dup());
|
|
TTree_node* child = _current->_son;
|
|
_current->_son = NULL;
|
|
add_son(obj);
|
|
_current->_son = child;
|
|
reparent(child, _current);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::push_up()
|
|
{
|
|
bool ok = has_father();
|
|
if (ok)
|
|
{
|
|
const bool is_single = !has_lbrother() && !has_rbrother();
|
|
TObject* obj = detach_object();
|
|
TTree_node* child = _current->_son;
|
|
_current->_son = NULL;
|
|
TTree_node* cur = _current->_father;
|
|
kill_node();
|
|
_current = cur;
|
|
if (is_single)
|
|
set_object(obj);
|
|
else
|
|
add_rbrother(obj);
|
|
_current->_son = child;
|
|
reparent(child, _current);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::create_root()
|
|
{
|
|
if (!has_root())
|
|
_root = _current = new TTree_node;
|
|
return goto_root();
|
|
}
|
|
|
|
bool TObject_tree::add_son(TObject* obj)
|
|
{
|
|
bool ok = false;
|
|
if (_root)
|
|
{
|
|
TTree_node*& curson = _current->_son;
|
|
TTree_node* newson = new TTree_node;
|
|
newson->_father = _current;
|
|
if (curson != NULL)
|
|
{
|
|
curson->_lbrother = newson;
|
|
newson->_rbrother = curson;
|
|
}
|
|
curson = newson;
|
|
ok = goto_firstson();
|
|
}
|
|
else
|
|
ok = create_root();
|
|
|
|
if (ok)
|
|
ok = set_object(obj);
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_son(const TObject& obj)
|
|
{
|
|
TObject* ptr = obj.dup();
|
|
bool ok = add_son(ptr);
|
|
if (!ok) delete ptr;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_brother(TObject* obj)
|
|
{
|
|
bool ok = false;
|
|
if (goto_father())
|
|
ok = add_son(obj);
|
|
else
|
|
ok = create_root() && set_object(obj);
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_brother(const TObject& obj)
|
|
{
|
|
TObject* ptr = obj.dup();
|
|
bool ok = add_brother(ptr);
|
|
if (!ok) delete ptr;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_rbrother(TObject* obj)
|
|
{
|
|
bool ok = false;
|
|
if (has_root()) // was has_father(); changed for sc0300 09/03/2012
|
|
{
|
|
CHECK(_current, "Can't add_rbrother to NULL node");
|
|
TTree_node* newbrother = new TTree_node;
|
|
newbrother->_father = _current->_father;
|
|
newbrother->_lbrother = _current;
|
|
if (_current->_rbrother != NULL)
|
|
{
|
|
newbrother->_rbrother = _current->_rbrother;
|
|
_current->_rbrother->_lbrother = newbrother;
|
|
}
|
|
_current->_rbrother = newbrother;
|
|
ok = goto_rbrother();
|
|
}
|
|
else
|
|
ok = create_root();
|
|
|
|
if (ok)
|
|
set_object(obj);
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_rbrother(const TObject& obj)
|
|
{
|
|
TObject* ptr = obj.dup();
|
|
bool ok = add_rbrother(ptr);
|
|
if (!ok) delete ptr;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_lbrother(TObject* obj)
|
|
{
|
|
bool ok = true;
|
|
if (has_root()) // was has_father(); changed for sc0300 09/03/2012
|
|
{
|
|
if (goto_lbrother())
|
|
ok = add_rbrother(obj);
|
|
else
|
|
{
|
|
TTree_node* newbrother = new TTree_node;
|
|
newbrother->_father = _current->_father;
|
|
newbrother->_rbrother = _current;
|
|
_current->_lbrother = newbrother;
|
|
if (_current->_father != NULL)
|
|
_current->_father->_son = newbrother;
|
|
_current = newbrother;
|
|
}
|
|
}
|
|
else
|
|
ok = create_root();
|
|
if (ok)
|
|
set_object(obj);
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::add_lbrother(const TObject& obj)
|
|
{
|
|
TObject* ptr = obj.dup();
|
|
bool ok = add_lbrother(ptr);
|
|
if (!ok) delete ptr;
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::kill_node()
|
|
{
|
|
bool ok = false;
|
|
if (_current)
|
|
{
|
|
TTree_node* cur = _current;
|
|
while (goto_firstson())
|
|
{
|
|
kill_node();
|
|
_current = cur;
|
|
}
|
|
if (_current->_lbrother)
|
|
{
|
|
_current->_lbrother->_rbrother = _current->_rbrother;
|
|
}
|
|
else
|
|
{
|
|
if (_current->_father)
|
|
_current->_father->_son = _current->_rbrother;
|
|
}
|
|
if (_current->_rbrother)
|
|
_current->_rbrother->_lbrother = _current->_lbrother;
|
|
|
|
#ifdef DBG_TREE
|
|
TString id; curr_id(id);
|
|
_expanded.remove(id);
|
|
#endif
|
|
|
|
TTree_node* to_be_killed = _current;
|
|
|
|
if (_current == _root)
|
|
_root = NULL;
|
|
|
|
if (_current->_rbrother)
|
|
_current = _current->_rbrother;
|
|
else
|
|
{
|
|
if (_current->_lbrother)
|
|
_current = _current->_lbrother;
|
|
else
|
|
_current = _current->_father;
|
|
}
|
|
|
|
delete to_be_killed;
|
|
|
|
ok = true;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TObject_tree::get_description(TString& str) const
|
|
{
|
|
TObject* obj = curr_node();
|
|
if (obj)
|
|
str << *obj;
|
|
return obj != NULL;
|
|
}
|
|
|
|
int TObject_tree::curr_depth() const
|
|
{
|
|
int n = -1;
|
|
if (_current != NULL)
|
|
{
|
|
const TTree_node* curr = _current;
|
|
for (n = 0; curr->_father; n++)
|
|
curr = curr->_father;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
TObject_tree::TObject_tree()
|
|
{
|
|
_root = _current = NULL;
|
|
}
|
|
|
|
TObject_tree::~TObject_tree()
|
|
{
|
|
if (goto_root())
|
|
kill_node();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TString_tree
|
|
///////////////////////////////////////////////////////////
|
|
|
|
bool TString_tree::get_description(TString& str) const
|
|
{
|
|
const TString* obj = (const TString*)curr_node();
|
|
if (obj)
|
|
str = *obj;
|
|
else
|
|
str.cut(0);
|
|
return obj != NULL;
|
|
}
|
|
|