/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: txtattrb.h,v 1.1.2.1 2004/07/09 01:50:15 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 ***** */

/////////////////////////////////////////////////////////////////////////////
//
//  TXTATTRB.H
//
//  This is the header file for the class TextAttributes, which holds the
//  text-to-be-rendered's attributes like font color, weight, size,
//  italicized or not, ...etc., and class TextAttributeStacks which is a
//  group of TextAttrbStack objects that keep track of changes in
//  attributes so that when the scope of a change ends (and that change
//  is "popped" from the stack), the previous value for that attribute
//  can be obtained and used for the next block of text.
//

#if !defined(_TXTATTRB_H_)
#define _TXTATTRB_H_

class TextWindow;

#if !defined(BAD_RGB_COLOR)
#define BAD_RGB_COLOR			0xBADCBADC //Illegal COLORTYPE val.
#endif
#if !defined(TRANSPARENT_COLOR)
#define TRANSPARENT_COLOR		0xFF000000
#endif
#define DEFAULT_TEXT_COLOR		0x00000000 //Black, in Windows.
//Means use MM_TRANSPARENT in TextOut():
#define DEFAULT_TEXT_BGCOLOR		BAD_RGB_COLOR 
#define DEFAULT_TICKER_UPPERCOLOR	0x00FFFFFF //White, in Windows.
#define DEFAULT_TICKER_LOWERCOLOR	0x0000FF00 //Light green, in Windows.
#define DEFAULT_FONT_PTSIZE		FONT_SIZE_0
#define DEFAULT_BLINKRATE		0

#define TIME_INVALID			((ULONG32)0xFFFFFFFF)

enum
{
    URL_TARGET_INVALID = 0L,
    URL_TARGET_PLAYER,
    URL_TARGET_BROWSER
};

//added this function which converts a predefined 
// string into a font index (returning default index if string unrecognized):
ULONG32 getFontFaceIndexFromString(_CHAR* pFntFc, ULONG32 len,
	ULONG32 ulMajorContentVersion, ULONG32 ulMinorContentVersion);


//////////////////////////////////////////////////////////////////////////////
//
//	TextAttributes class:
//
class TextAttributes 
{ 
  public: 
    TextAttributes() { init(); }
    
    //Call this right after calling the default T.A.(T.A.&)
    // constructor if you are creating a new TextLine with this call:
    void clearWithoutDeletingHrefBuf() { m_pHrefBuf=NULL; m_hrefBufLen=0L; 
	    m_ulTargetOfURL = URL_TARGET_INVALID;}

    ~TextAttributes() { delete_all(); }

    void delete_all() { clear_URL(); }

    void clear_URL();

    void clear()
    {
	//You MUST call this before init() unless in constructor:
	delete_all();
	init();
    }

    void init();
    
    //Data access functions:
    COLORTYPE getTextColor() { return (m_textColor); }
    COLORTYPE getTickertapeTextColor()
    {
	return(isTickerUpperText()?m_tickerUpperColor:m_tickerLowerColor);
    }
    COLORTYPE getTextBackgroundColor() { return (m_textBackgroundColor); }
    COLORTYPE getTickerUpperColor() { return (m_tickerUpperColor); }
    COLORTYPE getTickerLowerColor() { return (m_tickerLowerColor); }
    const _CHAR* getFontFaceString(
	    ULONG32 ulMajorContentVersion, ULONG32 ulMinorContentVersion);
    ULONG32 getFontFace() { return (m_fontFaceIndex); }
    ULONG32 getFontPointSize() { return (m_fontPointSize); } 
    ULONG32 getFontCharset() { return (m_fontCharset); } 
    BOOL isBold() { return (m_isBold); } 
    BOOL isItalicized() { return (m_isItalicized); } 
    BOOL isUnderlined() { return (m_isUnderlined); }
    BOOL isStruckOut() { return (m_isStruckOut); }
    BOOL isStartOfNewLine() { return (m_numNewlinesAtStart>0L); }
    //added this for crawlrate "newlines":
    BOOL isFakeNewLine() { return m_isFakeNewLine; }
    BOOL isWordWrapNewLine() { return m_isWordWrapNewLine; }
    ULONG32 getNumNewlinesAtStart() { return m_numNewlinesAtStart; }
    LONG32 GetBreakSpacingX() { return m_breakSpacingX; }
    LONG32 GetBreakSpacingY() { return m_breakSpacingY; }
    BOOL isTickerUpperText() { return (m_isTickerUpperText); }
    ULONG32 getBlinkRate() { return (m_blinkRate); }
    BOOL isCentered() { return m_isCentered; }
    BOOL isPreFormatted() { return m_bIsPreFormatted; }
    ULONG32 isRequired() { return m_ulRequired; }
    //added this for indenting text in lists and as requested:
    UINT16 getLineIndentAmtInPixels() { return(m_lineIndentAmtInPixels);}
    BOOL isLit() { return (m_isLit); } 
    _CHAR* getHrefBuf() { return (m_pHrefBuf); }
    ULONG32 getHrefBufLen() { return (m_hrefBufLen); }
    //This tells to which app (browser or player) to send the
    // URL in m_pHrefBuf when mouse-clicked:
    ULONG32 getTargetOfURL() {return m_ulTargetOfURL; }

    ULONG32 getBeginTime() { return (m_beginTime); }
    ULONG32 getStartTime() { return (m_beginTime); }
    ULONG32 getEndTime() { return (m_endTime); }
    ULONG32 getStopTime() { return (m_endTime); }
    ULONG32 getMostRecentTimeTagEndTime() { 
	    return m_ulMostRecentTimeTagEndTime; }
    ULONG32 getLastKnownTime() { return (m_lastKnownTime); }
    LONG32 getLastKnownX() { return (m_lastKnownX); } 
    LONG32 getLastKnownY() { return (m_lastKnownY); }
    LONG32 getXAtTimeZeroUpperLeftCorner() {
	    return (m_xAtTimeZeroUpperLeftCorner); } 
    LONG32 getYAtTimeZeroUpperLeftCorner() { 
	    return (m_yAtTimeZeroUpperLeftCorner); } 
    LONG32 getXUpperLeftCorner() { return (m_xUpperLeftCorner); } 
    LONG32 getYUpperLeftCorner() { return (m_yUpperLeftCorner); }
    LONG32 getXLowerRightCorner() { return (m_xUpperLeftCorner+m_xExtent-1);} 
    LONG32 getYLowerRightCorner() { return (m_yUpperLeftCorner+m_yExtent-1);}
    LONG32 getXExtent() { return (m_xExtent); }
    LONG32 getYExtent() { return (m_yExtent); }

    void setTextColor(COLORTYPE c) { m_textColor = c; }
    void setTextBackgroundColor(COLORTYPE c) { m_textBackgroundColor = c; }
    void setTickerUpperColor(COLORTYPE c) { m_tickerUpperColor = c; }
    void setTickerLowerColor(COLORTYPE c) { m_tickerLowerColor = c; }
    //Added this line to handle charsets:
    void setFontCharset(ULONG32 fntCharset) { m_fontCharset=fntCharset; } 
    void setFontPointSize(ULONG32 fntPtSz) { m_fontPointSize=fntPtSz; } 
    void isBold(BOOL isB) { m_isBold = isB; } 
    void isItalicized(BOOL isI) { m_isItalicized = isI; } 
    void isUnderlined(BOOL isU) { m_isUnderlined = isU; }
    void isStruckOut(BOOL isSU) { m_isStruckOut = isSU; }
    void setNumNewlinesAtStart(ULONG32 numNL) {m_numNewlinesAtStart = numNL;}
    //added this for crawlrate "newlines":
    void isFakeNewLine(BOOL isFNL) { m_isFakeNewLine = isFNL; }
    //added this to know who's a newline due to wordwrap:
    void isWordWrapNewLine(BOOL isWWNL) { m_isWordWrapNewLine = isWWNL; }
    void SetBreakSpacingX(LONG32 brkSpcX) { m_breakSpacingX = brkSpcX; }
    void SetBreakSpacingY(LONG32 brkSpcY) { m_breakSpacingY = brkSpcY; }
    void isTickerUpperText(BOOL isTUT) { m_isTickerUpperText = isTUT; }
    void setBlinkRate(ULONG32 br) { m_blinkRate = br; }
    void isCentered(BOOL isCntr) { m_isCentered = isCntr; }
    void isPreFormatted(BOOL bIsPre) { m_bIsPreFormatted = bIsPre; }
    void isRequired(ULONG32 ulRequired) { m_ulRequired = ulRequired; }

    //added this for indenting text in lists and as requested:
    void setLineIndentAmtInPixels(UINT16 li) { m_lineIndentAmtInPixels = li;}
    void isLit(BOOL isL) { m_isLit = isL; } 
    void setBeginTime(ULONG32 t) { m_beginTime = t; }
    void setStartTime(ULONG32 t) { setBeginTime(t); }
    void setEndTime(ULONG32 t) { m_endTime = t; }
    void setMostRecentTimeTagEndTime(ULONG32 t)
	    { m_ulMostRecentTimeTagEndTime = t; }
    void setStopTime(ULONG32 t) { setEndTime(t); }
    void setLastKnownTime(ULONG32 t) { m_lastKnownTime=t; }
    void setLastKnownX(LONG32 x) { m_lastKnownX=x; } 
    void setLastKnownY(LONG32 y) { m_lastKnownY=y; }
    void setXAtTimeZeroUpperLeftCorner(LONG32 x) { 
	    m_xAtTimeZeroUpperLeftCorner=x; } 
    void setYAtTimeZeroUpperLeftCorner(LONG32 y) { 
	    m_yAtTimeZeroUpperLeftCorner=y; } 
    void setXUpperLeftCorner(LONG32 x) { m_xUpperLeftCorner=x; } 
    void setYUpperLeftCorner(LONG32 y) { m_yUpperLeftCorner=y; }
    void setXExtent(LONG32 x) { m_xExtent=x; }
    void setYExtent(LONG32 y) { m_yExtent=y; }
    void setFontFace(_CHAR* pFntFc, ULONG32 len,
	    ULONG32 ulMajorContentVersion,
	    ULONG32 ulMinorContentVersion);
    void setFontFace(ULONG32 fntFcIndex);

    ULONG32 getNumLinkColorOverrides() { return m_ulNumLinkColorOverrides; }
    void setNumLinkColorOverrides(ULONG32 ulNLCO)
	    { m_ulNumLinkColorOverrides = ulNLCO; }

    //Creates new buffer and copies href into it;
    // returns FALSE if alloc (new) fails:
    BOOL copyIntoHrefBuf(_CHAR* pHref, ULONG32 len, ULONG32 ulTargetOfURL);
    //This gets called in response to a <CLEAR> tag being
    // encountered at time ulNewEndTime; if(m_startTime < ulNewEndTime),
    // this function resets m_endTime to min(m_endTime, ulNewEndTime);
    // returns TRUE if change is made to m_endTime, else FALSE:
    BOOL MarkForClear(ULONG32 ulNewEndTime, BOOL bIsLiveSource);
    LONG32 ComputeScrollDelta(ULONG32 ulCurTime, LONG32 scrollrate);
    LONG32 ComputeCrawlDelta(ULONG32 ulCurTime, LONG32 scrollrate);

    ///Changes the start and end times of *this if refTA's
    // start or end time is earlier or later, respectively, than this's:
    BOOL updateStartAndEndTimes(TextAttributes* pTA, BOOL bIsLiveSource);

    //Changes the start and end times of *this as
    // calculated by "appearance" of the text in the window, i.e.,
    // if there is a scrollrate or crawlrate, this calculates when it first
    // becomes visible in the window and then when it moves back out:
    BOOL adjustStartAndEndTimes(TextWindow* pTW);

  private:
    COLORTYPE m_textColor; //a.k.a., "Foreground Color".
    //Bkground color for just the text's bounding box:
    COLORTYPE m_textBackgroundColor;
    
    //Foreground color for "upper" line of ticker tape text:
    COLORTYPE m_tickerUpperColor;
    //Foreground color for "lower" line of ticker tape text:
    COLORTYPE m_tickerLowerColor;
    //Font face; defaults to NULL which means use system
    // fixed font.  This is only 32 chars because that is
    // the limit Windows placed on the lpszFace parameter
    // of CreateFont().  32 includes the terminating '\0':
    ULONG32 m_fontFaceIndex; 
    //Added this line to handle charsets:
    ULONG32 m_fontCharset;  //these are #defined (ULONG32)values
    //Font size if a scalable font is selected:
    ULONG32 m_fontPointSize;  
    //TRUE if text is to be rendered as bold. (Use <B>..</B> tags):
    BOOL m_isBold;
    //TRUE if text is to be in italics. (Use <I>..</I> tags):
    BOOL m_isItalicized;
    //TRUE if text is to be underlined. (Use <U>..</U> tags):
    BOOL m_isUnderlined;
    //TRUE if text is to be "crossed out". (Use <S>..</S> tags):
    BOOL m_isStruckOut; 
    // This is the number of newlines (<BR> or <P>..etc. tags)
    // that start this text (also, could be a newline from wordwraping):
    ULONG32 m_numNewlinesAtStart;
    //added the following to fake newlines in horizontal-
    // motion-only windows with no explicit line breaks (so file format can
    // divide the text up into time-based chunks based on visibility in the
    // window at any particular time):
    BOOL m_isFakeNewLine;
    //added the following to keep track of who starts a
    // new line due to wordwrap:
    BOOL m_isWordWrapNewLine;
    //This is the spacing, in logical units, that the <BR> tags (see
    // numNewlinesAtStart, above) moved the text's location, in X:
    LONG32 m_breakSpacingX;
    //This is the spacing, in logical units, that the <BR> tags (see
    // numNewlinesAtStart, above) moved the text's location, in Y:
    LONG32 m_breakSpacingY;
    //Is TRUE if is an upper-line text of tickertape window:
    BOOL m_isTickerUpperText; 
    //Is in msec. Isn't blinking if==0.  Example: 2000 means alternate
    // between ON for 2 seconds then OFF for 2 seconds:
    ULONG32 m_blinkRate;
    //If blinkRate != 0, this tells whether is lit or unlit since
    // last timer:
    BOOL m_isLit;
    //Tells whether *this's text is between <CENTER> and </CENTER> tags:
    BOOL m_isCentered;
    //Tells whether *this's text is between <PRE> and </PRE> tags:
    BOOL m_bIsPreFormatted;
    //Tells whether *this's text is between <REQUIRED> and </REQUIRED> tags:
    ULONG32 m_ulRequired; //Is count of <REQ..> tags since the last </REQ...>
    //Holds URL or filename contained inside <A> tag if the associated
    // text of *this was between a <A ..> and a </A>:
    _CHAR* m_pHrefBuf; 
    //  Use this so length doesn't have to be recalculated to use buffer:
    ULONG32 m_hrefBufLen; 

    ULONG32 m_ulTargetOfURL;
    
    //added this for indenting text in lists and
    // as requested:
    UINT16 m_lineIndentAmtInPixels;
    //This is the time after which the text should be drawn:
    ULONG32 m_beginTime;
    //This is the time after which the text should be deleted:
    ULONG32 m_endTime;
    //For calculating where text was last drawn so that next
    // draw will scroll or crawl at the proper rate:
    ULONG32 m_lastKnownTime;
    //For calculating where text was last drawn so that next
    // draw will scroll or crawl at the proper rate:
    LONG32 m_lastKnownX;	
    //For calculating where text was last drawn so that next
    // draw will scroll or crawl at the proper rate:
    LONG32 m_lastKnownY;

    //This is needed so that the file format can know whether or not the
    // anchor tag set the font color or if there is a <font color="foo">
    // tag after the <a...> and before the </a> tag.  This way, the packet
    // header can accurately order the <a> and <font> tags so that the
    // color comes out right at the renderer end:
    ULONG32 m_ulNumLinkColorOverrides;
    
    //This is needed because we need to know when the
    // last-seen "<TIME ... end=endTime>" was seen.  Since m_endTime may not
    // necessarily be equal to endTime (it can be adjusted down by 
    // adjustStartAndEndTimes() ), we need to know what the original endtime
    // was:
    ULONG32 m_ulMostRecentTimeTagEndTime;

    //Changed these from "AtBeginTime" to "AtTimeZero":
    LONG32 m_xAtTimeZeroUpperLeftCorner; //where text is initially drawn. 
    LONG32 m_yAtTimeZeroUpperLeftCorner; //where text is initially drawn. 
    
    LONG32 m_xUpperLeftCorner; //where TextOut() will draw the text. 
    LONG32 m_yUpperLeftCorner; //where TextOut() will draw the text. 
    LONG32 m_xExtent; //the calculated width, in pixels, of the text.
    LONG32 m_yExtent; //the calculated height, in pixels, of the text.
}; //END class TextAttributes declaration.




/*////////////////////////////////////////////////////////////////////////////
*
*	TextAttribStack class:
*/
class TextAttribStackULONG32 : public CHXStack
{
  public:
    TextAttribStackULONG32() { m_isInitialized = FALSE; }
    TextAttribStackULONG32(const ULONG32& defaultVal) { init(defaultVal); }

    ~TextAttribStackULONG32()
    {
	removeAll();
    };

    void init(const ULONG32& defaultVal)
    {
	m_defaultValue = defaultVal;
	push(m_defaultValue);
	m_isInitialized = TRUE;
    }


#if defined(SHOW_CODE_CHANGE_MESSAGES)
#pragma message("EH- in "__FILE__", do I want \"push(const T& t)\" here?")
#endif
/*
    void push(T& t);

    T& pop();  //returns reference to T on top of stack.

    T& peek(); //gets contents at top without popping it.
*/
    void push(ULONG32& ul)
    {
	ULONG32* p_ul = NULL;
	if((p_ul = getNew_ULONG32(ul)) != NULL)
	{
	    CHXStack::Push((void*)p_ul);
	}
    }

    ULONG32 pop()
    {
	if(GetSize() <= 0)
	    push(m_defaultValue);
	ULONG32* p_ul = (ULONG32*)CHXStack::Pop();
	ULONG32  ret_val;
	if(p_ul == (ULONG32*)0)
	{
	    return m_defaultValue;
	}
	else
	{
	    ret_val = *p_ul;
	    delete p_ul;
	    return ret_val;
	}
    }

    ULONG32& peek()
    {
	if(GetSize() <= 0)
	{
	    push(m_defaultValue);
	}
	ULONG32* p_ul = (ULONG32*)ElementAt(GetSize()-1);
	if(p_ul == (ULONG32*)0)
	{
	    return m_defaultValue;
	}
	else
	{
	    return *p_ul;
	}
    }

    void removeAll()
    {
	while (CHXStack::GetSize() > 0)
	{
	    ULONG32* p_ul = (ULONG32*)CHXStack::Pop();
	    delete p_ul;
	}

	RemoveAll();
    }

  private:
    ULONG32 m_defaultValue;

    BOOL m_isInitialized;

    ULONG32* getNew_ULONG32(ULONG32 ul)  //will return NULL if new() fails.
    {
	ULONG32* p_ul = new(ULONG32);
	if(p_ul)
	{
	    *p_ul = ul;
	}
	return p_ul;
    }
};

/*////////////////////////////////////////////////////////////////////////////
*
*	TextAttribStack class:
*/
class TextAttribStackBOOL
{
  public:
    TextAttribStackBOOL() { m_isInitialized = FALSE; m_ulTRUEcount=0L;}
    TextAttribStackBOOL(BOOL defaultVal) { init(defaultVal); }

    ~TextAttribStackBOOL()
    {
	removeAll();
    };

    void init(BOOL defaultVal)
    {
	m_ulTRUEcount =0L;
	m_defaultValue = defaultVal;
	push(m_defaultValue);
	m_isInitialized = TRUE;
    }


    void push(BOOL b)
    {
	if(b)
	    m_ulTRUEcount++;
	else if(m_ulTRUEcount > 0)
	    m_ulTRUEcount--;
    }

    ULONG32 pop()
    {
	if(!m_ulTRUEcount)
	    push(m_defaultValue);
	else
	   m_ulTRUEcount--;
	return m_ulTRUEcount;
    }

    ULONG32 peek()
    {
	if(!m_ulTRUEcount)
	    push(m_defaultValue);
	return m_ulTRUEcount;
    }

    void removeAll()
    {
	m_ulTRUEcount = 0L;
    }

  private:
    BOOL m_defaultValue;

    //If greater than 0, then there have been more TRUE "pushes" than
    // FALSE ones, e.g., if we see "<b><b></b>", then the count goes
    // from 0 to 1 to 2 to 1, and isBold is thus TRUE since its count
    // is 1.  "<b></b></b>" would go from 0 to 1 to 0 to 0, i.e., it
    // will not go below 0 so a subsequent <b> will be honored (by not
    // being matched with the prior </b>.
    ULONG32 m_ulTRUEcount;

    BOOL m_isInitialized;
};


/*////////////////////////////////////////////////////////////////////////////
*
*	TextAttributeStacks class:
*/

#define FONT_SIZE	0x00000001L
#define FONT_FACE	0x00000002L
#define FONT_COLOR	0x00000004L
#define FONT_BGCOLOR	0x00000008L
#define FONT_CHARSET	0x00000010L


class TextAttributeStacks
{ 
  public:
    TextAttributeStacks();

    ~TextAttributeStacks() { ;}

    void flush();

    void flushFontStacks();
    void flushTickerStacks();
    void flushBIUSandBlinkStacks();
    void flushIndentAmtStack();

    void setTextAttributesToTopsOfStacksVals(TextAttributes& ta);

    //The following return the default val if stack is empty:
    inline    ULONG32 popFontStack();
    inline    COLORTYPE popTextColorStack();
    inline    COLORTYPE popTextBackgroundColorStack();
    inline    COLORTYPE popTickerUpperColorStack();
    inline    COLORTYPE popTickerLowerColorStack();
    inline    ULONG32 popFontFaceStack();
    inline    ULONG32 popFontCharsetStack();
    inline    ULONG32 popFontPointSizeStack();
    inline    ULONG32 peekAtFontPointSizeStack();
    inline    BOOL popIsBoldStack();
    inline    BOOL popIsItalicizedStack();
    inline    BOOL popIsUnderlinedStack();
    inline    BOOL popIsStruckOutStack();
    inline    ULONG32 popBlinkRateStack();
    inline    BOOL popIsCenteredStack();

    inline    BOOL popIsRequiredStack();
    
    inline    BOOL popIsPreStack();
    inline    BOOL peekAtIsPreStack();
    
    inline    UINT16 popLineIndentAmtInPixelsStack();
    inline    UINT16 peekAtLineIndentAmtInPixelsStack();
    inline    ULONG32 popFontTagStartByteInFileStack();

    //The following return the default val if stack is empty:
    inline    void pushFontStack(ULONG32 ul);
    inline    void pushTextColorStack(COLORTYPE clr,
			    BOOL bPushFontStackToo=TRUE);
    inline    void pushTextBackgroundColorStack(COLORTYPE clr,
			    BOOL bPushFontStackToo=TRUE);
    inline    void pushFontCharsetStack(ULONG32 charset,
			    BOOL bPushFontStackToo=TRUE);
    inline    void pushFontPointSizeStack(ULONG32 siz,
			    BOOL bPushFontStackToo=TRUE);
    inline    void pushTickerUpperColorStack(COLORTYPE clr);
    inline    void pushTickerLowerColorStack(COLORTYPE clr);
    void pushFontFaceStack(ULONG32 ulFontFaceIndex);

    void      isTickerUpperText(BOOL itut) { m_bIsTickerUpperText = itut; }

    inline    void pushIsBoldStack(BOOL isBld);
    inline    void pushIsItalicizedStack(BOOL isItal);
    inline    void pushIsUnderlinedStack(BOOL isUndrln);
    inline    void pushIsStruckOutStack(BOOL isStrckOut);
    inline    void pushBlinkRateStack(ULONG32 blnkRt);
    inline    void pushIsCenteredStack(BOOL isCenterd);

    inline    void pushIsRequiredStack();

    inline    void pushIsPreStack();

    //For indenting text in lists and as requested:
    inline    void pushLineIndentAmtInPixelsStack(UINT16 lia);

    inline    void pushFontTagStartByteInFileStack(ULONG32 ulStartByte);

    ULONG32 peekAtTextColorStack() { return m_textColorStack.peek(); }
    ULONG32 peekAtTextBackgroundColorStack() { 
	    return m_textBackgroundColorStack.peek(); }
    ULONG32 peekAtPointSizeStack() { return m_fontPointSizeStack.peek(); }
    ULONG32 peekAtCharsetStack() { return m_fontCharsetStack.peek(); }
    ULONG32 peekAtFontFaceStack() { return m_fontFaceStack.peek(); }

  private:
    /*  Note: stacks are initialized to default vals (at index [0]) and if
     *  user tries to pop when stack top is [0], i.e., an "empty" stack,
     *  the default val in [0] is never removed and is returned:  */
    TextAttribStackULONG32 m_fontStack;
    TextAttribStackULONG32 m_textColorStack;
    TextAttribStackULONG32 m_textBackgroundColorStack; 
    TextAttribStackULONG32 m_fontFaceStack;
    TextAttribStackULONG32 m_fontCharsetStack;
    TextAttribStackULONG32 m_fontPointSizeStack;

    TextAttribStackULONG32 m_tickerUpperColorStack; 
    TextAttribStackULONG32 m_tickerLowerColorStack; 
    BOOL m_bIsTickerUpperText; 

    TextAttribStackBOOL m_isBoldStack;
    TextAttribStackBOOL m_isItalicizedStack;
    TextAttribStackBOOL m_isUnderlinedStack;
    TextAttribStackBOOL m_isStruckOutStack;
    TextAttribStackBOOL m_isCenteredStack;
    ULONG32 m_ulRequiredTagCount;
    ULONG32 m_ulPreTagCount;
    TextAttribStackULONG32 m_blinkRateStack;
    //added this for indenting text in lists and as requested:
    TextAttribStackULONG32 m_lineIndentAmtInPixelsStack;

    //This keeps track of the location in the file of each
    // <FONT> tag so each </FONT> tag knows where it's matching <FONT> tag is
    TextAttribStackULONG32 m_fontTagStartByteInFileStack;

};  //END class TextAttributeStacks declaration.


/********************************************************************
 *	Inline class TextAttributeStacks methods
 ********************************************************************/
//The following return the default val if stack is empty:
inline
ULONG32 TextAttributeStacks::popFontStack()
{
    ULONG32 fontTop = m_fontStack.peek();
    if(fontTop & FONT_SIZE)
    {
	popFontPointSizeStack();
    }
    if(fontTop & FONT_FACE)
    {
	popFontFaceStack();
    }
    if(fontTop & FONT_COLOR)
    {
	popTextColorStack();
    }
    if(fontTop & FONT_BGCOLOR)
    {
	popTextBackgroundColorStack();
    }
    if(fontTop & FONT_CHARSET)
    {
	popFontCharsetStack();
    }

    ULONG32 curFontTop = m_fontStack.peek();
    m_fontStack.pop();
 
    return fontTop;
}

inline
COLORTYPE TextAttributeStacks::popTextColorStack()
{
    ULONG32 fontTop = m_fontStack.pop();
    if(fontTop & FONT_COLOR)
    {
	fontTop -= FONT_COLOR; //clears the FONT_COLOR bit.
	m_fontStack.push(fontTop);//resets stack top with FONT_COLOR gone
    }

    return (m_textColorStack.pop());
}

inline
COLORTYPE TextAttributeStacks::popTextBackgroundColorStack()
{
    ULONG32 fontTop = m_fontStack.pop();
    if(fontTop & FONT_BGCOLOR)
    {
	fontTop -= FONT_BGCOLOR; //clears the FONT_BGCOLOR bit.
	m_fontStack.push(fontTop);//resets stack top with FONT_COLOR gone
    }

    return (m_textBackgroundColorStack.pop());
}

inline
COLORTYPE TextAttributeStacks::popTickerUpperColorStack()
{
    return (m_tickerUpperColorStack.pop());
}

inline
COLORTYPE TextAttributeStacks::popTickerLowerColorStack()
{
    return (m_tickerLowerColorStack.pop());
}

inline
ULONG32 TextAttributeStacks::popFontFaceStack()
{
    ULONG32 fontTop = m_fontStack.pop();
    if(fontTop & FONT_FACE)
    {
	fontTop -= FONT_FACE; //clears the FONT_FACE bit.
	m_fontStack.push(fontTop);//resets stack top with FONT_COLOR gone
    }
    return (m_fontFaceStack.pop());
}

inline
ULONG32 TextAttributeStacks::popFontCharsetStack()
{
    ULONG32 fontTop = m_fontStack.pop();
    if(fontTop & FONT_CHARSET)
    {
	fontTop -= FONT_CHARSET; //clears the FONT_CHARSET bit.
	m_fontStack.push(fontTop);//resets stack top with FONT_COLOR gone
    }

    return (m_fontCharsetStack.pop());
}

inline
ULONG32 TextAttributeStacks::popFontPointSizeStack()
{
    ULONG32 fontTop = m_fontStack.pop();
    if(fontTop & FONT_SIZE)
    {
	fontTop -= FONT_SIZE; //clears the FONT_SIZE bit.
	m_fontStack.push(fontTop);//resets stack top with FONT_COLOR gone
    }

    return (m_fontPointSizeStack.pop());
}

/*  Looks at, but doesn't change stack:  */
inline
ULONG32	TextAttributeStacks::peekAtFontPointSizeStack() 
{
    return (m_fontPointSizeStack.peek());
}

inline
BOOL TextAttributeStacks::popIsBoldStack()
{
    return ((BOOL)m_isBoldStack.pop());
}

inline
BOOL TextAttributeStacks::popIsItalicizedStack()
{
    return ((BOOL)m_isItalicizedStack.pop());
}

inline
BOOL TextAttributeStacks::popIsUnderlinedStack()
{
    return ((BOOL)m_isUnderlinedStack.pop());
}

inline
BOOL TextAttributeStacks::popIsStruckOutStack()
{
    return ((BOOL)m_isStruckOutStack.pop());
}

inline
ULONG32 TextAttributeStacks::popBlinkRateStack()
{
    return (m_blinkRateStack.pop());
}

inline
BOOL TextAttributeStacks::popIsCenteredStack()
{
    return ((BOOL)m_isCenteredStack.pop());
}

inline
BOOL TextAttributeStacks::popIsRequiredStack()
{
    if(m_ulRequiredTagCount>0L)
	return(BOOL(m_ulRequiredTagCount--));
    return (FALSE);
}

inline
BOOL TextAttributeStacks::popIsPreStack()
{
    if(m_ulPreTagCount>0L)
	return(BOOL(m_ulPreTagCount--));
    return (FALSE);
}
inline
BOOL TextAttributeStacks::peekAtIsPreStack()
{
    return(BOOL(m_ulPreTagCount));
}

//added this for indenting text in lists and as requested:
inline
UINT16 TextAttributeStacks::popLineIndentAmtInPixelsStack()
{
    return ((UINT16)m_lineIndentAmtInPixelsStack.pop());
}

//added this for indenting text in lists and as requested:
//  Looks at, but doesn't change stack:
inline
UINT16 TextAttributeStacks::peekAtLineIndentAmtInPixelsStack() 
{
    return ((UINT16)m_lineIndentAmtInPixelsStack.peek());
}

inline
ULONG32 TextAttributeStacks::popFontTagStartByteInFileStack()
{
    return (m_fontTagStartByteInFileStack.pop());
}


/* //////////////////////////////////////////////////////////////
 * All of the following return the default val if stack is empty:
 */

inline
void TextAttributeStacks::pushFontStack(ULONG32 ul)
{
    m_fontStack.push(ul);
}

inline
void TextAttributeStacks::pushTextColorStack(COLORTYPE clr,
	BOOL bPushFontStackToo)	 //defaults to TRUE.
{
    m_textColorStack.push(clr);

    //This is FALSE only in case where more than one FONT attribute
    // is inside a single FONT tag, like <FONT color=c someotherval=x>,
    // so that a subsequent </FONT> can pop both the color and the other val:
    if(bPushFontStackToo)  
    {
	pushFontStack(FONT_COLOR);
    }
}

inline
void TextAttributeStacks::pushTextBackgroundColorStack(COLORTYPE clr,
	BOOL bPushFontStackToo) //defaults to TRUE.
{
    m_textBackgroundColorStack.push(clr);
    
    //This is FALSE only in case where more than one FONT attribute
    // is inside a single FONT tag, like <FONT bgcolor=c someotherval=x>,
    // so that a subsequent </FONT> can pop both the bgcolor & the other val:
    if(bPushFontStackToo)
    {
	pushFontStack(FONT_BGCOLOR);
    }
}

inline
void TextAttributeStacks::pushFontCharsetStack(ULONG32 charset,
	BOOL bPushFontStackToo) //defaults to TRUE.
{
    m_fontCharsetStack.push(charset);
    
    //This is FALSE only in case where more than one FONT attribute
    // is inside a single FONT tag, like <FONT charset=c someotherval=x>,
    // so that a subsequent </FONT> can pop both the size and the other val:
    if(bPushFontStackToo)
    {
	pushFontStack(FONT_CHARSET);
    }
}

inline
void TextAttributeStacks::pushFontPointSizeStack(ULONG32 siz,
	BOOL bPushFontStackToo)	//defaults to TRUE.
{
    m_fontPointSizeStack.push(siz);
 
    //This is FALSE only in case where more than one FONT attribute
    // is inside a single FONT tag, like <FONT color=c someotherval=x>,
    // so that a subsequent </FONT> can pop both the size and the other val:
    if(bPushFontStackToo)
    {
	pushFontStack(FONT_SIZE);
    }
}

inline
void TextAttributeStacks::pushTickerUpperColorStack(COLORTYPE clr)
{
    m_tickerUpperColorStack.push(clr);
}

inline
void TextAttributeStacks::pushTickerLowerColorStack(COLORTYPE clr)
{
    m_tickerLowerColorStack.push(clr);
}

inline
void TextAttributeStacks::pushIsBoldStack(BOOL isBld)
{
    m_isBoldStack.push(isBld);
}

inline
void TextAttributeStacks::pushIsItalicizedStack(BOOL isItal)
{
    m_isItalicizedStack.push(isItal);
}

inline
void TextAttributeStacks::pushIsUnderlinedStack(BOOL isUndrln)
{
    m_isUnderlinedStack.push(isUndrln);
}

inline
void TextAttributeStacks::pushIsStruckOutStack(BOOL isStrckOut)
{
    m_isStruckOutStack.push(isStrckOut);
}

inline
void TextAttributeStacks::pushBlinkRateStack(ULONG32 blnkRt)
{
    m_blinkRateStack.push(blnkRt);
}

inline
void TextAttributeStacks::pushIsCenteredStack(BOOL isCenterd)
{
    m_isCenteredStack.push(isCenterd);
}

inline
void TextAttributeStacks::pushIsRequiredStack()
{
    m_ulRequiredTagCount++;
}

inline
void TextAttributeStacks::pushIsPreStack()
{
    m_ulPreTagCount++;
}

//added this for indenting text in lists and as requested:
inline
void TextAttributeStacks::pushLineIndentAmtInPixelsStack(
	UINT16 lineIndentAmt)
{
    ULONG32 ulCopy = lineIndentAmt;
    m_lineIndentAmtInPixelsStack.push(ulCopy);
}

inline
void TextAttributeStacks::pushFontTagStartByteInFileStack(
	ULONG32 ulStartByte)
{
    m_fontTagStartByteInFileStack.push(ulStartByte);
}


#endif

