LCOV - code coverage report
Current view: top level - sw/source/core/layout - tabfrm.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1910 2477 77.1 %
Date: 2014-04-11 Functions: 81 86 94.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "pagefrm.hxx"
      21             : #include "rootfrm.hxx"
      22             : #include "cntfrm.hxx"
      23             : #include "viewsh.hxx"
      24             : #include "doc.hxx"
      25             : #include "docsh.hxx"
      26             : #include "viewimp.hxx"
      27             : #include "swtable.hxx"
      28             : #include "dflyobj.hxx"
      29             : #include "flyfrm.hxx"
      30             : #include "frmtool.hxx"
      31             : #include "frmfmt.hxx"
      32             : #include "dcontact.hxx"
      33             : #include <anchoreddrawobject.hxx>
      34             : #include <fmtanchr.hxx>
      35             : #include "viewopt.hxx"
      36             : #include "hints.hxx"
      37             : #include "dbg_lay.hxx"
      38             : #include <ftnidx.hxx>
      39             : #include <svl/itemiter.hxx>
      40             : #include <docary.hxx>
      41             : #include <editeng/keepitem.hxx>
      42             : #include <editeng/ulspitem.hxx>
      43             : #include <editeng/lrspitem.hxx>
      44             : #include <editeng/brushitem.hxx>
      45             : #include <editeng/boxitem.hxx>
      46             : #include <vcl/outdev.hxx>
      47             : #include <fmtlsplt.hxx>
      48             : #include <fmtrowsplt.hxx>
      49             : #include <fmtsrnd.hxx>
      50             : #include <fmtornt.hxx>
      51             : #include <fmtpdsc.hxx>
      52             : #include <fmtfsize.hxx>
      53             : #include <swtblfmt.hxx>
      54             : #include <ndtxt.hxx>
      55             : #include "tabfrm.hxx"
      56             : #include "rowfrm.hxx"
      57             : #include "cellfrm.hxx"
      58             : #include "flyfrms.hxx"
      59             : #include "txtfrm.hxx"
      60             : #include "htmltbl.hxx"
      61             : #include "sectfrm.hxx"
      62             : #include <fmtfollowtextflow.hxx>
      63             : #include <sortedobjs.hxx>
      64             : #include <objectformatter.hxx>
      65             : #include <layouter.hxx>
      66             : #include <switerator.hxx>
      67             : 
      68             : extern void AppendObjs( const SwFrmFmts *pTbl, sal_uLong nIndex,
      69             :                         SwFrm *pFrm, SwPageFrm *pPage );
      70             : 
      71             : using namespace ::com::sun::star;
      72             : 
      73         499 : SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ):
      74             :     SwLayoutFrm( rTab.GetFrmFmt(), pSib ),
      75             :     SwFlowFrm( (SwFrm&)*this ),
      76         499 :     pTable( &rTab )
      77             : {
      78             :     bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove =
      79             :     bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
      80         499 :     bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
      81             :     // #i26945#
      82         499 :     bConsiderObjsForMinCellHeight = sal_True;
      83         499 :     bObjsDoesFit = sal_True;
      84         499 :     mbInRecalcLowerRow = false;
      85         499 :     mbFixSize = sal_False;     //Don't fall for import filter again.
      86         499 :     mnType = FRMC_TAB;
      87             : 
      88             :     //Create the lines and insert them.
      89         499 :     const SwTableLines &rLines = rTab.GetTabLines();
      90         499 :     SwFrm *pTmpPrev = 0;
      91        3081 :     for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
      92             :     {
      93        2582 :         SwRowFrm *pNew = new SwRowFrm( *rLines[i], this );
      94        2582 :         if( pNew->Lower() )
      95             :         {
      96        2582 :             pNew->InsertBehind( this, pTmpPrev );
      97        2582 :             pTmpPrev = pNew;
      98             :         }
      99             :         else
     100           0 :             delete pNew;
     101             :     }
     102             :     OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
     103         499 : }
     104             : 
     105         130 : SwTabFrm::SwTabFrm( SwTabFrm &rTab ) :
     106         130 :     SwLayoutFrm( rTab.GetFmt(), &rTab ),
     107             :     SwFlowFrm( (SwFrm&)*this ),
     108         260 :     pTable( rTab.GetTable() )
     109             : {
     110             :     bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove =
     111             :     bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
     112         130 :     bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
     113             :     // #i26945#
     114         130 :     bConsiderObjsForMinCellHeight = sal_True;
     115         130 :     bObjsDoesFit = sal_True;
     116         130 :     mbInRecalcLowerRow = false;
     117         130 :     mbFixSize = sal_False;     //Don't fall for import filter again.
     118         130 :     mnType = FRMC_TAB;
     119             : 
     120         130 :     SetFollow( rTab.GetFollow() );
     121         130 :     rTab.SetFollow( this );
     122         130 : }
     123             : 
     124             : extern const SwTable   *pColumnCacheLastTable;
     125             : extern const SwTabFrm  *pColumnCacheLastTabFrm;
     126             : extern const SwFrm     *pColumnCacheLastCellFrm;
     127             : extern const SwTable   *pRowCacheLastTable;
     128             : extern const SwTabFrm  *pRowCacheLastTabFrm;
     129             : extern const SwFrm     *pRowCacheLastCellFrm;
     130             : 
     131             : //return the SwTabFrm (if any) that this SwTabFrm is a follow flow line for
     132         629 : SwTabFrm* SwTabFrm::GetFollowFlowLineFor()
     133             : {
     134         629 :     SwFlowFrm *pPrec = GetPrecede();
     135         629 :     if (pPrec && pPrec->GetFrm()->IsTabFrm())
     136             :     {
     137           0 :         SwTabFrm *pPrevTabFrm = (SwTabFrm*)pPrec;
     138             :         assert(this == pPrevTabFrm->GetFollow());
     139           0 :         if (pPrevTabFrm->HasFollowFlowLine() && pPrevTabFrm->GetFollow() == this)
     140           0 :             return pPrevTabFrm;
     141             :     }
     142         629 :     return NULL;
     143             : }
     144             : 
     145        1887 : SwTabFrm::~SwTabFrm()
     146             : {
     147             :     //rhbz#907933, we are a follow flow line for something and have been
     148             :     //deleted, remove ourself as a follow flowline
     149         629 :     SwTabFrm* pFlowFrameFor = GetFollowFlowLineFor();
     150         629 :     if (pFlowFrameFor)
     151           0 :         pFlowFrameFor->RemoveFollowFlowLine();
     152             : 
     153             :     // There is some terrible code in fetab.cxx, that
     154             :     // makes use of these global pointers. Obviously
     155             :     // this code did not consider that a TabFrm can be
     156             :     // deleted.
     157         629 :     if ( this == pColumnCacheLastTabFrm )
     158             :     {
     159           1 :         pColumnCacheLastTable  = NULL;
     160           1 :         pColumnCacheLastTabFrm = NULL;
     161           1 :         pColumnCacheLastCellFrm= NULL;
     162           1 :         pRowCacheLastTable  = NULL;
     163           1 :         pRowCacheLastTabFrm = NULL;
     164           1 :         pRowCacheLastCellFrm= NULL;
     165             :     }
     166        1258 : }
     167             : 
     168           0 : void SwTabFrm::JoinAndDelFollows()
     169             : {
     170           0 :     SwTabFrm *pFoll = GetFollow();
     171           0 :     if ( pFoll->HasFollow() )
     172           0 :         pFoll->JoinAndDelFollows();
     173           0 :     pFoll->Cut();
     174           0 :     SetFollow( pFoll->GetFollow() );
     175           0 :     delete pFoll;
     176           0 : }
     177             : 
     178         189 : void SwTabFrm::RegistFlys()
     179             : {
     180             :     OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "No rows." );
     181             : 
     182         189 :     SwPageFrm *pPage = FindPageFrm();
     183         189 :     if ( pPage )
     184             :     {
     185         118 :         SwRowFrm *pRow = (SwRowFrm*)Lower();
     186         678 :         do
     187             :         {
     188         678 :             pRow->RegistFlys( pPage );
     189         678 :             pRow = (SwRowFrm*)pRow->GetNext();
     190             :         } while ( pRow );
     191             :     }
     192         189 : }
     193             : 
     194             : /*************************************************************************
     195             : |*  Some prototypes
     196             : |*************************************************************************/
     197             : void SwInvalidateAll( SwFrm *pFrm, long nBottom );
     198             : static void lcl_RecalcRow( SwRowFrm& rRow, long nBottom );
     199             : static bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, bool bInva );
     200             : // #i26945# - add parameter <_bOnlyRowsAndCells> to control
     201             : // that only row and cell frames are formatted.
     202             : static bool lcl_InnerCalcLayout( SwFrm *pFrm,
     203             :                                       long nBottom,
     204             :                                       bool _bOnlyRowsAndCells = false );
     205             : // OD 2004-02-18 #106629# - correct type of 1st parameter
     206             : // #i26945# - add parameter <_bConsiderObjs> in order to
     207             : // control, if floating screen objects have to be considered for the minimal
     208             : // cell height.
     209             : static SwTwips lcl_CalcMinRowHeight( const SwRowFrm *pRow,
     210             :                                           const sal_Bool _bConsiderObjs );
     211             : static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& );
     212             : 
     213             : /*************************************************************************
     214             : |*  START: local helper functions for repeated headlines
     215             : |*************************************************************************/
     216             : 
     217         180 : static SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount )
     218             : {
     219         180 :     if ( !nCount || !pStart)
     220         112 :         return 0;
     221             : 
     222          68 :     SwTwips nRet = 0;
     223          68 :     SWRECTFN( pStart )
     224         204 :     while ( pStart && nCount > 0 )
     225             :     {
     226          68 :         nRet += (pStart->Frm().*fnRect->fnGetHeight)();
     227          68 :         pStart = pStart->GetNext();
     228          68 :         --nCount;
     229             :     }
     230             : 
     231          68 :     return nRet;
     232             : }
     233             : 
     234             : /*************************************************************************
     235             : |*  END: local helper functions for repeated headlines
     236             : |*************************************************************************/
     237             : 
     238             : /*************************************************************************
     239             : |*  START: local helper functions for splitting row frames
     240             : |*************************************************************************/
     241             : 
     242             : // Local helper function to insert a new follow flow line
     243         112 : static SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine )
     244             : {
     245             :     OSL_ENSURE( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" );
     246         112 :     const SwRowFrm& rRow = (SwRowFrm&)rTmpRow;
     247             : 
     248         112 :     rTab.SetFollowFlowLine( sal_True );
     249         112 :     SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false );
     250         112 :     pFollowFlowLine->SetRowSpanLine( bRowSpanLine );
     251         112 :     SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow();
     252         112 :     pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow );
     253         112 :     return pFollowFlowLine;
     254             : }
     255             : 
     256             : // #i26945# - local helper function to invalidate all lower
     257             : // objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
     258             : // additionally the objects are moved 'out of range'.
     259        1782 : static void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm,
     260             :                               const bool _bMoveObjsOutOfRange = false,
     261             :                               SwPageFrm* _pPageFrm = 0L )
     262             : {
     263             :     // determine page frame, if needed
     264        1782 :     if ( !_pPageFrm )
     265             :     {
     266         730 :         _pPageFrm = _rLayoutFrm.FindPageFrm();
     267             :         OSL_ENSURE( _pPageFrm,
     268             :                 "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
     269         730 :         if ( !_pPageFrm )
     270             :         {
     271        1782 :             return;
     272             :         }
     273             :     }
     274             : 
     275             :     // loop on lower frames
     276        1782 :     SwFrm* pLowerFrm = _rLayoutFrm.Lower();
     277        6514 :     while ( pLowerFrm )
     278             :     {
     279        2950 :         if ( pLowerFrm->IsLayoutFrm() )
     280             :         {
     281             :             ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)),
     282        1052 :                                        _bMoveObjsOutOfRange, _pPageFrm );
     283             :         }
     284        2950 :         if ( pLowerFrm->GetDrawObjs() )
     285             :         {
     286          78 :             for ( sal_uInt16 i = 0; i < pLowerFrm->GetDrawObjs()->Count(); ++i )
     287             :             {
     288          48 :                 SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i];
     289             : 
     290             :                 // invalidate position of anchored object
     291          48 :                 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
     292          48 :                 pAnchoredObj->SetConsiderForTextWrap( false );
     293          48 :                 pAnchoredObj->UnlockPosition();
     294          48 :                 pAnchoredObj->InvalidateObjPos();
     295             : 
     296             :                 // move anchored object 'out of range'
     297          48 :                 if ( _bMoveObjsOutOfRange )
     298             :                 {
     299             :                     // indicate, that positioning is progress to avoid
     300             :                     // modification of the anchored object resp. its attributes
     301             :                     // due to the movement
     302          48 :                     SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
     303          48 :                     pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() );
     304             :                     // #115759# - reset character rectangle,
     305             :                     // top of line and relative position in order to assure,
     306             :                     // that anchored object is correctly positioned.
     307          48 :                     pAnchoredObj->ClearCharRectAndTopOfLine();
     308          48 :                     pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
     309          48 :                     if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
     310             :                             == FLY_AS_CHAR )
     311             :                     {
     312          48 :                         pAnchoredObj->AnchorFrm()
     313             :                                 ->Prepare( PREP_FLY_ATTR_CHG,
     314          48 :                                            &(pAnchoredObj->GetFrmFmt()) );
     315             :                     }
     316          48 :                     if ( pAnchoredObj->ISA(SwFlyFrm) )
     317             :                     {
     318           0 :                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
     319           0 :                         pFly->GetVirtDrawObj()->SetRectsDirty();
     320           0 :                         pFly->GetVirtDrawObj()->SetChanged();
     321          48 :                     }
     322             :                 }
     323             : 
     324             :                 // If anchored object is a fly frame, invalidate its lower objects
     325          48 :                 if ( pAnchoredObj->ISA(SwFlyFrm) )
     326             :                 {
     327           0 :                     SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
     328           0 :                     ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm );
     329             :                 }
     330             :             }
     331             :         }
     332        2950 :         pLowerFrm = pLowerFrm->GetNext();
     333             :     }
     334             : }
     335             : 
     336             : // Local helper function to shrink all lowers of rRow to 0 height
     337         187 : static void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow )
     338             : {
     339         187 :     SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower());
     340         187 :     SWRECTFN( pCurrMasterCell )
     341             : 
     342         867 :     while ( pCurrMasterCell )
     343             :     {
     344             :         // NEW TABLES
     345         493 :         SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ?
     346             :                                const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) :
     347         493 :                                *pCurrMasterCell;
     348             : 
     349             :         // #i26945#
     350             :         // all lowers should have the correct position
     351             :         lcl_ArrangeLowers( &rToAdjust,
     352         986 :                            (rToAdjust.*fnRect->fnGetPrtTop)(),
     353         986 :                            false );
     354             :         // TODO: Optimize number of frames which are set to 0 height
     355             :         // we have to start with the last lower frame, otherwise
     356             :         // the shrink will not shrink the current cell
     357         493 :         SwFrm* pTmp = rToAdjust.GetLastLower();
     358             : 
     359         493 :         if ( pTmp && pTmp->IsRowFrm() )
     360             :         {
     361           0 :             SwRowFrm* pTmpRow = (SwRowFrm*)pTmp;
     362           0 :             lcl_ShrinkCellsAndAllContent( *pTmpRow );
     363             :         }
     364             :         else
     365             :         {
     366             :             // TODO: Optimize number of frames which are set to 0 height
     367        1800 :             while ( pTmp )
     368             :             {
     369             :                 // the frames have to be shrunk
     370         814 :                 if ( pTmp->IsTabFrm() )
     371             :                 {
     372          30 :                     SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower();
     373         135 :                     while ( pTmpRow )
     374             :                     {
     375          75 :                         lcl_ShrinkCellsAndAllContent( *pTmpRow );
     376          75 :                         pTmpRow = (SwRowFrm*)pTmpRow->GetNext();
     377             :                     }
     378             :                 }
     379             :                 else
     380             :                 {
     381         784 :                     pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() );
     382         784 :                     (pTmp->Prt().*fnRect->fnSetTop)( 0 );
     383         784 :                     (pTmp->Prt().*fnRect->fnSetHeight)( 0 );
     384             :                 }
     385             : 
     386         814 :                 pTmp = pTmp->GetPrev();
     387             :             }
     388             : 
     389             :             // all lowers should have the correct position
     390             :             lcl_ArrangeLowers( &rToAdjust,
     391         986 :                                (rToAdjust.*fnRect->fnGetPrtTop)(),
     392         986 :                                false );
     393             :         }
     394             : 
     395         493 :         pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext());
     396             :     }
     397         187 : }
     398             : 
     399             : // Local helper function to move the content from rSourceLine to rDestLine
     400             : // The content is inserted behind the last content in the corresponding
     401             : // cell in rDestLine.
     402          92 : static void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine )
     403             : {
     404          92 :     SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower();
     405          92 :     SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
     406             : 
     407             :     // Move content of follow cells into master cells
     408         425 :     while ( pCurrSourceCell )
     409             :     {
     410         241 :         if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() )
     411             :         {
     412           0 :             SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
     413           0 :             while ( pTmpSourceRow )
     414             :             {
     415             :                 // #125926# Achtung! It is possible,
     416             :                 // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
     417             :                 // cannot be found. In this case, we have to move the complete
     418             :                 // row.
     419           0 :                 SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower();
     420             : 
     421           0 :                 if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow )
     422             :                 {
     423             :                     // move content from follow flow row to pTmpDestRow:
     424           0 :                     while ( pTmpDestRow->GetNext() )
     425           0 :                         pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext();
     426             : 
     427             :                     OSL_ENSURE( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Table contains node" );
     428             : 
     429           0 :                     lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow );
     430           0 :                     pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() );
     431           0 :                     pTmpSourceRow->Remove();
     432           0 :                     delete pTmpSourceRow;
     433             :                 }
     434             :                 else
     435             :                 {
     436             :                     // move complete row:
     437           0 :                     pTmpSourceRow->Remove();
     438           0 :                     pTmpSourceRow->InsertBefore( pCurrDestCell, 0 );
     439             :                 }
     440             : 
     441           0 :                 pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
     442             :             }
     443             :         }
     444             :         else
     445             :         {
     446         241 :             SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell );
     447         241 :             if ( pTmp )
     448             :             {
     449             :                 // NEW TABLES
     450         147 :                 SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell);
     451         147 :                 if ( pDestCell->GetTabBox()->getRowSpan() < 1 )
     452           0 :                     pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true ));
     453             : 
     454             :                 // Find last content
     455         147 :                 SwFrm* pFrm = pDestCell->GetLastLower();
     456         147 :                 ::RestoreCntnt( pTmp, pDestCell, pFrm, true );
     457             :             }
     458             :         }
     459         241 :         pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext();
     460         241 :         pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
     461             :     }
     462          92 : }
     463             : 
     464             : // Local helper function to move all footnotes in rRowFrm from
     465             : // the footnote boss of rSource to the footnote boss of rDest.
     466          80 : static void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm )
     467             : {
     468          80 :     if ( !rSource.GetFmt()->GetDoc()->GetFtnIdxs().empty() )
     469             :     {
     470           0 :         SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( sal_True );
     471           0 :         SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( sal_True );
     472           0 :         rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, sal_True );
     473             :     }
     474          80 : }
     475             : 
     476             : // Local helper function to handle nested table cells before the split process
     477         112 : static void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine,
     478             :                                 SwRowFrm& rFollowFlowLine, SwTwips nRemain )
     479             : {
     480         112 :     SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower();
     481         112 :     SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower();
     482             : 
     483         112 :     SWRECTFN( pCurrLastLineCell )
     484             : 
     485             :     // Move content of follow cells into master cells
     486         486 :     while ( pCurrLastLineCell )
     487             :     {
     488         262 :         if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() )
     489             :         {
     490           0 :             SwTwips nTmpCut = nRemain;
     491           0 :             SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower();
     492             : 
     493             :             // #i26945#
     494             :             SwTwips nCurrentHeight =
     495             :                     lcl_CalcMinRowHeight( pTmpLastLineRow,
     496           0 :                                           rTab.IsConsiderObjsForMinCellHeight() );
     497           0 :             while ( pTmpLastLineRow && pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight )
     498             :             {
     499           0 :                 nTmpCut -= nCurrentHeight;
     500           0 :                 pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
     501             :                 // #i26945#
     502             :                 nCurrentHeight =
     503             :                     lcl_CalcMinRowHeight( pTmpLastLineRow,
     504           0 :                                           rTab.IsConsiderObjsForMinCellHeight() );
     505             :             }
     506             : 
     507             :             // pTmpLastLineRow does not fit to the line or it is the last line
     508           0 :             if ( pTmpLastLineRow )
     509             :             {
     510             :                 // Check if we can move pTmpLastLineRow to the follow table,
     511             :                 // or if we have to split the line:
     512           0 :                 SwFrm* pCell = pTmpLastLineRow->Lower();
     513           0 :                 bool bTableLayoutToComplex = false;
     514           0 :                 long nMinHeight = 0;
     515             : 
     516             :                 // We have to take into account:
     517             :                 // 1. The fixed height of the row
     518             :                 // 2. The borders of the cells inside the row
     519             :                 // 3. The minimum height of the row
     520           0 :                 if ( pTmpLastLineRow->HasFixSize() )
     521           0 :                     nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)();
     522             :                 else
     523             :                 {
     524           0 :                     while ( pCell )
     525             :                     {
     526           0 :                         if ( ((SwCellFrm*)pCell)->Lower() &&
     527           0 :                              ((SwCellFrm*)pCell)->Lower()->IsRowFrm() )
     528             :                         {
     529           0 :                             bTableLayoutToComplex = true;
     530           0 :                             break;
     531             :                         }
     532             : 
     533           0 :                         SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
     534           0 :                         const SwBorderAttrs &rAttrs = *aAccess.Get();
     535           0 :                         nMinHeight = std::max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) );
     536           0 :                         pCell = pCell->GetNext();
     537           0 :                     }
     538             : 
     539           0 :                     const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize();
     540           0 :                     if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
     541           0 :                         nMinHeight = std::max( nMinHeight, rSz.GetHeight() );
     542             :                 }
     543             : 
     544             :                 // 1. Case:
     545             :                 // The line completely fits into the master table.
     546             :                 // Nevertheless, we build a follow (otherwise painting problems
     547             :                 // with empty cell).
     548             : 
     549             :                 // 2. Case:
     550             :                 // The line has to be split, the minimum height still fits into
     551             :                 // the master table, and the table structure is not to complex.
     552           0 :                 if ( nTmpCut > nCurrentHeight ||
     553           0 :                      ( pTmpLastLineRow->IsRowSplitAllowed() &&
     554           0 :                       !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
     555             :                 {
     556             :                     // The line has to be split:
     557           0 :                     SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false );
     558           0 :                     pNewRow->SetFollowFlowRow( true );
     559           0 :                     pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() );
     560           0 :                     pTmpLastLineRow->SetFollowRow( pNewRow );
     561           0 :                     pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 );
     562           0 :                     pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
     563             :                 }
     564             : 
     565             :                 // The following lines have to be moved:
     566           0 :                 while ( pTmpLastLineRow )
     567             :                 {
     568           0 :                     SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext();
     569           0 :                     lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow );
     570           0 :                     pTmpLastLineRow->Remove();
     571           0 :                     pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 );
     572           0 :                     pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
     573           0 :                     pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
     574           0 :                     pTmpLastLineRow = pTmp;
     575             :                 }
     576             :             }
     577             :         }
     578             : 
     579         262 :         pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext();
     580         262 :         pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext();
     581             :     }
     582         112 : }
     583             : 
     584             : // Local helper function to handle nested table cells after the split process
     585         112 : static void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine )
     586             : {
     587         112 :     SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
     588         486 :     while ( pCurrMasterCell )
     589             :     {
     590         456 :         if ( pCurrMasterCell->Lower() &&
     591         194 :              pCurrMasterCell->Lower()->IsRowFrm() )
     592             :         {
     593           0 :             SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower());
     594             : 
     595           0 :             if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() )
     596             :             {
     597             :                 OSL_ENSURE( pRowFrm->GetFollowRow(), "Deleting row frame without follow" );
     598             : 
     599             :                 // The footnotes have to be moved:
     600           0 :                 lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm );
     601           0 :                 pRowFrm->Cut();
     602           0 :                 SwRowFrm* pFollowRow = pRowFrm->GetFollowRow();
     603           0 :                 pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow );
     604           0 :                 pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() );
     605           0 :                 lcl_MoveRowContent( *pFollowRow, *pRowFrm );
     606           0 :                 pFollowRow->Cut();
     607           0 :                 delete pFollowRow;
     608           0 :                 ::SwInvalidateAll( pCurrMasterCell, LONG_MAX );
     609             :             }
     610             :         }
     611             : 
     612         262 :         pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
     613             :     }
     614         112 : }
     615             : 
     616             : // Local helper function to re-calculate the split line.
     617         134 : inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); }
     618         134 : inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); }
     619             : 
     620         112 : static bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine,
     621             :                           SwTwips nRemainingSpaceForLastRow )
     622             : {
     623         112 :     bool bRet = true;
     624             : 
     625         112 :     SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper();
     626             : 
     627             :     // If there are nested cells in rLastLine, the recalculation of the last
     628             :     // line needs some preprocessing.
     629         112 :     lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow );
     630             : 
     631             :     // Here the recalculation process starts:
     632         112 :     rTab.SetRebuildLastLine( sal_True );
     633             :     // #i26945#
     634         112 :     rTab.SetDoesObjsFit( sal_True );
     635         112 :     SWRECTFN( rTab.GetUpper() )
     636             : 
     637             :     // #i26945# - invalidate and move floating screen
     638             :     // objects 'out of range'
     639         112 :     ::lcl_InvalidateLowerObjs( rLastLine, true );
     640             : 
     641             :     // manipulate row and cell sizes
     642             : 
     643             :     // #i26945# - Do *not* consider floating screen objects
     644             :     // for the minimal cell height.
     645         112 :     rTab.SetConsiderObjsForMinCellHeight( sal_False );
     646         112 :     ::lcl_ShrinkCellsAndAllContent( rLastLine );
     647         112 :     rTab.SetConsiderObjsForMinCellHeight( sal_True );
     648             : 
     649             :     // invalidate last line
     650         112 :     ::SwInvalidateAll( &rLastLine, LONG_MAX );
     651             : 
     652             :     // Lock this tab frame and its follow
     653         112 :     bool bUnlockMaster = false;
     654         112 :     bool bUnlockFollow = false;
     655         112 :     SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0;
     656         112 :     if ( pMaster && !pMaster->IsJoinLocked() )
     657             :     {
     658          22 :         bUnlockMaster = true;
     659          22 :         ::TableSplitRecalcLock( pMaster );
     660             :     }
     661         112 :     if ( !rTab.GetFollow()->IsJoinLocked() )
     662             :     {
     663         112 :         bUnlockFollow = true;
     664         112 :         ::TableSplitRecalcLock( rTab.GetFollow() );
     665             :     }
     666             : 
     667             :     // Do the recalculation
     668         112 :     lcl_RecalcRow( rLastLine, LONG_MAX );
     669             :     // #115759# - force a format of the last line in order to
     670             :     // get the correct height.
     671         112 :     rLastLine.InvalidateSize();
     672         112 :     rLastLine.Calc();
     673             : 
     674             :     // Unlock this tab frame and its follow
     675         112 :     if ( bUnlockFollow )
     676         112 :         ::TableSplitRecalcUnlock( rTab.GetFollow() );
     677         112 :     if ( bUnlockMaster )
     678          22 :         ::TableSplitRecalcUnlock( pMaster );
     679             : 
     680             :     // If there are nested cells in rLastLine, the recalculation of the last
     681             :     // line needs some postprocessing.
     682         112 :     lcl_PostprocessRowsInCells( rTab, rLastLine );
     683             : 
     684             :     // Do a couple of checks on the current situation.
     685             : 
     686             :     // If we are not happy with the current situation we return false.
     687             :     // This will start a new try to split the table, this time we do not
     688             :     // try to split the table rows.
     689             : 
     690             :     // 1. Check if table fits to its upper.
     691             :     // #i26945# - include check, if objects fit
     692             :     const SwTwips nDistanceToUpperPrtBottom =
     693         112 :             (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
     694         112 :     if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() )
     695          61 :         bRet = false;
     696             : 
     697             :     // 2. Check if each cell in the last line has at least one content frame.
     698             : 
     699             :     // Note: a FollowFlowRow may contains empty cells!
     700         112 :     if ( bRet )
     701             :     {
     702          51 :         if ( !rLastLine.IsInFollowFlowRow() )
     703             :         {
     704          48 :             SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
     705         150 :             while ( pCurrMasterCell )
     706             :             {
     707          67 :                 if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 )
     708             :                 {
     709          13 :                     bRet = false;
     710          13 :                     break;
     711             :                 }
     712          54 :                 pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
     713             :             }
     714             :         }
     715             :     }
     716             : 
     717             :     // 3. Check if last line does not contain any content:
     718         112 :     if ( bRet )
     719             :     {
     720          38 :         if ( !rLastLine.ContainsCntnt() )
     721             :         {
     722           0 :             bRet = false;
     723             :         }
     724             :     }
     725             : 
     726             :     // 4. Check if follow flow line does not contain content:
     727         112 :     if ( bRet )
     728             :     {
     729          38 :         if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() )
     730             :         {
     731           0 :             bRet = false;
     732             :         }
     733             :     }
     734             : 
     735         112 :     if ( bRet )
     736             :     {
     737             :         // Everything looks fine. Splitting seems to be successful. We invalidate
     738             :         // rFollowLine to force a new formatting.
     739          38 :         ::SwInvalidateAll( &rFollowLine, LONG_MAX );
     740             :     }
     741             :     else
     742             :     {
     743             :         // Splitting the table row gave us an unexpected result.
     744             :         // Everything has to be prepared for a second try to split
     745             :         // the table, this time without splitting the row.
     746          74 :         ::SwInvalidateAll( &rLastLine, LONG_MAX );
     747             :     }
     748             : 
     749         112 :     rTab.SetRebuildLastLine( sal_False );
     750             :     // #i26945#
     751         112 :     rTab.SetDoesObjsFit( sal_True );
     752             : 
     753         112 :     return bRet;
     754             : }
     755             : 
     756             : // Sets the correct height for all spanned cells
     757           0 : static void lcl_AdjustRowSpanCells( SwRowFrm* pRow )
     758             : {
     759           0 :     SWRECTFN( pRow )
     760           0 :     SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower());
     761           0 :     while ( pCellFrm )
     762             :     {
     763           0 :         const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan();
     764           0 :         if ( nLayoutRowSpan > 1 )
     765             :         {
     766             :             // calculate height of cell:
     767           0 :             const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan );
     768           0 :             const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
     769           0 :             if ( nDiff )
     770           0 :                 (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
     771             :         }
     772             : 
     773           0 :         pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
     774             :     }
     775           0 : }
     776             : 
     777             : // Returns the maximum layout row span of the row
     778             : // Looking for the next row that contains no covered cells:
     779         803 : static long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow )
     780             : {
     781         803 :     long nRet = 1;
     782             : 
     783         803 :     const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext());
     784         803 :     bool bNextRow = false;
     785             : 
     786        2340 :     while ( pCurrentRowFrm )
     787             :     {
     788             :         // if there is any covered cell, we proceed to the next row frame
     789         734 :         const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower());
     790        3125 :         while ( pLower )
     791             :         {
     792        1657 :             if ( pLower->GetTabBox()->getRowSpan() < 0 )
     793             :             {
     794           0 :                 ++nRet;
     795           0 :                 bNextRow = true;
     796           0 :                 break;
     797             :             }
     798        1657 :             pLower = static_cast<const SwCellFrm*>(pLower->GetNext());
     799             :         }
     800             :         pCurrentRowFrm = bNextRow ?
     801           0 :                          static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) :
     802         734 :                          0;
     803             :     }
     804             : 
     805         803 :     return nRet;
     806             : }
     807             : 
     808             : /*************************************************************************
     809             : |*  END: local helper functions for splitting row frames
     810             : |*************************************************************************/
     811             : 
     812             : // Function to remove the FollowFlowLine of rTab.
     813             : // The content of the FollowFlowLine is moved to the associated line in the
     814             : // master table.
     815          92 : bool SwTabFrm::RemoveFollowFlowLine()
     816             : {
     817             :     // find FollowFlowLine
     818          92 :     SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow());
     819             : 
     820             :     // find last row in master
     821          92 :     SwFrm* pLastLine = GetLastLower();
     822             : 
     823             :     OSL_ENSURE( HasFollowFlowLine() &&
     824             :             pFollowFlowLine &&
     825             :             pLastLine, "There should be a flowline in the follow" );
     826             : 
     827             :     // We have to reset the flag here, because lcl_MoveRowContent
     828             :     // calls a GrowFrm(), which has a different bahavior if
     829             :     // this flag is set.
     830          92 :     SetFollowFlowLine( sal_False );
     831             : 
     832             :     // #140081# Make code robust.
     833          92 :     if ( !pFollowFlowLine || !pLastLine )
     834           0 :         return true;
     835             : 
     836             :     // Move content
     837          92 :     lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine );
     838             : 
     839             :     // NEW TABLES
     840             :     // If a row span follow flow line is removed, we want to move the whole span
     841             :     // to the master:
     842          92 :     long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine );
     843             : 
     844          92 :     if ( nRowsToMove > 1 )
     845             :     {
     846           0 :         SWRECTFN( this )
     847           0 :         SwFrm* pRow = pFollowFlowLine->GetNext();
     848           0 :         SwFrm* pInsertBehind = GetLastLower();
     849           0 :         SwTwips nGrow = 0;
     850             : 
     851           0 :         while ( pRow && nRowsToMove-- > 1 )
     852             :         {
     853           0 :             SwFrm* pNxt = pRow->GetNext();
     854           0 :             nGrow += (pRow->Frm().*fnRect->fnGetHeight)();
     855             : 
     856             :             // The footnotes have to be moved:
     857           0 :             lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow );
     858             : 
     859           0 :             pRow->Remove();
     860           0 :             pRow->InsertBehind( this, pInsertBehind );
     861           0 :             pRow->_InvalidateAll();
     862           0 :             pRow->CheckDirChange();
     863           0 :             pInsertBehind = pRow;
     864           0 :             pRow = pNxt;
     865             :         }
     866             : 
     867           0 :         SwFrm* pFirstRow = Lower();
     868           0 :         while ( pFirstRow )
     869             :         {
     870           0 :             lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) );
     871           0 :             pFirstRow = pFirstRow->GetNext();
     872             :         }
     873             : 
     874           0 :         Grow( nGrow );
     875           0 :         GetFollow()->Shrink( nGrow );
     876             :     }
     877             : 
     878          92 :     bool bJoin = !pFollowFlowLine->GetNext();
     879          92 :     pFollowFlowLine->Cut();
     880          92 :     delete pFollowFlowLine;
     881             : 
     882          92 :     return bJoin;
     883             : }
     884             : 
     885             : // #i26945# - Floating screen objects are no longer searched.
     886         180 : static bool lcl_FindSectionsInRow( const SwRowFrm& rRow )
     887             : {
     888         180 :     bool bRet = false;
     889         180 :     SwCellFrm* pLower = (SwCellFrm*)rRow.Lower();
     890         815 :     while ( pLower )
     891             :     {
     892         455 :         if ( pLower->IsVertical() != rRow.IsVertical() )
     893           0 :             return true;
     894             : 
     895         455 :         SwFrm* pTmpFrm = pLower->Lower();
     896        1650 :         while ( pTmpFrm )
     897             :         {
     898         740 :             if ( pTmpFrm->IsRowFrm() )
     899             :             {
     900           0 :                 bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm );
     901             :             }
     902             :             else
     903             :             {
     904             :                 // #i26945# - search only for sections
     905         740 :                 bRet = pTmpFrm->IsSctFrm();
     906             :             }
     907             : 
     908         740 :             if ( bRet )
     909           0 :                 return true;
     910         740 :             pTmpFrm = pTmpFrm->GetNext();
     911             :         }
     912             : 
     913         455 :         pLower = (SwCellFrm*)pLower->GetNext();
     914             :     }
     915         180 :     return bRet;
     916             : }
     917             : 
     918         180 : bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep )
     919             : {
     920         180 :     bool bRet = true;
     921             : 
     922         180 :     SWRECTFN( this )
     923             : 
     924             :     // #i26745# - format row and cell frames of table
     925             :     {
     926         180 :         this->Lower()->_InvalidatePos();
     927             :         // #i43913# - correction
     928             :         // call method <lcl_InnerCalcLayout> with first lower.
     929         180 :         lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
     930             :     }
     931             : 
     932             :     //In order to be able to compare the positions of the cells whit CutPos,
     933             :     //they have to be calculated consecutively starting from the table.
     934             :     //They can definitely be invalid because of position changes of the table.
     935         180 :     SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower());
     936         180 :     if( !pRow )
     937           0 :         return bRet;
     938             : 
     939         180 :     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
     940         180 :     sal_uInt16 nRowCount = 0;           // pRow currently points to the first row
     941             : 
     942             :     SwTwips nRemainingSpaceForLastRow =
     943         180 :         (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() );
     944         180 :     nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)();
     945             : 
     946             :     // Make pRow point to the line that does not fit anymore:
     947        6918 :     while( pRow->GetNext() &&
     948        9918 :            nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() +
     949        3306 :                                            (IsCollapsingBorders() ?
     950        3306 :                                             pRow->GetBottomLineSize() :
     951             :                                             0 ) ) )
     952             :     {
     953        3252 :         if( bTryToSplit || !pRow->IsRowSpanLine() ||
     954           0 :             0 != (pRow->Frm().*fnRect->fnGetHeight)() )
     955        3252 :             ++nRowCount;
     956        3252 :         nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)();
     957        3252 :         pRow = static_cast<SwRowFrm*>(pRow->GetNext());
     958             :     }
     959             : 
     960             :     // bSplitRowAllowed: Row may be split according to its attributes.
     961             :     // bTryToSplit:      Row will never be split if bTryToSplit = false.
     962             :     //                   This can either be passed as a parameter, indicating
     963             :     //                   that we are currently doing the second try to split the
     964             :     //                   table, or it will be set to falseunder certain
     965             :     //                   conditions that are not suitable for splitting
     966             :     //                   the row.
     967         180 :     bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
     968             : 
     969             :     // #i29438#
     970             :     // #i26945# - Floating screen objects no longer forbid
     971             :     // a splitting of the table row.
     972             :     // Special DoNotSplit case 1:
     973             :     // Search for sections inside pRow:
     974         180 :     if ( lcl_FindSectionsInRow( *pRow ) )
     975             :     {
     976           0 :         bTryToSplit = false;
     977             :     }
     978             : 
     979             :     // #i29771#
     980             :     // To avoid loops, we do some checks before actually trying to split
     981             :     // the row. Maybe we should keep the next row in this table.
     982             :     // Note: This is only done if we are at the beginning of our upper
     983         180 :     bool bKeepNextRow = false;
     984         180 :     if ( nRowCount < nRepeat )
     985             :     {
     986             :         // First case: One of the repeated headline does not fit to the page anymore.
     987             :         // At least one more non-heading row has to stay in this table in
     988             :         // order to avoid loops:
     989             :         OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
     990           0 :         bKeepNextRow = true;
     991             :     }
     992         180 :     else if ( !GetIndPrev() && nRepeat == nRowCount )
     993             :     {
     994             :         // Second case: The first non-headline row does not fit to the page.
     995             :         // If it is not allowed to be split, or it contains a sub-row that
     996             :         // is not allowed to be split, we keep the row in this table:
     997          13 :         if ( bTryToSplit && bSplitRowAllowed )
     998             :         {
     999             :             // Check if there are (first) rows inside this row,
    1000             :             // which are not allowed to be split.
    1001          13 :             SwCellFrm* pLowerCell = pRow ? (SwCellFrm*)pRow->Lower() : 0;
    1002          45 :             while ( pLowerCell )
    1003             :             {
    1004          19 :                 if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() )
    1005             :                 {
    1006           0 :                     const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower();
    1007           0 :                     if ( !pLowerRow->IsRowSplitAllowed() &&
    1008           0 :                         (pLowerRow->Frm().*fnRect->fnGetHeight)() >
    1009             :                         nRemainingSpaceForLastRow )
    1010             :                     {
    1011           0 :                         bKeepNextRow = true;
    1012           0 :                         break;
    1013             :                     }
    1014             :                 }
    1015          19 :                 pLowerCell = (SwCellFrm*)pLowerCell->GetNext();
    1016          13 :             }
    1017             :         }
    1018             :         else
    1019           0 :             bKeepNextRow = true;
    1020             :     }
    1021             : 
    1022             :     // Better keep the next row in this table:
    1023         180 :     if ( bKeepNextRow )
    1024             :     {
    1025           0 :         pRow = GetFirstNonHeadlineRow();
    1026           0 :         if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() )
    1027           0 :             pRow = static_cast<SwRowFrm*>(pRow->GetNext());
    1028           0 :         if ( pRow )
    1029             :         {
    1030           0 :             pRow = static_cast<SwRowFrm*>(pRow->GetNext());
    1031           0 :             ++nRowCount;
    1032             :         }
    1033             :     }
    1034             : 
    1035             :     // No more row to split or to move to follow table:
    1036         180 :     if ( !pRow )
    1037           0 :         return bRet;
    1038             : 
    1039             :     // We try to split the row if
    1040             :     // - the attributes of the row are set accordingly and
    1041             :     // - we are allowed to do so
    1042             :     // - the it should not keep with the next row
    1043         404 :     bSplitRowAllowed = bSplitRowAllowed && bTryToSplit &&
    1044         222 :                        ( !bTableRowKeep ||
    1045         290 :                          !pRow->ShouldRowKeepWithNext() );
    1046             : 
    1047             :     // Adjust pRow according to the keep-with-next attribute:
    1048         180 :     if ( !bSplitRowAllowed && bTableRowKeep )
    1049             :     {
    1050          66 :         SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev());
    1051          66 :         SwRowFrm* pOldRow = pRow;
    1052         132 :         while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
    1053             :                 nRowCount > nRepeat )
    1054             :         {
    1055           0 :             pRow = pTmpRow;
    1056           0 :             --nRowCount;
    1057           0 :             pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev());
    1058             :         }
    1059             : 
    1060             :         // loop prevention
    1061          66 :         if ( nRowCount == nRepeat && !GetIndPrev())
    1062             :         {
    1063           0 :             pRow = pOldRow;
    1064             :         }
    1065             :     }
    1066             : 
    1067             :     // If we do not indent to split pRow, we check if we are
    1068             :     // allowed to move pRow to a follow. Otherwise we return
    1069             :     // false, indicating an error
    1070         180 :     if ( !bSplitRowAllowed )
    1071             :     {
    1072          68 :         SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
    1073          68 :         if ( pRow == pFirstNonHeadlineRow )
    1074           0 :             return false;
    1075             : 
    1076             :         // #i91764#
    1077             :         // Ignore row span lines
    1078          68 :         SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
    1079         136 :         while ( pTmpRow && pTmpRow->IsRowSpanLine() )
    1080             :         {
    1081           0 :             pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext());
    1082             :         }
    1083          68 :         if ( !pTmpRow || pRow == pTmpRow )
    1084             :         {
    1085           0 :             return false;
    1086             :         }
    1087             :     }
    1088             : 
    1089             :     // Build follow table if not already done:
    1090             :     bool bNewFollow;
    1091             :     SwTabFrm *pFoll;
    1092         180 :     if ( GetFollow() )
    1093             :     {
    1094         110 :         pFoll = GetFollow();
    1095         110 :         bNewFollow = false;
    1096             :     }
    1097             :     else
    1098             :     {
    1099          70 :         bNewFollow = true;
    1100          70 :         pFoll = new SwTabFrm( *this );
    1101             : 
    1102             :         // We give the follow table an initial width.
    1103          70 :         (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() );
    1104          70 :         (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() );
    1105          70 :         (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() );
    1106             : 
    1107             :         // Insert the new follow table
    1108          70 :         pFoll->InsertBehind( GetUpper(), this );
    1109             : 
    1110             :         // Repeat the headlines.
    1111          70 :         for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount )
    1112             :         {
    1113             :             // Insert new headlines:
    1114           0 :             bDontCreateObjects = true;              //frmtool
    1115             :             SwRowFrm* pHeadline = new SwRowFrm(
    1116           0 :                                     *GetTable()->GetTabLines()[ nRowCount ], this );
    1117           0 :             pHeadline->SetRepeatedHeadline( true );
    1118           0 :             bDontCreateObjects = false;
    1119           0 :             pHeadline->InsertBefore( pFoll, 0 );
    1120             : 
    1121           0 :             SwPageFrm *pPage = pHeadline->FindPageFrm();
    1122           0 :             const SwFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts();
    1123           0 :             if( !pTbl->empty() )
    1124             :             {
    1125             :                 sal_uLong nIndex;
    1126           0 :                 SwCntntFrm* pFrm = pHeadline->ContainsCntnt();
    1127           0 :                 while( pFrm )
    1128             :                 {
    1129           0 :                     nIndex = pFrm->GetNode()->GetIndex();
    1130           0 :                     AppendObjs( pTbl, nIndex, pFrm, pPage );
    1131           0 :                     pFrm = pFrm->GetNextCntntFrm();
    1132           0 :                     if( !pHeadline->IsAnLower( pFrm ) )
    1133           0 :                         break;
    1134             :                 }
    1135             :             }
    1136             :         }
    1137             :     }
    1138             : 
    1139         180 :     SwRowFrm* pLastRow = 0;     // will point to the last remaining line in master
    1140         180 :     SwRowFrm* pFollowRow = 0;   // points to either the follow flow line of the
    1141             :                                 // first regular line in the follow
    1142             : 
    1143         180 :     if ( bSplitRowAllowed )
    1144             :     {
    1145             :         // If the row that does not fit anymore is allowed
    1146             :         // to be split, the next row has to be moved to the follow table.
    1147         112 :         pLastRow = pRow;
    1148         112 :         pRow = static_cast<SwRowFrm*>(pRow->GetNext());
    1149             : 
    1150             :         // new follow flow line for last row of master table
    1151         112 :         pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false );
    1152             :     }
    1153             :     else
    1154             :     {
    1155          68 :         pFollowRow = pRow;
    1156             : 
    1157             :         // NEW TABLES
    1158             :         // check if we will break a row span by moving pFollowRow to the follow:
    1159             :         // In this case we want to reformat the last line.
    1160          68 :         const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower());
    1161         329 :         while ( pCellFrm )
    1162             :         {
    1163         193 :             if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
    1164             :             {
    1165           0 :                 pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev());
    1166           0 :                 break;
    1167             :             }
    1168             : 
    1169         193 :             pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext());
    1170             :         }
    1171             : 
    1172             :         // new follow flow line for last row of master table
    1173          68 :         if ( pLastRow )
    1174           0 :             pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
    1175             :     }
    1176             : 
    1177         180 :     SwTwips nRet = 0;
    1178             : 
    1179             :     //Optimization: There is no paste needed for the new Follow and the
    1180             :     //optimized insert can be used (big amounts of rows luckily only occurs in
    1181             :     //such situations).
    1182         180 :     if ( bNewFollow )
    1183             :     {
    1184          70 :         SwFrm* pNxt = 0;
    1185          70 :         SwFrm* pInsertBehind = pFoll->GetLastLower();
    1186             : 
    1187        2577 :         while ( pRow )
    1188             :         {
    1189        2437 :             pNxt = pRow->GetNext();
    1190        2437 :             nRet += (pRow->Frm().*fnRect->fnGetHeight)();
    1191             :             // The footnotes do not have to be moved, this is done in the
    1192             :             // MoveFwd of the follow table!!!
    1193        2437 :             pRow->Remove();
    1194        2437 :             pRow->InsertBehind( pFoll, pInsertBehind );
    1195        2437 :             pRow->_InvalidateAll();
    1196        2437 :             pInsertBehind = pRow;
    1197        2437 :             pRow = static_cast<SwRowFrm*>(pNxt);
    1198             :         }
    1199             :     }
    1200             :     else
    1201             :     {
    1202         110 :         SwFrm* pNxt = 0;
    1203         110 :         SwFrm* pPasteBefore = HasFollowFlowLine() ?
    1204          48 :                               pFollowRow->GetNext() :
    1205         158 :                               pFoll->GetFirstNonHeadlineRow();
    1206             : 
    1207         300 :         while ( pRow )
    1208             :         {
    1209          80 :             pNxt = pRow->GetNext();
    1210          80 :             nRet += (pRow->Frm().*fnRect->fnGetHeight)();
    1211             : 
    1212             :             // The footnotes have to be moved:
    1213          80 :             lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
    1214             : 
    1215          80 :             pRow->Remove();
    1216          80 :             pRow->Paste( pFoll, pPasteBefore );
    1217             : 
    1218          80 :             pRow->CheckDirChange();
    1219          80 :             pRow = static_cast<SwRowFrm*>(pNxt);
    1220             :         }
    1221             :     }
    1222             : 
    1223         180 :     Shrink( nRet );
    1224             : 
    1225             :     // we rebuild the last line to assure that it will be fully formatted
    1226         180 :     if ( pLastRow )
    1227             :     {
    1228             :         // recalculate the split line
    1229         112 :         bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow );
    1230             : 
    1231             :         // NEW TABLES
    1232             :         // check if each cell in the row span line has a good height
    1233         112 :         if ( bRet && pFollowRow->IsRowSpanLine() )
    1234           0 :             lcl_AdjustRowSpanCells( pFollowRow );
    1235             : 
    1236             :         // We The RowSplitLine stuff did not work. In this case we conceal the split error:
    1237         112 :         if ( !bRet && !bSplitRowAllowed )
    1238             :         {
    1239           0 :             bRet = true;
    1240             :         }
    1241             :     }
    1242             : 
    1243         180 :     return bRet;
    1244             : }
    1245             : 
    1246          69 : bool SwTabFrm::Join()
    1247             : {
    1248             :     OSL_ENSURE( !HasFollowFlowLine(), "Joining follow flow line" );
    1249             : 
    1250          69 :     SwTabFrm *pFoll = GetFollow();
    1251             : 
    1252          69 :     if ( !pFoll->IsJoinLocked() )
    1253             :     {
    1254          69 :         SWRECTFN( this )
    1255          69 :         pFoll->Cut();   //Cut out first to avoid unnecessary notifications.
    1256             : 
    1257          69 :         SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(),
    1258             :               *pNxt;
    1259             : 
    1260          69 :         SwFrm* pPrv = GetLastLower();
    1261             : 
    1262          69 :         SwTwips nHeight = 0;    //Total height of the inserted rows as return value.
    1263             : 
    1264         195 :         while ( pRow )
    1265             :         {
    1266          57 :             pNxt = pRow->GetNext();
    1267          57 :             nHeight += (pRow->Frm().*fnRect->fnGetHeight)();
    1268          57 :             pRow->Remove();
    1269          57 :             pRow->_InvalidateAll();
    1270          57 :             pRow->InsertBehind( this, pPrv );
    1271          57 :             pRow->CheckDirChange();
    1272          57 :             pPrv = pRow;
    1273          57 :             pRow = pNxt;
    1274             :         }
    1275             : 
    1276          69 :         SetFollow( pFoll->GetFollow() );
    1277          69 :         SetFollowFlowLine( pFoll->HasFollowFlowLine() );
    1278          69 :         delete pFoll;
    1279             : 
    1280          69 :         Grow( nHeight );
    1281             :     }
    1282             : 
    1283          69 :     return true;
    1284             : }
    1285             : 
    1286         653 : void SwInvalidatePositions( SwFrm *pFrm, long nBottom )
    1287             : {
    1288             :     // LONG_MAX == nBottom means we have to calculate all
    1289         653 :     bool bAll = LONG_MAX == nBottom;
    1290         653 :     SWRECTFN( pFrm )
    1291        1175 :     do
    1292        1175 :     {   pFrm->_InvalidatePos();
    1293        1175 :         pFrm->_InvalidateSize();
    1294        1175 :         if( pFrm->IsLayoutFrm() )
    1295             :         {
    1296         618 :             if ( ((SwLayoutFrm*)pFrm)->Lower() )
    1297             :             {
    1298         618 :                 ::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom);
    1299             :                 // #i26945#
    1300         618 :                 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) );
    1301             :             }
    1302             :         }
    1303             :         else
    1304         557 :             pFrm->Prepare( PREP_ADJUST_FRM );
    1305        1175 :         pFrm = pFrm->GetNext();
    1306        1697 :     } while ( pFrm &&
    1307           0 :               ( bAll ||
    1308           0 :               (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
    1309         653 : }
    1310             : 
    1311        4656 : void SwInvalidateAll( SwFrm *pFrm, long nBottom )
    1312             : {
    1313             :     // LONG_MAX == nBottom means we have to calculate all
    1314        4656 :     bool bAll = LONG_MAX == nBottom;
    1315        4656 :     SWRECTFN( pFrm )
    1316        7824 :     do
    1317             :     {
    1318        7824 :         pFrm->_InvalidatePos();
    1319        7824 :         pFrm->_InvalidateSize();
    1320        7824 :         pFrm->_InvalidatePrt();
    1321        7824 :         if( pFrm->IsLayoutFrm() )
    1322             :         {
    1323             :             // NEW TABLES
    1324        4519 :             SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm);
    1325        4519 :             SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
    1326        4519 :             if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
    1327             :             {
    1328           0 :                 pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
    1329           0 :                 pToInvalidate->_InvalidatePos();
    1330           0 :                 pToInvalidate->_InvalidateSize();
    1331           0 :                 pToInvalidate->_InvalidatePrt();
    1332             :             }
    1333             : 
    1334        4519 :             if ( pToInvalidate->Lower() )
    1335        4432 :                 ::SwInvalidateAll( pToInvalidate->Lower(), nBottom);
    1336             :         }
    1337             :         else
    1338        3305 :             pFrm->Prepare( PREP_CLEAR );
    1339             : 
    1340        7824 :         pFrm = pFrm->GetNext();
    1341       10992 :     } while ( pFrm &&
    1342           0 :               ( bAll ||
    1343           0 :               (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
    1344        4656 : }
    1345             : 
    1346             : // #i29550#
    1347         289 : static void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm )
    1348             : {
    1349         289 :     pLayFrm->_InvalidatePrt();
    1350         289 :     pLayFrm->_InvalidateSize();
    1351         289 :     pLayFrm->SetCompletePaint();
    1352             : 
    1353         289 :     SwFrm* pFrm = pLayFrm->Lower();
    1354             : 
    1355         992 :     while ( pFrm )
    1356             :     {
    1357         414 :         if ( pFrm->IsLayoutFrm() )
    1358         209 :             lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm );
    1359             :         else
    1360             :         {
    1361         205 :             pFrm->_InvalidatePrt();
    1362         205 :             pFrm->_InvalidateSize();
    1363         205 :             pFrm->SetCompletePaint();
    1364             :         }
    1365             : 
    1366         414 :         pFrm = pFrm->GetNext();
    1367             :     }
    1368         289 : }
    1369             : 
    1370        1437 : bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave,
    1371             :                                  long nBottom, bool bSkipRowSpanCells )
    1372             : {
    1373        1437 :     if ( !pLay )
    1374           0 :         return true;
    1375             : 
    1376             :     // LONG_MAX == nBottom means we have to calculate all
    1377        1437 :     bool bAll = LONG_MAX == nBottom;
    1378        1437 :     bool bRet = false;
    1379        1437 :     SwCntntFrm *pCnt = pLay->ContainsCntnt();
    1380        1437 :     SWRECTFN( pLay )
    1381             : 
    1382             :     // FME 2007-08-30 #i81146# new loop control
    1383        1437 :     sal_uInt16 nLoopControlRuns = 0;
    1384        1437 :     const sal_uInt16 nLoopControlMax = 10;
    1385        1437 :     const SwModify* pLoopControlCond = 0;
    1386             : 
    1387       32735 :     while ( pCnt && pDontLeave->IsAnLower( pCnt ) )
    1388             :     {
    1389             :         // #115759# - check, if a format of content frame is
    1390             :         // possible. Thus, 'copy' conditions, found at the beginning of
    1391             :         // <SwCntntFrm::MakeAll(..)>, and check these.
    1392       60112 :         const bool bFormatPossible = !pCnt->IsJoinLocked() &&
    1393       60112 :                                      ( !pCnt->IsTxtFrm() ||
    1394      120224 :                                        !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) &&
    1395       90066 :                                      ( pCnt->IsFollow() || !StackHack::IsLocked() );
    1396             : 
    1397             :         // NEW TABLES
    1398       30056 :         bool bSkipContent = false;
    1399       30056 :         if ( bSkipRowSpanCells && pCnt->IsInTab() )
    1400             :         {
    1401       30056 :             const SwFrm* pCell = pCnt->GetUpper();
    1402       60112 :             while ( pCell && !pCell->IsCellFrm() )
    1403           0 :                 pCell = pCell->GetUpper();
    1404       30056 :             if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() )
    1405           0 :                 bSkipContent = true;
    1406             :         }
    1407             : 
    1408       30056 :         if ( bFormatPossible && !bSkipContent )
    1409             :         {
    1410       30056 :             bRet |= !pCnt->IsValid();
    1411             :             // #i26945# - no extra invalidation of floating
    1412             :             // screen objects needed.
    1413             :             // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
    1414       30056 :             pCnt->Calc();
    1415             :             // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
    1416             :             // to format the floating screen objects
    1417             :             // #i46941# - frame has to be valid
    1418             :             // Note: frame could be invalid after calling its format, if it's locked.
    1419             :             OSL_ENSURE( !pCnt->IsTxtFrm() ||
    1420             :                     pCnt->IsValid() ||
    1421             :                     static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(),
    1422             :                     "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." );
    1423       30056 :             if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
    1424             :             {
    1425             :                 // #i23129#, #i36347# - pass correct page frame to
    1426             :                 // the object formatter
    1427       30056 :                 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
    1428       30056 :                                                           *(pCnt->FindPageFrm()) ) )
    1429             :                 {
    1430           0 :                     if ( pCnt->GetRegisteredIn() == pLoopControlCond )
    1431           0 :                         ++nLoopControlRuns;
    1432             :                     else
    1433             :                     {
    1434           0 :                         nLoopControlRuns = 0;
    1435           0 :                         pLoopControlCond = pCnt->GetRegisteredIn();
    1436             :                     }
    1437             : 
    1438           0 :                     if ( nLoopControlRuns < nLoopControlMax )
    1439             :                     {
    1440             :                         // restart format with first content
    1441           0 :                         pCnt = pLay->ContainsCntnt();
    1442           0 :                         continue;
    1443             :                     }
    1444             : 
    1445             : #if OSL_DEBUG_LEVEL > 1
    1446             :                     OSL_FAIL( "LoopControl in SwCntntFrm::CalcLowers" );
    1447             : #endif
    1448             :                 }
    1449             :             }
    1450       30056 :             pCnt->GetUpper()->Calc();
    1451             :         }
    1452       30056 :         if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 )
    1453         195 :             break;
    1454       29861 :         pCnt = pCnt->GetNextCntntFrm();
    1455             :     }
    1456        1437 :     return bRet;
    1457             : }
    1458             : 
    1459             : // #i26945# - add parameter <_bOnlyRowsAndCells> to control
    1460             : // that only row and cell frames are formatted.
    1461       85643 : static bool lcl_InnerCalcLayout( SwFrm *pFrm,
    1462             :                                       long nBottom,
    1463             :                                       bool _bOnlyRowsAndCells )
    1464             : {
    1465             :     // LONG_MAX == nBottom means we have to calculate all
    1466       85643 :     bool bAll = LONG_MAX == nBottom;
    1467       85643 :     bool bRet = false;
    1468       85643 :     const SwFrm* pOldUp = pFrm->GetUpper();
    1469       85643 :     SWRECTFN( pFrm )
    1470      144363 :     do
    1471             :     {
    1472             :         // #i26945# - parameter <_bOnlyRowsAndCells> controls,
    1473             :         // if only row and cell frames are formatted.
    1474      312333 :         if ( pFrm->IsLayoutFrm() &&
    1475       89866 :              ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) )
    1476             :         {
    1477             :             // #130744# An invalid locked table frame will
    1478             :             // not be calculated => It will not become valid =>
    1479             :             // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
    1480       83985 :             bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() );
    1481       83985 :             pFrm->Calc();
    1482       83985 :             if( static_cast<SwLayoutFrm*>(pFrm)->Lower() )
    1483       83481 :                 bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom);
    1484             : 
    1485             :             // NEW TABLES
    1486       83985 :             SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
    1487       83985 :             if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
    1488             :             {
    1489           0 :                 SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
    1490           0 :                 bRet |= !rToCalc.IsValid();
    1491           0 :                 rToCalc.Calc();
    1492           0 :                 if ( rToCalc.Lower() )
    1493           0 :                     bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom);
    1494             :             }
    1495             :         }
    1496      144363 :         pFrm = pFrm->GetNext();
    1497       59052 :     } while( pFrm &&
    1498       28938 :             ( bAll ||
    1499       28938 :               (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 )
    1500      203083 :             && pFrm->GetUpper() == pOldUp );
    1501       85643 :     return bRet;
    1502             : }
    1503             : 
    1504         853 : static void lcl_RecalcRow( SwRowFrm& rRow, long nBottom )
    1505             : {
    1506             :     // FME 2007-08-30 #i81146# new loop control
    1507         853 :     sal_uInt16 nLoopControlRuns_1 = 0;
    1508         853 :     sal_uInt16 nLoopControlStage_1 = 0;
    1509         853 :     const sal_uInt16 nLoopControlMax = 10;
    1510             : 
    1511         853 :     bool bCheck = true;
    1512             :     do
    1513             :     {
    1514             :         // FME 2007-08-30 #i81146# new loop control
    1515        1437 :         sal_uInt16 nLoopControlRuns_2 = 0;
    1516        1437 :         sal_uInt16 nLoopControlStage_2 = 0;
    1517             : 
    1518        3419 :         while( lcl_InnerCalcLayout( &rRow, nBottom ) )
    1519             :         {
    1520         545 :             if ( ++nLoopControlRuns_2 > nLoopControlMax )
    1521             :             {
    1522             : #if OSL_DEBUG_LEVEL > 1
    1523             :                 OSL_ENSURE( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
    1524             :                 OSL_ENSURE( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
    1525             :                 OSL_ENSURE( 2 >  nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
    1526             : #endif
    1527           0 :                 rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ );
    1528           0 :                 nLoopControlRuns_2 = 0;
    1529           0 :                 if( nLoopControlStage_2 > 2 )
    1530           0 :                     break;
    1531             :             }
    1532             : 
    1533         545 :             bCheck = true;
    1534             :         }
    1535             : 
    1536        1437 :         if( bCheck )
    1537             :         {
    1538             :             // #115759# - force another format of the
    1539             :             // lowers, if at least one of it was invalid.
    1540        1437 :             bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true );
    1541             : 
    1542             :             // NEW TABLES
    1543             :             // First we calculate the cells with row span of < 1, afterwards
    1544             :             // all cells with row span of > 1:
    1545        4311 :             for ( int i = 0; i < 2; ++i )
    1546             :             {
    1547        2874 :                 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower());
    1548       13140 :                 while ( pCellFrm )
    1549             :                 {
    1550             :                     const bool bCalc = 0 == i ?
    1551        3696 :                                        pCellFrm->GetLayoutRowSpan() < 1 :
    1552       11088 :                                        pCellFrm->GetLayoutRowSpan() > 1;
    1553             : 
    1554        7392 :                     if ( bCalc )
    1555             :                     {
    1556             :                         SwCellFrm& rToRecalc = 0 == i ?
    1557             :                                                const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) :
    1558           0 :                                                *pCellFrm;
    1559           0 :                         bCheck  |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false );
    1560             :                     }
    1561             : 
    1562        7392 :                     pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
    1563             :                 }
    1564             :             }
    1565             : 
    1566        1437 :             if ( bCheck )
    1567             :             {
    1568         584 :                 if ( ++nLoopControlRuns_1 > nLoopControlMax )
    1569             :                 {
    1570             : #if OSL_DEBUG_LEVEL > 1
    1571             :                     OSL_ENSURE( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
    1572             :                     OSL_ENSURE( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
    1573             :                     OSL_ENSURE( 2 >  nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
    1574             : #endif
    1575           0 :                     rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ );
    1576           0 :                     nLoopControlRuns_1 = 0;
    1577           0 :                     if( nLoopControlStage_1 > 2 )
    1578           0 :                         break;
    1579             :                 }
    1580             : 
    1581         584 :                 continue;
    1582             :             }
    1583             :         }
    1584         853 :         break;
    1585         584 :     } while( true );
    1586         853 : }
    1587             : 
    1588          35 : static void lcl_RecalcTable( SwTabFrm& rTab,
    1589             :                                   SwLayoutFrm *pFirstRow,
    1590             :                                   SwLayNotify &rNotify )
    1591             : {
    1592          35 :     if ( rTab.Lower() )
    1593             :     {
    1594          35 :         if ( !pFirstRow )
    1595             :         {
    1596          35 :             pFirstRow = (SwLayoutFrm*)rTab.Lower();
    1597          35 :             rNotify.SetLowersComplete( sal_True );
    1598             :         }
    1599          35 :         ::SwInvalidatePositions( pFirstRow, LONG_MAX );
    1600          35 :         lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX );
    1601             :     }
    1602          35 : }
    1603             : 
    1604             : // This is a new function to check the first condition whether
    1605             : // a tab frame may move backward. It replaces the formerly used
    1606             : // GetIndPrev(), which did not work correctly for #i5947#
    1607        4039 : static bool lcl_NoPrev( const SwFrm& rFrm )
    1608             : {
    1609             :     // #i79774#
    1610             :     // skip empty sections on investigation of direct previous frame.
    1611             :     // use information, that at least one empty section is skipped in the following code.
    1612        4039 :     bool bSkippedDirectPrevEmptySection( false );
    1613        4039 :     if ( rFrm.GetPrev() )
    1614             :     {
    1615        1120 :         const SwFrm* pPrev( rFrm.GetPrev() );
    1616        3360 :         while ( pPrev &&
    1617        1120 :                 pPrev->IsSctFrm() &&
    1618           0 :                 !dynamic_cast<const SwSectionFrm*>(pPrev)->GetSection() )
    1619             :         {
    1620           0 :             pPrev = pPrev->GetPrev();
    1621           0 :             bSkippedDirectPrevEmptySection = true;
    1622             :         }
    1623        1120 :         if ( pPrev )
    1624             :         {
    1625        1120 :             return false;
    1626             :         }
    1627             :     }
    1628             : 
    1629        5838 :     if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) ||
    1630           0 :          ( bSkippedDirectPrevEmptySection &&
    1631           0 :            ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) )
    1632             :     {
    1633        2919 :         return true;
    1634             :     }
    1635             : 
    1636             :     // I do not have a direct prev, but I have an indirect prev.
    1637             :     // In section frames I have to check if I'm located inside
    1638             :     // the first column:
    1639           0 :     if ( rFrm.IsInSct() )
    1640             :     {
    1641           0 :         const SwFrm* pSct = rFrm.GetUpper();
    1642           0 :         if ( pSct && pSct->IsColBodyFrm() &&
    1643           0 :              pSct->GetUpper()->GetUpper()->IsSctFrm() )
    1644             :         {
    1645           0 :             const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev();
    1646           0 :             if ( pPrevCol )
    1647             :                 // I'm not inside the first column and do not have a direct
    1648             :                 // prev. I can try to go backward.
    1649           0 :                 return true;
    1650             :         }
    1651             :     }
    1652             : 
    1653           0 :     return false;
    1654             : }
    1655             : 
    1656             : #define KEEPTAB ( !GetFollow() && !IsFollow() )
    1657             : 
    1658             : // - helper method to find next content frame of
    1659             : // a table frame and format it to assure keep attribute.
    1660             : // method return true, if a next content frame is formatted.
    1661             : // Precondition: The given table frame hasn't a follow and isn't a follow.
    1662          13 : SwFrm* sw_FormatNextCntntForKeep( SwTabFrm* pTabFrm )
    1663             : {
    1664             :     // find next content, table or section
    1665          13 :     SwFrm* pNxt = pTabFrm->FindNext();
    1666             : 
    1667             :     // skip empty sections
    1668          26 :     while ( pNxt && pNxt->IsSctFrm() &&
    1669           0 :             !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
    1670             :     {
    1671           0 :         pNxt = pNxt->FindNext();
    1672             :     }
    1673             : 
    1674             :     // if found next frame is a section, get its first content.
    1675          13 :     if ( pNxt && pNxt->IsSctFrm() )
    1676             :     {
    1677           0 :         pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny();
    1678             :     }
    1679             : 
    1680             :     // format found next frame.
    1681             :     // if table frame is inside another table, method <SwFrm::MakeAll()> is
    1682             :     // called to avoid that the superior table frame is formatted.
    1683          13 :     if ( pNxt )
    1684             :     {
    1685          13 :         if ( pTabFrm->GetUpper()->IsInTab() )
    1686           0 :             pNxt->MakeAll();
    1687             :         else
    1688          13 :             pNxt->Calc();
    1689             :     }
    1690             : 
    1691          13 :     return pNxt;
    1692             : }
    1693             : 
    1694             : namespace {
    1695         182 :     bool AreAllRowsKeepWithNext( const SwRowFrm* pFirstRowFrm )
    1696             :     {
    1697         364 :         bool bRet = pFirstRowFrm != 0 &&
    1698         364 :                     pFirstRowFrm->ShouldRowKeepWithNext();
    1699             : 
    1700         364 :         while ( bRet && pFirstRowFrm->GetNext() != 0 )
    1701             :         {
    1702           0 :             pFirstRowFrm = dynamic_cast<const SwRowFrm*>(pFirstRowFrm->GetNext());
    1703           0 :             bRet = pFirstRowFrm != 0 &&
    1704           0 :                    pFirstRowFrm->ShouldRowKeepWithNext();
    1705             :         }
    1706             : 
    1707         182 :         return bRet;
    1708             :     }
    1709             : }
    1710       12742 : void SwTabFrm::MakeAll()
    1711             : {
    1712       12742 :     if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
    1713       19268 :         return;
    1714             : 
    1715        3108 :     if ( HasFollow() )
    1716             :     {
    1717         128 :         SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
    1718             :         OSL_ENSURE( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
    1719             :                 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" );
    1720         128 :         if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
    1721           0 :             return;
    1722             :     }
    1723             : 
    1724             :     PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
    1725             : 
    1726        3108 :     LockJoin(); //I don't want to be destroyed on the way.
    1727        3108 :     SwLayNotify aNotify( this );    //does the notification in the DTor
    1728             :     // If pos is invalid, we have to call a SetInvaKeep at aNotify.
    1729             :     // Otherwise the keep attribute would not work in front of a table.
    1730        3108 :     const sal_Bool bOldValidPos = GetValidPosFlag();
    1731             : 
    1732             :     //If my neighbour is my Follow at the same time, I'll swallow it up.
    1733             :     // OD 09.04.2003 #108698# - join all follows, which are placed on the
    1734             :     // same page/column.
    1735             :     // OD 29.04.2003 #109213# - join follow, only if join for the follow
    1736             :     // is not locked. Otherwise, join will not be performed and this loop
    1737             :     // will be endless.
    1738        6216 :     while ( GetNext() && GetNext() == GetFollow() &&
    1739           0 :             !GetFollow()->IsJoinLocked()
    1740             :           )
    1741             :     {
    1742           0 :         if ( HasFollowFlowLine() )
    1743           0 :             RemoveFollowFlowLine();
    1744           0 :         Join();
    1745             :     }
    1746             : 
    1747             :     // The bRemoveFollowFlowLinePending is set if the split attribute of the
    1748             :     // last line is set:
    1749        3108 :     if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
    1750             :     {
    1751           0 :         if ( RemoveFollowFlowLine() )
    1752           0 :             Join();
    1753           0 :         SetRemoveFollowFlowLinePending( sal_False );
    1754             :     }
    1755             : 
    1756        3108 :     if ( bResizeHTMLTable ) //Optimized interplay with grow/shrink of the content
    1757             :     {
    1758          64 :         bResizeHTMLTable = sal_False;
    1759          64 :         SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
    1760          64 :         if ( pLayout )
    1761             :             bCalcLowers = pLayout->Resize(
    1762          64 :                             pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
    1763             :     }
    1764             : 
    1765             :     // as long as bMakePage is true, a new page can be created (exactly once)
    1766        3108 :     bool bMakePage = true;
    1767             :     // bMovedBwd gets set to true when the frame flows backwards
    1768        3108 :     bool bMovedBwd = false;
    1769             :     // as long as bMovedFwd is false, the Frm may flow backwards (until
    1770             :     // it has been moved forward once)
    1771        3108 :     bool bMovedFwd  = false;
    1772             :     // gets set to true when the Frm is split
    1773        3108 :     bool bSplit = false;
    1774        3108 :     const bool bFtnsInDoc = !GetFmt()->GetDoc()->GetFtnIdxs().empty();
    1775             :     bool bMoveable;
    1776        3108 :     const sal_Bool bFly     = IsInFly();
    1777             : 
    1778        3108 :     SwBorderAttrAccess  *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
    1779        3108 :     const SwBorderAttrs *pAttrs = pAccess->Get();
    1780             : 
    1781             :     // The beloved keep attribute
    1782        3108 :     const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
    1783             : 
    1784             :     // All rows should keep together
    1785             :     // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
    1786        6020 :     const bool bDontSplit = !IsFollow() &&
    1787        8917 :                             ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
    1788             : 
    1789             :     // The number of repeated headlines
    1790        3108 :     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
    1791             : 
    1792             :     // This flag indicates that we are allowed to try to split the
    1793             :     // table rows.
    1794        3108 :     bool bTryToSplit = true;
    1795             : 
    1796             :     // #131283#
    1797             :     // Indicates that two individual rows may keep together, based on the keep
    1798             :     // attribute set at the first paragraph in the first cell.
    1799        3108 :     const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP);
    1800             : 
    1801             :     // The Magic Move: Used for the table row keep feature.
    1802             :     // If only the last row of the table wants to keep (implicitely by setting
    1803             :     // keep for the first paragraph in the first cell), and this table does
    1804             :     // not have a next, the last line will be cut. Loop prevention: Only
    1805             :     // one try.
    1806        3108 :     bool bLastRowHasToMoveToFollow = false;
    1807        3108 :     bool bLastRowMoveNoMoreTries = false;
    1808             : 
    1809             :     // Join follow table, if this table is not allowed to split:
    1810        3108 :     if ( bDontSplit )
    1811             :     {
    1812          10 :         while ( GetFollow() && !GetFollow()->IsJoinLocked() )
    1813             :         {
    1814           0 :             if ( HasFollowFlowLine() )
    1815           0 :                 RemoveFollowFlowLine();
    1816           0 :             Join();
    1817             :         }
    1818             :     }
    1819             : 
    1820             :     // Join follow table, if this does not have enough (repeated) lines:
    1821        3108 :     if ( nRepeat )
    1822             :     {
    1823          29 :         if( GetFollow() && !GetFollow()->IsJoinLocked() &&
    1824           0 :             0 == GetFirstNonHeadlineRow() )
    1825             :         {
    1826           0 :             if ( HasFollowFlowLine() )
    1827           0 :                 RemoveFollowFlowLine();
    1828           0 :             Join();
    1829             :         }
    1830             :     }
    1831             : 
    1832             :     // Join follow table, if last row of this table should keep:
    1833        3108 :     if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
    1834             :     {
    1835         116 :         const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
    1836         116 :         if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
    1837             :         {
    1838           0 :             if ( HasFollowFlowLine() )
    1839           0 :                 RemoveFollowFlowLine();
    1840           0 :             Join();
    1841             :         }
    1842             :     }
    1843             : 
    1844             :     // a new one is moved forwards immediately
    1845        3108 :     if ( !Frm().Top() && IsFollow() )
    1846             :     {
    1847          71 :         SwFrm *pPre = GetPrev();
    1848          71 :         if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
    1849             :         {
    1850          51 :             if ( !MoveFwd( bMakePage, sal_False ) )
    1851          42 :                 bMakePage = false;
    1852          51 :             bMovedFwd = true;
    1853             :         }
    1854             :     }
    1855             : 
    1856        3108 :     int nUnSplitted = 5; // Just another loop control :-(
    1857        3108 :     SWRECTFN( this )
    1858       10638 :     while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
    1859             :     {
    1860        4422 :         if ( (bMoveable = IsMoveable()) )
    1861        3815 :             if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
    1862             :             {
    1863           1 :                 bMovedFwd = true;
    1864           1 :                 bCalcLowers = sal_True;
    1865             :                 // #i99267#
    1866             :                 // reset <bSplit> after forward move to assure that follows
    1867             :                 // can be joined, if further space is available.
    1868           1 :                 bSplit = false;
    1869             :             }
    1870             : 
    1871        4422 :         Point aOldPos( (Frm().*fnRect->fnGetPos)() );
    1872        4422 :         MakePos();
    1873             : 
    1874        4422 :         if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
    1875             :         {
    1876         676 :             if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
    1877             :             {
    1878         631 :                 SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
    1879         631 :                 if( pLayout )
    1880             :                 {
    1881           3 :                     delete pAccess;
    1882             :                     bCalcLowers |= pLayout->Resize(
    1883           3 :                         pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
    1884           3 :                     pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
    1885           3 :                     pAttrs = pAccess->Get();
    1886             :                 }
    1887             : 
    1888         631 :                 mbValidPrtArea = sal_False;
    1889         631 :                 aNotify.SetLowersComplete( sal_False );
    1890             :             }
    1891             :             SwFrm *pPre;
    1892        1030 :             if ( bKeep || (0 != (pPre = FindPrev()) &&
    1893         354 :                 pPre->GetAttrSet()->GetKeep().GetValue()) )
    1894             :             {
    1895          11 :                 bCalcLowers = sal_True;
    1896             :                 // #i99267#
    1897             :                 // reset <bSplit> after forward move to assure that follows
    1898             :                 // can be joined, if further space is available.
    1899          11 :                 bSplit = false;
    1900             :             }
    1901             :         }
    1902             : 
    1903             :         //We need to know the height of the first row, because the master needs
    1904             :         //to be activated if it shrinks and then absorb the row if necessary.
    1905        4422 :         long n1StLineHeight = 0;
    1906        4422 :         if ( IsFollow() )
    1907             :         {
    1908         391 :             SwFrm* pFrm = GetFirstNonHeadlineRow();
    1909         391 :             if ( pFrm )
    1910         391 :                 n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
    1911             :         }
    1912             : 
    1913        4422 :         if ( !mbValidSize || !mbValidPrtArea )
    1914             :         {
    1915        3420 :             const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
    1916        3420 :             const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
    1917        3420 :             const Point aOldPrtPos  = (Prt().*fnRect->fnGetPos)();
    1918        3420 :             Format( pAttrs );
    1919             : 
    1920        3420 :             SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
    1921        3479 :             if ( pLayout &&
    1922         111 :                 ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
    1923          55 :                 (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
    1924             :             {
    1925           3 :                 delete pAccess;
    1926             :                 bCalcLowers |= pLayout->Resize(
    1927           3 :                     pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
    1928           3 :                 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
    1929           3 :                 pAttrs = pAccess->Get();
    1930             :             }
    1931        3420 :             if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
    1932         298 :                 aNotify.SetLowersComplete( sal_False );
    1933             :         }
    1934             : 
    1935             :         // If this is the first one in a chain, check if this can flow
    1936             :         // backwards (if this is movable at all).
    1937             :         // To prevent oscillations/loops, check that this has not just
    1938             :         // flowed forwards.
    1939        4422 :         if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
    1940             :         {
    1941             :             // for Follows notify Master.
    1942             :             // only move Follow if it has to skip empty pages.
    1943        2919 :             if ( IsFollow() )
    1944             :             {
    1945             :                 // Only if the height of the first line got smaller.
    1946         266 :                 SwFrm *pFrm = GetFirstNonHeadlineRow();
    1947         266 :                 if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
    1948             :                 {
    1949           0 :                     SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
    1950             :                     bool bDummy;
    1951           0 :                     if ( ShouldBwdMoved( pMaster->GetUpper(), false, bDummy ) )
    1952           0 :                         pMaster->InvalidatePos();
    1953             :                 }
    1954             :             }
    1955        2919 :             SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0;
    1956             :             bool bReformat;
    1957        2919 :             if ( MoveBwd( bReformat ) )
    1958             :             {
    1959          15 :                 SWREFRESHFN( this )
    1960          15 :                 bMovedBwd = true;
    1961          15 :                 aNotify.SetLowersComplete( sal_False );
    1962          15 :                 if ( bFtnsInDoc )
    1963           0 :                     MoveLowerFtns( 0, pOldBoss, 0, sal_True );
    1964          15 :                 if ( bReformat || bKeep )
    1965             :                 {
    1966          10 :                     long nOldTop = (Frm().*fnRect->fnGetTop)();
    1967          10 :                     MakePos();
    1968          10 :                     if( nOldTop != (Frm().*fnRect->fnGetTop)() )
    1969             :                     {
    1970             :                         SwHTMLTableLayout *pHTMLLayout =
    1971          10 :                             GetTable()->GetHTMLTableLayout();
    1972          10 :                         if( pHTMLLayout )
    1973             :                         {
    1974           0 :                             delete pAccess;
    1975             :                             bCalcLowers |= pHTMLLayout->Resize(
    1976           0 :                                 pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
    1977           0 :                                 sal_False );
    1978             : 
    1979           0 :                             pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
    1980           0 :                             pAttrs = pAccess->Get();
    1981             :                         }
    1982             : 
    1983          10 :                         mbValidPrtArea = sal_False;
    1984          10 :                         Format( pAttrs );
    1985             :                     }
    1986          10 :                     lcl_RecalcTable( *this, 0, aNotify );
    1987          10 :                     bLowersFormatted = sal_True;
    1988          10 :                     if ( bKeep && KEEPTAB )
    1989             :                     {
    1990             : 
    1991             :                         // Consider case that table is inside another table,
    1992             :                         // because it has to be avoided, that superior table
    1993             :                         // is formatted.
    1994             :                         // Thus, find next content, table or section
    1995             :                         // and, if a section is found, get its first
    1996             :                         // content.
    1997           0 :                         if ( 0 != sw_FormatNextCntntForKeep( this ) && !GetNext() )
    1998             :                         {
    1999           0 :                             mbValidPos = sal_False;
    2000             :                         }
    2001             :                     }
    2002             :                 }
    2003             :             }
    2004             :         }
    2005             : 
    2006             :         //Again an invalid value? - do it again...
    2007        4422 :         if ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
    2008        4859 :             continue;
    2009             : 
    2010             :         // check, if calculation of table frame is ready.
    2011             : 
    2012             :         // Local variable <nDistanceToUpperPrtBottom>
    2013             :         //     Introduce local variable and init it with the distance from the
    2014             :         //     table frame bottom to the bottom of the upper printing area.
    2015             :         // Note: negative values denotes the situation that table frame doesn't fit in its upper.
    2016             :         SwTwips nDistanceToUpperPrtBottom =
    2017        3979 :                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
    2018             : 
    2019             :         /// In online layout try to grow upper of table frame, if table frame doesn't fit in its upper.
    2020        3979 :         const SwViewShell *pSh = getRootFrm()->GetCurrShell();
    2021        3979 :         const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
    2022        3979 :         if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
    2023             :         {
    2024           0 :             if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
    2025             :             {
    2026             :                 // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
    2027           0 :                 nDistanceToUpperPrtBottom = (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
    2028             :             }
    2029             :         }
    2030             : 
    2031             :         // If there is still some space left in the upper, we check if we
    2032             :         // can join some rows of the follow.
    2033             :         // Setting bLastRowHasToMoveToFollow to true means we want to force
    2034             :         // the table to be split! Only skip this if condition once.
    2035        3979 :         if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
    2036             :         {
    2037             :             // If there is space left in the upper printing area, join as for trial
    2038             :             // at least one further row of an existing follow.
    2039        3589 :             if ( !bSplit && GetFollow() )
    2040             :             {
    2041             :                 bool bDummy;
    2042         734 :                 if ( GetFollow()->ShouldBwdMoved( GetUpper(), false, bDummy ) )
    2043             :                 {
    2044         715 :                     SwFrm *pTmp = GetUpper();
    2045         715 :                     SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
    2046         715 :                     if ( bBrowseMode )
    2047           0 :                         nDeadLine += pTmp->Grow( LONG_MAX, sal_True );
    2048         715 :                     if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
    2049             :                     {
    2050             :                         // First, we remove an existing follow flow line.
    2051         711 :                         if ( HasFollowFlowLine() )
    2052             :                         {
    2053           0 :                             SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
    2054           0 :                             RemoveFollowFlowLine();
    2055             :                             // invalidate and rebuild last row
    2056           0 :                             if ( pLastLine )
    2057             :                             {
    2058           0 :                                 ::SwInvalidateAll( pLastLine, LONG_MAX );
    2059           0 :                                 SetRebuildLastLine( sal_True );
    2060           0 :                                 lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
    2061           0 :                                 SetRebuildLastLine( sal_False );
    2062             :                             }
    2063             : 
    2064           0 :                             SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
    2065             : 
    2066           0 :                             if ( !pRow || !pRow->GetNext() )
    2067             :                                 //The follow becomes empty and invalid for this reason.
    2068           0 :                                 Join();
    2069             : 
    2070         711 :                             continue;
    2071             :                         }
    2072             : 
    2073             :                         // If there is no follow flow line, we move the first
    2074             :                         // row in the follow table to the master table.
    2075         711 :                         SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
    2076             : 
    2077             :                         //The follow becomes empty and invalid for this reason.
    2078         711 :                         if ( !pRow )
    2079             :                         {
    2080           0 :                             Join();
    2081           0 :                             continue;
    2082             :                         }
    2083             : 
    2084         711 :                         const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
    2085         711 :                         long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
    2086         711 :                         SwFrm* pRowToMove = pRow;
    2087             : 
    2088        2133 :                         while ( pRowToMove && nRowsToMove-- > 0 )
    2089             :                         {
    2090         711 :                             const bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
    2091             : 
    2092         711 :                             SwFtnBossFrm *pOldBoss = 0;
    2093         711 :                             if ( bMoveFtns )
    2094           0 :                                 pOldBoss = pRowToMove->FindFtnBossFrm( sal_True );
    2095             : 
    2096         711 :                             SwFrm* pNextRow = pRowToMove->GetNext();
    2097             : 
    2098         711 :                             if ( !pNextRow )
    2099             :                             {
    2100             :                                 //The follow becomes empty and invalid for this reason.
    2101          57 :                                 Join();
    2102             :                             }
    2103             :                             else
    2104             :                             {
    2105         654 :                                 pRowToMove->Cut();
    2106         654 :                                 pRowToMove->Paste( this );
    2107             :                             }
    2108             : 
    2109             :                             //Displace the footnotes!
    2110         711 :                             if ( bMoveFtns )
    2111           0 :                                 if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns( 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) )
    2112           0 :                                     GetUpper()->Calc();
    2113             : 
    2114         711 :                             pRowToMove = pNextRow;
    2115             :                         }
    2116             : 
    2117         711 :                         if ( nOld != (Frm().*fnRect->fnGetHeight)() )
    2118           0 :                             lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
    2119             : 
    2120         711 :                         continue;
    2121             :                     }
    2122             :                 }
    2123             :             }
    2124        2855 :             else if ( KEEPTAB )
    2125             :             {
    2126        2636 :                 bool bFormat = false;
    2127        2636 :                 if ( bKeep )
    2128           0 :                     bFormat = true;
    2129        2636 :                 else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
    2130             :                 {
    2131             :                     // We only want to give the last row one chance to move
    2132             :                     // to the follow table. Set the flag as early as possible:
    2133        1847 :                     bLastRowMoveNoMoreTries = true;
    2134             : 
    2135             :                     // The last line of the table has to be cut off if:
    2136             :                     // 1. The table does not want to keep with its next
    2137             :                     // 2. The compatibility option is set and the table is allowed to split
    2138             :                     // 3. We did not already cut off the last row
    2139             :                     // 4. There is not break after attribute set at the table
    2140             :                     // 5. There is no break before attribute set behind the table
    2141             :                     // 6. There is no section change behind the table (see IsKeep)
    2142             :                     // 7. The last table row wants to keep with its next.
    2143        1847 :                     const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
    2144        3615 :                     if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
    2145        1768 :                          pLastRow->ShouldRowKeepWithNext() )
    2146          13 :                         bFormat = true;
    2147             :                 }
    2148             : 
    2149        2636 :                 if ( bFormat )
    2150             :                 {
    2151          13 :                     delete pAccess;
    2152             : 
    2153             :                     // Consider case that table is inside another table, because
    2154             :                     // it has to be avoided, that superior table is formatted.
    2155             :                     // Thus, find next content, table or section and, if a section
    2156             :                     // is found, get its first content.
    2157          13 :                     const SwFrm* pTmpNxt = sw_FormatNextCntntForKeep( this );
    2158             : 
    2159          13 :                     pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
    2160          13 :                     pAttrs = pAccess->Get();
    2161             : 
    2162             :                     // The last row wants to keep with the frame behind the table.
    2163             :                     // Check if the next frame is on a different page and valid.
    2164             :                     // In this case we do a magic trick:
    2165          13 :                     if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
    2166             :                     {
    2167           0 :                         mbValidPos = sal_False;
    2168           0 :                         bLastRowHasToMoveToFollow = true;
    2169             :                     }
    2170             :                 }
    2171             :             }
    2172             : 
    2173        2878 :             if ( IsValid() )
    2174             :             {
    2175        2878 :                 if ( bCalcLowers )
    2176             :                 {
    2177          25 :                     lcl_RecalcTable( *this, 0, aNotify );
    2178          25 :                     bLowersFormatted = sal_True;
    2179          25 :                     bCalcLowers = sal_False;
    2180             :                 }
    2181        2853 :                 else if ( bONECalcLowers )
    2182             :                 {
    2183         353 :                     lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
    2184         353 :                     bONECalcLowers = sal_False;
    2185             :                 }
    2186             :             }
    2187        2878 :             continue;
    2188             :         }
    2189             : 
    2190             :         //I don't fit in the higher-ranked element anymore, therefore it's the
    2191             :         //right moment to do some preferably constructive changes.
    2192             : 
    2193             :         //If I'm NOT allowed to leave the parent Frm, I've got a problem.
    2194             :         // Following Artur Dent, we do the only thing that you can do with
    2195             :         // an unsolvable problem: We ignore it with all our power.
    2196         390 :         if ( !bMoveable )
    2197             :         {
    2198         204 :             if ( bCalcLowers && IsValid() )
    2199             :             {
    2200           0 :                 lcl_RecalcTable( *this, 0, aNotify );
    2201           0 :                 bLowersFormatted = sal_True;
    2202           0 :                 bCalcLowers = sal_False;
    2203             :             }
    2204         204 :             else if ( bONECalcLowers )
    2205             :             {
    2206           0 :                 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
    2207           0 :                 bONECalcLowers = sal_False;
    2208             :             }
    2209             : 
    2210             :             // It does not make sense to cut off the last line if we are
    2211             :             // not moveable:
    2212         204 :             bLastRowHasToMoveToFollow = false;
    2213             : 
    2214         204 :             continue;
    2215             :         }
    2216             : 
    2217         186 :         if ( bCalcLowers && IsValid() )
    2218             :         {
    2219           0 :             lcl_RecalcTable( *this, 0, aNotify );
    2220           0 :             bLowersFormatted = sal_True;
    2221           0 :             bCalcLowers = sal_False;
    2222           0 :             if( !IsValid() )
    2223           0 :                 continue;
    2224             :         }
    2225             : 
    2226             :         // First try to split the table. Condition:
    2227             :         // 1. We have at least one non headline row
    2228             :         // 2. If this row wants to keep, we need an additional row
    2229             :         // 3. The table is allowed to split or we do not have an pIndPrev:
    2230         186 :         SwFrm* pIndPrev = GetIndPrev();
    2231         186 :         const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
    2232             :         // #i120016# if this row wants to keep, allow split in case that all rows want to keep with next,
    2233             :         // the table can not move forward as it is the first one and a split is in general allowed.
    2234         182 :         const bool bAllowSplitOfRow = ( bTableRowKeep &&
    2235         182 :                                         AreAllRowsKeepWithNext( pFirstNonHeadlineRow ) ) &&
    2236         186 :                                       !pIndPrev &&
    2237         186 :                                       !bDontSplit;
    2238             : 
    2239         558 :         if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
    2240         926 :              ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() || bAllowSplitOfRow ) &&
    2241         186 :              ( !bDontSplit || !pIndPrev ) )
    2242             :         {
    2243             :             // #i29438#
    2244             :             // Special DoNotSplit case:
    2245             :             // We better avoid splitting of a row frame if we are inside a columned
    2246             :             // section which has a height of 0, because this is not growable and thus
    2247             :             // all kinds of unexpected things could happen.
    2248         372 :             if ( IsInSct() &&
    2249         186 :                 (FindSctFrm())->Lower()->IsColumnFrm() &&
    2250           0 :                 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)()  )
    2251             :             {
    2252           0 :                 bTryToSplit = false;
    2253             :             }
    2254             : 
    2255             :             // 1. Try: bTryToSplit = true  => Try to split the row.
    2256             :             // 2. Try: bTryToSplit = false => Split the table between the rows.
    2257         186 :             if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
    2258             :             {
    2259         180 :                 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
    2260         180 :                 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
    2261             :                     nDeadLine = (*fnRect->fnYInc)( nDeadLine,
    2262          18 :                                         GetUpper()->Grow( LONG_MAX, sal_True ) );
    2263             : 
    2264             :                 {
    2265         180 :                     SetInRecalcLowerRow( true );
    2266         180 :                     ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
    2267         180 :                     SetInRecalcLowerRow( false );
    2268             :                 }
    2269         180 :                 bLowersFormatted = sal_True;
    2270         180 :                 aNotify.SetLowersComplete( sal_True );
    2271             : 
    2272             :                 // One more check if its really necessary to split the table.
    2273             :                 // 1. The table either has to exceed the deadline or
    2274             :                 // 2. We explicitly want to cut off the last row.
    2275         180 :                 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
    2276             :                 {
    2277           0 :                     continue;
    2278             :                 }
    2279             : 
    2280             :                 // Set to false again as early as possible.
    2281         180 :                 bLastRowHasToMoveToFollow = false;
    2282             : 
    2283             :                 // #i52781#
    2284             :                 // YaSC - Yet another special case:
    2285             :                 // If our upper is inside a table cell which is not allowed
    2286             :                 // to split, we do not try to split:
    2287         180 :                 if ( GetUpper()->IsInTab() )
    2288             :                 {
    2289          18 :                     const SwFrm* pTmpRow = GetUpper();
    2290          54 :                     while ( pTmpRow && !pTmpRow->IsRowFrm() )
    2291          18 :                        pTmpRow = pTmpRow->GetUpper();
    2292          18 :                     if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
    2293           0 :                         continue;
    2294             :                 }
    2295             : 
    2296         180 :                 sal_uInt16 nMinNumOfLines = nRepeat;
    2297             : 
    2298         180 :                 if ( bTableRowKeep )
    2299             :                 {
    2300         176 :                     const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
    2301         352 :                     while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
    2302             :                     {
    2303           0 :                         ++nMinNumOfLines;
    2304           0 :                         pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
    2305             :                     }
    2306             :                 }
    2307             : 
    2308         180 :                 if ( !bTryToSplit )
    2309          68 :                     ++nMinNumOfLines;
    2310             : 
    2311             :                 const SwTwips nBreakLine = (*fnRect->fnYInc)(
    2312         360 :                         (Frm().*fnRect->fnGetTop)(),
    2313         180 :                         (this->*fnRect->fnGetTopMargin)() +
    2314         720 :                          lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
    2315             : 
    2316             :                 // Some more checks if we want to call the split algorithm or not:
    2317             :                 // The repeating lines / keeping lines still fit into the upper or
    2318             :                 // if we do not have an (in)direkt Prev, we split anyway.
    2319         180 :                 if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
    2320             :                 {
    2321         180 :                     aNotify.SetLowersComplete( sal_False );
    2322         180 :                     bSplit = true;
    2323             : 
    2324             :                     // An existing follow flow line has to be removed.
    2325         180 :                     if ( HasFollowFlowLine() )
    2326             :                     {
    2327          18 :                         RemoveFollowFlowLine();
    2328             :                     }
    2329             : 
    2330         180 :                     const bool bSplitError = !Split( nDeadLine, bTryToSplit, ( bTableRowKeep && !bAllowSplitOfRow ) );
    2331         180 :                     if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
    2332             :                     {
    2333          68 :                         --nUnSplitted;
    2334             :                     }
    2335             : 
    2336             :                     // #i29771# Two tries to split the table
    2337             :                     // If an error occurred during splitting. We start a second
    2338             :                     // try, this time without splitting of table rows.
    2339         180 :                     if ( bSplitError )
    2340             :                     {
    2341          74 :                         if ( HasFollowFlowLine() )
    2342          74 :                             RemoveFollowFlowLine();
    2343             :                     }
    2344             : 
    2345             :                     // #119477#
    2346             :                     // If splitting the table was successful or not,
    2347             :                     // we do not want to have 'empty' follow tables.
    2348         180 :                     if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
    2349          12 :                         Join();
    2350             : 
    2351             :                     // We want to restore the situation before the failed
    2352             :                     // split operation as good as possible. Therefore we
    2353             :                     // do some more calculations. Note: Restricting this
    2354             :                     // to nDeadLine may not be enough.
    2355         180 :                     if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
    2356             :                     {
    2357          74 :                         lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
    2358          74 :                         mbValidPos = sal_False;
    2359          74 :                         bTryToSplit = false;
    2360          74 :                         continue;
    2361             :                     }
    2362             : 
    2363         106 :                     bTryToSplit = !bSplitError;
    2364             : 
    2365             :                     //To avoid oscillations the Follow must become valid now
    2366         106 :                     if ( GetFollow() )
    2367             :                     {
    2368             :                         // #i80924#
    2369             :                         // After a successful split assure that the first row
    2370             :                         // is invalid. When graphics are present, this isn't hold.
    2371             :                         // Note: defect i80924 could also be fixed, if it is
    2372             :                         // assured, that <SwLayNotify::bLowersComplete> is only
    2373             :                         // set, if all lower are valid *and* are correct laid out.
    2374         106 :                         if ( !bSplitError && GetFollow()->GetLower() )
    2375             :                         {
    2376         106 :                             GetFollow()->GetLower()->InvalidatePos();
    2377             :                         }
    2378         106 :                         SWRECTFNX( GetFollow() )
    2379             : 
    2380             :                         static sal_uInt8 nStack = 0;
    2381         106 :                         if ( !StackHack::IsLocked() && nStack < 4 )
    2382             :                         {
    2383          99 :                             ++nStack;
    2384          99 :                             StackHack aHack;
    2385          99 :                             delete pAccess;
    2386             : 
    2387          99 :                             GetFollow()->MakeAll();
    2388             : 
    2389          99 :                             pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
    2390          99 :                             pAttrs = pAccess->Get();
    2391             : 
    2392          99 :                             ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False);
    2393             :                             // #i43913# - lock follow table
    2394             :                             // to avoid its formatting during the format of
    2395             :                             // its content.
    2396          99 :                             const bool bOldJoinLock =  GetFollow()->IsJoinLocked();
    2397          99 :                             GetFollow()->LockJoin();
    2398          99 :                             ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
    2399         198 :                                              (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
    2400             :                             // #i43913#
    2401             :                             // #i63632# Do not unlock the
    2402             :                             // follow if it wasn't locked before.
    2403          99 :                             if ( !bOldJoinLock )
    2404          99 :                                 GetFollow()->UnlockJoin();
    2405             : 
    2406          99 :                             if ( !GetFollow()->GetFollow() )
    2407             :                             {
    2408          40 :                                 SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
    2409          40 :                                 if ( pNxt )
    2410             :                                 {
    2411             :                                     // #i18103# - no formatting of found next
    2412             :                                     // frame, if its a follow section of the
    2413             :                                     // 'ColLocked' section, the follow table is
    2414             :                                     // in.
    2415          40 :                                     bool bCalcNxt = true;
    2416          40 :                                     if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
    2417             :                                     {
    2418           0 :                                         SwSectionFrm* pSct = GetFollow()->FindSctFrm();
    2419           0 :                                         if ( pSct->IsColLocked() &&
    2420           0 :                                              pSct->GetFollow() == pNxt )
    2421             :                                         {
    2422           0 :                                             bCalcNxt = false;
    2423             :                                         }
    2424             :                                     }
    2425          40 :                                     if ( bCalcNxt )
    2426             :                                     {
    2427          40 :                                         pNxt->Calc();
    2428             :                                     }
    2429             :                                 }
    2430             :                             }
    2431          99 :                             --nStack;
    2432             :                         }
    2433           7 :                         else if ( GetFollow() == GetNext() )
    2434           7 :                             ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False );
    2435             :                     }
    2436         106 :                     continue;
    2437             :                 }
    2438             :             }
    2439             :         }
    2440             : 
    2441             :         // Set to false again as early as possible.
    2442           6 :         bLastRowHasToMoveToFollow = false;
    2443             : 
    2444          12 :         if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
    2445           0 :             GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
    2446           6 :             ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
    2447           0 :             ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
    2448             :         {
    2449           0 :             bMovedFwd = false;
    2450             :         }
    2451             : 
    2452             :         // #i29771# Reset bTryToSplit flag on change of upper
    2453           6 :         const SwFrm* pOldUpper = GetUpper();
    2454             : 
    2455             :         //Let's see if we find some place anywhere...
    2456           6 :         if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
    2457           6 :             bMakePage = false;
    2458             : 
    2459             :         // #i29771# Reset bSplitError flag on change of upper
    2460           6 :         if ( GetUpper() != pOldUpper )
    2461             :         {
    2462           0 :             bTryToSplit = true;
    2463           0 :             nUnSplitted = 5;
    2464             :         }
    2465             : 
    2466           6 :         SWREFRESHFN( this )
    2467           6 :         bCalcLowers = sal_True;
    2468           6 :         bMovedFwd = true;
    2469           6 :         aNotify.SetLowersComplete( sal_False );
    2470           6 :         if ( IsFollow() )
    2471             :         {
    2472             :             //To avoid oscillations now invalid master should drop behind.
    2473           0 :             SwTabFrm *pTab = FindMaster();
    2474           0 :             if ( pTab->GetUpper() )
    2475           0 :                 pTab->GetUpper()->Calc();
    2476           0 :             pTab->Calc();
    2477           0 :             pTab->SetLowersFormatted( sal_False );
    2478             :         }
    2479             : 
    2480             :         //If my neighbour is my Follow at the same time, I'll swallow it up.
    2481           6 :         if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
    2482             :         {
    2483           0 :             if ( HasFollowFlowLine() )
    2484           0 :                 RemoveFollowFlowLine();
    2485           0 :             if ( GetFollow() )
    2486           0 :                 Join();
    2487             :         }
    2488             : 
    2489           6 :         if ( bMovedBwd && GetUpper() )
    2490             :         {
    2491             :             //During floating back the upper was animated to do a full repaint,
    2492             :             //we can now skip this after the whole back and forth floating.
    2493           0 :             GetUpper()->ResetCompletePaint();
    2494             :         }
    2495             : 
    2496           6 :         if ( bCalcLowers && IsValid() )
    2497             :         {
    2498             :             // #i44910# - format of lower frames unnecessary
    2499             :             // and can cause layout loops, if table doesn't fit and isn't
    2500             :             // allowed to split.
    2501             :             SwTwips nDistToUpperPrtBottom =
    2502           6 :                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
    2503           6 :             if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
    2504             :             {
    2505           0 :                 lcl_RecalcTable( *this, 0, aNotify );
    2506           0 :                 bLowersFormatted = sal_True;
    2507           0 :                 bCalcLowers = sal_False;
    2508             :             }
    2509             : #if OSL_DEBUG_LEVEL > 0
    2510             :             else
    2511             :             {
    2512             :                 OSL_FAIL( "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
    2513             :             }
    2514             : #endif
    2515             :         }
    2516             : 
    2517             :     } //while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
    2518             : 
    2519             :     //If my direct predecessor is my master now, it can destroy me during the
    2520             :     //next best opportunity.
    2521        3108 :     if ( IsFollow() )
    2522             :     {
    2523         201 :         SwFrm *pPre = GetPrev();
    2524         201 :         if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
    2525           0 :             pPre->InvalidatePos();
    2526             :     }
    2527             : 
    2528        3108 :     bCalcLowers = bONECalcLowers = sal_False;
    2529        3108 :     delete pAccess;
    2530        3108 :     UnlockJoin();
    2531        3108 :     if ( bMovedFwd || bMovedBwd || !bOldValidPos )
    2532        2967 :         aNotify.SetInvaKeep();
    2533             : }
    2534             : 
    2535             : /// Calculate the offsets arising because of FlyFrames
    2536        3500 : sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
    2537             :                                long& rLeftOffset,
    2538             :                                long& rRightOffset ) const
    2539             : {
    2540        3500 :     sal_Bool bInvalidatePrtArea = sal_False;
    2541        3500 :     const SwPageFrm *pPage = FindPageFrm();
    2542        3500 :     const SwFlyFrm* pMyFly = FindFlyFrm();
    2543             : 
    2544             :     // --> #108724# Page header/footer content doesn't have to wrap around
    2545             :     //              floating screen objects
    2546             : 
    2547        3500 :     const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
    2548       10248 :     const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
    2549       10488 :                                 ( !IsInFtn() && 0 == FindFooterOrHeader() );
    2550             : 
    2551        3500 :     if ( pPage->GetSortedObjs() && bWrapAllowed )
    2552             :     {
    2553         713 :         SWRECTFN( this )
    2554         713 :         const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
    2555         713 :         long nPrtPos = (Frm().*fnRect->fnGetTop)();
    2556         713 :         nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
    2557         713 :         SwRect aRect( Frm() );
    2558         713 :         long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
    2559         713 :         if( nYDiff > 0 )
    2560           0 :             (aRect.*fnRect->fnAddBottom)( -nYDiff );
    2561        1936 :         for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
    2562             :         {
    2563        1223 :             SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
    2564        1223 :             if ( pAnchoredObj->ISA(SwFlyFrm) )
    2565             :             {
    2566         719 :                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
    2567         719 :                 const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
    2568             :                 // #i26945# - correction of conditions,
    2569             :                 // if Writer fly frame has to be considered:
    2570             :                 // - no need to check, if top of Writer fly frame differs
    2571             :                 //   from FAR_AWAY, because its also check, if the Writer
    2572             :                 //   fly frame rectangle overlaps with <aRect>
    2573             :                 // - no check, if bottom of anchor frame is prior the top of
    2574             :                 //   the table, because Writer fly frames can be negative positioned.
    2575             :                 // - correct check, if the Writer fly frame is an lower of the
    2576             :                 //   table, because table lines/rows can split and a at-character
    2577             :                 //   anchored Writer fly frame could be positioned in the follow
    2578             :                 //   flow line.
    2579             :                 // - add condition, that an existing anchor character text frame
    2580             :                 //   has to be on the same page as the table.
    2581             :                 //   E.g., it could happen, that the fly frame is still registered
    2582             :                 //   at the page frame, the table is on, but it's anchor character
    2583             :                 //   text frame has already changed its page.
    2584         719 :                 const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
    2585             :                 bool bConsiderFly =
    2586             :                     // #i46807# - do not consider invalid
    2587             :                     // Writer fly frames.
    2588         899 :                     pFly->IsValid() &&
    2589             :                     // fly anchored at character
    2590         350 :                     pFly->IsFlyAtCntFrm() &&
    2591             :                     // fly overlaps with corresponding table rectangle
    2592         281 :                     aFlyRect.IsOver( aRect ) &&
    2593             :                     // fly isn't lower of table and
    2594             :                     // anchor character frame of fly isn't lower of table
    2595         218 :                     ( !IsAnLower( pFly ) &&
    2596         134 :                       ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
    2597             :                     // table isn't lower of fly
    2598         109 :                     !pFly->IsAnLower( this ) &&
    2599             :                     // fly is lower of fly, the table is in
    2600             :                     // #123274# - correction
    2601             :                     // assure that fly isn't a lower of a fly, the table isn't in.
    2602             :                     // E.g., a table in the body doesn't wrap around a graphic,
    2603             :                     // which is inside a frame.
    2604           0 :                     ( ( !pMyFly ||
    2605           2 :                         pMyFly->IsAnLower( pFly ) ) &&
    2606           4 :                       pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
    2607             :                     // anchor frame not on following page
    2608           2 :                     pPage->GetPhyPageNum() >=
    2609         725 :                       pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
    2610             :                     // anchor character text frame on same page
    2611           2 :                     ( !pAnchorCharFrm ||
    2612           2 :                       pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
    2613         721 :                         pPage->GetPhyPageNum() );
    2614             : 
    2615         719 :                 if ( bConsiderFly )
    2616             :                 {
    2617           2 :                     const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
    2618           2 :                     const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
    2619             : 
    2620           2 :                     if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
    2621             :                         // #148493# If bConsiderWrapOnObjPos is set,
    2622             :                         // we want to consider the fly if it is located in the header and
    2623             :                         // the table is located in the body:
    2624           0 :                          ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
    2625           0 :                         bConsiderFly = false;
    2626             :                 }
    2627             : 
    2628         719 :                 if ( bConsiderFly )
    2629             :                 {
    2630           2 :                     const SwFmtSurround   &rSur = pFly->GetFmt()->GetSurround();
    2631           2 :                     const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
    2632           2 :                     if ( SURROUND_NONE == rSur.GetSurround() )
    2633             :                     {
    2634           0 :                         long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
    2635           0 :                         if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
    2636           0 :                             nPrtPos = nBottom;
    2637           0 :                         bInvalidatePrtArea = sal_True;
    2638             :                     }
    2639           6 :                     if ( (SURROUND_RIGHT    == rSur.GetSurround() ||
    2640           2 :                           SURROUND_PARALLEL == rSur.GetSurround())&&
    2641           0 :                          text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
    2642             :                     {
    2643             :                         const long nWidth = (*fnRect->fnXDiff)(
    2644           0 :                             (aFlyRect.*fnRect->fnGetRight)(),
    2645           0 :                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
    2646           0 :                         rLeftOffset = std::max( rLeftOffset, nWidth );
    2647           0 :                         bInvalidatePrtArea = sal_True;
    2648             :                     }
    2649           6 :                     if ( (SURROUND_LEFT     == rSur.GetSurround() ||
    2650           2 :                           SURROUND_PARALLEL == rSur.GetSurround())&&
    2651           0 :                          text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
    2652             :                     {
    2653             :                         const long nWidth = (*fnRect->fnXDiff)(
    2654           0 :                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
    2655           0 :                             (aFlyRect.*fnRect->fnGetLeft)() );
    2656           0 :                         rRightOffset = std::max( rRightOffset, nWidth );
    2657           0 :                         bInvalidatePrtArea = sal_True;
    2658             :                     }
    2659             :                 }
    2660             :             }
    2661             :         }
    2662         713 :         rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
    2663             :     }
    2664             : 
    2665        3500 :     return bInvalidatePrtArea;
    2666             : }
    2667             : 
    2668             : /// "Formats" the frame; Frm and PrtArea.
    2669             : /// The fixed size is not adjusted here.
    2670        3430 : void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
    2671             : {
    2672             :     OSL_ENSURE( pAttrs, "TabFrm::Format, pAttrs ist 0." );
    2673             : 
    2674        3430 :     SWRECTFN( this )
    2675        3430 :     if ( !mbValidSize )
    2676             :     {
    2677        3285 :         long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
    2678        3285 :                      (Frm().*fnRect->fnGetWidth)();
    2679        3285 :         if( nDiff )
    2680         551 :             (maFrm.*fnRect->fnAddRight)( nDiff );
    2681             :     }
    2682             : 
    2683             :     //VarSize is always the height.
    2684             :     //For the upper/lower border the same rules apply as for cntfrms (see
    2685             :     //MakePrtArea() of those).
    2686             : 
    2687        3430 :     SwTwips nUpper = CalcUpperSpace( pAttrs );
    2688             : 
    2689             :     //We want to dodge the border. Two possibilities:
    2690             :     //1. There are borders with SurroundNone, dodge them completely
    2691             :     //2. There are borders which only float on the right or the left side and
    2692             :     //   are right or left aligned, those set the minimum for the borders.
    2693        3430 :     long nTmpRight = -1000000,
    2694        3430 :          nLeftOffset  = 0;
    2695        3430 :     if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
    2696           0 :         mbValidPrtArea = sal_False;
    2697        3430 :     long nRightOffset = std::max( 0L, nTmpRight );
    2698             : 
    2699        3430 :     SwTwips nLower = pAttrs->CalcBottomLine();
    2700             :     // #i29550#
    2701        3430 :     if ( IsCollapsingBorders() )
    2702        3424 :         nLower += GetBottomLineSize();
    2703             : 
    2704        3430 :     if ( !mbValidPrtArea )
    2705        3423 :     {   mbValidPrtArea = sal_True;
    2706             : 
    2707             :         //The width of the PrtArea is given by the FrmFmt, the borders have to
    2708             :         //be set accordingly.
    2709             :         //Minimum borders are determined depending on margins and shadows.
    2710             :         //The borders are adjusted so that the PrtArea is aligned into the Frm
    2711             :         //according to the adjustment.
    2712             :         //If the adjustment is 0, the borders are set according to the border
    2713             :         //attributes.
    2714             : 
    2715        3423 :         const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
    2716        3423 :         const SwTwips nMax = (maFrm.*fnRect->fnGetWidth)();
    2717             : 
    2718             :         // OD 14.03.2003 #i9040# - adjust variable names.
    2719        3423 :         const SwTwips nLeftLine  = pAttrs->CalcLeftLine();
    2720        3423 :         const SwTwips nRightLine = pAttrs->CalcRightLine();
    2721             : 
    2722             :         //The width possibly is a percentage value. If the table is inside
    2723             :         //something else, the value applies to the surrounding. If it's the body
    2724             :         //the value applies to the screen width in the BrowseView.
    2725        3423 :         const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
    2726             :         // OD 14.03.2003 #i9040# - adjust variable name.
    2727        3423 :         const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True );
    2728             : 
    2729        3423 :         bool bCheckBrowseWidth = false;
    2730             : 
    2731             :         // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
    2732        3423 :         SwTwips nLeftSpacing  = 0;
    2733        3423 :         SwTwips nRightSpacing = 0;
    2734        3423 :         switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
    2735             :         {
    2736             :             case text::HoriOrientation::LEFT:
    2737             :                 {
    2738             :                     // left indent:
    2739         191 :                     nLeftSpacing = nLeftLine + nLeftOffset;
    2740             :                     // OD 06.03.2003 #i9040# - correct calculation of right indent:
    2741             :                     // - Consider right indent given by right line attributes.
    2742             :                     // - Consider negative right indent.
    2743             :                     // wished right indent determined by wished table width and
    2744             :                     // left offset given by surround fly frames on the left:
    2745         191 :                     const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
    2746         191 :                     if ( nRightOffset > 0 )
    2747             :                     {
    2748             :                         // surrounding fly frames on the right
    2749             :                         // -> right indent is maximun of given right offset
    2750             :                         //    and wished right offset.
    2751           0 :                         nRightSpacing = nRightLine + std::max( nRightOffset, nWishRight );
    2752             :                     }
    2753             :                     else
    2754             :                     {
    2755             :                         // no surrounding fly frames on the right
    2756             :                         // If intrinsic right indent (intrinsic means not considering
    2757             :                         // determined left indent) is negative,
    2758             :                         //      then hold this intrinsic indent,
    2759             :                         //      otherwise non negative wished right indent is hold.
    2760         558 :                         nRightSpacing = nRightLine +
    2761         191 :                                         ( ( (nWishRight+nLeftOffset) < 0 ) ?
    2762          15 :                                             (nWishRight+nLeftOffset) :
    2763         543 :                                             std::max( 0L, nWishRight ) );
    2764             :                     }
    2765             :                 }
    2766         191 :                 break;
    2767             :             case text::HoriOrientation::RIGHT:
    2768             :                 {
    2769             :                     // right indent:
    2770           2 :                     nRightSpacing = nRightLine + nRightOffset;
    2771             :                     // OD 06.03.2003 #i9040# - correct calculation of left indent:
    2772             :                     // - Consider left indent given by left line attributes.
    2773             :                     // - Consider negative left indent.
    2774             :                     // wished left indent determined by wished table width and
    2775             :                     // right offset given by surrounding fyl frames on the right:
    2776           2 :                     const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
    2777           2 :                     if ( nLeftOffset > 0 )
    2778             :                     {
    2779             :                         // surrounding fly frames on the left
    2780             :                         // -> right indent is maximun of given left offset
    2781             :                         //    and wished left offset.
    2782           0 :                         nLeftSpacing = nLeftLine + std::max( nLeftOffset, nWishLeft );
    2783             :                     }
    2784             :                     else
    2785             :                     {
    2786             :                         // no surrounding fly frames on the left
    2787             :                         // If intrinsic left indent (intrinsic = not considering
    2788             :                         // determined right indent) is negative,
    2789             :                         //      then hold this intrinsic indent,
    2790             :                         //      otherwise non negative wished left indent is hold.
    2791           6 :                         nLeftSpacing = nLeftLine +
    2792           2 :                                        ( ( (nWishLeft+nRightOffset) < 0 ) ?
    2793           0 :                                            (nWishLeft+nRightOffset) :
    2794           6 :                                            std::max( 0L, nWishLeft ) );
    2795             :                     }
    2796             :                 }
    2797           2 :                 break;
    2798             :             case text::HoriOrientation::CENTER:
    2799             :                 {
    2800             :                     // OD 07.03.2003 #i9040# - consider left/right line attribute.
    2801             :                     // OD 10.03.2003 #i9040# -
    2802         346 :                     const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
    2803         346 :                     nLeftSpacing = nLeftLine +
    2804         346 :                                    ( (nLeftOffset > 0) ?
    2805           0 :                                      std::max( nCenterSpacing, nLeftOffset ) :
    2806         346 :                                      nCenterSpacing );
    2807         346 :                     nRightSpacing = nRightLine +
    2808         346 :                                     ( (nRightOffset > 0) ?
    2809           0 :                                       std::max( nCenterSpacing, nRightOffset ) :
    2810         346 :                                       nCenterSpacing );
    2811             :                 }
    2812         346 :                 break;
    2813             :             case text::HoriOrientation::FULL:
    2814             :                     //This things grows over the whole width.
    2815             :                     //Only the free space needed for the border is taken into
    2816             :                     //account. The attribute values of LRSpace are ignored
    2817             :                     //intentionally.
    2818         338 :                     bCheckBrowseWidth = true;
    2819         338 :                     nLeftSpacing  = nLeftLine + nLeftOffset;
    2820         338 :                     nRightSpacing = nRightLine + nRightOffset;
    2821         338 :                 break;
    2822             :             case text::HoriOrientation::NONE:
    2823             :                 {
    2824             :                     //The border are defined by the border attribute.
    2825           0 :                     nLeftSpacing = pAttrs->CalcLeft( this );
    2826           0 :                     if( nLeftOffset )
    2827             :                     {
    2828             :                         // OD 07.03.2003 #i9040# - surround fly frames only, if
    2829             :                         // they overlap with the table.
    2830             :                         // Thus, take maximun of left spacing and left offset.
    2831             :                         // OD 10.03.2003 #i9040# - consider left line attribute.
    2832           0 :                         nLeftSpacing = std::max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
    2833             :                     }
    2834             :                     // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
    2835           0 :                     nRightSpacing = pAttrs->CalcRight( this );
    2836           0 :                     if( nRightOffset )
    2837             :                     {
    2838             :                         // OD 07.03.2003 #i9040# - surround fly frames only, if
    2839             :                         // they overlap with the table.
    2840             :                         // Thus, take maximun of right spacing and right offset.
    2841             :                         // OD 10.03.2003 #i9040# - consider right line attribute.
    2842           0 :                         nRightSpacing = std::max( nRightSpacing, ( nRightOffset + nRightLine ) );
    2843             :                     }
    2844             :                 }
    2845           0 :                 break;
    2846             :             case text::HoriOrientation::LEFT_AND_WIDTH:
    2847             :                 {
    2848             :                     //Linker Rand und die Breite zaehlen (Word-Spezialitaet)
    2849             :                     // OD 10.03.2003 #i9040# - no width alignment in online mode.
    2850             :                     //bCheckBrowseWidth = true;
    2851        2546 :                     nLeftSpacing = pAttrs->CalcLeft( this );
    2852        2546 :                     if( nLeftOffset )
    2853             :                     {
    2854             :                         // OD 10.03.2003 #i9040# - surround fly frames only, if
    2855             :                         // they overlap with the table.
    2856             :                         // Thus, take maximun of right spacing and right offset.
    2857             :                         // OD 10.03.2003 #i9040# - consider left line attribute.
    2858           0 :                         nLeftSpacing = std::max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
    2859             :                     }
    2860             :                     // OD 10.03.2003 #i9040# - consider right and left line attribute.
    2861             :                     const SwTwips nWishRight =
    2862        2546 :                             nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
    2863        2546 :                     nRightSpacing = nRightLine +
    2864        2546 :                                     ( (nRightOffset > 0) ?
    2865           0 :                                       std::max( nWishRight, nRightOffset ) :
    2866        2546 :                                       nWishRight );
    2867             :                 }
    2868        2546 :                 break;
    2869             :             default:
    2870             :                 OSL_FAIL( "Ungueltige orientation fuer Table." );
    2871             :         }
    2872             : 
    2873             :         // #i26250# - extend bottom printing area, if table
    2874             :         // is last content inside a table cell.
    2875       10263 :         if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
    2876        3707 :              GetUpper()->IsInTab() && !GetIndNext() )
    2877             :         {
    2878          21 :             nLower += pAttrs->GetULSpace().GetLower();
    2879             :         }
    2880        3423 :         (this->*fnRect->fnSetYMargins)( nUpper, nLower );
    2881        3423 :         if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
    2882          34 :             (this->*fnRect->fnSetXMargins)( 0, 0 );
    2883             :         else
    2884        3389 :             (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
    2885             : 
    2886        3423 :         SwViewShell *pSh = getRootFrm()->GetCurrShell();
    2887        3761 :         if ( bCheckBrowseWidth &&
    2888         338 :              pSh && pSh->GetViewOptions()->getBrowseMode() &&
    2889        3423 :              GetUpper()->IsPageBodyFrm() &&  // only PageBodyFrms and not ColBodyFrms
    2890           0 :              pSh->VisArea().Width() )
    2891             :         {
    2892             :             //Don't overlap the edge of the visible area.
    2893             :             //The page width can be bigger because objects with
    2894             :             //"over-size" are possible (RootFrm::ImplCalcBrowseWidth())
    2895           0 :             long nWidth = pSh->GetBrowseWidth();
    2896           0 :             nWidth -= Prt().Left();
    2897           0 :             nWidth -= pAttrs->CalcRightLine();
    2898           0 :             Prt().Width( std::min( nWidth, Prt().Width() ) );
    2899             :         }
    2900             : 
    2901        3423 :         if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
    2902         427 :             mbValidSize = sal_False;
    2903             :     }
    2904             : 
    2905        3430 :     if ( !mbValidSize )
    2906             :     {
    2907        3292 :         mbValidSize = sal_True;
    2908             : 
    2909             :         //The size is defined by the content plus the borders.
    2910        3292 :         SwTwips nRemaining = 0, nDiff;
    2911        3292 :         SwFrm *pFrm = pLower;
    2912       46668 :         while ( pFrm )
    2913             :         {
    2914       40084 :             nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
    2915       40084 :             pFrm = pFrm->GetNext();
    2916             :         }
    2917             :         //And now add the borders
    2918        3292 :         nRemaining += nUpper + nLower;
    2919             : 
    2920        3292 :         nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
    2921        3292 :         if ( nDiff > 0 )
    2922          13 :             Shrink( nDiff );
    2923        3279 :         else if ( nDiff < 0 )
    2924         415 :             Grow( -nDiff );
    2925             :     }
    2926        3430 : }
    2927             : 
    2928       10155 : SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
    2929             : {
    2930       10155 :     SWRECTFN( this )
    2931       10155 :     SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
    2932       10155 :     if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
    2933        1160 :         nDist = LONG_MAX - nHeight;
    2934             : 
    2935       10155 :     if ( bTst && !IsRestrictTableGrowth() )
    2936         347 :         return nDist;
    2937             : 
    2938        9808 :     if ( GetUpper() )
    2939             :     {
    2940        9808 :         SwRect aOldFrm( Frm() );
    2941             : 
    2942             :         //The upper only grows as far as needed. nReal provides the distance
    2943             :         //which is already available.
    2944        9808 :         SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
    2945        9808 :         SwFrm *pFrm = GetUpper()->Lower();
    2946      105981 :         while ( pFrm && GetFollow() != pFrm )
    2947             :         {
    2948       86365 :             nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
    2949       86365 :             pFrm = pFrm->GetNext();
    2950             :         }
    2951             : 
    2952        9808 :         if ( nReal < nDist )
    2953             :         {
    2954        6266 :             long nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
    2955             : 
    2956        6266 :             if ( IsRestrictTableGrowth() )
    2957             :             {
    2958        2910 :                 nTmp = std::min( nDist, nReal + nTmp );
    2959        2910 :                 nDist = nTmp < 0 ? 0 : nTmp;
    2960             :             }
    2961             :         }
    2962             : 
    2963        9808 :         if ( !bTst )
    2964             :         {
    2965        8145 :             (Frm().*fnRect->fnAddBottom)( nDist );
    2966             : 
    2967        8145 :             SwRootFrm *pRootFrm = getRootFrm();
    2968        8145 :             if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
    2969           0 :                 pRootFrm->GetCurrShell() )
    2970             :             {
    2971           0 :                 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
    2972             :             }
    2973             :         }
    2974             :     }
    2975             : 
    2976        9808 :     if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
    2977             :     {
    2978        8145 :         SwPageFrm *pPage = FindPageFrm();
    2979        8145 :         if ( GetNext() )
    2980             :         {
    2981        5758 :             GetNext()->_InvalidatePos();
    2982        5758 :             if ( GetNext()->IsCntntFrm() )
    2983        3962 :                 GetNext()->InvalidatePage( pPage );
    2984             :         }
    2985             :         // #i28701# - Due to the new object positioning the
    2986             :         // frame on the next page/column can flow backward (e.g. it was moved
    2987             :         // forward due to the positioning of its objects ). Thus, invalivate this
    2988             :         // next frame, if document compatibility option 'Consider wrapping style
    2989             :         // influence on object positioning' is ON.
    2990        2387 :         else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
    2991             :         {
    2992        2188 :             InvalidateNextPos();
    2993             :         }
    2994        8145 :         _InvalidateAll();
    2995        8145 :         InvalidatePage( pPage );
    2996        8145 :         SetComplete();
    2997             : 
    2998        8145 :         const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
    2999        8145 :         if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
    3000           0 :             SetCompletePaint();
    3001             :     }
    3002             : 
    3003        9808 :     return nDist;
    3004             : }
    3005             : 
    3006          48 : void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
    3007             : {
    3008          48 :     sal_uInt8 nInvFlags = 0;
    3009          48 :     bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
    3010             : 
    3011          48 :     if( bAttrSetChg )
    3012             :     {
    3013          45 :         SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
    3014          90 :         SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
    3015          90 :         SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
    3016          90 :         SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
    3017             :         while( true )
    3018             :         {
    3019             :             _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
    3020             :                          (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
    3021          80 :                          &aOldSet, &aNewSet );
    3022          80 :             if( aNIter.IsAtEnd() )
    3023          45 :                 break;
    3024          35 :             aNIter.NextItem();
    3025          35 :             aOIter.NextItem();
    3026             :         }
    3027          45 :         if ( aOldSet.Count() || aNewSet.Count() )
    3028          70 :             SwLayoutFrm::Modify( &aOldSet, &aNewSet );
    3029             :     }
    3030             :     else
    3031           3 :         _UpdateAttr( pOld, pNew, nInvFlags );
    3032             : 
    3033          48 :     if ( nInvFlags != 0 )
    3034             :     {
    3035          40 :         SwPageFrm *pPage = FindPageFrm();
    3036          40 :         InvalidatePage( pPage );
    3037          40 :         if ( nInvFlags & 0x02 )
    3038          28 :             _InvalidatePrt();
    3039          40 :         if ( nInvFlags & 0x40 )
    3040          13 :             _InvalidatePos();
    3041             :         SwFrm *pTmp;
    3042          40 :         if ( 0 != (pTmp = GetIndNext()) )
    3043             :         {
    3044          40 :             if ( nInvFlags & 0x04 )
    3045             :             {
    3046           2 :                 pTmp->_InvalidatePrt();
    3047           2 :                 if ( pTmp->IsCntntFrm() )
    3048           2 :                     pTmp->InvalidatePage( pPage );
    3049             :             }
    3050          40 :             if ( nInvFlags & 0x10 )
    3051           2 :                 pTmp->SetCompletePaint();
    3052             :         }
    3053          40 :         if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
    3054             :         {
    3055           0 :             pTmp->_InvalidatePrt();
    3056           0 :             if ( pTmp->IsCntntFrm() )
    3057           0 :                 pTmp->InvalidatePage( pPage );
    3058             :         }
    3059          40 :         if ( nInvFlags & 0x20  )
    3060             :         {
    3061          27 :             if ( pPage && pPage->GetUpper() && !IsFollow() )
    3062          27 :                 ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
    3063             :         }
    3064          40 :         if ( nInvFlags & 0x80 )
    3065           1 :             InvalidateNextPos();
    3066             :     }
    3067          48 : }
    3068             : 
    3069          83 : void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
    3070             :                             sal_uInt8 &rInvFlags,
    3071             :                             SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
    3072             : {
    3073          83 :     bool bClear = true;
    3074          83 :     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
    3075          83 :     switch( nWhich )
    3076             :     {
    3077             :         case RES_TBLHEADLINECHG:
    3078           1 :             if ( IsFollow() )
    3079             :             {
    3080             :                 // Delete remaining headlines:
    3081           0 :                 SwRowFrm* pLowerRow = 0;
    3082           0 :                 while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
    3083             :                 {
    3084           0 :                     pLowerRow->Cut();
    3085           0 :                     delete pLowerRow;
    3086             :                 }
    3087             : 
    3088             :                 // insert new headlines
    3089           0 :                 const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
    3090           0 :                 for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
    3091             :                 {
    3092           0 :                     bDontCreateObjects = true;          //frmtool
    3093           0 :                     SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
    3094           0 :                     pHeadline->SetRepeatedHeadline( true );
    3095           0 :                     bDontCreateObjects = false;
    3096           0 :                     pHeadline->Paste( this, pLowerRow );
    3097             :                 }
    3098             :             }
    3099           1 :             rInvFlags |= 0x02;
    3100           1 :             break;
    3101             : 
    3102             :         case RES_FRM_SIZE:
    3103             :         case RES_HORI_ORIENT:
    3104          38 :             rInvFlags |= 0x22;
    3105          38 :             break;
    3106             : 
    3107             :         case RES_PAGEDESC:                      //Attribute changes (on/off)
    3108          11 :             if ( IsInDocBody() )
    3109             :             {
    3110          11 :                 rInvFlags |= 0x40;
    3111          11 :                 SwPageFrm *pPage = FindPageFrm();
    3112          11 :                 if ( !GetPrev() )
    3113          11 :                     CheckPageDescs( pPage );
    3114          11 :                 if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() )
    3115           0 :                     ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
    3116          11 :                 SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
    3117          11 :                 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
    3118             :             }
    3119          11 :             break;
    3120             : 
    3121             :         case RES_BREAK:
    3122           1 :             rInvFlags |= 0xC0;
    3123           1 :             break;
    3124             : 
    3125             :         case RES_LAYOUT_SPLIT:
    3126           1 :             if ( !IsFollow() )
    3127           1 :                 rInvFlags |= 0x40;
    3128           1 :             break;
    3129             :         case RES_FRAMEDIR :
    3130           0 :             SetDerivedR2L( sal_False );
    3131           0 :             CheckDirChange();
    3132           0 :             break;
    3133             :         case RES_COLLAPSING_BORDERS :
    3134           4 :             rInvFlags |= 0x02;
    3135           4 :             lcl_InvalidateAllLowersPrt( this );
    3136           4 :             break;
    3137             :         case RES_UL_SPACE:
    3138           2 :             rInvFlags |= 0x1C;
    3139             :             /* no break here */
    3140             : 
    3141             :         default:
    3142          27 :             bClear = false;
    3143             :     }
    3144          83 :     if ( bClear )
    3145             :     {
    3146          56 :         if ( pOldSet || pNewSet )
    3147             :         {
    3148          55 :             if ( pOldSet )
    3149          55 :                 pOldSet->ClearItem( nWhich );
    3150         110 :             if ( pNewSet )
    3151          55 :                 pNewSet->ClearItem( nWhich );
    3152             :         }
    3153             :         else
    3154           1 :             SwLayoutFrm::Modify( pOld, pNew );
    3155             :     }
    3156          83 : }
    3157             : 
    3158           0 : bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
    3159             : {
    3160           0 :     if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
    3161             :     {
    3162           0 :         SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
    3163           0 :         const SwPageFrm *pPage = FindPageFrm();
    3164           0 :         if ( pPage  )
    3165             :         {
    3166           0 :             if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
    3167             :             {
    3168             :                 //Here it should be (can temporary be different, should we be
    3169             :                 //                    concerned about this?)
    3170           0 :                 rInfo.SetInfo( pPage, this );
    3171           0 :                 return false;
    3172             :             }
    3173           0 :             if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
    3174           0 :                  (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
    3175             :             {
    3176             :                 //This could be the one.
    3177           0 :                 rInfo.SetInfo( pPage, this );
    3178             :             }
    3179             :         }
    3180             :     }
    3181           0 :     return true;
    3182             : }
    3183             : 
    3184        3366 : SwCntntFrm *SwTabFrm::FindLastCntnt()
    3185             : {
    3186        3366 :     SwFrm *pRet = pLower;
    3187             : 
    3188       13630 :     while ( pRet && !pRet->IsCntntFrm() )
    3189             :     {
    3190        6898 :         SwFrm *pOld = pRet;
    3191             : 
    3192        6898 :         SwFrm *pTmp = pRet;             // To skip empty section frames
    3193      214661 :         while ( pRet->GetNext() )
    3194             :         {
    3195      200865 :             pRet = pRet->GetNext();
    3196      200865 :             if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
    3197      200865 :                 pTmp = pRet;
    3198             :         }
    3199        6898 :         pRet = pTmp;
    3200             : 
    3201        6898 :         if ( pRet->GetLower() )
    3202        6696 :             pRet = pRet->GetLower();
    3203        6898 :         if ( pRet == pOld )
    3204             :         {
    3205             :             // Check all other columns if there is a column based section with
    3206             :             // an empty last column at the end of the last line - this is done
    3207             :             // by SwSectionFrm::FindLastCntnt
    3208          24 :             if( pRet->IsColBodyFrm() )
    3209             :             {
    3210             : #if OSL_DEBUG_LEVEL > 0
    3211             :                 SwSectionFrm* pSect = pRet->FindSctFrm();
    3212             :                 OSL_ENSURE( pSect, "Where does this column come fron?");
    3213             :                 OSL_ENSURE( IsAnLower( pSect ), "Splited cell?" );
    3214             : #endif
    3215           0 :                 return pRet->FindSctFrm()->FindLastCntnt();
    3216             :             }
    3217             : 
    3218             :             // pRet may be a cell frame without a lower (cell has been split).
    3219             :             // We have to find the last content the hard way:
    3220             : 
    3221             :             OSL_ENSURE( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" );
    3222          24 :             const SwFrm* pRow = pRet->GetUpper();
    3223          48 :             while ( pRow && !pRow->GetUpper()->IsTabFrm() )
    3224           0 :                 pRow = pRow->GetUpper();
    3225          24 :             SwCntntFrm* pCntntFrm = pRow ? ((SwLayoutFrm*)pRow)->ContainsCntnt() : NULL;
    3226          24 :             pRet = 0;
    3227             : 
    3228          78 :             while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
    3229             :             {
    3230          30 :                 pRet = pCntntFrm;
    3231          30 :                 pCntntFrm = pCntntFrm->GetNextCntntFrm();
    3232             :             }
    3233             :         }
    3234             :     }
    3235             : 
    3236             :     // #112929# There actually is a situation, which results in pRet = 0:
    3237             :     // Insert frame, insert table via text <-> table. This gives you a frame
    3238             :     // containing a table without any other content frames. Split the table
    3239             :     // and undo the splitting. This operation gives us a table frame without
    3240             :     // a lower.
    3241        3366 :     if ( pRet )
    3242             :     {
    3243        9650 :         while ( pRet->GetNext() )
    3244        2930 :             pRet = pRet->GetNext();
    3245             : 
    3246        3360 :         if( pRet->IsSctFrm() )
    3247           0 :             pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
    3248             :     }
    3249             : 
    3250        3366 :     return (SwCntntFrm*)pRet;
    3251             : }
    3252             : 
    3253             : /// Return value defines if the frm needs to be relocated
    3254         749 : bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, bool, bool &rReformat )
    3255             : {
    3256         749 :     rReformat = false;
    3257         749 :     if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
    3258             :     {
    3259             :         //Floating back Frm's is quite time consuming unfortunately.
    3260             :         //Most often the location where the Frm wants to float to has the same
    3261             :         //FixSize as the Frm itself. In such a situation it's easy to check if
    3262             :         //the Frm will find enough space for its VarSize, if this is not the
    3263             :         //case, the relocation can be skipped.
    3264             :         //Checking if the Frm will find enough space is done by the Frm itself,
    3265             :         //this also takes the possibility of splitting the Frm into account.
    3266             :         //If the FixSize is different or Flys are involved  (at the old or the
    3267             :         //new position) the whole checks don't make sense at all, the Frm then
    3268             :         //needs to be relocated tentatively (if a bit of space is available).
    3269             : 
    3270             :         //The FixSize of the surrounding which contain tables is always the
    3271             :         //width.
    3272             : 
    3273         749 :         SwPageFrm *pOldPage = FindPageFrm(),
    3274         749 :                   *pNewPage = pNewUpper->FindPageFrm();
    3275         749 :         bool bMoveAnyway = false;
    3276         749 :         SwTwips nSpace = 0;
    3277             : 
    3278         749 :         SWRECTFN( this )
    3279         749 :         if ( !SwFlowFrm::IsMoveBwdJump() )
    3280             :         {
    3281             : 
    3282         739 :             long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
    3283         739 :             SWRECTFNX( pNewUpper );
    3284         739 :             long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
    3285         739 :             if( std::abs( nNewWidth - nOldWidth ) < 2 )
    3286             :             {
    3287         735 :                 if( !( bMoveAnyway = (BwdMoveNecessary( pOldPage, Frm() ) > 1) ) )
    3288             :                 {
    3289         735 :                     SwRect aRect( pNewUpper->Prt() );
    3290         735 :                     aRect.Pos() += pNewUpper->Frm().Pos();
    3291         735 :                     const SwFrm *pPrevFrm = pNewUpper->Lower();
    3292        2608 :                     while ( pPrevFrm && pPrevFrm != this )
    3293             :                     {
    3294        1138 :                         (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
    3295        2276 :                                                     fnGetBottom)() );
    3296        1138 :                         pPrevFrm = pPrevFrm->GetNext();
    3297             :                     }
    3298         735 :                     bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
    3299             : 
    3300             :                     // #i54861# Due to changes made in PrepareMake,
    3301             :                     // the tabfrm may not have a correct position. Therefore
    3302             :                     // it is possible that pNewUpper->Prt().Height == 0. In this
    3303             :                     // case the above calculation of nSpace might give wrong
    3304             :                     // results and we really do not want to MoveBackwrd into a
    3305             :                     // 0 height frame. If nTmpSpace is already <= 0, we take this
    3306             :                     // value:
    3307         735 :                     const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
    3308         735 :                     if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
    3309         735 :                         nSpace = nTmpSpace;
    3310             : 
    3311         735 :                     const SwViewShell *pSh = getRootFrm()->GetCurrShell();
    3312         735 :                     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
    3313           0 :                         nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
    3314             :                 }
    3315             :             }
    3316           4 :             else if( !bLockBackMove )
    3317           4 :                 bMoveAnyway = true;
    3318             :         }
    3319          10 :         else if( !bLockBackMove )
    3320          10 :             bMoveAnyway = true;
    3321             : 
    3322         749 :         if ( bMoveAnyway )
    3323             :         {
    3324          14 :             rReformat = true;
    3325          14 :             return true;
    3326             :         }
    3327         735 :         if ( !bLockBackMove && nSpace > 0 )
    3328             :         {
    3329             :             // #i26945# - check, if follow flow line
    3330             :             // contains frame, which are moved forward due to its object
    3331             :             // positioning.
    3332         723 :             SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
    3333         723 :             if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
    3334             :                  SwLayouter::DoesRowContainMovedFwdFrm(
    3335           0 :                                             *(pFirstRow->GetFmt()->GetDoc()),
    3336           0 :                                             *(pFirstRow) ) )
    3337             :             {
    3338           0 :                 return false;
    3339             :             }
    3340         723 :             SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
    3341             : 
    3342             :             // #118840#
    3343             :             // For some mysterious reason, I changed the good old
    3344             :             // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
    3345             :             // This obviously results in problems with table frames in
    3346             :             // sections. Remember: Every twip is sacred.
    3347         723 :             return nTmpHeight <= nSpace;
    3348             :         }
    3349             :     }
    3350          12 :     return false;
    3351             : }
    3352             : 
    3353         106 : void SwTabFrm::Cut()
    3354             : {
    3355             :     OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
    3356             : 
    3357         106 :     SwPageFrm *pPage = FindPageFrm();
    3358         106 :     InvalidatePage( pPage );
    3359         106 :     SwFrm *pFrm = GetNext();
    3360         106 :     if( pFrm )
    3361             :     {
    3362             :         //The old follower eventually calculated a margin to the predecessor
    3363             :         //which is obsolete now as it became the first one
    3364          51 :         pFrm->_InvalidatePrt();
    3365          51 :         pFrm->_InvalidatePos();
    3366          51 :         if ( pFrm->IsCntntFrm() )
    3367          51 :             pFrm->InvalidatePage( pPage );
    3368          51 :         if( IsInSct() && !GetPrev() )
    3369             :         {
    3370           0 :             SwSectionFrm* pSct = FindSctFrm();
    3371           0 :             if( !pSct->IsFollow() )
    3372             :             {
    3373           0 :                 pSct->_InvalidatePrt();
    3374           0 :                 pSct->InvalidatePage( pPage );
    3375             :             }
    3376             :         }
    3377             :     }
    3378             :     else
    3379             :     {
    3380          55 :         InvalidateNextPos();
    3381             :         //Someone has to do the retouch: predecessor or upper
    3382          55 :         if ( 0 != (pFrm = GetPrev()) )
    3383           6 :         {   pFrm->SetRetouche();
    3384           6 :             pFrm->Prepare( PREP_WIDOWS_ORPHANS );
    3385           6 :             pFrm->_InvalidatePos();
    3386           6 :             if ( pFrm->IsCntntFrm() )
    3387           0 :                 pFrm->InvalidatePage( pPage );
    3388             :         }
    3389             :         //If I am (was) the only FlowFrm in my own upper, it has to do
    3390             :         //the retouch. Moreover it has to do the retouch.
    3391             :         else
    3392          49 :         {   SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
    3393          49 :             pRoot->SetSuperfluous();
    3394          49 :             GetUpper()->SetCompletePaint();
    3395          49 :             if( IsInSct() )
    3396             :             {
    3397           1 :                 SwSectionFrm* pSct = FindSctFrm();
    3398           1 :                 if( !pSct->IsFollow() )
    3399             :                 {
    3400           0 :                     pSct->_InvalidatePrt();
    3401           0 :                     pSct->InvalidatePage( pPage );
    3402             :                 }
    3403             :             }
    3404             :         }
    3405             :     }
    3406             : 
    3407             :     //First remove, then shrink the upper.
    3408         106 :     SwLayoutFrm *pUp = GetUpper();
    3409         106 :     SWRECTFN( this )
    3410         106 :     Remove();
    3411         106 :     if ( pUp )
    3412             :     {
    3413             :         OSL_ENSURE( !pUp->IsFtnFrm(), "Table in Footnote." );
    3414         106 :         SwSectionFrm *pSct = 0;
    3415             :         // #126020# - adjust check for empty section
    3416             :         // #130797# - correct fix #126020#
    3417         263 :         if ( !pUp->Lower() && pUp->IsInSct() &&
    3418         109 :              !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
    3419           1 :              !pSct->ContainsAny( true ) )
    3420             :         {
    3421           1 :             if ( pUp->GetUpper() )
    3422             :             {
    3423           1 :                 pSct->DelEmpty( sal_False );
    3424           1 :                 pSct->_InvalidateSize();
    3425             :             }
    3426             :         }
    3427         105 :         else if( (Frm().*fnRect->fnGetHeight)() )
    3428             :         {
    3429             :             // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
    3430             :             // undo changes of fix for #104992#
    3431          24 :             pUp->Shrink( Frm().Height() );
    3432             :         }
    3433             :     }
    3434             : 
    3435         106 :     if ( pPage && !IsFollow() && pPage->GetUpper() )
    3436          37 :         ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
    3437         106 : }
    3438             : 
    3439          78 : void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
    3440             : {
    3441             :     OSL_ENSURE( pParent, "No parent for pasting." );
    3442             :     OSL_ENSURE( pParent->IsLayoutFrm(), "Parent is CntntFrm." );
    3443             :     OSL_ENSURE( pParent != this, "I'm the parent myself." );
    3444             :     OSL_ENSURE( pSibling != this, "I'm my own neighbour." );
    3445             :     OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
    3446             :             "I'm still registred somewhere." );
    3447             : 
    3448             :     //Insert in the tree.
    3449          78 :     InsertBefore( (SwLayoutFrm*)pParent, pSibling );
    3450             : 
    3451          78 :     _InvalidateAll();
    3452          78 :     SwPageFrm *pPage = FindPageFrm();
    3453          78 :     InvalidatePage( pPage );
    3454             : 
    3455          78 :     if ( GetNext() )
    3456             :     {
    3457          63 :         GetNext()->_InvalidatePos();
    3458          63 :         GetNext()->_InvalidatePrt();
    3459          63 :         if ( GetNext()->IsCntntFrm() )
    3460          63 :             GetNext()->InvalidatePage( pPage );
    3461             :     }
    3462             : 
    3463          78 :     SWRECTFN( this )
    3464          78 :     if( (Frm().*fnRect->fnGetHeight)() )
    3465           2 :         pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
    3466             : 
    3467          78 :     if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
    3468          62 :         Prepare( PREP_FIXSIZE_CHG );
    3469          78 :     if ( GetPrev() )
    3470             :     {
    3471          40 :         if ( !IsFollow() )
    3472             :         {
    3473          40 :             GetPrev()->InvalidateSize();
    3474          40 :             if ( GetPrev()->IsCntntFrm() )
    3475          28 :                 GetPrev()->InvalidatePage( pPage );
    3476             :         }
    3477             :     }
    3478          38 :     else if ( GetNext() )
    3479             :         //Take the marging into account when dealing with CntntFrm's. There are
    3480             :         //two situations (both always happen at once):
    3481             :         //a) The Cntnt becomes the first in a chain
    3482             :         //b) The new follower was the first in a chain before
    3483          38 :         GetNext()->_InvalidatePrt();
    3484             : 
    3485          78 :     if ( pPage && !IsFollow() )
    3486             :     {
    3487          78 :         if ( pPage->GetUpper() )
    3488          78 :             ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
    3489             : 
    3490          78 :         if ( !GetPrev() )//At least needed for HTML with a table at the beginning.
    3491             :         {
    3492          38 :             const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
    3493          38 :             if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
    3494          38 :                  (!pDesc && pPage->GetPageDesc() != &GetFmt()->GetDoc()->GetPageDesc(0)) )
    3495           0 :                 CheckPageDescs( pPage, sal_True );
    3496             :         }
    3497             :     }
    3498          78 : }
    3499             : 
    3500         136 : void SwTabFrm::Prepare( const PrepareHint eHint, const void *, bool )
    3501             : {
    3502         136 :     if( PREP_BOSS_CHGD == eHint )
    3503          65 :         CheckDirChange();
    3504         136 : }
    3505             : 
    3506        2705 : SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
    3507             :     SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
    3508             :     pTabLine( &rLine ),
    3509             :     pFollowRow( 0 ),
    3510             :     // #i29550#
    3511             :     mnTopMarginForLowers( 0 ),
    3512             :     mnBottomMarginForLowers( 0 ),
    3513             :     mnBottomLineSize( 0 ),
    3514             :     // --> split table rows
    3515             :     bIsFollowFlowRow( false ),
    3516             :     // <-- split table rows
    3517             :     bIsRepeatedHeadline( false ),
    3518        2705 :     mbIsRowSpanLine( false )
    3519             : {
    3520        2705 :     mnType = FRMC_ROW;
    3521             : 
    3522             :     //Create the boxes and insert them.
    3523        2705 :     const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
    3524        2705 :     SwFrm *pTmpPrev = 0;
    3525       11101 :     for ( sal_uInt16 i = 0; i < rBoxes.size(); ++i )
    3526             :     {
    3527        8396 :         SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
    3528        8396 :         pNew->InsertBehind( this, pTmpPrev );
    3529        8396 :         pTmpPrev = pNew;
    3530             :     }
    3531        2705 : }
    3532             : 
    3533        8115 : SwRowFrm::~SwRowFrm()
    3534             : {
    3535        2705 :     SwModify* pMod = GetFmt();
    3536        2705 :     if( pMod )
    3537             :     {
    3538        2705 :         pMod->Remove( this );           // remove,
    3539        2705 :         if( !pMod->GetDepends() )
    3540           0 :             delete pMod;                // and delete
    3541             :     }
    3542        5410 : }
    3543             : 
    3544         689 : void SwRowFrm::RegistFlys( SwPageFrm *pPage )
    3545             : {
    3546         689 :     ::RegistFlys( pPage ? pPage : FindPageFrm(), this );
    3547         689 : }
    3548             : 
    3549          62 : void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
    3550             : {
    3551          62 :     bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
    3552          62 :     const SfxPoolItem *pItem = 0;
    3553             : 
    3554          62 :     if( bAttrSetChg )
    3555             :     {
    3556          62 :         const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
    3557          62 :         pChgSet->GetItemState( RES_FRM_SIZE, false, &pItem);
    3558          62 :         if ( !pItem )
    3559          44 :             pChgSet->GetItemState( RES_ROW_SPLIT, false, &pItem);
    3560             :     }
    3561           0 :     else if (pNew && (RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which()))
    3562           0 :         pItem = pNew;
    3563             : 
    3564          62 :     if ( pItem )
    3565             :     {
    3566          21 :         SwTabFrm *pTab = FindTabFrm();
    3567          21 :         if ( pTab )
    3568             :         {
    3569          21 :             const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
    3570          21 :                                                 this == pTab->GetFirstNonHeadlineRow();
    3571             :             // #i35063#
    3572             :             // Invalidation required is pRow is last row
    3573          21 :             if ( bInFirstNonHeadlineRow || !GetNext() )
    3574             :             {
    3575          11 :                 if ( bInFirstNonHeadlineRow )
    3576           0 :                     pTab = pTab->FindMaster();
    3577          11 :                 pTab->InvalidatePos();
    3578             :             }
    3579             :         }
    3580             :     }
    3581             : 
    3582          62 :     SwLayoutFrm::Modify( pOld, pNew );
    3583          62 : }
    3584             : 
    3585       12879 : void SwRowFrm::MakeAll()
    3586             : {
    3587       12879 :     if ( !GetNext() )
    3588        2396 :         mbValidSize = sal_False;
    3589       12879 :     SwLayoutFrm::MakeAll();
    3590       12879 : }
    3591             : 
    3592      111675 : long CalcHeightWidthFlys( const SwFrm *pFrm )
    3593             : {
    3594      111675 :     SWRECTFN( pFrm )
    3595      111675 :     long nHeight = 0;
    3596      111675 :     const SwFrm* pTmp = pFrm->IsSctFrm() ?
    3597      111675 :             ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
    3598      223350 :     while( pTmp )
    3599             :     {
    3600             :         // #i26945# - consider follow text frames
    3601      111675 :         const SwSortedObjs* pObjs( 0L );
    3602      111675 :         bool bIsFollow( false );
    3603      111675 :         if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
    3604             :         {
    3605             :             const SwFrm* pMaster;
    3606             :             // #i46450# Master does not necessarily have
    3607             :             // to exist if this function is called from JoinFrm() ->
    3608             :             // Cut() -> Shrink()
    3609        1464 :             const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
    3610        4450 :             if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
    3611        2986 :                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
    3612         761 :                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
    3613           0 :                  pMaster = 0;
    3614             :             else
    3615        1464 :                  pMaster = pTmpFrm->FindMaster();
    3616             : 
    3617        1464 :             if ( pMaster )
    3618             :             {
    3619        1464 :                  pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
    3620        1464 :                 bIsFollow = true;
    3621             :             }
    3622             :         }
    3623             :         else
    3624             :         {
    3625      110211 :             pObjs = pTmp->GetDrawObjs();
    3626             :         }
    3627      111675 :         if ( pObjs )
    3628             :         {
    3629        2532 :             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
    3630             :             {
    3631        1406 :                 const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
    3632             :                 // #i26945# - if <pTmp> is follow, the
    3633             :                 // anchor character frame has to be <pTmp>.
    3634        1454 :                 if ( bIsFollow &&
    3635          48 :                      const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
    3636             :                 {
    3637          48 :                     continue;
    3638             :                 }
    3639             :                 // #i26945# - consider also drawing objects
    3640             :                 {
    3641             :                     // OD 30.09.2003 #i18732# - only objects, which follow
    3642             :                     // the text flow have to be considered.
    3643        1358 :                     const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
    3644             :                     const bool bConsiderObj =
    3645        1668 :                         (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
    3646        1940 :                             pAnchoredObj->GetObjRect().Top() != FAR_AWAY &&
    3647        2833 :                             rFrmFmt.GetFollowTextFlow().GetValue() &&
    3648        2561 :                             pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
    3649        1358 :                     if ( bConsiderObj )
    3650             :                     {
    3651           0 :                         const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
    3652           0 :                         if( !rSz.GetHeightPercent() )
    3653             :                         {
    3654             :                             const SwTwips nDistOfFlyBottomToAnchorTop =
    3655           0 :                                 (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
    3656             :                                     ( bVert ?
    3657           0 :                                       pAnchoredObj->GetCurrRelPos().X() :
    3658           0 :                                       pAnchoredObj->GetCurrRelPos().Y() );
    3659             : 
    3660             :                             const SwTwips nFrmDiff =
    3661             :                                 (*fnRect->fnYDiff)(
    3662           0 :                                     (pTmp->Frm().*fnRect->fnGetTop)(),
    3663           0 :                                     (pFrm->Frm().*fnRect->fnGetTop)() );
    3664             : 
    3665           0 :                             nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
    3666           0 :                                             (pFrm->Frm().*fnRect->fnGetHeight)() );
    3667             : 
    3668             :                             // #i56115# The first height calculation
    3669             :                             // gives wrong results if pFrm->Prt().Y() > 0. We do
    3670             :                             // a second calculation based on the actual rectangles of
    3671             :                             // pFrm and pAnchoredObj, and use the maximum of the results.
    3672             :                             // I do not want to remove the first calculation because
    3673             :                             // if clipping has been applied, using the GetCurrRelPos
    3674             :                             // might be the better option to calculate nHeight.
    3675             :                             const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
    3676           0 :                                                                             (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
    3677           0 :                                                                             (pFrm->Frm().*fnRect->fnGetBottom)() );
    3678             : 
    3679           0 :                             nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop2 );
    3680             :                         }
    3681             :                     }
    3682             :                 }
    3683             :             }
    3684             :         }
    3685      111675 :         if( !pFrm->IsSctFrm() )
    3686      111665 :             break;
    3687          10 :         pTmp = pTmp->FindNextCnt();
    3688          10 :         if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
    3689          10 :             break;
    3690             :     }
    3691      111675 :     return nHeight;
    3692             : }
    3693             : 
    3694       73952 : static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
    3695             : {
    3696       73952 :     const SwTabFrm* pTab = rCell.FindTabFrm();
    3697       73952 :     SwTwips nTopSpace = 0;
    3698       73952 :     SwTwips nBottomSpace = 0;
    3699             : 
    3700             :     // #i29550#
    3701       73952 :     if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
    3702             :     {
    3703       73918 :         nTopSpace    = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
    3704       73918 :         nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
    3705             :     }
    3706             :     else
    3707             :     {
    3708          34 :         if ( pTab->IsVertical() != rCell.IsVertical() )
    3709             :         {
    3710           0 :             nTopSpace    = rAttrs.CalcLeft( &rCell );
    3711           0 :             nBottomSpace = rAttrs.CalcRight( &rCell );
    3712             :         }
    3713             :         else
    3714             :         {
    3715          34 :             nTopSpace    = rAttrs.CalcTop();
    3716          34 :             nBottomSpace = rAttrs.CalcBottom();
    3717             :         }
    3718             :     }
    3719             : 
    3720       73952 :     return nTopSpace + nBottomSpace;
    3721             : }
    3722             : 
    3723             : // #i26945# - add parameter <_bConsiderObjs> in order to
    3724             : // control, if floating screen objects have to be considered for the minimal
    3725             : // cell height.
    3726       68767 : static SwTwips lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
    3727             :                                            const sal_Bool _bConsiderObjs,
    3728             :                                            const SwBorderAttrs *pAttrs = 0 )
    3729             : {
    3730       68767 :     SWRECTFN( _pCell )
    3731       68767 :     SwTwips nHeight = 0;
    3732       68767 :     const SwFrm* pLow = _pCell->Lower();
    3733       68767 :     if ( pLow )
    3734             :     {
    3735       66819 :         long nFlyAdd = 0;
    3736      251786 :         while ( pLow )
    3737             :         {
    3738             :             // OD 2004-02-18 #106629# - change condition and switch then-body
    3739             :             // and else-body
    3740      118148 :             if ( pLow->IsRowFrm() )
    3741             :             {
    3742             :                 // #i26945#
    3743             :                 nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
    3744           0 :                                                    _bConsiderObjs );
    3745             :             }
    3746             :             else
    3747             :             {
    3748      118148 :                 long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
    3749      118148 :                 nHeight += nLowHeight;
    3750             :                 // #i26945#
    3751      118148 :                 if ( _bConsiderObjs )
    3752             :                 {
    3753      111675 :                     nFlyAdd = std::max( 0L, nFlyAdd - nLowHeight );
    3754      111675 :                     nFlyAdd = std::max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
    3755             :                 }
    3756             :             }
    3757             : 
    3758      118148 :             pLow = pLow->GetNext();
    3759             :         }
    3760       66819 :         if ( nFlyAdd )
    3761           0 :             nHeight += nFlyAdd;
    3762             :     }
    3763             :     //The border needs to be considered too, unfortunately it can't be
    3764             :     //calculated using PrtArea and Frm because those can be invalid in arbitrary
    3765             :     //combinations.
    3766       68767 :     if ( _pCell->Lower() )
    3767             :     {
    3768       66819 :         if ( pAttrs )
    3769       19040 :             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
    3770             :         else
    3771             :         {
    3772       47779 :             SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
    3773       47779 :             const SwBorderAttrs &rAttrs = *aAccess.Get();
    3774       47779 :             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
    3775             :         }
    3776             :     }
    3777       68767 :     return nHeight;
    3778             : }
    3779             : 
    3780             : // OD 2004-02-18 #106629# - correct type of 1st parameter
    3781             : // #i26945# - add parameter <_bConsiderObjs> in order to control,
    3782             : // if floating screen objects have to be considered for the minimal cell height
    3783       16286 : static SwTwips lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
    3784             :                                           const sal_Bool _bConsiderObjs )
    3785             : {
    3786       16286 :     SWRECTFN( _pRow )
    3787             : 
    3788       16286 :     const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
    3789             : 
    3790       16286 :     if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
    3791             :     {
    3792             :         OSL_ENSURE( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" );
    3793           0 :         return rSz.GetHeight();
    3794             :     }
    3795             : 
    3796       16286 :     SwTwips nHeight = 0;
    3797       16286 :     const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
    3798       82236 :     while ( pLow )
    3799             :     {
    3800       49664 :         SwTwips nTmp = 0;
    3801       49664 :         const long nRowSpan = pLow->GetLayoutRowSpan();
    3802             :         // --> NEW TABLES
    3803             :         // Consider height of
    3804             :         // 1. current cell if RowSpan == 1
    3805             :         // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
    3806             :         // 3. master cell if RowSpan == -1
    3807       49664 :         if ( 1 == nRowSpan )
    3808             :         {
    3809       49489 :             nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
    3810             :         }
    3811         175 :         else if ( -1 == nRowSpan )
    3812             :         {
    3813             :             // Height of the last cell of a row span is height of master cell
    3814             :             // minus the height of the other rows which are covered by the master
    3815             :             // cell:
    3816          98 :             const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
    3817          98 :             nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
    3818          98 :             const SwFrm* pMasterRow = rMaster.GetUpper();
    3819         327 :             while ( pMasterRow && pMasterRow != _pRow )
    3820             :             {
    3821         131 :                 nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
    3822         131 :                 pMasterRow = pMasterRow->GetNext();
    3823             :             }
    3824             :         }
    3825             :         // <-- NEW TABLES
    3826             : 
    3827             :         // Do not consider rotated cells:
    3828       49664 :         if ( pLow->IsVertical() == bVert && nTmp > nHeight )
    3829       16739 :             nHeight = nTmp;
    3830             : 
    3831       49664 :         pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
    3832             :     }
    3833       16286 :     if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
    3834        8479 :         nHeight = std::max( nHeight, rSz.GetHeight() );
    3835       16286 :     return nHeight;
    3836             : }
    3837             : 
    3838             : // #i29550#
    3839             : 
    3840             : // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
    3841       13035 : static sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
    3842             : {
    3843       13035 :     sal_uInt16 nTopSpace = 0;
    3844       47792 :     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
    3845       34757 :           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
    3846             :     {
    3847       34757 :         sal_uInt16 nTmpTopSpace = 0;
    3848       34757 :         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
    3849           0 :             nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
    3850             :         else
    3851             :         {
    3852       34757 :             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
    3853       34757 :             const SvxBoxItem& rBoxItem = rSet.GetBox();
    3854       34757 :             nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, true );
    3855             :         }
    3856       34757 :         nTopSpace  = std::max( nTopSpace, nTmpTopSpace );
    3857             :     }
    3858       13035 :     return nTopSpace;
    3859             : }
    3860             : 
    3861             : // Calculate the maximum of TopLineDist over all lowers:
    3862       13035 : static sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
    3863             : {
    3864       13035 :     sal_uInt16 nTopLineDist = 0;
    3865       47792 :     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
    3866       34757 :           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
    3867             :     {
    3868       34757 :         sal_uInt16 nTmpTopLineDist = 0;
    3869       34757 :         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
    3870           0 :             nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
    3871             :         else
    3872             :         {
    3873       34757 :             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
    3874       34757 :             const SvxBoxItem& rBoxItem = rSet.GetBox();
    3875       34757 :             nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
    3876             :         }
    3877       34757 :         nTopLineDist = std::max( nTopLineDist, nTmpTopLineDist );
    3878             :     }
    3879       13035 :     return nTopLineDist;
    3880             : }
    3881             : 
    3882             : // Calculate the maximum of BottomLineSize over all lowers:
    3883       13035 : static sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
    3884             : {
    3885       13035 :     sal_uInt16 nBottomLineSize = 0;
    3886       47792 :     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
    3887       34757 :           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
    3888             :     {
    3889       34757 :         sal_uInt16 nTmpBottomLineSize = 0;
    3890       34757 :         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
    3891             :         {
    3892           0 :             const SwFrm* pRow = pCurrLower->GetLastLower();
    3893           0 :             nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
    3894             :         }
    3895             :         else
    3896             :         {
    3897       34757 :             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
    3898       34757 :             const SvxBoxItem& rBoxItem = rSet.GetBox();
    3899       34757 :             nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, true ) -
    3900       34757 :                                  rBoxItem.GetDistance( BOX_LINE_BOTTOM );
    3901             :         }
    3902       34757 :         nBottomLineSize = std::max( nBottomLineSize, nTmpBottomLineSize );
    3903             :     }
    3904       13035 :     return nBottomLineSize;
    3905             : }
    3906             : 
    3907             : // Calculate the maximum of BottomLineDist over all lowers:
    3908       13035 : static sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
    3909             : {
    3910       13035 :     sal_uInt16 nBottomLineDist = 0;
    3911       47792 :     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
    3912       34757 :           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
    3913             :     {
    3914       34757 :         sal_uInt16 nTmpBottomLineDist = 0;
    3915       34757 :         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
    3916             :         {
    3917           0 :             const SwFrm* pRow = pCurrLower->GetLastLower();
    3918           0 :             nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
    3919             :         }
    3920             :         else
    3921             :         {
    3922       34757 :             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
    3923       34757 :             const SvxBoxItem& rBoxItem = rSet.GetBox();
    3924       34757 :             nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
    3925             :         }
    3926       34757 :         nBottomLineDist = std::max( nBottomLineDist, nTmpBottomLineDist );
    3927             :     }
    3928       13035 :     return nBottomLineDist;
    3929             : }
    3930             : 
    3931       13041 : void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
    3932             : {
    3933       13041 :     SWRECTFN( this )
    3934             :     OSL_ENSURE( pAttrs, "SwRowFrm::Format without Attrs." );
    3935             : 
    3936       13041 :     const sal_Bool bFix = mbFixSize;
    3937             : 
    3938       13041 :     if ( !mbValidPrtArea )
    3939             :     {
    3940             :         //RowFrms don't have borders and so on therefore the PrtArea always
    3941             :         //matches the Frm.
    3942       13041 :         mbValidPrtArea = sal_True;
    3943       13041 :         maPrt.Left( 0 );
    3944       13041 :         maPrt.Top( 0 );
    3945       13041 :         maPrt.Width ( maFrm.Width() );
    3946       13041 :         maPrt.Height( maFrm.Height() );
    3947             : 
    3948             :         // #i29550#
    3949             :         // Here we calculate the top-printing area for the lower cell frames
    3950       13041 :         SwTabFrm* pTabFrm = FindTabFrm();
    3951       13041 :         if ( pTabFrm->IsCollapsingBorders() )
    3952             :         {
    3953       13035 :             const sal_uInt16 nTopSpace        = lcl_GetTopSpace(       *this );
    3954       13035 :             const sal_uInt16 nTopLineDist     = lcl_GetTopLineDist(    *this );
    3955       13035 :             const sal_uInt16 nBottomLineSize  = lcl_GetBottomLineSize( *this );
    3956       13035 :             const sal_uInt16 nBottomLineDist  = lcl_GetBottomLineDist( *this );
    3957             : 
    3958       13035 :             const SwRowFrm* pPreviousRow = 0;
    3959             : 
    3960             :             // #i32456#
    3961             :             // In order to calculate the top printing area for the lower cell
    3962             :             // frames, we have to find the 'previous' row frame and compare
    3963             :             // the bottom values of the 'previous' row with the 'top' values
    3964             :             // of this row. The best way to find the 'previous' row is to
    3965             :             // use the table structure:
    3966       13035 :             const SwTable* pTable = pTabFrm->GetTable();
    3967       13035 :             const SwTableLine* pPrevTabLine = 0;
    3968       13035 :             const SwRowFrm* pTmpRow = this;
    3969             : 
    3970       39105 :             while ( pTmpRow && !pPrevTabLine )
    3971             :             {
    3972       13035 :                 sal_uInt16 nIdx = 0;
    3973       13035 :                 const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
    3974           0 :                                              pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
    3975       13035 :                                              pTable->GetTabLines();
    3976             : 
    3977      772959 :                 while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
    3978      746889 :                     ++nIdx;
    3979             : 
    3980       13035 :                 if ( nIdx > 0 )
    3981             :                 {
    3982             :                     // pTmpRow has a 'previous' row in the table structure:
    3983       10950 :                     pPrevTabLine = rLines[ nIdx - 1 ];
    3984             :                 }
    3985             :                 else
    3986             :                 {
    3987             :                     // pTmpRow is a first row in the table structue.
    3988             :                     // We go up in the table structure:
    3989        4170 :                     pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
    3990        2085 :                               pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
    3991           0 :                               static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
    3992        2085 :                               0;
    3993             :                 }
    3994             :             }
    3995             : 
    3996             :             // If we found a 'previous' row, we look for the appropriate row frame:
    3997       13035 :             if ( pPrevTabLine )
    3998             :             {
    3999       10950 :                 SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
    4000       20531 :                 for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
    4001             :                 {
    4002             :                     // #115759# - do *not* take repeated
    4003             :                     // headlines, because during split of table it can be
    4004             :                     // invalid and thus can't provide correct border values.
    4005       31481 :                     if ( pRow->GetTabLine() == pPrevTabLine &&
    4006       10950 :                          !pRow->IsRepeatedHeadline() )
    4007             :                     {
    4008       10950 :                         pPreviousRow = pRow;
    4009       10950 :                         break;
    4010             :                     }
    4011       10950 :                 }
    4012             :             }
    4013             : 
    4014       13035 :             sal_uInt16 nTopPrtMargin = nTopSpace;
    4015       13035 :             if ( pPreviousRow )
    4016             :             {
    4017       10950 :                 const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
    4018       10950 :                 if ( nTmpPrtMargin > nTopPrtMargin )
    4019         941 :                     nTopPrtMargin = nTmpPrtMargin;
    4020             :             }
    4021             : 
    4022             :             // table has to be notified if it has to change its lower
    4023             :             // margin due to changes of nBottomLineSize:
    4024       13035 :             if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
    4025         316 :                  pTabFrm->_InvalidatePrt();
    4026             : 
    4027             :             // If there are rows nested inside this row, the nested rows
    4028             :             // may not have been calculated yet. Therefore the
    4029             :             // ::lcl_CalcMinRowHeight( this ) operation later in this
    4030             :             // function cannot consider the correct border values. We
    4031             :             // have to trigger the invalidation of the outer row frame
    4032             :             // manually:
    4033             :             // Note: If any further invalidations should be necessary, we
    4034             :             // should consider moving the invalidation stuff to the
    4035             :             // appropriate SwNotify object.
    4036       13035 :             if ( GetUpper()->GetUpper()->IsRowFrm() &&
    4037           0 :                  ( nBottomLineDist != GetBottomMarginForLowers() ||
    4038           0 :                    nTopPrtMargin   != GetTopMarginForLowers() ) )
    4039           0 :                 GetUpper()->GetUpper()->_InvalidateSize();
    4040             : 
    4041       13035 :             SetBottomMarginForLowers( nBottomLineDist );    //  3.
    4042       13035 :             SetBottomLineSize( nBottomLineSize );           //  4.
    4043       13035 :             SetTopMarginForLowers( nTopPrtMargin );         //  5.
    4044             : 
    4045             :         }
    4046             :     }
    4047             : 
    4048       39123 :     while ( !mbValidSize )
    4049             :     {
    4050       13041 :         mbValidSize = sal_True;
    4051             : 
    4052             : #if OSL_DEBUG_LEVEL > 0
    4053             :         if ( HasFixSize() )
    4054             :         {
    4055             :             const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
    4056             :             OSL_ENSURE( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
    4057             :         }
    4058             : #endif
    4059       39123 :         const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
    4060       13210 :                               ( HasFixSize() && !IsRowSpanLine()
    4061         169 :                                 ? pAttrs->GetSize().Height()
    4062             :                                 // #i26945#
    4063             :                                 : ::lcl_CalcMinRowHeight( this,
    4064       25913 :                                     FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
    4065       13041 :         if ( nDiff )
    4066             :         {
    4067        2292 :             mbFixSize = sal_False;
    4068        2292 :             if ( nDiff > 0 )
    4069         180 :                 Shrink( nDiff, sal_False, sal_True );
    4070        2112 :             else if ( nDiff < 0 )
    4071        2112 :                 Grow( -nDiff );
    4072        2292 :             mbFixSize = bFix;
    4073             :         }
    4074             :     }
    4075             : 
    4076             :     // last row will fill the space in its upper.
    4077       13041 :     if ( !GetNext() )
    4078             :     {
    4079             :         //The last fills the remaining space in the upper.
    4080        2921 :         SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
    4081        2921 :         SwFrm *pSibling = GetUpper()->Lower();
    4082       22309 :         do
    4083       22309 :         {   nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
    4084       22309 :             pSibling = pSibling->GetNext();
    4085             :         } while ( pSibling );
    4086        2921 :         if ( nDiff > 0 )
    4087             :         {
    4088           0 :             mbFixSize = sal_False;
    4089           0 :             Grow( nDiff );
    4090           0 :             mbFixSize = bFix;
    4091           0 :             mbValidSize = sal_True;
    4092             :         }
    4093             :     }
    4094       13041 : }
    4095             : 
    4096       20881 : void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight )
    4097             : {
    4098       20881 :     SwFrm *pFrm = Lower();
    4099       20881 :     if ( bHeight )
    4100             :     {
    4101       18528 :         SwRootFrm *pRootFrm = getRootFrm();
    4102       18528 :         SWRECTFN( this )
    4103       18528 :         SwRect aOldFrm;
    4104             : 
    4105      100686 :         while ( pFrm )
    4106             :         {
    4107       63630 :             SwFrm* pNotify = 0;
    4108             : 
    4109       63630 :             SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
    4110             : 
    4111             :             // NEW TABLES
    4112             :             // Which cells need to be adjusted if the current row changes
    4113             :             // its height?
    4114             : 
    4115             :             // Current frame is a covered frame:
    4116             :             // Set new height for covered cell and adjust master cell:
    4117       63630 :             if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
    4118             :             {
    4119             :                 // Set height of current (covered) cell to new line height.
    4120         151 :                 const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
    4121         151 :                 if ( nDiff )
    4122             :                 {
    4123          59 :                     (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
    4124          59 :                     pCellFrm->_InvalidatePrt();
    4125             :                 }
    4126             :             }
    4127             : 
    4128       63630 :             SwCellFrm* pToAdjust = 0;
    4129       63630 :             SwFrm* pToAdjustRow = 0;
    4130             : 
    4131             :             // If current frame is covered frame, we still want to adjust the
    4132             :             // height of the cell starting the row span
    4133       63630 :             if ( pCellFrm->GetLayoutRowSpan() < 1 )
    4134             :             {
    4135         151 :                 pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
    4136         151 :                 pToAdjustRow = pToAdjust->GetUpper();
    4137             :             }
    4138             :             else
    4139             :             {
    4140       63479 :                 pToAdjust = pCellFrm;
    4141       63479 :                 pToAdjustRow = this;
    4142             :             }
    4143             : 
    4144             :             // Set height of master cell to height of all lines spanned by this line.
    4145       63630 :             long nRowSpan = pToAdjust->GetLayoutRowSpan();
    4146       63630 :             SwTwips nSumRowHeight = 0;
    4147      127607 :             while ( pToAdjustRow )
    4148             :             {
    4149             :                 // Use new height for the current row:
    4150       63977 :                 nSumRowHeight += pToAdjustRow == this ?
    4151             :                                  nHeight :
    4152       63977 :                                  (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
    4153             : 
    4154       63977 :                 if ( nRowSpan-- == 1 )
    4155       63630 :                     break;
    4156             : 
    4157         347 :                 pToAdjustRow = pToAdjustRow->GetNext();
    4158             :             }
    4159             : 
    4160       63630 :             if ( pToAdjustRow && pToAdjustRow != this )
    4161         109 :                 pToAdjustRow->_InvalidateSize();
    4162             : 
    4163       63630 :             const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
    4164       63630 :             if ( nDiff )
    4165             :             {
    4166       25599 :                 aOldFrm = pToAdjust->Frm();
    4167       25599 :                 (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
    4168       25599 :                 pNotify = pToAdjust;
    4169             :             }
    4170             : 
    4171       63630 :             if ( pNotify )
    4172             :             {
    4173       25599 :                 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
    4174           0 :                     pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
    4175             : 
    4176       25599 :                 pNotify->_InvalidatePrt();
    4177             :             }
    4178             : 
    4179       63630 :             pFrm = pFrm->GetNext();
    4180             :         }
    4181             :     }
    4182             :     else
    4183       11463 :     {   while ( pFrm )
    4184             :         {
    4185        6757 :             pFrm->_InvalidateAll();
    4186        6757 :             pFrm = pFrm->GetNext();
    4187             :         }
    4188             :     }
    4189       20881 :     InvalidatePage();
    4190       20881 : }
    4191             : 
    4192         755 : void SwRowFrm::Cut()
    4193             : {
    4194         755 :     SwTabFrm *pTab = FindTabFrm();
    4195         755 :     if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
    4196             :     {
    4197         746 :         pTab->FindMaster()->InvalidatePos();
    4198             :     }
    4199             : 
    4200             :     // #i103961#
    4201             :     // notification for accessibility
    4202             :     {
    4203         755 :         SwRootFrm *pRootFrm = getRootFrm();
    4204         755 :         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
    4205             :         {
    4206           0 :             SwViewShell* pVSh = pRootFrm->GetCurrShell();
    4207           0 :             if ( pVSh && pVSh->Imp() )
    4208             :             {
    4209           0 :                 SwFrm* pCellFrm( GetLower() );
    4210           0 :                 while ( pCellFrm )
    4211             :                 {
    4212             :                     OSL_ENSURE( pCellFrm->IsCellFrm(),
    4213             :                             "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
    4214           0 :                     pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
    4215             : 
    4216           0 :                     pCellFrm = pCellFrm->GetNext();
    4217             :                 }
    4218             :             }
    4219             :         }
    4220             :     }
    4221             : 
    4222         755 :     SwLayoutFrm::Cut();
    4223         755 : }
    4224             : 
    4225       10070 : SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
    4226             : {
    4227       10070 :     SwTwips nReal = 0;
    4228             : 
    4229       10070 :     SwTabFrm* pTab = FindTabFrm();
    4230       10070 :     SWRECTFN( pTab )
    4231             : 
    4232             :     bool bRestrictTableGrowth;
    4233       10070 :     bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
    4234             : 
    4235       10070 :     if ( GetUpper()->IsTabFrm() )
    4236             :     {
    4237       10070 :         const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
    4238       10070 :         bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
    4239             :     }
    4240             :     else
    4241             :     {
    4242             :         OSL_ENSURE( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" );
    4243           0 :         bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
    4244             :         OSL_ENSURE( !bRestrictTableGrowth || !GetNext(),
    4245             :                 "GetFollowRow for row frame that has a Next" );
    4246             : 
    4247             :         // There may still be some space left in my direct upper:
    4248             :         const SwTwips nAdditionalSpace =
    4249           0 :                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
    4250           0 :         if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
    4251             :         {
    4252           0 :             nReal = std::min( nAdditionalSpace, nDist );
    4253           0 :             nDist -= nReal;
    4254           0 :             if ( !bTst )
    4255           0 :                 (Frm().*fnRect->fnAddBottom)( nReal );
    4256             :         }
    4257             :     }
    4258             : 
    4259       10070 :     if ( bRestrictTableGrowth )
    4260        3318 :         pTab->SetRestrictTableGrowth( sal_True );
    4261             :     else
    4262             :     {
    4263             :         // Ok, this looks like a hack, indeed, it is a hack.
    4264             :         // If the current row frame is inside another cell frame,
    4265             :         // and the current row frame has no follow, it should not
    4266             :         // be allowed to grow. In fact, setting bRestrictTableGrowth
    4267             :         // to 'false' does not work, because the surrounding RowFrm
    4268             :         // would set this to 'true'.
    4269        6752 :         pTab->SetFollowFlowLine( sal_False );
    4270             :     }
    4271             : 
    4272       10070 :     nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
    4273             : 
    4274       10070 :     pTab->SetRestrictTableGrowth( sal_False );
    4275       10070 :     pTab->SetFollowFlowLine( bHasFollowFlowLine );
    4276             : 
    4277             :     //Update the height of the cells to the newest value.
    4278       10070 :     if ( !bTst )
    4279             :     {
    4280        8060 :         SWRECTFNX( this )
    4281        8060 :         AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True );
    4282        8060 :         if ( nReal )
    4283        6586 :             SetCompletePaint();
    4284             :     }
    4285             : 
    4286       10070 :     return nReal;
    4287             : }
    4288             : 
    4289        8213 : SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
    4290             : {
    4291        8213 :     SWRECTFN( this )
    4292        8213 :     if( HasFixSize() )
    4293             :     {
    4294         299 :         AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True );
    4295         299 :         return 0L;
    4296             :     }
    4297             : 
    4298             :     // bInfo may be set to sal_True by SwRowFrm::Format; we need to hangle this
    4299             :     // here accordingly
    4300        7914 :     const sal_Bool bShrinkAnyway = bInfo;
    4301             : 
    4302             :     //Only shrink as much as the content of the biggest cell allows.
    4303        7914 :     SwTwips nRealDist = nDist;
    4304             :     {
    4305        7914 :         const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
    4306        7914 :         SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
    4307             :                              rSz.GetHeight() :
    4308        7914 :                              0;
    4309             : 
    4310             :         // Only necessary to calculate minimal row height if height
    4311             :         // of pRow is at least nMinHeight. Otherwise nMinHeight is the
    4312             :         // minimum height.
    4313        7914 :         if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
    4314             :         {
    4315             :             // #i26945#
    4316             :             OSL_ENSURE( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
    4317        3414 :             const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
    4318        3414 :             nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
    4319             :         }
    4320             : 
    4321        7914 :         if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
    4322        6919 :             nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
    4323             :     }
    4324        7914 :     if ( nRealDist < 0 )
    4325           7 :         nRealDist = 0;
    4326             : 
    4327        7914 :     SwTwips nReal = nRealDist;
    4328        7914 :     if ( nReal )
    4329             :     {
    4330        1181 :         if ( !bTst )
    4331             :         {
    4332        1181 :             SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
    4333        1181 :             (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
    4334             :             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    4335        1181 :             if( IsVertical() && !IsVertLR() && !bRev )
    4336           0 :                 Frm().Pos().X() += nReal;
    4337             :         }
    4338             : 
    4339        1181 :         SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
    4340        1181 :         if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
    4341             :         {
    4342             :             //The last one gets the leftover in the upper and therefore takes
    4343             :             //care (otherwise: endless loop)
    4344           0 :             if ( !bTst )
    4345             :             {
    4346           0 :                 nReal -= nTmp;
    4347           0 :                 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
    4348           0 :                 (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
    4349             :                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    4350           0 :                 if( IsVertical() && !IsVertLR() && !bRev )
    4351           0 :                     Frm().Pos().X() -= nReal;
    4352             :             }
    4353           0 :             nReal = nTmp;
    4354             :         }
    4355             :     }
    4356             : 
    4357             :     //Invalidate if possible and update the height to the newest value.
    4358        7914 :     if ( !bTst )
    4359             :     {
    4360        7914 :         if ( nReal )
    4361             :         {
    4362        1181 :             if ( GetNext() )
    4363         165 :                 GetNext()->_InvalidatePos();
    4364        1181 :             _InvalidateAll();
    4365        1181 :             SetCompletePaint();
    4366             : 
    4367        1181 :             SwTabFrm *pTab = FindTabFrm();
    4368        2362 :             if ( !pTab->IsRebuildLastLine()
    4369         600 :                  && pTab->IsFollow()
    4370         277 :                  && this == pTab->GetFirstNonHeadlineRow()
    4371        1354 :                  && !pTab->IsInRecalcLowerRow() )
    4372             :             {
    4373         173 :                 SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
    4374         173 :                 pMasterTab->InvalidatePos();
    4375             :             }
    4376             :         }
    4377        7914 :         AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True );
    4378             :     }
    4379        7914 :     return nReal;
    4380             : }
    4381             : 
    4382        1653 : bool SwRowFrm::IsRowSplitAllowed() const
    4383             : {
    4384             :     // Fixed size rows are never allowed to split:
    4385        1653 :     if ( HasFixSize() )
    4386             :     {
    4387             :         OSL_ENSURE( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" );
    4388           3 :         return false;
    4389             :     }
    4390             : 
    4391             :     // Repeated headlines are never allowed to split:
    4392        1650 :     const SwTabFrm* pTabFrm = FindTabFrm();
    4393        1650 :     if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
    4394           0 :          pTabFrm->IsInHeadline( *this ) )
    4395           0 :         return false;
    4396             : 
    4397        1650 :     const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
    4398        1650 :     const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
    4399        1650 :     return rLP.GetValue();
    4400             : }
    4401             : 
    4402        3275 : bool SwRowFrm::ShouldRowKeepWithNext() const
    4403             : {
    4404        3275 :     bool bRet = false;
    4405             : 
    4406        3275 :     const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
    4407        3275 :     const SwFrm* pTxt = pCell->Lower();
    4408             : 
    4409        3275 :     if ( pTxt && pTxt->IsTxtFrm() )
    4410             :     {
    4411        3145 :         bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
    4412             :     }
    4413        3275 :     return bRet;
    4414             : }
    4415             : 
    4416        8396 : SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
    4417             :     SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
    4418        8396 :     pTabBox( &rBox )
    4419             : {
    4420        8396 :     mnType = FRMC_CELL;
    4421             : 
    4422        8396 :     if ( !bInsertContent )
    4423        8658 :         return;
    4424             : 
    4425             :     //If a StartIdx is available, CntntFrms are added in the cell, otherwise
    4426             :     //Rows have to be present and those are added.
    4427        8134 :     if ( rBox.GetSttIdx() )
    4428             :     {
    4429        8134 :         sal_uLong nIndex = rBox.GetSttIdx();
    4430        8134 :         ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
    4431             :     }
    4432             :     else
    4433             :     {
    4434           0 :         const SwTableLines &rLines = rBox.GetTabLines();
    4435           0 :         SwFrm *pTmpPrev = 0;
    4436           0 :         for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
    4437             :         {
    4438           0 :             SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
    4439           0 :             pNew->InsertBehind( this, pTmpPrev );
    4440           0 :             pTmpPrev = pNew;
    4441             :         }
    4442             :     }
    4443             : }
    4444             : 
    4445       25188 : SwCellFrm::~SwCellFrm()
    4446             : {
    4447        8396 :     SwModify* pMod = GetFmt();
    4448        8396 :     if( pMod )
    4449             :     {
    4450             :         // At this stage the lower frames aren't destroyed already,
    4451             :         // therefore we have to do a recursive dispose.
    4452        8396 :         SwRootFrm *pRootFrm = getRootFrm();
    4453        8396 :         if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
    4454           0 :             pRootFrm->GetCurrShell() )
    4455             :         {
    4456           0 :             pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, true );
    4457             :         }
    4458             : 
    4459        8396 :         pMod->Remove( this );           // remove,
    4460        8396 :         if( !pMod->GetDepends() )
    4461           0 :             delete pMod;                // and delete
    4462             :     }
    4463       16792 : }
    4464             : 
    4465       19558 : static bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, bool bInva )
    4466             : {
    4467       19558 :     bool bRet = false;
    4468       19558 :     SwFrm *pFrm = pLay->Lower();
    4469       19558 :     SWRECTFN( pLay )
    4470       81425 :     while ( pFrm )
    4471             :     {
    4472       42309 :         long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
    4473       42309 :         if( nFrmTop != lYStart )
    4474             :         {
    4475       28792 :             bRet = true;
    4476       28792 :             const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
    4477       28792 :             const long lDiffX = lYStart - nFrmTop;
    4478       28792 :             (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
    4479       28792 :             (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
    4480       28792 :             pFrm->SetCompletePaint();
    4481       28792 :             if ( !pFrm->GetNext() )
    4482       16123 :                 pFrm->SetRetouche();
    4483       28792 :             if( bInva )
    4484       14852 :                 pFrm->Prepare( PREP_POS_CHGD );
    4485       28792 :             if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
    4486             :                 lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
    4487         985 :                     (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
    4488        1970 :                     + lDiffX, bInva );
    4489       28792 :             if ( pFrm->GetDrawObjs() )
    4490             :             {
    4491         291 :                 for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
    4492             :                 {
    4493         168 :                     SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
    4494             :                     // #i26945# - check, if anchored object
    4495             :                     // is lower of layout frame by checking, if the anchor
    4496             :                     // frame, which contains the anchor position, is a lower
    4497             :                     // of the layout frame.
    4498         168 :                     if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
    4499             :                     {
    4500           0 :                         continue;
    4501             :                     }
    4502             :                     // #i52904# - distinguish between anchored
    4503             :                     // objects, whose vertical position depends on its anchor
    4504             :                     // frame and whose vertical position is independent
    4505             :                     // from its anchor frame.
    4506         168 :                     bool bVertPosDepOnAnchor( true );
    4507             :                     {
    4508         168 :                         SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
    4509         168 :                         switch ( aVert.GetRelationOrient() )
    4510             :                         {
    4511             :                             case text::RelOrientation::PAGE_FRAME:
    4512             :                             case text::RelOrientation::PAGE_PRINT_AREA:
    4513           0 :                                 bVertPosDepOnAnchor = false;
    4514           0 :                                 break;
    4515         168 :                             default: break;
    4516         168 :                         }
    4517             :                     }
    4518         168 :                     if ( pAnchoredObj->ISA(SwFlyFrm) )
    4519             :                     {
    4520          32 :                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
    4521             : 
    4522             :                         // OD 2004-05-18 #i28701# - no direct move of objects,
    4523             :                         // which are anchored to-paragraph/to-character, if
    4524             :                         // the wrapping style influence has to be considered
    4525             :                         // on the object positioning.
    4526             :                         // #i52904# - no direct move of objects,
    4527             :                         // whose vertical position doesn't depend on anchor frame.
    4528             :                         const bool bDirectMove =
    4529          50 :                                 FAR_AWAY != pFly->Frm().Top() &&
    4530          50 :                                 bVertPosDepOnAnchor &&
    4531          50 :                                 !pFly->ConsiderObjWrapInfluenceOnObjPos();
    4532          32 :                         if ( bDirectMove )
    4533             :                         {
    4534          18 :                             (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
    4535          18 :                             (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
    4536          18 :                             pFly->GetVirtDrawObj()->SetRectsDirty();
    4537             :                             // --> OD 2004-08-17 - also notify view of <SdrObject>
    4538             :                             // instance, which represents the Writer fly frame in
    4539             :                             // the drawing layer
    4540          18 :                             pFly->GetVirtDrawObj()->SetChanged();
    4541             :                             // #i58280#
    4542          18 :                             pFly->InvalidateObjRectWithSpaces();
    4543             :                         }
    4544             : 
    4545          32 :                         if ( pFly->IsFlyInCntFrm() )
    4546             :                         {
    4547          19 :                             static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
    4548             :                             // #115759# - reset current relative
    4549             :                             // position to get re-positioned, if not directly moved.
    4550          19 :                             if ( !bDirectMove )
    4551             :                             {
    4552           1 :                                 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
    4553             :                             }
    4554             :                         }
    4555          13 :                         else if( pFly->IsAutoPos() )
    4556             :                         {
    4557           1 :                             pFly->AddLastCharY( lDiff );
    4558             :                             // OD 2004-05-18 #i28701# - follow-up of #i22341#
    4559             :                             // <mnLastTopOfLine> has also been adjusted.
    4560           1 :                             pFly->AddLastTopOfLineY( lDiff );
    4561             :                         }
    4562             :                         // #i26945# - re-registration at
    4563             :                         // page frame of anchor frame, if table frame isn't
    4564             :                         // a follow table and table frame isn't in its
    4565             :                         // rebuild of last line.
    4566          32 :                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
    4567             :                         // #115759#
    4568             :                         // - save: check, if table frame is found.
    4569          64 :                         if ( pTabFrm &&
    4570          32 :                              !( pTabFrm->IsFollow() &&
    4571          64 :                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
    4572          32 :                              pFly->IsFlyFreeFrm() )
    4573             :                         {
    4574          13 :                             SwPageFrm* pPageFrm = pFly->GetPageFrm();
    4575          13 :                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
    4576          13 :                             if ( pPageFrm != pPageOfAnchor )
    4577             :                             {
    4578           0 :                                 pFly->InvalidatePos();
    4579           0 :                                 if ( pPageFrm )
    4580           0 :                                     pPageFrm->MoveFly( pFly, pPageOfAnchor );
    4581             :                                 else
    4582           0 :                                     pPageOfAnchor->AppendFlyToPage( pFly );
    4583             :                             }
    4584             :                         }
    4585             :                         // OD 2004-05-11 #i28701# - Because of the introduction
    4586             :                         // of new positionings and alignments (e.g. aligned at
    4587             :                         // page area, but anchored at-character), the position
    4588             :                         // of the Writer fly frame has to be invalidated.
    4589          32 :                         pFly->InvalidatePos();
    4590             : 
    4591             :                         // #i26945# - follow-up of #i3317#
    4592             :                         // No arrangement of lowers, if Writer fly frame isn't
    4593             :                         // moved
    4594          50 :                         if ( bDirectMove &&
    4595             :                              ::lcl_ArrangeLowers( pFly,
    4596          36 :                                                   (pFly->*fnRect->fnGetPrtTop)(),
    4597          54 :                                                   bInva ) )
    4598             :                         {
    4599          18 :                             pFly->SetCompletePaint();
    4600             :                         }
    4601             :                     }
    4602         136 :                     else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
    4603             :                     {
    4604             :                         // #i26945#
    4605         136 :                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
    4606         272 :                         if ( pTabFrm &&
    4607         136 :                              !( pTabFrm->IsFollow() &&
    4608         272 :                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
    4609         118 :                             (pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
    4610             :                                                             != FLY_AS_CHAR))
    4611             :                         {
    4612          26 :                             SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
    4613          26 :                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
    4614          26 :                             if ( pPageFrm != pPageOfAnchor )
    4615             :                             {
    4616          11 :                                 pAnchoredObj->InvalidateObjPos();
    4617          11 :                                 if ( pPageFrm )
    4618             :                                 {
    4619          11 :                                     pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
    4620             :                                 }
    4621          11 :                                 pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
    4622             :                             }
    4623             :                         }
    4624             :                         // #i28701# - adjust last character
    4625             :                         // rectangle and last top of line.
    4626         136 :                         pAnchoredObj->AddLastCharY( lDiff );
    4627         136 :                         pAnchoredObj->AddLastTopOfLineY( lDiff );
    4628             :                         // #i52904# - re-introduce direct move
    4629             :                         // of drawing objects
    4630             :                         const bool bDirectMove =
    4631         264 :                                 static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
    4632         264 :                                 bVertPosDepOnAnchor &&
    4633         264 :                                 !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
    4634         136 :                         if ( bDirectMove )
    4635             :                         {
    4636         128 :                             SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
    4637         128 :                             if ( bVert )
    4638             :                             {
    4639           0 :                                 pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
    4640             :                             }
    4641             :                             else
    4642             :                             {
    4643         128 :                                 pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
    4644             :                             }
    4645             :                             // #i58280#
    4646         128 :                             pAnchoredObj->InvalidateObjRectWithSpaces();
    4647             :                         }
    4648         136 :                         pAnchoredObj->InvalidateObjPos();
    4649             :                     }
    4650             :                     else
    4651             :                     {
    4652             :                         OSL_FAIL( "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
    4653             :                     }
    4654             :                 }
    4655             :             }
    4656             :         }
    4657             :         // Columns and cells are ordered horizontal, not vertical
    4658       42309 :         if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
    4659             :             lYStart = (*fnRect->fnYInc)( lYStart,
    4660       41606 :                                         (pFrm->Frm().*fnRect->fnGetHeight)() );
    4661             : 
    4662             :         // Nowadays, the content inside a cell can flow into the follow table.
    4663             :         // Thus, the cell may only grow up to the end of the environment.
    4664             :         // So the content may have grown, but the cell could not grow.
    4665             :         // Therefore we have to trigger a formatting for the frames, which do
    4666             :         // not fit into the cell anymore:
    4667             :         SwTwips nDistanceToUpperPrtBottom =
    4668       42309 :             (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
    4669             :         // #i56146# - Revise fix of issue #i26945#
    4670             :         // do *not* consider content inside fly frames, if it's an undersized paragraph.
    4671             :         // #i26945# - consider content inside fly frames
    4672       42857 :         if ( nDistanceToUpperPrtBottom < 0 &&
    4673         413 :              ( ( pFrm->IsInFly() &&
    4674           0 :                  ( !pFrm->IsTxtFrm() ||
    4675         413 :                    !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
    4676         413 :                pFrm->IsInSplitTableRow() ) )
    4677             :         {
    4678         135 :             pFrm->InvalidatePos();
    4679             :         }
    4680             : 
    4681       42309 :         pFrm = pFrm->GetNext();
    4682             :     }
    4683       19558 :     return bRet;
    4684             : }
    4685             : 
    4686       19218 : void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
    4687             : {
    4688             :     OSL_ENSURE( pAttrs, "CellFrm::Format, pAttrs ist 0." );
    4689       19218 :     const SwTabFrm* pTab = FindTabFrm();
    4690       19218 :     SWRECTFN( pTab )
    4691             : 
    4692       19218 :     if ( !mbValidPrtArea )
    4693             :     {
    4694       19218 :         mbValidPrtArea = sal_True;
    4695             : 
    4696             :         //Adjust position.
    4697       19218 :         if ( Lower() )
    4698             :         {
    4699             :             SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
    4700             :             // #i29550#
    4701       19078 :             if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm()  )
    4702             :             {
    4703       19058 :                 const SvxBoxItem& rBoxItem = pAttrs->GetBox();
    4704       19058 :                 nLeftSpace   = rBoxItem.GetDistance( BOX_LINE_LEFT );
    4705       19058 :                 nRightSpace  = rBoxItem.GetDistance( BOX_LINE_RIGHT );
    4706       19058 :                 nTopSpace    =  ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
    4707       19058 :                 nBottomSpace =  ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
    4708             :             }
    4709             :             else
    4710             :             {
    4711             :                 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
    4712          20 :                 nLeftSpace   = pAttrs->CalcLeft( this );
    4713          20 :                 nRightSpace  = pAttrs->CalcRight( this );
    4714          20 :                 nTopSpace    = pAttrs->CalcTop();
    4715          20 :                 nBottomSpace = pAttrs->CalcBottom();
    4716             :             }
    4717       19078 :             (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
    4718       19078 :             (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
    4719             :         }
    4720             :     }
    4721             :     // #i26945#
    4722       19218 :     long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
    4723       19180 :                       ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
    4724       38398 :                       0;
    4725       19218 :     if ( !mbValidSize )
    4726             :     {
    4727       12753 :         mbValidSize = sal_True;
    4728             : 
    4729             :         //The VarSize of the CellFrms is always the width.
    4730             :         //The width is not variable though, it is defined by the format.
    4731             :         //This predefined value however does not necessary match the actual
    4732             :         //width. The width is calculated based on the attribute, the value in
    4733             :         //the attribute matches the desired value of the TabFrm. Changes which
    4734             :         //were done there are taken into account here proportionately.
    4735             :         //If the cell doesn't have a neighbour anymore, it does not take the
    4736             :         //attribute into account and takes the rest of the upper instead.
    4737             :         SwTwips nWidth;
    4738       12753 :         if ( GetNext() )
    4739             :         {
    4740        7936 :             const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
    4741        7936 :             nWidth = pAttrs->GetSize().Width();
    4742             : 
    4743             :             OSL_ENSURE( nWish, "Table without width?" );
    4744             :             OSL_ENSURE( nWidth <= nWish, "Width of cell larger than table." );
    4745             :             OSL_ENSURE( nWidth > 0, "Box without width" );
    4746             : 
    4747        7936 :             const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
    4748        7936 :             if ( nWish != nPrtWidth )
    4749             :             {
    4750             :                 // Avoid rounding problems, at least for the new table model
    4751        1887 :                 if ( pTab->GetTable()->IsNewModel() )
    4752             :                 {
    4753             :                     // 1. sum of widths of cells up to this cell (in model)
    4754        1887 :                     const SwTableLine* pTabLine = GetTabBox()->GetUpper();
    4755        1887 :                     const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
    4756        1887 :                     const SwTableBox* pTmpBox = 0;
    4757             : 
    4758        1887 :                     SwTwips nSumWidth = 0;
    4759        1887 :                     sal_uInt16 i = 0;
    4760        4296 :                     do
    4761             :                     {
    4762        4296 :                         pTmpBox = rBoxes[ i++ ];
    4763        4296 :                         nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
    4764             :                     }
    4765        4296 :                     while ( pTmpBox != GetTabBox() );
    4766             : 
    4767             :                     // 2. calculate actual width of cells up to this one
    4768        1887 :                     double nTmpWidth = nSumWidth;
    4769        1887 :                     nTmpWidth *= nPrtWidth;
    4770        1887 :                     nTmpWidth /= nWish;
    4771        1887 :                     nWidth = (SwTwips)nTmpWidth;
    4772             : 
    4773             :                     // 3. calculate frame widths of cells up to this one:
    4774        1887 :                     const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
    4775        1887 :                     SwTwips nSumFrameWidths = 0;
    4776        6183 :                     while ( pTmpCell != this )
    4777             :                     {
    4778        2409 :                         nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
    4779        2409 :                         pTmpCell = pTmpCell->GetNext();
    4780             :                     }
    4781             : 
    4782        1887 :                     nWidth = nWidth - nSumFrameWidths;
    4783             :                 }
    4784             :                 else
    4785             :                 {
    4786             :                     // #i12092# use double instead of long,
    4787             :                     // otherwise this could lead to overflows
    4788           0 :                     double nTmpWidth = nWidth;
    4789           0 :                     nTmpWidth *= nPrtWidth;
    4790           0 :                     nTmpWidth /= nWish;
    4791           0 :                     nWidth = (SwTwips)nTmpWidth;
    4792             :                 }
    4793             :             }
    4794             :         }
    4795             :         else
    4796             :         {
    4797             :             OSL_ENSURE( pAttrs->GetSize().Width() > 0, "Box without width" );
    4798        4817 :             nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
    4799        4817 :             SwFrm *pPre = GetUpper()->Lower();
    4800       15756 :             while ( pPre != this )
    4801             :             {
    4802        6122 :                 nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
    4803        6122 :                 pPre = pPre->GetNext();
    4804             :             }
    4805             :         }
    4806       12753 :         const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
    4807       12753 :         if( IsNeighbourFrm() && IsRightToLeft() )
    4808           0 :             (Frm().*fnRect->fnSubLeft)( nDiff );
    4809             :         else
    4810       12753 :             (Frm().*fnRect->fnAddRight)( nDiff );
    4811       12753 :         (Prt().*fnRect->fnAddRight)( nDiff );
    4812             : 
    4813             :         //Adjust the height, it's defined through the content and the border.
    4814       12753 :         const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
    4815       12753 :         if ( nDiffHeight )
    4816             :         {
    4817        6761 :             if ( nDiffHeight > 0 )
    4818             :             {
    4819             :                 //Validate again if no growth happened. Invalidation is done
    4820             :                 //through AdjustCells of the row.
    4821          36 :                 if ( !Grow( nDiffHeight ) )
    4822          36 :                     mbValidSize = mbValidPrtArea = sal_True;
    4823             :             }
    4824             :             else
    4825             :             {
    4826             :                 //Only keep invalidated if shrinking was done; this can be
    4827             :                 //dismissed because all adjoined cells have to be the same size.
    4828        6725 :                 if ( !Shrink( -nDiffHeight ) )
    4829        6724 :                     mbValidSize = mbValidPrtArea = sal_True;
    4830             :             }
    4831             :         }
    4832             :     }
    4833       19218 :     const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
    4834             : 
    4835       19218 :     if ( !Lower() )
    4836         140 :         return;
    4837             : 
    4838             :     // From now on, all operations are related to the table cell.
    4839       19078 :     SWREFRESHFN( this )
    4840             : 
    4841       19078 :     SwPageFrm* pPg = 0;
    4842       63670 :     if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
    4843             :     // #158225# no vertical alignment of covered cells
    4844       40513 :          !IsCoveredCell() &&
    4845             :     // #116532# Do not consider vertical alignment in grid mode
    4846       14290 :          !(pPg = FindPageFrm())->HasGrid() )
    4847             :     {
    4848        7145 :         if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
    4849             :         {
    4850             :             // OSL_ENSURE(for HTML-import!
    4851             :             OSL_ENSURE( !this, "VAlign to cell without content" );
    4852           0 :             return;
    4853             :         }
    4854        7145 :         bool bVertDir = true;
    4855             :         // #i43913# - no vertical alignment, if wrapping
    4856             :         // style influence is considered on object positioning and
    4857             :         // an object is anchored inside the cell.
    4858        7145 :         const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
    4859             :         //No alignment if border with flow overlaps the cell.
    4860        7145 :         if ( pPg->GetSortedObjs() )
    4861             :         {
    4862        2059 :             SwRect aRect( Prt() ); aRect += Frm().Pos();
    4863        5636 :             for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i )
    4864             :             {
    4865        3589 :                 const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
    4866        3589 :                 SwRect aTmp( pAnchoredObj->GetObjRect() );
    4867        3589 :                 if ( aTmp.IsOver( aRect ) )
    4868             :                 {
    4869         449 :                     const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
    4870         449 :                     const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
    4871             : 
    4872         449 :                     if ( SURROUND_THROUGHT != rSur.GetSurround() )
    4873             :                     {
    4874             :                         // frames, which the cell is a lower of, aren't relevant
    4875         354 :                         if ( pAnchoredObj->ISA(SwFlyFrm) )
    4876             :                         {
    4877             :                             const SwFlyFrm *pFly =
    4878         354 :                                     static_cast<const SwFlyFrm*>(pAnchoredObj);
    4879         354 :                             if ( pFly->IsAnLower( this ) )
    4880         684 :                                 continue;
    4881             :                         }
    4882             : 
    4883          12 :                         const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
    4884             :                         // #i43913#
    4885             :                         // #i52904# - no vertical alignment,
    4886             :                         // if object, anchored inside cell, has temporarly
    4887             :                         // consider its wrapping style on object positioning.
    4888             :                         // #i58806# - no vertical alignment
    4889             :                         // if object does not follow the text flow.
    4890          12 :                         if ( bConsiderWrapOnObjPos ||
    4891           0 :                              !IsAnLower( pAnch ) ||
    4892          12 :                              pAnchoredObj->IsTmpConsiderWrapInfluence() ||
    4893           0 :                              !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
    4894             :                         {
    4895          12 :                             bVertDir = false;
    4896          24 :                             break;
    4897             :                         }
    4898             :                     }
    4899             :                 }
    4900             :             }
    4901             :         }
    4902             : 
    4903        7145 :         long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
    4904        9380 :         if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
    4905        2235 :             (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
    4906             :         {
    4907        5784 :             long nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
    4908        5784 :             if ( nDiff >= 0 )
    4909             :             {
    4910        5784 :                 long lTopOfst = 0;
    4911        5784 :                 if ( bVertDir )
    4912             :                 {
    4913        5778 :                     switch ( rOri.GetVertOrient() )
    4914             :                     {
    4915        2236 :                         case text::VertOrientation::CENTER:   lTopOfst = nDiff / 2; break;
    4916        2438 :                         case text::VertOrientation::BOTTOM:   lTopOfst = nDiff;     break;
    4917        1104 :                         default: break;
    4918             :                     };
    4919             :                 }
    4920             :                 long nTmp = (*fnRect->fnYInc)(
    4921        5784 :                                     (this->*fnRect->fnGetPrtTop)(), lTopOfst );
    4922        5784 :                 if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
    4923        5408 :                     SetCompletePaint();
    4924             :             }
    4925             :         }
    4926             :     }
    4927             :     else
    4928             :     {
    4929             :         //Was an old alignment taken into account?
    4930       11933 :         if ( Lower()->IsCntntFrm() )
    4931             :         {
    4932       11785 :             const long lYStart = (this->*fnRect->fnGetPrtTop)();
    4933       11785 :             lcl_ArrangeLowers( this, lYStart, true );
    4934             :         }
    4935             :     }
    4936             : }
    4937             : 
    4938         180 : void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
    4939             : {
    4940         180 :     bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
    4941         180 :     const SfxPoolItem *pItem = 0;
    4942             : 
    4943         180 :     if( bAttrSetChg )
    4944         180 :         ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, false, &pItem);
    4945           0 :     else if (pNew && RES_VERT_ORIENT == pNew->Which())
    4946           0 :         pItem = pNew;
    4947             : 
    4948         180 :     if ( pItem )
    4949             :     {
    4950           0 :         bool bInva = true;
    4951           0 :         if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
    4952             :              // OD 04.11.2003 #112910#
    4953           0 :              Lower() && Lower()->IsCntntFrm() )
    4954             :         {
    4955           0 :             SWRECTFN( this )
    4956           0 :             const long lYStart = (this->*fnRect->fnGetPrtTop)();
    4957           0 :             bInva = lcl_ArrangeLowers( this, lYStart, false );
    4958             :         }
    4959           0 :         if ( bInva )
    4960             :         {
    4961           0 :             SetCompletePaint();
    4962           0 :             InvalidatePrt();
    4963             :         }
    4964             :     }
    4965             : 
    4966         360 :     if ( ( bAttrSetChg &&
    4967         360 :            SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, false ) ) ||
    4968         180 :          RES_PROTECT == pNew->Which() )
    4969             :     {
    4970           0 :         SwViewShell *pSh = getRootFrm()->GetCurrShell();
    4971           0 :         if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
    4972           0 :             pSh->Imp()->InvalidateAccessibleEditableState( true, this );
    4973             :     }
    4974             : 
    4975         360 :     if ( bAttrSetChg &&
    4976         180 :          SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, false, &pItem ) )
    4977             :     {
    4978           0 :         SetDerivedVert( sal_False );
    4979           0 :         CheckDirChange();
    4980             :     }
    4981             : 
    4982             :     // #i29550#
    4983         360 :     if ( bAttrSetChg &&
    4984         180 :          SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, false, &pItem ) )
    4985             :     {
    4986          51 :         SwFrm* pTmpUpper = GetUpper();
    4987         102 :         while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
    4988           0 :             pTmpUpper = pTmpUpper->GetUpper();
    4989             : 
    4990          51 :         SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
    4991          51 :         if ( pTabFrm->IsCollapsingBorders() )
    4992             :         {
    4993             :             // Invalidate lowers of this and next row:
    4994          51 :             lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
    4995          51 :             pTmpUpper = pTmpUpper->GetNext();
    4996          51 :             if ( pTmpUpper )
    4997          25 :                 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
    4998             :             else
    4999          26 :                 pTabFrm->InvalidatePrt();
    5000             :         }
    5001             :     }
    5002             : 
    5003         180 :     SwLayoutFrm::Modify( pOld, pNew );
    5004         180 : }
    5005             : 
    5006      361346 : long SwCellFrm::GetLayoutRowSpan() const
    5007             : {
    5008      361346 :     long nRet = GetTabBox()->getRowSpan();
    5009      361346 :     if ( nRet < 1 )
    5010             :     {
    5011         492 :         const SwFrm* pRow = GetUpper();
    5012         492 :         const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
    5013             : 
    5014         492 :         if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
    5015           0 :             nRet = -nRet;
    5016             :     }
    5017      361346 :     return  nRet;
    5018             : }
    5019             : 
    5020             : // #i103961#
    5021           0 : void SwCellFrm::Cut()
    5022             : {
    5023             :     // notification for accessibility
    5024             :     {
    5025           0 :         SwRootFrm *pRootFrm = getRootFrm();
    5026           0 :         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
    5027             :         {
    5028           0 :             SwViewShell* pVSh = pRootFrm->GetCurrShell();
    5029           0 :             if ( pVSh && pVSh->Imp() )
    5030             :             {
    5031           0 :                 pVSh->Imp()->DisposeAccessibleFrm( this );
    5032             :             }
    5033             :         }
    5034             :     }
    5035             : 
    5036           0 :     SwLayoutFrm::Cut();
    5037           0 : }
    5038             : 
    5039             : // Helper functions for repeated headlines:
    5040             : 
    5041        2204 : bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
    5042             : {
    5043             :     OSL_ENSURE( IsAnLower( &rFrm ) && rFrm.IsInTab(),
    5044             :              "SwTabFrm::IsInHeadline called for frame not lower of table" );
    5045             : 
    5046        2204 :     const SwFrm* pTmp = &rFrm;
    5047        7760 :     while ( !pTmp->GetUpper()->IsTabFrm() )
    5048        3352 :         pTmp = pTmp->GetUpper();
    5049             : 
    5050        2204 :     return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
    5051             : }
    5052             : 
    5053             : /*
    5054             :  * If this is a master table, we can may assume, that there are at least
    5055             :  * nRepeat lines in the table.
    5056             :  * If this is a follow table, there are intermediate states for the table
    5057             :  * layout, e.g., during deletion of rows, which makes it necessary to find
    5058             :  * the first non-headline row by evaluating the headline flag at the row frame.
    5059             :  */
    5060       12142 : SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
    5061             : {
    5062       12142 :     SwRowFrm* pRet = (SwRowFrm*)Lower();
    5063       12142 :     if ( pRet )
    5064             :     {
    5065       12054 :         if ( IsFollow() )
    5066             :         {
    5067       23966 :             while ( pRet && pRet->IsRepeatedHeadline() )
    5068           0 :                 pRet = (SwRowFrm*)pRet->GetNext();
    5069             :         }
    5070             :         else
    5071             :         {
    5072          71 :             sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
    5073         142 :             while ( pRet && nRepeat > 0 )
    5074             :             {
    5075           0 :                 pRet = (SwRowFrm*)pRet->GetNext();
    5076           0 :                 --nRepeat;
    5077             :             }
    5078             :         }
    5079             :     }
    5080             : 
    5081       12142 :     return (SwRowFrm*)pRet;
    5082             : }
    5083             : 
    5084       11190 : bool SwTable::IsHeadline( const SwTableLine& rLine ) const
    5085             : {
    5086       11196 :     for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
    5087           6 :         if ( GetTabLines()[ i ] == &rLine )
    5088           0 :             return true;
    5089             : 
    5090       11190 :     return false;
    5091             : }
    5092             : 
    5093           0 : bool SwTabFrm::IsLayoutSplitAllowed() const
    5094             : {
    5095           0 :     return GetFmt()->GetLayoutSplit().GetValue();
    5096             : }
    5097             : 
    5098             : // #i29550#
    5099             : 
    5100        3424 : sal_uInt16 SwTabFrm::GetBottomLineSize() const
    5101             : {
    5102             :     OSL_ENSURE( IsCollapsingBorders(),
    5103             :             "BottomLineSize only required for collapsing borders" );
    5104             : 
    5105             :     OSL_ENSURE( Lower(), "Warning! Trying to prevent a crash, please inform FME" );
    5106             : 
    5107        3424 :     const SwFrm* pTmp = GetLastLower();
    5108             : 
    5109             :     // #124755# Try to make code robust
    5110        3424 :     if ( !pTmp ) return 0;
    5111             : 
    5112        3424 :     return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
    5113             : }
    5114             : 
    5115      120904 : bool SwTabFrm::IsCollapsingBorders() const
    5116             : {
    5117      120904 :     return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
    5118             : }
    5119             : 
    5120             : /// Local helper function to calculate height of first text row
    5121           7 : static SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
    5122             : {
    5123             :     // Find corresponding split line in master table
    5124           7 :     const SwTabFrm* pTab = rSourceLine.FindTabFrm();
    5125           7 :     SWRECTFN( pTab )
    5126           7 :     const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
    5127             : 
    5128             :     // 1. Case: rSourceLine is a follow flow line.
    5129             :     // In this case we have to return the minimum of the heights
    5130             :     // of the first lines in rSourceLine.
    5131             : 
    5132             :     // 2. Case: rSourceLine is not a follow flow line.
    5133             :     // In this case we have to return the maximum of the heights
    5134             :     // of the first lines in rSourceLine.
    5135           7 :     bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
    5136           7 :     SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
    5137             : 
    5138          28 :     while ( pCurrSourceCell )
    5139             :     {
    5140             :         // NEW TABLES
    5141             :         // Skip cells which are not responsible for the height of
    5142             :         // the follow flow line:
    5143          14 :         if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
    5144             :         {
    5145           0 :             pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
    5146           0 :             continue;
    5147             :         }
    5148             : 
    5149          14 :         const SwFrm *pTmp = pCurrSourceCell->Lower();
    5150          14 :         if ( pTmp )
    5151             :         {
    5152          14 :             SwTwips nTmpHeight = USHRT_MAX;
    5153             :             // #i32456# Consider lower row frames
    5154          14 :             if ( pTmp->IsRowFrm() )
    5155             :             {
    5156           0 :                 const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
    5157           0 :                 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
    5158             :             }
    5159          14 :             if ( pTmp->IsTabFrm() )
    5160             :             {
    5161           0 :                 nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
    5162             :             }
    5163          14 :             else if ( pTmp->IsTxtFrm() )
    5164             :             {
    5165          14 :                 SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
    5166          14 :                 pTxtFrm->GetFormatted();
    5167          14 :                 nTmpHeight = pTxtFrm->FirstLineHeight();
    5168             :             }
    5169             : 
    5170          14 :             if ( USHRT_MAX != nTmpHeight )
    5171             :             {
    5172          14 :                 const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
    5173          14 :                 if ( pPrevCell )
    5174             :                 {
    5175             :                     // If we are in a split row, there may be some space
    5176             :                     // left in the cell frame of the master row.
    5177             :                     // We look for the minimum of all first line heights;
    5178           0 :                     SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
    5179           0 :                     const SwFrm* pFrm = pPrevCell->Lower();
    5180           0 :                     const SwFrm* pLast = pFrm;
    5181           0 :                     while ( pFrm )
    5182             :                     {
    5183           0 :                         nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
    5184           0 :                         pLast = pFrm;
    5185           0 :                         pFrm = pFrm->GetNext();
    5186             :                     }
    5187             : 
    5188             :                     // #i26831#, #i26520#
    5189             :                     // The additional lower space of the current last.
    5190             :                     // #115759# - do *not* consider the
    5191             :                     // additional lower space for 'master' text frames
    5192           0 :                     if ( pLast && pLast->IsFlowFrm() &&
    5193           0 :                          ( !pLast->IsTxtFrm() ||
    5194           0 :                            !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
    5195             :                     {
    5196           0 :                         nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
    5197             :                     }
    5198             :                     // Don't forget the upper space and lower space,
    5199             :                     // #115759# - do *not* consider the upper
    5200             :                     // and the lower space for follow text frames.
    5201           0 :                     if ( pTmp->IsFlowFrm() &&
    5202           0 :                          ( !pTmp->IsTxtFrm() ||
    5203           0 :                            !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
    5204             :                     {
    5205           0 :                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
    5206           0 :                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
    5207             :                     }
    5208             :                     // #115759# - consider additional lower
    5209             :                     // space of <pTmp>, if contains only one line.
    5210             :                     // In this case it would be the new last text frame, which
    5211             :                     // would have no follow and thus would add this space.
    5212           0 :                     if ( pTmp->IsTxtFrm() &&
    5213             :                          const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
    5214           0 :                                             ->GetLineCount( COMPLETE_STRING ) == 1 )
    5215             :                     {
    5216             :                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
    5217           0 :                                         ->CalcAddLowerSpaceAsLastInTableCell();
    5218             :                     }
    5219           0 :                     if ( nReal > 0 )
    5220           0 :                         nTmpHeight -= nReal;
    5221             :                 }
    5222             :                 else
    5223             :                 {
    5224             :                     // pFirstRow is not a FollowFlowRow. In this case,
    5225             :                     // we look for the maximum of all first line heights:
    5226          14 :                     SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
    5227          14 :                     const SwBorderAttrs &rAttrs = *aAccess.Get();
    5228          14 :                     nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
    5229             :                     // #i26250#
    5230             :                     // Don't forget the upper space and lower space,
    5231          14 :                     if ( pTmp->IsFlowFrm() )
    5232             :                     {
    5233          14 :                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
    5234          14 :                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
    5235          14 :                     }
    5236             :                 }
    5237             :             }
    5238             : 
    5239          14 :             if ( bIsInFollowFlowLine )
    5240             :             {
    5241             :                 // minimum
    5242           0 :                 if ( nTmpHeight < nHeight )
    5243           0 :                     nHeight = nTmpHeight;
    5244             :             }
    5245             :             else
    5246             :             {
    5247             :                 // maximum
    5248          14 :                 if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
    5249          10 :                     nHeight = nTmpHeight;
    5250             :             }
    5251             :         }
    5252             : 
    5253          14 :         pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
    5254             :     }
    5255             : 
    5256           7 :     return ( LONG_MAX == nHeight ) ? 0 : nHeight;
    5257             : }
    5258             : 
    5259             : /// Function to calculate height of first text row
    5260         723 : SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
    5261             : {
    5262         723 :     SWRECTFN( this )
    5263             : 
    5264         723 :     const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
    5265             : 
    5266         723 :     if ( bDontSplit )
    5267             :     {
    5268             :         // Table is not allowed to split: Take the whole height, that's all
    5269           0 :         return (Frm().*fnRect->fnGetHeight)();
    5270             :     }
    5271             : 
    5272         723 :     SwTwips nTmpHeight = 0;
    5273             : 
    5274         723 :     SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
    5275             :     OSL_ENSURE( !IsFollow() || pFirstRow, "FollowTable without Lower" );
    5276             : 
    5277             :     // NEW TABLES
    5278         723 :     if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
    5279           0 :         pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
    5280             : 
    5281             :     // Calculate the height of the headlines:
    5282         723 :     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
    5283         723 :     SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
    5284             : 
    5285             :     // Calculate the height of the keeping lines
    5286             :     // (headlines + following keeping lines):
    5287         723 :     SwTwips nKeepHeight = nRepeatHeight;
    5288         723 :     if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
    5289             :     {
    5290         672 :         sal_uInt16 nKeepRows = nRepeat;
    5291             : 
    5292             :         // Check how many rows want to keep together
    5293        1344 :         while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
    5294             :         {
    5295           0 :             ++nKeepRows;
    5296           0 :             pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
    5297             :         }
    5298             : 
    5299         672 :         if ( nKeepRows > nRepeat )
    5300           0 :             nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
    5301             :     }
    5302             : 
    5303             :     // For master tables, the height of the headlines + the height of the
    5304             :     // keeping lines (if any) has to be considered. For follow tables, we
    5305             :     // only consider the height of the keeping rows without the repeated lines:
    5306         723 :     if ( !IsFollow() )
    5307             :     {
    5308           5 :         nTmpHeight = nKeepHeight;
    5309             :     }
    5310             :     else
    5311             :     {
    5312         718 :         nTmpHeight = nKeepHeight - nRepeatHeight;
    5313             :     }
    5314             : 
    5315             :     // pFirstRow row is the first non-heading row.
    5316             :     // nTmpHeight is the height of the heading row if we are a follow.
    5317         723 :     if ( pFirstRow )
    5318             :     {
    5319         723 :         const bool bSplittable = pFirstRow->IsRowSplitAllowed();
    5320         723 :         const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
    5321             : 
    5322         723 :         if ( !bSplittable )
    5323             :         {
    5324             :             // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
    5325             :             // actually is determined by a lower cell with rowspan = -1. In this case we should not
    5326             :             // just return the height of the first line. Basically we need to get the height of the
    5327             :             // line as it would be on the last page. Since this is quite complicated to calculate,
    5328             :             // we olny calculate the height of the first line.
    5329           3 :             if ( pFirstRow->GetPrev() &&
    5330           0 :                  static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
    5331             :             {
    5332             :                 // Calculate maximum height of all cells with rowspan = 1:
    5333           0 :                 SwTwips nMaxHeight = 0;
    5334           0 :                 const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
    5335           0 :                 while ( pLower2 )
    5336             :                 {
    5337           0 :                     if ( 1 == pLower2->GetTabBox()->getRowSpan() )
    5338             :                     {
    5339           0 :                         const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True );
    5340           0 :                         nMaxHeight = std::max( nCellHeight, nMaxHeight );
    5341             :                     }
    5342           0 :                     pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
    5343             :                 }
    5344           0 :                 nTmpHeight += nMaxHeight;
    5345             :             }
    5346             :             else
    5347             :             {
    5348           3 :                 nTmpHeight += nFirstLineHeight;
    5349             :             }
    5350             :         }
    5351             : 
    5352             :         // #118411#
    5353             :         // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
    5354             :         // a formatting of the row frame (via the GetFormatted()). We don't
    5355             :         // want this formatting if the row does not have a height.
    5356         720 :         else if ( 0 != nFirstLineHeight )
    5357             :         {
    5358           7 :             const bool bOldJoinLock = IsJoinLocked();
    5359           7 :             ((SwTabFrm*)this)->LockJoin();
    5360           7 :             const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
    5361             : 
    5362             :             // Consider minimum row height:
    5363           7 :             const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
    5364           7 :             const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
    5365           7 :                                           rSz.GetHeight() : 0;
    5366             : 
    5367           7 :             nTmpHeight += std::max( nHeightOfFirstContentLine, nMinRowHeight );
    5368             : 
    5369           7 :             if ( !bOldJoinLock )
    5370           7 :                 ((SwTabFrm*)this)->UnlockJoin();
    5371             :         }
    5372             :     }
    5373             : 
    5374         723 :     return nTmpHeight;
    5375             : }
    5376             : 
    5377             : // Some more functions for covered/covering cells. This way inclusion of
    5378             : // SwCellFrm can be avoided
    5379             : 
    5380       55053 : bool SwFrm::IsLeaveUpperAllowed() const
    5381             : {
    5382       55053 :     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
    5383       55053 :     return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
    5384             : }
    5385             : 
    5386       62043 : bool SwFrm::IsCoveredCell() const
    5387             : {
    5388       62043 :     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
    5389       62043 :     return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
    5390             : }
    5391             : 
    5392        4996 : bool SwFrm::IsInCoveredCell() const
    5393             : {
    5394        4996 :     bool bRet = false;
    5395             : 
    5396        4996 :     const SwFrm* pThis = this;
    5397       19641 :     while ( pThis && !pThis->IsCellFrm() )
    5398        9649 :         pThis = pThis->GetUpper();
    5399             : 
    5400        4996 :     if ( pThis )
    5401         304 :         bRet = pThis->IsCoveredCell();
    5402             : 
    5403        4996 :     return bRet;
    5404             : }
    5405             : 
    5406             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10