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

Symbian

开发平台:

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