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

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.  * Defines
  37.  */
  38. #define INITGUID     /* Interface ID's */
  39. #if !defined(STRICT)
  40. #define STRICT
  41. #endif
  42. /****************************************************************************
  43.  * Includes
  44.  */
  45. #include "hxtypes.h"
  46. #include <stdlib.h>
  47. #include <ctype.h>
  48. #include <stdio.h>
  49. #include <string.h> // /for memset, strncmp, stricmp
  50. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  51. #include <gdi.h>       // /For CFont, TFontSpec, CGraphicsDevice, ...etc.
  52. #include <utf.h>  // /For CnvUtfConverter::ConvertToUnicodeFromUtf8();
  53. #include <coecntrl.h>
  54. #include <fbs.h>       // /For CFbsBitmap
  55. #include <eikenv.h>
  56. #endif // /_SYMBIAN                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  57. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  58.     #include <windows.h>
  59.     #include "platform\win\resource.h"
  60. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  61. #if defined(_UNIX) && (!(defined(_BEOS)))
  62.     #include <stdlib.h>
  63.     #include <unistd.h>
  64.     #include <X11/Intrinsic.h>
  65.     #include <X11/StringDefs.h>
  66.     #include <X11/Shell.h>
  67.     #include <X11/Xaw/Label.h>
  68. #endif
  69. #include "hxwintyp.h"
  70. #include "hxevent.h"
  71. #include "hxcom.h"
  72. #include "hxcomm.h"
  73. #include "chxpckts.h"
  74. #include "baseobj.h"
  75. #include "hxfiles.h"
  76. #include "hxcore.h"
  77. #include "hxrendr.h"
  78. #include "hxhyper.h"
  79. #include "hxplugn.h"
  80. #include "hxwin.h"
  81. #include "hxasm.h"
  82. #include "hxver.h"
  83. #include "hxvsurf.h"
  84. #include "hxslist.h"
  85. #include "hxtick.h" //for HX_GET_BETTERTICKCOUNT()
  86. #include "rule2flg.h" // /For RuleToFlagMap
  87. #include "3gppttstructs.h"
  88. #include "3gppttutils.h"
  89. #include "3gppttrenderer.h"
  90. #include "3gppttrenderer.ver"
  91. #include "hxheap.h"
  92. #ifdef _DEBUG
  93. #undef HX_THIS_FILE
  94. static const char HX_THIS_FILE[] = __FILE__;
  95. #endif
  96. // /#define XXXEH_DEBUGOUT_DRAW_3GPPTT
  97. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  98. #pragma message("====##### THIS CODE SHOULD NOT BE ENABLED IN SOURCE REPOSITORY #####====")
  99. static UINT32 ulCount;
  100. FILE* pFile = NULL;
  101. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  102. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  103. extern HINSTANCE g_hInstance;
  104. COLORREF convertARGBtoWinBGRColor(UINT32 ulARGBVal)
  105. {
  106.     COLORREF winColor = 0L;
  107.     UCHAR red, green, blue;
  108.     red = (UCHAR)(ulARGBVal>>16); //red is bytes 4,5
  109.     green = (UCHAR)(ulARGBVal>>8); //green is 2,3
  110.     blue = (UCHAR)ulARGBVal; //and blue is bytes 0,1
  111.     winColor = (COLORREF)red | (COLORREF(green)<<8) | 
  112.             (COLORREF(blue)<<16); 
  113.     return winColor;
  114. }
  115. #endif // /_WINDOWS.                                                           _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  116. //
  117. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  118. void convertARGBtoSymbianTrgbColor(TRgb& rgbColor,
  119.                                    UINT32 ulARGBVal)
  120. {
  121.     UCHAR red, green, blue;
  122.     red = (UCHAR)(ulARGBVal>>16); //red is bytes 4,5
  123.     green = (UCHAR)(ulARGBVal>>8); //green is 2,3
  124.     blue = (UCHAR)ulARGBVal; //and blue is bytes 0,1
  125.     // /TRgb is: 0x00bbggrr :
  126.     rgbColor = (UINT32)red | (UINT32(green)<<8) | 
  127.             (UINT32(blue)<<16);
  128. }
  129. #endif // /_SYMBIAN.                                                           _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  130. /****************************************************************************
  131.  *  HXCreateInstance                                        ref:  hxplugn.h
  132.  *
  133.  *  This routine creates a new instance of the C3GPPTimedTextRenderer class.
  134.  *  It is called when the Helix core application is launched, and whenever
  135.  *  a stream associated with this plug-in needs to be rendered.
  136.  */
  137. STDAPI
  138. ENTRYPOINT(HXCREATEINSTANCE)(IUnknown** ppIUnknown)
  139. {
  140.     *ppIUnknown = (IUnknown*)(IHXPlugin*)new C3GPPTimedTextRenderer();
  141.     if (*ppIUnknown)
  142.     {
  143.         (*ppIUnknown)->AddRef();
  144.         return HXR_OK;
  145.     }
  146.     return HXR_OUTOFMEMORY;
  147. }
  148. /****************************************************************************
  149.  * 
  150.  *  Function:
  151.  * 
  152.  *      CanUnload2()
  153.  * 
  154.  *  Purpose:
  155.  * 
  156.  *      Function implemented by all plugin DLL's if it returns HXR_OK 
  157.  *      then the pluginhandler can unload the DLL
  158.  *
  159.  */
  160. STDAPI ENTRYPOINT(CanUnload2)(void)
  161. {
  162.     return ((CHXBaseCountingObject::ObjectsActive() > 0) ?
  163.             HXR_FAIL : HXR_OK);
  164. }
  165. /****************************************************************************
  166.  *  C3GPPTimedTextRenderer static variables              ref:  3gppttrender.h
  167.  *
  168.  *  These variables are passed to the Helix core to provide information about
  169.  *  this plug-in. They are required to be static in order to remain valid
  170.  *  for the lifetime of the plug-in.
  171.  */
  172. const char* const C3GPPTimedTextRenderer::zm_pDescription    = "3GPP Timed Text Renderer Plugin";
  173. const char* const C3GPPTimedTextRenderer::zm_pCopyright      = HXVER_COPYRIGHT;
  174. const char* const C3GPPTimedTextRenderer::zm_pMoreInfoURL    = HXVER_MOREINFO;
  175. const char* const C3GPPTimedTextRenderer::zm_pStreamMimeTypes[] = {"video/X-RN-3GPP-TEXT", NULL};
  176. /****************************************************************************
  177.  *  IHXPlugin::GetPluginInfo                                ref:  hxplugn.h
  178.  *
  179.  *  This routine returns descriptive information about the plug-in, most
  180.  *  of which is used in the About box of the user interface. It is called
  181.  *  when the Helix core application is launched.
  182.  */
  183. STDMETHODIMP
  184. C3GPPTimedTextRenderer::GetPluginInfo
  185. (
  186.     REF(BOOL)        /*OUT*/ bLoadMultiple,
  187.     REF(const char*) /*OUT*/ pDescription,
  188.     REF(const char*) /*OUT*/ pCopyright,
  189.     REF(const char*) /*OUT*/ pMoreInfoURL,
  190.     REF(UINT32)      /*OUT*/ ulVersionNumber
  191. )
  192. {
  193.     bLoadMultiple   = TRUE;
  194.     pDescription    = zm_pDescription;
  195.     pCopyright      = zm_pCopyright;
  196.     pMoreInfoURL    = zm_pMoreInfoURL;
  197.     ulVersionNumber = TARVER_ULONG32_VERSION;
  198.     return HXR_OK;
  199. }
  200. /****************************************************************************
  201.  *  IHXRenderer::GetRendererInfo                            ref:  hxrendr.h
  202.  *
  203.  *  This routine returns crucial information required to associate this
  204.  *  plug-in with a given stream MIME type. This information tells the Helix
  205.  *  core which Renderer to use to display a particular type of stream. This
  206.  *  method is called when the Helix core application is launched.
  207.  */
  208. STDMETHODIMP
  209. C3GPPTimedTextRenderer::GetRendererInfo
  210. (
  211.     REF(const char**) /*OUT*/ pStreamMimeTypes,
  212.     REF(UINT32)       /*OUT*/ unInitialGranularity
  213. )
  214. {
  215.     pStreamMimeTypes =  (const char**)zm_pStreamMimeTypes;
  216.     // /XXXEH- todo: adjust this on the fly when scrolling is happening;
  217.     // scrollrate can change over time:
  218.     unInitialGranularity = 50; // OnTimeSync() every 50ms
  219.     return HXR_OK;
  220. }
  221. /****************************************************************************
  222.  *  IHXPlugin::InitPlugin                                   ref:  hxplugn.h
  223.  *
  224.  *  This routine performs initialization steps such as determining if
  225.  *  required interfaces are available. It is called when the Helix core 
  226.  *  application is launched, and whenever a stream associated with this
  227.  *  plug-in needs to be rendered.
  228.  */
  229. STDMETHODIMP
  230. C3GPPTimedTextRenderer::InitPlugin(IUnknown* /*IN*/ pContext)
  231. {
  232.     m_pContext = pContext;
  233.     m_pContext->AddRef();
  234.     m_pContext->QueryInterface(IID_IHXHyperNavigate, (void**) &m_pHyperNavigate);
  235.     m_pContext->QueryInterface(IID_IHXCommonClassFactory,(void**)&m_pCommonClassFactory);
  236. #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
  237.     m_pContext->QueryInterface(IID_IHXStatusMessage, (void**)&m_pStatusMessage);
  238. #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
  239.     return HXR_OK;
  240. }
  241. /****************************************************************************
  242.  *  IHXRenderer::StartStream                                ref:  hxrendr.h
  243.  *
  244.  *  The Helix core calls this routine to provide access to the stream and
  245.  *  player. It is called when the plug-in is being initialized.
  246.  */
  247. STDMETHODIMP
  248. C3GPPTimedTextRenderer::StartStream
  249. (
  250.     IHXStream*      pStream,
  251.     IHXPlayer*      pPlayer
  252. )
  253. {
  254.     m_pStream  = pStream;
  255.     m_pPlayer  = pPlayer;
  256.     if (m_pStream ) m_pStream->AddRef();
  257.     if (m_pPlayer ) m_pPlayer->AddRef();
  258. #if defined (HELIX_FEATURE_MISU)
  259.     m_pCommonClassFactory->CreateInstance(CLSID_IHXMultiInstanceSiteUserSupplier,
  260.                                           (void**)&m_pMISUS);
  261.     if (m_pMISUS)
  262.     {
  263. m_pMISUS->SetSingleSiteUser((IUnknown*)(IHXSiteUser*) this);
  264.     }
  265. #endif //HELIX_FEATURE_MISU
  266.     if (m_pStream)
  267.     {
  268.         IHXStreamSource* pSource = 0;
  269.         if (m_pStream->GetSource(pSource) == HXR_OK)
  270.         {
  271.             /* It is OK if the source does not support backchannel. Reasons:
  272.              *
  273.              * 1. This stream may not be coming from the MP4/3GPP fileformat.
  274.              *    It may instead be merged into a container fileformat which
  275.              *    maybe does not support BackChannel.
  276.              *
  277.              * 2. The protocol used to serve this stream may not support 
  278.              *    BackChannel.
  279.              */
  280.             pSource->QueryInterface(IID_IHXBackChannel, (void**) &m_pBackChannel);
  281.             
  282.             pSource->Release();
  283.         }
  284.         /* Is ASM supported on this stream? */
  285.         m_pStream->QueryInterface(IID_IHXASMStream, (void**) &m_pASMStream);
  286.     }
  287.     return HXR_OK;
  288. }
  289. /****************************************************************************
  290.  *  IHXRenderer::OnHeader                                   ref:  hxrendr.h
  291.  *
  292.  *  This routine is passed the stream header object created by the associated
  293.  *  file format plug-in. Use the methods defined in the IHXValues interface
  294.  *  to access the stream header data. This method is called from the Helix
  295.  *  core when the plug-in is being initialized.
  296.  */
  297. STDMETHODIMP
  298. C3GPPTimedTextRenderer::OnHeader(IHXValues* pHeader)
  299. {
  300.     HX_RESULT hxrslt = HXR_OK;
  301.     IHXBuffer* pRuleToFlagMapValue = NULL;
  302.     UINT32 ulRegionWidth = 0;
  303.     UINT32 ulRegionHeight = 0;
  304.     UINT32 ulTransformX = 0;
  305.     UINT32 ulTransformY = 0;
  306.     // Keep this for later use...
  307.     m_pHeader = pHeader;
  308.     m_pHeader->AddRef();
  309.     m_pHeader->GetPropertyULONG32("duration", m_ulDuration);
  310.     HX_RESULT hxGetPropRslt = HXR_OK;
  311.     // /Get this from numEntries of RuleToFlagMap that is "OpaqueData" buffer (below)
  312.     if (HXR_OK == pHeader->GetPropertyBuffer(HX_3GPPTT_RULE_TO_FLAG_MAP_PROPERTY,
  313.             pRuleToFlagMapValue))
  314.     {
  315.         m_pRuleToFlagMap = new RuleToFlagMap;
  316.         if (m_pRuleToFlagMap)
  317.         {
  318.             m_pRuleToFlagMap->unpack(pRuleToFlagMapValue->GetBuffer(),
  319.                     pRuleToFlagMapValue->GetSize());
  320.         }
  321.     }
  322.     HX_RELEASE(pRuleToFlagMapValue);
  323.     hxGetPropRslt = m_pHeader->GetPropertyBuffer("OpaqueData",
  324.             m_p3GPPTextSampleEntryPackedArray);
  325.     HX_ASSERT(HXR_OK==hxGetPropRslt  &&  m_p3GPPTextSampleEntryPackedArray);
  326.     if (HXR_OK == hxGetPropRslt  &&  m_p3GPPTextSampleEntryPackedArray)
  327.     {
  328.         const UINT8* pData = m_p3GPPTextSampleEntryPackedArray->GetBuffer();
  329.         
  330.         // /The first byte is the 'stsd's version, the next 3 bytes are the
  331.         // 'stsd's flags, and the next 4 bytes are the entryCount
  332.         pData+=(1+3); // /Skip past the version and the flags.
  333.         m_ulNumTextSampleEntries = ReadUL32(pData);
  334.        
  335.         HX_ASSERT(m_ulNumTextSampleEntries > 0);
  336.         HX_ASSERT(0 == m_textSampleEntries.GetCount());
  337.         hxrslt = m_textSampleEntries.Reset(m_ulNumTextSampleEntries);
  338.         if(SUCCEEDED(hxrslt))
  339.         {
  340.             // create table of sample entries
  341.             for (UINT32 ulSampleIndx = 0; ulSampleIndx < m_ulNumTextSampleEntries; ulSampleIndx++)
  342.             {
  343.                 C3GPPTextSampleEntry* pEntry = new C3GPPTextSampleEntry();
  344.                 if( !pEntry )
  345.                 {
  346.                     hxrslt = HXR_OUTOFMEMORY;
  347.                     goto cleanup;
  348.                 }
  349.                 hxrslt = pEntry->Build(pData);
  350.                 if(FAILED(hxrslt))
  351.                 {
  352.                     HX_DELETE(pEntry);
  353.                     goto cleanup;
  354.                 }
  355.                 m_textSampleEntries[ulSampleIndx] = pEntry;
  356.             }
  357.         }
  358.     }
  359.     // /_______________________________________________________________
  360.     // /
  361.     // /Get the media's native width and height:
  362.     m_pHeader->GetPropertyULONG32("3GPPTextTrackWidth", ulRegionWidth);
  363.     m_pHeader->GetPropertyULONG32("3GPPTextTrackHeight", ulRegionHeight);
  364.     // /This is the offset from the text window's origin:
  365.     m_pHeader->GetPropertyULONG32("3GPPTextTrackTransformX", ulTransformX);
  366.     m_pHeader->GetPropertyULONG32("3GPPTextTrackTransformY", ulTransformY);
  367.     m_originTransformXY.x = (INT32)ulTransformX;
  368.     m_originTransformXY.y = (INT32)ulTransformY;
  369.     m_size.cx = (INT32)ulRegionWidth;
  370.     m_size.cy = (INT32)ulRegionHeight;
  371.     
  372.     // /_______________________________________________________________
  373.     // /
  374.     // /Set up the offscreen draw buffer:
  375.     hxrslt = CreateOffscreenBuffer(m_size);
  376.     // /_______________________________________________________________
  377.     // /
  378.     
  379. cleanup:
  380.     return hxrslt;
  381. }
  382. /****************************************************************************
  383.  *  IHXRenderer::OnBegin                                   ref:  hxrendr.h
  384.  *
  385.  *  This routine is called by the Helix core to inform the Renderer that 
  386.  *  playback has just begun or has been resumed. The stream's time value just
  387.  *  after resuming the playback is provided.
  388.  */
  389. STDMETHODIMP
  390. C3GPPTimedTextRenderer::OnBegin(UINT32 ulTime)
  391. {
  392.     return HXR_OK;
  393. }
  394. /****************************************************************************
  395.  *  IHXRenderer::GetDisplayType                             ref:  hxrendr.h
  396.  *
  397.  *  This routine returns the preferred display type of the Renderer. Any
  398.  *  other additional information necessary for the display can also be
  399.  *  provided. This method is called by the Helix core when the plug-in is being
  400.  *  initialized.
  401.  */
  402. STDMETHODIMP
  403. C3GPPTimedTextRenderer::GetDisplayType
  404. (
  405.     REF(HX_DISPLAY_TYPE)   ulFlags,
  406.     REF(IHXBuffer*)         pBuffer
  407. )
  408. {
  409.     ulFlags = HX_DISPLAY_WINDOW;
  410.     return HXR_OK;
  411. }
  412. /****************************************************************************
  413.  *  IHXRenderer::OnPacket                                   ref:  hxrendr.h
  414.  *
  415.  *  This routine is passed the packet object streamed by the associated
  416.  *  file format plug-in. It is called by the Helix core when a packet is due
  417.  *  to be delivered. In most cases, the actual rendering of the packet is
  418.  *  done in this method. The stream's time offset with respect to the master
  419.  *  timeline is provided.
  420.  */
  421. STDMETHODIMP
  422. C3GPPTimedTextRenderer::OnPacket
  423. (
  424.     IHXPacket* pPacket,
  425.     INT32 lTimeOffset
  426. )
  427. {
  428. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  429. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  430. if (pFile)
  431. {
  432.     fprintf(pFile, "[OnPacket] at %ldtlTimeOffset=%ldtpktContentTime=%ldtpktTime=%ldt%st%sn",
  433.             HX_GET_BETTERTICKCOUNT(), lTimeOffset,
  434.             pPacket? GetPacketContentTime(pPacket):0xFFFFFFFF,
  435.             pPacket?pPacket->GetTime():0xFFFFFFFF,
  436.             m_bInSeekMode?"Skipped: m_bInSeekMode=TRUE":"",
  437.             m_bGotAllPacketsAlready?"Skipped: m_bGotAllPacketsAlready=TRUE":"");
  438.     fclose(pFile);
  439. }
  440. ulCount++;
  441. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  442.     HX_RESULT hxrslt = HXR_OK;
  443.     /* Ignore pre-seek packets. Some renderers may want to use them though */
  444.     if (m_bInSeekMode)
  445.     {
  446.         return hxrslt;
  447.     }
  448.     // /If we have all packets already, then we're receiving resends after a
  449.     // seek and we don't need the data resent because we store it all:
  450.     if (m_bGotAllPacketsAlready)
  451.     {
  452.         return hxrslt;
  453.     }
  454.     // Release the last packet if we had one...
  455.     if (m_pLatestPacket)
  456.     {
  457.         HX_RELEASE(m_pLatestPacket);
  458.     }
  459.     // Keep this one for later use...
  460.     m_pLatestPacket = pPacket;
  461.     BOOL bFirstPkt = FALSE;
  462.     if (m_pLatestPacket)
  463.     {
  464.         m_pLatestPacket->AddRef();
  465.         if (!m_pTextContainerList)
  466.         {
  467.             bFirstPkt = TRUE;
  468.             m_pTextContainerList = new CHXSimpleList();
  469.             if (!m_pTextContainerList)
  470.             {
  471.                 hxrslt = HXR_OUTOFMEMORY;
  472.             }
  473.         }
  474.         if (HXR_OK == hxrslt)
  475.         {
  476.             LISTPOSITION plistPosOfFirstTxtCntnr = NULL;
  477.             HandleNewText(m_pLatestPacket, plistPosOfFirstTxtCntnr);
  478.             if (bFirstPkt)
  479.             {
  480.                 m_pTextContainerListFutureTimePos =
  481.                         m_pTextContainerList->GetHeadPosition();
  482.             }
  483.             else
  484.             {
  485.                 // /Not first packet, but it points past end of list,
  486.                 // so point it to last in list:
  487.                 if (!m_pTextContainerListFutureTimePos)
  488.                 {
  489.                     HX_ASSERT(plistPosOfFirstTxtCntnr);
  490.                     // /Use first of HandleNewText()'s TC's, not last:
  491.                     m_pTextContainerListFutureTimePos = plistPosOfFirstTxtCntnr;
  492.                     if (NULL == m_pTextContainerListFutureTimePos)
  493.                     {
  494.                         // /Use tail if no T.C. was created from this new pkt:
  495.                         m_pTextContainerListFutureTimePos =
  496.                                 m_pTextContainerList->GetTailPosition();
  497.                     }
  498.                 }
  499.                 // /Now go through prior packet's T.C.'s and establish their
  500.                 // end times (which == m_pLatestPacket->GetRTPTime() ):
  501.                 SetPriorPacketTCsEndTimes();
  502.             }
  503.         }
  504. // /#define DUMP_3GPPTEXT_PACKET_CONTENTS
  505. #if defined(DUMP_3GPPTEXT_PACKET_CONTENTS)
  506. #if !defined(_DEBUG)
  507. #pragma message("====##### ***RELEASE BUILD: THIS TEST CODE SHOULD BE #####====")
  508. #pragma message("====#####    ifdef'd OUT BEFORE BEING CHECKED IN     #####====")
  509. #endif
  510. {
  511.     static UINT32 ulPktNum = 0;
  512.     FILE* pFile = fopen("c:\3gppttdump.txt", ulPktNum?"a+":"w");
  513.     if (pFile)
  514.     {
  515.         IHXBuffer* pBuff = pPacket->GetBuffer();
  516.         char* pText = pBuff? (char*)pBuff->GetBuffer() : "[NULL]";
  517.         fprintf(pFile, "packet  t%lunpkt timet%lunpacket content timet"
  518.             "%luncur time%lunsize    t%dncontentst{{{[len=%u]%s}}}nn",
  519.                 ulPktNum, pPacket->GetTime(), GetPacketContentTime(
  520.                 m_pLatestPacket), m_ulTimeOfLastTimeSync,
  521.                 pPacket->GetBuffer()->GetSize(),
  522.                 ((*pText)<< 8)|(*(pText+1)), &pText[2]);
  523.         fclose(pFile);
  524.     }
  525.     ulPktNum++;
  526. }
  527. #endif
  528.     }
  529.     // NOTE: If this stream has been offset in time due to start, end, or
  530.     // groupstart properties on the stream, packets will need to be adjusted
  531.     // before comparing against the time line.   The following code determines
  532.     // the offset of this packet's delivery time in the real timeline.
  533.     UINT32 ulPacketContentTime = GetPacketContentTime(pPacket);
  534.     UINT32 ulRealContentTime;
  535.  
  536.     if ((UINT32)lTimeOffset > ulPacketContentTime)
  537.     {
  538.         ulRealContentTime = 0;
  539.     }
  540.     else
  541.     {
  542.         ulRealContentTime = ulPacketContentTime - lTimeOffset;
  543.     }
  544.     m_ulLastPacketTime = ulPacketContentTime;
  545.     m_ulLastRealPacketTime = ulRealContentTime;
  546.     return hxrslt;
  547. }
  548. /****************************************************************************
  549.  *  IHXRenderer::OnTimeSync                                 ref:  hxrendr.h
  550.  *
  551.  *  This routine is called by the Helix core periodically passing the current
  552.  *  playback time. The Renderer should use this time value to synchronize the
  553.  *  playback of various streams.
  554.  */
  555. STDMETHODIMP
  556. C3GPPTimedTextRenderer::OnTimeSync(UINT32 ulTime)
  557. {
  558.     // Here's a good time to actually render the data!
  559.     // Remember the time we are!
  560.     m_ulTimeOfLastTimeSync = ulTime;
  561.     BOOL bForceDraw = FALSE;
  562.     C3GPPTextContainer* pTextContainer = NULL;
  563.     // /Find out if any begin time was hit:
  564.     if (m_pTextContainerList  &&  m_pTextContainerListFutureTimePos)
  565.     {
  566.         pTextContainer = (C3GPPTextContainer*)
  567.                 m_pTextContainerList->GetAt(m_pTextContainerListFutureTimePos);
  568. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  569. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  570. if (pFile)
  571. {
  572.     fprintf(pFile, "[OnTimeSync - 1] T.C. = %p, begin time=%lu, at time %lu, "
  573.         "m_pTextContainerListFutureTimePos=%xn", pTextContainer,
  574.         pTextContainer->GetBeginTime(), ulTime, m_pTextContainerListFutureTimePos);
  575.     fclose(pFile);
  576. }
  577. ulCount++;
  578. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  579.         if (pTextContainer  &&
  580.                 // /XXXEH- handle possible time-offset!:
  581.                 pTextContainer->GetBeginTime() <= ulTime  &&
  582.                 pTextContainer->GetEndTime() > ulTime)
  583.         {
  584.             bForceDraw = TRUE;
  585.         }
  586.     }
  587.     // /No new ones need drawing? Then see if any current ones need redrawing
  588.     // due to scrolling or blinking:
  589.     if (!bForceDraw  &&  m_pTextContainerRedrawList  &&
  590.                 m_pTextContainerRedrawList->GetCount())
  591.     {
  592.         pTextContainer = (C3GPPTextContainer*)
  593.                 m_pTextContainerRedrawList->GetHead();
  594. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  595. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  596. if (pFile)
  597. {
  598.     fprintf(pFile, "[OnTimeSync - 2] T.C. = %p (begin=%lu,tend=%lu,t"
  599.         "nextActive=%lu)tat time %lutm_pTextContainerListFutureTimePos=%pn",
  600.         pTextContainer, pTextContainer->GetBeginTime(),
  601.         pTextContainer->GetEndTime(), pTextContainer->GetNextActivityTime(),
  602.         m_ulTimeOfLastTimeSync, m_pTextContainerListFutureTimePos);
  603.     fclose(pFile);
  604. }
  605. ulCount++;
  606. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  607.         if (pTextContainer  &&
  608.                 // /XXXEH- handle possible time-offset!
  609.                 pTextContainer->GetNextActivityTime() <= ulTime)
  610.         {
  611.             bForceDraw = TRUE;
  612.         }
  613.     }
  614.     if (bForceDraw)
  615.     {
  616.         UpdateDisplay(ulTime);
  617.         // Draw the new text by damaging the entire area of our data
  618.         HXxRect damageRect = {0, 0, m_size.cx, m_size.cy };
  619.         m_pMISUSSite->DamageRect(damageRect);
  620.         m_pMISUSSite->ForceRedraw();
  621.     }
  622.     return HXR_OK;
  623. }
  624. /****************************************************************************
  625.  *  IHXRenderer::OnPreSeek                                  ref:  hxrendr.h
  626.  *
  627.  *  This routine is called by the Helix core before a seek is about to occur.
  628.  *  The stream's time value just before the seek, and the time value just
  629.  *  after the seek are provided.
  630.  */
  631. STDMETHODIMP
  632. C3GPPTimedTextRenderer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  633. {
  634. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  635. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  636. if (pFile)
  637. {
  638.     fprintf(pFile, "[OnPreSeek] at %ldtulNewTime=%lu,tulOldTime=%lu,n",
  639.             HX_GET_BETTERTICKCOUNT(), ulOldTime, ulNewTime);
  640.     fclose(pFile);
  641. }
  642. ulCount++;
  643. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  644.     m_bInSeekMode   = TRUE;
  645.     return HXR_OK;
  646. }
  647. /****************************************************************************
  648.  *  IHXRenderer::OnPostSeek                                 ref:  hxrendr.h
  649.  *
  650.  *  This routine is called by the Helix core just after a seek has occured.
  651.  *  The stream's time value just before the seek, and the time value just
  652.  *  after the seek are provided.
  653.  */
  654. STDMETHODIMP
  655. C3GPPTimedTextRenderer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  656. {
  657. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  658. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  659. if (pFile)
  660. {
  661.     fprintf(pFile, "[OnPostSeek] at %ldtulNewTime=%lu,tulOldTime=%lu,n",
  662.             HX_GET_BETTERTICKCOUNT(), ulOldTime, ulNewTime);
  663.     fclose(pFile);
  664. }
  665. ulCount++;
  666. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  667.     RecomputeTextContainerDrawList(ulNewTime);
  668.     m_bInSeekMode   = FALSE;
  669.     return HXR_OK;
  670. }
  671. /****************************************************************************
  672.  *  IHXRenderer::OnPause                                    ref:  hxrendr.h
  673.  *
  674.  *  This routine is called by the Helix core just after a pause has occured.
  675.  *  The stream's time value just before pausing is provided.
  676.  */
  677. STDMETHODIMP
  678. C3GPPTimedTextRenderer::OnPause(UINT32 ulTime)
  679. {
  680.     return HXR_OK;
  681. }
  682. /****************************************************************************
  683.  *  IHXRenderer::OnBuffering                                ref:  hxrendr.h
  684.  *
  685.  *  This routine is called by the Helix core to inform the Renderer that
  686.  *  buffering of data is occuring. The reason for buffering (e.g. start-up
  687.  *  of stream, seek has occured, network congestion, etc.), as well as the
  688.  *  percentage of the buffering process complete are provided.
  689.  */
  690. STDMETHODIMP
  691. C3GPPTimedTextRenderer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
  692. {
  693. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  694. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  695. if (pFile)
  696. {
  697.     fprintf(pFile, "[OnBuffering] at %ldtunPercentComplete=%u",
  698.             HX_GET_BETTERTICKCOUNT(), unPercentComplete);
  699.     fclose(pFile);
  700. }
  701. ulCount++;
  702. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  703.     return HXR_OK;
  704. }
  705. /****************************************************************************
  706.  *  IHXRenderer::OnEndofPackets                             ref:  hxrendr.h
  707.  *
  708.  *  Called by client engine to inform the renderer that all the
  709.  *  packets have been delivered. However, if the user seeks before
  710.  *  EndStream() is called, renderer may start getting packets again
  711.  *  and the client engine will eventually call this function again.
  712.  */
  713. STDMETHODIMP
  714. C3GPPTimedTextRenderer::OnEndofPackets(void)
  715. {
  716.     m_bGotAllPacketsAlready = TRUE;
  717.     return HXR_OK;
  718. }
  719. /****************************************************************************
  720.  *  IHXRenderer::EndStream                                  ref:  hxrendr.h
  721.  *
  722.  *  This routine is called by the Helix core when the rendering of the stream
  723.  *  has completed. Deallocation of any resources should be done here.
  724.  */
  725. STDMETHODIMP
  726. C3GPPTimedTextRenderer::EndStream()
  727. {
  728.     /* Send report of a mouse click to the fileformat if backchannel 
  729.      * is supported
  730.      */
  731.     if (m_pBackChannel && m_pCommonClassFactory && m_pStream)
  732.     {
  733.         IHXPacket* pPacket = 0;
  734.         IHXBuffer* pBuffer = 0;
  735.         char tmpStr[100];
  736.         if ((HXR_OK == m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
  737.                                                (void**)&pBuffer)) &&
  738.             (HXR_OK == m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket,
  739.                                                (void**)&pPacket)))
  740.         {
  741.             ::sprintf(tmpStr, "Number of clicks = %lun", m_ulNumberOfClicks);
  742.             pBuffer->Set((UCHAR*) tmpStr, ::strlen(tmpStr) + 1);
  743.             pPacket->Set(pBuffer,0,m_pStream->GetStreamNumber(),
  744.                          HX_ASM_SWITCH_ON, 0);
  745.             pBuffer->Release();
  746.             m_pBackChannel->PacketReady(pPacket);
  747.             pPacket->Release();
  748.         }
  749.     }
  750.     // You can't use IHXStream, IHXSourceStream, IHXBackChannel, or
  751.     // IHXASMStream after EndStream has been called.
  752.     HX_RELEASE(m_pStream);
  753.     HX_RELEASE(m_pBackChannel);
  754.     HX_RELEASE(m_pASMStream);
  755.     return HXR_OK;
  756. }
  757. /****************************************************************************
  758.  *  C3GPPTimedTextRenderer::ClearTextContainerLists      ref:  3gppttrender.h
  759.  *
  760.  *  Removes all contents of the list of text packets
  761.  */
  762. void
  763. C3GPPTimedTextRenderer::ClearTextContainerLists(BOOL bDeleteListPtrWhenCleared)
  764. {
  765.     if (m_pTextContainerRedrawList)
  766.     {
  767.         // /We don't need to delete the text containers inside since they are
  768.         // owned by (& will be cleaned up by) the m_pTextContainerList, below:
  769.         m_pTextContainerRedrawList->RemoveAll();
  770.     }
  771.     if (m_pTextContainerList)
  772.     {
  773.         LISTPOSITION pos = m_pTextContainerList->GetHeadPosition();
  774.         while (pos)
  775.         {
  776.             C3GPPTextContainer* pTextContainer =
  777.                     (C3GPPTextContainer*)m_pTextContainerList->GetNext(pos);
  778.             HX_ASSERT(pTextContainer);
  779.             if (pTextContainer)
  780.             {
  781.                 HX_DELETE(pTextContainer);
  782.             }
  783.         }
  784.         m_pTextContainerList->RemoveAll();
  785.     }
  786.     if (bDeleteListPtrWhenCleared)
  787.     {
  788.         HX_DELETE(m_pTextContainerList);
  789.         HX_DELETE(m_pTextContainerRedrawList);
  790.     }
  791. }
  792. /****************************************************************************
  793.  *  C3GPPTimedTextRenderer::C3GPPTimedTextRenderer       ref:  3gppttrender.h
  794.  *
  795.  *  Constructor
  796.  */
  797. C3GPPTimedTextRenderer::C3GPPTimedTextRenderer()
  798.         : m_lRefCount(0)
  799.         , m_pContext(NULL)
  800.         , m_pStream(NULL)
  801.         , m_pPlayer(NULL)
  802.         , m_pHeader(NULL)
  803.         , m_pLatestPacket(NULL)
  804.         , m_bGotAllPacketsAlready(FALSE)
  805.         , m_ulTimeOfLastTimeSync(HX_3GPPTT_INVALID_TIME)
  806.         , m_ulLastPacketTime(HX_3GPPTT_INVALID_TIME)
  807.         , m_ulLastRealPacketTime(HX_3GPPTT_INVALID_TIME)
  808.         , m_pHyperNavigate(NULL)
  809.         , m_pBackChannel(NULL)
  810.         , m_pASMStream(NULL)
  811.         , m_pCommonClassFactory(NULL)
  812.         , m_ulNumberOfClicks(0)
  813.         , m_bIsSubscribed(TRUE)
  814.         , m_pMISUS(NULL)
  815.         , m_pMISUSSite(NULL)
  816.         , m_bInSeekMode(FALSE)
  817.         , m_bRTPPacketTested(FALSE)
  818.         , m_bUsesRTPPackets(FALSE)
  819.         , m_ulDuration(0)
  820.         , m_ulNumTextSampleEntries(0)
  821.         , m_p3GPPTextSampleEntryPackedArray(NULL)
  822.         , m_pTextContainerList(NULL)
  823.         , m_pTextContainerListFutureTimePos(NULL)
  824.         , m_pTextContainerRedrawList(NULL)
  825.         , m_nLastMouseMoveXPos(0)
  826.         , m_nLastMouseMoveYPos(0)
  827.         , m_pEvent(NULL)
  828.         , m_pDrawOutputBuffer(NULL)
  829.         , m_ulDrawOutputBufferSizeInBytes(0)
  830.         , m_ulBitsPerPixel(HX_3GPPTT_DEFAULT_bits_PER_PIXEL)
  831.         , m_lXScrollOffset(0)
  832.         , m_lYScrollOffset(0)
  833.         , m_dScrollFactor(0.0)
  834.         , m_bDrawInNonTextScrollArea(FALSE)
  835.         , m_pRuleToFlagMap(NULL)
  836. #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
  837.         , m_pStatusMessage(NULL)
  838.         , m_bStatusMsgWillNeedErasing(FALSE)
  839.         , m_pszHLinkToDisplay(NULL)
  840. #endif // /HELIX_3GPPTT_USE_STATUS_BAR
  841. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  842.         , m_bNeedToSetHyperlinkHandCursor(FALSE)
  843.         , m_hPreHyperlinkCursor(NULL)
  844.         , m_hHyperlinkCursor(NULL)
  845.         , m_pDeviceContextMemory(NULL)
  846.         , m_pFont(NULL)
  847.         , m_pFontOld(NULL)
  848. #if defined(USE_DIB_SECTION)
  849.         , m_hBitmap(NULL)
  850.         , m_hOldBitmap(NULL)
  851.         , m_LPBITMAPINFO(NULL)
  852. #endif /* USE_DIB_SECTION */
  853. #elif defined(_MACINTOSH)
  854.         , m_CurrentCursor(CURSOR_ARROW)
  855.         , m_pOffScreenWorld(NULL)
  856. #elif defined(_UNIX) && (!(defined(_BEOS)))
  857.         , m_hHyperlinkCursor(0)
  858.         , m_bHandActivated(FALSE)
  859.         , m_pdisp(NULL)
  860.         , m_window(NULL)
  861.         , m_gc(NULL)
  862. #elif defined(_SYMBIAN)
  863.         , m_pBitMap(NULL)
  864.         , m_pFont(NULL)
  865.         , m_pScreenDevice(NULL)
  866.         , m_pGCSite(NULL)
  867.         , m_pGCOffscreen(NULL)
  868. #endif // /_WINDOWS -else- _MACINTOSH -else- (_UNIX && !_BEOS)                 _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  869.     {
  870.         m_originTransformXY.x = m_originTransformXY.y = 0;
  871.         m_size.cx = 0;
  872.         m_size.cy = 0;
  873.         memset(&m_BitmapInfoHeader, 0, sizeof(HXBitmapInfoHeader));
  874. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  875.         m_pDeviceContextMemory = (void*)CreateCompatibleDC(NULL);
  876. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  877. #if defined(_MACINTOSH)
  878.         const short HAND_CURSOR = 1313;
  879.         m_pResourceLoader = CResourceLoader::CreateInstance(g_DLLFSpec);
  880.         m_hHyperlinkCursor = (CursHandle)m_pResourceLoader->LoadResource('CURS', HAND_CURSOR);
  881. #endif // /_MACINTOSH
  882.     }
  883. /****************************************************************************
  884.  *  C3GPPTimedTextRenderer::~C3GPPTimedTextRenderer      ref:  3gppttrender.h
  885.  *
  886.  *  Destructor
  887.  */
  888. C3GPPTimedTextRenderer::~C3GPPTimedTextRenderer()
  889. {
  890.     for ( UINT32 idx = 0; idx != m_textSampleEntries.GetCount(); ++idx )
  891.     {
  892. C3GPPTextSampleEntry*& pEntry = (C3GPPTextSampleEntry*&)(m_textSampleEntries[idx]);
  893. delete pEntry;
  894.     }
  895.     m_textSampleEntries.Reset(0);
  896.     // /TRUE = delete m_pTextContainerList & m_pTextContainerRedrawList:
  897.     ClearTextContainerLists(TRUE);
  898.     /* Free the draw output buffer (but not w/DIB section) */
  899. #if !defined(USE_DIB_SECTION)  &&  !defined(_SYMBIAN)
  900.     if (m_pDrawOutputBuffer) // /Note: in Symbian, this points into m_pBitMap:
  901.     {
  902.         HX_VECTOR_DELETE(m_pDrawOutputBuffer);
  903.         m_pDrawOutputBuffer = NULL;
  904.         m_ulDrawOutputBufferSizeInBytes = 0;
  905.     }
  906. #endif // /!USE_DIB_SECTION.
  907. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  908.     // /Free the DIB-section-only data:
  909. #if defined(USE_DIB_SECTION)
  910.     if(m_hBitmap)
  911.     {
  912.         DeleteObject(m_hBitmap);
  913.     }
  914.     if(m_hOldBitmap  &&  m_pDeviceContextMemory)
  915.     {
  916.         SelectObject((HDC)m_pDeviceContextMemory, m_hOldBitmap);
  917.     }
  918.     m_hOldBitmap = NULL;
  919.     
  920.     if(m_LPBITMAPINFO)
  921.     {
  922.         delete m_LPBITMAPINFO;
  923.         m_LPBITMAPINFO = NULL;
  924.     }
  925. #endif // /USE_DIB_SECTION.
  926.     if(m_pDeviceContextMemory)
  927.     {
  928.         DeleteDC((HDC)m_pDeviceContextMemory);
  929.     }
  930. #elif defined(_MACINTOSH)
  931.     if(m_pOffScreenWorld)
  932.     {
  933.         DisposeGWorld(m_pOffScreenWorld);
  934.         m_pOffScreenWorld=NULL;
  935.     }
  936. #elif defined(_SYMBIAN)
  937.     if (m_pBitMap)
  938.     {
  939.         HX_DELETE(m_pBitMap);
  940.         m_pDrawOutputBuffer = NULL;
  941.     }
  942.     // /Discard and destroy the font:
  943.     if (m_pFont)
  944.     {
  945.         if (m_pGCOffscreen)
  946.         {
  947.             m_pGCOffscreen->DiscardFont();
  948.             HX_DELETE(m_pGCOffscreen);
  949.         }
  950.         // /m_pGCSite is not ours to delete.
  951.         if (m_pScreenDevice)
  952.         {
  953.             m_pScreenDevice->ReleaseFont(m_pFont);
  954.         }
  955.         m_pFont = NULL;
  956.     }
  957. #endif // /_WINDOWS elif _MACINTOSH elif _SYMBIAN                              _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  958.     HX_RELEASE(m_pHeader);
  959.     HX_RELEASE(m_pLatestPacket);
  960.     HX_RELEASE(m_pContext);
  961.     HX_RELEASE(m_pHyperNavigate);
  962. #if defined(HELIX_3GPPTT_USE_STATUS_BAR)
  963.     HX_RELEASE(m_pStatusMessage);
  964.     HX_VECTOR_DELETE(m_pszHLinkToDisplay);
  965. #endif /* HELIX_3GPPTT_USE_STATUS_BAR */
  966.     HX_RELEASE(m_pCommonClassFactory);
  967.     HX_RELEASE(m_pPlayer);
  968. }
  969. // IHXSiteUser Interface Methods
  970. /****************************************************************************
  971.  *  IHXSiteUser::AttachSite                                   ref:  hxwin.h
  972.  *
  973.  */
  974. STDMETHODIMP
  975. C3GPPTimedTextRenderer::AttachSite(IHXSite* /*IN*/ pSite)
  976. {
  977.     if (m_pMISUSSite)
  978.     {
  979.         return HXR_UNEXPECTED;
  980.     }
  981.     m_pMISUSSite = pSite;
  982.     m_pMISUSSite->AddRef();
  983.     m_pMISUSSite->SetSize(m_size);
  984.     
  985. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  986.     IHXSiteWindowed* pSiteWindowed = NULL;
  987.     if (m_pMISUSSite->QueryInterface(IID_IHXSiteWindowed,
  988.                  (void**) &pSiteWindowed)
  989.                     == HXR_OK)
  990.     {
  991.         HXxWindow* pHXxWindow = pSiteWindowed->GetWindow();
  992.         HX_ASSERT(pHXxWindow);
  993.         if (pHXxWindow)
  994.         {
  995.             CDirectScreenAccess* pDirectScreen = pHXxWindow->iDSA;
  996.             if (pDirectScreen)
  997.             {    
  998.                 m_pScreenDevice = pDirectScreen->ScreenDevice();
  999.                 if(m_pScreenDevice)
  1000.                 {
  1001.                     m_pGCSite = pDirectScreen->Gc();
  1002.                 }
  1003.             }    
  1004.         }
  1005.     }
  1006.     HX_RELEASE(pSiteWindowed);
  1007.     HX_ASSERT(m_pScreenDevice);
  1008.     HX_ASSERT(m_pGCSite);
  1009. #endif /* _SYMBIAN */ // /                                                     _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1010.     
  1011.     // /XXXEH- once we get text site to same postion as video site, we can QI
  1012.     // site for IHXSite2 and then call MoveSiteToTop() to make sure it's on
  1013.     // top of the video.
  1014. /*  // /XXXEH- We need to use a site watcher to watch for TLC moving our window
  1015.     // because in RealOne player, the TLC tiles multiple sites if no explicit
  1016.     // layout exists.  On mobile players, the TLC leaves everyt site at (0,0).
  1017.     HXxPoint point;
  1018.     m_pMISUSSite->GetPosition(point);
  1019.     // /XXXEH- we need to move the video to client area (0,0) so text can
  1020.     // appear on top of video as well as below.  Coords of display rect of
  1021.     // 3GPP TT assumes origin of region (this site) is same as video's, but
  1022.     // our default site-layout code puts our origin at (0, video's bottom):
  1023.     point.x -= ulTransformX;
  1024.     point.y -= ulTransformY; // /XXXEH- this doesn't work; it's still Blt'ing
  1025.                              // in the same place, below the vid.
  1026.     HX_RESULT hxr = m_pMISUSSite->SetPosition(point);
  1027.     m_pMISUSSite->GetPosition(point); // /TESTING: [X] returns changed-position point
  1028.  */
  1029.     return HXR_OK;
  1030. }
  1031. /****************************************************************************
  1032.  *  IHXSiteUser::DetachSite                                   ref:  hxwin.h
  1033.  *
  1034.  */
  1035. STDMETHODIMP
  1036. C3GPPTimedTextRenderer::DetachSite()
  1037. {
  1038.     HX_RELEASE(m_pMISUSSite);
  1039.     // We're done with these...
  1040.     if (m_pMISUS) m_pMISUS->ReleaseSingleSiteUser();
  1041.     HX_RELEASE(m_pMISUS);
  1042.     return HXR_OK;
  1043. }
  1044. /****************************************************************************
  1045.  *  IHXSiteUser::NeedsWindowedSites                           ref:  hxwin.h
  1046.  *
  1047.  */
  1048. STDMETHODIMP_(BOOL)
  1049. C3GPPTimedTextRenderer::NeedsWindowedSites() 
  1050.     return FALSE; 
  1051. };
  1052. /****************************************************************************
  1053.  *  IHXSiteUser::HandleEvent                                  ref:  hxwin.h
  1054.  *
  1055.  */
  1056. STDMETHODIMP
  1057. C3GPPTimedTextRenderer::HandleEvent(HXxEvent* /*IN*/ pEvent)
  1058. {
  1059.     HX_RESULT hxrslt = HXR_OK;
  1060.     pEvent->handled = FALSE;
  1061.     pEvent->result  = 0;
  1062. #if defined(_UNIX) && (!(defined(_BEOS)))
  1063.     // XEvent* xevent = (XEvent*)pEvent->param1;
  1064.     // what is pEvent->window?
  1065. #endif
  1066. #if defined(_UNIX) && (!(defined(_BEOS)))
  1067.     //XXX: This assumes a single window for the duration
  1068.     if( !m_window )
  1069.     {
  1070.         m_window = (Window)pEvent->window;
  1071.         if( !m_window )
  1072.             return HXR_OK;
  1073.     }
  1074.     if( !m_gc )
  1075.     {
  1076.         XGCValues vals;
  1077.         HXxWindow *pWnd = (HXxWindow*)pEvent->param2;
  1078.         m_pdisp = (Display*)pWnd->display;
  1079.         if( !m_pdisp ) return HXR_OK;
  1080.         XFontStruct* pfs = XLoadQueryFont( m_pdisp, "6x10" );
  1081.         if( !pfs ) return HXR_OK;
  1082.         //XXX: Could use WhitePixel() and BlackPixel()
  1083.         vals.foreground = 0xffffffff;
  1084.         vals.background = 0;
  1085.         vals.font = pfs->fid;
  1086.         m_gc = XCreateGC( m_pdisp, m_window, (GCForeground|GCBackground|GCFont), &vals );
  1087.         if( !m_gc ) return HXR_OK;
  1088.     }
  1089. #endif /* _UNIX  &&  !_BEOS */
  1090.     switch (pEvent->event)
  1091.     {
  1092.         case HX_MOUSE_ENTER:
  1093.         case HX_MOUSE_LEAVE:
  1094.         case HX_MOUSE_MOVE:
  1095.         {
  1096.             pEvent->handled = TRUE;
  1097.             m_pEvent = pEvent;
  1098.             HXxPoint* mousePt = (HXxPoint*) pEvent->param1;
  1099.             OnMouseMove (0, (INT16)mousePt->x, (INT16)mousePt->y);
  1100.         }
  1101.         break;
  1102.         case HX_PRIMARY_BUTTON_UP:
  1103.         {
  1104.             HXxPoint* mousePt = (HXxPoint*) pEvent->param1;
  1105.             hxrslt = HandleClick(0, (INT16)mousePt->x, (INT16)mousePt->y);
  1106.             pEvent->handled = TRUE;
  1107.         }
  1108.         break;
  1109.         case HX_SURFACE_UPDATE:
  1110.         {
  1111.             m_pEvent = pEvent;
  1112.             IHXVideoSurface *pSurface = (IHXVideoSurface*) (pEvent->param1);
  1113.             HX_ASSERT(pSurface);
  1114.             if (pSurface)
  1115.             {
  1116.                 hxrslt = Draw(pSurface);
  1117.             }
  1118.             pEvent->handled = TRUE;
  1119.             m_pEvent = NULL;
  1120.         }
  1121.         break;
  1122. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1123.         case WM_SETCURSOR:
  1124.         {
  1125.             pEvent->handled = TRUE;
  1126.             if(m_bNeedToSetHyperlinkHandCursor)
  1127.             {
  1128.                 m_hPreHyperlinkCursor = SetCursor(m_hHyperlinkCursor);
  1129.             }
  1130.             else
  1131.             {
  1132.                 // /set the cursor back to arrow cursor:
  1133.                 SetCursor(LoadCursor(NULL, IDC_ARROW));
  1134.             }
  1135.         }
  1136.         break;
  1137. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1138.     }
  1139.     return hxrslt;
  1140. }
  1141. //
  1142. // Called to ensure cached output buffer pointer is valid before 
  1143. // we use it. On most platforms this remains constant. On Symbian 
  1144. // this can change (e.g., when menus go up).
  1145. //
  1146. void C3GPPTimedTextRenderer::SetDrawOutputBuffer()
  1147. {
  1148. #if defined(_SYMBIAN)
  1149.     m_pDrawOutputBuffer = m_pBitMap ? (UCHAR*)m_pBitMap->DataAddress() : 0;
  1150. #endif
  1151. }
  1152. /****************************************************************************
  1153.  *  C3GPPTimedTextRenderer::Draw                         ref:  3gppttrender.h
  1154.  *
  1155.  */
  1156. HX_RESULT
  1157. C3GPPTimedTextRenderer::UpdateDisplay(UINT32 ulTime)
  1158. {
  1159.     HX_RESULT hxrslt = HXR_OK;
  1160.     C3GPPTextContainer* pTextContainer = NULL;
  1161.     const C3GPPTextSampleEntry* pLastHandledTextSampleEntry = NULL;
  1162.     INT32 lXScrollOffset = 0;
  1163.     INT32 lYScrollOffset = 0;
  1164.     BOOL bIsScrollingOut = FALSE;
  1165.     double dScrollFactor = 0.0;
  1166.     UINT32 ulBgColorARGB = 0x0;
  1167.     BOOL bHasNonOpaqueAlpha = FALSE;
  1168.     SetDrawOutputBuffer();
  1169. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1170.     HDC hDC = (HDC)m_pDeviceContextMemory;
  1171. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1172. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1173.     HBufC16* pHBufUTF16Text = NULL;
  1174.     HBufC8*  pHBufUTF8Text = NULL;
  1175.     HX_ASSERT(m_pGCSite  &&  m_pGCOffscreen);
  1176.     if (!m_pGCSite  ||  !m_pGCOffscreen)
  1177.     {
  1178.         hxrslt = HXR_UNEXPECTED;
  1179.         goto cleanup;
  1180.     }
  1181. #endif // /_SYMBIAN                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1182. #if !defined(USE_DIB_SECTION) /* else DIB_SECTION code below will create it */ // /-----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1183.     HX_ASSERT(m_pDrawOutputBuffer); // /Should have been created in OnHeader().
  1184.     if (m_pDrawOutputBuffer  &&
  1185. #else // /else USE_DIB_SECTION
  1186.     if (
  1187. #endif   // /(else of) !USE_DIB_SECTION                                        // /_____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1188.             (m_pTextContainerList  &&  m_pTextContainerListFutureTimePos)
  1189.             // /Or, maybe we're done with new text and we need to redraw
  1190.             // current text:
  1191.             ||  (m_pTextContainerRedrawList  &&
  1192.             m_pTextContainerRedrawList->GetCount()) )
  1193.     {
  1194.         //------------- TEXT DRAWING CODE -- MOVE OUT TO X-PLAT CALL! -------
  1195.         //------------------ START TEXT PUT-GLYPHS-TO-cANVAS CODE:  ---------
  1196.         INT32 liCursorX = INITIAL_CURSOR_X;
  1197.         INT32 liCursorY = INITIAL_CURSOR_Y;
  1198.         BOOL bFinishedWithCurTimeTCs = FALSE;
  1199.         UINT32 ulTextContainersHandled = 0;
  1200.         // /If we haven't yet gotten an OnTimeSync(), then don't draw anything:
  1201.         if (HX_3GPPTT_INVALID_TIME == m_ulTimeOfLastTimeSync)
  1202.         {
  1203.             goto cleanup;
  1204.         }
  1205.         // /If we find that all T.C.s from the main list (at or beyond the
  1206.         // future list pos) are all still in the future, then we might be here
  1207.         // because of some T.C. needing redrawing (for scrolling or blinking):
  1208.         BOOL bGetTextContainersFromRedrawList = FALSE;
  1209.         BOOL bTextContainerIsFromMainList = FALSE;
  1210.         BOOL bATextContainerFromMainListWasHandled = FALSE;
  1211.         UINT32 ulKaraokeHighlightStartTimeInGlobalTime = HX_3GPPTT_INVALID_TIME;
  1212.         UINT32 ulKaraokeHighlightEndTimeInGlobalTime = HX_3GPPTT_INVALID_TIME;
  1213.         do // /Go through textContainers and draw all that are valid @ present:
  1214.         {
  1215.             BOOL bReuseTCsPriorDrawRect = FALSE;
  1216.             if (!bGetTextContainersFromRedrawList  &&
  1217.                     NULL != m_pTextContainerListFutureTimePos)
  1218.             {
  1219.                 pTextContainer = (C3GPPTextContainer*)
  1220.                         m_pTextContainerList->GetAt(
  1221.                         m_pTextContainerListFutureTimePos);
  1222.                 HX_ASSERT(pTextContainer);
  1223.                 bTextContainerIsFromMainList = TRUE;
  1224.             }
  1225.             else if (m_pTextContainerRedrawList  &&
  1226.                     m_pTextContainerRedrawList->GetCount())
  1227.             {
  1228.                 pTextContainer = (C3GPPTextContainer*)
  1229.                         m_pTextContainerRedrawList->GetHead();
  1230.                 bTextContainerIsFromMainList = FALSE;
  1231.                 if (pTextContainer  &&
  1232.                         pTextContainer->GetEndTime() <= m_ulTimeOfLastTimeSync)
  1233.                 {
  1234.                     // /It's too old to be redrawn (next time) so remove it
  1235.                     // from the list:
  1236.                     pTextContainer =  NULL;
  1237.                     m_pTextContainerRedrawList->RemoveHead();
  1238.                 }
  1239.             }
  1240.             else
  1241.             {
  1242.                 break; // /None from either list need drawing
  1243.             }
  1244. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  1245. FILE* pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  1246. if (pFile)
  1247. {
  1248.     fprintf(pFile, "[step -1] T.C. = %p at time %lu (text containers "
  1249.         "handled = %ld), m_pTextContainerListFutureTimePos=%pn",
  1250.         pTextContainer, m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  1251.         m_pTextContainerListFutureTimePos);
  1252.     fclose(pFile);
  1253. }
  1254. ulCount++;
  1255. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  1256.             if (!pTextContainer  ||  !pTextContainer->m_pPacket)
  1257.             {
  1258.                 // /There should always be something to draw at any given time
  1259.                 // (unless the 3GPP-TT docs are incomplete) since one packet's
  1260.                 // begin time sets the end of the prior packet.  (There is one
  1261.                 // exception, and that is when we're drawing off the main list
  1262.                 // and the next T.C. in the redraw list has been removed when
  1263.                 // found (above) to be past its end time):
  1264.                 HX_ASSERT(pTextContainer  ||  !bTextContainerIsFromMainList);
  1265.                 HX_ASSERT(pTextContainer? NULL!=pTextContainer->m_pPacket : 1);
  1266.                 goto cleanup; // /Something's not right
  1267.             }
  1268. /*
  1269. #if 0 // /For testing/debugging:
  1270. {
  1271.     IHXPacket* pTextPkt = pTextContainer->m_pPacket;
  1272.     static UINT32 ulDrawCount = 0;
  1273.     FILE* pFile = fopen("c:\3gppttdump.txt", ulDrawCount?"a+":"w");
  1274.     if (pFile)
  1275.     {
  1276.         IHXBuffer* pBuff = pTextPkt?pTextPkt->GetBuffer():NULL;
  1277.         char* pText = pBuff? (char*)pBuff->GetBuffer() : "99[NULL]";
  1278.         fprintf(pFile, "Drawct  t%lunpkt timet%luncur time%lun"
  1279.                 "m_pTextContainerListFutureTimePos = %pn"
  1280.                 "size    t%dncontentst{{{[len=%u]%s}}}nn",
  1281.                 ulDrawCount, pTextPkt? pTextPkt->GetTime():9999999, m_ulTimeOfLastTimeSync,
  1282.                 m_pTextContainerListFutureTimePos,
  1283.                 pTextPkt? pTextPkt->GetBuffer()->GetSize():9999999,
  1284.                 ((*pText)<< 8)|(*(pText+1)), &pText[2]);
  1285.         fclose(pFile);
  1286.     }
  1287.     ulDrawCount++;
  1288. }
  1289. #endif
  1290. */
  1291. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  1292. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  1293. if (pFile)
  1294. {
  1295.     fprintf(pFile, "[step 0] T.C. = %p (begin=%lu,tend=%lu,tnextActive=%lu)t"
  1296.         "at time %lut(text containers handled = %ld),t"
  1297.         "m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  1298.         pTextContainer->GetBeginTime(), pTextContainer->GetEndTime(),
  1299.         pTextContainer->GetNextActivityTime(), m_ulTimeOfLastTimeSync,
  1300.         ulTextContainersHandled, m_pTextContainerListFutureTimePos);
  1301.     fclose(pFile);
  1302. }
  1303. ulCount++;
  1304. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  1305.             // /The sample entry associated with the text sample:
  1306.             const C3GPPTextSampleEntry* pCurTextSampleEntry = NULL;
  1307.                     // /XXXEH- handle possible time-offset w/m_ulTimeOfLastTimeSync!
  1308.             if (    pTextContainer->GetNextActivityTime() <= m_ulTimeOfLastTimeSync  &&
  1309.                     pTextContainer->GetEndTime() > m_ulTimeOfLastTimeSync  &&
  1310.                     pTextContainer->m_pTextSample  &&
  1311.                     pTextContainer->m_pTextSample->GetText()  &&
  1312.                     pTextContainer->m_pTextSample->GetTextLenInBytes())
  1313.             {
  1314. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  1315. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  1316. if (pFile)
  1317. {
  1318.     fprintf(pFile, "[step 1] T.C. = %p at time %lu (text containers handled = "
  1319.         "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  1320.         m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  1321.         m_pTextContainerListFutureTimePos);
  1322.     fclose(pFile);
  1323. }
  1324. ulCount++;
  1325. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  1326.                 bATextContainerFromMainListWasHandled =
  1327.                         bTextContainerIsFromMainList;
  1328.                 ulTextContainersHandled++;
  1329.                 // /The sample entry associated with the text sample:
  1330.                 pCurTextSampleEntry = NULL;
  1331. // /XXXEH- todo: Maybe replace the following ~15 lines w/new pTextContainer->GetSampleDescIndex() method:
  1332.                 // /Find out which sample description to associate with a text
  1333.                 // sample (one per packet):
  1334.                 UINT32 ulPktRuleNum = pTextContainer->GetASMRuleNumber();
  1335.                 // /Initialize it to rule # (which may be wrong index), then
  1336.                 // find the correct index value in the ruleToFlagMap:
  1337.                 UINT32 ulAssocSampleDescIndex = ulPktRuleNum;
  1338.                 HX_ASSERT(m_pRuleToFlagMap  &&
  1339.                         ulAssocSampleDescIndex < m_pRuleToFlagMap->num_rules);
  1340.                 if (m_pRuleToFlagMap  &&  ulAssocSampleDescIndex <
  1341.                         m_pRuleToFlagMap->num_rules)
  1342.                 {
  1343.                     ulAssocSampleDescIndex =
  1344.                         m_pRuleToFlagMap->rule_to_flag_map[ulPktRuleNum];
  1345.                 }
  1346.                 pCurTextSampleEntry = (const C3GPPTextSampleEntry*)
  1347.                         m_textSampleEntries.GetItem(ulAssocSampleDescIndex);
  1348.                 HX_ASSERT(pCurTextSampleEntry);
  1349.                 ulBgColorARGB = pCurTextSampleEntry->GetBGColor();
  1350.                 // /Fill background, but only if desc. differs from prev:
  1351.                 if (pCurTextSampleEntry != pLastHandledTextSampleEntry
  1352.                         // /...and also only if this is 1st one at this time:
  1353.                         &&  1 == ulTextContainersHandled
  1354.                         // /...and also only if this is not a redraw due to
  1355.                         // blinking; if it is, only redraw it and leave the
  1356.                         // rest of the (non-blinking) text that's already
  1357.                         // drawn (and still time-valid) alone:
  1358.                         &&  bTextContainerIsFromMainList)
  1359.                 {
  1360.                     FillRectangle(ulBgColorARGB);
  1361.                 }
  1362.                 if (bTextContainerIsFromMainList)
  1363.                 {
  1364.                     // /This one is now in the past (hendled), so move past it:
  1365.                     m_pTextContainerList->GetNext(
  1366.                             m_pTextContainerListFutureTimePos);
  1367.                 }
  1368.                 const C3GPPStyleRecord& defStyle = pCurTextSampleEntry->GetDefaultStyle();
  1369.                 UINT32 ulScaledHeight = defStyle.GetFontSize();
  1370.                 UINT32 defFaceStyleFlags = defStyle.GetFaceStyleFlags();
  1371.                 BOOL bIsBolded = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_BOLD);
  1372.                 BOOL bIsItalicized = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_ITALIC);
  1373.                 BOOL bIsUnderlined = (defFaceStyleFlags & HX_3GPPTT_FACE_STYLE_UNDERLINE);
  1374.                 BOOL bIsStruckThrough = FALSE;
  1375.                 char* pCurFontFaceString = NULL;
  1376.                 UINT32 ulTextColorARGB = defStyle.GetTextColor();
  1377.                 UINT32 ulTextColorARGBOld = 0;
  1378.                 UINT16 uiFontID_override = HX_3GPPTT_INVALID_INDEX;
  1379.                 
  1380.                 // /Init to totally transparent (which means ignore it):
  1381.                 UINT32 ulHighlightColorARGB = HX_3GPPTT_FULLY_TRANSPARENT;
  1382.                 BOOL bHasHighlightColor = FALSE;
  1383.                 if (pTextContainer->IsHyperlinked())
  1384.                 {
  1385.                     // /Draw text in red w/underline:
  1386.                     bIsUnderlined = TRUE;
  1387.                     // /Keep the alpha value but clear RGB part to red:
  1388.                     ulTextColorARGB = (ulTextColorARGB & HX_3GPPTT_FULLY_TRANSPARENT) |
  1389.                             HX_3GPPTT_HYPERLINK_RGB_COLOR;
  1390.                 }
  1391.                 if (pTextContainer->m_pTextHilightColorBox)
  1392.                 {
  1393.                     ulHighlightColorARGB = 
  1394.                             pTextContainer->m_pTextHilightColorBox->GetHighlightColor();
  1395.                     if (pTextContainer->m_pTextHighlightBox)
  1396.                     {
  1397.                         // /Has highlight unless highlight color is fully transparent:
  1398.                         bHasHighlightColor = (ulHighlightColorARGB < HX_3GPPTT_FULLY_TRANSPARENT);
  1399.                     }
  1400.                 }
  1401.                 // /Use style overrides, if any, for this time container:
  1402.                 if (HX_3GPPTT_INVALID_INDEX != pTextContainer->m_uiTextStyleBoxIndex  &&
  1403.                         pTextContainer->m_pTextStyleBox)
  1404.                 {
  1405.                     
  1406.                     const C3GPPStyleRecord* pStyleRecordOverride =
  1407.                             pTextContainer->m_pTextStyleBox->GetStyleRecord(
  1408.                             pTextContainer->m_uiTextStyleBoxIndex);
  1409.                     HX_ASSERT(pStyleRecordOverride);
  1410.                     if (pStyleRecordOverride)
  1411.                     {
  1412.                         UINT32 flags = pStyleRecordOverride->GetFaceStyleFlags();                 
  1413.                         bIsUnderlined = (flags & HX_3GPPTT_FACE_STYLE_UNDERLINE);
  1414.                         bIsBolded = (flags & HX_3GPPTT_FACE_STYLE_BOLD);
  1415.                         bIsItalicized = (flags & HX_3GPPTT_FACE_STYLE_ITALIC);
  1416.                         ulTextColorARGB = pStyleRecordOverride->GetTextColor();
  1417.                         ulScaledHeight = pStyleRecordOverride->GetFontSize();
  1418.                         uiFontID_override = pStyleRecordOverride->GetFontID();
  1419.                     }
  1420.                 }
  1421.                 if (HX_3GPPTT_INVALID_INDEX != pTextContainer->m_uiTextKaraokeBoxIndex  &&
  1422.                         pTextContainer->m_pTextKaraokeBox)
  1423.                 {
  1424.                     const C3GPPTextKaraokeBox::C3GPPTextKaraokeControlEntry*
  1425.                             pCurKaraokeCtrlEntry =
  1426.                             pTextContainer->m_pTextKaraokeBox->GetKaraokeControlEntry(
  1427.                             pTextContainer->m_uiTextKaraokeBoxIndex);
  1428.                     HX_ASSERT(pCurKaraokeCtrlEntry);
  1429.                     if (pCurKaraokeCtrlEntry)
  1430.                     {
  1431.                         // /Reuse position info from last draw if this is a redraw:
  1432.                         bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
  1433.                         // /Start time is end of prior highlight span; if
  1434.                         // that's invalid, use highlightstart time of
  1435.                         // TextKaraokeBox:
  1436.                         ulKaraokeHighlightStartTimeInGlobalTime =
  1437.                                 ulKaraokeHighlightEndTimeInGlobalTime;
  1438. //#error: should be: if (0 == pTextContainer->m_uiTextKaraokeBoxIndex  ...(||?)
  1439.                         if (HX_3GPPTT_INVALID_TIME ==
  1440.                                 ulKaraokeHighlightStartTimeInGlobalTime)
  1441.                         {
  1442.                             ulKaraokeHighlightStartTimeInGlobalTime =
  1443.                                     pTextContainer->GetBeginTime() +
  1444.                                     pTextContainer->m_pTextKaraokeBox->
  1445.                                     Get1stHighlightStartTime();
  1446.                         }
  1447.                         ulKaraokeHighlightEndTimeInGlobalTime =
  1448.                                 pTextContainer->GetBeginTime() +
  1449.                                 pCurKaraokeCtrlEntry->GetHighlightEndTime();
  1450.                         // /Set text color to hightlightColor unless curtime
  1451.                         // is outside of this TC's begin-end range:
  1452.                         if (m_ulTimeOfLastTimeSync >=
  1453.                                 ulKaraokeHighlightStartTimeInGlobalTime  &&
  1454.                                 m_ulTimeOfLastTimeSync <
  1455.                                 ulKaraokeHighlightEndTimeInGlobalTime)
  1456.                         {
  1457.                             ulTextColorARGB = ulHighlightColorARGB;
  1458.                             pTextContainer->m_ulNextDrawUpdateTimeOffset =
  1459.                                     ulKaraokeHighlightEndTimeInGlobalTime -
  1460.                                     pTextContainer->GetBeginTime();
  1461.                             InsertInRedrawListInTemporalOrder(pTextContainer);
  1462.                         }
  1463.                         else // /We're (not yet | no longer) in the highlight period:
  1464.                         {
  1465.                             UINT32 ulPrvActTime = pTextContainer->GetPrevActivityTime();
  1466.                             // /However, if highlight has been performed
  1467.                             // and then undone, remove it from redraw list
  1468.                             // then skip this TC and get next...
  1469.                             if (HX_3GPPTT_INVALID_TIME != ulPrvActTime)
  1470.                             {
  1471.                                 if (m_ulTimeOfLastTimeSync >=
  1472.                                     ulKaraokeHighlightEndTimeInGlobalTime)
  1473.                                 {
  1474. #if defined(_DEBUG)
  1475.                                     HX_RESULT hxrRemove =
  1476. #endif // /_DEBUG
  1477.                                     RemoveFromRedrawList(pTextContainer);
  1478. #if defined(_DEBUG)
  1479.                                     HX_ASSERT(HXR_OK == hxrRemove);
  1480. #endif // /_DEBUG
  1481.                                     // /If we've already returned it to pre-
  1482.                                     // highlight color by drawing after its
  1483.                                     // highlight end time, then skip it now:
  1484.                                     if (ulPrvActTime >=
  1485.                                             ulKaraokeHighlightEndTimeInGlobalTime)
  1486.                                     {
  1487.                                         continue;
  1488.                                     }
  1489.                                 }
  1490.                                 // /...else if highlight has been done but not
  1491.                                 // undone yet, set next activity time to highlight
  1492.                                 // end time and then skip drawing this TC @ now:
  1493.                                 else if (ulPrvActTime >
  1494.                                         ulKaraokeHighlightStartTimeInGlobalTime)
  1495.                                 {
  1496.                                     // /Set next activity time in local (offset) time:
  1497. #if defined(XXXEH_SHOW_TODO_MESSAGES)
  1498. #pragma message("====##### XXXEH- todo: replace w/ ->setDrawUpdateTimeOffset() method #####====")
  1499. #endif // /XXXEH_SHOW_TODO_MESSAGES.
  1500.                                     pTextContainer->m_ulNextDrawUpdateTimeOffset =
  1501.                                             ulKaraokeHighlightEndTimeInGlobalTime -
  1502.                                             pTextContainer->GetBeginTime();
  1503.                                     InsertInRedrawListInTemporalOrder(pTextContainer);
  1504.                                     continue;
  1505.                                 }
  1506.                             }
  1507.                             else // /Not yet drawn, so next draw will be highlight:
  1508.                                 // if (m_ulTimeOfLastTimeSync <
  1509.                                 //    ulKaraokeHighlightStartTimeInGlobalTime  &&
  1510.                                 //    pTextContainer->m_ulNextDrawUpdateTimeOffset +
  1511.                                 //    pTextContainer->GetBeginTime() !=
  1512.                                 //    ulKaraokeHighlightStartTimeInGlobalTime)
  1513.                             {
  1514.                                 // /Set next activity time in local (offset) time:
  1515. #if defined(XXXEH_SHOW_TODO_MESSAGES)
  1516. #pragma message("====##### XXXEH- todo: replace w/ ->setDrawUpdateTimeOffset() method #####====")
  1517. #endif // /XXXEH_SHOW_TODO_MESSAGES.
  1518.                                 pTextContainer->m_ulNextDrawUpdateTimeOffset =
  1519.                                         ulKaraokeHighlightStartTimeInGlobalTime -
  1520.                                         pTextContainer->GetBeginTime();
  1521.                                 // /Call this even if pT.C.'s end is exceeded because this
  1522.                                 // method will remove & not reinsert it in that case:
  1523.                                 InsertInRedrawListInTemporalOrder(pTextContainer);
  1524.                             }
  1525.                         }
  1526.                     }
  1527.                 } // /end KaraokeBox handling.
  1528.                 
  1529.                 // /First see if we have a scroll offset:
  1530.                 TextSampleScrollDirection scrolldir =
  1531.                         pCurTextSampleEntry->getScrollDirection();
  1532.                 if (scrollDirNone != scrolldir)
  1533.                 {
  1534.                     UINT32 ulScrollDelay = 0;
  1535.                     if (pTextContainer->m_pTextScrollDelayBox)
  1536.                     {
  1537.                         ulScrollDelay = pTextContainer->m_pTextScrollDelayBox->GetScrollDelay();
  1538.                     }
  1539.                     HX_ASSERT(m_ulTimeOfLastTimeSync >= pTextContainer->GetBeginTime());
  1540.                     UINT32 ulDurForThisScroll = pTextContainer->GetDuration();
  1541.                     HX_ASSERT(ulDurForThisScroll > ulScrollDelay);
  1542.                     if (ulDurForThisScroll <= ulScrollDelay)
  1543.                     {
  1544.                         ulDurForThisScroll = 1; // /Avoid div by zero, below.
  1545.                     }
  1546.                     else
  1547.                     {
  1548.                         ulDurForThisScroll -= ulScrollDelay;
  1549.                     }
  1550.                     UINT32 ulLocalTime = m_ulTimeOfLastTimeSync -
  1551.                             pTextContainer->GetBeginTime();
  1552.                     // /Handle in & out when both are active on this entry:
  1553.                     bIsScrollingOut = pCurTextSampleEntry->hasScrollOut();
  1554.                     if (pCurTextSampleEntry->hasScrollIn()  &&  bIsScrollingOut)
  1555.                     {
  1556.                         ulDurForThisScroll /= 2; // /Use only half dur in all calcs:
  1557.                         // /Find out if we're in the scroll-in (1st half) or
  1558.                         // the scroll-out (2nd half) part:
  1559.                         if (ulLocalTime < ulDurForThisScroll)
  1560.                         {
  1561.                             bIsScrollingOut = FALSE; // /In 1st half.
  1562.                         }
  1563.                         else
  1564.                         {
  1565.                             // /Get local time into 2nd-half-only coordinate space:
  1566.                             ulLocalTime -= ulDurForThisScroll;
  1567.                         }
  1568.                     }
  1569.                     if (ulScrollDelay  &&  bIsScrollingOut)
  1570.                     {
  1571.                         // /Adjust local time to zero to await end of scroll delay:
  1572.                         if (ulLocalTime <= ulScrollDelay)
  1573.                         {
  1574.                             ulLocalTime = 0;
  1575.                         }
  1576.                         else
  1577.                         {
  1578.                             ulLocalTime -= ulScrollDelay;
  1579.                         }
  1580.                     }
  1581.                     double dTCDurationRemaining = 1.0 - (
  1582.                             double(ulLocalTime) / double(ulDurForThisScroll) );
  1583.                     if (dTCDurationRemaining < 0.0)
  1584.                     {
  1585.                         dTCDurationRemaining = 0.0;
  1586.                     }
  1587.                     dScrollFactor = dTCDurationRemaining;
  1588.                     switch (scrolldir)
  1589.                     {
  1590.                         case scrollDirLeftToRight:
  1591.                             dScrollFactor = 1.0 - dScrollFactor;
  1592.                         case scrollDirRightToLeft:
  1593.                             lXScrollOffset = INT32(dScrollFactor * m_size.cx);
  1594.                             break;
  1595.                         case scrollDirDown:
  1596.                             dScrollFactor = 1.0 - dScrollFactor;
  1597.                         case scrollDirUp:
  1598.                             lYScrollOffset = INT32(dScrollFactor * m_size.cy);
  1599.                             break;
  1600.                     }
  1601. #if defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  1602. #else
  1603.                     if (!bIsScrollingOut) // /Scrolling in:
  1604.                     {
  1605.                         switch (scrolldir)
  1606.                         {
  1607.                             case scrollDirLeftToRight:
  1608.                                 lXScrollOffset -= m_size.cx;
  1609.                                 break;
  1610.                             case scrollDirRightToLeft:
  1611.                                 break;
  1612.                             case scrollDirDown:
  1613.                                 lYScrollOffset -= m_size.cy;
  1614.                                 break;
  1615.                             case scrollDirUp:
  1616.                                 break;
  1617.                         }
  1618.                     }
  1619.                     else // /Is scrolling out:
  1620.                     {
  1621.                         switch (scrolldir)
  1622.                         {
  1623.                             case scrollDirLeftToRight:
  1624.                                 break;
  1625.                             case scrollDirRightToLeft:
  1626.                                 lXScrollOffset -= m_size.cx;
  1627.                                 break;
  1628.                             case scrollDirDown:
  1629.                                 break;
  1630.                             case scrollDirUp:
  1631.                                 lYScrollOffset -= m_size.cy;
  1632.                                 break;
  1633.                         }
  1634.                     }
  1635. #endif // /End else of defined(XXXEH_SCROLLING_TRY1_BUT_BUG_IN_CORE)
  1636. #if defined(XXXEH_SHOW_TODO_MESSAGES)
  1637. #pragma message("====##### XXXEH- todo: SCROLLING OPTIMIZATION NEEDED; increment #####====")
  1638. #pragma message("====#####   by an amount that will make for smoothest motion:   #####====")
  1639. #endif // /XXXEH_SHOW_TODO_MESSAGES.
  1640.                     pTextContainer->m_ulNextDrawUpdateTimeOffset +=  50;
  1641.                     // /Call this even if pT.C.'s end is exceeded because this
  1642.                     // method will remove & not reinsert it in that case:
  1643.                     InsertInRedrawListInTemporalOrder(pTextContainer);
  1644.                     // /Reuse position info from last draw if this is a redraw:
  1645.                     bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
  1646.                 } // /end scroll-offset handling.
  1647.                 
  1648.                 if (pTextContainer->m_pTextBlinkBox)
  1649.                 {
  1650.                     // /Set this text to ON if drawTime is even # seconds,
  1651.                     // otherwise to OFF:
  1652.                     if ((pTextContainer->m_ulNextDrawUpdateTimeOffset /
  1653.                             HX_3GPPTT_BLINK_HALFINTERVAL_TIME) % 2)
  1654.                     {
  1655.                         ulTextColorARGB = ulBgColorARGB;
  1656.                     }
  1657.                     pTextContainer->m_ulNextDrawUpdateTimeOffset +=
  1658.                             HX_3GPPTT_BLINK_HALFINTERVAL_TIME;
  1659.                     // /Call this even if pT.C.'s end is exceeded because this
  1660.                     // method will remove & not reinsert it in that case:
  1661.                     InsertInRedrawListInTemporalOrder(pTextContainer);
  1662.                     // /Reuse position info from last draw if this is a redraw:
  1663.                     bReuseTCsPriorDrawRect = !bTextContainerIsFromMainList;
  1664. // /#define XXXEH_TESTING_BLINK_REDRAW
  1665. #if defined(XXXEH_TESTING_BLINK_REDRAW) // /XXXEH- DON'T CHECK THIS IN!
  1666. static UINT32 ulTmpCount = 0;
  1667. FILE* pTmpFile = fopen("c:\3gppttBlinkDump.txt", ulTmpCount?"a+":"w");
  1668. if (pTmpFile)
  1669. {
  1670.     fprintf(pTmpFile, "T.C. = %x at time %lu (new draw time = %lu, T.C.'s end "
  1671.         "time= %ld) ulTextColorARGB=%p (text containers handled = %ld)n",
  1672.         pTextContainer, m_ulTimeOfLastTimeSync,
  1673.         pTextContainer->GetNextActivityTime(), pTextContainer->GetEndTime(),
  1674.         ulTextColorARGB, ulTextContainersHandled, m_pTextContainerListFutureTimePos);
  1675.     fclose(pTmpFile);
  1676. }
  1677. ulTmpCount++;
  1678. #endif
  1679.                 } // / end blinkBox handling.
  1680. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  1681. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  1682. if (pFile)
  1683. {
  1684.     fprintf(pFile, "[step 2] T.C. = %p at time %lu (text containers handled = "
  1685.         "%ld), m_pTextContainerListFutureTimePos=%pn", pTextContainer,
  1686.         m_ulTimeOfLastTimeSync, ulTextContainersHandled,
  1687.         m_pTextContainerListFutureTimePos);
  1688.     fclose(pFile);
  1689. }
  1690. ulCount++;
  1691. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  1692.                 // /Use ARGB instead of RGB if the background color, text color, or
  1693.                 // highlight color is not fully opaque:
  1694.                 bHasNonOpaqueAlpha = (ulTextColorARGB & HX_3GPPTT_FULLY_TRANSPARENT) |
  1695.                         (ulBgColorARGB & HX_3GPPTT_FULLY_TRANSPARENT);
  1696.                 if (bHasHighlightColor  &&  !bHasNonOpaqueAlpha)
  1697.                 {
  1698.                     bHasNonOpaqueAlpha = (ulHighlightColorARGB & HX_3GPPTT_FULLY_TRANSPARENT);
  1699.                 }
  1700.                 // /Windows needs to have UTF-8 converted to UTF-16
  1701.                 // and then from that to native Windows.  The result
  1702.                 // is Japanese showing up on a Japanese OS, Korean
  1703.                 // showing up on a Korean OS, ...etc.
  1704. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1705.                 char* pConvertedText = NULL;
  1706.                 INT32 lConvertedTextLen = 0;
  1707. #else  // /else of: _WINDOWS                                                   ------------------------------------
  1708.                 const char* pConvertedText = pTextContainer->m_pTextSample->GetText() +
  1709.                         pTextContainer->m_uiUnpackedStartCharOffset;
  1710.                 INT32 lConvertedTextLen = (INT32)
  1711.                         ((UINT32)pTextContainer->GetTextByteLength());
  1712. #endif // /end else of: _WINDOWS                                               _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1713.                 HX_RESULT hxrsltCnvrtChars = HXR_OK;
  1714.                 
  1715. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1716.                 DWORD fdwCharSet = ANSI_CHARSET;
  1717.                 // /Moved this call up to here so the charset is established
  1718.                 // prior to the CreateFont() call; fixes Japanese (and others)
  1719.                 // not displaying (Helix Issue 666):
  1720.                 hxrsltCnvrtChars =
  1721.                         ConvertToOSRenderableChars(pTextContainer,
  1722.                         fdwCharSet, //(REF)
  1723.                         pConvertedText, lConvertedTextLen); //(REF,REF)
  1724.                 int bkModeOld;
  1725.                 int bkModeCur = TRANSPARENT;
  1726.                 // /If highlight is set for the text, use OPAQUE, not TRANSPARENT,
  1727.                 // and set bk color to highlight color:
  1728.                 if (bHasHighlightColor)
  1729.                 {
  1730.                     bkModeCur = OPAQUE;
  1731.                     SetBkColor(hDC, convertARGBtoWinBGRColor(ulHighlightColorARGB));
  1732.                 }
  1733.                 bkModeOld = SetBkMode(hDC, bkModeCur);
  1734.                 ulTextColorARGBOld = SetTextColor(
  1735.                         hDC, convertARGBtoWinBGRColor(ulTextColorARGB) );
  1736.                 if(CLR_INVALID == ulTextColorARGBOld)
  1737.                 {
  1738. #if !defined(USE_DIB_SECTION)
  1739.                     SelectObject(hDC, hbmpOld);
  1740. #endif // /USE_DIB_SECTION.
  1741.                     DeleteObject(m_pFont);
  1742.                     hxrslt = HXR_UNEXPECTED;
  1743.                     goto cleanup;
  1744.                 }
  1745.                 SetMapMode(hDC, MM_TEXT); // /1 logical unit mapped to 1 device pixel
  1746. #elif defined(_SYMBIAN)
  1747.                 // /If highlight is set for the text, set bk color to
  1748.                 // highlight color:
  1749.                 if (bHasHighlightColor)
  1750.                 {
  1751.                     TRgb rgbBgColor;
  1752.                     convertARGBtoSymbianTrgbColor(rgbBgColor, ulHighlightColorARGB);
  1753.                     m_pGCOffscreen->SetBrushStyle(CGraphicsContext::ESolidBrush);
  1754.                     m_pGCOffscreen->SetBrushColor(rgbBgColor);
  1755.                 }
  1756.                 // /Set foreground color (i.e., pen color):
  1757.                 TRgb rgbFgColor;
  1758.                 convertARGBtoSymbianTrgbColor(rgbFgColor, ulTextColorARGB);
  1759.                 m_pGCOffscreen->SetPenColor(rgbFgColor);
  1760. #else  // /end else of: #if _WINDOWS, #elif _SYMBIAN
  1761. #pragma message("====##### This OS needs code that sets text/bg colors #####====")
  1762. #endif // /end else of _WINDOWS.                                               _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1763.                 // /XXXEH- todo: optimization would be to keep current m_pFont
  1764.                 // if it's determined to be identical in all respects to prior
  1765.                 // TextContainer's font; if so, don't call SetFont(), below:
  1766.                 hxrslt = SetFont(pCurTextSampleEntry,
  1767.                         uiFontID_override,
  1768.                         pCurFontFaceString,
  1769.                         bIsBolded, bIsItalicized, bIsUnderlined, bIsStruckThrough,
  1770.                         ulScaledHeight
  1771. #if defined(_WINDOWS) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1772.                         , fdwCharSet
  1773. #endif // /_WINDOWS                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1774.                         );
  1775.                 if (HXR_OK != hxrslt)
  1776.                 {
  1777.                     goto cleanup;
  1778.                 }
  1779.                 // /In case the loaded font's size differs from the requested
  1780.                 // size, we have to just go with the font's size for all
  1781.                 // further calculations otherwise text lines may overlap:
  1782. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1783.                 ulScaledHeight = m_pFont->HeightInPixels();
  1784. #endif // /_SYMBIAN                                                            _____^^^^^^^^^^^^^^^^^^^^^^^^^^_____
  1785.                 // /If a newline(s) starts this TextContainer, reset liCursorX
  1786.                 // to initial (post-carriage-return) position and bump
  1787.                 // liCursorY by this's scaled height times number of newlines:
  1788.                 const char* pTxt = pTextContainer->m_pTextSample->GetText() +
  1789.                         pTextContainer->m_uiUnpackedStartCharOffset;
  1790.                 if (HX_3GPPTT_INVALID_INT16 ==
  1791.                         pTextContainer->m_lNumUTF16NewlinesAtStart)
  1792.                 {
  1793.                     if ('r' == *pTxt  ||  'n' == *pTxt)
  1794.                     {
  1795.                         // /XXXEH- I don't think we should ever get here;
  1796.                         // remove this assert if content is valid and trips
  1797.                         // this, i.e., it has 'r' or 'n' which was not
  1798.                         // counted in T.C.'s m_lNumUTF16NewlinesAtStart:
  1799.                         HX_ASSERT(0);
  1800.                         liCursorX = INITIAL_CURSOR_X;
  1801.                         liCursorY += ulScaledHeight;
  1802.                     }
  1803.                 }
  1804.                 else if (pTextContainer->m_lNumUTF16NewlinesAtStart > 0)
  1805.                 {
  1806.                     // /Perform carriage return:
  1807.                     liCursorX = INITIAL_CURSOR_X;
  1808.                     liCursorY += pTextContainer->m_lNumUTF16NewlinesAtStart *
  1809.                             ulScaledHeight;
  1810.                 }
  1811.                 // /XXXEH- todo: revisit with UTF8 in mind:
  1812.                 // /XXXEH- todo: We need to use m_originTransformXY.(x,y); (0,0)
  1813.                 // puts it at top-left of video, so we need to move our site's
  1814.                 // origin to client-area(0,0) in calculating the draw location:
  1815.                 HXxRect drawRect;
  1816.                 if (bReuseTCsPriorDrawRect)
  1817.                 {
  1818.                     drawRect.left =
  1819.                             pTextContainer->m_BoundingRectOfInitialDraw.left;
  1820.                     drawRect.top =
  1821.                             pTextContainer->m_BoundingRectOfInitialDraw.top;
  1822.                     drawRect.right =
  1823.                             pTextContainer->m_BoundingRectOfInitialDraw.right;
  1824.                     drawRect.bottom =
  1825.                             pTextContainer->m_BoundingRectOfInitialDraw.bottom;
  1826.                 }
  1827.                 else
  1828.                 {
  1829.                     const C3GPPTextboxBox& box = pCurTextSampleEntry->GetDefaultTextBox();
  1830.                     drawRect.top    = liCursorY + (INT32)box.Top();
  1831.                     drawRect.left   = liCursorX + (INT32)box.Left();
  1832.                     // /XXXEH- ? don't add liCursorY here (for slightly quicker
  1833.                     // DrawText() performance) but need to test heavily first:
  1834.                     drawRect.bottom = liCursorY + (INT32)box.Bottom();
  1835.                     // /XXXEH- ? don't add liCursorX here (for slightly quicker
  1836.                     // DrawText() performance) but need to test heavily first:
  1837.                     drawRect.right  = liCursorX + (INT32)box.Right();
  1838.                     if (pTextContainer->m_pTextboxBox)
  1839.                     {
  1840.                         // /Override with 'tbox's rect:
  1841. // /XXXEH- keep track if this TC has same m_pTextboXBox as prior TC; if not, don't add liCursor[X|Y] to any of these!
  1842.                         
  1843.                         drawRect.top    = liCursorY + (INT32)
  1844.                                 pTextContainer->m_pTextboxBox->Top();
  1845.                         drawRect.left   = liCursorX + (INT32)
  1846.                                 pTextContainer->m_pTextboxBox->Left();
  1847.                         drawRect.right  = liCursorY + (INT32)
  1848.                                 pTextContainer->m_pTextboxBox->Bottom();
  1849.                         drawRect.bottom = liCursorX + (INT32)
  1850.                                 pTextContainer->m_pTextboxBox->Right();
  1851.                     }
  1852.                 }
  1853.                 UINT32 ulTextFormatFlags =
  1854.                         SetJustificationFlags(pCurTextSampleEntry);
  1855.                 // /This T.C. will be drawn, below, so set time of
  1856.                 // last draw to cur time:
  1857.                 pTextContainer->SetPrevActivityTime(m_ulTimeOfLastTimeSync);
  1858.                 BOOL bTextContainerTextIsUTF16ReverseEncoded = FALSE;
  1859.                 BOOL bTextContainerTextIsUTF16Encoded =
  1860.                         IsUTF16Encoded((UCHAR*)pConvertedText,
  1861.                         lConvertedTextLen,
  1862.                         bTextContainerTextIsUTF16ReverseEncoded);
  1863.                 INT32 lTextLenInChars = lConvertedTextLen;
  1864.                 if (bTextContainerTextIsUTF16Encoded)
  1865.                 {
  1866.                     HX_ASSERT(!(lTextLenInChars & 0x1)); // /Shouldn't be odd
  1867.                     lTextLenInChars >>= 1; // /Divide by 2: 2 bytes/char
  1868.                     // /Skip past 0xfffe UTF-16 flag at start:
  1869.                     pConvertedText += 2;
  1870.                     lTextLenInChars--;
  1871.                 }
  1872. #if defined(XXXEH_DEBUGOUT_DRAW_3GPPTT)
  1873. pFile = fopen("c:\3gppttdrawPos.txt", ulCount?"a+":"w");
  1874. if (pFile)
  1875. {
  1876.     fprintf(pFile, "[step 5] T.C. = %x at time %lu (text containers "
  1877.         "handled = %ld), m_pTextContainerListFutureTimePos=%p, prevActivityTime "
  1878.         "was just set to%lun", pTextContainer, m_ulTimeOfLastTimeSync,
  1879.         ulTextContainersHandled, m_pTextContainerListFutureTimePos,
  1880.         pTextContainer->GetPrevActivityTime());
  1881.     fclose(pFile);
  1882. }
  1883. ulCount++;
  1884. #endif // /XXXEH_DEBUGOUT_DRAW_3GPPTT.
  1885.                 if (hxrsltCnvrtChars==HXR_OK  &&  pConvertedText  &&
  1886.                         lConvertedTextLen > 0)
  1887.                 {
  1888. #if defined(_SYMBIAN) // /                                                     -----vvvvvvvvvvvvvvvvvvvvvvvvvv-----
  1889.                     TInt iCharsToSkipOver = 0;
  1890.                     TInt iNumLinesOfTextAtStart = 0;
  1891. #else // /                                                                     ------------------------------------