#if !defined(CASTDOWN_H) && !defined(__BEDRC__)
#define CASTDOWN_H
//========================================================================================
//
//     File:			castdown.h
//     Release Version:	$ 1.0d1 $
//
//     Creation Date:	December 10, 1991
//
//     COPYRIGHT 1991-1993 SYMANTEC CORPORATION. ALL RIGHTS RESERVED. UNPUBLISHED -- RIGHTS
//     RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. USE OF COPYRIGHT NOTICE IS
//     PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION OR DISCLOSURE.
//
//     THIS SOFTWARE CONTAINS PROPRIETARY AND CONFIDENTIAL INFORMATION OF SYMANTEC
//     CORPORATION. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
//     EXPRESS WRITTEN PERMISSION OF SYMANTEC CORPORATION.
//
//     RESTRICTED RIGHTS LEGEND
//     Use, duplication, or disclosure by the Government is subject to restrictions as set
//     forth in subparagraph (c)(l)(ii) of the Rights in Technical Data and Computer
//     Software clause at DFARS 252.227-7013. Symantec Corporation, 10201 Torre Avenue,
//     Cupertino, CA 95014.
//
//========================================================================================

//----------------------------------------------------------------------------------------
// ISKINDOF
//----------------------------------------------------------------------------------------

#define ISKINDOF(target, p) \
	((p) && p->_CastDown(target::_GetClassName()))
	
//----------------------------------------------------------------------------------------
// CASTDOWN
//----------------------------------------------------------------------------------------

#define CASTDOWN(target, p) (target::CastDown(p))

//----------------------------------------------------------------------------------------
// DefineCastDownRefFunction
//----------------------------------------------------------------------------------------

#if defined BR_DEBUG && !defined BR_BUILD_WIN && !defined BR_BUILD_MAC 

#define DefineCastDownRefFunction(CLASSNAME)											\
    static CLASSNAME& CastDown(BR_CObject& Obj)											\
    {																					\
        if(&Obj != NULL)																\
        {																				\
            CLASSNAME* p = (CLASSNAME*)Obj._CastDown(_GetClassName());					\
            if(p == NULL)																\
                BR_DEBUG_STRING(kDebugTargetNotFound);										\
																						\
            return(*p);																	\
        } else																			\
        	return(NULLOBJECT(CLASSNAME));												\
    }
#else

#define DefineCastDownRefFunction(CLASSNAME)											\
    static CLASSNAME& CastDown(BR_CObject& Obj)											\
    {																					\
        if(&Obj != NULL)																\
            return(*(CLASSNAME*)Obj._CastDown(_GetClassName()));						\
        else																			\
        	return(NULLOBJECT(CLASSNAME));												\
    }
#endif

//----------------------------------------------------------------------------------------
// DefineCastDownPtrFunction
//----------------------------------------------------------------------------------------

#if defined BR_DEBUG && !defined BR_BUILD_WIN && !defined BR_BUILD_MAC 

#define DefineCastDownPtrFunction(CLASSNAME)											\
    static CLASSNAME * CastDown(BR_CObject* pObj)										\
    {																					\
        if(pObj != NULL)																\
        {																				\
            CLASSNAME * p = (CLASSNAME *)pObj->_CastDown(_GetClassName());				\
            if(p == NULL)																\
                BR_DEBUG_STRING(kDebugTargetNotFound);										\
																						\
            return(p);																	\
        } else																			\
        	return((CLASSNAME *)NULL);													\
    }
#else

#define DefineCastDownPtrFunction(CLASSNAME) 											\
    static CLASSNAME * CastDown(BR_CObject* pObj)										\
    {																					\
        if(pObj != NULL)																\
            return((CLASSNAME *)pObj->_CastDown(_GetClassName()));						\
        else																			\
        	return((CLASSNAME *)NULL);													\
    }
#endif

//----------------------------------------------------------------------------------------
// DefineCastDownConstRefFunction
//----------------------------------------------------------------------------------------

#if defined BR_DEBUG && !defined BR_BUILD_WIN && !defined BR_BUILD_MAC 

#define DefineCastDownConstRefFunction(CLASSNAME)										\
    static const CLASSNAME& CastDown(const BR_CObject& Obj)								\
    {																					\
        if(&Obj != NULL)																\
        {																				\
            const CLASSNAME* p = (const CLASSNAME*)Obj._CastDown(_GetClassName());		\
            if(p == NULL)																\
                BR_DEBUG_STRING(kDebugTargetNotFound);										\
																						\
            return(*p);																	\
        } else																			\
        	return(NULLOBJECT(CLASSNAME));												\
    }
#else

#define DefineCastDownConstRefFunction(CLASSNAME)										\
    static const CLASSNAME& CastDown(const BR_CObject& Obj)								\
    {																					\
        if(&Obj != NULL)																\
            return(*(const CLASSNAME*)Obj._CastDown(_GetClassName()));					\
        else																			\
        	return(NULLOBJECT(CLASSNAME));												\
    }
#endif

//----------------------------------------------------------------------------------------
// DefineCastDownConstPtrFunction
//----------------------------------------------------------------------------------------

#if defined BR_DEBUG && !defined BR_BUILD_WIN && !defined BR_BUILD_MAC 

#define DefineCastDownConstPtrFunction(CLASSNAME)										\
    static const CLASSNAME * CastDown(const BR_CObject* pObj)							\
    {																					\
        if(pObj != NULL)																\
        {																				\
            const CLASSNAME* p = (const CLASSNAME*)pObj->_CastDown(_GetClassName());	\
            if(p == NULL)																\
                BR_DEBUG_STRING(kDebugTargetNotFound);										\
																						\
            return(p);																	\
        } else																			\
        	return((const CLASSNAME *)NULL);											\
    }
#else

#define DefineCastDownConstPtrFunction(CLASSNAME)										\
    static const CLASSNAME * CastDown(const BR_CObject* pObj)							\
    {																					\
        if(pObj != NULL)																\
            return((const CLASSNAME *)pObj->_CastDown(_GetClassName()));				\
        else																			\
        	return((const CLASSNAME *)NULL);											\
    }
#endif

//----------------------------------------------------------------------------------------
// DECLARE_CASTDOWN
//----------------------------------------------------------------------------------------

#define DECLARE_CASTDOWN(CLASSNAME)                        \
        DefineCastDownPtrFunction(CLASSNAME)               \
        DefineCastDownConstPtrFunction(CLASSNAME)          \
        DefineCastDownRefFunction(CLASSNAME)               \
        DefineCastDownConstRefFunction(CLASSNAME)          \
        static BR_Boolean IsKindOf(const BR_CObject& Obj)  {return(&CLASSNAME::CastDown(Obj) != (CLASSNAME*)NULL);} \
        static BR_Boolean IsKindOf(const BR_CObject* pObj) {return(CLASSNAME::CastDown(pObj) != (CLASSNAME*)NULL);}

//----------------------------------------------------------------------------------------
// BR_SETCLASSNAME
//----------------------------------------------------------------------------------------

#define BR_SETCLASSNAME(CLASSNAME)                             \
    public:                                                 \
        DECLARE_CASTDOWN(CLASSNAME)                         \
        virtual void* _CastDown(const char*) const;         \
        static const char* _GetClassName(void);             \
        virtual const char* ClassName(void) const

//----------------------------------------------------------------------------------------
// _DEFINE_CASTDOWN
//----------------------------------------------------------------------------------------

#define _DEFINE_CASTDOWN(CLASSNAME, BASE)                   \
    void* CLASSNAME::_CastDown(const char* pTarget) const   \
    {                                                       \
        return( (pTarget == _GetClassName()) ?              \
                    (void*)this                             \
                  : BASE::_CastDown(pTarget));              \
    }

#ifdef BR_DEBUG
void* AmbigCheck(void* p, void* q);
#endif

//----------------------------------------------------------------------------------------
// _DEFINE_CASTDOWN2
//----------------------------------------------------------------------------------------
#ifdef BR_DEBUG

#define _DEFINE_CASTDOWN2(CLASSNAME, BASE1, BASE2)                  \
    void* CLASSNAME::_CastDown(const char* pTarget) const           \
    {                                                               \
        if(pTarget == _GetClassName())                              \
            return((void*)this);                                    \
                                                                    \
        return(::AmbigCheck(CLASSNAME::BASE1::_CastDown(pTarget),   \
                           CLASSNAME::BASE2::_CastDown(pTarget)));  \
    }
#else

#define _DEFINE_CASTDOWN2(CLASSNAME, BASE1, BASE2)                  \
    void* CLASSNAME::_CastDown(const char* pTarget) const           \
    {                                                               \
        if(pTarget == _GetClassName())                              \
            return((void*)this);                                    \
                                                                    \
        void* p = BASE1::_CastDown(pTarget);                        \
                                                                    \
        if(p != NULL)                                               \
            return(p);                                              \
                                                                    \
        return(BASE2::_CastDown(pTarget));                          \
    }
#endif

//----------------------------------------------------------------------------------------
// _DEFINE_CASTDOWN3
//----------------------------------------------------------------------------------------
#ifdef BR_DEBUG

#define _DEFINE_CASTDOWN3(CLASSNAME, BASE1, BASE2, BASE3)               \
    void* CLASSNAME::_CastDown(const char* pTarget) const               \
    {                                                                   \
        if(pTarget == _GetClassName())                                  \
            return((void*)this);                                        \
                                                                        \
        void* p = ::AmbigCheck(CLASSNAME::BASE1::_CastDown(pTarget),    \
                               CLASSNAME::BASE2::_CastDown(pTarget));   \
                                                                        \
        return(::AmbigCheck(p, CLASSNAME::BASE3::_CastDown(pTarget)));  \
    }
#else

#define _DEFINE_CASTDOWN3(CLASSNAME, BASE1, BASE2, BASE3)               \
    void* CLASSNAME::_CastDown(const char* pTarget) const               \
    {                                                                   \
        if(pTarget == _GetClassName())                                  \
            return((void*)this);                                        \
                                                                        \
        void* p = BASE1::_CastDown(pTarget);                            \
                                                                        \
        if(p != NULL)                                                   \
            return(p);                                                  \
                                                                        \
        p = BASE2::_CastDown(pTarget);                                  \
                                                                        \
        if(p != NULL)                                                   \
            return(p);                                                  \
                                                                        \
        return(BASE3::_CastDown(pTarget));                              \
    }
#endif

//----------------------------------------------------------------------------------------
// _DEFINE_CLASS_ALWAYS
//----------------------------------------------------------------------------------------

#define _DEFINE_CLASS_ALWAYS(CLASSNAME)                     \
    const char* CLASSNAME::_GetClassName(void)              \
    {                                                       \
        return(#CLASSNAME);                                 \
    }                                                       \
    const char* CLASSNAME::ClassName(void) const            \
    {                                                       \
        return(CLASSNAME::_GetClassName());                 \
    }

//----------------------------------------------------------------------------------------
// DEFINE_CLASS
//----------------------------------------------------------------------------------------

#define DEFINE_CLASS(CLASSNAME,BASE)                        \
    _DEFINE_CASTDOWN(CLASSNAME,BASE)                        \
    _DEFINE_CLASS_ALWAYS(CLASSNAME)

//----------------------------------------------------------------------------------------
// DEFINE_CLASS_MI2
//----------------------------------------------------------------------------------------

#define DEFINE_CLASS_MI2(CLASSNAME, BASE1, BASE2)           \
    _DEFINE_CASTDOWN2(CLASSNAME, BASE1, BASE2)              \
    _DEFINE_CLASS_ALWAYS(CLASSNAME)

//----------------------------------------------------------------------------------------
// DEFINE_CLASS_MI3
//----------------------------------------------------------------------------------------

#define DEFINE_CLASS_MI3(CLASSNAME, BASE1, BASE2, BASE3)    \
    _DEFINE_CASTDOWN3(CLASSNAME, BASE1, BASE2, BASE3)       \
    _DEFINE_CLASS_ALWAYS(CLASSNAME)

#endif
