/**************************************************************
 * 
 * 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 <svl/smplhint.hxx>
#include <svl/itemiter.hxx>
#include <hints.hxx>
#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <fmtclbl.hxx>
#include "sectfrm.hxx"
#include "section.hxx"		// SwSection
#include "frmtool.hxx"		// StackHack
#include "doc.hxx"			// SwDoc
#include "cntfrm.hxx"		// SwCntntFrm
#include "rootfrm.hxx"		// SwRootFrm
#include "pagefrm.hxx"		// SwPageFrm
#include "fmtpdsc.hxx"		// SwFmtPageDesc
#include "fmtcntnt.hxx"		// SwFmtCntnt
#include "ndindex.hxx"		// SwNodeIndex
#include "ftnidx.hxx"
#include "txtfrm.hxx"		// SwTxtFrm
#include "fmtclds.hxx"		// SwFmtCol
#include "colfrm.hxx"		// SwColumnFrm
#include "tabfrm.hxx"		// SwTabFrm
#include "flyfrm.hxx"		// SwFlyFrm
#include "ftnfrm.hxx"		// SwFtnFrm
#include "layouter.hxx"		// SwLayouter
#include "dbg_lay.hxx"
#include "viewsh.hxx"
#include "viewopt.hxx"
#include "viewimp.hxx"
#include <editeng/ulspitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/brshitem.hxx>
#include <fmtftntx.hxx>
// OD 2004-05-24 #i28701#
#include <dflyobj.hxx>
#include <flyfrms.hxx>
#include <sortedobjs.hxx>

SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )

/*************************************************************************
|*
|*	SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
|*
|*	Ersterstellung		AMA 26. Nov. 97
|*	Letzte Aenderung	AMA 26. Nov. 97
|*
|*************************************************************************/
SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
	SwLayoutFrm( rSect.GetFmt(), pSib ),
	SwFlowFrm( (SwFrm&)*this ),
	pSection( &rSect )
{
    nType = FRMC_SECTION;

	CalcFtnAtEndFlag();
	CalcEndAtEndFlag();
}

SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
	SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
	SwFlowFrm( (SwFrm&)*this ),
	pSection( rSect.GetSection() )
{
	bFtnAtEnd = rSect.IsFtnAtEnd();
	bEndnAtEnd = rSect.IsEndnAtEnd();
	bLockJoin = sal_False;
    nType = FRMC_SECTION;

	PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )

	if( bMaster )
	{
		if( rSect.IsFollow() )
		{
            SwSectionFrm* pMaster = rSect.FindMaster();
			pMaster->SetFollow( this );
			bIsFollow = sal_True;
		}
		else
			rSect.bIsFollow = sal_True;
		SetFollow( &rSect );
	}
	else
	{
		bIsFollow = sal_True;
		SetFollow( rSect.GetFollow() );
		rSect.SetFollow( this );
		if( !GetFollow() )
			rSect.SimpleFormat();
		if( !rSect.IsColLocked() )
			rSect.InvalidateSize();
	}
}

// NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
//       frame and its insert in the layout.
void SwSectionFrm::Init()
{
    ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" );
    SWRECTFN( this )
    long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
    (Frm().*fnRect->fnSetWidth)( nWidth );
    (Frm().*fnRect->fnSetHeight)( 0 );

    // #109700# LRSpace for sections
    const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
    (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
    (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
                                 rLRSpace.GetRight() );
    (Prt().*fnRect->fnSetHeight)( 0 );

    const SwFmtCol &rCol = GetFmt()->GetCol();
    if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
	{
        const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
        ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
        if( pOld != &rCol )
            delete pOld;
	}
}

SwSectionFrm::~SwSectionFrm()
{
	if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
	{
		SwRootFrm *pRootFrm = getRootFrm();
		if( pRootFrm )
			pRootFrm->RemoveFromList( this );	//swmod 071108//swmod 071225
		if( IsFollow() )
		{
            SwSectionFrm *pMaster = FindMaster();
			if( pMaster )
			{
				PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
				pMaster->SetFollow( GetFollow() );
				// Ein Master greift sich immer den Platz bis zur Unterkante seines
				// Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
				// freigeben, deshalb wird die Size des Masters invalidiert.
				if( !GetFollow() )
					pMaster->InvalidateSize();
			}
		}
		else if( HasFollow() )
		{
			PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
			GetFollow()->bIsFollow = sal_False;
		}
	}
}


/*************************************************************************
|*
|*	SwSectionFrm::DelEmpty()
|*
|*	Ersterstellung		AMA 17. Dec. 97
|*	Letzte Aenderung	AMA 17. Dec. 97
|*
|*************************************************************************/
void SwSectionFrm::DelEmpty( sal_Bool bRemove )
{
	if( IsColLocked() )
	{
		ASSERT( !bRemove, "Don't delete locked SectionFrms" );
		return;
	}
	SwFrm* pUp = GetUpper();
	if( pUp )
    {
        // --> OD 2005-12-01 #i27138#
        // notify accessibility paragraphs objects about changed
        // CONTENT_FLOWS_FROM/_TO relation.
        // Relation CONTENT_FLOWS_FROM for current next paragraph will change
        // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
        {
            ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
            if ( pViewShell && pViewShell->GetLayout() &&
                 pViewShell->GetLayout()->IsAnyShellAccessible() )
            {
                pViewShell->InvalidateAccessibleParaFlowRelation(
                                dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
                                dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
            }
        }
        // <--
        _Cut( bRemove );
    }
	if( IsFollow() )
	{
        SwSectionFrm *pMaster = FindMaster();
		pMaster->SetFollow( GetFollow() );
		// Ein Master greift sich immer den Platz bis zur Unterkante seines
		// Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
		// freigeben, deshalb wird die Size des Masters invalidiert.
		if( !GetFollow() && !pMaster->IsColLocked() )
			pMaster->InvalidateSize();
		bIsFollow = sal_False;
	}
	else if( HasFollow() )
		GetFollow()->bIsFollow = sal_False;
	pFollow = NULL;
	if( pUp )
	{
		Frm().Height( 0 );
		// Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
		// uns gar nicht erst in die Liste eintragen
		if( bRemove )
		{   // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
			// stehen wir vermutlich auch in der Liste und muessen uns
			// dort austragen
			if( !pSection && getRootFrm() )
				getRootFrm()->RemoveFromList( this );
		}
		else if( getRootFrm() )
			getRootFrm()->InsertEmptySct( this );	//swmod 071108//swmod 071225
		pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
	}
}

/*************************************************************************
|*
|*	SwSectionFrm::Cut()
|*
|*	Ersterstellung		AMA 02. Dec. 97
|*	Letzte Aenderung	AMA 02. Dec. 97
|*
|*************************************************************************/
void SwSectionFrm::Cut()
{
	_Cut( sal_True );
}

void SwSectionFrm::_Cut( sal_Bool bRemove )
{
	ASSERT( GetUpper(), "Cut ohne Upper()." );

	PROTOCOL( this, PROT_CUT, 0, GetUpper() )

	SwPageFrm *pPage = FindPageFrm();
	InvalidatePage( pPage );
	SwFrm *pFrm = GetNext();
	SwFrm* pPrepFrm = NULL;
	while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
		pFrm = pFrm->GetNext();
	if( pFrm )
	{	//Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
		//berechnet der ist jetzt wo er der erste wird obsolete
		pFrm->_InvalidatePrt();
		pFrm->_InvalidatePos();
		if( pFrm->IsSctFrm() )
			pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
		if ( pFrm && pFrm->IsCntntFrm() )
		{
			pFrm->InvalidatePage( pPage );
			if( IsInFtn() && !GetIndPrev() )
				pPrepFrm = pFrm;
		}
	}
	else
	{
		InvalidateNextPos();
		//Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
		if ( 0 != (pFrm = GetPrev()) )
		{	pFrm->SetRetouche();
			pFrm->Prepare( PREP_WIDOWS_ORPHANS );
			if ( pFrm->IsCntntFrm() )
				pFrm->InvalidatePage( pPage );
		}
		//Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
		//er die Retouche uebernehmen.
		//Ausserdem kann eine Leerseite entstanden sein.
		else
		{	SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
			pRoot->SetSuperfluous();
			GetUpper()->SetCompletePaint();
		}
	}
	//Erst removen, dann Upper Shrinken.
	SwLayoutFrm *pUp = GetUpper();
	if( bRemove )
	{
		Remove();
		if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
			pUp->GetUpper() )
		{
			pUp->Cut();
			delete pUp;
			pUp = NULL;
		}
	}
	if( pPrepFrm )
		pPrepFrm->Prepare( PREP_FTN );
	if ( pUp )
	{
        SWRECTFN( this );
        SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
        if( nFrmHeight > 0 )
		{
			if( !bRemove )
			{
                (Frm().*fnRect->fnSetHeight)( 0 );
                (Prt().*fnRect->fnSetHeight)( 0 );
			}
            pUp->Shrink( nFrmHeight );
		}
	}
}

/*************************************************************************
|*
|*	SwSectionFrm::Paste()
|*
|*	Ersterstellung		AMA 04. Dec. 97
|*	Letzte Aenderung	AMA 04. Dec. 97
|*
|*************************************************************************/

void SwSectionFrm::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() && !GetUpper(),
			"Bin noch irgendwo angemeldet." );

	PROTOCOL( this, PROT_PASTE, 0, GetUpper() )

	//In den Baum einhaengen.
	SwSectionFrm* pSect = pParent->FindSctFrm();
    // --> OD 2008-06-23 #156927#
    // Assure that parent is not inside a table frame, which is inside the found section frame.
    if ( pSect )
    {
        SwTabFrm* pTableFrm = pParent->FindTabFrm();
        if ( pTableFrm &&
             pSect->IsAnLower( pTableFrm ) )
        {
            pSect = 0;
        }
    }
    // <--

    SWRECTFN( pParent )
	if( pSect && HasToBreak( pSect ) )
	{
		if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
		{
			// Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
			// auf den ersten Frame der naechsten Spalte zeigen, damit
			// der Inhalt der naechsten Spalte von InsertGroup richtig in den
			// neu angelegten pSect umgehaengt wird.
			SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
			while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
				pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
			if( pSibling )
			{
				// Schlimmer noch: alle folgenden Spalteninhalte muessen
				// an die pSibling-Kette angehaengt werden, damit sie
				// mitgenommen werden.
				SwFrm *pTmp = pSibling;
				while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
				{
					while ( pTmp->GetNext() )
						pTmp = pTmp->GetNext();
					SwFrm* pSave = ::SaveCntnt( pCol );
                    ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
                }
			}
		}
		pParent = pSect;
		pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
		// Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
		// neuen, zweiten Teil angebracht werden.
		pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
		((SwSectionFrm*)pParent)->SetFollow( NULL );
		if( pSect->GetFollow() )
			pParent->_InvalidateSize();

		InsertGroupBefore( pParent, pSibling, pSect );
        pSect->Init();
        (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
		if( !((SwLayoutFrm*)pParent)->Lower() )
		{
			SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
			pParent = this;
		}
	}
	else
		InsertGroupBefore( pParent, pSibling, NULL );

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

	if ( pSibling )
	{
		pSibling->_InvalidatePos();
		pSibling->_InvalidatePrt();
		if ( pSibling->IsCntntFrm() )
			pSibling->InvalidatePage( pPage );
	}

    SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
    if( nFrmHeight )
        pParent->Grow( nFrmHeight );

	if ( GetPrev() )
	{
		if ( !IsFollow() )
		{
			GetPrev()->InvalidateSize();
			if ( GetPrev()->IsCntntFrm() )
				GetPrev()->InvalidatePage( pPage );
		}
	}
}


/*************************************************************************
|*
|*	SwSectionFrm::HasToBreak()
|*
|*  Hier wird entschieden, ob der this-SectionFrm den uebergebenen
|*  (Section)Frm aufbrechen soll oder nicht.
|*  Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
|*  spaeter koennte man es einstellbar machen.
|*
|*	Ersterstellung		AMA 12. Dec. 97
|*	Letzte Aenderung	AMA 12. Dec. 97
|*
|*************************************************************************/

sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
{
	if( !pFrm->IsSctFrm() )
		return sal_False;

	SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
//	if( !pTmp->GetSect().GetValue() )
//		return sal_False;

	const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
	do
	{
		pTmp = pTmp->GetParent();
		if( !pTmp )
			return sal_False;
		if( pTmp == pOtherFmt )
			return sal_True;
	} while( sal_True ); //	( pTmp->GetSect().GetValue() );
}

/*************************************************************************
|*
|*	SwSectionFrm::MergeNext()
|*
|*	Ersterstellung		AMA 04. Dec. 97
|*	Letzte Aenderung	AMA 04. Dec. 97
|*
|*  Verschmilzt zwei SectionFrms, falls es sich um den
|*  gleichen Bereich handelt.
|*  Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
|*  einen anderen in zwei Teile zerlegt hatte.
|*
|*************************************************************************/

void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
{
	if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
	{
		PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )

		SwFrm* pTmp = ::SaveCntnt( pNxt );
		if( pTmp )
		{
			SwFrm* pLast = Lower();
			SwLayoutFrm* pLay = this;
			if( pLast )
			{
				while( pLast->GetNext() )
					pLast = pLast->GetNext();
				if( pLast->IsColumnFrm() )
				{   // Spalten jetzt mit BodyFrm
					pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
					pLast = pLay->Lower();
					if( pLast )
						while( pLast->GetNext() )
							pLast = pLast->GetNext();
				}
			}
            ::RestoreCntnt( pTmp, pLay, pLast, true );
        }
		SetFollow( pNxt->GetFollow() );
		pNxt->SetFollow( NULL );
		pNxt->bIsFollow = sal_False;
		pNxt->Cut();
		delete pNxt;
		InvalidateSize();
	}
}

/*************************************************************************
|*
|*	SwSectionFrm::SplitSect()
|*
|*	Ersterstellung		AMA 29. Apr. 99
|*	Letzte Aenderung	AMA 29. Apr. 99
|*
|*  Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
|*  uebergebenen Frame.
|*  Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
|*  von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
|*  haben kann.
|*
|*************************************************************************/

sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
{
	ASSERT( pFrm, "SplitSect: Why?" );
	SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
	if( !pOther )
		return sal_False;
	SwSectionFrm* pSect = pOther->FindSctFrm();
    if( pSect != this )
		return sal_False;
	// Den Inhalt zur Seite stellen
	SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
	ASSERT( pSav, "SplitSect: What's on?" );
	if( pSav ) // Robust
	{	// Einen neuen SctFrm anlegen, nicht als Follow/Master
        SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
		pNew->InsertBehind( pSect->GetUpper(), pSect );
        pNew->Init();
        SWRECTFN( this )
        (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
        // OD 25.03.2003 #108339# - restore content:
        // determine layout frame for restoring content after the initialization
        // of the section frame. In the section initialization the columns are
        // created.
        {
            SwLayoutFrm* pLay = pNew;
            // Search for last layout frame, e.g. for columned sections.
            while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
                pLay = (SwLayoutFrm*)pLay->Lower();
            ::RestoreCntnt( pSav, pLay, NULL, true );
        }
        _InvalidateSize();
        if( HasFollow() )
        {
            pNew->SetFollow( GetFollow() );
            SetFollow( NULL );
        }
		return sal_True;
	}
	return sal_False;
}

/*************************************************************************
|*
|*	SwSectionFrm::MoveCntntAndDelete()
|*
|*	Ersterstellung		AMA 29. Jan 99
|*	Letzte Aenderung	AMA 29. Jan 99
|*
|*  MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
|*  Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
|*  Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
|*  den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
|*  umgehaengt, dieser muss ggf. gemergt werden.
|*
|*************************************************************************/
// Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
// invalidiert werden

void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
{
	while ( pFrm )
	{
		pFrm->InvalidateInfFlags();
		if( bInva )
		{
			pFrm->_InvalidatePos();
			pFrm->_InvalidateSize();
			pFrm->_InvalidatePrt();
		}
		if( pFrm->IsLayoutFrm() )
			lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
		pFrm = pFrm->GetNext();
	}
}


//
// Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
//
SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
{
    if ( bFwd )
    {
        if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
            return (SwCntntFrm*)pLay->GetNext();
    }
    else
    {
        if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
            return (SwCntntFrm*)pLay->GetPrev();
    }

    // #100926#
    const SwFrm* pFrm = pLay;
    SwCntntFrm *pCntntFrm = 0;
    sal_Bool bGoingUp = sal_True;
    do {
        const SwFrm *p = 0;
        sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;

        bGoingDown = !bGoingUp && ( 0 !=  ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
        if ( !bGoingDown )
        {
            bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
                                          ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
                                          ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
            if ( !bGoingFwdOrBwd )
            {
                bGoingUp = (0 != (p = pFrm->GetUpper() ) );
                if ( !bGoingUp )
                    return 0;
            }
        }

        bGoingUp = !( bGoingFwdOrBwd || bGoingDown );

        if( !bFwd && bGoingDown && p )
            while ( p->GetNext() )
                p = p->GetNext();

        pFrm = p;
    } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));

    return pCntntFrm;
}

#define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
					? pLayFrm->GetNextLayoutLeaf() \
					: pLayFrm )

void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
{
	sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
	SwFrm* pPrv = pDel->GetPrev();
	SwLayoutFrm* pUp = pDel->GetUpper();
    // OD 27.03.2003 #i12711# - initialize local pointer variables.
    SwSectionFrm* pPrvSct = NULL;
    SwSectionFrm* pNxtSct = NULL;
    SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
	if( pDel->IsInTab() && pParent )
	{
		SwTabFrm *pTab = pDel->FindTabFrm();
		// Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
		// aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
		// einen Bereich, der die gesamte Tabelle umfasst.
		if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
			pParent = NULL;
	}
	// Wenn unser Format einen Parent besitzt, so haben wir vermutlich
	// einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
	// dazu besorgen wir uns zunaechst den vorhergehende und den nach-
	// folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
    // OD 27.03.2003 #i12711# - check, if previous and next section belonging
    // together and can be joined, *not* only if deleted section contains content.
    if ( pParent )
    {
        SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
        pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
        SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
        pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
    }
    else
    {
        pParent = NULL;
        pPrvSct = pNxtSct = NULL;
    }

	// Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
	SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
	sal_Bool bOldFtn = sal_True;
	if( pSave && pUp->IsFtnFrm() )
	{
		bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
		((SwFtnFrm*)pUp)->ColLock();
	}
	pDel->DelEmpty( sal_True );
	delete pDel;
	if( pParent )
	{	// Hier wird die geeignete Einfuegeposition gesucht
		if( pNxtSct && pNxtSct->GetFmt() == pParent )
		{   // Hier koennen wir uns am Anfang einfuegen
			pUp = FIRSTLEAF( pNxtSct );
			pPrv = NULL;
			if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
				pPrvSct = NULL; // damit nicht gemergt wird
		}
		else if( pPrvSct && pPrvSct->GetFmt() == pParent )
		{   // Wunderbar, hier koennen wir uns am Ende einfuegen
			pUp = pPrvSct;
			if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
			{
                pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
                // Der Body der letzten Spalte
                pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
			}
            // damit hinter dem letzten eingefuegt wird
            pPrv = pUp->GetLastLower();
            pPrvSct = NULL; // damit nicht gemergt wird
		}
		else
		{
			if( pSave )
			{	// Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
				// ist entweder die Bereichsgrenze des umfassenden Bereichs oder
				// es schliesst ein anderer (Geschwister-)Bereich direkt an, der
				// vom gleichen Parent abgeleitet ist.
				// Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
				// aufnehmen kann,also bauen wir ihn uns.
                pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
				pPrvSct->InsertBehind( pUp, pPrv );
                pPrvSct->Init();
                SWRECTFN( pUp )
                (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
				pUp = FIRSTLEAF( pPrvSct );
				pPrv = NULL;
			}
			pPrvSct = NULL; // damit nicht gemergt wird
		}
	}
	// Der Inhalt wird eingefuegt..
	if( pSave )
	{
		lcl_InvalidateInfFlags( pSave, bSize );
        ::RestoreCntnt( pSave, pUp, pPrv, true );
        pUp->FindPageFrm()->InvalidateCntnt();
		if( !bOldFtn )
			((SwFtnFrm*)pUp)->ColUnlock();
	}
	// jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
	if( pPrvSct && !pPrvSct->IsJoinLocked() )
	{
		ASSERT( pNxtSct, "MoveCntnt: No Merge" );
		pPrvSct->MergeNext( pNxtSct );
	}
}

void SwSectionFrm::MakeAll()
{
	if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
		return;
	if( !pSection ) // Durch DelEmpty
	{
		ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
		if( !bValidPos )
		{
            if( GetUpper() )
            {
                SWRECTFN( GetUpper() )
                (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
			}
        }
		bValidSize = bValidPos = bValidPrtArea = sal_True;
		return;
	}
	LockJoin();	//Ich lass mich nicht unterwegs vernichten.

	while( GetNext() && GetNext() == GetFollow() )
	{
		const SwFrm* pFoll = GetFollow();
		MergeNext( (SwSectionFrm*)GetNext() );
		if( pFoll == GetFollow() )
			break;
	}

    // OD 2004-03-15 #116561# - In online layout join the follows, if section
    // can grow.
    const ViewShell *pSh = getRootFrm()->GetCurrShell();
    if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
         ( Grow( LONG_MAX, true ) > 0 ) )
    {
        while( GetFollow() )
        {
            const SwFrm* pFoll = GetFollow();
            MergeNext( GetFollow() );
            if( pFoll == GetFollow() )
                break;
        }
    }

	// Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
	// in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
	if( !bValidPos && ToMaximize( sal_False ) )
		bValidSize = sal_False;

#if OSL_DEBUG_LEVEL > 1
	const SwFmtCol &rCol = GetFmt()->GetCol();
    (void)rCol;
#endif
	SwLayoutFrm::MakeAll();
	UnlockJoin();
	if( pSection && IsSuperfluous() )
		DelEmpty( sal_False );
}

sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
{
	ASSERT( sal_False, "Hups, wo ist meine Tarnkappe?" );
	return sal_False;
}

const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
{
	const SwSectionFmt *pFmt = pSection->GetFmt();
	while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
	{
		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
		else
			return NULL;
	}
	return pFmt;
}

void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
	SwFrm* pFrm, sal_Bool &rbChkFtn )
{
	if( pFrm )
	{
		while( pFrm->GetNext() )
			pFrm = pFrm->GetNext();
		while( !rpCntntFrm && pFrm )
		{
			if( pFrm->IsCntntFrm() )
				rpCntntFrm = (SwCntntFrm*)pFrm;
			else if( pFrm->IsLayoutFrm() )
			{
				if( pFrm->IsFtnFrm() )
				{
					if( rbChkFtn )
					{
						rpFtnFrm = (SwFtnFrm*)pFrm;
						rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
					}
				}
				else
					lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
						((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
			}
			pFrm = pFrm->GetPrev();
		}
	}
}

SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
{
	SwCntntFrm *pRet = NULL;
	SwFtnFrm *pFtnFrm = NULL;
	SwSectionFrm *pSect = this;
	if( nMode )
	{
		const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
			  					   pSection->GetFmt();
		do {
			while( pSect->HasFollow() )
				pSect = pSect->GetFollow();
			SwFrm* pTmp = pSect->FindNext();
			while( pTmp && pTmp->IsSctFrm() &&
				   !((SwSectionFrm*)pTmp)->GetSection() )
				pTmp = pTmp->FindNext();
			if( pTmp && pTmp->IsSctFrm() &&
				((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
				pSect = (SwSectionFrm*)pTmp;
			else
				break;
		} while( sal_True );
	}
	sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
	do
	{
		lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
		if( pRet || !pSect->IsFollow() || !nMode ||
			( FINDMODE_MYLAST == nMode && this == pSect ) )
			break;
        pSect = pSect->FindMaster();
	} while( pSect );
	if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
		pRet = pFtnFrm->ContainsCntnt();
	return pRet;
}

sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
{
	if( ToMaximize( sal_True ) )
	{
        SWRECTFN( this )
        rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
        rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
        return sal_True;
	}
	return sal_False;
}

/*************************************************************************
 *
 * 	SwSectionFrm::CollectEndnotes(  )
 *
 *	Ersterstellung		AMA 03. Nov 99
 *	Letzte Aenderung	AMA 03. Nov 99
 *
 *  CollectEndnotes looks for endnotes in the sectionfrm and his follows,
 *  the endnotes will cut off the layout and put into the array.
 *  If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
 *  contains only endnotes and it is not necessary to collect them.
 *
 *************************************************************************/

SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
	SwLayouter *pLayouter )
{
	// if rEmpty is set, the rpSect is already searched
	SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
	while( pSect )
	{
       ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
                "InsertEndnotes: Where's my column?" );

        // i73332: Columned section in endnote
        SwColumnFrm* pCol = 0;
        if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
            pCol = (SwColumnFrm*)pSect->Lower();

        while( pCol ) // check all columns
		{
			SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
			if( pFtnCont )
			{
				SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
				while( pRet ) // look for endnotes
				{
					if( pRet->GetAttr()->GetFtn().IsEndNote() )
					{
						if( pRet->GetMaster() )
						{
							if( pLayouter )
								pLayouter->CollectEndnote( pRet );
							else
								return 0;
						}
						else
							return pRet; // Found
					}
					pRet = (SwFtnFrm*)pRet->GetNext();
				}
			}
			pCol = (SwColumnFrm*)pCol->GetNext();
        }
		rpSect = pSect;
		pSect = pLayouter ? pSect->GetFollow() : NULL;
		rbEmpty = sal_True;
	}
	return NULL;
}

void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
{
	while( pSect )
	{
		sal_Bool bOldLock = pSect->IsColLocked();
		pSect->ColLock();
		if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
		{
			SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
			do
			{	pCol->_InvalidateSize();
				pCol->_InvalidatePos();
				((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
				pCol->Calc();   // calculation of column and
				((SwLayoutFrm*)pCol)->Lower()->Calc();  // body
				pCol = (SwColumnFrm*)pCol->GetNext();
			} while ( pCol );
		}
		if( !bOldLock )
			pSect->ColUnlock();
		if( bFollow )
			pSect = pSect->GetFollow();
		else
			pSect = NULL;
	}
}

void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
{
	ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" );
    // i73332: Section in footnode does not have columns!
    ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );

	SwSectionFrm* pSect = this;
	SwFtnFrm* pFtn;
	sal_Bool bEmpty = sal_False;
	// pSect is the last sectionfrm without endnotes or the this-pointer
	// the first sectionfrm with endnotes may be destroyed, when the endnotes
	// is cutted
	while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
		pLayouter->CollectEndnote( pFtn );
	if( pLayouter->HasEndnotes() )
		lcl_ColumnRefresh( this, sal_True );
}

/*************************************************************************
|*
|*	SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
|*
|*	Beschreibung:		Passt die Groesse an die Umgebung an.
|*  	Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
|*      des Uppers gehen (bMaximize).
|*		Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
|*		seinen Upper zu growen.
|*      Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
|*
|*************************************************************************/

/// OD 18.09.2002 #100522#
/// perform calculation of content, only if height has changed.
void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
{
    SWRECTFN( this )
    long nDiff;
    SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
	if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
				   !FindFlyFrm()->IsLocked() ) )
	{
        nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
        if( !bMaximize )
            nDiff += Undersize();
        if( nDiff > 0 )
        {
            long nAdd = GetUpper()->Grow( nDiff );
            if( bVert && !bRev )
                nDeadLine -= nAdd;
            else
                nDeadLine += nAdd;
        }
	}
    nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
    SetUndersized( !bMaximize && nDiff >= 0 );
    const bool bCalc = ( IsUndersized() || bMaximize ) &&
                       ( nDiff ||
                         (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
    // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
    // that a calculation has to be done beside the value of <bCalc>.
    bool bExtraCalc = false;
    if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
	{
		SwSectionFrm *pSect = this;
		sal_Bool bEmpty = sal_False;
		SwLayoutFrm* pFtn = IsEndnAtEnd() ?
			lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
		if( pFtn )
		{
			pFtn = pFtn->FindFtnBossFrm();
			SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
            // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
            if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
                bExtraCalc = true;
		}
		else if( GetFollow() && !GetFollow()->ContainsAny() )
            bExtraCalc = true;
	}
    if ( bCalc || bExtraCalc )
	{
        nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
        if( nDiff < 0 )
        {
            nDiff = 0;
            nDeadLine = (Frm().*fnRect->fnGetTop)();
        }
        const Size aOldSz( Prt().SSize() );
        long nTop = (this->*fnRect->fnGetTopMargin)();
        (Frm().*fnRect->fnSetBottom)( nDeadLine );
        nDiff = (Frm().*fnRect->fnGetHeight)();
        if( nTop > nDiff )
            nTop = nDiff;
        (this->*fnRect->fnSetYMargins)( nTop, 0 );

        // OD 18.09.2002 #100522#
        // Determine, if height has changed.
        // Note: In vertical layout the height equals the width value.
        bool bHeightChanged = bVert ?
                            (aOldSz.Width() != Prt().Width()) :
                            (aOldSz.Height() != Prt().Height());
        // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
		// dann wird das innere Layout (Columns) kalkuliert und
		// der Inhalt ebenfalls.
        // OD 18.09.2002 #100522#
        // calculate content, only if height has changed.
        // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
        // If an endnote has an incorrect position or a follow section contains
        // no content except footnotes/endnotes, the content has also been calculated.
        if ( ( bHeightChanged || bExtraCalc ) && Lower() )
		{
			if( Lower()->IsColumnFrm() )
			{
				lcl_ColumnRefresh( this, sal_False );
                ::CalcCntnt( this );
			}
			else
			{
				ChgLowersProp( aOldSz );
				if( !bMaximize && !IsCntntLocked() )
					::CalcCntnt( this );
			}
		}
	}
}

void SwSectionFrm::SimpleFormat()
{
	if ( IsJoinLocked() || IsColLocked() )
		return;
	// ASSERT( pFollow, "SimpleFormat: Follow required" );
	LockJoin();
    SWRECTFN( this )
    if( GetPrev() || GetUpper() )
	{
        // --> OD 2009-09-28 #b6882166#
        // assure notifications on position changes.
        const SwLayNotify aNotify( this );
        // <--
        (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
		bValidPos = sal_True;
	}
    SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
    // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
    // order to get calculated lowers, not only if there space left in its upper.
    if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
	{
        (Frm().*fnRect->fnSetBottom)( nDeadLine );
        long nHeight = (Frm().*fnRect->fnGetHeight)();
        long nTop = CalcUpperSpace();
        if( nTop > nHeight )
            nTop = nHeight;
        (this->*fnRect->fnSetYMargins)( nTop, 0 );
	}
    lcl_ColumnRefresh( this, sal_False );
	UnlockJoin();
}

// --> OD 2005-01-11 #i40147# - helper class to perform extra section format
// to position anchored objects and to keep the position of whose objects locked.
class ExtraFormatToPositionObjs
{
    private:
        SwSectionFrm* mpSectFrm;
        bool mbExtraFormatPerformed;

    public:
        ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
            : mpSectFrm( &_rSectFrm ),
              mbExtraFormatPerformed( false )
        {}

        ~ExtraFormatToPositionObjs()
        {
            if ( mbExtraFormatPerformed )
            {
                // release keep locked position of lower floating screen objects
                SwPageFrm* pPageFrm = mpSectFrm->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 ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
                        {
                            pAnchoredObj->SetKeepPosLocked( false );
                        }
                    }
                }
            }
        }

        // --> OD 2008-06-20 #i81555#
        void InitObjs( SwFrm& rFrm )
        {
            SwSortedObjs* pObjs = rFrm.GetDrawObjs();
            if ( pObjs )
            {
                sal_uInt32 i = 0;
                for ( i = 0; i < pObjs->Count(); ++i )
                {
                    SwAnchoredObject* pAnchoredObj = (*pObjs)[i];

                    pAnchoredObj->UnlockPosition();
                    pAnchoredObj->SetClearedEnvironment( false );
                }
            }
            SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
            if ( pLayoutFrm != 0 )
            {
                SwFrm* pLowerFrm = pLayoutFrm->GetLower();
                while ( pLowerFrm != 0 )
                {
                    InitObjs( *pLowerFrm );

                    pLowerFrm = pLowerFrm->GetNext();
                }
            }
        }
        // <--

        void FormatSectionToPositionObjs()
        {
            // perform extra format for multi-columned section.
            if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
                 mpSectFrm->Lower()->GetNext() )
            {
                // grow section till bottom of printing area of upper frame
                SWRECTFN( mpSectFrm );
                SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
                Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
                SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
                                        (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
                (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
                (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
                // --> OD 2006-05-08 #i59789#
                // suppress formatting, if printing area of section is too narrow
                if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
                {
                    return;
                }
                // <--
                mpSectFrm->ChgLowersProp( aOldSectPrtSize );

                // format column frames and its body and footnote container
                SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
                while ( pColFrm )
                {
                    pColFrm->Calc();
                    pColFrm->Lower()->Calc();
                    if ( pColFrm->Lower()->GetNext() )
                    {
                        pColFrm->Lower()->GetNext()->Calc();
                    }

                    pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
                }

                // unlock position of lower floating screen objects for the extra format
                // --> OD 2008-06-20 #i81555#
                // Section frame can already have changed the page and its content
                // can still be on the former page.
                // Thus, initialize objects via lower-relationship
                InitObjs( *mpSectFrm );
                // <--

                // format content - first with collecting its foot-/endnotes before content
                // format, second without collecting its foot-/endnotes.
                ::CalcCntnt( mpSectFrm );
                ::CalcCntnt( mpSectFrm, true );

                // keep locked position of lower floating screen objects
                SwPageFrm* pPageFrm = mpSectFrm->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 ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
                        {
                            pAnchoredObj->SetKeepPosLocked( true );
                        }
                    }
                }

                mbExtraFormatPerformed = true;
            }
        }
};

/*************************************************************************
|*
|*	SwSectionFrm::Format()
|*
|*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea.
|*	Ersterstellung		AMA 03. Dec. 97
|* 	Letzte Aenderung	MA 09. Oct. 98
|*
|*************************************************************************/

void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
{
	if( !pSection ) // Durch DelEmpty
	{
		ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
		bValidSize = bValidPos = bValidPrtArea = sal_True;
		return;
	}
    SWRECTFN( this )
	if ( !bValidPrtArea )
	{
		PROTOCOL( this, PROT_PRTAREA, 0, 0 )
		bValidPrtArea = sal_True;
		SwTwips nUpper = CalcUpperSpace();

        // #109700# LRSpace for sections
        const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
        (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );

        if( nUpper != (this->*fnRect->fnGetTopMargin)() )
		{
			bValidSize = sal_False;
			SwFrm* pOwn = ContainsAny();
			if( pOwn )
				pOwn->_InvalidatePos();
		}
        (this->*fnRect->fnSetYMargins)( nUpper, 0 );
	}

	if ( !bValidSize )
	{
		PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
        const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
		sal_Bool bOldLock = IsColLocked();
		ColLock();

		bValidSize = sal_True;

        //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
		//keinen Follow hat. Anderfalls fuellt er immer den Upper bis
		//zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
		//Inhalt selbst verantwortlich.
		sal_Bool bMaximize = ToMaximize( sal_False );

        // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
        // on object positioning, an extra formatting has to be performed
        // to determine the correct positions the floating screen objects.
        // --> OD 2005-01-11 #i40147#
        // use new helper class <ExtraFormatToPositionObjs>.
        // This class additionally keep the locked position of the objects
        // and releases this position lock keeping on destruction.
        ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
        if ( !bMaximize &&
             GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
             !GetFmt()->GetBalancedColumns().GetValue() )
        {
            aExtraFormatToPosObjs.FormatSectionToPositionObjs();
        }
        // <--

        // Column widths have to be adjusted before calling _CheckClipping.
        // _CheckClipping can cause the formatting of the lower frames
        // which still have a width of 0.
        const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
        if ( bHasColumns && Lower()->GetNext() )
            AdjustColumns( 0, sal_False );

		if( GetUpper() )
		{
            long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
            (aFrm.*fnRect->fnSetWidth)( nWidth );

            // #109700# LRSpace for sections
            const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
            (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
                                        rLRSpace.GetRight() );

            // OD 15.10.2002 #103517# - allow grow in online layout
            // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
            // method <_CheckClipping(..)>.
            const ViewShell *pSh = getRootFrm()->GetCurrShell();
            _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
			bMaximize = ToMaximize( sal_False );
			bValidSize = sal_True;
		}

        //Breite der Spalten pruefen und ggf. einstellen.
        if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
            ((SwColumnFrm*)Lower())->Lower()->Calc();

		if ( !bMaximize )
		{
            SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
			SwFrm *pFrm = pLower;
			if( pFrm )
			{
				if( pFrm->IsColumnFrm() && pFrm->GetNext() )
				{
                    // --> OD 2006-05-08 #i61435#
                    // suppress formatting, if upper frame has height <= 0
                    if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
                    {
                        FormatWidthCols( *pAttr, nRemaining, MINLAY );
                    }
                    // <--
                    // --> OD 2006-01-04 #126020# - adjust check for empty section
                    // --> OD 2006-02-01 #130797# - correct fix #126020#
                    while( HasFollow() && !GetFollow()->ContainsCntnt() &&
                           !GetFollow()->ContainsAny( true ) )
                    // <--
					{
						SwFrm* pOld = GetFollow();
						GetFollow()->DelEmpty( sal_False );
						if( pOld == GetFollow() )
							break;
					}
					bMaximize = ToMaximize( sal_False );
                    nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
				}
				else
				{
					if( pFrm->IsColumnFrm() )
					{
						pFrm->Calc();
						pFrm = ((SwColumnFrm*)pFrm)->Lower();
						pFrm->Calc();
						pFrm = ((SwLayoutFrm*)pFrm)->Lower();
						CalcFtnCntnt();
					}
					// Wenn wir in einem spaltigen Rahmen stehen und dieser
					// gerade im FormatWidthCols ein CalcCntnt ruft, muss
					// unser Inhalt ggf. kalkuliert werden.
					if( pFrm && !pFrm->IsValid() && IsInFly() &&
						FindFlyFrm()->IsColLocked() )
						::CalcCntnt( this );
					nRemaining += InnerHeight();
					bMaximize = HasFollow();
				}
			}

            SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
			if( nDiff < 0)
			{
                SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
				{
                    long nBottom = (Frm().*fnRect->fnGetBottom)();
                    nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
                    long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
                    if( nTmpDiff > 0 )
					{
                        nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
                        nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
                        nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
                        if( nTmpDiff > 0 )
                            nDiff += nTmpDiff;
						if( nDiff > 0 )
							nDiff = 0;
					}
				}
			}
			if( nDiff )
			{
                long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
                long nTop = (this->*fnRect->fnGetTopMargin)();
                (Frm().*fnRect->fnAddBottom)( nTmp );
                (this->*fnRect->fnSetYMargins)( nTop, 0 );
				InvalidateNextPos();
				if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
				{
					// Wenn ein einspaltiger Bereich gerade den Platz geschaffen
					// hat, den sich die "undersized" Absaetze gewuenscht haben,
					// muessen diese invalidiert und kalkuliert werden, damit
					// sie diesen ausfuellen.
					pFrm = pLower;
					if( pFrm->IsColumnFrm() )
					{
						pFrm->_InvalidateSize();
						pFrm->_InvalidatePos();
						pFrm->Calc();
						pFrm = ((SwColumnFrm*)pFrm)->Lower();
						pFrm->Calc();
						pFrm = ((SwLayoutFrm*)pFrm)->Lower();
						CalcFtnCntnt();
					}
					sal_Bool bUnderSz = sal_False;
					while( pFrm )
					{
						if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
						{
							pFrm->Prepare( PREP_ADJUST_FRM );
							bUnderSz = sal_True;
						}
						pFrm = pFrm->GetNext();
					}
					if( bUnderSz && !IsCntntLocked() )
						::CalcCntnt( this );
				}
			}
		}

		//Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
		//Follows die Unterkante auch nicht unterschreiten.
		if ( GetUpper() )
			_CheckClipping( sal_True, bMaximize );
		if( !bOldLock )
			ColUnlock();
        long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
        if( nDiff > 0 )
		{
			if( !GetNext() )
				SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
            if( GetUpper() && !GetUpper()->IsFooterFrm() )
                GetUpper()->Shrink( nDiff );
		}
		if( IsUndersized() )
			bValidPrtArea = sal_True;
    }
}

/*************************************************************************
|*
|*	SwFrm::GetNextSctLeaf()
|*
|*	Beschreibung		Liefert das naechste Layoutblatt in das der	Frame
|* 		gemoved werden kann.
|* 		Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
|*	Ersterstellung		AMA 07. Jan. 98
|*	Letzte Aenderung	AMA 07. Jan. 98
|*
|*************************************************************************/


SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
{
	//Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.

	PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )

	// Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
	// Koennen wir in die naechste Spalte des Bereichs rutschen?
	if( IsColBodyFrm() && GetUpper()->GetNext() )
		return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
	if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
		return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
	// Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
	// nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
	if( GetUpper()->IsInTab() || FindFooterOrHeader() )
		return 0;

//MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
//FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
//GetLeaf gerufen wird.
//	SwSectionFrm *pSect = GetUpper()->FindSctFrm();
	SwSectionFrm *pSect = FindSctFrm();
	sal_Bool bWrongPage = sal_False;
	ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" );

	// Hier eine Abkuerzung fuer Bereiche mit Follows,
	// dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
	// dazwischen liegen.
	// Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
	if( pSect->HasFollow() && pSect->IsInDocBody() )
	{
		if( pSect->GetFollow() == pSect->GetNext() )
		{
			SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
			if( WrongPageDesc( pPg ) )
				bWrongPage = sal_True;
			else
				return FIRSTLEAF( pSect->GetFollow() );
		}
		else
		{
			SwFrm* pTmp;
			if( !pSect->GetUpper()->IsColBodyFrm() ||
				0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
				pTmp = pSect->FindPageFrm()->GetNext();
			if( pTmp ) // ist jetzt die naechste Spalte oder Seite
			{
				SwFrm* pTmpX = pTmp;
				if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
					pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
				SwFrm *pUp = pSect->GetFollow()->GetUpper();
				// pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
				// liegt, ansonsten die Seite:
				if( !pUp->IsColBodyFrm() ||
					!( pUp = pUp->GetUpper() )->GetPrev() )
					pUp = pUp->FindPageFrm();
				// Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
				// sonst liegen Seiten oder Spalten zwischen Master und Follow.
				if( pUp == pTmp || pUp->GetNext() == pTmpX )
				{
					SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
										(SwPageFrm*)pUp : pUp->FindPageFrm();
					if( WrongPageDesc( pNxtPg ) )
						bWrongPage = sal_True;
					else
						return FIRSTLEAF( pSect->GetFollow() );
				}
			}
		}
	}

	// Immer im gleichen Bereich landen: Body wieder in Body etc.
	const sal_Bool bBody = IsInDocBody();
	const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();

	SwLayoutFrm *pLayLeaf;
	// Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
	if( bWrongPage )
		pLayLeaf = 0;
	else if( IsTabFrm() )
    {
		SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
        pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
    }
	else
	{
		pLayLeaf = GetNextLayoutLeaf();
		if( IsColumnFrm() )
		{
			while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
				pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
		}
	}

	SwLayoutFrm *pOldLayLeaf = 0;			//Damit bei neu erzeugten Seiten
											//nicht wieder vom Anfang gesucht
											//wird.

	while( sal_True )
	{
		if( pLayLeaf )
		{
			// Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
			// ob hier ein weiterer SectionFrm eingefuegt werden kann
			// oder ob wir weitersuchen muessen.
			SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
			if ( !bFtnPage && pNxtPg->IsFtnPage() )
			{	//Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
				pLayLeaf = 0;
				continue;
			}
			// Einmal InBody, immer InBody, nicht in Tabellen hinein
			// und nicht in fremde Bereiche hinein
			if ( (bBody && !pLayLeaf->IsInDocBody()) ||
				 (IsInFtn() != pLayLeaf->IsInFtn() ) ||
				 pLayLeaf->IsInTab() ||
				 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
				   || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
			{
				//Er will mich nicht; neuer Versuch, neues Glueck
				pOldLayLeaf = pLayLeaf;
				pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
				continue;
			}
			if( WrongPageDesc( pNxtPg ) )
			{
				if( bWrongPage )
					break; // there's a column between me and my right page
				pLayLeaf = 0;
				bWrongPage = sal_True;
				pOldLayLeaf = 0;
				continue;
			}
		}
		//Es gibt keinen passenden weiteren LayoutFrm, also muss eine
		//neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
		//neue Seiten nichts.
		else if( !pSect->IsInFly() &&
			( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
		{
			InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
					   sal_False );
			//und nochmal das ganze
			pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
			continue;
		}
		break;
	}

	if( pLayLeaf )
	{
		// Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
		// Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
		// andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
		SwSectionFrm* pNew;

		//Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
		SwFrm* pFirst = pLayLeaf->Lower();
		// Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
		while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
			pFirst = pFirst->GetNext();
		if( pFirst && pFirst->IsSctFrm() &&	pSect->GetFollow() == pFirst )
			pNew = pSect->GetFollow();
		else if( MAKEPAGE_NOSECTION == eMakePage )
			return pLayLeaf;
		else
		{
            pNew = new SwSectionFrm( *pSect, sal_False );
			pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
            pNew->Init();
            SWRECTFN( pNew )
            (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );

			// Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
			// umgehaengt werden hinter den neuen Follow der Bereichsframes.
			SwFrm* pTmp = pSect->GetNext();
			if( pTmp && pTmp != pSect->GetFollow() )
			{
				SwFlowFrm* pNxt;
				SwCntntFrm* pNxtCntnt = NULL;
				if( pTmp->IsCntntFrm() )
				{
					pNxt = (SwCntntFrm*)pTmp;
					pNxtCntnt = (SwCntntFrm*)pTmp;
				}
				else
				{
					pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
					if( pTmp->IsSctFrm() )
						pNxt = (SwSectionFrm*)pTmp;
					else
					{
						ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
						pNxt = (SwTabFrm*)pTmp;
					}
					while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
					{
						if( pTmp->IsCntntFrm() )
							pNxtCntnt = (SwCntntFrm*)pTmp;
						else
							pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
					}
				}
				if( pNxtCntnt )
				{
					SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
					if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
					{
						SwSaveFtnHeight aHeight( pOldBoss,
							pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
						pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
									pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
					}
				}
				((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
			}
			if( pNew->GetFollow() )
				pNew->SimpleFormat();
		}
		// Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
		pLayLeaf = FIRSTLEAF( pNew );
	}
	return pLayLeaf;
}

/*************************************************************************
|*
|*	SwFrm::GetPrevSctLeaf()
|*
|*	Beschreibung		Liefert das vorhergehende LayoutBlatt in das der
|* 		Frame gemoved werden kann.
|*	Ersterstellung		AMA 07. Jan. 98
|*	Letzte Aenderung	AMA 07. Jan. 98
|*
|*************************************************************************/


SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
{
	PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )

	SwLayoutFrm* pCol;
	// ColumnFrm beinhalten jetzt stets einen BodyFrm
	if( IsColBodyFrm() )
		pCol = GetUpper();
	else if( GetUpper()->IsColBodyFrm() )
		pCol = GetUpper()->GetUpper();
	else
		pCol = NULL;
	sal_Bool bJump = sal_False;
	if( pCol )
	{
		if( pCol->GetPrev() )
		{
			do
			{
				pCol = (SwLayoutFrm*)pCol->GetPrev();
				// Gibt es dort Inhalt?
				if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
				{
					if( bJump )		// Haben wir eine leere Spalte uebersprungen?
						SwFlowFrm::SetMoveBwdJump( sal_True );
					return (SwLayoutFrm*)pCol->Lower();  // Der Spaltenbody
				}
				bJump = sal_True;
			} while( pCol->GetPrev() );

			// Hier landen wir, wenn alle Spalten leer sind,
			// pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
			pCol = (SwLayoutFrm*)pCol->Lower();
		}
		else
			pCol = NULL;
	}

	if( bJump )		// Haben wir eine leere Spalte uebersprungen?
		SwFlowFrm::SetMoveBwdJump( sal_True );

	// Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
	// nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
	// zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
	// Jetzt ziehen wir sogar eine leere Spalte in Betracht...
	ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
	if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
		return pCol;

    // === IMPORTANT ===
    // Precondition, which needs to be hold, is that the <this> frame can be
    // inside a table, but then the found section frame <pSect> is also inside
    // this table.
    SwSectionFrm *pSect = FindSctFrm();

    // --> OD 2009-01-16 #i95698#
    // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
    // Thus, a table inside a section, which is inside another table can only
    // flow backward in the columns of its section.
    // Note: The table cell, which contains the section, can not have a master table cell.
    if ( IsTabFrm() && pSect->IsInTab() )
    {
        return pCol;
    }
    // <--

    {
        SwFrm *pPrv;
        if( 0 != ( pPrv = pSect->GetIndPrev() ) )
        {
            // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
            while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
                pPrv = pPrv->GetPrev();
            if( pPrv )
                return pCol;
        }
    }

	const sal_Bool bBody = IsInDocBody();
	const sal_Bool bFly  = IsInFly();

	SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
	SwLayoutFrm *pPrevLeaf = 0;

	while ( pLayLeaf )
    {
        //In Tabellen oder Bereiche geht's niemals hinein.
        if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
        {
            pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
        }
		else if ( bBody && pLayLeaf->IsInDocBody() )
		{
            // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
            // Exception: pLayLeaf->Lower() is a zombie section frame
            const SwFrm* pTmp = pLayLeaf->Lower();
            // OD 11.04.2003 #108824# - consider, that the zombie section frame
            // can have frame below it in the found layout leaf.
            // Thus, skipping zombie section frame, if possible.
            while ( pTmp && pTmp->IsSctFrm() &&
                    !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
                    pTmp->GetNext()
                  )
            {
                pTmp = pTmp->GetNext();
            }
            if ( pTmp &&
                 ( !pTmp->IsSctFrm() ||
                   ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
                 )
               )
            {
        	    break;
            }
			pPrevLeaf = pLayLeaf;
			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
			if ( pLayLeaf )
				SwFlowFrm::SetMoveBwdJump( sal_True );
		}
		else if ( bFly )
			break;	//Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
		else
			pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
	}
	if( !pLayLeaf )
	{
		if( !pPrevLeaf )
			return pCol;
		pLayLeaf = pPrevLeaf;
	}

	SwSectionFrm* pNew = NULL;
	// Zunaechst einmal an das Ende des Layoutblatts gehen
	SwFrm *pTmp = pLayLeaf->Lower();
	if( pTmp )
	{
		while( pTmp->GetNext() )
			pTmp = pTmp->GetNext();
		if( pTmp->IsSctFrm() )
		{
			// Halbtote stoeren hier nur...
			while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
					pTmp->GetPrev()->IsSctFrm() )
				pTmp = pTmp->GetPrev();
			if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
				pNew = (SwSectionFrm*)pTmp;
		}
	}
	if( !pNew )
	{
        pNew = new SwSectionFrm( *pSect, sal_True );
		pNew->InsertBefore( pLayLeaf, NULL );
        pNew->Init();
        SWRECTFN( pNew )
        (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );

		pLayLeaf = FIRSTLEAF( pNew );
		if( !pNew->Lower() )    // einspaltige Bereiche formatieren
		{
			pNew->MakePos();
			pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
		}
		else
			pNew->SimpleFormat();
	}
	else
	{
		pLayLeaf = FIRSTLEAF( pNew );
		if( pLayLeaf->IsColBodyFrm() )
        {
            // In existent section columns we're looking for the last not empty
            // column.
            SwLayoutFrm *pTmpLay = pLayLeaf;
			while( pLayLeaf->GetUpper()->GetNext() )
            {
				pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
                if( pLayLeaf->Lower() )
                    pTmpLay = pLayLeaf;
            }
            // If we skipped an empty column, we've to set the jump-flag
            if( pLayLeaf != pTmpLay )
            {
                pLayLeaf = pTmpLay;
                SwFlowFrm::SetMoveBwdJump( sal_True );
            }
		}
	}
	return pLayLeaf;
}

SwTwips lcl_DeadLine( const SwFrm* pFrm )
{
	const SwLayoutFrm* pUp = pFrm->GetUpper();
	while( pUp && pUp->IsInSct() )
	{
		if( pUp->IsSctFrm() )
			pUp = pUp->GetUpper();
		// Spalten jetzt mit BodyFrm
		else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
			pUp = pUp->GetUpper()->GetUpper();
		else
			break;
	}
    SWRECTFN( pFrm )
    return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
                 (pFrm->Frm().*fnRect->fnGetBottom)();
}

// SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
// ggf. muss die Umgebung gefragt werden

sal_Bool SwSectionFrm::Growable() const
{
    SWRECTFN( this )
    if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
        (Frm().*fnRect->fnGetBottom)() ) > 0 )
		return sal_True;

    return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
}

/*************************************************************************
|*
|*	SwSectionFrm::_Grow(), _Shrink()
|*
|*	Ersterstellung		AMA 14. Jan. 98
|*	Letzte Aenderung	AMA 14. Jan. 98
|*
|*************************************************************************/

SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
{
    if ( !IsColLocked() && !HasFixSize() )
	{
        SWRECTFN( this )
        long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
        if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
            nDist = LONG_MAX - nFrmHeight;

		if ( nDist <= 0L )
			return 0L;

        sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
        // OD 2004-03-15 #116561# - allow grow in online layout
        sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
             GetSection()->GetFmt()->GetBalancedColumns().GetValue();
        if( !bGrow )
        {
             const ViewShell *pSh = getRootFrm()->GetCurrShell();
             bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
        }
        if( bGrow )
		{
            SwTwips nGrow;
            if( IsInFtn() )
                nGrow = 0;
            else
            {
                nGrow = lcl_DeadLine( this );
                nGrow = (*fnRect->fnYDiff)( nGrow,
                                           (Frm().*fnRect->fnGetBottom)() );
            }
			SwTwips nSpace = nGrow;
            if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
                nGrow += GetUpper()->Grow( LONG_MAX, sal_True );

			if( nGrow > nDist )
				nGrow = nDist;
			if( nGrow <= 0 )
			{
				nGrow = 0;
				if( nDist && !bTst )
				{
					if( bInCalcCntnt )
						_InvalidateSize();
					else
						InvalidateSize();
				}
			}
			else if( !bTst )
			{
				if( bInCalcCntnt )
					_InvalidateSize();
				else if( nSpace < nGrow &&  nDist != nSpace + GetUpper()->
                         Grow( nGrow - nSpace, sal_False ) )
					InvalidateSize();
				else
				{
					const SvxGraphicPosition ePos =
						GetAttrSet()->GetBackground().GetGraphicPos();
					if ( GPOS_RT < ePos && GPOS_TILED != ePos )
					{
						SetCompletePaint();
						InvalidatePage();
					}
                    if( GetUpper() && GetUpper()->IsHeaderFrm() )
                        GetUpper()->InvalidateSize();
				}
                (Frm().*fnRect->fnAddBottom)( nGrow );
                long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
                (Prt().*fnRect->fnSetHeight)( nPrtHeight );

                if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
				{
					SwFrm* pTmp = Lower();
					do
					{
						pTmp->_InvalidateSize();
						pTmp = pTmp->GetNext();
					} while ( pTmp );
					_InvalidateSize();
				}
				if( GetNext() )
				{
					SwFrm *pFrm = GetNext();
					while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
						pFrm = pFrm->GetNext();
					if( pFrm )
					{
						if( bInCalcCntnt )
							pFrm->_InvalidatePos();
						else
							pFrm->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 ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
                {
                    InvalidateNextPos();
                }
                // <--
			}
			return nGrow;
		}
		if ( !bTst )
		{
			if( bInCalcCntnt )
				_InvalidateSize();
			else
				InvalidateSize();
		}
	}
	return 0L;
}

SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
{
    if ( Lower() && !IsColLocked() && !HasFixSize() )
	{
		if( ToMaximize( sal_False ) )
		{
			if( !bTst )
				InvalidateSize();
		}
		else
		{
            SWRECTFN( this )
            long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
            if ( nDist > nFrmHeight )
                nDist = nFrmHeight;

			if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
				 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
			{	//Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
				//das Wachstum (wg. des Ausgleichs).
				if ( !bTst )
					InvalidateSize();
				return nDist;
			}
			else if( !bTst )
			{
				const SvxGraphicPosition ePos =
					GetAttrSet()->GetBackground().GetGraphicPos();
				if ( GPOS_RT < ePos && GPOS_TILED != ePos )
				{
					SetCompletePaint();
					InvalidatePage();
				}
                (Frm().*fnRect->fnAddBottom)( -nDist );
                long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
                (Prt().*fnRect->fnSetHeight)( nPrtHeight );

                SwTwips nReal = 0;
                // We do not allow a section frame to shrink the its upper
                // footer frame. This is because in the calculation of a
                // footer frame, the content of the section frame is _not_
                // calculated. If there is a fly frame overlapping with the
                // footer frame, the section frame is not affected by this
                // during the calculation of the footer frame size.
                // The footer frame does not grow in its FormatSize function
                // but during the calculation of the content of the section
                // frame. The section frame grows until some of its text is
                // located on top of the fly frame. The next call of CalcCntnt
                // tries to shrink the section and here it would also shrink
                // the footer. This may not happen, because shrinking the footer
                // would cause the top of the section frame to overlap with the
                // fly frame again, this would result in a perfect loop.
                if( GetUpper() && !GetUpper()->IsFooterFrm() )
                    nReal = GetUpper()->Shrink( nDist, bTst );

                if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
				{
					SwFrm* pTmp = Lower();
					do
					{
						pTmp->_InvalidateSize();
						pTmp = pTmp->GetNext();
					} while ( pTmp );
				}
				if( GetNext() )
				{
					SwFrm* pFrm = GetNext();
					while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
						pFrm = pFrm->GetNext();
					if( pFrm )
						pFrm->InvalidatePos();
					else
						SetRetouche();
				}
				else
					SetRetouche();
				return nDist;
			}
		}
	}
	return 0L;
}

/*************************************************************************
|*
|*	SwSectionFrm::MoveAllowed()
|*
|*	Ersterstellung		MA 08. Oct. 98
|*	Letzte Aenderung	MA 08. Oct. 98
|*
|*	Wann sind Frms innerhalb eines SectionFrms moveable?
|*  Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
|* 	wenn es einen Follow gibt,
|*  wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
|*  dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
|*  finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
|* 	geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
|*  und auch im Fussnoten dagegen immer.
|*
|*  Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
|* 	(Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
|*
|*************************************************************************/

sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
{
	// Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
	if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
		pFrm->GetUpper()->GetUpper()->GetNext() ) )
		return sal_True;
	if( pFrm->IsInFtn() )
	{
		if( IsInFtn() )
		{
			if( GetUpper()->IsInSct() )
			{
				if( Growable() )
					return sal_False;
				return GetUpper()->FindSctFrm()->MoveAllowed( this );
			}
			else
				return sal_True;
		}
		// The content of footnote inside a columned sectionfrm is moveable
		// except in the last column
		const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
		if( pLay->IsColumnFrm() && pLay->GetNext() )
		{
			// The first paragraph in the first footnote in the first column
			// in the sectionfrm at the top of the page is not moveable,
			// if the columnbody is empty.
			sal_Bool bRet = sal_False;
			if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
				pFrm->FindFtnFrm()->GetPrev() )
				bRet = sal_True;
			else
			{
				SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
				if( pBody && pBody->Lower() )
					bRet = sal_True;
			}
			if( bRet && ( IsFtnAtEnd() || !Growable() ) )
				return sal_True;
		}
	}
	// Oder kann der Bereich noch wachsen?
	if(	!IsColLocked() && Growable() )
		return sal_False;
	// Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
	// ein Bereichsfollow erzeugt werden kann.
	if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
		return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
	if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
		return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
	return sal_True;
}

/** Called for a frame inside a section with no direct previous frame (or only
    previous empty section frames) the previous frame of the outer section is
    returned, if the frame is the first flowing content of this section.

    Note: For a frame inside a table frame, which is inside a section frame,
          NULL is returned.
*/
SwFrm* SwFrm::_GetIndPrev() const
{
	SwFrm *pRet = NULL;
    // --> OD 2007-09-04 #i79774#, #b659654#
    // Do not assert, if the frame has a direct previous frame, because it
    // could be an empty section frame. The caller has to assure, that the
    // frame has no direct previous frame or only empty section frames as
    // previous frames.
    ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" );
    // <--
    const SwFrm* pSct = GetUpper();
	if( !pSct )
		return NULL;
	if( pSct->IsSctFrm() )
		pRet = pSct->GetIndPrev();
	else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
    {
        // Do not return the previous frame of the outer section, if in one
        // of the previous columns is content.
        const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
		while( pCol )
		{
			ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
			ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
					"GetIndPrev(): Where's the body?");
			if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
				return NULL;
			pCol = pCol->GetPrev();
		}
		pRet = pSct->GetIndPrev();
	}

    // skip empty section frames
	while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
		pRet = pRet->GetIndPrev();
	return pRet;
}

SwFrm* SwFrm::_GetIndNext()
{
	ASSERT( !pNext && IsInSct(), "Why?" );
	SwFrm* pSct = GetUpper();
	if( !pSct )
		return NULL;
	if( pSct->IsSctFrm() )
		return pSct->GetIndNext();
	if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
	{	// Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
		// wenn in keiner folgenden Spalte mehr Inhalt ist
		SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
		while( pCol )
		{
			ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
			ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
					"GetIndNext(): Where's the body?");
			if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
				return NULL;
			pCol = pCol->GetNext();
		}
		return pSct->GetIndNext();
	}
	return NULL;
}

sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
{
	if( !pSection || !pFmt )
		return sal_False;
	const SwSectionFmt *pMyFmt = pSection->GetFmt();
	while( pFmt != pMyFmt )
	{
		if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
			pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
		else
			return sal_False;
	}
	return sal_True;
}

void SwSectionFrm::CalcFtnAtEndFlag()
{
	SwSectionFmt *pFmt = GetSection()->GetFmt();
	sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
	bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
	bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
				 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
	while( !bFtnAtEnd && !bOwnFtnNum )
	{
		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
		else
			break;
		nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
		if( FTNEND_ATPGORDOCEND != nVal )
		{
			bFtnAtEnd = sal_True;
			bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
						 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
		}
	}
}

sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
{
	return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
}

void SwSectionFrm::CalcEndAtEndFlag()
{
	SwSectionFmt *pFmt = GetSection()->GetFmt();
	bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
	while( !bEndnAtEnd )
	{
		if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
			pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
		else
			break;
		bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
	}
}

/*************************************************************************
|*
|*	SwSectionFrm::Modify()
|*
|*	Ersterstellung		MA 08. Oct. 98
|*	Letzte Aenderung	MA 08. Oct. 98
|*
|*************************************************************************/

void SwSectionFrm::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() )
			SwLayoutFrm::Modify( &aOldSet, &aNewSet );
	}
	else
		_UpdateAttr( pOld, pNew, nInvFlags );

	if ( nInvFlags != 0 )
	{
		if ( nInvFlags & 0x01 )
			InvalidateSize();
		if ( nInvFlags & 0x10 )
			SetCompletePaint();
	}
}

void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
{
    // --> OD #i117863#
    const SwSectionFrmMoveAndDeleteHint* pHint = 
                    dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint);
    if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
    {
        SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() );
    }
    // <--
}

void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
							sal_uInt8 &rInvFlags,
							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
{
	sal_Bool bClear = sal_True;
	const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
	switch( nWhich )
	{   // Mehrspaltigkeit in Fussnoten unterdruecken...
		case RES_FMT_CHG:
		{
			const SwFmtCol& rNewCol = GetFmt()->GetCol();
			if( !IsInFtn() )
			{
				//Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
				//nicht auf das alte Spaltenattribut verlassen. Da diese
				//wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
				//bleibt uns nur einen temporaeres Attribut zu basteln.
				SwFmtCol aCol;
				if ( Lower() && Lower()->IsColumnFrm() )
				{
					sal_uInt16 nCol = 0;
					SwFrm *pTmp = Lower();
					do
					{	++nCol;
						pTmp = pTmp->GetNext();
					} while ( pTmp );
					aCol.Init( nCol, 0, 1000 );
				}
				sal_Bool bChgFtn = IsFtnAtEnd();
				sal_Bool bChgEndn = IsEndnAtEnd();
				sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
				CalcFtnAtEndFlag();
				CalcEndAtEndFlag();
				bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
						  ( bChgEndn != IsEndnAtEnd() ) ||
						  ( bChgMyEndn != IsEndnoteAtMyEnd() );
				ChgColumns( aCol, rNewCol, bChgFtn );
				rInvFlags |= 0x10;
			}
			rInvFlags |= 0x01;
			bClear = sal_False;
		}
			break;

		case RES_COL:
			if( !IsInFtn() )
			{
				ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
				rInvFlags |= 0x11;
			}
			break;

		case RES_FTN_AT_TXTEND:
			if( !IsInFtn() )
			{
				sal_Bool bOld = IsFtnAtEnd();
				CalcFtnAtEndFlag();
				if( bOld != IsFtnAtEnd() )
				{
					const SwFmtCol& rNewCol = GetFmt()->GetCol();
					ChgColumns( rNewCol, rNewCol, sal_True );
					rInvFlags |= 0x01;
				}
			}
			break;

		case RES_END_AT_TXTEND:
			if( !IsInFtn() )
			{
				sal_Bool bOld = IsEndnAtEnd();
				sal_Bool bMyOld = IsEndnoteAtMyEnd();
				CalcEndAtEndFlag();
				if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
				{
					const SwFmtCol& rNewCol = GetFmt()->GetCol();
					ChgColumns( rNewCol, rNewCol, sal_True );
					rInvFlags |= 0x01;
				}
			}
			break;
		case RES_COLUMNBALANCE:
			rInvFlags |= 0x01;
			break;

        case RES_FRAMEDIR :
            SetDerivedR2L( sal_False );
            CheckDirChange();
            break;

		case RES_PROTECT:
			{
				ViewShell *pSh = getRootFrm()->GetCurrShell();
				if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
					pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
			}
			break;

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

/*-----------------09.06.99 14:58-------------------
 * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
 * page causes a maximal Size of the sectionframe.
 * --------------------------------------------------*/

sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
{
	if( HasFollow() )
	{
		if( !bCheckFollow ) // Don't check superfluous follows
			return sal_True;
		const SwSectionFrm* pFoll = GetFollow();
		while( pFoll && pFoll->IsSuperfluous() )
			pFoll = pFoll->GetFollow();
		if( pFoll )
			return sal_True;
	}
	if( IsFtnAtEnd() )
		return sal_False;
	const SwFtnContFrm* pCont = ContainsFtnCont();
	if( !IsEndnAtEnd() )
		return 0 != pCont;
	sal_Bool bRet = sal_False;
	while( pCont && !bRet )
	{
		if( pCont->FindFootNote() )
			bRet = sal_True;
		else
			pCont = ContainsFtnCont( pCont );
	}
	return bRet;
}

/*-----------------09.06.99 15:07-------------------
 * sal_Bool SwSectionFrm::ContainsFtnCont()
 * checks every Column for FtnContFrms.
 * --------------------------------------------------*/

SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
{
	SwFtnContFrm* pRet = NULL;
	const SwLayoutFrm* pLay;
	if( pCont )
	{
		pLay = pCont->FindFtnBossFrm( 0 );
		ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
		pLay = (SwLayoutFrm*)pLay->GetNext();
	}
	else if( Lower() && Lower()->IsColumnFrm() )
		pLay = (SwLayoutFrm*)Lower();
	else
		pLay = NULL;
	while ( !pRet && pLay )
	{
		if( pLay->Lower() && pLay->Lower()->GetNext() )
		{
			ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(),
					"ToMaximize: Unexspected Frame" );
			pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
		}
		ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
				"ToMaximize: ColFrm exspected" );
		pLay = (SwLayoutFrm*)pLay->GetNext();
	}
	return pRet;
}

void SwSectionFrm::InvalidateFtnPos()
{
	SwFtnContFrm* pCont = ContainsFtnCont( NULL );
	if( pCont )
	{
		SwFrm *pTmp = pCont->ContainsCntnt();
		if( pTmp )
			pTmp->_InvalidatePos();
	}
}

/*-----------------18.03.99 10:37-------------------
 * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
 * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
 * Das Undersized-Flag wird ggf. korrigiert.
 * --------------------------------------------------*/

long SwSectionFrm::Undersize( sal_Bool bOverSize )
{
	bUndersized = sal_False;
    SWRECTFN( this )
    long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
	if( nRet > 0 )
		bUndersized = sal_True;
	else if( !bOverSize )
		nRet = 0;
	return nRet;
}

/// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
/// before format of current one, because current one can move backward.
/// After moving backward to a previous page method <FindNext()> will return
/// the text frame presenting the first page footnote, if it exists. Thus, the
/// rest of the footnote/endnote container would not be formatted.
void SwSectionFrm::CalcFtnCntnt()
{
	SwFtnContFrm* pCont = ContainsFtnCont();
	if( pCont )
	{
		SwFrm* pFrm = pCont->ContainsAny();
		if( pFrm )
			pCont->Calc();
		while( pFrm && IsAnLower( pFrm ) )
		{
			SwFtnFrm* pFtn = pFrm->FindFtnFrm();
			if( pFtn )
				pFtn->Calc();
            // OD 01.04.2003 #108446# - determine next frame before format current frame.
            SwFrm* pNextFrm = 0;
            {
                if( pFrm->IsSctFrm() )
                {
                    pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
                }
                if( !pNextFrm )
                {
                    pNextFrm = pFrm->FindNext();
                }
            }
			pFrm->Calc();
            pFrm = pNextFrm;
		}
	}
}

/* -----------------09.02.99 14:26-------------------
 * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
 * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
 * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
 * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
 * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
 * muessen vom Layout/beim Formatieren ignoriert werden.
 *
 * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
 * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
 * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
 * --------------------------------------------------*/

void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
{
	if( !pDestroy )
		pDestroy = new SwDestroyList;
	sal_uInt16 nPos;
	if( !pDestroy->Seek_Entry( pDel, &nPos ) )
		pDestroy->Insert( pDel );
}

void SwRootFrm::_DeleteEmptySct()
{
	ASSERT( pDestroy, "Keine Liste, keine Kekse" );
	while( pDestroy->Count() )
	{
		SwSectionFrm* pSect = (*pDestroy)[0];
		pDestroy->Remove( sal_uInt16(0) );
		ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
				"DeleteEmptySct: Locked SectionFrm" );
		if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
		{
			SwLayoutFrm* pUp = pSect->GetUpper();
			pSect->Remove();
			delete pSect;
			if( pUp && !pUp->Lower() )
			{
				if( pUp->IsPageBodyFrm() )
					pUp->getRootFrm()->SetSuperfluous();
				else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
					pUp->GetUpper() )
				{
					pUp->Cut();
					delete pUp;
				}
			}
		}
		else {
			ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
        }
	}
}

void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
{
	ASSERT( pDestroy, "Where's my list?" );
	sal_uInt16 nPos;
	if( pDestroy->Seek_Entry( pSct, &nPos ) )
		pDestroy->Remove( nPos );
}

#ifdef DBG_UTIL

sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
{
	sal_uInt16 nPos;
	return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
}

#endif

bool SwSectionFrm::IsBalancedSection() const
{
    bool bRet = false;
    if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
    {
        bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
    }
    return bRet;
}

