//#################################################################################
//
// BASE IMPLEMENTATION CLASS OF DLL interface Modification
//
//#################################################################################
//
//

#include "stdafx.h"
#include "ACP_Base.h"
#include "ITF.h"

#include "TAC.h"
#include "TFA.h"
#include "TAN.h"
// Shaitan Clean Env {
//#include "incsrf.h"
//End Shaitan Clean Env }

#include "STModif.hpp"
#include "ACInterf.hpp"

#include "x:\Cpa\Main\inc\_EditID.h"

///////////////////////////////////////////////////////////////////////////////
// MACROS
///////////////////////////////////////////////////////////////////////////////
#define M_ForEachElement(oList,p_oElement,Pos)\
            for( p_oElement = (oList) . GetHeadElement( Pos ) ;\
                 p_oElement ;\
                 p_oElement = (oList) . GetNextElement( Pos )\
                )

#define M_DeleteList(oList)\
    while( ! (oList) . IsEmpty() )\
        delete (oList) . RemoveHead();

#define M_FreeList(oList)\
    while( ! (oList) . IsEmpty() )\
        free( (oList) . RemoveHead() );

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_New

State_New::State_New(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction,
                     CPA_Animation *_p_oAnim, char *_szNewName, BOOL _bNormalState, CPA_SaveObject *_p_oMeca)
           :CPA_Modif(0, "New state", FALSE)
{
    m_p_oParentDLL  = _p_oParentDLL ;
    m_p_oAction     = _p_oAction ;
    m_p_oAnim       = _p_oAnim ;
    m_szName        = (char*) malloc ( strlen ( _szNewName ) + 1 ) ;
    strcpy ( m_szName , _szNewName )  ;
    m_p_oState      = NULL ;
    m_bNormalState  = _bNormalState;
    if( _p_oMeca == NULL )
    {
        // uses "Marche" meca
        _p_oMeca = (CPA_SaveObject*) m_p_oParentDLL -> GetMainWorld() -> fn_p_oFindObject( "Base", C_szMecaCardTypeName );
    }
    m_p_oMeca       = _p_oMeca;
}

State_New::~State_New()
{
    if( m_szName )
        free(m_szName);
    if( ! HasBeenDone() && m_p_oState )
        delete m_p_oState;
}

BOOL State_New::Do()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    // make data modif
    if( m_p_oState == NULL )
    {
        // create state
        m_p_oState = new CPA_State( m_p_oParentDLL, p_oFamily , NULL, m_p_oAnim, m_szName );
        // add to action
        m_p_oState -> mfn_vSetAction( m_p_oAction );
		m_p_oState -> mfn_vFillTransitionStateList();
	}
    else
    {
        // Re-register state
        free( m_szName );
        m_szName = (char*) malloc ( m_p_oState -> GetName() . GetLength() + 1 );
        strcpy( m_szName, (char*)(LPCTSTR)m_p_oState -> GetName() );
        m_p_oState -> fn_bValidate();
        m_p_oState -> fn_vNotifySave();
    }
    m_p_oState -> mfn_vSetMecaCard( m_p_oMeca );
    m_p_oAction -> fn_vNotifySave();

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // add state to action
    m_p_oAction -> mfn_vAddState( m_p_oState );
    //
    m_p_oState -> mfn_vSetTransitional( !m_bNormalState );

// CPA_Ed_1 Mihaela Tancu begin
	m_p_oState -> mfn_p_oGetAction()->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateCreated( m_p_oAction , m_p_oState );

    return TRUE;
}

BOOL State_New::Undo()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    // make data modif
    // unregister
    m_p_oState -> fn_bUnValidate() ;
    m_p_oState -> fn_vNotifyUnSave();
    // remove from action
    m_p_oAction -> mfn_vRemoveState( m_p_oState );

// CPA_Ed_1 Mihaela Tancu begin
	m_p_oState -> mfn_p_oGetAction()->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateDeleted ( m_p_oAction ) ;

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_CreateFromAnims

State_CreateFromAnims::State_CreateFromAnims(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction)
                      :CPA_Modif(0, "Create States From Anims", FALSE)
{
    m_p_oParentDLL  = _p_oParentDLL;
    m_p_oAction     = _p_oAction;
    m_bNormalState  = TRUE;
    m_p_oMeca       = (CPA_SaveObject*) m_p_oParentDLL -> GetMainWorld() -> fn_p_oFindObject( "Base", C_szMecaCardTypeName );

    m_oListOfCreatedStates . RemoveAll();
    m_oListOfAnimations . RemoveAll();
}

State_CreateFromAnims::~State_CreateFromAnims()
{
    if( ! HasBeenDone() )
    {
        M_DeleteList( m_oListOfCreatedStates );
    }
    m_oListOfCreatedStates . RemoveAll();
}

// init
void State_CreateFromAnims::mfn_vAddAnim(CPA_Animation *_p_oAnim)
{
    ASSERT( _p_oAnim );
    m_oListOfAnimations . AddTail( _p_oAnim );
}

void State_CreateFromAnims::mfn_vSetNormalState(BOOL _bNormalState)
{
    m_bNormalState = _bNormalState;
}

void State_CreateFromAnims::mfn_vSetMecaCard(CPA_SaveObject *_p_oMeca)
{
    m_p_oMeca = _p_oMeca;
}

// actions
BOOL State_CreateFromAnims::Do()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;

    // make data modif
    if( m_oListOfCreatedStates . IsEmpty() )
    {
        CPA_Animation *p_oAnimation;
        // create states
        M_ForEachElement( m_oListOfAnimations, p_oAnimation, xPos )
        {
            CPA_State *p_oState = new CPA_State( m_p_oParentDLL, p_oFamily , NULL, p_oAnimation, "St_" + p_oAnimation -> GetName() );
            // add to action
            p_oState -> mfn_vSetAction( m_p_oAction );
			p_oState -> mfn_vFillTransitionStateList();
            p_oState -> mfn_vSetMecaCard( m_p_oMeca );
            m_p_oAction -> mfn_vAddState( p_oState );
            p_oState -> mfn_vSetTransitional( !m_bNormalState );
            m_oListOfCreatedStates . AddTail( p_oState );
        }
        // sequence states
        if( m_oListOfCreatedStates . GetCount() == 1 )
        {
            m_oListOfCreatedStates . GetHead() -> mfn_vSetNextState( m_bNormalState ? m_oListOfCreatedStates . GetHead()
                                                                                    : m_p_oAction -> mfn_p_oGetDefaultState() );
        }
        else
        {
            CPA_State *p_oPrevious = m_oListOfCreatedStates . GetHead();
            xPos = m_oListOfCreatedStates . GetHeadPosition();
            m_oListOfCreatedStates . GetNext( xPos );
            while( xPos )
            {
                p_oPrevious -> mfn_vSetNextState( m_oListOfCreatedStates . GetAt( xPos ) );
                p_oPrevious = m_oListOfCreatedStates . GetNext( xPos );
            }
            // last state
            p_oPrevious -> mfn_vSetNextState( m_bNormalState ? m_oListOfCreatedStates . GetHead()
                                                             : m_p_oAction -> mfn_p_oGetDefaultState());
        }
        m_oListOfAnimations . RemoveAll();
    }
    else
    {
        CPA_State *p_oState;
        M_ForEachElement( m_oListOfCreatedStates, p_oState, xPos )
        {
            // Re-register state
            p_oState -> fn_bValidate();
            p_oState -> fn_vNotifySave();
            m_p_oAction -> mfn_vAddState( p_oState );
            p_oState -> mfn_vSetTransitional( !m_bNormalState );
        }
    }

    m_p_oAction -> fn_vNotifySave();
// CPA_Ed_1 Mihaela Tancu begin
	m_p_oAction->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vActionCreated( p_oFamily, m_p_oAction );

    return TRUE;
}

BOOL State_CreateFromAnims::Undo()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;
    CPA_State  *p_oState;
    // make data modif
    M_ForEachElement( m_oListOfCreatedStates, p_oState, xPos)
    {
        // unregister
        p_oState -> fn_bUnValidate() ;
        p_oState -> fn_vNotifyUnSave();
        // remove from action
        m_p_oAction -> mfn_vRemoveState( p_oState );
    }
// CPA_Ed_1 Mihaela Tancu begin
	m_p_oAction->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vActionCreated( p_oFamily, m_p_oAction );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_Copy

State_Copy::State_Copy(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction, CPA_State *_p_oState)
           :CPA_Modif(0, "Copy State", FALSE)
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oAction = _p_oAction ;
    m_p_oStateSource = _p_oState ;
    m_p_oStateTarget = NULL ;
}

State_Copy::~State_Copy()
{
    if( !HasBeenDone() && m_p_oStateTarget)
    {
        delete m_p_oStateTarget;
    }
}

BOOL State_Copy::Do()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    // make data modif
    if( m_p_oStateTarget == NULL )
    {
        // create copy
        m_p_oStateTarget = m_p_oStateSource -> mfn_p_oDuplicateState () ;
    }
    else
    {
        // Re-register state
        m_p_oStateTarget -> fn_bValidate();
        m_p_oStateTarget -> fn_vNotifySave();
    }
    m_p_oAction -> fn_vNotifySave();

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // add state to action
    m_p_oAction -> mfn_vAddState( m_p_oStateTarget );
// CPA_Ed_1 Mihaela Tancu begin
	m_p_oAction->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateCreated( m_p_oAction , m_p_oStateTarget );

    return TRUE;
}

BOOL State_Copy::Undo()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    // make data modif
    // unregister
    m_p_oStateTarget -> fn_bUnValidate() ;
    m_p_oStateTarget -> fn_vNotifyUnSave();
    // remove from action
    m_p_oAction -> mfn_vRemoveState( m_p_oStateTarget );
// CPA_Ed_1 Mihaela Tancu begin
	m_p_oAction->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateDeleted ( m_p_oAction ) ;

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_Rename

State_Rename::State_Rename(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction, CPA_State *_p_oState, char *_szNewName)
              :CPA_Modif(0, "Rename State", FALSE)
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oAction = _p_oAction ;
    m_p_oState = _p_oState ;
    m_szNewName = (char*) malloc ( strlen ( _szNewName ) + 1 ) ;
    strcpy ( m_szNewName , _szNewName )  ;
}

State_Rename::~State_Rename()
{
    if( m_szNewName )
        free(m_szNewName);
}

// actions
BOOL State_Rename::Do()
{
    char *szLastName;
    POSITION xPos;
    tdstZAListInfo *p_stZAInfoList;
    CPA_State *p_oState;

    // make data modif
    szLastName = (char*) malloc ( strlen ( m_p_oState -> GetName () ) + 1 ) ;
    strcpy ( szLastName , m_p_oState -> GetName () ) ;
    if( m_p_oState -> fn_eRename ( m_szNewName ) != E_mc_None )
    {
        free( szLastName );
        return FALSE;
    }
    free ( m_szNewName ) ;
    m_szNewName = szLastName;
    // notify all ActivationState
    M_ForEachElement( m_p_oState -> m_oListOfUsedOnZAList, p_stZAInfoList, xPos)
    {
        ((CPA_ZonesActivatingList*)p_stZAInfoList -> p_oZAList) -> mfn_vStateRenamed( m_p_oState );
    }
    // notify all states in whitch state is next state
    M_ForEachElement( m_p_oState -> m_oListOfUsedAsNextState, p_oState, xPos )
    {
        if( p_oState -> fn_bIsValid() )
            p_oState -> fn_vNotifySave();
    }
    //

    if( m_p_oState -> mfn_bGetTransitional() )
    {
        // notify all states in which state is TargetState  (Transition)
        M_ForEachElement( m_p_oState -> m_oListOfUsedAsTransitional, p_oState, xPos )
        {
            if( p_oState -> fn_bIsValid() )
                p_oState -> fn_vNotifySave();
        }
    }
    else if( m_p_oState == m_p_oAction -> mfn_p_oGetDefaultState() )
    {
        // notify all states in which state is StateToGo    (Transition)
        // notify all states interrupted by action
        M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
        {
            if( p_oState -> fn_bIsValid() )
                p_oState -> fn_vNotifySave();
        }
    }
    m_p_oAction -> fn_vNotifySave();
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateCreated( m_p_oAction , m_p_oState );

    return TRUE;
}

BOOL State_Rename::Undo()
{
    return Do();
}

///////////////////////////////////////////////////////////////////////////////
// class State_Delete

State_Delete::State_Delete(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction, CPA_State *_p_oState)
              :CPA_Modif(0, "Delete state", FALSE)
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oAction = _p_oAction ;
    m_p_oState = _p_oState ;
    m_bIsDefault = (m_p_oState == m_p_oAction -> mfn_p_oGetDefaultState() );
// CPA_Ed_1 Mihaela Tancu begin
    m_p_oStateNext = NULL ;
    m_p_Previous = NULL ;
    m_p_PreviousNext = NULL ;
	m_bDefault = FALSE;
// CPA_Ed_1 Mihaela Tancu end
}

State_Delete::~State_Delete()
{
    if( HasBeenDone() && m_p_oState )
    {

        delete m_p_oState;
    }
}

// actions
BOOL State_Delete::Do()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;
    CPA_State  *p_oState;

// CPA_Ed_1 Mihaela Tancu begin
	CPA_List<CPA_State> &r_oListOfStates = m_p_oAction->m_oListOfStates;
	POSITION stPos =	r_oListOfStates.Find(m_p_oState);
	POSITION stPos1=stPos;
	if(stPos)	// we found the state
	{	if (m_p_oState && !m_p_oState->mfn_bGetTransitional()) 
		{	// if it is a normal state
			m_p_oStateNext = m_p_oState->mfn_p_oGetNextState();
			r_oListOfStates.GetPrev(stPos);
			if(stPos)	// test if we have an element before
			{	
				// we do have a previous state
				m_p_Previous = r_oListOfStates.GetAt(stPos);	// this is the previous state
				if(!m_p_Previous->mfn_bGetTransitional()) 
					m_p_PreviousNext = m_p_Previous->mfn_p_oGetNextState();
				if(!m_p_Previous->mfn_bGetTransitional() &&
					m_p_PreviousNext == m_p_oState)
				{
					// the previous state is a normal state and it points to the state to delete, so we update the links
					CPA_State *p_OldNextState = m_p_oState->mfn_p_oGetNextState(); // the next state of the state to delete
					if (p_OldNextState == m_p_oState) 
						m_p_Previous->mfn_vSetNextState(m_p_Previous);// if the state to delete pointed to itself, we do the same for the previous state
					else
						m_p_Previous->mfn_vSetNextState(p_OldNextState);
					m_p_Previous-> fn_vNotifySave();
				}
			}
			if ( m_bIsDefault) //m_p_oState == m_p_oAction->mfn_p_oGetDefaultState())
			{	CPA_State * _p_oDefault=NULL;
				r_oListOfStates.GetNext(stPos1);
				if (stPos1)
					_p_oDefault = r_oListOfStates.GetAt(stPos1);
				//set the next normal state to be default
				if (_p_oDefault&&!_p_oDefault->mfn_bGetTransitional())
				{	m_p_oAction->mfn_vSetDefaultState(_p_oDefault);
					m_p_oAction -> fn_vNotifySave();
					//
					// change all states interrupted by action
					if( _p_oDefault )
					{
						CPA_State *p_oState;
						POSITION xPos;
						M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
						{
							if( p_oState -> fn_bIsValid() )
								p_oState -> fn_vNotifySave();
						}
					}
				}
				else
				{//if it is the only normal state, do nothing
				}
				m_bDefault = TRUE;
			}
		}
	}
// CPA_Ed_1 Mihaela Tancu end


    // make data modif
    // default state
    if( m_bIsDefault )
    {
        M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
        {
            if( p_oState -> fn_bIsValid() )
                p_oState -> fn_vNotifySave();
        }
    }
    // unregister
    m_p_oState -> fn_bUnValidate() ;
    // remove state from action
    m_p_oAction -> mfn_vRemoveState( m_p_oState );
    // remove from all states in whitch state is next state
    M_ForEachElement( m_p_oState -> m_oListOfUsedAsNextState, p_oState, xPos )
    {
        p_oState -> mfn_vSetNextState( NULL, TRUE );
        if( p_oState -> fn_bIsValid() )
            p_oState -> fn_vNotifySave();
    }
    // remove from all state in whitch this state is a transitional state
    M_ForEachElement( m_p_oState -> m_oListOfUsedAsTransitional, p_oState, xPos )
    {
        tdstTransitionStateInfo *p_stTSI = p_oState -> mfn_p_stGetTransitionStateInfo( m_p_oAction );
        if( p_stTSI )
        {
            p_oState -> mfn_vSetTransitionStateInfo( m_p_oAction, p_stTSI -> eState, NULL );
            if( p_oState -> fn_bIsValid() )
            {
                p_oState -> fn_vNotifySave();
            }
        }
    }

    // delete script state
    m_p_oState -> fn_vNotifyUnSave();
    // rebuild script action
    m_p_oAction -> fn_vNotifySave();

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateDeleted( m_p_oAction );

    return TRUE;
}

BOOL State_Delete::Undo()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;
    CPA_State  *p_oState;

    // make data modif
    // Re-register state
    m_p_oState -> fn_bValidate();
    // restore state
    m_p_oAction -> mfn_vAddState( m_p_oState );
    // restore default
    if( m_bIsDefault )
    {
        m_p_oAction -> mfn_vSetDefaultState( m_p_oState );
        M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
        {
            if( p_oState -> fn_bIsValid() )
                p_oState -> fn_vNotifySave();
        }
    }
    // restore from all states in whitch this state is the next state
    M_ForEachElement( m_p_oState -> m_oListOfUsedAsNextState, p_oState, xPos )
    {
        p_oState -> mfn_vSetNextState( m_p_oState );
        if( p_oState -> fn_bIsValid() )
            p_oState -> fn_vNotifySave();
    }
    // restore from all states in whitch this state is a transitional state
    M_ForEachElement( m_p_oState -> m_oListOfUsedAsTransitional, p_oState, xPos )
    {
        tdstTransitionStateInfo *p_stTSI = p_oState -> mfn_p_stGetTransitionStateInfo( m_p_oAction );
        if( p_stTSI )
        {
            p_oState -> mfn_vSetTransitionStateInfo( m_p_oAction, p_stTSI -> eState, NULL );
            if( p_oState -> fn_bIsValid() )
            {
                p_oState -> fn_vNotifySave();
            }
        }
    }
// CPA_Ed_1 Mihaela Tancu begin
	if (m_p_oState->mfn_bGetTransitional())
	{	//if the state is transitional, add it at the beginning
		m_p_oAction ->m_oListOfStates.RemoveTail();
		m_p_oAction ->m_oListOfStates.AddHead(m_p_oState);
	}
	else {	//if the state is normal 
			if (m_p_oStateNext && !m_p_oStateNext->mfn_bGetTransitional())		
			{
				if (m_bDefault) //m_p_oStateNext == m_p_oAction->mfn_p_oGetDefaultState())
				{	//if it was a default state
					m_p_oAction->mfn_vSetDefaultState(m_p_oState);
					m_p_oAction -> fn_vNotifySave();
					//
					// change all states interrupted by action
					if( m_p_oState )
					{
						CPA_State *p_oState;
						POSITION xPos;
						M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
						{
							if( p_oState -> fn_bIsValid() )
								p_oState -> fn_vNotifySave();
						}
					}
					m_bDefault = FALSE;
				}
			}
			//update the links for the previous state if it was one
			if(m_p_Previous && !m_p_Previous->mfn_bGetTransitional())
			{	m_p_Previous->mfn_vSetNextState(m_p_PreviousNext);
				m_p_Previous->fn_vNotifySave();
			}
			//update the links for the state
			if(m_p_oState && !m_p_oState->mfn_bGetTransitional())
				m_p_oState->mfn_vSetNextState(m_p_oStateNext);
			if (!m_p_oAction ->m_oListOfStates.IsEmpty())
				m_p_oAction ->m_oListOfStates.RemoveTail();
			POSITION stPos;
			stPos= m_p_oAction ->m_oListOfStates.Find(m_p_Previous);
			if (stPos)
			{	m_p_oAction ->m_oListOfStates.GetNext(stPos);
				//add the state at the good position
				if (stPos)
					m_p_oAction ->m_oListOfStates.InsertBefore(stPos, m_p_oState);
				else
					m_p_oAction ->m_oListOfStates.AddTail(m_p_oState);
			}
			else
			{	// if it does not have a previous in the list
				m_p_oAction ->m_oListOfStates.AddHead( m_p_oState);
			}
	}
	m_p_oState -> mfn_p_oGetAction()->mfn_vSetListOfStates(); // it is updating the order in the list
// CPA_Ed_1 Mihaela Tancu end

    m_p_oState -> fn_vNotifyRestore();
    // rebuild script action
    m_p_oAction -> fn_vNotifySave();

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateCreated( m_p_oAction , m_p_oState );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_Default

State_Default::State_Default(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction, CPA_State *_p_oNewState)
              :CPA_Modif(0, "Set default state", FALSE)
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oAction = _p_oAction ;
    m_p_oNewDefaultState = _p_oNewState ;
}

State_Default::~State_Default()
{
}

// actions
BOOL State_Default::Do()
{
    return mfn_vSwapDefaultState();
}

BOOL State_Default::Undo()
{
    return mfn_vSwapDefaultState();
}

BOOL State_Default::mfn_vSwapDefaultState()
{
    // get current default state
    CPA_State *p_oPreviousDefaultState = m_p_oAction -> mfn_p_oGetDefaultState ();
    //
    if( m_p_oNewDefaultState == p_oPreviousDefaultState )
        return FALSE;
    // set new default state
    m_p_oAction -> mfn_vSetDefaultState ( m_p_oNewDefaultState ) ;
    m_p_oAction -> fn_vNotifySave();
    //
    // change all states interrupted by action
    if( p_oPreviousDefaultState )
    {
        CPA_State *p_oState;
        POSITION xPos;
        M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
        {
            if( p_oState -> fn_bIsValid() )
                p_oState -> fn_vNotifySave();
        }
    }

// CPA_Ed_1 Mihaela Tancu begin
	m_p_oAction ->mfn_vSetListOfStates(); // it is updating the order in the list
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
       m_p_oParentDLL -> mfn_vActionCreated( p_oPreviousDefaultState->mfn_p_oGetFamily(), m_p_oAction  );
// CPA_Ed_1 Mihaela Tancu end
    
	//
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateCreated( m_p_oAction , m_p_oNewDefaultState );
    //
    m_p_oNewDefaultState = p_oPreviousDefaultState;

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifAnim

State_ModifAnim::State_ModifAnim(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState,CPA_Animation *_p_oNewAnim)
                :CPA_Modif(0, "Change Animation" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
    m_p_oNewAnim = _p_oNewAnim ;
}

State_ModifAnim::~State_ModifAnim()
{
}

// actions
BOOL State_ModifAnim::Do()
{
    return mfn_vSwapAnimation();
}

BOOL State_ModifAnim::Undo()
{
    return mfn_vSwapAnimation();
}

BOOL State_ModifAnim::mfn_vSwapAnimation()
{
    CPA_Animation *p_oPreviousAnimation = m_p_oState -> mfn_p_oGetAnimation();
    //
    if( m_p_oNewAnim == p_oPreviousAnimation )
        return FALSE;
    //
    m_p_oState -> mfn_vSetAnimation( m_p_oNewAnim );
    m_p_oState -> fn_vNotifySave();

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oState->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    //
    m_p_oNewAnim = p_oPreviousAnimation;
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iAnim );

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifNextState

State_ModifNextState::State_ModifNextState(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState,CPA_State *_p_oNewState)
                :CPA_Modif(0, "Change Next State" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
    m_p_oNewNextState = _p_oNewState ;
}

State_ModifNextState::~State_ModifNextState()
{
}

// actions
BOOL State_ModifNextState::Do()
{
    return mfn_vSwapNextState();
}

BOOL State_ModifNextState::Undo()
{
    return mfn_vSwapNextState();
}

BOOL State_ModifNextState::mfn_vSwapNextState()
{
    CPA_State *p_oPreviousNextState = m_p_oState -> mfn_p_oGetNextState();
    //
    if( m_p_oNewNextState == p_oPreviousNextState )
        return FALSE;

    m_p_oState -> mfn_vSetNextState( m_p_oNewNextState );
// CPA_Ed_1 Mihaela Tancu begin
	m_p_oState -> mfn_p_oGetAction()->mfn_vSetListOfStates(); // it is updating the order in the list
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
       m_p_oParentDLL -> mfn_vActionCreated( m_p_oState->mfn_p_oGetFamily(), m_p_oState -> mfn_p_oGetAction() );
// CPA_Ed_1 Mihaela Tancu end

    m_p_oState -> fn_vNotifySave();
    //
    m_p_oNewNextState = p_oPreviousNextState;
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iNextState );

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifSpeed

State_ModifSpeed::State_ModifSpeed(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState,signed char _cNewSpeed)
                :CPA_Modif(0, "Change Next State" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
    m_cNewSpeed = _cNewSpeed ;
    m_bFirstDo = TRUE;
}

State_ModifSpeed::~State_ModifSpeed()
{
}

// actions
BOOL State_ModifSpeed::Do()
{
    return mfn_vSwapSpeed();
}

BOOL State_ModifSpeed::Undo()
{
    return mfn_vSwapSpeed();
}

BOOL State_ModifSpeed::mfn_vSwapSpeed()
{
    signed char cPreviousSpeed = m_p_oState -> mfn_cGetSpeed();

    if( m_cNewSpeed == cPreviousSpeed )
        return FALSE;

    // modify data
    m_p_oState -> mfn_vSetSpeed( m_cNewSpeed );
    m_p_oState -> fn_vNotifySave();
    //
    m_cNewSpeed = cPreviousSpeed;
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , m_bFirstDo ? C_iSpeedW : C_iSpeed );

    m_bFirstDo = FALSE;

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifReplay

State_ModifReplay::State_ModifReplay(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState,unsigned char _ucNewReplay)
                :CPA_Modif(0, "Change Next State" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
    m_ucNewReplay = _ucNewReplay ;
    m_bFirstDo = TRUE;
}

State_ModifReplay::~State_ModifReplay()
{
}

// actions
BOOL State_ModifReplay::Do()
{
    return mfn_vSwapReplay();
}

BOOL State_ModifReplay::Undo()
{
    return mfn_vSwapReplay();
}

BOOL State_ModifReplay::mfn_vSwapReplay()
{
    unsigned char ucPreviousReplay = m_p_oState -> mfn_ucGetReplay() ;
    //
    if( ucPreviousReplay == m_ucNewReplay )
        return FALSE;
    //
    m_p_oState -> mfn_vSetReplay( m_ucNewReplay );
    m_p_oState -> fn_vNotifySave();
    //
    m_ucNewReplay = ucPreviousReplay;
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , m_bFirstDo ? C_iReplayW : C_iReplay );

    m_bFirstDo = FALSE;
    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifMechanic
State_ModifMechanic::State_ModifMechanic(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState,
                                         CPA_SaveObject *_p_oNewMeca)
                    :CPA_Modif(0, "Change mechanics" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
    m_p_oNewMeca = _p_oNewMeca;
}

State_ModifMechanic::~State_ModifMechanic()
{
}

// actions
BOOL State_ModifMechanic::Do()
{
    return mfn_vSwapMecaCard();
}

BOOL State_ModifMechanic::Undo()
{
    return mfn_vSwapMecaCard();
}

BOOL State_ModifMechanic::mfn_vSwapMecaCard()
{
    CPA_SaveObject *p_oPreviousMeca = m_p_oState -> mfn_p_oGetMecaCard();
    //
    if( m_p_oNewMeca == p_oPreviousMeca )
        return FALSE;
    //
    m_p_oState -> mfn_vSetMecaCard( m_p_oNewMeca );
    m_p_oState -> fn_vNotifySave();
    //
    m_p_oNewMeca = p_oPreviousMeca;
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iMeca );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifTransition

State_ModifTransition::State_ModifTransition( TAction_Interface *_p_oParentDLL, CPA_State *_p_oState, CPA_Action *_p_oAction,
                                              tdeTransitionState _eState, CPA_State *_p_oStatoToGo /*=NULL*/ )
                      :CPA_Modif(0, "Change a transition" , FALSE )
{
    m_p_oParentDLL                      = _p_oParentDLL ;
    m_p_oState                          = _p_oState ;
    m_stNextTransition . p_oAction      = _p_oAction;
    m_stNextTransition . eState         = _eState;
    m_stNextTransition . p_oStateToGo   = _p_oStatoToGo;
}

State_ModifTransition::~State_ModifTransition()
{
}

BOOL State_ModifTransition::Do()
{
    return mfn_bMakeDo();
}

BOOL State_ModifTransition::Undo()
{
    return mfn_bMakeDo();
}

BOOL State_ModifTransition::mfn_bMakeDo()
{
    tdstTransitionStateInfo   stCurrentTransition;
    tdstTransitionStateInfo  *p_stTSI;

    // get current transition
    p_stTSI = m_p_oState -> mfn_p_stGetTransitionStateInfo( m_stNextTransition . p_oAction );
    if( p_stTSI )
    {
        memcpy( & stCurrentTransition, p_stTSI, sizeof tdstTransitionStateInfo );
    }
    else
    {
        stCurrentTransition . p_oAction     = m_stNextTransition . p_oAction;
        stCurrentTransition . eState        = m_p_oState -> mfn_eGetTransitionForAction( m_stNextTransition . p_oAction );
        stCurrentTransition . p_oStateToGo  = NULL;
    }
    // set next transition
    m_p_oState -> mfn_vSetTransitionStateInfo( m_stNextTransition . p_oAction, m_stNextTransition . eState, m_stNextTransition . p_oStateToGo );
	m_p_oState -> fn_vNotifySave();
    memcpy( & m_stNextTransition, & stCurrentTransition, sizeof tdstTransitionStateInfo );

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iInterruptState );

    return TRUE;
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifTransitionExtended

State_ModifTransitionExtended::State_ModifTransitionExtended( TAction_Interface *_p_oParentDLL, CPA_State *_p_oCurrentState )
                              :CPA_Modif(0, "Change several transitions" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
	m_p_oCurrentState = _p_oCurrentState;
	m_oListOfStates . RemoveAll();
    m_oListOfTSI . RemoveAll();
	m_oListOfTSIState . RemoveAll();
    m_bEndCreation = FALSE;
}

State_ModifTransitionExtended::~State_ModifTransitionExtended()
{
    M_FreeList( m_oListOfTSI );
    while( ! m_oListOfTSIState . IsEmpty() )
    {
        tdstTSIState *p_stTSIState = m_oListOfTSIState . RemoveHead();
        free( p_stTSIState -> p_stTSI );
        free( p_stTSIState );
    }
}

void State_ModifTransitionExtended::mfn_vAddState( CPA_State *_p_oState )
{
	if( m_oListOfStates . Find( _p_oState ) == NULL )
		m_oListOfStates . AddTail( _p_oState );
}

void State_ModifTransitionExtended::mfn_vAddTransition( CPA_Action *_p_oAction, tdeTransitionState _eState, CPA_State *_p_oStatoToGo /*=NULL*/ )
{
    tdstTransitionStateInfo  *p_stTSI = (tdstTransitionStateInfo*) malloc( sizeof tdstTransitionStateInfo );

    p_stTSI -> p_oAction     = _p_oAction;
    p_stTSI -> eState        = _eState;
    p_stTSI -> p_oStateToGo  = _p_oStatoToGo;

    m_oListOfTSI . AddTail( p_stTSI );
}

void State_ModifTransitionExtended::mfn_vEndCreation( void )
{
	CPA_State				*p_oState;
	tdstTransitionStateInfo	*p_stTSI;
	POSITION				 xPos;
	tdstTSIState			*p_stTSIState;

    ASSERT( ! m_bEndCreation );

	while( ! m_oListOfStates . IsEmpty() )
	{
		p_oState = m_oListOfStates . RemoveHead();
		M_ForEachElement( m_oListOfTSI, p_stTSI, xPos )
		{
			p_stTSIState = (tdstTSIState*) malloc( sizeof tdstTSIState);

			p_stTSIState -> p_oState = p_oState;
			p_stTSIState -> p_stTSI = (tdstTransitionStateInfo*) malloc( sizeof tdstTransitionStateInfo );
            memcpy( p_stTSIState -> p_stTSI , p_stTSI, sizeof tdstTransitionStateInfo);

			m_oListOfTSIState . AddTail( p_stTSIState );
		}
	}
	M_FreeList( m_oListOfTSI );
	m_bEndCreation = TRUE;
}
// actions
BOOL State_ModifTransitionExtended::Do()
{
    return mfn_bMakeDo();
}

BOOL State_ModifTransitionExtended::Undo()
{
    return mfn_bMakeDo();
}

BOOL State_ModifTransitionExtended::mfn_bMakeDo()
{
    tdstTSIState  *p_stNextTSIState;
    POSITION       xPos;

    ASSERT( m_bEndCreation );

    M_ForEachElement( m_oListOfTSIState, p_stNextTSIState, xPos )
    {
        tdstTransitionStateInfo   stCurrentTransition;
        tdstTransitionStateInfo  *p_stTSI;

        // get current transition
        p_stTSI = p_stNextTSIState -> p_oState -> mfn_p_stGetTransitionStateInfo( p_stNextTSIState -> p_stTSI -> p_oAction );
        if( p_stTSI )
        {
            memcpy( & stCurrentTransition, p_stTSI, sizeof tdstTransitionStateInfo );
        }
        else
        {
            stCurrentTransition . p_oAction     = p_stNextTSIState -> p_stTSI -> p_oAction;
            stCurrentTransition . eState        = p_stNextTSIState -> p_oState -> mfn_eGetTransitionForAction( p_stNextTSIState -> p_stTSI -> p_oAction );
            stCurrentTransition . p_oStateToGo  = NULL;
        }
        // set next transition
        p_stNextTSIState -> p_oState -> mfn_vSetTransitionStateInfo( p_stNextTSIState -> p_stTSI -> p_oAction,
																	 p_stNextTSIState -> p_stTSI -> eState,
																	 p_stNextTSIState -> p_stTSI -> p_oStateToGo );
		p_stNextTSIState -> p_oState -> fn_vNotifySave();
        memcpy( p_stNextTSIState -> p_stTSI, & stCurrentTransition, sizeof tdstTransitionStateInfo );
    }
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oCurrentState , C_iInterruptState );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_SwapDefaultTransitionStatus

State_SwapDefaultTransitionStatus::State_SwapDefaultTransitionStatus( TAction_Interface *_p_oParentDLL, CPA_State *_p_oState )
                                  :CPA_Modif(0, "Swap default transition status" , FALSE )
{
    m_p_oParentDLL = _p_oParentDLL ;
    m_p_oState = _p_oState ;
}

State_SwapDefaultTransitionStatus::~State_SwapDefaultTransitionStatus()
{
}

BOOL State_SwapDefaultTransitionStatus::Do()
{
    return mfn_bMakeDo();
}

BOOL State_SwapDefaultTransitionStatus::Undo()
{
    return mfn_bMakeDo();
}

BOOL State_SwapDefaultTransitionStatus::mfn_bMakeDo()
{
    m_p_oState -> mfn_vSetProhibitedByDefault( ! m_p_oState -> mfn_bIsProhibitedByDefault() );
	m_p_oState -> fn_vNotifySave();
    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iDefaultStatus );

	return TRUE;
}


// CPA_Ed_1 Mihaela Tancu begin
///////////////////////////////////////////////////////////////////////////////
// class State_Move
State_Move::State_Move(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction,
               CPA_State *_p_oPrevStateToMove, CPA_State *_p_oStateToMove, 
			   CPA_State *_p_oPrevStateTarget, CPA_State *_p_oStateTarget,
			   CPA_State *_p_oPrevStateToMoveNext, CPA_State *_p_oStateToMoveNext,
			   CPA_State *_p_oPrevStateTargetNext,
			   BOOL _bDefault, BOOL _bDefaultTarget)
           :CPA_Modif(0, "Move State", FALSE)
{
    m_p_oParentDLL = _p_oParentDLL ;   
    m_p_oAction = _p_oAction ;
    m_p_oPrevStateToMove = _p_oPrevStateToMove;
    m_p_oStateToMove = _p_oStateToMove;
    m_p_oPrevStateTarget = _p_oPrevStateTarget;
    m_p_oStateTarget = _p_oStateTarget;
    m_p_oPrevStateToMoveNext = _p_oPrevStateToMoveNext;
    m_p_oStateToMoveNext = _p_oStateToMoveNext;
    m_p_oPrevStateTargetNext = _p_oPrevStateTargetNext;
	m_bDefault = _bDefault;
	m_bDefaultTarget = _bDefaultTarget;

}

State_Move::~State_Move()
{
}

void State_Move::mfn_vMoveNormalState()
{
	// get the next states of the states only if these states are normal states
	if (m_p_oPrevStateToMove && !m_p_oPrevStateToMove->mfn_bGetTransitional()) 
		m_p_oPrevStateToMoveNext = m_p_oPrevStateToMove-> mfn_p_oGetNextState();
	if (m_p_oStateToMove && !m_p_oStateToMove->mfn_bGetTransitional()) 
		m_p_oStateToMoveNext	 = m_p_oStateToMove-> mfn_p_oGetNextState();
	if (m_p_oPrevStateTarget && !m_p_oPrevStateTarget->mfn_bGetTransitional())
		m_p_oPrevStateTargetNext = m_p_oPrevStateTarget-> mfn_p_oGetNextState();

	// update the links for the previous state of the state to be moved
	if (m_p_oPrevStateToMove && (!m_p_oPrevStateToMove->mfn_bGetTransitional()))
	{
		if (m_p_oPrevStateToMoveNext==m_p_oStateToMove)
		{	if (m_p_oStateToMoveNext == m_p_oStateToMove)
				m_p_oPrevStateToMove->mfn_vSetNextState(m_p_oPrevStateToMove);
			else
				m_p_oPrevStateToMove->mfn_vSetNextState(m_p_oStateToMoveNext);
			m_p_oPrevStateToMove-> fn_vNotifySave();
		}
	}

	// remove the state from the list and set the default state to the next one 
	// if the state to be moved is default
	POSITION stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateToMove);
	ASSERT(stPos);
	if (stPos)
	{	//the state is found in the list
		if (m_p_oStateToMove == m_p_oAction->mfn_p_oGetDefaultState())
		{   // if the state to be moved is a normal state than put a 
			// default state to be the next one in the list
			m_p_oAction->m_oListOfStates.GetNext(stPos);
			if (stPos)
			{
				CPA_State * _p_oState = m_p_oAction->m_oListOfStates.GetAt(stPos);
				m_p_oAction->mfn_vSetDefaultState(_p_oState);
				m_p_oAction -> fn_vNotifySave();
				//
				// change all states interrupted by action
				if( _p_oState )
				{
					CPA_State *p_oState;
					POSITION xPos;
					M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
					{
						if( p_oState -> fn_bIsValid() )
							p_oState -> fn_vNotifySave();
					}
				}
				m_bDefault = TRUE;
				m_p_oAction->m_oListOfStates.GetPrev(stPos);
				if (stPos)
					m_p_oAction->m_oListOfStates.RemoveAt(stPos);
			}
		}
		else m_p_oAction->m_oListOfStates.RemoveAt(stPos);
	}
	
	if (m_p_oStateTarget) // if is inserted before one state
	{
		if (!m_p_oStateTarget->mfn_bGetTransitional())
		{   // before a normal state
			stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateTarget);
			if (stPos)
			{
				m_p_oAction->m_oListOfStates.InsertBefore(stPos, m_p_oStateToMove);
				// update the links
				if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
					// it points to the new state!!!!
				{	
					m_p_oStateToMove->mfn_vSetNextState(m_p_oPrevStateTarget->mfn_p_oGetNextState());
					m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oStateToMove);
					m_p_oPrevStateTarget->fn_vNotifySave();
				}
				else m_p_oStateToMove->mfn_vSetNextState(m_p_oStateTarget);
				if (m_p_oStateTarget == m_p_oAction->mfn_p_oGetDefaultState())
				{	//if the target state is default, than the new state moved will be the default state
					m_p_oAction->mfn_vSetDefaultState(m_p_oStateToMove);
					m_p_oAction -> fn_vNotifySave();
					//
					// change all states interrupted by action
					if( m_p_oStateToMove )
					{
						CPA_State *p_oState;
						POSITION xPos;
						M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
						{
							if( p_oState -> fn_bIsValid() )
								p_oState -> fn_vNotifySave();
						}
					}
					m_bDefaultTarget = TRUE;
				}
			}
		}
	}
	else  // if the target state doen't exist, it is inserted at the end
	{
		m_p_oAction->m_oListOfStates.AddTail (m_p_oStateToMove);
		if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
		{	//update the links
			m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oStateToMove);
			m_p_oPrevStateTarget->fn_vNotifySave();
			m_p_oStateToMove->mfn_vSetNextState(m_p_oPrevStateTargetNext);
		}
	}
	if (m_p_oStateToMove) m_p_oStateToMove->fn_vNotifySave();
}



void State_Move::mfn_vMoveTransitionalState()
{
	//we move the transitional states in the list box with states
	if (m_p_oPrevStateToMove && m_p_oPrevStateToMove->mfn_bGetTransitional()) 
		m_p_oPrevStateToMoveNext = m_p_oPrevStateToMove-> mfn_p_oGetNextState();
	if (m_p_oStateToMove && m_p_oStateToMove->mfn_bGetTransitional()) 
		m_p_oStateToMoveNext	 = m_p_oStateToMove-> mfn_p_oGetNextState();
	if (m_p_oPrevStateTarget && m_p_oPrevStateTarget->mfn_bGetTransitional())
		m_p_oPrevStateTargetNext = m_p_oPrevStateTarget-> mfn_p_oGetNextState();

	// update the links for the previous state of the state to be moved
	if (m_p_oPrevStateToMove && (m_p_oPrevStateToMove->mfn_bGetTransitional()))
	{
		if (m_p_oPrevStateToMoveNext==m_p_oStateToMove)
		{	
			m_p_oPrevStateToMove->mfn_vSetNextState(m_p_oStateToMoveNext);
			m_p_oPrevStateToMove-> fn_vNotifySave();
		}
	}
	// remove the state from the list 
	POSITION stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateToMove);
	ASSERT(stPos);
	if (m_p_oStateTarget) // if is inserted before one state
	{
		if (stPos)
			m_p_oAction->m_oListOfStates.RemoveAt(stPos);
		stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateTarget);
		if (stPos)
		{
			m_p_oAction->m_oListOfStates.InsertBefore(stPos, m_p_oStateToMove);
			// update the links
			if (m_p_oPrevStateTarget && (m_p_oPrevStateTarget->mfn_bGetTransitional()))
			{	
				// if the previous state exist and is a transitional state
				if (m_p_oPrevStateTargetNext!=m_p_oAction->mfn_p_oGetDefaultState())
				{
					//only if the previous target state is not pointing to the default state
					m_p_oStateToMove->mfn_vSetNextState(m_p_oPrevStateTargetNext);
					m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oStateToMove);
					m_p_oPrevStateTarget->fn_vNotifySave();
				}
				else
					m_p_oStateToMove->mfn_vSetNextState(m_p_oStateTarget);
			}
			else 
				m_p_oStateToMove->mfn_vSetNextState(m_p_oStateTarget);
		}
	}
	if (m_p_oStateToMove) m_p_oStateToMove->fn_vNotifySave();
}



BOOL State_Move::Do()
{

	if (m_p_oStateToMove == NULL) return 1;

	if (!m_p_oStateToMove->mfn_bGetTransitional()) 
		mfn_vMoveNormalState();
	else
		mfn_vMoveTransitionalState();

    // update display
	if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
		if (m_p_oStateToMove) m_p_oParentDLL -> mfn_vActionCreated( m_p_oStateToMove->mfn_p_oGetFamily(), m_p_oAction);

    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
		// m_p_oParentDLL -> mfn_vStateChanged( m_p_oStateToMove , C_iNextState );
		m_p_oParentDLL -> mfn_vSetCurrentState( m_p_oStateToMove );

	return TRUE;
}


void State_Move::mfn_vUndoMoveTransitionalState()
{
	// we undo the move for the transitional state
	// set the old next state of the previous state of the state which was moved only 
	// if it was a normal state
	if (m_p_oPrevStateToMove && (m_p_oPrevStateToMove->mfn_bGetTransitional()))
	{	m_p_oPrevStateToMove->mfn_vSetNextState(m_p_oPrevStateToMoveNext);
		m_p_oPrevStateToMove-> fn_vNotifySave();
	}
	POSITION stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateToMove);
	ASSERT(stPos);
	if (stPos)
	{	//delete the state to move from its position
		m_p_oAction->m_oListOfStates.RemoveAt(stPos);
		if (m_p_oPrevStateToMove)
		{	
			stPos = m_p_oAction->m_oListOfStates.Find(m_p_oPrevStateToMove);
			if (stPos)
			{	//inserting it in the last place
				m_p_oAction->m_oListOfStates.GetNext(stPos);
				if (stPos)
					m_p_oAction->m_oListOfStates.InsertBefore(stPos, m_p_oStateToMove);
				else
					m_p_oAction->m_oListOfStates.AddTail(m_p_oStateToMove);
			}
		}
		else //if the previous state of the state to be moved do not exit, add the state at the beggining
			m_p_oAction->m_oListOfStates.AddHead(m_p_oStateToMove);
	}

	CPA_State* _p_oStateToMoveOldNext = m_p_oStateToMove->mfn_p_oGetNextState();
	m_p_oStateToMove->mfn_vSetNextState(m_p_oStateToMoveNext);
	
	if (m_p_oStateToMove) m_p_oStateToMove-> fn_vNotifySave();
	
	if (m_p_oStateTarget) // if is inserted before one state
	{
		if (m_p_oStateTarget->mfn_bGetTransitional())
		{
			if (m_p_oPrevStateTarget && (m_p_oPrevStateTarget->mfn_bGetTransitional()))
			{	m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oPrevStateTargetNext);
				m_p_oPrevStateTarget->fn_vNotifySave();
			}
		}
	}

}


void State_Move::mfn_vUndoMoveNormalState()
{
	// set the old next state of the previous state of the state which was moved only 
	// if it was a normal state
	if (m_p_oPrevStateToMove && (!m_p_oPrevStateToMove->mfn_bGetTransitional()))
	{	m_p_oPrevStateToMove->mfn_vSetNextState(m_p_oPrevStateToMoveNext);
		m_p_oPrevStateToMove-> fn_vNotifySave();
	}

	POSITION stPos = m_p_oAction->m_oListOfStates.Find (m_p_oStateToMove);
	ASSERT(stPos);
	if (stPos)
	{	//delete the state to move from its position
		m_p_oAction->m_oListOfStates.RemoveAt(stPos);
		if (m_p_oPrevStateToMove)
		{	
			stPos = m_p_oAction->m_oListOfStates.Find(m_p_oPrevStateToMove);
			if (stPos)
			{	//inserting it in the last place (the previous before moving)
				m_p_oAction->m_oListOfStates.GetNext(stPos);
				if (stPos)
					m_p_oAction->m_oListOfStates.InsertBefore(stPos, m_p_oStateToMove);
				else
					m_p_oAction->m_oListOfStates.AddTail(m_p_oStateToMove);
			}
		}
		else 
			m_p_oAction->m_oListOfStates.AddHead(m_p_oStateToMove);
	}
	CPA_State* _p_oStateToMoveOldNext = m_p_oStateToMove->mfn_p_oGetNextState();

	m_p_oStateToMove->mfn_vSetNextState(m_p_oStateToMoveNext);
	
	if (m_bDefault)  // if the state to move was default, make it default again
	{	m_p_oAction->mfn_vSetDefaultState(m_p_oStateToMove);
		m_p_oAction -> fn_vNotifySave();
		//
		// change all states interrupted by action
		if( m_p_oStateToMove )
		{
			CPA_State *p_oState;
			POSITION xPos;
			M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
			{
				if( p_oState -> fn_bIsValid() )
					p_oState -> fn_vNotifySave();
			}
		}
	}
	if (m_p_oStateToMove) m_p_oStateToMove-> fn_vNotifySave();
	
	if (m_p_oStateTarget) // if is inserted before one state
	{
		if (!m_p_oStateTarget->mfn_bGetTransitional())
		{
			if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
			{	m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oPrevStateTargetNext);
				m_p_oPrevStateTarget->fn_vNotifySave();
			}
			if (m_bDefaultTarget)  //if the target state was default state, make it default again
			{	m_p_oAction->mfn_vSetDefaultState(m_p_oStateTarget);
				m_p_oAction -> fn_vNotifySave();
				//
				// change all states interrupted by action
				if( m_p_oStateTarget )
				{
					CPA_State *p_oState;
					POSITION xPos;
					M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
					{
						if( p_oState -> fn_bIsValid() )
							p_oState -> fn_vNotifySave();
					}
				}
			}
		}
	}
	else  // if it is inserted at the end
	{	//update the links for the state before the target state
		if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
		{	m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oPrevStateTargetNext);
			m_p_oPrevStateTarget->fn_vNotifySave();
		}
	}
}


BOOL State_Move::Undo()
{

	if (!m_p_oStateToMove->mfn_bGetTransitional()) 
		mfn_vUndoMoveNormalState();
	else
		mfn_vUndoMoveTransitionalState();

    // update display
	if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
		if (m_p_oStateToMove) m_p_oParentDLL -> mfn_vActionCreated( m_p_oStateToMove->mfn_p_oGetFamily(), m_p_oAction);

    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
		// m_p_oParentDLL -> mfn_vStateChanged( m_p_oStateToMove , C_iNextState );
		m_p_oParentDLL -> mfn_vSetCurrentState( m_p_oStateToMove );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// class State_CreateFromAnimsMove

State_CreateFromAnimsMove::State_CreateFromAnimsMove(TAction_Interface *_p_oParentDLL, CPA_Action *_p_oAction,
													 CPA_State *_p_oPrevStateTarget, CPA_State *_p_oStateTarget,
													 CPA_State *_p_oPrevStateTargetNext)
                      :CPA_Modif(0, "Create States From Anims Move", FALSE)
{
    m_p_oParentDLL  = _p_oParentDLL;
    m_p_oAction     = _p_oAction;
    m_bNormalState  = TRUE;
    m_p_oMeca       = (CPA_SaveObject*) m_p_oParentDLL -> GetMainWorld() -> fn_p_oFindObject( "Base", C_szMecaCardTypeName );

    m_oListOfCreatedStates . RemoveAll();
    m_oListOfAnimations . RemoveAll();
	m_p_oPrevStateTarget = _p_oPrevStateTarget;
	m_p_oStateTarget = _p_oStateTarget;
	m_p_oPrevStateTargetNext = _p_oPrevStateTargetNext;
	m_bDefaultTarget = FALSE;
}

State_CreateFromAnimsMove::~State_CreateFromAnimsMove()
{
    if( ! HasBeenDone() )
    {
        M_DeleteList( m_oListOfCreatedStates );
    }
    m_oListOfCreatedStates . RemoveAll();
}

// init
void State_CreateFromAnimsMove::mfn_vAddAnim(CPA_Animation *_p_oAnim)
{
    ASSERT( _p_oAnim );
    m_oListOfAnimations . AddTail( _p_oAnim );
}

void State_CreateFromAnimsMove::mfn_vSetNormalState(BOOL _bNormalState)
{
    m_bNormalState = _bNormalState;
}

void State_CreateFromAnimsMove::mfn_vSetMecaCard(CPA_SaveObject *_p_oMeca)
{
    m_p_oMeca = _p_oMeca;
}

void State_CreateFromAnimsMove::mfn_vDoMany(int iNumber)
{		
	// for the case when we drag & drop several states from animations
	int k = iNumber;
	CPA_State* _p_oState = m_p_oAction->m_oListOfStates . RemoveTail( );
	iNumber--;
	POSITION stPos ;
	if(_p_oState && (_p_oState->mfn_bGetTransitional()) )
	{	while (iNumber)  //if the states were transitional add them at the head
		{
			m_p_oAction->m_oListOfStates . AddHead(_p_oState);
			_p_oState = m_p_oAction->m_oListOfStates . RemoveTail( );
			iNumber--;
		}
		m_p_oAction->m_oListOfStates . AddHead(_p_oState);
	}
	else // it is a normal state 
	 	 // get the next states of the previous state
	{	 // if it is going to be inserted at the ending of the list box
		if ((!m_p_oPrevStateTarget && !m_p_oStateTarget)||(m_p_oStateTarget && m_p_oStateTarget->mfn_bGetTransitional()))
		{	// the case when the states are inserted at the end of the list box.
			//CPA_State* _p_oStates[20];
			CArray<CPA_State*,CPA_State*> _p_oStates;
			_p_oStates . SetSize( iNumber + 1 );
			if (!m_p_oAction->m_oListOfStates.IsEmpty())
			{
				while (iNumber)
				{	_p_oStates[iNumber]=m_p_oAction ->m_oListOfStates.RemoveTail();
				    iNumber--;
				}
				// the last state from the list box is pointing to the first state
				// and the last state is pointing to the previous next state of the last state
				CPA_State *_p_LastState=m_p_oAction ->m_oListOfStates.GetTail();
				if (_p_LastState && (!_p_LastState->mfn_bGetTransitional()))
				{	
					CPA_State *_p_LastStateNext = _p_LastState-> mfn_p_oGetNextState();
					_p_LastState->mfn_vSetNextState(_p_oStates[1]);
					_p_oState->mfn_vSetNextState( _p_LastStateNext);
					if (_p_LastState) _p_LastState->fn_vNotifySave();
					_p_oState->fn_vNotifySave();
				}
				for (int j=1; j< k; j++)
					m_p_oAction->m_oListOfStates . AddTail(_p_oStates[j]);
			}
			m_p_oAction->m_oListOfStates . AddTail( _p_oState);
		}
		if (m_p_oPrevStateTarget) 
			m_p_oPrevStateTargetNext = m_p_oPrevStateTarget-> mfn_p_oGetNextState();
		// update the links for the previous state of the state to be moved
		if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
		{	//CPA_State * _p_oFirstState[20];
			CArray<CPA_State*,CPA_State*> _p_oFirstState;
			_p_oFirstState . SetSize( iNumber + 1 );
			while (iNumber)
			{	_p_oFirstState[iNumber]=m_p_oAction ->m_oListOfStates.RemoveTail();
			    iNumber--;
			}
			//update the links for the state previous of the state target to the last state
			m_p_oPrevStateTarget->mfn_vSetNextState(_p_oFirstState[k-1]);
			_p_oState->mfn_vSetNextState(m_p_oPrevStateTargetNext);
			m_p_oPrevStateTarget->fn_vNotifySave();
			stPos = m_p_oAction->m_oListOfStates .Find(m_p_oPrevStateTarget);
			m_p_oAction->m_oListOfStates . GetNext(stPos);
			if (stPos)
				m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oState);					
			else
				m_p_oAction->m_oListOfStates . AddTail(_p_oState);
			// for the case when we have more than one animation selected
			for (int j=k-1; j>0; j--)
			{	stPos = m_p_oAction->m_oListOfStates .Find(m_p_oPrevStateTarget);
				m_p_oAction->m_oListOfStates . GetNext(stPos);
				if (stPos)
					m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oFirstState[j]);					
			}
			_p_oState->fn_vNotifySave();
		}
		else
		{	if (m_p_oStateTarget && !m_p_oStateTarget->mfn_bGetTransitional())
			{	//if the target state is a normal state make the links between the new states and the target state
				//CPA_State* _p_oStates[20];
				CArray<CPA_State*,CPA_State*> _p_oStates;
				_p_oStates . SetSize( iNumber + 1 );
				_p_oState->mfn_vSetNextState(m_p_oStateTarget);
				stPos = m_p_oAction->m_oListOfStates .Find(m_p_oStateTarget);
				if (stPos)  // the target state exists
					m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oState);
				_p_oState->fn_vNotifySave();
				while (iNumber)
				{	_p_oStates[iNumber]=m_p_oAction ->m_oListOfStates.RemoveTail();
				    iNumber--;
				}
				m_p_oAction->m_oListOfStates .GetPrev(stPos);
				if (stPos)
					m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oStates[k-1]);
				for (int j=k-1; j>1; j--)
				{
					m_p_oAction->m_oListOfStates .GetPrev(stPos);
					if (stPos)
						m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oStates[j-1]);
				}
				// if the target state is a default state, than the first state will be a default state					
				if (m_p_oStateTarget == m_p_oAction->mfn_p_oGetDefaultState())
				{
					m_p_oAction->mfn_vSetDefaultState(_p_oStates[1]);
					m_p_oAction -> fn_vNotifySave();
					// change all states interrupted by action
					if( _p_oStates[1] )
					{
						CPA_State *p_oState;
						POSITION xPos;
						M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
						{
							if( p_oState -> fn_bIsValid() )
								p_oState -> fn_vNotifySave();
						}
					}
					m_bDefaultTarget = TRUE;
				}
			}
		}
	}
}



// actions
BOOL State_CreateFromAnimsMove::Do()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;

    // make data modif
    if( m_oListOfCreatedStates . IsEmpty() )
    {
        CPA_Animation *p_oAnimation;
        // create states
        M_ForEachElement( m_oListOfAnimations, p_oAnimation, xPos )
        {
            CPA_State *p_oState = new CPA_State( m_p_oParentDLL, p_oFamily , NULL, p_oAnimation, "St_" + p_oAnimation -> GetName() );
            // add to action
            p_oState -> mfn_vSetAction( m_p_oAction );
			p_oState -> mfn_vFillTransitionStateList();
            p_oState -> mfn_vSetMecaCard( m_p_oMeca );
			m_p_oAction -> mfn_vAddState( p_oState );
            p_oState -> mfn_vSetTransitional( !m_bNormalState );
            m_oListOfCreatedStates . AddTail( p_oState );
        }

		// sequence states
		// transitional states have always default state of action as next state
        if( m_oListOfCreatedStates . GetCount() == 1 )
        {
            m_oListOfCreatedStates . GetHead() -> mfn_vSetNextState( m_bNormalState ? m_oListOfCreatedStates . GetHead()
                                                                                    : m_p_oAction -> mfn_p_oGetDefaultState() );
        }
		else
		{
			CPA_State *p_oPrevious = m_oListOfCreatedStates . GetHead();
			xPos = m_oListOfCreatedStates . GetHeadPosition();
			m_oListOfCreatedStates . GetNext( xPos );
			while( xPos )
			{
				p_oPrevious -> mfn_vSetNextState( m_oListOfCreatedStates . GetAt( xPos ) );
				p_oPrevious = m_oListOfCreatedStates . GetNext( xPos );
			}
	           // last state
		       p_oPrevious -> mfn_vSetNextState( m_bNormalState ? m_oListOfCreatedStates . GetHead()
                                                            : m_p_oAction -> mfn_p_oGetDefaultState());
		}

		// updating the links between the states and inserting the new states (state) at 
		// the good position in the list with states
		if( m_oListOfCreatedStates . GetCount() != m_p_oAction -> m_oListOfStates . GetCount() )
		{
			if (m_oListOfCreatedStates . GetCount()==1)
				mfn_vDo();
			else
				mfn_vDoMany(m_oListOfCreatedStates . GetCount());
		}
        m_oListOfAnimations . RemoveAll();
    }
    else //redo
    {
        CPA_State *p_oState;
        M_ForEachElement( m_oListOfCreatedStates, p_oState, xPos )
        {
            // Re-register state
            p_oState -> fn_bValidate();
            p_oState -> fn_vNotifySave();
            m_p_oAction -> mfn_vAddState( p_oState );
            p_oState -> mfn_vSetTransitional( !m_bNormalState );
        }

		// updating the links between the states and reinserting the new states (state) at 
		// the good position in the list with states
		if( m_oListOfCreatedStates . GetCount() != m_p_oAction -> m_oListOfStates . GetCount() )
		{
			if (m_oListOfCreatedStates . GetCount()==1)
				mfn_vDo();
			else
				mfn_vDoMany(m_oListOfCreatedStates . GetCount());
		}
	}

    m_p_oAction -> fn_vNotifySave();
    //m_p_oParentDLL -> mfn_vNotifyAllZAList( p_oFamily, TRUE );

// Shaitan => optimisation lists in the level
	// set modification flag in the corresponding family
	((CPA_Family *) m_p_oAction->GetOwner())->mfn_vSetModifiedStateList();
// End Shaitan => optimisation lists in the level

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vActionCreated( p_oFamily, m_p_oAction );

    return TRUE;
}

void State_CreateFromAnimsMove::mfn_vDo(void)
{		
	CPA_State* _p_oState = m_p_oAction->m_oListOfStates . RemoveTail( );
	POSITION stPos ;

	// when we create only one state

	if (_p_oState && (_p_oState->mfn_bGetTransitional()) )
		m_p_oAction->m_oListOfStates . AddHead(_p_oState);
	else // it is a normal state 
		// get the next states of the previous state
	{	// if it is going to be inserted at the ending of the list box
		if ((!m_p_oPrevStateTarget && !m_p_oStateTarget)||(m_p_oStateTarget && m_p_oStateTarget->mfn_bGetTransitional()))
		{   // the case for inserting at the end of the list box
			if (!m_p_oAction->m_oListOfStates.IsEmpty())
			{
				CPA_State *_p_LastState=m_p_oAction ->m_oListOfStates.GetTail();
				if (_p_LastState && (!_p_LastState->mfn_bGetTransitional()))
				{	
					CPA_State *_p_LastStateNext = _p_LastState-> mfn_p_oGetNextState();
					_p_LastState->mfn_vSetNextState(_p_oState);
					_p_oState->mfn_vSetNextState( _p_LastStateNext);
					if (_p_LastState) _p_LastState->fn_vNotifySave();
					_p_oState->fn_vNotifySave();
				}
			}
			m_p_oAction->m_oListOfStates . AddTail( _p_oState);
		}
		if (m_p_oPrevStateTarget) 
			m_p_oPrevStateTargetNext = m_p_oPrevStateTarget-> mfn_p_oGetNextState();
		// update the links for the previous state of the state to be moved
		if (m_p_oPrevStateTarget && (!m_p_oPrevStateTarget->mfn_bGetTransitional()))
		{	// if the previous state of the state before which is going to be inserted 
			// the new state is a normal state make the links between this one and the new state
			m_p_oPrevStateTarget->mfn_vSetNextState(_p_oState);
			_p_oState->mfn_vSetNextState(m_p_oPrevStateTargetNext);
			m_p_oPrevStateTarget->fn_vNotifySave();
			stPos = m_p_oAction->m_oListOfStates .Find(m_p_oPrevStateTarget);
			m_p_oAction->m_oListOfStates . GetNext(stPos);
			if (stPos)
				m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oState);
			else
				m_p_oAction->m_oListOfStates . AddTail(_p_oState);
			_p_oState->fn_vNotifySave();
		}
		else
		{	
			if (m_p_oStateTarget && !m_p_oStateTarget->mfn_bGetTransitional())
			{	// if the target state is a normal state make the links with the new state				
				_p_oState->mfn_vSetNextState(m_p_oStateTarget);
				stPos = m_p_oAction->m_oListOfStates .Find(m_p_oStateTarget);
				if (stPos)
					m_p_oAction->m_oListOfStates . InsertBefore(stPos, _p_oState);
				_p_oState->fn_vNotifySave();
				// if the target state is a default state , than make the new state a default state
				if (m_p_oStateTarget == m_p_oAction->mfn_p_oGetDefaultState())
				{
					m_p_oAction->mfn_vSetDefaultState(_p_oState);
					m_p_oAction -> fn_vNotifySave();
					// change all states interrupted by action
					if( _p_oState )
					{
						CPA_State *p_oState;
						POSITION xPos;
						M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
						{
							if( p_oState -> fn_bIsValid() )
								p_oState -> fn_vNotifySave();
						}
					}
					m_bDefaultTarget = TRUE;
				}
			}
		}
	}
}

void State_CreateFromAnimsMove::mfn_vUndoMany(int iNumber)
{
    CPA_State  *p_oState;

	// for the case when there are many states included
	if ((!m_p_oPrevStateTarget && !m_p_oStateTarget) || (m_p_oStateTarget && m_p_oStateTarget->mfn_bGetTransitional()))
	{	
		if (!m_p_oAction->m_oListOfStates.IsEmpty())
		{	// update the links to the previous values for the last state in the list box
			POSITION stPos = m_p_oAction ->m_oListOfStates.GetTailPosition();
			CPA_State *p_oStateOldNext;
			for (int j=iNumber; j>0; j--)
			{
				if (stPos)
				{
					p_oState = m_p_oAction ->m_oListOfStates.GetPrev(stPos);
					if (j==iNumber)
						if (p_oState && !p_oState->mfn_bGetTransitional())
							p_oStateOldNext = p_oState->mfn_p_oGetNextState();
				}
			}
			if (stPos)
			{
				CPA_State * _p_LastState = m_p_oAction ->m_oListOfStates.GetAt(stPos);
				if (_p_LastState && (!_p_LastState->mfn_bGetTransitional()))
				{	_p_LastState->mfn_vSetNextState(p_oStateOldNext);
					if (_p_LastState) _p_LastState->fn_vNotifySave();
				}
			}
		}
	}
}

BOOL State_CreateFromAnimsMove::Undo()
{
    CPA_Family *p_oFamily = (CPA_Family*) m_p_oAction -> GetOwner() ;
    POSITION    xPos;
    CPA_State  *p_oState;

	mfn_vUndoMany(m_oListOfCreatedStates . GetCount());
	
	if (m_p_oStateTarget && !m_p_oStateTarget->mfn_bGetTransitional())
	{	// if the target state was a normal state update again its links
		if ((m_p_oPrevStateTarget)&&!m_p_oPrevStateTarget->mfn_bGetTransitional())
		{
			m_p_oPrevStateTarget->mfn_vSetNextState(m_p_oPrevStateTargetNext);
			m_p_oPrevStateTarget->fn_vNotifySave();
		}
		if (m_bDefaultTarget)  // if it was a default state make it default again
		{
			m_p_oAction->mfn_vSetDefaultState(m_p_oStateTarget);
			m_p_oAction -> fn_vNotifySave();
			//
			// change all states interrupted by action
			if( m_p_oStateTarget)
			{
				CPA_State *p_oState;
				POSITION xPos;
				M_ForEachElement( m_p_oAction -> m_oListOfStatesInterrupted, p_oState, xPos )
				{
					if( p_oState -> fn_bIsValid() )
						p_oState -> fn_vNotifySave();
				}
			}
		}
	}

    // make data modif
    M_ForEachElement( m_oListOfCreatedStates, p_oState, xPos)
    {
        // unregister
        p_oState -> fn_bUnValidate() ;
        p_oState -> fn_vNotifyUnSave();
        // remove from action
        m_p_oAction -> mfn_vRemoveState( p_oState );
    }

	// update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vActionCreated( p_oFamily, m_p_oAction );

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// class State_ModifCustomBits

State_ModifCustomBits::State_ModifCustomBits(TAction_Interface *_p_oParentDLL, CPA_State *_p_oState, unsigned char	_ucCBNumber)
					  :CPA_Modif(0, "Change Custom bits" , FALSE )
{
    m_p_oParentDLL	= _p_oParentDLL ;
    m_p_oState		= _p_oState ;
    m_ucCBNumber	= _ucCBNumber ;
    m_bFirstDo		= TRUE;
}

State_ModifCustomBits::~State_ModifCustomBits()
{
}

// actions
BOOL State_ModifCustomBits::Do()
{
    return mfn_vSwapCB();
}

BOOL State_ModifCustomBits::Undo()
{
    return mfn_vSwapCB();
}

BOOL State_ModifCustomBits::mfn_vSwapCB()
{
	unsigned char ucCBCurrent = m_p_oState -> mfn_ucGetCustomBits();
	unsigned char ucValue	  = (1<<m_ucCBNumber);
    // modify data
	if(ucCBCurrent & ucValue )
	{
		ucCBCurrent &= ~ucValue;
	}
	else
	{
		ucCBCurrent |= ucValue;
	}
    m_p_oState -> mfn_vSetCustomBits( ucCBCurrent );
    m_p_oState -> fn_vNotifySave();

    // update display
    if( m_p_oParentDLL -> fn_bIsCurrentEditor () )
        m_p_oParentDLL -> mfn_vStateChanged( m_p_oState , C_iCustomBits );

    m_bFirstDo = FALSE;

    return TRUE;
}

// CPA_Ed_1 Mihaela Tancu end
