/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_starmath.hxx"

#include "node.hxx"
#include "rect.hxx"
#include "symbol.hxx"
#include "smmod.hxx"
#include "document.hxx"
#include "view.hxx"
#include "mathtype.hxx"

#include <tools/gen.hxx>
#include <tools/fract.hxx>
#include <rtl/math.hxx>
#include <tools/color.hxx>
#include <vcl/metric.hxx>
#include <vcl/lineinfo.hxx>
#include <vcl/outdev.hxx>
#include <sfx2/module.hxx>

#include <math.h>
#include <float.h>


#define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii))

// define this to draw rectangles for debugging
//#define SM_RECT_DEBUG


using ::rtl::OUString;


////////////////////////////////////////
// SmTmpDevice
// Allows for font and color changes. The original settings will be restored
// in the destructor.
// It's main purpose is to allow for the "const" in the 'OutputDevice'
// argument in the 'Arrange' functions and restore changes made in the 'Draw'
// functions.
// Usually a MapMode of 1/100th mm will be used.
//

class SmTmpDevice
{
	OutputDevice  &rOutDev;

	// disallow use of copy-constructor and assignment-operator
	SmTmpDevice(const SmTmpDevice &rTmpDev);
	SmTmpDevice & operator = (const SmTmpDevice &rTmpDev);

    Color   Impl_GetColor( const Color& rColor );

public:
    SmTmpDevice(OutputDevice &rTheDev, sal_Bool bUseMap100th_mm);
    ~SmTmpDevice()  { rOutDev.Pop(); }

    void SetFont(const Font &rNewFont);

    void SetLineColor( const Color& rColor )    { rOutDev.SetLineColor( Impl_GetColor(rColor) ); }
    void SetFillColor( const Color& rColor )    { rOutDev.SetFillColor( Impl_GetColor(rColor) ); }
    void SetTextColor( const Color& rColor )    { rOutDev.SetTextColor( Impl_GetColor(rColor) ); }

    operator OutputDevice & () { return rOutDev; }
};


SmTmpDevice::SmTmpDevice(OutputDevice &rTheDev, sal_Bool bUseMap100th_mm) :
	rOutDev(rTheDev)
{
    rOutDev.Push( PUSH_FONT | PUSH_MAPMODE |
                  PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR );
    if (bUseMap100th_mm  &&  MAP_100TH_MM != rOutDev.GetMapMode().GetMapUnit())
    {
        DBG_ERROR( "incorrect MapMode?" );
        rOutDev.SetMapMode( MAP_100TH_MM );     //Immer fuer 100% fomatieren
    }
}


Color SmTmpDevice::Impl_GetColor( const Color& rColor )
{
    ColorData nNewCol = rColor.GetColor();
    if (COL_AUTO == nNewCol)
    {
        if (OUTDEV_PRINTER == rOutDev.GetOutDevType())
            nNewCol = COL_BLACK;
        else
        {
            Color aBgCol( rOutDev.GetBackground().GetColor() );
            if (OUTDEV_WINDOW == rOutDev.GetOutDevType())
                aBgCol = ((Window &) rOutDev).GetDisplayBackground().GetColor();

            nNewCol = SM_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;

            Color aTmpColor( nNewCol );
            if (aBgCol.IsDark() && aTmpColor.IsDark())
                nNewCol = COL_WHITE;
            else if (aBgCol.IsBright() && aTmpColor.IsBright())
                nNewCol = COL_BLACK;
        }
    }
    return Color( nNewCol );
}


void SmTmpDevice::SetFont(const Font &rNewFont)
{
    rOutDev.SetFont( rNewFont );
    rOutDev.SetTextColor( Impl_GetColor( rNewFont.GetColor() ) );
}


///////////////////////////////////////////////////////////////////////////


SmNode::SmNode(SmNodeType eNodeType, const SmToken &rNodeToken)
{
	eType	   = eNodeType;
	eScaleMode = SCALE_NONE;
	aNodeToken = rNodeToken;
    nAccIndex  = -1;
}


SmNode::~SmNode()
{
}


sal_Bool SmNode::IsVisible() const
{
    return sal_False;
}


sal_uInt16 SmNode::GetNumSubNodes() const
{
	return 0;
}


SmNode * SmNode::GetSubNode(sal_uInt16 /*nIndex*/)
{
	return NULL;
}


SmNode * SmNode::GetLeftMost()
	//	returns leftmost node of current subtree.
	//! (this assumes the one with index 0 is always the leftmost subnode
	//! for the current node).
{
	SmNode *pNode = GetNumSubNodes() > 0 ?
						GetSubNode(0) : NULL;

	return pNode ? pNode->GetLeftMost() : this;
}


void SmNode::SetPhantom(sal_Bool bIsPhantomP)
{
	if (! (Flags() & FLG_VISIBLE))
		bIsPhantom = bIsPhantomP;

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetPhantom(bIsPhantom);
}


void SmNode::SetColor(const Color& rColor)
{
	if (! (Flags() & FLG_COLOR))
		GetFont().SetColor(rColor);

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetColor(rColor);
}


void SmNode::SetAttribut(sal_uInt16 nAttrib)
{
	if (
        (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) ||
        (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
       )
    {
		nAttributes |= nAttrib;
    }

	SmNode *pNode;
	sal_uInt16 nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetAttribut(nAttrib);
}


void SmNode::ClearAttribut(sal_uInt16 nAttrib)
{
	if (
        (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) ||
        (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
       )
    {
		nAttributes &= ~nAttrib;
    }

	SmNode *pNode;
	sal_uInt16 nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->ClearAttribut(nAttrib);
}


void SmNode::SetFont(const SmFace &rFace)
{
	if (!(Flags() & FLG_FONT))
		GetFont() = rFace;

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetFont(rFace);
}


void SmNode::SetFontSize(const Fraction &rSize, sal_uInt16 nType)
	//! 'rSize' is in units of pts
{
    Size  aFntSize;

	if (!(Flags() & FLG_SIZE))
	{
		Fraction  aVal (SmPtsTo100th_mm(rSize.GetNumerator()),
						rSize.GetDenominator());
		//long	  nHeight = ::rtl::math::round(aVal);
		long	  nHeight = (long)aVal;

        aFntSize = GetFont().GetSize();
        aFntSize.Width() = 0;
		switch(nType)
		{
			case FNTSIZ_ABSOLUT:
                aFntSize.Height() = nHeight;
				break;

			case FNTSIZ_PLUS:
                aFntSize.Height() += nHeight;
				break;

			case FNTSIZ_MINUS:
                aFntSize.Height() -= nHeight;
				break;

			case FNTSIZ_MULTIPLY:
                aFntSize.Height()   = (long) (Fraction(aFntSize.Height()) * rSize);
				break;

			case FNTSIZ_DIVIDE:
				if (rSize != Fraction(0L))
                    aFntSize.Height()   = (long) (Fraction(aFntSize.Height()) / rSize);
				break;
            default:
                break;
		}

		// check the requested size against maximum value
		static int __READONLY_DATA	nMaxVal = SmPtsTo100th_mm(128);
        if (aFntSize.Height() > nMaxVal)
            aFntSize.Height() = nMaxVal;

        GetFont().SetSize(aFntSize);
	}

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetFontSize(rSize, nType);
}


void SmNode::SetSize(const Fraction &rSize)
{
	GetFont() *= rSize;

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->SetSize(rSize);
}


void SmNode::SetRectHorAlign(RectHorAlign eHorAlign, sal_Bool bApplyToSubTree )
{
	if (!(Flags() & FLG_HORALIGN))
		eRectHorAlign = eHorAlign;

    if (bApplyToSubTree)
    {
        SmNode *pNode;
        sal_uInt16  nSize = GetNumSubNodes();
        for (sal_uInt16 i = 0; i < nSize; i++)
            if (NULL != (pNode = GetSubNode(i)))
                pNode->SetRectHorAlign(eHorAlign);
    }
}


void SmNode::PrepareAttributes()
{
	GetFont().SetWeight((Attributes() & ATTR_BOLD)	 ? WEIGHT_BOLD	 : WEIGHT_NORMAL);
	GetFont().SetItalic((Attributes() & ATTR_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE);
}


void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
#if OSL_DEBUG_LEVEL > 1
	bIsDebug	= sal_True;
#else
	bIsDebug 	= sal_False;
#endif
	bIsPhantom	= sal_False;
	nFlags		= 0;
	nAttributes = 0;

	switch (rFormat.GetHorAlign())
	{	case AlignLeft:		eRectHorAlign = RHA_LEFT;	break;
		case AlignCenter:	eRectHorAlign = RHA_CENTER;	break;
		case AlignRight:	eRectHorAlign = RHA_RIGHT;	break;
	}

	GetFont() = rFormat.GetFont(FNT_MATH);
    //GetFont().SetCharSet(RTL_TEXTENCODING_SYMBOL);
    DBG_ASSERT( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
            "unexpected CharSet" );
	GetFont().SetWeight(WEIGHT_NORMAL);
	GetFont().SetItalic(ITALIC_NONE);

	SmNode *pNode;
	sal_uInt16  	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->Prepare(rFormat, rDocShell);
}


#if OSL_DEBUG_LEVEL > 1
void  SmNode::ToggleDebug() const
	// toggle 'bIsDebug' in current subtree
{
	SmNode *pThis = (SmNode *) this;

	pThis->bIsDebug = bIsDebug ? sal_False : sal_True;

	SmNode *pNode;
	sal_uInt16  	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = pThis->GetSubNode(i)))
			pNode->ToggleDebug();
}
#endif


void SmNode::Move(const Point& rPosition)
{
	if (rPosition.X() == 0	&&	rPosition.Y() == 0)
		return;

	SmRect::Move(rPosition);

	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->Move(rPosition);
}


void SmNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->Arrange(rDev, rFormat);
}

void SmNode::CreateTextFromNode(String &rText)
{
	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	if (nSize > 1)
		rText.Append('{');
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->CreateTextFromNode(rText);
	if (nSize > 1)
	{
		rText.EraseTrailingChars();
		APPEND(rText,"} ");
	}
}


void SmNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong /*nWidth*/)
{
}


void SmNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong /*nHeight*/)
{
}


void SmNode::Draw(OutputDevice &rDev, const Point &rPosition) const
{
	if (IsPhantom())
		return;

	const SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	for (sal_uInt16 i = 0; i < nSize; i++)
        if (NULL != (pNode = GetSubNode(i)))
		{	Point  aOffset (pNode->GetTopLeft() - GetTopLeft());
			pNode->Draw(rDev, rPosition + aOffset);
		}

#ifdef SM_RECT_DEBUG
	if (!IsDebug())
		return;

	int  nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
	SmRect::Draw(rDev, rPosition, nRFlags);
#endif
}

const SmNode * SmNode::FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const
	// returns (first) ** visible ** (sub)node with the tokens text at
	// position 'nRow', 'nCol'.
	//! (there should be exactly one such node if any)
{
	if (	IsVisible()
		&&	nRow == GetToken().nRow
		&&	nCol >= GetToken().nCol  &&  nCol < GetToken().nCol + GetToken().aText.Len())
		return this;
	else
	{
		sal_uInt16	nNumSubNodes = GetNumSubNodes();
		for (sal_uInt16  i = 0;  i < nNumSubNodes;	i++)
		{	const SmNode *pNode = GetSubNode(i);

			if (!pNode)
				continue;

			const SmNode *pResult = pNode->FindTokenAt(nRow, nCol);
			if (pResult)
				return pResult;
		}
	}

	return 0;
}


const SmNode * SmNode::FindRectClosestTo(const Point &rPoint) const
{
	long  		  nDist   = LONG_MAX;
	const SmNode *pResult = 0;

	if (IsVisible())
		pResult = this;
	else
	{
		sal_uInt16	nNumSubNodes = GetNumSubNodes();
		for (sal_uInt16  i = 0;  i < nNumSubNodes;	i++)
		{	const SmNode *pNode = GetSubNode(i);

			if (!pNode)
				continue;

			long  nTmp;
			const SmNode *pFound = pNode->FindRectClosestTo(rPoint);
			if (pFound  &&  (nTmp = pFound->OrientedDist(rPoint)) < nDist)
			{	nDist	= nTmp;
				pResult = pFound;

				// quit immediately if 'rPoint' is inside the *should not
				// overlap with other rectangles* part.
				// This (partly) serves for getting the attributes in eg
				// "bar overstrike a".
				// ('nDist < 0' is used as *quick shot* to avoid evaluation of
				// the following expression, where the result is already determined)
				if (nDist < 0  &&  pFound->IsInsideRect(rPoint))
					break;
			}
		}
	}

	return pResult;
}

void SmNode::GetAccessibleText( String &/*rText*/ ) const
{
    DBG_ERROR( "SmNode: GetAccessibleText not overloaded" );
}

const SmNode * SmNode::FindNodeWithAccessibleIndex(xub_StrLen nAccIdx) const
{
	const SmNode *pResult = 0;

    sal_Int32 nIdx = GetAccessibleIndex();
    String aTxt;
    if (nIdx >= 0)
        GetAccessibleText( aTxt );  // get text if used in following 'if' statement

    if (nIdx >= 0
        &&  nIdx <= nAccIdx  &&  nAccIdx < nIdx + aTxt.Len())
		pResult = this;
	else
	{
		sal_uInt16	nNumSubNodes = GetNumSubNodes();
		for (sal_uInt16  i = 0;  i < nNumSubNodes;	i++)
        {
            const SmNode *pNode = GetSubNode(i);
			if (!pNode)
				continue;

            pResult = pNode->FindNodeWithAccessibleIndex(nAccIdx);
            if (pResult)
                return pResult;
		}
	}

	return pResult;
}


long SmNode::GetFormulaBaseline() const
{
    DBG_ASSERT( 0, "This dummy implementation should not have been called." );
    return 0;
}

///////////////////////////////////////////////////////////////////////////

SmStructureNode::SmStructureNode( const SmStructureNode &rNode ) :
    SmNode( rNode.GetType(), rNode.GetToken() )
{
    sal_uLong i;
    for (i = 0;  i < aSubNodes.size();  i++)
        delete aSubNodes[i];
    aSubNodes.resize(0);

    sal_uLong nSize = rNode.aSubNodes.size();
    aSubNodes.resize( nSize );
    for (i = 0;  i < nSize;  ++i)
    {
        SmNode *pNode = rNode.aSubNodes[i];
        aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0;
    }
}


SmStructureNode::~SmStructureNode()
{
	SmNode *pNode;

	for (sal_uInt16 i = 0;	i < GetNumSubNodes();  i++)
        if (NULL != (pNode = GetSubNode(i)))
			delete pNode;
}


SmStructureNode & SmStructureNode::operator = ( const SmStructureNode &rNode )
{
    SmNode::operator = ( rNode );

    sal_uLong i;
    for (i = 0;  i < aSubNodes.size();  i++)
        delete aSubNodes[i];
    aSubNodes.resize(0);

    sal_uLong nSize = rNode.aSubNodes.size();
    aSubNodes.resize( nSize );
    for (i = 0;  i < nSize;  ++i)
    {
        SmNode *pNode = rNode.aSubNodes[i];
        aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0;
    }

    return *this;
}


void SmStructureNode::SetSubNodes(SmNode *pFirst, SmNode *pSecond, SmNode *pThird)
{
    size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0));
    aSubNodes.resize( nSize );
	if (pFirst)
        aSubNodes[0] = pFirst;
	if (pSecond)
        aSubNodes[1] = pSecond;
	if (pThird)
        aSubNodes[2] = pThird;
}


void SmStructureNode::SetSubNodes(const SmNodeArray &rNodeArray)
{
	aSubNodes = rNodeArray;
}


sal_Bool SmStructureNode::IsVisible() const
{
	return sal_False;
}


sal_uInt16 SmStructureNode::GetNumSubNodes() const
{
    return (sal_uInt16) aSubNodes.size();
}


SmNode * SmStructureNode::GetSubNode(sal_uInt16 nIndex)
{
    return aSubNodes[nIndex];
}


void SmStructureNode::GetAccessibleText( String &rText ) const
{
    sal_uInt16 nNodes = GetNumSubNodes();
    for (sal_uInt16 i = 0;  i < nNodes;  ++i)
    {
        const SmNode *pNode = ((SmStructureNode *) this)->GetSubNode(i);
        if (pNode)
        {
            if (pNode->IsVisible())
                ((SmStructureNode *) pNode)->nAccIndex = rText.Len();
            pNode->GetAccessibleText( rText );
//            if (rText.Len()  &&  ' ' != rText.GetChar( rText.Len() - 1 ))
//                rText += String::CreateFromAscii( " " );
        }
    }
}

///////////////////////////////////////////////////////////////////////////


sal_Bool SmVisibleNode::IsVisible() const
{
	return sal_True;
}


sal_uInt16 SmVisibleNode::GetNumSubNodes() const
{
	return 0;
}


SmNode * SmVisibleNode::GetSubNode(sal_uInt16 /*nIndex*/)
{
	return NULL;
}


///////////////////////////////////////////////////////////////////////////

void SmGraphicNode::GetAccessibleText( String &rText ) const
{
    rText += GetToken().aText;
}

///////////////////////////////////////////////////////////////////////////


void SmExpressionNode::CreateTextFromNode(String &rText)
{
	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	if (nSize > 1)
		rText.Append('{');
	for (sal_uInt16 i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
		{
			pNode->CreateTextFromNode(rText);
			//Just a bit of foo to make unary +asd -asd +-asd -+asd look nice
			if (pNode->GetType() == NMATH)
				if ((nSize != 2) || ((rText.GetChar(rText.Len()-1) != '+') &&
					(rText.GetChar(rText.Len()-1) != '-')))
					rText.Append(' ');
		}

	if (nSize > 1)
	{
		rText.EraseTrailingChars();
		APPEND(rText,"} ");
	}
}


///////////////////////////////////////////////////////////////////////////

void SmTableNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
	// arranges all subnodes in one column
{
	Point rPosition;

	SmNode *pNode;
	sal_uInt16	nSize	= GetNumSubNodes();

	// make distance depend on font size
	long  nDist = +(rFormat.GetDistance(DIS_VERTICAL)
					* GetFont().GetSize().Height()) / 100L;

	if (nSize < 1)
		return;

	// arrange subnodes and get maximum width of them
	long  nMaxWidth = 0,
		  nTmp;
    sal_uInt16 i;
	for (i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
		{	pNode->Arrange(rDev, rFormat);
			if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth)
				nMaxWidth = nTmp;
		}

	Point  aPos;
	SmRect::operator = (SmRect(nMaxWidth, 1));
	for (i = 0;  i < nSize;  i++)
    {   if (NULL != (pNode = GetSubNode(i)))
		{	const SmRect &rNodeRect = pNode->GetRect();
			const SmNode *pCoNode	= pNode->GetLeftMost();
            //SmTokenType   eType    = pCoNode->GetToken().eType;
            RectHorAlign  eHorAlign = pCoNode->GetRectHorAlign();

			aPos = rNodeRect.AlignTo(*this, RP_BOTTOM,
						eHorAlign, RVA_BASELINE);
			if (i)
				aPos.Y() += nDist;
			pNode->MoveTo(aPos);
			ExtendBy(rNodeRect, nSize > 1 ? RCP_NONE : RCP_ARG);
		}
	}
    // --> 4.7.2010 #i972#
    if (HasBaseline())
        nFormulaBaseline = GetBaseline();
    else
    {
        SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
        aTmpDev.SetFont(GetFont());

        SmRect aRect = (SmRect(aTmpDev, &rFormat, C2S("a"),
                               GetFont().GetBorderWidth()));
        nFormulaBaseline = GetAlignM();
        // move from middle position by constant - distance
        // between middle and baseline for single letter
        nFormulaBaseline += aRect.GetBaseline() - aRect.GetAlignM();
    }
    // <--
}


SmNode * SmTableNode::GetLeftMost()
{
	return this;
}


long SmTableNode::GetFormulaBaseline() const
{
    return nFormulaBaseline;
}


/**************************************************************************/


void SmLineNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

	//! wir verwenden hier den 'FNT_VARIABLE' Font, da er vom Ascent und Descent
	//! ia besser zum Rest der Formel passt als der 'FNT_MATH' Font.
	GetFont() = rFormat.GetFont(FNT_VARIABLE);
	Flags() |= FLG_FONT;
}


/**************************************************************************/


void SmLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
	// arranges all subnodes in one row with some extra space between
{
	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
	sal_uInt16 i;
	for (i = 0;	i < nSize;	i++)
        if (NULL != (pNode = GetSubNode(i)))
			pNode->Arrange(rDev, rFormat);

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

    if (nSize < 1)
    {
        // provide an empty rectangle with alignment parameters for the "current"
        // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the
        // same sub-/supscript positions.)
        //! be sure to use a character that has explicitly defined HiAttribut
        //! line in rect.cxx such as 'a' in order to make 'vec a' look same to
        //! 'vec {a}'.
        SmRect::operator = (SmRect(aTmpDev, &rFormat, C2S("a"),
                            GetFont().GetBorderWidth()));
        // make sure that the rectangle occupies (almost) no space
        SetWidth(1);
        SetItalicSpaces(0, 0);
        return;
    }

	// make distance depend on font size
	long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetSize().Height()) / 100L;
	if (!IsUseExtraSpaces())
        nDist = 0;

	Point   aPos;
    // copy the first node into LineNode and extend by the others
    if (NULL != (pNode = GetSubNode(0)))
        SmRect::operator = (pNode->GetRect());

    for (i = 1;  i < nSize;  i++)
        if (NULL != (pNode = GetSubNode(i)))
		{
			aPos = pNode->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);

            // add horizontal space to the left for each but the first sub node
			aPos.X() += nDist;

			pNode->MoveTo(aPos);
            ExtendBy( *pNode, RCP_XOR );
		}
}


/**************************************************************************/


void SmExpressionNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
	// as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode
{
	SmLineNode::Arrange(rDev, rFormat);

	//	copy alignment of leftmost subnode if any
    SmNode *pNode = GetLeftMost();
	if (pNode)
        SetRectHorAlign(pNode->GetRectHorAlign(), sal_False);
}


/**************************************************************************/


void SmUnHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	sal_Bool  bIsPostfix = GetToken().eType == TFACT;

	SmNode *pOper = GetSubNode(bIsPostfix ? 1 : 0),
		   *pBody = GetSubNode(bIsPostfix ? 0 : 1);
	DBG_ASSERT(pOper, "Sm: NULL pointer");
	DBG_ASSERT(pBody, "Sm: NULL pointer");

	pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
	pOper->Arrange(rDev, rFormat);
	pBody->Arrange(rDev, rFormat);

	Point  aPos = pOper->AlignTo(*pBody, bIsPostfix ? RP_RIGHT : RP_LEFT,
						RHA_CENTER, RVA_BASELINE);
	// add a bit space between operator and argument
	// (worst case -{1 over 2} where - and over have almost no space inbetween)
	long  nDelta = pOper->GetFont().GetSize().Height() / 20;
	if (bIsPostfix)
		aPos.X() += nDelta;
	else
		aPos.X() -= nDelta;
	pOper->MoveTo(aPos);

	SmRect::operator = (*pBody);
	long  nOldBot = GetBottom();

	ExtendBy(*pOper, RCP_XOR);

	// workaround for Bug 50865: "a^2 a^+2" have different baselines
	// for exponents (if size of exponent is large enough)
	SetBottom(nOldBot);
}


/**************************************************************************/


void SmRootNode::GetHeightVerOffset(const SmRect &rRect,
									long &rHeight, long &rVerOffset) const
	// calculate height and vertical offset of root sign suitable for 'rRect'
{
	rVerOffset = (rRect.GetBottom() - rRect.GetAlignB()) / 2;
	rHeight    = rRect.GetHeight() - rVerOffset;

	DBG_ASSERT(rHeight	  >= 0, "Sm : Ooops...");
	DBG_ASSERT(rVerOffset >= 0, "Sm : Ooops...");
}


Point SmRootNode::GetExtraPos(const SmRect &rRootSymbol,
							  const SmRect &rExtra) const
{
	const Size &rSymSize = rRootSymbol.GetSize();

	Point  aPos = rRootSymbol.GetTopLeft()
			+ Point((rSymSize.Width()  * 70) / 100,
					(rSymSize.Height() * 52) / 100);

	// from this calculate topleft edge of 'rExtra'
	aPos.X() -= rExtra.GetWidth() + rExtra.GetItalicRightSpace();
	aPos.Y() -= rExtra.GetHeight();
	// if there's enough space move a bit less to the right
	// examples: "nroot i a", "nroot j a"
	// (it looks better if we don't use italic-spaces here)
	long  nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100;
	if (aPos.X() > nX)
		aPos.X() = nX;

	return aPos;
}


void SmRootNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	//! pExtra needs to have the smaller index than pRootSym in order to
	//! not to get the root symbol but the pExtra when clicking on it in the
	//! GraphicWindow. (That is because of the simplicity of the algorithm
	//! that finds the node corresponding to a mouseclick in the window.)
	SmNode *pExtra	 = GetSubNode(0),
		   *pRootSym = GetSubNode(1),
		   *pBody	 = GetSubNode(2);
	DBG_ASSERT(pRootSym, "Sm: NULL pointer");
	DBG_ASSERT(pBody,	 "Sm: NULL pointer");

	pBody->Arrange(rDev, rFormat);

	long  nHeight,
		  nVerOffset;
	GetHeightVerOffset(*pBody, nHeight, nVerOffset);
	nHeight += rFormat.GetDistance(DIS_ROOT)
			   * GetFont().GetSize().Height() / 100L;

    // font specialist advised to change the width first
    pRootSym->AdaptToY(rDev, nHeight);
	pRootSym->AdaptToX(rDev, pBody->GetItalicWidth());

	pRootSym->Arrange(rDev, rFormat);

	Point  aPos = pRootSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE);
	//! overrride calculated vertical position
	aPos.Y()  = pRootSym->GetTop() + pBody->GetBottom() - pRootSym->GetBottom();
	aPos.Y() -= nVerOffset;
	pRootSym->MoveTo(aPos);

	if (pExtra)
	{	pExtra->SetSize(Fraction(rFormat.GetRelSize(SIZ_INDEX), 100));
		pExtra->Arrange(rDev, rFormat);

		aPos = GetExtraPos(*pRootSym, *pExtra);
		pExtra->MoveTo(aPos);
	}

	SmRect::operator = (*pBody);
	ExtendBy(*pRootSym, RCP_THIS);
	if (pExtra)
		ExtendBy(*pExtra, RCP_THIS, (sal_Bool) sal_True);
}


void SmRootNode::CreateTextFromNode(String &rText)
{
	SmNode *pExtra = GetSubNode(0);
	if (pExtra)
	{
		APPEND(rText,"nroot ");
		pExtra->CreateTextFromNode(rText);
	}
	else
		APPEND(rText,"sqrt ");
	GetSubNode(2)->CreateTextFromNode(rText);
}


/**************************************************************************/


void SmBinHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pLeft  = GetSubNode(0),
		   *pOper  = GetSubNode(1),
		   *pRight = GetSubNode(2);
	DBG_ASSERT(pLeft  != NULL, "Sm: NULL pointer");
	DBG_ASSERT(pOper  != NULL, "Sm: NULL pointer");
	DBG_ASSERT(pRight != NULL, "Sm: NULL pointer");

	pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));

	pLeft ->Arrange(rDev, rFormat);
	pOper ->Arrange(rDev, rFormat);
    pRight->Arrange(rDev, rFormat);

	const SmRect &rOpRect = pOper->GetRect();

	long nDist = (rOpRect.GetWidth() *
				 rFormat.GetDistance(DIS_HORIZONTAL)) / 100L;

	SmRect::operator = (*pLeft);

	Point aPos;
	aPos = pOper->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
	aPos.X() += nDist;
	pOper->MoveTo(aPos);
	ExtendBy(*pOper, RCP_XOR);

	aPos = pRight->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
	aPos.X() += nDist;

	pRight->MoveTo(aPos);
	ExtendBy(*pRight, RCP_XOR);
}


/**************************************************************************/


void SmBinVerNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pNum   = GetSubNode(0),
		   *pLine  = GetSubNode(1),
		   *pDenom = GetSubNode(2);
	DBG_ASSERT(pNum,   "Sm : NULL pointer");
	DBG_ASSERT(pLine,  "Sm : NULL pointer");
	DBG_ASSERT(pDenom, "Sm : NULL pointer");

	sal_Bool  bIsTextmode = rFormat.IsTextmode();
	if (bIsTextmode)
	{
		Fraction  aFraction(rFormat.GetRelSize(SIZ_INDEX), 100);
		pNum  ->SetSize(aFraction);
		pLine ->SetSize(aFraction);
		pDenom->SetSize(aFraction);
	}

	pNum  ->Arrange(rDev, rFormat);
	pDenom->Arrange(rDev, rFormat);

	long  nFontHeight = GetFont().GetSize().Height(),
		  nExtLen	  = nFontHeight * rFormat.GetDistance(DIS_FRACTION)	/ 100L,
		  nThick	  = nFontHeight * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L,
		  nWidth	  = Max(pNum->GetItalicWidth(), pDenom->GetItalicWidth()),
		  nNumDist    = bIsTextmode ? 0 :
							nFontHeight * rFormat.GetDistance(DIS_NUMERATOR)   / 100L,
		  nDenomDist  = bIsTextmode ? 0 :
							nFontHeight * rFormat.GetDistance(DIS_DENOMINATOR) / 100L;

    // font specialist advised to change the width first
    pLine->AdaptToY(rDev, nThick);
	pLine->AdaptToX(rDev, nWidth + 2 * nExtLen);
	pLine->Arrange(rDev, rFormat);

	// get horizontal alignment for numerator
	const SmNode *pLM		= pNum->GetLeftMost();
    RectHorAlign  eHorAlign = pLM->GetRectHorAlign();

	// move numerator to its position
	Point  aPos = pNum->AlignTo(*pLine, RP_TOP, eHorAlign, RVA_BASELINE);
	aPos.Y() -= nNumDist;
	pNum->MoveTo(aPos);

	// get horizontal alignment for denominator
	pLM		  = pDenom->GetLeftMost();
    eHorAlign = pLM->GetRectHorAlign();

	// move denominator to its position
	aPos = pDenom->AlignTo(*pLine, RP_BOTTOM, eHorAlign, RVA_BASELINE);
	aPos.Y() += nDenomDist;
	pDenom->MoveTo(aPos);

	SmRect::operator = (*pNum);
	ExtendBy(*pDenom, RCP_NONE).ExtendBy(*pLine, RCP_NONE, pLine->GetCenterY());
}

void SmBinVerNode::CreateTextFromNode(String &rText)
{
	SmNode *pNum   = GetSubNode(0),
    //      *pLine  = GetSubNode(1),
		   *pDenom = GetSubNode(2);
	pNum->CreateTextFromNode(rText);
	APPEND(rText,"over ");
	pDenom->CreateTextFromNode(rText);
}


SmNode * SmBinVerNode::GetLeftMost()
{
	return this;
}


/**************************************************************************/


double Det(const Point &rHeading1, const Point &rHeading2)
	// gibt den Wert der durch die beiden Punkte gebildeten Determinante
    // zurueck
{
	return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X();
}


sal_Bool IsPointInLine(const Point &rPoint1,
				   const Point &rPoint2, const Point &rHeading2)
    // ergibt sal_True genau dann, wenn der Punkt 'rPoint1' zu der Gerade gehoert die
	// durch den Punkt 'rPoint2' geht und den Richtungsvektor 'rHeading2' hat
{
	DBG_ASSERT(rHeading2 != Point(), "Sm : 0 vector");

	sal_Bool bRes = sal_False;
	const double eps = 5.0 * DBL_EPSILON;

	double fLambda;
	if (labs(rHeading2.X()) > labs(rHeading2.Y()))
	{
		fLambda = (rPoint1.X() - rPoint2.X()) / (double) rHeading2.X();
		bRes = fabs(rPoint1.Y() - (rPoint2.Y() + fLambda * rHeading2.Y())) < eps;
	}
	else
	{
		fLambda = (rPoint1.Y() - rPoint2.Y()) / (double) rHeading2.Y();
		bRes = fabs(rPoint1.X() - (rPoint2.X() + fLambda * rHeading2.X())) < eps;
	}

	return bRes;
}


sal_uInt16 GetLineIntersectionPoint(Point &rResult,
								const Point& rPoint1, const Point &rHeading1,
								const Point& rPoint2, const Point &rHeading2)
{
	DBG_ASSERT(rHeading1 != Point(), "Sm : 0 vector");
	DBG_ASSERT(rHeading2 != Point(), "Sm : 0 vector");

	sal_uInt16 nRes = 1;
	const double eps = 5.0 * DBL_EPSILON;

    // sind die Richtumgsvektoren linear abhaengig ?
	double  fDet = Det(rHeading1, rHeading2);
	if (fabs(fDet) < eps)
	{
		nRes    = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0;
		rResult = nRes ? rPoint1 : Point();
	}
	else
	{
		// hier achten wir nicht auf Rechengenauigkeit
        // (das wuerde aufwendiger und lohnt sich hier kaum)
		double fLambda = (	  (rPoint1.Y() - rPoint2.Y()) * rHeading2.X()
							- (rPoint1.X() - rPoint2.X()) * rHeading2.Y())
						 / fDet;
		rResult = Point(rPoint1.X() + (long) (fLambda * rHeading1.X()),
						rPoint1.Y() + (long) (fLambda * rHeading1.Y()));
	}

	return nRes;
}



SmBinDiagonalNode::SmBinDiagonalNode(const SmToken &rNodeToken)
:	SmStructureNode(NBINDIAGONAL, rNodeToken)
{
	bAscending = sal_False;
	SetNumSubNodes(3);
}


void SmBinDiagonalNode::GetOperPosSize(Point &rPos, Size &rSize,
						const Point &rDiagPoint, double fAngleDeg) const
    // gibt die Position und Groesse fuer den Diagonalstrich zurueck.
    // Vor.: das SmRect des Nodes gibt die Begrenzung vor(!), muss also selbst
	//		bereits bekannt sein.

{
	const double  fPi   = 3.1415926535897932384626433;
	double  fAngleRad   = fAngleDeg / 180.0 * fPi;
	long	nRectLeft   = GetItalicLeft(),
			nRectRight  = GetItalicRight(),
			nRectTop    = GetTop(),
			nRectBottom = GetBottom();
	Point  	aRightHdg	  (100, 0),
			aDownHdg	  (0, 100),
			aDiagHdg	  ( (long)(100.0 * cos(fAngleRad)),
							(long)(-100.0 * sin(fAngleRad)) );

    long  nLeft, nRight, nTop, nBottom;     // Raender des Rechtecks fuer die
											// Diagonale
	Point aPoint;
	if (IsAscending())
	{
		//
		// obere rechte Ecke bestimmen
		//
		GetLineIntersectionPoint(aPoint,
			Point(nRectLeft, nRectTop), aRightHdg,
			rDiagPoint, aDiagHdg);
		//
		// gibt es einen Schnittpunkt mit dem oberen Rand ?
		if (aPoint.X() <= nRectRight)
		{
			nRight = aPoint.X();
			nTop   = nRectTop;
		}
		else
		{
            // es muss einen Schnittpunkt mit dem rechten Rand geben!
			GetLineIntersectionPoint(aPoint,
				Point(nRectRight, nRectTop), aDownHdg,
				rDiagPoint, aDiagHdg);

			nRight = nRectRight;
			nTop   = aPoint.Y();
		}

		//
		// untere linke Ecke bestimmen
		//
		GetLineIntersectionPoint(aPoint,
			Point(nRectLeft, nRectBottom), aRightHdg,
			rDiagPoint, aDiagHdg);
		//
		// gibt es einen Schnittpunkt mit dem unteren Rand ?
		if (aPoint.X() >= nRectLeft)
		{
			nLeft   = aPoint.X();
			nBottom = nRectBottom;
		}
		else
		{
            // es muss einen Schnittpunkt mit dem linken Rand geben!
			GetLineIntersectionPoint(aPoint,
				Point(nRectLeft, nRectTop), aDownHdg,
				rDiagPoint, aDiagHdg);

			nLeft   = nRectLeft;
			nBottom = aPoint.Y();
		}
	}
	else
	{
		//
		// obere linke Ecke bestimmen
		//
		GetLineIntersectionPoint(aPoint,
			Point(nRectLeft, nRectTop), aRightHdg,
			rDiagPoint, aDiagHdg);
		//
		// gibt es einen Schnittpunkt mit dem oberen Rand ?
		if (aPoint.X() >= nRectLeft)
		{
			nLeft = aPoint.X();
			nTop  = nRectTop;
		}
		else
		{
            // es muss einen Schnittpunkt mit dem linken Rand geben!
			GetLineIntersectionPoint(aPoint,
				Point(nRectLeft, nRectTop), aDownHdg,
				rDiagPoint, aDiagHdg);

			nLeft = nRectLeft;
			nTop  = aPoint.Y();
		}

		//
		// untere rechte Ecke bestimmen
		//
		GetLineIntersectionPoint(aPoint,
			Point(nRectLeft, nRectBottom), aRightHdg,
			rDiagPoint, aDiagHdg);
		//
		// gibt es einen Schnittpunkt mit dem unteren Rand ?
		if (aPoint.X() <= nRectRight)
		{
			nRight  = aPoint.X();
			nBottom = nRectBottom;
		}
		else
		{
            // es muss einen Schnittpunkt mit dem rechten Rand geben!
			GetLineIntersectionPoint(aPoint,
				Point(nRectRight, nRectTop), aDownHdg,
				rDiagPoint, aDiagHdg);

			nRight  = nRectRight;
			nBottom = aPoint.Y();
		}
	}

	rSize = Size(nRight - nLeft + 1, nBottom - nTop + 1);
	rPos.X() = nLeft;
	rPos.Y() = nTop;
}


void SmBinDiagonalNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
    //! die beiden Argumente muessen in den Subnodes vor dem Operator kommen,
	//! damit das anklicken im GraphicWindow den FormulaCursor richtig setzt
	//! (vgl SmRootNode)
	SmNode *pLeft  = GetSubNode(0),
		   *pRight = GetSubNode(1);
	DBG_ASSERT(pLeft, "Sm : NULL pointer");
	DBG_ASSERT(pRight, "Sm : NULL pointer");

	DBG_ASSERT(GetSubNode(2)->GetType() == NPOLYLINE, "Sm : falscher Nodetyp");
	SmPolyLineNode *pOper = (SmPolyLineNode *) GetSubNode(2);
	DBG_ASSERT(pOper, "Sm : NULL pointer");

	//! some routines being called extract some info from the OutputDevice's
	//! font (eg the space to be used for borders OR the font name(!!)).
	//! Thus the font should reflect the needs and has to be set!
    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	pLeft->Arrange(aTmpDev, rFormat);
	pRight->Arrange(aTmpDev, rFormat);

	// implizit die Weite (incl Rand) des Diagonalstrichs ermitteln
	pOper->Arrange(aTmpDev, rFormat);

	long nDelta = pOper->GetWidth() * 8 / 10;

	// TopLeft Position vom rechten Argument ermitteln
	Point aPos;
	aPos.X() = pLeft->GetItalicRight() + nDelta + pRight->GetItalicLeftSpace();
	if (IsAscending())
		aPos.Y() = pLeft->GetBottom() + nDelta;
	else
		aPos.Y() = pLeft->GetTop() - nDelta - pRight->GetHeight();

	pRight->MoveTo(aPos);

	// neue Baseline bestimmen
    long nTmpBaseline = IsAscending() ? (pLeft->GetBottom() + pRight->GetTop()) / 2
						: (pLeft->GetTop() + pRight->GetBottom()) / 2;
	Point  aLogCenter ((pLeft->GetItalicRight() + pRight->GetItalicLeft()) / 2,
                       nTmpBaseline);

	SmRect::operator = (*pLeft);
	ExtendBy(*pRight, RCP_NONE);


    // Position und Groesse des Diagonalstrich ermitteln
    Size  aTmpSize;
    GetOperPosSize(aPos, aTmpSize, aLogCenter, IsAscending() ? 60.0 : -60.0);

    // font specialist advised to change the width first
    pOper->AdaptToY(aTmpDev, aTmpSize.Height());
    pOper->AdaptToX(aTmpDev, aTmpSize.Width());
	// und diese wirksam machen
	pOper->Arrange(aTmpDev, rFormat);

	pOper->MoveTo(aPos);

    ExtendBy(*pOper, RCP_NONE, nTmpBaseline);
}


/**************************************************************************/


void SmSubSupNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	DBG_ASSERT(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES,
			   "Sm: falsche Anzahl von subnodes");

	SmNode *pBody = GetBody();
	DBG_ASSERT(pBody, "Sm: NULL pointer");

	long  nOrigHeight = pBody->GetFont().GetSize().Height();

	pBody->Arrange(rDev, rFormat);

	const SmRect &rBodyRect = pBody->GetRect();
	SmRect::operator = (rBodyRect);

	// line that separates sub- and supscript rectangles
	long  nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4);

	Point  aPos;
	long   nDelta, nDist;

	// iterate over all possible sub-/supscripts
	SmRect	aTmpRect (rBodyRect);
	for (int i = 0;  i < SUBSUP_NUM_ENTRIES;  i++)
	{	SmSubSup  eSubSup = (SmSubSup) i;	// cast
		SmNode *pSubSup = GetSubSup(eSubSup);

		if (!pSubSup)
			continue;

		// switch position of limits if we are in textmode
		if (rFormat.IsTextmode()  &&  (GetToken().nGroup & TGLIMIT))
			switch (eSubSup)
			{	case CSUB:	eSubSup = RSUB;		break;
				case CSUP:	eSubSup = RSUP;		break;
                default:
                    break;
			}

		// prevent sub-/supscripts from diminishing in size
		// (as would be in "a_{1_{2_{3_4}}}")
		if (GetFont().GetSize().Height() > rFormat.GetBaseSize().Height() / 3)
		{
			sal_uInt16 nIndex = (eSubSup == CSUB  ||  eSubSup == CSUP) ?
									SIZ_LIMITS : SIZ_INDEX;
			Fraction  aFraction ( rFormat.GetRelSize(nIndex), 100 );
			pSubSup->SetSize(aFraction);
		}

		pSubSup->Arrange(rDev, rFormat);

		sal_Bool  bIsTextmode = rFormat.IsTextmode();
		nDist = 0;

		//! be sure that CSUB, CSUP are handled before the other cases!
		switch (eSubSup)
		{	case RSUB :
			case LSUB :
				if (!bIsTextmode)
					nDist = nOrigHeight
							* rFormat.GetDistance(DIS_SUBSCRIPT) / 100L;
				aPos  = pSubSup->GetRect().AlignTo(aTmpRect,
								eSubSup == LSUB ? RP_LEFT : RP_RIGHT,
								RHA_CENTER, RVA_BOTTOM);
				aPos.Y() += nDist;
				nDelta = nDelimLine - aPos.Y();
				if (nDelta > 0)
					aPos.Y() += nDelta;
				break;
			case RSUP :
			case LSUP :
				if (!bIsTextmode)
					nDist = nOrigHeight
							* rFormat.GetDistance(DIS_SUPERSCRIPT) / 100L;
				aPos  = pSubSup->GetRect().AlignTo(aTmpRect,
								eSubSup == LSUP ? RP_LEFT : RP_RIGHT,
								RHA_CENTER, RVA_TOP);
				aPos.Y() -= nDist;
				nDelta = aPos.Y() + pSubSup->GetHeight() - nDelimLine;
				if (nDelta > 0)
					aPos.Y() -= nDelta;
				break;
			case CSUB :
				if (!bIsTextmode)
					nDist = nOrigHeight
							* rFormat.GetDistance(DIS_LOWERLIMIT) / 100L;
				aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_BOTTOM,
								RHA_CENTER, RVA_BASELINE);
				aPos.Y() += nDist;
				break;
			case CSUP :
				if (!bIsTextmode)
					nDist = nOrigHeight
							* rFormat.GetDistance(DIS_UPPERLIMIT) / 100L;
				aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_TOP,
								RHA_CENTER, RVA_BASELINE);
				aPos.Y() -= nDist;
				break;
			default :
				DBG_ASSERT(sal_False, "Sm: unbekannter Fall");
                break;
		}

		pSubSup->MoveTo(aPos);
		ExtendBy(*pSubSup, RCP_THIS, (sal_Bool) sal_True);

		// update rectangle to which  RSUB, RSUP, LSUB, LSUP
		// will be aligned to
		if (eSubSup == CSUB  ||  eSubSup == CSUP)
			aTmpRect = *this;
	}
}

void SmSubSupNode::CreateTextFromNode(String &rText)
{
	SmNode *pNode;
	GetSubNode(0)->CreateTextFromNode(rText);

    if (NULL != (pNode = GetSubNode(LSUB+1)))
	{
		APPEND(rText,"lsub ");
		pNode->CreateTextFromNode(rText);
	}
    if (NULL != (pNode = GetSubNode(LSUP+1)))
	{
		APPEND(rText,"lsup ");
		pNode->CreateTextFromNode(rText);
	}
    if (NULL != (pNode = GetSubNode(CSUB+1)))
	{
		APPEND(rText,"csub ");
		pNode->CreateTextFromNode(rText);
	}
    if (NULL != (pNode = GetSubNode(CSUP+1)))
	{
		APPEND(rText,"csup ");
		pNode->CreateTextFromNode(rText);
	}
    if (NULL != (pNode = GetSubNode(RSUB+1)))
	{
		rText.EraseTrailingChars();
		rText.Append('_');
		pNode->CreateTextFromNode(rText);
	}
    if (NULL != (pNode = GetSubNode(RSUP+1)))
	{
		rText.EraseTrailingChars();
		rText.Append('^');
		pNode->CreateTextFromNode(rText);
	}
}


/**************************************************************************/

void SmBraceNode::CreateTextFromNode(String &rText)
{
	if (GetScaleMode() == SCALE_HEIGHT)
		APPEND(rText,"left ");
    {
        String aStr;
	    GetSubNode(0)->CreateTextFromNode(aStr);
        aStr.EraseLeadingAndTrailingChars();
        aStr.EraseLeadingChars('\\');
        if (aStr.Len())
        {
            if (aStr.EqualsAscii("divides"))
                APPEND(rText,"lline");
            else if (aStr.EqualsAscii("parallel"))
                APPEND(rText,"ldline");
            else if (aStr.EqualsAscii("<"))
                APPEND(rText,"langle");
            else
                rText.Append(aStr);
	        rText.Append(' ');
        }
        else
            APPEND(rText,"none ");
    }
	GetSubNode(1)->CreateTextFromNode(rText);
	if (GetScaleMode() == SCALE_HEIGHT)
		APPEND(rText,"right ");
    {
        String aStr;
	    GetSubNode(2)->CreateTextFromNode(aStr);
        aStr.EraseLeadingAndTrailingChars();
        aStr.EraseLeadingChars('\\');
        if (aStr.Len())
        {
            if (aStr.EqualsAscii("divides"))
                APPEND(rText,"rline");
            else if (aStr.EqualsAscii("parallel"))
                APPEND(rText,"rdline");
            else if (aStr.EqualsAscii(">"))
                APPEND(rText,"rangle");
            else
                rText.Append(aStr);
	        rText.Append(' ');
        }
        else
            APPEND(rText,"none ");
    }
	rText.Append(' ');

}

void SmBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pLeft  = GetSubNode(0),
		   *pBody  = GetSubNode(1),
		   *pRight = GetSubNode(2);
	DBG_ASSERT(pLeft,  "Sm: NULL pointer");
	DBG_ASSERT(pBody,  "Sm: NULL pointer");
	DBG_ASSERT(pRight, "Sm: NULL pointer");

	pBody->Arrange(rDev, rFormat);

	sal_Bool  bIsScaleNormal = rFormat.IsScaleNormalBrackets(),
		  bScale 	     = pBody->GetHeight() > 0  &&
						   (GetScaleMode() == SCALE_HEIGHT  ||  bIsScaleNormal),
		  bIsABS 	     = GetToken().eType == TABS;

	long  nFaceHeight = GetFont().GetSize().Height();

    // Uebergroesse in % ermitteln
	sal_uInt16	nPerc = 0;
	if (!bIsABS && bScale)
    {   // im Fall von Klammern mit Uebergroesse...
        sal_uInt16 nIndex = GetScaleMode() == SCALE_HEIGHT ?
							DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
		nPerc = rFormat.GetDistance(nIndex);
	}

    // ermitteln der Hoehe fuer die Klammern
	long  nBraceHeight;
	if (bScale)
	{
		nBraceHeight = pBody->GetType() == NBRACEBODY ?
							  ((SmBracebodyNode *) pBody)->GetBodyHeight()
							: pBody->GetHeight();
		nBraceHeight += 2 * (nBraceHeight * nPerc / 100L);
	}
	else
		nBraceHeight = nFaceHeight;

	// Abstand zum Argument
	nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE);
	long  nDist = nFaceHeight * nPerc / 100L;

    // sofern erwuenscht skalieren der Klammern auf die gewuenschte Groesse
	if (bScale)
	{
        Size  aTmpSize (pLeft->GetFont().GetSize());
        DBG_ASSERT(pRight->GetFont().GetSize() == aTmpSize,
                    "Sm : unterschiedliche Fontgroessen");
        aTmpSize.Width() = Min((long) nBraceHeight * 60L / 100L,
							rFormat.GetBaseSize().Height() * 3L / 2L);
        // correction factor since change from StarMath to OpenSymbol font
        // because of the different font width in the FontMetric
        aTmpSize.Width() *= 182;
        aTmpSize.Width() /= 267;

		xub_Unicode cChar = pLeft->GetToken().cMathChar;
		if (cChar != MS_LINE  &&  cChar != MS_DLINE)
            pLeft ->GetFont().SetSize(aTmpSize);

		cChar = pRight->GetToken().cMathChar;
		if (cChar != MS_LINE  &&  cChar != MS_DLINE)
            pRight->GetFont().SetSize(aTmpSize);

		pLeft ->AdaptToY(rDev, nBraceHeight);
		pRight->AdaptToY(rDev, nBraceHeight);
	}

	pLeft ->Arrange(rDev, rFormat);
	pRight->Arrange(rDev, rFormat);

    // damit auch "\(a\) - (a) - left ( a right )" vernuenftig aussieht
	RectVerAlign  eVerAlign = bScale ? RVA_CENTERY : RVA_BASELINE;

	Point  		  aPos;
	aPos = pLeft->AlignTo(*pBody, RP_LEFT, RHA_CENTER, eVerAlign);
	aPos.X() -= nDist;
	pLeft->MoveTo(aPos);

	aPos = pRight->AlignTo(*pBody, RP_RIGHT, RHA_CENTER, eVerAlign);
	aPos.X() += nDist;
	pRight->MoveTo(aPos);

	SmRect::operator = (*pBody);
	ExtendBy(*pLeft, RCP_THIS).ExtendBy(*pRight, RCP_THIS);
}


/**************************************************************************/


void SmBracebodyNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	sal_uInt16  nNumSubNodes = GetNumSubNodes();
	if (nNumSubNodes == 0)
		return;

	// arrange arguments
	sal_uInt16 i;
	for (i = 0;  i < nNumSubNodes;  i += 2)
		GetSubNode(i)->Arrange(rDev, rFormat);

	// build reference rectangle with necessary info for vertical alignment
	SmRect  aRefRect (*GetSubNode(0));
	for (i = 0;  i < nNumSubNodes;  i += 2)
	{
		SmRect aTmpRect (*GetSubNode(i));
		Point  aPos = aTmpRect.AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
		aTmpRect.MoveTo(aPos);
		aRefRect.ExtendBy(aTmpRect, RCP_XOR);
	}

	nBodyHeight = aRefRect.GetHeight();

	// scale separators to required height and arrange them
	sal_Bool bScale  = GetScaleMode() == SCALE_HEIGHT  ||  rFormat.IsScaleNormalBrackets();
	long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetSize().Height();
    sal_uInt16 nIndex  = GetScaleMode() == SCALE_HEIGHT ?
						DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
	sal_uInt16 nPerc   = rFormat.GetDistance(nIndex);
	if (bScale)
		nHeight += 2 * (nHeight * nPerc / 100L);
	for (i = 1;  i < nNumSubNodes;  i += 2)
	{
		SmNode *pNode = GetSubNode(i);
		pNode->AdaptToY(rDev, nHeight);
		pNode->Arrange(rDev, rFormat);
	}

	// horizontal distance between argument and brackets or separators
	long  nDist = GetFont().GetSize().Height()
				  * rFormat.GetDistance(DIS_BRACKETSPACE) / 100L;

	SmNode *pLeft = GetSubNode(0);
	SmRect::operator = (*pLeft);
	for (i = 1;  i < nNumSubNodes;  i++)
	{
		sal_Bool          bIsSeparator = i % 2 != 0;
		RectVerAlign  eVerAlign    = bIsSeparator ? RVA_CENTERY : RVA_BASELINE;

		SmNode *pRight = GetSubNode(i);
		Point  aPosX = pRight->AlignTo(*pLeft,   RP_RIGHT, RHA_CENTER, eVerAlign),
			   aPosY = pRight->AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, eVerAlign);
		aPosX.X() += nDist;

		pRight->MoveTo(Point(aPosX.X(), aPosY.Y()));
		ExtendBy(*pRight, bIsSeparator ? RCP_THIS : RCP_XOR);

		pLeft = pRight;
	}
}


/**************************************************************************/


void SmVerticalBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pBody   = GetSubNode(0),
		   *pBrace  = GetSubNode(1),
		   *pScript = GetSubNode(2);
	DBG_ASSERT(pBody,   "Sm: NULL pointer!");
	DBG_ASSERT(pBrace,  "Sm: NULL pointer!");
	DBG_ASSERT(pScript, "Sm: NULL pointer!");

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	pBody->Arrange(aTmpDev, rFormat);

	// Groesse wie bei Grenzen fuer diesen Teil
	pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) );
	// etwas hoehere Klammern als normal
	pBrace ->SetSize( Fraction(3, 2) );

	long  nItalicWidth = pBody->GetItalicWidth();
	if (nItalicWidth > 0)
		pBrace->AdaptToX(aTmpDev, nItalicWidth);

	pBrace ->Arrange(aTmpDev, rFormat);
	pScript->Arrange(aTmpDev, rFormat);

	// die relativen Position und die Abstaende zueinander bestimmen
	RectPos  eRectPos;
	long nFontHeight = pBody->GetFont().GetSize().Height();
	long nDistBody   = nFontHeight * rFormat.GetDistance(DIS_ORNAMENTSIZE),
		 nDistScript = nFontHeight;
	if (GetToken().eType == TOVERBRACE)
	{
		eRectPos = RP_TOP;
		nDistBody    = - nDistBody;
		nDistScript *= - rFormat.GetDistance(DIS_UPPERLIMIT);
	}
	else // TUNDERBRACE
	{
		eRectPos = RP_BOTTOM;
		nDistScript *= + rFormat.GetDistance(DIS_LOWERLIMIT);
	}
	nDistBody   /= 100L;
	nDistScript /= 100L;

	Point  aPos = pBrace->AlignTo(*pBody, eRectPos, RHA_CENTER, RVA_BASELINE);
	aPos.Y() += nDistBody;
	pBrace->MoveTo(aPos);

	aPos = pScript->AlignTo(*pBrace, eRectPos, RHA_CENTER, RVA_BASELINE);
	aPos.Y() += nDistScript;
	pScript->MoveTo(aPos);

	SmRect::operator = (*pBody);
	ExtendBy(*pBrace, RCP_THIS).ExtendBy(*pScript, RCP_THIS);
}


/**************************************************************************/


SmNode * SmOperNode::GetSymbol()
{
	SmNode *pNode = GetSubNode(0);
	DBG_ASSERT(pNode, "Sm: NULL pointer!");

	if (pNode->GetType() == NSUBSUP)
		pNode = ((SmSubSupNode *) pNode)->GetBody();

	DBG_ASSERT(pNode, "Sm: NULL pointer!");
	return pNode;
}


long SmOperNode::CalcSymbolHeight(const SmNode &rSymbol,
								  const SmFormat &rFormat) const
	// returns the font height to be used for operator-symbol
{
	long  nHeight = GetFont().GetSize().Height();

    SmTokenType  eTmpType = GetToken().eType;
    if (eTmpType == TLIM  ||  eTmpType == TLIMINF  ||  eTmpType == TLIMSUP)
		return nHeight;

	if (!rFormat.IsTextmode())
	{
		// set minimum size ()
		nHeight += (nHeight * 20L) / 100L;

		nHeight += nHeight
				   * rFormat.GetDistance(DIS_OPERATORSIZE) / 100L;
		nHeight = nHeight * 686L / 845L;
	}

    // correct user-defined symbols to match height of sum from used font
    if (rSymbol.GetToken().eType == TSPECIAL)
		nHeight = nHeight * 845L / 686L;

	return nHeight;
}


void SmOperNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pOper = GetSubNode(0);
	SmNode *pBody = GetSubNode(1);

	DBG_ASSERT(pOper, "Sm: Subnode fehlt");
	DBG_ASSERT(pBody, "Sm: Subnode fehlt");

	SmNode *pSymbol = GetSymbol();
	pSymbol->SetSize(Fraction(CalcSymbolHeight(*pSymbol, rFormat),
							  pSymbol->GetFont().GetSize().Height()));

	pBody->Arrange(rDev, rFormat);
	pOper->Arrange(rDev, rFormat);

	long  nOrigHeight = GetFont().GetSize().Height(),
		  nDist = nOrigHeight
				  * rFormat.GetDistance(DIS_OPERATORSPACE) / 100L;

	Point aPos = pOper->AlignTo(*pBody, RP_LEFT, RHA_CENTER, /*RVA_CENTERY*/RVA_MID);
	aPos.X() -= nDist;
	pOper->MoveTo(aPos);

	SmRect::operator = (*pBody);
	ExtendBy(*pOper, RCP_THIS);
}


/**************************************************************************/


void SmAlignNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
	// setzt im ganzen subtree (incl aktuellem node) das alignment
{
	DBG_ASSERT(GetNumSubNodes() > 0, "Sm: SubNode fehlt");

	SmNode	*pNode = GetSubNode(0);

    RectHorAlign  eHorAlign = RHA_CENTER;
	switch (GetToken().eType)
	{
		case TALIGNL:	eHorAlign = RHA_LEFT;	break;
		case TALIGNC:	eHorAlign = RHA_CENTER;	break;
		case TALIGNR:	eHorAlign = RHA_RIGHT;	break;
        default:
            break;
	}
	SetRectHorAlign(eHorAlign);

	pNode->Arrange(rDev, rFormat);

	SmRect::operator = (pNode->GetRect());
}


/**************************************************************************/


void SmAttributNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pAttr = GetSubNode(0),
		   *pBody = GetSubNode(1);
	DBG_ASSERT(pBody, "Sm: Body fehlt");
	DBG_ASSERT(pAttr, "Sm: Attribut fehlt");

	pBody->Arrange(rDev, rFormat);

	if (GetScaleMode() == SCALE_WIDTH)
		pAttr->AdaptToX(rDev, pBody->GetItalicWidth());
	pAttr->Arrange(rDev, rFormat);

	// get relative position of attribut
	RectVerAlign  eVerAlign;
	long  		  nDist = 0;
	switch (GetToken().eType)
	{	case TUNDERLINE :
			eVerAlign = RVA_ATTRIBUT_LO;
			break;
		case TOVERSTRIKE :
			eVerAlign = RVA_ATTRIBUT_MID;
			break;
		default :
			eVerAlign = RVA_ATTRIBUT_HI;
			if (pBody->GetType() == NATTRIBUT)
				nDist = GetFont().GetSize().Height()
						* rFormat.GetDistance(DIS_ORNAMENTSPACE) / 100L;
	}
	Point  aPos = pAttr->AlignTo(*pBody, RP_ATTRIBUT, RHA_CENTER, eVerAlign);
	aPos.Y() -= nDist;
	pAttr->MoveTo(aPos);

	SmRect::operator = (*pBody);
	ExtendBy(*pAttr, RCP_THIS, (sal_Bool) sal_True);
}


/**************************************************************************/




void SmFontNode::CreateTextFromNode(String &rText)
{
	switch (GetToken().eType)
	{
		case TBOLD:
			APPEND(rText,"bold ");
			break;
		case TNBOLD:
			APPEND(rText,"nbold ");
			break;
		case TITALIC:
			APPEND(rText,"italic ");
			break;
		case TNITALIC:
			APPEND(rText,"nitalic ");
			break;
		case TPHANTOM:
			APPEND(rText,"phantom ");
			break;
		case TSIZE:
			{
				APPEND(rText,"size ");
				switch (nSizeType)
				{
					case FNTSIZ_PLUS:
						rText.Append('+');
						break;
					case FNTSIZ_MINUS:
						rText.Append('-');
						break;
					case FNTSIZ_MULTIPLY:
						rText.Append('*');
						break;
					case FNTSIZ_DIVIDE:
						rText.Append('/');
						break;
					case FNTSIZ_ABSOLUT:
					default:
						break;
				}
                rText += String( ::rtl::math::doubleToUString(
                            static_cast<double>(aFontSize),
                            rtl_math_StringFormat_Automatic,
                            rtl_math_DecimalPlaces_Max, '.', sal_True));
				rText.Append(' ');
			}
			break;
		case TBLACK:
			APPEND(rText,"color black ");
			break;
		case TWHITE:
			APPEND(rText,"color white ");
			break;
		case TRED:
			APPEND(rText,"color red ");
			break;
		case TGREEN:
			APPEND(rText,"color green ");
			break;
		case TBLUE:
			APPEND(rText,"color blue ");
			break;
		case TCYAN:
			APPEND(rText,"color cyan ");
			break;
		case TMAGENTA:
			APPEND(rText,"color magenta ");
			break;
		case TYELLOW:
			APPEND(rText,"color yellow ");
			break;
        case TTEAL:
            APPEND(rText,"color teal");
            break;
        case TSILVER:
            APPEND(rText,"color silver");
            break;
        case TGRAY:
            APPEND(rText,"color gray");
            break;
        case TMAROON:
            APPEND(rText,"color maroon");
            break;
        case TPURPLE:
            APPEND(rText,"color purple");
            break;
        case TLIME:
            APPEND(rText,"color lime");
            break;
        case TOLIVE:
            APPEND(rText,"color olive");
            break;
        case TNAVY:
            APPEND(rText,"color navy");
            break;
        case TAQUA:
            APPEND(rText,"color aqua");
            break;
        case TFUCHSIA:
            APPEND(rText,"color fuchsia");
            break;
		case TSANS:
			APPEND(rText,"font sans ");
			break;
		case TSERIF:
			APPEND(rText,"font serif ");
			break;
		case TFIXED:
			APPEND(rText,"font fixed ");
			break;
		default:
			break;
	}
	GetSubNode(1)->CreateTextFromNode(rText);
}


void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	//! prepare subnodes first
	SmNode::Prepare(rFormat, rDocShell);

	int  nFnt = -1;
	switch (GetToken().eType)
	{
		case TFIXED:	nFnt = FNT_FIXED;	break;
		case TSANS:		nFnt = FNT_SANS;	break;
		case TSERIF:	nFnt = FNT_SERIF;	break;
        default:
            break;
	}
	if (nFnt != -1)
    {   GetFont() = rFormat.GetFont( sal::static_int_cast< sal_uInt16 >(nFnt) );
		SetFont(GetFont());
	}

	//! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of
	//! other font nodes (those with lower depth in the tree)
	Flags() |= FLG_FONT;
}


void SmFontNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	SmNode *pNode = GetSubNode(1);
	DBG_ASSERT(pNode, "Sm: SubNode fehlt");

	switch (GetToken().eType)
	{	case TSIZE :
			pNode->SetFontSize(aFontSize, nSizeType);
			break;
		case TSANS :
		case TSERIF :
		case TFIXED :
			pNode->SetFont(GetFont());
			break;
		case TUNKNOWN :	break;	// no assertion on "font <?> <?>"

		case TPHANTOM :	SetPhantom(sal_True);				break;
		case TBOLD :	SetAttribut(ATTR_BOLD);			break;
		case TITALIC :	SetAttribut(ATTR_ITALIC);		break;
		case TNBOLD :	ClearAttribut(ATTR_BOLD);		break;
		case TNITALIC :	ClearAttribut(ATTR_ITALIC);		break;

		case TBLACK :	SetColor(Color(COL_BLACK));		break;
		case TWHITE :	SetColor(Color(COL_WHITE));		break;
		case TRED :		SetColor(Color(COL_LIGHTRED));		break;
		case TGREEN :	SetColor(Color(COL_GREEN));		break;
		case TBLUE :	SetColor(Color(COL_LIGHTBLUE));		break;
		case TCYAN :	SetColor(Color(COL_LIGHTCYAN));		break; // as in Calc
		case TMAGENTA :	SetColor(Color(COL_LIGHTMAGENTA));	break; // as in Calc
		case TYELLOW :	SetColor(Color(COL_YELLOW));	break;
        case TTEAL :    SetColor(Color(COL_CYAN));  break;
        case TSILVER :  SetColor(Color(COL_LIGHTGRAY));  break;
        case TGRAY :    SetColor(Color(COL_GRAY));  break;
        case TMAROON :  SetColor(Color(COL_RED));  break;
        case TPURPLE :  SetColor(Color(COL_MAGENTA));  break;
        case TLIME :    SetColor(Color(COL_LIGHTGREEN));  break;
        case TOLIVE :   SetColor(Color(COL_BROWN));  break;
        case TNAVY :    SetColor(Color(COL_BLUE));  break;
        case TAQUA :    SetColor(Color(COL_LIGHTCYAN));  break;
        case TFUCHSIA : SetColor(Color(COL_LIGHTMAGENTA));  break;

		default:
			DBG_ASSERT(sal_False, "Sm: unbekannter Fall");
	}

	pNode->Arrange(rDev, rFormat);

	SmRect::operator = (pNode->GetRect());
}


void SmFontNode::SetSizeParameter(const Fraction& rValue, sal_uInt16 Type)
{
	nSizeType = Type;
	aFontSize = rValue;
}


/**************************************************************************/


SmPolyLineNode::SmPolyLineNode(const SmToken &rNodeToken)
:	SmGraphicNode(NPOLYLINE, rNodeToken)
{
	aPoly.SetSize(2);
	nWidth = 0;
}


void SmPolyLineNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nNewWidth)
{
    aToSize.Width() = nNewWidth;
}


void SmPolyLineNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nNewHeight)
{
	GetFont().FreezeBorderWidth();
    aToSize.Height() = nNewHeight;
}


void SmPolyLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	//! some routines being called extract some info from the OutputDevice's
	//! font (eg the space to be used for borders OR the font name(!!)).
	//! Thus the font should reflect the needs and has to be set!
    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	long  nBorderwidth = GetFont().GetBorderWidth();

	//
	// Das Polygon mit den beiden Endpunkten bilden
	//
	DBG_ASSERT(aPoly.GetSize() == 2, "Sm : falsche Anzahl von Punkten");
	Point  aPointA, aPointB;
	if (GetToken().eType == TWIDESLASH)
	{
		aPointA.X() = nBorderwidth;
		aPointA.Y() = aToSize.Height() - nBorderwidth;
		aPointB.X() = aToSize.Width() - nBorderwidth;
		aPointB.Y() = nBorderwidth;
	}
	else
	{
		DBG_ASSERT(GetToken().eType == TWIDEBACKSLASH, "Sm : unerwartetes Token");
		aPointA.X() =
		aPointA.Y() = nBorderwidth;
		aPointB.X() = aToSize.Width() - nBorderwidth;
		aPointB.Y() = aToSize.Height() - nBorderwidth;
	}
	aPoly.SetPoint(aPointA, 0);
	aPoly.SetPoint(aPointB, 1);

	long  nThick	   = GetFont().GetSize().Height()
							* rFormat.GetDistance(DIS_STROKEWIDTH) / 100L;
	nWidth = nThick + 2 * nBorderwidth;

	SmRect::operator = (SmRect(aToSize.Width(), aToSize.Height()));
}


void SmPolyLineNode::Draw(OutputDevice &rDev, const Point &rPosition) const
{
	if (IsPhantom())
		return;

	long nBorderwidth = GetFont().GetBorderWidth();

	LineInfo  aInfo;
	aInfo.SetWidth(nWidth - 2 * nBorderwidth);

	Point aOffset (Point() - aPoly.GetBoundRect().TopLeft()
				   + Point(nBorderwidth, nBorderwidth)),
		  aPos (rPosition + aOffset);
	((Polygon &) aPoly).Move(aPos.X(), aPos.Y());

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_False);
    aTmpDev.SetLineColor( GetFont().GetColor() );

    rDev.DrawPolyLine(aPoly, aInfo);

#ifdef SM_RECT_DEBUG
	if (!IsDebug())
		return;

	int  nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
	SmRect::Draw(rDev, rPosition, nRFlags);
#endif
}


/**************************************************************************/

void SmRootSymbolNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth)
{
    nBodyWidth = nWidth;
}


void SmRootSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
{
    // etwas extra Laenge damit der horizontale Balken spaeter ueber dem
    // Argument positioniert ist
    SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10L);
}


void SmRootSymbolNode::Draw(OutputDevice &rDev, const Point &rPosition) const
{
	if (IsPhantom())
		return;

	// draw root-sign itself
    SmMathSymbolNode::Draw(rDev, rPosition);

    SmTmpDevice  aTmpDev( (OutputDevice &) rDev, sal_True );
    aTmpDev.SetFillColor(GetFont().GetColor());
    rDev.SetLineColor();
    aTmpDev.SetFont( GetFont() );

    // since the width is always unscaled it corresponds ot the _original_
    // _unscaled_ font height to be used, we use that to calculate the
    // bar height. Thus it is independent of the arguments height.
    // ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} )
    long nBarHeight = GetWidth() * 7L / 100L;
    long nBarWidth = nBodyWidth + GetBorderWidth();
    Point aBarOffset( GetWidth(), +GetBorderWidth() );
    Point aBarPos( rPosition + aBarOffset );

    Rectangle  aBar(aBarPos, Size( nBarWidth, nBarHeight) );
    //! avoid GROWING AND SHRINKING of drawn rectangle when constantly
    //! increasing zoomfactor.
    //  This is done by shifting it's output-position to a point that
    //  corresponds exactly to a pixel on the output device.
    Point  aDrawPos( rDev.PixelToLogic(rDev.LogicToPixel(aBar.TopLeft())) );
    //aDrawPos.X() = aBar.Left();     //! don't change X position
    aBar.SetPos( aDrawPos );

    rDev.DrawRect( aBar );

#ifdef SM_RECT_DEBUG
	if (!IsDebug())
		return;

	int  nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
	SmRect::Draw(rDev, rPosition, nRFlags);
#endif
}


/**************************************************************************/


void SmRectangleNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth)
{
	aToSize.Width() = nWidth;
}


void SmRectangleNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nHeight)
{
	GetFont().FreezeBorderWidth();
	aToSize.Height() = nHeight;
}


void SmRectangleNode::Arrange(const OutputDevice &rDev, const SmFormat &/*rFormat*/)
{
	long  nFontHeight = GetFont().GetSize().Height();
	long  nWidth  = aToSize.Width(),
		  nHeight = aToSize.Height();
	if (nHeight == 0)
		nHeight = nFontHeight / 30;
	if (nWidth == 0)
		nWidth	= nFontHeight / 3;

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	// add some borderspace
    sal_uLong  nTmpBorderWidth = GetFont().GetBorderWidth();
    //nWidth  += nTmpBorderWidth;
    nHeight += 2 * nTmpBorderWidth;

	//! use this method in order to have 'SmRect::HasAlignInfo() == sal_True'
	//! and thus having the attribut-fences updated in 'SmRect::ExtendBy'
	SmRect::operator = (SmRect(nWidth, nHeight));
}


void SmRectangleNode::Draw(OutputDevice &rDev, const Point &rPosition) const
{
	if (IsPhantom())
		return;

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_False);
    aTmpDev.SetFillColor(GetFont().GetColor());
    rDev.SetLineColor();
    aTmpDev.SetFont(GetFont());

    sal_uLong  nTmpBorderWidth = GetFont().GetBorderWidth();

	// get rectangle and remove borderspace
	Rectangle  aTmp (AsRectangle() + rPosition - GetTopLeft());
    aTmp.Left()   += nTmpBorderWidth;
    aTmp.Right()  -= nTmpBorderWidth;
    aTmp.Top()    += nTmpBorderWidth;
    aTmp.Bottom() -= nTmpBorderWidth;

	DBG_ASSERT(aTmp.GetHeight() > 0  &&  aTmp.GetWidth() > 0,
			   "Sm: leeres Rechteck");

	//! avoid GROWING AND SHRINKING of drawn rectangle when constantly
	//! increasing zoomfactor.
	//	This is done by shifting it's output-position to a point that
	//	corresponds exactly to a pixel on the output device.
    Point  aPos (rDev.PixelToLogic(rDev.LogicToPixel(aTmp.TopLeft())));
	aTmp.SetPos(aPos);

    rDev.DrawRect(aTmp);

#ifdef SM_RECT_DEBUG
	if (!IsDebug())
		return;

	int  nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
	SmRect::Draw(rDev, rPosition, nRFlags);
#endif
}


/**************************************************************************/


SmTextNode::SmTextNode( SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP ) :
    SmVisibleNode(eNodeType, rNodeToken)
{
    nFontDesc = nFontDescP;
}


SmTextNode::SmTextNode( const SmToken &rNodeToken, sal_uInt16 nFontDescP ) :
    SmVisibleNode(NTEXT, rNodeToken)
{
	nFontDesc = nFontDescP;
}


void SmTextNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

    // default setting for horizontal alignment of nodes with TTEXT
    // content is as alignl (cannot be done in Arrange since it would
    // override the settings made by an SmAlignNode before)
    if (TTEXT == GetToken().eType)
        SetRectHorAlign( RHA_LEFT );

    aText = GetToken().aText;
	GetFont() = rFormat.GetFont(GetFontDesc());

    if (IsItalic( GetFont() ))
		Attributes() |= ATTR_ITALIC;
    if (IsBold( GetFont() ))
		Attributes() |= ATTR_BOLD;

	// special handling for ':' where it is a token on it's own and is likely
	// to be used for mathematical notations. (E.g. a:b = 2:3)
	// In that case it should not be displayed in italic.
	if (GetToken().aText.Len() == 1 && GetToken().aText.GetChar(0) == ':')
		Attributes() &= ~ATTR_ITALIC;
};


void SmTextNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	PrepareAttributes();

	sal_uInt16	nSizeDesc = GetFontDesc() == FNT_FUNCTION ?
							SIZ_FUNCTION : SIZ_TEXT;
	GetFont() *= Fraction (rFormat.GetRelSize(nSizeDesc), 100);

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	SmRect::operator = (SmRect(aTmpDev, &rFormat, aText, GetFont().GetBorderWidth()));
}

void SmTextNode::CreateTextFromNode(String &rText)
{
    sal_Bool bQuoted=sal_False;
	if (GetToken().eType == TTEXT)
    {
		rText.Append('\"');
        bQuoted=sal_True;
    }
    else
    {
        SmParser aParseTest;
        SmNode *pTable = aParseTest.Parse(GetToken().aText);
        bQuoted=sal_True;
        if ( (pTable->GetType() == NTABLE) && (pTable->GetNumSubNodes() == 1) )
        {
            SmNode *pResult = pTable->GetSubNode(0);
            if ( (pResult->GetType() == NLINE) &&
                (pResult->GetNumSubNodes() == 1) )
            {
                pResult = pResult->GetSubNode(0);
                if ( (pResult->GetType() == NEXPRESSION) &&
                    (pResult->GetNumSubNodes() == 1) )
                {
                    pResult = pResult->GetSubNode(0);
                    if (pResult->GetType() == NTEXT)
                        bQuoted=sal_False;
                }
            }
        }
        delete pTable;

        if ((GetToken().eType == TIDENT) && (GetFontDesc() == FNT_FUNCTION))
        {
            //Search for existing functions and remove extraenous keyword
            APPEND(rText,"func ");
        }
        else if (bQuoted)
            APPEND(rText,"italic ");

        if (bQuoted)
            rText.Append('\"');

    }

	rText.Append(GetToken().aText);

	if (bQuoted)
		rText.Append('\"');
	rText.Append(' ');
}

void SmTextNode::Draw(OutputDevice &rDev, const Point& rPosition) const
{
	if (IsPhantom()  ||  aText.Len() == 0  ||  aText.GetChar(0) == xub_Unicode('\0'))
		return;

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_False);
    aTmpDev.SetFont(GetFont());

    Point  aPos (rPosition);
	aPos.Y() += GetBaselineOffset();
	// auf Pixelkoordinaten runden
    aPos = rDev.PixelToLogic( rDev.LogicToPixel(aPos) );

#if OSL_DEBUG_LEVEL > 1
    sal_Int32 nPos = 0;
    sal_UCS4 cChar = OUString( aText ).iterateCodePoints( &nPos );
    (void) cChar;
#endif

    rDev.DrawStretchText(aPos, GetWidth(), aText);

#ifdef SM_RECT_DEBUG
	if (!IsDebug())
		return;

	int  nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
	SmRect::Draw(rDev, rPosition, nRFlags);
#endif
}

void SmTextNode::GetAccessibleText( String &rText ) const
{
    rText += aText;
}

/**************************************************************************/

void SmMatrixNode::CreateTextFromNode(String &rText)
{
	APPEND(rText,"matrix {");
    for (sal_uInt16 i = 0;  i < nNumRows; i++)
	{
        for (sal_uInt16 j = 0;  j < nNumCols; j++)
		{
			SmNode *pNode = GetSubNode(i * nNumCols + j);
			pNode->CreateTextFromNode(rText);
			if (j != nNumCols-1)
				APPEND(rText,"# ");
		}
		if (i != nNumRows-1)
			APPEND(rText,"## ");
	}
	rText.EraseTrailingChars();
	APPEND(rText,"} ");
}


void SmMatrixNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	Point	aPosition,
			aOffset;
	SmNode *pNode;
    sal_uInt16  i, j;

	// initialize array that is to hold the maximum widhts of all
	// elements (subnodes) in that column.
	long *pColWidth = new long[nNumCols];
	for (j = 0;  j	< nNumCols;  j++)
		pColWidth[j] = 0;

	// arrange subnodes and calculate the aboves arrays contents
    sal_uInt16 nNodes = GetNumSubNodes();
    for (i = 0;  i < nNodes;  i++)
    {
        sal_uInt16 nIdx = nNodes - 1 - i;
        if (NULL != (pNode = GetSubNode(nIdx)))
        {
            pNode->Arrange(rDev, rFormat);
            int  nCol = nIdx % nNumCols;
            pColWidth[nCol] = Max(pColWidth[nCol], pNode->GetItalicWidth());
        }
    }

	// norm distance from which the following two are calculated
	const int  nNormDist = 3 * GetFont().GetSize().Height();

	// define horizontal and vertical minimal distances that separate
	// the elements
	long  nHorDist = nNormDist * rFormat.GetDistance(DIS_MATRIXCOL) / 100L,
		  nVerDist = nNormDist * rFormat.GetDistance(DIS_MATRIXROW) / 100L;

	// build array that holds the leftmost position for each column
	long *pColLeft = new long[nNumCols];
	long  nX = 0;
	for (j = 0;  j < nNumCols;	j++)
	{	pColLeft[j] = nX;
		nX += pColWidth[j] + nHorDist;
	}

	Point	aPos, aDelta;
	SmRect	aLineRect;
	SmRect::operator = (SmRect());
	for (i = 0;  i < nNumRows;	i++)
	{	aLineRect = SmRect();
		for (j = 0;  j < nNumCols;	j++)
        {   SmNode *pTmpNode = GetSubNode(i * nNumCols + j);
            DBG_ASSERT(pTmpNode, "Sm: NULL pointer");

            const SmRect &rNodeRect = pTmpNode->GetRect();

			// align all baselines in that row if possible
			aPos = rNodeRect.AlignTo(aLineRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
			aPos.X() += nHorDist;

			// get horizontal alignment
            const SmNode *pCoNode   = pTmpNode->GetLeftMost();
            RectHorAlign  eHorAlign = pCoNode->GetRectHorAlign();

			// calculate horizontal position of element depending on column
			// and horizontal alignment
			switch (eHorAlign)
			{	case RHA_LEFT:
					aPos.X() = rNodeRect.GetLeft() + pColLeft[j];
					break;
				case RHA_CENTER:
					aPos.X() = rNodeRect.GetLeft() + pColLeft[j]
							   + pColWidth[j] / 2
							   - rNodeRect.GetItalicCenterX();
					break;
				case RHA_RIGHT:
					aPos.X() = rNodeRect.GetLeft() + pColLeft[j]
							   + pColWidth[j] - rNodeRect.GetItalicWidth();
					break;
			}

            pTmpNode->MoveTo(aPos);
			aLineRect.ExtendBy(rNodeRect, RCP_XOR);
		}

		aPos = aLineRect.AlignTo(*this, RP_BOTTOM, RHA_CENTER, RVA_BASELINE);
		aPos.Y() += nVerDist;

		// move 'aLineRect' and rectangles in that line to final position
		aDelta.X() = 0;		// since horizontal alignment is already done
		aDelta.Y() = aPos.Y() - aLineRect.GetTop();
		aLineRect.Move(aDelta);
		for (j = 0;  j < nNumCols;	j++)
            if (NULL != (pNode = GetSubNode(i * nNumCols + j)))
				pNode->Move(aDelta);

		ExtendBy(aLineRect, RCP_NONE);
	}

	delete [] pColLeft;
	delete [] pColWidth;
}


void SmMatrixNode::SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols)
{
	nNumRows = nMatrixRows;
	nNumCols = nMatrixCols;
}


SmNode * SmMatrixNode::GetLeftMost()
{
	return this;
}


/**************************************************************************/


SmMathSymbolNode::SmMathSymbolNode(const SmToken &rNodeToken)
:	SmSpecialNode(NMATH, rNodeToken, FNT_MATH)
{
	xub_Unicode cChar = GetToken().cMathChar;
	if ((xub_Unicode) '\0' != cChar)
		SetText( cChar );
}

void SmMathSymbolNode::AdaptToX(const OutputDevice &rDev, sal_uLong nWidth)
{
    // Since there is no function to do this, we try to approximate it:
    Size  aFntSize (GetFont().GetSize());

    //! however the result is a bit better with 'nWidth' as initial font width
    aFntSize.Width() = nWidth;
    GetFont().SetSize(aFntSize);

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
    aTmpDev.SetFont(GetFont());

    // get denominator of error factor for width
    long nTmpBorderWidth = GetFont().GetBorderWidth();
    long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetItalicWidth();

    // scale fontwidth with this error factor
    aFntSize.Width() *= nWidth;
    aFntSize.Width() /= nDenom ? nDenom : 1;

    GetFont().SetSize(aFntSize);
}

void SmMathSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
{
    GetFont().FreezeBorderWidth();
    Size  aFntSize (GetFont().GetSize());

    // da wir nur die Hoehe skalieren wollen muesen wir hier ggf die Fontweite
    // ermitteln um diese beizubehalten.
    if (aFntSize.Width() == 0)
    {
        OutputDevice &rDevNC = (OutputDevice &) rDev;
        rDevNC.Push(PUSH_FONT | PUSH_MAPMODE);
        rDevNC.SetFont(GetFont());
        aFntSize.Width() = rDev.GetFontMetric().GetSize().Width();
        rDevNC.Pop();
    }
    DBG_ASSERT(aFntSize.Width() != 0, "Sm: ");

    //! however the result is a bit better with 'nHeight' as initial
    //! font height
    aFntSize.Height() = nHeight;
    GetFont().SetSize(aFntSize);

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
    aTmpDev.SetFont(GetFont());

    // get denominator of error factor for height
    long nTmpBorderWidth = GetFont().GetBorderWidth();
    long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetHeight();

    // scale fontwidth with this error factor
    aFntSize.Height() *= nHeight;
    aFntSize.Height() /= nDenom ? nDenom : 1;

    GetFont().SetSize(aFntSize);
}


void SmMathSymbolNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

	GetFont() = rFormat.GetFont(GetFontDesc());
	// use same font size as is used for variables
	GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() );

    DBG_ASSERT(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL  ||
               GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
        "incorrect charset for character from StarMath/OpenSymbol font");

	Flags() |= FLG_FONT | FLG_ITALIC;
};


void SmMathSymbolNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	const XubString &rText = GetText();

	if (rText.Len() == 0  ||  rText.GetChar(0) == xub_Unicode('\0'))
	{	SmRect::operator = (SmRect());
		return;
	}

	PrepareAttributes();

	GetFont() *= Fraction (rFormat.GetRelSize(SIZ_TEXT), 100);

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
}

void SmMathSymbolNode::CreateTextFromNode(String &rText)
{
	String sStr;
	MathType::LookupChar(GetToken().cMathChar, sStr);
	rText.Append(sStr);
}

void SmRectangleNode::CreateTextFromNode(String &rText)
{
    switch (GetToken().eType)
    {
    case TUNDERLINE:
        APPEND(rText,"underline ");
        break;
    case TOVERLINE:
        APPEND(rText,"overline ");
        break;
    case TOVERSTRIKE:
        APPEND(rText,"overstrike ");
        break;
    default:
        break;
    }
}

void SmAttributNode::CreateTextFromNode(String &rText)
{
	SmNode *pNode;
	sal_uInt16	nSize = GetNumSubNodes();
    DBG_ASSERT(nSize == 2, "Node missing members");
    rText.Append('{');
    sal_Unicode nLast=0;
    if (NULL != (pNode = GetSubNode(0)))
    {
        String aStr;
        pNode->CreateTextFromNode(aStr);
        if (aStr.Len() > 1)
            rText.Append(aStr);
        else
        {
            nLast = aStr.GetChar(0);
            switch (nLast)
            {
            case 0xAF: // MACRON
                APPEND(rText,"overline ");
                break;
            case 0x2d9: // DOT ABOVE
                APPEND(rText,"dot ");
                break;
            case 0x2dc: // SMALL TILDE
                APPEND(rText,"widetilde ");
                break;
            case 0xA8: // DIAERESIS
                APPEND(rText,"ddot ");
                break;
            case 0xE082:
                break;
            case 0xE09B:
            case 0x20DB: // COMBINING THREE DOTS ABOVE
                APPEND(rText,"dddot ");
                break;
            case 0x301: // COMBINING ACUTE ACCENT
                APPEND(rText,"acute ");
                break;
            case 0x300: // COMBINING GRAVE ACCENT
                APPEND(rText,"grave ");
                break;
            case 0x30C: // COMBINING CARON
                APPEND(rText,"check ");
                break;
            case 0x306: // COMBINING BREVE
                APPEND(rText,"breve ");
                break;
            case 0x30A: // COMBINING RING ABOVE
                APPEND(rText,"circle ");
                break;
            case 0x20D7: // COMBINING RIGHT ARROW ABOVE
                APPEND(rText,"vec ");
                break;
            case 0x303: // COMBINING TILDE
                APPEND(rText,"tilde ");
                break;
            case 0x302: // COMBINING CIRCUMFLEX ACCENT
                APPEND(rText,"hat ");
                break;
            case 0x304: // COMBINING MACRON
                APPEND(rText,"bar ");
                break;
            default:
                rText.Append(nLast);
                break;
            }
        }
    }

	if (nSize == 2)
        if (NULL != (pNode = GetSubNode(1)))
			pNode->CreateTextFromNode(rText);

	rText.EraseTrailingChars();

    if (nLast == 0xE082)
        APPEND(rText," overbrace {}");

	APPEND(rText,"} ");
}

/**************************************************************************/

bool lcl_IsFromGreekSymbolSet( const String &rTokenText )
{
    bool bRes = false;

    // valid symbol name needs to have a '%' at pos 0 and at least an additional char
    if (rTokenText.Len() > 2 && rTokenText.GetBuffer()[0] == (sal_Unicode)'%')
    {
        String aName( rTokenText.Copy(1) );
        SmSym *pSymbol = SM_MOD()->GetSymbolManager().GetSymbolByName( aName );
        if (pSymbol && GetExportSymbolSetName( pSymbol->GetSymbolSetName() ).EqualsAscii( "Greek" ) )
            bRes = true;
    }

    return bRes;
}


SmSpecialNode::SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc) :
    SmTextNode(eNodeType, rNodeToken, _nFontDesc)
{
    bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText );
}


SmSpecialNode::SmSpecialNode(const SmToken &rNodeToken) :
    SmTextNode(NSPECIAL, rNodeToken, FNT_MATH)	//! default Font nicht immer richtig
{
    bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText );
}


void SmSpecialNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

	const SmSym	  *pSym;
    SmModule  *pp = SM_MOD();

    String aName( GetToken().aText.Copy(1) );
    if (NULL != (pSym = pp->GetSymbolManager().GetSymbolByName( aName )))
    {
        sal_UCS4 cChar = pSym->GetCharacter();
        String aTmp( OUString( &cChar, 1 ) );
        SetText( aTmp );
		GetFont() = pSym->GetFace();
	}
	else
    {
        SetText( GetToken().aText );
		GetFont() = rFormat.GetFont(FNT_VARIABLE);
	}
	// use same font size as is used for variables
	GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() );

	//! eigentlich sollten nur WEIGHT_NORMAL und WEIGHT_BOLD vorkommen...
	//! In der sms-Datei gibt es jedoch zB auch 'WEIGHT_ULTRALIGHT'
	//! daher vergleichen wir hier mit  >  statt mit  !=  .
    //! (Langfristig sollte die Notwendigkeit fuer 'PrepareAttribut', und damit
    //! fuer dieses hier, mal entfallen.)
    //
    //! see also SmFontStyles::GetStyleName
    if (IsItalic( GetFont() ))
        SetAttribut(ATTR_ITALIC);
    if (IsBold( GetFont() ))
		SetAttribut(ATTR_BOLD);

	Flags() |= FLG_FONT;

    if (bIsFromGreekSymbolSet)
    {
        DBG_ASSERT( GetText().Len() == 1, "a symbol should only consist of 1 char!" );
        bool bItalic = false;
        sal_Int16 nStyle = rFormat.GetGreekCharStyle();
        DBG_ASSERT( nStyle >= 0 && nStyle <= 2, "unexpected value for GreekCharStyle" );
        if (nStyle == 1)
            bItalic = true;
        else if (nStyle == 2)
        {
            String aTmp( GetText() );
            if (aTmp.Len() > 0)
            {
                const sal_Unicode cUppercaseAlpha = 0x0391;
                const sal_Unicode cUppercaseOmega = 0x03A9;
                sal_Unicode cChar = aTmp.GetBuffer()[0];
                // uppercase letters should be straight and lowercase letters italic
                bItalic = !(cUppercaseAlpha <= cChar && cChar <= cUppercaseOmega);
            }
        }

        if (bItalic)
            Attributes() |= ATTR_ITALIC;
        else
            Attributes() &= ~ATTR_ITALIC;
    }
};


void SmSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	PrepareAttributes();

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
}


void SmSpecialNode::Draw(OutputDevice &rDev, const Point& rPosition) const
{
	//! since this chars might come from any font, that we may not have
	//! set to ALIGN_BASELINE yet, we do it now.
	((SmSpecialNode *)this)->GetFont().SetAlign(ALIGN_BASELINE);

	SmTextNode::Draw(rDev, rPosition);
}


/**************************************************************************/


void SmGlyphSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	PrepareAttributes();

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(),
							   GetFont().GetBorderWidth()).AsGlyphRect());
}


/**************************************************************************/


void SmPlaceNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

	GetFont().SetColor(COL_GRAY);
	Flags() |= FLG_COLOR | FLG_FONT | FLG_ITALIC;
};


void SmPlaceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	PrepareAttributes();

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
}


/**************************************************************************/


void SmErrorNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

	GetFont().SetColor(COL_RED);
	Flags() |= FLG_VISIBLE | FLG_BOLD | FLG_ITALIC
			   | FLG_COLOR | FLG_FONT | FLG_SIZE;
}


void SmErrorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
	PrepareAttributes();

    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

	const XubString &rText = GetText();
	SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
}


/**************************************************************************/


void SmBlankNode::IncreaseBy(const SmToken &rToken)
{
	switch(rToken.eType)
	{
		case TBLANK:	nNum += 4;	break;
		case TSBLANK:	nNum += 1;	break;
        default:
            break;
	}
}


void SmBlankNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
{
	SmNode::Prepare(rFormat, rDocShell);

    //! hier muss/sollte es lediglich nicht der StarMath Font sein,
    //! damit fuer das in Arrange verwendete Zeichen ein "normales"
	//! (ungecliptes) Rechteck erzeugt wird.
	GetFont() = rFormat.GetFont(FNT_VARIABLE);

	Flags() |= FLG_FONT | FLG_BOLD | FLG_ITALIC;
}


void SmBlankNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
    SmTmpDevice  aTmpDev ((OutputDevice &) rDev, sal_True);
	aTmpDev.SetFont(GetFont());

    // Abstand von der Fonthoehe abhaengig machen
    // (damit er beim skalieren (zB size *2 {a ~ b}) mitwaechst)
	long  nDist  = GetFont().GetSize().Height() / 10L,
		  nSpace = nNum * nDist;

	// ein SmRect mit Baseline und allem drum und dran besorgen
	SmRect::operator = (SmRect(aTmpDev, &rFormat, XubString(xub_Unicode(' ')),
							   GetFont().GetBorderWidth()));

    // und dieses auf die gewuenschte Breite bringen
	SetItalicSpaces(0, 0);
	SetWidth(nSpace);
}
