/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: drawptxt.cpp,v 1.1.2.1 2004/07/09 01:50:45 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

/////////////////////////////////////////////////////////////////////////////
//
// drawptxt.cpp
//
// Function:
//  BOOL DrawPlainText(TextWindow* pTextWindow, void* pDC, void* pPaintstruct,
//	    ULONG32 ulTimeOfCurrentDraw);
// Purpose:
//  This function handles the rendering of plain text by calling an
//  OS-specific API to draw the text in the given window.  Note that, since
//  this funciton deals strictly with plain text, it doesn't need to worry
//  about doing anything to any particular piece of text, e.g., underlining,
//  coloring, font sizing, ...etc., but it *does* have to do that for *all*
//  text if a <param> in the SMIL file that uses this text has dictated such
//  an attribute value (for the entire text).
//    - Windows: calls DrawText()
//
//  This Function is called from WM_PAINT and hdc and paintStruct are from
//  BeginPaint(); paintStruct holds the invalid rectangle to be updated: 
// Returns:
//  Returns FALSE on error, TRUE otherwise. 

#include "hxtypes.h" /*Must be included before windows.h for VC6 compiler*/

#if defined(_WINDOWS)
#include <windows.h>
#endif

#include "hxassert.h"

#include "hxstack.h"
#include "hxslist.h"

#include "rt_types.h" /* for _CHAR, RED_GREEN_OR_BLUE, COLORTYPE */

#include "fontdefs.h"
#include "txtattrb.h"
#include "txtcntnr.h"
#include "textline.h"
#include "atocolor.h"

#include "chxxtype.h"
#include "txtwindw.h" /* for class TextWindow. */
#include "hxcom.h"
#include "hxvsurf.h"
#include "textprsr.h" /* for REAL_TEXT_TRANSPARENT_BGCOLOR_MAJOR_VERSION + ... */
#include "fontinfo.h" /* for ConvertAcrossCharacterSets(). */

#if defined(_WINDOWS)
#include "../rtwin.h"
#elif defined(_MACINTOSH)
#include "rtwin.h"
#endif


#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE		
static char HX_THIS_FILE[] = __FILE__;
#endif


UINT32
getPlainTextFormat(TextWindow* pTextWindow)
{
    UINT32 ulFormat = DT_NOCLIP;
    if (!pTextWindow)
    {
	return 0;
    }

    if (pTextWindow->isRightToLeftReading())
    {
 	// /For Hebrew & Arabic fonts: draw right-to-left;
	ulFormat |= DT_RTLREADING;
    }

    if (pTextWindow->expandTabs())
    {
	ulFormat |= DT_EXPANDTABS;
    }
    // /Fixes PR 95128 where some computers are displaying boxes instead of
    // spaces when DT_EXPANDTABS is false; the following goes ahead and sets
    // it to expand tabs but only to 1-char width stops:
    else
    {
        // /Bits 15–8 of ulFormat specify # of chars for each tab;
        // we'll let it default to 8 if expandTabs is TRUE, above, otherwise
        // we'll go ahead and set DT_EXPANDTABS but set the tabstop width to 1
        // (which is 1 average-character width):
        ulFormat |= DT_TABSTOP | DT_EXPANDTABS;
        ulFormat &= 0xFFFF00FF; // /Clears bits 15-through-8
        ulFormat |= 0x00000100; // /Sets bit #8 which means tabstop value is 1.
    }

    textHorizAlign curHorizAlign = pTextWindow->getHorizAlign();
    if (!pTextWindow->usingWordwrap())
    {
	textVertAlign curVertAlign = pTextWindow->getVertAlign();
	if (pTextWindow->wasVertAlignExplicitlySet())
	{
	    // /Fixes PR 7XYZZ: forces newline chars to act as space chars,
	    // so only do this if author explicitly set the vert alignment
	    // attribute which only works if all text is on a single-line:
    	    ulFormat |= DT_SINGLELINE;
	}
	if (kVAlignCenter == curVertAlign)
	{
	    ulFormat |= DT_VCENTER;
	}
	else if (kVAlignBottom == curVertAlign)
	{
	    ulFormat |= DT_BOTTOM;
	}
	else
	{
	    HX_ASSERT(kVAlignTop == curVertAlign);
	    ulFormat |= DT_TOP;
	}
    }
    else // /multi-line:
    {
	ulFormat |= DT_WORDBREAK; // /Performs word wrapping

	if (kHAlignCenter == curHorizAlign)
	{
	    ulFormat |= DT_CENTER;
	}
	else if (kHAlignRight == curHorizAlign)
	{
	    ulFormat |= DT_RIGHT;
	}
	else
	{
	    HX_ASSERT(kHAlignLeft == curHorizAlign);
	    ulFormat |= DT_LEFT;
	}
    }

    return ulFormat;
}



BOOL
DrawPlainText(TextWindow* pTextWindow, void* pVoid, void* pPaintstruct,
	ULONG32 ulTimeOfCurrentDraw)
{
    HX_ASSERT_VALID_PTR(pTextWindow);
    HX_ASSERT(pVoid);
    HX_ASSERT_VALID_PTR(pPaintstruct);
    if(!pTextWindow  ||  !pVoid  ||  !pPaintstruct
	    ||  !pTextWindow->m_hBitmap)
    {
	return FALSE;
    }

    // Initialize chromaKey flag. If the background
    // color is the same as the chroma key, then we 
    // know we are applying the chroma key. Also, when
    // we draw text of a certain color later down in
    // this method, we may be setting this flag, depending
    // on the text color.
    BOOL bChromaKeyWasApplied = FALSE;
    if (pTextWindow->isChromaKeySet())
    {
        if (DoesChromaKeyMatch(pTextWindow->getBackgroundColor(),
                               pTextWindow->getChromaKey(),
                               pTextWindow->getChromaKeyTolerance()))
        {
            if (pTextWindow->getChromaKeyOpacity() < 255)
            {
                bChromaKeyWasApplied = TRUE;
            }
        }
    }

    LONG32 lWindowWidth = pTextWindow->getWindowWidth();
    LONG32 lWindowHeight = pTextWindow->getWindowHeight();

    
    PAINTSTRUCT paintStruct = *((PAINTSTRUCT*)pPaintstruct);
#if !defined(USE_DIB_SECTION)
    HBITMAP hbmpOld;
#endif
    BOOL b_FunctionSucceeded = TRUE;
    RECT updateRect = paintStruct.rcPaint;
    //Due to window-offset-in-layout problem,
    // we need to translate the rect by the upperleftX,Y of pTextWindow:
    updateRect.left -= pTextWindow->getUpperLeftX();
    updateRect.top -= pTextWindow->getUpperLeftY();

    ULONG32 listSize = pTextWindow->textCntnrListSize();
    
    if(!pTextWindow->m_pDeviceContextMemory)
    {
	return FALSE;	
    }

    HDC	hDC = (HDC)pTextWindow->m_pDeviceContextMemory;

#if !defined(USE_DIB_SECTION)
    hbmpOld = (HBITMAP)SelectObject(hDC,
	    (HBITMAP)pTextWindow->m_pBmpCompat);
    if(!hbmpOld)
    {
	return FALSE;
    }
#endif

    if(!PaintBackground(pTextWindow, pPaintstruct))
    {
#if !defined(USE_DIB_SECTION)
	SelectObject(hDC, hbmpOld);
#endif
	return FALSE;
    }
    
    if(listSize  &&
	    (TIME_INVALID != ulTimeOfCurrentDraw) )
    {
	LISTPOSITION pos = pTextWindow->GetStartPosition();

	int bkModeOld;
	bkModeOld = SetBkMode(hDC, TRANSPARENT);

	// /GM_ADVANCED is a graphics mode that allows char orientation;
	// doesn't work on Win95:
	int iOldGrphicsMode = SetGraphicsMode(hDC, GM_ADVANCED);

	while(pos)
	{
	    TextContainer* curTextContainerPtr =
			    /*  Note: effectively does GetAt(pos++):  */
			    (TextContainer*)pTextWindow->GetNext(pos);

	    ///Added call to the new function 
	    ///	"::textShouldBeDrawn()" because textHasChanged..() was
	    ///	not enough -- repaint of background was overwriting
	    /// non-moved text:

	    if(curTextContainerPtr->textHasChangedSinceLastDraw()  ||
		    curTextContainerPtr->textShouldBeDrawn())
	    {
		_CHAR* pTextbuffer = curTextContainerPtr->getBuffer();
		ULONG32 ulTextLengthPlusOneOfCurTC =
			curTextContainerPtr->getTextLengthPlus1();

		if (!pTextbuffer  ||  ulTextLengthPlusOneOfCurTC <= 1)
		{
		    curTextContainerPtr->textHasChangedSinceLastDraw(FALSE);
		    continue;
		}

		LONG32 lUpperLeftXWithOffsets =
			curTextContainerPtr->getXUpperLeftCorner();
		LONG32 lLowerRightXWithOffsets =
			curTextContainerPtr->getXLowerRightCorner();
		LONG32 lUpperLeftYWithOffsets =
			curTextContainerPtr->getYUpperLeftCorner();
		LONG32 lLowerRightYWithOffsets =
			curTextContainerPtr->getYLowerRightCorner();

		LONG32 xScaled  = lUpperLeftXWithOffsets;

		LONG32 yScaled = lUpperLeftYWithOffsets;

		HFONT hfont, hfontOld;

		const char* pCurFontFaceString = // /NOTE: NULL is valid value:
			pTextWindow->getDefaultFontFaceString();

		DWORD fdwCharset = DEFAULT_CHARSET;
		const char* pCharset = pTextWindow->getDefaultCharsetString();

		if (pCharset)
		{
		    ULONG32 ulCharset = CHARSET__default;
		    pTextWindow->getCharsetULONG32(pCharset,
			    PLAINTEXT_MAX_CHARSET_LEVEL_SUPPORTED, ulCharset);

		    BOOL bMightNeedCharsetTranslationForWindows = FALSE;

		    // /XXXEH- Windows has a MAC_CHARSET option, but that
		    // had no effect when I tried it, so do our own
		    // conversion within ANSI_CHARSET (which doesn't
		    // contain all Mac chars, so some will be wrong):
		    if (CHARSET__x_mac_roman == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
		    }
		    else if (CHARSET__iso_8859_1 == ulCharset)
		    {
			fdwCharset = ANSI_CHARSET;
			// /This maps exactly to WinTurkish, but do the
			// following, anyway, to clear out invalid 0x80-0x9F's:
			bMightNeedCharsetTranslationForWindows = TRUE;
		    }
		    else if (CHARSET__us_ascii == ulCharset)
		    {
			fdwCharset = ANSI_CHARSET;
			// /Do the following to ignore high-order (8th) bit:
			bMightNeedCharsetTranslationForWindows = TRUE;
		    }
		    else if (CHARSET__x_sjis == ulCharset)
		    {
			fdwCharset = SHIFTJIS_CHARSET;
		    }
		    else if (CHARSET__hangeul == ulCharset  ||
			    CHARSET__ksc5601 == ulCharset)
		    {
			fdwCharset = HANGEUL_CHARSET;
		    }
		    else if (CHARSET__johab == ulCharset)// /http://czyborra.com/charsets/iso8859.html
		    {
			fdwCharset = JOHAB_CHARSET;
		    }
		    else if (ulCharset & HX_CHINESE_CHARSET)
		    {
			//Note: there are two charsets for 2312, namely
			// CHARSET__gb_2312 and CHARSET__gb_2312_80, but Windows
			// doesn't know about the _80 one, so treat them both as
			// GB2312_CHARSET.
			fdwCharset = GB2312_CHARSET; 
			if (CHARSET__big5 == ulCharset  ||
				CHARSET__x_euc_tw == ulCharset)
			{
			    fdwCharset = CHINESEBIG5_CHARSET;
			}
		    } 
		    else if (CHARSET__iso_8859_2 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = EASTEUROPE_CHARSET;
		    }
		    else if (CHARSET__iso_8859_6 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = ARABIC_CHARSET;
		    }
		    else if (CHARSET__iso_8859_7 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = GREEK_CHARSET;
		    }
		    else if (CHARSET__iso_8859_8 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = HEBREW_CHARSET;
		    }
		    else if (CHARSET__iso_8859_9 == ulCharset)
		    {
			// /This maps exactly to WinTurkish, but call the
			// following, anyway, to clear out invalid 0x80-0x9F's:
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = TURKISH_CHARSET;
		    }
		    else if (CHARSET__iso_8859_13 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = BALTIC_CHARSET;
		    }
		    else if (CHARSET__iso_ir_166 == ulCharset  ||
			    CHARSET__iso_8859_11 == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = THAI_CHARSET;
		    }
		    else if (CHARSET__iso_8859_5 == ulCharset  ||
			    CHARSET__koi8_r == ulCharset)
		    {
			bMightNeedCharsetTranslationForWindows = TRUE;
			fdwCharset = RUSSIAN_CHARSET;
		    }
		    else if (CHARSET__windows_1251 == ulCharset)
		    {
			fdwCharset = RUSSIAN_CHARSET;
		    }
		    // /For plain text, just use the default one if not specified
		    // by a <param> value in the SMIL file:
		    else
		    {
			// /XXXEH- OEM_CHARSET, the Operating-system dependent
			// charset, should work, but DEFAULT_CHARSET will work
			// better if, say, "Osaka" is the font and OEM charset
			// isn't Japanese.  However, DEFAULT_CHARSET may result
			// in garbage if exact font face isn't found:
			fdwCharset = DEFAULT_CHARSET;
		    }

		    // /These charsets need to be translated fon Windows:
		    if (bMightNeedCharsetTranslationForWindows)
		    {
			if (!pTextWindow->isCharsetTranslatedForOS())
			{
			    if (ConvertAcrossCharacterSets(pTextbuffer,
				    ulCharset, TRUE,
				    PLAINTEXT_MAX_CHARSET_LEVEL_SUPPORTED))
			    {
				pTextWindow->setCharsetTranslatedForOS(TRUE);
			    }
			}
		    }
		}

#if XXXEH_HANDLE_UNDERLINE
		BOOL bIsUnderlined =
			pTextWindow->isUnderlinedPlainText();
#else
		ULONG32 ulFontWeight =
			pTextWindow->getDefaultFontWeight();
		BOOL bIsItalicized =
			pTextWindow->isDefaultFontStyleItalic();
		BOOL bIsUnderlined = FALSE;
#endif

		// /Create the appropriate font for all the text:

		ULONG32 ulBasePointSize  = pTextWindow->getDefaultPtSize();

		LONG32 nScaledWidth  = 0; // /0 forces closest match based on ht.

		double dAngleOfEscapement =
			pTextWindow->getPlainTextAngleOfEscapement()*10.0;

		double dAngleOfCharOrientation =
			pTextWindow->getPlainTextAngleOfCharOrientation()*10.0;		

		hfont = CreateFont(
			(INT32)ulBasePointSize, //logical ht 
			nScaledWidth, // logical average character width 
			// /<param name="escapementAngle"
			//         value="[float:0.0-360.0]"/>:
			dAngleOfEscapement, // /(In 10ths of a degree)
			// /<param name="charAngle"
			//         value="[float:0.0-360.0]"/>:
			// /defaults to angleOfEscapement():
			// /XXXEH- If Chinese or Japanese, should this be 0 if
			// escapement is 90 or 180?
			dAngleOfCharOrientation, // /(==escapement Win95)
			// /<param name="fontWeight"
			//         value="100|200|...|900|bold|normal"/>:
			(int)ulFontWeight, // /400==normal, 700==bold
			// /<param name="fontStyle" value="{true | false}"/>:
			bIsItalicized,//italic flag
#if XXXEH_HANDLE_UNDERLINE
			// /<param name="fontDecoration" value="underline"/>:
#endif
			bIsUnderlined,
			FALSE, // /strike-through text
			// /<param name="charset"
			//         value="[see textlib's fontdefs.h]"/>
			fdwCharset,
			OUT_DEFAULT_PRECIS,	// output precision 
			// /CLIP_LH_ANGLES OR'd in, here, tells orientation to
			// go clockwise for right-to-left fonts:
			CLIP_DEFAULT_PRECIS,// clipping precision
			// /<param name="quality" value="draft|normal|proof"
			DEFAULT_QUALITY,// output quality 
			DEFAULT_PITCH|FF_DONTCARE,// pitch and family
			// /<param name="fontFace" value="[whatever]"
			(char*)pCurFontFaceString
			);

		if(!hfont)
		{
#if !defined(USE_DIB_SECTION)
		    SelectObject(hDC, hbmpOld);
#endif
		    return FALSE;
		}

		hfontOld = (HFONT)SelectObject(hDC, hfont);
		if(!hfontOld)
		{
#if !defined(USE_DIB_SECTION)
		    SelectObject(hDC, hbmpOld);
#endif
		    DeleteObject(hfont);
		    return FALSE;
		}

		COLORTYPE textColor, textColorOld;
		textColor = pTextWindow->getDefaultTextColor();
		textColorOld = SetTextColor(
			hDC, convertCOLORTYPEtoWinBGRColor(textColor) );
		if(CLR_INVALID == textColorOld)
		{
#if !defined(USE_DIB_SECTION)
		    SelectObject(hDC, hbmpOld);
#endif
		    DeleteObject(hfont);
		    return FALSE;
		}

		COLORTYPE textBgColor, textBgColorOld;
		textBgColor = pTextWindow->getDefaultTextBgColor();
		int iPrevBkMode = GetBkMode(hDC);
		BOOL bNeedToUndoBkColor = FALSE;
		if (BGCOLOR_RGB_UNSPECIFIED != textBgColor  &&
			TRANSPARENT_COLOR != textBgColor)
		{
		    iPrevBkMode = SetBkMode(hDC, OPAQUE);
 		    textBgColorOld = SetBkColor(
		    	    hDC, convertCOLORTYPEtoWinBGRColor(textBgColor) );
		    bNeedToUndoBkColor = TRUE;

		    // /If SetBkColor fails, it's not a show-stopper; keep going
		}
 
                INT32 lXStart = xScaled;
		// /XXXEH- should be 0 (always, unless escapement angle is
		// between .1 and 179.9, in which case ...???):
                INT32 lYStart = yScaled;

		UINT32 ulAngle = (UINT32)(float)(dAngleOfEscapement/10.0);
		for (int iCt = 0; iCt < 2; iCt++)
		{
		    // /If escapement angle and/or char angle is below the
		    // horizon, we need to adjust a bit to the right so
		    // left-most chars are visible:
		    while (ulAngle < 0)
		    {
			ulAngle += 360;
		    }
		    ulAngle = ulAngle % 360;
		    if (ulAngle > 180  &&  ulAngle < 360)
		    {
			updateRect.left+= (UINT32)(((360-ulAngle)/180.0) *
				double((float)ulBasePointSize) * 2.0);
			lXStart = updateRect.left;
		    }
		    // /Now do char angle:
		    ulAngle = (UINT32)(float)(dAngleOfCharOrientation/10.0);
		}

		UINT32 ulDTFormat = 0;
		ulDTFormat = getPlainTextFormat(pTextWindow);

		INT32 lOriginalUpdateRectX = (LONG32)updateRect.left;
		if (0 == lOriginalUpdateRectX)
		{
		    updateRect.left = 2; // /Move text away from the edge.
		}


		// /Note: drawing the entire string using DrawText..() fixes
		// PR 65448:

		UINT32 ulHeightOfTextOutput =
#if defined(HANDLE_TAB_STOPS_AND_MARGINS)  &&  !IS_WIN32S
			DrawTextEx( // /NOTE: API not available on Win16 / Win32s
#else
			DrawText(
#endif
			hDC,
			LPSTR(pTextbuffer),
			INT32(ulTextLengthPlusOneOfCurTC)-1,
                        &updateRect,
			ulDTFormat
#if defined(HANDLE_TAB_STOPS_AND_MARGINS)  &&  !IS_WIN32S
			// /XXXEH- we could use DrawTextEX with a 6th parameter,
			// DRAWTEXTPARAMS, if we want to set tab stops, ...etc:
			,NULL
#endif
			);

		if (0 == lOriginalUpdateRectX)
		{
		    updateRect.left = 0; // Move it back.
		}

                // The following code handles both media opacity
                // and chroma key
                BOOL bChromaMatch = FALSE;
                if (pTextWindow->isChromaKeySet())
                {
                    bChromaMatch = DoesChromaKeyMatch(textColor,
			    pTextWindow->getChromaKey(),
			    pTextWindow->getChromaKeyTolerance());
                }
                if (pTextWindow->getMediaOpacity() < 255 ||
                    (bChromaMatch && pTextWindow->getChromaKeyOpacity() < 255))
                {
                    UINT32 ulOpacity = pTextWindow->getMediaOpacity();
                    if (bChromaMatch)
                    {
                        ulOpacity            = pTextWindow->getChromaKeyOpacity();
                        bChromaKeyWasApplied = TRUE;
                    }
		    // /XXXEH- #error: either call the following for the
		    // *entire* damaged rect (window) after all text has
		    // been drawn, or get the text "extent" (including
		    // effects of any word wrapping):
		    SIZE strsize;
		    // /XXXEH- #error: call DrawTextEx() with DT_CALCRECT
		    // in the dwDTFormat (4th) parameter to figure the
		    // actual bounding rect of the text output by DrawText():
                    // (but note: don't use DT_TABSTOP w/DT_CALCRECT and
                    // DT_TABSTOP is needed to fix PR 95128)
		    BOOL bGTEPSucceeded =
			    GetTextExtentPoint32(hDC, pTextbuffer,
			    ulTextLengthPlusOneOfCurTC-1, &strsize);

                    ApplyTextOpacity(pTextWindow, lXStart, lYStart,
			    strsize.cx, strsize.cy, TRUE, textColor,
			    ulOpacity);
                }
#if 0
UINT prevAlignment = 
	SetTextAlign(hDC, VTA_BASELINE);
#endif

#if 0
if(GDI_ERROR != prevAlignment)
{
    SetTextAlign(hDC, prevAlignment);
}
#endif

		/*  Restore the previous font:  */
		SelectObject(hDC, hfontOld);
		DeleteObject(hfont);

		/*  Restore the previous colors:  */
		SetTextColor(hDC, textColorOld);
		if (bNeedToUndoBkColor)
		{
		    SetBkColor(hDC, textBgColorOld);
		    SetBkMode(hDC, iPrevBkMode);
		}
/* XXXXXEH> no need to do this: (right?)
		SetBkColor(hDC, textColorOld); 
<XXXXXEH. */
		curTextContainerPtr->textHasChangedSinceLastDraw(FALSE);
	    } //end "if(curTextContainerPtr->textHasChangedSinceLastDraw())".
	} //end "while(pos)".

	SetBkMode(hDC, bkModeOld);
	SetGraphicsMode(hDC, iOldGrphicsMode);

    } //end "if(listSize)".

#if !defined(USE_DIB_SECTION)
    // retreive the bitmap handler
    HBITMAP hBM = (HBITMAP)SelectObject(hDC, hbmpOld);
#endif

    UCHAR*  pBits = NULL;
    LPBITMAPINFOHEADER pHeader = NULL;

#if !defined(USE_DIB_SECTION)
    // convert HBITMAP to DIB:
    if (pTextWindow->m_hDIB &&
	HXR_OK == pTextWindow->m_hDIB->GetDIBits(hDC, hBM, pBits, pHeader))
    {				    
#else //USE_DIB_SECTION:
    //we already have a DIB, so use it:
    if(pTextWindow->m_pBits)
    {
	pBits = (UCHAR*)(pTextWindow->m_pBits);
	pHeader = &(pTextWindow->m_BITMAPINFOHEADER);
#endif
	CHXxRect* pDestRect = (CHXxRect*)((HXxEvent*)pVoid)->param2;

	CHXxRect srcRect(0, 0, lWindowWidth, lWindowHeight);
	
	LONG32 lImageOffset = 0L;

#if defined(SCROLLINGVERSION_SCROLL_BY_MOVING_WINDOW)
	//Keep the offscreen height so we can reset it after doing the Blt():
	LONG32 lSavedHeaderHeight = pHeader->biHeight;
	//If we're just using part of a larger offscreen area, then we need to
	// send an offset into the buffer that accounts for the extra vertical
	// lines of data (which, in Windows, byte 0 of the data is the first
	// byte of the LAST scan line, i.e., starts line # pBitmapInfo->biHeight):
	if(pHeader->biHeight != srcRect.Height())
	{
	    lImageOffset =
		    (pHeader->biHeight - srcRect.Height() - srcRect.top) *
		    (pHeader->biBitCount / 8) * pHeader->biWidth;
	    if(lImageOffset > 0L)
	    {
		if(srcRect.top != 0)
		    srcRect.bottom -= srcRect.top;
		srcRect.top = 0;
		pHeader->biHeight = srcRect.Height();
		pHeader->biSizeImage = WIDTHBYTES((pHeader->biWidth * 
			pHeader->biBitCount) * pHeader->biHeight);
	    }
	    else
	    {
		lImageOffset = 0L;
	    }
	}
#endif

	CHXxRect destRect;

	if (pDestRect)
	{
	    destRect.SetRect(pDestRect->left, 
			     pDestRect->top, 
			     pDestRect->right,
			     pDestRect->bottom);
	}
	else
	{
	    destRect.SetRect(0,
			     0,
			     lWindowWidth, 
			     lWindowHeight);
	}

	IHXVideoSurface* pVideoSurface = (IHXVideoSurface*)((HXxEvent*)pVoid)->param1;
	pVideoSurface->AddRef();

	if(!pTextWindow->m_bHandlingWindowResizing
		&&  pTextWindow->m_hBitmap)//avoid race condition
				      // when re-allocating offscreen bitmap:
	{
#if defined(XXXMEH_BACKGROUND_NO_GDI) && defined(HANDLE_TRANSPARENT_WINDOW_BACKGROUND)
            DWORD oldComp = pHeader->biCompression;
            if (pTextWindow->getBackgroundOpacity() < 255 ||
                pTextWindow->getMediaOpacity() < 255 ||
                bChromaKeyWasApplied)
            {
                pHeader->biCompression = HX_ARGB;
            }
#endif
	    ((HXxEvent*)pVoid)->result = pVideoSurface->Blt(
		    pBits + lImageOffset,
		    (HXBitmapInfoHeader*)pHeader,
		    destRect, 
		    srcRect);
#if defined(XXXMEH_BACKGROUND_NO_GDI) && defined(HANDLE_TRANSPARENT_WINDOW_BACKGROUND)
            pHeader->biCompression = oldComp;
#endif
	}

#if defined(SCROLLINGVERSION_SCROLL_BY_MOVING_WINDOW)
	pHeader->biHeight = lSavedHeaderHeight; //Restore it for the next time.
#endif

	HX_RELEASE(pVideoSurface);
    }
    else
    {
	b_FunctionSucceeded = FALSE;
    }
    
    return b_FunctionSucceeded;
}
