/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: smlparse.h,v 1.6.12.1 2004/07/09 01:57:56 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#ifndef _SMLPARSE_H_
#define _SMLPARSE_H_

#define MAX_PENDING_CHECK_CALLDEPTH 20

/* <body dur="20s">[no sources]</body> is valid; we need to handle it: */
#define DEFAULT_DUR_IF_NO_SOURCES_SCHEDULED   SMILTIME_INVALID

// forward declarations
typedef _INTERFACE IHXSystemRequired     IHXSystemRequired;
typedef _INTERFACE IHXBuffer             IHXBuffer;
typedef _INTERFACE IHXValues             IHXValues;
typedef _INTERFACE IHXXMLParserResponse  IHXXMLParserResponse;
typedef _INTERFACE IHXCommonClassFactory IHXCommonClassFactory;
typedef _INTERFACE IHXXMLParser          IHXXMLParser;
typedef void*                             LISTPOSITION;
class CHXString;
class SMILNodeList;
class CSmilElement;
class CHXSimpleList;
class ErrorNotifier;
class CSmilParser;
class CSmilElementHandler;
class SmilTimeValue;
class CHXPtrArray;
class CSmilAnchorElement;
class CHXStack;
class CSmilRegion;
class CSmilRegPoint;
#if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
class CSmilViewport;
#endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
class CSmilTransition;
class CSmilRootLayout;
class CSmilMeta;
class CSmilMetadata;
class CSmilRendererPreFetch;
class CSmilSource;
class CSmilPriorityClassElement;
class CSmilAAnchorElement;
class CSmilSeqElement;
class CSmilParElement;
class CSmilExclElement;
class CSmilAnimateElement;
class CSmilParamElement;
class CSmilCustomTest;
class XMLError;
class CHXMapLongToObj;
class CHXMapStringToOb;
#if defined(HELIX_FEATURE_SMIL2_VALIDATION)
class CRNBinaryMap;
#endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
class CNamespaceInfo;
class CSmilBodyElement;
class CSmilTimelineElementManager;

/* // /XXXEH- we can't do the following until the core starts notifying
// us every time a repeated track begins:
//#define XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED
*/


#define NUM_SUPPORTED_SMIL_2_0_MODULE_NAMESPACES   55


class SMILNamespace
{
public:
    SMILNamespace(SMILNamespace* pNS);
    SMILNamespace(const char* name, IHXBuffer* pVal);
    virtual ~SMILNamespace();

    char*       m_name;
    IHXBuffer* m_pValue;
};

class SMILNode
{
public:
    SMILNode();
    virtual ~SMILNode();
#if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
    SMILNode(const SMILNode&, BOOL bKeepId=FALSE, CSmilParser* pParser = NULL);
#else
    SMILNode(const SMILNode&, BOOL bKeepId=FALSE, CSmilParser* pParser = NULL,
             UINT32 ulRepeatNum=0);
#endif

    SMILNode* getFirstChild();
    SMILNode* getNextChild();

    CHXString      m_repeatid;
    CHXString      m_id;
    CHXString      m_name;
    UINT32         m_num;    
    SMILNodeTag    m_tag;
    SMILNode*      m_pParent;
    SMILNode*      m_pDependency;
    SMILNodeList*  m_pNodeList;
    IHXValues*    m_pValues;
    CSmilElement*  m_pElement;
    UINT16         m_nGroup;
    RepeatTag      m_repeatTag;
    CHXString      m_trackHint;
    UINT32         m_ulTagStartLine;
    UINT32         m_ulTagStartColumn;
    UINT16         m_nPrefetchTrackNum;
    double         m_fPartialPlayFactor;
    UINT32         m_ulRepeatDur;
    CHXSimpleList* m_pNamespaceList;
    SMIL2Element   m_eElement;
    // ONLY HX_BITFIELD MEMBERS SHOULD GO BELOW THIS LINE!
    // ALL OTHER MEMBER TYPES SHOULD GO ABOVE THIS LINE!
    HX_BITFIELD    m_bLastInGroup : 1;
    HX_BITFIELD    m_bDelete : 1;
    HX_BITFIELD    m_bSkipContent : 1;
    HX_BITFIELD    m_bRepeatHandled : 1;
    HX_BITFIELD    m_bIsSeqWrapperForRepeatElement : 1;
    HX_BITFIELD    m_bIsOuterWrapperTimeContainer : 1;
    HX_BITFIELD    m_bBeginHandledByWrapperParent : 1;
    HX_BITFIELD    m_bEndHandledByWrapperParent : 1;
    HX_BITFIELD    m_bMinHandledByWrapperParent : 1;
    HX_BITFIELD    m_bMaxHandledByWrapperParent : 1;
    HX_BITFIELD    m_bNeedToResolveRepeatDurVSRepeatCount : 1;
    HX_BITFIELD    m_bCloseNode : 1;
    HX_BITFIELD    m_bNamespacedElement : 1;
private:
    LISTPOSITION   m_curPosition;
};

class SMILNodeList: public CHXSimpleList
{
public:
    SMILNodeList();
    virtual ~SMILNodeList();

    SMILNodeList* copy(SMILNode* pParent, BOOL bKeepId = FALSE, CSmilParser* pParser = NULL);

    SMILNode* m_pParentNode;
};

class CNamespaceInfo
{
public:
    CNamespaceInfo();
    ~CNamespaceInfo();

    char*              m_pszPrefix;
    char*              m_pszURL;
    SupportedNamespace m_eNamespace;
    // ONLY HX_BITFIELD MEMBERS SHOULD GO BELOW THIS LINE!
    // ALL OTHER MEMBER TYPES SHOULD GO ABOVE THIS LINE!
    HX_BITFIELD        m_bImplemented : 1;
};


class CSmilParserResponse : public IHXXMLParserResponse,
                            public ErrorNotifier
{
public:
    CSmilParserResponse(CSmilParser* pParser);
    virtual ~CSmilParserResponse();

    // IUnknown methods
    STDMETHOD(QueryInterface)    (THIS_ REFIID riid, void** ppvObj);
    STDMETHOD_(ULONG32, AddRef)  (THIS);
    STDMETHOD_(ULONG32, Release) (THIS);

    // IHXXMLParserResponse methods
    STDMETHOD(HandleStartElement)          (THIS_ const char* pName,
                                                  IHXValues* pAttributes,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleEndElement)            (THIS_ const char* pName,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleCharacterData)         (THIS_ IHXBuffer* pBuffer,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleProcessingInstruction) (THIS_ const char* pTarget,
                                                  IHXValues* pAttributes,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleUnparsedEntityDecl)    (THIS_ const char* pEntityName,
                                                  const char* pSystemID,
                                                  const char* pPublicID,
                                                  const char* pNotationName,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleNotationDecl)          (THIS_ const char* pNotationName,
                                                  const char* pSystemID,
                                                  const char* pPublicID,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleComment)               (THIS_ const char* pComment,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleUnparsedDoctypeDecl)   (THIS_ const char* pName, 
                                                  const char* pSystemID,
                                                  const char* pPublicID, 
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);
    STDMETHOD(HandleDefault)               (THIS_ IHXBuffer* pBuffer,
                                                  UINT32      ulLineNumber,
                                                  UINT32      ulColumNumber);

    // ErrorNotifer methods
    HX_RESULT ErrorInLastTag(HX_RESULT   Error,
                             const char* pErrorString,
                             const char* pFrameString,
                             UINT32      ulLineNumber,
                             UINT32      ulLinePosition);
private:
    CSmilParser* m_pParser;
    INT32        m_lRefCount;
    SMILNode*    m_pCurrentNode;
};

struct ExternalEventInfo
{
    CHXString       m_EventBaseID;
    CHXString       m_PrefixedEventName;
    CHXString       m_EventName;
    CNamespaceInfo* m_pInfo;
};

class CSmilParser
{
public:
    CSmilParser(IUnknown* pContext);
    virtual ~CSmilParser();

    HX_RESULT            init(BOOL bStoreErrors = FALSE);
    HX_RESULT            parse(IHXBuffer* pBuffer, BOOL bIsFinal);
    HX_RESULT            parse(const char* pSmilText);
#if defined(HELIX_FEATURE_SMIL2_VALIDATION)
    HX_RESULT            validateContentModel(UINT32 ulElement, SMILNodeList* pChildren);
    HX_RESULT            validateNode(SMILNode* pNode);
    HX_RESULT            validateCDATA(const char* pszStr) const;
    HX_RESULT            validateIDREF(const char* pszStr) const;
    HX_RESULT            validateNMTOKEN(const char* pszStr) const;
    HX_RESULT            validateEnumerated(UINT32 ulElem, UINT32 ulAttr, const char* pszStr);
    BOOL                 isXMLLetter(char c) const;
    BOOL                 isXMLDigit(char c) const;
    BOOL                 isXMLNameChar(char c) const;
    BOOL                 isNamespacePrefixed(const char* pszStr);
    HX_RESULT            normalizeAttribute(const char* pszStr,
                                            BOOL        bIsCDATA,
                                            REF(char*)  rpszNormal);
    HX_RESULT            validateAttribute(UINT32 ulElement, UINT32 ulAttrib,
                                           const char* pszStr, REF(char*) rpszNormStr);
    HX_RESULT            validateElementName(SMILNode* pNode);
    HX_RESULT            setupValidationNamespaces(SMILNode* pNode);
    HX_RESULT            validateAgainstDTD();
    HX_RESULT            checkExtensionElementNamespace(SMIL2Element eElem,
                                                        SupportedNamespace eNS);
    HX_RESULT            checkExtensionAttributeNamespace(SMIL2Attribute eAttr,
                                                          SupportedNamespace eNS);
#endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
    CNamespaceInfo*      getNamespaceInfo(const char* pszStr, REF(const char*) rpszAttr);
    HX_RESULT            createElements();
    HX_RESULT            durationResolved(const char* pID, UINT32 ulDuration,
                                          BOOL bSetByParent=FALSE,
                                          BOOL bDurationExtendingDueToPause=FALSE);
    HX_RESULT            trackRemoved(const char* pID, UINT32 ulDuration);
    HX_RESULT            adjustForNegativeOffset(const char* pID);
    void                 insertTimelineElement(const char* pID, UINT32 ulDelay);
    void                 resetTimelineElementDuration(const char* pID,
                                                      UINT32 ulDuration,
                                                      UINT32 ulPriorDuration);
    void                 resetTimelineElementDelay(const char* pID, UINT32 ulDelay,
                                                   UINT32 ulPriorDelay);
    void                 resetTimeline();
    HX_RESULT		 prepForSeek(UINT32 ulOldTime, UINT32 ulNewTime);
    HX_RESULT            handlePrefetchFinished(const char* pID, UINT32 ulTimeFinished);
    UINT16               getFragmentGroup(const char* pFragment);
    UINT32               getFragmentOffset(const char* pFragment,
                                           BOOL& bFragFoundAndResolved,
                                           BOOL bResolveBeginOfFragmentTarget=FALSE,
                                           ULONG32 ulCurTime=0);
    HX_RESULT            handleNextElement(CSmilElementHandler* pHandler);
    HX_RESULT            setAllElementHandlers(CSmilElementHandler* pHandler);
    SMILNode*            findFirstNode(SMILNodeTag tag);
    SMILNode*            getFirstNodeChild(SMILNode* pNode);
    SMILNode*            getPrevNode(SMILNode* pCurrentNode);
    CSmilElement*        findElement(const char* pID);
    SMILNode*            getNextNodeChild();
    SMILNodeTag          getSyncTag(SMILNode* pNode);
    void                 getPacketPending(UINT16 unStreamNumber);
    HX_RESULT            addGlobalNamespace(const char* pNamespace, const char* pPrefix);
    HX_RESULT            storeNamespaces(SMILNode* pNode);
    HX_RESULT            addToNamespaceScope(SMILNode* pNode);
    HX_RESULT            removeFromNamespaceScope(SMILNode* pNode);
    BOOL                 isSupportedNonRNNamespace(const char* pNamespace);
    HX_RESULT            addBeginTimeSyncElement(CSmilElement* pElement);
    HX_RESULT            addEndTimeSyncElement(CSmilElement* pElement);
    HX_RESULT            resolveSyncBaseElements();
    HX_RESULT            handleExclDescendants();
    HX_RESULT            addBeginEventElement(SmilTimeValue* pTimeVal);
    HX_RESULT            tryToResolveBeginEndEvents(const char* pEventName,
                                                    const char* pEventElementId,
                                                    ULONG32     ulEventTime);
    HX_RESULT            addEndEventElement(SmilTimeValue* pTimeVal);
    HX_RESULT            addBeginMediaMarkerSyncElement(SmilTimeValue* pTmpVal);
    HX_RESULT            addEndMediaMarkerSyncElement(SmilTimeValue* pTmpVal);
    HX_RESULT            resolveMediaMarkerTime(const char* pszID,
                                                const char* pszMarkerName,
                                                UINT32      ulMarkerTime,
                                                REF(BOOL)   rbNeedHandleElements);
    HX_RESULT            handlePendingScheduling(INT32 lCurTime,
                                                 INT16 iCurrentGroupIndex,
                                                 REF(BOOL) bSomeScheduleWasChanged,
                                                 /*OUT*/ CHXSimpleList* pPauseDisplayElementHideList,
                                                 /*OUT*/ CHXSimpleList* pPauseDisplayDisableElementList);
    HX_RESULT            checkPendingBeginAndEndTimes(INT32     lCurTime,
                                                      INT16 iCurrentGroupIndex,
                                                      REF(BOOL) bREFSomeScheduleWasChanged,
                                                      INT32     lRecursionCount,
                                                      /*OUT*/ CHXSimpleList* pPauseDisplayElementHideList,
                                                      /*OUT*/ CHXSimpleList* pPauseDisplayDisableElementList,
                                                      BOOL bDoHandleExclBeforePlaybackStarts);
    HX_RESULT            insertElementWithPendingBeginOrEnd(CSmilElement*      pElement,
                                                            INT32              lCurTime,
                                                            SmilTimingListType listType);
    void                 handleAllXMMFReferences();
    CHXMapStringToOb*    findNextPendingOnLoadURL(UINT32 lCurTime);
    BOOL                 hasActivateEventListener(const char* pMediaID,
                                                  INT16 iCurrentGroupIndex);
    const char*          getDefaultNamespace();
    // note -- the pErr array returned has the same scope as the SMILParser 
    // object
    HX_RESULT            getErrors(CHXPtrArray** pErrs);
    SMILNode*            getSyncAncestor(SMILNode* pNode);
    // /NOTE: sync base is not always begin of sync ancestor; in a seq, it's
    // end of prior sibling (if any), so this calculates all that:
    virtual ULONG32      getSyncBaseTimeInGroupTimeCoords(SMILNode* pNode);

    // /Tells whether any node all the way up to the root has specified
    // ancestor tag:
    BOOL                 hasAncestor(SMILNodeTag ancestor, SMILNode* pNode);

    // Added to be able to quickly lookup <anchor> or <area> tags
    // by id and not by the region they map to.
    CSmilAnchorElement*  getAnchorOrAreaElement(const char* pID);
    // XXXMEH - moved this from private to public so that we 
    // could animate the coords attribute. This method is needed
    // to parse the coords attribute.
    HX_RESULT            parseAnchorCoords(const char*         pCoords,
                                           CSmilAnchorElement* pAnchor);
    BOOL                 presentationContainsASource() {return m_bContainsSource; }
    BOOL                 presentationContainsInitiallyScheduledTrack() {
	                    return m_bContainsInitiallyScheduledTrack; }
    ULONG32              presentationDurIfNoInitialTracksScheduled() {
                            return m_ulDurIfNoInitialTracksScheduled; }
    BOOL                 EstablishBeginTimeList();
    BOOL                 EstablishEndTimeList();
    BOOL                 EstablishBeginEventList();
    BOOL                 EstablishEndEventList();
    CHXSimpleList*       GetPendingBeginTimeList() {return m_pPendingBeginTimeList;}
    CHXSimpleList*       GetPendingEndTimeList() {return m_pPendingEndTimeList;}
    CHXSimpleList*       GetBeginEventList() {return m_pBeginEventList;}
    CHXSimpleList*       GetEndEventList()   {return m_pEndEventList;}
    BOOL                 isDuplicateEntry(CHXSimpleList* pList,
                                          SmilTimeValue* pTimeValue);
    HX_RESULT            addResumeEvent(SmilTimeValue* pTimeValue,
                                        REF(BOOL) bOldResumeEventWasRemoved);
    HX_RESULT            addUndeferEvent(SmilTimeValue* pTimeValue,
                                        REF(BOOL) bOldUndeferEventWasRemoved);
    HX_RESULT            addResumeOrUndeferEvent(SmilTimeValue* pTimeValue,
                                        REF(BOOL) bOldSuchEventWasRemoved,
					BOOL bIsResumeEvent);
    HX_RESULT            computeRemoveTime(const char* pszID,
                                           REF(UINT32) rulRemoveTime);
    void                 InitPersistent(UINT32 ulPersistentComponentID, IHXValues* pProperties);
    BOOL                 isTimelineObject(SMILNode* pNode);
    static BOOL          isMediaObject(SMILNode* pNode);
    BOOL                 isNonMediaPlayableObject(SMILNode* pNode);
    BOOL                 isTimeContainerObject(SMILNode* pNode);
    UINT16               getNumGroups() const { return m_usNumGroups; }
    const char*          getEnumAttrString(SMIL2Attribute eAttr, BYTE ucVal);
    void                 setParseError(HX_RESULT rv) { m_lParseError = rv;   }
    HX_RESULT            getParseError() const       { return m_lParseError; }
    BOOL                 isAttributeAnimated(const char* pszElementID,
                                             UINT32      ulAttrName);
    SMIL2Element         getSMIL2Element(const char* pszStr);
    SMIL2Attribute       getSMIL2Attribute(const char* pszStr);
    void                 checkForExternalEvents();
    BOOL                 anyExternalEvents(const char* pszID);
    ExternalEventInfo*   getFirstExternalEvent(const char* pszID);
    ExternalEventInfo*   getNextExternalEvent(const char* pszID);
    void                 checkForEventHandlers();
    AccessErrorBehavior  getAccessErrorBehavior(SMILNode* pNode);
    UINT32               GetUniqueNumber() { return m_ulNextVar++; }

    // CSmilParser static public member methods
    static HX_RESULT     parseRegionDimension(const char*   pszStr,
                                              REF(double)   rdValue,
                                              REF(CSS2Type) reType);
    static HX_RESULT     parseZIndex(const char*   pszStr,
                                     REF(INT32)    rlValue,
                                     REF(CSS2Type) reType);
    static HX_RESULT     parseColor(const char*   pszStr,
                                    REF(UINT32)   rulColor,
                                    REF(CSS2Type) reType);
    static HX_RESULT     parseFit(const char*   pszStr,
                                  REF(Fit)      reValue);
    static HX_RESULT     parseRegAlign(const char*   pszStr,
                                       REF(RegAlign) reValue);
    static HX_RESULT     parseOpacity(const char* pszStr, REF(UINT32) rulOpacity);
    static HX_RESULT     parseFill(const char* pszStr, REF(FillType) reFill);
    static HX_RESULT     getFillString(FillType eFill, REF(CHXString) rcFill);
    static HX_RESULT     getEraseString(EraseType eErase, REF(CHXString) rcErase);
    static HX_RESULT     parseFillDefault(const char* pszStr, REF(FillDefaultType) reFillDefault);
    static HX_RESULT     parseAccelDecel(const char* pszStr, REF(double) rdVal);
#if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
    static HX_RESULT     getDefaultTransitionSubType(const char* pszType, REF(CHXString) rcSubType);
    static BOOL          isLegalTransitionType(const char* pszType);
    static BOOL          isLegalTransitionSubType(const char* pszType, const char* pszSubType);
#endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
    static HX_RESULT     parseMarkerURI(const char*    pszStr,
                                        REF(CHXString) rcMarker,
                                        REF(BOOL)      rbExternal,
                                        REF(CHXString) rcExternalFileName);
    static HX_RESULT     parseHandlerForID(const char*    pszStr,
                                           REF(CHXString) rcHandlerID);
    static HX_RESULT     parseAccessErrorBehavior(const char* pszStr,
                                                  REF(AccessErrorBehavior) reErr);
#if defined(XXXMEH_SPLINE_ANIMATION)
    static HX_RESULT     parseKeyTimes(const char* pszVal, CSmilAnimateElement* pAnim);
    static HX_RESULT     parseKeySplines(const char* pszVal, CSmilAnimateElement* pAnim);
    static HX_RESULT     parseSVGPath(const char* pszVal, CSmilAnimateElement* pAnim);
#endif
    static BOOL          isDataURL(const char* pszURL);
    static HX_RESULT     validateDataURL(const char* pszURL);
    static void          addStringProperty(IHXValues* pValues,
                                           IUnknown*   pContext,
                                           const char* pszName,
                                           const char* pszValue);

    BOOL                 allTracksNeedReflushHint() { return m_bAllTracksNeedReflushHint; }

    // CSmilParser public members    
    CHXStack*     m_pNodeListStack;
    SMILNodeList* m_pNodeList;
    UINT32        m_ulErrorLineNumber;
    UINT32        m_ulErrorColumnNumber;
    IHXBuffer*   m_pErrorText;
    IHXBuffer*   m_pDefaultNamespace;
    UINT32        m_ulPersistentComponentDelay;
    UINT32        m_ulPersistentComponentDuration;
    CSmilTimelineElementManager* m_pTimelineElementManager;
    friend class CSmilParserResponse;
private:
    void                   close();
    void                   initRequireTags();
    void		   GetSystemScreenInfo(REF(UINT32) rulScreenHeight,
					       REF(UINT32) rulScreenWidth,
					       REF(UINT32) rulScreenBitDepth);
    void                   getPreferences();
    HX_RESULT              createHeadElements(SMILNodeList* pNodeList);
    HX_RESULT              createSeqWrapper(SMILNodeList* pNodeList, BOOL bMakeInnerPar);
    HX_RESULT              createBodyElements(SMILNodeList* pNodeList);
    HX_RESULT              createElementForAnchorTarget(CSmilAAnchorElement* pAnchor,
                                                       SMILNodeList* pNodeList);
#if 0  /*XXXEH- I wrote this and then didn't need it but it may come in
         handy later so #if(0) it out: */
    BOOL                   hasNoSourceChildren(SMILNode* pNode);
#endif
    HX_RESULT              assignGroupIndexes(SMILNodeList* pNodeList);
    HX_RESULT              assignGroupIndexOnPar(SMILNode* pNode, UINT16 nGroup);
    HX_RESULT              assignGroupIndexOnSeq(SMILNode* pNode, UINT16& nGroup);
    HX_RESULT              constructTimelineElements(SMILNodeList* pNodeList);
    HX_RESULT              setInitialDelays(SMILNodeList* pNodeList);
    void                   setInitialDelay(SMILNode* pNode);
    void                   setInitialDelayOnSeq(SMILNode* pNode);
    HX_RESULT              expandRepeatElements(SMILNodeList* pNodeList);
    HX_RESULT              printBodyElements(SMILNodeList* pNodeList);
    HX_RESULT              updateEventElements(SMILNodeList* pNodeList);
    HX_RESULT              insertElementByTimestamp(CSmilElement* pElement);
    HX_RESULT              addGroup(SMILNode* pNode);
    HX_RESULT              insertGroups();
    HX_RESULT              mapID(SMILNode* pNode, BOOL bOverWrite = FALSE);
    HX_RESULT              mapChildrenIDs(SMILNodeList* pNodeList, BOOL bOverWrite = FALSE);
    HX_RESULT              markRepeatReplica(SMILNodeList* pNodeList, RepeatTag repeatTag);

    BOOL                   testAttributeFailed(SMILNode* pNode);
    BOOL                   customTestFailed(SMILNode* pNode);
    BOOL                   systemComponentFailed(IHXBuffer* pRequiredValue);
    HX_RESULT              markTestAttributeNodes(SMILNodeList* pNodeList);
    HX_RESULT              selectSwitchNodes(SMILNode* pNode);

    BOOL                   inSeq(SMILNode* pNode);
    HX_RESULT              createParent(SMILNode* pChildNode, SMILNodeTag tag,
                                        SMILNode*& pParent, SMILNode*& pParentEnd);
    void                   resolveTimestamps();
    void                   resolveTimestamps(SMILNodeList* pNodeList);
    UINT32                 getStartTime(SMILNode* pNode);
    CSmilRegion*           makeRegion(SMILNode* pNode);
    CSmilRegPoint*         makeRegPoint(SMILNode* pNode);
#if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
    CSmilViewport*         makeViewport(SMILNode* pNode);
#endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
    CSmilTransition*       makeTransition(SMILNode* pNode, REF(HX_RESULT) retVal);
    CSmilRootLayout*       makeRootLayout(SMILNode* pNode);
    CSmilMeta*             makeMeta(SMILNode* pNode);
    CSmilMetadata*         makeMetadata(SMILNode* pNode);
    CSmilCustomTest*       makeCustomTest(SMILNode* pNode,
                                    REF(HX_RESULT) retVal);
    CSmilRendererPreFetch* makeRendererPreFetch(SMILNode* pNode);
    CSmilSource*           makeSource(SMILNode* pNode);
    CSmilPriorityClassElement* makePriorityClassElement(SMILNode* pNode);
    CSmilAAnchorElement*   makeAAnchorElement(SMILNode* pNode);
    CSmilAnchorElement*    makeAnchorElement(SMILNode* pNode);
    CSmilSeqElement*       makeSeqElement(SMILNode* pNode);
    CSmilParElement*       makeParElement(SMILNode* pNode);
    CSmilExclElement*      makeExclElement(SMILNode* pNode);
    CSmilParamElement*     makeParamElement(SMILNode* pNode);
    CSmilBodyElement*      makeBodyElement(SMILNode* pNode);
#if defined(HELIX_FEATURE_SMIL2_ANIMATION)
    CSmilAnimateElement*   makeAnimateElement(SMILNode* pNode);
    HX_RESULT              animSetupElement(CSmilAnimateElement* pAnim);
#if defined(XXXMEH_SPLINE_ANIMATION)
    HX_RESULT              checkSplineAnimation(CSmilAnimateElement* pAnim);
    HX_RESULT              makeSVGPathExplicit(CSmilAnimateElement* pAnim);
#endif
    HX_RESULT              animCountValues(const char* pszStr, REF(char*)  rpStr,
                                           REF(UINT32) rulNumValues, REF(char**) rppStr);
    HX_RESULT              animParseValue(CSmilAnimateElement* pAnim,
                                          const char*          pszVal,
                                          UINT32               i);
#endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
    SMILNode*              getSpecificAncestor(SMILNodeTag ancestor, SMILNode* pNode);
    SMILNode*              findAnyActiveDescendant(SMILNode* pNode,
                               LONG32 lCurTime, SMILNode* pButNotThisNode);
    SMILNode*              findActiveChildOfAncestorExcl(SMILNode* pNode, LONG32 lCurTime);
    SMILNode*              findLastDeferredChildOfAncestorExcl(
                                   SMILNode* pInterruptingNode, LONG32 lCurTime);
    SMILNode*              findLastDeferredDescendant(SMILNode* pNode,
                                     LONG32 lCurTime,
                                     SMILNode* pButNotThisNode,
                                     SMILNode* pLastDeferredChild);
    BOOL                   firstDependentChild(SMILNode* pNode);
    SMILNode*              findFirstNode(SMILNodeList* pNodelist, SMILNodeTag tag);
    // /Finds parent's next child; doesn't have to be a timeline element:
    SMILNode*              findNextSibling(SMILNode* pNode);
    SMILNode*              getTimelineDescendent(SMILNode* pParentNode, SMILNode* pSiblingNode);
    SMILNode*              getTimelineDescendent(SMILNode* pParentNode);
    const char*            assignID(const char* pPrefix);
    HX_RESULT              parseDuration(const char*          pDuration,
                                         CSmilElement*        pElement,
                                         SMILSyncAttributeTag nTag);
    HX_RESULT              parseMarkerClipBeginEnd(const char* pszStr,
                                                   REF(char*)  rpszMarkerName,
                                                   REF(char*)  rpszExtFileName);
    HX_RESULT              adjustDuration(CSmilElement* pElement);
    HX_RESULT              parseClockValue(const char* pValue, UINT32& ulClockValue);
    HX_RESULT              parseSyncBehaviorVal(const char*          pSyncBhvrBuf,
                                                CSmilElement*        pElement,
                                                SMILSyncAttributeTag nTag);
    HX_RESULT              parsePeersHigherLower(const char* pBuf,
                                CSmilPriorityClassElement* pPCElement,
                                SMILPriorityClassPeersHigherLowerAttrib nAttrib);
    HX_RESULT              parsePauseDisplay(const char* pBuf,
                                CSmilPriorityClassElement* pPCElement);
    BOOL                   inLanguagePreference(const char* pLang);
    BOOL                   isRelativeURL(const char* pURL);
    UINT8                  getColorElement(const char* pColorFragment, int len);
    void                   handleXMLParserError(XMLError* pError);
    void                   badAttributeError(SMILNodeTag tag,
                                             const char* pNodeName,
                                             UINT32      ulLineNumber,
                                             BOOL        bJustStore);
    void                   initTagAttributes();
    void                   deleteTagAttributes();
    BOOL                   isLegalAttribute(SMILNodeTag tag, const char* pAttrName);
    HX_RESULT              storeError(HX_RESULT   errCode, 
                                      const char* pErrorString, 
                                      const char* pFrameString,
                                      UINT32      ulLineNumber, 
                                      UINT32      ulLinePosition,
                                      BOOL        bXml = TRUE);
    BOOL                   isEndTagObject(SMILNode* pNode);
    const char*            removeSurroundingWhitespace(const char* pValue);
    HX_RESULT              parseBeginEnd(const char*          pBuffer, 
                                         CSmilElement*        pElement,
                                         SMILSyncAttributeTag nTag);
    HX_RESULT              parseSmil1SyncbaseValue(const char*          pCh, 
                                                   CSmilElement*        pElement,
                                                   SMILSyncAttributeTag nTag);
    HX_RESULT              parseCoord(IHXBuffer* pBuf, REF(float) f);
    HX_RESULT              parseDigit(IHXBuffer* pBuf, REF(UINT32) ul);
    HX_RESULT              parseRestart(const char* pBuffer, CSmilElement* pElement);
    HX_RESULT              parseRestartDefault(const char* pBuffer, CSmilElement* pElement);
    HX_RESULT              parseSensitivity(const char* pszValue, CSmilElement* pSource);
    FillDefaultType        getFillDefault(CSmilElement* pElement);
    void                   resolveFillValue(CSmilElement* pElement);
    BOOL                   isAttributeSpecified(CSmilElement* pElement, const char* pszAttr);
#if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
    HX_RESULT              getNextTransitionEnd(CSmilElement* pElement, REF(UINT32) rulTime);
#endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
    void                   initParsingMaps();
#if defined(HELIX_FEATURE_SMIL2_VALIDATION)
    void                   processCollection(CRNBinaryMap* pMap,
                                             UINT32        ulElement,
                                             UINT32        ulCollection);
    void                   deleteEnumAttrMaps();
    void                   deleteReqAttrLists();
#endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
    void                   deleteValidationNamespaceList();
    void                   checkForXMMFDependency(CSmilElement* pElement);
    void                   handleBeginEndListXMMFReferences(CSmilElement*  pElement,
                                                            CHXSimpleList* pList);
    void                   handleClipBeginEndXMMFReference(CSmilElement*  pElement,
                                                           BOOL           bIsClipBegin);
    HX_RESULT              setElementHandler(SMILNode* pNode, CSmilElementHandler* pHandler);
    void                   addToBeginOrEndTimeMap(SmilTimeValue*     pValue,
                                                  SmilTimingListType eType);
    void                   removeFromBeginOrEndTimeMap(SmilTimeValue*     pValue,
                                                       SmilTimingListType eType);
    BOOL                   isTimeValueListPresent(const char*         pszEventName,
                                                  const char*         pszElementID,
                                                  SmilTimingListType  eType,
                                                  REF(CHXSimpleList*) rpList);
    void                   clearTimeValueMap(SmilTimingListType eType);
    void                   checkNodeForExternalEvents(SMILNode* pNode);
    void                   checkNodeTimeListForExternalEvents(CHXSimpleList* pList);
    void                   addExternalEventToList(const char*     pszID,
                                                  const char*     pszFullName,
                                                  const char*     pszName,
                                                  CNamespaceInfo* pInfo);
    void                   clearExternalEventList();

    IUnknown*               m_pContext;
    IHXCommonClassFactory* m_pClassFactory;
    IHXSystemRequired*     m_pISystemRequired;
    IHXXMLParser*          m_pParser;
    CSmilParserResponse*    m_pResponse;
    SMILNode*               m_pCurNode;
    CHXStack*               m_pNodeDependencies;
    SMILNode*               m_pCurrentDependentNode;
    CHXStack*               m_pAnchorStack;
    CSmilAAnchorElement*    m_pCurrentAnchor;
    INT32                   m_lLastCheckPendingTime;
    CHXSimpleList*          m_pPacketQueue;
    CHXSimpleList*          m_pSourceUpdateList;
    CHXMapLongToObj*        m_pAddGroupMap;
    CHXMapLongToObj*        m_pTagAttributeMap;
    CHXMapStringToOb*       m_pIDMap;
    CHXMapStringToOb*       m_pRequireTagsMap;
#if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
    CHXMapStringToOb*       m_pTransitionMap;
#endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
    CHXMapStringToOb*       m_pActiveNamespaceMap;
    CHXMapStringToOb*       m_pCustomTestMap;
    CHXSimpleList*          m_pNSConflictList;
    CHXSimpleList*          m_pBeginTimeSyncList;
    CHXSimpleList*          m_pEndTimeSyncList;
    CHXSimpleList*          m_pBeginEventList;
    CHXSimpleList*          m_pEndEventList;
    CHXSimpleList*          m_pBeginMediaMarkerList;
    CHXSimpleList*          m_pEndMediaMarkerList;
    CHXSimpleList*          m_pClipBeginMarkerList;
    CHXSimpleList*          m_pClipEndMarkerList;
    CHXSimpleList*          m_pPendingBeginTimeList;
    CHXSimpleList*          m_pPendingEndTimeList;
    CHXSimpleList*          m_pOnLoadURLList;
    CHXSimpleList*          m_pOnLoadURLListCopyForPostSeek; 
    BOOL                    m_bHandlePostSeekOnLoadURLs;
    char*                   m_pBasePath;
    CHXSimpleList*          m_pTrackHintList;
    UINT32                  m_ulBandwidthPreference;
    UINT32                  m_ulScreenHeightPreference;
    UINT32                  m_ulScreenWidthPreference;
    UINT32                  m_ulScreenDepthPreference;
    UINT32                  m_ulDurIfNoInitialTracksScheduled;
    char*                   m_pOverdubOrCaptionPreference;
    char*                   m_pEncoding;
    CHXSimpleList*          m_pLanguagePreferenceList;
    CHXPtrArray*            m_pErrors;
    time_t                  m_tRefTime;
    HXVERSIONINFO           m_versionInfo;
    ULONG32                 m_ulPlatformVer; // /Ret val of HXGetWinVer().
    CHXMapStringToOb*       m_pElementMap;
    CHXMapStringToOb*       m_pAttributeMap;
#if defined(HELIX_FEATURE_SMIL2_VALIDATION)
    CHXMapStringToOb*       m_pExtElementMap;
    CHXMapStringToOb*       m_pExtAttributeMap;
    CHXMapStringToOb*       m_pNamespaceMap;
    CRNBinaryMap*           m_pLegalAttrMap;
    CRNBinaryMap*           m_pContentModelMap;
    XMLAttributeType*       m_pAttrType;
    CHXMapStringToOb**      m_ppEnumAttrMap;
    CHXSimpleList**         m_ppReqAttrList;
#endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
    CHXSimpleList*          m_pValNSList;
    CHXSimpleList*          m_pXMMFElementList;
    UINT32                  m_ulPersistentComponentID;
    ElementWithinTag        m_elementWithinTag;
    UINT16                  m_usNumGroups;
    HX_RESULT               m_lParseError;
    CHXSimpleList*          m_pAnimateElementList;
    CHXMapStringToOb*       m_pBeginTimeMap;
    CHXMapStringToOb*       m_pEndTimeMap;
    CHXSimpleList*          m_pExternalEventList;
    LISTPOSITION            m_pExternalEventListPos;
    CHXSimpleList*          m_pElementsWithHandlerList;
    char*                   m_pVarName;
    UINT32                  m_ulNextVar;
    static const char* const zm_pSupportedSMIL2ModuleNamespaces[
                               NUM_SUPPORTED_SMIL_2_0_MODULE_NAMESPACES + 1];
    // ONLY HX_BITFIELD MEMBERS SHOULD GO BELOW THIS LINE!
    // ALL OTHER MEMBER TYPES SHOULD GO ABOVE THIS LINE!
    HX_BITFIELD             m_bIgnoreUnrecognizedElements : 1;
    HX_BITFIELD             m_bNoNamespaces : 1;
    HX_BITFIELD             m_bRNNamespace : 1;
    HX_BITFIELD             m_bSMILRootLayoutAlreadyFound : 1;
    HX_BITFIELD             m_bCaptionsPreference : 1;
    HX_BITFIELD             m_bSystemAudioDescPreference : 1;
    HX_BITFIELD             m_bUseSystemCPU : 1;
    HX_BITFIELD             m_bUseSystemOS : 1;
    HX_BITFIELD             m_bContainsSource : 1;
    HX_BITFIELD             m_bContainsInitiallyScheduledTrack: 1;
    HX_BITFIELD             m_bStoreErrors : 1;
    HX_BITFIELD             m_bFirstPacket : 1;
    HX_BITFIELD             m_bTimestampsResolved : 1;
    HX_BITFIELD             m_bAllowPlaylistBehavior : 1;
    HX_BITFIELD             m_bAllTracksNeedReflushHint : 1;
};

#if defined(HELIX_FEATURE_SMIL2_VALIDATION)

inline BOOL CSmilParser::isXMLLetter(char ch) const
{
    BOOL bRet = FALSE;

    // /Fixes some gcc compiler warnings that might actually be bugs in our
    // UNIX player; need to compare unsigneds with the 0x..'s which are unsigned:
    const unsigned char c = (unsigned char)ch;

    if ((c >= 0x41 && c <= 0x5A) ||
        (c >= 0x61 && c <= 0x7A) ||
        (c >= 0xC0 && c <= 0xD6) ||
        (c >= 0xD8 && c <= 0xF6) ||
        (c >= 0xF8 && c <= 0xFF))
    {
        bRet = TRUE;
    }

    return bRet;
}

inline BOOL CSmilParser::isXMLDigit(char c) const
{
    return ((c >= 0x30 && c <= 0x39) ? TRUE : FALSE);
}

inline BOOL CSmilParser::isXMLNameChar(char ch) const
{
    BOOL bRet = FALSE;

    // /Fixes some gcc compiler warnings that might actually be bugs in our
    // UNIX player; need to compare unsigneds with the 0x..'s which are unsigned:
    const unsigned char c = (unsigned char)ch;

    if (isXMLLetter(c) ||
        isXMLDigit(c)  ||
        c == '.'       ||
        c == '-'       ||
        c == '_'       ||
        c == ':'       ||
        c == 0xB7)
    {
        bRet = TRUE;
    }

    return bRet;
}

#endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */

#endif  /* _SMLPARSE_H_ */
