LCOV - code coverage report
Current view: top level - sw/source/core/text - itrform2.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1346 0.0 %
Date: 2014-04-14 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "hintids.hxx"
      21             : 
      22             : #include <boost/scoped_ptr.hpp>
      23             : #include <com/sun/star/i18n/ScriptType.hpp>
      24             : #include <editeng/lspcitem.hxx>
      25             : #include <txtflcnt.hxx>
      26             : #include <txtftn.hxx>
      27             : #include <flyfrms.hxx>
      28             : #include <fmtflcnt.hxx>
      29             : #include <fmtftn.hxx>
      30             : #include <ftninfo.hxx>
      31             : #include <charfmt.hxx>
      32             : #include <editeng/charrotateitem.hxx>
      33             : #include <layfrm.hxx>
      34             : #include <viewsh.hxx>
      35             : #include <viewopt.hxx>
      36             : #include <paratr.hxx>
      37             : #include <itrform2.hxx>
      38             : #include <porrst.hxx>
      39             : #include <portab.hxx>
      40             : #include <porfly.hxx>
      41             : #include <portox.hxx>
      42             : #include <porref.hxx>
      43             : #include <porfld.hxx>
      44             : #include <porftn.hxx>
      45             : #include <porhyph.hxx>
      46             : #include <pordrop.hxx>
      47             : #include <guess.hxx>
      48             : #include <blink.hxx>
      49             : #include <ftnfrm.hxx>
      50             : #include <redlnitr.hxx>
      51             : #include <pagefrm.hxx>
      52             : #include <pagedesc.hxx>
      53             : #include <tgrditem.hxx>
      54             : #include <doc.hxx>
      55             : #include <pormulti.hxx>
      56             : #include <unotools/charclass.hxx>
      57             : #include <xmloff/odffields.hxx>
      58             : 
      59             : #include <vector>
      60             : 
      61             : #include <config_graphite.h>
      62             : 
      63             : #if OSL_DEBUG_LEVEL > 1
      64             : #include <ndtxt.hxx>
      65             : #endif
      66             : 
      67             : using namespace ::com::sun::star;
      68             : 
      69             : namespace {
      70             :     //! Calculates and sets optimal repaint offset for the current line
      71             :     static long lcl_CalcOptRepaint( SwTxtFormatter &rThis,
      72             :                                     SwLineLayout &rCurr,
      73             :                                     const sal_Int32 nOldLineEnd,
      74             :                                     const std::vector<long> &rFlyStarts );
      75             :     //! Determine if we need to build hidden portions
      76             :     static bool lcl_BuildHiddenPortion( const SwTxtSizeInfo& rInf, sal_Int32 &rPos );
      77             : 
      78             :     // Check whether the two font has the same border
      79             :     static bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond);
      80             : }
      81             : 
      82           0 : inline void ClearFly( SwTxtFormatInfo &rInf )
      83             : {
      84           0 :     delete rInf.GetFly();
      85           0 :     rInf.SetFly(0);
      86           0 : }
      87             : 
      88             : /*************************************************************************
      89             :  *                  SwTxtFormatter::CtorInitTxtFormatter()
      90             :  *************************************************************************/
      91             : 
      92           0 : void SwTxtFormatter::CtorInitTxtFormatter( SwTxtFrm *pNewFrm, SwTxtFormatInfo *pNewInf )
      93             : {
      94           0 :     CtorInitTxtPainter( pNewFrm, pNewInf );
      95           0 :     pInf = pNewInf;
      96           0 :     pDropFmt = GetInfo().GetDropFmt();
      97           0 :     pMulti = NULL;
      98             : 
      99           0 :     bOnceMore = false;
     100           0 :     bFlyInCntBase = false;
     101           0 :     bChanges = false;
     102           0 :     bTruncLines = false;
     103           0 :     nCntEndHyph = 0;
     104           0 :     nCntMidHyph = 0;
     105           0 :     nLeftScanIdx = COMPLETE_STRING;
     106           0 :     nRightScanIdx = 0;
     107           0 :     m_nHintEndIndex = 0;
     108           0 :     m_pFirstOfBorderMerge = 0;
     109             : 
     110           0 :     if( nStart > GetInfo().GetTxt().getLength() )
     111             :     {
     112             :         OSL_ENSURE( !this, "+SwTxtFormatter::CTOR: bad offset" );
     113           0 :         nStart = GetInfo().GetTxt().getLength();
     114             :     }
     115             : 
     116           0 : }
     117             : 
     118             : /*************************************************************************
     119             :  *                      SwTxtFormatter::DTOR
     120             :  *************************************************************************/
     121             : 
     122           0 : SwTxtFormatter::~SwTxtFormatter()
     123             : {
     124             :     // Extremly unlikely, but still possible
     125             :     // e.g.: field splits up, widows start to matter
     126           0 :     if( GetInfo().GetRest() )
     127             :     {
     128           0 :         delete GetInfo().GetRest();
     129           0 :         GetInfo().SetRest(0);
     130             :     }
     131           0 : }
     132             : 
     133             : /*************************************************************************
     134             :  *                      SwTxtFormatter::Insert()
     135             :  *************************************************************************/
     136             : 
     137           0 : void SwTxtFormatter::Insert( SwLineLayout *pLay )
     138             : {
     139             :     // Insert BEHIND the current element
     140           0 :     if ( pCurr )
     141             :     {
     142           0 :         pLay->SetNext( pCurr->GetNext() );
     143           0 :         pCurr->SetNext( pLay );
     144             :     }
     145             :     else
     146           0 :         pCurr = pLay;
     147           0 : }
     148             : 
     149             : /*************************************************************************
     150             :  *                  SwTxtFormatter::GetFrmRstHeight()
     151             :  *************************************************************************/
     152             : 
     153           0 : KSHORT SwTxtFormatter::GetFrmRstHeight() const
     154             : {
     155             :     // We want the rest height relative to the page.
     156             :     // If we're in a table, then pFrm->GetUpper() is not the page.
     157             : 
     158             :     // GetFrmRstHeight() is being called with Ftn.
     159             :     // Wrong: const SwFrm *pUpper = pFrm->GetUpper();
     160           0 :     const SwFrm *pPage = (const SwFrm*)pFrm->FindPageFrm();
     161           0 :     const SwTwips nHeight = pPage->Frm().Top()
     162           0 :                           + pPage->Prt().Top()
     163           0 :                           + pPage->Prt().Height() - Y();
     164           0 :     if( 0 > nHeight )
     165           0 :         return pCurr->Height();
     166             :     else
     167           0 :         return KSHORT( nHeight );
     168             : }
     169             : 
     170             : /*************************************************************************
     171             :  *                  SwTxtFormatter::Underflow()
     172             :  *************************************************************************/
     173             : 
     174           0 : SwLinePortion *SwTxtFormatter::Underflow( SwTxtFormatInfo &rInf )
     175             : {
     176             :     // Save values and initialize rInf
     177           0 :     SwLinePortion *pUnderflow = rInf.GetUnderflow();
     178           0 :     if( !pUnderflow )
     179           0 :         return 0;
     180             : 
     181             :     // We format backwards, i.e. attribute changes can happen the next
     182             :     // line again.
     183             :     // Can be seen in 8081.sdw, if you enter text in the first line
     184             : 
     185           0 :     const sal_Int32 nSoftHyphPos = rInf.GetSoftHyphPos();
     186           0 :     const sal_Int32 nUnderScorePos = rInf.GetUnderScorePos();
     187             : 
     188             :     // Save flys and set to 0, or else segmentation fault
     189             :     // Not ClearFly(rInf) !
     190           0 :     SwFlyPortion *pFly = rInf.GetFly();
     191           0 :     rInf.SetFly( 0 );
     192             : 
     193           0 :     FeedInf( rInf );
     194           0 :     rInf.SetLast( pCurr );
     195             :     // pUnderflow does not need to be deleted, because it will drown in the following
     196             :     // Truncate()
     197           0 :     rInf.SetUnderflow(0);
     198           0 :     rInf.SetSoftHyphPos( nSoftHyphPos );
     199           0 :     rInf.SetUnderScorePos( nUnderScorePos );
     200           0 :     rInf.SetPaintOfst( GetLeftMargin() );
     201             : 
     202             :     // We look for the portion with the under-flow position
     203           0 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
     204           0 :     if( pPor != pUnderflow )
     205             :     {
     206             :         // pPrev will be the last portion before pUnderflow,
     207             :         // which still has a real width.
     208             :         // Exception: SoftHyphPortions must not be forgotten, of course!
     209             :         // Although they don't have a width.
     210           0 :         SwLinePortion *pTmpPrev = pPor;
     211           0 :         while( pPor && pPor != pUnderflow )
     212             :         {
     213           0 :             if( !pPor->IsKernPortion() &&
     214           0 :                 ( pPor->Width() || pPor->IsSoftHyphPortion() ) )
     215             :             {
     216           0 :                 while( pTmpPrev != pPor )
     217             :                 {
     218           0 :                     pTmpPrev->Move( rInf );
     219           0 :                     rInf.SetLast( pTmpPrev );
     220           0 :                     pTmpPrev = pTmpPrev->GetPortion();
     221             :                     OSL_ENSURE( pTmpPrev, "Underflow: Loosing control!" );
     222             :                 };
     223             :             }
     224           0 :             pPor = pPor->GetPortion();
     225             :         }
     226           0 :         pPor = pTmpPrev;
     227           0 :         if( pPor && // Flies + Initialen werden nicht beim Underflow mitgenommen
     228           0 :             ( pPor->IsFlyPortion() || pPor->IsDropPortion() ||
     229           0 :               pPor->IsFlyCntPortion() ) )
     230             :         {
     231           0 :             pPor->Move( rInf );
     232           0 :             rInf.SetLast( pPor );
     233           0 :             rInf.SetStopUnderflow( true );
     234           0 :             pPor = pUnderflow;
     235             :         }
     236             :     }
     237             : 
     238             :     // What? The under-flow portion is not in the portion chain?
     239             :     OSL_ENSURE( pPor, "SwTxtFormatter::Underflow: overflow but underflow" );
     240             : 
     241             :     // OD 2004-05-26 #i29529# - correction: no delete of footnotes
     242             : //    if( rInf.IsFtnInside() && pPor && !rInf.IsQuick() )
     243             : //    {
     244             : //        SwLinePortion *pTmp = pPor->GetPortion();
     245             : //        while( pTmp )
     246             : //        {
     247             : //            if( pTmp->IsFtnPortion() )
     248             : //                ((SwFtnPortion*)pTmp)->ClearFtn();
     249             : //            pTmp = pTmp->GetPortion();
     250             : //        }
     251             : //    }
     252             : 
     253             :     /*--------------------------------------------------
     254             :      * Snapshot
     255             :      * --------------------------------------------------*/
     256           0 :     if ( pPor==rInf.GetLast() )
     257             :     {
     258             :         // We end up here, if the portion triggering the under-flow
     259             :         // spans over the whole line. E.g. if a word spans across
     260             :         // multiple lines and flows into a fly in the second line.
     261           0 :         rInf.SetFly( pFly );
     262           0 :         pPor->Truncate();
     263           0 :         return pPor; // Is that enough?
     264             :     }
     265             :     /*---------------------------------------------------
     266             :      * End the snapshot
     267             :      * --------------------------------------------------*/
     268             : 
     269             :     // X + Width == 0 with SoftHyph > Line?!
     270           0 :     if( !pPor || !(rInf.X() + pPor->Width()) )
     271             :     {
     272           0 :         delete pFly;
     273           0 :         return 0;
     274             :     }
     275             : 
     276             :     // Preparing for Format()
     277             :     // We need to chip off the chain behind pLast, because we Insert after the Format()
     278           0 :     SeekAndChg( rInf );
     279             : 
     280             :     // line width is adjusted, so that pPor does not fit to current
     281             :     // line anymore
     282           0 :     rInf.Width( (sal_uInt16)(rInf.X() + (pPor->Width() ? pPor->Width() - 1 : 0)) );
     283           0 :     rInf.SetLen( pPor->GetLen() );
     284           0 :     rInf.SetFull( false );
     285           0 :     if( pFly )
     286             :     {
     287             :         // We need to recalculate the FlyPortion due to the following reason:
     288             :         // If the base line is lowered by a big font in the middle of the line,
     289             :         // causing overlapping with a fly, the FlyPortion has a wrong size/fixed
     290             :         // size.
     291           0 :         rInf.SetFly( pFly );
     292           0 :         CalcFlyWidth( rInf );
     293             :     }
     294           0 :     rInf.GetLast()->SetPortion(0);
     295             : 
     296             :     // The SwLineLayout is an exception to this, which splits at the first
     297             :     // portion change.
     298             :     // Here inly the other way around:
     299           0 :     if( rInf.GetLast() == pCurr )
     300             :     {
     301           0 :         if( pPor->InTxtGrp() && !pPor->InExpGrp() )
     302             :         {
     303           0 :             MSHORT nOldWhich = pCurr->GetWhichPor();
     304           0 :             *(SwLinePortion*)pCurr = *pPor;
     305           0 :             pCurr->SetPortion( pPor->GetPortion() );
     306           0 :             pCurr->SetWhichPor( nOldWhich );
     307           0 :             pPor->SetPortion( 0 );
     308           0 :             delete pPor;
     309           0 :             pPor = pCurr;
     310             :         }
     311             :     }
     312           0 :     pPor->Truncate();
     313           0 :     SwLinePortion *const pRest( rInf.GetRest() );
     314           0 :     if (pRest && pRest->InFldGrp() &&
     315           0 :         static_cast<SwFldPortion*>(pRest)->IsNoLength())
     316             :     {
     317             :         // HACK: decrement again, so we pick up the suffix in next line!
     318           0 :         --m_nHintEndIndex;
     319             :     }
     320           0 :     delete pRest;
     321           0 :     rInf.SetRest(0);
     322           0 :     return pPor;
     323             : }
     324             : 
     325             : /*************************************************************************
     326             :  *                      SwTxtFormatter::InsertPortion()
     327             :  *************************************************************************/
     328             : 
     329           0 : void SwTxtFormatter::InsertPortion( SwTxtFormatInfo &rInf,
     330             :                                     SwLinePortion *pPor ) const
     331             : {
     332             :     // The new portion is inserted, but everything's different for
     333             :     // LineLayout ...
     334           0 :     if( pPor == pCurr )
     335             :     {
     336           0 :         if ( pCurr->GetPortion() )
     337             :         {
     338           0 :             pPor = pCurr->GetPortion();
     339             :         }
     340             : 
     341             :         // #i112181#
     342           0 :         rInf.SetOtherThanFtnInside( rInf.IsOtherThanFtnInside() || !pPor->IsFtnPortion() );
     343             :     }
     344             :     else
     345             :     {
     346           0 :         SwLinePortion *pLast = rInf.GetLast();
     347           0 :         if( pLast->GetPortion() )
     348             :         {
     349           0 :             while( pLast->GetPortion() )
     350           0 :                 pLast = pLast->GetPortion();
     351           0 :             rInf.SetLast( pLast );
     352             :         }
     353           0 :         pLast->Insert( pPor );
     354             : 
     355           0 :         rInf.SetOtherThanFtnInside( rInf.IsOtherThanFtnInside() || !pPor->IsFtnPortion() );
     356             : 
     357             :         // Adjust maxima
     358           0 :         if( pCurr->Height() < pPor->Height() )
     359           0 :             pCurr->Height( pPor->Height() );
     360           0 :         if( pCurr->GetAscent() < pPor->GetAscent() )
     361           0 :             pCurr->SetAscent( pPor->GetAscent() );
     362             :     }
     363             : 
     364             :     // Sometimes chains are constructed (e.g. by hyphenate)
     365           0 :     rInf.SetLast( pPor );
     366           0 :     while( pPor )
     367             :     {
     368           0 :         pPor->Move( rInf );
     369           0 :         rInf.SetLast( pPor );
     370           0 :         pPor = pPor->GetPortion();
     371             :     }
     372           0 : }
     373             : 
     374             : /*************************************************************************
     375             :  *                      SwTxtFormatter::BuildPortion()
     376             :  *************************************************************************/
     377             : 
     378           0 : void SwTxtFormatter::BuildPortions( SwTxtFormatInfo &rInf )
     379             : {
     380             :     OSL_ENSURE( rInf.GetTxt().getLength() < COMPLETE_STRING,
     381             :             "SwTxtFormatter::BuildPortions: bad text length in info" );
     382             : 
     383           0 :     rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
     384             : 
     385             :     // First NewTxtPortion() decides whether pCurr ends up in pPor.
     386             :     // We need to make sure that the font is being set in any case.
     387             :     // This is done automatically in CalcAscent.
     388           0 :     rInf.SetLast( pCurr );
     389           0 :     rInf.ForcedLeftMargin( 0 );
     390             : 
     391             :     OSL_ENSURE( pCurr->FindLastPortion() == pCurr, "pLast supposed to equal pCurr" );
     392             : 
     393           0 :     if( !pCurr->GetAscent() && !pCurr->Height() )
     394           0 :         CalcAscent( rInf, pCurr );
     395             : 
     396           0 :     SeekAndChg( rInf );
     397             : 
     398             :     // Width() is shortened in CalcFlyWidth if we have a FlyPortion
     399             :     OSL_ENSURE( !rInf.X() || pMulti, "SwTxtFormatter::BuildPortion X=0?" );
     400           0 :     CalcFlyWidth( rInf );
     401           0 :     SwFlyPortion *pFly = rInf.GetFly();
     402           0 :     if( pFly )
     403             :     {
     404           0 :         if ( 0 < pFly->Fix() )
     405           0 :             ClearFly( rInf );
     406             :         else
     407           0 :             rInf.SetFull(true);
     408             :     }
     409             : 
     410           0 :     SwLinePortion *pPor = NewPortion( rInf );
     411             : 
     412             :     // Asian grid stuff
     413           0 :     SwTextGridItem const*const pGrid(GetGridItem(pFrm->FindPageFrm()));
     414           0 :     const bool bHasGrid = pGrid && rInf.SnapToGrid() &&
     415           0 :                               GRID_LINES_CHARS == pGrid->GetGridType();
     416             : 
     417           0 :     const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
     418           0 :     const sal_uInt16 nGridWidth = (bHasGrid) ? GetGridWidth(*pGrid, *pDoc) : 0;
     419             : 
     420             :     // used for grid mode only:
     421             :     // the pointer is stored, because after formatting of non-asian text,
     422             :     // the width of the kerning portion has to be adjusted
     423           0 :     SwKernPortion* pGridKernPortion = 0;
     424             : 
     425           0 :     bool bFull = false;
     426           0 :     SwTwips nUnderLineStart = 0;
     427           0 :     rInf.Y( Y() );
     428             : 
     429           0 :     while( pPor && !rInf.IsStop() )
     430             :     {
     431             :         OSL_ENSURE( rInf.GetLen() < COMPLETE_STRING &&
     432             :                 rInf.GetIdx() <= rInf.GetTxt().getLength(),
     433             :                 "SwTxtFormatter::BuildPortions: bad length in info" );
     434             : 
     435             :         // We have to check the script for fields in order to set the
     436             :         // correct nActual value for the font.
     437           0 :         if( pPor->InFldGrp() )
     438           0 :             ((SwFldPortion*)pPor)->CheckScript( rInf );
     439             : 
     440           0 :         if( ! bHasGrid && rInf.HasScriptSpace() &&
     441           0 :             rInf.GetLast() && rInf.GetLast()->InTxtGrp() &&
     442           0 :             rInf.GetLast()->Width() && !rInf.GetLast()->InNumberGrp() )
     443             :         {
     444           0 :             sal_uInt8 nNxtActual = rInf.GetFont()->GetActual();
     445           0 :             sal_uInt8 nLstActual = nNxtActual;
     446           0 :             sal_uInt16 nLstHeight = (sal_uInt16)rInf.GetFont()->GetHeight();
     447           0 :             bool bAllowBefore = false;
     448           0 :             bool bAllowBehind = false;
     449           0 :             const CharClass& rCC = GetAppCharClass();
     450             : 
     451             :             // are there any punctuation characters on both sides
     452             :             // of the kerning portion?
     453           0 :             if ( pPor->InFldGrp() )
     454             :             {
     455           0 :                 OUString aAltTxt;
     456           0 :                 if ( ((SwFldPortion*)pPor)->GetExpTxt( rInf, aAltTxt ) &&
     457           0 :                         !aAltTxt.isEmpty() )
     458             :                 {
     459           0 :                     bAllowBehind = rCC.isLetterNumeric( aAltTxt, 0 );
     460             : 
     461           0 :                     const SwFont* pTmpFnt = ((SwFldPortion*)pPor)->GetFont();
     462           0 :                     if ( pTmpFnt )
     463           0 :                         nNxtActual = pTmpFnt->GetActual();
     464           0 :                 }
     465             :             }
     466             :             else
     467             :             {
     468           0 :                 const OUString& rTxt = rInf.GetTxt();
     469           0 :                 sal_Int32 nIdx = rInf.GetIdx();
     470           0 :                 bAllowBehind = nIdx < rTxt.getLength() ? rCC.isLetterNumeric(rTxt, nIdx) : false;
     471             :             }
     472             : 
     473           0 :             const SwLinePortion* pLast = rInf.GetLast();
     474           0 :             if ( bAllowBehind && pLast )
     475             :             {
     476           0 :                 if ( pLast->InFldGrp() )
     477             :                 {
     478           0 :                     OUString aAltTxt;
     479           0 :                     if ( ((SwFldPortion*)pLast)->GetExpTxt( rInf, aAltTxt ) &&
     480           0 :                          !aAltTxt.isEmpty() )
     481             :                     {
     482           0 :                         bAllowBefore = rCC.isLetterNumeric( aAltTxt, aAltTxt.getLength() - 1 );
     483             : 
     484           0 :                         const SwFont* pTmpFnt = ((SwFldPortion*)pLast)->GetFont();
     485           0 :                         if ( pTmpFnt )
     486             :                         {
     487           0 :                             nLstActual = pTmpFnt->GetActual();
     488           0 :                             nLstHeight = (sal_uInt16)pTmpFnt->GetHeight();
     489             :                         }
     490           0 :                     }
     491             :                 }
     492           0 :                 else if ( rInf.GetIdx() )
     493             :                 {
     494           0 :                     bAllowBefore = rCC.isLetterNumeric( rInf.GetTxt(), rInf.GetIdx() - 1 );
     495             :                     // Note: ScriptType returns values in [1,4]
     496           0 :                     if ( bAllowBefore )
     497           0 :                         nLstActual = pScriptInfo->ScriptType( rInf.GetIdx() - 1 ) - 1;
     498             :                 }
     499             : 
     500           0 :                 nLstHeight /= 5;
     501             :                 // does the kerning portion still fit into the line?
     502           0 :                 if( bAllowBefore && ( nLstActual != nNxtActual ) &&
     503           0 :                     nLstHeight && rInf.X() + nLstHeight <= rInf.Width() )
     504             :                 {
     505             :                     SwKernPortion* pKrn =
     506             :                         new SwKernPortion( *rInf.GetLast(), nLstHeight,
     507           0 :                                            pLast->InFldGrp() && pPor->InFldGrp() );
     508           0 :                     rInf.GetLast()->SetPortion( NULL );
     509           0 :                     InsertPortion( rInf, pKrn );
     510             :                 }
     511             :             }
     512             :         }
     513           0 :         else if ( bHasGrid && ! pGridKernPortion && ! pMulti )
     514             :         {
     515             :             // insert a grid kerning portion
     516           0 :             if ( ! pGridKernPortion )
     517           0 :                 pGridKernPortion = pPor->IsKernPortion() ?
     518             :                                    (SwKernPortion*)pPor :
     519           0 :                                    new SwKernPortion( *pCurr );
     520             : 
     521             :             // if we have a new GridKernPortion, we initially calculate
     522             :             // its size so that its ends on the grid
     523           0 :             const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
     524           0 :             const SwLayoutFrm* pBody = pPageFrm->FindBodyCont();
     525           0 :             SWRECTFN( pPageFrm )
     526             : 
     527             :             const long nGridOrigin = pBody ?
     528           0 :                                     (pBody->*fnRect->fnGetPrtLeft)() :
     529           0 :                                     (pPageFrm->*fnRect->fnGetPrtLeft)();
     530             : 
     531           0 :             SwTwips nStartX = rInf.X() + GetLeftMargin();
     532           0 :             if ( bVert )
     533             :             {
     534           0 :                 Point aPoint( nStartX, 0 );
     535           0 :                 pFrm->SwitchHorizontalToVertical( aPoint );
     536           0 :                 nStartX = aPoint.Y();
     537             :             }
     538             : 
     539           0 :             const SwTwips nOfst = nStartX - nGridOrigin;
     540           0 :             if ( nOfst )
     541             :             {
     542             :                 const sal_uLong i = ( nOfst > 0 ) ?
     543           0 :                                 ( ( nOfst - 1 ) / nGridWidth + 1 ) :
     544           0 :                                 0;
     545           0 :                 const SwTwips nKernWidth = i * nGridWidth - nOfst;
     546           0 :                 const SwTwips nRestWidth = rInf.Width() - rInf.X();
     547             : 
     548           0 :                 if ( nKernWidth <= nRestWidth )
     549           0 :                     pGridKernPortion->Width( (sal_uInt16)nKernWidth );
     550             :             }
     551             : 
     552           0 :             if ( pGridKernPortion != pPor )
     553           0 :                 InsertPortion( rInf, pGridKernPortion );
     554             :         }
     555             : 
     556           0 :         if( pPor->IsDropPortion() )
     557           0 :             MergeCharacterBorder(*static_cast<SwDropPortion*>(pPor));
     558             : 
     559             :         // the multi-portion has it's own format function
     560           0 :         if( pPor->IsMultiPortion() && ( !pMulti || pMulti->IsBidi() ) )
     561           0 :             bFull = BuildMultiPortion( rInf, *((SwMultiPortion*)pPor) );
     562             :         else
     563           0 :             bFull = pPor->Format( rInf );
     564             : 
     565           0 :         if( rInf.IsRuby() && !rInf.GetRest() )
     566           0 :             bFull = true;
     567             : 
     568             :         // if we are underlined, we store the beginning of this underlined
     569             :         // segment for repaint optimization
     570           0 :         if ( UNDERLINE_NONE != pFnt->GetUnderline() && ! nUnderLineStart )
     571           0 :             nUnderLineStart = GetLeftMargin() + rInf.X();
     572             : 
     573           0 :         if ( pPor->IsFlyPortion() )
     574           0 :             pCurr->SetFly( true );
     575             :         // some special cases, where we have to take care for the repaint
     576             :         // offset:
     577             :         // 1. Underlined portions due to special underline feature
     578             :         // 2. Right Tab
     579             :         // 3. BidiPortions
     580             :         // 4. other Multiportions
     581             :         // 5. DropCaps
     582             :         // 6. Grid Mode
     583           0 :         else if ( ( ! rInf.GetPaintOfst() || nUnderLineStart < rInf.GetPaintOfst() ) &&
     584             :                   // 1. Underlined portions
     585           0 :                   nUnderLineStart &&
     586             :                      // reformat is at end of an underlined portion and next portion
     587             :                      // is not underlined
     588           0 :                   ( ( rInf.GetReformatStart() == rInf.GetIdx() &&
     589           0 :                       UNDERLINE_NONE == pFnt->GetUnderline()
     590           0 :                     ) ||
     591             :                      // reformat is inside portion and portion is underlined
     592           0 :                     ( rInf.GetReformatStart() >= rInf.GetIdx() &&
     593           0 :                       rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() &&
     594           0 :                       UNDERLINE_NONE != pFnt->GetUnderline() ) ) )
     595           0 :             rInf.SetPaintOfst( nUnderLineStart );
     596           0 :         else if (  ! rInf.GetPaintOfst() &&
     597             :                    // 2. Right Tab
     598           0 :                    ( ( pPor->InTabGrp() && !pPor->IsTabLeftPortion() ) ||
     599             :                    // 3. BidiPortions
     600           0 :                      ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi() ) ||
     601             :                    // 4. Multi Portion and 5. Drop Caps
     602           0 :                      ( ( pPor->IsDropPortion() || pPor->IsMultiPortion() ) &&
     603           0 :                        rInf.GetReformatStart() >= rInf.GetIdx() &&
     604           0 :                        rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() )
     605             :                    // 6. Grid Mode
     606           0 :                      || ( bHasGrid && SW_CJK != pFnt->GetActual() )
     607             :                    )
     608             :                 )
     609             :             // we store the beginning of the critical portion as our
     610             :             // paint offset
     611           0 :             rInf.SetPaintOfst( GetLeftMargin() + rInf.X() );
     612             : 
     613             :         // under one of these conditions we are allowed to delete the
     614             :         // start of the underline portion
     615           0 :         if ( IsUnderlineBreak( *pPor, *pFnt ) )
     616           0 :             nUnderLineStart = 0;
     617             : 
     618           0 :         if( pPor->IsFlyCntPortion() || ( pPor->IsMultiPortion() &&
     619           0 :             ((SwMultiPortion*)pPor)->HasFlyInCntnt() ) )
     620           0 :             SetFlyInCntBase();
     621             :         // bUnderflow needs to be reset or we wrap again at the next softhyphen
     622           0 :         if ( !bFull )
     623             :         {
     624           0 :             rInf.ClrUnderflow();
     625           0 :             if( ! bHasGrid && rInf.HasScriptSpace() && pPor->InTxtGrp() &&
     626           0 :                 pPor->GetLen() && !pPor->InFldGrp() )
     627             :             {
     628             :                 // The distance between two different scripts is set
     629             :                 // to 20% of the fontheight.
     630           0 :                 sal_Int32 nTmp = rInf.GetIdx() + pPor->GetLen();
     631           0 :                 if( nTmp == pScriptInfo->NextScriptChg( nTmp - 1 ) &&
     632           0 :                     nTmp != rInf.GetTxt().getLength() )
     633             :                 {
     634           0 :                     sal_uInt16 nDist = (sal_uInt16)(rInf.GetFont()->GetHeight()/5);
     635             : 
     636           0 :                     if( nDist )
     637             :                     {
     638             :                         // we do not want a kerning portion if any end
     639             :                         // would be a punctuation character
     640           0 :                         const CharClass& rCC = GetAppCharClass();
     641           0 :                         if ( rCC.isLetterNumeric( rInf.GetTxt(), nTmp - 1 ) &&
     642           0 :                              rCC.isLetterNumeric( rInf.GetTxt(), nTmp ) )
     643             :                         {
     644             :                             // does the kerning portion still fit into the line?
     645           0 :                             if ( rInf.X() + pPor->Width() + nDist <= rInf.Width() )
     646           0 :                                 new SwKernPortion( *pPor, nDist );
     647             :                             else
     648           0 :                                 bFull = true;
     649             :                         }
     650             :                     }
     651             :                 }
     652             :             }
     653             :         }
     654             : 
     655           0 :         if ( bHasGrid && pPor != pGridKernPortion && ! pMulti )
     656             :         {
     657           0 :             sal_Int32 nTmp = rInf.GetIdx() + pPor->GetLen();
     658           0 :             const SwTwips nRestWidth = rInf.Width() - rInf.X() - pPor->Width();
     659             : 
     660           0 :             const sal_uInt8 nCurrScript = pFnt->GetActual(); // pScriptInfo->ScriptType( rInf.GetIdx() );
     661           0 :             const sal_uInt8 nNextScript = nTmp >= rInf.GetTxt().getLength() ?
     662             :                                      SW_CJK :
     663           0 :                                      SwScriptInfo::WhichFont( nTmp, 0, pScriptInfo );
     664             : 
     665             :             // snap non-asian text to grid if next portion is ASIAN or
     666             :             // there are no more portions in this line
     667             :             // be careful when handling an underflow event: the gridkernportion
     668             :             // could have been deleted
     669           0 :             if ( nRestWidth > 0 && SW_CJK != nCurrScript &&
     670           0 :                 ! rInf.IsUnderflow() && ( bFull || SW_CJK == nNextScript ) )
     671             :             {
     672             :                 OSL_ENSURE( pGridKernPortion, "No GridKernPortion available" );
     673             : 
     674             :                 // calculate size
     675           0 :                 SwLinePortion* pTmpPor = pGridKernPortion->GetPortion();
     676           0 :                 sal_uInt16 nSumWidth = pPor->Width();
     677           0 :                 while ( pTmpPor )
     678             :                 {
     679           0 :                     nSumWidth = nSumWidth + pTmpPor->Width();
     680           0 :                     pTmpPor = pTmpPor->GetPortion();
     681             :                 }
     682             : 
     683             :                 const sal_uInt16 i = nSumWidth ?
     684           0 :                                  ( nSumWidth - 1 ) / nGridWidth + 1 :
     685           0 :                                  0;
     686           0 :                 const SwTwips nTmpWidth = i * nGridWidth;
     687           0 :                 const SwTwips nKernWidth = std::min( (SwTwips)(nTmpWidth - nSumWidth),
     688           0 :                                                 nRestWidth );
     689           0 :                 const sal_uInt16 nKernWidth_1 = (sal_uInt16)(nKernWidth / 2);
     690             : 
     691             :                 OSL_ENSURE( nKernWidth <= nRestWidth,
     692             :                         "Not enough space left for adjusting non-asian text in grid mode" );
     693             : 
     694           0 :                 pGridKernPortion->Width( pGridKernPortion->Width() + nKernWidth_1 );
     695           0 :                 rInf.X( rInf.X() + nKernWidth_1 );
     696             : 
     697           0 :                 if ( ! bFull )
     698             :                     new SwKernPortion( *pPor, (short)(nKernWidth - nKernWidth_1),
     699           0 :                                        false, true );
     700             : 
     701           0 :                 pGridKernPortion = 0;
     702             :             }
     703           0 :             else if ( pPor->IsMultiPortion() || pPor->InFixMargGrp() ||
     704           0 :                       pPor->IsFlyCntPortion() || pPor->InNumberGrp() ||
     705           0 :                       pPor->InFldGrp() || nCurrScript != nNextScript )
     706             :                 // next portion should snap to grid
     707           0 :                 pGridKernPortion = 0;
     708             :         }
     709             : 
     710           0 :         rInf.SetFull( bFull );
     711             : 
     712           0 :         if( !pPor->IsDropPortion() )
     713           0 :             MergeCharacterBorder(*pPor, rInf);
     714             : 
     715             :         // Restportions from fields with multiple lines don't yet have the right ascent
     716           0 :         if ( !pPor->GetLen() && !pPor->IsFlyPortion()
     717           0 :             && !pPor->IsGrfNumPortion() && ! pPor->InNumberGrp()
     718           0 :             && !pPor->IsMultiPortion() )
     719           0 :             CalcAscent( rInf, pPor );
     720             : 
     721           0 :         InsertPortion( rInf, pPor );
     722           0 :         pPor = NewPortion( rInf );
     723             :     }
     724             : 
     725           0 :     if( !rInf.IsStop() )
     726             :     {
     727             :         // The last right centered, decimal tab
     728           0 :         SwTabPortion *pLastTab = rInf.GetLastTab();
     729           0 :         if( pLastTab )
     730           0 :             pLastTab->FormatEOL( rInf );
     731           0 :         else if( rInf.GetLast() && rInf.LastKernPortion() )
     732           0 :             rInf.GetLast()->FormatEOL( rInf );
     733             :     }
     734           0 :     if( pCurr->GetPortion() && pCurr->GetPortion()->InNumberGrp()
     735           0 :         && ((SwNumberPortion*)pCurr->GetPortion())->IsHide() )
     736           0 :         rInf.SetNumDone( false );
     737             : 
     738             :     // Delete fly in any case
     739           0 :     ClearFly( rInf );
     740             : 
     741             :     // Reinit the tab overflow flag after the line
     742           0 :     rInf.SetTabOverflow( false );
     743           0 : }
     744             : 
     745             : /*************************************************************************
     746             :  *                 SwTxtFormatter::CalcAdjustLine()
     747             :  *************************************************************************/
     748             : 
     749           0 : void SwTxtFormatter::CalcAdjustLine( SwLineLayout *pCurrent )
     750             : {
     751           0 :     if( SVX_ADJUST_LEFT != GetAdjust() && !pMulti)
     752             :     {
     753           0 :         pCurrent->SetFormatAdj(true);
     754           0 :         if( IsFlyInCntBase() )
     755             :         {
     756           0 :             CalcAdjLine( pCurrent );
     757             :             // For e.g. centered fly we need to switch the RefPoint
     758             :             // That's why bAlways = true
     759           0 :             UpdatePos( pCurrent, GetTopLeft(), GetStart(), true );
     760             :         }
     761             :     }
     762           0 : }
     763             : 
     764             : /*************************************************************************
     765             :  *                      SwTxtFormatter::CalcAscent()
     766             :  *************************************************************************/
     767             : 
     768           0 : void SwTxtFormatter::CalcAscent( SwTxtFormatInfo &rInf, SwLinePortion *pPor )
     769             : {
     770           0 :     bool bCalc = false;
     771           0 :     if ( pPor->InFldGrp() && ((SwFldPortion*)pPor)->GetFont() )
     772             :     {
     773             :         // Numbering + InterNetFlds can keep an own font, then their size is
     774             :         // independent from hard attribute values
     775           0 :         SwFont* pFldFnt = ((SwFldPortion*)pPor)->pFnt;
     776           0 :         SwFontSave aSave( rInf, pFldFnt );
     777           0 :         pPor->Height( rInf.GetTxtHeight() );
     778           0 :         pPor->SetAscent( rInf.GetAscent() );
     779           0 :         bCalc = true;
     780             :     }
     781             :     // #i89179#
     782             :     // tab portion representing the list tab of a list label gets the
     783             :     // same height and ascent as the corresponding number portion
     784           0 :     else if ( pPor->InTabGrp() && pPor->GetLen() == 0 &&
     785           0 :               rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
     786           0 :               static_cast<const SwNumberPortion*>(rInf.GetLast())->HasFont() )
     787             :     {
     788           0 :         const SwLinePortion* pLast = rInf.GetLast();
     789           0 :         pPor->Height( pLast->Height() );
     790           0 :         pPor->SetAscent( pLast->GetAscent() );
     791             :     }
     792             :     else
     793             :     {
     794           0 :         const SwLinePortion *pLast = rInf.GetLast();
     795           0 :         bool bChg = false;
     796             : 
     797             :         // In empty lines the attributes are switched on via SeekStart
     798           0 :         const bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
     799           0 :         if ( pPor->IsQuoVadisPortion() )
     800           0 :             bChg = SeekStartAndChg( rInf, true );
     801             :         else
     802             :         {
     803           0 :             if( bFirstPor )
     804             :             {
     805           0 :                 if( !rInf.GetTxt().isEmpty() )
     806             :                 {
     807           0 :                     if ( pPor->GetLen() || !rInf.GetIdx()
     808           0 :                          || ( pCurr != pLast && !pLast->IsFlyPortion() )
     809           0 :                          || !pCurr->IsRest() ) // instead of !rInf.GetRest()
     810           0 :                         bChg = SeekAndChg( rInf );
     811             :                     else
     812           0 :                         bChg = SeekAndChgBefore( rInf );
     813             :                 }
     814           0 :                 else if ( pMulti )
     815             :                     // do not open attributes starting at 0 in empty multi
     816             :                     // portions (rotated numbering followed by a footnote
     817             :                     // can cause trouble, because the footnote attribute
     818             :                     // starts at 0, but if we open it, the attribute handler
     819             :                     // cannot handle it.
     820           0 :                     bChg = false;
     821             :                 else
     822           0 :                     bChg = SeekStartAndChg( rInf );
     823             :             }
     824             :             else
     825           0 :                 bChg = SeekAndChg( rInf );
     826             :         }
     827           0 :         if( bChg || bFirstPor || !pPor->GetAscent()
     828           0 :             || !rInf.GetLast()->InTxtGrp() )
     829             :         {
     830           0 :             pPor->SetAscent( rInf.GetAscent()  );
     831           0 :             pPor->Height( rInf.GetTxtHeight() );
     832           0 :             bCalc = true;
     833             :         }
     834             :         else
     835             :         {
     836           0 :             pPor->Height( pLast->Height() );
     837           0 :             pPor->SetAscent( pLast->GetAscent() );
     838             :         }
     839             :     }
     840             : 
     841           0 :     if( pPor->InTxtGrp() && bCalc )
     842             :     {
     843           0 :         pPor->SetAscent(pPor->GetAscent() +
     844           0 :             rInf.GetFont()->GetTopBorderSpace());
     845           0 :         pPor->Height(pPor->Height() +
     846           0 :             rInf.GetFont()->GetTopBorderSpace() +
     847           0 :             rInf.GetFont()->GetBottomBorderSpace() );
     848             :     }
     849           0 : }
     850             : 
     851             : /*************************************************************************
     852             :  *                      class SwMetaPortion
     853             :  *************************************************************************/
     854             : 
     855           0 : class SwMetaPortion : public SwTxtPortion
     856             : {
     857             : public:
     858           0 :     inline  SwMetaPortion() { SetWhichPor( POR_META ); }
     859             :     virtual void Paint( const SwTxtPaintInfo &rInf ) const SAL_OVERRIDE;
     860             : //    OUTPUT_OPERATOR
     861             : };
     862             : 
     863             : /*************************************************************************
     864             :  *               virtual SwMetaPortion::Paint()
     865             :  *************************************************************************/
     866             : 
     867           0 : void SwMetaPortion::Paint( const SwTxtPaintInfo &rInf ) const
     868             : {
     869           0 :     if ( Width() )
     870             :     {
     871           0 :         rInf.DrawViewOpt( *this, POR_META );
     872           0 :         SwTxtPortion::Paint( rInf );
     873             :     }
     874           0 : }
     875             : 
     876             : namespace sw { namespace mark {
     877           0 :     OUString ExpandFieldmark(IFieldmark* pBM)
     878             :     {
     879           0 :         const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
     880           0 :         sal_Int32 nCurrentIdx = 0;
     881           0 :         const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(OUString(ODF_FORMDROPDOWN_RESULT));
     882           0 :         if(pResult != pParameters->end())
     883           0 :             pResult->second >>= nCurrentIdx;
     884             : 
     885           0 :         const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(OUString(ODF_FORMDROPDOWN_LISTENTRY));
     886           0 :         if (pListEntries != pParameters->end())
     887             :         {
     888           0 :             uno::Sequence< OUString > vListEntries;
     889           0 :             pListEntries->second >>= vListEntries;
     890           0 :             if (nCurrentIdx < vListEntries.getLength())
     891           0 :                 return vListEntries[nCurrentIdx];
     892             :         }
     893           0 :         return OUString();
     894             :     }
     895             : } }
     896             : 
     897             : /*************************************************************************
     898             :  *                      SwTxtFormatter::WhichTxtPor()
     899             :  *************************************************************************/
     900           0 : SwTxtPortion *SwTxtFormatter::WhichTxtPor( SwTxtFormatInfo &rInf ) const
     901             : {
     902           0 :     SwTxtPortion *pPor = 0;
     903           0 :     if( GetFnt()->IsTox() )
     904             :     {
     905           0 :         pPor = new SwToxPortion;
     906             :     }
     907           0 :     else if ( GetFnt()->IsInputField() )
     908             :     {
     909           0 :         pPor = new SwTxtInputFldPortion();
     910             :     }
     911             :     else
     912             :     {
     913           0 :         if( GetFnt()->IsRef() )
     914           0 :             pPor = new SwRefPortion;
     915           0 :         else if (GetFnt()->IsMeta())
     916             :         {
     917           0 :             pPor = new SwMetaPortion;
     918             :         }
     919             :         else
     920             :         {
     921             :             // Only at the End!
     922             :             // If pCurr does not have a width, it can however aready have content.
     923             :             // E.g. for non-displayable characters
     924           0 :             if( rInf.GetLen() > 0 )
     925             :             {
     926           0 :                 if( rInf.GetTxt()[rInf.GetIdx()]==CH_TXT_ATR_FIELDSTART )
     927           0 :                     pPor = new SwFieldMarkPortion();
     928           0 :                 else if( rInf.GetTxt()[rInf.GetIdx()]==CH_TXT_ATR_FIELDEND )
     929           0 :                     pPor = new SwFieldMarkPortion();
     930           0 :                 else if( rInf.GetTxt()[rInf.GetIdx()]==CH_TXT_ATR_FORMELEMENT )
     931             :                 {
     932           0 :                     SwTxtNode *pNd = const_cast<SwTxtNode *>(rInf.GetTxtFrm()->GetTxtNode());
     933           0 :                     const SwDoc *doc = pNd->GetDoc();
     934           0 :                     SwIndex aIndex(pNd, rInf.GetIdx());
     935           0 :                     SwPosition aPosition(*pNd, aIndex);
     936           0 :                     sw::mark::IFieldmark *pBM = doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
     937             :                     OSL_ENSURE(pBM != NULL, "Where is my form field bookmark???");
     938           0 :                     if (pBM != NULL)
     939             :                     {
     940           0 :                         if (pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
     941             :                         {
     942           0 :                             pPor = new SwFieldFormCheckboxPortion();
     943             :                         }
     944           0 :                         else if (pBM->GetFieldname( ) == ODF_FORMDROPDOWN)
     945             :                         {
     946           0 :                             pPor = new SwFieldFormDropDownPortion(sw::mark::ExpandFieldmark(pBM));
     947             :                         }
     948             :                         else
     949             :                         {
     950             :                             assert( false );        // unknown type...
     951             :                         }
     952           0 :                     }
     953             :                 }
     954             :             }
     955           0 :             if( !pPor )
     956             :             {
     957           0 :                 if( !rInf.X() && !pCurr->GetPortion() && !pCurr->GetLen() && !GetFnt()->IsURL() )
     958           0 :                     pPor = pCurr;
     959             :                 else
     960             :                 {
     961           0 :                     pPor = new SwTxtPortion;
     962           0 :                     if ( GetFnt()->IsURL() )
     963             :                     {
     964           0 :                         pPor->SetWhichPor( POR_URL );
     965             :                     }
     966             :                 }
     967             :             }
     968             :         }
     969             :     }
     970           0 :     return pPor;
     971             : }
     972             : 
     973             : /*************************************************************************
     974             :  *                      SwTxtFormatter::NewTxtPortion()
     975             :  *************************************************************************/
     976             : // We calculate the length, the following portion limits are defined:
     977             : // 1) Tabs
     978             : // 2) Linebreaks
     979             : // 3) CH_TXTATR_BREAKWORD / CH_TXTATR_INWORD
     980             : // 4) next attribute change
     981             : 
     982           0 : SwTxtPortion *SwTxtFormatter::NewTxtPortion( SwTxtFormatInfo &rInf )
     983             : {
     984             :     // If we're at the line's beginning, we take pCurr
     985             :     // If pCurr is not derived from SwTxtPortion, we need to duplicate
     986           0 :     Seek( rInf.GetIdx() );
     987           0 :     SwTxtPortion *pPor = WhichTxtPor( rInf );
     988             : 
     989             :     // until next attribute change:
     990           0 :     const sal_Int32 nNextAttr = GetNextAttr();
     991           0 :     sal_Int32 nNextChg = std::min( nNextAttr, rInf.GetTxt().getLength() );
     992             : 
     993             :     // end of script type:
     994           0 :     const sal_Int32 nNextScript = pScriptInfo->NextScriptChg( rInf.GetIdx() );
     995           0 :     nNextChg = std::min( nNextChg, nNextScript );
     996             : 
     997             :     // end of direction:
     998           0 :     const sal_Int32 nNextDir = pScriptInfo->NextDirChg( rInf.GetIdx() );
     999           0 :     nNextChg = std::min( nNextChg, nNextDir );
    1000             : 
    1001             :     // Turbo boost:
    1002             :     // We assume that a font's characters are not larger than twice
    1003             :     // as wide as heigh.
    1004             :     // Very crazy: We need to take the ascent into account.
    1005             : 
    1006             :     // Mind the trap! GetSize() contains the wished-for height, the real height
    1007             :     // is only known in CalcAscent!
    1008             : 
    1009             :     // The ratio is even crazier: a blank in Times New Roman has an ascent of
    1010             :     // 182, a height of 200 and a width of 53!
    1011             :     // It follows that a line with a lot of blanks is processed incorrectly.
    1012             :     // Therefore we increase from factor 2 to 8 (due to negative kerning).
    1013             : 
    1014           0 :     pPor->SetLen(1);
    1015           0 :     CalcAscent( rInf, pPor );
    1016             : 
    1017           0 :     const SwFont* pTmpFnt = rInf.GetFont();
    1018           0 :     sal_Int32 nExpect = std::min( sal_Int32( ((Font *)pTmpFnt)->GetSize().Height() ),
    1019           0 :                              sal_Int32( pPor->GetAscent() ) ) / 8;
    1020           0 :     if ( !nExpect )
    1021           0 :         nExpect = 1;
    1022           0 :     nExpect = rInf.GetIdx() + ((rInf.Width() - rInf.X()) / nExpect);
    1023           0 :     if( nExpect > rInf.GetIdx() && nNextChg > nExpect )
    1024           0 :         nNextChg = std::min( nExpect, rInf.GetTxt().getLength() );
    1025             : 
    1026             :     // we keep an invariant during method calls:
    1027             :     // there are no portion ending characters like hard spaces
    1028             :     // or tabs in [ nLeftScanIdx, nRightScanIdx ]
    1029           0 :     if ( nLeftScanIdx <= rInf.GetIdx() && rInf.GetIdx() <= nRightScanIdx )
    1030             :     {
    1031           0 :         if ( nNextChg > nRightScanIdx )
    1032             :             nNextChg = nRightScanIdx =
    1033           0 :                 rInf.ScanPortionEnd( nRightScanIdx, nNextChg );
    1034             :     }
    1035             :     else
    1036             :     {
    1037           0 :         nLeftScanIdx = rInf.GetIdx();
    1038             :         nNextChg = nRightScanIdx =
    1039           0 :                 rInf.ScanPortionEnd( rInf.GetIdx(), nNextChg );
    1040             :     }
    1041             : 
    1042           0 :     pPor->SetLen( nNextChg - rInf.GetIdx() );
    1043           0 :     rInf.SetLen( pPor->GetLen() );
    1044           0 :     return pPor;
    1045             : }
    1046             : 
    1047             : /*************************************************************************
    1048             :  *                 SwTxtFormatter::WhichFirstPortion()
    1049             :  *************************************************************************/
    1050           0 : SwLinePortion *SwTxtFormatter::WhichFirstPortion(SwTxtFormatInfo &rInf)
    1051             : {
    1052           0 :     SwLinePortion *pPor = 0;
    1053             : 
    1054           0 :     if( rInf.GetRest() )
    1055             :     {
    1056             :         // Tabs and fields
    1057           0 :         if( '\0' != rInf.GetHookChar() )
    1058           0 :             return 0;
    1059             : 
    1060           0 :         pPor = rInf.GetRest();
    1061           0 :         if( pPor->IsErgoSumPortion() )
    1062           0 :             rInf.SetErgoDone(true);
    1063             :         else
    1064           0 :             if( pPor->IsFtnNumPortion() )
    1065           0 :                 rInf.SetFtnDone(true);
    1066             :             else
    1067           0 :                 if( pPor->InNumberGrp() )
    1068           0 :                     rInf.SetNumDone(true);
    1069             : 
    1070           0 :         rInf.SetRest(0);
    1071           0 :         pCurr->SetRest( true );
    1072           0 :         return pPor;
    1073             :     }
    1074             : 
    1075             :     // We can stand in the follow, it's crucial that
    1076             :     // pFrm->GetOfst() == 0!
    1077           0 :     if( rInf.GetIdx() )
    1078             :     {
    1079             :         // We now too can elongate FtnPortions and ErgoSumPortions
    1080             : 
    1081             :         // 1. The ErgoSumTexts
    1082           0 :         if( !rInf.IsErgoDone() )
    1083             :         {
    1084           0 :             if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
    1085           0 :                 pPor = (SwLinePortion*)NewErgoSumPortion( rInf );
    1086           0 :             rInf.SetErgoDone( true );
    1087             :         }
    1088             : 
    1089             :         // 2. Arrow portions
    1090           0 :         if( !pPor && !rInf.IsArrowDone() )
    1091             :         {
    1092           0 :             if( pFrm->GetOfst() && !pFrm->IsFollow() &&
    1093           0 :                 rInf.GetIdx() == pFrm->GetOfst() )
    1094           0 :                 pPor = new SwArrowPortion( *pCurr );
    1095           0 :             rInf.SetArrowDone( true );
    1096             :         }
    1097             : 
    1098             :         // 3. Kerning portions at beginning of line in grid mode
    1099           0 :         if ( ! pPor && ! pCurr->GetPortion() )
    1100             :         {
    1101             :             SwTextGridItem const*const pGrid(
    1102           0 :                     GetGridItem(GetTxtFrm()->FindPageFrm()));
    1103           0 :             if ( pGrid )
    1104           0 :                 pPor = new SwKernPortion( *pCurr );
    1105             :         }
    1106             : 
    1107             :         // 4. The line rests (multiline fields)
    1108           0 :         if( !pPor )
    1109             :         {
    1110           0 :             pPor = rInf.GetRest();
    1111             :             // Only for pPor of course
    1112           0 :             if( pPor )
    1113             :             {
    1114           0 :                 pCurr->SetRest( true );
    1115           0 :                 rInf.SetRest(0);
    1116             :             }
    1117             :         }
    1118             :     }
    1119             :     else
    1120             :     {
    1121             :         // 5. The foot note count
    1122           0 :         if( !rInf.IsFtnDone() )
    1123             :         {
    1124             :             OSL_ENSURE( ( ! rInf.IsMulti() && ! pMulti ) || pMulti->HasRotation(),
    1125             :                      "Rotated number portion trouble" );
    1126             : 
    1127           0 :             const bool bFtnNum = pFrm->IsFtnNumFrm();
    1128           0 :             rInf.GetParaPortion()->SetFtnNum( bFtnNum );
    1129           0 :             if( bFtnNum )
    1130           0 :                 pPor = (SwLinePortion*)NewFtnNumPortion( rInf );
    1131           0 :             rInf.SetFtnDone( true );
    1132             :         }
    1133             : 
    1134             :         // 6. The ErgoSumTexts of course also exist in the TextMaster,
    1135             :         // it's crucial whether the SwFtnFrm is aFollow
    1136           0 :         if( !rInf.IsErgoDone() && !pPor && ! rInf.IsMulti() )
    1137             :         {
    1138           0 :             if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
    1139           0 :                 pPor = (SwLinePortion*)NewErgoSumPortion( rInf );
    1140           0 :             rInf.SetErgoDone( true );
    1141             :         }
    1142             : 
    1143             :         // 7. The numbering
    1144           0 :         if( !rInf.IsNumDone() && !pPor )
    1145             :         {
    1146             :             OSL_ENSURE( ( ! rInf.IsMulti() && ! pMulti ) || pMulti->HasRotation(),
    1147             :                      "Rotated number portion trouble" );
    1148             : 
    1149             :             // If we're in the follow, then of course not
    1150           0 :             if( GetTxtFrm()->GetTxtNode()->GetNumRule() )
    1151           0 :                 pPor = (SwLinePortion*)NewNumberPortion( rInf );
    1152           0 :             rInf.SetNumDone( true );
    1153             :         }
    1154             :         // 8. The DropCaps
    1155           0 :         if( !pPor && GetDropFmt() && ! rInf.IsMulti() )
    1156           0 :             pPor = (SwLinePortion*)NewDropPortion( rInf );
    1157             : 
    1158             :         // 9. Kerning portions at beginning of line in grid mode
    1159           0 :         if ( !pPor && !pCurr->GetPortion() )
    1160             :         {
    1161             :             SwTextGridItem const*const pGrid(
    1162           0 :                     GetGridItem(GetTxtFrm()->FindPageFrm()));
    1163           0 :             if ( pGrid )
    1164           0 :                 pPor = new SwKernPortion( *pCurr );
    1165             :         }
    1166             :     }
    1167             : 
    1168             :         // 10. Decimal tab portion at the beginning of each line in table cells
    1169           0 :         if ( !pPor && !pCurr->GetPortion() &&
    1170           0 :              GetTxtFrm()->IsInTab() &&
    1171           0 :              GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) )
    1172             :         {
    1173           0 :             pPor = NewTabPortion( rInf, true );
    1174             :         }
    1175             : 
    1176             :         // 11. suffix of meta-field
    1177           0 :         if (!pPor)
    1178             :         {
    1179           0 :             pPor = TryNewNoLengthPortion(rInf);
    1180             :         }
    1181             : 
    1182           0 :     return pPor;
    1183             : }
    1184             : 
    1185           0 : static bool lcl_OldFieldRest( const SwLineLayout* pCurr )
    1186             : {
    1187           0 :     if( !pCurr->GetNext() )
    1188           0 :         return false;
    1189           0 :     const SwLinePortion *pPor = pCurr->GetNext()->GetPortion();
    1190           0 :     bool bRet = false;
    1191           0 :     while( pPor && !bRet )
    1192             :     {
    1193           0 :         bRet = (pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()) ||
    1194           0 :             (pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsFollowFld());
    1195           0 :         if( !pPor->GetLen() )
    1196           0 :             break;
    1197           0 :         pPor = pPor->GetPortion();
    1198             :     }
    1199           0 :     return bRet;
    1200             : }
    1201             : 
    1202             : /*************************************************************************
    1203             :  *                      SwTxtFormatter::NewPortion()
    1204             :  *************************************************************************/
    1205             : 
    1206             : /* NewPortion sets rInf.nLen
    1207             :  * A SwTxtPortion is limited by a tab, break, txtatr or attr change
    1208             :  * We can have three cases:
    1209             :  * 1) The line is full and the wrap was not emulated
    1210             :  *    -> return 0;
    1211             :  * 2) The line is full and a wrap was emulated
    1212             :  *    -> Reset width and return new FlyPortion
    1213             :  * 3) We need to construct a new portion
    1214             :  *    -> CalcFlyWidth emulates the width and return portion, if needed
    1215             :  */
    1216             : 
    1217           0 : SwLinePortion *SwTxtFormatter::NewPortion( SwTxtFormatInfo &rInf )
    1218             : {
    1219             :     // Underflow takes precedence
    1220           0 :     rInf.SetStopUnderflow( false );
    1221           0 :     if( rInf.GetUnderflow() )
    1222             :     {
    1223             :         OSL_ENSURE( rInf.IsFull(), "SwTxtFormatter::NewPortion: underflow but not full" );
    1224           0 :         return Underflow( rInf );
    1225             :     }
    1226             : 
    1227             :     // If the line is full, flys and Underflow portions could be waiting ...
    1228           0 :     if( rInf.IsFull() )
    1229             :     {
    1230             :         // LineBreaks and Flys (bug05.sdw)
    1231             :         // IsDummy()
    1232           0 :         if( rInf.IsNewLine() && (!rInf.GetFly() || !pCurr->IsDummy()) )
    1233           0 :             return 0;
    1234             : 
    1235             :         // Wenn der Text an den Fly gestossen ist, oder wenn
    1236             :         // der Fly als erstes drankommt, weil er ueber dem linken
    1237             :         // Rand haengt, wird GetFly() returnt.
    1238             :         // Wenn IsFull() und kein GetFly() vorhanden ist, gibt's
    1239             :         // naturgemaesz eine 0.
    1240           0 :         if( rInf.GetFly() )
    1241             :         {
    1242           0 :             if( rInf.GetLast()->IsBreakPortion() )
    1243             :             {
    1244           0 :                 delete rInf.GetFly();
    1245           0 :                 rInf.SetFly( 0 );
    1246             :             }
    1247             : 
    1248           0 :             return rInf.GetFly();
    1249             :         }
    1250             :         // Ein fieser Sonderfall: ein Rahmen ohne Umlauf kreuzt den
    1251             :         // Ftn-Bereich. Wir muessen die Ftn-Portion als Zeilenrest
    1252             :         // bekanntgeben, damit SwTxtFrm::Format nicht abbricht
    1253             :         // (die Textmasse wurde ja durchformatiert).
    1254           0 :         if( rInf.GetRest() )
    1255           0 :             rInf.SetNewLine( true );
    1256             :         else
    1257             :         {
    1258             :             // Wenn die naechste Zeile mit einem Rest eines Feldes beginnt,
    1259             :             // jetzt aber kein Rest mehr anliegt,
    1260             :             // muss sie auf jeden Fall neu formatiert werden!
    1261           0 :             if( lcl_OldFieldRest( GetCurr() ) )
    1262           0 :                 rInf.SetNewLine( true );
    1263             :             else
    1264             :             {
    1265           0 :                 SwLinePortion *pFirst = WhichFirstPortion( rInf );
    1266           0 :                 if( pFirst )
    1267             :                 {
    1268           0 :                     rInf.SetNewLine( true );
    1269           0 :                     if( pFirst->InNumberGrp() )
    1270           0 :                         rInf.SetNumDone( false) ;
    1271           0 :                     delete pFirst;
    1272             :                 }
    1273             :             }
    1274             :         }
    1275             : 
    1276           0 :         return 0;
    1277             :     }
    1278             : 
    1279           0 :     SwLinePortion *pPor = WhichFirstPortion( rInf );
    1280             : 
    1281             :     // Check for Hidden Portion:
    1282           0 :     if ( !pPor )
    1283             :     {
    1284           0 :         sal_Int32 nEnd = rInf.GetIdx();
    1285           0 :         if ( ::lcl_BuildHiddenPortion( rInf, nEnd ) )
    1286           0 :             pPor = new SwHiddenTextPortion( nEnd - rInf.GetIdx() );
    1287             :     }
    1288             : 
    1289           0 :     if( !pPor )
    1290             :     {
    1291           0 :         if( ( !pMulti || pMulti->IsBidi() ) &&
    1292             :             // #i42734#
    1293             :             // No multi portion if there is a hook character waiting:
    1294           0 :             ( !rInf.GetRest() || '\0' == rInf.GetHookChar() ) )
    1295             :         {
    1296             :             // We open a multiportion part, if we enter a multi-line part
    1297             :             // of the paragraph.
    1298           0 :             sal_Int32 nEnd = rInf.GetIdx();
    1299           0 :             SwMultiCreator* pCreate = rInf.GetMultiCreator( nEnd, pMulti );
    1300           0 :             if( pCreate )
    1301             :             {
    1302           0 :                 SwMultiPortion* pTmp = NULL;
    1303             : 
    1304           0 :                 if ( SW_MC_BIDI == pCreate->nId )
    1305           0 :                     pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
    1306           0 :                 else if ( SW_MC_RUBY == pCreate->nId )
    1307             :                 {
    1308           0 :                     Seek( rInf.GetIdx() );
    1309           0 :                     bool bRubyTop = false;
    1310           0 :                     bool* pRubyPos = 0;
    1311             : 
    1312           0 :                     if ( rInf.SnapToGrid() )
    1313             :                     {
    1314             :                         SwTextGridItem const*const pGrid(
    1315           0 :                                 GetGridItem(GetTxtFrm()->FindPageFrm()));
    1316           0 :                         if ( pGrid )
    1317             :                         {
    1318           0 :                             bRubyTop = ! pGrid->GetRubyTextBelow();
    1319           0 :                             pRubyPos = &bRubyTop;
    1320             :                         }
    1321             :                     }
    1322             : 
    1323           0 :                     pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
    1324           0 :                                               *GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess(),
    1325           0 :                                               nEnd, 0, pRubyPos );
    1326             :                 }
    1327           0 :                 else if( SW_MC_ROTATE == pCreate->nId )
    1328             :                     pTmp = new SwRotatedPortion( *pCreate, nEnd,
    1329           0 :                                                  GetTxtFrm()->IsRightToLeft() );
    1330             :                 else
    1331           0 :                     pTmp = new SwDoubleLinePortion( *pCreate, nEnd );
    1332             : 
    1333           0 :                 delete pCreate;
    1334           0 :                 CalcFlyWidth( rInf );
    1335             : 
    1336           0 :                 return pTmp;
    1337             :             }
    1338             :         }
    1339             :         // 5010: Tabs und Felder
    1340           0 :         sal_Unicode cChar = rInf.GetHookChar();
    1341             : 
    1342           0 :         if( cChar )
    1343             :         {
    1344             :             /* Wir holen uns nocheinmal cChar, um sicherzustellen, dass das
    1345             :              * Tab jetzt wirklich ansteht und nicht auf die naechste Zeile
    1346             :              * gewandert ist ( so geschehen hinter Rahmen ).
    1347             :              * Wenn allerdings eine FldPortion im Rest wartet, muessen wir
    1348             :              * das cChar natuerlich aus dem Feldinhalt holen, z.B. bei
    1349             :              * DezimalTabs und Feldern (22615)
    1350             :             */
    1351           0 :             if( !rInf.GetRest() || !rInf.GetRest()->InFldGrp() )
    1352           0 :                 cChar = rInf.GetChar( rInf.GetIdx() );
    1353           0 :             rInf.ClearHookChar();
    1354             :         }
    1355             :         else
    1356             :         {
    1357           0 :             if( rInf.GetIdx() >= rInf.GetTxt().getLength() )
    1358             :             {
    1359           0 :                 rInf.SetFull(true);
    1360           0 :                 CalcFlyWidth( rInf );
    1361           0 :                 return pPor;
    1362             :             }
    1363           0 :             cChar = rInf.GetChar( rInf.GetIdx() );
    1364             :         }
    1365             : 
    1366           0 :         switch( cChar )
    1367             :         {
    1368             :             case CH_TAB:
    1369           0 :                 pPor = NewTabPortion( rInf, false ); break;
    1370             : 
    1371             :             case CH_BREAK:
    1372           0 :                 pPor = new SwBreakPortion( *rInf.GetLast() ); break;
    1373             : 
    1374             :             case CHAR_SOFTHYPHEN:                   // soft hyphen
    1375           0 :                 pPor = new SwSoftHyphPortion; break;
    1376             : 
    1377             :             case CHAR_HARDBLANK:                    // no-break space
    1378           0 :                 pPor = new SwBlankPortion( ' ' ); break;
    1379             : 
    1380             :             case CHAR_HARDHYPHEN:               // non-breaking hyphen
    1381           0 :                 pPor = new SwBlankPortion( '-' ); break;
    1382             : 
    1383             :             case CHAR_ZWSP:                     // zero width space
    1384             :             case CHAR_ZWNBSP :                  // word joiner
    1385           0 :                 pPor = new SwControlCharPortion( cChar ); break;
    1386             : 
    1387             :             case CH_TXTATR_BREAKWORD:
    1388             :             case CH_TXTATR_INWORD:
    1389           0 :                 if( rInf.HasHint( rInf.GetIdx() ) )
    1390             :                 {
    1391           0 :                     pPor = NewExtraPortion( rInf );
    1392           0 :                     break;
    1393             :                 }
    1394             :                 // No break
    1395             :             default        :
    1396             :                 {
    1397           0 :                 SwTabPortion* pLastTabPortion = rInf.GetLastTab();
    1398           0 :                 if ( pLastTabPortion && cChar == rInf.GetTabDecimal() )
    1399             :                 {
    1400             :                     // #127428# Abandon dec. tab position if line is full
    1401             :                     // We have a decimal tab portion in the line and the next character has to be
    1402             :                     // aligned at the tab stop position. We store the width from the beginning of
    1403             :                     // the tab stop portion up to the portion containint the decimal separator:
    1404           0 :                   if ( GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) /*rInf.GetVsh()->IsTabCompat();*/ &&
    1405           0 :                          POR_TABDECIMAL == pLastTabPortion->GetWhichPor() )
    1406             :                     {
    1407             :                         OSL_ENSURE( rInf.X() >= pLastTabPortion->Fix(), "Decimal tab stop position cannot be calculated" );
    1408           0 :                         const sal_uInt16 nWidthOfPortionsUpToDecimalPosition = (sal_uInt16)(rInf.X() - pLastTabPortion->Fix() );
    1409           0 :                         static_cast<SwTabDecimalPortion*>(pLastTabPortion)->SetWidthOfPortionsUpToDecimalPosition( nWidthOfPortionsUpToDecimalPosition );
    1410           0 :                         rInf.SetTabDecimal( 0 );
    1411             :                     }
    1412             :                     else
    1413           0 :                         rInf.SetFull( rInf.GetLastTab()->Format( rInf ) );
    1414             :                 }
    1415             : 
    1416           0 :                 if( rInf.GetRest() )
    1417             :                 {
    1418           0 :                     if( rInf.IsFull() )
    1419             :                     {
    1420           0 :                         rInf.SetNewLine(true);
    1421           0 :                         return 0;
    1422             :                     }
    1423           0 :                     pPor = rInf.GetRest();
    1424           0 :                     rInf.SetRest(0);
    1425             :                 }
    1426             :                 else
    1427             :                 {
    1428           0 :                     if( rInf.IsFull() )
    1429           0 :                         return 0;
    1430           0 :                     pPor = NewTxtPortion( rInf );
    1431             :                 }
    1432           0 :                 break;
    1433             :             }
    1434             :         }
    1435             : 
    1436             :         // if a portion is created despite there being a pending RestPortion,
    1437             :         // then it is a field which has been split (e.g. because it contains a Tab)
    1438           0 :         if( pPor && rInf.GetRest() )
    1439           0 :             pPor->SetLen( 0 );
    1440             : 
    1441             :         // robust:
    1442           0 :         if( !pPor || rInf.IsStop() )
    1443             :         {
    1444           0 :             delete pPor;
    1445           0 :             return 0;
    1446             :         }
    1447             :     }
    1448             : 
    1449             :     // Special portions containing numbers (footnote anchor, footnote number,
    1450             :     // numbering) can be contained in a rotated portion, if the user
    1451             :     // choose a rotated character attribute.
    1452           0 :     if ( pPor && ! pMulti )
    1453             :     {
    1454           0 :         if ( pPor->IsFtnPortion() )
    1455             :         {
    1456           0 :             const SwTxtFtn* pTxtFtn = ((SwFtnPortion*)pPor)->GetTxtFtn();
    1457             : 
    1458           0 :             if ( pTxtFtn )
    1459             :             {
    1460           0 :                 SwFmtFtn& rFtn = (SwFmtFtn&)pTxtFtn->GetFtn();
    1461           0 :                 const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
    1462             :                 const SwEndNoteInfo* pInfo;
    1463           0 :                 if( rFtn.IsEndNote() )
    1464           0 :                     pInfo = &pDoc->GetEndNoteInfo();
    1465             :                 else
    1466           0 :                     pInfo = &pDoc->GetFtnInfo();
    1467           0 :                 const SwAttrSet& rSet = pInfo->GetAnchorCharFmt((SwDoc&)*pDoc)->GetAttrSet();
    1468             : 
    1469             :                 const SfxPoolItem* pItem;
    1470           0 :                 sal_uInt16 nDir = 0;
    1471           0 :                 if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ROTATE,
    1472           0 :                     true, &pItem ))
    1473           0 :                     nDir = ((SvxCharRotateItem*)pItem)->GetValue();
    1474             : 
    1475           0 :                 if ( 0 != nDir )
    1476             :                 {
    1477           0 :                     delete pPor;
    1478           0 :                     pPor = new SwRotatedPortion( rInf.GetIdx() + 1, 900 == nDir ?
    1479             :                                                     DIR_BOTTOM2TOP :
    1480           0 :                                                     DIR_TOP2BOTTOM );
    1481             :                 }
    1482             :             }
    1483             :         }
    1484           0 :         else if ( pPor->InNumberGrp() )
    1485             :         {
    1486           0 :             const SwFont* pNumFnt = ((SwFldPortion*)pPor)->GetFont();
    1487             : 
    1488           0 :             if ( pNumFnt )
    1489             :             {
    1490           0 :                 sal_uInt16 nDir = pNumFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
    1491           0 :                 if ( 0 != nDir )
    1492             :                 {
    1493           0 :                     delete pPor;
    1494             :                     pPor = new SwRotatedPortion( 0, 900 == nDir ?
    1495             :                                                     DIR_BOTTOM2TOP :
    1496           0 :                                                     DIR_TOP2BOTTOM );
    1497             : 
    1498           0 :                     rInf.SetNumDone( false );
    1499           0 :                     rInf.SetFtnDone( false );
    1500             :                 }
    1501             :             }
    1502             :         }
    1503             :     }
    1504             : 
    1505             :     // Der Font wird im Outputdevice eingestellt,
    1506             :     // der Ascent und die Hoehe werden berechnet.
    1507           0 :     if( !pPor->GetAscent() && !pPor->Height() )
    1508           0 :         CalcAscent( rInf, pPor );
    1509           0 :     rInf.SetLen( pPor->GetLen() );
    1510             : 
    1511             :     // In CalcFlyWidth wird Width() verkuerzt, wenn eine FlyPortion vorliegt.
    1512           0 :     CalcFlyWidth( rInf );
    1513             : 
    1514             :     // Man darf nicht vergessen, dass pCurr als GetLast() vernuenftige
    1515             :     // Werte bereithalten muss:
    1516           0 :     if( !pCurr->Height() )
    1517             :     {
    1518             :         OSL_ENSURE( pCurr->Height(), "SwTxtFormatter::NewPortion: limbo dance" );
    1519           0 :         pCurr->Height( pPor->Height() );
    1520           0 :         pCurr->SetAscent( pPor->GetAscent() );
    1521             :     }
    1522             : 
    1523             :     OSL_ENSURE( !pPor || pPor->Height(),
    1524             :             "SwTxtFormatter::NewPortion: something went wrong");
    1525           0 :     if( pPor->IsPostItsPortion() && rInf.X() >= rInf.Width() && rInf.GetFly() )
    1526             :     {
    1527           0 :         delete pPor;
    1528           0 :         pPor = rInf.GetFly();
    1529             :     }
    1530           0 :     return pPor;
    1531             : }
    1532             : 
    1533             : /*************************************************************************
    1534             :  *                      SwTxtFormatter::FormatLine()
    1535             :  *************************************************************************/
    1536             : 
    1537           0 : sal_Int32 SwTxtFormatter::FormatLine(const sal_Int32 nStartPos)
    1538             : {
    1539             :     OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
    1540             :             "SwTxtFormatter::FormatLine( nStartPos ) with unswapped frame" );
    1541             : 
    1542             :     // For the formatting routines, we set pOut to the reference device.
    1543           0 :     SwHookOut aHook( GetInfo() );
    1544           0 :     if( GetInfo().GetLen() < GetInfo().GetTxt().getLength() )
    1545           0 :         GetInfo().SetLen( GetInfo().GetTxt().getLength() );
    1546             : 
    1547           0 :     bool bBuild = true;
    1548           0 :     SetFlyInCntBase( false );
    1549           0 :     GetInfo().SetLineHeight( 0 );
    1550           0 :     GetInfo().SetLineNettoHeight( 0 );
    1551             : 
    1552             :     // Recycling muss bei geaenderter Zeilenhoehe unterdrueckt werden
    1553             :     // und auch bei geaendertem Ascent (Absenken der Grundlinie).
    1554           0 :     const KSHORT nOldHeight = pCurr->Height();
    1555           0 :     const KSHORT nOldAscent = pCurr->GetAscent();
    1556             : 
    1557           0 :     pCurr->SetEndHyph( false );
    1558           0 :     pCurr->SetMidHyph( false );
    1559             : 
    1560             :     // fly positioning can make it necessary format a line several times
    1561             :     // for this, we have to keep a copy of our rest portion
    1562           0 :     SwLinePortion* pFld = GetInfo().GetRest();
    1563           0 :     boost::scoped_ptr<SwFldPortion> xSaveFld;
    1564             : 
    1565           0 :     if ( pFld && pFld->InFldGrp() && !pFld->IsFtnPortion() )
    1566           0 :         xSaveFld.reset(new SwFldPortion( *((SwFldPortion*)pFld) ));
    1567             : 
    1568             :     // for an optimal repaint rectangle, we want to compare fly portions
    1569             :     // before and after the BuildPortions call
    1570           0 :     const bool bOptimizeRepaint = AllowRepaintOpt();
    1571           0 :     const sal_Int32 nOldLineEnd = nStartPos + pCurr->GetLen();
    1572           0 :     std::vector<long> flyStarts;
    1573             : 
    1574             :     // these are the conditions for a fly position comparison
    1575           0 :     if ( bOptimizeRepaint && pCurr->IsFly() )
    1576             :     {
    1577           0 :         SwLinePortion* pPor = pCurr->GetFirstPortion();
    1578           0 :         long nPOfst = 0;
    1579           0 :         while ( pPor )
    1580             :         {
    1581           0 :             if ( pPor->IsFlyPortion() )
    1582             :                 // insert start value of fly portion
    1583           0 :                 flyStarts.push_back( nPOfst );
    1584             : 
    1585           0 :             nPOfst += pPor->Width();
    1586           0 :             pPor = pPor->GetPortion();
    1587             :         }
    1588             :     }
    1589             : 
    1590             :     // Hier folgt bald die Unterlaufpruefung.
    1591           0 :     while( bBuild )
    1592             :     {
    1593           0 :         GetInfo().SetFtnInside( false );
    1594           0 :         GetInfo().SetOtherThanFtnInside( false );
    1595             : 
    1596             :         // These values must not be reset by FormatReset();
    1597           0 :         const bool bOldNumDone = GetInfo().IsNumDone();
    1598           0 :         const bool bOldArrowDone = GetInfo().IsArrowDone();
    1599           0 :         const bool bOldErgoDone = GetInfo().IsErgoDone();
    1600             : 
    1601             :         // besides other things, this sets the repaint offset to 0
    1602           0 :         FormatReset( GetInfo() );
    1603             : 
    1604           0 :         GetInfo().SetNumDone( bOldNumDone );
    1605           0 :         GetInfo().SetArrowDone( bOldArrowDone );
    1606           0 :         GetInfo().SetErgoDone( bOldErgoDone );
    1607             : 
    1608             :         // build new portions for this line
    1609           0 :         BuildPortions( GetInfo() );
    1610             : 
    1611           0 :         if( GetInfo().IsStop() )
    1612             :         {
    1613           0 :             pCurr->SetLen( 0 );
    1614           0 :             pCurr->Height( GetFrmRstHeight() + 1 );
    1615           0 :             pCurr->SetRealHeight( GetFrmRstHeight() + 1 );
    1616           0 :             pCurr->Width(0);
    1617           0 :             pCurr->Truncate();
    1618           0 :             return nStartPos;
    1619             :         }
    1620           0 :         else if( GetInfo().IsDropInit() )
    1621             :         {
    1622           0 :             DropInit();
    1623           0 :             GetInfo().SetDropInit( false );
    1624             :         }
    1625             : 
    1626           0 :         pCurr->CalcLine( *this, GetInfo() );
    1627           0 :         CalcRealHeight( GetInfo().IsNewLine() );
    1628             : 
    1629             :         //#i120864# For Special case that at the first calculation couldn't get
    1630             :         //correct height. And need to recalculate for the right height.
    1631           0 :         SwLinePortion* pPorTmp = pCurr->GetPortion();
    1632           0 :         if ( IsFlyInCntBase() && (!IsQuick() || (pPorTmp && pPorTmp->IsFlyCntPortion() && !pPorTmp->GetPortion() &&
    1633           0 :             pCurr->Height() > pPorTmp->Height())))
    1634             :         {
    1635             :             KSHORT nTmpAscent, nTmpHeight;
    1636           0 :             CalcAscentAndHeight( nTmpAscent, nTmpHeight );
    1637           0 :             AlignFlyInCntBase( Y() + long( nTmpAscent ) );
    1638           0 :             pCurr->CalcLine( *this, GetInfo() );
    1639           0 :             CalcRealHeight();
    1640             :         }
    1641             : 
    1642             :         // bBuild entscheidet, ob noch eine Ehrenrunde gedreht wird
    1643           0 :         if ( pCurr->GetRealHeight() <= GetInfo().GetLineHeight() )
    1644             :         {
    1645           0 :             pCurr->SetRealHeight( GetInfo().GetLineHeight() );
    1646           0 :             bBuild = false;
    1647             :         }
    1648             :         else
    1649             :         {
    1650           0 :             bBuild = ( GetInfo().GetTxtFly()->IsOn() && ChkFlyUnderflow(GetInfo()) )
    1651           0 :                      || GetInfo().CheckFtnPortion(pCurr);
    1652           0 :             if( bBuild )
    1653             :             {
    1654           0 :                 GetInfo().SetNumDone( bOldNumDone );
    1655           0 :                 GetInfo().ResetMaxWidthDiff();
    1656             : 
    1657             :                 // delete old rest
    1658           0 :                 if ( GetInfo().GetRest() )
    1659             :                 {
    1660           0 :                     delete GetInfo().GetRest();
    1661           0 :                     GetInfo().SetRest( 0 );
    1662             :                 }
    1663             : 
    1664             :                 // set original rest portion
    1665           0 :                 if ( xSaveFld )
    1666           0 :                     GetInfo().SetRest( new SwFldPortion( *xSaveFld ) );
    1667             : 
    1668           0 :                 pCurr->SetLen( 0 );
    1669           0 :                 pCurr->Width(0);
    1670           0 :                 pCurr->Truncate();
    1671             :             }
    1672             :         }
    1673             :     }
    1674             : 
    1675             :     // In case of compat mode, it's possible that a tab portion is wider after
    1676             :     // formatting than before. If this is the case, we also have to make sure
    1677             :     // the SwLineLayout is wider as well.
    1678           0 :     if (GetInfo().GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_OVER_MARGIN))
    1679             :     {
    1680           0 :         sal_uInt16 nSum = 0;
    1681           0 :         SwLinePortion* pPor = pCurr->GetFirstPortion();
    1682             : 
    1683           0 :         while (pPor)
    1684             :         {
    1685           0 :             nSum += pPor->Width();
    1686           0 :             pPor = pPor->GetPortion();
    1687             :         }
    1688             : 
    1689           0 :         if (nSum > pCurr->Width())
    1690           0 :             pCurr->Width(nSum);
    1691             :     }
    1692             : 
    1693             :     // calculate optimal repaint rectangle
    1694           0 :     if ( bOptimizeRepaint )
    1695             :     {
    1696           0 :         GetInfo().SetPaintOfst( ::lcl_CalcOptRepaint( *this, *pCurr, nOldLineEnd, flyStarts ) );
    1697           0 :         flyStarts.clear();
    1698             :     }
    1699             :     else
    1700             :         // Special case: We do not allow an optimitation of the repaint
    1701             :         // area, but during formatting the repaint offset is set to indicate
    1702             :         // a maximum value for the offset. This value has to be reset:
    1703           0 :         GetInfo().SetPaintOfst( 0 );
    1704             : 
    1705             :     // This corrects the start of the reformat range if something has
    1706             :     // moved to the next line. Otherwise IsFirstReformat in AllowRepaintOpt
    1707             :     // will give us a wrong result if we have to reformat another line
    1708           0 :     GetInfo().GetParaPortion()->GetReformat()->LeftMove( GetInfo().GetIdx() );
    1709             : 
    1710             :     // delete master copy of rest portion
    1711           0 :     xSaveFld.reset();
    1712             : 
    1713           0 :     sal_Int32 nNewStart = nStartPos + pCurr->GetLen();
    1714             : 
    1715             :     // adjust text if kana compression is enabled
    1716           0 :     if ( GetInfo().CompressLine() )
    1717             :     {
    1718           0 :         SwTwips nRepaintOfst = CalcKanaAdj( pCurr );
    1719             : 
    1720             :         // adjust repaint offset
    1721           0 :         if ( nRepaintOfst < GetInfo().GetPaintOfst() )
    1722           0 :             GetInfo().SetPaintOfst( nRepaintOfst );
    1723             :     }
    1724             : 
    1725           0 :     CalcAdjustLine( pCurr );
    1726             : 
    1727           0 :     if( nOldHeight != pCurr->Height() || nOldAscent != pCurr->GetAscent() )
    1728             :     {
    1729           0 :         SetFlyInCntBase();
    1730           0 :         GetInfo().SetPaintOfst( 0 ); //geaenderte Zeilenhoehe => kein Recycling
    1731             :         // alle weiteren Zeilen muessen gepaintet und, wenn Flys im Spiel sind
    1732             :         // auch formatiert werden.
    1733           0 :         GetInfo().SetShift( true );
    1734             :     }
    1735             : 
    1736           0 :     if ( IsFlyInCntBase() && !IsQuick() )
    1737           0 :         UpdatePos( pCurr, GetTopLeft(), GetStart() );
    1738             : 
    1739           0 :     return nNewStart;
    1740             : }
    1741             : 
    1742             : /*************************************************************************
    1743             :  *                      SwTxtFormatter::RecalcRealHeight()
    1744             :  *************************************************************************/
    1745             : 
    1746           0 : void SwTxtFormatter::RecalcRealHeight()
    1747             : {
    1748           0 :     do
    1749             :     {
    1750           0 :         CalcRealHeight();
    1751           0 :     } while (Next());
    1752           0 : }
    1753             : 
    1754             : /*************************************************************************
    1755             :  *                    SwTxtFormatter::CalcRealHeight()
    1756             :  *************************************************************************/
    1757             : 
    1758           0 : void SwTxtFormatter::CalcRealHeight( bool bNewLine )
    1759             : {
    1760           0 :     KSHORT nLineHeight = pCurr->Height();
    1761           0 :     pCurr->SetClipping( false );
    1762             : 
    1763           0 :     SwTextGridItem const*const pGrid(GetGridItem(pFrm->FindPageFrm()));
    1764           0 :     if ( pGrid && GetInfo().SnapToGrid() )
    1765             :     {
    1766           0 :         const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
    1767           0 :         const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
    1768           0 :         const bool bRubyTop = ! pGrid->GetRubyTextBelow();
    1769             : 
    1770           0 :         nLineHeight = nGridWidth + nRubyHeight;
    1771           0 :         sal_uInt16 nLineDist = nLineHeight;
    1772             : 
    1773           0 :         while ( pCurr->Height() > nLineHeight )
    1774           0 :             nLineHeight = nLineHeight + nLineDist;
    1775             : 
    1776           0 :         KSHORT nAsc = pCurr->GetAscent() +
    1777             :                       ( bRubyTop ?
    1778           0 :                        ( nLineHeight - pCurr->Height() + nRubyHeight ) / 2 :
    1779           0 :                        ( nLineHeight - pCurr->Height() - nRubyHeight ) / 2 );
    1780             : 
    1781           0 :         pCurr->Height( nLineHeight );
    1782           0 :         pCurr->SetAscent( nAsc );
    1783           0 :         pInf->GetParaPortion()->SetFixLineHeight();
    1784             : 
    1785             :         // we ignore any line spacing options except from ...
    1786           0 :         const SvxLineSpacingItem* pSpace = aLineInf.GetLineSpacing();
    1787           0 :         if ( ! IsParaLine() && pSpace &&
    1788           0 :              SVX_INTER_LINE_SPACE_PROP == pSpace->GetInterLineSpaceRule() )
    1789             :         {
    1790           0 :             sal_uLong nTmp = pSpace->GetPropLineSpace();
    1791             : 
    1792           0 :             if( nTmp < 100 )
    1793           0 :                 nTmp = 100;
    1794             : 
    1795           0 :             nTmp *= nLineHeight;
    1796           0 :             nLineHeight = (sal_uInt16)(nTmp / 100);
    1797             :         }
    1798             : 
    1799           0 :         pCurr->SetRealHeight( nLineHeight );
    1800           0 :         return;
    1801             :     }
    1802             : 
    1803             :     // Das Dummyflag besitzen Zeilen, die nur Flyportions enthalten, diese
    1804             :     // sollten kein Register etc. beachten. Dummerweise hat kann es eine leere
    1805             :     // Zeile am Absatzende geben (bei leeren Abs?tzen oder nach einem
    1806             :     // Shift-Return), die das Register durchaus beachten soll.
    1807           0 :     if( !pCurr->IsDummy() || ( !pCurr->GetNext() &&
    1808           0 :         GetStart() >= GetTxtFrm()->GetTxt().getLength() && !bNewLine ) )
    1809             :     {
    1810           0 :         const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
    1811           0 :         if( pSpace )
    1812             :         {
    1813           0 :             switch( pSpace->GetLineSpaceRule() )
    1814             :             {
    1815             :                 case SVX_LINE_SPACE_AUTO:
    1816           0 :             if (pSpace->GetInterLineSpaceRule()==SVX_INTER_LINE_SPACE_PROP) {
    1817           0 :                         long nTmp = pSpace->GetPropLineSpace();
    1818           0 :                         if (nTmp<100) { // code adaped from fixed line height
    1819           0 :                             nTmp *= nLineHeight;
    1820           0 :                             nTmp /= 100;
    1821           0 :                             if( !nTmp )
    1822           0 :                                 ++nTmp;
    1823           0 :                             nLineHeight = (KSHORT)nTmp;
    1824             : /*
    1825             :                             //@TODO figure out how WW maps ascent and descent
    1826             :                             //in case of prop  line spacing <100%
    1827             :                             KSHORT nAsc = ( 4 * nLineHeight ) / 5;  // 80%
    1828             :                             if( nAsc < pCurr->GetAscent() ||
    1829             :                                 nLineHeight - nAsc < pCurr->Height() -
    1830             : pCurr->GetAscent() )
    1831             :                                 pCurr->SetClipping( true );
    1832             :                             pCurr->SetAscent( nAsc );
    1833             : */
    1834           0 :                             pCurr->Height( nLineHeight );
    1835           0 :                             pInf->GetParaPortion()->SetFixLineHeight();
    1836             :                         }
    1837             :                     }
    1838           0 :                 break;
    1839             :                 case SVX_LINE_SPACE_MIN:
    1840             :                 {
    1841           0 :                     if( nLineHeight < KSHORT( pSpace->GetLineHeight() ) )
    1842           0 :                         nLineHeight = pSpace->GetLineHeight();
    1843           0 :                     break;
    1844             :                 }
    1845             :                 case SVX_LINE_SPACE_FIX:
    1846             :                 {
    1847           0 :                     nLineHeight = pSpace->GetLineHeight();
    1848           0 :                     KSHORT nAsc = ( 4 * nLineHeight ) / 5;  // 80%
    1849           0 :                     if( nAsc < pCurr->GetAscent() ||
    1850           0 :                         nLineHeight - nAsc < pCurr->Height() - pCurr->GetAscent() )
    1851           0 :                         pCurr->SetClipping( true );
    1852           0 :                     pCurr->Height( nLineHeight );
    1853           0 :                     pCurr->SetAscent( nAsc );
    1854           0 :                     pInf->GetParaPortion()->SetFixLineHeight();
    1855             :                 }
    1856           0 :                 break;
    1857             :                 default: OSL_FAIL( ": unknown LineSpaceRule" );
    1858             :             }
    1859           0 :             if( !IsParaLine() )
    1860           0 :                 switch( pSpace->GetInterLineSpaceRule() )
    1861             :                 {
    1862             :                     case SVX_INTER_LINE_SPACE_OFF:
    1863           0 :                     break;
    1864             :                     case SVX_INTER_LINE_SPACE_PROP:
    1865             :                     {
    1866           0 :                         long nTmp = pSpace->GetPropLineSpace();
    1867             :                         // 50% ist das Minimum, bei 0% schalten wir auf
    1868             :                         // den Defaultwert 100% um ...
    1869           0 :                         if( nTmp < 50 )
    1870           0 :                             nTmp = nTmp ? 50 : 100;
    1871             : 
    1872           0 :                         nTmp *= nLineHeight;
    1873           0 :                         nTmp /= 100;
    1874           0 :                         if( !nTmp )
    1875           0 :                             ++nTmp;
    1876           0 :                         nLineHeight = (KSHORT)nTmp;
    1877           0 :                         break;
    1878             :                     }
    1879             :                     case SVX_INTER_LINE_SPACE_FIX:
    1880             :                     {
    1881           0 :                         nLineHeight = nLineHeight + pSpace->GetInterLineSpace();
    1882           0 :                         break;
    1883             :                     }
    1884             :                     default: OSL_FAIL( ": unknown InterLineSpaceRule" );
    1885             :                 }
    1886             :         }
    1887             : #if OSL_DEBUG_LEVEL > 1
    1888             :         KSHORT nDummy = nLineHeight + 1;
    1889             :         (void)nDummy;
    1890             : #endif
    1891             : 
    1892           0 :         if( IsRegisterOn() )
    1893             :         {
    1894           0 :             SwTwips nTmpY = Y() + pCurr->GetAscent() + nLineHeight - pCurr->Height();
    1895           0 :             SWRECTFN( pFrm )
    1896           0 :             if ( bVert )
    1897           0 :                 nTmpY = pFrm->SwitchHorizontalToVertical( nTmpY );
    1898           0 :             nTmpY = (*fnRect->fnYDiff)( nTmpY, RegStart() );
    1899           0 :             KSHORT nDiff = KSHORT( nTmpY % RegDiff() );
    1900           0 :             if( nDiff )
    1901           0 :                 nLineHeight += RegDiff() - nDiff;
    1902             :         }
    1903             :     }
    1904           0 :     pCurr->SetRealHeight( nLineHeight );
    1905             : }
    1906             : 
    1907             : /*************************************************************************
    1908             :  *                      SwTxtFormatter::FeedInf()
    1909             :  *************************************************************************/
    1910             : 
    1911           0 : void SwTxtFormatter::FeedInf( SwTxtFormatInfo &rInf ) const
    1912             : {
    1913             :     // 3260, 3860: Fly auf jeden Fall loeschen!
    1914           0 :     ClearFly( rInf );
    1915           0 :     rInf.Init();
    1916             : 
    1917           0 :     rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
    1918           0 :     rInf.SetRoot( pCurr );
    1919           0 :     rInf.SetLineStart( nStart );
    1920           0 :     rInf.SetIdx( nStart );
    1921             : 
    1922             :     // Handle overflows:
    1923             :     // #i34348# Changed type from sal_uInt16 to SwTwips
    1924           0 :     SwTwips nTmpLeft = Left();
    1925           0 :     SwTwips nTmpRight = Right();
    1926           0 :     SwTwips nTmpFirst = FirstLeft();
    1927             : 
    1928           0 :     if ( nTmpLeft > USHRT_MAX ||
    1929           0 :          nTmpRight > USHRT_MAX ||
    1930             :          nTmpFirst > USHRT_MAX )
    1931             :     {
    1932           0 :         SWRECTFN( rInf.GetTxtFrm() )
    1933           0 :         nTmpLeft = (rInf.GetTxtFrm()->Frm().*fnRect->fnGetLeft)();
    1934           0 :         nTmpRight = (rInf.GetTxtFrm()->Frm().*fnRect->fnGetRight)();
    1935           0 :         nTmpFirst = nTmpLeft;
    1936             :     }
    1937             : 
    1938           0 :     rInf.Left(  nTmpLeft  );
    1939           0 :     rInf.Right( nTmpRight );
    1940           0 :     rInf.First( nTmpFirst );
    1941             : 
    1942           0 :     rInf.RealWidth( KSHORT(rInf.Right()) - KSHORT(GetLeftMargin()) );
    1943           0 :     rInf.Width( rInf.RealWidth() );
    1944           0 :     if( ((SwTxtFormatter*)this)->GetRedln() )
    1945             :     {
    1946           0 :         ((SwTxtFormatter*)this)->GetRedln()->Clear( ((SwTxtFormatter*)this)->GetFnt() );
    1947           0 :         ((SwTxtFormatter*)this)->GetRedln()->Reset();
    1948             :     }
    1949           0 : }
    1950             : 
    1951             : /*************************************************************************
    1952             :  *                      SwTxtFormatter::FormatReset()
    1953             :  *************************************************************************/
    1954             : 
    1955           0 : void SwTxtFormatter::FormatReset( SwTxtFormatInfo &rInf )
    1956             : {
    1957           0 :     pCurr->Truncate();
    1958           0 :     pCurr->Init();
    1959           0 :     if( pBlink && pCurr->IsBlinking() )
    1960           0 :         pBlink->Delete( pCurr );
    1961             : 
    1962             :     // delete pSpaceAdd und pKanaComp
    1963           0 :     pCurr->FinishSpaceAdd();
    1964           0 :     pCurr->FinishKanaComp();
    1965           0 :     pCurr->ResetFlags();
    1966           0 :     FeedInf( rInf );
    1967           0 : }
    1968             : 
    1969             : /*************************************************************************
    1970             :  *                SwTxtFormatter::CalcOnceMore()
    1971             :  *************************************************************************/
    1972             : 
    1973           0 : bool SwTxtFormatter::CalcOnceMore()
    1974             : {
    1975           0 :     if( pDropFmt )
    1976             :     {
    1977           0 :         const KSHORT nOldDrop = GetDropHeight();
    1978           0 :         CalcDropHeight( pDropFmt->GetLines() );
    1979           0 :         bOnceMore = nOldDrop != GetDropHeight();
    1980             :     }
    1981             :     else
    1982           0 :         bOnceMore = false;
    1983           0 :     return bOnceMore;
    1984             : }
    1985             : 
    1986             : /*************************************************************************
    1987             :  *                SwTxtFormatter::CalcBottomLine()
    1988             :  *************************************************************************/
    1989             : 
    1990           0 : SwTwips SwTxtFormatter::CalcBottomLine() const
    1991             : {
    1992           0 :     SwTwips nRet = Y() + GetLineHeight();
    1993           0 :     SwTwips nMin = GetInfo().GetTxtFly()->GetMinBottom();
    1994           0 :     if( nMin && ++nMin > nRet )
    1995             :     {
    1996           0 :         SwTwips nDist = pFrm->Frm().Height() - pFrm->Prt().Height()
    1997           0 :                         - pFrm->Prt().Top();
    1998           0 :         if( nRet + nDist < nMin )
    1999             :         {
    2000           0 :             const bool bRepaint = HasTruncLines() &&
    2001           0 :                 GetInfo().GetParaPortion()->GetRepaint()->Bottom() == nRet-1;
    2002           0 :             nRet = nMin - nDist;
    2003           0 :             if( bRepaint )
    2004             :             {
    2005           0 :                 ((SwRepaint*)GetInfo().GetParaPortion()
    2006           0 :                     ->GetRepaint())->Bottom( nRet-1 );
    2007           0 :                 ((SwTxtFormatInfo&)GetInfo()).SetPaintOfst( 0 );
    2008             :             }
    2009             :         }
    2010             :     }
    2011           0 :     return nRet;
    2012             : }
    2013             : 
    2014             : /*************************************************************************
    2015             :  *                SwTxtFormatter::_CalcFitToContent()
    2016             :  *
    2017             :  * FME/OD: This routine does a limited text formatting.
    2018             :  *************************************************************************/
    2019             : 
    2020           0 : SwTwips SwTxtFormatter::_CalcFitToContent()
    2021             : {
    2022           0 :     FormatReset( GetInfo() );
    2023           0 :     BuildPortions( GetInfo() );
    2024           0 :     pCurr->CalcLine( *this, GetInfo() );
    2025           0 :     return pCurr->Width();
    2026             : }
    2027             : 
    2028             : /*************************************************************************
    2029             :  *                      SwTxtFormatter::AllowRepaintOpt()
    2030             :  *
    2031             :  * determines if the calculation of a repaint offset is allowed
    2032             :  * otherwise each line is painted from 0 (this is a copy of the beginning
    2033             :  * of the former SwTxtFormatter::Recycle() function
    2034             :  *************************************************************************/
    2035           0 : bool SwTxtFormatter::AllowRepaintOpt() const
    2036             : {
    2037             :     // reformat position in front of current line? Only in this case
    2038             :     // we want to set the repaint offset
    2039           0 :     bool bOptimizeRepaint = nStart < GetInfo().GetReformatStart() &&
    2040           0 :                                 pCurr->GetLen();
    2041             : 
    2042             :     // a special case is the last line of a block adjusted paragraph:
    2043           0 :     if ( bOptimizeRepaint )
    2044             :     {
    2045           0 :         switch( GetAdjust() )
    2046             :         {
    2047             :         case SVX_ADJUST_BLOCK:
    2048             :         {
    2049           0 :             if( IsLastBlock() || IsLastCenter() )
    2050           0 :                 bOptimizeRepaint = false;
    2051             :             else
    2052             :             {
    2053             :                 // ????: Blank in der letzten Masterzeile (blocksat.sdw)
    2054           0 :                 bOptimizeRepaint = 0 == pCurr->GetNext() && !pFrm->GetFollow();
    2055           0 :                 if ( bOptimizeRepaint )
    2056             :                 {
    2057           0 :                     SwLinePortion *pPos = pCurr->GetFirstPortion();
    2058           0 :                     while ( pPos && !pPos->IsFlyPortion() )
    2059           0 :                         pPos = pPos->GetPortion();
    2060           0 :                     bOptimizeRepaint = !pPos;
    2061             :                 }
    2062             :             }
    2063           0 :             break;
    2064             :         }
    2065             :         case SVX_ADJUST_CENTER:
    2066             :         case SVX_ADJUST_RIGHT:
    2067           0 :             bOptimizeRepaint = false;
    2068           0 :             break;
    2069             :         default: ;
    2070             :         }
    2071             :     }
    2072             : 
    2073             :     // Schon wieder ein Sonderfall: unsichtbare SoftHyphs
    2074           0 :     const sal_Int32 nReformat = GetInfo().GetReformatStart();
    2075           0 :     if( bOptimizeRepaint && COMPLETE_STRING != nReformat )
    2076             :     {
    2077           0 :         const sal_Unicode cCh = nReformat >= GetInfo().GetTxt().getLength() ? 0 : GetInfo().GetTxt()[ nReformat ];
    2078           0 :         bOptimizeRepaint = ( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
    2079           0 :                             || ! GetInfo().HasHint( nReformat );
    2080             :     }
    2081             : 
    2082           0 :     return bOptimizeRepaint;
    2083             : }
    2084             : 
    2085           0 : void SwTxtFormatter::CalcUnclipped( SwTwips& rTop, SwTwips& rBottom )
    2086             : {
    2087             :     OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
    2088             :             "SwTxtFormatter::CalcUnclipped with unswapped frame" );
    2089             : 
    2090             :     long nFlyAsc, nFlyDesc;
    2091           0 :     pCurr->MaxAscentDescent( rTop, rBottom, nFlyAsc, nFlyDesc );
    2092           0 :     rTop = Y() + GetCurr()->GetAscent();
    2093           0 :     rBottom = rTop + nFlyDesc;
    2094           0 :     rTop -= nFlyAsc;
    2095           0 : }
    2096             : 
    2097           0 : void SwTxtFormatter::UpdatePos( SwLineLayout *pCurrent, Point aStart,
    2098             :     sal_Int32 nStartIdx, bool bAlways ) const
    2099             : {
    2100             :     OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
    2101             :             "SwTxtFormatter::UpdatePos with unswapped frame" );
    2102             : 
    2103           0 :     if( GetInfo().IsTest() )
    2104           0 :         return;
    2105           0 :     SwLinePortion *pFirst = pCurrent->GetFirstPortion();
    2106           0 :     SwLinePortion *pPos = pFirst;
    2107           0 :     SwTxtPaintInfo aTmpInf( GetInfo() );
    2108           0 :     aTmpInf.SetpSpaceAdd( pCurrent->GetpLLSpaceAdd() );
    2109           0 :     aTmpInf.ResetSpaceIdx();
    2110           0 :     aTmpInf.SetKanaComp( pCurrent->GetpKanaComp() );
    2111           0 :     aTmpInf.ResetKanaIdx();
    2112             : 
    2113             :     // The frame's size
    2114           0 :     aTmpInf.SetIdx( nStartIdx );
    2115           0 :     aTmpInf.SetPos( aStart );
    2116             : 
    2117             :     long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
    2118           0 :     pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
    2119             : 
    2120           0 :     KSHORT nTmpHeight = pCurrent->GetRealHeight();
    2121           0 :     KSHORT nAscent = pCurrent->GetAscent() + nTmpHeight - pCurrent->Height();
    2122           0 :     objectpositioning::AsCharFlags nFlags = AS_CHAR_ULSPACE;
    2123           0 :     if( GetMulti() )
    2124             :     {
    2125           0 :         aTmpInf.SetDirection( GetMulti()->GetDirection() );
    2126           0 :         if( GetMulti()->HasRotation() )
    2127             :         {
    2128           0 :             nFlags |= AS_CHAR_ROTATE;
    2129           0 :             if( GetMulti()->IsRevers() )
    2130             :             {
    2131           0 :                 nFlags |= AS_CHAR_REVERSE;
    2132           0 :                 aTmpInf.X( aTmpInf.X() - nAscent );
    2133             :             }
    2134             :             else
    2135           0 :                 aTmpInf.X( aTmpInf.X() + nAscent );
    2136             :         }
    2137             :         else
    2138             :         {
    2139           0 :             if ( GetMulti()->IsBidi() )
    2140           0 :                 nFlags |= AS_CHAR_BIDI;
    2141           0 :             aTmpInf.Y( aTmpInf.Y() + nAscent );
    2142             :         }
    2143             :     }
    2144             :     else
    2145           0 :         aTmpInf.Y( aTmpInf.Y() + nAscent );
    2146             : 
    2147           0 :     while( pPos )
    2148             :     {
    2149             :         // We only know one case where changing the position (caused by the
    2150             :         // adjustment) could be relevant for a portion: We need to SetRefPoint
    2151             :         // for FlyCntPortions.
    2152           0 :         if( ( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
    2153           0 :             && ( bAlways || !IsQuick() ) )
    2154             :         {
    2155           0 :             pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
    2156             : 
    2157           0 :             if( pPos->IsGrfNumPortion() )
    2158             :             {
    2159           0 :                 if( !nFlyAsc && !nFlyDesc )
    2160             :                 {
    2161           0 :                     nTmpAscent = nAscent;
    2162           0 :                     nFlyAsc = nAscent;
    2163           0 :                     nTmpDescent = nTmpHeight - nAscent;
    2164           0 :                     nFlyDesc = nTmpDescent;
    2165             :                 }
    2166             :                 ((SwGrfNumPortion*)pPos)->SetBase( nTmpAscent, nTmpDescent,
    2167           0 :                                                    nFlyAsc, nFlyDesc );
    2168             :             }
    2169             :             else
    2170             :             {
    2171           0 :                 Point aBase( aTmpInf.GetPos() );
    2172           0 :                 if ( GetInfo().GetTxtFrm()->IsVertical() )
    2173           0 :                     GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aBase );
    2174             : 
    2175           0 :                 ((SwFlyCntPortion*)pPos)->SetBase( *aTmpInf.GetTxtFrm(),
    2176             :                     aBase, nTmpAscent, nTmpDescent, nFlyAsc,
    2177           0 :                     nFlyDesc, nFlags );
    2178             :             }
    2179             :         }
    2180           0 :         if( pPos->IsMultiPortion() && ((SwMultiPortion*)pPos)->HasFlyInCntnt() )
    2181             :         {
    2182             :             OSL_ENSURE( !GetMulti(), "Too much multi" );
    2183           0 :             ((SwTxtFormatter*)this)->pMulti = (SwMultiPortion*)pPos;
    2184           0 :             SwLineLayout *pLay = &GetMulti()->GetRoot();
    2185           0 :             Point aSt( aTmpInf.X(), aStart.Y() );
    2186             : 
    2187           0 :             if ( GetMulti()->HasBrackets() )
    2188             :             {
    2189             :                 OSL_ENSURE( GetMulti()->IsDouble(), "Brackets only for doubles");
    2190           0 :                 aSt.X() += ((SwDoubleLinePortion*)GetMulti())->PreWidth();
    2191             :             }
    2192           0 :             else if( GetMulti()->HasRotation() )
    2193             :             {
    2194           0 :                 aSt.Y() += pCurrent->GetAscent() - GetMulti()->GetAscent();
    2195           0 :                 if( GetMulti()->IsRevers() )
    2196           0 :                     aSt.X() += GetMulti()->Width();
    2197             :                 else
    2198           0 :                     aSt.Y() += GetMulti()->Height();
    2199             :                }
    2200           0 :             else if ( GetMulti()->IsBidi() )
    2201             :                 // jump to end of the bidi portion
    2202           0 :                 aSt.X() += pLay->Width();
    2203             : 
    2204           0 :             sal_Int32 nStIdx = aTmpInf.GetIdx();
    2205           0 :             do
    2206             :             {
    2207           0 :                 UpdatePos( pLay, aSt, nStIdx, bAlways );
    2208           0 :                 nStIdx = nStIdx + pLay->GetLen();
    2209           0 :                 aSt.Y() += pLay->Height();
    2210           0 :                 pLay = pLay->GetNext();
    2211             :             } while ( pLay );
    2212           0 :             ((SwTxtFormatter*)this)->pMulti = NULL;
    2213             :         }
    2214           0 :         pPos->Move( aTmpInf );
    2215           0 :         pPos = pPos->GetPortion();
    2216           0 :     }
    2217             : }
    2218             : 
    2219           0 : void SwTxtFormatter::AlignFlyInCntBase( long nBaseLine ) const
    2220             : {
    2221             :     OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
    2222             :             "SwTxtFormatter::AlignFlyInCntBase with unswapped frame" );
    2223             : 
    2224           0 :     if( GetInfo().IsTest() )
    2225           0 :         return;
    2226           0 :     SwLinePortion *pFirst = pCurr->GetFirstPortion();
    2227           0 :     SwLinePortion *pPos = pFirst;
    2228           0 :     objectpositioning::AsCharFlags nFlags = AS_CHAR_NOFLAG;
    2229           0 :     if( GetMulti() && GetMulti()->HasRotation() )
    2230             :     {
    2231           0 :         nFlags |= AS_CHAR_ROTATE;
    2232           0 :         if( GetMulti()->IsRevers() )
    2233           0 :             nFlags |= AS_CHAR_REVERSE;
    2234             :     }
    2235             : 
    2236             :     long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
    2237             : 
    2238           0 :     while( pPos )
    2239             :     {
    2240           0 :         if( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
    2241             :         {
    2242           0 :             pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
    2243             : 
    2244           0 :             if( pPos->IsGrfNumPortion() )
    2245             :                 ((SwGrfNumPortion*)pPos)->SetBase( nTmpAscent, nTmpDescent,
    2246           0 :                                                    nFlyAsc, nFlyDesc );
    2247             :             else
    2248             :             {
    2249           0 :                 Point aBase;
    2250           0 :                 if ( GetInfo().GetTxtFrm()->IsVertical() )
    2251             :                 {
    2252           0 :                     nBaseLine = GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( nBaseLine );
    2253           0 :                     aBase = Point( nBaseLine, ((SwFlyCntPortion*)pPos)->GetRefPoint().Y() );
    2254             :                 }
    2255             :                 else
    2256           0 :                     aBase = Point( ((SwFlyCntPortion*)pPos)->GetRefPoint().X(), nBaseLine );
    2257             : 
    2258           0 :                 ((SwFlyCntPortion*)pPos)->SetBase( *GetInfo().GetTxtFrm(), aBase, nTmpAscent, nTmpDescent,
    2259           0 :                     nFlyAsc, nFlyDesc, nFlags );
    2260             :             }
    2261             :         }
    2262           0 :         pPos = pPos->GetPortion();
    2263             :     }
    2264             : }
    2265             : 
    2266           0 : bool SwTxtFormatter::ChkFlyUnderflow( SwTxtFormatInfo &rInf ) const
    2267             : {
    2268             :     OSL_ENSURE( rInf.GetTxtFly()->IsOn(), "SwTxtFormatter::ChkFlyUnderflow: why?" );
    2269           0 :     if( GetCurr() )
    2270             :     {
    2271             :         // First we check, whether a fly overlaps with the line.
    2272             :         // = GetLineHeight()
    2273           0 :         const long nHeight = GetCurr()->GetRealHeight();
    2274           0 :         SwRect aLine( GetLeftMargin(), Y(), rInf.RealWidth(), nHeight );
    2275             : 
    2276           0 :         SwRect aLineVert( aLine );
    2277           0 :         if ( pFrm->IsVertical() )
    2278           0 :             pFrm->SwitchHorizontalToVertical( aLineVert );
    2279           0 :         SwRect aInter( rInf.GetTxtFly()->GetFrm( aLineVert ) );
    2280           0 :         if ( pFrm->IsVertical() )
    2281           0 :             pFrm->SwitchVerticalToHorizontal( aInter );
    2282             : 
    2283           0 :         if( !aInter.HasArea() )
    2284           0 :             return false;
    2285             : 
    2286             :         // We now check every portion that could have lowered for overlapping
    2287             :         // with the fly.
    2288           0 :         const SwLinePortion *pPos = GetCurr()->GetFirstPortion();
    2289           0 :         aLine.Pos().Y() = Y() + GetCurr()->GetRealHeight() - GetCurr()->Height();
    2290           0 :         aLine.Height( GetCurr()->Height() );
    2291             : 
    2292           0 :         while( pPos )
    2293             :         {
    2294           0 :             aLine.Width( pPos->Width() );
    2295             : 
    2296           0 :             aLineVert = aLine;
    2297           0 :             if ( pFrm->IsVertical() )
    2298           0 :                 pFrm->SwitchHorizontalToVertical( aLineVert );
    2299           0 :             aInter = rInf.GetTxtFly()->GetFrm( aLineVert );
    2300           0 :             if ( pFrm->IsVertical() )
    2301           0 :                 pFrm->SwitchVerticalToHorizontal( aInter );
    2302             : 
    2303             :             // New flys from below?
    2304           0 :             if( !pPos->IsFlyPortion() )
    2305             :             {
    2306           0 :                 if( aInter.IsOver( aLine ) )
    2307             :                 {
    2308           0 :                     aInter._Intersection( aLine );
    2309           0 :                     if( aInter.HasArea() )
    2310             :                     {
    2311             :                         // To be evaluated during reformat of this line:
    2312             :                         // RealHeight including spacing
    2313           0 :                         rInf.SetLineHeight( KSHORT(nHeight) );
    2314             :                         // Height without extra spacing
    2315           0 :                         rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
    2316           0 :                         return true;
    2317             :                     }
    2318             :                 }
    2319             :             }
    2320             :             else
    2321             :             {
    2322             :                 // The fly portion is not intersected by a fly anymore
    2323           0 :                 if ( ! aInter.IsOver( aLine ) )
    2324             :                 {
    2325           0 :                     rInf.SetLineHeight( KSHORT(nHeight) );
    2326           0 :                     rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
    2327           0 :                     return true;
    2328             :                 }
    2329             :                 else
    2330             :                 {
    2331           0 :                     aInter._Intersection( aLine );
    2332             : 
    2333             :                     // No area means a fly has become invalid because of
    2334             :                     // lowering the line => reformat the line
    2335             :                     // we also have to reformat the line, if the fly size
    2336             :                     // differs from the intersection interval's size.
    2337           0 :                     if( ! aInter.HasArea() ||
    2338           0 :                         ((SwFlyPortion*)pPos)->GetFixWidth() != aInter.Width() )
    2339             :                     {
    2340           0 :                         rInf.SetLineHeight( KSHORT(nHeight) );
    2341           0 :                         rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
    2342           0 :                         return true;
    2343             :                     }
    2344             :                 }
    2345             :             }
    2346             : 
    2347           0 :             aLine.Left( aLine.Left() + pPos->Width() );
    2348           0 :             pPos = pPos->GetPortion();
    2349             :         }
    2350             :     }
    2351           0 :     return false;
    2352             : }
    2353             : 
    2354           0 : void SwTxtFormatter::CalcFlyWidth( SwTxtFormatInfo &rInf )
    2355             : {
    2356           0 :     if( GetMulti() || rInf.GetFly() )
    2357           0 :         return;
    2358             : 
    2359           0 :     SwTxtFly *pTxtFly = rInf.GetTxtFly();
    2360           0 :     if( !pTxtFly->IsOn() || rInf.IsIgnoreFly() )
    2361           0 :         return;
    2362             : 
    2363           0 :     const SwLinePortion *pLast = rInf.GetLast();
    2364             : 
    2365             :     long nAscent;
    2366           0 :     long nTop = Y();
    2367             :     long nHeight;
    2368             : 
    2369           0 :     if( rInf.GetLineHeight() )
    2370             :     {
    2371             :         // Real line height has already been calculated, we only have to
    2372             :         // search for intersections in the lower part of the strip
    2373           0 :         nAscent = pCurr->GetAscent();
    2374           0 :         nHeight = rInf.GetLineNettoHeight();
    2375           0 :         nTop += rInf.GetLineHeight() - nHeight;
    2376             :     }
    2377             :     else
    2378             :     {
    2379           0 :         nAscent = pLast->GetAscent();
    2380           0 :         nHeight = pLast->Height();
    2381             : 
    2382             :         // We make a first guess for the lines real height
    2383           0 :         if ( ! pCurr->GetRealHeight() )
    2384           0 :             CalcRealHeight();
    2385             : 
    2386           0 :         if ( pCurr->GetRealHeight() > nHeight )
    2387           0 :             nTop += pCurr->GetRealHeight() - nHeight;
    2388             :         else
    2389             :             // Important for fixed space between lines
    2390           0 :             nHeight = pCurr->GetRealHeight();
    2391             :     }
    2392             : 
    2393           0 :     const long nLeftMar = GetLeftMargin();
    2394           0 :     const long nLeftMin = (rInf.X() || GetDropLeft()) ? nLeftMar : GetLeftMin();
    2395             : 
    2396           0 :     SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
    2397           0 :                   + nLeftMar - nLeftMin , nHeight );
    2398             : 
    2399           0 :     SwRect aLineVert( aLine );
    2400           0 :     if ( pFrm->IsRightToLeft() )
    2401           0 :         pFrm->SwitchLTRtoRTL( aLineVert );
    2402             : 
    2403           0 :     if ( pFrm->IsVertical() )
    2404           0 :         pFrm->SwitchHorizontalToVertical( aLineVert );
    2405           0 :     SwRect aInter( pTxtFly->GetFrm( aLineVert ) );
    2406             : 
    2407           0 :     if ( pFrm->IsRightToLeft() )
    2408           0 :         pFrm->SwitchRTLtoLTR( aInter );
    2409             : 
    2410           0 :     if ( pFrm->IsVertical() )
    2411           0 :         pFrm->SwitchVerticalToHorizontal( aInter );
    2412             : 
    2413           0 :     if( aInter.IsOver( aLine ) )
    2414             :     {
    2415           0 :         aLine.Left( rInf.X() + nLeftMar );
    2416           0 :         bool bForced = false;
    2417           0 :         if( aInter.Left() <= nLeftMin )
    2418             :         {
    2419           0 :             SwTwips nFrmLeft = GetTxtFrm()->Frm().Left();
    2420           0 :             if( GetTxtFrm()->Prt().Left() < 0 )
    2421           0 :                 nFrmLeft += GetTxtFrm()->Prt().Left();
    2422           0 :             if( aInter.Left() < nFrmLeft )
    2423           0 :                 aInter.Left( nFrmLeft );
    2424             : 
    2425           0 :             long nAddMar = 0;
    2426           0 :             if ( pFrm->IsRightToLeft() )
    2427             :             {
    2428           0 :                 nAddMar = pFrm->Frm().Right() - Right();
    2429           0 :                 if ( nAddMar < 0 )
    2430           0 :                     nAddMar = 0;
    2431             :             }
    2432             :             else
    2433           0 :                 nAddMar = nLeftMar - nFrmLeft;
    2434             : 
    2435           0 :             aInter.Width( aInter.Width() + nAddMar );
    2436             :             // For a negative first line indent, we set this flag to show
    2437             :             // that the indentation/margin has been moved.
    2438             :             // This needs to be respected by the DefaultTab at the zero position.
    2439           0 :             if( IsFirstTxtLine() && HasNegFirst() )
    2440           0 :                 bForced = true;
    2441             :         }
    2442           0 :         aInter.Intersection( aLine );
    2443           0 :         if( !aInter.HasArea() )
    2444           0 :             return;
    2445             : 
    2446           0 :         const bool bFullLine =  aLine.Left()  == aInter.Left() &&
    2447           0 :                                 aLine.Right() == aInter.Right();
    2448             : 
    2449             :         // Although no text is left, we need to format another line,
    2450             :         // because also empty lines need to avoid a Fly with no wrapping.
    2451           0 :         if( bFullLine && rInf.GetIdx() == rInf.GetTxt().getLength() )
    2452             :         {
    2453           0 :             rInf.SetNewLine( true );
    2454             :             // 8221: We know that for dummies, it holds ascent == height
    2455           0 :             pCurr->SetDummy(true);
    2456             :         }
    2457             : 
    2458             :         // aInter becomes frame-local
    2459           0 :         aInter.Pos().X() -= nLeftMar;
    2460           0 :         SwFlyPortion *pFly = new SwFlyPortion( aInter );
    2461           0 :         if( bForced )
    2462             :         {
    2463           0 :             pCurr->SetForcedLeftMargin( true );
    2464           0 :             rInf.ForcedLeftMargin( (sal_uInt16)aInter.Width() );
    2465             :         }
    2466             : 
    2467           0 :         if( bFullLine )
    2468             :         {
    2469             :             // 8110: In order to properly flow around Flys with different
    2470             :             // wrapping attributes, we need to increase by units of line height.
    2471             :             // The last avoiding line should be adjusted in height, so that
    2472             :             // we don't get a frame spacing effect.
    2473             :             // 8221: It is important that ascent == height, because the FlyPortion
    2474             :             // values are transferred to pCurr in CalcLine and IsDummy() relies
    2475             :             // on this behaviour.
    2476             :             // To my knowledge we only have two places where DummyLines can be
    2477             :             // created: here and in MakeFlyDummies.
    2478             :             // IsDummy() is evaluated in IsFirstTxtLine(), when moving lines
    2479             :             // and in relation with DropCaps.
    2480           0 :             pFly->Height( KSHORT(aInter.Height()) );
    2481             : 
    2482             :             // nNextTop now contains the margin's bottom edge, which we avoid
    2483             :             // or the next margin's top edge, which we need to respect.
    2484             :             // That means we can comfortably grow up to this value; that's how
    2485             :             // we save a few empty lines.
    2486           0 :             long nNextTop = pTxtFly->GetNextTop();
    2487           0 :             if ( pFrm->IsVertical() )
    2488           0 :                 nNextTop = pFrm->SwitchVerticalToHorizontal( nNextTop );
    2489           0 :             if( nNextTop > aInter.Bottom() )
    2490             :             {
    2491           0 :                 SwTwips nH = nNextTop - aInter.Top();
    2492           0 :                 if( nH < KSHRT_MAX )
    2493           0 :                     pFly->Height( KSHORT( nH ) );
    2494             :             }
    2495           0 :             if( nAscent < pFly->Height() )
    2496           0 :                 pFly->SetAscent( KSHORT(nAscent) );
    2497             :             else
    2498           0 :                 pFly->SetAscent( pFly->Height() );
    2499             :         }
    2500             :         else
    2501             :         {
    2502           0 :             if( rInf.GetIdx() == rInf.GetTxt().getLength() )
    2503             :             {
    2504             :                 // Don't use nHeight, or we have a huge descent
    2505           0 :                 pFly->Height( pLast->Height() );
    2506           0 :                 pFly->SetAscent( pLast->GetAscent() );
    2507             :             }
    2508             :             else
    2509             :             {
    2510           0 :                 pFly->Height( KSHORT(aInter.Height()) );
    2511           0 :                 if( nAscent < pFly->Height() )
    2512           0 :                     pFly->SetAscent( KSHORT(nAscent) );
    2513             :                 else
    2514           0 :                     pFly->SetAscent( pFly->Height() );
    2515             :             }
    2516             :         }
    2517             : 
    2518           0 :         rInf.SetFly( pFly );
    2519             : 
    2520           0 :         if( pFly->Fix() < rInf.Width() )
    2521           0 :             rInf.Width( pFly->Fix() );
    2522             : 
    2523           0 :         SwTextGridItem const*const pGrid(GetGridItem(pFrm->FindPageFrm()));
    2524           0 :         if ( pGrid )
    2525             :         {
    2526           0 :             const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
    2527           0 :             const SwLayoutFrm* pBody = pPageFrm->FindBodyCont();
    2528             : 
    2529           0 :             SWRECTFN( pPageFrm )
    2530             : 
    2531             :             const long nGridOrigin = pBody ?
    2532           0 :                                     (pBody->*fnRect->fnGetPrtLeft)() :
    2533           0 :                                     (pPageFrm->*fnRect->fnGetPrtLeft)();
    2534             : 
    2535           0 :             const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
    2536           0 :             const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc);
    2537             : 
    2538           0 :             SwTwips nStartX = GetLeftMargin();
    2539           0 :             if ( bVert )
    2540             :             {
    2541           0 :                 Point aPoint( nStartX, 0 );
    2542           0 :                 pFrm->SwitchHorizontalToVertical( aPoint );
    2543           0 :                 nStartX = aPoint.Y();
    2544             :             }
    2545             : 
    2546           0 :             const SwTwips nOfst = nStartX - nGridOrigin;
    2547           0 :             const SwTwips nTmpWidth = rInf.Width() + nOfst;
    2548             : 
    2549           0 :             const sal_uLong i = nTmpWidth / nGridWidth + 1;
    2550             : 
    2551           0 :             const long nNewWidth = ( i - 1 ) * nGridWidth - nOfst;
    2552           0 :             if ( nNewWidth > 0 )
    2553           0 :                 rInf.Width( (sal_uInt16)nNewWidth );
    2554             :             else
    2555           0 :                 rInf.Width( 0 );
    2556             :         }
    2557             :     }
    2558             : }
    2559             : 
    2560           0 : SwFlyCntPortion *SwTxtFormatter::NewFlyCntPortion( SwTxtFormatInfo &rInf,
    2561             :                                                    SwTxtAttr *pHint ) const
    2562             : {
    2563           0 :     SwFlyCntPortion *pRet = 0;
    2564           0 :     const SwFrm *pFrame = (SwFrm*)pFrm;
    2565             : 
    2566             :     SwFlyInCntFrm *pFly;
    2567           0 :     SwFrmFmt* pFrmFmt = ((SwTxtFlyCnt*)pHint)->GetFlyCnt().GetFrmFmt();
    2568           0 :     if( RES_FLYFRMFMT == pFrmFmt->Which() )
    2569           0 :         pFly = ((SwTxtFlyCnt*)pHint)->GetFlyFrm(pFrame);
    2570             :     else
    2571           0 :         pFly = NULL;
    2572             :     // aBase is the document-global position, from which the new extra portion is placed
    2573             :     // aBase.X() = Offset in in the line after the current position
    2574             :     // aBase.Y() = LineIter.Y() + Ascent of the current position
    2575             : 
    2576             :     long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
    2577             :     // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
    2578             :     //SwLinePortion *pPos = pCurr->GetFirstPortion();
    2579             :     //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
    2580           0 :     pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
    2581             : 
    2582             :     // If the ascent of the frame is larger than the ascent of the current position,
    2583             :     // we use this one when calculating the base, or the frame would be positioned
    2584             :     // too much to the top, sliding down after all causing a repaint in an area
    2585             :     // he actually never was in.
    2586           0 :     KSHORT nAscent = 0;
    2587             : 
    2588           0 :     const bool bTxtFrmVertical = GetInfo().GetTxtFrm()->IsVertical();
    2589             : 
    2590           0 :     const bool bUseFlyAscent = pFly && pFly->GetValidPosFlag() &&
    2591           0 :                                0 != ( bTxtFrmVertical ?
    2592           0 :                                       pFly->GetRefPoint().X() :
    2593           0 :                                       pFly->GetRefPoint().Y() );
    2594             : 
    2595           0 :     if ( bUseFlyAscent )
    2596             :          nAscent = static_cast<sal_uInt16>( std::abs( int( bTxtFrmVertical ?
    2597           0 :                                                   pFly->GetRelPos().X() :
    2598           0 :                                                   pFly->GetRelPos().Y() ) ) );
    2599             : 
    2600             :     // Check if be prefer to use the ascent of the last portion:
    2601           0 :     if ( IsQuick() ||
    2602           0 :          !bUseFlyAscent ||
    2603           0 :          nAscent < rInf.GetLast()->GetAscent() )
    2604             :     {
    2605           0 :         nAscent = rInf.GetLast()->GetAscent();
    2606             :     }
    2607           0 :     else if( nAscent > nFlyAsc )
    2608           0 :         nFlyAsc = nAscent;
    2609             : 
    2610           0 :     Point aBase( GetLeftMargin() + rInf.X(), Y() + nAscent );
    2611           0 :     objectpositioning::AsCharFlags nMode = IsQuick() ? AS_CHAR_QUICK : 0;
    2612           0 :     if( GetMulti() && GetMulti()->HasRotation() )
    2613             :     {
    2614           0 :         nMode |= AS_CHAR_ROTATE;
    2615           0 :         if( GetMulti()->IsRevers() )
    2616           0 :             nMode |= AS_CHAR_REVERSE;
    2617             :     }
    2618             : 
    2619           0 :     Point aTmpBase( aBase );
    2620           0 :     if ( GetInfo().GetTxtFrm()->IsVertical() )
    2621           0 :         GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aTmpBase );
    2622             : 
    2623           0 :     if( pFly )
    2624             :     {
    2625           0 :         pRet = new SwFlyCntPortion( *GetInfo().GetTxtFrm(), pFly, aTmpBase,
    2626           0 :                                     nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode );
    2627             :         // We need to make sure that our font is set again in the OutputDevice
    2628             :         // It could be that the FlyInCnt was added anew and GetFlyFrm() would
    2629             :         // in turn cause, that it'd be created anew again.
    2630             :         // This one's frames get formatted right away, which change the font and
    2631             :         // we have a bug (3322).
    2632           0 :         rInf.SelectFont();
    2633           0 :         if( pRet->GetAscent() > nAscent )
    2634             :         {
    2635           0 :             aBase.Y() = Y() + pRet->GetAscent();
    2636           0 :             nMode |= AS_CHAR_ULSPACE;
    2637           0 :             if( !rInf.IsTest() )
    2638             :             {
    2639           0 :                 aTmpBase = aBase;
    2640           0 :                 if ( GetInfo().GetTxtFrm()->IsVertical() )
    2641           0 :                     GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aTmpBase );
    2642             : 
    2643           0 :                 pRet->SetBase( *rInf.GetTxtFrm(), aTmpBase, nTmpAscent,
    2644           0 :                                nTmpDescent, nFlyAsc, nFlyDesc, nMode );
    2645             :             }
    2646             :         }
    2647             :     }
    2648             :     else
    2649             :     {
    2650           0 :         pRet = new SwFlyCntPortion( *rInf.GetTxtFrm(), (SwDrawContact*)pFrmFmt->FindContactObj(),
    2651           0 :            aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode );
    2652             :     }
    2653           0 :     return pRet;
    2654             : }
    2655             : 
    2656             : /* Drop portion is a special case, because it has parts which aren't portions
    2657             :    but we have handle them just like portions */
    2658           0 : void SwTxtFormatter::MergeCharacterBorder( SwDropPortion& rPortion )
    2659             : {
    2660           0 :     if( rPortion.GetLines() > 1 )
    2661             :     {
    2662           0 :         SwDropPortionPart* pCurrPart = rPortion.GetPart();
    2663           0 :         while( pCurrPart )
    2664             :         {
    2665           0 :             if( pCurrPart->GetFollow() &&
    2666           0 :                 ::lcl_HasSameBorder(pCurrPart->GetFont(), pCurrPart->GetFollow()->GetFont()) )
    2667             :             {
    2668           0 :                 pCurrPart->SetJoinBorderWithNext(true);
    2669           0 :                 pCurrPart->GetFollow()->SetJoinBorderWithPrev(true);
    2670             :             }
    2671           0 :             pCurrPart = pCurrPart->GetFollow();
    2672             :         }
    2673             :     }
    2674           0 : }
    2675             : 
    2676           0 : void SwTxtFormatter::MergeCharacterBorder( SwLinePortion& rPortion, SwTxtFormatInfo& rInf )
    2677             : {
    2678           0 :     const SwFont aCurFont = *rInf.GetFont();
    2679           0 :     if( aCurFont.HasBorder() )
    2680             :     {
    2681             :         // The current portion isn't inserted into the portion chain yet, so the info's
    2682             :         // last portion will be the previous one
    2683           0 :         if( rInf.GetLast() && rInf.GetLast() != &rPortion && // For para portion (special case)
    2684           0 :             rInf.GetLast()->GetJoinBorderWithNext() )
    2685             :         {
    2686             :             // In some case border merge is called twice to the portion
    2687           0 :             if( !rPortion.GetJoinBorderWithPrev() )
    2688             :             {
    2689           0 :                 rPortion.SetJoinBorderWithPrev(true);
    2690           0 :                 if( rPortion.InTxtGrp() && rPortion.Width() > aCurFont.GetLeftBorderSpace() )
    2691           0 :                     rPortion.Width(rPortion.Width() - aCurFont.GetLeftBorderSpace());
    2692             :             }
    2693             :         }
    2694             :         else
    2695             :         {
    2696           0 :             rPortion.SetJoinBorderWithPrev(false);
    2697           0 :             m_pFirstOfBorderMerge = &rPortion;
    2698             :         }
    2699             : 
    2700             :         // Get next portion's font
    2701           0 :         bool bSeek = false;
    2702           0 :         if( !rInf.IsFull() && // Not the last portion of the line (in case of line break)
    2703           0 :             rInf.GetIdx() + rPortion.GetLen() != rInf.GetTxt().getLength() ) // Not the last portion of the paragraph
    2704           0 :             bSeek = Seek(rInf.GetIdx() + rPortion.GetLen());
    2705             : 
    2706             :         // If next portion has the same border then merge
    2707           0 :         if( bSeek && GetFnt()->HasBorder() && ::lcl_HasSameBorder(aCurFont, *GetFnt()) )
    2708             :         {
    2709             :             // In some case border merge is called twice to the portion
    2710           0 :             if( !rPortion.GetJoinBorderWithNext() )
    2711             :             {
    2712           0 :                 rPortion.SetJoinBorderWithNext(true);
    2713           0 :                 if( rPortion.InTxtGrp() && rPortion.Width() > aCurFont.GetRightBorderSpace() )
    2714           0 :                     rPortion.Width(rPortion.Width() - aCurFont.GetRightBorderSpace());
    2715             :             }
    2716             :         }
    2717             :         // If this is the last portion of the merge group then make the real height merge
    2718             :         else
    2719             :         {
    2720           0 :             rPortion.SetJoinBorderWithNext(false);
    2721           0 :             if( m_pFirstOfBorderMerge != &rPortion )
    2722             :             {
    2723             :                 // Calculate maximum height and ascent
    2724           0 :                 SwLinePortion* pActPor = m_pFirstOfBorderMerge;
    2725           0 :                 sal_uInt16 nMaxAscent = 0;
    2726           0 :                 sal_uInt16 nMaxHeight = 0;
    2727           0 :                 bool bReachCurrent = false;
    2728           0 :                 while( pActPor )
    2729             :                 {
    2730           0 :                     if( nMaxHeight < pActPor->Height() )
    2731           0 :                         nMaxHeight = pActPor->Height();
    2732           0 :                     if( nMaxAscent < pActPor->GetAscent() )
    2733           0 :                         nMaxAscent = pActPor->GetAscent();
    2734             : 
    2735           0 :                     pActPor = pActPor->GetPortion();
    2736           0 :                     if( !pActPor && !bReachCurrent )
    2737             :                     {
    2738           0 :                         pActPor = &rPortion;
    2739           0 :                         bReachCurrent = true;
    2740             :                     }
    2741             :                 }
    2742             : 
    2743             :                 // Change all portion's height and ascent
    2744           0 :                 pActPor = m_pFirstOfBorderMerge;
    2745           0 :                 bReachCurrent = false;
    2746           0 :                 while( pActPor )
    2747             :                 {
    2748           0 :                     if( nMaxHeight > pActPor->Height() )
    2749           0 :                         pActPor->Height(nMaxHeight);
    2750           0 :                     if( nMaxAscent > pActPor->GetAscent() )
    2751           0 :                         pActPor->SetAscent(nMaxAscent);
    2752             : 
    2753           0 :                     pActPor = pActPor->GetPortion();
    2754           0 :                     if( !pActPor && !bReachCurrent )
    2755             :                     {
    2756           0 :                         pActPor = &rPortion;
    2757           0 :                         bReachCurrent = true;
    2758             :                     }
    2759             :                 }
    2760           0 :                 m_pFirstOfBorderMerge = 0;
    2761             :             }
    2762             :         }
    2763           0 :         Seek(rInf.GetIdx());
    2764           0 :     }
    2765           0 : }
    2766             : 
    2767             : namespace {
    2768             :     /*************************************************************************
    2769             :     *                      ::CalcOptRepaint()
    2770             :     *
    2771             :     * calculates and sets optimal repaint offset for the current line
    2772             :     *************************************************************************/
    2773           0 :     long lcl_CalcOptRepaint( SwTxtFormatter &rThis,
    2774             :                          SwLineLayout &rCurr,
    2775             :                          const sal_Int32 nOldLineEnd,
    2776             :                          const std::vector<long> &rFlyStarts )
    2777             :     {
    2778           0 :         SwTxtFormatInfo txtFmtInfo = rThis.GetInfo();
    2779           0 :         if ( txtFmtInfo.GetIdx() < txtFmtInfo.GetReformatStart() )
    2780             :         // the reformat position is behind our new line, that means
    2781             :         // something of our text has moved to the next line
    2782           0 :             return 0;
    2783             : 
    2784           0 :         sal_Int32 nReformat = std::min<sal_Int32>( txtFmtInfo.GetReformatStart(), nOldLineEnd );
    2785             : 
    2786             :         // in case we do not have any fly in our line, our repaint position
    2787             :         // is the changed position - 1
    2788           0 :         if ( rFlyStarts.empty() && ! rCurr.IsFly() )
    2789             :         {
    2790             :             // this is the maximum repaint offset determined during formatting
    2791             :             // for example: the beginning of the first right tab stop
    2792             :             // if this value is 0, this means that we do not have an upper
    2793             :             // limit for the repaint offset
    2794           0 :             const long nFormatRepaint = txtFmtInfo.GetPaintOfst();
    2795             : 
    2796           0 :             if ( nReformat < txtFmtInfo.GetLineStart() + 3 )
    2797           0 :                 return 0;
    2798             : 
    2799             :             // step back two positions for smoother repaint
    2800           0 :             nReformat -= 2;
    2801             : 
    2802             :     #ifndef MACOSX
    2803             :     #if ! ENABLE_GRAPHITE
    2804             :             // #i28795#, #i34607#, #i38388#
    2805             :             // step back six(!) more characters for complex scripts
    2806             :             // this is required e.g., for Khmer (thank you, Javier!)
    2807             :             const SwScriptInfo& rSI = txtFmtInfo.GetParaPortion()->GetScriptInfo();
    2808             :             sal_Int32 nMaxContext = 0;
    2809             :             if( ::i18n::ScriptType::COMPLEX == rSI.ScriptType( nReformat ) )
    2810             :                 nMaxContext = 6;
    2811             :     #else
    2812             :             // Some Graphite fonts need context for scripts not marked as complex
    2813             :             static const sal_Int32 nMaxContext = 10;
    2814             :     #endif
    2815             :     #else
    2816             :             // some fonts like Quartz's Zapfino need more context
    2817             :             // TODO: query FontInfo for maximum unicode context
    2818             :             static const sal_Int32 nMaxContext = 8;
    2819             :     #endif
    2820             :             if( nMaxContext > 0 )
    2821             :             {
    2822           0 :                 if ( nReformat > txtFmtInfo.GetLineStart() + nMaxContext )
    2823           0 :                     nReformat = nReformat - nMaxContext;
    2824             :                 else
    2825           0 :                     nReformat = txtFmtInfo.GetLineStart();
    2826             :             }
    2827             : 
    2828             :             // Weird situation: Our line used to end with a hole portion
    2829             :             // and we delete some characters at the end of our line. We have
    2830             :             // to take care for repainting the blanks which are not anymore
    2831             :             // covered by the hole portion
    2832           0 :             while ( nReformat > txtFmtInfo.GetLineStart() &&
    2833           0 :                     CH_BLANK == txtFmtInfo.GetChar( nReformat ) )
    2834           0 :                 --nReformat;
    2835             : 
    2836             :             OSL_ENSURE( nReformat < txtFmtInfo.GetIdx(), "Reformat too small for me!" );
    2837           0 :             SwRect aRect;
    2838             : 
    2839             :             // Note: GetChareRect is not const. It definitely changes the
    2840             :             // bMulti flag. We have to save and resore the old value.
    2841           0 :             bool bOldMulti = txtFmtInfo.IsMulti();
    2842           0 :             rThis.GetCharRect( &aRect, nReformat );
    2843           0 :             txtFmtInfo.SetMulti( bOldMulti );
    2844             : 
    2845           0 :             return nFormatRepaint ? std::min( aRect.Left(), nFormatRepaint ) :
    2846           0 :                                     aRect.Left();
    2847             :         }
    2848             :         else
    2849             :         {
    2850             :             // nReformat may be wrong, if something around flys has changed:
    2851             :             // we compare the former and the new fly positions in this line
    2852             :             // if anything has changed, we carefully have to adjust the right
    2853             :             // repaint position
    2854           0 :             long nPOfst = 0;
    2855           0 :             sal_uInt16 nCnt = 0;
    2856           0 :             sal_uInt16 nX = 0;
    2857           0 :             sal_uInt16 nIdx = rThis.GetInfo().GetLineStart();
    2858           0 :             SwLinePortion* pPor = rCurr.GetFirstPortion();
    2859             : 
    2860           0 :             while ( pPor )
    2861             :             {
    2862           0 :                 if ( pPor->IsFlyPortion() )
    2863             :                 {
    2864             :                     // compare start of fly with former start of fly
    2865           0 :                     if (nCnt < rFlyStarts.size() &&
    2866           0 :                         nX == rFlyStarts[ nCnt ] &&
    2867           0 :                         nIdx < nReformat
    2868             :                     )
    2869             :                         // found fix position, nothing has changed left from nX
    2870           0 :                         nPOfst = nX + pPor->Width();
    2871             :                     else
    2872           0 :                         break;
    2873             : 
    2874           0 :                     nCnt++;
    2875             :                 }
    2876           0 :                 nX = nX + pPor->Width();
    2877           0 :                 nIdx = nIdx + pPor->GetLen();
    2878           0 :                 pPor = pPor->GetPortion();
    2879             :             }
    2880             : 
    2881           0 :             return nPOfst + rThis.GetLeftMargin();
    2882           0 :         }
    2883             :     }
    2884             : 
    2885             :     // Determine if we need to build hidden portions
    2886           0 :     bool lcl_BuildHiddenPortion( const SwTxtSizeInfo& rInf, sal_Int32 &rPos )
    2887             :     {
    2888             :         // Only if hidden text should not be shown:
    2889             :     //    if ( rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar() )
    2890           0 :         const bool bShowInDocView = rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar();
    2891           0 :         const bool bShowForPrinting = rInf.GetOpt().IsShowHiddenChar( true ) && rInf.GetOpt().IsPrinting();
    2892           0 :         if (bShowInDocView || bShowForPrinting)
    2893           0 :             return false;
    2894             : 
    2895           0 :         const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
    2896             :         sal_Int32 nHiddenStart;
    2897             :         sal_Int32 nHiddenEnd;
    2898           0 :         rSI.GetBoundsOfHiddenRange( rPos, nHiddenStart, nHiddenEnd );
    2899           0 :         if ( nHiddenEnd )
    2900             :         {
    2901           0 :             rPos = nHiddenEnd;
    2902           0 :             return true;
    2903             :         }
    2904             : 
    2905           0 :         return false;
    2906             :     }
    2907             : 
    2908           0 :     bool lcl_HasSameBorder(const SwFont& rFirst, const SwFont& rSecond)
    2909             :     {
    2910             :         return
    2911           0 :             rFirst.GetTopBorder() == rSecond.GetTopBorder() &&
    2912           0 :             rFirst.GetBottomBorder() == rSecond.GetBottomBorder() &&
    2913           0 :             rFirst.GetLeftBorder() == rSecond.GetLeftBorder() &&
    2914           0 :             rFirst.GetRightBorder() == rSecond.GetRightBorder() &&
    2915           0 :             rFirst.GetTopBorderDist() == rSecond.GetTopBorderDist() &&
    2916           0 :             rFirst.GetBottomBorderDist() == rSecond.GetBottomBorderDist() &&
    2917           0 :             rFirst.GetLeftBorderDist() == rSecond.GetLeftBorderDist() &&
    2918           0 :             rFirst.GetRightBorderDist() == rSecond.GetRightBorderDist() &&
    2919           0 :             rFirst.GetOrientation() == rSecond.GetOrientation() &&
    2920           0 :             rFirst.GetShadowColor() == rSecond.GetShadowColor() &&
    2921           0 :             rFirst.GetShadowWidth() == rSecond.GetShadowWidth() &&
    2922           0 :             rFirst.GetShadowLocation() == rSecond.GetShadowLocation();
    2923             :     }
    2924             : 
    2925             : } //end unnamed namespace
    2926             : 
    2927             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10