/**************************************************************
 * 
 * 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_sw.hxx"


#include "hintids.hxx"
#include "flyfrm.hxx"	  // SwFlyInCntFrm
#include "viewopt.hxx"	// SwViewOptions
#include "errhdl.hxx"
#include "txtatr.hxx"  // SwINetFmt
#include <tools/multisel.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/lrspitem.hxx>
#include <txtinet.hxx>
#include <fchrfmt.hxx>
#include <frmatr.hxx>
#include <sfx2/printer.hxx>
#include <fmtftn.hxx>
#include <fmtfld.hxx>
#include <fldbas.hxx>      // SwField
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <pagedesc.hxx> // SwPageDesc
#include <tgrditem.hxx>

// --> FME 2004-06-08 #i12836# enhanced pdf export
#include <EnhancedPDFExportHelper.hxx>
// <--


#include "flyfrms.hxx"
#include "viewsh.hxx"
#include "txtcfg.hxx"
#include "itrpaint.hxx"
#include "txtfrm.hxx"   // pFrm
#include "txtfly.hxx"
#include "swfont.hxx"
#include "txtpaint.hxx"
#include "portab.hxx"   // SwTabPortion::IsFilled
#include "porfly.hxx"	  // SwFlyCntPortion
#include "porfld.hxx"	// SwGrfNumPortion
#include "frmfmt.hxx"	// LRSpace
#include "txatbase.hxx" // SwTxtAttr
#include "charfmt.hxx"  // SwFmtCharFmt
#include "redlnitr.hxx" // SwRedlineItr
#include "porrst.hxx"	// SwArrowPortion
#include "pormulti.hxx"

/*************************************************************************
 *                  IsUnderlineBreak
 *
 * Returns, if we have an underline breaking situation
 * Adding some more conditions here means you also have to change them
 * in SwTxtPainter::CheckSpecialUnderline
 *************************************************************************/
sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
{
    return UNDERLINE_NONE == rFnt.GetUnderline() ||
           rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
           rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
           rPor.IsHolePortion() ||
          ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
           rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
           SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
}

/*************************************************************************
 *					SwTxtPainter::CtorInitTxtPainter()
 *************************************************************************/
void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
{
    CtorInitTxtCursor( pNewFrm, pNewInf );
	pInf = pNewInf;
    SwFont *pMyFnt = GetFnt();
    GetInfo().SetFont( pMyFnt );
#ifdef DBG_UTIL
    if( ALIGN_BASELINE != pMyFnt->GetAlign() )
	{
        ASSERT( ALIGN_BASELINE == pMyFnt->GetAlign(),
				"+SwTxtPainter::CTOR: font alignment revolution" );
        pMyFnt->SetAlign( ALIGN_BASELINE );
	}
#endif
	bPaintDrop = sal_False;
}


/*************************************************************************
 *					  SwTxtPainter::CalcPaintOfst()
 *************************************************************************/
SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
{
	SwLinePortion *pPor = pCurr->GetFirstPortion();
	GetInfo().SetPaintOfst( 0 );
	SwTwips nPaintOfst = rPaint.Left();

	// nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
	// nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
	// const KSHORT nLeftMar = KSHORT(GetLeftMargin());
	// 8310: painten von LineBreaks in leeren Zeilen.
	if( nPaintOfst && pCurr->Width() )
	{
		SwLinePortion *pLast = 0;
		// 7529 und 4757: nicht <= nPaintOfst
		while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
					   < nPaintOfst )
		{
			DBG_LOOP;
			if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
			{
				long nTmp = GetInfo().X() +pPor->Width() +
					pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
				if( nTmp + (pPor->Height()/2) >= nPaintOfst )
					break;
				GetInfo().X( nTmp );
				GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
			}
			else
				pPor->Move( GetInfo() );
			pLast = pPor;
			pPor = pPor->GetPortion();
		}

		// 7529: bei PostIts auch pLast returnen.
		if( pLast && !pLast->Width() &&	pLast->IsPostItsPortion() )
		{
			pPor = pLast;
			GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
		}
	}
	return pPor;
}

/*************************************************************************
 *                    SwTxtPainter::DrawTextLine()
 *
 * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
 * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
 *	  (objektiv schnell, subjektiv langsam).
 * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
 *	  ausgefuehrt (objektiv langsam, subjektiv schnell).
 * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
 * als Default eingestellt.
 *************************************************************************/
void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
								 const sal_Bool bUnderSz )
{
#if OSL_DEBUG_LEVEL > 1
//    sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
//    sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
#endif

    // Adjustierung ggf. nachholen
	GetAdjusted();
    GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
	GetInfo().ResetSpaceIdx();
    GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
    GetInfo().ResetKanaIdx();
	// Die Groesse des Frames
	GetInfo().SetIdx( GetStart() );
	GetInfo().SetPos( GetTopLeft() );

	const sal_Bool bDrawInWindow = GetInfo().OnWin();

	// 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
	const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();

	SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );

	// Optimierung!
	const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
	const SwTwips nTmpLeft = GetInfo().X();
	if( !bEndPor && nTmpLeft >= nMaxRight )
		return;

	// DropCaps!
	// 7538: natuerlich auch auf dem Drucker
	if( !bPaintDrop )
	{
		// 8084: Optimierung, weniger Painten.
		// AMA: Durch 8084 wurde 7538 wiederbelebt!
		// bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
		bPaintDrop = pPor == pCurr->GetFirstPortion()
					 && GetDropLines() >= GetLineNr();
	}

	KSHORT nTmpHeight, nTmpAscent;
	CalcAscentAndHeight( nTmpAscent, nTmpHeight );

	// bClip entscheidet darueber, ob geclippt werden muss.
	// Das Ganze muss vor der Retusche stehen

	sal_Bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
	if( bClip && pPor )
	{
		// Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
		// muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
		// in der folgenden Ausgabeschleife...

		if( GetInfo().GetPos().X() < rPaint.Left() ||
			GetInfo().GetPos().Y() < rPaint.Top() ||
			GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
		{
			bClip = sal_False;
            rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
		}
#if OSL_DEBUG_LEVEL > 1
		static sal_Bool bClipAlways = sal_False;
		if( bClip && bClipAlways )
		{	bClip = sal_False;
			rClip.ChgClip( rPaint );
		}
#endif
	}

	// Alignment:
	sal_Bool bPlus = sal_False;
    OutputDevice* pOut = GetInfo().GetOut();
	Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
	if ( aPnt1.X() < rPaint.Left() )
		aPnt1.X() = rPaint.Left();
	if ( aPnt1.Y() < rPaint.Top() )
		aPnt1.Y() = rPaint.Top();
	Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
				 GetInfo().GetPos().Y() + nTmpHeight );
	if ( aPnt2.X() > rPaint.Right() )
		aPnt2.X() = rPaint.Right();
	if ( aPnt2.Y() > rPaint.Bottom() )
	{
		aPnt2.Y() = rPaint.Bottom();
		bPlus = sal_True;
	}

	const SwRect aLineRect( aPnt1, aPnt2 );

	if( pCurr->IsClipping() )
	{
        rClip.ChgClip( aLineRect, pFrm );
		bClip = sal_False;
	}

	if( !pPor && !bEndPor )
	{
#ifdef DBGTXT
		aDbstream << "PAINTER: done nothing" << endl;
#endif
		return;
	}

	// Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
    // if no special vertical alignment is used,
    // we calculate Y value for the whole line
    GETGRID( GetTxtFrm()->FindPageFrm() )
    const sal_Bool bAdjustBaseLine =
        GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
        ( 0 != pGrid );
    const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
    if ( ! bAdjustBaseLine )
        GetInfo().Y( nLineBaseLine );

	// 7529: PostIts prepainten
	if( GetInfo().OnWin() && pPor && !pPor->Width() )
	{
		SeekAndChg( GetInfo() );

        if( bAdjustBaseLine )
        {
            const SwTwips nOldY = GetInfo().Y();

            GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
                GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
                GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
            ) );

            pPor->PrePaint( GetInfo(), pPor );
            GetInfo().Y( nOldY );
        }
        else
            pPor->PrePaint( GetInfo(), pPor );
	}

	// 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
	if( bEndPor )
		SeekStartAndChg( GetInfo() );

	sal_Bool bRest = pCurr->IsRest();
	sal_Bool bFirst = sal_True;

	SwArrowPortion *pArrow = NULL;
    // Reference portion for the paragraph end portion
    SwLinePortion* pEndTempl = pCurr->GetFirstPortion();

	while( pPor )
	{
		DBG_LOOP;
		sal_Bool bSeeked = sal_True;
		GetInfo().SetLen( pPor->GetLen() );

        const SwTwips nOldY = GetInfo().Y();

        if ( bAdjustBaseLine )
        {
            GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );

            // we store the last portion, because a possible paragraph
            // end character has the same font as this portion
            // (only in special vertical alignment case, otherwise the first
            // portion of the line is used)
            if ( pPor->Width() && pPor->InTxtGrp() )
                pEndTempl = pPor;
        }

		// Ein Sonderfall sind GluePortions, die Blanks ausgeben.

		// 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
		// Portion an, dies wird durch SeekAndChgBefore vermieden:
		if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
			SeekAndChgBefore( GetInfo() );
		else if ( pPor->IsQuoVadisPortion() )
		{
			xub_StrLen nOffset = GetInfo().GetIdx();
			SeekStartAndChg( GetInfo(), sal_True );
			if( GetRedln() && pCurr->HasRedline() )
				GetRedln()->Seek( *pFnt, nOffset, 0 );
		}
		else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
			SeekAndChg( GetInfo() );
		else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
		{
			// Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
			// haben, es sei denn, es gibt Redlining in dem Absatz.
			if( GetRedln() )
				SeekAndChg( GetInfo() );
			else
				SeekAndChgBefore( GetInfo() );
		}
		else
			bSeeked = sal_False;

//		bRest = sal_False;

		// Wenn das Ende der Portion hinausragt, wird geclippt.
		// Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
		// damit die TTF-"f" nicht im Seitenrand haengen...
        if( bClip &&
            GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
        {
            bClip = sal_False;
            rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
		}

		// Portions, die "unter" dem Text liegen wie PostIts
		SwLinePortion *pNext = pPor->GetPortion();
        if( GetInfo().OnWin() && pNext && !pNext->Width() )
		{
			// Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
			// Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
			// durch bSeeked wird Last!=Owner vermieden.
			if ( !bSeeked )
				SeekAndChg( GetInfo() );
            pNext->PrePaint( GetInfo(), pPor );
		}

        // We calculate a separate font for underlining.
        CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
        SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
        if ( pUnderLineFnt )
        {
            const Point aTmpPoint( GetInfo().X(),
                                   bAdjustBaseLine ?
                                   pUnderLineFnt->GetPos().Y() :
                                   nLineBaseLine );
            pUnderLineFnt->SetPos( aTmpPoint );
        }


        // in extended input mode we do not want a common underline font.
        SwUnderlineFont* pOldUnderLineFnt = 0;
        if ( GetRedln() && GetRedln()->ExtOn() )
        {
            pOldUnderLineFnt = GetInfo().GetUnderFnt();
            GetInfo().SetUnderFnt( 0 );
        }

        {
            // --> FME 2004-06-24 #i16816# tagged pdf support
            Por_Info aPorInfo( *pPor, *this );
            SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
            // <--

            if( pPor->IsMultiPortion() )
                PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
            else
                pPor->Paint( GetInfo() );
        }

        // reset underline font
        if ( pOldUnderLineFnt )
            GetInfo().SetUnderFnt( pOldUnderLineFnt );

        // reset (for special vertical alignment)
        GetInfo().Y( nOldY );

        if( GetFnt()->IsURL() && pPor->InTxtGrp() )
			GetInfo().NotifyURL( *pPor );

		bFirst &= !pPor->GetLen();
		if( pNext || !pPor->IsMarginPortion() )
			pPor->Move( GetInfo() );
		if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
			pArrow = (SwArrowPortion*)pPor;

        pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
               // --> FME 2004-06-24 #i16816# tagged pdf support
               ( GetInfo().GetVsh() &&
                 GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
                 pNext && pNext->IsHolePortion() ) ?
               // <--
               pNext :
               0;
	}

    // delete underline font
    delete GetInfo().GetUnderFnt();
    GetInfo().SetUnderFnt( 0 );

    // paint remaining stuff
	if( bDrawInWindow )
	{
        // If special vertical alignment is enabled, GetInfo().Y() is the
        // top of the current line. Therefore is has to be adjusted for
        // the painting of the remaining stuff. We first store the old value.
        const SwTwips nOldY = GetInfo().Y();

        if( !GetNextLine() &&
			GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
			GetInfo().GetOpt().IsParagraph() &&	!GetTxtFrm()->GetFollow() &&
			GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
		{
            const SwTmpEndPortion aEnd( *pEndTempl );
            GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );

            if ( bAdjustBaseLine )
                GetInfo().Y( GetInfo().GetPos().Y()
                           + AdjustBaseLine( *pCurr, &aEnd ) );

            aEnd.Paint( GetInfo() );
            GetInfo().Y( nOldY );
        }
        if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
        {
            const sal_Bool bNextUndersized =
                ( GetTxtFrm()->GetNext() &&
                  0 == GetTxtFrm()->GetNext()->Prt().Height() &&
                  GetTxtFrm()->GetNext()->IsTxtFrm() &&
                  ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;

            if( bUnderSz || bNextUndersized )
			{
                if ( bAdjustBaseLine )
                    GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );

                if( pArrow )
                    GetInfo().DrawRedArrow( *pArrow );

                // GetInfo().Y() must be current baseline.
                SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
                if( ( nDiff > 0 &&
                      ( GetEnd() < GetInfo().GetTxt().Len() ||
                        ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
                    (nDiff >= 0 && bNextUndersized) )

                {
                    SwArrowPortion aArrow( GetInfo() );
                    GetInfo().DrawRedArrow( aArrow );
                }

                GetInfo().Y( nOldY );
			}
		}
	}

    if( pCurr->IsClipping() )
        rClip.ChgClip( rPaint, pFrm );
}

void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
                                          long nAdjustBaseLine )
{
    // Check if common underline should not be continued.
    if ( IsUnderlineBreak( *pPor, *pFnt ) )
    {
        // delete underline font
        delete GetInfo().GetUnderFnt();
        GetInfo().SetUnderFnt( 0 );
        return;
    }

    // If current underline matches the common underline font, we continue
    // to use the common underline font.
	//Bug 120769:Color of underline display wrongly
		Color aAutoCo(COL_AUTO);
    if ( GetInfo().GetUnderFnt() &&
		GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() && 
        GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != aAutoCo )
		return;
	//Bug 120769(End)
    // calculate the new common underline font
    SwFont* pUnderlineFnt = 0;
    Point aCommonBaseLine;

    Range aRange( 0, GetInfo().GetTxt().Len() );
    MultiSelection aUnderMulti( aRange );

    ASSERT( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
            "CheckSpecialUnderline without underlined font" )
    const SwFont* pParaFnt = GetAttrHandler().GetFont();
    if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
        aUnderMulti.SelectAll();

    SwTxtAttr* pTxtAttr;
    if( HasHints() )
	{
        sal_Bool bUnder = sal_False;
		MSHORT nTmp = 0;

        while( nTmp < pHints->GetStartCount() )
		{
			pTxtAttr = pHints->GetStart( nTmp++ );
            sal_Bool bUnderSelect = sal_False;

            const SvxUnderlineItem* pItem =
                    static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));

            if ( pItem )
            {
                bUnder = sal_True;
                bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
            }

            if( bUnder )
			{
				xub_StrLen nSt = *pTxtAttr->GetStart();
				xub_StrLen nEnd = *pTxtAttr->GetEnd();
				if( nEnd > nSt )
				{
					Range aTmp( nSt, nEnd - 1 );
					if( bUnder )
						aUnderMulti.Select( aTmp, bUnderSelect );
				}
				bUnder = sal_False;
			}
		}
    }

    MSHORT i;
    xub_StrLen nIndx = GetInfo().GetIdx();
    long nUnderStart = 0;
    long nUnderEnd = 0;
    MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();

    // find the underline range the current portion is contained in
    for( i = 0; i < nCnt; ++i )
    {
        const Range& rRange = aUnderMulti.GetRange( i );
        if( nUnderEnd == rRange.Min() )
            nUnderEnd = rRange.Max();
        else if( nIndx >= rRange.Min() )
        {
            nUnderStart = rRange.Min();
            nUnderEnd = rRange.Max();
        }
        else
            break;
    }

    // restrict start and end to current line
    if ( GetStart() > nUnderStart )
        nUnderStart = GetStart();

    if ( GetEnd() && GetEnd() <= nUnderEnd )
        nUnderEnd = GetEnd() - 1;


    // check, if underlining is not isolated
    if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
    {
        //
        // here starts the algorithm for calculating the underline font
        //
        SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
        SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
                          rScriptInfo );

        xub_StrLen nTmpIdx = nIndx;
        sal_uLong nSumWidth = 0;
        sal_uLong nSumHeight = 0;
        sal_uLong nBold = 0;
        sal_uInt16 nMaxBaseLineOfst = 0;
        sal_uInt16 nNumberOfPortions = 0;

        while( nTmpIdx <= nUnderEnd && pPor )
        {
            if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
                pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
                pPor->IsHolePortion() ||
                ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
                break;

            aIter.Seek( nTmpIdx );

            if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
                 SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
                break;

            if ( !aIter.GetFnt()->GetEscapement() )
            {
                nSumWidth += pPor->Width();
                const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();

                // If we do not have a common baseline we take the baseline
                // and the font of the lowest portion.
                if ( nAdjustBaseLine )
                {
                    sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
                    if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
                    {
                        nMaxBaseLineOfst = nTmpBaseLineOfst;
                        nSumHeight = nFontHeight;
                    }
                }
                // in horizontal layout we build a weighted sum of the heights
                else
                    nSumHeight += pPor->Width() * nFontHeight;

                if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
                    nBold += pPor->Width();
            }

            ++nNumberOfPortions;

            nTmpIdx = nTmpIdx + pPor->GetLen();
            pPor = pPor->GetPortion();
        }

        // resulting height
        if ( nNumberOfPortions > 1 && nSumWidth )
        {
            const sal_uLong nNewFontHeight = nAdjustBaseLine ?
                                         nSumHeight :
                                         nSumHeight / nSumWidth;

            pUnderlineFnt = new SwFont( *GetInfo().GetFont() );

            // font height
            const sal_uInt8 nActual = pUnderlineFnt->GetActual();
            pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
                                          nNewFontHeight ), nActual );

            // font weight
            if ( 2 * nBold > nSumWidth )
                pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
            else
                pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );

            // common base line
            aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
        }
    }

    // an escaped redlined portion should also have a special underlining
    if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
        GetRedln()->ChkSpecialUnderline() )
        pUnderlineFnt = new SwFont( *pFnt );

    delete GetInfo().GetUnderFnt();

    if ( pUnderlineFnt )
    {
        pUnderlineFnt->SetProportion( 100 );
        pUnderlineFnt->SetEscapement( 0 );
        pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
        pUnderlineFnt->SetOverline( UNDERLINE_NONE );
        const Color aFillColor( COL_TRANSPARENT );
        pUnderlineFnt->SetFillColor( aFillColor );

        GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
                                                     aCommonBaseLine ) );
    }
    else
        // I'm sorry, we do not have a special underlining font for you.
        GetInfo().SetUnderFnt( 0 );
}
