/****************************************************
 
	        BreakPoints for AI Debugger
 
	implementation file
	David Reizer December 1997
 
*****************************************************/
 
#include "AIUseCPA.h"
#include "StrIntel.h"
#include "EnumOper.h"
 
#include "AID_Erm.h"
 
#include "BreakPts.h"
 
 
#if defined(ACTIVE_AIDEBUG)
 
#define M_bIsBreakableOperator(_eId)\
	( ((_eId) == eOperator_Affect) ||\
		((_eId) == eOperator_PlusAffect) ||\
		((_eId) == eOperator_MinusAffect) ||\
		((_eId) == eOperator_MulAffect) ||\
		((_eId) == eOperator_DivAffect) ||\
		((_eId) == eOperator_VectorPlusVector) ||\
		((_eId) == eOperator_VectorMinusVector) ||\
		((_eId) == eOperator_VectorMulScalar) ||\
		((_eId) == eOperator_VectorDivScalar) ||\
		((_eId) == eOperator_SetVectorX) ||\
		((_eId) == eOperator_SetVectorY) ||\
		((_eId) == eOperator_SetVectorZ) )
 
/***
**** Return True if the Node accepts a breakpoint
***/
ACP_tdxBool fn_bIsBreakableNode( tdstNodeInterpret *_pstNode )
{
	tdeTypeInterpret eType;
	tdeOperatorId eId;
	
	if( _pstNode == NULL )
		{
		Erm_M_UpdateLastError( AIDebug,
													 C_ucErmDefaultChannel,
													 E_uwAIDebugWarningNullPointer,
													 C_lErmNoDebugData,
													 C_ucErmOpenInfoWindow,
													 C_ucAllowStopForDebug,
													 NULL );
		return FALSE;
		}
 
	eType = M_GetTypeInterpret(_pstNode);
	eId = M_eOperatorIdInterpret(_pstNode);
 
	return( (eType == E_ti_KeyWord)    || 
					(eType == E_ti_Procedure)  ||
					(eType == E_ti_MetaAction) ||
					((eType == E_ti_Operator) && M_bIsBreakableOperator(eId)) );
}
 
 
/***
**** Find the tree containing a given node
***/
tdstTreeInterpret * fn_pstFindTreeWithNode( tdstScriptAI *_pstScript, unsigned long _ulNb, tdstNodeInterpret *_pstNode )
{
	tdstComport *pstComport = NULL;
	tdstTreeInterpret * pstTree = NULL;
	int i = 0;
 
	/*** first get the comport ***/
	pstComport = M_GetScriptAIComportN( _pstScript, _ulNb );
	if( pstComport == NULL )
		{
		Erm_M_UpdateLastError( AIDebug,
													 C_ucErmDefaultChannel,
													 E_uwAIDebugWarningNullPointer,
													 C_lErmNoDebugData,
													 C_ucErmOpenInfoWindow,
													 C_ucAllowStopForDebug,
													 "The comport is null" );
		return NULL;
		}
 
	/*** Search in schedule ***/
	pstTree = M_GetComportSchedule( pstComport );
	if( pstTree == NULL )
		{
		Erm_M_UpdateLastError( AIDebug,
													 C_ucErmDefaultChannel,
													 E_uwAIDebugWarningNullPointer,
													 C_lErmNoDebugData,
													 C_ucErmOpenInfoWindow,
													 C_ucAllowStopForDebug,
													 "The schedule is null" );
		}
	else
		if( ( M_GetNodeInterpret(pstTree) <= _pstNode ) && ( _pstNode < (M_GetNodeInterpret(pstTree) + M_GetNbNodeInterpret(pstTree)) ) )
			return pstTree;
 
	/*** Search in rules ***/
	for( i=0; i < M_GetComportNbRules(pstComport); i++ )
		{
		pstTree = M_GetComportRuleN( pstComport, i );
		if( pstTree == NULL )
		{
			Erm_M_UpdateLastError( AIDebug,
													 C_ucErmDefaultChannel,
													 E_uwAIDebugWarningNullPointer,
													 C_lErmNoDebugData,
													 C_ucErmOpenInfoWindow,
													 C_ucAllowStopForDebug,
													 "The rule is null" );
		}
		else
			if( ( M_GetNodeInterpret(pstTree) <= _pstNode ) && ( _pstNode < (M_GetNodeInterpret(pstTree) + M_GetNbNodeInterpret(pstTree)) ) )
				return pstTree;
		}
 
	return NULL;
}
 
 
 
/**************************************************************************************
* Set a breakpoint on the first breakable node before the one passed as a parameter 
*
* Input : the proposed node for BreakPoint
*         the script containing the node
*         the number of the comport containing the node
*
* Output: the actual node with the breakpoint or NULL
*
*****************************************************************************************/
 
tdstNodeInterpret * fn_pstSetValidBreakPoint( tdstNodeInterpret *_pstNode, tdstScriptAI *_pstScript, unsigned long _ulNb )
{
	tdstTreeInterpret *pstTree = NULL;
	tdstNodeInterpret *pstTmpNode = NULL;
 
	/*** if node accepts breakpoint then it is used ***/
	if( fn_bIsBreakableNode( _pstNode ) )
		{
		M_SetBreakPoint( _pstNode, TRUE );
		return _pstNode;
		}
 
	/*** else find the tree containing the node ***/
	pstTree = fn_pstFindTreeWithNode( _pstScript, _ulNb, _pstNode );
	if( pstTree == NULL )
		{
		Erm_M_UpdateLastError( AIDebug,
													 C_ucErmDefaultChannel,
													 E_uwAIDebugWarningNullPointer,
													 C_lErmNoDebugData,
													 C_ucErmOpenInfoWindow,
													 C_ucAllowStopForDebug,
													 "The found tree is null" );
 
		return NULL;
		}
 
	/*** Serach for the previous breakable node ***/
	pstTmpNode = _pstNode;
	while( (pstTmpNode >= M_GetNodeInterpret(pstTree)) && !(fn_bIsBreakableNode( pstTmpNode )) )
		pstTmpNode --;
 
	/*** a node is found ***/
	if( fn_bIsBreakableNode( pstTmpNode ) )
		{
		M_SetBreakPoint( pstTmpNode, TRUE );
		return pstTmpNode;
		}
	/*** no node is found, the breakpoint is invalid ***/
	else
		return NULL;
}
 
 
#endif /*ACTIVE_AIDEBUG*/
