LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/text - frmform.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 367 906 40.5 %
Date: 2012-12-27 Functions: 16 24 66.7 %
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             : 
      21             : #include <hintids.hxx>
      22             : #include <editeng/keepitem.hxx>
      23             : #include <editeng/hyznitem.hxx>
      24             : #include <pagefrm.hxx>      // ChangeFtnRef
      25             : #include <ndtxt.hxx>        // MakeFrm()
      26             : #include <dcontact.hxx>     // SwDrawContact
      27             : #include <dflyobj.hxx>      // SwVirtFlyDrawObj
      28             : #include <flyfrm.hxx>
      29             : #include <ftnfrm.hxx>       // SwFtnFrm
      30             : #include <txtftn.hxx>
      31             : #include <fmtftn.hxx>
      32             : #include <paratr.hxx>
      33             : #include <viewopt.hxx>      // SwViewOptions
      34             : #include <viewsh.hxx>       // ViewShell
      35             : #include <frmatr.hxx>
      36             : #include <pam.hxx>
      37             : #include <flyfrms.hxx>
      38             : #include <fmtanchr.hxx>
      39             : #include <itrform2.hxx>     // SwTxtFormatter
      40             : #include <widorp.hxx>       // Widows and Orphans
      41             : #include <txtcache.hxx>
      42             : #include <porrst.hxx>       // SwEmptyPortion
      43             : #include <blink.hxx>        // pBlink
      44             : #include <porfld.hxx>       // SwFldPortion
      45             : #include <sectfrm.hxx>      // SwSectionFrm
      46             : #include <pormulti.hxx>     // SwMultiPortion
      47             : 
      48             : #include <rootfrm.hxx>
      49             : #include <frmfmt.hxx>       // SwFrmFmt
      50             : // OD 2004-05-24 #i28701#
      51             : #include <sortedobjs.hxx>
      52             : 
      53             : // Tolerance in formatting and text output
      54             : #define SLOPPY_TWIPS    5
      55             : 
      56             : class FormatLevel
      57             : {
      58             :     static MSHORT nLevel;
      59             : public:
      60         784 :     inline FormatLevel()  { ++nLevel; }
      61         784 :     inline ~FormatLevel() { --nLevel; }
      62         784 :     inline MSHORT GetLevel() const { return nLevel; }
      63           0 :     static bool LastLevel() { return 10 < nLevel; }
      64             : };
      65             : MSHORT FormatLevel::nLevel = 0;
      66             : 
      67           5 : void ValidateTxt( SwFrm *pFrm )     // Friend of frame
      68             : {
      69          10 :     if ( ( ! pFrm->IsVertical() &&
      70           5 :              pFrm->Frm().Width() == pFrm->GetUpper()->Prt().Width() ) ||
      71           0 :          (   pFrm->IsVertical() &&
      72           0 :              pFrm->Frm().Height() == pFrm->GetUpper()->Prt().Height() ) )
      73           5 :         pFrm->bValidSize = sal_True;
      74           5 : }
      75             : 
      76           5 : void SwTxtFrm::ValidateFrm()
      77             : {
      78             :     // Validate surroundings to avoid oscillation
      79           5 :     SWAP_IF_SWAPPED( this )
      80             : 
      81           5 :     if ( !IsInFly() && !IsInTab() )
      82             :     {   // Only validate 'this' when inside a fly, the rest should actually only be
      83             :         // needed for footnotes, which do not exist in flys.
      84           5 :         SwSectionFrm* pSct = FindSctFrm();
      85           5 :         if( pSct )
      86             :         {
      87           0 :             if( !pSct->IsColLocked() )
      88           0 :                 pSct->ColLock();
      89             :             else
      90           0 :                 pSct = NULL;
      91             :         }
      92             : 
      93           5 :         SwFrm *pUp = GetUpper();
      94           5 :         pUp->Calc();
      95           5 :         if( pSct )
      96           0 :             pSct->ColUnlock();
      97             :     }
      98           5 :     ValidateTxt( this );
      99             : 
     100             :     // We at least have to save the MustFit flag!
     101             :     OSL_ENSURE( HasPara(), "ResetPreps(), missing ParaPortion." );
     102           5 :     SwParaPortion *pPara = GetPara();
     103           5 :     const sal_Bool bMustFit = pPara->IsPrepMustFit();
     104           5 :     ResetPreps();
     105           5 :     pPara->SetPrepMustFit( bMustFit );
     106             : 
     107           5 :     UNDO_SWAP( this )
     108           5 : }
     109             : 
     110             : /*************************************************************************
     111             :  * ValidateBodyFrm()
     112             :  * After a RemoveFtn the BodyFrm and all Frms contained within it, need to be
     113             :  * recalculated, so that the DeadLine is right.
     114             :  * First we search outwards, on the way back we calculate everything.
     115             : *************************************************************************/
     116             : 
     117           5 : void _ValidateBodyFrm( SwFrm *pFrm )
     118             : {
     119           5 :     if( pFrm && !pFrm->IsCellFrm() )
     120             :     {
     121           5 :         if( !pFrm->IsBodyFrm() && pFrm->GetUpper() )
     122           0 :             _ValidateBodyFrm( pFrm->GetUpper() );
     123           5 :         if( !pFrm->IsSctFrm() )
     124           5 :             pFrm->Calc();
     125             :         else
     126             :         {
     127           0 :             sal_Bool bOld = ((SwSectionFrm*)pFrm)->IsCntntLocked();
     128           0 :             ((SwSectionFrm*)pFrm)->SetCntntLock( sal_True );
     129           0 :             pFrm->Calc();
     130           0 :             if( !bOld )
     131           0 :                 ((SwSectionFrm*)pFrm)->SetCntntLock( sal_False );
     132             :         }
     133             :     }
     134           5 : }
     135             : 
     136           5 : void SwTxtFrm::ValidateBodyFrm()
     137             : {
     138           5 :     SWAP_IF_SWAPPED( this )
     139             : 
     140             :      // See comment in ValidateFrm()
     141          15 :     if ( !IsInFly() && !IsInTab() &&
     142           5 :          !( IsInSct() && FindSctFrm()->Lower()->IsColumnFrm() ) )
     143           5 :         _ValidateBodyFrm( GetUpper() );
     144             : 
     145           5 :     UNDO_SWAP( this )
     146           5 : }
     147             : 
     148           0 : sal_Bool SwTxtFrm::_GetDropRect( SwRect &rRect ) const
     149             : {
     150           0 :     SWAP_IF_NOT_SWAPPED( this )
     151             : 
     152             :     OSL_ENSURE( HasPara(), "SwTxtFrm::_GetDropRect: try again next year." );
     153           0 :     SwTxtSizeInfo aInf( (SwTxtFrm*)this );
     154           0 :     SwTxtMargin aLine( (SwTxtFrm*)this, &aInf );
     155           0 :     if( aLine.GetDropLines() )
     156             :     {
     157           0 :         rRect.Top( aLine.Y() );
     158           0 :         rRect.Left( aLine.GetLineStart() );
     159           0 :         rRect.Height( aLine.GetDropHeight() );
     160           0 :         rRect.Width( aLine.GetDropLeft() );
     161             : 
     162           0 :         if ( IsRightToLeft() )
     163           0 :             SwitchLTRtoRTL( rRect );
     164             : 
     165           0 :         if ( IsVertical() )
     166           0 :             SwitchHorizontalToVertical( rRect );
     167           0 :         UNDO_SWAP( this )
     168           0 :         return sal_True;
     169             :     }
     170             : 
     171           0 :     UNDO_SWAP( this )
     172             : 
     173           0 :     return sal_False;
     174             : }
     175             : 
     176         664 : const SwBodyFrm *SwTxtFrm::FindBodyFrm() const
     177             : {
     178         664 :     if ( IsInDocBody() )
     179             :     {
     180         555 :         const SwFrm *pFrm = GetUpper();
     181        1646 :         while( pFrm && !pFrm->IsBodyFrm() )
     182         536 :             pFrm = pFrm->GetUpper();
     183         555 :         return (const SwBodyFrm*)pFrm;
     184             :     }
     185         109 :     return 0;
     186             : }
     187             : 
     188           0 : sal_Bool SwTxtFrm::CalcFollow( const xub_StrLen nTxtOfst )
     189             : {
     190           0 :     SWAP_IF_SWAPPED( this )
     191             : 
     192             :     OSL_ENSURE( HasFollow(), "CalcFollow: missing Follow." );
     193             : 
     194           0 :     SwTxtFrm* pMyFollow = GetFollow();
     195             : 
     196           0 :     SwParaPortion *pPara = GetPara();
     197           0 :     sal_Bool bFollowFld = pPara ? pPara->IsFollowField() : sal_False;
     198             : 
     199           0 :     if( !pMyFollow->GetOfst() || pMyFollow->GetOfst() != nTxtOfst ||
     200           0 :         bFollowFld || pMyFollow->IsFieldFollow() ||
     201           0 :         ( pMyFollow->IsVertical() && !pMyFollow->Prt().Width() ) ||
     202           0 :         ( ! pMyFollow->IsVertical() && !pMyFollow->Prt().Height() ) )
     203             :     {
     204             : #if OSL_DEBUG_LEVEL > 0
     205             :         const SwFrm *pOldUp = GetUpper();
     206             : #endif
     207             : 
     208           0 :         SWRECTFN ( this )
     209           0 :         SwTwips nOldBottom = (GetUpper()->Frm().*fnRect->fnGetBottom)();
     210           0 :         SwTwips nMyPos = (Frm().*fnRect->fnGetTop)();
     211             : 
     212           0 :         const SwPageFrm *pPage = 0;
     213           0 :         sal_Bool  bOldInvaCntnt = sal_True;
     214           0 :         if ( !IsInFly() && GetNext() )
     215             :         {
     216           0 :             pPage = FindPageFrm();
     217             :             // Minimize = that is set back if needed - for invalidation see below
     218           0 :             bOldInvaCntnt  = pPage->IsInvalidCntnt();
     219             :         }
     220             : 
     221           0 :         pMyFollow->_SetOfst( nTxtOfst );
     222           0 :         pMyFollow->SetFieldFollow( bFollowFld );
     223           0 :         if( HasFtn() || pMyFollow->HasFtn() )
     224             :         {
     225           0 :             ValidateFrm();
     226           0 :             ValidateBodyFrm();
     227           0 :             if( pPara )
     228             :             {
     229           0 :                 *(pPara->GetReformat()) = SwCharRange();
     230           0 :                 *(pPara->GetDelta()) = 0;
     231             :             }
     232             :         }
     233             : 
     234             :         // The footnote area must not get larger
     235           0 :         SwSaveFtnHeight aSave( FindFtnBossFrm( sal_True ), LONG_MAX );
     236             : 
     237           0 :         pMyFollow->CalcFtnFlag();
     238           0 :         if ( !pMyFollow->GetNext() && !pMyFollow->HasFtn() )
     239           0 :             nOldBottom = bVert ? 0 : LONG_MAX;
     240             : 
     241           0 :         while( true )
     242             :         {
     243           0 :             if( !FormatLevel::LastLevel() )
     244             :             {
     245             :                 // If the follow is contained within a column section or column
     246             :                 // frame, we need to calculate that first. This is because the
     247             :                 // FormatWidthCols() does not work if it is called from MakeAll
     248             :                 // of the _locked_ follow.
     249           0 :                 SwSectionFrm* pSct = pMyFollow->FindSctFrm();
     250           0 :                 if( pSct && !pSct->IsAnLower( this ) )
     251             :                 {
     252           0 :                     if( pSct->GetFollow() )
     253           0 :                         pSct->SimpleFormat();
     254           0 :                     else if( ( pSct->IsVertical() && !pSct->Frm().Width() ) ||
     255           0 :                              ( ! pSct->IsVertical() && !pSct->Frm().Height() ) )
     256           0 :                         break;
     257             :                 }
     258             :                 // OD 14.03.2003 #i11760# - intrinsic format of follow is controlled.
     259           0 :                 if ( FollowFormatAllowed() )
     260             :                 {
     261             :                     // OD 14.03.2003 #i11760# - no nested format of follows, if
     262             :                     // text frame is contained in a column frame.
     263             :                     // Thus, forbid intrinsic format of follow.
     264             :                     {
     265           0 :                         bool bIsFollowInColumn = false;
     266           0 :                         SwFrm* pFollowUpper = pMyFollow->GetUpper();
     267           0 :                         while ( pFollowUpper )
     268             :                         {
     269           0 :                             if ( pFollowUpper->IsColumnFrm() )
     270             :                             {
     271           0 :                                 bIsFollowInColumn = true;
     272           0 :                                 break;
     273             :                             }
     274           0 :                             if ( pFollowUpper->IsPageFrm() ||
     275           0 :                                  pFollowUpper->IsFlyFrm() )
     276             :                             {
     277           0 :                                 break;
     278             :                             }
     279           0 :                             pFollowUpper = pFollowUpper->GetUpper();
     280             :                         }
     281           0 :                         if ( bIsFollowInColumn )
     282             :                         {
     283           0 :                             pMyFollow->ForbidFollowFormat();
     284             :                         }
     285             :                     }
     286             : 
     287           0 :                     pMyFollow->Calc();
     288             :                     // The Follow can tell from its Frm().Height() that something went wrong
     289             :                     OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: cheesy follow" );
     290           0 :                     if( pMyFollow->GetPrev() )
     291             :                     {
     292           0 :                         pMyFollow->Prepare( PREP_CLEAR );
     293           0 :                         pMyFollow->Calc();
     294             :                         OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: very cheesy follow" );
     295             :                     }
     296             : 
     297             :                     // OD 14.03.2003 #i11760# - reset control flag for follow format.
     298           0 :                     pMyFollow->AllowFollowFormat();
     299             :                 }
     300             : 
     301             :                 // Make sure that the Follow gets painted
     302           0 :                 pMyFollow->SetCompletePaint();
     303             :             }
     304             : 
     305           0 :             pPara = GetPara();
     306             :             // As long as the Follow is requested due to orphan lines, it is passed these
     307             :             // and is reformatted if possible
     308           0 :             if( pPara && pPara->IsPrepWidows() )
     309           0 :                 CalcPreps();
     310             :             else
     311           0 :                 break;
     312             :         }
     313             : 
     314           0 :         if( HasFtn() || pMyFollow->HasFtn() )
     315             :         {
     316           0 :             ValidateBodyFrm();
     317           0 :             ValidateFrm();
     318           0 :             if( pPara )
     319             :             {
     320           0 :                 *(pPara->GetReformat()) = SwCharRange();
     321           0 :                 *(pPara->GetDelta()) = 0;
     322             :             }
     323             :         }
     324             : 
     325           0 :         if ( pPage )
     326             :         {
     327           0 :             if ( !bOldInvaCntnt )
     328           0 :                 pPage->ValidateCntnt();
     329             :         }
     330             : 
     331             : #if OSL_DEBUG_LEVEL > 0
     332             :         OSL_ENSURE( pOldUp == GetUpper(), "SwTxtFrm::CalcFollow: heavy follow" );
     333             : #endif
     334             : 
     335             :         const long nRemaining =
     336           0 :                  - (GetUpper()->Frm().*fnRect->fnBottomDist)( nOldBottom );
     337           0 :         if (  nRemaining > 0 && !GetUpper()->IsSctFrm() &&
     338             :               nRemaining != ( bVert ?
     339           0 :                               nMyPos - Frm().Right() :
     340           0 :                               Frm().Top() - nMyPos ) )
     341             :         {
     342           0 :             UNDO_SWAP( this )
     343           0 :             return sal_True;
     344           0 :         }
     345             :     }
     346             : 
     347           0 :     UNDO_SWAP( this )
     348             : 
     349           0 :     return sal_False;
     350             : }
     351             : 
     352         982 : void SwTxtFrm::AdjustFrm( const SwTwips nChgHght, sal_Bool bHasToFit )
     353             : {
     354         982 :     if( IsUndersized() )
     355             :     {
     356          27 :         if( GetOfst() && !IsFollow() ) // A scrolled paragraph (undersized)
     357           0 :             return;
     358          27 :         SetUndersized( nChgHght == 0 || bHasToFit );
     359             :     }
     360             : 
     361             :     // AdjustFrm is called with a swapped frame during
     362             :     // formatting but the frame is not swapped during FormatEmpty
     363         982 :     SWAP_IF_SWAPPED( this )
     364         982 :     SWRECTFN ( this )
     365             : 
     366             :     // The Frame's size variable is incremented by Grow or decremented by Shrink.
     367             :     // If the size cannot change, nothing should happen!
     368         982 :     if( nChgHght >= 0)
     369             :     {
     370         982 :         SwTwips nChgHeight = nChgHght;
     371         982 :         if( nChgHght && !bHasToFit )
     372             :         {
     373         875 :             if( IsInFtn() && !IsInSct() )
     374             :             {
     375           5 :                 SwTwips nReal = Grow( nChgHght, sal_True );
     376           5 :                 if( nReal < nChgHght )
     377             :                 {
     378           0 :                     SwTwips nBot = (*fnRect->fnYInc)( (Frm().*fnRect->fnGetBottom)(),
     379           0 :                                                       nChgHght - nReal );
     380           0 :                     SwFrm* pCont = FindFtnFrm()->GetUpper();
     381             : 
     382           0 :                     if( (pCont->Frm().*fnRect->fnBottomDist)( nBot ) > 0 )
     383             :                     {
     384           0 :                         (Frm().*fnRect->fnAddBottom)( nChgHght );
     385           0 :                         if( bVert )
     386           0 :                             Prt().SSize().Width() += nChgHght;
     387             :                         else
     388           0 :                             Prt().SSize().Height() += nChgHght;
     389           0 :                         UNDO_SWAP( this )
     390           0 :                         return;
     391             :                     }
     392             :                 }
     393             :             }
     394             : 
     395         875 :             Grow( nChgHght );
     396             : 
     397         875 :             if ( IsInFly() )
     398             :             {
     399             :                 // If one of the Upper is a Fly, it's very likely that this fly changes its
     400             :                 // position by the Grow. Therefore, my position has to be corrected also or
     401             :                 // the check further down is not meaningful.
     402             :                 // The predecessors need to be calculated, so that the position can be
     403             :                 // calculated correctly.
     404          29 :                 if ( GetPrev() )
     405             :                 {
     406           7 :                     SwFrm *pPre = GetUpper()->Lower();
     407          10 :                     do
     408          10 :                     {   pPre->Calc();
     409          10 :                         pPre = pPre->GetNext();
     410             :                     } while ( pPre && pPre != this );
     411             :                 }
     412          29 :                 const Point aOldPos( Frm().Pos() );
     413          29 :                 MakePos();
     414          29 :                 if ( aOldPos != Frm().Pos() )
     415             :                 {
     416             :                     // OD 2004-07-01 #i28701# - use new method <SwFrm::InvalidateObjs(..)>
     417             :                     // No format is performed for the floating screen objects.
     418           0 :                     InvalidateObjs( true );
     419             :                 }
     420             :             }
     421         875 :             nChgHeight = 0;
     422             :         }
     423             :         // A Grow() is always accepted by the Layout, even if the
     424             :         // FixSize of the surrounding layout frame should not allow it.
     425             :         // We text for this case and correct the values.
     426             :         // The Frm must NOT be shrinked further than its size permits
     427             :         // even in the case of an emergency.
     428             :         SwTwips nRstHeight;
     429         982 :         if ( IsVertical() )
     430             :         {
     431             :             OSL_ENSURE( ! IsSwapped(),"Swapped frame while calculating nRstHeight" );
     432             : 
     433             :             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     434           0 :             if ( IsVertLR() )
     435           0 :                     nRstHeight = GetUpper()->Frm().Left()
     436           0 :                                + GetUpper()->Prt().Left()
     437           0 :                                + GetUpper()->Prt().Width()
     438           0 :                                - Frm().Left();
     439             :             else
     440           0 :                 nRstHeight = Frm().Left() + Frm().Width() -
     441           0 :                             ( GetUpper()->Frm().Left() + GetUpper()->Prt().Left() );
     442             :          }
     443             :         else
     444         982 :             nRstHeight = GetUpper()->Frm().Top()
     445         982 :                        + GetUpper()->Prt().Top()
     446         982 :                        + GetUpper()->Prt().Height()
     447        1964 :                        - Frm().Top();
     448             : 
     449             :         // We can get a bit of space in table cells, because there could be some
     450             :         // left through a vertical alignment to the top.
     451             :         // #115759# - assure, that first lower in upper
     452             :         // is the current one or is valid.
     453        1324 :         if ( IsInTab() &&
     454         341 :              ( GetUpper()->Lower() == this ||
     455           1 :                GetUpper()->Lower()->IsValid() ) )
     456             :         {
     457         682 :             long nAdd = (*fnRect->fnYDiff)( (GetUpper()->Lower()->Frm().*fnRect->fnGetTop)(),
     458        1023 :                                             (GetUpper()->*fnRect->fnGetPrtTop)() );
     459             :             OSL_ENSURE( nAdd >= 0, "Ey" );
     460         341 :             nRstHeight += nAdd;
     461             :         }
     462             : 
     463             : /* ------------------------------------
     464             :  * nRstHeight < 0 means that the TxtFrm is located completely outside of its Upper.
     465             :  * This can happen, if it's located within a FlyAtCntFrm, which changed sides by a
     466             :  * Grow(). In such a case, it's wrong to execute the following Grow().
     467             :  * In the case of a bug, we end up with an infinite loop.
     468             :  * -----------------------------------*/
     469         982 :         SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
     470         982 :         SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
     471             : 
     472         982 :         if( nRstHeight < nFrmHeight )
     473             :         {
     474             :             // It can be that I have the right size, but the Upper is too small and can get me some room
     475          29 :             if( ( nRstHeight >= 0 || ( IsInFtn() && IsInSct() ) ) && !bHasToFit )
     476          29 :                 nRstHeight += GetUpper()->Grow( nFrmHeight - nRstHeight );
     477             :             // In column sections we do not want to get too big or else more areas are created by
     478             :             // GetNextSctLeaf. Instead, we shrink and remember bUndersized, so that FormatWidthCols
     479             :             // can calculate the right column size.
     480          29 :             if ( nRstHeight < nFrmHeight )
     481             :             {
     482          31 :                 if( bHasToFit || !IsMoveable() ||
     483           2 :                     ( IsInSct() && !FindSctFrm()->MoveAllowed(this) ) )
     484             :                 {
     485          28 :                     SetUndersized( sal_True );
     486          28 :                     Shrink( Min( ( nFrmHeight - nRstHeight), nPrtHeight ) );
     487             :                 }
     488             :                 else
     489           1 :                     SetUndersized( sal_False );
     490             :             }
     491             :         }
     492         953 :         else if( nChgHeight )
     493             :         {
     494           0 :             if( nRstHeight - nFrmHeight < nChgHeight )
     495           0 :                 nChgHeight = nRstHeight - nFrmHeight;
     496           0 :             if( nChgHeight )
     497           0 :                 Grow( nChgHeight );
     498             :         }
     499             :     }
     500             :     else
     501           0 :         Shrink( -nChgHght );
     502             : 
     503         982 :     UNDO_SWAP( this )
     504             : }
     505             : 
     506             : /*************************************************************************
     507             :  * SwTxtFrm::AdjustFollow()
     508             :  * AdjustFollow expects the following situation:
     509             :  * The SwTxtIter points to the lower end of the Master, the Offset is set in
     510             :  * the Follow.
     511             :  * nOffset holds the Offset in the text string, from which the Master closes
     512             :  * and the Follow starts.
     513             :  * If it's 0, the FollowFrame is deleted.
     514             :  *************************************************************************/
     515             : 
     516          10 : void SwTxtFrm::_AdjustFollow( SwTxtFormatter &rLine,
     517             :                              const xub_StrLen nOffset, const xub_StrLen nEnd,
     518             :                              const sal_uInt8 nMode )
     519             : {
     520          10 :     SwFrmSwapper aSwapper( this, sal_False );
     521             : 
     522             :     // We got the rest of the text mass: Delete all Follows
     523             :     // DummyPortions() are a special case.
     524             :     // Special cases are controlled by parameter <nMode>.
     525          10 :     if( HasFollow() && !(nMode & 1) && nOffset == nEnd )
     526             :     {
     527           0 :         while( GetFollow() )
     528             :         {
     529           0 :             if( ((SwTxtFrm*)GetFollow())->IsLocked() )
     530             :             {
     531             :                 OSL_FAIL( "+SwTxtFrm::JoinFrm: Follow is locked." );
     532             :                 return;
     533             :             }
     534           0 :             JoinFrm();
     535             :         }
     536             : 
     537             :         return;
     538             :     }
     539             : 
     540             :     // Dancing on the volcano: We'll just format the last line quickly
     541             :     // for the QuoVadis stuff.
     542             :     // The Offset can move of course:
     543          20 :     const xub_StrLen nNewOfst = ( IsInFtn() && ( !GetIndNext() || HasFollow() ) ) ?
     544          20 :                             rLine.FormatQuoVadis(nOffset) : nOffset;
     545             : 
     546          10 :     if( !(nMode & 1) )
     547             :     {
     548             :         // We steal text mass from our Follows
     549             :         // It can happen that we have to join some of them
     550          20 :         while( GetFollow() && GetFollow()->GetFollow() &&
     551           0 :                nNewOfst >= GetFollow()->GetFollow()->GetOfst() )
     552             :         {
     553           0 :             JoinFrm();
     554             :         }
     555             :     }
     556             : 
     557             :     // The Offset moved
     558          10 :     if( GetFollow() )
     559             :     {
     560             : #if OSL_DEBUG_LEVEL > 1
     561             :         static bool bTest = false;
     562             :         if( !bTest || ( nMode & 1 ) )
     563             : #endif
     564           0 :         if ( nMode )
     565           0 :             GetFollow()->ManipOfst( 0 );
     566             : 
     567           0 :         if ( CalcFollow( nNewOfst ) )   // CalcFollow only at the end, we do a SetOfst there
     568           0 :             rLine.SetOnceMore( sal_True );
     569          10 :     }
     570             : }
     571             : 
     572           0 : SwCntntFrm *SwTxtFrm::JoinFrm()
     573             : {
     574             :     OSL_ENSURE( GetFollow(), "+SwTxtFrm::JoinFrm: no follow" );
     575           0 :     SwTxtFrm  *pFoll = GetFollow();
     576             : 
     577           0 :     SwTxtFrm *pNxt = pFoll->GetFollow();
     578             : 
     579             :     // All footnotes of the to-be-destroyed Follow are relocated to us
     580           0 :     xub_StrLen nStart = pFoll->GetOfst();
     581           0 :     if ( pFoll->HasFtn() )
     582             :     {
     583           0 :         const SwpHints *pHints = pFoll->GetTxtNode()->GetpSwpHints();
     584           0 :         if( pHints )
     585             :         {
     586           0 :             SwFtnBossFrm *pFtnBoss = 0;
     587           0 :             SwFtnBossFrm *pEndBoss = 0;
     588           0 :             for ( sal_uInt16 i = 0; i < pHints->Count(); ++i )
     589             :             {
     590           0 :                 const SwTxtAttr *pHt = (*pHints)[i];
     591           0 :                 if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nStart )
     592             :                 {
     593           0 :                     if( pHt->GetFtn().IsEndNote() )
     594             :                     {
     595           0 :                         if( !pEndBoss )
     596           0 :                             pEndBoss = pFoll->FindFtnBossFrm();
     597           0 :                         pEndBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this );
     598             :                     }
     599             :                     else
     600             :                     {
     601           0 :                         if( !pFtnBoss )
     602           0 :                             pFtnBoss = pFoll->FindFtnBossFrm( sal_True );
     603           0 :                         pFtnBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this );
     604             :                     }
     605           0 :                     SetFtn( sal_True );
     606             :                 }
     607             :             }
     608             :         }
     609             :     }
     610             : 
     611             : #ifdef DBG_UTIL
     612             :     else if ( pFoll->GetValidPrtAreaFlag() ||
     613             :               pFoll->GetValidSizeFlag() )
     614             :     {
     615             :         pFoll->CalcFtnFlag();
     616             :         OSL_ENSURE( !pFoll->HasFtn(), "Missing FtnFlag." );
     617             :     }
     618             : #endif
     619             : 
     620           0 :     pFoll->MoveFlyInCnt( this, nStart, STRING_LEN );
     621           0 :     pFoll->SetFtn( sal_False );
     622             :     // #i27138#
     623             :     // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
     624             :     // Relation CONTENT_FLOWS_FROM for current next paragraph will change
     625             :     // and relation CONTENT_FLOWS_TO for current previous paragraph, which
     626             :     // is <this>, will change.
     627             :     {
     628           0 :         ViewShell* pViewShell( pFoll->getRootFrm()->GetCurrShell() );
     629           0 :         if ( pViewShell && pViewShell->GetLayout() &&
     630           0 :              pViewShell->GetLayout()->IsAnyShellAccessible() )
     631             :         {
     632             :             pViewShell->InvalidateAccessibleParaFlowRelation(
     633           0 :                             dynamic_cast<SwTxtFrm*>(pFoll->FindNextCnt( true )),
     634           0 :                             this );
     635             :         }
     636             :     }
     637           0 :     pFoll->Cut();
     638           0 :     SetFollow(pNxt);
     639           0 :     delete pFoll;
     640           0 :     return pNxt;
     641             : }
     642             : 
     643           0 : SwCntntFrm *SwTxtFrm::SplitFrm( const xub_StrLen nTxtPos )
     644             : {
     645           0 :     SWAP_IF_SWAPPED( this )
     646             : 
     647             :     // The Paste sends a Modify() to me
     648             :     // I lock myself, so that my data does not disappear
     649           0 :     SwTxtFrmLocker aLock( this );
     650           0 :     SwTxtFrm *pNew = (SwTxtFrm *)(GetTxtNode()->MakeFrm( this ));
     651             : 
     652           0 :     pNew->SetFollow( GetFollow() );
     653           0 :     SetFollow( pNew );
     654             : 
     655           0 :     pNew->Paste( GetUpper(), GetNext() );
     656             :     // #i27138#
     657             :     // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
     658             :     // Relation CONTENT_FLOWS_FROM for current next paragraph will change
     659             :     // and relation CONTENT_FLOWS_TO for current previous paragraph, which
     660             :     // is <this>, will change.
     661             :     {
     662           0 :         ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
     663           0 :         if ( pViewShell && pViewShell->GetLayout() &&
     664           0 :              pViewShell->GetLayout()->IsAnyShellAccessible() )
     665             :         {
     666             :             pViewShell->InvalidateAccessibleParaFlowRelation(
     667           0 :                             dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
     668           0 :                             this );
     669             :         }
     670             :     }
     671             : 
     672             :     // If footnotes end up in pNew bz our actions, we need
     673             :     // to re-register them
     674           0 :     if ( HasFtn() )
     675             :     {
     676           0 :         const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
     677           0 :         if( pHints )
     678             :         {
     679           0 :             SwFtnBossFrm *pFtnBoss = 0;
     680           0 :             SwFtnBossFrm *pEndBoss = 0;
     681           0 :             for ( sal_uInt16 i = 0; i < pHints->Count(); ++i )
     682             :             {
     683           0 :                 const SwTxtAttr *pHt = (*pHints)[i];
     684           0 :                 if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nTxtPos )
     685             :                 {
     686           0 :                     if( pHt->GetFtn().IsEndNote() )
     687             :                     {
     688           0 :                         if( !pEndBoss )
     689           0 :                             pEndBoss = FindFtnBossFrm();
     690           0 :                         pEndBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew );
     691             :                     }
     692             :                     else
     693             :                     {
     694           0 :                         if( !pFtnBoss )
     695           0 :                             pFtnBoss = FindFtnBossFrm( sal_True );
     696           0 :                         pFtnBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew );
     697             :                     }
     698           0 :                     pNew->SetFtn( sal_True );
     699             :                 }
     700             :             }
     701             :         }
     702             :     }
     703             : 
     704             : #ifdef DBG_UTIL
     705             :     else
     706             :     {
     707             :         CalcFtnFlag( nTxtPos-1 );
     708             :         OSL_ENSURE( !HasFtn(), "Missing FtnFlag." );
     709             :     }
     710             : #endif
     711             : 
     712           0 :     MoveFlyInCnt( pNew, nTxtPos, STRING_LEN );
     713             : 
     714             :     // No SetOfst or CalcFollow, because an AdjustFollow follows immediately anyways
     715             : 
     716           0 :     pNew->ManipOfst( nTxtPos );
     717             : 
     718           0 :     UNDO_SWAP( this )
     719           0 :     return pNew;
     720             : }
     721             : 
     722           0 : void SwTxtFrm::_SetOfst( const xub_StrLen nNewOfst )
     723             : {
     724             :     // We do not need to invalidate out Follow.
     725             :     // We are a Follow, get formatted right away and call
     726             :     // SetOfst() from there
     727           0 :     nOfst = nNewOfst;
     728           0 :     SwParaPortion *pPara = GetPara();
     729           0 :     if( pPara )
     730             :     {
     731           0 :         SwCharRange &rReformat = *(pPara->GetReformat());
     732           0 :         rReformat.Start() = 0;
     733           0 :         rReformat.Len() = GetTxt().Len();
     734           0 :         *(pPara->GetDelta()) = rReformat.Len();
     735             :     }
     736           0 :     InvalidateSize();
     737           0 : }
     738             : 
     739         784 : sal_Bool SwTxtFrm::CalcPreps()
     740             : {
     741             :     OSL_ENSURE( ! IsVertical() || ! IsSwapped(), "SwTxtFrm::CalcPreps with swapped frame" );
     742         784 :     SWRECTFN( this );
     743             : 
     744         784 :     SwParaPortion *pPara = GetPara();
     745         784 :     if ( !pPara )
     746         631 :         return sal_False;
     747         153 :     sal_Bool bPrep = pPara->IsPrep();
     748         153 :     sal_Bool bPrepWidows = pPara->IsPrepWidows();
     749         153 :     sal_Bool bPrepAdjust = pPara->IsPrepAdjust();
     750         153 :     sal_Bool bPrepMustFit = pPara->IsPrepMustFit();
     751         153 :     ResetPreps();
     752             : 
     753         153 :     sal_Bool bRet = sal_False;
     754         153 :     if( bPrep && !pPara->GetReformat()->Len() )
     755             :     {
     756             :         // PREP_WIDOWS means that the orphans rule got activated in the Follow.
     757             :         // In unfortunate cases we could also have a PrepAdjust!
     758          19 :         if( bPrepWidows )
     759             :         {
     760           0 :             if( !GetFollow() )
     761             :             {
     762             :                 OSL_ENSURE( GetFollow(), "+SwTxtFrm::CalcPreps: no credits" );
     763           0 :                 return sal_False;
     764             :             }
     765             : 
     766             :             // We need to prepare for two cases:
     767             :             // We were able to hand over a few lines to the Follow
     768             :             // -> we need to shrink
     769             :             // or we need to go on the next page
     770             :             // -> we let our Frame become too big
     771             : 
     772           0 :             SwTwips nChgHeight = GetParHeight();
     773           0 :             if( nChgHeight >= (Prt().*fnRect->fnGetHeight)() )
     774             :             {
     775           0 :                 if( bPrepMustFit )
     776             :                 {
     777           0 :                     GetFollow()->SetJustWidow( sal_True );
     778           0 :                     GetFollow()->Prepare( PREP_CLEAR );
     779             :                 }
     780           0 :                 else if ( bVert )
     781             :                 {
     782           0 :                     Frm().Width( Frm().Width() + Frm().Left() );
     783           0 :                     Prt().Width( Prt().Width() + Frm().Left() );
     784           0 :                     Frm().Left( 0 );
     785           0 :                     SetWidow( sal_True );
     786             :                 }
     787             :                 else
     788             :                 {
     789           0 :                     SwTwips nTmp  = LONG_MAX - (Frm().Top()+10000);
     790           0 :                     SwTwips nDiff = nTmp - Frm().Height();
     791           0 :                     Frm().Height( nTmp );
     792           0 :                     Prt().Height( Prt().Height() + nDiff );
     793           0 :                     SetWidow( sal_True );
     794             :                 }
     795             :             }
     796             :             else
     797             :             {
     798             :                 OSL_ENSURE( nChgHeight < (Prt().*fnRect->fnGetHeight)(),
     799             :                         "+SwTxtFrm::CalcPrep: wanna shrink" );
     800             : 
     801           0 :                 nChgHeight = (Prt().*fnRect->fnGetHeight)() - nChgHeight;
     802             : 
     803           0 :                 GetFollow()->SetJustWidow( sal_True );
     804           0 :                 GetFollow()->Prepare( PREP_CLEAR );
     805           0 :                 Shrink( nChgHeight );
     806           0 :                 SwRect &rRepaint = *(pPara->GetRepaint());
     807             : 
     808           0 :                 if ( bVert )
     809             :                 {
     810           0 :                     SwRect aRepaint( Frm().Pos() + Prt().Pos(), Prt().SSize() );
     811           0 :                     SwitchVerticalToHorizontal( aRepaint );
     812           0 :                     rRepaint.Chg( aRepaint.Pos(), aRepaint.SSize() );
     813             :                 }
     814             :                 else
     815           0 :                     rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
     816             : 
     817           0 :                 if( 0 >= rRepaint.Width() )
     818           0 :                     rRepaint.Width(1);
     819             :             }
     820           0 :             bRet = sal_True;
     821             :         }
     822             : 
     823          19 :         else if ( bPrepAdjust )
     824             :         {
     825          19 :             if ( HasFtn() )
     826             :             {
     827           0 :                 if( !CalcPrepFtnAdjust() )
     828             :                 {
     829           0 :                     if( bPrepMustFit )
     830             :                     {
     831           0 :                         SwTxtLineAccess aAccess( this );
     832           0 :                         aAccess.GetPara()->SetPrepMustFit( sal_True );
     833             :                     }
     834           0 :                     return sal_False;
     835             :                 }
     836             :             }
     837             : 
     838          19 :             SWAP_IF_NOT_SWAPPED( this )
     839             : 
     840          19 :             SwTxtFormatInfo aInf( this );
     841          19 :             SwTxtFormatter aLine( this, &aInf );
     842             : 
     843          19 :             WidowsAndOrphans aFrmBreak( this );
     844             :             // Whatever the attributes say: we split the paragraph in
     845             :             // MustFit in any case
     846          19 :             if( bPrepMustFit )
     847             :             {
     848           0 :                 aFrmBreak.SetKeep( sal_False );
     849           0 :                 aFrmBreak.ClrOrphLines();
     850             :             }
     851             :             // Before calling FormatAdjust, we need to make sure
     852             :             // that the lines protruding at the bottom get indeed
     853             :             // truncated
     854          19 :             sal_Bool bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine );
     855          19 :             bRet = sal_True;
     856          42 :             while( !bBreak && aLine.Next() )
     857             :             {
     858           4 :                 bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine );
     859             :             }
     860          19 :             if( bBreak )
     861             :             {
     862             :                 // We run into troubles: when TruncLines get called, the
     863             :                 // conditions in IsInside change immediately such that
     864             :                 // IsBreakNow can return different results.
     865             :                 // For this reason, we make it clear to rFrmBreak, that the
     866             :                 // end is reached at the location of rLine.
     867             :                 // Let's see if it works ...
     868           0 :                 aLine.TruncLines();
     869           0 :                 aFrmBreak.SetRstHeight( aLine );
     870           0 :                 FormatAdjust( aLine, aFrmBreak, aInf.GetTxt().Len(), aInf.IsStop() );
     871             :             }
     872             :             else
     873             :             {
     874          19 :                 if( !GetFollow() )
     875             :                 {
     876             :                     FormatAdjust( aLine, aFrmBreak,
     877          19 :                                   aInf.GetTxt().Len(), aInf.IsStop() );
     878             :                 }
     879           0 :                 else if ( !aFrmBreak.IsKeepAlways() )
     880             :                 {
     881             :                     // We delete a line before the Master, because the Follow
     882             :                     // could hand over a line
     883           0 :                     const SwCharRange aFollowRg( GetFollow()->GetOfst(), 1 );
     884           0 :                     *(pPara->GetReformat()) += aFollowRg;
     885             :                     // We should continue!
     886           0 :                     bRet = sal_False;
     887             :                 }
     888             :             }
     889             : 
     890          19 :             UNDO_SWAP( this )
     891             :             // A final check, if FormatAdjust() didn't help we need to
     892             :             // truncate
     893          19 :             if( bPrepMustFit )
     894             :             {
     895           0 :                 const SwTwips nMust = (GetUpper()->*fnRect->fnGetPrtBottom)();
     896           0 :                 const SwTwips nIs   = (Frm().*fnRect->fnGetBottom)();
     897             : 
     898           0 :                 if( bVert && nIs < nMust )
     899             :                 {
     900           0 :                     Shrink( nMust - nIs );
     901           0 :                     if( Prt().Width() < 0 )
     902           0 :                         Prt().Width( 0 );
     903           0 :                     SetUndersized( sal_True );
     904             :                 }
     905           0 :                 else if ( ! bVert && nIs > nMust )
     906             :                 {
     907           0 :                     Shrink( nIs - nMust );
     908           0 :                     if( Prt().Height() < 0 )
     909           0 :                         Prt().Height( 0 );
     910           0 :                     SetUndersized( sal_True );
     911             :                 }
     912          19 :             }
     913             :         }
     914             :     }
     915         153 :     pPara->SetPrepMustFit( bPrepMustFit );
     916         153 :     return bRet;
     917             : }
     918             : 
     919             : /*************************************************************************
     920             :  * SwTxtFrm::FormatAdjust()
     921             :  * We rewire the footnotes and the character bound objects
     922             :  *************************************************************************/
     923             : 
     924             : #define CHG_OFFSET( pFrm, nNew )\
     925             :     {\
     926             :         if( pFrm->GetOfst() < nNew )\
     927             :             pFrm->MoveFlyInCnt( this, 0, nNew );\
     928             :         else if( pFrm->GetOfst() > nNew )\
     929             :             MoveFlyInCnt( pFrm, nNew, STRING_LEN );\
     930             :     }
     931             : 
     932         662 : void SwTxtFrm::FormatAdjust( SwTxtFormatter &rLine,
     933             :                              WidowsAndOrphans &rFrmBreak,
     934             :                              const xub_StrLen nStrLen,
     935             :                              const sal_Bool bDummy )
     936             : {
     937         662 :     SWAP_IF_NOT_SWAPPED( this )
     938             : 
     939         662 :     SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
     940             : 
     941         662 :     xub_StrLen nEnd = rLine.GetStart();
     942             : 
     943         662 :     sal_Bool bHasToFit = pPara->IsPrepMustFit();
     944             : 
     945             :     // The StopFlag is set by footnotes which want to go onto the next page
     946             :     // Call base class method <SwTxtFrmBreak::IsBreakNow(..)>
     947             :     // instead of method <WidowsAndOrphans::IsBreakNow(..)> to get a break,
     948             :     // even if due to widow rule no enough lines exists.
     949         662 :     sal_uInt8 nNew = ( !GetFollow() &&
     950             :                        nEnd < nStrLen &&
     951         584 :                        ( rLine.IsStop() ||
     952             :                          ( bHasToFit
     953           0 :                            ? ( rLine.GetLineNr() > 1 &&
     954           0 :                                !rFrmBreak.IsInside( rLine ) )
     955         584 :                            : rFrmBreak.IsBreakNow( rLine ) ) ) )
     956        1246 :                      ? 1 : 0;
     957             :     // --> OD #i84870#
     958             :     // no split of text frame, which only contains a as-character anchored object
     959             :     const bool bOnlyContainsAsCharAnchoredObj =
     960         662 :             !IsFollow() && nStrLen == 1 &&
     961         252 :             GetDrawObjs() && GetDrawObjs()->Count() == 1 &&
     962         914 :             (*GetDrawObjs())[0]->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR;
     963         662 :     if ( nNew && bOnlyContainsAsCharAnchoredObj )
     964             :     {
     965           0 :         nNew = 0;
     966             :     }
     967             :     // <--
     968         662 :     if ( nNew )
     969             :     {
     970           0 :         SplitFrm( nEnd );
     971             :     }
     972             : 
     973         662 :     const SwFrm *pBodyFrm = (const SwFrm*)(FindBodyFrm());
     974             : 
     975         553 :     const long nBodyHeight = pBodyFrm ? ( IsVertical() ?
     976           0 :                                           pBodyFrm->Frm().Width() :
     977        1215 :                                           pBodyFrm->Frm().Height() ) : 0;
     978             : 
     979             :     // If the current values have been calculated, show that they
     980             :     // are valid now
     981         662 :     *(pPara->GetReformat()) = SwCharRange();
     982         662 :     bool bDelta = *pPara->GetDelta() != 0;
     983         662 :     *(pPara->GetDelta()) = 0;
     984             : 
     985         662 :     if( rLine.IsStop() )
     986             :     {
     987           0 :         rLine.TruncLines( true );
     988           0 :         nNew = 1;
     989             :     }
     990             : 
     991             :     // FindBreak truncates the last line
     992         662 :     if( !rFrmBreak.FindBreak( this, rLine, bHasToFit ) )
     993             :     {
     994             :         // If we're done formatting, we set nEnd to the end.
     995             :         // AdjustFollow might execute JoinFrm() because of this.
     996             :         // Else, nEnd is the end of the last line in the Master.
     997         662 :         xub_StrLen nOld = nEnd;
     998         662 :         nEnd = rLine.GetEnd();
     999         662 :         if( GetFollow() )
    1000             :         {
    1001           0 :             if( nNew && nOld < nEnd )
    1002           0 :                 RemoveFtn( nOld, nEnd - nOld );
    1003           0 :             CHG_OFFSET( GetFollow(), nEnd )
    1004           0 :             if( !bDelta )
    1005           0 :                 GetFollow()->ManipOfst( nEnd );
    1006             :         }
    1007             :     }
    1008             :     else
    1009             :     {   // If we pass over lines, we must not call Join in Follows, instead we even
    1010             :         // need to create a Follow.
    1011             :         // We also need to do this if the whole mass of text remains in the Master,
    1012             :         // because a hard line break could necessitate another line (without text mass)!
    1013           0 :         nEnd = rLine.GetEnd();
    1014           0 :         if( GetFollow() )
    1015             :         {
    1016             :             // Another case for not joining the follow:
    1017             :             // Text frame has no content, but a numbering. Then, do *not* join.
    1018             :             // Example of this case: When an empty, but numbered paragraph
    1019             :             // at the end of page is completely displaced by a fly frame.
    1020             :             // Thus, the text frame introduced a follow by a
    1021             :             // <SwTxtFrm::SplitFrm(..)> - see below. The follow then shows
    1022             :             // the numbering and must stay.
    1023           0 :             if ( GetFollow()->GetOfst() != nEnd ||
    1024           0 :                  GetFollow()->IsFieldFollow() ||
    1025           0 :                  ( nStrLen == 0 && GetTxtNode()->GetNumRule() ) )
    1026             :             {
    1027           0 :                 nNew |= 3;
    1028             :             }
    1029           0 :             CHG_OFFSET( GetFollow(), nEnd )
    1030           0 :             GetFollow()->ManipOfst( nEnd );
    1031             :         }
    1032             :         else
    1033             :         {
    1034             :             // Only split frame, if the frame contains
    1035             :             // content or contains no content, but has a numbering.
    1036             :             // OD #i84870# - no split, if text frame only contains one
    1037             :             // as-character anchored object.
    1038           0 :             if ( !bOnlyContainsAsCharAnchoredObj &&
    1039             :                  ( nStrLen > 0 ||
    1040           0 :                    ( nStrLen == 0 && GetTxtNode()->GetNumRule() ) )
    1041             :                )
    1042             :             {
    1043           0 :                 SplitFrm( nEnd );
    1044           0 :                 nNew |= 3;
    1045             :             }
    1046             :         }
    1047             :         // If the remaining height changed e.g by RemoveFtn() we need to
    1048             :         // fill up in order to avoid oscillation.
    1049           0 :         if( bDummy && pBodyFrm &&
    1050           0 :            nBodyHeight < ( IsVertical() ?
    1051           0 :                            pBodyFrm->Frm().Width() :
    1052           0 :                            pBodyFrm->Frm().Height() ) )
    1053           0 :             rLine.MakeDummyLine();
    1054             :     }
    1055             : 
    1056             :     // In AdjustFrm() we set ourselves via Grow/Shrink
    1057             :     // In AdjustFollow() we set our FollowFrame
    1058             : 
    1059         662 :     const SwTwips nDocPrtTop = Frm().Top() + Prt().Top();
    1060         662 :     const SwTwips nOldHeight = Prt().SSize().Height();
    1061         662 :     SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight;
    1062             :     // --> OD #i84870# - no shrink of text frame, if it only contains one
    1063             :     // as-character anchored object.
    1064         662 :     if ( nChg < 0 &&
    1065             :          bOnlyContainsAsCharAnchoredObj )
    1066             :     {
    1067           0 :         nChg = 0;
    1068             :     }
    1069             :     // <--
    1070             : 
    1071             :     // Vertical Formatting:
    1072             :     // The (rotated) repaint rectangle's x coordinate referes to the frame.
    1073             :     // If the frame grows (or shirks) the repaint rectangle cannot simply
    1074             :     // be rotated back after formatting, because we use the upper left point
    1075             :     // of the frame for rotation. This point changes when growing/shrinking.
    1076             : 
    1077             :     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    1078         662 :     if ( IsVertical() && !IsVertLR() && nChg )
    1079             :     {
    1080           0 :         SwRect &rRepaint = *(pPara->GetRepaint());
    1081           0 :         rRepaint.Left( rRepaint.Left() - nChg );
    1082           0 :         rRepaint.Width( rRepaint.Width() - nChg );
    1083             :     }
    1084             : 
    1085         662 :     AdjustFrm( nChg, bHasToFit );
    1086             : 
    1087         662 :     if( HasFollow() || IsInFtn() )
    1088          10 :         _AdjustFollow( rLine, nEnd, nStrLen, nNew );
    1089             : 
    1090         662 :     pPara->SetPrepMustFit( sal_False );
    1091             : 
    1092         662 :     UNDO_SWAP( this )
    1093         662 : }
    1094             : 
    1095             : /*************************************************************************
    1096             :  * SwTxtFrm::FormatLine()
    1097             :  * bPrev is set whether Reformat.Start() was called because of Prev().
    1098             :  * Else, wo don't know whether we can limit the repaint or not.
    1099             : *************************************************************************/
    1100             : 
    1101         724 : sal_Bool SwTxtFrm::FormatLine( SwTxtFormatter &rLine, const sal_Bool bPrev )
    1102             : {
    1103             :     OSL_ENSURE( ! IsVertical() || IsSwapped(),
    1104             :             "SwTxtFrm::FormatLine( rLine, bPrev) with unswapped frame" );
    1105         724 :     SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
    1106         724 :     const SwLineLayout *pOldCur = rLine.GetCurr();
    1107         724 :     const xub_StrLen nOldLen    = pOldCur->GetLen();
    1108         724 :     const KSHORT nOldAscent = pOldCur->GetAscent();
    1109         724 :     const KSHORT nOldHeight = pOldCur->Height();
    1110         724 :     const SwTwips nOldWidth = pOldCur->Width() + pOldCur->GetHangingMargin();
    1111         724 :     const sal_Bool bOldHyph = pOldCur->IsEndHyph();
    1112         724 :     SwTwips nOldTop = 0;
    1113         724 :     SwTwips nOldBottom = 0;
    1114         724 :     if( rLine.GetCurr()->IsClipping() )
    1115           0 :         rLine.CalcUnclipped( nOldTop, nOldBottom );
    1116             : 
    1117         724 :     const xub_StrLen nNewStart = rLine.FormatLine( rLine.GetStart() );
    1118             : 
    1119             :     OSL_ENSURE( Frm().Pos().Y() + Prt().Pos().Y() == rLine.GetFirstPos(),
    1120             :             "SwTxtFrm::FormatLine: frame leaves orbit." );
    1121             :     OSL_ENSURE( rLine.GetCurr()->Height(),
    1122             :             "SwTxtFrm::FormatLine: line height is zero" );
    1123             : 
    1124             :     // The current line break object
    1125         724 :     const SwLineLayout *pNew = rLine.GetCurr();
    1126             : 
    1127         724 :     bool bUnChg = nOldLen == pNew->GetLen() &&
    1128         724 :                   bOldHyph == pNew->IsEndHyph();
    1129         724 :     if ( bUnChg && !bPrev )
    1130             :     {
    1131          86 :         const long nWidthDiff = nOldWidth > pNew->Width()
    1132           0 :                                 ? nOldWidth - pNew->Width()
    1133          86 :                                 : pNew->Width() - nOldWidth;
    1134             : 
    1135             :         // we only declare a line as unchanged, if its main values have not
    1136             :         // changed and it is not the last line (!paragraph end symbol!)
    1137          86 :         bUnChg = nOldHeight == pNew->Height() &&
    1138          12 :                  nOldAscent == pNew->GetAscent() &&
    1139             :                  nWidthDiff <= SLOPPY_TWIPS &&
    1140          98 :                  pOldCur->GetNext();
    1141             :     }
    1142             : 
    1143             :     // Calculate rRepaint
    1144         724 :     const SwTwips nBottom = rLine.Y() + rLine.GetLineHeight();
    1145         724 :     SwRepaint &rRepaint = *(pPara->GetRepaint());
    1146         724 :     if( bUnChg && rRepaint.Top() == rLine.Y()
    1147           0 :                && (bPrev || nNewStart <= pPara->GetReformat()->Start())
    1148           0 :                && ( nNewStart < GetTxtNode()->GetTxt().Len() ) )
    1149             :     {
    1150           0 :         rRepaint.Top( nBottom );
    1151           0 :         rRepaint.Height( 0 );
    1152             :     }
    1153             :     else
    1154             :     {
    1155         724 :         if( nOldTop )
    1156             :         {
    1157           0 :             if( nOldTop < rRepaint.Top() )
    1158           0 :                 rRepaint.Top( nOldTop );
    1159           0 :             if( !rLine.IsUnclipped() || nOldBottom > rRepaint.Bottom() )
    1160             :             {
    1161           0 :                 rRepaint.Bottom( nOldBottom - 1 );
    1162           0 :                 rLine.SetUnclipped( sal_True );
    1163             :             }
    1164             :         }
    1165         724 :         if( rLine.GetCurr()->IsClipping() && rLine.IsFlyInCntBase() )
    1166             :         {
    1167             :             SwTwips nTmpTop, nTmpBottom;
    1168           3 :             rLine.CalcUnclipped( nTmpTop, nTmpBottom );
    1169           3 :             if( nTmpTop < rRepaint.Top() )
    1170           0 :                 rRepaint.Top( nTmpTop );
    1171           3 :             if( !rLine.IsUnclipped() || nTmpBottom > rRepaint.Bottom() )
    1172             :             {
    1173           3 :                 rRepaint.Bottom( nTmpBottom - 1 );
    1174           3 :                 rLine.SetUnclipped( sal_True );
    1175             :             }
    1176             :         }
    1177             :         else
    1178             :         {
    1179         721 :             if( !rLine.IsUnclipped() || nBottom > rRepaint.Bottom() )
    1180             :             {
    1181         721 :                 rRepaint.Bottom( nBottom - 1 );
    1182         721 :                 rLine.SetUnclipped( sal_False );
    1183             :             }
    1184             :         }
    1185         724 :         SwTwips nRght = Max( nOldWidth, pNew->Width() +
    1186         724 :                              pNew->GetHangingMargin() );
    1187         724 :         ViewShell *pSh = getRootFrm()->GetCurrShell();
    1188         724 :         const SwViewOption *pOpt = pSh ? pSh->GetViewOptions() : 0;
    1189         724 :         if( pOpt && (pOpt->IsParagraph() || pOpt->IsLineBreak()) )
    1190           0 :             nRght += ( Max( nOldAscent, pNew->GetAscent() ) );
    1191             :         else
    1192         724 :             nRght += ( Max( nOldAscent, pNew->GetAscent() ) / 4);
    1193         724 :         nRght += rLine.GetLeftMargin();
    1194         724 :         if( rRepaint.GetOfst() || rRepaint.GetRightOfst() < nRght )
    1195         656 :             rRepaint.SetRightOfst( nRght );
    1196             : 
    1197             :         // Finally we enlarge the repaint rectangle if we found an underscore
    1198             :         // within our line. 40 Twips should be enough
    1199             :         const sal_Bool bHasUnderscore =
    1200         724 :                 ( rLine.GetInfo().GetUnderScorePos() < nNewStart );
    1201         724 :         if ( bHasUnderscore || rLine.GetCurr()->HasUnderscore() )
    1202           6 :             rRepaint.Bottom( rRepaint.Bottom() + 40 );
    1203             : 
    1204         724 :         ((SwLineLayout*)rLine.GetCurr())->SetUnderscore( bHasUnderscore );
    1205             :     }
    1206         724 :     if( !bUnChg )
    1207         724 :         rLine.SetChanges();
    1208             : 
    1209             :     // Calculating the good ol' nDelta
    1210         724 :     *(pPara->GetDelta()) -= long(pNew->GetLen()) - long(nOldLen);
    1211             : 
    1212             :     // Stop!
    1213         724 :     if( rLine.IsStop() )
    1214           0 :         return sal_False;
    1215             : 
    1216             :     // Absolutely another line
    1217         724 :     if( rLine.IsNewLine() )
    1218           3 :         return sal_True;
    1219             : 
    1220             :     // Until the String's end?
    1221         721 :     if( nNewStart >= GetTxtNode()->GetTxt().Len() )
    1222         643 :         return sal_False;
    1223             : 
    1224          78 :     if( rLine.GetInfo().IsShift() )
    1225          78 :         return sal_True;
    1226             : 
    1227             :     // Reached the Reformat's end?
    1228           0 :     const xub_StrLen nEnd = pPara->GetReformat()->Start() +
    1229           0 :                         pPara->GetReformat()->Len();
    1230             : 
    1231           0 :     if( nNewStart <= nEnd )
    1232           0 :         return sal_True;
    1233             : 
    1234           0 :     return 0 != *(pPara->GetDelta());
    1235             : }
    1236             : 
    1237         643 : void SwTxtFrm::_Format( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf,
    1238             :                         const sal_Bool bAdjust )
    1239             : {
    1240             :     OSL_ENSURE( ! IsVertical() || IsSwapped(),"SwTxtFrm::_Format with unswapped frame" );
    1241             : 
    1242         643 :     SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
    1243         643 :     rLine.SetUnclipped( sal_False );
    1244             : 
    1245             :     // That was too complicated for the C30: aString( GetTxt() );
    1246         643 :     const XubString &rString = GetTxtNode()->GetTxt();
    1247         643 :     const xub_StrLen nStrLen = rString.Len();
    1248             : 
    1249         643 :     SwCharRange &rReformat = *(pPara->GetReformat());
    1250         643 :     SwRepaint   &rRepaint = *(pPara->GetRepaint());
    1251         643 :     SwRepaint *pFreeze = NULL;
    1252             : 
    1253             :     // Due to performance reasons we set rReformat to STRING_LEN in Init()
    1254             :     // In this case we adjust rReformat
    1255         643 :     if( rReformat.Len() > nStrLen )
    1256         635 :         rReformat.Len() = nStrLen;
    1257             : 
    1258             :     // Optimized:
    1259         643 :     xub_StrLen nEnd = rReformat.Start() + rReformat.Len();
    1260         643 :     if( nEnd > nStrLen )
    1261             :     {
    1262           0 :         rReformat.Len() = nStrLen - rReformat.Start();
    1263           0 :         nEnd = nStrLen;
    1264             :     }
    1265             : 
    1266             :     SwTwips nOldBottom;
    1267         643 :     if( GetOfst() && !IsFollow() )
    1268             :     {
    1269           0 :         rLine.Bottom();
    1270           0 :         nOldBottom = rLine.Y();
    1271           0 :         rLine.Top();
    1272             :     }
    1273             :     else
    1274         643 :         nOldBottom = 0;
    1275         643 :     rLine.CharToLine( rReformat.Start() );
    1276             : 
    1277             :     // Words can be swapped-out when inserting a space into the
    1278             :     // line that comes before the edited one. That's why we also
    1279             :     // need to format that.
    1280             :     // Optimization: If rReformat starts after the first word of the line
    1281             :     // this line cannot possibly influence the previous one.
    1282             :     // Unfortunately it can: Text size changes + FlyFrames.
    1283             :     // The backlash can affect multiple lines (Frame!)!
    1284             : 
    1285             :     // #i46560#
    1286             :     // FME: Yes, consider this case: (word) has to go to the next line
    1287             :     // because) is a forbidden character at the beginning of a line although
    1288             :     // (word would still fit on the previous line. Adding text right in front
    1289             :     // of) would not trigger a reformatting of the previous line. Adding 1
    1290             :     // to the result of FindBrk() does not solve the problem in all cases,
    1291             :     // nevertheless it should be sufficient.
    1292         643 :     bool bPrev = rLine.GetPrev() &&
    1293           0 :                      ( FindBrk( rString, rLine.GetStart(), rReformat.Start() + 1 )
    1294             :                        // #i46560#
    1295             :                        + 1
    1296           0 :                        >= rReformat.Start() ||
    1297         643 :                        rLine.GetCurr()->IsRest() );
    1298         643 :     if( bPrev )
    1299             :     {
    1300           0 :         while( rLine.Prev() )
    1301           0 :             if( rLine.GetCurr()->GetLen() && !rLine.GetCurr()->IsRest() )
    1302             :             {
    1303           0 :                 if( !rLine.GetStart() )
    1304           0 :                     rLine.Top(); // So that NumDone doesn't get confused
    1305           0 :                 break;
    1306             :             }
    1307           0 :         xub_StrLen nNew = rLine.GetStart() + rLine.GetLength();
    1308           0 :         if( nNew )
    1309             :         {
    1310           0 :             --nNew;
    1311           0 :             if( CH_BREAK == rString.GetChar( nNew ) )
    1312             :             {
    1313           0 :                 ++nNew;
    1314           0 :                 rLine.Next();
    1315           0 :                 bPrev = false;
    1316             :             }
    1317             :         }
    1318           0 :         rReformat.Len()  += rReformat.Start() - nNew;
    1319           0 :         rReformat.Start() = nNew;
    1320             :     }
    1321             : 
    1322         643 :     rRepaint.SetOfst( 0 );
    1323         643 :     rRepaint.SetRightOfst( 0 );
    1324         643 :     rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
    1325         643 :     if( pPara->IsMargin() )
    1326           0 :         rRepaint.Width( rRepaint.Width() + pPara->GetHangingMargin() );
    1327         643 :     rRepaint.Top( rLine.Y() );
    1328         643 :     if( 0 >= rRepaint.Width() )
    1329           0 :         rRepaint.Width(1);
    1330         643 :     WidowsAndOrphans aFrmBreak( this, rInf.IsTest() ? 1 : 0 );
    1331             : 
    1332             :     // rLine is now set to the first line which needs formatting.
    1333             :     // The bFirst flag makes sure that Next() is not called.
    1334             :     // The whole thing looks weird, but we need to make sure that
    1335             :     // rLine stops at the last non-fitting line when calling IsBreakNow.
    1336         643 :     bool bFirst  = true;
    1337         643 :     sal_Bool bFormat = sal_True;
    1338             : 
    1339             :     // The CharToLine() can also get us into the danger zone.
    1340             :     // In that case we need to walk back until rLine is set
    1341             :     // to the non-fitting line. Or else the mass of text is lost,
    1342             :     // because the Ofst was set wrongly in the Follow.
    1343             : 
    1344         643 :     sal_Bool bBreak = ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 )
    1345         643 :                     && aFrmBreak.IsBreakNowWidAndOrp( rLine );
    1346         643 :     if( bBreak )
    1347             :     {
    1348           0 :         bool bPrevDone = 0 != rLine.Prev();
    1349           0 :         while( bPrevDone && aFrmBreak.IsBreakNowWidAndOrp(rLine) )
    1350           0 :             bPrevDone = 0 != rLine.Prev();
    1351           0 :         if( bPrevDone )
    1352             :         {
    1353           0 :             aFrmBreak.SetKeep( sal_False );
    1354           0 :             rLine.Next();
    1355             :         }
    1356           0 :         rLine.TruncLines();
    1357             : 
    1358             :         // Play it safe
    1359           0 :         bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine) &&
    1360           0 :                   ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 );
    1361             :     }
    1362             : 
    1363             :  /* Meaning if the following flags are set:
    1364             : 
    1365             :     Watch(End/Mid)Hyph: we need to format if we have a break at
    1366             :     the line end/Fly, as long as MaxHyph is reached
    1367             : 
    1368             :     Jump(End/Mid)Flag: the next line which has no break (line end/Fly),
    1369             :     needs to be formatted, because we could wrap now. This might have been
    1370             :     forbidden earlier by MaxHyph
    1371             : 
    1372             :     Watch(End/Mid)Hyph: if the last formatted line got a cutoff point, but
    1373             :     didn't have one before
    1374             : 
    1375             :     Jump(End/Mid)Hyph: if a cutoff point disappears
    1376             :  */
    1377         643 :     sal_Bool bJumpEndHyph  = sal_False,
    1378         643 :          bWatchEndHyph = sal_False,
    1379         643 :          bJumpMidHyph  = sal_False,
    1380         643 :          bWatchMidHyph = sal_False;
    1381             : 
    1382         643 :     const SwAttrSet& rAttrSet = GetTxtNode()->GetSwAttrSet();
    1383             :     bool bMaxHyph = ( 0 !=
    1384         643 :         ( rInf.MaxHyph() = rAttrSet.GetHyphenZone().GetMaxHyphens() ) );
    1385         643 :     if ( bMaxHyph )
    1386           0 :         rLine.InitCntHyph();
    1387             : 
    1388         643 :     if( IsFollow() && IsFieldFollow() && rLine.GetStart() == GetOfst() )
    1389             :     {
    1390           0 :         SwTxtFrm *pMaster = FindMaster();
    1391             :         OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" );
    1392           0 :         const SwLineLayout* pLine=NULL;
    1393           0 :         if (pMaster)
    1394             :         {
    1395           0 :             if( !pMaster->HasPara() )
    1396           0 :                 pMaster->GetFormatted();
    1397           0 :             SwTxtSizeInfo aInf( pMaster );
    1398           0 :             SwTxtIter aMasterLine( pMaster, &aInf );
    1399           0 :             aMasterLine.Bottom();
    1400           0 :             pLine = aMasterLine.GetCurr();
    1401             :         }
    1402             :         SwLinePortion* pRest = pLine ?
    1403           0 :             rLine.MakeRestPortion(pLine, GetOfst()) : NULL;
    1404           0 :         if( pRest )
    1405           0 :             rInf.SetRest( pRest );
    1406             :         else
    1407           0 :             SetFieldFollow( sal_False );
    1408             :     }
    1409             : 
    1410             :     /* Ad cancel criterion:
    1411             :      * In order to recognize, whether a line does not fit onto the page
    1412             :      * anymore, we need to format it. This overflow is removed again in
    1413             :      * e.g. AdjustFollow.
    1414             :      * Another complication: if we are the Master, we need to traverse
    1415             :      * the lines, because it could happen that one line can overflow
    1416             :      * from the Follow to the Master.
    1417             :      */
    1418          81 :     do
    1419             :     {
    1420         724 :         if( bFirst )
    1421         643 :             bFirst = false;
    1422             :         else
    1423             :         {
    1424          81 :             if ( bMaxHyph )
    1425             :             {
    1426           0 :                 if ( rLine.GetCurr()->IsEndHyph() )
    1427           0 :                     rLine.CntEndHyph()++;
    1428             :                 else
    1429           0 :                     rLine.CntEndHyph() = 0;
    1430           0 :                 if ( rLine.GetCurr()->IsMidHyph() )
    1431           0 :                     rLine.CntMidHyph()++;
    1432             :                 else
    1433           0 :                     rLine.CntMidHyph() = 0;
    1434             :             }
    1435          81 :             if( !rLine.Next() )
    1436             :             {
    1437          81 :                 if( !bFormat )
    1438             :                 {
    1439             :                     SwLinePortion* pRest =
    1440           0 :                         rLine.MakeRestPortion( rLine.GetCurr(), rLine.GetEnd() );
    1441           0 :                     if( pRest )
    1442           0 :                         rInf.SetRest( pRest );
    1443             :                 }
    1444          81 :                 rLine.Insert( new SwLineLayout() );
    1445          81 :                 rLine.Next();
    1446          81 :                 bFormat = sal_True;
    1447             :             }
    1448             :         }
    1449         724 :         if ( !bFormat && bMaxHyph &&
    1450             :               (bWatchEndHyph || bJumpEndHyph || bWatchMidHyph || bJumpMidHyph) )
    1451             :         {
    1452           0 :             if ( rLine.GetCurr()->IsEndHyph() )
    1453             :             {
    1454           0 :                 if ( bWatchEndHyph )
    1455           0 :                     bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() );
    1456             :             }
    1457             :             else
    1458             :             {
    1459           0 :                 bFormat = bJumpEndHyph;
    1460           0 :                 bWatchEndHyph = sal_False;
    1461           0 :                 bJumpEndHyph = sal_False;
    1462             :             }
    1463           0 :             if ( rLine.GetCurr()->IsMidHyph() )
    1464             :             {
    1465           0 :                 if ( bWatchMidHyph && !bFormat )
    1466           0 :                     bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() );
    1467             :             }
    1468             :             else
    1469             :             {
    1470           0 :                 bFormat = bFormat || bJumpMidHyph;
    1471           0 :                 bWatchMidHyph = sal_False;
    1472           0 :                 bJumpMidHyph = sal_False;
    1473             :             }
    1474             :         }
    1475         724 :         if( bFormat )
    1476             :         {
    1477         724 :             sal_Bool bOldEndHyph = rLine.GetCurr()->IsEndHyph();
    1478         724 :             sal_Bool bOldMidHyph = rLine.GetCurr()->IsMidHyph();
    1479         724 :             bFormat = FormatLine( rLine, bPrev );
    1480             :             // There can only be one bPrev ... (???)
    1481         724 :             bPrev = sal_False;
    1482         724 :             if ( bMaxHyph )
    1483             :             {
    1484           0 :                 if ( rLine.GetCurr()->IsEndHyph() != bOldEndHyph )
    1485             :                 {
    1486           0 :                     bWatchEndHyph = !bOldEndHyph;
    1487           0 :                     bJumpEndHyph = bOldEndHyph;
    1488             :                 }
    1489           0 :                 if ( rLine.GetCurr()->IsMidHyph() != bOldMidHyph )
    1490             :                 {
    1491           0 :                     bWatchMidHyph = !bOldMidHyph;
    1492           0 :                     bJumpMidHyph = bOldMidHyph;
    1493             :                 }
    1494             :             }
    1495             :         }
    1496             : 
    1497         724 :         if( !rInf.IsNewLine() )
    1498             :         {
    1499         721 :             if( !bFormat )
    1500         643 :                  bFormat = 0 != rInf.GetRest();
    1501         721 :             if( rInf.IsStop() || rInf.GetIdx() >= nStrLen )
    1502         643 :                 break;
    1503          78 :             if( !bFormat && ( !bMaxHyph || ( !bWatchEndHyph &&
    1504             :                     !bJumpEndHyph && !bWatchMidHyph && !bJumpMidHyph ) ) )
    1505             :             {
    1506           0 :                 if( GetFollow() )
    1507             :                 {
    1508           0 :                     while( rLine.Next() )
    1509             :                         ; //Nothing
    1510           0 :                     pFreeze = new SwRepaint( rRepaint ); // to minimize painting
    1511             :                 }
    1512             :                 else
    1513           0 :                     break;
    1514             :             }
    1515             :         }
    1516          81 :         bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine);
    1517          81 :     }while( !bBreak );
    1518             : 
    1519         643 :     if( pFreeze )
    1520             :     {
    1521           0 :         rRepaint = *pFreeze;
    1522           0 :         delete pFreeze;
    1523             :     }
    1524             : 
    1525         643 :     if( !rLine.IsStop() )
    1526             :     {
    1527             :         // If we're finished formatting the text and we still
    1528             :         // have other line objects left, these are superfluous
    1529             :         // now because the text has gotten shorter.
    1530        1286 :         if( rLine.GetStart() + rLine.GetLength() >= nStrLen &&
    1531         643 :             rLine.GetCurr()->GetNext() )
    1532             :         {
    1533           0 :             rLine.TruncLines();
    1534           0 :             rLine.SetTruncLines( sal_True );
    1535             :         }
    1536             :     }
    1537             : 
    1538         643 :     if( !rInf.IsTest() )
    1539             :     {
    1540             :         // FormatAdjust does not pay off at OnceMore
    1541         643 :         if( bAdjust || !rLine.GetDropFmt() || !rLine.CalcOnceMore() )
    1542             :         {
    1543         643 :             FormatAdjust( rLine, aFrmBreak, nStrLen, rInf.IsStop() );
    1544             :         }
    1545         643 :         if( rRepaint.HasArea() )
    1546         643 :             SetRepaint();
    1547         643 :         rLine.SetTruncLines( sal_False );
    1548         643 :         if( nOldBottom ) // We check whether paragraphs that need scrolling can
    1549             :                          // be shrunk, so that they don't need scrolling anymore
    1550             :         {
    1551           0 :             rLine.Bottom();
    1552           0 :             SwTwips nNewBottom = rLine.Y();
    1553           0 :             if( nNewBottom < nOldBottom )
    1554           0 :                 _SetOfst( 0 );
    1555             :         }
    1556             :     }
    1557         643 : }
    1558             : 
    1559           0 : void SwTxtFrm::FormatOnceMore( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf )
    1560             : {
    1561             :     OSL_ENSURE( ! IsVertical() || IsSwapped(),
    1562             :             "A frame is not swapped in SwTxtFrm::FormatOnceMore" );
    1563             : 
    1564           0 :     SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
    1565           0 :     if( !pPara )
    1566           0 :         return;
    1567             : 
    1568             :     // If necessary the pPara
    1569           0 :     KSHORT nOld  = ((const SwTxtMargin&)rLine).GetDropHeight();
    1570           0 :     sal_Bool bShrink = sal_False,
    1571           0 :          bGrow   = sal_False,
    1572           0 :          bGoOn   = rLine.IsOnceMore();
    1573           0 :     sal_uInt8 nGo    = 0;
    1574           0 :     while( bGoOn )
    1575             :     {
    1576           0 :         ++nGo;
    1577           0 :         rInf.Init();
    1578           0 :         rLine.Top();
    1579           0 :         if( !rLine.GetDropFmt() )
    1580           0 :             rLine.SetOnceMore( sal_False );
    1581           0 :         SwCharRange aRange( 0, rInf.GetTxt().Len() );
    1582           0 :         *(pPara->GetReformat()) = aRange;
    1583           0 :         _Format( rLine, rInf );
    1584             : 
    1585           0 :         bGoOn = rLine.IsOnceMore();
    1586           0 :         if( bGoOn )
    1587             :         {
    1588           0 :             const KSHORT nNew = ((const SwTxtMargin&)rLine).GetDropHeight();
    1589           0 :             if( nOld == nNew )
    1590           0 :                 bGoOn = sal_False;
    1591             :             else
    1592             :             {
    1593           0 :                 if( nOld > nNew )
    1594           0 :                     bShrink = sal_True;
    1595             :                 else
    1596           0 :                     bGrow = sal_True;
    1597             : 
    1598           0 :                 if( bShrink == bGrow || 5 < nGo )
    1599           0 :                     bGoOn = sal_False;
    1600             : 
    1601           0 :                 nOld = nNew;
    1602             :             }
    1603             : 
    1604             :             // If something went wrong, we need to reformat again
    1605           0 :             if( !bGoOn )
    1606             :             {
    1607           0 :                 rInf.CtorInitTxtFormatInfo( this );
    1608           0 :                 rLine.CtorInitTxtFormatter( this, &rInf );
    1609           0 :                 rLine.SetDropLines( 1 );
    1610           0 :                 rLine.CalcDropHeight( 1 );
    1611           0 :                 SwCharRange aTmpRange( 0, rInf.GetTxt().Len() );
    1612           0 :                 *(pPara->GetReformat()) = aTmpRange;
    1613           0 :                 _Format( rLine, rInf, sal_True );
    1614             :                 // We paint everything ...
    1615           0 :                 SetCompletePaint();
    1616             :             }
    1617             :         }
    1618             :     }
    1619             : }
    1620             : 
    1621         643 : void SwTxtFrm::_Format( SwParaPortion *pPara )
    1622             : {
    1623         643 :     const xub_StrLen nStrLen = GetTxt().Len();
    1624             : 
    1625         643 :     if ( !nStrLen )
    1626             :     {
    1627             :         // Empty lines do not get tortured for very long:
    1628             :         // pPara is cleared, which is the same as:
    1629             :         // *pPara = SwParaPortion;
    1630          76 :         sal_Bool bMustFit = pPara->IsPrepMustFit();
    1631          76 :         pPara->Truncate();
    1632          76 :         pPara->FormatReset();
    1633          76 :         if( pBlink && pPara->IsBlinking() )
    1634           0 :             pBlink->Delete( pPara );
    1635             : 
    1636             :         // delete pSpaceAdd und pKanaComp
    1637          76 :         pPara->FinishSpaceAdd();
    1638          76 :         pPara->FinishKanaComp();
    1639          76 :         pPara->ResetFlags();
    1640          76 :         pPara->SetPrepMustFit( bMustFit );
    1641             :     }
    1642             : 
    1643             :     OSL_ENSURE( ! IsSwapped(), "A frame is swapped before _Format" );
    1644             : 
    1645         643 :     if ( IsVertical() )
    1646           0 :         SwapWidthAndHeight();
    1647             : 
    1648         643 :     SwTxtFormatInfo aInf( this );
    1649         643 :     SwTxtFormatter  aLine( this, &aInf );
    1650             : 
    1651         643 :     HideAndShowObjects();
    1652             : 
    1653         643 :     _Format( aLine, aInf );
    1654             : 
    1655         643 :     if( aLine.IsOnceMore() )
    1656           0 :         FormatOnceMore( aLine, aInf );
    1657             : 
    1658         643 :     if ( IsVertical() )
    1659           0 :         SwapWidthAndHeight();
    1660             : 
    1661             :     OSL_ENSURE( ! IsSwapped(), "A frame is swapped after _Format" );
    1662             : 
    1663         643 :     if( 1 < aLine.GetDropLines() )
    1664             :     {
    1665           0 :         if( SVX_ADJUST_LEFT != aLine.GetAdjust() &&
    1666           0 :             SVX_ADJUST_BLOCK != aLine.GetAdjust() )
    1667             :         {
    1668           0 :             aLine.CalcDropAdjust();
    1669           0 :             aLine.SetPaintDrop( sal_True );
    1670             :         }
    1671             : 
    1672           0 :         if( aLine.IsPaintDrop() )
    1673             :         {
    1674           0 :             aLine.CalcDropRepaint();
    1675           0 :             aLine.SetPaintDrop( sal_False );
    1676             :         }
    1677         643 :     }
    1678         643 : }
    1679             : 
    1680             : /*************************************************************************
    1681             :  * SwTxtFrm::Format()
    1682             :  * We calculate the text frame's size and send a notification.
    1683             :  * Shrink() or Grow() to adjust the frame's size to the changed required space.
    1684             :  *************************************************************************/
    1685             : 
    1686        1099 : void SwTxtFrm::Format( const SwBorderAttrs * )
    1687             : {
    1688        1099 :     SWRECTFN( this )
    1689             : 
    1690        1099 :     CalcAdditionalFirstLineOffset();
    1691             : 
    1692             :     // The range autopilot or the BASIC interface pass us TxtFrms with
    1693             :     // a width <= 0 from time to time
    1694        1099 :     if( (Prt().*fnRect->fnGetWidth)() <= 0 )
    1695             :     {
    1696             :         // If MustFit is set, we shrink to the Upper's bottom edge if needed.
    1697             :         // Else we just take a standard size of 12 Pt. (240 twip).
    1698           1 :         SwTxtLineAccess aAccess( this );
    1699           1 :         long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    1700           1 :         if( aAccess.GetPara()->IsPrepMustFit() )
    1701             :         {
    1702           0 :             const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
    1703           0 :             const SwTwips nDiff = - (Frm().*fnRect->fnBottomDist)( nLimit );
    1704           0 :             if( nDiff > 0 )
    1705           0 :                 Shrink( nDiff );
    1706             :         }
    1707           1 :         else if( 240 < nFrmHeight )
    1708           0 :             Shrink( nFrmHeight - 240 );
    1709           1 :         else if( 240 > nFrmHeight )
    1710           1 :             Grow( 240 - nFrmHeight );
    1711           1 :         nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    1712             : 
    1713           1 :         long nTop = (this->*fnRect->fnGetTopMargin)();
    1714           1 :         if( nTop > nFrmHeight )
    1715           0 :             (this->*fnRect->fnSetYMargins)( nFrmHeight, 0 );
    1716           1 :         else if( (Prt().*fnRect->fnGetHeight)() < 0 )
    1717           0 :             (Prt().*fnRect->fnSetHeight)( 0 );
    1718           1 :         return;
    1719             :     }
    1720             : 
    1721        1098 :     const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len();
    1722        1098 :     if ( nStrLen || !FormatEmpty() )
    1723             :     {
    1724             : 
    1725         784 :         SetEmpty( sal_False );
    1726             :         // In order to not get confused by nested Formats
    1727         784 :         FormatLevel aLevel;
    1728         784 :         if( 12 == aLevel.GetLevel() )
    1729             :             return;
    1730             : 
    1731             :         // We could be possibly not allowed to alter the format information
    1732         784 :         if( IsLocked() )
    1733             :             return;
    1734             : 
    1735             :         // Attention: Format() could be triggered by GetFormatted()
    1736         784 :         if( IsHiddenNow() )
    1737             :         {
    1738           0 :             long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
    1739           0 :             if( nPrtHeight )
    1740             :             {
    1741           0 :                 HideHidden();
    1742           0 :                 Shrink( nPrtHeight );
    1743             :             }
    1744             :             else
    1745             :             {
    1746             :                 // Assure that objects anchored
    1747             :                 // at paragraph resp. at/as character inside paragraph
    1748             :                 // are hidden.
    1749           0 :                 HideAndShowObjects();
    1750             :             }
    1751           0 :             ChgThisLines();
    1752             :             return;
    1753             :         }
    1754             : 
    1755             :         // We do not want to be interrupted during formatting
    1756         784 :         SwTxtFrmLocker aLock(this);
    1757         784 :         SwTxtLineAccess aAccess( this );
    1758         784 :         const bool bNew = !aAccess.SwTxtLineAccess::IsAvailable();
    1759         784 :         const bool bSetOfst = ( GetOfst() && GetOfst() > GetTxtNode()->GetTxt().Len() );
    1760             : 
    1761         784 :         if( CalcPreps() )
    1762             :             ; // nothing
    1763             :         // We return if already formatted, but if the TxtFrm was just created
    1764             :         // and does not have any format information
    1765         765 :         else if( !bNew && !aAccess.GetPara()->GetReformat()->Len() )
    1766             :         {
    1767         122 :             if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
    1768             :             {
    1769           0 :                 aAccess.GetPara()->SetPrepAdjust( sal_True );
    1770           0 :                 aAccess.GetPara()->SetPrep( sal_True );
    1771           0 :                 CalcPreps();
    1772             :             }
    1773         122 :             SetWidow( sal_False );
    1774             :         }
    1775         643 :         else if( bSetOfst && IsFollow() )
    1776             :         {
    1777           0 :             SwTxtFrm *pMaster = FindMaster();
    1778             :             OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" );
    1779           0 :             if( pMaster )
    1780           0 :                 pMaster->Prepare( PREP_FOLLOW_FOLLOWS );
    1781           0 :             SwTwips nMaxY = (GetUpper()->*fnRect->fnGetPrtBottom)();
    1782           0 :             if( (Frm().*fnRect->fnOverStep)( nMaxY  ) )
    1783           0 :                 (this->*fnRect->fnSetLimit)( nMaxY );
    1784           0 :             else if( (Frm().*fnRect->fnBottomDist)( nMaxY  ) < 0 )
    1785           0 :                 (Frm().*fnRect->fnAddBottom)( -(Frm().*fnRect->fnGetHeight)() );
    1786             :         }
    1787             :         else
    1788             :         {
    1789             :             // bSetOfst here means that we have the "red arrow situation"
    1790         643 :             if ( bSetOfst )
    1791           0 :                 _SetOfst( 0 );
    1792             : 
    1793         643 :             const sal_Bool bOrphan = IsWidow();
    1794         643 :             const SwFtnBossFrm* pFtnBoss = HasFtn() ? FindFtnBossFrm() : 0;
    1795         643 :             SwTwips nFtnHeight = 0;
    1796         643 :             if( pFtnBoss )
    1797             :             {
    1798           0 :                 const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont();
    1799           0 :                 nFtnHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0;
    1800             :             }
    1801           0 :             do
    1802             :             {
    1803         643 :                 _Format( aAccess.GetPara() );
    1804         643 :                 if( pFtnBoss && nFtnHeight )
    1805             :                 {
    1806           0 :                     const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont();
    1807           0 :                     SwTwips nNewHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0;
    1808             :                     // If we lost some footnotes, we may have more space
    1809             :                     // for our main text, so we have to format again ...
    1810           0 :                     if( nNewHeight < nFtnHeight )
    1811           0 :                         nFtnHeight = nNewHeight;
    1812             :                     else
    1813           0 :                         break;
    1814             :                 }
    1815             :                 else
    1816         643 :                     break;
    1817             :             } while ( pFtnBoss );
    1818         643 :             if( bOrphan )
    1819             :             {
    1820           0 :                 ValidateFrm();
    1821           0 :                 SetWidow( sal_False );
    1822             :             }
    1823             :         }
    1824         784 :         if( IsEmptyMaster() )
    1825             :         {
    1826           0 :             SwFrm* pPre = GetPrev();
    1827           0 :             if( pPre &&
    1828             :                 // #i10826# It's the first, it cannot keep!
    1829           0 :                 pPre->GetIndPrev() &&
    1830           0 :                 pPre->GetAttrSet()->GetKeep().GetValue() )
    1831             :             {
    1832           0 :                 pPre->InvalidatePos();
    1833             :             }
    1834         784 :         }
    1835             :     }
    1836             : 
    1837        1098 :     ChgThisLines();
    1838             : 
    1839             :     // the PrepMustFit should not survive a Format operation
    1840        1098 :     SwParaPortion *pPara = GetPara();
    1841        1098 :     if ( pPara )
    1842         784 :            pPara->SetPrepMustFit( sal_False );
    1843             : 
    1844        1098 :     CalcBaseOfstForFly();
    1845        1098 :     _CalcHeightOfLastLine(); // #i11860#
    1846             : }
    1847             : 
    1848             : /*************************************************************************
    1849             :  * SwTxtFrm::FormatQuick()
    1850             :  *
    1851             :  * bForceQuickFormat is set if GetFormatted() has been called during the
    1852             :  * painting process. Actually I cannot imagine a situation which requires
    1853             :  * a full formatting of the paragraph during painting, on the other hand
    1854             :  * a full formatting can cause the invalidation of other layout frames,
    1855             :  * e.g., if there are footnotes in this paragraph, and invalid layout
    1856             :  * frames will not calculated during the painting. So I actually want to
    1857             :  * avoid a formatting during painting, but since I'm a coward, I'll only
    1858             :  * force the quick formatting in the situation of issue i29062.
    1859             :  *************************************************************************/
    1860             : 
    1861           0 : sal_Bool SwTxtFrm::FormatQuick( bool bForceQuickFormat )
    1862             : {
    1863             :     OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
    1864             :             "SwTxtFrm::FormatQuick with swapped frame" );
    1865             : 
    1866             : #if OSL_DEBUG_LEVEL > 1
    1867             :     const XubString aXXX = GetTxtNode()->GetTxt();
    1868             :     const SwTwips nDbgY = Frm().Top();
    1869             :     (void)nDbgY;
    1870             :     // nStopAt allows CV to alter it
    1871             :     static MSHORT nStopAt = 0;
    1872             :     if( nStopAt == GetFrmId() )
    1873             :     {
    1874             :         int i = GetFrmId();
    1875             :         (void)i;
    1876             :     }
    1877             : #endif
    1878             : 
    1879           0 :     if( IsEmpty() && FormatEmpty() )
    1880           0 :         return sal_True;
    1881             : 
    1882             :     // We're very picky:
    1883           0 :     if( HasPara() || IsWidow() || IsLocked()
    1884           0 :         || !GetValidSizeFlag() ||
    1885           0 :         ( ( IsVertical() ? Prt().Width() : Prt().Height() ) && IsHiddenNow() ) )
    1886           0 :         return sal_False;
    1887             : 
    1888           0 :     SwTxtLineAccess aAccess( this );
    1889           0 :     SwParaPortion *pPara = aAccess.GetPara();
    1890           0 :     if( !pPara )
    1891           0 :         return sal_False;
    1892             : 
    1893           0 :     SwFrmSwapper aSwapper( this, sal_True );
    1894             : 
    1895           0 :     SwTxtFrmLocker aLock(this);
    1896           0 :     SwTxtFormatInfo aInf( this, sal_False, sal_True );
    1897           0 :     if( 0 != aInf.MaxHyph() )   // Respect MaxHyphen!
    1898           0 :         return sal_False;
    1899             : 
    1900           0 :     SwTxtFormatter  aLine( this, &aInf );
    1901             : 
    1902             :     // DropCaps are too complicated ...
    1903           0 :     if( aLine.GetDropFmt() )
    1904           0 :         return sal_False;
    1905             : 
    1906           0 :     xub_StrLen nStart = GetOfst();
    1907           0 :     const xub_StrLen nEnd = GetFollow()
    1908           0 :                       ? GetFollow()->GetOfst() : aInf.GetTxt().Len();
    1909           0 :     do
    1910             :     {
    1911           0 :         nStart = aLine.FormatLine( nStart );
    1912           0 :         if( aInf.IsNewLine() || (!aInf.IsStop() && nStart < nEnd) )
    1913           0 :             aLine.Insert( new SwLineLayout() );
    1914           0 :     } while( aLine.Next() );
    1915             : 
    1916             :     // Last exit: the heights need to match
    1917           0 :     Point aTopLeft( Frm().Pos() );
    1918           0 :     aTopLeft += Prt().Pos();
    1919           0 :     const SwTwips nNewHeight = aLine.Y() + aLine.GetLineHeight();
    1920           0 :     const SwTwips nOldHeight = aTopLeft.Y() + Prt().Height();
    1921             : 
    1922           0 :     if( !bForceQuickFormat && nNewHeight != nOldHeight && !IsUndersized() )
    1923             :     {
    1924             :         // Attention: This situation can occur due to FormatLevel==12. Don't panic!
    1925           0 :         const xub_StrLen nStrt = GetOfst();
    1926           0 :         _InvalidateRange( SwCharRange( nStrt, nEnd - nStrt) );
    1927           0 :         return sal_False;
    1928             :     }
    1929             : 
    1930           0 :     if (m_pFollow && nStart != (static_cast<SwTxtFrm*>(m_pFollow))->GetOfst())
    1931           0 :         return sal_False; // can be caused by e.g. Orphans
    1932             : 
    1933             :     // We made it!
    1934             : 
    1935             :     // Set repaint
    1936           0 :     pPara->GetRepaint()->Pos( aTopLeft );
    1937           0 :     pPara->GetRepaint()->SSize( Prt().SSize() );
    1938             : 
    1939             :     // Delete reformat
    1940           0 :     *(pPara->GetReformat()) = SwCharRange();
    1941           0 :     *(pPara->GetDelta()) = 0;
    1942             : 
    1943           0 :     return sal_True;
    1944             : }
    1945             : 
    1946             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10