smlparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:137k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include "hxtypes.h"
  39. #include "hxresult.h"
  40. #include "hxcom.h"
  41. #include "hxcomm.h"
  42. #include "ihxpckts.h"
  43. #include "hxfiles.h"
  44. #include "hxformt.h"
  45. #include "hxengin.h"
  46. #include "hxplugn.h"
  47. #include "hxpends.h"
  48. #include "hxasm.h"
  49. #include "hxprefs.h"
  50. #include "hxupgrd.h"
  51. #include "hxassert.h"
  52. #include "chxpckts.h"
  53. #include "upgrdcol.h"
  54. #include "nptime.h"
  55. #include "smpte.h"
  56. #include "debug.h"
  57. #include "hxstrutl.h"
  58. #include "hxstring.h"
  59. #include "cbqueue.h"
  60. #include "hxslist.h"
  61. #include "hxurl.h"
  62. #include "hxmap.h"
  63. #include "hxstack.h"
  64. #include "hxwintyp.h"
  65. #include "chxxtype.h"
  66. #include "hxparse.h"
  67. #include "hxxml.h"
  68. #include "xmlreslt.h"
  69. #include "looseprs.h"
  70. #include "hxxmlprs.h" //HXXMLParser
  71. #include "sm1elem.h"
  72. #include "sm1time.h"
  73. #include "sm1error.h"
  74. #include "sm1parse.h"
  75. #include "hxmon.h"
  76. #include "debugout.h"
  77. #include "hxheap.h"
  78. #ifdef _DEBUG
  79. #undef HX_THIS_FILE
  80. static const char HX_THIS_FILE[] = __FILE__;
  81. #endif
  82. static const UINT32 MAX_DRIVER_PACKET_SIZE = 1024;
  83. static const UINT32 INITIAL_STREAM1_TIMESTAMP = 1;
  84. static const UINT32 INITIAL_STREAM0_TIMESTAMP = 0;
  85. static const UINT32 MAX_ERROR_LEN = 1024;
  86. static const char* const RN_PREFIX = "rn";
  87. static const char* const RN_TAG_RENDERER_LIST = "rn:renderer-list";
  88. static const char* const RN_TAG_RENDERER = "rn:renderer";
  89. static const char* const SYSTEM_COMPONENT_NAMESPACE = "http://features.real.com/systemComponent";
  90. static const char* const SYSTEM_COMPONENT = "systemComponent";
  91. static const struct smil1ColorTable
  92. {
  93.     char* m_pColorName;
  94.     UINT8 m_ucRed;
  95.     UINT8 m_ucGreen;
  96.     UINT8 m_ucBlue;
  97. } Smil1ColorTable[] =
  98. {
  99.     {"black",  0x00, 0x00, 0x00},
  100.     {"silver",  0xc0, 0xc0, 0xc0},
  101.     {"gray",   0x80, 0x80, 0x80},
  102.     {"white",  0xff, 0xff, 0xff},
  103.     {"maroon", 0x80, 0x00, 0x00},
  104.     {"red",    0xff, 0x00, 0x00},
  105.     {"purple", 0x80, 0x00, 0x80},
  106.     {"fuchsia", 0xff, 0x00, 0xff},
  107.     {"green", 0x00, 0x80, 0x00},
  108.     {"lime", 0x00, 0xff, 0x00},
  109.     {"olive", 0x80, 0x80, 0x00},
  110.     {"yellow", 0xff, 0xff, 0x00},
  111.     {"navy", 0x00, 0x00, 0x80},
  112.     {"blue", 0x00, 0x00, 0xff},
  113.     {"teal", 0x00, 0x80, 0x80},
  114.     {"aqua", 0x00, 0xff, 0xff},
  115.     {0, 0x00, 0x00, 0x00}
  116. };
  117. static const struct smil1TagTable
  118. {
  119.     SMIL1NodeTag m_tag;
  120.     const char* m_name;
  121. } smil1TagTable[] =
  122. {
  123.     {SMILSmil,     "smil"},
  124.     {SMILMeta,     "meta"},
  125.     {SMILHead,     "head"},
  126.     {SMILBody,     "body"},
  127.     {SMILBasicLayout,     "layout"},
  128.     {SMILRootLayout,     "root-layout"},
  129.     {SMILRegion,     "region"},
  130.     {SMILSwitch,     "switch"},
  131.     {SMILText,     "text"},
  132.     {SMILImg,     "img"},
  133.     {SMILRef,     "ref"},
  134.     {SMILAudio,     "audio"},
  135.     {SMILVideo,     "video"},
  136.     {SMILAnimation,     "animation"},
  137.     {SMILTextstream,     "textstream"},
  138.     {SMILAnchor,     "anchor"},
  139.     {SMILAAnchor,     "a"},
  140.     {SMILPar,     "par"},
  141.     {SMILSeq,     "seq"},
  142.     {SMILRNRendererList,    RN_TAG_RENDERER_LIST},
  143.     {SMILRendererPreFetch,  RN_TAG_RENDERER},
  144.     {SMILUnknown,     "unknown"}
  145. };
  146. CSmil1Parser::CSmil1Parser(IUnknown* pContext):
  147.     m_pContext(pContext),
  148.     m_pClassFactory(NULL),
  149.     m_pISystemRequired(NULL),
  150.     m_pNodeList(0),
  151.     m_pNodeListStack(0),
  152.     m_pPacketQueue(0),
  153.     m_pIDMap(0),
  154.     m_pAddGroupMap(0),
  155.     m_pSourceUpdateList(0),
  156.     m_pRequireTagsMap(0),
  157.     m_bNoNamespaces(FALSE),
  158.     m_bRNNamespace(FALSE),
  159.     m_bIgnoreUnrecognizedElements(TRUE),
  160.     m_bSMILRootLayoutAlreadyFound(FALSE),
  161.     m_bSMIL10FullCompliance(FALSE),
  162.     m_pActiveNamespaceMap(NULL),
  163.     m_pNSConflictList(NULL),
  164.     m_bTimestampsResolved(FALSE),
  165.     m_pCurNode(0),
  166.     m_pNodeDependencies(0),
  167.     m_pCurrentDependentNode(0),
  168.     m_pAnchorStack(0),
  169.     m_pCurrentAnchor(0),
  170.     m_pEndLayout(0),
  171.     m_ulBandwidthPreference(0),
  172.     m_ulScreenHeightPreference(0),
  173.     m_ulScreenWidthPreference(0),
  174.     m_ulScreenDepthPreference(0),
  175.     m_pLanguagePreferenceList(0),
  176.     m_bCaptionsPreference(FALSE),
  177.     m_pOverdubOrCaptionPreference(0),
  178.     m_pBasePath(0),
  179.     m_pTagAttributeMap(0),
  180.     m_bContainsSource(FALSE),
  181.     m_pEncoding(0),
  182.     m_pTrackHintList(0),
  183.     m_pParser(NULL),
  184.     m_pResponse(NULL),
  185.     m_ulErrorLineNumber(0),
  186.     m_ulErrorColumnNumber(0),
  187.     m_pErrorText(NULL)
  188.     , m_bStoreErrors(FALSE)
  189.     , m_pErrors(NULL)
  190.     , m_ulPersistentComponentID(0)
  191.     , m_elementWithinTag(WithinUnknown)
  192.     , m_pVarName(NULL)
  193.     , m_ulNextVar(0)
  194.     , m_pTimelineElementManager(NULL)
  195. {
  196.     if(m_pContext)
  197.     {
  198. m_pContext->AddRef();
  199. m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pClassFactory);
  200.     }
  201.     initRequireTags();
  202.     initTagAttributes();
  203.     getPreferences();
  204.     m_pVarName = new char [256];
  205.     m_pTimelineElementManager = new CSmil1TimelineElementManager;
  206. }
  207. CSmil1Parser::~CSmil1Parser()
  208. {
  209.     deleteTagAttributes();
  210.     HX_DELETE(m_pRequireTagsMap);
  211.     if (m_pErrors)
  212.     {
  213. int size = m_pErrors->GetSize();
  214. for (int i =0; i < size; ++i)
  215. {
  216.     IHXBuffer* pBuf = (IHXBuffer*)(*m_pErrors)[i];
  217.     HX_RELEASE(pBuf);
  218.     (*m_pErrors)[i] = NULL;
  219. }
  220. HX_DELETE(m_pErrors);
  221.     }
  222.     
  223.     if (m_pActiveNamespaceMap != NULL)
  224.     {
  225. CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
  226. for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
  227. {
  228.     IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
  229.     HX_RELEASE(pBuffer);
  230. }
  231. HX_DELETE(m_pActiveNamespaceMap);
  232.     }
  233.     if (m_pNSConflictList != NULL)
  234.     {
  235. CHXSimpleList::Iterator ndx = m_pNSConflictList->Begin();
  236. for (; ndx != m_pNSConflictList->End(); ++ndx)
  237. {
  238.     SMIL1Namespace* pNS = (SMIL1Namespace*)(*ndx);
  239.     HX_DELETE(pNS);
  240. }
  241. HX_DELETE(m_pNSConflictList);
  242.     }
  243.     HX_DELETE(m_pNodeDependencies);
  244.     HX_DELETE(m_pAnchorStack);
  245.     HX_VECTOR_DELETE(m_pEncoding);
  246.     if(m_pLanguagePreferenceList)
  247.     {
  248. CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
  249. for(; i != m_pLanguagePreferenceList->End(); ++i)
  250. {
  251.     char* pLang = (char*)(*i);
  252.     delete[] pLang;
  253. }
  254. HX_DELETE(m_pLanguagePreferenceList);
  255.     }
  256.     HX_DELETE(m_pOverdubOrCaptionPreference);
  257.     HX_DELETE(m_pBasePath);
  258.     close();
  259.     HX_RELEASE(m_pClassFactory);
  260.     HX_RELEASE(m_pContext);
  261.     HX_VECTOR_DELETE(m_pVarName);
  262.     HX_DELETE(m_pTimelineElementManager);
  263. }
  264. void
  265. CSmil1Parser::initRequireTags()
  266. {
  267.     //XXXBAB - add required tags here
  268. #if 0
  269.     m_pRequireTagsMap = new CHXMapStringToOb;
  270.     (*m_pRequireTagsMap)["foo-require"] = 0;
  271.     (*m_pRequireTagsMap)["boo-require"] = 0;
  272. #endif
  273. }
  274. void
  275. CSmil1Parser::getPreferences()
  276. {
  277.     IHXPreferences* pPrefs = 0;
  278.     IHXRegistry* pRegistry = NULL;
  279.     m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  280.     if(HXR_OK == m_pContext->QueryInterface(
  281. IID_IHXPreferences, (void**)&pPrefs))
  282.     {
  283. IHXBuffer* pBuf = 0;
  284. CHXString strTemp;
  285. strTemp.Format("%s.%s",HXREGISTRY_PREFPROPNAME,"Language");
  286. if(pRegistry && HXR_OK == pRegistry->GetStrByName(strTemp, pBuf))
  287. {
  288.     // language preference can be a comma-separated list
  289.     const char* pLang = (const char*)pBuf->GetBuffer();
  290.     // gonna call strtok, so copy the string...
  291.     char* pLangCopy = new_string(pLang);
  292.     m_pLanguagePreferenceList = new CHXSimpleList;
  293.     char* pTok = strtok(pLangCopy, ",");
  294.     while(pTok)
  295.     {
  296. char* pLangString = new_string(pTok);
  297. m_pLanguagePreferenceList->AddTail(pLangString);
  298. pTok = strtok(NULL, ",");
  299.     }
  300.     delete[] pLangCopy;
  301.     HX_RELEASE(pBuf);
  302. }
  303. if(HXR_OK == pPrefs->ReadPref("bandwidth", pBuf)  ||
  304. // /Fixes PR 84098 (SMIL 1.0 version) on Mac whose player
  305. // registry is case-sensitive and the registry value is
  306. // Bandwidth with a capital B:
  307. HXR_OK == pPrefs->ReadPref("Bandwidth", pBuf))
  308. {
  309.     m_ulBandwidthPreference = 
  310. (UINT32)atol((const char*)pBuf->GetBuffer());
  311.     HX_RELEASE(pBuf);
  312. }
  313. if(HXR_OK == pPrefs->ReadPref("screen_depth", pBuf))
  314. {
  315.     m_ulScreenDepthPreference =
  316. (UINT32)atol((const char*)pBuf->GetBuffer());
  317.     HX_RELEASE(pBuf);
  318. }
  319. if(HXR_OK == pPrefs->ReadPref("screen_height", pBuf))
  320. {
  321.     m_ulScreenHeightPreference =
  322. (UINT32)atol((const char*)pBuf->GetBuffer());
  323.     HX_RELEASE(pBuf);
  324. }
  325. if(HXR_OK == pPrefs->ReadPref("screen_width", pBuf))
  326. {
  327.     m_ulScreenWidthPreference =
  328. (UINT32)atol((const char*)pBuf->GetBuffer());
  329.     HX_RELEASE(pBuf);
  330. }
  331. if(HXR_OK == pPrefs->ReadPref("caption_switch", pBuf))
  332. {
  333.     m_bCaptionsPreference = 
  334. (UINT32)atol((const char*)pBuf->GetBuffer());
  335.     HX_RELEASE(pBuf);
  336. }
  337. if(HXR_OK == pPrefs->ReadPref("overdub_or_caption", pBuf))
  338. {
  339.     const char* pStr = (const char*)pBuf->GetBuffer();
  340.     m_pOverdubOrCaptionPreference = new_string(pStr);
  341.     HX_RELEASE(pBuf);
  342. }
  343. HX_RELEASE(pPrefs);
  344.     }
  345.     HX_RELEASE(pRegistry);
  346. }
  347. void
  348. CSmil1Parser::close()
  349. {
  350.     HX_DELETE(m_pPacketQueue);
  351.     HX_DELETE(m_pEndLayout);
  352.     HX_DELETE(m_pTrackHintList);
  353.     HX_RELEASE(m_pResponse);
  354.     HX_RELEASE(m_pErrorText);
  355.     if (m_pParser)
  356.     {
  357. m_pParser->Close();
  358. HX_RELEASE(m_pParser);
  359.     }
  360.     HX_RELEASE(m_pISystemRequired);
  361.     if(m_pIDMap)
  362.     {
  363. CHXMapStringToOb::Iterator i = m_pIDMap->Begin();
  364. for(; i != m_pIDMap->End(); ++i)
  365. {
  366.     SMIL1Node* pNode = (SMIL1Node*)(*i);
  367.     HX_DELETE(pNode->m_pElement);
  368. }
  369. HX_DELETE(m_pIDMap);
  370.     }
  371.     if(m_pAddGroupMap)
  372.     {
  373. CHXMapLongToObj::Iterator i = m_pAddGroupMap->Begin();
  374. for(; i != m_pAddGroupMap->End(); ++i)
  375. {
  376.     CSmil1AddGroup* pAddGroup = (CSmil1AddGroup*)(*i);
  377.     delete pAddGroup;
  378. }
  379. HX_DELETE(m_pAddGroupMap);
  380.     }
  381.     if(m_pSourceUpdateList)
  382.     {
  383. CHXSimpleList::Iterator i = m_pSourceUpdateList->Begin();
  384. for(; i != m_pSourceUpdateList->End(); ++i)
  385. {
  386.     CSmil1SourceUpdate* pUpdate = (CSmil1SourceUpdate*)(*i);
  387.     delete pUpdate;
  388. }
  389. HX_DELETE(m_pSourceUpdateList);
  390.     }
  391.     if (m_pActiveNamespaceMap)
  392.     {
  393. CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
  394. for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
  395. {
  396.     IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
  397.     HX_RELEASE(pBuffer);
  398. }
  399. HX_DELETE(m_pActiveNamespaceMap);
  400.     }
  401.     if (m_pNSConflictList != NULL)
  402.     {
  403. CHXSimpleList::Iterator ndx = m_pNSConflictList->Begin();
  404. for (; ndx != m_pNSConflictList->End(); ++ndx)
  405. {
  406.     SMIL1Namespace* pNS = (SMIL1Namespace*)(*ndx);
  407.     HX_DELETE(pNS);
  408. }
  409. HX_DELETE(m_pNSConflictList);
  410.     }
  411.     delete m_pNodeListStack;
  412.     if(m_pNodeList)
  413.     {
  414. delete m_pNodeList->m_pParentNode;
  415.     }
  416. }
  417. HX_RESULT
  418. CSmil1Parser::init(BOOL bStoreErrors)
  419. {
  420.     HX_RESULT rc = HXR_OK;
  421.     close();
  422.     m_pNodeListStack = new CHXStack;
  423.     m_pPacketQueue = new CHXSimpleList;
  424.     m_pIDMap = new CHXMapStringToOb;
  425.     m_pAddGroupMap = new CHXMapLongToObj;
  426.     m_bStoreErrors = bStoreErrors;
  427.     if (m_bStoreErrors)
  428.     {
  429. // XXXJHUG  error stuff.
  430. // In the future if there was any reason, we could 
  431. // store the errors in the nodes that the errors occurred in.
  432. // for now when we get an error notification, we will
  433. // just call the storeError function which will add
  434. // a new IHXBuffer to this array..  This will also be
  435. // called when problems are found with tags...
  436. // this will save having to walk the tree when it 
  437. // is time to dump the errors.
  438. m_pErrors = new CHXPtrArray;
  439.     }
  440.     SMIL1Node* pRootNode = new SMIL1Node;
  441.     pRootNode->m_id = "root";
  442.     pRootNode->m_name = "root";
  443.     m_pNodeList = new SMIL1NodeList;
  444.     pRootNode->m_pNodeList = m_pNodeList;
  445.     m_pNodeList->m_pParentNode = pRootNode;
  446.     m_pNodeListStack->Push(pRootNode);
  447. #ifdef USE_EXPAT_FOR_SMIL
  448.     rc = m_pClassFactory->CreateInstance(CLSID_IHXXMLParser, (void**)&m_pParser);
  449.     if (FAILED(rc))
  450.     {
  451. // they don't have the parser...  use old one?
  452. // Don't QI core for IID_IHXXMLParser; use our own instance.
  453. m_pParser = new HXXMLParser;
  454. if (m_pParser)
  455. {
  456.     rc = HXR_OK;
  457.     m_pParser->AddRef();
  458. }
  459. else
  460. {
  461.     rc = HXR_OUTOFMEMORY;
  462. }
  463.     }
  464.     HX_RELEASE(pFact);
  465.     if (SUCCEEDED(rc))
  466.     {
  467. m_pResponse = new CSmil1ParserResponse(this);
  468. m_pResponse->AddRef();
  469. // Expat is created off the CCF.
  470. // In strict mode it requires 100% compliant XML.   We will
  471. // create a "loose" version that allows &'s in attribute values.
  472. // (this parser is still MUCH stricter than the original XML parser)
  473. rc = m_pParser->Init(m_pResponse, "iso-8859-1", FALSE);
  474.     }
  475. #else
  476.     // Don't QI core for IID_IHXXMLParser; use our own instance.
  477.     HXXMLParser* parser = new HXXMLParser();
  478.     if (parser)
  479.     {
  480. parser->AddRef();
  481.     }
  482.     else
  483.     {
  484. rc = HXR_OUTOFMEMORY;
  485.     }
  486.     
  487.     if (SUCCEEDED(rc))
  488.     {
  489. m_pResponse = new CSmil1ParserResponse(this);
  490. m_pResponse->AddRef();
  491. rc = parser->Init(m_pResponse, NULL, TRUE); // strict parser
  492.     }
  493.     if (m_bStoreErrors && parser)
  494.     {
  495. parser->InitErrorNotifier(m_pResponse);
  496.     }
  497.     m_pParser = (IHXXMLParser*)parser;
  498. #endif
  499.     
  500.     return rc;
  501. }
  502. HX_RESULT
  503. CSmil1Parser::parse(IHXBuffer* pBuffer, BOOL bIsFinal)
  504. {
  505.     HX_RESULT rc = HXR_OK;
  506.     rc = m_pParser->Parse(pBuffer, bIsFinal);
  507.     if(HXR_OK != rc)
  508.     {
  509. m_pParser->GetCurrentLineNumber(m_ulErrorLineNumber);
  510. m_pParser->GetCurrentColumnNumber(m_ulErrorColumnNumber);
  511. HX_RELEASE(m_pErrorText);
  512. m_pParser->GetCurrentErrorText(m_pErrorText);
  513.     }
  514.     return rc;
  515. }
  516. HX_RESULT
  517. CSmil1Parser::durationResolved(const char* pID, UINT32 ulDuration)
  518. {
  519.     SMIL1Node* pNode = NULL;
  520.     IHXBuffer* pBuf = NULL;
  521.     if(m_pIDMap->Lookup(pID, (void*&)pNode))
  522.     {
  523. if (pNode->m_pElement->m_bIndefiniteDuration)
  524. {
  525.     goto cleanup;
  526. }
  527. // add duration to parent element
  528. if(pNode &&
  529.    pNode->m_pElement &&
  530.    pNode->m_pElement->m_pTimelineElement)
  531. {
  532.     pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration);
  533. }
  534.     }
  535. cleanup:
  536.     HX_RELEASE(pBuf);
  537.     return HXR_OK;
  538. }
  539. BOOL AncestorEventsAreResolved(SMIL1Node* pNode)
  540. {
  541.     if (!pNode  ||  !pNode->m_pElement  ||
  542.     !pNode->m_pElement->m_pTimelineElement  ||  pNode->m_tag == SMILBody)
  543.     {
  544. return TRUE;
  545.     }
  546.     //Now, look to see if its duration and delay events, if any, are
  547.     // resolved:
  548.     if ( ( (pNode->m_pElement->m_pTimelineElement->durationEvent()  &&
  549. !pNode->m_pElement->m_pTimelineElement->durationSet())  ||
  550. (pNode->m_pElement->m_pTimelineElement->delayEvent()  &&
  551. !pNode->m_pElement->m_pTimelineElement->initialDelaySet()) )  &&
  552. //[SMIL 1.0 compliance] Helps fix PR 32578:
  553. //However, if we have a duration event and it's based on a child's
  554. // timing (as can happen via endsync="id(child)", then we want to
  555. // avoid this element waiting for its parent to be resolved while
  556. // the parent is waiting for this element to be resolved:
  557. (!pNode->m_pElement->m_pTimelineElement->durationEvent()  ||
  558. SMILEventSourceID != pNode->m_pElement->m_nEndsyncEventSourceTag) )
  559.     {
  560. return FALSE; //We still need to await event resolution.
  561.     }
  562.     //pNode is ok but its dependency ancestors may still be unresolved and
  563.     // thus pNode may still have timing constraints from its dependency
  564.     // ancestors due to their unresolved event(s):
  565.     return AncestorEventsAreResolved(pNode->m_pParent);
  566. }
  567. void
  568. CSmil1Parser::insertTimelineElement(const char* pID, UINT32 ulDelay)
  569. {
  570.     SMIL1Node* pNode = 0;
  571.     if(m_pIDMap->Lookup(pID, (void*&)pNode))
  572.     {
  573. if(pNode &&
  574.     pNode->m_pElement &&
  575.     !pNode->m_pElement->m_bInsertedIntoTimeline  &&
  576.     //[SMIL 1.0 compliance] Helps fix PR 16629:
  577.     // We don't want to insert a node into the timeline if
  578.     // its begin or end is dependent on another (not-yet-
  579.     // resolved) element:
  580.     ( (!pNode->m_pElement->m_pTimelineElement->durationEvent()  ||
  581.     pNode->m_pElement->m_pTimelineElement->durationSet())  &&
  582.     (!pNode->m_pElement->m_pTimelineElement->delayEvent()  ||
  583.     pNode->m_pElement->m_pTimelineElement->initialDelaySet()) )
  584.     //[SMIL 1.0 compliance] Helps fix 14420:
  585.     // First, we need to look all the way up the tree of ancestors
  586.     // to see if any of them have event-based delays or durations
  587.     // and to make sure the appropriate time(s) are resolved.  If
  588.     // not, we'll have to await those event resolutions before
  589.     // inserting this element into the timeline:
  590.     &&  AncestorEventsAreResolved(pNode)
  591.     )
  592. {
  593.     // /[SMIL 1.0 Compliance] Fixes PR 27644:
  594.     // if our begin offset is same or greater than our parent's
  595.     // end offset, then we should be ignored:
  596.     if ( pNode->m_pParent  &&  pNode->m_pParent->m_pElement  &&
  597.     pNode->m_pElement->m_ulBeginOffset != ((UINT32)-1)  &&
  598.     pNode->m_pParent->m_pElement->m_ulEndOffset != 
  599.     ((UINT32)-1)  &&
  600.     (pNode->m_pElement->m_ulBeginOffset >
  601.     pNode->m_pParent->m_pElement->m_ulEndOffset) )
  602.     {
  603. return; //Don't insert this because it can't ever play.
  604.     }
  605.     // skip the element if its duration == 0
  606.     if (0 == pNode->m_pElement->m_ulDuration)
  607.     {
  608. durationResolved(pNode->m_id, 0);
  609.     }
  610.     else
  611.     {
  612. pNode->m_pElement->m_ulDelay = ulDelay;
  613. pNode->m_pElement->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
  614. pNode->m_pElement->m_bInsertedIntoTimeline = TRUE;
  615. insertElementByTimestamp(pNode->m_pElement);
  616.     }
  617. }
  618.     }
  619. }
  620. void
  621. CSmil1Parser::resetTimelineElementDuration(const char* pID, 
  622.   UINT32 ulDuration)
  623. {
  624.     SMIL1Node* pNode = NULL;
  625.     if(m_pIDMap->Lookup(pID, (void*&)pNode))
  626.     {
  627. CSmil1SourceUpdate* pUpdate = new CSmil1SourceUpdate;
  628. pUpdate->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
  629. pUpdate->m_srcID = pID;
  630. pUpdate->m_ulUpdatedDuration = ulDuration;
  631. if(!m_pSourceUpdateList)
  632. {
  633.     m_pSourceUpdateList = new CHXSimpleList;
  634. }
  635. m_pSourceUpdateList->AddTail(pUpdate);
  636. insertElementByTimestamp(pUpdate);
  637.     }
  638. }
  639. CSmil1Element*
  640. CSmil1Parser::findElement(const char* pID)
  641. {
  642.     SMIL1Node* pNode = NULL;
  643.     if(m_pIDMap->Lookup(pID, (void*&)pNode))
  644.     {
  645. return pNode->m_pElement;
  646.     }
  647.     return NULL;
  648. }
  649. const char*
  650. CSmil1Parser::assignID(const char* pPrefix)
  651. {
  652.     SafeSprintf(m_pVarName, 256, "%s_%ld", pPrefix, GetUniqueNumber());
  653.     return m_pVarName;
  654. }
  655. UINT16
  656. CSmil1Parser::getFragmentGroup(const char* pFragment)
  657. {
  658.     if(pFragment)
  659.     {
  660. SMIL1Node* pNode = 0;
  661. if(m_pIDMap->Lookup(pFragment, (void*&)pNode))
  662. {
  663.     if(!pNode->m_bDelete)
  664.     {
  665. if(pNode->m_tag == SMILAAnchor ||
  666.     pNode->m_tag == SMILSwitch)
  667. {
  668.     SMIL1Node* pChildNode = getTimelineDescendent(pNode, NULL);
  669.     while(pChildNode)
  670.     {
  671. if(!pChildNode->m_bDelete)
  672. {
  673.     return pChildNode->m_nGroup;
  674. }
  675. pChildNode = getTimelineDescendent(pNode, pChildNode);
  676.     }
  677. }
  678. else if(pNode->m_tag == SMILAnchor)
  679. {
  680.     SMIL1Node* pParentNode = pNode->m_pParent;
  681.     if(pParentNode &&
  682. !pParentNode->m_bDelete)
  683.     {
  684. return pParentNode->m_nGroup;
  685.     }
  686. }
  687. else
  688. {
  689.     return pNode->m_nGroup;
  690. }
  691.     }
  692. }
  693.     }
  694.     return 0;
  695. }
  696. UINT32
  697. CSmil1Parser::getFragmentOffset(const char* pFragment,
  698. //This BOOL will be set to FALSE if the fragment
  699. // does not exist or does not yet have a resolved
  700. // begin time.  This was necessary to fix PR 22655:
  701. BOOL& bFragFoundAndResolved)
  702. {
  703.     bFragFoundAndResolved = FALSE;
  704.     if(pFragment)
  705.     {
  706. UINT32 ulAnchorBegin = 0;
  707. SMIL1Node* pNode = NULL;
  708. CSmil1Element* pElement = NULL;
  709. CSmil1Element* pActualElement = NULL;
  710. if(m_pIDMap->Lookup(pFragment, (void*&)pNode) &&
  711.     pNode->m_pElement)
  712. {
  713.     pElement = pNode->m_pElement;
  714.     if(pNode->m_tag == SMILSwitch ||
  715. pNode->m_tag == SMILAAnchor)
  716.     {
  717. SMIL1Node* pChildNode = getTimelineDescendent(
  718.     pNode, NULL);
  719. while(pChildNode)
  720. {
  721.     if(!pChildNode->m_bDelete)
  722.     {
  723. pActualElement = pChildNode->m_pElement;
  724. break;
  725.     }
  726.     pChildNode = getTimelineDescendent(
  727. pNode, pChildNode);
  728. }
  729.     }
  730.     else if(pNode->m_tag == SMILAnchor)
  731.     {
  732. if(pElement->m_ulBeginOffset != (UINT32)-1)
  733. {
  734.     ulAnchorBegin = pElement->m_ulBeginOffset;
  735. }
  736. SMIL1Node* pParent = pNode->m_pParent;
  737. if(pParent)
  738. {
  739.     pActualElement = pParent->m_pElement;
  740. }
  741.     }
  742.     else
  743.     {
  744. pActualElement = pElement;
  745.     }
  746.     if(pActualElement)
  747.     {
  748. //[SMIL 1.0 Compliance] Fixes PR 26464:
  749. // Use delay (which already includes begin offset)
  750. // if it's a valid value, else use begin offset
  751. // without delay added (see comment below):
  752. if(pActualElement->m_ulDelay != (UINT32)-1)
  753. {
  754.     bFragFoundAndResolved = TRUE;
  755.     return pActualElement->m_ulDelay +
  756. ulAnchorBegin;
  757. }
  758. else if(pActualElement->m_ulBeginOffset != (UINT32)-1)
  759.     bFragFoundAndResolved = TRUE; 
  760.     //Changed this while fixing PR 26464:
  761.     // This used to return pActualElement->m_ulDelay +
  762.     // pActualElement->m_ulBeginOffset + ulAnchorBegin but
  763.     // the delay can already account for the begin if both
  764.     // are set so we'd end up seeking past where we were
  765.     // supposed to go by the amount of the begin offset. 
  766.     // Also, we weren't even checking to see
  767.     // if delay was valid before using it (and now we're
  768.     // sure it is invalid per check above): 
  769.     return pActualElement->m_ulBeginOffset +
  770. ulAnchorBegin; 
  771. else
  772. {
  773.     return 0;
  774. }
  775.     }
  776. }
  777.     }
  778.     return 0;
  779. }
  780. SMIL1Node*
  781. CSmil1Parser::findFirstNode(SMIL1NodeList* pNodeList, SMIL1NodeTag tag)
  782. {
  783.     if(!pNodeList)
  784.     {
  785. return 0;
  786.     }
  787.     SMIL1Node* pFoundNode = 0;
  788.     CHXSimpleList::Iterator i;
  789.     for(i=pNodeList->Begin();i!=pNodeList->End();++i)
  790.     {
  791. SMIL1Node* pNode = (SMIL1Node*)(*i);
  792. if(pNode->m_tag == tag)
  793. {
  794.     pFoundNode = pNode;
  795. }
  796. else
  797. {
  798.     pFoundNode = findFirstNode(pNode->m_pNodeList, tag);
  799. }
  800. if(pFoundNode)
  801. {
  802.     break;
  803. }
  804.     }
  805.     return pFoundNode;
  806. }
  807. SMIL1Node*
  808. CSmil1Parser::findFirstNode(SMIL1NodeTag tag)
  809. {
  810.     return findFirstNode(m_pNodeList, tag);
  811. }
  812. SMIL1Node*
  813. CSmil1Parser::getFirstNodeChild(SMIL1Node* pNode)
  814. {
  815.     m_pCurNode = pNode;
  816.     if(!m_pCurNode)
  817.     {
  818. return 0;
  819.     }
  820.    return m_pCurNode->getFirstChild();
  821. }
  822. SMIL1Node*
  823. CSmil1Parser::getNextNodeChild()
  824. {
  825.     if(!m_pCurNode)
  826.     {
  827. return 0;
  828.     }
  829.     return m_pCurNode->getNextChild();
  830. }
  831. HX_RESULT
  832. CSmil1Parser::parseClockValue(const char* pValue, UINT32& ulTimeValue)
  833. {
  834.     // try npt
  835.     char* pPtr = (char *)strstr(pValue, "npt=");
  836.     if(pPtr)
  837.     {
  838. pPtr += 4;  // point to beginning of clock value
  839. //[SMIL 1.0 compliance] fixes PR 26445: if "npt=4h" is specified,
  840. // we need to convert to "14400s" otherwise the 4 is treated as
  841. // seconds:
  842. char* pHourChar = strchr(pPtr, 'h');
  843. if (pHourChar  &&  !strchr(pPtr, ':')) //then it's hours without ':'
  844. {
  845.     IHXBuffer* pBuf = new CHXBuffer;
  846.     if (pBuf)
  847.     {
  848. pBuf->AddRef();
  849. *pHourChar = ''; //get rid of the 'h' in pPtr.
  850. pBuf->Set((const unsigned char *)pPtr,
  851.     strlen(pPtr) + strlen(":00:00") + 1);
  852. char* pTmp = (char*)pBuf->GetBuffer();
  853. strcat(pTmp, ":00:00"); /* Flawfinder: ignore */
  854. NPTime clockTime((const char*)pTmp);
  855. ulTimeValue = (UINT32)clockTime;
  856. pBuf->Release();
  857.     }
  858.     else
  859.     {
  860. return HXR_OUTOFMEMORY;
  861.     }
  862. }
  863. //END fix for PR 26445.
  864. else
  865. {
  866.     NPTime clockTime(pPtr);
  867.     ulTimeValue = (UINT32)clockTime;
  868. }
  869. return HXR_OK;
  870.     }
  871.     // try smpte
  872.     pPtr = (char *)strstr(pValue, "smpte=");
  873.     if(pPtr)
  874.     {
  875. pPtr += 6;  // point to beginning of clock value
  876. SMPTETimeCode clockTime(pPtr);
  877. ulTimeValue = (UINT32)clockTime;
  878. return HXR_OK;
  879.     }
  880.     pPtr = (char *)strstr(pValue, "smpte-30-drop=");
  881.     if(pPtr)
  882.     {
  883. pPtr += 14;  // point to beginning of clock value
  884. SMPTETimeCode clockTime(pPtr);
  885. ulTimeValue = (UINT32)clockTime;
  886. return HXR_OK;
  887.     }
  888.     pPtr = (char *)strstr(pValue, "smpte-25=");
  889.     if(pPtr)
  890.     {
  891. pPtr += 9;  // point to beginning of clock value
  892. SMPTETimeCode clockTime;
  893.         clockTime.m_framesPerSec = SMPTETimeCode::FPS_25;
  894.         clockTime.fromString(pPtr);
  895. ulTimeValue = (UINT32)clockTime;
  896. return HXR_OK;
  897.     }
  898.     else if(strchr(pValue, ':'))     // try just hh:mm:ss with no prefix/suffix
  899.     {
  900. NPTime clockTime(pValue);
  901. ulTimeValue = (UINT32)clockTime;
  902. return HXR_OK;
  903.     }
  904.     // ok, try h/min/s/ms
  905.     char* pEndPtr = 0;
  906.     double dVal = strtod(pValue, &pEndPtr);
  907.     if(strcmp(pEndPtr, "h") == 0)
  908.     {
  909. ulTimeValue = (UINT32)(dVal * 60.0 * 60.0 * 1000.0);
  910. return HXR_OK;
  911.     }
  912.     else if(strcmp(pEndPtr, "min") == 0)
  913.     {
  914. ulTimeValue = (UINT32)(dVal * 60.0 * 1000.0);
  915. return HXR_OK;
  916.     }
  917.     else if(strcmp(pEndPtr, "s") == 0  ||
  918.     //[SMIL 1.0 compliance] Fixes PR 22673: the SMIL doc says that we
  919.     // need to default to seconds if no unit-type is given:
  920.     //     Timecount-val         ::= Timecount ("." Fraction)?
  921.     //              ("h" | "min" | "s" | "ms")? ; default is "s"
  922.     (!strlen(pEndPtr)) )
  923.     {
  924. ulTimeValue = (UINT32)(dVal * 1000.0);
  925. return HXR_OK;
  926.     }
  927.     else if(strcmp(pEndPtr, "ms") == 0)
  928.     {
  929. ulTimeValue = (UINT32)(dVal);
  930. return HXR_OK;
  931.     }
  932.     //else something other than "h", "min", "s", "", or "ms" was specified:
  933.     else
  934.     {
  935. return HXR_FAIL;
  936.     }
  937. }
  938. HX_RESULT
  939. CSmil1Parser::parseAnchorCoords(const char* pCoords, CSmil1AnchorElement* pAnchor)
  940. {
  941.     HX_RESULT rc = HXR_OK;
  942.     double coordArray[4];
  943.     BOOL percentArray[4];
  944.     int i = 0;
  945.     for(i=0; i<4; ++i)
  946.     {
  947. coordArray[i] = 0.0;
  948. percentArray[i] = FALSE;
  949.     }
  950.     char* pCoordCopy = new_string(pCoords);
  951.     char* pTok = strtok(pCoordCopy, ",");
  952.     for(i=0;i<4,pTok;++i)
  953.     {
  954. char* pEndPtr = 0;
  955. double dVal = strtod(pTok, &pEndPtr);
  956. coordArray[i] = dVal;
  957. percentArray[i] = (*pEndPtr == '%') ? TRUE: FALSE;
  958. pTok = strtok(NULL, ",");
  959.     }
  960.     delete[] pCoordCopy;
  961.     pAnchor->m_ulOriginalLeftX = pAnchor->m_ulLeftX = 
  962. (UINT32)coordArray[0];
  963.     pAnchor->m_bLeftXIsPercent = percentArray[0];
  964.     pAnchor->m_ulOriginalTopY = pAnchor->m_ulTopY = 
  965. (UINT32)coordArray[1];
  966.     pAnchor->m_bTopYIsPercent = percentArray[1];
  967.     pAnchor->m_ulOriginalRightX = pAnchor->m_ulRightX = 
  968. (UINT32)coordArray[2];
  969.     pAnchor->m_bRightXIsPercent = percentArray[2];
  970.     pAnchor->m_ulOriginalBottomY = pAnchor->m_ulBottomY = 
  971. (UINT32)coordArray[3];
  972.     pAnchor->m_bBottomYIsPercent = percentArray[3];
  973.     
  974.     pAnchor->m_bCoordsSet = TRUE;
  975.     return rc;
  976. }
  977. HX_RESULT
  978. CSmil1Parser::parseDuration(const char* pDuration, CSmil1Element* pElement,
  979.     SMILSyncAttributeTag nTag)
  980. {
  981.     HX_RESULT rc = HXR_OK;
  982.     if(!pDuration)
  983.     {
  984. return HXR_FAIL;
  985.     }
  986.     const char* pCh = pDuration;
  987.     // check for event-source
  988.     // syntax is: id(a)(4s)
  989.     if(strncmp(pCh, "id(", 3) == 0)
  990.     {
  991. BOOL bParseError = FALSE;
  992. BOOL bHasEvent = TRUE;
  993. UINT32 clockValue = 0;
  994. char* pIdTag = new char[strlen(pDuration)+1];
  995. char* pEvent = new char[strlen(pDuration)+1];
  996. pIdTag[0] = 0;
  997. pEvent[0] = 0;
  998. pCh += 3; // skip over 'id('
  999. int i = 0;
  1000. while(*pCh && (*pCh != ')'))
  1001. {
  1002.     pIdTag[i++] = *pCh++;
  1003. }
  1004. if(*pCh == ')')
  1005. {
  1006.     pIdTag[i] = 0;
  1007.     // lookup ID to see if it references an existing entity,
  1008.     // otherwise it is an error
  1009.     void* pDummy = NULL;
  1010.     if(!m_pIDMap->Lookup(pIdTag, pDummy))
  1011.     {
  1012. rc = HXR_FAIL;
  1013. CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1014. errHandler.ReportError(SMILErrorBadDuration, pDuration, 
  1015.     pElement->m_pNode->m_ulTagStartLine);
  1016. bParseError = TRUE;
  1017.     }
  1018.     else
  1019.     {
  1020. switch(nTag)
  1021. {
  1022.     case SMILSyncAttrBegin:
  1023.     {
  1024. pElement->m_BeginEventSourceID = pIdTag;
  1025.     }
  1026.     break;
  1027.     case SMILSyncAttrEnd:
  1028.     {
  1029. pElement->m_EndEventSourceID = pIdTag;
  1030.     }
  1031.     break;
  1032.     case SMILSyncAttrEndsync:
  1033.     {
  1034. pElement->m_EndsyncEventSourceID = pIdTag;
  1035.     }
  1036.     break;
  1037.     default:
  1038.     break;
  1039. }
  1040.     }
  1041.     delete[] pIdTag;
  1042.     if(strlen(pCh) > 2)
  1043.     {
  1044. if(nTag != SMILSyncAttrEndsync)
  1045. {
  1046.     pCh++; // skip over ')'
  1047.     pCh++;  // skip over '('
  1048.     i = 0;
  1049.     while(*pCh && (*pCh != ')'))
  1050.     {
  1051. pEvent[i++] = *pCh++;
  1052.     }
  1053.     if(*pCh == ')')
  1054.     {
  1055. pEvent[i] = 0;
  1056.     }
  1057.     else
  1058.     {
  1059. bParseError = TRUE;
  1060.     }
  1061. }
  1062. else
  1063. {
  1064.     bParseError = TRUE;
  1065. }
  1066.     }
  1067.     else
  1068.     {
  1069. if(nTag == SMILSyncAttrEndsync)
  1070. {
  1071.     pElement->m_nEndsyncEventSourceTag = SMILEventSourceID;
  1072.     bHasEvent = FALSE;
  1073. }
  1074. else
  1075. {
  1076.     bParseError = TRUE;
  1077. }
  1078.     }
  1079. }
  1080. else
  1081. {
  1082.     bParseError = TRUE;
  1083. }
  1084. if(bParseError)
  1085. {
  1086.     rc = HXR_FAIL;
  1087.     CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1088.     errHandler.ReportError(SMILErrorBadDuration, pDuration, 
  1089. pElement->m_pNode->m_ulTagStartLine);
  1090. }
  1091. else if(bHasEvent)
  1092. {
  1093.     SMILEventSourceTag eSourceTag = SMILEventSourceNone;
  1094.     UINT32 ulEventClockValue = 0;
  1095.     if(strcmp(pEvent, "begin") == 0)
  1096.     {
  1097. eSourceTag = SMILEventSourceBegin;
  1098.     }
  1099.     else if(strcmp(pEvent, "end") == 0)
  1100.     {
  1101. eSourceTag = SMILEventSourceEnd;
  1102.     }
  1103.     else
  1104.     {
  1105. if(HXR_OK == parseClockValue(pEvent, ulEventClockValue))
  1106. {
  1107.     eSourceTag = SMILEventSourceClock;
  1108. }
  1109. else
  1110. {
  1111.     rc = HXR_FAIL;
  1112.     CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1113.     errHandler.ReportError(SMILErrorBadDuration, pDuration, 
  1114. pElement->m_pNode->m_ulTagStartLine);
  1115. }
  1116.     }
  1117.     switch(nTag)
  1118.     {
  1119. case SMILSyncAttrBegin:
  1120. {
  1121.     pElement->m_nBeginEventSourceTag = eSourceTag;
  1122.     pElement->m_ulBeginEventClockValue = ulEventClockValue;
  1123. }
  1124. break;
  1125. case SMILSyncAttrEnd:
  1126. {
  1127.     pElement->m_nEndEventSourceTag = eSourceTag;
  1128.     pElement->m_ulEndEventClockValue = ulEventClockValue;
  1129. }
  1130. break;
  1131. case SMILSyncAttrEndsync:
  1132. {
  1133.     pElement->m_nEndsyncEventSourceTag = eSourceTag;
  1134. }
  1135. break;
  1136. default:
  1137. break;
  1138.     }
  1139. }
  1140. delete[] pEvent;
  1141.     }
  1142.     else if(strcmp(pCh, "first") == 0)
  1143.     {
  1144. if(nTag == SMILSyncAttrEndsync)
  1145. {
  1146.     pElement->m_nEndsyncEventSourceTag = SMILEventSourceFirst;
  1147. }
  1148.     }
  1149.     else if(strcmp(pCh, "last") == 0)
  1150.     {
  1151. if(nTag == SMILSyncAttrEndsync)
  1152. {
  1153.     pElement->m_nEndsyncEventSourceTag = SMILEventSourceLast;
  1154. }
  1155.     }
  1156.     else if(strcmp(pCh, "indefinite") == 0)
  1157.     {
  1158. if (pElement->m_pNode->m_tag == SMILSeq || 
  1159.     pElement->m_pNode->m_tag == SMILPar)
  1160. {
  1161.     rc = HXR_FAIL;
  1162.     CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1163.     errHandler.ReportError(SMILErrorIndefiniteNotSupported, NULL, 
  1164. pElement->m_pNode->m_ulTagStartLine);
  1165. }
  1166. else
  1167. {
  1168.     pElement->m_bIndefiniteDuration = TRUE;
  1169. }
  1170.     }
  1171.     else
  1172.     {
  1173. UINT32 ulClockValue = 0;
  1174. if(HXR_OK == parseClockValue(pCh, ulClockValue))
  1175. {
  1176.     switch(nTag)
  1177.     {
  1178. case SMILSyncAttrBegin:
  1179. {
  1180.     pElement->m_ulBeginOffset = ulClockValue;
  1181. }
  1182. break;
  1183. case SMILSyncAttrEnd:
  1184. {
  1185.     pElement->m_ulEndOffset = ulClockValue;
  1186. }
  1187. break;
  1188. case SMILSyncAttrDur:
  1189. {
  1190.     pElement->m_ulDuration = ulClockValue;
  1191. }
  1192. break;
  1193. case SMILSyncAttrEndsync:
  1194. {
  1195.     pElement->m_ulEndSync = ulClockValue;
  1196. }
  1197. break;
  1198. case SMILSyncAttrClipBegin:
  1199. {
  1200.     pElement->m_ulClipBegin = ulClockValue;
  1201. }
  1202. break;
  1203. case SMILSyncAttrClipEnd:
  1204. {
  1205.     pElement->m_ulClipEnd = ulClockValue;
  1206. }
  1207. break;
  1208.     
  1209. default:
  1210. break;
  1211.     }
  1212. }
  1213. else
  1214. {
  1215.     rc = HXR_FAIL;
  1216.     CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1217.     errHandler.ReportError(SMILErrorBadDuration, pCh, 
  1218. pElement->m_pNode->m_ulTagStartLine);
  1219. }
  1220.     }
  1221.     return rc;
  1222. }
  1223. HX_RESULT
  1224. CSmil1Parser::adjustDuration(CSmil1Element* pElement)
  1225. {
  1226.     HX_RESULT rc = HXR_OK;
  1227.     // check for duration errors
  1228.     if(pElement->m_ulEndOffset != (UINT32)-1)
  1229.     {
  1230. if(pElement->m_ulBeginOffset != (UINT32)-1)
  1231. {
  1232.     if(pElement->m_ulEndOffset < 
  1233. pElement->m_ulBeginOffset)
  1234.     {
  1235. pElement->m_ulDuration = 0;
  1236. goto exit;
  1237.     }
  1238.     if(pElement->m_ulDuration != (UINT32)-1)
  1239.     {
  1240. if(pElement->m_ulDuration !=
  1241.     pElement->m_ulEndOffset -
  1242.     pElement->m_ulBeginOffset)
  1243. {
  1244.     // If the element has both an explicit dur and an explicit
  1245.     // end, the desired end is the minimum of: the sum of the 
  1246.     // desired begin and the explicit dur; and the explicit end. 
  1247.     
  1248.     // override "dur"
  1249.     if ( pElement->m_ulBeginOffset + pElement->m_ulDuration > 
  1250. pElement->m_ulEndOffset )
  1251.     {
  1252. // we want to override the duration, because it is 
  1253. // greater than the end offset.
  1254. pElement->m_ulDuration =
  1255.     pElement->m_ulEndOffset -
  1256.     pElement->m_ulBeginOffset;
  1257.     }
  1258.     else
  1259.     {
  1260. // else we want to use the current duration, 
  1261. // and override the end offset.
  1262. pElement->m_ulEndOffset = pElement->m_ulBeginOffset
  1263.     + pElement->m_ulDuration;
  1264.     }
  1265.     goto exit;
  1266. }
  1267.     }
  1268. }
  1269. else
  1270. {
  1271.     if(pElement->m_ulDuration != (UINT32)-1)
  1272.     {
  1273. if(pElement->m_ulEndOffset >
  1274.     pElement->m_ulDuration)
  1275. {
  1276.     pElement->m_ulDuration = pElement->m_ulEndOffset;
  1277.     goto exit;
  1278. }
  1279.     }
  1280. }
  1281.     }
  1282.    
  1283.     // adjust for begin/end/dur attributes
  1284.     if(pElement->m_ulDuration == (UINT32)-1) // duration not set
  1285.     {
  1286. if(pElement->m_ulEndOffset != (UINT32)-1)
  1287. {
  1288.     // has an end but no duration
  1289.     if(pElement->m_ulBeginOffset != (UINT32)-1)
  1290.     {
  1291. pElement->m_ulDuration = pElement->m_ulEndOffset -
  1292. pElement->m_ulBeginOffset;
  1293.     }
  1294.     else
  1295.     {
  1296. pElement->m_ulDuration = pElement->m_ulEndOffset;
  1297.     }
  1298. }
  1299.     }
  1300.     else    // explicit duration set
  1301.     {
  1302. if(pElement->m_ulEndOffset != (UINT32)-1)
  1303. {
  1304.     // has a duration and an end
  1305.     UINT32 ulDur = 0;
  1306.     if(pElement->m_ulBeginOffset != (UINT32)-1)
  1307.     {
  1308. ulDur = pElement->m_ulEndOffset - 
  1309.          pElement->m_ulBeginOffset;
  1310.     }
  1311.     else
  1312.     {
  1313. ulDur = pElement->m_ulEndOffset;
  1314.     }
  1315.     pElement->m_ulDuration = ulDur;
  1316. }
  1317.     }
  1318. exit:
  1319.     return rc;
  1320. }
  1321. UINT8
  1322. CSmil1Parser::getColorElement(const char* pColorFrag, int len)
  1323. {
  1324.     UINT8 ucValue = 0;
  1325.     char* pTmpBuf = new char[len+1];
  1326.     strncpy(pTmpBuf, pColorFrag, len); /* Flawfinder: ignore */
  1327.     pTmpBuf[len] = 0;
  1328.     ucValue = (UINT8)strtol(pTmpBuf, 0, 16);
  1329.     delete[] pTmpBuf;
  1330.     return ucValue;
  1331. }
  1332.     
  1333. HXxColor
  1334. CSmil1Parser::parseColor(const char* pColorString)
  1335. {
  1336.     HXxColor theColor = 0;
  1337.     UINT8 ucRed = 0;
  1338.     UINT8 ucGreen = 0;
  1339.     UINT8 ucBlue = 0;
  1340.     if(pColorString[0] == '#')
  1341.     {
  1342. if(strlen(pColorString) == 4)
  1343. {
  1344.     /* #rgb, duplicate the numbers */
  1345.     char tmpBuf[6]; /* Flawfinder: ignore */
  1346.     tmpBuf[0] = tmpBuf[1] = pColorString[1];
  1347.     tmpBuf[2] = tmpBuf[3] = pColorString[2];
  1348.     tmpBuf[4] = tmpBuf[5] = pColorString[3];
  1349.     ucRed = getColorElement(&tmpBuf[0], 2);
  1350.     ucGreen = getColorElement(&tmpBuf[2], 2);
  1351.     ucBlue = getColorElement(&tmpBuf[4], 2);
  1352. }
  1353. else if(strlen(pColorString) == 7)
  1354. {
  1355.     /* #rrggbb */
  1356.     ucRed = getColorElement(&pColorString[1], 2);
  1357.     ucGreen = getColorElement(&pColorString[3], 2);
  1358.     ucBlue = getColorElement(&pColorString[5], 2);
  1359. }
  1360.     }
  1361.     else
  1362.     {
  1363. // string, try to get it from the color table
  1364. int i = 0;
  1365. const char* pColorName = Smil1ColorTable[i].m_pColorName;
  1366. while(pColorName)
  1367. {
  1368.     if(strcmp(pColorName, pColorString) == 0)
  1369.     {
  1370. ucRed = Smil1ColorTable[i].m_ucRed;
  1371. ucBlue = Smil1ColorTable[i].m_ucBlue;
  1372. ucGreen = Smil1ColorTable[i].m_ucGreen;
  1373. break;
  1374.     }
  1375.     pColorName = Smil1ColorTable[++i].m_pColorName;
  1376. }
  1377.     }
  1378. #ifdef _WINDOWS
  1379.     theColor = (HXxColor)(RGB(ucRed, ucGreen, ucBlue));
  1380. #else
  1381.     theColor = (HXxColor)
  1382.     (ucRed << 16 |
  1383.     ucGreen << 8 |
  1384.     ucBlue);
  1385. #endif
  1386.     return theColor;
  1387. }
  1388. void
  1389. CSmil1Parser::badAttributeError(SMIL1NodeTag tag, const char* pAttrName,
  1390.        UINT32 ulLineNumber, BOOL bJustStore)
  1391. {
  1392.     const char* pTagName = "unknown";
  1393.     // get tag name from table
  1394.     int i = 0;
  1395.     SMIL1NodeTag thisTag = smil1TagTable[i].m_tag;
  1396.     while(thisTag != SMILUnknown)
  1397.     {
  1398. if(thisTag == tag)
  1399. {
  1400.     pTagName = smil1TagTable[i].m_name;
  1401.     break;
  1402. }
  1403. ++i;
  1404. thisTag = smil1TagTable[i].m_tag;
  1405.     }
  1406.     
  1407.     char tmpBuf[256]; /* Flawfinder: ignore */
  1408.     SafeSprintf(tmpBuf, 256, "<%s>: %s",
  1409. pTagName, pAttrName);
  1410.     if (m_bStoreErrors)
  1411.     {
  1412. storeError(SMILErrorUnrecognizedAttribute, tmpBuf, 0, 
  1413.     ulLineNumber, 0, FALSE);
  1414.     }
  1415.     if (!bJustStore)
  1416.     {
  1417. CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1418. errHandler.ReportError(SMILErrorUnrecognizedAttribute, tmpBuf, ulLineNumber);
  1419.     }
  1420. }
  1421. CSmil1Meta*
  1422. CSmil1Parser::makeMeta(SMIL1Node* pNode)
  1423. {
  1424.     CSmil1Meta* pMeta = new CSmil1Meta(pNode);
  1425.     if(pNode->m_pValues)
  1426.     {
  1427. const char* pName = 0;
  1428. IHXBuffer* pBuf = 0;
  1429. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1430. while(HXR_OK == rc)
  1431. {
  1432.     if(strcmp(pName, "name") == 0)
  1433.     {
  1434. pMeta->m_name = (const char*)pBuf->GetBuffer();
  1435.     }
  1436.     else if(strcmp(pName, "content") == 0)
  1437.     {
  1438. pMeta->m_content = (const char*)pBuf->GetBuffer();
  1439.     }
  1440.     HX_RELEASE(pBuf);
  1441.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1442. }
  1443. HX_RELEASE(pBuf);
  1444. // check for 'base'
  1445. if(pMeta->m_name == "base")
  1446. {
  1447.     HX_DELETE(m_pBasePath);
  1448.     m_pBasePath = new_string((const char*)pMeta->m_content);
  1449.     HX_RELEASE(pBuf);
  1450. }
  1451.     }
  1452.     return pMeta;
  1453. }
  1454. CSmil1RendererPreFetch*
  1455. CSmil1Parser::makeRendererPreFetch(SMIL1Node* pNode)
  1456. {
  1457.     CSmil1RendererPreFetch* pRenderer = 
  1458. new CSmil1RendererPreFetch(pNode);
  1459.     if(pNode->m_pValues)
  1460.     {
  1461. const char* pName = 0;
  1462. IHXBuffer* pBuf = 0;
  1463. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1464. while(HXR_OK == rc)
  1465. {
  1466.     if(strcmp(pName, "type") == 0)
  1467.     {
  1468. pRenderer->m_mimeType = (const char*)pBuf->GetBuffer();
  1469.     }
  1470.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1471. }
  1472.     }
  1473.     return pRenderer;
  1474. }
  1475. CSmil1RootLayout*
  1476. CSmil1Parser::makeRootLayout(SMIL1Node* pNode)
  1477. {
  1478.     BOOL bHasHeight = FALSE;
  1479.     BOOL bHasWidth = FALSE;
  1480.     //[SMIL 1.0 compliance] Fixes PR 22674.  SMIL 1.0 documentation states:
  1481.     //  "If a document contains more than one "root-layout" element,
  1482.     //   this is an error, and the document should not be displayed."
  1483.     if (m_bSMILRootLayoutAlreadyFound  &&  m_bSMIL10FullCompliance)
  1484.     {
  1485. CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  1486. errHandler.ReportError(SMILErrorUnexpectedTag,
  1487. (const char*)pNode->m_name, pNode->m_ulTagStartLine);
  1488. return NULL;
  1489.     }
  1490.     else if (m_bStoreErrors && m_bSMILRootLayoutAlreadyFound)
  1491.     {
  1492. storeError(SMILErrorUnexpectedTag, pNode->m_name, 0, 
  1493. pNode->m_ulTagStartLine, 0, FALSE);
  1494.     }
  1495.     m_bSMILRootLayoutAlreadyFound = TRUE;
  1496.     CSmil1RootLayout* pLayout = new CSmil1RootLayout(pNode);
  1497.     if(pNode->m_pValues)
  1498.     {
  1499. const char* pName = 0;
  1500. IHXBuffer* pBuf = 0;
  1501. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1502. while(HXR_OK == rc)
  1503. {
  1504.     //[SMIL 1.0 compliance] Fixes PR 24628.  SMIL 1.0
  1505.     // documentation states in section 3.3.1 that only "length"
  1506.     // values are allowed in a root-layout height or width;
  1507.     // percentages are not allowed:
  1508.     // [SMIL 1.0 compliance] Also fixes PR 25694: don't allow
  1509.     // ANYTHING other than numeric values with 'px' allowed as
  1510.     // the only valid units string:
  1511.     if (m_bSMIL10FullCompliance)
  1512.     {
  1513. if(!strcmp(pName, "height")  ||  !strcmp(pName, "width"))
  1514. {
  1515.     const char* pTmp = (const char*)pBuf->GetBuffer();
  1516.     UINT32 ulBuflen = pBuf->GetSize();
  1517.     UINT32 ulCounter = 0L;
  1518.     BOOL bNumCharFound = FALSE;
  1519.     BOOL bPxFoundAlready = FALSE;
  1520.     while (pTmp  &&  *pTmp)
  1521.     {
  1522. //The SMIL 1.0 spec says to use a "length" value as
  1523. // defined in the CSS2 spec, except that the "px"
  1524. // units are optional.  The CSS2 spec can be found
  1525. // here:
  1526. //  http://www.w3.org/TR/REC-CSS2/syndata.html
  1527. // with the specific definition found here in that
  1528. // page:
  1529. //    .../syndata.html#value-def-length
  1530. // Look for: "[+|-](#*)[.][(#*)][px]"
  1531. if (bPxFoundAlready  ||  
  1532. ( ('0' > *pTmp  ||  '9' < *pTmp)  &&
  1533. '.' != *pTmp  &&
  1534. (bNumCharFound  ||  ('-' != *pTmp  &&
  1535. '+' != *pTmp)) ) )
  1536. {
  1537.     //If at least one number was found already
  1538.     // and "px" follows, then this char (*pTmp)
  1539.     // is not illegal here:
  1540.     if (!bPxFoundAlready  &&
  1541.     bNumCharFound  &&
  1542.     'p' == *pTmp  &&
  1543.     ulCounter < ulBuflen-1  &&
  1544.     'x' == *(pTmp+1) )
  1545.     {
  1546. //the first "px" following a number is ok;
  1547. bPxFoundAlready = TRUE;
  1548. ++pTmp; //jump past the 'x'.
  1549.     }
  1550.     else
  1551.     {
  1552. CSmil1SMILSyntaxErrorHandler errHandler(
  1553.         m_pContext);
  1554. errHandler.ReportError(SMILErrorBadAttribute,
  1555.         (const char*)pBuf->GetBuffer(),
  1556. pNode->m_ulTagStartLine);
  1557. return NULL;
  1558.     }
  1559. }
  1560. else if ('.' == *pTmp  ||  '-' == *pTmp  ||
  1561. '+' == *pTmp)
  1562. {
  1563.     //Valid chars at start, so keep going.
  1564. }
  1565. else
  1566. {
  1567.     bNumCharFound = TRUE;
  1568. }
  1569. ++pTmp;
  1570. ++ulCounter;
  1571.     }
  1572. }
  1573.     }
  1574.     if(strcmp(pName, "height") == 0)
  1575.     {
  1576. pLayout->m_ulHeight = atol((const char*)pBuf->GetBuffer());
  1577. bHasHeight = TRUE;
  1578.     }
  1579.     else if(strcmp(pName, "width") == 0)
  1580.     {
  1581. pLayout->m_ulWidth = atol((const char*)pBuf->GetBuffer());
  1582. bHasWidth = TRUE;
  1583.     }
  1584.     else if(strcmp(pName, "background-color") == 0)
  1585.     {
  1586.                 UINT32    ulColor = 0;
  1587.                 HX_RESULT rv = HXParseColorUINT32((const char*) pBuf->GetBuffer(),
  1588.                                                   ulColor);
  1589.                 if (SUCCEEDED(rv))
  1590.                 {
  1591.                     pLayout->m_ulBgColor = ulColor;
  1592.                 }
  1593.     }
  1594.     else if(strcmp(pName, "overflow") == 0)
  1595.     {
  1596. pLayout->m_overflow = (const char*)pBuf->GetBuffer();
  1597.     }
  1598.     else if(strcmp(pName, "title") == 0)
  1599.     {
  1600. pLayout->m_title = (const char*)pBuf->GetBuffer();
  1601.     }
  1602.     else if((strcmp(pName, "id") == 0) ||
  1603.     (strcmp(pName, "skip-content") == 0))
  1604.     {
  1605. // dont' do anything with these attributes
  1606.     }
  1607.     
  1608.     HX_RELEASE(pBuf);
  1609.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1610. }
  1611.     }
  1612.     //[SMIL 1.0 Compliance]: PR 24630:
  1613.     // height and width are not required in root layout, per the 1.0 spec:
  1614.     pLayout->m_bHeightUnspecified = !bHasHeight;
  1615.     pLayout->m_bWidthUnspecified = !bHasWidth;
  1616.     return pLayout;
  1617. }
  1618. CSmil1Region*
  1619. CSmil1Parser::makeRegion(SMIL1Node* pNode)
  1620. {
  1621.     CSmil1Region* pRegion = new CSmil1Region(pNode);
  1622.     if(pNode->m_pValues)
  1623.     {
  1624. const char* pName = 0;
  1625. IHXBuffer* pBuf = 0;
  1626. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1627. while(HXR_OK == rc)
  1628. {
  1629.     //[SMIL 1.0 compliance] Fixes PR 25697.  SMIL 1.0
  1630.     // documentation states in section 3.3.1 that only percentage and
  1631.     // "length" values are allowed in a root-layout height or width;
  1632.     if (m_bSMIL10FullCompliance)
  1633.     {
  1634. if(!strcmp(pName, "height")  ||  !strcmp(pName, "width")  ||
  1635. !strcmp(pName, "top")  ||  !strcmp(pName, "left"))
  1636. {
  1637.     const char* pTmp = (const char*)pBuf->GetBuffer();
  1638.     UINT32 ulBuflen = pBuf->GetSize();
  1639.     UINT32 ulCounter = 0L;
  1640.     BOOL bNumCharFound = FALSE;
  1641.     BOOL bPxOrPercentFoundAlready = FALSE;
  1642.     while (pTmp  &&  *pTmp)
  1643.     {
  1644. //The SMIL 1.0 spec says to use a percentage value
  1645. // or a "length" value as defined in the CSS2 spec,
  1646. // except that the "px" units are the only ones
  1647. // allowed and are optional.
  1648. // The CSS2 spec can be found here:
  1649. //  http://www.w3.org/TR/REC-CSS2/syndata.html
  1650. // with the specific definition found here in that
  1651. // page:
  1652. //    .../syndata.html#value-def-length
  1653. // Look for: "[+|-](#*)[.][(#*)][px|%]"
  1654. if (bPxOrPercentFoundAlready  ||
  1655. ( ('0' > *pTmp  ||  '9' < *pTmp)  &&
  1656. '.' != *pTmp  &&
  1657. (bNumCharFound  ||  ('-' != *pTmp  &&
  1658. '+' != *pTmp)) ) )
  1659. {
  1660.     //If at least one number was found already
  1661.     // and "px" or "%" follows, then this char
  1662.     // (*pTmp) is not illegal here:
  1663.     if (!bPxOrPercentFoundAlready  &&
  1664.     bNumCharFound  &&
  1665.     ( '%' == *pTmp  ||
  1666.     ('p' == *pTmp  &&
  1667.     ulCounter < ulBuflen-1  &&
  1668.     'x' == *(pTmp+1))) )
  1669.     {
  1670. //The first "px" or "%" following a number
  1671. // is ok;
  1672. bPxOrPercentFoundAlready = TRUE;
  1673. if ('p' == *pTmp)
  1674. {
  1675.     ++pTmp; //jump past the 'x'.
  1676. }
  1677.     }
  1678.     else
  1679.     {
  1680. CSmil1SMILSyntaxErrorHandler errHandler(
  1681.         m_pContext);
  1682. errHandler.ReportError(SMILErrorBadAttribute,
  1683.         (const char*)pBuf->GetBuffer(),
  1684. pNode->m_ulTagStartLine);
  1685. return NULL;
  1686.     }
  1687. }
  1688. else if ('.' == *pTmp  ||  '-' == *pTmp  ||
  1689. '+' == *pTmp)
  1690. {
  1691.     //Valid chars at start, so keep going.
  1692. }
  1693. else
  1694. {
  1695.     bNumCharFound = TRUE;
  1696. }
  1697. ++pTmp;
  1698. ++ulCounter;
  1699.     }
  1700. }
  1701.     }
  1702.     if(strcmp(pName, "left") == 0)
  1703.     {
  1704. pRegion->m_left = (const char*)pBuf->GetBuffer();
  1705.     }
  1706.     else if(strcmp(pName, "top") == 0)
  1707.     {
  1708. pRegion->m_top = (const char*)pBuf->GetBuffer();
  1709.     }
  1710.     else if(strcmp(pName, "height") == 0)
  1711.     {
  1712. pRegion->m_height = (const char*)pBuf->GetBuffer();
  1713.     }
  1714.     else if(strcmp(pName, "width") == 0)
  1715.     {
  1716. pRegion->m_width = (const char*)pBuf->GetBuffer();
  1717.     }
  1718.     else if(strcmp(pName, "fit") == 0)
  1719.     {
  1720. pRegion->m_fit = (const char*)pBuf->GetBuffer();
  1721.     }
  1722.     else if(strcmp(pName, "z-index") == 0)
  1723.     {
  1724. pRegion->m_zIndex = atol((const char*)pBuf->GetBuffer());
  1725.     }
  1726.     else if(strcmp(pName, "background-color") == 0)
  1727.     {
  1728. const char* pActualColor = (const char*)pBuf->GetBuffer();
  1729. if(strcmp(pActualColor, "transparent") == 0)
  1730. {
  1731.     pRegion->m_bBgColorSet = FALSE;
  1732. }
  1733. else
  1734. {
  1735.                     UINT32 ulColor = 0;
  1736.                     HX_RESULT rv = HXParseColorUINT32((const char*) pBuf->GetBuffer(),
  1737.                                                       ulColor);
  1738.                     if (SUCCEEDED(rv))
  1739.                     {
  1740.                         pRegion->m_ulBgColor   = ulColor;
  1741.                         pRegion->m_bBgColorSet = TRUE;
  1742.                     }
  1743. }
  1744.     }
  1745.     
  1746.     pBuf->Release();
  1747.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1748. }
  1749.     }
  1750.     return pRegion;
  1751. }
  1752. CSmil1AAnchorElement*
  1753. CSmil1Parser::makeAAnchorElement(SMIL1Node* pNode)
  1754. {
  1755.     CSmil1AAnchorElement* pAnchor = 
  1756. new CSmil1AAnchorElement(pNode);
  1757.     if(pNode->m_pValues)
  1758.     {
  1759. const char* pName = 0;
  1760. IHXBuffer* pBuf = 0;
  1761. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1762. while(HXR_OK == rc)
  1763. {
  1764.     if(strcmp(pName, "href") == 0)
  1765.     {
  1766. pAnchor->m_href = (const char*)pBuf->GetBuffer();
  1767.     }
  1768.     else if(strcmp(pName, "show") == 0)
  1769.     {
  1770. pAnchor->m_show = (const char*)pBuf->GetBuffer();
  1771.     }
  1772.     pBuf->Release();
  1773.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1774. }
  1775.     }
  1776.     return pAnchor;
  1777. }
  1778. CSmil1AnchorElement*
  1779. CSmil1Parser::makeAnchorElement(SMIL1Node* pNode)
  1780. {
  1781.     CSmil1AnchorElement* pAnchor = new CSmil1AnchorElement(pNode);
  1782.     if(pNode->m_pValues)
  1783.     {
  1784. const char* pName = 0;
  1785. IHXBuffer* pBuf = 0;
  1786. HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1787. while(HXR_OK == rc)
  1788. {
  1789.     if(strcmp(pName, "href") == 0)
  1790.     {
  1791. pAnchor->m_href = (const char*)pBuf->GetBuffer();
  1792.     }
  1793.     else if(strcmp(pName, "show") == 0)
  1794.     {
  1795. pAnchor->m_show = (const char*)pBuf->GetBuffer();
  1796.     }
  1797.     else if(strcmp(pName, "coords") == 0)
  1798.     {
  1799. rc = parseAnchorCoords((const char*)pBuf->GetBuffer(),
  1800.     pAnchor);
  1801.     }
  1802.     else if(strcmp(pName, "fragment-id") == 0)
  1803.     {
  1804. pAnchor->m_fragmentID = (const char*)pBuf->GetBuffer();
  1805.     }
  1806.     else if(strcmp(pName, "z-index") == 0)
  1807.     {
  1808. pAnchor->m_zIndex = atol((const char*)pBuf->GetBuffer());
  1809.     }
  1810.     else if(strcmp(pName, "begin") == 0)
  1811.     {
  1812. rc = parseDuration((const char*)pBuf->GetBuffer(), pAnchor, 
  1813.     SMILSyncAttrBegin);
  1814. if(HXR_OK == rc)
  1815. {
  1816.     pAnchor->m_bTimeValueSet = TRUE;
  1817. }
  1818.     }
  1819.     else if(strcmp(pName, "end") == 0)
  1820.     {
  1821. rc = parseDuration((const char*)pBuf->GetBuffer(), pAnchor,
  1822.     SMILSyncAttrEnd);
  1823. if(HXR_OK == rc)
  1824. {
  1825.     pAnchor->m_bTimeValueSet = TRUE;
  1826. }
  1827.     }
  1828.     pBuf->Release();
  1829.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1830. }
  1831.     }
  1832.     return pAnchor;
  1833. }
  1834. CSmil1Source*
  1835. CSmil1Parser::makeSource(SMIL1Node* pNode)
  1836. {
  1837.     HX_RESULT rc = HXR_OK;
  1838.     CSmil1Source* pSource = new CSmil1Source(pNode);
  1839.     // assign to a group
  1840.     if(pNode->m_nGroup == (UINT16)-1)
  1841.     {
  1842. SMIL1Node* pParent = pNode->m_pParent;
  1843. while(pParent)
  1844. {
  1845.     if(pParent->m_nGroup != (UINT16)-1)
  1846.     {
  1847. pNode->m_nGroup = pParent->m_nGroup;
  1848. break;
  1849.     }
  1850.     pParent = pParent->m_pParent;
  1851. }
  1852.     }
  1853.     if(pNode->m_pValues)
  1854.     {
  1855. const char* pName = 0;
  1856. IHXBuffer* pBuf = 0;
  1857. rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1858. while(HXR_OK == rc)
  1859. {
  1860.     if(strcmp(pName, "src") == 0)
  1861.     {
  1862. CHXString src = (const char*)pBuf->GetBuffer();
  1863. // trim leading/trailing spaces
  1864. src.TrimRight();
  1865. src.TrimLeft();
  1866. if(m_pBasePath &&
  1867.     isRelativeURL(src))
  1868. {
  1869.     pSource->m_src = CHXString(m_pBasePath) + src;
  1870. }
  1871. else
  1872. {
  1873.     pSource->m_src = src;
  1874. }
  1875.     }
  1876.     else if(strcmp(pName, "region") == 0)
  1877.     {
  1878. //char szPersistentComponentID[MAX_DISPLAY_NAME] = {0};
  1879. //itoa(m_ulPersistentComponentID, szPersistentComponentID, 10);
  1880.    
  1881. // append persistent ID to the end of region id
  1882. // to make it unique in nested meta
  1883. pSource->m_region = (const char*)pBuf->GetBuffer();
  1884. //pSource->m_region += "_";
  1885. //pSource->m_region += szPersistentComponentID;
  1886.     }
  1887.     else if(strcmp(pName, "begin") == 0)
  1888.     {
  1889. rc = parseDuration((const char*)pBuf->GetBuffer(), pSource, 
  1890.     SMILSyncAttrBegin);
  1891.     }
  1892.     else if(strcmp(pName, "end") == 0)
  1893.     {
  1894. rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
  1895.     SMILSyncAttrEnd);
  1896.     }
  1897.     else if(strcmp(pName, "clip-begin") == 0)
  1898.     {
  1899. rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
  1900.     SMILSyncAttrClipBegin);
  1901.     }
  1902.     else if(strcmp(pName, "clip-end") == 0)
  1903.     {
  1904. rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
  1905.     SMILSyncAttrClipEnd);
  1906.     }
  1907.     else if(strcmp(pName, "dur") == 0)
  1908.     {
  1909. rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
  1910.     SMILSyncAttrDur);
  1911.     }
  1912.     else if(strcmp(pName, "fill") == 0)
  1913.     {
  1914. pSource->m_fill = (const char*)pBuf->GetBuffer();
  1915.     }
  1916.     else if(strcmp(pName, "title") == 0)
  1917.     {
  1918. pSource->m_title = (const char*)pBuf->GetBuffer();
  1919.     }
  1920.     else if(strcmp(pName, "repeat") == 0)
  1921.     {
  1922. const char* pRepeatCount = (const char*)pBuf->GetBuffer();
  1923. if(strcmp(pRepeatCount, "indefinite") == 0)
  1924. {
  1925.     pSource->m_ulRepeatValue = MAX_UINT32;
  1926. }
  1927. else
  1928. {
  1929.     pSource->m_ulRepeatValue = atol(pRepeatCount);
  1930. }
  1931.     }
  1932.     pBuf->Release();
  1933.     if(HXR_OK != rc)
  1934.     {
  1935. goto exit;
  1936.     }
  1937.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1938. }
  1939.     }
  1940.     rc = adjustDuration(pSource);
  1941. exit:
  1942.     if(HXR_OK != rc)
  1943.     {
  1944. HX_DELETE(pSource);
  1945.     }
  1946.     return pSource;
  1947. }
  1948. CSmil1SeqElement*
  1949. CSmil1Parser::makeSeqElement(SMIL1Node* pNode)
  1950. {
  1951.     HX_RESULT rc = HXR_OK;
  1952.     CSmil1SeqElement* pElement = 
  1953. new CSmil1SeqElement(pNode);
  1954.     if(pNode->m_pValues)
  1955.     {
  1956. const char* pName = 0;
  1957. IHXBuffer* pBuf = 0;
  1958. rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  1959. while(HXR_OK == rc)
  1960. {
  1961.     if(strcmp(pName, "dur") == 0)
  1962.     {
  1963. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  1964.     SMILSyncAttrDur);
  1965.     }
  1966.             else if(strcmp(pName, "begin") == 0)
  1967.             {
  1968. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  1969.     SMILSyncAttrBegin);
  1970.             }
  1971.             else if(strcmp(pName, "end") == 0)
  1972.             {
  1973. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  1974.     SMILSyncAttrEnd);
  1975.             }
  1976.     else if(strcmp(pName, "title") == 0)
  1977.     {
  1978. pElement->m_title = (const char*)pBuf->GetBuffer();
  1979.     }
  1980.     else if(strcmp(pName, "repeat") == 0)
  1981.     {
  1982. pElement->m_ulRepeatValue = atol((const char*)pBuf->GetBuffer());
  1983.     }
  1984.     pBuf->Release();
  1985.     if(HXR_OK != rc)
  1986.     {
  1987. goto exit;
  1988.     }
  1989.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  1990. }
  1991.     }
  1992.     rc = adjustDuration(pElement);
  1993. exit:
  1994.     if(HXR_OK != rc)
  1995.     {
  1996. HX_DELETE(pElement);
  1997.     }
  1998.     return pElement;
  1999. }
  2000. CSmil1ParElement*
  2001. CSmil1Parser::makeParElement(SMIL1Node* pNode)
  2002. {
  2003.     HX_RESULT rc = HXR_OK;
  2004.     CSmil1ParElement* pElement = 
  2005. new CSmil1ParElement(pNode);
  2006.     if(pNode->m_pValues)
  2007.     {
  2008. const char* pName = 0;
  2009. IHXBuffer* pBuf = 0;
  2010. rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
  2011. while(HXR_OK == rc)
  2012. {
  2013.     if(strcmp(pName, "dur") == 0)
  2014.     {
  2015. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  2016.     SMILSyncAttrDur);
  2017.     }
  2018.             else if(strcmp(pName, "begin") == 0)
  2019.             {
  2020. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  2021.     SMILSyncAttrBegin);
  2022.             }
  2023.             else if(strcmp(pName, "end") == 0)
  2024.             {
  2025. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  2026.     SMILSyncAttrEnd);
  2027.             }
  2028.     else if(strcmp(pName, "endsync") == 0)
  2029.     {
  2030. rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
  2031.     SMILSyncAttrEndsync);
  2032.     }
  2033.     else if(strcmp(pName, "title") == 0)
  2034.     {
  2035. pElement->m_title = (const char*)pBuf->GetBuffer();
  2036.     }
  2037.     else if(strcmp(pName, "repeat") == 0)
  2038.     {
  2039. pElement->m_ulRepeatValue = atol((const char*)pBuf->GetBuffer());
  2040.     }
  2041.     pBuf->Release();
  2042.     if(HXR_OK != rc)
  2043.     {
  2044. goto exit;
  2045.     }
  2046.     rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
  2047. }
  2048.     }
  2049.     rc = adjustDuration(pElement);
  2050. exit:
  2051.     if(HXR_OK != rc)
  2052.     {
  2053. HX_DELETE(pElement);
  2054.     }
  2055.     return pElement;
  2056. }
  2057. HX_RESULT
  2058. CSmil1Parser::insertElementByTimestamp(CSmil1Element* pPacket)
  2059. {
  2060.     LISTPOSITION lPos = m_pPacketQueue->GetHeadPosition();
  2061.     LISTPOSITION lPrev = lPos;
  2062.     while(lPos)
  2063.     {
  2064. CSmil1Element* pPkt = (CSmil1Element*)m_pPacketQueue->GetNext(lPos);
  2065. if(pPkt->m_ulTimestamp > pPacket->m_ulTimestamp)
  2066. {
  2067.     m_pPacketQueue->InsertBefore(lPrev, pPacket);
  2068.     return HXR_OK;
  2069. }
  2070. lPrev = lPos;
  2071.     }
  2072.     m_pPacketQueue->AddTail(pPacket);
  2073.     return HXR_OK;
  2074. }
  2075. HX_RESULT
  2076. CSmil1Parser::mapID(SMIL1Node* pNode, BOOL bOverWrite)
  2077. {
  2078.     HX_RESULT rc = HXR_OK;
  2079.     void* pTmp = 0;
  2080.     if(!bOverWrite && m_pIDMap->Lookup((const char*)pNode->m_id, (void*&)pTmp))
  2081.     {
  2082. rc = HXR_FAIL;
  2083. CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  2084. errHandler.ReportError(SMILErrorDuplicateID, pNode->m_id, 
  2085. pNode->m_ulTagStartLine);
  2086.     }
  2087.     else
  2088.     {
  2089. (*m_pIDMap)[(const char*)pNode->m_id] = pNode;
  2090.     }
  2091.     return rc;
  2092. }
  2093. //This function is needed to fix PR 13319.  If you have a repeat of greater
  2094. // than 1 in a <seq>, we need a way to map the IDs of the children created
  2095. // when the additional <seq>(s) are created
  2096. HX_RESULT
  2097. CSmil1Parser::mapChildrenIDs(SMIL1NodeList* pNodeList, BOOL bOverWrite)
  2098. {
  2099.     HX_RESULT rc = HXR_OK;
  2100.     if (!pNodeList)
  2101.     {
  2102. return rc;
  2103.     }
  2104.     CHXSimpleList::Iterator i;
  2105.     for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
  2106.     {
  2107. SMIL1Node* pNode = (SMIL1Node*)(*i);
  2108. rc = mapID(pNode, bOverWrite);
  2109. HX_ASSERT(rc == HXR_OK);
  2110. if(pNode->m_pNodeList)
  2111. {
  2112.     rc = mapChildrenIDs(pNode->m_pNodeList, bOverWrite);
  2113. }
  2114.     }
  2115.     return rc;
  2116. }
  2117. HX_RESULT
  2118. CSmil1Parser::markRepeatReplica(SMIL1NodeList* pNodeList, RepeatTag repeatTag)
  2119. {
  2120.     HX_RESULT rc = HXR_OK;
  2121.     if(!pNodeList)
  2122.     {
  2123. return rc;
  2124.     }
  2125.     CHXSimpleList::Iterator i;
  2126.     for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
  2127.     {
  2128. SMIL1Node* pNode = (SMIL1Node*)(*i);
  2129. pNode->m_repeatTag = repeatTag;
  2130. if(pNode->m_pNodeList)
  2131. {
  2132.     rc = markRepeatReplica(pNode->m_pNodeList, repeatTag);
  2133. }
  2134.     }
  2135.     return rc;
  2136. }
  2137. HX_RESULT
  2138. CSmil1Parser::createElements()
  2139. {
  2140.     HX_RESULT rc = HXR_OK;
  2141.     
  2142.     SMIL1Node* pSMIL1Node = findFirstNode(SMILSmil);
  2143.     if(!pSMIL1Node)  // dangerwillrobinson!!!
  2144.     {
  2145. rc = HXR_FAIL;
  2146. CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
  2147. errHandler.ReportError(SMILErrorNotSMIL, NULL, 0);
  2148. return rc;
  2149.     }
  2150.     rc = addToNamespaceScope(pSMIL1Node);
  2151.     if (SUCCEEDED(rc))
  2152.     {
  2153. // XXXJEFFA Hardcode "cv" namespace prefix for Redstone alpha 7
  2154. rc = addGlobalNamespace((const char*) SYSTEM_COMPONENT_NAMESPACE, "cv");
  2155.     }
  2156.     
  2157.     if (FAILED(rc))
  2158.     {
  2159. HX_ASSERT(FALSE);
  2160. return rc;
  2161.     }
  2162.     
  2163.     SMIL1Node* pHeadNode = findFirstNode(SMILHead);
  2164.     if(pHeadNode)
  2165.     {
  2166. rc = markTestAttributeNodes(pHeadNode->m_pNodeList);
  2167. if (SUCCEEDED(rc))
  2168. {
  2169.     rc = addToNamespaceScope(pHeadNode);
  2170. }
  2171. if(SUCCEEDED(rc))
  2172. {
  2173.     rc = createHeadElements(pHeadNode->m_pNodeList);
  2174. }
  2175. if (SUCCEEDED(rc))
  2176. {
  2177.     rc = removeFromNamespaceScope(pHeadNode);
  2178. }
  2179.     }
  2180.     if(rc == HXR_OK)
  2181.     {
  2182. SMIL1Node* pBodyNode = findFirstNode(SMILBody);
  2183. if(pBodyNode && 
  2184.     pBodyNode->m_pNodeList)
  2185. {
  2186.       rc = addToNamespaceScope(pBodyNode);
  2187.       if (SUCCEEDED(rc))
  2188.        {
  2189. SMIL1Node* pTopNode = getTimelineDescendent(pBodyNode, NULL);
  2190. if(pTopNode &&
  2191.     pTopNode->m_tag != SMILSeq)
  2192. {
  2193.     createSeqWrapper(pBodyNode->m_pNodeList);
  2194. }
  2195. //[SMIL 1.0 compliance] fix for PR 23050:
  2196. // if first descendent of body is a <switch> and its first child
  2197. // is a <seq> that did not get chosen in the switch, then we
  2198. // would be tricked into thinking we already had a valid outer
  2199. // seq, but we wouldn't.  Let's put one there in this case,
  2200. // noting that we don't yet know if that seq is valid or not.
  2201. // However, it doesn't matter either way:
  2202. if(pTopNode  &&  SMILSeq == pTopNode->m_tag  &&
  2203. pTopNode->m_pParent  &&
  2204. pTopNode->m_pParent->m_tag == SMILSwitch)
  2205. {
  2206.     createSeqWrapper(pBodyNode->m_pNodeList);
  2207. }
  2208. if(HXR_OK != markTestAttributeNodes(pBodyNode->m_pNodeList) ||
  2209.    HXR_OK != expandRepeatElements(pBodyNode->m_pNodeList) ||
  2210.    HXR_OK != createBodyElements(pBodyNode->m_pNodeList) ||
  2211.    HXR_OK != assignGroupIndexes(pBodyNode->m_pNodeList) ||
  2212.    HXR_OK != constructTimelineElements(pBodyNode->m_pNodeList) ||
  2213.    HXR_OK != setInitialDelays(pBodyNode->m_pNodeList) ||
  2214.    // HXR_OK != updateEventElements(pBodyNode->m_pNodeList) ||
  2215. #ifdef _DEBUG
  2216.    HXR_OK != printBodyElements(pBodyNode->m_pNodeList) ||
  2217. #endif
  2218.    HXR_OK != insertGroups())
  2219. {
  2220.     rc = HXR_FAIL;
  2221. }
  2222.     }
  2223.     if (SUCCEEDED(rc))
  2224.        {
  2225. rc = removeFromNamespaceScope(pBodyNode);
  2226.        }
  2227. }
  2228. if(rc == HXR_OK && !m_bContainsSource)
  2229. {
  2230.     rc = HXR_OK;
  2231.     //[SMIL 1.0 compliance] fixes PR 27672:
  2232.     // don't call SMILErrorNoBodyElements error as it is not one
  2233.     // per the SMIL 1.0 spec.
  2234. }
  2235.     }
  2236.     return rc;
  2237. }
  2238. HX_RESULT
  2239. CSmil1Parser::createSeqWrapper(SMIL1NodeList* pNodeList)
  2240. {
  2241.     // create a default <seq></seq> wrapper within the <body></body>
  2242.     HX_RESULT rc = HXR_OK;
  2243.     SMIL1Node* pSeqNode = new SMIL1Node;
  2244.     pSeqNode->m_name = "seq";
  2245.     pSeqNode->m_pParent = pNodeList->m_pParentNode;
  2246.     pSeqNode->m_id = assignID("seq");
  2247.     pSeqNode->m_tag = SMILSeq;
  2248.     pSeqNode->m_pNodeList = new SMIL1NodeList;
  2249.     // Must put the node in the id map - otherwise
  2250.     // we leak the node
  2251.     mapID(pSeqNode, TRUE);
  2252.     // move children from bodyNode list to seq list
  2253.     int count = pNodeList->GetCount();
  2254.     SMIL1Node* pEndBodyNode = NULL;
  2255.     while( count > 0) // don't reparent </body> tag 
  2256.     {
  2257. SMIL1Node* pChildNode = (SMIL1Node*)pNodeList->RemoveHead();
  2258. //XXXJHUG don't reparent the </body> tag...
  2259. if ( pChildNode->m_id != "CLOSE-body" )
  2260. {
  2261.     pChildNode->m_pParent = pSeqNode;
  2262.     pSeqNode->m_pNodeList->AddTail(pChildNode);
  2263. }
  2264. else
  2265. {
  2266.     pEndBodyNode = pChildNode;
  2267. }
  2268. --count;
  2269.     }
  2270.     SMIL1Node* pEndSeqNode = new SMIL1Node;
  2271.     pEndSeqNode->m_name = "seq";
  2272.     pEndSeqNode->m_id = "CLOSE-seq";
  2273.     pEndSeqNode->m_pParent = pSeqNode;
  2274.     pEndSeqNode->m_tag = SMILEndSeq;
  2275.     pSeqNode->m_pNodeList->AddTail(pEndSeqNode);
  2276.     // now add it to the <body> parent...
  2277.     pNodeList->AddHead(pSeqNode);
  2278.     pNodeList->AddTail(pEndBodyNode);
  2279.     return rc;
  2280. }
  2281. #if 0
  2282. //XXXBAB - useful for debugging
  2283. void
  2284. CSmil1Parser::PrintNode(SMIL1Node* pNode, FILE* fp, int level)
  2285. {
  2286.     for(int tab=0;tab<level;++tab)
  2287.     {
  2288. fprintf(fp, "t");
  2289.     }
  2290.     fprintf(fp, "%sn", (const char*)pNode->m_id);
  2291.     if(pNode->m_pNodeList)
  2292.     {
  2293. CHXSimpleList::Iterator i = pNode->m_pNodeList->Begin();
  2294. for(; i != pNode->m_pNodeList->End(); ++i)
  2295. {
  2296.     SMIL1Node* pChildNode = (SMIL1Node*)(*i);
  2297.     PrintNode(pChildNode, fp, level+1);
  2298. }
  2299.     }
  2300. }
  2301. void
  2302. CSmil1Parser::PrintNodes()
  2303. {
  2304.     FILE* fp = fopen("nodes.txt", "w");
  2305.     SMIL1Node* pNode = (SMIL1Node*)m_pNodeList->GetHead();
  2306.     PrintNode(pNode, fp, 0);
  2307.     fclose(fp);
  2308. }
  2309. #endif
  2310. HX_RESULT
  2311. CSmil1Parser::printBodyElements(SMIL1NodeList* pNodeList)
  2312. {
  2313.     // debugging code...
  2314.     HX_RESULT rc = HXR_OK;
  2315. //#define XXXEH_FOR_DEBUGGING_ONLY
  2316. #if defined(XXXEH_FOR_DEBUGGING_ONLY)
  2317.     static int level = 0;
  2318.     if(!pNodeList)
  2319.     {
  2320. return rc;
  2321.     }
  2322.     CHXSimpleList::Iterator i;
  2323.     for(i=pNodeList->Begin();i!=pNodeList->End();++i)
  2324.     {
  2325. if(HXR_OK != rc)
  2326. {
  2327.     return rc;
  2328. }
  2329. SMIL1Node* pNode = (SMIL1Node*)(*i);
  2330. FILE* fp=fopen("c:\temp\smil.txt", "a+");
  2331. if (!fp)
  2332. {
  2333.     break;
  2334. }
  2335. for(int i=0;i<level;++i)
  2336. {
  2337.     fprintf(fp, "t");
  2338. }
  2339. UINT32 ulDelay = (UINT32)-1;
  2340. if(pNode->m_pElement &&
  2341.     pNode->m_pElement->m_pTimelineElement)
  2342. {
  2343.     ulDelay = pNode->m_pElement->m_pTimelineElement->getDelay();
  2344. }
  2345. fprintf(fp, "%s tag %d group %d repeatid %s delay %d deleted %dn", (const char*)pNode->m_id,
  2346.     pNode->m_tag, pNode->m_nGroup, (const char*)pNode->m_repeatid, ulDelay, pNode->m_bDelete);
  2347. fclose(fp);
  2348. if(pNode->m_pNodeList)
  2349. {
  2350.     ++level;
  2351.     rc = printBodyElements(pNode->m_pNodeList);
  2352.     --level;
  2353. }
  2354.     }
  2355. #endif
  2356.     return rc;
  2357. }
  2358. HX_RESULT
  2359. CSmil1Parser::insertGroups()
  2360. {
  2361.     HX_RESULT rc = HXR_OK;
  2362.     if(!m_pAddGroupMap)
  2363.     {
  2364. rc = HXR_UNEXPECTED;
  2365.     }
  2366.     else
  2367.     {
  2368. UINT32 ulGroupNo = 0;
  2369. CSmil1AddGroup* pAddGroup = 0;
  2370. BOOL bGroupInserted = FALSE;
  2371. while(m_pAddGroupMap->Lookup(ulGroupNo++, (void*&)pAddGroup))
  2372. {
  2373.     bGroupInserted = TRUE;
  2374.     pAddGroup->m_ulDelay = 0;
  2375.     pAddGroup->m_ulTimestamp = INITIAL_STREAM0_TIMESTAMP;
  2376.     insertElementByTimestamp(pAddGroup);
  2377. }
  2378.     }
  2379.     return rc;
  2380. }
  2381. BOOL
  2382. CSmil1Parser::inLanguagePreference(const char* pLang)
  2383. {
  2384.     // return FALSE if language preference is not in m_pLanguagePreferenceList
  2385.     BOOL rc = FALSE;
  2386.     // pLang can be comma separated lists,
  2387.     // with '*' accepting all languages
  2388.     // copy the string so strtok doesn't modify something bad...
  2389.     char* pLangCopy = new_string(pLang);
  2390.     char* pLangFrag = strtok(pLangCopy, ",");
  2391.     while(pLangFrag)
  2392.     {
  2393. if(*pLangFrag == '*') // wildcard
  2394. {
  2395.     rc = TRUE;
  2396.     break;
  2397. }
  2398. // copy the primary tag part of the language (up to '-')
  2399. char* pPrimaryTag = new char[strlen(pLang)+1];
  2400. char* pTagPtr = pPrimaryTag;
  2401. char* pFragPtr = pLangFrag;
  2402. while(*pFragPtr && *pFragPtr != '-')
  2403. {
  2404.     *pTagPtr++ = *pFragPtr++;
  2405. }
  2406. *pTagPtr = '';
  2407. CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
  2408. for(; i != m_pLanguagePreferenceList->End(); ++i)
  2409. {
  2410.     char* pPrefLang = (char*)(*i);
  2411.     if(*pPrefLang == '*') // wildcard
  2412.     {
  2413. rc = TRUE;
  2414.     }
  2415.     else if(strcmp(pPrefLang, pLangFrag) == 0)
  2416.     {
  2417. rc = TRUE;
  2418.     }
  2419.     else if(strncmp(pPrefLang, pPrimaryTag, strlen(pPrimaryTag)) == 0)
  2420.     {
  2421. rc = TRUE;
  2422.     }
  2423.     if(rc)
  2424.     {
  2425. break;
  2426.     }
  2427. }
  2428. delete[] pPrimaryTag;
  2429. if(rc)
  2430. {
  2431.     break;
  2432. }
  2433. pLangFrag = strtok(NULL, ",");
  2434.     }
  2435.     delete[] pLangCopy;
  2436.     return rc;
  2437. }
  2438. BOOL
  2439. CSmil1Parser::systemComponentFailed(IHXBuffer* pRequiredValue)
  2440. {
  2441.     BOOL bFailed = TRUE;
  2442.     IHXUpgradeCollection* pUpgradeCollection = new HXUpgradeCollection;
  2443.     pUpgradeCollection->AddRef();
  2444.     pUpgradeCollection->Add(eUT_Required, pRequiredValue, 0, 0);
  2445.     if (m_pISystemRequired == NULL)
  2446.     {
  2447. m_pContext->QueryInterface(IID_IHXSystemRequired, 
  2448.     (void**)&m_pISystemRequired);
  2449.     }
  2450.     // there may not be a system required interface
  2451.     if (m_pISystemRequired != NULL)
  2452.     {
  2453. bFailed = FAILED(m_pISystemRequired->HasFeatures(pUpgradeCollection));
  2454.     }
  2455.     HX_RELEASE(pUpgradeCollection);
  2456.     return bFailed;
  2457. }
  2458. BOOL
  2459. CSmil1Parser::testAttributeFailed(SMIL1Node* pNode)
  2460. {
  2461.     HX_RESULT rc = HXR_OK;
  2462.     BOOL bFailed = FALSE;
  2463.     IHXBuffer* pBuf = 0;
  2464.     if(pNode->m_pValues)
  2465.     {
  2466. rc = pNode->m_pValues->GetPropertyCString("system-required", pBuf);
  2467. if(HXR_OK == rc)
  2468. {
  2469.     const char* pActualString = (const char*)pBuf->GetBuffer();
  2470.     // Check with the core first
  2471.     
  2472.     if(m_pRequireTagsMap)
  2473.     {
  2474. void* pTag = 0;
  2475. if(!m_pRequireTagsMap->Lookup(pActualString, 
  2476.     (void*&) pTag))
  2477. {
  2478.     bFailed = TRUE;
  2479. }
  2480.     }
  2481.     else // no required list, can't parse it
  2482.     {
  2483. bFailed = TRUE;
  2484.     }
  2485.     pBuf->Release();
  2486.     if(bFailed)
  2487.     {
  2488. goto exit;
  2489.     }
  2490. }
  2491. rc = pNode->m_pValues->GetPropertyCString("system-bitrate", pBuf);
  2492. if(HXR_OK == rc)
  2493. {
  2494.     UINT32 ulBandwidth = atol((const char*)pBuf->GetBuffer());
  2495.     if(m_ulBandwidthPreference < ulBandwidth)
  2496.     {
  2497. bFailed = TRUE;
  2498.     }
  2499.     pBuf->Release();
  2500.     if(bFailed)
  2501.     {
  2502. goto exit;
  2503.     }
  2504. }
  2505. rc = pNode->m_pValues->GetPropertyCString("system-language", pBuf);
  2506. if(HXR_OK == rc)
  2507. {
  2508.     if(m_pLanguagePreferenceList)
  2509.     {
  2510. const char* pLang = (const char*)pBuf->GetBuffer();
  2511. if(!inLanguagePreference(pLang))
  2512. {
  2513.     bFailed = TRUE;
  2514. }
  2515.     }
  2516.     else    // no preference, can't do it...
  2517.     {
  2518. bFailed = TRUE;
  2519.     }
  2520.     pBuf->Release();
  2521.     if(bFailed)
  2522.     {
  2523. goto exit;
  2524.     }
  2525. }
  2526. rc = pNode->m_pValues->GetPropertyCString("system-captions", pBuf);
  2527. if(HXR_OK == rc)
  2528. {
  2529.     const char* pActualValue = (const char*)pBuf->GetBuffer();
  2530.     if(strcmp(pActualValue, "on") == 0)
  2531.     {
  2532. if(!m_bCaptionsPreference)
  2533. {
  2534.     bFailed = TRUE;
  2535. }
  2536.     }
  2537.     else
  2538.     {
  2539. if(m_bCaptionsPreference)
  2540. {
  2541.     bFailed = TRUE;
  2542. }
  2543.     }
  2544.     pBuf->Release();
  2545.     if(bFailed)
  2546.     {
  2547. goto exit;
  2548.     }
  2549. }
  2550. if(HXR_OK == pNode->m_pValues->GetPropertyCString(
  2551.     "system-overdub-or-caption", pBuf))
  2552. {
  2553.     if(m_pOverdubOrCaptionPreference)
  2554.     {
  2555. const char* pActualValue = (const char*)pBuf->GetBuffer();
  2556. if(strcmp(pActualValue, "caption") == 0)
  2557. {
  2558.     if(strcmp(m_pOverdubOrCaptionPreference, "caption") != 0)
  2559.     {
  2560. bFailed = TRUE;
  2561.     }
  2562. }
  2563. else if(strcmp(pActualValue, "overdub") == 0)
  2564. {
  2565.     if(strcmp(m_pOverdubOrCaptionPreference, "overdub") != 0)
  2566.     {
  2567. bFailed = TRUE;
  2568.     }
  2569. }
  2570.     }
  2571.     else
  2572.     {
  2573. bFailed = TRUE;
  2574.     }
  2575.     pBuf->Release();
  2576.     if(bFailed)
  2577.     {
  2578. goto exit;
  2579.     }
  2580. }
  2581. rc = pNode->m_pValues->GetPropertyCString(
  2582.     "system-screen-size", pBuf);
  2583. if(HXR_OK == rc)
  2584. {
  2585.     UINT32 ulScreenHeight = 0;
  2586.     UINT32 ulScreenWidth = 0;
  2587.     const char* pScreenSize = (const char*)pBuf->GetBuffer();
  2588.     // format is screen-height "X" screen-width
  2589.     char tmp[256]; /* Flawfinder: ignore */
  2590.     strcpy(tmp, pScreenSize); /* Flawfinder: ignore */
  2591.     char* pScreenHeight = strtok(tmp, "X");
  2592.     if(pScreenHeight)
  2593.     {
  2594. ulScreenHeight = atol(pScreenHeight);
  2595. char* pScreenWidth = strtok(NULL, "");
  2596. if(pScreenWidth)
  2597. {
  2598.     ulScreenWidth = atol(pScreenWidth);
  2599. }
  2600.     }
  2601.     if((m_ulScreenHeightPreference < ulScreenHeight) ||
  2602.        (m_ulScreenWidthPreference < ulScreenWidth))
  2603.     {
  2604. bFailed = TRUE;
  2605.     }
  2606.     pBuf->Release();
  2607.     if(bFailed)
  2608.     {
  2609. goto exit;
  2610.     }
  2611. }
  2612. rc = pNode->m_pValues->GetPropertyCString(
  2613.     "system-screen-depth", pBuf);
  2614. if(HXR_OK == rc)
  2615. {
  2616.     UINT32 ulScreenDepth = atol((const char*)pBuf->GetBuffer());
  2617.     if(m_ulScreenDepthPreference < ulScreenDepth)
  2618.     {
  2619. bFailed = TRUE;
  2620.     }
  2621.     pBuf->Release();
  2622.     if(bFailed)
  2623.     {
  2624. goto exit;
  2625.     }
  2626. }
  2627. if (m_pActiveNamespaceMap)
  2628. {
  2629.     // look through name spaces for systemComponent name space.  If it's there
  2630.     // append the prefix and look for systemComponent test attribute
  2631.     CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
  2632.     for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
  2633.     {
  2634. IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
  2635. if (strcmp((const char*) SYSTEM_COMPONENT_NAMESPACE, (const char*)pBuffer->GetBuffer()) == 0)
  2636. {
  2637.     const char* pPrefix = (const char*)ndxBuffer.get_key();
  2638.     // +1 for the : in the namespace and 1 for the 
  2639.     char* pAttrName = new char[strlen(pPrefix) + strlen((const char*) SYSTEM_COMPONENT) + 2];
  2640.     
  2641.     pAttrName[0] = '';
  2642.     strcat(pAttrName, pPrefix); /* Flawfinder: ignore */
  2643.     strcat(pAttrName, ":"); /* Flawfinder: ignore */
  2644.     strcat(pAttrName, (const char*) SYSTEM_COMPONENT); /* Flawfinder: ignore */
  2645.     rc = pNode->m_pValues->GetPropertyCString(
  2646. pAttrName, pBuf);
  2647.     HX_VECTOR_DELETE(pAttrName);
  2648.     
  2649.     if(HXR_OK == rc)
  2650.     {
  2651. bFailed = systemComponentFailed(pBuf);
  2652. pBuf->Release();
  2653. // If I get in here, I found the right prefix
  2654. if (bFailed)
  2655. {
  2656.     goto exit;
  2657. }
  2658.     }
  2659. }
  2660.     }
  2661. }
  2662.     }
  2663. exit:
  2664.     return bFailed;
  2665. }
  2666. HX_RESULT
  2667. CSmil1Parser::selectSwitchNodes(SMIL1Node* pSwitchNode)
  2668. {
  2669.     HX_RESULT rc = HXR_OK;