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



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


#include <hintids.hxx>
#include <hints.hxx>
#include <tools/pstm.hxx>
#include <vcl/outdev.hxx>
#include <svl/itemiter.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/keepitem.hxx>
#include <editeng/brkitem.hxx>
#include <fmtornt.hxx>
#include <pagefrm.hxx>
#include <section.hxx>
#include <rootfrm.hxx>
#include <cntfrm.hxx>
#include <dcontact.hxx>
#include <anchoreddrawobject.hxx>
#include <fmtanchr.hxx>
#include <viewsh.hxx>
#include <viewimp.hxx>
#include "viewopt.hxx"
#include <doc.hxx>
#include <fesh.hxx>
#include <docsh.hxx>
#include <flyfrm.hxx>
#include <frmtool.hxx>
#include <ftninfo.hxx>
#include <dflyobj.hxx>
#include <fmtclbl.hxx>
#include <fmtfordr.hxx>
#include <fmtfsize.hxx>
#include <fmtpdsc.hxx>
#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <fmtsrnd.hxx>
#include <ftnfrm.hxx>
#include <tabfrm.hxx>
#include <htmltbl.hxx>
#include <flyfrms.hxx>
#include <sectfrm.hxx>
#include <fmtclds.hxx>
#include <txtfrm.hxx>
#include <ndtxt.hxx>
#include <bodyfrm.hxx>
#include <cellfrm.hxx>
#include <dbg_lay.hxx>
#include <editeng/frmdiritem.hxx>
// OD 2004-05-24 #i28701#
#include <sortedobjs.hxx>


using namespace ::com::sun::star;


/*************************************************************************
|*
|*	SwFrm::SwFrm()
|*
|*	Ersterstellung		AK 12-Feb-1991
|*	Letzte Aenderung	MA 05. Apr. 94
|*
|*************************************************************************/

SwFrm::SwFrm( SwModify *pMod, SwFrm* pSib ) :
	SwClient( pMod ),
	//Solution:Add a member to identify if the acc table should dispose
	bIfAccTableShouldDisposing( sal_False ),
    // --> OD 2006-05-10 #i65250#
    mnFrmId( SwFrm::mnLastFrmId++ ),
    // <--
    mpRoot( pSib ? pSib->getRootFrm() : 0 ),
    pUpper( 0 ),
    pNext( 0 ),
    pPrev( 0 ),
    pDrawObjs( 0 )
    , bInfBody( sal_False )
    , bInfTab ( sal_False )
    , bInfFly ( sal_False )
    , bInfFtn ( sal_False )
    , bInfSct ( sal_False )
{
#ifdef DBG_UTIL
    bFlag01 = bFlag02 = bFlag03 = bFlag04 = bFlag05 = 0;
#endif

	ASSERT( pMod, "Kein Frameformat uebergeben." );
    bInvalidR2L = bInvalidVert = 1;
    //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    bDerivedR2L = bDerivedVert = bRightToLeft = bVertical = bReverse = bVertLR = 0;

    bValidPos = bValidPrtArea = bValidSize = bValidLineNum = bRetouche =
    bFixSize = bColLocked = sal_False;
    bCompletePaint = bInfInvalid = sal_True;
}

bool SwFrm::KnowsFormat( const SwFmt& rFmt ) const
{ 
    return GetRegisteredIn() == &rFmt; 
}

void SwFrm::RegisterToFormat( SwFmt& rFmt )
{
    rFmt.Add( this );
}

void SwFrm::CheckDir( sal_uInt16 nDir, sal_Bool bVert, sal_Bool bOnlyBiDi, sal_Bool bBrowse )
{
    if( FRMDIR_ENVIRONMENT == nDir || ( bVert && bOnlyBiDi ) )
    {
        bDerivedVert = 1;
        if( FRMDIR_ENVIRONMENT == nDir )
            bDerivedR2L = 1;
        SetDirFlags( bVert );
    }
    else if( bVert )
    {
        bInvalidVert = 0;
        if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir
            || bBrowse )
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        {
            bVertical = 0;
            bVertLR = 0;
		}
        else
       	{
            bVertical = 1;
            if(FRMDIR_VERT_TOP_RIGHT == nDir)
				bVertLR = 0;
	       	else if(FRMDIR_VERT_TOP_LEFT==nDir)
		       		bVertLR = 1;
		}
    }
    else
    {
        bInvalidR2L = 0;
        if( FRMDIR_HORI_RIGHT_TOP == nDir )
            bRightToLeft = 1;
        else
            bRightToLeft = 0;
    }
}

void SwFrm::CheckDirection( sal_Bool bVert )
{
    if( bVert )
    {
        if( !IsHeaderFrm() && !IsFooterFrm() )
        {
            bDerivedVert = 1;
            SetDirFlags( bVert );
        }
    }
    else
    {
        bDerivedR2L = 1;
        SetDirFlags( bVert );
    }
}

void SwSectionFrm::CheckDirection( sal_Bool bVert )
{
    const SwFrmFmt* pFmt = GetFmt();
    if( pFmt )
    {
        const ViewShell *pSh = getRootFrm()->GetCurrShell();
        const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
                    bVert, sal_True, bBrowseMode );
    }
    else
        SwFrm::CheckDirection( bVert );
}

void SwFlyFrm::CheckDirection( sal_Bool bVert )
{
    const SwFrmFmt* pFmt = GetFmt();
    if( pFmt )
    {
        const ViewShell *pSh = getRootFrm()->GetCurrShell();
        const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
                    bVert, sal_False, bBrowseMode );
    }
    else
        SwFrm::CheckDirection( bVert );
}

void SwTabFrm::CheckDirection( sal_Bool bVert )
{
    const SwFrmFmt* pFmt = GetFmt();
    if( pFmt )
    {
        const ViewShell *pSh = getRootFrm()->GetCurrShell();
        const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
                    bVert, sal_True, bBrowseMode );
    }
    else
        SwFrm::CheckDirection( bVert );
}

void SwCellFrm::CheckDirection( sal_Bool bVert )
{
    const SwFrmFmt* pFmt = GetFmt();
    const SfxPoolItem* pItem;
    // --> FME 2006-03-30 #b6402837# Check if the item is set, before actually
    // using it. Otherwise the dynamic pool default is used, which may be set
    // to LTR in case of OOo 1.0 documents.
    // <--
    if( pFmt && SFX_ITEM_SET == pFmt->GetItemState( RES_FRAMEDIR, sal_True, &pItem ) )
    {
        const SvxFrameDirectionItem* pFrmDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
        const ViewShell *pSh = getRootFrm()->GetCurrShell();
        const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir( pFrmDirItem->GetValue(), bVert, sal_False, bBrowseMode );
    }
    else
        SwFrm::CheckDirection( bVert );
}

void SwTxtFrm::CheckDirection( sal_Bool bVert )
{
    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
    CheckDir( GetTxtNode()->GetSwAttrSet().GetFrmDir().GetValue(), bVert,
              sal_True, bBrowseMode );
}

/*************************************************************************/
void SwFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
{
	sal_uInt8 nInvFlags = 0;

	if( pNew && RES_ATTRSET_CHG == pNew->Which() )
	{
		SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
		SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
		while( sal_True )
		{
			_UpdateAttrFrm( (SfxPoolItem*)aOIter.GetCurItem(),
						 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags );
			if( aNIter.IsAtEnd() )
				break;
			aNIter.NextItem();
			aOIter.NextItem();
		}
	}
	else
		_UpdateAttrFrm( pOld, pNew, nInvFlags );

	if ( nInvFlags != 0 )
	{
		SwPageFrm *pPage = FindPageFrm();
		InvalidatePage( pPage );
		if ( nInvFlags & 0x01 )
		{
			_InvalidatePrt();
			if( !GetPrev() && IsTabFrm() && IsInSct() )
				FindSctFrm()->_InvalidatePrt();
		}
		if ( nInvFlags & 0x02 )
			_InvalidateSize();
		if ( nInvFlags & 0x04 )
			_InvalidatePos();
		if ( nInvFlags & 0x08 )
			SetCompletePaint();
		SwFrm *pNxt;
		if ( nInvFlags & 0x30 && 0 != (pNxt = GetNext()) )
		{
			pNxt->InvalidatePage( pPage );
			if ( nInvFlags & 0x10 )
				pNxt->_InvalidatePos();
			if ( nInvFlags & 0x20 )
				pNxt->SetCompletePaint();
		}
	}
}

void SwFrm::_UpdateAttrFrm( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
						 sal_uInt8 &rInvFlags )
{
	sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
	switch( nWhich )
	{
		case RES_BOX:
		case RES_SHADOW:
			Prepare( PREP_FIXSIZE_CHG );
			// hier kein break !
		case RES_LR_SPACE:
		case RES_UL_SPACE:
			rInvFlags |= 0x0B;
			break;

        case RES_HEADER_FOOTER_EAT_SPACING:
            rInvFlags |= 0x03;
            break;

		case RES_BACKGROUND:
			rInvFlags |= 0x28;
			break;

		case RES_KEEP:
			rInvFlags |= 0x04;
			break;

		case RES_FRM_SIZE:
			ReinitializeFrmSizeAttrFlags();
			rInvFlags |= 0x13;
			break;

		case RES_FMT_CHG:
			rInvFlags |= 0x0F;
			break;

        case RES_ROW_SPLIT:
        {
            if ( IsRowFrm() )
            {
                sal_Bool bInFollowFlowRow = 0 != IsInFollowFlowRow();
                if ( bInFollowFlowRow || 0 != IsInSplitTableRow() )
                {
                    SwTabFrm* pTab = FindTabFrm();
                    if ( bInFollowFlowRow )
                        pTab = pTab->FindMaster();
                    pTab->SetRemoveFollowFlowLinePending( sal_True );
                }
            }
            break;
        }
        case RES_COL:
			ASSERT( sal_False, "Spalten fuer neuen FrmTyp?" );
			break;

		default:
			/* do Nothing */;
	}
}

/*************************************************************************
|*
|*	  SwFrm::Prepare()
|*	  Ersterstellung	MA 13. Apr. 93
|*	  Letzte Aenderung	MA 26. Jun. 96
|*
|*************************************************************************/
void SwFrm::Prepare( const PrepareHint, const void *, sal_Bool )
{
	/* Do nothing */
}

/*************************************************************************
|*
|*	  SwFrm::InvalidatePage()
|*	  Beschreibung:		Invalidiert die Seite, in der der Frm gerade steht.
|*		Je nachdem ob es ein Layout, Cntnt oder FlyFrm ist wird die Seite
|*		entsprechend Invalidiert.
|*	  Ersterstellung	MA 22. Jul. 92
|*	  Letzte Aenderung	MA 14. Oct. 94
|*
|*************************************************************************/
void SwFrm::InvalidatePage( const SwPageFrm *pPage ) const
{
    if ( !pPage )
    {
		pPage = FindPageFrm();
        // --> OD 2004-07-02 #i28701# - for at-character and as-character
        // anchored Writer fly frames additionally invalidate also page frame
        // its 'anchor character' is on.
        if ( pPage && pPage->GetUpper() && IsFlyFrm() )
        {
            const SwFlyFrm* pFlyFrm = static_cast<const SwFlyFrm*>(this);
            if ( pFlyFrm->IsAutoPos() || pFlyFrm->IsFlyInCntFrm() )
            {
                // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
                // is replaced by method <FindPageFrmOfAnchor()>. It's return value
                // have to be checked.
                SwPageFrm* pPageFrmOfAnchor =
                        const_cast<SwFlyFrm*>(pFlyFrm)->FindPageFrmOfAnchor();
                if ( pPageFrmOfAnchor && pPageFrmOfAnchor != pPage )
                // <--
                {
                    InvalidatePage( pPageFrmOfAnchor );
                }
            }
        }
        // <--
    }

	if ( pPage && pPage->GetUpper() )
	{
		if ( pPage->GetFmt()->GetDoc()->IsInDtor() )
			return;

		SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
		const SwFlyFrm *pFly = FindFlyFrm();
		if ( IsCntntFrm() )
		{
			if ( pRoot->IsTurboAllowed() )
			{
				// JP 21.09.95: wenn sich der ContentFrame 2 mal eintragen
				//				will, kann es doch eine TurboAction bleiben.
				//	ODER????
				if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
					pRoot->SetTurbo( (const SwCntntFrm*)this );
				else
				{
					pRoot->DisallowTurbo();
					//Die Seite des Turbo koennte eine andere als die meinige
					//sein, deshalb muss sie invalidiert werden.
					const SwFrm *pTmp = pRoot->GetTurbo();
					pRoot->ResetTurbo();
					pTmp->InvalidatePage();
				}
			}
			if ( !pRoot->GetTurbo() )
			{
				if ( pFly )
				{	if( !pFly->IsLocked() )
					{
						if ( pFly->IsFlyInCntFrm() )
						{	pPage->InvalidateFlyInCnt();
							((SwFlyInCntFrm*)pFly)->InvalidateCntnt();
                            pFly->GetAnchorFrm()->InvalidatePage();
						}
						else
							pPage->InvalidateFlyCntnt();
					}
				}
				else
					pPage->InvalidateCntnt();
			}
		}
		else
		{
			pRoot->DisallowTurbo();
			if ( pFly )
            {
                if ( !pFly->IsLocked() )
				{
					if ( pFly->IsFlyInCntFrm() )
                    {
                        pPage->InvalidateFlyInCnt();
						((SwFlyInCntFrm*)pFly)->InvalidateLayout();
                        pFly->GetAnchorFrm()->InvalidatePage();
					}
					else
						pPage->InvalidateFlyLayout();
				}
			}
			else
				pPage->InvalidateLayout();

			if ( pRoot->GetTurbo() )
			{	const SwFrm *pTmp = pRoot->GetTurbo();
				pRoot->ResetTurbo();
				pTmp->InvalidatePage();
			}
		}
		pRoot->SetIdleFlags();

		const SwTxtFrm *pTxtFrm = dynamic_cast< const SwTxtFrm * >(this);
		if (pTxtFrm)
		{
			const SwTxtNode *pTxtNode = pTxtFrm->GetTxtNode();
			if (pTxtNode && pTxtNode->IsGrammarCheckDirty())
				pRoot->SetNeedGrammarCheck( sal_True );
		}
	}
}

/*************************************************************************
|*
|*	SwFrm::ChgSize()
|*
|*	Ersterstellung		AK 15-Feb-1991
|*	Letzte Aenderung	MA 18. Nov. 98
|*
|*************************************************************************/
Size SwFrm::ChgSize( const Size& aNewSize )
{
    bFixSize = sal_True;
	const Size aOldSize( Frm().SSize() );
	if ( aNewSize == aOldSize )
		return aOldSize;

	if ( GetUpper() )
	{
        SWRECTFN2( this )
        SwRect aNew( Point(0,0), aNewSize );
        (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
        long nNew = (aNew.*fnRect->fnGetHeight)();
        long nDiff = nNew - (aFrm.*fnRect->fnGetHeight)();
		if( nDiff )
		{
            if ( GetUpper()->IsFtnBossFrm() && HasFixSize() &&
				 NA_GROW_SHRINK !=
				 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this ) )
			{
                (aFrm.*fnRect->fnSetHeight)( nNew );
                SwTwips nReal = ((SwLayoutFrm*)this)->AdjustNeighbourhood(nDiff);
				if ( nReal != nDiff )
                    (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
			}
			else
			{
                // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
                // NOTE: neighbour frames are cell and column frames.
                if ( !bNeighb )
                {
                    if ( nDiff > 0 )
                        Grow( nDiff );
                    else
                        Shrink( -nDiff );

                    if ( GetUpper() && (aFrm.*fnRect->fnGetHeight)() != nNew )
                        GetUpper()->_InvalidateSize();
                }

                // Auch wenn das Grow/Shrink noch nicht die gewuenschte Breite eingestellt hat,
                // wie z.B. beim Aufruf durch ChgColumns, um die Spaltenbreiten einzustellen,
                // wird die Breite jetzt gesetzt.
                (aFrm.*fnRect->fnSetHeight)( nNew );
			}
		}
	}
	else
        aFrm.SSize( aNewSize );

	if ( Frm().SSize() != aOldSize )
	{
		SwPageFrm *pPage = FindPageFrm();
		if ( GetNext() )
		{
			GetNext()->_InvalidatePos();
			GetNext()->InvalidatePage( pPage );
		}
        if( IsLayoutFrm() )
        {
            if( IsRightToLeft() )
                _InvalidatePos();
            if( ((SwLayoutFrm*)this)->Lower() )
                ((SwLayoutFrm*)this)->Lower()->_InvalidateSize();
        }
		_InvalidatePrt();
		_InvalidateSize();
		InvalidatePage( pPage );
	}

    return aFrm.SSize();
}

/*************************************************************************
|*
|*	SwFrm::InsertBefore()
|*
|*	Beschreibung		SwFrm wird in eine bestehende Struktur eingefuegt
|* 						Eingefuegt wird unterhalb des Parent und entweder
|* 						vor pBehind oder am Ende der Kette wenn pBehind
|* 						leer ist.
|*	Letzte Aenderung	MA 06. Aug. 99
|*
|*************************************************************************/
void SwFrm::InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind )
{
	ASSERT( pParent, "Kein Parent fuer Insert." );
	ASSERT( (!pBehind || (pBehind && pParent == pBehind->GetUpper())),
			"Framebaum inkonsistent." );

	pUpper = pParent;
	pNext = pBehind;
	if( pBehind )
	{	//Einfuegen vor pBehind.
		if( 0 != (pPrev = pBehind->pPrev) )
			pPrev->pNext = this;
		else
			pUpper->pLower = this;
		pBehind->pPrev = this;
	}
	else
	{	//Einfuegen am Ende, oder als ersten Node im Unterbaum
		pPrev = pUpper->Lower();
		if ( pPrev )
		{
			while( pPrev->pNext )
				pPrev = pPrev->pNext;
			pPrev->pNext = this;
		}
		else
			pUpper->pLower = this;
	}
}

/*************************************************************************
|*
|*	SwFrm::InsertBehind()
|*
|*	Beschreibung		SwFrm wird in eine bestehende Struktur eingefuegt
|* 						Eingefuegt wird unterhalb des Parent und entweder
|* 						hinter pBefore oder am Anfang der Kette wenn pBefore
|* 						leer ist.
|*	Letzte Aenderung	MA 06. Aug. 99
|*
|*************************************************************************/
void SwFrm::InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore )
{
	ASSERT( pParent, "Kein Parent fuer Insert." );
	ASSERT( (!pBefore || (pBefore && pParent == pBefore->GetUpper())),
			"Framebaum inkonsistent." );

	pUpper = pParent;
	pPrev = pBefore;
	if ( pBefore )
	{
		//Einfuegen hinter pBefore
		if ( 0 != (pNext = pBefore->pNext) )
			pNext->pPrev = this;
		pBefore->pNext = this;
	}
	else
	{
		//Einfuegen am Anfang der Kette
		pNext = pParent->Lower();
		if ( pParent->Lower() )
			pParent->Lower()->pPrev = this;
		pParent->pLower = this;
	}
}

/*************************************************************************
|*
|*	SwFrm::InsertGroup()
|*
|*	Beschreibung		Eine Kette von SwFrms wird in eine bestehende Struktur
|* 						eingefuegt
|*	Letzte Aenderung	AMA 9. Dec. 97
|*
|*  Bisher wird dies genutzt, um einen SectionFrame, der ggf. schon Geschwister
|*	mit sich bringt, in eine bestehende Struktur einzufuegen.
|*
|*  Wenn man den dritten Parameter als NULL uebergibt, entspricht
|*  diese Methode dem SwFrm::InsertBefore(..), nur eben mit Geschwistern.
|*
|*  Wenn man einen dritten Parameter uebergibt, passiert folgendes:
|*  this wird pNext von pParent,
|*  pSct wird pNext vom Letzten der this-Kette,
|*  pBehind wird vom pParent an den pSct umgehaengt.
|*	Dies dient dazu: ein SectionFrm (this) wird nicht als
|*	Kind an einen anderen SectionFrm (pParent) gehaengt, sondern pParent
|*	wird in zwei Geschwister aufgespalten (pParent+pSct) und this dazwischen
|*  eingebaut.
|*
|*************************************************************************/
void SwFrm::InsertGroupBefore( SwFrm* pParent, SwFrm* pBehind, SwFrm* pSct )
{
	ASSERT( pParent, "Kein Parent fuer Insert." );
	ASSERT( (!pBehind || (pBehind && ( pParent == pBehind->GetUpper())
			|| ( pParent->IsSctFrm() && pBehind->GetUpper()->IsColBodyFrm() ) ) ),
			"Framebaum inkonsistent." );
	if( pSct )
	{
		pUpper = pParent->GetUpper();
		SwFrm *pLast = this;
		while( pLast->GetNext() )
		{
			pLast = pLast->GetNext();
			pLast->pUpper = GetUpper();
		}
		if( pBehind )
		{
			pLast->pNext = pSct;
			pSct->pPrev = pLast;
			pSct->pNext = pParent->GetNext();
		}
		else
		{
			pLast->pNext = pParent->GetNext();
			if( pLast->GetNext() )
				pLast->GetNext()->pPrev = pLast;
		}
		pParent->pNext = this;
		pPrev = pParent;
		if( pSct->GetNext() )
			pSct->GetNext()->pPrev = pSct;
		while( pLast->GetNext() )
		{
			pLast = pLast->GetNext();
			pLast->pUpper = GetUpper();
		}
		if( pBehind )
		{	//Einfuegen vor pBehind.
			if( pBehind->GetPrev() )
				pBehind->GetPrev()->pNext = NULL;
			else
				pBehind->GetUpper()->pLower = NULL;
			pBehind->pPrev = NULL;
			SwLayoutFrm* pTmp = (SwLayoutFrm*)pSct;
			if( pTmp->Lower() )
			{
				ASSERT( pTmp->Lower()->IsColumnFrm(), "InsertGrp: Used SectionFrm" );
				pTmp = (SwLayoutFrm*)((SwLayoutFrm*)pTmp->Lower())->Lower();
				ASSERT( pTmp, "InsertGrp: Missing ColBody" );
			}
			pBehind->pUpper = pTmp;
			pBehind->GetUpper()->pLower = pBehind;
			pLast = pBehind->GetNext();
			while ( pLast )
			{
				pLast->pUpper = pBehind->GetUpper();
				pLast = pLast->GetNext();
			};
		}
		else
		{
			ASSERT( pSct->IsSctFrm(), "InsertGroup: For SectionFrms only" );
			delete ((SwSectionFrm*)pSct);
		}
	}
	else
	{
		pUpper = (SwLayoutFrm*)pParent;
		SwFrm *pLast = this;
		while( pLast->GetNext() )
		{
			pLast = pLast->GetNext();
			pLast->pUpper = GetUpper();
		}
		pLast->pNext = pBehind;
		if( pBehind )
		{	//Einfuegen vor pBehind.
			if( 0 != (pPrev = pBehind->pPrev) )
				pPrev->pNext = this;
			else
				pUpper->pLower = this;
			pBehind->pPrev = pLast;
		}
		else
		{	//Einfuegen am Ende, oder des ersten Nodes im Unterbaum
			pPrev = pUpper->Lower();
			if ( pPrev )
			{
				while( pPrev->pNext )
					pPrev = pPrev->pNext;
				pPrev->pNext = this;
			}
			else
				pUpper->pLower = this;
		}
	}
}

/*************************************************************************
|*
|*	SwFrm::Remove()
|*
|*	Ersterstellung		AK 01-Mar-1991
|*	Letzte Aenderung	MA 07. Dec. 95
|*
|*************************************************************************/
void SwFrm::Remove()
{
	ASSERT( pUpper, "Removen ohne Upper?" );

	if( pPrev )
		// einer aus der Mitte wird removed
		pPrev->pNext = pNext;
	else
	{	// der erste in einer Folge wird removed
		ASSERT( pUpper->pLower == this, "Layout inkonsistent." );
		pUpper->pLower = pNext;
	}
	if( pNext )
		pNext->pPrev = pPrev;

	// Verbindung kappen.
	pNext  = pPrev  = 0;
	pUpper = 0;
}
/*************************************************************************
|*
|*	SwCntntFrm::Paste()
|*
|*	Ersterstellung		MA 23. Feb. 94
|*	Letzte Aenderung	MA 09. Sep. 98
|*
|*************************************************************************/
void SwCntntFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
{
	ASSERT( pParent, "Kein Parent fuer Paste." );
	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
	ASSERT( pParent != this, "Bin selbst der Parent." );
	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
	ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
			"Bin noch irgendwo angemeldet." );
    ASSERT( !pSibling || pSibling->IsFlowFrm(),
            "<SwCntntFrm::Paste(..)> - sibling not of expected type." )

	//In den Baum einhaengen.
	InsertBefore( (SwLayoutFrm*)pParent, pSibling );

	SwPageFrm *pPage = FindPageFrm();
	_InvalidateAll();
	InvalidatePage( pPage );

	if( pPage )
	{
		pPage->InvalidateSpelling();
        pPage->InvalidateSmartTags();   // SMARTTAGS
        pPage->InvalidateAutoCompleteWords();
        pPage->InvalidateWordCount();
	}

	if ( GetNext() )
	{
		SwFrm* pNxt = GetNext();
		pNxt->_InvalidatePrt();
		pNxt->_InvalidatePos();
		pNxt->InvalidatePage( pPage );
		if( pNxt->IsSctFrm() )
			pNxt = ((SwSectionFrm*)pNxt)->ContainsCntnt();
		if( pNxt && pNxt->IsTxtFrm() && pNxt->IsInFtn() )
			pNxt->Prepare( PREP_FTN, 0, sal_False );
	}

	if ( Frm().Height() )
        pParent->Grow( Frm().Height() );

	if ( Frm().Width() != pParent->Prt().Width() )
		Prepare( PREP_FIXSIZE_CHG );

	if ( GetPrev() )
	{
		if ( IsFollow() )
			//Ich bin jetzt direkter Nachfolger meines Masters geworden
			((SwCntntFrm*)GetPrev())->Prepare( PREP_FOLLOW_FOLLOWS );
		else
		{
			if ( GetPrev()->Frm().Height() !=
				 GetPrev()->Prt().Height() + GetPrev()->Prt().Top() )
				//Umrandung zu beruecksichtigen?
				GetPrev()->_InvalidatePrt();
            // OD 18.02.2003 #104989# - force complete paint of previous frame,
            // if frame is inserted at the end of a section frame, in order to
            // get subsidiary lines repainted for the section.
            if ( pParent->IsSctFrm() && !GetNext() )
            {
                // force complete paint of previous frame, if new inserted frame
                // in the section is the last one.
                GetPrev()->SetCompletePaint();
            }
			GetPrev()->InvalidatePage( pPage );
		}
	}
	if ( IsInFtn() )
	{
		SwFrm* pFrm = GetIndPrev();
		if( pFrm && pFrm->IsSctFrm() )
			pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
		if( pFrm )
			pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
		if( !GetNext() )
		{
			pFrm = FindFtnFrm()->GetNext();
			if( pFrm && 0 != (pFrm=((SwLayoutFrm*)pFrm)->ContainsAny()) )
				pFrm->_InvalidatePrt();
		}
	}

	_InvalidateLineNum();
	SwFrm *pNxt = FindNextCnt();
	if ( pNxt  )
	{
		while ( pNxt && pNxt->IsInTab() )
		{
			if( 0 != (pNxt = pNxt->FindTabFrm()) )
				pNxt = pNxt->FindNextCnt();
		}
		if ( pNxt )
		{
			pNxt->_InvalidateLineNum();
			if ( pNxt != GetNext() )
				pNxt->InvalidatePage();
		}
	}
}

/*************************************************************************
|*
|*	SwCntntFrm::Cut()
|*
|*	Ersterstellung		AK 14-Feb-1991
|*	Letzte Aenderung	MA 09. Sep. 98
|*
|*************************************************************************/
void SwCntntFrm::Cut()
{
	ASSERT( GetUpper(), "Cut ohne Upper()." );

	SwPageFrm *pPage = FindPageFrm();
	InvalidatePage( pPage );
	SwFrm *pFrm = GetIndPrev();
	if( pFrm )
	{
		if( pFrm->IsSctFrm() )
			pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
		if ( pFrm && pFrm->IsCntntFrm() )
		{
			pFrm->_InvalidatePrt();
			if( IsInFtn() )
				pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
		}
        // --> OD 2004-07-15 #i26250# - invalidate printing area of previous
        // table frame.
        else if ( pFrm && pFrm->IsTabFrm() )
        {
            pFrm->InvalidatePrt();
        }
        // <--
	}

	SwFrm *pNxt = FindNextCnt();
	if ( pNxt )
	{
		while ( pNxt && pNxt->IsInTab() )
		{
			if( 0 != (pNxt = pNxt->FindTabFrm()) )
				pNxt = pNxt->FindNextCnt();
		}
		if ( pNxt )
		{
			pNxt->_InvalidateLineNum();
			if ( pNxt != GetNext() )
				pNxt->InvalidatePage();
		}
	}

	if( 0 != (pFrm = GetIndNext()) )
	{	//Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
		//berechnet, der ist jetzt, wo er der erste wird obsolet bzw. anders.
		pFrm->_InvalidatePrt();
		pFrm->_InvalidatePos();
		pFrm->InvalidatePage( pPage );
		if( pFrm->IsSctFrm() )
		{
			pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
			if( pFrm )
			{
				pFrm->_InvalidatePrt();
				pFrm->_InvalidatePos();
				pFrm->InvalidatePage( pPage );
			}
		}
		if( pFrm && IsInFtn() )
			pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
		if( IsInSct() && !GetPrev() )
		{
			SwSectionFrm* pSct = FindSctFrm();
			if( !pSct->IsFollow() )
			{
				pSct->_InvalidatePrt();
				pSct->InvalidatePage( pPage );
			}
		}
	}
	else
	{
		InvalidateNextPos();
		//Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
		if ( 0 != (pFrm = GetPrev()) )
		{	pFrm->SetRetouche();
			pFrm->Prepare( PREP_WIDOWS_ORPHANS );
			pFrm->_InvalidatePos();
			pFrm->InvalidatePage( pPage );
		}
		//Wenn ich der einzige CntntFrm in meinem Upper bin (war), so muss
		//er die Retouche uebernehmen.
		//Ausserdem kann eine Leerseite entstanden sein.
		else
		{	SwRootFrm *pRoot = getRootFrm();
			if ( pRoot )
			{
				pRoot->SetSuperfluous();
				GetUpper()->SetCompletePaint();
				GetUpper()->InvalidatePage( pPage );
			}
			if( IsInSct() )
			{
				SwSectionFrm* pSct = FindSctFrm();
				if( !pSct->IsFollow() )
				{
					pSct->_InvalidatePrt();
					pSct->InvalidatePage( pPage );
				}
			}
            // --> FME 2005-08-03 #i52253# The master table should take care
            // of removing the follow flow line.
            if ( IsInTab() )
            {
                SwTabFrm* pThisTab = FindTabFrm();
                SwTabFrm* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : 0;
                if ( pMasterTab )
                {
                    pMasterTab->_InvalidatePos();
                    pMasterTab->SetRemoveFollowFlowLinePending( sal_True );
                }
            }
            // <--
		}
	}
	//Erst removen, dann Upper Shrinken.
	SwLayoutFrm *pUp = GetUpper();
	Remove();
	if ( pUp )
	{
        SwSectionFrm *pSct = 0;
        if ( !pUp->Lower() &&
             ( ( pUp->IsFtnFrm() && !pUp->IsColLocked() ) ||
               ( pUp->IsInSct() &&
                 // -->  FME 2004-06-03 #i29438#
                 // We have to consider the case that the section may be "empty"
                 // except from a temporary empty table frame.
                 // This can happen due to the new cell split feature.
                 !pUp->IsCellFrm() &&
                 // <--
                 // --> OD 2006-01-04 #126020# - adjust check for empty section
                 // --> OD 2006-02-01 #130797# - correct fix #126020#
                 !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
                 !pSct->ContainsAny( true ) ) ) )
                 // <--
        {
			if ( pUp->GetUpper() )
			{
                // --> OD 2006-09-25 #b6448963#
                // prevent delete of <ColLocked> footnote frame
//                if( pUp->IsFtnFrm() )
                if ( pUp->IsFtnFrm() && !pUp->IsColLocked())
                // <--
				{
					if( pUp->GetNext() && !pUp->GetPrev() )
					{
						SwFrm* pTmp = ((SwLayoutFrm*)pUp->GetNext())->ContainsAny();
						if( pTmp )
							pTmp->_InvalidatePrt();
					}
					pUp->Cut();
					delete pUp;
				}
                else
                {
                    // --> OD 2006-09-25 #b6448963#
//                    if ( pSct->IsColLocked() || !pSct->IsInFtn() )
                    if ( pSct->IsColLocked() || !pSct->IsInFtn() ||
                         ( pUp->IsFtnFrm() && pUp->IsColLocked() ) )
                    // <--
					{
						pSct->DelEmpty( sal_False );
                        // Wenn ein gelockter Bereich nicht geloescht werden darf,
                        // so ist zumindest seine Groesse durch das Entfernen seines
                        // letzten Contents ungueltig geworden.
						pSct->_InvalidateSize();
					}
					else
					{
						pSct->DelEmpty( sal_True );
						delete pSct;
					}
				}
			}
		}
        else
        {
            SWRECTFN( this )
            long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
            if( nFrmHeight )
                pUp->Shrink( nFrmHeight );
        }
	}
}

/*************************************************************************
|*
|*	SwLayoutFrm::Paste()
|*
|*	Ersterstellung		MA 23. Feb. 94
|*	Letzte Aenderung	MA 23. Feb. 94
|*
|*************************************************************************/
void SwLayoutFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
{
	ASSERT( pParent, "Kein Parent fuer Paste." );
	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
	ASSERT( pParent != this, "Bin selbst der Parent." );
	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
	ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
			"Bin noch irgendwo angemeldet." );

	//In den Baum einhaengen.
	InsertBefore( (SwLayoutFrm*)pParent, pSibling );

    // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
    // <fnRect> is used for the following:
    // (1) To invalidate the frame's size, if its size, which has to be the
    //      same as its upper/parent, differs from its upper's/parent's.
    // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
    //      size, which is not determined by its upper/parent.
    // Which size is which depends on the frame type and the layout direction
    // (vertical or horizontal).
    // There are the following cases:
    // (A) Header and footer frames both in vertical and in horizontal layout
    //      have to size the width to the upper/parent. A dimension in the height
    //      has to cause a adjustment/grow of the upper/parent.
    //      --> <fnRect> = fnRectHori
    // (B) Cell and column frames in vertical layout, the width has to be the
    //          same as upper/parent and a dimension in height causes adjustment/grow
    //          of the upper/parent.
    //          --> <fnRect> = fnRectHori
    //      in horizontal layout the other way around
    //          --> <fnRect> = fnRectVert
    // (C) Other frames in vertical layout, the height has to be the
    //          same as upper/parent and a dimension in width causes adjustment/grow
    //          of the upper/parent.
    //          --> <fnRect> = fnRectVert
    //      in horizontal layout the other way around
    //          --> <fnRect> = fnRectHori
    //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
    SwRectFn fnRect;
    if ( IsHeaderFrm() || IsFooterFrm() )
        fnRect = fnRectHori;
    else if ( IsCellFrm() || IsColumnFrm() )
    	//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert );
    else
    	//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;


    if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)())
		_InvalidateSize();
	_InvalidatePos();
	const SwPageFrm *pPage = FindPageFrm();
	InvalidatePage( pPage );
	SwFrm *pFrm;
	if( !IsColumnFrm() )
	{
		if( 0 != ( pFrm = GetIndNext() ) )
		{
			pFrm->_InvalidatePos();
			if( IsInFtn() )
			{
				if( pFrm->IsSctFrm() )
					pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
				if( pFrm )
					pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
			}
		}
		if ( IsInFtn() && 0 != ( pFrm = GetIndPrev() ) )
		{
			if( pFrm->IsSctFrm() )
				pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
			if( pFrm )
				pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
		}
	}

    if( (Frm().*fnRect->fnGetHeight)() )
	{
		// AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
		// die sich nicht in Rahmen befinden
		sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
				((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
				: NA_GROW_SHRINK;
        SwTwips nGrow = (Frm().*fnRect->fnGetHeight)();
		if( NA_ONLY_ADJUST == nAdjust )
			AdjustNeighbourhood( nGrow );
		else
		{
			SwTwips nReal = 0;
			if( NA_ADJUST_GROW == nAdjust )
				nReal = AdjustNeighbourhood( nGrow );
			if( nReal < nGrow )
                nReal += pParent->Grow( nGrow - nReal );
			if( NA_GROW_ADJUST == nAdjust && nReal < nGrow )
				AdjustNeighbourhood( nGrow - nReal );
		}
	}
}

/*************************************************************************
|*
|*	SwLayoutFrm::Cut()
|*
|*	Ersterstellung		MA 23. Feb. 94
|*	Letzte Aenderung	MA 23. Feb. 94
|*
|*************************************************************************/
void SwLayoutFrm::Cut()
{
	if ( GetNext() )
		GetNext()->_InvalidatePos();

    SWRECTFN( this )
    SwTwips nShrink = (Frm().*fnRect->fnGetHeight)();

	//Erst removen, dann Upper Shrinken.
	SwLayoutFrm *pUp = GetUpper();

	// AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
	// die sich nicht in Rahmen befinden

	// Remove must not be called before a AdjustNeighbourhood, but it has to
	// be called before the upper-shrink-call, if the upper-shrink takes care
	// of his content
	if ( pUp && nShrink )
	{
		if( pUp->IsFtnBossFrm() )
		{
			sal_uInt8 nAdjust= ((SwFtnBossFrm*)pUp)->NeighbourhoodAdjustment( this );
			if( NA_ONLY_ADJUST == nAdjust )
				AdjustNeighbourhood( -nShrink );
			else
			{
				SwTwips nReal = 0;
				if( NA_ADJUST_GROW == nAdjust )
					nReal = -AdjustNeighbourhood( -nShrink );
				if( nReal < nShrink )
				{
                    SwTwips nOldHeight = (Frm().*fnRect->fnGetHeight)();
                    (Frm().*fnRect->fnSetHeight)( 0 );
                    nReal += pUp->Shrink( nShrink - nReal );
                    (Frm().*fnRect->fnSetHeight)( nOldHeight );
				}
				if( NA_GROW_ADJUST == nAdjust && nReal < nShrink )
					AdjustNeighbourhood( nReal - nShrink );
			}
			Remove();
		}
		else
		{
			Remove();
            pUp->Shrink( nShrink );
		}
	}
	else
		Remove();

	if( pUp && !pUp->Lower() )
	{
		pUp->SetCompletePaint();
		pUp->InvalidatePage();
	}
}

/*************************************************************************
|*
|*	SwFrm::Grow()
|*
|*	Ersterstellung		AK 19-Feb-1991
|*	Letzte Aenderung	MA 05. May. 94
|*
|*************************************************************************/
SwTwips SwFrm::Grow( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
	ASSERT( nDist >= 0, "Negatives Wachstum?" );

	PROTOCOL_ENTER( this, bTst ? PROT_GROW_TST : PROT_GROW, 0, &nDist )

	if ( nDist )
	{
        SWRECTFN( this )

        SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
        if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
            nDist = LONG_MAX - nPrtHeight;

		if ( IsFlyFrm() )
            return ((SwFlyFrm*)this)->_Grow( nDist, bTst );
		else if( IsSctFrm() )
            return ((SwSectionFrm*)this)->_Grow( nDist, bTst );
		else
		{
            const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
            if ( pThisCell )
            {
                const SwTabFrm* pTab = FindTabFrm();

                // NEW TABLES
                if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
                     pThisCell->GetLayoutRowSpan() < 1 )
                    return 0;
            }

            const SwTwips nReal = GrowFrm( nDist, bTst, bInfo );
			if( !bTst )
            {
                nPrtHeight = (Prt().*fnRect->fnGetHeight)();
                (Prt().*fnRect->fnSetHeight)( nPrtHeight +
                        ( IsCntntFrm() ? nDist : nReal ) );
            }
			return nReal;
		}
	}
	return 0L;
}

/*************************************************************************
|*
|*	SwFrm::Shrink()
|*
|*	Ersterstellung		AK 14-Feb-1991
|*	Letzte Aenderung	MA 05. May. 94
|*
|*************************************************************************/
SwTwips SwFrm::Shrink( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
	ASSERT( nDist >= 0, "Negative Verkleinerung?" );

	PROTOCOL_ENTER( this, bTst ? PROT_SHRINK_TST : PROT_SHRINK, 0, &nDist )

	if ( nDist )
	{
		if ( IsFlyFrm() )
            return ((SwFlyFrm*)this)->_Shrink( nDist, bTst );
		else if( IsSctFrm() )
            return ((SwSectionFrm*)this)->_Shrink( nDist, bTst );
		else
		{
            const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
            if ( pThisCell )
            {
                const SwTabFrm* pTab = FindTabFrm();

                // NEW TABLES
                if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
                     pThisCell->GetLayoutRowSpan() < 1 )
                    return 0;
            }

            SWRECTFN( this )
            SwTwips nReal = (Frm().*fnRect->fnGetHeight)();
            ShrinkFrm( nDist, bTst, bInfo );
            nReal -= (Frm().*fnRect->fnGetHeight)();
			if( !bTst )
            {
                const SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
                (Prt().*fnRect->fnSetHeight)( nPrtHeight -
                        ( IsCntntFrm() ? nDist : nReal ) );
            }
			return nReal;
		}
	}
	return 0L;
}

/*************************************************************************
|*
|*	SwFrm::AdjustNeighbourhood()
|*
|*	Beschreibung		Wenn sich die Groesse eines Frm's direkt unterhalb
|* 		eines Fussnotenbosses (Seite/Spalte) veraendert hat, so muss dieser
|*  	"Normalisiert" werden.
|* 		Es gibt dort immer einen Frame, der den "maximal moeglichen" Raum
|*		einnimmt (der Frame, der den Body.Text enhaelt) und keinen oder
|* 		mehrere Frames die den Platz einnehmen den sie halt brauchen
|* 		(Kopf-/Fussbereich, Fussnoten).
|*		Hat sich einer der Frames veraendert, so muss der Body-Text-Frame
|*		entsprechen wachsen oder schrumpfen; unabhaegig davon, dass er fix ist.
|* 		!! Ist es moeglich dies allgemeiner zu loesen, also nicht auf die
|* 		Seite beschraenkt und nicht auf einen Speziellen Frame, der den
|* 		maximalen Platz einnimmt (gesteuert ueber Attribut FrmSize)? Probleme:
|* 		Was ist wenn mehrere Frames nebeneinander stehen, die den maximalen
|* 		Platz einnehmen?
|*		Wie wird der Maximale Platz berechnet?
|* 		Wie klein duerfen diese Frames werden?
|*
|* 		Es wird auf jeden Fall nur so viel Platz genehmigt, dass ein
|* 		Minimalwert fuer die Hoehe des Bodys nicht unterschritten wird.
|*
|*	Parameter: nDiff ist der Betrag, um den Platz geschaffen werden muss
|*
|*	Ersterstellung		MA 07. May. 92
|*	Letzte Aenderung	AMA 02. Nov. 98
|*
|*************************************************************************/
SwTwips SwFrm::AdjustNeighbourhood( SwTwips nDiff, sal_Bool bTst )
{
	PROTOCOL_ENTER( this, PROT_ADJUSTN, 0, &nDiff );

	if ( !nDiff || !GetUpper()->IsFtnBossFrm() ) // nur innerhalb von Seiten/Spalten
		return 0L;

    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();

	//Der (Page)Body veraendert sich nur im BrowseMode, aber nicht wenn er
	//Spalten enthaelt.
	if ( IsPageBodyFrm() && (!bBrowse ||
		  (((SwLayoutFrm*)this)->Lower() &&
		   ((SwLayoutFrm*)this)->Lower()->IsColumnFrm())) )
		return 0L;

	//In der BrowseView kann der PageFrm selbst ersteinmal einiges von den
	//Wuenschen abfangen.
	long nBrowseAdd = 0;
	if ( bBrowse && GetUpper()->IsPageFrm() ) // nur (Page)BodyFrms
	{
		ViewShell *pViewShell = getRootFrm()->GetCurrShell();
		SwLayoutFrm *pUp = GetUpper();
		long nChg;
		const long nUpPrtBottom = pUp->Frm().Height() -
								  pUp->Prt().Height() - pUp->Prt().Top();
		SwRect aInva( pUp->Frm() );
		if ( pViewShell )
		{
			aInva.Pos().X() = pViewShell->VisArea().Left();
			aInva.Width( pViewShell->VisArea().Width() );
		}
		if ( nDiff > 0 )
		{
			nChg = BROWSE_HEIGHT - pUp->Frm().Height();
			nChg = Min( nDiff, nChg );

			if ( !IsBodyFrm() )
			{
				SetCompletePaint();
				if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->Frm().Height() )
				{
					//Ersteinmal den Body verkleinern. Der waechst dann schon
					//wieder.
					SwFrm *pBody = ((SwFtnBossFrm*)pUp)->FindBodyCont();
					const long nTmp = nChg - pBody->Prt().Height();
					if ( !bTst )
					{
						pBody->Frm().Height(Max( 0L, pBody->Frm().Height() - nChg ));
						pBody->_InvalidatePrt();
						pBody->_InvalidateSize();
						if ( pBody->GetNext() )
							pBody->GetNext()->_InvalidatePos();
						if ( !IsHeaderFrm() )
							pBody->SetCompletePaint();
					}
					nChg = nTmp <= 0 ? 0 : nTmp;
				}
			}

			const long nTmp = nUpPrtBottom + 20;
			aInva.Top( aInva.Bottom() - nTmp );
			aInva.Height( nChg + nTmp );
		}
		else
		{
			//Die Seite kann bis auf 0 schrumpfen. Die erste Seite bleibt
			//mindestens so gross wie die VisArea.
			nChg = nDiff;
			long nInvaAdd = 0;
			if ( pViewShell && !pUp->GetPrev() &&
				 pUp->Frm().Height() + nDiff < pViewShell->VisArea().Height() )
			{
				//Das heisst aber wiederum trotzdem, das wir geeignet invalidieren
				//muessen.
				nChg = pViewShell->VisArea().Height() - pUp->Frm().Height();
				nInvaAdd = -(nDiff - nChg);
			}

			//Invalidieren inklusive unterem Rand.
			long nBorder = nUpPrtBottom + 20;
			nBorder -= nChg;
			aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
			if ( !IsBodyFrm() )
			{
				SetCompletePaint();
				if ( !IsHeaderFrm() )
					((SwFtnBossFrm*)pUp)->FindBodyCont()->SetCompletePaint();
			}
			//Wegen der Rahmen die Seite invalidieren. Dadurch wird die Seite
			//wieder entsprechend gross wenn ein Rahmen nicht passt. Das
			//funktioniert anderfalls nur zufaellig fuer absatzgebundene Rahmen
			//(NotifyFlys).
			pUp->InvalidateSize();
		}
		if ( !bTst )
		{
			//Unabhaengig von nChg
			if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
				pViewShell->InvalidateWindows( aInva );
		}
		if ( !bTst && nChg )
		{
			const SwRect aOldRect( pUp->Frm() );
			pUp->Frm().SSize().Height() += nChg;
			pUp->Prt().SSize().Height() += nChg;
			if ( pViewShell )
				pViewShell->Imp()->SetFirstVisPageInvalid();

			if ( GetNext() )
				GetNext()->_InvalidatePos();

			//Ggf. noch ein Repaint ausloesen.
			const SvxGraphicPosition ePos = pUp->GetFmt()->GetBackground().GetGraphicPos();
			if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
				pViewShell->InvalidateWindows( pUp->Frm() );

			if ( pUp->GetUpper() )
			{
				if ( pUp->GetNext() )
					pUp->GetNext()->InvalidatePos();

				//Mies aber wahr: im Notify am ViewImp wird evtl. ein Calc
				//auf die Seite und deren Lower gerufen. Die Werte sollten
				//unverandert bleiben, weil der Aufrufer bereits fuer die
				//Anpassung von Frm und Prt sorgen wird.
				const long nOldFrmHeight = Frm().Height();
				const long nOldPrtHeight = Prt().Height();
				const sal_Bool bOldComplete = IsCompletePaint();
				if ( IsBodyFrm() )
					Prt().SSize().Height() = nOldFrmHeight;

                // PAGES01
                if ( pUp->GetUpper() )
                    static_cast<SwRootFrm*>(pUp->GetUpper())->CheckViewLayout( 0, 0 );
                //((SwPageFrm*)pUp)->AdjustRootSize( CHG_CHGPAGE, &aOldRect );

                Frm().SSize().Height() = nOldFrmHeight;
				Prt().SSize().Height() = nOldPrtHeight;
				bCompletePaint = bOldComplete;
			}
			if ( !IsBodyFrm() )
				pUp->_InvalidateSize();
			InvalidatePage( (SwPageFrm*)pUp );
		}
		nDiff -= nChg;
		if ( !nDiff )
			return nChg;
		else
			nBrowseAdd = nChg;
	}

	const SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();

	SwTwips nReal = 0,
			nAdd  = 0;
	SwFrm *pFrm = 0;
    SWRECTFN( this )

	if( IsBodyFrm() )
	{
		if( IsInSct() )
		{
			SwSectionFrm *pSect = FindSctFrm();
			if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
				GetNext()->IsFtnContFrm() )
			{
				SwFtnContFrm* pCont = (SwFtnContFrm*)GetNext();
				SwTwips nMinH = 0;
				SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
				sal_Bool bFtn = sal_False;
				while( pFtn )
				{
					if( !pFtn->GetAttr()->GetFtn().IsEndNote() )
					{
                        nMinH += (pFtn->Frm().*fnRect->fnGetHeight)();
						bFtn = sal_True;
					}
					pFtn = (SwFtnFrm*)pFtn->GetNext();
				}
				if( bFtn )
                    nMinH += (pCont->Prt().*fnRect->fnGetTop)();
                nReal = (pCont->Frm().*fnRect->fnGetHeight)() - nMinH;
				if( nReal > nDiff )
					nReal = nDiff;
				if( nReal > 0 )
					pFrm = GetNext();
				else
					nReal = 0;
			}
			if( !bTst && !pSect->IsColLocked() )
				pSect->InvalidateSize();
		}
		if( !pFrm )
			return nBrowseAdd;
	}
	else
	{
		const sal_Bool bFtnPage = pBoss->IsPageFrm() && ((SwPageFrm*)pBoss)->IsFtnPage();
		if ( bFtnPage && !IsFtnContFrm() )
			pFrm = (SwFrm*)pBoss->FindFtnCont();
		if ( !pFrm )
			pFrm = (SwFrm*)pBoss->FindBodyCont();

		if ( !pFrm )
			return 0;

		//Wenn ich keinen finde eruebrigt sich alles weitere.
        nReal = (pFrm->Frm().*fnRect->fnGetHeight)();
        if( nReal > nDiff )
            nReal = nDiff;
		if( !bFtnPage )
		{
			//Minimalgrenze beachten!
			if( nReal )
			{
				const SwTwips nMax = pBoss->GetVarSpace();
				if ( nReal > nMax )
					nReal = nMax;
			}
			if( !IsFtnContFrm() && nDiff > nReal &&
                pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm()
                && ( pFrm->GetNext()->IsVertical() == IsVertical() )
                )
			{
				//Wenn der Body nicht genuegend her gibt, kann ich noch mal
				//schauen ob es eine Fussnote gibt, falls ja kann dieser
				//entsprechend viel gemopst werden.
                const SwTwips nAddMax = (pFrm->GetNext()->Frm().*fnRect->
                                        fnGetHeight)();
				nAdd = nDiff - nReal;
				if ( nAdd > nAddMax )
					nAdd = nAddMax;
				if ( !bTst )
				{
                    (pFrm->GetNext()->Frm().*fnRect->fnSetHeight)(nAddMax-nAdd);
                    //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
                    if( bVert && !bVertL2R && !bRev )
                        pFrm->GetNext()->Frm().Pos().X() += nAdd;
					pFrm->GetNext()->InvalidatePrt();
					if ( pFrm->GetNext()->GetNext() )
						pFrm->GetNext()->GetNext()->_InvalidatePos();
				}
			}
		}
	}

	if ( !bTst && nReal )
	{
        SwTwips nTmp = (pFrm->Frm().*fnRect->fnGetHeight)();
        (pFrm->Frm().*fnRect->fnSetHeight)( nTmp - nReal );
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( bVert && !bVertL2R && !bRev )
            pFrm->Frm().Pos().X() += nReal;
		pFrm->InvalidatePrt();
		if ( pFrm->GetNext() )
			pFrm->GetNext()->_InvalidatePos();
		if( nReal < 0 && pFrm->IsInSct() )
		{
			SwLayoutFrm* pUp = pFrm->GetUpper();
			if( pUp && 0 != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrm() &&
				!pUp->IsColLocked() )
				pUp->InvalidateSize();
		}
		if( ( IsHeaderFrm() || IsFooterFrm() ) && pBoss->GetDrawObjs() )
		{
            const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
			ASSERT( pBoss->IsPageFrm(), "Header/Footer out of page?" );
            for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
			{
                SwAnchoredObject* pAnchoredObj = rObjs[i];
                if ( pAnchoredObj->ISA(SwFlyFrm) )
				{
                    SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
					ASSERT( !pFly->IsFlyInCntFrm(), "FlyInCnt at Page?" );
					const SwFmtVertOrient &rVert =
										pFly->GetFmt()->GetVertOrient();
				   // Wann muss invalidiert werden?
				   // Wenn ein Rahmen am SeitenTextBereich ausgerichtet ist,
				   // muss bei Aenderung des Headers ein TOP, MIDDLE oder NONE,
				   // bei Aenderung des Footers ein BOTTOM oder MIDDLE
				   // ausgerichteter Rahmen seine Position neu berechnen.
                    if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
                          rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )    &&
                        ((IsHeaderFrm() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
                         (IsFooterFrm() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
                          rVert.GetVertOrient() != text::VertOrientation::TOP)) )
					{
						pFly->_InvalidatePos();
						pFly->_Invalidate();
					}
				}
			}
		}
	}
	return (nBrowseAdd + nReal + nAdd);
}

/*************************************************************************
|*
|*	SwFrm::ImplInvalidateSize(), ImplInvalidatePrt(), ImplInvalidatePos(),
|* 		   ImplInvalidateLineNum()
|*
|*	Ersterstellung		MA 15. Oct. 92
|*	Letzte Aenderung	MA 24. Mar. 94
|*
|*************************************************************************/
/** method to perform additional actions on an invalidation

    OD 2004-05-19 #i28701#

    @author OD
*/
void SwFrm::_ActionOnInvalidation( const InvalidationType )
{
    // default behaviour is to perform no additional action
}

/** method to determine, if an invalidation is allowed.

    OD 2004-05-19 #i28701#

    @author OD
*/
bool SwFrm::_InvalidationAllowed( const InvalidationType ) const
{
    // default behaviour is to allow invalidation
    return true;
}

void SwFrm::ImplInvalidateSize()
{
    if ( _InvalidationAllowed( INVALID_SIZE ) )
    {
        bValidSize = sal_False;
        if ( IsFlyFrm() )
            ((SwFlyFrm*)this)->_Invalidate();
        else
            InvalidatePage();

        // OD 2004-05-19 #i28701#
        _ActionOnInvalidation( INVALID_SIZE );
    }
}

void SwFrm::ImplInvalidatePrt()
{
    if ( _InvalidationAllowed( INVALID_PRTAREA ) )
    {
        bValidPrtArea = sal_False;
        if ( IsFlyFrm() )
            ((SwFlyFrm*)this)->_Invalidate();
        else
            InvalidatePage();

        // OD 2004-05-19 #i28701#
        _ActionOnInvalidation( INVALID_PRTAREA );
    }
}

void SwFrm::ImplInvalidatePos()
{
    if ( _InvalidationAllowed( INVALID_POS ) )
    {
        bValidPos = sal_False;
        if ( IsFlyFrm() )
        {
            ((SwFlyFrm*)this)->_Invalidate();
        }
        else
        {
            InvalidatePage();
        }

        // OD 2004-05-19 #i28701#
        _ActionOnInvalidation( INVALID_POS );
    }
}

void SwFrm::ImplInvalidateLineNum()
{
    if ( _InvalidationAllowed( INVALID_LINENUM ) )
    {
        bValidLineNum = sal_False;
        ASSERT( IsTxtFrm(), "line numbers are implemented for text only" );
        InvalidatePage();

        // OD 2004-05-19 #i28701#
        _ActionOnInvalidation( INVALID_LINENUM );
    }
}

/*************************************************************************
|*
|*	SwFrm::ReinitializeFrmSizeAttrFlags
|*
|*	Ersterstellung		MA 15. Oct. 96
|*	Letzte Aenderung	MA 15. Oct. 96
|*
|*************************************************************************/
void SwFrm::ReinitializeFrmSizeAttrFlags()
{
	const SwFmtFrmSize &rFmtSize = GetAttrSet()->GetFrmSize();
    if ( ATT_VAR_SIZE == rFmtSize.GetHeightSizeType() ||
         ATT_MIN_SIZE == rFmtSize.GetHeightSizeType())
	{
        bFixSize = sal_False;
		if ( GetType() & (FRM_HEADER | FRM_FOOTER | FRM_ROW) )
		{
			SwFrm *pFrm = ((SwLayoutFrm*)this)->Lower();
			while ( pFrm )
			{	pFrm->_InvalidateSize();
				pFrm->_InvalidatePrt();
				pFrm = pFrm->GetNext();
			}
			SwCntntFrm *pCnt = ((SwLayoutFrm*)this)->ContainsCntnt();
            // --> OD 2004-12-20 #i36991# - be save.
            // E.g., a row can contain *no* content.
            if ( pCnt )
            {
                pCnt->InvalidatePage();
                do
                {
                    pCnt->Prepare( PREP_ADJUST_FRM );
                    pCnt->_InvalidateSize();
                    pCnt = pCnt->GetNextCntntFrm();
                } while ( ((SwLayoutFrm*)this)->IsAnLower( pCnt ) );
            }
            // <--
		}
	}
    else if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
    {
        if( IsVertical() )
			ChgSize( Size( rFmtSize.GetWidth(), Frm().Height()));
        else
			ChgSize( Size( Frm().Width(), rFmtSize.GetHeight()));
	}
}

/*************************************************************************
|*  SwFrm::ValidateThisAndAllLowers()
 *
 * FME 2007-08-30 #i81146# new loop control
|*************************************************************************/
void SwFrm::ValidateThisAndAllLowers( const sal_uInt16 nStage )
{
    // Stage 0: Only validate frames. Do not process any objects.
    // Stage 1: Only validate fly frames and all of their contents.
    // Stage 2: Validate all.

    const bool bOnlyObject = 1 == nStage;
    const bool bIncludeObjects = 1 <= nStage;

    if ( !bOnlyObject || ISA(SwFlyFrm) )
    {
        bValidSize = sal_True;
        bValidPrtArea = sal_True;
        bValidPos = sal_True;
    }

    if ( bIncludeObjects )
    {
        const SwSortedObjs* pObjs = GetDrawObjs();
        if ( pObjs )
        {
            const sal_uInt32 nCnt = pObjs->Count();
            for ( sal_uInt32 i = 0; i < nCnt; ++i )
            {
                SwAnchoredObject* pAnchObj = (*pObjs)[i];
                if ( pAnchObj->ISA(SwFlyFrm) )
                    static_cast<SwFlyFrm*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
                else if ( pAnchObj->ISA(SwAnchoredDrawObject) )
                    static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
            }
        }
    }

    if ( IsLayoutFrm() )
    {
        SwFrm* pLower = static_cast<SwLayoutFrm*>(this)->Lower();
        while ( pLower )
        {
            pLower->ValidateThisAndAllLowers( nStage );
            pLower = pLower->GetNext();
        }
    }
}

/*************************************************************************
|*
|*	SwCntntFrm::GrowFrm()
|*
|*	Ersterstellung		MA 30. Jul. 92
|*	Letzte Aenderung	MA 25. Mar. 99
|*
|*************************************************************************/
SwTwips SwCntntFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
    SWRECTFN( this )

    SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    if( nFrmHeight > 0 &&
         nDist > (LONG_MAX - nFrmHeight ) )
        nDist = LONG_MAX - nFrmHeight;

    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
    const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
    if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
	{
		if ( !bTst )
		{
            (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
            //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
            if( IsVertical() && !IsVertLR() && !IsReverse() )
                Frm().Pos().X() -= nDist;
			if ( GetNext() )
            {
				GetNext()->InvalidatePos();
            }
            // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
            // frame on the next page/column can flow backward (e.g. it was moved forward
            // due to the positioning of its objects ). Thus, invalivate this next frame,
            // if document compatibility option 'Consider wrapping style influence on
            // object positioning' is ON.
            else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
            {
                InvalidateNextPos();
            }
            // <--
		}
		return 0;
	}

    SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
	SwFrm *pFrm = GetUpper()->Lower();
    while( pFrm && nReal > 0 )
    {   nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
		pFrm = pFrm->GetNext();
	}

	if ( !bTst )
	{
		//Cntnts werden immer auf den gewuenschten Wert gebracht.
        long nOld = (Frm().*fnRect->fnGetHeight)();
        (Frm().*fnRect->fnSetHeight)( nOld + nDist );
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( IsVertical()&& !IsVertLR() && !IsReverse() )
            Frm().Pos().X() -= nDist;
		if ( nOld && IsInTab() )
		{
			SwTabFrm *pTab = FindTabFrm();
			if ( pTab->GetTable()->GetHTMLTableLayout() &&
				 !pTab->IsJoinLocked() &&
				 !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
			{
				pTab->InvalidatePos();
				pTab->SetResizeHTMLTable();
			}
		}
	}

	//Upper nur growen wenn notwendig.
	if ( nReal < nDist )
    {
        if( GetUpper() )
        {
            if( bTst || !GetUpper()->IsFooterFrm() )
                nReal = GetUpper()->Grow( nDist - (nReal > 0 ? nReal : 0),
                                          bTst, bInfo );
            else
            {
                nReal = 0;
                GetUpper()->InvalidateSize();
            }
        }
        else
            nReal = 0;
    }
    else
		nReal = nDist;

    // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
    // frame on the next page/column can flow backward (e.g. it was moved forward
    // due to the positioning of its objects ). Thus, invalivate this next frame,
    // if document compatibility option 'Consider wrapping style influence on
    // object positioning' is ON.
    if ( !bTst )
    {
        if ( GetNext() )
        {
            GetNext()->InvalidatePos();
        }
        else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
        {
            InvalidateNextPos();
        }
    }
    // <--

	return nReal;
}

/*************************************************************************
|*
|*	SwCntntFrm::ShrinkFrm()
|*
|*	Ersterstellung		MA 30. Jul. 92
|*	Letzte Aenderung	MA 05. May. 94
|*
|*************************************************************************/
SwTwips SwCntntFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
    SWRECTFN( this )
	ASSERT( nDist >= 0, "nDist < 0" );
    ASSERT( nDist <= (Frm().*fnRect->fnGetHeight)(),
			"nDist > als aktuelle Grosse." );

	if ( !bTst )
	{
        SwTwips nRstHeight;
        if( GetUpper() )
            nRstHeight = (Frm().*fnRect->fnBottomDist)
                         ( (GetUpper()->*fnRect->fnGetPrtBottom)() );
        else
            nRstHeight = 0;
		if( nRstHeight < 0 )
        {
            SwTwips nNextHeight = 0;
            if( GetUpper()->IsSctFrm() && nDist > LONG_MAX/2 )
            {
                SwFrm *pNxt = GetNext();
                while( pNxt )
                {
                    nNextHeight += (pNxt->Frm().*fnRect->fnGetHeight)();
                    pNxt = pNxt->GetNext();
                }
            }
            nRstHeight = nDist + nRstHeight - nNextHeight;
        }
        else
			nRstHeight = nDist;
        (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() - nDist );
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( IsVertical() && !IsVertLR() )
            Frm().Pos().X() += nDist;
		nDist = nRstHeight;
		if ( IsInTab() )
		{
			SwTabFrm *pTab = FindTabFrm();
			if ( pTab->GetTable()->GetHTMLTableLayout() &&
				 !pTab->IsJoinLocked() &&
				 !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
			{
				pTab->InvalidatePos();
				pTab->SetResizeHTMLTable();
			}
		}
	}

    SwTwips nReal;
    if( GetUpper() && nDist > 0 )
    {
        if( bTst || !GetUpper()->IsFooterFrm() )
            nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
        else
        {
            nReal = 0;

            // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
            // if there are any objects anchored inside your content, which
            // overlap with the shrinking frame.
            // This may lead to a footer frame that is too big, but this is better
            // than looping.
            // #109722# : The fix for #108745# was too strict.

            bool bInvalidate = true;
            const SwRect aRect( Frm() );
            const SwPageFrm* pPage = FindPageFrm();
            const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : 0;
            if( pSorted )
            {
                for ( sal_uInt16 i = 0; i < pSorted->Count(); ++i )
                {
                    const SwAnchoredObject* pAnchoredObj = (*pSorted)[i];
                    const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );

                    if( aBound.Left() > aRect.Right() )
                        continue;

                    if( aBound.IsOver( aRect ) )
                    {
                        const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
                        if( SURROUND_THROUGHT != rFmt.GetSurround().GetSurround() )
                        {
                            const SwFrm* pAnchor = pAnchoredObj->GetAnchorFrm();
                            if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
                            {
                                bInvalidate = false;
                                break;
                            }
                        }
                    }
                }
            }

            if ( bInvalidate )
                GetUpper()->InvalidateSize();
        }
    }
    else
        nReal = 0;

	if ( !bTst )
	{
		//Die Position des naechsten Frm's veraendert sich auf jeden Fall.
		InvalidateNextPos();

        //Wenn ich keinen Nachfolger habe, so muss ich mich eben selbst um
		//die Retusche kuemmern.
		if ( !GetNext() )
			SetRetouche();
	}
	return nReal;
}

/*************************************************************************
|*
|*	  SwCntntFrm::Modify()
|*
|*	  Beschreibung
|*	  Ersterstellung	AK 05-Mar-1991
|*	  Letzte Aenderung	MA 13. Oct. 95
|*
|*************************************************************************/
void SwCntntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
{
	sal_uInt8 nInvFlags = 0;

	if( pNew && RES_ATTRSET_CHG == pNew->Which() )
	{
		SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
		SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
		SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
		SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
		while( sal_True )
		{
			_UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
						 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
						 &aOldSet, &aNewSet );
			if( aNIter.IsAtEnd() )
				break;
			aNIter.NextItem();
			aOIter.NextItem();
		}
		if ( aOldSet.Count() || aNewSet.Count() )
			SwFrm::Modify( &aOldSet, &aNewSet );
	}
	else
		_UpdateAttr( pOld, pNew, nInvFlags );

	if ( nInvFlags != 0 )
	{
		SwPageFrm *pPage = FindPageFrm();
		InvalidatePage( pPage );
		if ( nInvFlags & 0x01 )
			SetCompletePaint();
		if ( nInvFlags & 0x02 )
			_InvalidatePos();
		if ( nInvFlags & 0x04 )
			_InvalidateSize();
		if ( nInvFlags & 0x88 )
		{
			if( IsInSct() && !GetPrev() )
			{
				SwSectionFrm *pSect = FindSctFrm();
				if( pSect->ContainsAny() == this )
				{
					pSect->_InvalidatePrt();
					pSect->InvalidatePage( pPage );
				}
			}
			_InvalidatePrt();
		}
        SwFrm* pNextFrm = GetIndNext();
        if ( pNextFrm && nInvFlags & 0x10)
		{
            pNextFrm->_InvalidatePrt();
            pNextFrm->InvalidatePage( pPage );
		}
        if ( pNextFrm && nInvFlags & 0x80 )
        {
            pNextFrm->SetCompletePaint();
        }
        if ( nInvFlags & 0x20 )
		{
            SwFrm* pPrevFrm = GetPrev();
            if ( pPrevFrm )
            {
                pPrevFrm->_InvalidatePrt();
                pPrevFrm->InvalidatePage( pPage );
            }
		}
		if ( nInvFlags & 0x40 )
			InvalidateNextPos();
	}
}

void SwCntntFrm::_UpdateAttr( const SfxPoolItem* pOld, const SfxPoolItem* pNew,
							  sal_uInt8 &rInvFlags,
							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
{
	sal_Bool bClear = sal_True;
	sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
	switch ( nWhich )
	{
		case RES_FMT_CHG:
			rInvFlags = 0xFF;
			/* kein break hier */

		case RES_PAGEDESC:						//Attributaenderung (an/aus)
			if ( IsInDocBody() && !IsInTab() )
			{
				rInvFlags |= 0x02;
				SwPageFrm *pPage = FindPageFrm();
				if ( !GetPrev() )
					CheckPageDescs( pPage );
				if ( pPage && GetAttrSet()->GetPageDesc().GetNumOffset() )
					((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
				SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
				pPage->GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
			}
			break;

		case RES_UL_SPACE:
			{
                // OD 2004-02-18 #106629# - correction
                // Invalidation of the printing area of next frame, not only
                // for footnote content.
                if ( !GetIndNext() )
				{
					SwFrm* pNxt = FindNext();
                    if ( pNxt )
					{
						SwPageFrm* pPg = pNxt->FindPageFrm();
						pNxt->InvalidatePage( pPg );
						pNxt->_InvalidatePrt();
						if( pNxt->IsSctFrm() )
						{
							SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
							if( pCnt )
							{
								pCnt->_InvalidatePrt();
								pCnt->InvalidatePage( pPg );
							}
						}
						pNxt->SetCompletePaint();
                    }
				}
                // OD 2004-03-17 #i11860#
                if ( GetIndNext() &&
                     !GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
                {
                    // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
                    GetIndNext()->InvalidateObjs( true );
                }
                Prepare( PREP_UL_SPACE );   //TxtFrm muss Zeilenabst. korrigieren.
				rInvFlags |= 0x80;
				/* kein Break hier */
			}
		case RES_LR_SPACE:
		case RES_BOX:
		case RES_SHADOW:
			Prepare( PREP_FIXSIZE_CHG );
			SwFrm::Modify( pOld, pNew );
			rInvFlags |= 0x30;
			break;

		case RES_BREAK:
			{
				rInvFlags |= 0x42;
                const IDocumentSettingAccess* pIDSA = GetUpper()->GetFmt()->getIDocumentSettingAccess();
                if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
                    pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) )
				{
					rInvFlags |= 0x1;
					SwFrm* pNxt = FindNext();
					if( pNxt )
					{
						SwPageFrm* pPg = pNxt->FindPageFrm();
						pNxt->InvalidatePage( pPg );
						pNxt->_InvalidatePrt();
						if( pNxt->IsSctFrm() )
						{
							SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
							if( pCnt )
							{
								pCnt->_InvalidatePrt();
								pCnt->InvalidatePage( pPg );
							}
						}
						pNxt->SetCompletePaint();
					}
				}
			}
			break;

        // OD 2004-02-26 #i25029#
        case RES_PARATR_CONNECT_BORDER:
        {
            rInvFlags |= 0x01;
            if ( IsTxtFrm() )
            {
                InvalidateNextPrtArea();
            }
            if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
            {
                FindTabFrm()->InvalidateSize();
            }
        }
        break;

		case RES_PARATR_TABSTOP:
		case RES_CHRATR_PROPORTIONALFONTSIZE:
		case RES_CHRATR_SHADOWED:
		case RES_CHRATR_AUTOKERN:
		case RES_CHRATR_UNDERLINE:
		case RES_CHRATR_OVERLINE:
		case RES_CHRATR_KERNING:
		case RES_CHRATR_FONT:
		case RES_CHRATR_FONTSIZE:
		case RES_CHRATR_ESCAPEMENT:
		case RES_CHRATR_CONTOUR:
        case RES_PARATR_NUMRULE:
			rInvFlags |= 0x01;
			break;


		case RES_FRM_SIZE:
			rInvFlags |= 0x01;
			/* no break here */

		default:
			bClear = sal_False;
	}
	if ( bClear )
	{
		if ( pOldSet || pNewSet )
		{
			if ( pOldSet )
				pOldSet->ClearItem( nWhich );
			if ( pNewSet )
				pNewSet->ClearItem( nWhich );
		}
		else
			SwFrm::Modify( pOld, pNew );
	}
}

/*************************************************************************
|*
|*	SwLayoutFrm::SwLayoutFrm()
|*
|*	Ersterstellung		AK 14-Feb-1991
|*	Letzte Aenderung	MA 12. May. 95
|*
|*************************************************************************/
SwLayoutFrm::SwLayoutFrm( SwFrmFmt* pFmt, SwFrm* pSib ):
	SwFrm( pFmt, pSib ),
    pLower( 0 )
{
	const SwFmtFrmSize &rFmtSize = pFmt->GetFrmSize();
    if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
        bFixSize = sal_True;
}

// --> OD 2004-06-29 #i28701#
TYPEINIT1(SwLayoutFrm,SwFrm);
// <--
/*-----------------10.06.99 09:42-------------------
 * SwLayoutFrm::InnerHeight()
 * --------------------------------------------------*/

SwTwips SwLayoutFrm::InnerHeight() const
{
	if( !Lower() )
		return 0;
	SwTwips nRet = 0;
	const SwFrm* pCnt = Lower();
    SWRECTFN( this )
	if( pCnt->IsColumnFrm() || pCnt->IsCellFrm() )
	{
		do
		{
			SwTwips nTmp = ((SwLayoutFrm*)pCnt)->InnerHeight();
			if( pCnt->GetValidPrtAreaFlag() )
                nTmp += (pCnt->Frm().*fnRect->fnGetHeight)() -
                        (pCnt->Prt().*fnRect->fnGetHeight)();
            if( nRet < nTmp )
				nRet = nTmp;
			pCnt = pCnt->GetNext();
		} while ( pCnt );
	}
	else
	{
		do
		{
            nRet += (pCnt->Frm().*fnRect->fnGetHeight)();
			if( pCnt->IsCntntFrm() && ((SwTxtFrm*)pCnt)->IsUndersized() )
                nRet += ((SwTxtFrm*)pCnt)->GetParHeight() -
                        (pCnt->Prt().*fnRect->fnGetHeight)();
			if( pCnt->IsLayoutFrm() && !pCnt->IsTabFrm() )
                nRet += ((SwLayoutFrm*)pCnt)->InnerHeight() -
                        (pCnt->Prt().*fnRect->fnGetHeight)();
			pCnt = pCnt->GetNext();
		} while( pCnt );

	}
	return nRet;
}

/*************************************************************************
|*
|*	SwLayoutFrm::GrowFrm()
|*
|*	Ersterstellung		MA 30. Jul. 92
|*	Letzte Aenderung	MA 23. Sep. 96
|*
|*************************************************************************/
SwTwips SwLayoutFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
    const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
    if( !(GetType() & nTmpType) && HasFixSize() )
		return 0;

    SWRECTFN( this )
    const SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    const SwTwips nFrmPos = Frm().Pos().X();

    if ( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
        nDist = LONG_MAX - nFrmHeight;

    SwTwips nMin = 0;
    if ( GetUpper() && !IsCellFrm() )
	{
        SwFrm *pFrm = GetUpper()->Lower();
        while( pFrm )
        {   nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
            pFrm = pFrm->GetNext();
        }
        nMin = (GetUpper()->Prt().*fnRect->fnGetHeight)() - nMin;
		if ( nMin < 0 )
			nMin = 0;
	}

	SwRect aOldFrm( Frm() );
	sal_Bool bMoveAccFrm = sal_False;

    sal_Bool bChgPos = IsVertical() && !IsReverse();
	if ( !bTst )
    {
        (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( bChgPos && !IsVertLR() )
            Frm().Pos().X() -= nDist;
		bMoveAccFrm = sal_True;
    }

	SwTwips nReal = nDist - nMin;
	if ( nReal > 0 )
	{
		if ( GetUpper() )
		{   // AdjustNeighbourhood jetzt auch in Spalten (aber nicht in Rahmen)
			sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
				((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
				: NA_GROW_SHRINK;
			if( NA_ONLY_ADJUST == nAdjust )
				nReal = AdjustNeighbourhood( nReal, bTst );
			else
			{
				if( NA_ADJUST_GROW == nAdjust )
					nReal += AdjustNeighbourhood( nReal, bTst );

                SwTwips nGrow = 0;
				if( 0 < nReal )
                {
                    SwFrm* pToGrow = GetUpper();
                    // NEW TABLES
                    // A cell with a row span of > 1 is allowed to grow the
                    // line containing the end of the row span if it is
                    // located in the same table frame:
                    const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
                    if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
                    {
                        SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
                        if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
                            pToGrow = rEndCell.GetUpper();
                        else
                            pToGrow = 0;
                    }

                    nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
                }

				if( NA_GROW_ADJUST == nAdjust && nGrow < nReal )
					nReal += AdjustNeighbourhood( nReal - nGrow, bTst );

                if ( IsFtnFrm() && (nGrow != nReal) && GetNext() )
				{
					//Fussnoten koennen ihre Nachfolger verdraengen.
					SwTwips nSpace = bTst ? 0 : -nDist;
					const SwFrm *pFrm = GetUpper()->Lower();
					do
                    {   nSpace += (pFrm->Frm().*fnRect->fnGetHeight)();
						pFrm = pFrm->GetNext();
					} while ( pFrm != GetNext() );
                    nSpace = (GetUpper()->Prt().*fnRect->fnGetHeight)() -nSpace;
					if ( nSpace < 0 )
						nSpace = 0;
					nSpace += nGrow;
					if ( nReal > nSpace )
						nReal = nSpace;
					if ( nReal && !bTst )
						((SwFtnFrm*)this)->InvalidateNxtFtnCnts( FindPageFrm() );
				}
				else
					nReal = nGrow;
			}
		}
		else
			nReal = 0;

		nReal += nMin;
	}
	else
		nReal = nDist;

	if ( !bTst )
	{
        if( nReal != nDist &&
            // NEW TABLES
            ( !IsCellFrm() || static_cast<SwCellFrm*>(this)->GetLayoutRowSpan() > 1 ) )
        {
            (Frm().*fnRect->fnSetHeight)( nFrmHeight + nReal );
            //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
            if( bChgPos && !IsVertLR() )
                Frm().Pos().X() = nFrmPos - nReal;
			bMoveAccFrm = sal_True;
        }

		if ( nReal )
		{
			SwPageFrm *pPage = FindPageFrm();
			if ( GetNext() )
			{
				GetNext()->_InvalidatePos();
				if ( GetNext()->IsCntntFrm() )
					GetNext()->InvalidatePage( pPage );
			}
			if ( !IsPageBodyFrm() )
			{
				_InvalidateAll();
				InvalidatePage( pPage );
			}
			if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
                NotifyLowerObjs();

			if( IsCellFrm() )
                InvaPercentLowers( nReal );

			const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
			if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
				SetCompletePaint();
		}
	}

	if( bMoveAccFrm && IsAccessibleFrm() )
	{
		SwRootFrm *pRootFrm = getRootFrm();
		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
			pRootFrm->GetCurrShell() )
		{
			pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
		}
	}
	return nReal;
}

/*************************************************************************
|*
|*	SwLayoutFrm::ShrinkFrm()
|*
|*	Ersterstellung		MA 30. Jul. 92
|*	Letzte Aenderung	MA 25. Mar. 99
|*
|*************************************************************************/
SwTwips SwLayoutFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
{
    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
    const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
    if( !(GetType() & nTmpType) && HasFixSize() )
		return 0;

	ASSERT( nDist >= 0, "nDist < 0" );
    SWRECTFN( this )
    SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    if ( nDist > nFrmHeight )
        nDist = nFrmHeight;

	SwTwips nMin = 0;
    sal_Bool bChgPos = IsVertical() && !IsReverse();
	if ( Lower() )
	{
        if( !Lower()->IsNeighbourFrm() )
        {   const SwFrm *pFrm = Lower();
            const long nTmp = (Prt().*fnRect->fnGetHeight)();
            while( pFrm && nMin < nTmp )
            {   nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
				pFrm = pFrm->GetNext();
			}
		}
	}
	SwTwips nReal = nDist;
    SwTwips nMinDiff = (Prt().*fnRect->fnGetHeight)() - nMin;
    if( nReal > nMinDiff )
        nReal = nMinDiff;
    if( nReal <= 0 )
		return nDist;

	SwRect aOldFrm( Frm() );
	sal_Bool bMoveAccFrm = sal_False;

	SwTwips nRealDist = nReal;
	if ( !bTst )
    {
        (Frm().*fnRect->fnSetHeight)( nFrmHeight - nReal );
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( bChgPos && !IsVertLR() )
        	Frm().Pos().X() += nReal;
		bMoveAccFrm = sal_True;
    }

	sal_uInt8 nAdjust = GetUpper() && GetUpper()->IsFtnBossFrm() ?
				   ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
				   : NA_GROW_SHRINK;

	// AdjustNeighbourhood auch in Spalten (aber nicht in Rahmen)
	if( NA_ONLY_ADJUST == nAdjust )
	{
		if ( IsPageBodyFrm() && !bBrowse )
			nReal = nDist;
		else
		{	nReal = AdjustNeighbourhood( -nReal, bTst );
			nReal *= -1;
			if ( !bTst && IsBodyFrm() && nReal < nRealDist )
            {
                (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
                                            + nRealDist - nReal );
                //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
                if( bChgPos && !IsVertLR() )
                    Frm().Pos().X() += nRealDist - nReal;
				ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
            }
		}
	}
    else if( IsColumnFrm() || IsColBodyFrm() )
    {
        SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
		if ( nTmp != nReal )
		{
            (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
                                          + nReal - nTmp );
            //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
            if( bChgPos && !IsVertLR() )
                Frm().Pos().X() += nTmp - nReal;
			ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
			nReal = nTmp;
		}
	}
	else
	{
		SwTwips nShrink = nReal;
        SwFrm* pToShrink = GetUpper();
        const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
        // NEW TABLES
        if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
        {
            SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
            pToShrink = rEndCell.GetUpper();
        }

        nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
		if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
			&& nReal < nShrink )
			AdjustNeighbourhood( nReal - nShrink );
	}

	if( bMoveAccFrm && IsAccessibleFrm() )
	{
		SwRootFrm *pRootFrm = getRootFrm();
		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
			pRootFrm->GetCurrShell() )
		{
			pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
		}
	}
	if ( !bTst && (IsCellFrm() || IsColumnFrm() ? nReal : nRealDist) )
	{
		SwPageFrm *pPage = FindPageFrm();
		if ( GetNext() )
		{
			GetNext()->_InvalidatePos();
			if ( GetNext()->IsCntntFrm() )
				GetNext()->InvalidatePage( pPage );
			if ( IsTabFrm() )
				((SwTabFrm*)this)->SetComplete();
		}
		else
		{	if ( IsRetoucheFrm() )
				SetRetouche();
			if ( IsTabFrm() )
			{
				if( IsTabFrm() )
					((SwTabFrm*)this)->SetComplete();
				if ( Lower() ) 	//Kann auch im Join stehen und leer sein!
					InvalidateNextPos();
			}
		}
		if ( !IsBodyFrm() )
		{
			_InvalidateAll();
			InvalidatePage( pPage );
			const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
			if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
				SetCompletePaint();
		}

		if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
            NotifyLowerObjs();

		if( IsCellFrm() )
            InvaPercentLowers( nReal );

		SwCntntFrm *pCnt;
		if( IsFtnFrm() && !((SwFtnFrm*)this)->GetAttr()->GetFtn().IsEndNote() &&
			( GetFmt()->GetDoc()->GetFtnInfo().ePos != FTNPOS_CHAPTER ||
              ( IsInSct() && FindSctFrm()->IsFtnAtEnd() ) ) &&
              0 != (pCnt = ((SwFtnFrm*)this)->GetRefFromAttr() ) )
		{
			if ( pCnt->IsFollow() )
			{   // Wenn wir sowieso schon in einer anderen Spalte/Seite sitzen
				// als der Frame mit der Referenz, dann brauchen wir nicht
				// auch noch seinen Master zu invalidieren.
				SwFrm *pTmp = pCnt->FindFtnBossFrm(sal_True) == FindFtnBossFrm(sal_True)
							  ?  pCnt->FindMaster()->GetFrm() : pCnt;
				pTmp->Prepare( PREP_ADJUST_FRM );
				pTmp->InvalidateSize();
			}
			else
				pCnt->InvalidatePos();
		}
	}
	return nReal;
}
/*************************************************************************
|*
|*	SwLayoutFrm::ChgLowersProp()
|*
|*	Beschreibung		Aendert die Grosse der direkt untergeordneten Frm's
|* 		die eine Fixe Groesse haben, proportional zur Groessenaenderung der
|* 		PrtArea des Frm's.
|* 		Die Variablen Frm's werden auch proportional angepasst; sie werden
|* 		sich schon wieder zurechtwachsen/-schrumpfen.
|*	Ersterstellung		MA 11.03.92
|*	Letzte Aenderung	AMA 2. Nov. 98
|*
|*************************************************************************/
void SwLayoutFrm::ChgLowersProp( const Size& rOldSize )
{
    // no change of lower properties for root frame or if no lower exists.
    if ( IsRootFrm() || !Lower() )
		return;

    // declare and init <SwFrm* pLowerFrm> with first lower
    SwFrm *pLowerFrm = Lower();

    // declare and init const booleans <bHeightChgd> and <bWidthChg>
    const bool bHeightChgd = rOldSize.Height() != Prt().Height();
    const bool bWidthChgd  = rOldSize.Width()  != Prt().Width();

    // declare and init variables <bVert>, <bRev> and <fnRect>
    SWRECTFN( this )

    // This shortcut basically tries to handle only lower frames that
    // are affected by the size change. Otherwise much more lower frames
    // are invalidated.
    if ( !( bVert ? bHeightChgd : bWidthChgd ) &&
         ! Lower()->IsColumnFrm() &&
           ( ( IsBodyFrm() && IsInDocBody() && ( !IsInSct() || !FindSctFrm()->IsColLocked() ) ) ||
                // --> FME 2004-07-21 #i10826# Section frames without columns should not
                // invalidate all lowers!
               IsSctFrm() ) )
               // <--
    {
        // Determine page frame the body frame resp. the section frame belongs to.
		SwPageFrm *pPage = FindPageFrm();
        // Determine last lower by traveling through them using <GetNext()>.
        // During travel check each section frame, if it will be sized to
        // maximum. If Yes, invalidate size of section frame and set
        // corresponding flags at the page.
        do
        {
            if( pLowerFrm->IsSctFrm() &&((SwSectionFrm*)pLowerFrm)->_ToMaximize() )
            {
                pLowerFrm->_InvalidateSize();
                pLowerFrm->InvalidatePage( pPage );
            }
            if( pLowerFrm->GetNext() )
                pLowerFrm = pLowerFrm->GetNext();
            else
                break;
        } while( sal_True );
        // If found last lower is a section frame containing no section
        // (section frame isn't valid and will be deleted in the future),
        // travel backwards.
        while( pLowerFrm->IsSctFrm() && !((SwSectionFrm*)pLowerFrm)->GetSection() &&
               pLowerFrm->GetPrev() )
            pLowerFrm = pLowerFrm->GetPrev();
        // If found last lower is a section frame, set <pLowerFrm> to its last
        // content, if the section frame is valid and is not sized to maximum.
        // Otherwise set <pLowerFrm> to NULL - In this case body frame only
        //      contains invalid section frames.
        if( pLowerFrm->IsSctFrm() )
            pLowerFrm = ((SwSectionFrm*)pLowerFrm)->GetSection() &&
                   !((SwSectionFrm*)pLowerFrm)->ToMaximize( sal_False ) ?
                   ((SwSectionFrm*)pLowerFrm)->FindLastCntnt() : NULL;

        // continue with found last lower, probably the last content of a section
        if ( pLowerFrm )
		{
            // If <pLowerFrm> is in a table frame, set <pLowerFrm> to this table
            // frame and continue.
            if ( pLowerFrm->IsInTab() )
            {
                // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrm> to
                // its table frame - check, if the table frame is also a lower
                // of the body frame, in order to assure that <pLowerFrm> is not
                // set to a frame, which is an *upper* of the body frame.
                SwFrm* pTableFrm = pLowerFrm->FindTabFrm();
                if ( IsAnLower( pTableFrm ) )
                {
                    pLowerFrm = pTableFrm;
                }
            }
            // Check, if variable size of body frame resp. section frame has grown
            // OD 28.10.2002 #97265# - correct check, if variable size has grown.
            SwTwips nOldHeight = bVert ? rOldSize.Width() : rOldSize.Height();
            if( nOldHeight < (Prt().*fnRect->fnGetHeight)() )
			{
                // If variable size of body|section frame has grown, only found
                // last lower and the position of the its next have to be invalidated.
                pLowerFrm->_InvalidateAll();
                pLowerFrm->InvalidatePage( pPage );
                if( !pLowerFrm->IsFlowFrm() ||
                    !SwFlowFrm::CastFlowFrm( pLowerFrm )->HasFollow() )
                    pLowerFrm->InvalidateNextPos( sal_True );
                if ( pLowerFrm->IsTxtFrm() )
                    ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
			}
			else
			{
                // variable size of body|section frame has shrinked. Thus,
                // invalidate all lowers not matching the new body|section size
                // and the dedicated new last lower.
                if( bVert )
                {
                    SwTwips nBot = Frm().Left() + Prt().Left();
                    while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Left() < nBot )
                    {
                        pLowerFrm->_InvalidateAll();
                        pLowerFrm->InvalidatePage( pPage );
                        pLowerFrm = pLowerFrm->GetPrev();
                    }
                }
                else
                {
                    SwTwips nBot = Frm().Top() + Prt().Bottom();
                    while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Top() > nBot )
                    {
                        pLowerFrm->_InvalidateAll();
                        pLowerFrm->InvalidatePage( pPage );
                        pLowerFrm = pLowerFrm->GetPrev();
                    }
                }
                if ( pLowerFrm )
				{
                    pLowerFrm->_InvalidateSize();
                    pLowerFrm->InvalidatePage( pPage );
                    if ( pLowerFrm->IsTxtFrm() )
                        ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
				}
			}
            // --> OD 2005-01-31 #i41694# - improvement by removing duplicates
            if ( pLowerFrm )
            {
                if ( pLowerFrm->IsInSct() )
                {
                    // --> OD 2005-01-31 #i41694# - follow-up of issue #i10826#:
                    // No invalidation of section frame, if it's the this.
                    SwFrm* pSectFrm = pLowerFrm->FindSctFrm();
                    if( pSectFrm != this && IsAnLower( pSectFrm ) )
                    {
                        pSectFrm->_InvalidateSize();
                        pSectFrm->InvalidatePage( pPage );
                    }
                    // <--
                }
            }
            // <--
        }
		return;
    } // end of { special case }


    // Invalidate page for content only once.
    bool bInvaPageForCntnt = true;

    // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
    // adjustment, if fixed/variable size has changed.
    bool bFixChgd, bVarChgd;
    if( bVert == pLowerFrm->IsNeighbourFrm() )
	{
		bFixChgd = bWidthChgd;
		bVarChgd = bHeightChgd;
	}
	else
	{
		bFixChgd = bHeightChgd;
		bVarChgd = bWidthChgd;
	}

    // Declare const unsigned short <nFixWidth> and init it this frame types
    // which has fixed width in vertical respectively horizontal layout.
    // In vertical layout these are neighbour frames (cell and column frames),
    //      header frames and footer frames.
    // In horizontal layout these are all frames, which aren't neighbour frames.
    const sal_uInt16 nFixWidth = bVert ? (FRM_NEIGHBOUR | FRM_HEADFOOT)
                                   : ~FRM_NEIGHBOUR;

    // Declare const unsigned short <nFixHeight> and init it this frame types
    // which has fixed height in vertical respectively horizontal layout.
    // In vertical layout these are all frames, which aren't neighbour frames,
    //      header frames, footer frames, body frames or foot note container frames.
    // In horizontal layout these are neighbour frames.
    const sal_uInt16 nFixHeight= bVert ? ~(FRM_NEIGHBOUR | FRM_HEADFOOT | FRM_BODYFTNC)
                                   : FRM_NEIGHBOUR;

    // Travel through all lowers using <GetNext()>
    while ( pLowerFrm )
    {
        if ( pLowerFrm->IsTxtFrm() )
		{
            // Text frames will only be invalidated - prepare invalidation
			if ( bFixChgd )
                static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_FIXSIZE_CHG );
			if ( bVarChgd )
                static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_ADJUST_FRM );
		}
        else
        {
            // If lower isn't a table, row, cell or section frame, adjust its
            // frame size.
            const sal_uInt16 nLowerType = pLowerFrm->GetType();
            if ( !(nLowerType & (FRM_TAB|FRM_ROW|FRM_CELL|FRM_SECTION)) )
            {
                if ( bWidthChgd )
                {
                    if( nLowerType & nFixWidth )
                    {
                        // Considering previous conditions:
                        // In vertical layout set width of column, header and
                        // footer frames to its upper width.
                        // In horizontal layout set width of header, footer,
                        // foot note container, foot note, body and no-text
                        // frames to its upper width.
                        pLowerFrm->Frm().Width( Prt().Width() );
                    }
                    else if( rOldSize.Width() && !pLowerFrm->IsFtnFrm() )
                    {
                        // Adjust frame width proportional, if lower isn't a
                        // foot note frame and condition <nLowerType & nFixWidth>
                        // isn't true.
                        // Considering previous conditions:
                        // In vertical layout these are foot note container,
                        // body and no-text frames.
                        // In horizontal layout these are column and no-text frames.
                        // OD 24.10.2002 #97265# - <double> calculation
                        // Perform <double> calculation of new width, if
                        // one of the coefficients is greater than 50000
                        SwTwips nNewWidth;
                        if ( (pLowerFrm->Frm().Width() > 50000) ||
                             (Prt().Width() > 50000) )
                        {
                            double nNewWidthTmp =
                                ( double(pLowerFrm->Frm().Width())
                                  * double(Prt().Width()) )
                                / double(rOldSize.Width());
                            nNewWidth = SwTwips(nNewWidthTmp);
                        }
                        else
                        {
                            nNewWidth =
                                (pLowerFrm->Frm().Width() * Prt().Width()) / rOldSize.Width();
                        }
                        pLowerFrm->Frm().Width( nNewWidth );
                    }
                }
                if ( bHeightChgd )
                {
                    if( nLowerType & nFixHeight )
                    {
                        // Considering previous conditions:
                        // In vertical layout set height of foot note and
                        // no-text frames to its upper height.
                        // In horizontal layout set height of column frames
                        // to its upper height.
                        pLowerFrm->Frm().Height( Prt().Height() );
                    }
                    // OD 01.10.2002 #102211#
                    // add conditions <!pLowerFrm->IsHeaderFrm()> and
                    // <!pLowerFrm->IsFooterFrm()> in order to avoid that
                    // the <Grow> of header or footer are overwritten.
                    // NOTE: Height of header/footer frame is determined by contents.
                    else if ( rOldSize.Height() &&
                              !pLowerFrm->IsFtnFrm() &&
                              !pLowerFrm->IsHeaderFrm() &&
                              !pLowerFrm->IsFooterFrm()
                            )
                    {
                        // Adjust frame height proportional, if lower isn't a
                        // foot note, a header or a footer frame and
                        // condition <nLowerType & nFixHeight> isn't true.
                        // Considering previous conditions:
                        // In vertical layout these are column, foot note container,
                        // body and no-text frames.
                        // In horizontal layout these are column, foot note
                        // container, body and no-text frames.

                        // OD 29.10.2002 #97265# - special case for page lowers
                        // The page lowers that have to be adjusted on page height
                        // change are the body frame and the foot note container
                        // frame.
                        // In vertical layout the height of both is directly
                        // adjusted to the page height change.
                        // In horizontal layout the height of the body frame is
                        // directly adjsuted to the page height change and the
                        // foot note frame height isn't touched, because its
                        // determined by its content.
                        // OD 31.03.2003 #108446# - apply special case for page
                        // lowers - see description above - also for section columns.
                        if ( IsPageFrm() ||
                             ( IsColumnFrm() && IsInSct() )
                           )
                        {
                            ASSERT( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm(),
                                    "ChgLowersProp - only for body or foot note container" );
                            if ( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm() )
                            {
                                if ( IsVertical() || pLowerFrm->IsBodyFrm() )
                                {
                                    SwTwips nNewHeight =
                                            pLowerFrm->Frm().Height() +
                                            ( Prt().Height() - rOldSize.Height() );
                                    if ( nNewHeight < 0)
                                    {
                                        // OD 01.04.2003 #108446# - adjust assertion condition and text
                                        ASSERT( !( IsPageFrm() &&
                                                   (pLowerFrm->Frm().Height()>0) &&
                                                   (pLowerFrm->IsValid()) ),
                                                    "ChgLowersProg - negative height for lower.");
                                        nNewHeight = 0;
                                    }
                                    pLowerFrm->Frm().Height( nNewHeight );
                                }
                            }
                        }
                        else
                        {
                            SwTwips nNewHeight;
                            // OD 24.10.2002 #97265# - <double> calculation
                            // Perform <double> calculation of new height, if
                            // one of the coefficients is greater than 50000
                            if ( (pLowerFrm->Frm().Height() > 50000) ||
                                 (Prt().Height() > 50000) )
                            {
                                double nNewHeightTmp =
                                    ( double(pLowerFrm->Frm().Height())
                                      * double(Prt().Height()) )
                                    / double(rOldSize.Height());
                                nNewHeight = SwTwips(nNewHeightTmp);
                            }
                            else
                            {
                                nNewHeight = ( pLowerFrm->Frm().Height()
                                             * Prt().Height() ) / rOldSize.Height();
                            }
                            if( !pLowerFrm->GetNext() )
                            {
                                SwTwips nSum = Prt().Height();
                                SwFrm* pTmp = Lower();
                                while( pTmp->GetNext() )
                                {
                                    if( !pTmp->IsFtnContFrm() || !pTmp->IsVertical() )
                                        nSum -= pTmp->Frm().Height();
                                    pTmp = pTmp->GetNext();
                                }
                                if( nSum - nNewHeight == 1 &&
                                    nSum == pLowerFrm->Frm().Height() )
                                    nNewHeight = nSum;
                            }
                            pLowerFrm->Frm().Height( nNewHeight );
                        }
                    }
                }
            }
        } // end of else { NOT text frame }

        pLowerFrm->_InvalidateAll();
        if ( bInvaPageForCntnt && pLowerFrm->IsCntntFrm() )
        {
            pLowerFrm->InvalidatePage();
            bInvaPageForCntnt = false;
        }

        if ( !pLowerFrm->GetNext() && pLowerFrm->IsRetoucheFrm() )
		{
			//Wenn ein Wachstum stattgefunden hat, und die untergeordneten
			//zur Retouche faehig sind (derzeit Tab, Section und Cntnt), so
			//trigger ich sie an.
			if ( rOldSize.Height() < Prt().SSize().Height() ||
				 rOldSize.Width() < Prt().SSize().Width() )
                pLowerFrm->SetRetouche();
		}
        pLowerFrm = pLowerFrm->GetNext();
	}

    // Finally adjust the columns if width is set to auto
    // Possible optimisation: execute this code earlier in this function and
    // return???
    if ( ( (bVert && bHeightChgd) || (! bVert && bWidthChgd) ) &&
           Lower()->IsColumnFrm() )
    {
        // get column attribute
	    const SwFmtCol* pColAttr = NULL;
        if ( IsPageBodyFrm() )
        {
            ASSERT( GetUpper()->IsPageFrm(), "Upper is not page frame" )
            pColAttr = &GetUpper()->GetFmt()->GetCol();
        }
        else
        {
            ASSERT( IsFlyFrm() || IsSctFrm(), "Columns not in fly or section" )
            pColAttr = &GetFmt()->GetCol();
		}

		if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
            AdjustColumns( pColAttr, sal_False );
	}
}

/*************************************************************************
|*
|*	SwLayoutFrm::Format()
|*
|*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea.
|*						Die Fixsize wird hier nicht eingestellt.
|*	Ersterstellung		MA 28. Jul. 92
|*	Letzte Aenderung	MA 21. Mar. 95
|*
|*************************************************************************/
void SwLayoutFrm::Format( const SwBorderAttrs *pAttrs )
{
	ASSERT( pAttrs, "LayoutFrm::Format, pAttrs ist 0." );

	if ( bValidPrtArea && bValidSize )
		return;

    const sal_uInt16 nLeft = (sal_uInt16)pAttrs->CalcLeft( this );
    const sal_uInt16 nUpper = pAttrs->CalcTop();

    const sal_uInt16 nRight = (sal_uInt16)((SwBorderAttrs*)pAttrs)->CalcRight( this );
    const sal_uInt16 nLower = pAttrs->CalcBottom();
    sal_Bool bVert = IsVertical() && !IsPageFrm();
    //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;    
	if ( !bValidPrtArea )
	{
		bValidPrtArea = sal_True;
        (this->*fnRect->fnSetXMargins)( nLeft, nRight );
        (this->*fnRect->fnSetYMargins)( nUpper, nLower );
	}

	if ( !bValidSize )
	{
        if ( !HasFixSize() )
		{
            const SwTwips nBorder = nUpper + nLower;
			const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
            SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? rSz.GetHeight() : 0;
			do
			{	bValidSize = sal_True;

				//Die Groesse in der VarSize wird durch den Inhalt plus den
				//Raendern bestimmt.
				SwTwips nRemaining = 0;
				SwFrm *pFrm = Lower();
				while ( pFrm )
                {   nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
					if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
					// Dieser TxtFrm waere gern ein bisschen groesser
						nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
                                      - (pFrm->Prt().*fnRect->fnGetHeight)();
					else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
						nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
					pFrm = pFrm->GetNext();
				}
				nRemaining += nBorder;
				nRemaining = Max( nRemaining, nMinHeight );
                const SwTwips nDiff = nRemaining-(Frm().*fnRect->fnGetHeight)();
                const long nOldLeft = (Frm().*fnRect->fnGetLeft)();
                const long nOldTop = (Frm().*fnRect->fnGetTop)();
				if ( nDiff )
				{
					if ( nDiff > 0 )
                        Grow( nDiff );
					else
                        Shrink( -nDiff );
					//Schnell auf dem kurzen Dienstweg die Position updaten.
					MakePos();
				}
				//Unterkante des Uppers nicht ueberschreiten.
                if ( GetUpper() && (Frm().*fnRect->fnGetHeight)() )
				{
                    const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
                    if( (this->*fnRect->fnSetLimit)( nLimit ) &&
                        nOldLeft == (Frm().*fnRect->fnGetLeft)() &&
                        nOldTop  == (Frm().*fnRect->fnGetTop)() )
                        bValidSize = bValidPrtArea = sal_True;
				}
			} while ( !bValidSize );
		}
		else if ( GetType() & 0x0018 )
		{
			do
			{	if ( Frm().Height() != pAttrs->GetSize().Height() )
					ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
				bValidSize = sal_True;
				MakePos();
			} while ( !bValidSize );
		}
		else
			bValidSize = sal_True;
	}
}

/*************************************************************************
|*
|*	SwLayoutFrm::InvalidatePercentLowers()
|*
|*	Ersterstellung		MA 13. Jun. 96
|*	Letzte Aenderung	MA 13. Jun. 96
|*
|*************************************************************************/
static void InvaPercentFlys( SwFrm *pFrm, SwTwips nDiff )
{
	ASSERT( pFrm->GetDrawObjs(), "Can't find any Objects" );
	for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
	{
        SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
        if ( pAnchoredObj->ISA(SwFlyFrm) )
		{
            SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
			const SwFmtFrmSize &rSz = pFly->GetFmt()->GetFrmSize();
			if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
            {
                sal_Bool bNotify = sal_True;
                // If we've a fly with more than 90% relative height...
                if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrm() &&
                    rSz.GetHeightPercent() != 0xFF && nDiff )
                {
                    const SwFrm *pRel = pFly->IsFlyLayFrm() ? pFly->GetAnchorFrm():
                                        pFly->GetAnchorFrm()->GetUpper();
                    // ... and we have already more than 90% height and we
                    // not allow the text to go through...
                    // then a notifycation could cause an endless loop, e.g.
                    // 100% height and no text wrap inside a cell of a table.
                    if( pFly->Frm().Height()*10 >
                        ( nDiff + pRel->Prt().Height() )*9 &&
                        pFly->GetFmt()->GetSurround().GetSurround() !=
                        SURROUND_THROUGHT )
                       bNotify = sal_False;
                }
                if( bNotify )
                    pFly->InvalidateSize();
            }
		}
	}
}

void SwLayoutFrm::InvaPercentLowers( SwTwips nDiff )
{
	if ( GetDrawObjs() )
        ::InvaPercentFlys( this, nDiff );

	SwFrm *pFrm = ContainsCntnt();
	if ( pFrm )
		do
		{
			if ( pFrm->IsInTab() && !IsTabFrm() )
			{
				SwFrm *pTmp = pFrm->FindTabFrm();
				ASSERT( pTmp, "Where's my TabFrm?" );
				if( IsAnLower( pTmp ) )
					pFrm = pTmp;
			}

			if ( pFrm->IsTabFrm() )
			{
				const SwFmtFrmSize &rSz = ((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize();
				if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
					pFrm->InvalidatePrt();
			}
			else if ( pFrm->GetDrawObjs() )
                ::InvaPercentFlys( pFrm, nDiff );
			pFrm = pFrm->FindNextCnt();
		} while ( pFrm && IsAnLower( pFrm ) ) ;
}

/*************************************************************************
|*
|*	SwLayoutFrm::CalcRel()
|*
|*	Ersterstellung		MA 13. Jun. 96
|*	Letzte Aenderung	MA 10. Oct. 96
|*
|*************************************************************************/
long SwLayoutFrm::CalcRel( const SwFmtFrmSize &rSz, sal_Bool ) const
{
    long nRet     = rSz.GetWidth(),
		 nPercent = rSz.GetWidthPercent();

	if ( nPercent )
	{
		const SwFrm *pRel = GetUpper();
		long nRel = LONG_MAX;
		const ViewShell *pSh = getRootFrm()->GetCurrShell();
        const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        if( pRel->IsPageBodyFrm() && pSh && bBrowseMode && pSh->VisArea().Width() )
		{
			nRel = pSh->GetBrowseWidth();
			long nDiff = nRel - pRel->Prt().Width();
			if ( nDiff > 0 )
				nRel -= nDiff;
		}
		nRel = Min( nRel, pRel->Prt().Width() );
		nRet = nRel * nPercent / 100;
	}
	return nRet;
}

/*************************************************************************
|*  Local helpers for SwLayoutFrm::FormatWidthCols()
|*************************************************************************/
long MA_FASTCALL lcl_CalcMinColDiff( SwLayoutFrm *pLayFrm )
{
	long nDiff = 0, nFirstDiff = 0;
	SwLayoutFrm *pCol = (SwLayoutFrm*)pLayFrm->Lower();
	ASSERT( pCol, "Where's the columnframe?" );
	SwFrm *pFrm = pCol->Lower();
	do
    {
        if( pFrm && pFrm->IsBodyFrm() )
            pFrm = ((SwBodyFrm*)pFrm)->Lower();
        if ( pFrm && pFrm->IsTxtFrm() )
		{
			const long nTmp = ((SwTxtFrm*)pFrm)->FirstLineHeight();
			if ( nTmp != USHRT_MAX )
			{
				if ( pCol == pLayFrm->Lower() )
					nFirstDiff = nTmp;
				else
					nDiff = nDiff ? Min( nDiff, nTmp ) : nTmp;
			}
		}
		//Leere Spalten ueberspringen!
		pCol = (SwLayoutFrm*)pCol->GetNext();
		while ( pCol && 0 == (pFrm = pCol->Lower()) )
			pCol = (SwLayoutFrm*)pCol->GetNext();

	} while ( pFrm && pCol );

	return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
}

sal_Bool lcl_IsFlyHeightClipped( SwLayoutFrm *pLay )
{
	SwFrm *pFrm = pLay->ContainsCntnt();
	while ( pFrm )
    {
        if ( pFrm->IsInTab() )
			pFrm = pFrm->FindTabFrm();

		if ( pFrm->GetDrawObjs() )
		{
            sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
			for ( sal_uInt16 i = 0; i < nCnt; ++i )
			{
                SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
                if ( pAnchoredObj->ISA(SwFlyFrm) )
                {
                    SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
                    if ( pFly->IsHeightClipped() &&
                         ( !pFly->IsFlyFreeFrm() || pFly->GetPageFrm() ) )
                        return sal_True;
                }
			}
		}
		pFrm = pFrm->FindNextCnt();
	}
	return sal_False;
}

/*************************************************************************
|*  SwLayoutFrm::FormatWidthCols()
|*************************************************************************/
void SwLayoutFrm::FormatWidthCols( const SwBorderAttrs &rAttrs,
                                   const SwTwips nBorder, const SwTwips nMinHeight )
{
	//Wenn Spalten im Spiel sind, so wird die Groesse an der
	//letzten Spalte ausgerichtet.
	//1. Inhalt formatieren.
	//2. Hoehe der letzten Spalte ermitteln, wenn diese zu
	//	 zu gross ist muss der Fly wachsen.
	//	 Der Betrag um den der Fly waechst ist aber nicht etwa
	//	 der Betrag des Ueberhangs, denn wir muessen davon
	//	 ausgehen, dass etwas Masse zurueckfliesst und so
	//	 zusaetzlicher Platz geschaffen wird.
	//	 Im Ersten Ansatz ist der Betrag um den gewachsen wird
	//	 der Ueberhang geteilt durch die Spaltenanzahl oder
	//	 der Ueberhang selbst wenn er kleiner als die Spalten-
	//	 anzahl ist.
	//3. Weiter mit 1. bis zur Stabilitaet.

	const SwFmtCol &rCol = rAttrs.GetAttrSet().GetCol();
	const sal_uInt16 nNumCols = rCol.GetNumCols();

	sal_Bool bEnd = sal_False;
	sal_Bool bBackLock = sal_False;
	ViewShell *pSh = getRootFrm()->GetCurrShell();
	SwViewImp *pImp = pSh ? pSh->Imp() : 0;
	{
		// Zugrunde liegender Algorithmus
		// Es wird versucht, eine optimale Hoehe fuer die Spalten zu finden.
		// nMinimum beginnt mit der uebergebenen Mindesthoehe und wird dann als
		// Maximum der Hoehen gepflegt, bei denen noch Spalteninhalt aus einer
		// Spalte herausragt.
		// nMaximum beginnt bei LONG_MAX und wird als Minimum der Hoehen gepflegt,
		// bei denen der Inhalt gepasst hat.
		// Bei spaltigen Bereichen beginnt nMaximum bei dem maximalen Wert, den
		// die Umgebung vorgibt, dies kann natuerlich ein Wert sein, bei dem noch
		// Inhalt heraushaengt.
		// Es werden die Spalten formatiert, wenn Inhalt heraushaengt, wird nMinimum
		// ggf. angepasst, dann wird gewachsen, mindestens um nMinDiff, aber nicht ueber
		// ein groesseres nMaximum hinaus. Wenn kein Inhalt heraushaengt, sondern
		// noch Luft in einer Spalte ist, schrumpfen wir entsprechend, mindestens um
		// nMinDiff, aber nicht unter das nMinimum.
		// Abgebrochen wird, wenn kein Inhalt mehr heraushaengt und das Minimum sich auf
		// weniger als ein MinDiff dem Maximum angenaehert hat oder das von der
		// Umgebung vorgegebene Maximum erreicht ist und trotzdem Inhalt heraus-
		// haengt.

		// Kritik an der Implementation
		// 1. Es kann theoretisch Situationen geben, in denen der Inhalt in einer geringeren
		// Hoehe passt und in einer groesseren Hoehe nicht passt. Damit der Code robust
		// gegen solche Verhaeltnisse ist, sind ein paar Abfragen bezgl. Minimum und Maximum
		// drin, die wahrscheinlich niemals zuschlagen koennen.
		// 2. Es wird fuer das Schrumpfen das gleiche nMinDiff benutzt wie fuer das Wachstum,
		// das nMinDiff ist allerdings mehr oder weniger die kleinste erste Zeilenhoehe und
		// als Mindestwert fuer das Schrumpfen nicht unbedingt optimal.

		long nMinimum = nMinHeight;
		long nMaximum;
		sal_Bool bNoBalance = sal_False;
        SWRECTFN( this )
		if( IsSctFrm() )
		{
            nMaximum = (Frm().*fnRect->fnGetHeight)() - nBorder +
                       (Frm().*fnRect->fnBottomDist)(
                                        (GetUpper()->*fnRect->fnGetPrtBottom)() );
            nMaximum += GetUpper()->Grow( LONG_MAX, sal_True );
			if( nMaximum < nMinimum )
			{
				if( nMaximum < 0 )
					nMinimum = nMaximum = 0;
				else
					nMinimum = nMaximum;
			}
			if( nMaximum > BROWSE_HEIGHT )
				nMaximum = BROWSE_HEIGHT;

			bNoBalance = ((SwSectionFrm*)this)->GetSection()->GetFmt()->
						 GetBalancedColumns().GetValue();
			SwFrm* pAny = ContainsAny();
			if( bNoBalance ||
                ( !(Frm().*fnRect->fnGetHeight)() && pAny ) )
			{
                long nTop = (this->*fnRect->fnGetTopMargin)();
                // --> OD 2004-11-01 #i23129# - correction: enlarge section
                // to the calculated maximum height.
                (Frm().*fnRect->fnAddBottom)( nMaximum -
                                              (Frm().*fnRect->fnGetHeight)() );
                // <--
                if( nTop > nMaximum )
                    nTop = nMaximum;
                (this->*fnRect->fnSetYMargins)( nTop, 0 );
			}
			if( !pAny && !((SwSectionFrm*)this)->IsFtnLock() )
			{
				SwFtnContFrm* pFtnCont = ((SwSectionFrm*)this)->ContainsFtnCont();
				if( pFtnCont )
				{
					SwFrm* pFtnAny = pFtnCont->ContainsAny();
					if( pFtnAny && pFtnAny->IsValid() )
					{
						bBackLock = sal_True;
						((SwSectionFrm*)this)->SetFtnLock( sal_True );
					}
				}
			}
        }
		else
			nMaximum = LONG_MAX;

        // --> OD 2004-08-25 #i3317# - reset temporarly consideration
        // of wrapping style influence
        SwPageFrm* pPageFrm = FindPageFrm();
        SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
        if ( pObjs )
        {
            sal_uInt32 i = 0;
            for ( i = 0; i < pObjs->Count(); ++i )
            {
                SwAnchoredObject* pAnchoredObj = (*pObjs)[i];

                if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
                {
                    pAnchoredObj->SetTmpConsiderWrapInfluence( false );
                }
            }
        }
        // <--
        do
		{
			//Kann eine Weile dauern, deshalb hier auf Waitcrsr pruefen.
			if ( pImp )
				pImp->CheckWaitCrsr();

			bValidSize = sal_True;
			//Erstmal die Spalten formatieren, das entlastet den
			//Stack ein wenig.
			//Bei der Gelegenheit stellen wir auch gleich mal die
			//Breiten und Hoehen der Spalten ein (so sie denn falsch sind).
			SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();

            // --> FME 2004-07-19 #i27399#
            // Simply setting the column width based on the values returned by
            // CalcColWidth does not work for automatic column width.
            AdjustColumns( &rCol, sal_False );
            // <--

            for ( sal_uInt16 i = 0; i < nNumCols; ++i )
			{
                pCol->Calc();
				// ColumnFrms besitzen jetzt einen BodyFrm, der auch kalkuliert werden will
				pCol->Lower()->Calc();
				if( pCol->Lower()->GetNext() )
					pCol->Lower()->GetNext()->Calc();  // SwFtnCont
				pCol = (SwLayoutFrm*)pCol->GetNext();
            }

            ::CalcCntnt( this );

			pCol = (SwLayoutFrm*)Lower();
			ASSERT( pCol && pCol->GetNext(), ":-( Spalten auf Urlaub?");
			// bMinDiff wird gesetzt, wenn es keine leere Spalte gibt
			sal_Bool bMinDiff = sal_True;
            // OD 28.03.2003 #108446# - check for all column content and all columns
            while ( bMinDiff && pCol )
            {
                bMinDiff = 0 != pCol->ContainsCntnt();
                pCol = (SwLayoutFrm*)pCol->GetNext();
            }
			pCol = (SwLayoutFrm*)Lower();
            // OD 28.03.2003 #108446# - initialize local variable
            SwFrm *pLow = NULL;
			SwTwips nDiff = 0;
			SwTwips nMaxFree = 0;
			SwTwips nAllFree = LONG_MAX;
			// bFoundLower wird gesetzt, wenn es mind. eine nichtleere Spalte gibt
			sal_Bool bFoundLower = sal_False;
			while( pCol )
			{
				SwLayoutFrm* pLay = (SwLayoutFrm*)pCol->Lower();
                SwTwips nInnerHeight = (pLay->Frm().*fnRect->fnGetHeight)() -
                                       (pLay->Prt().*fnRect->fnGetHeight)();
				if( pLay->Lower() )
				{
					bFoundLower = sal_True;
					nInnerHeight += pLay->InnerHeight();
				}
				else if( nInnerHeight < 0 )
					nInnerHeight = 0;

				if( pLay->GetNext() )
				{
					bFoundLower = sal_True;
					pLay = (SwLayoutFrm*)pLay->GetNext();
					ASSERT( pLay->IsFtnContFrm(),"FtnContainer exspected" );
					nInnerHeight += pLay->InnerHeight();
                    nInnerHeight += (pLay->Frm().*fnRect->fnGetHeight)() -
                                    (pLay->Prt().*fnRect->fnGetHeight)();
				}
                nInnerHeight -= (pCol->Prt().*fnRect->fnGetHeight)();
				if( nInnerHeight > nDiff )
				{
					nDiff = nInnerHeight;
					nAllFree = 0;
				}
				else
				{
					if( nMaxFree < -nInnerHeight )
						nMaxFree = -nInnerHeight;
					if( nAllFree > -nInnerHeight )
						nAllFree = -nInnerHeight;
				}
				pCol = (SwLayoutFrm*)pCol->GetNext();
			}

			if ( bFoundLower || ( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() ) )
			{
				SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
				// Hier wird entschieden, ob wir wachsen muessen, naemlich wenn
				// ein Spalteninhalt (nDiff) oder ein Fly herausragt.
				// Bei spaltigen Bereichen wird beruecksichtigt, dass mit dem
				// Besitz eines nichtleeren Follows die Groesse festgelegt ist.
				if ( nDiff || ::lcl_IsFlyHeightClipped( this ) ||
					 ( IsSctFrm() && ((SwSectionFrm*)this)->CalcMinDiff( nMinDiff ) ) )
				{
                    long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
					// Das Minimum darf nicht kleiner sein als unsere PrtHeight,
					// solange noch etwas herausragt.
                    if( nMinimum < nPrtHeight )
                        nMinimum = nPrtHeight;
					// Es muss sichergestellt sein, dass das Maximum nicht kleiner
					// als die PrtHeight ist, wenn noch etwas herausragt
                    if( nMaximum < nPrtHeight )
                        nMaximum = nPrtHeight;  // Robust, aber kann das ueberhaupt eintreten?
					if( !nDiff ) // wenn nur Flys herausragen, wachsen wir um nMinDiff
						nDiff = nMinDiff;
					// Wenn wir um mehr als nMinDiff wachsen wollen, wird dies auf die
					// Spalten verteilt
					if ( Abs(nDiff - nMinDiff) > nNumCols && nDiff > (long)nNumCols )
						nDiff /= nNumCols;

					if ( bMinDiff )
					{   // Wenn es keinen leeren Spalten gibt, wollen wir mind. um nMinDiff
						// wachsen. Sonderfall: Wenn wir kleiner als die minimale Frmhoehe
						// sind und die PrtHeight kleiner als nMinDiff ist, wachsen wir so,
						// dass die PrtHeight hinterher genau nMinDiff ist.
                        long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
                        if ( nFrmHeight > nMinHeight || nPrtHeight >= nMinDiff )
							nDiff = Max( nDiff, nMinDiff );
						else if( nDiff < nMinDiff )
                            nDiff = nMinDiff - nPrtHeight + 1;
					}
					// nMaximum ist eine Groesse, in der der Inhalt gepasst hat,
					// oder der von der Umgebung vorgegebene Wert, deshalb
					// brauchen wir nicht ueber diesen Wrt hinauswachsen.
                    if( nDiff + nPrtHeight > nMaximum )
                        nDiff = nMaximum - nPrtHeight;
				}
				else if( nMaximum > nMinimum ) // Wir passen, haben wir auch noch Spielraum?
				{
                    long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
                    if ( nMaximum < nPrtHeight )
                        nDiff = nMaximum - nPrtHeight; // wir sind ueber eine funktionierende
						// Hoehe hinausgewachsen und schrumpfen wieder auf diese zurueck,
						// aber kann das ueberhaupt eintreten?
					else
					{   // Wir haben ein neues Maximum, eine Groesse, fuer die der Inhalt passt.
                        nMaximum = nPrtHeight;
						// Wenn der Freiraum in den Spalten groesser ist als nMinDiff und wir
						// nicht dadurch wieder unter das Minimum rutschen, wollen wir ein wenig
						// Luft herauslassen.
                        if ( !bNoBalance &&
                             // --> OD 2004-11-04 #i23129# - <nMinDiff> can be
                             // big, because of an object at the beginning of
                             // a column. Thus, decrease optimization here.
                             //nMaxFree >= nMinDiff &&
                             nMaxFree > 0 &&
                             // <--
                             ( !nAllFree ||
                               nMinimum < nPrtHeight - nMinDiff ) )
						{
							nMaxFree /= nNumCols; // auf die Spalten verteilen
							nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // mind. nMinDiff
                            if( nPrtHeight + nDiff <= nMinimum ) // Unter das Minimum?
								nDiff = ( nMinimum - nMaximum ) / 2; // dann lieber die Mitte
						}
						else if( nAllFree )
						{
							nDiff = -nAllFree;
                            if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
								nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
						}
					}
				}
				if( nDiff ) // jetzt wird geschrumpft oder gewachsen..
				{
					Size aOldSz( Prt().SSize() );
                    long nTop = (this->*fnRect->fnGetTopMargin)();
                    nDiff = (Prt().*fnRect->fnGetHeight)() + nDiff + nBorder -
                            (Frm().*fnRect->fnGetHeight)();
                    (Frm().*fnRect->fnAddBottom)( nDiff );
                    // --> OD 2006-08-16 #i68520#
                    if ( dynamic_cast<SwFlyFrm*>(this) )
                    {
                        dynamic_cast<SwFlyFrm*>(this)->InvalidateObjRectWithSpaces();
                    }
                    // <--
                    (this->*fnRect->fnSetYMargins)( nTop, nBorder - nTop );
					ChgLowersProp( aOldSz );
                    NotifyLowerObjs();

                    // --> OD 2004-08-25 #i3317# - reset temporarly consideration
                    // of wrapping style influence
                    SwPageFrm* pTmpPageFrm = FindPageFrm();
                    SwSortedObjs* pTmpObjs = pTmpPageFrm ? pTmpPageFrm->GetSortedObjs() : 0L;
                    if ( pTmpObjs )
                    {
                        sal_uInt32 i = 0;
                        for ( i = 0; i < pTmpObjs->Count(); ++i )
                        {
                            SwAnchoredObject* pAnchoredObj = (*pTmpObjs)[i];

                            if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
                            {
                                pAnchoredObj->SetTmpConsiderWrapInfluence( false );
                            }
                        }
                    }
                    // <--
					//Es muss geeignet invalidiert werden, damit
					//sich die Frms huebsch ausbalancieren
					//- Der jeweils erste ab der zweiten Spalte bekommt
					//	ein InvalidatePos();
					pCol = (SwLayoutFrm*)Lower()->GetNext();
					while ( pCol )
					{
						pLow = pCol->Lower();
						if ( pLow )
							pLow->_InvalidatePos();
						pCol = (SwLayoutFrm*)pCol->GetNext();
					}
					if( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() )
					{
						// Wenn wir einen Follow erzeugt haben, muessen wir
						// seinem Inhalt die Chance geben, im CalcCntnt
						// zurueckzufliessen
						SwCntntFrm* pTmpCntnt =
							((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
						if( pTmpCntnt )
							pTmpCntnt->_InvalidatePos();
					}
				}
				else
					bEnd = sal_True;
			}
			else
				bEnd = sal_True;

		} while ( !bEnd || !bValidSize );
	}
    // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
    // 2nd parameter to <true>.
    ::CalcCntnt( this, true );
	if( IsSctFrm() )
	{
        // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
        ::CalcCntnt( this, true );
		if( bBackLock )
			((SwSectionFrm*)this)->SetFtnLock( sal_False );
	}
}


/*************************************************************************
|*
|*	SwRootFrm::InvalidateAllCntnt()
|*
|*	Ersterstellung		MA 13. Feb. 98
|*	Letzte Aenderung	MA 12. Aug. 00
|*
|*************************************************************************/

SwCntntFrm* lcl_InvalidateSection( SwFrm *pCnt, sal_uInt8 nInv )
{
	SwSectionFrm* pSect = pCnt->FindSctFrm();
	// Wenn unser CntntFrm in einer Tabelle oder Fussnote steht, sind nur
	// Bereiche gemeint, die ebenfalls innerhalb liegen.
	// Ausnahme: Wenn direkt eine Tabelle uebergeben wird.
	if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
		( pCnt->IsInFtn() && !pSect->IsInFtn() ) ) && !pCnt->IsTabFrm() )
		return NULL;
	if( nInv & INV_SIZE )
		pSect->_InvalidateSize();
	if( nInv & INV_POS )
		pSect->_InvalidatePos();
	if( nInv & INV_PRTAREA )
		pSect->_InvalidatePrt();
	SwFlowFrm *pFoll = pSect->GetFollow();
	// Temporary separation from follow
	pSect->SetFollow( NULL );
	SwCntntFrm* pRet = pSect->FindLastCntnt();
	pSect->SetFollow( pFoll );
	return pRet;
}

SwCntntFrm* lcl_InvalidateTable( SwTabFrm *pTable, sal_uInt8 nInv )
{
	if( ( nInv & INV_SECTION ) && pTable->IsInSct() )
		lcl_InvalidateSection( pTable, nInv );
	if( nInv & INV_SIZE )
		pTable->_InvalidateSize();
	if( nInv & INV_POS )
		pTable->_InvalidatePos();
	if( nInv & INV_PRTAREA )
		pTable->_InvalidatePrt();
	return pTable->FindLastCntnt();
}

void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv );

void lcl_InvalidateCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
{
	SwCntntFrm *pLastTabCnt = NULL;
	SwCntntFrm *pLastSctCnt = NULL;
	while ( pCnt )
	{
		if( nInv & INV_SECTION )
		{
			if( pCnt->IsInSct() )
			{
				// Siehe oben bei Tabellen
				if( !pLastSctCnt )
					pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
				if( pLastSctCnt == pCnt )
					pLastSctCnt = NULL;
			}
#ifdef DBG_UTIL
			else
				ASSERT( !pLastSctCnt, "Where's the last SctCntnt?" );
#endif
		}
		if( nInv & INV_TABLE )
		{
			if( pCnt->IsInTab() )
			{
				// Um nicht fuer jeden CntntFrm einer Tabelle das FindTabFrm() zu rufen
				// und wieder die gleiche Tabelle zu invalidieren, merken wir uns den letzten
				// CntntFrm der Tabelle und reagieren erst wieder auf IsInTab(), wenn wir
				// an diesem vorbei sind.
				// Beim Eintritt in die Tabelle wird der LastSctCnt auf Null gesetzt,
				// damit Bereiche im Innern der Tabelle richtig invalidiert werden.
				// Sollte die Tabelle selbst in einem Bereich stehen, so wird an
				// diesem die Invalidierung bis zu dreimal durchgefuehrt, das ist vertretbar.
				if( !pLastTabCnt )
				{
					pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrm(), nInv );
					pLastSctCnt = NULL;
				}
				if( pLastTabCnt == pCnt )
				{
					pLastTabCnt = NULL;
					pLastSctCnt = NULL;
				}
			}
#ifdef DBG_UTIL
			else
				ASSERT( !pLastTabCnt, "Where's the last TabCntnt?" );
#endif
		}

		if( nInv & INV_SIZE )
			pCnt->Prepare( PREP_CLEAR, 0, sal_False );
		if( nInv & INV_POS )
			pCnt->_InvalidatePos();
		if( nInv & INV_PRTAREA )
			pCnt->_InvalidatePrt();
		if ( nInv & INV_LINENUM )
			pCnt->InvalidateLineNum();
		if ( pCnt->GetDrawObjs() )
			lcl_InvalidateAllCntnt( pCnt, nInv );
		pCnt = pCnt->GetNextCntntFrm();
	}
}

void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
{
    SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
	for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
	{
        SwAnchoredObject* pAnchoredObj = rObjs[i];
        if ( pAnchoredObj->ISA(SwFlyFrm) )
		{
            SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
			if ( pFly->IsFlyInCntFrm() )
            {
				::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
                if( nInv & INV_DIRECTION )
                    pFly->CheckDirChange();
            }
		}
	}
}

void SwRootFrm::InvalidateAllCntnt( sal_uInt8 nInv )
{
	// Erst werden alle Seitengebundenen FlyFrms abgearbeitet.
	SwPageFrm *pPage = (SwPageFrm*)Lower();
	while( pPage )
	{
		pPage->InvalidateFlyLayout();
		pPage->InvalidateFlyCntnt();
		pPage->InvalidateFlyInCnt();
		pPage->InvalidateLayout();
		pPage->InvalidateCntnt();
		pPage->InvalidatePage( pPage ); //Damit ggf. auch der Turbo verschwindet

		if ( pPage->GetSortedObjs() )
		{
            const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
			for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
			{
                SwAnchoredObject* pAnchoredObj = rObjs[i];
                if ( pAnchoredObj->ISA(SwFlyFrm) )
                {
                    SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
                    ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
                    if ( nInv & INV_DIRECTION )
                        pFly->CheckDirChange();
                }
			}
		}
        if( nInv & INV_DIRECTION )
            pPage->CheckDirChange();
		pPage = (SwPageFrm*)(pPage->GetNext());
	}

	//Hier den gesamten Dokumentinhalt und die zeichengebundenen Flys.
	::lcl_InvalidateCntnt( ContainsCntnt(), nInv );

	if( nInv & INV_PRTAREA )
	{
		ViewShell *pSh  = getRootFrm()->GetCurrShell();
		if( pSh )
			pSh->InvalidateWindows( Frm() );
	}
}

/** method to invalidate/re-calculate the position of all floating
    screen objects (Writer fly frames and drawing objects), which are
    anchored to paragraph or to character.

    OD 2004-03-16 #i11860#

    @author OD
*/
void SwRootFrm::InvalidateAllObjPos()
{
    const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>(Lower());
    while( pPageFrm )
    {
        pPageFrm->InvalidateFlyLayout();

        if ( pPageFrm->GetSortedObjs() )
        {
            const SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
            for ( sal_uInt8 i = 0; i < rObjs.Count(); ++i )
            {
                SwAnchoredObject* pAnchoredObj = rObjs[i];
                const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
                if ((rAnch.GetAnchorId() != FLY_AT_PARA) &&
                    (rAnch.GetAnchorId() != FLY_AT_CHAR))
                {
                    // only to paragraph and to character anchored objects are considered.
                    continue;
                }
                // --> OD 2004-07-07 #i28701# - special invalidation for anchored
                // objects, whose wrapping style influence has to be considered.
                if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
                    pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
                else
                    pAnchoredObj->InvalidateObjPos();
                // <--
            }
        }

        pPageFrm = static_cast<const SwPageFrm*>(pPageFrm->GetNext());
    }
}