#include "gosGml.hpp"

//===========================================================================//
// File:	 Tree.cpp														 //
// Project:  gosGml				                                         //
// Contents: 																 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 4/10/00   JR     Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 2000 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include <string.h>
#include "tree.h"
#include "stdlib.h"

gosGmlTreeNode::gosGmlTreeNode(const char * tagName, const char * fileName)
{
	// copy the tagName into our memory
	m_tagName = (char *) gos_Malloc (mstrlen(tagName)+1);
	mstrcpy(m_tagName, tagName);

	// copy the fileName into our memory
	m_fileName = (char *) gos_Malloc(mstrlen(fileName)+2);
	mstrcpy(m_fileName, fileName);

	m_pParent = NULL;
	m_pChildren = NULL;
	m_pPrevChild = NULL;
	m_pNextChild = NULL;
	m_expanded = false;
}

gosGmlTreeNode::~gosGmlTreeNode()
{
	// free the tagName
	if (m_tagName)
	{
		gos_Free((void *) m_tagName);
		m_tagName = 0;
	}

	// free the fileName
	if (m_fileName)
	{
		gos_Free((void *) m_fileName);
		m_fileName = 0;
	}

	// iterate & free children

	if (m_pChildren)
	{
		delete m_pChildren;
		m_pChildren = 0;
	}

	if (m_pNextChild)
	{
		delete m_pNextChild;
		m_pNextChild = 0;
	}
}

void gosGmlTreeNode::AddChild(gosGmlTreeNode * tnp)
{
	// add the sibling to the END of the list
	gosGmlTreeNode * ChildList =m_pChildren;
	gosGmlTreeNode * lastChild = ChildList;
	while(ChildList)
	{
		lastChild = ChildList;
		ChildList = ChildList->m_pNextChild;
	}

	if (lastChild == NULL)
	{
		m_pChildren = tnp;
		tnp->m_pParent = this;
	}
	else
	{
		lastChild->m_pNextChild = tnp;
		tnp->m_pPrevChild = lastChild;
		tnp->m_pParent = this;
	}
}

gosGmlTreeNode * gosGmlTreeNode::GetNext()
{
	return m_pNextChild;
}

gosGmlTreeNode * gosGmlTreeNode::GetChildList()
{
	return m_pChildren;
}

gosGmlTreeNode * gosGmlTreeNode::GetParent()
{
	return m_pParent;
}

const char * gosGmlTreeNode::TagName()
{
	return m_tagName;
}

void gosGmlTreeNode::ToggleExpanded()
{
	m_expanded = !m_expanded;
}

bool gosGmlTreeNode::IsExpanded()
{
	return m_expanded;
}

void gosGmlTreeNode::SetLine(int v)
{
	m_linesFromTop = v;
}

int gosGmlTreeNode::GetLine()
{
	return m_linesFromTop;
}

gosGmlTreeNode * gosGmlTreeNode::Lookup(int value)
{
	int indent = 0;
	gosGmlTreeNode * ptr = this;
	while(ptr)
	{
		if (ptr->GetLine() == value)
			return ptr;
		if ( ptr->GetChildList() && ( ptr->IsExpanded() || ptr == this) )
		{
			indent++;
			ptr = ptr->GetChildList();
		}
		else
		if (ptr->GetNext())
		{
			ptr->SetLine(-1);
			ptr = ptr->GetNext();
		}
		else
		{
			ptr->SetLine(-1);
			indent --;
			ptr = ptr->GetParent();
			while(ptr)
			{
				if (!ptr->GetNext())
				{
					ptr = ptr->GetParent();
					if (ptr)
					{
						ptr = ptr->GetNext();
						indent --;
						break;
					}
				}
				else
				{
					ptr = ptr->GetNext();
					break;
				}
				indent --;
				if (indent == 0)
					break;
			}
		}
	}
	return NULL;
}

const char * gosGmlTreeNode::GetFile()
{
	return m_fileName;
}
