/**************************************************************
 * 
 * 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 "rootfrm.hxx"
#include "pagefrm.hxx"
#include "cntfrm.hxx"
#include "viewsh.hxx"
#include "doc.hxx"
#include "viewimp.hxx"
#include "viewopt.hxx"
#include "swtypes.hxx"
#include "dflyobj.hxx"
#include "dcontact.hxx"
#include "flyfrm.hxx"
#include "frmtool.hxx"
#include "txtftn.hxx"
#include "fmtftn.hxx"
#include <editeng/ulspitem.hxx>
#include <editeng/keepitem.hxx>

#include <vcl/outdev.hxx>
#include <fmtfsize.hxx>
#include <fmtanchr.hxx>
#include <fmtclbl.hxx>

#include "tabfrm.hxx"
#include "ftnfrm.hxx"
#include "txtfrm.hxx"
#include "pagedesc.hxx"
#include "ftninfo.hxx"
#include "sectfrm.hxx"
#include "dbg_lay.hxx"

// --> OD 2004-06-23 #i28701#
#include <sortedobjs.hxx>
#include <layouter.hxx>
// --> OD 2004-11-01 #i36347#
#include <flyfrms.hxx>
// <--

//------------------------------------------------------------------------
//				Move-Methoden
//------------------------------------------------------------------------

/*************************************************************************
|*
|*	SwCntntFrm::ShouldBwdMoved()
|*
|* 	Beschreibung		Returnwert sagt, ob der Frm verschoben werden sollte.
|*	Ersterstellung		MA 05. Dec. 96
|*	Letzte Aenderung	MA 05. Dec. 96
|*
|*************************************************************************/


sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & )
{
	if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
	{
		//Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
		//Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
		//moechte die FixSize die gleiche ist, die der Frm selbst hat.
		//In diesem Fall kann einfach geprueft werden, ob der Frm genug
		//Platz fuer seine VarSize findet, ist dies nicht der Fall kann
		//gleich auf das Verschieben verzichtet werden.
		//Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
		//durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
		//aufspalten kann.
		//Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
		//(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
		//der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
		//etwas Platz zur Verfuegung steht).

		//Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
		//Die Breite.

		//Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
		//von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
		//falls der Frm nicht in das Blatt passt, nicht mehr auf die
		//dazwischenliegenden Blaetter geachtet werden.
		sal_uInt8 nMoveAnyway = 0;
		SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
		SwPageFrm *pOldPage = FindPageFrm();

		if ( SwFlowFrm::IsMoveBwdJump() )
			return sal_True;

		if( IsInFtn() && IsInSct() )
		{
			SwFtnFrm* pFtn = FindFtnFrm();
			SwSectionFrm* pMySect = pFtn->FindSctFrm();
			if( pMySect && pMySect->IsFtnLock() )
			{
				SwSectionFrm *pSect = pNewUpper->FindSctFrm();
				while( pSect && pSect->IsInFtn() )
					pSect = pSect->GetUpper()->FindSctFrm();
				ASSERT( pSect, "Escaping footnote" );
				if( pSect != pMySect )
					return sal_False;
			}
		}
        SWRECTFN( this )
        SWRECTFNX( pNewUpper )
        if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
                 (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 )
			nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage

        // OD 2004-05-26 #i25904# - do *not* move backward,
        // if <nMoveAnyway> equals 3 and no space is left in new upper.
        nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
		{
            const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
			SwTwips nSpace = 0;
			SwRect aRect( pNewUpper->Prt() );
			aRect.Pos() += pNewUpper->Frm().Pos();
			const SwFrm *pPrevFrm = pNewUpper->Lower();
			while ( pPrevFrm )
			{
                SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
                // OD 2004-03-01 #106629#:
                // consider lower spacing of last frame in a table cell
                {
                    // check, if last frame is inside table and if it includes
                    // its lower spacing.
                    if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
                         pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
                    {
                        const SwFrm* pLastFrm = pPrevFrm;
                        // if last frame is a section, take its last content
                        if ( pPrevFrm->IsSctFrm() )
                        {
                            pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
                            if ( pLastFrm &&
                                 pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
                            {
                                pLastFrm = pLastFrm->FindTabFrm();
                            }
                        }

                        if ( pLastFrm )
                        {
                            SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
                            const SwBorderAttrs& rAttrs = *aAccess.Get();
                            nNewTop -= rAttrs.GetULSpace().GetLower();
                        }
                    }
                }
                (aRect.*fnRectX->fnSetTop)( nNewTop );

                pPrevFrm = pPrevFrm->GetNext();
            }

			nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);

            //determine space left in new upper frame
            nSpace = (aRect.*fnRectX->fnGetHeight)();
            const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
            if ( IsInFtn() ||
                 (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
                 pNewUpper->IsCellFrm() ||
                 ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
                   ( pNewUpper->IsColBodyFrm() &&
                     !pNewUpper->GetUpper()->GetPrev() &&
                     !pNewUpper->GetUpper()->GetNext() ) ) ) )
                nSpace += pNewUpper->Grow( LONG_MAX, sal_True );

			if ( nMoveAnyway < 3 )
			{
                if ( nSpace )
				{
					//Keine Beruecksichtigung der Fussnoten die an dem Absatz
					//kleben, denn dies wuerde extrem unuebersichtlichen Code
					//beduerfen (wg. Beruecksichtung der Breiten und vor allem
					//der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).

					// _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
					// befragt werden.
					// _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
					// dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
					// vorgenommen wird.
                    // --> OD 2007-11-26 #b6614158#
                    const sal_uInt8 nBwdMoveNecessaryResult =
                                            BwdMoveNecessary( pNewPage, aRect);
                    const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
                                                nBwdMoveNecessaryResult == 3 );

                    return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
                                      bObjsInNewUpper );
                    // <--
				}
				//Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
				//brauchbares Ergebnis liefern, also muessen wir wirklich
				//zurueckfliessen
				else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
                    !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
					( pNewUpper->GetUpper()->GetPrev() ||
					  pNewUpper->GetUpper()->GetNext() ) )
					return sal_True;
				else
					return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
			}
            else
            {
                // OD 2004-05-26 #i25904# - check for space left in new upper
                if ( nSpace )
                    return sal_True;
                else
                    return sal_False;
            }
		}
	}
	return  sal_False;
}

//------------------------------------------------------------------------
//				Calc-Methoden
//------------------------------------------------------------------------

/*************************************************************************
|*
|*	SwFrm::Prepare()
|*
|*	Beschreibung		Bereitet den Frm auf die 'Formatierung' (MakeAll())
|*		vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
|*		denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
|*		die Position von Upper und Prev gueltig sind, mithin also ein
|*		rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
|*		Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
|*		das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
|*		deshalb solle der Rekursive Aufruf hier kein Problem sein.
|*		Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
|*		damit die Formatierung von Vorgaengern umgangen werden kann.
|*		So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
|*	Ersterstellung		MA ??
|*	Letzte Aenderung	MA 13. Dec. 93
|*
|*************************************************************************/
//Zwei kleine Freundschaften werden hier zu einem Geheimbund.
inline void PrepareLock( SwFlowFrm *pTab )
{
	pTab->LockJoin();
}
inline void PrepareUnlock( SwFlowFrm *pTab )
{
	pTab->UnlockJoin();

}

// hopefully, one day this function simply will return 'false'
bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
{
    return !rFrm.GetUpper()->IsSctFrm() &&
           !rFrm.GetUpper()->IsFooterFrm() &&
           // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
           !rFrm.GetUpper()->IsFlyFrm() &&
           // <--
           !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
           !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
}

void SwFrm::PrepareMake()
{
    StackHack aHack;
	if ( GetUpper() )
	{
        if ( lcl_IsCalcUpperAllowed( *this ) )
            GetUpper()->Calc();
		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
		if ( !GetUpper() )
			return;

		const sal_Bool bCnt = IsCntntFrm();
		const sal_Bool bTab = IsTabFrm();
		sal_Bool bNoSect = IsInSct();
		sal_Bool bOldTabLock = sal_False, bFoll = sal_False;
		SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;

		if ( bTab )
		{
			pThis = (SwTabFrm*)this;
			bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
			::PrepareLock( (SwTabFrm*)this );
			bFoll = pThis->IsFollow();
		}
		else if( IsSctFrm() )
		{
			pThis = (SwSectionFrm*)this;
			bFoll = pThis->IsFollow();
			bNoSect = sal_False;
		}
		else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) &&
			 GetPrev() )
		{
			//Wenn der Master gereade ein CalcFollow ruft braucht die Kette
			//nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
			if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() )
			{
				MakeAll();
				return;
			}
		}

        // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
        // frame is a table frame and its previous frame wants to keep with it.
        const bool bFormatPrev = !bTab ||
                                 !GetPrev() ||
                                 !GetPrev()->GetAttrSet()->GetKeep().GetValue();
        if ( bFormatPrev )
        {
            SwFrm *pFrm = GetUpper()->Lower();
            while ( pFrm != this )
            {
                ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
                if ( !pFrm )
                    return; //Oioioioi ...

                if ( !pFrm->IsValid() )
                {
                    //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
                    //der Stabilitaet beitraegt:
                    //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
                    //so wuerde dieser mich beim Formatieren deleten; wie jeder
                    //leicht sehen kann waere dies eine etwas unuebersichtliche
                    //Situation die es zu vermeiden gilt.
                    if ( bFoll && pFrm->IsFlowFrm() &&
                         (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
                        break;

    //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
    //die ganze Kette nocheinmal abhuenern.
    //              pFrm->Calc();
                    pFrm->MakeAll();
                    if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
                        break;
                }
                //Die Kette kann bei CntntFrms waehrend des durchlaufens
                //aufgebrochen werden, deshalb muss der Nachfolger etwas
                //umstaendlich ermittelt werden. However, irgendwann _muss_
                //ich wieder bei mir selbst ankommen.
                pFrm = pFrm->FindNext();

                //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
                //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
                //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
                // => wir finden uns selbst nicht mehr!
                if( bNoSect && pFrm && pFrm->IsSctFrm() )
                {
                    SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
                    if( pCnt )
                        pFrm = pCnt;
                }
            }
            ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
            if ( !GetUpper() )
                return;

            if ( lcl_IsCalcUpperAllowed( *this ) )
                GetUpper()->Calc();

            ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
        }

		if ( bTab && !bOldTabLock )
			::PrepareUnlock( (SwTabFrm*)this );
	}
	MakeAll();
}

void SwFrm::OptPrepareMake()
{
    // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
    if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
         !GetUpper()->IsFlyFrm() )
    // <--
	{
		GetUpper()->Calc();
		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
		if ( !GetUpper() )
			return;
	}
	if ( GetPrev() && !GetPrev()->IsValid() )
		PrepareMake();
	else
	{
		StackHack aHack;
		MakeAll();
	}
}



void SwFrm::PrepareCrsr()
{
	StackHack aHack;
	if( GetUpper() && !GetUpper()->IsSctFrm() )
	{
		GetUpper()->PrepareCrsr();
		GetUpper()->Calc();

		ASSERT( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
		if ( !GetUpper() )
			return;

		const sal_Bool bCnt = IsCntntFrm();
		const sal_Bool bTab = IsTabFrm();
		sal_Bool bNoSect = IsInSct();

		sal_Bool bOldTabLock = sal_False, bFoll;
		SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;

		if ( bTab )
		{
			bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
			::PrepareLock( (SwTabFrm*)this );
			pThis = (SwTabFrm*)this;
		}
		else if( IsSctFrm() )
		{
			pThis = (SwSectionFrm*)this;
			bNoSect = sal_False;
		}
		bFoll = pThis && pThis->IsFollow();

		SwFrm *pFrm = GetUpper()->Lower();
		while ( pFrm != this )
		{
			ASSERT( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
			if ( !pFrm )
				return;	//Oioioioi ...

			if ( !pFrm->IsValid() )
			{
				//Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
				//der Stabilitaet beitraegt:
				//Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
				//so wuerde dieser mich beim Formatieren deleten; wie jeder
				//leicht sehen kann waere dies eine etwas unuebersichtliche
				//Situation die es zu vermeiden gilt.
				if ( bFoll && pFrm->IsFlowFrm() &&
					 (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
					break;

				pFrm->MakeAll();
			}
			//Die Kette kann bei CntntFrms waehrend des durchlaufens
			//aufgebrochen werden, deshalb muss der Nachfolger etwas
			//umstaendlich ermittelt werden. However, irgendwann _muss_
			//ich wieder bei mir selbst ankommen.
			pFrm = pFrm->FindNext();
			if( bNoSect && pFrm && pFrm->IsSctFrm() )
			{
				SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
				if( pCnt )
					pFrm = pCnt;
			}
		}
		ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
		if ( !GetUpper() )
			return;

		GetUpper()->Calc();

		ASSERT( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );

		if ( bTab && !bOldTabLock )
			::PrepareUnlock( (SwTabFrm*)this );
	}
	Calc();
}

/*************************************************************************
|*
|*	SwFrm::MakePos()
|*
|*	Ersterstellung		MA ??
|*	Letzte Aenderung	MA 24. May. 93
|*
|*************************************************************************/

// Hier wird GetPrev() zurueckgegeben, allerdings werden
// dabei leere SectionFrms ueberlesen
SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True )
{
	SwFrm* pRet = pFrm->GetPrev();
	if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
		bSectPrv && !pFrm->IsColumnFrm() )
		pRet = pFrm->GetUpper()->GetPrev();
	while( pRet && pRet->IsSctFrm() &&
		   !((SwSectionFrm*)pRet)->GetSection() )
		pRet = pRet->GetPrev();
	return pRet;
}

SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
{
	SwFrm *pRet = pFrm;
	do
	{
		pRet = lcl_Prev( pRet );
	} while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
	return pRet;
}

void SwFrm::MakePos()
{
	if ( !bValidPos )
	{
		bValidPos = sal_True;
		sal_Bool bUseUpper = sal_False;
		SwFrm* pPrv = lcl_Prev( this );
        if ( pPrv &&
             ( !pPrv->IsCntntFrm() ||
               ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
           )
		{
            if ( !StackHack::IsLocked() &&
                 ( !IsInSct() || IsSctFrm() ) &&
                 !pPrv->IsSctFrm() &&
                 !pPrv->GetAttrSet()->GetKeep().GetValue()
               )
            {
				pPrv->Calc();	//hierbei kann der Prev verschwinden!
            }
			else if ( pPrv->Frm().Top() == 0 )
            {
				bUseUpper = sal_True;
            }
		}

		pPrv = lcl_Prev( this, sal_False );
        sal_uInt16 nMyType = GetType();
        SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this  ) )
        if ( !bUseUpper && pPrv )
        {
            aFrm.Pos( pPrv->Frm().Pos() );
            if( FRM_NEIGHBOUR & nMyType )
            {
                sal_Bool bR2L = IsRightToLeft();
                if( bR2L )
                    (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
                                               (aFrm.*fnRect->fnGetWidth)() );
                else
                    (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
                                          (pPrv->Frm().*fnRect->fnGetWidth)() );

                // cells may now leave their uppers
                if( bVert && FRM_CELL & nMyType && !bReverse )
                    aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
            }
            else if( bVert && FRM_NOTE_VERT & nMyType )
            {
                if( bReverse )
                    aFrm.Pos().X() += pPrv->Frm().Width();
                else
                    //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
                {
					if ( bVertL2R )
                   		aFrm.Pos().X() += pPrv->Frm().Width();
                	else
                   		aFrm.Pos().X() -= aFrm.Width();
              	}
            }
            else
                aFrm.Pos().Y() += pPrv->Frm().Height();
        }
		else if ( GetUpper() )
		{
            // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
            // If parent frame is a footer frame and its <ColLocked()>, then
            // do *not* calculate it.
            // NOTE: Footer frame is <ColLocked()> during its
            //     <FormatSize(..)>, which is called from <Format(..)>, which
            //     is called from <MakeAll()>, which is called from <Calc()>.
            // --> OD 2005-11-17 #i56850#
            // - no format of upper Writer fly frame, which is anchored
            //   at-paragraph or at-character.
            if ( !GetUpper()->IsTabFrm() &&
                 !( IsTabFrm() && GetUpper()->IsInTab() ) &&
                 !GetUpper()->IsSctFrm() &&
                 !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) &&
                 !( GetUpper()->IsFooterFrm() &&
                    GetUpper()->IsColLocked() )
               )
            {
                GetUpper()->Calc();
            }
            // <--
			pPrv = lcl_Prev( this, sal_False );
			if ( !bUseUpper && pPrv )
            {
                aFrm.Pos( pPrv->Frm().Pos() );
                if( FRM_NEIGHBOUR & nMyType )
                {
                    sal_Bool bR2L = IsRightToLeft();
                    if( bR2L )
                        (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
                                                 (aFrm.*fnRect->fnGetWidth)() );
                    else
                        (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
                                          (pPrv->Frm().*fnRect->fnGetWidth)() );

                    // cells may now leave their uppers
                    if( bVert && FRM_CELL & nMyType && !bReverse )
                        aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
                }
                else if( bVert && FRM_NOTE_VERT & nMyType )
                {
                    if( bReverse )
                        aFrm.Pos().X() += pPrv->Frm().Width();
                    else
                        aFrm.Pos().X() -= aFrm.Width();
                }
                else
                    aFrm.Pos().Y() += pPrv->Frm().Height();
			}
			else
			{
				aFrm.Pos( GetUpper()->Frm().Pos() );
				aFrm.Pos() += GetUpper()->Prt().Pos();
                if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
                {
                    if( bVert )
                        aFrm.Pos().Y() += GetUpper()->Prt().Height()
                                          - aFrm.Height();
                    else
                        aFrm.Pos().X() += GetUpper()->Prt().Width()
                                          - aFrm.Width();
                }
                //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
                else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse )
                    aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
			}
		}
		else
			aFrm.Pos().X() = aFrm.Pos().Y() = 0;
        //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
        if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() )
            aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
		bValidPos = sal_True;
	}
}

/*************************************************************************
|*
|*	SwPageFrm::MakeAll()
|*
|*	Ersterstellung		MA 23. Feb. 93
|*	Letzte Aenderung	MA 20. Jul. 98
|*
|*************************************************************************/
// --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
{
	//Und dann kann es natuerlich noch Absatzgebundene
	//Rahmen geben, die unterhalb ihres Absatzes stehen.
	long nMax = 0;
	for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
	{
        // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
        // entries.
        SwAnchoredObject* pObj = (*pSortedObjs)[i];
		long nTmp = 0;
        if ( pObj->ISA(SwFlyFrm) )
		{
            SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
			if( pFly->Frm().Top() != WEIT_WECH &&
				( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
				  ( pFly->IsFlyAtCntFrm() &&
                    ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
                                          pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
			{
				nTmp = pFly->Frm().Bottom();
			}
		}
		else
            nTmp = pObj->GetObjRect().Bottom();
		nMax = Max( nTmp, nMax );
        // <--
	}
	++nMax; //Unterkante vs. Hoehe!
	rBot = Max( rBot, nMax );
}

void SwPageFrm::MakeAll()
{
	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )

	const SwRect aOldRect( Frm() );		//Anpassung der Root-Groesse
	const SwLayNotify aNotify( this );	//uebernimmt im DTor die Benachrichtigung
	SwBorderAttrAccess *pAccess = 0;
	const SwBorderAttrs*pAttrs = 0;

    while ( !bValidPos || !bValidSize || !bValidPrtArea )
	{
		if ( !bValidPos )
		{
            // PAGES01
            bValidPos = sal_True; // positioning of the pages is taken care of by the root frame
        }

		if ( !bValidSize || !bValidPrtArea )
		{
			if ( IsEmptyPage() )
			{
				Frm().Width( 0 );  Prt().Width( 0 );
				Frm().Height( 0 ); Prt().Height( 0 );
				Prt().Left( 0 );   Prt().Top( 0 );
				bValidSize = bValidPrtArea = sal_True;
			}
			else
			{
				if ( !pAccess )
				{
					pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
					pAttrs = pAccess->Get();
				}
				//Bei der BrowseView gelten feste Einstellungen.
				ViewShell *pSh = getRootFrm()->GetCurrShell();
                if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
				{
					const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
					const long nTop    = pAttrs->CalcTopLine()   + aBorder.Height();
					const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();

					long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
					if ( nWidth < pSh->GetBrowseWidth() )
						nWidth = pSh->GetBrowseWidth();
					nWidth += + 2 * aBorder.Width();
/*
					long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
					if ( nWidth < pSh->VisArea().Width() )
						nWidth = pSh->VisArea().Width(); */

					nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
					Frm().Width( nWidth );

					SwLayoutFrm *pBody = FindBodyCont();
					if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
					{
						//Fuer Spalten gilt eine feste Hoehe
						Frm().Height( pAttrs->GetSize().Height() );
					}
					else
					{
						//Fuer Seiten ohne Spalten bestimmt der Inhalt die
						//Groesse.
						long nBot = Frm().Top() + nTop;
						SwFrm *pFrm = Lower();
						while ( pFrm )
						{
							long nTmp = 0;
							SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
							while ( pCnt && (pCnt->GetUpper() == pFrm ||
											 ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
							{
								nTmp += pCnt->Frm().Height();
								if( pCnt->IsTxtFrm() &&
									((SwTxtFrm*)pCnt)->IsUndersized() )
									nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
											- pCnt->Prt().Height();
								else if( pCnt->IsSctFrm() &&
										 ((SwSectionFrm*)pCnt)->IsUndersized() )
									nTmp += ((SwSectionFrm*)pCnt)->Undersize();
								pCnt = pCnt->FindNext();
							}
                            // OD 29.10.2002 #97265# - consider invalid body frame properties
                            if ( pFrm->IsBodyFrm() &&
                                 ( !pFrm->GetValidSizeFlag() ||
                                   !pFrm->GetValidPrtAreaFlag() ) &&
                                 ( pFrm->Frm().Height() < pFrm->Prt().Height() )
                               )
                            {
                                nTmp = Min( nTmp, pFrm->Frm().Height() );
                            }
                            else
                            {
                                // OD 30.10.2002 #97265# - assert invalid lower property
                                ASSERT( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
                                        "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
                                nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
                            }
							if ( !pFrm->IsBodyFrm() )
								nTmp = Min( nTmp, pFrm->Frm().Height() );
							nBot += nTmp;
							// Hier werden die absatzgebundenen Objekte ueberprueft,
							// ob sie ueber den Body/FtnCont hinausragen.
							if( pSortedObjs && !pFrm->IsHeaderFrm() &&
								!pFrm->IsFooterFrm() )
								lcl_CheckObjects( pSortedObjs, pFrm, nBot );
							pFrm = pFrm->GetNext();
						}
						nBot += nBottom;
						//Und die Seitengebundenen
						if ( pSortedObjs )
							lcl_CheckObjects( pSortedObjs, this, nBot );
						nBot -= Frm().Top();
                        // --> OD 2004-11-10 #i35143# - If second page frame
                        // exists, the first page doesn't have to fulfill the
                        // visible area.
                        if ( !GetPrev() && !GetNext() )
                        // <--
                        {
                            nBot = Max( nBot, pSh->VisArea().Height() );
                        }
                        // --> OD 2004-11-10 #i35143# - Assure, that the page
                        // doesn't exceed the defined browse height.
                        Frm().Height( Min( nBot, BROWSE_HEIGHT ) );
                        // <--
					}
					Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
					Prt().Top  ( nTop );
					Prt().Width( Frm().Width() - ( Prt().Left()
						+ pAttrs->CalcRightLine() + aBorder.Width() ) );
					Prt().Height( Frm().Height() - (nTop + nBottom) );
					bValidSize = bValidPrtArea = sal_True;
				}
				else
				{	//FixSize einstellen, bei Seiten nicht vom Upper sondern vom
					//Attribut vorgegeben.
					Frm().SSize( pAttrs->GetSize() );
					Format( pAttrs );
				}
			}
		}
	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
	delete pAccess;

    // PAGES01
    if ( Frm() != aOldRect && GetUpper() )
        static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );

#ifdef DBG_UTIL
	//Der Upper (Root) muss mindestens so breit
	//sein, dass er die breiteste Seite aufnehmen kann.
	if ( GetUpper() )
    {
        ASSERT( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
	}
#endif
}

/*************************************************************************
|*
|*	SwLayoutFrm::MakeAll()
|*
|*	Ersterstellung		MA ??
|*	Letzte Aenderung	MA 28. Nov. 95
|*
|*************************************************************************/


void SwLayoutFrm::MakeAll()
{
	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )

		//uebernimmt im DTor die Benachrichtigung
	const SwLayNotify aNotify( this );
    sal_Bool bVert = IsVertical();
    //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );

	SwBorderAttrAccess *pAccess = 0;
	const SwBorderAttrs*pAttrs = 0;

	while ( !bValidPos || !bValidSize || !bValidPrtArea )
	{
		if ( !bValidPos )
			MakePos();

		if ( GetUpper() )
		{
            // NEW TABLES
            if ( IsLeaveUpperAllowed() )
            {
                if ( !bValidSize )
                    bValidPrtArea = sal_False;
            }
            else
            {
                if ( !bValidSize )
                {
                    //FixSize einstellen, die VarSize wird von Format() nach
                    //Berechnung der PrtArea eingestellt.
                    bValidPrtArea = sal_False;

                    SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
                    if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
                    {
                        SwFrm* pNxt = GetPrev();
                        while( pNxt && !pNxt->IsHeaderFrm() )
                            pNxt = pNxt->GetPrev();
                        if( pNxt )
                            nPrtWidth -= pNxt->Frm().Height();
                        pNxt = GetNext();
                        while( pNxt && !pNxt->IsFooterFrm() )
                            pNxt = pNxt->GetNext();
                        if( pNxt )
                            nPrtWidth -= pNxt->Frm().Height();
                    }

                    const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();

                    if( IsNeighbourFrm() && IsRightToLeft() )
                        (Frm().*fnRect->fnSubLeft)( nDiff );
                    else
                        (Frm().*fnRect->fnAddRight)( nDiff );
                }
                else
                {
                    // Don't leave your upper
                    const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
                    if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
                        bValidSize = sal_False;
                }
            }
		}
		if ( !bValidSize || !bValidPrtArea )
		{
			if ( !pAccess )
			{
				pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
				pAttrs  = pAccess->Get();
			}
			Format( pAttrs );
		}
	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
	if ( pAccess )
		delete pAccess;
}

/*************************************************************************
|*
|*	SwCntntFrm::MakePrtArea()
|*
|*	Ersterstellung		MA 17. Nov. 92
|*	Letzte Aenderung	MA 03. Mar. 96
|*
|*************************************************************************/

sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
{
	sal_Bool bSizeChgd = sal_False;

	if ( !bValidPrtArea )
	{
		bValidPrtArea = sal_True;

        SWRECTFN( this )
		const sal_Bool bTxtFrm = IsTxtFrm();
		SwTwips nUpper = 0;
		if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
		{
			if ( ((SwTxtFrm*)this)->HasFollow() )
				((SwTxtFrm*)this)->JoinFrm();

            if( (Prt().*fnRect->fnGetHeight)() )
				((SwTxtFrm*)this)->HideHidden();
            Prt().Pos().X() = Prt().Pos().Y() = 0;
            (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
            (Prt().*fnRect->fnSetHeight)( 0 );
            nUpper = -( (Frm().*fnRect->fnGetHeight)() );
		}
		else
		{
			//Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!

			//An der FixSize gibt der umgebende Frame die Groesse vor, die
			//Raender werden einfach abgezogen.
            const long nLeft = rAttrs.CalcLeft( this );
            const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
            (this->*fnRect->fnSetXMargins)( nLeft, nRight );

			ViewShell *pSh = getRootFrm()->GetCurrShell();
            SwTwips nWidthArea;
            if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
                GetUpper()->IsPageBodyFrm() &&  // nicht dagegen bei BodyFrms in Columns
                pSh->GetViewOptions()->getBrowseMode() )
			{
				//Nicht ueber die Kante des sichbaren Bereiches hinausragen.
				//Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
				//geben kann (RootFrm::ImplCalcBrowseWidth())
				long nMinWidth = 0;

				for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i)
				{
                    // --> OD 2004-07-01 #i28701# - consider changed type of
                    // <SwSortedObjs> entries
                    SwAnchoredObject* pObj = (*GetDrawObjs())[i];
                    const SwFrmFmt& rFmt = pObj->GetFrmFmt();
                    const sal_Bool bFly = pObj->ISA(SwFlyFrm);
                    if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width()))
                        || rFmt.GetFrmSize().GetWidthPercent())
                    {
						continue;
                    }

                    if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
                    {
						nMinWidth = Max( nMinWidth,
                                         bFly ? rFmt.GetFrmSize().GetWidth()
                                              : pObj->GetObjRect().Width() );
                    }
                    // <--
				}

				const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
                long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
                nWidth -= (Prt().*fnRect->fnGetLeft)();
				nWidth -= rAttrs.CalcRightLine();
				nWidth = Max( nMinWidth, nWidth );
                (Prt().*fnRect->fnSetWidth)( Min( nWidth,
                                            (Prt().*fnRect->fnGetWidth)() ) );
			}

            if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
			{
				//Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
				//zu den Minimalwerten des UI
                (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY),
                                             (Frm().*fnRect->fnGetWidth)() ) );
                SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
                               (Prt().*fnRect->fnGetWidth)();
                if( (Prt().*fnRect->fnGetLeft)() > nTmp )
                    (Prt().*fnRect->fnSetLeft)( nTmp );
			}

			//Fuer die VarSize gelten folgende Regeln:
			//1. Der erste einer Kette hat keinen Rand nach oben
			//2. Nach unten gibt es nie einen Rand
			//3. Der Rand nach oben ist das Maximum aus dem Abstand des
			//	 Prev nach unten und dem eigenen Abstand nach oben.
			//Die drei Regeln werden auf die Berechnung der Freiraeume, die von
			//UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
			//Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
			//Umrandung und/oder Schatten vorgegeben.
			//4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss

			nUpper = CalcUpperSpace( &rAttrs, NULL );

            // OD 2004-03-02 #106629# - use new method <CalcLowerSpace(..)>
            SwTwips nLower = CalcLowerSpace( &rAttrs );
//            // in balanced columned section frames we do not want the
//            // common border
//            sal_Bool bCommonBorder = sal_True;
//            if ( IsInSct() && GetUpper()->IsColBodyFrm() )
//            {
//                const SwSectionFrm* pSct = FindSctFrm();
//                bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
//            }
//            SwTwips nLower = bCommonBorder ?
//                             rAttrs.GetBottomLine( this ) :
//                             rAttrs.CalcBottomLine();

            (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
            nUpper += nLower;
            nUpper -= (Frm().*fnRect->fnGetHeight)() -
                      (Prt().*fnRect->fnGetHeight)();
		}
		//Wenn Unterschiede zwischen Alter und neuer Groesse,
		//Grow() oder Shrink() rufen
		if ( nUpper )
		{
			if ( nUpper > 0 )
                GrowFrm( nUpper );
			else
                ShrinkFrm( -nUpper );
			bSizeChgd = sal_True;
		}
	}
	return bSizeChgd;
}

/*************************************************************************
|*
|*	SwCntntFrm::MakeAll()
|*
|*	Ersterstellung		MA ??
|*	Letzte Aenderung	MA 16. Dec. 96
|*
|*************************************************************************/

#define STOP_FLY_FORMAT 10
// --> OD 2006-09-25 #b6448963# - loop prevention
const int cnStopFormat = 15;
// <--

inline void ValidateSz( SwFrm *pFrm )
{
	if ( pFrm )
	{
		pFrm->bValidSize = sal_True;
		pFrm->bValidPrtArea = sal_True;
	}
}

void SwCntntFrm::MakeAll()
{
	ASSERT( GetUpper(), "keinen Upper?" );
	ASSERT( IsTxtFrm(), "MakeAll(), NoTxt" );

	if ( !IsFollow() && StackHack::IsLocked() )
		return;

	if ( IsJoinLocked() )
		return;

    ASSERT( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );

    StackHack aHack;

	if ( ((SwTxtFrm*)this)->IsLocked() )
	{
		ASSERT( sal_False, "Format fuer gelockten TxtFrm." );
		return;
	}

	LockJoin();
    long nFormatCount = 0;
    // --> OD 2006-09-25 #b6448963# - loop prevention
    int nConsequetiveFormatsWithoutChange = 0;
    // <--
	PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )

#ifdef DBG_UTIL
    const SwDoc *pDoc = GetAttrSet()->GetDoc();
	if( pDoc )
	{
		static sal_Bool bWarn = sal_False;
		if( pDoc->InXMLExport() )
		{
			ASSERT( bWarn, "Formatting during XML-export!" );
			bWarn = sal_True;
		}
		else
			bWarn = sal_False;
	}
#endif

	//uebernimmt im DTor die Benachrichtigung
	SwCntntNotify *pNotify = new SwCntntNotify( this );

	sal_Bool	bMakePage	= sal_True;		//solange sal_True kann eine neue Seite
									//angelegt werden (genau einmal)
	sal_Bool 	bMovedBwd	= sal_False;	//Wird sal_True wenn der Frame zurueckfliesst
	sal_Bool	bMovedFwd	= sal_False;	//solange sal_False kann der Frm zurueck-
									//fliessen (solange, bis er einmal
									//vorwaerts ge'moved wurde).
	sal_Bool	bFormatted	= sal_False;	//Fuer die Witwen und Waisen Regelung
									//wird der letzte CntntFrm einer Kette
									//u.U. zum Formatieren angeregt, dies
									//braucht nur einmal zu passieren.
									//Immer wenn der Frm gemoved wird muss
									//das Flag zurueckgesetzt werden.
	sal_Bool	bMustFit	= sal_False;	//Wenn einmal die Notbremse gezogen wurde,
									//werden keine anderen Prepares mehr
									//abgesetzt.
	sal_Bool	bFitPromise = sal_False;	//Wenn ein Absatz nicht passte, mit WouldFit
									//aber verspricht, dass er sich passend
									//einstellt wird dieses Flag gesetzt.
									//Wenn er dann sein Versprechen nicht haelt,
									//kann kontrolliert verfahren werden.
	sal_Bool bMoveable;
	const sal_Bool bFly	= IsInFly();
	const sal_Bool bTab = IsInTab();
	const sal_Bool bFtn = IsInFtn();
	const sal_Bool bSct = IsInSct();
	Point aOldFrmPos;				//Damit bei Turnarounds jew. mit der
	Point aOldPrtPos;				//letzten Pos verglichen und geprueft
									//werden kann, ob ein Prepare sinnvoll ist.

	SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
	const SwBorderAttrs &rAttrs = *aAccess.Get();

    // OD 2004-02-26 #i25029#
    if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
    {
        pNotify->SetBordersJoinedWithPrev();
    }

    const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() );

	SwSaveFtnHeight *pSaveFtn = 0;
	if ( bFtn )
	{
		SwFtnFrm *pFtn = FindFtnFrm();
		SwSectionFrm* pSct = pFtn->FindSctFrm();
		if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
		{
			SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
									pFtn->GetAttr()->GetFtn().IsEndNote() );
			if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
				pSaveFtn = new SwSaveFtnHeight( pBoss,
                    ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
		}
	}

    // --> OD 2008-08-12 #b6732519#
    if ( GetUpper()->IsSctFrm() &&
         HasFollow() &&
         GetFollow()->GetFrm() == GetNext() )
    {
        dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
    }
    // <--

    // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
    // because of its object positioning.
    if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
    {
        sal_uInt32 nToPageNum = 0L;
        const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
                                                    *(GetAttrSet()->GetDoc()),
                                                    *(static_cast<SwTxtFrm*>(this)),
                                                    nToPageNum );
        // --> OD 2006-01-27 #i58182#
        // Also move a paragraph forward, which is the first one inside a table cell.
        if ( bMoveFwdByObjPos &&
             FindPageFrm()->GetPhyPageNum() < nToPageNum &&
             ( lcl_Prev( this ) ||
               GetUpper()->IsCellFrm() ||
               ( GetUpper()->IsSctFrm() &&
                 GetUpper()->GetUpper()->IsCellFrm() ) ) &&
             IsMoveable() )
        {
            bMovedFwd = sal_True;
            MoveFwd( bMakePage, sal_False );
        }
        // <--
    }
    // <--

    //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
	//gleich verschoben werden.
    if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
	{
		bMovedFwd = sal_True;
        // OD 2004-03-02 #106629# - If follow frame is in table, it's master
        // will be the last in the current table cell. Thus, invalidate the
        // printing area of the master,
        if ( IsInTab() )
        {
            lcl_Prev( this )->InvalidatePrt();
        }
        MoveFwd( bMakePage, sal_False );
    }

    // OD 08.11.2002 #104840# - check footnote content for forward move.
    // If a content of a footnote is on a prior page/column as its invalid
    // reference, it can be moved forward.
    if ( bFtn && !bValidPos )
    {
        SwFtnFrm* pFtn = FindFtnFrm();
        SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
        if ( pRefCnt && !pRefCnt->IsValid() )
        {
            SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
            SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
            //<loop of movefwd until condition held or no move>
            if ( pFtnBossOfFtn && pFtnBossOfRef &&
                 pFtnBossOfFtn != pFtnBossOfRef &&
                 pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
            {
                bMovedFwd = sal_True;
                MoveFwd( bMakePage, sal_False );
            }
        }
    }

    SWRECTFN( this )

	while ( !bValidPos || !bValidSize || !bValidPrtArea )
	{
        // --> OD 2006-09-25 #b6448963# - loop prevention
        SwRect aOldFrm_StopFormat( Frm() );
        SwRect aOldPrt_StopFormat( Prt() );
        // <--
		if ( sal_True == (bMoveable = IsMoveable()) )
		{
			SwFrm *pPre = GetIndPrev();
			if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
			{
                SWREFRESHFN( this )
				bMovedFwd = sal_True;
				if ( bMovedBwd )
				{
					//Beim zurueckfliessen wurde der Upper angeregt sich
					//vollstaendig zu Painten, dass koennen wir uns jetzt
					//nach dem hin und her fliessen sparen.
					GetUpper()->ResetCompletePaint();
					//Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
					ASSERT( pPre, "missing old Prev" );
					if( !pPre->IsSctFrm() )
						::ValidateSz( pPre );
				}
				bMoveable = IsMoveable();
			}
		}

        aOldFrmPos = (Frm().*fnRect->fnGetPos)();
        aOldPrtPos = (Prt().*fnRect->fnGetPos)();

		if ( !bValidPos )
			MakePos();

		//FixSize einstellen, die VarSize wird von Format() justiert.
		if ( !bValidSize )
        {
            // --> OD 2006-01-03 #125452#
            // invalidate printing area flag, if the following conditions are hold:
            // - current frame width is 0.
            // - current printing area width is 0.
            // - frame width is adjusted to a value greater than 0.
            // - printing area flag is sal_True.
            // Thus, it's assured that the printing area is adjusted, if the
            // frame area width changes its width from 0 to something greater
            // than 0.
            // Note: A text frame can be in such a situation, if the format is
            //       triggered by method call <SwCrsrShell::SetCrsr()> after
            //       loading the document.
            const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
            if ( bValidPrtArea && nNewFrmWidth > 0 &&
                 (Frm().*fnRect->fnGetWidth)() == 0 &&
                 (Prt().*fnRect->fnGetWidth)() == 0 )
            {
                bValidPrtArea = sal_False;
            }

            (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
            // <--
        }
		if ( !bValidPrtArea )
		{
            const long nOldW = (Prt().*fnRect->fnGetWidth)();
            // --> OD 2004-09-28 #i34730# - keep current frame height
            const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
            // <--
			MakePrtArea( rAttrs );
            if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
				Prepare( PREP_FIXSIZE_CHG );
            // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
            // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
            // force a format. The format will check in its method
            // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
            // fit and if not, performs necessary actions.
            // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
            if ( bValidSize && !IsUndersized() &&
                 nOldH != (Frm().*fnRect->fnGetHeight)() )
            {
                // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
                // invalidation, if height decreases only by the additional
                // lower space as last content of a table cell and an existing
                // follow containing one line exists.
                const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
                const bool bNoPrepAdjustFrm =
                    nHDiff > 0 && IsInTab() && GetFollow() &&
                    ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
                    GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
                if ( !bNoPrepAdjustFrm )
                {
                    Prepare( PREP_ADJUST_FRM );
                    bValidSize = sal_False;
                }
                // <--
            }
            // <--
		}

		//Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
		//CntntFrm benachrichtigt werden.
		//Kriterium:
		//- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
		//- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
		if ( !bMustFit )
		{
			sal_Bool bWidow = sal_True;
            const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
            if ( bMoveable && !bFormatted && ( GetFollow() ||
                 ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
            {
				Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
				bValidSize = bWidow = sal_False;
			}
            if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
                (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
			{
				// In diesem Prepare erfolgt ggf. ein _InvalidateSize().
				// bValidSize wird sal_False und das Format() wird gerufen.
				Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
				if ( bWidow && GetFollow() )
				{	Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
					bValidSize = sal_False;
				}
			}
		}
		if ( !bValidSize )
        {
            bValidSize = bFormatted = sal_True;
            ++nFormatCount;
            if( nFormatCount > STOP_FLY_FORMAT )
                SetFlyLock( sal_True );
            // --> OD 2006-09-25 #b6448963# - loop prevention
            // No format any longer, if <cnStopFormat> consequetive formats
            // without change occur.
            if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
            {
                Format();
            }
#if OSL_DEBUG_LEVEL > 1
            else
            {
                ASSERT( false, "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
            }
#endif
            // <--
		}

        // FME 16.07.2003 #i16930# - removed this code because it did not work

        // OD 04.04.2003 #108446# - react on the situation detected in the text
        // formatting - see <SwTxtFrm::FormatAdjust(..)>:
        // text frame has to move forward, because its text formatting stopped,
        // created a follow and detected, that it contains no content.
/*        if ( IsTxtFrm() && bValidPos && bValidSize && bValidPrtArea &&
             (Frm().*fnRect->fnGetHeight)() == 0 &&
             HasFollow()
           )
        {
            SwFrm* pOldUpper = GetUpper();
            MoveFwd( sal_True, sal_False );
            if ( GetUpper() != pOldUpper )
            {
                bMovedFwd = sal_True;
                SWREFRESHFN( this )
                continue;
            }
        } */

        //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
		//ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
		//Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
		//geflossen sein.
		sal_Bool bDummy;
        if ( !lcl_Prev( this ) &&
             !bMovedFwd &&
             ( bMoveable || ( bFly && !bTab ) ) &&
			 ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
             && MoveBwd( bDummy ) )
        {
            SWREFRESHFN( this )
			bMovedBwd = sal_True;
			bFormatted = sal_False;
            if ( bKeep && bMoveable )
			{
				if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) )
				{
					bMovedFwd = sal_True;
					bMoveable = IsMoveable();
                    SWREFRESHFN( this )
				}
                Point aOldPos = (Frm().*fnRect->fnGetPos)();
                MakePos();
                if( aOldPos != (Frm().*fnRect->fnGetPos)() )
				{
					Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
					if ( !bValidSize )
					{
                        (Frm().*fnRect->fnSetWidth)( (GetUpper()->
                                                Prt().*fnRect->fnGetWidth)() );
						if ( !bValidPrtArea )
						{
                            const long nOldW = (Prt().*fnRect->fnGetWidth)();
                            MakePrtArea( rAttrs );
                            if( nOldW != (Prt().*fnRect->fnGetWidth)() )
								Prepare( PREP_FIXSIZE_CHG, 0, sal_False );
						}
						if( GetFollow() )
							Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
						bValidSize = bFormatted = sal_True;
						Format();
					}
				}
                SwFrm *pNxt = HasFollow() ? NULL : FindNext();
				while( pNxt && pNxt->IsSctFrm() )
				{   // Leere Bereiche auslassen, in die anderen hinein
					if( ((SwSectionFrm*)pNxt)->GetSection() )
					{
						SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
						if( pTmp )
						{
							pNxt = pTmp;
							break;
						}
					}
					pNxt = pNxt->FindNext();
				}
                if ( pNxt )
				{
                    pNxt->Calc();
                    if( bValidPos && !GetIndNext() )
                    {
                        SwSectionFrm *pSct = FindSctFrm();
                        if( pSct && !pSct->GetValidSizeFlag() )
                        {
                            SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
                            if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
                                bValidPos = sal_False;
                        }
                        else
                            bValidPos = sal_False;
                    }
				}
			}
		}

		//Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
		//dazu fuehren, dass seine Position obwohl unrichtig valide ist.
		if ( bValidPos )
		{
            // --> OD 2006-01-23 #i59341#
            // Workaround for inadequate layout algorithm:
            // suppress invalidation and calculation of position, if paragraph
            // has formatted itself at least STOP_FLY_FORMAT times and
            // has anchored objects.
            // Thus, the anchored objects get the possibility to format itself
            // and this probably solve the layout loop.
            if ( bFtn &&
                 nFormatCount <= STOP_FLY_FORMAT &&
                 !GetDrawObjs() )
            // <--
            {
                bValidPos = sal_False;
                MakePos();
                aOldFrmPos = (Frm().*fnRect->fnGetPos)();
                aOldPrtPos = (Prt().*fnRect->fnGetPos)();
            }
		}

        // --> OD 2006-09-25 #b6448963# - loop prevention
        {
            if ( aOldFrm_StopFormat == Frm() &&
                 aOldPrt_StopFormat == Prt() )
            {
                ++nConsequetiveFormatsWithoutChange;
            }
            else
            {
                nConsequetiveFormatsWithoutChange = 0;
            }
        }
        // <--

		//Wieder ein Wert ungueltig? - dann nochmal das ganze...
		if ( !bValidPos || !bValidSize || !bValidPrtArea )
			continue;

		//Fertig?
		// Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
        // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
        const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
        const long nBottomDist =  (Frm().*fnRect->fnBottomDist)( nPrtBottom );
        if( nBottomDist >= 0 )
		{
            if ( bKeep && bMoveable )
			{
				//Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
				//wird. Dadurch halten wir das Heft in der Hand, bis wirklich
				//(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
				//die durch staendig wiederholte Versuche entstehen.
				//Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
				//in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
				//Schema und spielte lieber Tuerme von Hanoi (#43669#).
                SwFrm *pNxt = HasFollow() ? NULL : FindNext();
				// Bei Bereichen nehmen wir lieber den Inhalt, denn nur
				// dieser kann ggf. die Seite wechseln
				while( pNxt && pNxt->IsSctFrm() )
				{
					if( ((SwSectionFrm*)pNxt)->GetSection() )
					{
						pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
						break;
					}
					pNxt = pNxt->FindNext();
				}
				if ( pNxt )
				{
                    const sal_Bool bMoveFwdInvalid = 0 != GetIndNext();
                    const sal_Bool bNxtNew =
                        ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
                        (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());

                    pNxt->Calc();

                    if ( !bMovedBwd &&
                         ((bMoveFwdInvalid && !GetIndNext()) ||
                          bNxtNew) )
                    {
                        if( bMovedFwd )
                            pNotify->SetInvaKeep();
                        bMovedFwd = sal_False;
                    }
				}
			}
			continue;
		}

		//Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
		//an der Zeit moeglichst konstruktive Veranderungen vorzunehmen

		//Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
		//ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
		//mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
		//zwar mit aller Kraft.
		if ( !bMoveable || IsUndersized() )
		{
			if( !bMoveable && IsInTab() )
			{
                long nDiff = -(Frm().*fnRect->fnBottomDist)(
                                        (GetUpper()->*fnRect->fnGetPrtBottom)() );
                long nReal = GetUpper()->Grow( nDiff );
				if( nReal )
					continue;
			}
			break;
		}

		//Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
		//so kann die Situation vielleicht doch noch durch Aufbrechen
		//aufgeklart werden. Diese Situation tritt bei einem frisch
		//erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
		//aber selbst noch zu gross fuer diese ist; also wiederum
		//aufgespalten werden muss.
		//Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
		//ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
		//trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
		sal_Bool bMoveOrFit = sal_False;
		sal_Bool bDontMoveMe = !GetIndPrev();
		if( bDontMoveMe && IsInSct() )
		{
			SwFtnBossFrm* pBoss = FindFtnBossFrm();
			bDontMoveMe = !pBoss->IsInSct() ||
						  ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
		}

        // Finally, we are able to split table rows. Therefore, bDontMoveMe
        // can be set to sal_False:
        if( bDontMoveMe && IsInTab() &&
            0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
            bDontMoveMe = sal_False;

        if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
                            (GetUpper()->Prt().*fnRect->fnGetHeight)() )
		{
            if ( !bFitPromise )
			{
                SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
                               (Prt().*fnRect->fnGetTop)();
                sal_Bool bSplit = !IsFwdMoveAllowed();
                if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) )
				{
					Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
					bValidSize = sal_False;
					bFitPromise = sal_True;
					continue;
				}
				/* -----------------19.02.99 12:58-------------------
				 * Frueher wurde in Rahmen und Bereichen niemals versucht,
				 * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
				 * Attribute (Widows,Keep) doch noch passend zu bekommen.
				 * Dies haette zumindest bei spaltigen Rahmen versucht
				 * werden muessen, spaetestens bei verketteten Rahmen und
				 * in Bereichen muss es versucht werden.
				 * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
				 * Attribute nicht ausser Acht gelassen werden.
				 * --------------------------------------------------*/
				else if ( !bFtn && bMoveable &&
					  ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
					  ( !bSct || !FindSctFrm()->IsColLocked() ) )
					bMoveOrFit = sal_True;
            }
#ifdef DBG_UTIL
			else
			{
				ASSERT( sal_False, "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
			}
#endif
		}

		//Mal sehen ob ich irgenwo Platz finde...
		//Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
		SwFrm *pPre = GetIndPrev();
		SwFrm *pOldUp = GetUpper();

/* MA 13. Oct. 98: Was soll das denn sein!?
 * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
 * 		bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
 * 		Seite wandern und dort einen Section-Follow erzeugen.
 */
		if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
			pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
			( pPre || pOldUp->GetUpper()->GetPrev() ) &&
			((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
			bMovedFwd = sal_False;

        const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
        const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();

		if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
			bMakePage = sal_False;
        SWREFRESHFN( this )

        // If MoveFwd moves the paragraph to the next page, a following
        // paragraph, which contains footnotes can can cause the old upper
        // frame to grow. In this case we explicitely allow a new check
        // for MoveBwd. Robust: We also check the bMovedBwd flag again.
        // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
        // Therefore we only check for growing body frames.
        if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
             (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
            bMovedFwd = sal_False;
        else
            bMovedFwd = sal_True;

        bFormatted = sal_False;
		if ( bMoveOrFit && GetUpper() == pOldUp )
		{
            // FME 2007-08-30 #i81146# new loop control
            if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
            {
    			Prepare( PREP_MUST_FIT, 0, sal_False );
	    		bValidSize = sal_False;
		    	bMustFit = sal_True;
			    continue;
            }

#if OSL_DEBUG_LEVEL > 1
            ASSERT( false, "LoopControl in SwCntntFrm::MakeAll" )
#endif
		}
		if ( bMovedBwd && GetUpper() )
		{	//Unuetz gewordene Invalidierungen zuruecknehmen.
			GetUpper()->ResetCompletePaint();
			if( pPre && !pPre->IsSctFrm() )
				::ValidateSz( pPre );
		}

	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )


    // NEW: Looping Louie (Light). Should not be applied in balanced sections.
    // Should only be applied if there is no better solution!
    LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
                            (

                                // --> FME 2005-01-26 #118572#
                                ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
                                // <--

                                // --> FME 2005-01-27 #i33887#
                                ( IsInSct() && bKeep )
                                // <--

                                // ... add your conditions here ...

                            ),
                         static_cast<SwTxtFrm&>(*this) );


    if ( pSaveFtn )
		delete pSaveFtn;

	UnlockJoin();
	if ( bMovedFwd || bMovedBwd )
		pNotify->SetInvaKeep();
    // OD 2004-02-26 #i25029#
    if ( bMovedFwd )
    {
        pNotify->SetInvalidatePrevPrtArea();
    }
	delete pNotify;
    SetFlyLock( sal_False );
}

/*************************************************************************
|*
|*	SwCntntFrm::_WouldFit()
|*
|*	Ersterstellung		MA 28. Feb. 95
|*	Letzte Aenderung	AMA 15. Feb. 99
|*
|*************************************************************************/




void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
{
	//fix(25455): Validieren, sonst kommt es zu einer Rekursion.
	//Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
	//fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
	//korrekt beachtet wird (27417)
	const sal_Bool bOldPos = pFrm->GetValidPosFlag();
	const sal_Bool bOldSz  = pFrm->GetValidSizeFlag();
	const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag();
	pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True;

	//fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
	//und kommt rekursiv wieder herein.
	if ( pNxt->IsCntntFrm() )
	{
		SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
		const SwBorderAttrs &rAttrs = *aAccess.Get();
		if ( !pNxt->GetValidSizeFlag() )
        {
            if( pNxt->IsVertical() )
                pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
            else
                pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
        }
		((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
		pNxt->Format( &rAttrs );
	}
	else
	{
		SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
		const SwBorderAttrs &rAttrs = *aAccess.Get();
		if ( !pNxt->GetValidSizeFlag() )
        {
            if( pNxt->IsVertical() )
                pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
            else
                pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
        }
		pNxt->Format( &rAttrs );
	}

	pFrm->bValidPos  	 = bOldPos;
	pFrm->bValidSize 	 = bOldSz;
	pFrm->bValidPrtArea  = bOldPrt;
}

// Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
// von pNxt keine anderen FtnBosse liegen

sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
{
	ASSERT( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" );
	pFrm = pFrm->FindFtnBossFrm();
	pNxt = pNxt->FindFtnBossFrm();
	// Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
	while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
		pFrm = pFrm->GetUpper()->FindFtnBossFrm();
	// Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
	while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
		pNxt = pNxt->GetUpper()->FindFtnBossFrm();
	// So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
	return ( pFrm && pNxt && pFrm->GetNext() == pNxt );
}

// --> OD 2007-11-26 #b6614158#
sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace,
                            SwLayoutFrm *pNewUpper,
                            sal_Bool bTstMove,
                            const bool bObjsInNewUpper )
// <--
{
	//Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
	//sie in jedem Fall gemoved werden, wenn zwischen dem
	//neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
	//Seite/Spalte liegt.
	SwFtnFrm* pFtnFrm = 0;
	if ( IsInFtn() )
	{
		if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
			return sal_True;
		pFtnFrm = FindFtnFrm();
	}

	sal_Bool bRet;
	sal_Bool bSplit = !pNewUpper->Lower();
	SwCntntFrm *pFrm = this;
    const SwFrm *pTmpPrev = pNewUpper->Lower();
    if( pTmpPrev && pTmpPrev->IsFtnFrm() )
        pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
    while ( pTmpPrev && pTmpPrev->GetNext() )
        pTmpPrev = pTmpPrev->GetNext();
	do
	{
        // --> FME 2005-03-31 #b6236853# #i46181#
        SwTwips nSecondCheck = 0;
        SwTwips nOldSpace = nSpace;
        sal_Bool bOldSplit = bSplit;
        // <--

		if ( bTstMove || IsInFly() || ( IsInSct() &&
			 ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
			   pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
		{
			//Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
			//lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
			//moveable, mit Ausnahme der in der letzten Spalte (siehe
			//SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
			//Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
			//der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
			//vorzugaukeln haenge ich ihn einfach solange um.
			// Auch bei spaltigen Bereichen muss umgehaengt werden, damit
			// SwSectionFrm::Growable() den richtigen Wert liefert.
			// Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
			// falls es dort keinen SwFtnFrm gibt.
			SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
							 (SwFrm*)pFrm->FindFtnFrm() : pFrm;
			SwLayoutFrm *pUp = pTmpFrm->GetUpper();
			SwFrm *pOldNext = pTmpFrm->GetNext();
			pTmpFrm->Remove();
			pTmpFrm->InsertBefore( pNewUpper, 0 );
            if ( pFrm->IsTxtFrm() &&
                 ( bTstMove ||
                   ((SwTxtFrm*)pFrm)->HasFollow() ||
                   ( !((SwTxtFrm*)pFrm)->HasPara() &&
                     !((SwTxtFrm*)pFrm)->IsEmpty()
                   )
                 )
               )
			{
				bTstMove = sal_True;
                bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
			}
			else
                bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );

            pTmpFrm->Remove();
			pTmpFrm->InsertBefore( pUp, pOldNext );
		}
		else
        {
            bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
            nSecondCheck = !bSplit ? 1 : 0;
        }

        SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
        const SwBorderAttrs &rAttrs = *aAccess.Get();

		//Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
		//Bei TestFormatierung ist dies bereits geschehen.
		if ( bRet && !bTstMove )
		{
			SwTwips nUpper;

            if ( pTmpPrev )
			{
                nUpper = CalcUpperSpace( NULL, pTmpPrev );

                // in balanced columned section frames we do not want the
                // common border
                sal_Bool bCommonBorder = sal_True;
                if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
                {
                    const SwSectionFrm* pSct = pFrm->FindSctFrm();
                    bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
                }

                // --> FME 2005-03-31 #b6236853# #i46181#
                nSecondCheck = ( 1 == nSecondCheck &&
                                 pFrm == this &&
                                 IsTxtFrm() &&
                                 bCommonBorder &&
                                 !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
                                 nUpper :
                                 0;
                // <--

                nUpper += bCommonBorder ?
                          rAttrs.GetBottomLine( *(pFrm) ) :
                          rAttrs.CalcBottomLine();

            }
			else
            {
                // --> FME 2005-03-31 #b6236853# #i46181#
                nSecondCheck = 0;
                // <--

                if( pFrm->IsVertical() )
                    nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
                else
                    nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
            }

			nSpace -= nUpper;

			if ( nSpace < 0 )
            {
				bRet = sal_False;

                // --> FME 2005-03-31 #b6236853# #i46181#
                if ( nSecondCheck > 0 )
                {
                    // The following code is indented to solve a (rare) problem
                    // causing some frames not to move backward:
                    // SwTxtFrm::WouldFit() claims that the whole paragraph
                    // fits into the given space and subtracts the height of
                    // all lines from nSpace. nSpace - nUpper is not a valid
                    // indicator if the frame should be allowed to move backward.
                    // We do a second check with the original remaining space
                    // reduced by the required upper space:
                    nOldSpace -= nSecondCheck;
                    const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False );
                    if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
                    {
                        bRet = sal_True;
                        bSplit = sal_True;
                    }
                }
                // <--
            }
		}

        // OD 2004-03-01 #106629# - also consider lower spacing in table cells
        if ( bRet && IsInTab() &&
             pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
        {
            nSpace -= rAttrs.GetULSpace().GetLower();
            if ( nSpace < 0 )
            {
                bRet = sal_False;
            }
        }

        if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
		{
			if( bTstMove )
            {
				while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
                {
					pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
                }
                // OD 11.04.2003 #108824# - If last follow frame of <this> text
                // frame isn't valid, a formatting of the next content frame
                // doesn't makes sense. Thus, return sal_True.
                if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
                {
                    ASSERT( false, "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
                    return sal_True;
                }
            }
			SwFrm *pNxt;
			if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
				( !pFtnFrm || ( pNxt->IsInFtn() &&
				  pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
			{
				// ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
                // --> OD 2007-11-26 #b6614158#
                // current solution for the test formatting doesn't work, if
                // objects are present in the remaining area of the new upper
                if ( bTstMove &&
                     ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
                {
                    return sal_True;
                }
                // <--

				if ( !pNxt->IsValid() )
					MakeNxt( pFrm, pNxt );

				//Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
				//er den Absatzabstand bereits berechnet. Er braucht dann nicht
				//teuer kalkuliert werden.
				if( lcl_NotHiddenPrev( pNxt ) )
                    pTmpPrev = 0;
				else
				{
					if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
                        pTmpPrev = lcl_NotHiddenPrev( pFrm );
					else
                        pTmpPrev = pFrm;
				}
				pFrm = (SwCntntFrm*)pNxt;
			}
			else
				pFrm = 0;
		}
		else
			pFrm = 0;

	} while ( bRet && pFrm );

	return bRet;
}
