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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2003 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. /****************************************************************************
  36.  *  Includes
  37.  */
  38. #include <string.h> // /for memset, strncmp, stricmp
  39. #include "hlxclib/memory.h" // /for memset, memcpy
  40. #include "chxpckts.h" // /For IHXPacket
  41. #include "hxwintyp.h" // /For HXxRect
  42. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  43. #include <utf.h>  // /For CnvUtfConverter::ConvertToUnicodeFromUtf8();
  44. #endif // /_SYMBIAN                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  45. #include "3gppttstructs.h"
  46. #include "3gppttutils.h"
  47. #include "hxheap.h"
  48. #ifdef _DEBUG
  49. #undef HX_THIS_FILE
  50. static const char HX_THIS_FILE[] = __FILE__;
  51. #endif
  52. // for DPRINTF
  53. //#define INCLUDE_DPRINTF
  54. #if(INCLUDE_DPRINTF)
  55. #   include "debug.h"
  56. #   define D_TIMEDTEXT D_INFO
  57. #else
  58. #   define DPRINTF(a,b)
  59. #endif
  60. HX_RESULT C3GPPTextboxBox::Build(const UINT8*& pData)
  61. {
  62.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextboxBox::Build()n"));
  63.     m_top = ReadUI16(pData);
  64.     m_left = ReadUI16(pData);
  65.     m_bottom = ReadUI16(pData);
  66.     m_right = ReadUI16(pData);
  67.     return HXR_OK;
  68. }
  69. HX_RESULT C3GPPStyleRecord::Build(const UINT8*& pData)
  70. {
  71.     DPRINTF(D_TIMEDTEXT, ("C3GPPStyleRecord::Build()n"));
  72.     m_uiStartCharOffset = ReadUI16(pData);
  73.     m_uiEndCharOffset = ReadUI16(pData);
  74.     m_uiFontID = ReadUI16(pData);
  75.     m_uFaceStyleFlags = *pData++;
  76.     m_uFontSize = *pData++;
  77.     m_textColor = ReadARGB(pData);
  78.     return HXR_OK;
  79. }
  80. HX_RESULT C3GPPFontRecord::Build(const UINT8*& pData)
  81. {
  82.     DPRINTF(D_TIMEDTEXT, ("C3GPPFontRecord::Build()n"));
  83.     m_uiFontID = ReadUI16(pData);
  84.     UINT8 cchFontName = *pData++;
  85.     HX_RESULT hr = m_strFont.Set((const char*)pData, cchFontName);
  86.     if(SUCCEEDED(hr))
  87.     {
  88.         pData += cchFontName;
  89.     }
  90.     return hr;
  91. }
  92. HX_RESULT C3GPPTextHyperTextBox::Build(const UINT8*& pData) 
  93.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextHyperTextBox::Build()n"));
  94.     m_uiStartCharOffset = ReadUI16(pData);
  95.     m_uiEndCharOffset = ReadUI16(pData);
  96.     UINT8 cchURL = *pData++;
  97.  
  98.     HX_RESULT hr = m_strURL.Set((const char*)pData, cchURL);
  99.     if(SUCCEEDED(hr))
  100.     {
  101.         pData += cchURL;
  102.         cchURL = *pData++;
  103.         hr = m_strAltURL.Set((const char*)pData, cchURL);
  104.         if(SUCCEEDED(hr))
  105.         {
  106.             pData += cchURL;
  107.         }
  108.     }
  109.     return hr;
  110. }
  111. HX_RESULT C3GPPTextSampleEntry::Build(const UINT8*& pData)
  112. {
  113.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextSampleEntry::Build()n"));
  114.     HX_RESULT hr = C3GPPArrayEntry::Build(pData);
  115.     if(SUCCEEDED(hr))
  116.     {
  117.         m_ulDisplayFlags = ReadUL32(pData);
  118.         m_horizontalJustification   = *pData++;
  119.         m_verticalJustification     = *pData++;
  120.         m_bgColor = ReadARGB(pData);
  121.         hr = m_defaultTextBox.Build(pData);
  122.         if(SUCCEEDED(hr))
  123.         {
  124.             hr = m_defaultStyle.Build(pData);
  125.             if(SUCCEEDED(hr))
  126.             {
  127.                 hr = m_fontTable.Build(pData);
  128.             }
  129.         }
  130.     }
  131.     return hr;
  132. }
  133. C3GPPTextSampleEntry::C3GPPTextSampleEntry()
  134. : m_ulDisplayFlags(0)
  135. , m_horizontalJustification(0)
  136. , m_verticalJustification(0)
  137. , m_bgColor(0)
  138. {  
  139. }
  140. TextSampleScrollDirection
  141. C3GPPTextSampleEntry::getScrollDirection() const
  142. {
  143.     TextSampleScrollDirection retval = scrollDirNone;
  144.     if (hasScrollIn()  ||  hasScrollOut())
  145.     {
  146.         switch (m_ulDisplayFlags & HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_MASK)
  147.         {
  148.             case HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_UP:
  149.                 retval = scrollDirUp;
  150.                 break;
  151.             case HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_RTOL:
  152.                 retval = scrollDirRightToLeft;
  153.                 break;
  154.             case HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_DOWN:
  155.                 retval = scrollDirDown;
  156.                 break;
  157.             case HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_LTOR:
  158.                 retval = scrollDirLeftToRight;
  159.                 break;
  160.             default:
  161.                 // /Should be one of the above:
  162.                 HX_ASSERT(m_ulDisplayFlags & HX_3GPPTT_DISPLAYFLAGS_SCROLL_DIR_MASK);
  163.                 retval = scrollDirNone;
  164.                 break;
  165.         }
  166.     }
  167.     return retval;
  168. }
  169. C3GPPTextSampleModifierBox::ModifierType C3GPPTextSampleModifierBox::ReadType(const UINT8*& pData)
  170. {
  171.     const char* pchType = (const char*)pData;
  172.     pData += 4;
  173.     ModifierType type = UNKNOWN;
  174.     if      (!strncmp(pchType, "styl", 4) )
  175.     {
  176.         type = STYL;
  177.     }
  178.     else if (!strncmp(pchType, "hlit", 4) )
  179.     {
  180.         type = HLIT;
  181.     }
  182.     else if (!strncmp(pchType, "hclr", 4) )
  183.     {
  184.         type = HCLR;
  185.     }
  186.     else if (!strncmp(pchType, "krok", 4) )
  187.     {
  188.         type = KROK;
  189.     }
  190.     else if (!strncmp(pchType, "dlay", 4) )
  191.     {
  192.         type = DLAY;
  193.     }
  194.     else if (!strncmp(pchType, "href", 4) )
  195.     {
  196.         type = HREF;
  197.     }
  198.     else if (!strncmp(pchType, "tbox", 4) )
  199.     {
  200.         type = TBOX;
  201.     }
  202.     else if (!strncmp(pchType, "blnk", 4) )
  203.     {
  204.         type = BLNK;
  205.     }
  206.     return type;
  207. }
  208. HX_RESULT C3GPPTextSample::Init(IHXBuffer* pIHXBuff)
  209. {
  210.     HX_ASSERT(pIHXBuff);
  211.     m_pIHXBuff->AddRef();
  212.     const UINT8* pPackedBuff  = m_pIHXBuff->GetBuffer();
  213.     HX_ASSERT(pPackedBuff);
  214.     UINT32 cbSampleTotal = m_pIHXBuff->GetSize();
  215.     m_uiTextLengthInBytes = ReadUI16(pPackedBuff);
  216.     UINT32 cbSampleTextBox = 2 + m_uiTextLengthInBytes; //size field + text
  217.     HX_ASSERT(cbSampleTotal >= cbSampleTextBox);
  218.     if (m_uiTextLengthInBytes && (cbSampleTotal > 2) )
  219.     {
  220.         // /NOTE: The spec says:
  221.         //   "Authors should limit the string in each text sample to not more
  222.         //    than 2048 bytes, for maximum terminal interoperability."
  223.         // and it also says:
  224.         //   "Any unrecognised box found in the text sample should be skipped
  225.         //    and ignored, and processing continue as if it were not there."
  226.         m_pText = (const char*) pPackedBuff;
  227.         
  228.         m_uiTextModifiersTotalSize = UINT16(cbSampleTotal - cbSampleTextBox);
  229.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextSample::Init(): %.*s;n", 200, m_pText));
  230.         if (m_uiTextModifiersTotalSize)
  231.         {
  232.             // text modifiers follow
  233.             m_pTextModifierData = pPackedBuff +  m_uiTextLengthInBytes;
  234.             
  235.         }
  236.     }    
  237.     return HXR_OK;
  238. }
  239. C3GPPTextSample::C3GPPTextSample(IHXBuffer* pIHXBuff) 
  240. : m_pText(NULL)
  241. , m_uiTextLengthInBytes(0)
  242. , m_pTextModifierData(NULL)
  243. , m_uiTextModifiersTotalSize(0)
  244. , m_pIHXBuff(pIHXBuff)
  245. {
  246.     Init(pIHXBuff);
  247. }
  248. HX_RESULT C3GPPTextStyleBox::Build(const UINT8*& pData)
  249. {
  250.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextStyleBox::Build()n"));
  251.     HX_RESULT hr = HXR_OK;
  252.     UINT16 entryCount = ReadUI16(pData);
  253.     HX_ASSERT(m_entries.GetCount() == 0);
  254.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextStyleBox::Build(): %u entriesn", entryCount));
  255.     hr = m_entries.Reset(entryCount);
  256.     if(SUCCEEDED(hr))
  257.     {
  258.         for(UINT16 idx = 0; idx < entryCount; ++idx)
  259.         {
  260.             C3GPPStyleRecord* pEntry = new C3GPPStyleRecord();
  261.             if(!pEntry)
  262.             {
  263.                 return HXR_OUTOFMEMORY;
  264.             }
  265.             hr = pEntry->Build(pData);
  266.             if(FAILED(hr))
  267.             {
  268.                 HX_DELETE(pEntry);
  269.                 break;
  270.             }
  271.             m_entries[idx] = pEntry;
  272.         }
  273.     }
  274.     return hr;
  275. }
  276. C3GPPFontTableBox::~C3GPPFontTableBox()
  277. {
  278.     CleanUp();
  279. }
  280. void C3GPPFontTableBox::CleanUp()
  281. {
  282.     for ( UINT32 idx = 0; idx != m_entries.GetCount(); ++idx )
  283.     {
  284. C3GPPFontRecord*& pEntry = (C3GPPFontRecord*&)(m_entries[idx]);
  285. delete pEntry;
  286.     }
  287.     m_entries.Reset(0);
  288. }
  289. HX_RESULT C3GPPFontTableBox::Build(const UINT8*& pData)
  290. {
  291.     DPRINTF(D_TIMEDTEXT, ("C3GPPFontTableBox::Build()n"));
  292.     HX_RESULT hr = HXR_OK;
  293.     m_ulFontTableSizeInBytes = ReadUL32(pData);
  294.     // skip ftab
  295.     HX_ASSERT(!strncmp((const char*)pData, "ftab", 4));
  296.     pData += 4;
  297.     UINT16 entryCount = ReadUI16(pData);
  298.     HX_ASSERT(m_entries.GetCount() == 0);
  299.     DPRINTF(D_TIMEDTEXT, ("C3GPPFontTableBox::Build(): %u entriesn", entryCount));
  300.     hr = m_entries.Reset(entryCount);
  301.     if(SUCCEEDED(hr))
  302.     {
  303.         for(UINT16 idx = 0; idx < entryCount; ++idx)
  304.         {
  305.             C3GPPFontRecord* pEntry = new C3GPPFontRecord();
  306.             if(!pEntry)
  307.             {
  308.                 return HXR_OUTOFMEMORY;
  309.             }
  310.             hr = pEntry->Build(pData);
  311.             if(FAILED(hr))
  312.             {
  313.                 HX_ASSERT(false);
  314.                 HX_DELETE(pEntry);
  315.                 break;
  316.             }
  317.             HX_ASSERT(0 == m_entries[idx]);
  318.             m_entries[idx] = pEntry;
  319.         }
  320.     }
  321.     return hr;
  322. }
  323. C3GPPTextStyleBox::~C3GPPTextStyleBox()
  324. {
  325.     CleanUp();
  326. }
  327. void C3GPPTextStyleBox::CleanUp()
  328. {
  329.     for ( INT32 idx = 0; idx != m_entries.GetCount(); ++idx )
  330.     {
  331. C3GPPStyleRecord*& pEntry = (C3GPPStyleRecord*&)(m_entries[idx]);
  332. delete pEntry;
  333.     }
  334.     m_entries.Reset(0);
  335. }
  336. HX_RESULT C3GPPTextKaraokeBox::Build(const UINT8*& pData)
  337. {
  338.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextKaraokeBox::Build()n"));
  339.     HX_RESULT hr = HXR_OK;
  340.     m_ul1stHighlightStartTime = ReadUL32(pData);
  341.     UINT16 entryCount = ReadUI16(pData);
  342.     HX_ASSERT(m_entries.GetCount() == 0);
  343.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextKaraokeBox::Build(): %u entriesn", entryCount));
  344.     hr = m_entries.Reset(entryCount);
  345.     if(SUCCEEDED(hr))
  346.     {
  347.         for(UINT16 idx = 0; idx < entryCount; ++idx)
  348.         {
  349.             C3GPPTextKaraokeControlEntry* pEntry = new C3GPPTextKaraokeControlEntry();
  350.             if(!pEntry)
  351.             {
  352.                 return HXR_OUTOFMEMORY;
  353.             }
  354.             hr = pEntry->Build(pData);
  355.             if(FAILED(hr))
  356.             {
  357.                 HX_ASSERT(false);
  358.                 HX_DELETE(pEntry);
  359.                 break;
  360.             }
  361.             m_entries[idx] = pEntry;
  362.         }
  363.     }
  364.     return hr;
  365. }
  366. C3GPPTextKaraokeBox::~C3GPPTextKaraokeBox()
  367. {
  368.     CleanUp();
  369. }
  370. void C3GPPTextKaraokeBox::CleanUp()
  371. {
  372.     for ( INT32 idx = 0; idx != m_entries.GetCount(); ++idx )
  373.     {
  374. C3GPPTextKaraokeControlEntry*& pEntry = (C3GPPTextKaraokeControlEntry*&)(m_entries[idx]);
  375. delete pEntry;
  376.     }
  377.     m_entries.Reset(0);
  378. }
  379. HX_RESULT C3GPPTextKaraokeBox::C3GPPTextKaraokeControlEntry::Build(const UINT8*& pData)
  380. {
  381.     m_ulHighlightEndTime = ReadUL32(pData);
  382.     m_uiStartCharOffset = ReadUI16(pData); 
  383.     m_uiEndCharOffset = ReadUI16(pData);
  384.     return HXR_OK;
  385. }
  386. HX_RESULT C3GPPTextContainer::BuildKROK(const UINT8*& pData, 
  387.                                         UINT16& uiLowestPotentialNextTCStartOffsetFound,
  388.                                         BOOL& bNeedToBreakTCsUpAtNewlines,
  389.                                         UINT16& curEndCharOffset)
  390. {
  391.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildKROK()n"));
  392.     HX_ASSERT(!m_pTextKaraokeBox);
  393.  
  394.     m_pTextKaraokeBox = new C3GPPTextKaraokeBox();
  395.     if(!m_pTextKaraokeBox)
  396.     {
  397.         return HXR_OUTOFMEMORY;
  398.     }
  399.     HX_RESULT hr = m_pTextKaraokeBox->Build(pData);
  400.     if(SUCCEEDED(hr))
  401.     {
  402.         BOOL bAssignBoxToCurrent = FALSE;
  403.         m_uiTextKaraokeBoxIndex = HX_3GPPTT_INVALID_INDEX;
  404.         // /Go through the array of C3GPPTextKaraokeControlEntry(s)
  405.         // & look at their m_uiStartCharOffset & m_uiEndCharOffset.
  406.         // If all are fully before or fully after, ignore the
  407.         // whole enchilada:
  408.         UINT16 uiEntryCount = m_pTextKaraokeBox->GetEntryCount();
  409.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildKROK(): %u entriesn", uiEntryCount));
  410.         for (UINT16 uiCurEntry = 0; uiCurEntry < uiEntryCount; uiCurEntry++)
  411.         {
  412.             const C3GPPTextKaraokeBox::C3GPPTextKaraokeControlEntry*
  413.                     pCurKaraokeCtrlEntry =
  414.                     m_pTextKaraokeBox->GetKaraokeControlEntry(uiCurEntry);
  415.             HX_ASSERT(pCurKaraokeCtrlEntry);
  416.             if (pCurKaraokeCtrlEntry)
  417.             {
  418.                 UINT16 uiCurStartCharOffset =
  419.                         pCurKaraokeCtrlEntry->GetStartOffset();
  420.                 curEndCharOffset =
  421.                         pCurKaraokeCtrlEntry->GetEndOffset();
  422.                 DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildKROK(): range %u, %un", uiCurStartCharOffset, curEndCharOffset));
  423.                 if (HXR_OK != UpdateLowestPotentialNextTCStartOffset(
  424.                         uiCurStartCharOffset, curEndCharOffset,
  425.                         /*REF IN/OUT */ uiLowestPotentialNextTCStartOffsetFound,
  426.                         /*REF OUT*/ bAssignBoxToCurrent) )
  427.                 {
  428.                     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildKROK(): discarding entry %u n", uiCurEntry));
  429.                     continue; // /Ignore this entry; bad data.
  430.                 }
  431.                 if (bAssignBoxToCurrent)
  432.                 {
  433.                     m_uiTextKaraokeBoxIndex = uiCurEntry;
  434.                     break;
  435.                 }
  436.             }
  437.         }
  438.         if (HX_3GPPTT_INVALID_INDEX == m_uiTextKaraokeBoxIndex)
  439.         {
  440.             // /All Karaoke control entries are before or after,
  441.             // so ignore this entire karaoke modifier:
  442.             HX_DELETE(m_pTextKaraokeBox);
  443.         }
  444.         bNeedToBreakTCsUpAtNewlines = TRUE;
  445.     }
  446.     else
  447.     {
  448.         HX_ASSERT(false);
  449.         HX_DELETE(m_pTextKaraokeBox);
  450.     }
  451.     return hr;
  452. }
  453. HX_RESULT C3GPPTextContainer::BuildDLAY(const UINT8*& pData)
  454. {        
  455.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildDLAY()n"));
  456.     HX_ASSERT(!m_pTextScrollDelayBox);
  457.     m_pTextScrollDelayBox = new C3GPPTextScrollDelayBox();
  458.     if(!m_pTextScrollDelayBox)
  459.     {
  460.         return HXR_OUTOFMEMORY;
  461.     }
  462.     HX_RESULT hr = m_pTextScrollDelayBox->Build(pData);
  463.     if(FAILED(hr))
  464.     {
  465.         HX_ASSERT(false);
  466.         HX_DELETE(m_pTextScrollDelayBox);
  467.     }
  468.     return hr;
  469.     
  470. }
  471. HX_RESULT C3GPPTextContainer::BuildHCLR(const UINT8*& pData)
  472. {        
  473.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHCLR()n"));
  474.     HX_ASSERT(!m_pTextHilightColorBox);
  475.     m_pTextHilightColorBox = new C3GPPTextHilightColorBox();
  476.     if(!m_pTextHilightColorBox)
  477.     {
  478.         return HXR_OUTOFMEMORY;
  479.     }
  480.     HX_RESULT hr = m_pTextHilightColorBox->Build(pData);
  481.     if(FAILED(hr))
  482.     {
  483.         HX_ASSERT(false);
  484.         HX_DELETE(m_pTextHilightColorBox);
  485.     }
  486.     return hr;
  487. }
  488. HX_RESULT C3GPPTextContainer::BuildTBOX(const UINT8*& pData)
  489. {        
  490.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildTBOX(): text boxn"));
  491.     HX_ASSERT(!m_pTextboxBox);
  492.     m_pTextboxBox = new C3GPPTextboxBox();
  493.     if(!m_pTextboxBox)
  494.     {
  495.         return HXR_OUTOFMEMORY;
  496.     }
  497.     HX_RESULT hr = m_pTextboxBox->Build(pData);
  498.     if(FAILED(hr))
  499.     {
  500.         HX_ASSERT(false);
  501.         HX_DELETE(m_pTextboxBox);
  502.     }
  503.     return hr;
  504. }
  505.   
  506. HX_RESULT C3GPPTextContainer::BuildHLIT(const UINT8*& pData, 
  507.                                         UINT16& uiLowestPotentialNextTCStartOffsetFound,
  508.                                         BOOL& bNeedToBreakTCsUpAtNewlines,
  509.                                         UINT16& curEndCharOffset)
  510. {
  511.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHLIT()n"));
  512.     HX_ASSERT(!m_pTextHighlightBox);
  513.  
  514.     m_pTextHighlightBox = new C3GPPTextHighlightBox();
  515.     if(!m_pTextHighlightBox)
  516.     {
  517.         return HXR_OUTOFMEMORY;
  518.     }
  519.     HX_RESULT hr = m_pTextHighlightBox->Build(pData);
  520.     if(SUCCEEDED(hr))
  521.     {
  522.         BOOL bAssignBoxToCurrent = FALSE;
  523.         UINT16 uiCurStartCharOffset = m_pTextHighlightBox->GetStartOffset();
  524.         curEndCharOffset = m_pTextHighlightBox->GetEndOffset();
  525.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHLIT(): range %u, %un", uiCurStartCharOffset, curEndCharOffset));
  526.         // /If data is bad or if this is out of range, then
  527.         // this hlit box is not this's modifier:
  528.         if (HXR_OK != UpdateLowestPotentialNextTCStartOffset(
  529.                 uiCurStartCharOffset, curEndCharOffset,
  530.                 /*REF IN/OUT */ uiLowestPotentialNextTCStartOffsetFound,
  531.                 /*REF OUT*/ bAssignBoxToCurrent)
  532.                 // /FALSE means this is out of box's range:
  533.                 || !bAssignBoxToCurrent)
  534.         {
  535.             DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHLIT(): discardingn"));
  536.             HX_DELETE(m_pTextHighlightBox);
  537.         }
  538.         
  539.         bNeedToBreakTCsUpAtNewlines = TRUE;
  540.     }
  541.     else
  542.     {
  543.         HX_ASSERT(false);
  544.         HX_DELETE(m_pTextBlinkBox);
  545.     }
  546.     return hr;
  547. }
  548. HX_RESULT C3GPPTextContainer::BuildHREF(const UINT8*& pData, 
  549.                                         UINT16& uiLowestPotentialNextTCStartOffsetFound,
  550.                                         BOOL& bNeedToBreakTCsUpAtNewlines,
  551.                                         UINT16& curEndCharOffset)
  552. {
  553.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHREF()n"));
  554.     HX_ASSERT(!m_pTextHyperTextBox);
  555.     m_pTextHyperTextBox = new C3GPPTextHyperTextBox();
  556.     if(!m_pTextHyperTextBox)
  557.     {
  558.         return HXR_OUTOFMEMORY;
  559.     }
  560.     HX_RESULT hr = m_pTextHyperTextBox->Build(pData);
  561.     if(SUCCEEDED(hr))
  562.     {
  563.         BOOL bAssignBoxToCurrent = FALSE;
  564.         UINT16 uiCurStartCharOffset = m_pTextHyperTextBox->GetStartOffset();
  565.         curEndCharOffset = m_pTextHyperTextBox->GetEndOffset();
  566.             
  567.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHREF(): range %u, %un", uiCurStartCharOffset, curEndCharOffset));
  568.         // /If data is bad or if this is out of range, then
  569.         // this hlit box is not this's modifier:
  570.         if (HXR_OK != UpdateLowestPotentialNextTCStartOffset(
  571.                 uiCurStartCharOffset, curEndCharOffset,
  572.                 /*REF IN/OUT */ uiLowestPotentialNextTCStartOffsetFound,
  573.                 /*REF OUT */ bAssignBoxToCurrent)
  574.                 // /FALSE means this is out of box's range:
  575.                 || !bAssignBoxToCurrent)
  576.         {
  577.             DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildHREF(): discardingn"));
  578.             HX_DELETE(m_pTextHyperTextBox);
  579.         }
  580.         
  581.         bNeedToBreakTCsUpAtNewlines = TRUE;
  582.     }
  583.     else
  584.     {
  585.         HX_ASSERT(false);
  586.         HX_DELETE(m_pTextHyperTextBox);
  587.     }
  588.     return hr;
  589. }
  590. HX_RESULT C3GPPTextContainer::BuildBLNK(const UINT8*& pData, 
  591.                                         UINT16& uiLowestPotentialNextTCStartOffsetFound,
  592.                                         BOOL& bNeedToBreakTCsUpAtNewlines,
  593.                                         UINT16& curEndCharOffset)
  594. {
  595.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildBLNK()n"));
  596.     HX_ASSERT(!m_pTextBlinkBox);
  597.     m_pTextBlinkBox = new C3GPPTextBlinkBox();
  598.     if(!m_pTextBlinkBox)
  599.     {
  600.         return HXR_OUTOFMEMORY;
  601.     }
  602.     HX_RESULT hr = m_pTextBlinkBox->Build(pData);
  603.     if(SUCCEEDED(hr))
  604.     {
  605.         BOOL bAssignBoxToCurrent = FALSE;
  606.         UINT16 uiCurStartCharOffset = m_pTextBlinkBox->GetStartOffset();
  607.         curEndCharOffset = m_pTextBlinkBox->GetEndOffset();
  608.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildBLNK(): range %u, %un", uiCurStartCharOffset, curEndCharOffset));
  609.         // /If data is bad or if this is out of range, then
  610.         // this hlit box is not this's modifier:
  611.         if (HXR_OK != UpdateLowestPotentialNextTCStartOffset(
  612.                 uiCurStartCharOffset, curEndCharOffset,
  613.                 /*REF IN/OUT */ uiLowestPotentialNextTCStartOffsetFound,
  614.                 /*REF OUT */ bAssignBoxToCurrent)
  615.                 // /FALSE means this is out of box's range:
  616.                 || !bAssignBoxToCurrent)
  617.         {
  618.             DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildBLNK(): discardingn"));
  619.             HX_DELETE(m_pTextBlinkBox);
  620.         }
  621.         
  622.         bNeedToBreakTCsUpAtNewlines = TRUE;
  623.     }
  624.     else
  625.     {
  626.         HX_ASSERT(false);
  627.         HX_DELETE(m_pTextBlinkBox);
  628.     }
  629.     return hr;
  630. }
  631. HX_RESULT C3GPPTextContainer::BuildSTYL(const UINT8*& pData, 
  632.                                         UINT16& uiLowestPotentialNextTCStartOffsetFound,
  633.                                         BOOL& bNeedToBreakTCsUpAtNewlines,
  634.                                         UINT16& curEndCharOffset)
  635. {
  636.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSTYL()n"));
  637.     HX_ASSERT(!m_pTextStyleBox);
  638.     m_pTextStyleBox = new C3GPPTextStyleBox();
  639.     if(!m_pTextStyleBox)
  640.     {
  641.         return HXR_OUTOFMEMORY;
  642.     }
  643.     HX_RESULT hr = m_pTextStyleBox->Build(pData);
  644.     if(SUCCEEDED(hr))
  645.     {
  646.         BOOL bAssignBoxToCurrent = FALSE;
  647.         m_uiTextStyleBoxIndex = HX_3GPPTT_INVALID_INDEX;
  648.         // /Go through the array of C3GPPStyleRecords and look
  649.         // at their m_uiStartCharOffset and m_uiEndCharOffset.
  650.         // If all are fully before or fully after, ignore the
  651.         // whole shebang:
  652.         UINT16 uiEntryCount = m_pTextStyleBox->GetEntryCount();
  653.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSTYL(): %u entriesn", uiEntryCount));
  654.         for (UINT16 uiCurEntry = 0; uiCurEntry < uiEntryCount; uiCurEntry++)
  655.         {
  656.             const C3GPPStyleRecord* pCurStyleRecord =
  657.                     m_pTextStyleBox->GetStyleRecord(uiCurEntry);
  658.             HX_ASSERT(pCurStyleRecord);
  659.             if (pCurStyleRecord)
  660.             {
  661.                 UINT16 uiCurStartCharOffset = pCurStyleRecord->GetStartOffset();
  662.                 curEndCharOffset = pCurStyleRecord->GetEndOffset();
  663.                 DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSTYL(): [entry %u] range %u, %un", uiCurEntry, uiCurStartCharOffset, curEndCharOffset));
  664.                 if (HXR_OK != UpdateLowestPotentialNextTCStartOffset(
  665.                         uiCurStartCharOffset, curEndCharOffset,
  666.                         /*REF IN/OUT */ uiLowestPotentialNextTCStartOffsetFound,
  667.                         /*REF OUT*/ bAssignBoxToCurrent) )
  668.                 {
  669.                     // ignore, bad data
  670.                     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSTYL(): discardingn"));
  671.                     continue;
  672.                 }
  673.                 if (bAssignBoxToCurrent)
  674.                 {
  675.                     m_uiTextStyleBoxIndex = uiCurEntry;
  676.                     break;
  677.                 }
  678.             }
  679.         }
  680.      
  681.     
  682.         if (HX_3GPPTT_INVALID_INDEX == m_uiTextStyleBoxIndex)
  683.         {
  684.             // /All style records are before or after, so
  685.             // ignore entire style modifier:
  686.             HX_DELETE(m_pTextStyleBox);
  687.         }
  688.         bNeedToBreakTCsUpAtNewlines = TRUE;
  689.     }
  690.     else
  691.     {
  692.         HX_ASSERT(false);
  693.         HX_DELETE(m_pTextStyleBox);
  694.     }
  695.     return hr;
  696. }
  697. HX_RESULT C3GPPTextContainer::BuildSampleModifiers(BOOL& bNeedToBreakTCsUpAtNewlines)
  698. {
  699.     DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSampleModifiers()n"));
  700.     bNeedToBreakTCsUpAtNewlines = FALSE;
  701.     HX_ASSERT(m_pTextSample);
  702.     if (!m_pTextSample->GetModifierData())
  703.     {
  704.         // no modifiers; no work to do
  705.         DPRINTF(D_TIMEDTEXT, ("C3GPPTextContainer::BuildSampleModifiers(): no sample modifiersn"));
  706.         return HXR_OK;
  707.     }
  708.             
  709.     HX_RESULT hr = HXR_OK;
  710.     // /Walk the sampleModifier array and find the next start-
  711.     // index boundary that is greater than m_uiStartCharOffset;
  712.     // What we find, if any, is 1 + our end index:
  713.     UINT16 uiLowestPotentialNextTCStartOffsetFound =
  714.             HX_3GPPTT_MAX_CHAR_OFFSET;
  715.     UINT16 curEndCharOffset = HX_3GPPTT_INVALID_INDEX;
  716.     
  717.     const UINT8* pData = m_pTextSample->GetModifierData();
  718.     HX_ASSERT(m_pTextSample->GetModifierDataSize() > 0);
  719.     const UINT8* pDataEnd = pData + m_pTextSample->GetModifierDataSize();
  720.     while (pData < pDataEnd)
  721.     {
  722.         // get sample modifier type and size
  723.         C3GPPTextSampleModifierBox box;
  724.         
  725.         hr = box.Build(pData);
  726.         HX_ASSERT(HXR_OK == hr);
  727.         if(pData + box.GetDataSize() > pDataEnd)
  728.         {
  729.             HX_ASSERT(false);
  730.             hr = HXR_FAIL;
  731.             break;
  732.         }
  733.         // create sample modifier object for this modifier type
  734.         switch(box.GetType())
  735.         {
  736.         case C3GPPTextSampleModifierBox::STYL:
  737.             hr = BuildSTYL(pData, 
  738.                 uiLowestPotentialNextTCStartOffsetFound, 
  739.                 bNeedToBreakTCsUpAtNewlines, curEndCharOffset);
  740.             break;
  741.         case C3GPPTextSampleModifierBox::HLIT:
  742.              hr = BuildHLIT(pData, 
  743.                 uiLowestPotentialNextTCStartOffsetFound, 
  744.                 bNeedToBreakTCsUpAtNewlines, curEndCharOffset);
  745.             break;
  746.         case C3GPPTextSampleModifierBox::HCLR:
  747.             hr = BuildHCLR(pData);
  748.             break;
  749.         case C3GPPTextSampleModifierBox::KROK:
  750.             hr = BuildKROK(pData, 
  751.                 uiLowestPotentialNextTCStartOffsetFound, 
  752.                 bNeedToBreakTCsUpAtNewlines, curEndCharOffset);
  753.             break;
  754.         case C3GPPTextSampleModifierBox::DLAY:
  755.             hr = BuildDLAY(pData);
  756.             break;
  757.         case C3GPPTextSampleModifierBox::HREF:
  758.             hr = BuildHREF(pData, 
  759.                 uiLowestPotentialNextTCStartOffsetFound,
  760.                 bNeedToBreakTCsUpAtNewlines, curEndCharOffset);
  761.             break;
  762.         case C3GPPTextSampleModifierBox::TBOX:
  763.             hr = BuildTBOX(pData);
  764.             break;
  765.         case C3GPPTextSampleModifierBox::BLNK:
  766.             hr = BuildBLNK(pData, 
  767.                 uiLowestPotentialNextTCStartOffsetFound, 
  768.                 bNeedToBreakTCsUpAtNewlines, curEndCharOffset);
  769.             break;
  770.         default:
  771.             HX_ASSERT(false); //XXXLCM skip unknown types?
  772.             hr = HXR_FAIL;
  773.             break;
  774.         }
  775.         if(FAILED(hr))
  776.         {
  777.             HX_ASSERT(false);
  778.             break;
  779.         }
  780.        
  781.         // we should consume the box data size exactly
  782.         HX_ASSERT( UINT32(pData - box.GetData()) == box.GetDataSize());
  783.         // /If we found one, then use it if it's lowest so far:
  784.         if (curEndCharOffset <
  785.                 uiLowestPotentialNextTCStartOffsetFound  &&
  786.                 // /Ignore if end is prior to our start:
  787.                 // /(Changed '>=' to '>' to prevent infinite loop)
  788.                 curEndCharOffset > m_uiUnpackedStartCharOffset)
  789.         {
  790.             uiLowestPotentialNextTCStartOffsetFound =
  791.                     curEndCharOffset;
  792.         }
  793.     }
  794.     if(SUCCEEDED(hr))
  795.     {
  796.         // we should always end up exactly at end of data
  797.         HX_ASSERT(pData == pDataEnd);
  798.         // /OK, our end char offset is one less than the lowest start
  799.         // of the next T.C. found, above, (& not less than our start):
  800.         HX_ASSERT(uiLowestPotentialNextTCStartOffsetFound > 0);
  801.         if (HX_3GPPTT_MAX_CHAR_OFFSET !=
  802.                 uiLowestPotentialNextTCStartOffsetFound)
  803.         {
  804.             // /Don't add 1 here; it's end-point exclusive:
  805.             m_uiUnpackedEndCharOffset = uiLowestPotentialNextTCStartOffsetFound;
  806.         }
  807.         else
  808.         {
  809.             m_uiUnpackedEndCharOffset = HX_3GPPTT_MAX_CHAR_OFFSET;
  810.         }
  811.     }
  812.     return hr;
  813.             
  814. }
  815. HX_RESULT C3GPPTextContainer::Init
  816. (
  817.     IHXPacket* pPacket,
  818.     UINT32 ulPacketContentsBeginTime,
  819.     UINT32 ulMaxEndTime,
  820.     UINT16 uiStartCharOffset, 
  821.     /*OUT*/ UINT16& uiREFIndexOfLastChar)
  822. {
  823.     HX_RESULT hxr = HXR_OK;
  824.     HX_ASSERT(pPacket);
  825.     m_pPacket = pPacket;
  826.     m_pPacket->AddRef();
  827.     m_ulEndTime = ulMaxEndTime; // /Initialize for now to this
  828.     m_ulBeginTime = ulPacketContentsBeginTime;
  829.     m_uiUnpackedStartCharOffset = uiStartCharOffset;
  830.     uiREFIndexOfLastChar = HX_3GPPTT_INVALID_INDEX;
  831.     BOOL bNeedToBreakTCsUpAtNewlines = FALSE;
  832.     
  833.     // /Go through the textModifiers of the packet and figure out what our
  834.     // end index is in the text buffer based on where the end of same-
  835.     // attributed continguous text ends.  Return the end index in
  836.     // uiREFIndexOfLastChar so, if there's any text remaining, another
  837.     // C3GPPTextContainer can be created knowing where to start:
  838. //-----------------------------------------------------------------------------
  839.     IHXBuffer* pBuff = m_pPacket->GetBuffer();
  840.     if (pBuff)
  841.     {
  842.         BOOL bTextIsUTF16ReverseEncoded = FALSE;
  843.         BOOL bTextIsUTF16Encoded = FALSE;
  844.         m_pTextSample = new C3GPPTextSample(pBuff);
  845.         HX_ASSERT(m_pTextSample);
  846.         if (!m_pTextSample)
  847.         {
  848.             hxr = HXR_OUTOFMEMORY;
  849.             goto cleanup;
  850.         }
  851.         bTextIsUTF16Encoded = IsUTF16Encoded(
  852.                 (UCHAR*)(m_pTextSample->GetText()),
  853.                 m_pTextSample->GetTextLenInBytes(),
  854.                 bTextIsUTF16ReverseEncoded);
  855.         hxr = BuildSampleModifiers(bNeedToBreakTCsUpAtNewlines);
  856.         if(FAILED(hxr))
  857.         {
  858.             goto cleanup;
  859.         }
  860.         // /XXXEH- TODO: this is not UTF-8 friendly code (when 2-byte
  861.         // 00r or 00n chars are present)!  Also, r or n may be 2nd
  862.         // byte of a 2-byte value and not meant as a newline (CR or LF,
  863.         // respectively) char!
  864.         // /Before patting ourselves on the back for finding the start &
  865.         // end offsets of this text container, we need to look for
  866.         // newline characters and break up TC's at each new-line
  867.         // character, but only if m_pTextSample->m_pTextModifiers exists
  868.         // and modified individual parts of the text and not just the
  869.         // entire thing, e.g., as 'tbox' does.  Otherwise it's OK to
  870.         // leave entire packet's text as one TextContainer even if it
  871.         // has newline chars:
  872.         // /Note: these are the supported UNICODE text wrap controls:
  873.         //  u000a (LF)
  874.         //  u000d (CR)
  875.         //  u000du000a (CRLF)
  876.         //  u0085 (NEXT LINE)
  877.         //  u2028 (LINE SEP)
  878.         //  u2029 (PARA SEP)
  879. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  880.         // /Convert to UTF-16 then go through and start a new
  881.         // TextContainer wherever a newline char is found that
  882.         // does not immediately follow another newline:
  883.         HX_RESULT hxrsltCnvrtChars = HXR_OK;
  884.         HBufC16* pHBufUTF16Text = NULL;
  885.         HBufC8*  pHBufUTF8Text = NULL;
  886.         const char* pUnconvertedText = m_pTextSample->GetText() + m_uiUnpackedStartCharOffset;
  887.         INT32 lUnconvertedTextLen = (INT32)
  888.                 ((UINT32)GetTextByteLength());
  889.         HX_ASSERT(m_uiUnpackedEndCharOffset >= (UINT32)lUnconvertedTextLen);
  890.         BOOL bDummyVar = FALSE;
  891.         BOOL bTextContainerTextStartsWithUTF16EncodeFlag =
  892.                 IsUTF16Encoded((UCHAR*)pUnconvertedText,
  893.                 lUnconvertedTextLen,
  894.                 bDummyVar);
  895.         INT32 lTextLenInChars = lUnconvertedTextLen;
  896.         if (bTextIsUTF16Encoded)
  897.         {
  898.             HX_ASSERT(!(lTextLenInChars & 0x1)); // /Shouldn't be odd
  899.             lTextLenInChars >>= 1; // /Divide by 2: 2 bytes/char
  900.             if (bTextContainerTextStartsWithUTF16EncodeFlag)
  901.             {
  902.                 // /Skip past 0xfffe UTF-16 flag at start:
  903.                 pUnconvertedText += 2;
  904.                 lTextLenInChars--;
  905.             }
  906.         }
  907.         if (hxrsltCnvrtChars==HXR_OK  &&  pUnconvertedText  &&
  908.                 lUnconvertedTextLen > 0)
  909.         {
  910.             pHBufUTF16Text = HBufC16::NewMax((TInt)lTextLenInChars);
  911.             if (pHBufUTF16Text)
  912.             {
  913.                 TInt tiNumLinesOfText = 1;
  914.                 // /UTF-8 to UTF-16 translation:
  915.                 if (bTextIsUTF16Encoded)
  916.                 {
  917.                     TInt leadByteOffset = 0;
  918.                     TInt trailingByteOffset = 1;
  919.                     if (bTextIsUTF16ReverseEncoded)
  920.                     {
  921.                         leadByteOffset = 1;
  922.                         trailingByteOffset = 0;
  923.                     }
  924.                     for (TInt i = 0; i < (TInt)lTextLenInChars ; i++)
  925.                     {
  926.                         pHBufUTF16Text->Des()[i] =
  927.                                 ((UINT16)(pUnconvertedText[
  928.                                     (i*2)+leadByteOffset])) <<8 |
  929.                                 pUnconvertedText[
  930.                                     (i*2)+trailingByteOffset];
  931.                     }
  932.                 }
  933.                 else
  934.                 {
  935.                     pHBufUTF8Text = HBufC8::NewMax((TInt)lTextLenInChars);
  936.                     for (TInt i = 0; i < (TInt)lTextLenInChars ; i++) 
  937.                     {
  938.                         pHBufUTF8Text->Des()[i] =
  939.                                 (UINT8)(pUnconvertedText[i]);
  940.                     }
  941.                     TInt kErr =
  942.                             CnvUtfConverter::ConvertToUnicodeFromUtf8(
  943.                             pHBufUTF16Text->Des(),
  944.                             pHBufUTF8Text->Des() );
  945.                     delete pHBufUTF8Text;
  946.                 }
  947.                 // /Now step through UTF-16 chars in pHBufUTF16Text:
  948.                 const TInt iStrLen16 = pHBufUTF16Text->Length();
  949.                 HX_ASSERT(iStrLen16);
  950.                 if (iStrLen16)
  951.                 {
  952.                     TInt tiChars = 0;
  953.                     TInt tiNewlines = 0;
  954.                     UINT16 ch16 =
  955.                             pHBufUTF16Text->Des()[tiChars];
  956.                     BOOL bPriorCharWasCarriageReturn = FALSE;
  957.                     BOOL bCurCharIsCarriageReturn = FALSE;
  958.                     BOOL bCurCharIsAtomicNewline = FALSE;
  959.                     // /First, skip newline chars at the start:
  960.                     while (tiChars < iStrLen16  &&
  961.                             isUTF16NewlineChar(ch16,
  962.                             bPriorCharWasCarriageReturn,
  963.                             /*REF*/ bCurCharIsCarriageReturn,
  964.                             /*REF*/ bCurCharIsAtomicNewline) )
  965.                     {
  966.                         tiChars++;
  967.                         // /If it's not LF of CRLF, then ++ newlines:
  968.                         if (bCurCharIsAtomicNewline)
  969.                         {
  970.                             tiNewlines++;
  971.                         }
  972.                         if (tiChars >= iStrLen16)
  973.                         {
  974.                             break;
  975.                         }
  976.                         ch16 = pHBufUTF16Text->Des()[tiChars];
  977.                         bPriorCharWasCarriageReturn =
  978.                                 bCurCharIsCarriageReturn;
  979.                     }
  980.                     m_lNumUTF16NewlinesAtStart = (INT16)tiNewlines;
  981.                     m_lNumUTF16NewlineCharsAtStart = (INT16)tiChars;
  982.                     // /Next, find any newline chars in the middle:
  983.                     bPriorCharWasCarriageReturn = FALSE;
  984.                     while (tiChars < iStrLen16)
  985.                     {
  986.                         ch16 = pHBufUTF16Text->Des()[tiChars];
  987.                         if (isUTF16NewlineChar(ch16,
  988.                                 bPriorCharWasCarriageReturn,
  989.                                 /*REF*/ bCurCharIsCarriageReturn,
  990.                                 /*REF*/ bCurCharIsAtomicNewline))
  991.                         {
  992.                             // /Start a new TextContainer at this
  993.                             // newline char:
  994.                             m_uiUnpackedEndCharOffset = tiChars +
  995.                                     // /Add offset to get it back into
  996.                                     // proper coords:
  997.                                     m_uiUnpackedStartCharOffset;
  998.                             break;
  999.                         }
  1000.                         bPriorCharWasCarriageReturn =
  1001.                                 bCurCharIsCarriageReturn;
  1002.                         tiChars++;
  1003.                     }
  1004.                 }
  1005.             }
  1006.         }
  1007. #else  // / else not _SYMBIAN                                                  ------------------------------------
  1008.         if (bNeedToBreakTCsUpAtNewlines)
  1009.         {
  1010.             const char* pTextOfThis = m_pTextSample->GetText() + m_uiUnpackedStartCharOffset;
  1011.             HX_ASSERT(pTextOfThis); // /Asserted? notify ehodge@real.com w/.3gp content
  1012.             if (pTextOfThis)
  1013.             {
  1014.                 UINT16 uiLen = GetTextByteLength();
  1015. #pragma message("&&&& XXXEH- 20031027- check for UTF8 or UTF16; if 16, step by 2's. If 8... &&&&")
  1016.                 BOOL bIsReverseUTF16 = FALSE;
  1017.                 BOOL bIsUTF16 = IsUTF16Encoded(pTextOfThis,
  1018.                         (INT32)uiLen, bIsReverseUTF16);
  1019.                 const UCHAR* pStepper = pTextOfThis;
  1020.                 // /First, skip newline chars at the start:
  1021.                 while (('r' == *pStepper  ||  'n' == *pStepper)  &&
  1022.                         pStepper < pTextOfThis + uiLen)
  1023.                 {
  1024.                     pStepper++;
  1025.                 }
  1026.                 // /Next, find any newline chars in the middle:
  1027.                 do
  1028.                 {
  1029.                     if ('r' == *pStepper  ||  'n' == *pStepper)
  1030.                     {
  1031.                         // /Start a new TextContainer at this newline char:
  1032.                         m_uiUnpackedEndCharOffset = pStepper - pTextOfThis +
  1033.                                 // /Need offset to get back into proper coords:
  1034.                                 m_uiUnpackedStartCharOffset;
  1035.                         break;
  1036.                     }
  1037.                 } while (++pStepper < pTextOfThis + uiLen);
  1038.             }
  1039.         }
  1040. #endif // /if _SYMBIAN else...                                                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1041.     }
  1042. //-----------------------------------------------------------------------------
  1043.     
  1044. cleanup:
  1045.     uiREFIndexOfLastChar = m_uiUnpackedEndCharOffset;
  1046.     return hxr;
  1047. }
  1048. C3GPPTextContainer::C3GPPTextContainer() 
  1049. : m_pPacket(NULL)
  1050. , m_pTextSample(NULL)
  1051. , m_uiUnpackedStartCharOffset(HX_3GPPTT_INVALID_INDEX)
  1052. , m_uiUnpackedEndCharOffset(HX_3GPPTT_INVALID_INDEX)
  1053. , m_uiTextStyleBoxIndex(HX_3GPPTT_INVALID_INDEX)
  1054. , m_uiTextKaraokeBoxIndex(HX_3GPPTT_INVALID_INDEX)
  1055. , m_pTextStyleBox(NULL)
  1056. , m_pTextHighlightBox(NULL)
  1057. , m_pTextHilightColorBox(NULL)
  1058. , m_pTextKaraokeBox(NULL)
  1059. , m_pTextScrollDelayBox(NULL)
  1060. , m_pTextHyperTextBox(NULL)
  1061. , m_pTextboxBox(NULL)
  1062. , m_pTextBlinkBox(NULL)
  1063. , m_ulBeginTime(HX_3GPPTT_INVALID_TIME)
  1064. , m_ulEndTime(HX_3GPPTT_INVALID_TIME) 
  1065. , m_ulNextDrawUpdateTimeOffset(0)
  1066. , m_ulPrevDrawUpdateTimeOffset(HX_3GPPTT_INVALID_TIME)
  1067. , m_lNumUTF16NewlineCharsAtStart(HX_3GPPTT_INVALID_INT16)
  1068. , m_lNumUTF16NewlinesAtStart(HX_3GPPTT_INVALID_INT16)
  1069. {
  1070.     m_BoundingRectOfInitialDraw.left = m_BoundingRectOfInitialDraw.right = 0;
  1071.     m_BoundingRectOfInitialDraw.top = m_BoundingRectOfInitialDraw.bottom = 0;
  1072.     
  1073. }
  1074. C3GPPTextContainer::~C3GPPTextContainer()
  1075. {
  1076.     HX_RELEASE(m_pPacket);
  1077.     HX_DELETE(m_pTextSample);
  1078.     HX_DELETE(m_pTextStyleBox);
  1079.     HX_DELETE(m_pTextHighlightBox);
  1080.     HX_DELETE(m_pTextHilightColorBox);
  1081.     HX_DELETE(m_pTextKaraokeBox);
  1082.     HX_DELETE(m_pTextScrollDelayBox);
  1083.     HX_DELETE(m_pTextHyperTextBox);
  1084.     HX_DELETE(m_pTextboxBox);
  1085.     HX_DELETE(m_pTextBlinkBox);
  1086. }
  1087. BOOL
  1088. C3GPPTextContainer::ContainsPoint(INT16 iX, INT16 iY) const
  1089. {
  1090.     return (   iX >= m_BoundingRectOfInitialDraw.left   &&
  1091.            iX <= m_BoundingRectOfInitialDraw.right  &&
  1092.            iY >= m_BoundingRectOfInitialDraw.top    &&
  1093.            iY <= m_BoundingRectOfInitialDraw.bottom);
  1094. }
  1095. HX_RESULT
  1096. C3GPPTextContainer::UpdateLowestPotentialNextTCStartOffset(
  1097.         UINT16 uiCurStartCharOffset, UINT16 uiCurEndCharOffset,
  1098.         UINT16& /*REF IN-&-OUT*/ uiLowestPotentialNextTCStartOffsetFound,
  1099.         BOOL&   /*REF OUT*/ bAssignBoxToCurrent)
  1100. {
  1101.     bAssignBoxToCurrent = FALSE; // /Initialize.
  1102.     // /Error if start is after end or even if they are equal since indices
  1103.     // are end-point exclusive:
  1104.     if (uiCurStartCharOffset >= uiCurEndCharOffset)
  1105.     {
  1106.         // /Don't bother asserting; it's a bad test file (3GPPtext-e-06-00.3gp)
  1107.         return HXR_UNEXPECTED; // /BAD DATA!
  1108.     }
  1109.     // /To avoid crash @ draw time w/corrupt data, make sure these don't
  1110.     // exceed the complete buffer's size:
  1111.     if (uiCurStartCharOffset > m_pTextSample->GetTextLenInBytes()  ||
  1112.             uiCurEndCharOffset > m_pTextSample->GetTextLenInBytes())
  1113.     {
  1114.         HX_ASSERT(uiCurStartCharOffset > m_pTextSample->GetTextLenInBytes());
  1115.         HX_ASSERT(uiCurEndCharOffset > m_pTextSample->GetTextLenInBytes());
  1116.         return HXR_UNEXPECTED; // /Ignore this entry.
  1117.     }
  1118.     if (m_uiUnpackedStartCharOffset >= uiCurStartCharOffset  &&
  1119.             uiCurEndCharOffset > // /(end-pt exclusive)
  1120.             m_uiUnpackedStartCharOffset)
  1121.     {
  1122.         bAssignBoxToCurrent = TRUE; // /this's begin is within current range
  1123.         HX_ASSERT(uiLowestPotentialNextTCStartOffsetFound >= uiCurEndCharOffset);
  1124.         if (uiLowestPotentialNextTCStartOffsetFound > uiCurEndCharOffset)
  1125.         {
  1126.             // /Don't add 1 here; it's end-point exclusive:
  1127.             uiLowestPotentialNextTCStartOffsetFound = uiCurEndCharOffset;
  1128.         }
  1129.     }
  1130.     // /Use start as potential end if lowest so far:
  1131.     else if (uiCurStartCharOffset < uiLowestPotentialNextTCStartOffsetFound  &&
  1132.             // /Ignore if prior to our start:
  1133.             uiCurStartCharOffset >= m_uiUnpackedStartCharOffset)
  1134.     {
  1135.         uiLowestPotentialNextTCStartOffsetFound = uiCurStartCharOffset;
  1136.         // /I think the logic of the if(), above,
  1137.         // handles this but I'm too lazy to check:
  1138.         HX_ASSERT(0 != uiLowestPotentialNextTCStartOffsetFound);
  1139.     }
  1140.     return HXR_OK;
  1141. }
  1142. UINT32
  1143. C3GPPTextContainer::GetNextActivityTime() const
  1144. {
  1145.     UINT32 ulBegin = GetBeginTime();
  1146.     if (HX_3GPPTT_INVALID_TIME == ulBegin)
  1147.     {
  1148.         return ulBegin;
  1149.     }
  1150.     return (m_ulNextDrawUpdateTimeOffset + ulBegin);
  1151. }
  1152. UINT32
  1153. C3GPPTextContainer::GetPrevActivityTime() const
  1154. {
  1155.     UINT32 ulBegin = GetBeginTime();
  1156.     if (HX_3GPPTT_INVALID_TIME == ulBegin  ||
  1157.             HX_3GPPTT_INVALID_TIME == m_ulPrevDrawUpdateTimeOffset)
  1158.     {
  1159.         return HX_3GPPTT_INVALID_TIME;
  1160.     }
  1161.     return (m_ulPrevDrawUpdateTimeOffset + ulBegin);
  1162. }
  1163. void
  1164. C3GPPTextContainer::SetPrevActivityTime(UINT32 ulAbsoluteTime)
  1165. {
  1166.     UINT32 ulBegin = GetBeginTime();
  1167.     if (HX_3GPPTT_INVALID_TIME == ulBegin  ||  ulBegin > ulAbsoluteTime)
  1168.     {
  1169.         m_ulPrevDrawUpdateTimeOffset = HX_3GPPTT_INVALID_TIME;
  1170.     }
  1171.     else
  1172.     {
  1173.         m_ulPrevDrawUpdateTimeOffset = ulAbsoluteTime - ulBegin;
  1174.     }
  1175. }