smlparse.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:137k
源码类别:

Symbian

开发平台:

Visual C++

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