//This file is a SND adaptation of ACP's LSTEDLST.HPP 

//(c) Ubi Studios 1996
// See Vincent Greco for any comment or question

#ifndef __SNDLSTED_HPP__
#define __SNDLSTED_HPP__

#include "SNDLstMt.Hpp"
//#include "ErrHie.h"



#define TemplateParam	\
template<class EditorClass, class tdxHandleToStruct, class tdxPointerToAnchorStruct>


#define SNDLST2_ElementClass	\
SNDLST2_EdElement<EditorClass, tdxHandleToStruct, tdxPointerToAnchorStruct>

#define SNDLST2_ListClass	\
SNDLST2_EdList<EditorClass,tdxHandleToStruct,tdxPointerToAnchorStruct>

#define SNDLST2_ListBaseClass	\
SNDLST2_List<SNDLST2_ElementClass >
//Be careful the space character must not be removed (class<class<param> > is OK,  class<class<param>> is Wrong) 



//**************************************
//assumes that tdxHandleToStruct has a tdxPointerToAnchorStruct * pAnchor member
//assumes that tdxHandleToStruct has a tdxHandleToStruct * hNextBrother member
//assumes that tdxHandleToStruct has a tdxHandleToStruct * hPrevBrother member



TemplateParam class SNDLST2_EdList;


TemplateParam
class SNDLST2_EdElement : virtual public SNDLST2_EdMot<tdxHandleToStruct>
{
private:
	SNDLST2_ListClass * m_pList;

public:
	SNDLST2_EdElement(void){m_pList=NULL;}//use SetList(NULL) ???
	virtual ~SNDLST2_EdElement(void){}

public:
	//accessors to private member
	SNDLST2_ListClass *GetList(void){return m_pList;}
	void SetList(SNDLST2_ListClass * _pList, BOOL ModifyEngine=TRUE)
	{
		m_pList=_pList;
		if(ModifyEngine)
		{
			if(_pList)
			{
				SNDLST2_M_StaticGetFather(GetStruct())=_pList->GetEngineAnchor();
			}
			else
			{
				SNDLST2_M_StaticGetFather(GetStruct())=NULL;
			}

		}
	}

public:
	tdxHandleToStruct GetPrevStruct(void);
	tdxHandleToStruct GetNextStruct(void);
	void Isolate(BOOL ModifyEngine=TRUE);
//	void InsertBetween(tdxHandleToStruct pPrev, tdxHandleToStruct pNext);

};


TemplateParam
class SNDLST2_EdList : public SNDLST2_ListBaseClass 
{
private:
	tdxPointerToAnchorStruct m_pAnchor;

public:
    SNDLST2_EdList() {}
    virtual ~SNDLST2_EdList(void){}

public:
	//accessors to private member
	tdxPointerToAnchorStruct GetEngineAnchor() {return m_pAnchor;}
	void SetEngineAnchor(tdxPointerToAnchorStruct  _pAnchor){m_pAnchor=_pAnchor;}

public:
	//redefined functions
	POSITION InsertAfter(POSITION position, SNDLST2_ElementClass* newElement, BOOL ModifyEngine=TRUE);
	POSITION InsertBefore(POSITION position, SNDLST2_ElementClass* newElement, BOOL ModifyEngine=TRUE);
	POSITION AddHead(SNDLST2_ElementClass* newElement, BOOL ModifyEngine=TRUE);
	POSITION AddTail(SNDLST2_ElementClass* newElement, BOOL ModifyEngine=TRUE);
	void RemoveAt(POSITION position, BOOL ModifyEngine=TRUE);
	EditorClass* RemoveHead(BOOL ModifyEngine=TRUE);
	EditorClass* RemoveTail(BOOL ModifyEngine=TRUE);
	void RemoveAll(BOOL ModifyEngine=TRUE);

	//simple type conversions
	EditorClass* GetAt(POSITION position) {return (EditorClass*)SNDLST2_ListBaseClass::GetAt(position);}
	EditorClass* GetNext(POSITION& position) {return (EditorClass*)SNDLST2_ListBaseClass::GetNext(position);}
	EditorClass* GetPrev(POSITION& position) {return (EditorClass*)SNDLST2_ListBaseClass::GetPrev(position);}
	EditorClass* GetHead() {return (EditorClass*)SNDLST2_ListBaseClass::GetHead();}
	EditorClass* GetTail() {return (EditorClass*)SNDLST2_ListBaseClass::GetTail();}
	
	EditorClass* GetHeadElement(POSITION& rPosition) const {return (EditorClass*)SNDLST2_ListBaseClass::GetHeadElement(rPosition);}
    EditorClass* GetTailElement(POSITION& rPosition) const {return (EditorClass*)SNDLST2_ListBaseClass::GetTailElement(rPosition);}
	EditorClass* GetNextElement(POSITION& rPosition) const {return (EditorClass*)SNDLST2_ListBaseClass::GetNextElement(rPosition);}
	EditorClass* GetPrevElement(POSITION& rPosition) const {return (EditorClass*)SNDLST2_ListBaseClass::GetPrevElement(rPosition);}

	EditorClass* GetHeadElement(void) const {return (EditorClass*)SNDLST2_ListBaseClass::GetHeadElement();}
    EditorClass* GetTailElement(void) const {return (EditorClass*)SNDLST2_ListBaseClass::GetTailElement();}
	EditorClass* GetNextElement(SNDLST2_ElementClass * pElement) const {return (EditorClass*)SNDLST2_ListBaseClass::GetNextElement(pElement);}
	EditorClass* GetPrevElement(SNDLST2_ElementClass * pElement) const {return (EditorClass*)SNDLST2_ListBaseClass::GetPrevElement(pElement);}
};


//------------------------------------------------------------------


TemplateParam tdxHandleToStruct SNDLST2_ElementClass::GetPrevStruct(void)
{
	tdxHandleToStruct hStruct=  GetStruct();
	return SNDLST2_M_StaticGetPrevElement(hStruct);
}

TemplateParam tdxHandleToStruct SNDLST2_ElementClass::GetNextStruct(void)
{
	tdxHandleToStruct hStruct=  GetStruct();
	return SNDLST2_M_StaticGetNextElement(hStruct);
}

TemplateParam void SNDLST2_ElementClass::Isolate(BOOL ModifyEngine)//can be called as many times as you want.
{
	if(GetList())
	{
		POSITION P=GetList()->Find(this);
		GetList()->RemoveAt(P, ModifyEngine);
//		SetList(NULL);//modifyEngine ???
       SetList(NULL,ModifyEngine);
	}
}


//-----------------------------------------


TemplateParam POSITION SNDLST2_ListClass::InsertAfter(POSITION position, SNDLST2_ElementClass* newElement, BOOL ModifyEngine)
{
	if(!position) return AddHead(newElement, ModifyEngine);
	SNDLST2_ElementClass* pPrevObj=GetAt(position);//can't be NULL
	newElement->Isolate(ModifyEngine);
	if(ModifyEngine)
	{
		tdxHandleToStruct pPrev=pPrevObj->GetStruct();
		tdxHandleToStruct pNext=pPrevObj->GetNextStruct();
		SNDLST2_M_StaticInsertBetween(newElement->GetStruct(),pPrev,pNext);
	}	
	newElement->SetList(this, ModifyEngine);
	return SNDLST2_ListBaseClass::InsertAfter(position, newElement);
}


TemplateParam POSITION SNDLST2_ListClass::InsertBefore(POSITION position, SNDLST2_ElementClass* newElement, BOOL ModifyEngine)
{
	if(!position) return AddTail(newElement, ModifyEngine);
	SNDLST2_ElementClass* pNextObj=GetAt(position);//can't be NULL
	newElement->Isolate(ModifyEngine);
	if(ModifyEngine)
	{
		tdxHandleToStruct pNext=pNextObj->GetStruct();
		tdxHandleToStruct pPrev=pNextObj->GetPrevStruct();
		SNDLST2_M_StaticInsertBetween(newElement->GetStruct(),pPrev,pNext);
    }
	newElement->SetList(this, ModifyEngine);
	return SNDLST2_ListBaseClass::InsertBefore(position, newElement);
}

TemplateParam POSITION SNDLST2_ListClass::AddHead(SNDLST2_ElementClass* newElement, BOOL ModifyEngine )
{
	newElement->Isolate(ModifyEngine);
	if(ModifyEngine)
	{
		SNDLST2_M_StaticAddHead(GetEngineAnchor(),newElement->GetStruct());	
    }
	newElement->SetList(this, ModifyEngine);
	return SNDLST2_ListBaseClass::AddHead(newElement);
}


TemplateParam POSITION SNDLST2_ListClass::AddTail(SNDLST2_ElementClass* newElement, BOOL ModifyEngine )
{
	newElement->Isolate(ModifyEngine);
	if(ModifyEngine)
	{
		SNDLST2_M_StaticAddTail(GetEngineAnchor(),newElement->GetStruct());	
    }
	newElement->SetList(this, ModifyEngine);
	return SNDLST2_ListBaseClass::AddTail(newElement);
}


TemplateParam void SNDLST2_ListClass::RemoveAt(POSITION position, BOOL ModifyEngine)
{
	SNDLST2_ElementClass *pOldObj = GetAt(position);
	if(ModifyEngine)
	{
		SNDLST2_M_StaticIsolate(pOldObj->GetStruct());
	}
	pOldObj->SetList(NULL, ModifyEngine);
//	pOldObj->SetAnchor(NULL, ModifyEngine);
	SNDLST2_ListBaseClass::RemoveAt(position);
}

TemplateParam EditorClass* SNDLST2_ListClass::RemoveHead(BOOL ModifyEngine)
{
	SNDLST2_ElementClass *pOldObj = SNDLST2_ListBaseClass::RemoveHead();
	if(ModifyEngine)
	{
		SNDLST2_M_StaticIsolate(pOldObj->GetStruct());
	}
	pOldObj->SetList(NULL, ModifyEngine);
	//pOldObj->SetAnchor(NULL, ModifyEngine);
	return (EditorClass*)pOldObj;
}


TemplateParam EditorClass* SNDLST2_ListClass::RemoveTail(BOOL ModifyEngine)
{
	SNDLST2_ElementClass *pOldObj = SNDLST2_ListBaseClass::RemoveTail();
	if(ModifyEngine)
	{
		SNDLST2_M_StaticIsolate(pOldObj->GetStruct());
	}
	pOldObj->SetList(NULL, ModifyEngine);
	return (EditorClass*)pOldObj;
}

TemplateParam void SNDLST2_ListClass::RemoveAll(BOOL ModifyEngine)//not tested !!!
{
	if(ModifyEngine)
	{
		SNDLST2_M_StaticInitAnchor(GetEngineAnchor());
	}
	SNDLST2_ListBaseClass::RemoveAll();
}

//-----------------------------------------



#endif //__LSTEDLST_HPP__
