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



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#include <tools/bigint.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/keepitem.hxx>
#include <editeng/shaditem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/boxitem.hxx>
#include <sfx2/printer.hxx>
#include <editeng/lspcitem.hxx>

#include <fmtornt.hxx>
#include <fmtanchr.hxx>
#include <fmthdft.hxx>
#include <fmtcntnt.hxx>
#include <fmtfsize.hxx>
#include <fmtsrnd.hxx>
#include <docary.hxx>
#include <lineinfo.hxx>
#include <swmodule.hxx>
#include "pagefrm.hxx"
#include "colfrm.hxx"
#include "doc.hxx"
#include "fesh.hxx"
#include "viewimp.hxx"
#include "viewopt.hxx"
#include "pam.hxx"
#include "dflyobj.hxx"
#include "dcontact.hxx"
#include "frmtool.hxx"
#include "docsh.hxx"
#include "tabfrm.hxx"
#include "rowfrm.hxx"
#include "ftnfrm.hxx"
#include "txtfrm.hxx"
#include "notxtfrm.hxx"
#include "flyfrms.hxx"
#include "layact.hxx"
#include "pagedesc.hxx"
#include "section.hxx"
#include "sectfrm.hxx"
#include "node2lay.hxx"
#include "ndole.hxx"
#include "ndtxt.hxx"
#include "swtable.hxx"
#include "hints.hxx"
#include <layhelp.hxx>
#include <laycache.hxx>
#include <rootfrm.hxx>
#include "mdiexp.hxx"
#include "statstr.hrc"
#include <paratr.hxx>
#include <sortedobjs.hxx>
#include <objectformatter.hxx>
#include <switerator.hxx>

// ftnfrm.cxx:
void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );

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


sal_Bool bObjsDirect = sal_True;
sal_Bool bDontCreateObjects = sal_False;
sal_Bool bSetCompletePaintOnInvalidate = sal_False;

sal_uInt8 StackHack::nCnt = 0;
sal_Bool StackHack::bLocked = sal_False;



/*************************************************************************/

SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
	pFrm( pF ),
	aFrm( pF->Frm() ),
	aPrt( pF->Prt() ),
    bInvaKeep( sal_False ),
    bValidSize( pF->GetValidSizeFlag() ),
    mbFrmDeleted( false )     // #i49383#
{
    if ( pF->IsTxtFrm() )
    {
        mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
        mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
    }
    else
    {
        mnFlyAnchorOfst = 0;
        mnFlyAnchorOfstNoWrap = 0;
    }

	bHadFollow = pF->IsCntntFrm() ?
					(((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
					sal_False;
}

/*************************************************************************/

SwFrmNotify::~SwFrmNotify()
{
    // #i49383#
    if ( mbFrmDeleted )
    {
        return;
    }

    SWRECTFN( pFrm )
    const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
    const sal_Bool bChgWidth =
            (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
    const sal_Bool bChgHeight =
            (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
    const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
       ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
         ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );

	if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
	{
		SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );

		if ( !pFlow->IsFollow() )
		{
			if ( !pFrm->GetIndPrev() )
			{
				if ( bInvaKeep )
				{
                    SwFrm *pPre = pFrm->FindPrev();
                    if ( pPre && pPre->IsFlowFrm() )
                    {
                        // 1. pPre wants to keep with me:
                        bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();

                        // 2. pPre is a table and the last row wants to keep with me:
                        if ( !bInvalidPrePos && pPre->IsTabFrm() )
                        {
                            SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
                            if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
                            {
                                SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
                                if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
                                    bInvalidPrePos = true;
                            }
                        }

                        if ( bInvalidPrePos )
                            pPre->InvalidatePos();
                    }
				}
			}
            else if ( !pFlow->HasFollow() )
            {
                long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
                long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
                if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
                    pFlow->CheckKeep();
            }
		}
	}

	if ( bAbsP )
	{
		pFrm->SetCompletePaint();

		SwFrm* pNxt = pFrm->GetIndNext();
        // #121888# - skip empty section frames
        while ( pNxt &&
                pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
        {
            pNxt = pNxt->GetIndNext();
        }

		if ( pNxt )
			pNxt->InvalidatePos();
		else
		{
            // #104100# - correct condition for setting retouche
            // flag for vertical layout.
            if( pFrm->IsRetoucheFrm() &&
                (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
            {
				pFrm->SetRetouche();
            }

            // A fresh follow frame does not have to be invalidated, because
            // it is already formatted:
            if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
            {
                if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
                    pFrm->InvalidateNextPos();
            }
        }
	}

	//Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
    const sal_Bool bPrtWidth =
            (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
    const sal_Bool bPrtHeight =
            (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
    if ( bPrtWidth || bPrtHeight )
	{
		const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
		if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
			pFrm->SetCompletePaint();
	}
    else
    {
        // #97597# - consider case that *only* margins between
        // frame and printing area has changed. Then, frame has to be repainted,
        // in order to force paint of the margin areas.
        if ( !bAbsP && (bChgWidth || bChgHeight) )
        {
            pFrm->SetCompletePaint();
        }
    }

	const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
    if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
         bPrtWidth || bPrtHeight || bChgFlyBasePos )
	{
		if( pFrm->IsAccessibleFrm() )
		{
			SwRootFrm *pRootFrm = pFrm->getRootFrm();
			if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
				pRootFrm->GetCurrShell() )
			{
				pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
			}
		}

        // Notification of anchored objects
        if ( pFrm->GetDrawObjs() )
        {
            const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
            SwPageFrm* pPageFrm = 0;
            for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
            {
                // OD 2004-03-31 #i26791# - no general distinction between
                // Writer fly frames and drawing objects
                bool bNotify = false;
                bool bNotifySize = false;
                SwAnchoredObject* pObj = rObjs[i];
                SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
                // --> OD 2004-12-08 #115759#
                const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
                if ( !bAnchoredAsChar )
                // <--
                {
                    // Notify object, which aren't anchored as-character:

                    // always notify objects, if frame position has changed
                    // or if the object is to-page|to-fly anchored.
                    if ( bAbsP ||
                         pContact->ObjAnchoredAtPage() ||
                         pContact->ObjAnchoredAtFly() )
                    {
                        bNotify = true;

                        // assure that to-fly anchored Writer fly frames are
                        // registered at the correct page frame, if frame
                        // position has changed.
                        if ( bAbsP && pContact->ObjAnchoredAtFly() &&
                             pObj->ISA(SwFlyFrm) )
                        {
                            // determine to-fly anchored Writer fly frame
                            SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
                            // determine page frame of to-fly anchored
                            // Writer fly frame
                            SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
                            // determine page frame, if needed.
                            if ( !pPageFrm )
                            {
                                pPageFrm = pFrm->FindPageFrm();
                            }
                            if ( pPageFrm != pFlyPageFrm )
                            {
                                ASSERT( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
                                if( pFlyPageFrm )
                                    pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
                                else
                                    pPageFrm->AppendFlyToPage( pFlyFrm );
                            }
                        }
                    }
                    // otherwise the objects are notified in dependence to
                    // its positioning and alignment
                    else
                    {
                        const SwFmtVertOrient& rVert =
                                        pContact->GetFmt()->GetVertOrient();
                        if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
                               rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
                               rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
                             ( bChgHeight || bPrtHeight ) )
                        {
                            bNotify = true;
                        }
                        if ( !bNotify )
                        {
                            const SwFmtHoriOrient& rHori =
                                        pContact->GetFmt()->GetHoriOrient();
                            if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
                                   rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
                                   rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
                                 ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
                            {
                                bNotify = true;
                            }
                        }
                    }
                }
                else if ( bPrtWidth )
                {
                    // Notify as-character anchored objects, if printing area
                    // width has changed.
                    bNotify = true;
                    bNotifySize = true;
                }

                // perform notification via the corresponding invalidations
                if ( bNotify )
                {
                    if ( pObj->ISA(SwFlyFrm) )
                    {
                        SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
                        if ( bNotifySize )
                            pFlyFrm->_InvalidateSize();
                        // --> OD 2004-12-08 #115759# - no invalidation of
                        // position for as-character anchored objects.
                        if ( !bAnchoredAsChar )
                        {
                            pFlyFrm->_InvalidatePos();
                        }
                        // <--
                        pFlyFrm->_Invalidate();
                    }
                    else if ( pObj->ISA(SwAnchoredDrawObject) )
                    {
                        // --> OD 2004-12-08 #115759# - no invalidation of
                        // position for as-character anchored objects.
                        if ( !bAnchoredAsChar )
                        {
                            pObj->InvalidateObjPos();
                        }
                        // <--
                    }
                    else
                    {
                        ASSERT( false,
                                "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
                    }
                }
            }
        }
	}
	else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
	{
		SwRootFrm *pRootFrm = pFrm->getRootFrm();
		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
			pRootFrm->GetCurrShell() )
		{
			pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
		}
	}

    // #i9046# Automatic frame width
    SwFlyFrm* pFly = 0;
    // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
    // necessarily have to have an upper!
    if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
    // <--
    {
        // --> OD 2006-05-08 #i61999#
        // no invalidation of columned Writer fly frames, because automatic
        // width doesn't make sense for such Writer fly frames.
        if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
        {
            const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();

            // This could be optimized. Basically the fly frame only has to
            // be invalidated, if the first line of pFrm (if pFrm is a content
            // frame, for other frame types its the print area) has changed its
            // size and pFrm was responsible for the current width of pFly. On
            // the other hand, this is only rarely used and re-calculation of
            // the fly frame does not cause too much trouble. So we keep it this
            // way:
            if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
            {
                // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
                // of as-character anchored fly frames not needed and can cause
                // layout loops
                if ( !pFly->ISA(SwFlyInCntFrm) )
                {
                    pFly->InvalidatePos();
                }
                // <--
                pFly->InvalidateSize();
            }
        }
        // <--
    }
}

/*************************************************************************/

SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
	SwFrmNotify( pLayFrm ),
    bLowersComplete( sal_False )
{
}

/*************************************************************************/

// OD 2004-05-11 #i28701# - local method to invalidate the position of all
// frames inclusive its floating screen objects, which are lowers of the given
// layout frame
void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
{
    if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
    {
        _rLayoutFrm.InvalidateObjs( true, false );
    }

    SwFrm* pLowerFrm = _rLayoutFrm.Lower();
    while ( pLowerFrm )
    {
        pLowerFrm->InvalidatePos();
        if ( pLowerFrm->IsTxtFrm() )
        {
            static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
        }
        else if ( pLowerFrm->IsTabFrm() )
        {
            pLowerFrm->InvalidatePrt();
        }

        pLowerFrm->InvalidateObjs( true, false );

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

SwLayNotify::~SwLayNotify()
{
    // --> OD 2005-07-29 #i49383#
    if ( mbFrmDeleted )
    {
        return;
    }
    // <--

	SwLayoutFrm *pLay = GetLay();
    SWRECTFN( pLay )
	sal_Bool bNotify = sal_False;
	if ( pLay->Prt().SSize() != aPrt.SSize() )
	{
		if ( !IsLowersComplete() )
		{
			sal_Bool bInvaPercent;

			if ( pLay->IsRowFrm() )
			{
				bInvaPercent = sal_True;
                long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
                if( nNew != (aPrt.*fnRect->fnGetHeight)() )
                     ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
                if( (pLay->Prt().*fnRect->fnGetWidth)()
                    != (aPrt.*fnRect->fnGetWidth)() )
					 ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
			}
			else
			{
				//Proportionale Anpassung der innenliegenden.
				//1. Wenn der Formatierte kein Fly ist
				//2. Wenn er keine Spalten enthaelt
				//3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
				//	 Hoehe danebenliegen.
				//4. niemals bei SectionFrms.
				sal_Bool bLow;
				if( pLay->IsFlyFrm() )
				{
					if ( pLay->Lower() )
					{
						bLow = !pLay->Lower()->IsColumnFrm() ||
                            (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
                             != (pLay->Prt().*fnRect->fnGetHeight)();
					}
					else
						bLow = sal_False;
				}
				else if( pLay->IsSctFrm() )
				{
					if ( pLay->Lower() )
					{
						if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
							bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
						else
							bLow = pLay->Prt().Width() != aPrt.Width();
					}
					else
						bLow = sal_False;
				}
                else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
                    bLow = pLay->Prt().Width() != aPrt.Width();
                else
					bLow = sal_True;
				bInvaPercent = bLow;
				if ( bLow )
				{
                    pLay->ChgLowersProp( aPrt.SSize() );
                }
				//Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
				//Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
				//mithin muss also der 'moeglicherweise passende' Invalidiert werden.
				//Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
				//Uppers um eine Moveable-Section handelt.
				//Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
				//geworden ist.
				if ( (pLay->Prt().Height() > aPrt.Height() ||
					  pLay->Prt().Width()  > aPrt.Width()) &&
					 (pLay->IsMoveable() || pLay->IsFlyFrm()) )
				{
                    SwFrm *pTmpFrm = pLay->Lower();
                    if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
					{
                        while ( pTmpFrm->GetNext() )
                            pTmpFrm = pTmpFrm->GetNext();
                        pTmpFrm->InvalidateNextPos();
					}
				}
			}
			bNotify = sal_True;
			//TEUER!! aber wie macht man es geschickter?
			if( bInvaPercent )
                pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
		}
		if ( pLay->IsTabFrm() )
			//Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird.
			((SwTabFrm*)pLay)->SetComplete();
        else
        {
            const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
            if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
				  !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
			//Damit die untergeordneten sauber retouchiert werden.
			//Problembsp: Flys an den Henkeln packen und verkleinern.
			//Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
			pLay->SetCompletePaint();
        }
	}
	//Lower benachrichtigen wenn sich die Position veraendert hat.
    const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
    const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
	const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize();

	if ( bPos && pLay->Lower() && !IsLowersComplete() )
		pLay->Lower()->InvalidatePos();

    if ( bPrtPos )
		pLay->SetCompletePaint();

	//Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
	if ( bSize )
	{
		if( pLay->GetNext() )
		{
			if ( pLay->GetNext()->IsLayoutFrm() )
				pLay->GetNext()->_InvalidatePos();
			else
				pLay->GetNext()->InvalidatePos();
		}
		else if( pLay->IsSctFrm() )
			pLay->InvalidateNextPos();
	}
	if ( !IsLowersComplete() &&
		 !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
			pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
		 (bPos || bNotify) && !(pLay->GetType() & 0x1823) )  //Tab, Row, FtnCont, Root, Page
	{
        // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
        // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
        // if <pLay> is a cell frame, and its table frame resp. its parent table
        // frame is locked.
        // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
        // only if position of layout frame has changed.
        bool bUnlockPosOfObjs( bPos );
        if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
        {
            SwTabFrm* pTabFrm( pLay->FindTabFrm() );
            if ( pTabFrm &&
                 ( pTabFrm->IsJoinLocked() ||
                   ( pTabFrm->IsFollow() &&
                     pTabFrm->FindMaster()->IsJoinLocked() ) ) )
            {
                bUnlockPosOfObjs = false;
            }
        }
        // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
        // of position of lower objects is allowed.
        else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
        {
            bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
        }
        // <--
        // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
        else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
        {
            bUnlockPosOfObjs = false;
        }
        // <--
        pLay->NotifyLowerObjs( bUnlockPosOfObjs );
        // <--
	}
	if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
	{
        // OD 2004-05-11 #i28701#
        ::lcl_InvalidatePosOfLowers( *pLay );
	}
    if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
          && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
        ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
}

/*************************************************************************/

SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
	SwLayNotify( pFlyFrm ),
    // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
    // the Writer fly frame is currently registered at.
    pOldPage( pFlyFrm->GetPageFrm() ),
    // <--
    aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
{
}

/*************************************************************************/

SwFlyNotify::~SwFlyNotify()
{
    // --> OD 2005-07-29 #i49383#
    if ( mbFrmDeleted )
    {
        return;
    }
    // <--

	SwFlyFrm *pFly = GetFly();
	if ( pFly->IsNotifyBack() )
	{
		ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
		SwViewImp *pImp = pSh ? pSh->Imp() : 0;
		if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
		{
			//Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
			//dass die alte Seite inzwischen vernichtet wurde!
            ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
            // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
            // if Writer fly frame has changed its page
            if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
                 pFly->GetPageFrm() != pOldPage )
            {
                pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
            }
            // <--
		}
		pFly->ResetNotifyBack();
	}

	//Haben sich Groesse oder Position geaendert, so sollte die View
	//das wissen.
    SWRECTFN( pFly )
    const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
    const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
    const bool bPrtChgd = aPrt != pFly->Prt();
    if ( bPosChgd || bFrmChgd || bPrtChgd )
	{
		pFly->NotifyDrawObj();
	}
	if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
	{
        // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
        // reason: New positioning and alignment (e.g. to-paragraph anchored,
        // but aligned at page) are introduced.
        // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
        // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.

		if ( pFly->IsFlyAtCntFrm() )
		{
            SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
			if ( pNxt )
            {
				pNxt->InvalidatePos();
            }
		}

        // --> OD 2004-11-05 #i26945# - notify anchor.
        // Needed for negative positioned Writer fly frames
        if ( pFly->GetAnchorFrm()->IsTxtFrm() )
        {
            pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
        }
        // <--
	}

    // OD 2004-05-13 #i28701#
    // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
    // further notifications/invalidations, if format is called by grow/shrink
    if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
         ( !pFly->ISA(SwFlyFreeFrm) ||
           !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
    // <--
    {
        // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
        // on changed frame height.
        // Note: It doesn't seem to be necessary and can cause layout loops.
        if ( bPosChgd )
        // <--
        {
            // indicate a restart of the layout process
            pFly->SetRestartLayoutProcess( true );
        }
        else
        {
            // lock position
            pFly->LockPosition();

            if ( !pFly->ConsiderForTextWrap() )
            {
                // indicate that object has to be considered for text wrap
                pFly->SetConsiderForTextWrap( true );
                // invalidate 'background' in order to allow its 'background'
                // to wrap around it.
                pFly->NotifyBackground( pFly->GetPageFrm(),
                                        pFly->GetObjRectWithSpaces(),
                                        PREP_FLY_ARRIVE );
                // invalidate position of anchor frame in order to force
                // a re-format of the anchor frame, which also causes a
                // re-format of the invalid previous frames of the anchor frame.
                pFly->AnchorFrm()->InvalidatePos();
            }
        }
    }
}

/*************************************************************************/

SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
    SwFrmNotify( pCntntFrm ),
    // OD 08.01.2004 #i11859#
    mbChkHeightOfLastLine( false ),
    mnHeightOfLastLine( 0L ),
    // OD 2004-02-26 #i25029#
    mbInvalidatePrevPrtArea( false ),
    mbBordersJoinedWithPrev( false )
{
    // OD 08.01.2004 #i11859#
    if ( pCntntFrm->IsTxtFrm() )
    {
        SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
        if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
        {
            const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
            const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
            if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
            {
                mbChkHeightOfLastLine = true;
                mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
            }
        }
    }
}

/*************************************************************************/

SwCntntNotify::~SwCntntNotify()
{
    // --> OD 2005-07-29 #i49383#
    if ( mbFrmDeleted )
    {
        return;
    }
    // <--

	SwCntntFrm *pCnt = GetCnt();
	if ( bSetCompletePaintOnInvalidate )
		pCnt->SetCompletePaint();

    SWRECTFN( pCnt )
    if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
							 pCnt->Frm().SSize() != aFrm.SSize()))
	{
		SwLayoutFrm* pCell = pCnt->GetUpper();
		while( !pCell->IsCellFrm() && pCell->GetUpper() )
			pCell = pCell->GetUpper();
		ASSERT( pCell->IsCellFrm(), "Where's my cell?" );
        if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
			pCell->InvalidatePrt();	//fuer vertikale Ausrichtung.
	}

    // OD 2004-02-26 #i25029#
    if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
         pCnt->IsTxtFrm() &&
         !pCnt->IsFollow() && !pCnt->GetIndPrev() )
    {
        // determine previous frame
        SwFrm* pPrevFrm = pCnt->FindPrev();
        // skip empty section frames and hidden text frames
        {
            while ( pPrevFrm &&
                    ( ( pPrevFrm->IsSctFrm() &&
                        !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
                      ( pPrevFrm->IsTxtFrm() &&
                        static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
            {
                pPrevFrm = pPrevFrm->FindPrev();
            }
        }

        // Invalidate printing area of found previous frame
        if ( pPrevFrm )
        {
            if ( pPrevFrm->IsSctFrm() )
            {
                if ( pCnt->IsInSct() )
                {
                    // Note: found previous frame is a section frame and
                    //       <pCnt> is also inside a section.
                    //       Thus due to <mbBordersJoinedWithPrev>,
                    //       <pCnt> had joined its borders/shadow with the
                    //       last content of the found section.
                    // Invalidate printing area of last content in found section.
                    SwFrm* pLstCntntOfSctFrm =
                            static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
                    if ( pLstCntntOfSctFrm )
                    {
                        pLstCntntOfSctFrm->InvalidatePrt();
                    }
                }
            }
            else
            {
                pPrevFrm->InvalidatePrt();
            }
        }
    }

    const bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;

	if ( pCnt->IsNoTxtFrm() )
	{
		//Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
		//mitbekommen, damit sie Ihr Window entsprechend verschieben.
		ViewShell *pSh  = pCnt->getRootFrm()->GetCurrShell();
		if ( pSh )
		{
            SwOLENode *pNd;
			if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
				 (pNd->GetOLEObj().IsOleRef() ||
				  pNd->IsOLESizeInvalid()) )
			{
                // --> OD #i117189#
                const bool bNoTxtFrmPrtAreaChanged = 
                        ( aPrt.SSize().Width() != 0 && 
                          aPrt.SSize().Height() != 0 ) &&
                        aPrt.SSize() != pCnt->Prt().SSize();
                // <--
				ASSERT( pCnt->IsInFly(), "OLE not in FlyFrm" );
				SwFlyFrm *pFly = pCnt->FindFlyFrm();
                svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
				SwFEShell *pFESh = 0;
				ViewShell *pTmp = pSh;
				do
				{	if ( pTmp->ISA( SwCrsrShell ) )
					{
						pFESh = (SwFEShell*)pTmp;
                        // #108369#: Here used to be the condition if (!bFirst).
                        // I think this should mean "do not call CalcAndSetScale"
                        // if the frame is formatted for the first time.
                        // Unfortunately this is not valid anymore since the
                        // SwNoTxtFrm already gets a width during CalcLowerPreps.
                        // Nevertheless, the indention of !bFirst seemed to be
                        // to assure that the OLE objects have already been notified
                        // if necessary before calling CalcAndSetScale.
                        // So I replaced !bFirst by !IsOLESizeInvalid. There is
                        // one additional problem specific to the word import:
                        // The layout is calculated _before_ calling PrtOLENotify,
                        // and the OLE objects are not invalidated during import.
                        // Therefore I added the condition !IsUpdateExpFld,
                        // have a look at the occurence of CalcLayout in
                        // uiview/view.cxx.
                        if ( !pNd->IsOLESizeInvalid() &&
                             !pSh->GetDoc()->IsUpdateExpFld() )
                            pFESh->CalcAndSetScale( xObj, 
                                                    &pFly->Prt(), &pFly->Frm(),
                                                    bNoTxtFrmPrtAreaChanged );
					}
					pTmp = (ViewShell*)pTmp->GetNext();
				} while ( pTmp != pSh );

				if ( pFESh && pNd->IsOLESizeInvalid() )
				{
					pNd->SetOLESizeInvalid( sal_False );
                    //TODO/LATER: needs OnDocumentPrinterChanged
                    //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
					pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
				}
            }
			//dito Animierte Grafiken
			if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
			{
				((SwNoTxtFrm*)pCnt)->StopAnimation();
				pSh->InvalidateWindows( Frm() );
			}
		}
	}

	if ( bFirst )
	{
		pCnt->SetRetouche();	//fix(13870)

		SwDoc *pDoc = pCnt->GetNode()->GetDoc();
		if ( pDoc->GetSpzFrmFmts()->Count() &&
			 pDoc->DoesContainAtPageObjWithContentAnchor() && !pDoc->IsNewDoc() )
		{
            // If certain import filters for foreign file format import 
            // AT_PAGE anchored objects, the corresponding page number is 
            // typically not known. In this case the content position is
            // stored at which the anchored object is found in the 
            // imported document.
            // When this content is formatted it is the time at which 
            // the page is known. Thus, this data can be corrected now.

            const SwPageFrm* pPage = 0;
            SwNodeIndex *pIdx  = 0;
            SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
            for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
            {
                SwFrmFmt *pFmt = (*pTbl)[i];
                const SwFmtAnchor &rAnch = pFmt->GetAnchor();
                if ( FLY_AT_PAGE != rAnch.GetAnchorId() ||
                     rAnch.GetCntntAnchor() == 0 )
                {
                    continue;
                }

                if ( !pIdx )
                {
                    pIdx = new SwNodeIndex( *pCnt->GetNode() );
                }
                if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
                {
                    ASSERT( false, "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
                    if ( !pPage )
                    {
                        pPage = pCnt->FindPageFrm();
                    }
                    SwFmtAnchor aAnch( rAnch );
                    aAnch.SetAnchor( 0 );
                    aAnch.SetPageNum( pPage->GetPhyPageNum() );
                    pFmt->SetFmtAttr( aAnch );
                    if ( RES_DRAWFRMFMT != pFmt->Which() )
                    {
                        pFmt->MakeFrms();
                    }
                }
            }
            delete pIdx;
        }
    }

    // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
    //  if height of last line has changed.
    if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
    {
        if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
        {
            pCnt->InvalidateNextPrtArea();
        }
    }

    // --> OD 2005-03-07 #i44049#
    if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
    {
        pCnt->InvalidateObjs( true );
    }
    // <--

    // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
    // anchored objects due to a change of its anchor character from
    // method <SwTxtFrm::Format(..)>.
    if ( pCnt->IsTxtFrm() )
    {
        SwTxtFrm* pMasterFrm = pCnt->IsFollow()
                               ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
                               : static_cast<SwTxtFrm*>(pCnt);
        if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
             pMasterFrm->GetDrawObjs() )
        {
            SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
            for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
            {
                SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
                if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
                        == FLY_AT_CHAR )
                {
                    pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
                }
            }
        }
    }
    // <--
}

/*************************************************************************/

void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
						SwFrm *pFrm, SwPageFrm *pPage )
{
	for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
	{
		SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
		const SwFmtAnchor &rAnch = pFmt->GetAnchor();
		if ( rAnch.GetCntntAnchor() &&
			 (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
		{
            const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
            //Wird ein Rahmen oder ein SdrObject beschrieben?
            const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
            // OD 23.06.2003 #108784# - append also drawing objects anchored
            // as character.
            const bool bDrawObjInCntnt = bSdrObj &&
                                         (rAnch.GetAnchorId() == FLY_AS_CHAR);

            if( bFlyAtFly ||
                (rAnch.GetAnchorId() == FLY_AT_PARA) ||
                (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
                bDrawObjInCntnt )
			{
                SdrObject* pSdrObj = 0;
                if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
				{
					ASSERT( !bSdrObj, "DrawObject not found." );
					pFmt->GetDoc()->DelFrmFmt( pFmt );
					--i;
					continue;
				}
				if ( pSdrObj )
				{
					if ( !pSdrObj->GetPage() )
                    {
                        pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
								InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
                    }

                    SwDrawContact* pNew =
                        static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
                    if ( !pNew->GetAnchorFrm() )
                    {
                        pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
                    }
                    // OD 19.06.2003 #108784# - add 'virtual' drawing object,
                    // if necessary. But control objects have to be excluded.
                    else if ( !::CheckControlLayer( pSdrObj ) &&
                              pNew->GetAnchorFrm() != pFrm &&
                              !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
                    {
                        SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
                        pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );

						// for repaint, use new ActionChanged()
                        // pDrawVirtObj->SendRepaintBroadcast();
                        pDrawVirtObj->ActionChanged();
                    }

				}
				else
				{
					SwFlyFrm *pFly;
					if( bFlyAtFly )
						pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
					else
						pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
					pFly->Lock();
					pFrm->AppendFly( pFly );
					pFly->Unlock();
					if ( pPage )
						::RegistFlys( pPage, pFly );
				}
			}
		}
	}
}

bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
{
	SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
	if ( RES_FLYFRMFMT == pFmt->Which() )
    {
        const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
        const SwFlyFrm* pTmpFrm;
		for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
        {
            if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
                return true;
        }
    }
	else
	{
		SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
		if ( pContact )
            return pContact->GetAnchorFrm() != 0;
	}
	return false;
}

/** helper method to determine, if a <SwFrmFmt>, which has an object connected,
    is located in header or footer.

    OD 23.06.2003 #108784#

    @author OD
*/
bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
{
    bool bRetVal = false;

    const SwFmtAnchor& rAnch = _rFmt.GetAnchor();

    if (rAnch.GetAnchorId() != FLY_AT_PAGE)
    {
        bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
    }

    return bRetVal;
}

void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib )
{
	//Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
	//Layout.
	//Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate
	//uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch
	//Objecte die in zeichengebundenen verankert sind.

	SwSpzFrmFmts aCpy( 255, 255 );
	aCpy.Insert( pTbl, 0 );

	sal_uInt16 nOldCnt = USHRT_MAX;

	while ( aCpy.Count() && aCpy.Count() != nOldCnt )
	{
		nOldCnt = aCpy.Count();
		for ( int i = 0; i < int(aCpy.Count()); ++i )
		{
			SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
			const SwFmtAnchor &rAnch = pFmt->GetAnchor();
			sal_Bool bRemove = sal_False;
            if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
                (rAnch.GetAnchorId() == FLY_AS_CHAR))
            {
				//Seitengebunde sind bereits verankert, zeichengebundene
				//will ich hier nicht.
				bRemove = sal_True;
            }
            else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
                      ::lcl_InHeaderOrFooter( *pFmt ) )
			{
            // OD 23.06.2003 #108784# - correction: for objects in header
            // or footer create frames, in spite of the fact that an connected
            // objects already exists.
				//Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
				//keine abhaengigen Existieren, andernfalls, oder wenn das
				//MakeFrms keine abhaengigen erzeugt, entfernen.
				pFmt->MakeFrms();
				bRemove = ::lcl_ObjConnected( pFmt, pSib );
			}
			if ( bRemove )
			{
				aCpy.Remove( sal_uInt16(i) );
				--i;
			}
		}
	}
	aCpy.Remove( 0, aCpy.Count() );
}

/** local method to set 'working' position for newly inserted frames

    OD 12.08.2003 #i17969#

    @author OD
*/
void lcl_SetPos( SwFrm&             _rNewFrm,
                 const SwLayoutFrm& _rLayFrm )
{
    SWRECTFN( (&_rLayFrm) )
    (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
    // move position by one SwTwip in text flow direction in order to get
    // notifications for a new calculated position after its formatting.
    if ( bVert )
        _rNewFrm.Frm().Pos().X() -= 1;
    else
        _rNewFrm.Frm().Pos().Y() += 1;
}

void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
							 sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
							 SwFrm *pPrv )
{
	pDoc->BlockIdling();
	SwRootFrm* pLayout = pLay->getRootFrm();
    const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
	if( bOldCallbackActionEnabled )
        pLayout->SetCallbackActionEnabled( sal_False );

	//Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann
	//werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
	//und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
	//angelegt.
	//Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
	//Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
	//lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
	//ertraegliches mass reduziert hat.
	//Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
	//Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach
	//Node noch etwas drauf.
	//Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist
	//(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
	//ausgegengen.
	const sal_Bool bStartPercent = bPages && !nEndIndex;

	SwPageFrm *pPage = pLay->FindPageFrm();
	const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
	SwFrm		*pFrm = 0;
	sal_Bool   bBreakAfter	 = sal_False;

    SwActualSection *pActualSection = 0;
    SwLayHelper *pPageMaker;

    //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress
	//an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
	//passiert erst am Ende der Funktion.
    if ( bPages )
    {
        // Attention: the SwLayHelper class uses references to the content-,
        // page-, layout-frame etc. and may change them!
        pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
                pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
        if( bStartPercent )
        {
            const sal_uLong nPageCount = pPageMaker->CalcPageCount();
            if( nPageCount )
                bObjsDirect = sal_False;
        }
	}
    else
        pPageMaker = NULL;

    if( pLay->IsInSct() &&
		( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
			// abgefangen, deren Flags noch nicht ermittelt werden koennen,
			// so z.B. beim Einfuegen einer Tabelle
	{
		SwSectionFrm* pSct = pLay->FindSctFrm();
		// Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
		// Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
		// Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
		// Kandidat fuer pActualSection.
		// Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
		// eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
		// aufgebrochen werden.
		if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
			( !pLay->IsInTab() || pSct->IsInTab() ) )
		{
			pActualSection = new SwActualSection( 0, pSct, 0 );
			ASSERT( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
				"_InsertCnt: Wrong Call" );
		}
	}

    //If a section is "open", the pActualSection points to an SwActualSection.
    //If the page breaks, for "open" sections a follow will created.
    //For nested sections (which have, however, not a nested layout),
    //the SwActualSection class has a member, which points to an upper(section).
    //When the "inner" section finishs, the upper will used instead.

	while( sal_True )
	{
		SwNode *pNd = pDoc->GetNodes()[nIndex];
		if ( pNd->IsCntntNode() )
		{
			SwCntntNode* pNode = (SwCntntNode*)pNd;
			pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) :
										pNode->MakeFrm( pLay );
            if( pPageMaker )
                pPageMaker->CheckInsert( nIndex );

            pFrm->InsertBehind( pLay, pPrv );
            // --> OD 2005-12-01 #i27138#
            // notify accessibility paragraphs objects about changed
            // CONTENT_FLOWS_FROM/_TO relation.
            // Relation CONTENT_FLOWS_FROM for next paragraph will change
            // and relation CONTENT_FLOWS_TO for previous paragraph will change.
            if ( pFrm->IsTxtFrm() )
            {
                ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
                // no notification, if <ViewShell> is in construction
                if ( pViewShell && !pViewShell->IsInConstructor() &&
                     pViewShell->GetLayout() &&
                     pViewShell->GetLayout()->IsAnyShellAccessible() )
                {
                    pViewShell->InvalidateAccessibleParaFlowRelation(
                        dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
                        dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
                    // --> OD 2006-08-28 #i68958#
                    // The information flags of the text frame are validated
                    // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
                    // The information flags have to be invalidated, because
                    // it is possible, that the one of its upper frames
                    // isn't inserted into the layout.
                    pFrm->InvalidateInfFlags();
                    // <--
                }
            }
            // <--
            // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
            // for setting position at newly inserted frame
            lcl_SetPos( *pFrm, *pLay );
			pPrv = pFrm;

			if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
				AppendObjs( pTbl, nIndex, pFrm, pPage );
		}
		else if ( pNd->IsTableNode() )
		{	//Sollten wir auf eine Tabelle gestossen sein?
			SwTableNode *pTblNode = (SwTableNode*)pNd;

            // #108116# loading may produce table structures that GCLines
            // needs to clean up. To keep table formulas correct, change
            // all table formulas to internal (BOXPTR) representation.
            SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
            aMsgHnt.eFlags = TBL_BOXPTR;
            pDoc->UpdateTblFlds( &aMsgHnt );
            pTblNode->GetTable().GCLines();

			pFrm = pTblNode->MakeFrm( pLay );

            if( pPageMaker )
                pPageMaker->CheckInsert( nIndex );

			pFrm->InsertBehind( pLay, pPrv );
            // --> OD 2005-12-01 #i27138#
            // notify accessibility paragraphs objects about changed
            // CONTENT_FLOWS_FROM/_TO relation.
            // Relation CONTENT_FLOWS_FROM for next paragraph will change
            // and relation CONTENT_FLOWS_TO for previous paragraph will change.
            {
                ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
                // no notification, if <ViewShell> is in construction
                if ( pViewShell && !pViewShell->IsInConstructor() &&
                     pViewShell->GetLayout() &&
                     pViewShell->GetLayout()->IsAnyShellAccessible() )
                {
                    pViewShell->InvalidateAccessibleParaFlowRelation(
                            dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
                            dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
                }
            }
            // <--
            if ( bObjsDirect && pTbl->Count() )
				((SwTabFrm*)pFrm)->RegistFlys();
            // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
            // for setting position at newly inserted frame
            lcl_SetPos( *pFrm, *pLay );

            pPrv = pFrm;
			//Index auf den Endnode der Tabellensection setzen.
			nIndex = pTblNode->EndOfSectionIndex();

            SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
            while ( pTmpFrm )
            {
                pTmpFrm->CheckDirChange();
                pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
            }

		}
		else if ( pNd->IsSectionNode() )
		{
			SwSectionNode *pNode = (SwSectionNode*)pNd;
			if( pNode->GetSection().CalcHiddenFlag() )
				// ist versteckt, ueberspringe den Bereich
				nIndex = pNode->EndOfSectionIndex();
			else
			{
                pFrm = pNode->MakeFrm( pLay );
				pActualSection = new SwActualSection( pActualSection,
												(SwSectionFrm*)pFrm, pNode );
				if ( pActualSection->GetUpper() )
				{
					//Hinter den Upper einsetzen, beim EndNode wird der "Follow"
					//des Uppers erzeugt.
					SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
					pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
                    // OD 25.03.2003 #108339# - direct initialization of section
                    // after insertion in the layout
                    static_cast<SwSectionFrm*>(pFrm)->Init();
				}
				else
				{
					pFrm->InsertBehind( pLay, pPrv );
                    // OD 25.03.2003 #108339# - direct initialization of section
                    // after insertion in the layout
                    static_cast<SwSectionFrm*>(pFrm)->Init();

                    // --> FME 2004-09-08 #i33963#
                    // Do not trust the IsInFtn flag. If we are currently
                    // building up a table, the upper of pPrv may be a cell
                    // frame, but the cell frame does not have an upper yet.
                    if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
                    // <--
                    {
						if( pPrv->IsSctFrm() )
							pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
						if( pPrv && pPrv->IsTxtFrm() )
							((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False );
					}
				}
                // --> OD 2005-12-01 #i27138#
                // notify accessibility paragraphs objects about changed
                // CONTENT_FLOWS_FROM/_TO relation.
                // Relation CONTENT_FLOWS_FROM for next paragraph will change
                // and relation CONTENT_FLOWS_TO for previous paragraph will change.
                {
                    ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
                    // no notification, if <ViewShell> is in construction
                    if ( pViewShell && !pViewShell->IsInConstructor() &&
                         pViewShell->GetLayout() &&
                         pViewShell->GetLayout()->IsAnyShellAccessible() )
                    {
                        pViewShell->InvalidateAccessibleParaFlowRelation(
                            dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
                            dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
                    }
                }
                // <--
                pFrm->CheckDirChange();

                // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
                // for setting position at newly inserted frame
                lcl_SetPos( *pFrm, *pLay );

                // OD 20.11.2002 #105405# - no page, no invalidate.
                if ( pPage )
                {
                    // OD 18.09.2002 #100522#
                    // invalidate page in order to force format and paint of
                    // inserted section frame
                    pFrm->InvalidatePage( pPage );

                    // FME 10.11.2003 #112243#
                    // Invalidate fly content flag:
                    if ( pFrm->IsInFly() )
                        pPage->InvalidateFlyCntnt();

                    // OD 14.11.2002 #104684# - invalidate page content in order to
                    // force format and paint of section content.
                    pPage->InvalidateCntnt();
                }

				pLay = (SwLayoutFrm*)pFrm;
				if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
					pLay = pLay->GetNextLayoutLeaf();
				pPrv = 0;
			}
		}
        else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
		{
			ASSERT( pActualSection, "Sectionende ohne Anfang?" );
            ASSERT( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
							"Sectionende mit falschen Start Node?" );

			//Section schliessen, ggf. die umgebende Section wieder
			//aktivieren.
			SwActualSection *pTmp = pActualSection->GetUpper();
			delete pActualSection;
			pLay = pLay->FindSctFrm();
			if ( 0 != (pActualSection = pTmp) )
			{
				//Koennte noch sein, das der letzte SectionFrm leer geblieben
				//ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
				if ( !pLay->ContainsCntnt() )
				{
                    SwFrm *pTmpFrm = pLay;
                    pLay = pTmpFrm->GetUpper();
                    pPrv = pTmpFrm->GetPrev();
                    pTmpFrm->Remove();
                    delete pTmpFrm;
				}
				else
				{
					pPrv = pLay;
					pLay = pLay->GetUpper();
				}

                // new section frame
                pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
                pFrm->InsertBehind( pLay, pPrv );
                static_cast<SwSectionFrm*>(pFrm)->Init();

                // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
                // for setting position at newly inserted frame
                lcl_SetPos( *pFrm, *pLay );

                SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();

                // a follow has to be appended to the new section frame
                SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
                if ( pFollow )
                {
                    pOuterSectionFrm->SetFollow( NULL );
                    pOuterSectionFrm->InvalidateSize();
                    ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
                }

				// Wir wollen keine leeren Teile zuruecklassen
                if( ! pOuterSectionFrm->IsColLocked() &&
                    ! pOuterSectionFrm->ContainsCntnt() )
				{
                    pOuterSectionFrm->DelEmpty( sal_True );
                    delete pOuterSectionFrm;
				}
				pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );

				pLay = (SwLayoutFrm*)pFrm;
				if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
					pLay = pLay->GetNextLayoutLeaf();
				pPrv = 0;
			}
			else
			{
				//Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
				//weiter.
				pPrv = pLay;
				pLay = pLay->GetUpper();
			}
		}
		else if( pNd->IsStartNode() &&
				 SwFlyStartNode	== ((SwStartNode*)pNd)->GetStartNodeType() )
		{
			if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
			{
				SwFlyFrm* pFly = pLay->FindFlyFrm();
				if( pFly )
					AppendObjs( pTbl, nIndex, pFly, pPage );
			}
		}
		else
			// Weder Cntnt noch Tabelle noch Section,
			// also muessen wir fertig sein.
			break;

		++nIndex;
		// Der Endnode wird nicht mehr mitgenommen, es muss vom
		// Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
		// des Bereichs vor dem EndIndex liegt!
		if ( nEndIndex && nIndex >= nEndIndex )
			break;
	}

	if ( pActualSection )
	{
		//Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
		if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
		{
			pLay->Remove();
			delete pLay;
		}
		delete pActualSection;
	}

	if ( bPages )		//Jetzt noch die Flys verbinden lassen.
	{
		if ( !bDontCreateObjects )
			AppendAllObjs( pTbl, pLayout );
		bObjsDirect = sal_True;
	}

    if( pPageMaker )
    {
        pPageMaker->CheckFlyCache( pPage );
        delete pPageMaker;
        if( pDoc->GetLayoutCache() )
        {
#ifdef DBG_UTIL
#if OSL_DEBUG_LEVEL > 1
            pDoc->GetLayoutCache()->CompareLayout( *pDoc );
#endif
#endif
            pDoc->GetLayoutCache()->ClearImpl();
        }
    }

    pDoc->UnblockIdling();
	if( bOldCallbackActionEnabled )
        pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
}


void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
			   const SwNodeIndex &rEndIdx )
{
    bObjsDirect = sal_False;

	SwNodeIndex aTmp( rSttIdx );
	sal_uLong nEndIdx = rEndIdx.GetIndex();
    SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
											pDoc->GetNodes()[ nEndIdx-1 ]);
	if ( pNd )
	{
		sal_Bool bApres = aTmp < rSttIdx;
		SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
		SwFrm* pFrm;
		while( 0 != (pFrm = aNode2Layout.NextFrm()) )
		{
			SwLayoutFrm *pUpper = pFrm->GetUpper();
			SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
			sal_Bool bOldLock, bOldFtn;
			if( pFtnFrm )
			{
				bOldFtn = pFtnFrm->IsColLocked();
				pFtnFrm->ColLock();
			}
			else
				bOldFtn = sal_True;
			SwSectionFrm* pSct = pUpper->FindSctFrm();
			// Es sind innerhalb von Fussnoten nur die Bereiche interessant,
			// die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
			// in denen die Fussnoten(Container) liegen.
            // #109767# Table frame is in section, insert section in cell frame.
			if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
				pSct = NULL;
			if( pSct )
			{   // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
				bOldLock = pSct->IsColLocked();
				pSct->ColLock();
			}
			else
				bOldLock = sal_True;

            // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
			// auf die naechste Seite schieben. Innerhalb eines Rahmens auch
			// nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
			// Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
            sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
            sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
                 (!pFrm->IsInTab() || pFrm->IsTabFrm() );
            if ( bMoveNext && bAllowMove )
			{
				SwFrm *pMove = pFrm;
				SwFrm *pPrev = pFrm->GetPrev();
				SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
				ASSERT( pTmp, "Missing FlowFrm" );

				if ( bApres )
				{
					// Wir wollen, dass der Rest der Seite leer ist, d.h.
					// der naechste muss auf die naechste Seite wandern.
					// Dieser kann auch in der naechsten Spalte stehen!
					ASSERT( !pTmp->HasFollow(), "Follows forbidden" );
					pPrev = pFrm;
					// Wenn unser umgebender SectionFrm einen Next besitzt,
					// so soll dieser ebenfalls gemoved werden!
					pMove = pFrm->GetIndNext();
					SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
					if( pCol )
						pCol = (SwColumnFrm*)pCol->GetNext();
					do
					{
						if( pCol && !pMove )
						{   // Bisher haben wir keinen Nachfolger gefunden
							// jetzt gucken wir in die naechste Spalte
							pMove = pCol->ContainsAny();
							if( pCol->GetNext() )
								pCol = (SwColumnFrm*)pCol->GetNext();
							else if( pCol->IsInSct() )
							{   // Wenn es keine naechste Spalte gibt, wir aber
								// innerhalb eines spaltigen Bereichs sind,
								// koennte es noch ausserhalb des Bereich
								// (Seiten-)Spalten geben
								pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
								if( pCol )
									pCol = (SwColumnFrm*)pCol->GetNext();
							}
							else
								pCol = NULL;
						}
						// Falls hier verschrottete SectionFrms herumgammeln,
						// muessen diese uebersprungen werden.
						while( pMove && pMove->IsSctFrm() &&
							   !((SwSectionFrm*)pMove)->GetSection() )
							pMove = pMove->GetNext();
					} while( !pMove && pCol );

					if( pMove )
					{
						if ( pMove->IsCntntFrm() )
							pTmp = (SwCntntFrm*)pMove;
						else if ( pMove->IsTabFrm() )
							pTmp = (SwTabFrm*)pMove;
						else if ( pMove->IsSctFrm() )
						{
							pMove = ((SwSectionFrm*)pMove)->ContainsAny();
							if( pMove )
								pTmp = SwFlowFrm::CastFlowFrm( pMove );
							else
								pTmp = NULL;
						}
					}
					else
						pTmp = 0;
				}
				else
				{
					ASSERT( !pTmp->IsFollow(), "Follows really forbidden" );
					// Bei Bereichen muss natuerlich der Inhalt auf die Reise
					// geschickt werden.
					if( pMove->IsSctFrm() )
					{
						while( pMove && pMove->IsSctFrm() &&
							   !((SwSectionFrm*)pMove)->GetSection() )
							pMove = pMove->GetNext();
						if( pMove && pMove->IsSctFrm() )
							pMove = ((SwSectionFrm*)pMove)->ContainsAny();
						if( pMove )
							pTmp = SwFlowFrm::CastFlowFrm( pMove );
						else
							pTmp = NULL;
					}
				}

				if( pTmp )
				{
					SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
					// MoveFwd==sal_True bedeutet, dass wir auf der gleichen
					// Seite geblieben sind, wir wollen aber die Seite wechseln,
					// sofern dies moeglich ist
                    sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
					pTmp->LockJoin();
					while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
					{
						if( pOldUp == pTmp->GetFrm()->GetUpper() )
							break;
						pOldUp = pTmp->GetFrm()->GetUpper();
					}
                    if( !bTmpOldLock )
						pTmp->UnlockJoin();
				}
				::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
							  pFrm->IsInDocBody(), nEndIdx, pPrev );
			}
			else
			{
				sal_Bool bSplit;
				SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
				// Wenn in einen SectionFrm ein anderer eingefuegt wird,
				// muss dieser aufgebrochen werden
				if( pSct && rSttIdx.GetNode().IsSectionNode() )
				{
					bSplit = pSct->SplitSect( pFrm, bApres );
					// Wenn pSct nicht aufgespalten werden konnte
					if( !bSplit && !bApres )
					{
						pUpper = pSct->GetUpper();
						pPrv = pSct->GetPrev();
					}
				}
				else
					bSplit = sal_False;
                ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
                              nEndIdx, pPrv );
                // OD 23.06.2003 #108784# - correction: append objects doesn't
                // depend on value of <bAllowMove>
                if( !bDontCreateObjects )
                {
                    const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
                    if( pTbl->Count() )
                        AppendAllObjs( pTbl, pUpper );
                }

				// Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
				// muss das Splitten rueckgaengig gemacht werden
				if( bSplit && pSct && pSct->GetNext()
					&& pSct->GetNext()->IsSctFrm() )
					pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
				if( pFrm->IsInFly() )
					pFrm->FindFlyFrm()->_Invalidate();
				if( pFrm->IsInTab() )
					pFrm->InvalidateSize();
			}

			SwPageFrm *pPage = pUpper->FindPageFrm();
			SwFrm::CheckPageDescs( pPage, sal_False );
			if( !bOldFtn )
				pFtnFrm->ColUnlock();
			if( !bOldLock )
			{
				pSct->ColUnlock();
				// Zum Beispiel beim Einfuegen von gelinkten Bereichen,
				// die wiederum Bereiche enthalten, kann pSct jetzt leer sein
				// und damit ruhig zerstoert werden.
				if( !pSct->ContainsCntnt() )
				{
					pSct->DelEmpty( sal_True );
					pUpper->getRootFrm()->RemoveFromList( pSct );
					delete pSct;
				}
			}
		}
	}

    bObjsDirect = sal_True;
}


/*************************************************************************/

SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
	SwCacheObj( pMod ),
	rAttrSet( pConstructor->IsCntntFrm()
					? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
					: ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
	rUL 	( rAttrSet.GetULSpace() ),
    // --> OD 2008-12-04 #i96772#
    // LRSpaceItem is copied due to the possibility that it is adjusted - see below
    rLR     ( rAttrSet.GetLRSpace() ),
    // <--
	rBox	( rAttrSet.GetBox() 	),
	rShadow ( rAttrSet.GetShadow()	),
	aFrmSize( rAttrSet.GetFrmSize().GetSize() )
{
    // --> OD 2008-12-02 #i96772#
    const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
    if ( pTxtFrm )
    {
        pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
    }

	//Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
	//nicht initialisiert!

	//Muessen alle einmal berechnet werden:
	bTopLine = bBottomLine = bLeftLine = bRightLine =
    bTop     = bBottom     = bLine   = sal_True;

	bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
    // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
    // and <bJoinedWithNext>, which aren't initialized by default.
    bCachedJoinedWithPrev = sal_False;
    bCachedJoinedWithNext = sal_False;

	bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
}

SwBorderAttrs::~SwBorderAttrs()
{
	((SwModify*)pOwner)->SetInCache( sal_False );
}

/*************************************************************************
|*
|*	SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
|*
|*	Beschreibung		Die Calc-Methoden errechnen zusaetzlich zu den
|*		von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
|*		der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
|*		Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
|*		groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
|*
|*************************************************************************/

void SwBorderAttrs::_CalcTop()
{
	nTop = CalcTopLine() + rUL.GetUpper();
	bTop = sal_False;
}

void SwBorderAttrs::_CalcBottom()
{
	nBottom = CalcBottomLine() + rUL.GetLower();
	bBottom = sal_False;
}

long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
{
    long nRight;

    // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
    // and right border are painted on the right respectively left.
    if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
        nRight = CalcLeftLine();
    else
        nRight = CalcRightLine();

    // for paragraphs, "left" is "before text" and "right" is "after text"
    if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
        nRight += rLR.GetLeft();
    else
        nRight += rLR.GetRight();

    // --> OD 2008-01-21 #newlistlevelattrs#
    // correction: retrieve left margin for numbering in R2L-layout
    if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
    {
        nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
    }
    // <--

    return nRight;
}

long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
{
    long nLeft;

    // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
    // and right border are painted on the right respectively left.
    if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
        nLeft = CalcRightLine();
    else
        nLeft = CalcLeftLine();

    // for paragraphs, "left" is "before text" and "right" is "after text"
    if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
        nLeft += rLR.GetRight();
    else
        nLeft += rLR.GetLeft();

    // --> OD 2008-01-21 #newlistlevelattrs#
    // correction: do not retrieve left margin for numbering in R2L-layout
//    if ( pCaller->IsTxtFrm() )
    if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
    // <--
    {
        nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
    }

    return nLeft;
}

/*************************************************************************
|*
|*	SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
|*				   CalcLeftLine(), CalcRightLine()
|*
|*	Beschreibung		Berechnung der Groessen fuer Umrandung und Schatten.
|* 						Es kann auch ohne Linien ein Abstand erwuenscht sein,
|* 						dieser wird  dann nicht vom Attribut sondern hier
|* 						beruecksichtigt (bBorderDist, z.B. fuer Zellen).
|*
|*************************************************************************/

void SwBorderAttrs::_CalcTopLine()
{
	nTopLine = (bBorderDist && !rBox.GetTop())
							? rBox.GetDistance  (BOX_LINE_TOP)
							: rBox.CalcLineSpace(BOX_LINE_TOP);
	nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
	bTopLine = sal_False;
}

void SwBorderAttrs::_CalcBottomLine()
{
	nBottomLine = (bBorderDist && !rBox.GetBottom())
							? rBox.GetDistance  (BOX_LINE_BOTTOM)
							: rBox.CalcLineSpace(BOX_LINE_BOTTOM);
	nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
	bBottomLine = sal_False;
}

void SwBorderAttrs::_CalcLeftLine()
{
	nLeftLine = (bBorderDist && !rBox.GetLeft())
							? rBox.GetDistance  (BOX_LINE_LEFT)
							: rBox.CalcLineSpace(BOX_LINE_LEFT);
	nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
	bLeftLine = sal_False;
}

void SwBorderAttrs::_CalcRightLine()
{
	nRightLine = (bBorderDist && !rBox.GetRight())
							? rBox.GetDistance  (BOX_LINE_RIGHT)
							: rBox.CalcLineSpace(BOX_LINE_RIGHT);
	nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
	bRightLine = sal_False;
}

/*************************************************************************/

void SwBorderAttrs::_IsLine()
{
	bIsLine = rBox.GetTop() || rBox.GetBottom() ||
			  rBox.GetLeft()|| rBox.GetRight();
	bLine = sal_False;
}

/*************************************************************************
|*
|*	SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
|*
|*		Die Umrandungen benachbarter Absaetze werden nach folgendem
|*		Algorithmus zusammengefasst:
|*
|*		1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
|*		   Umrandung oben aufweist und 3. Zutrifft.
|*		   Zusaetzlich muss der Absatz mindestens rechts oder links oder
|*		   unten eine Umrandung haben.
|*		2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
|*		   Umrandung untern aufweist und 3. Zustrifft.
|*		   Zusaetzlich muss der Absatz mindestens rechts oder links oder
|*		   oben eine Umrandung haben.
|*		3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
|*		   sind identisch.
|*
|*************************************************************************/
inline int CmpLines( const SvxBorderLine *pL1, const SvxBorderLine *pL2 )
{
	return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
}

// OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
// OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
//          instead of only the right LR-spacing, because R2L-layout has to be
//          considered.
sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
								  const SwFrm *pCaller,
								  const SwFrm *pCmp ) const
{
    return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft()  ) &&
             CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
             CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
             // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
             CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
}

sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
                                  const SwFrm& _rCmpFrm ) const
{
    sal_Bool bReturnVal = sal_False;

    SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
    const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
    if ( rShadow == rCmpAttrs.GetShadow() &&
         CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
         CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
         CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
       )
    {
        bReturnVal = sal_True;
    }

    return bReturnVal;
}

// OD 21.05.2003 #108789# - method to determine, if borders are joined with
// previous frame. Calculated value saved in cached value <bJoinedWithPrev>
// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
                                         const SwFrm* _pPrevFrm )
{
    // set default
    bJoinedWithPrev = sal_False;

    if ( _rFrm.IsTxtFrm() )
    {
        // text frame can potentially join with previous text frame, if
        // corresponding attribute set is set at previous text frame.
        // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
        // one as previous frame.
        const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
        // OD 2004-02-13 #i25029# - skip hidden text frames.
        while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
                static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
        {
            pPrevFrm = pPrevFrm->GetPrev();
        }
        if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
             pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
           )
        {
            bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
        }
    }

    // valid cache status, if demanded
    // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
    // is set.
    bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
}

// OD 21.05.2003 #108789# - method to determine, if borders are joined with
// next frame. Calculated value saved in cached value <bJoinedWithNext>
void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
{
    // set default
    bJoinedWithNext = sal_False;

    if ( _rFrm.IsTxtFrm() )
    {
        // text frame can potentially join with next text frame, if
        // corresponding attribute set is set at current text frame.
        // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
        const SwFrm* pNextFrm = _rFrm.GetNext();
        while ( pNextFrm && pNextFrm->IsTxtFrm() &&
                static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
        {
            pNextFrm = pNextFrm->GetNext();
        }
        if ( pNextFrm && pNextFrm->IsTxtFrm() &&
             _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
           )
        {
            bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
        }
    }

    // valid cache status, if demanded
    bCachedJoinedWithNext = bCacheGetLine;
}

// OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
// method <_CalcJoindWithPrev(..)>.
sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
                                    const SwFrm* _pPrevFrm ) const
{
    if ( !bCachedJoinedWithPrev || _pPrevFrm )
    {
        // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
        const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
    }

    return bJoinedWithPrev;
}

sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
{
    if ( !bCachedJoinedWithNext )
    {
        const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
    }

    return bJoinedWithNext;
}

// OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
// method <JoinedWithPrev>
void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
                                 const SwFrm* _pPrevFrm )
{
    sal_uInt16 nRet = CalcTopLine();

    // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
    // OD 2004-02-26 #i25029# - add 2nd parameter
    if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
    {
        nRet = 0;
    }

    bCachedGetTopLine = bCacheGetLine;

	nGetTopLine = nRet;
}

void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
{
	sal_uInt16 nRet = CalcBottomLine();

    // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
    if ( JoinedWithNext( _rFrm ) )
    {
        nRet = 0;
    }

    bCachedGetBottomLine = bCacheGetLine;

	nGetBottomLine = nRet;
}

/*************************************************************************/

SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
    SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
								(void*)((SwCntntFrm*)pFrm)->GetNode() :
								(void*)((SwLayoutFrm*)pFrm)->GetFmt()),
						   (sal_Bool)(pFrm->IsCntntFrm() ?
				((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
				((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
	pConstructor( pFrm )
{
}

/*************************************************************************/

SwCacheObj *SwBorderAttrAccess::NewObj()
{
	((SwModify*)pOwner)->SetInCache( sal_True );
	return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
}

SwBorderAttrs *SwBorderAttrAccess::Get()
{
	return (SwBorderAttrs*)SwCacheAccess::Get();
}

/*************************************************************************/

SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
	pPage( pPg ),
	pCurrent( 0 ),
	bFlysOnly( bFlys )
{
}

/*************************************************************************/

const SdrObject *SwOrderIter::Top()
{
	pCurrent = 0;
	if ( pPage->GetSortedObjs() )
	{
		sal_uInt32 nTopOrd = 0;
        const SwSortedObjs *pObjs = pPage->GetSortedObjs();
		if ( pObjs->Count() )
		{
            (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
			{
                const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
					continue;
				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
				if ( nTmp >= nTopOrd )
				{
					nTopOrd = nTmp;
					pCurrent = pObj;
				}
			}
		}
	}
	return pCurrent;
}

/*************************************************************************/

const SdrObject *SwOrderIter::Bottom()
{
	pCurrent = 0;
	if ( pPage->GetSortedObjs() )
	{
		sal_uInt32 nBotOrd = USHRT_MAX;
        const SwSortedObjs *pObjs = pPage->GetSortedObjs();
		if ( pObjs->Count() )
		{
            (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
			{
                const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
					continue;
				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
				if ( nTmp < nBotOrd )
				{
					nBotOrd = nTmp;
					pCurrent = pObj;
				}
			}
		}
	}
	return pCurrent;
}

/*************************************************************************/

const SdrObject *SwOrderIter::Next()
{
	const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
	pCurrent = 0;
	if ( pPage->GetSortedObjs() )
	{
		sal_uInt32 nOrd = USHRT_MAX;
        const SwSortedObjs *pObjs = pPage->GetSortedObjs();
		if ( pObjs->Count() )
		{
            (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
			{
                const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
					continue;
				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
				if ( nTmp > nCurOrd && nTmp < nOrd )
				{
					nOrd = nTmp;
					pCurrent = pObj;
				}
			}
		}
	}
	return pCurrent;
}

/*************************************************************************/

const SdrObject *SwOrderIter::Prev()
{
	const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
	pCurrent = 0;
	if ( pPage->GetSortedObjs() )
	{
		sal_uInt32 nOrd = 0;
        const SwSortedObjs *pObjs = pPage->GetSortedObjs();
		if ( pObjs->Count() )
		{
            (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
			{
                const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
					continue;
				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
				if ( nTmp < nCurOrd && nTmp >= nOrd )
				{
					nOrd = nTmp;
					pCurrent = pObj;
				}
			}
		}
	}
	return pCurrent;
}

/*************************************************************************/

//Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
//restaurieren.
//Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
//die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
//Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
//Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
//angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
//die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
//auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
//Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
//verboten.
//Unterwegs werden die Flys bei der Seite abgemeldet.

// --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
// at-fly anchored objects from page
void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
{
    ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
    SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
	for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
	{
        SwAnchoredObject* pObj = rObjs[i];
        // --> OD 2004-11-29 #115759# - reset member, at which the anchored
        // object orients its vertical position
        pObj->ClearVertPosOrientFrm();
        // <--
        // --> OD 2005-03-03 #i43913#
        pObj->ResetLayoutProcessBools();
        // <--
        // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
        // anchored Writer fly frames from page
        if ( pObj->ISA(SwFlyFrm) )
        {
            SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);

            // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
            // fly frame from page
            if ( pFlyFrm->GetDrawObjs() )
            {
                ::lcl_RemoveObjsFromPage( pFlyFrm );
            }
            // <--

            SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
            while ( pCnt )
            {
                if ( pCnt->GetDrawObjs() )
                    ::lcl_RemoveObjsFromPage( pCnt );
                pCnt = pCnt->GetNextCntntFrm();
            }
            if ( pFlyFrm->IsFlyFreeFrm() )
            {
                // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
                pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
            }
        }
        // <--
        // --> OD 2004-11-29 #115759# - remove also drawing objects from page
        else if ( pObj->ISA(SwAnchoredDrawObject) )
        {
            if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
            {
                pObj->GetPageFrm()->RemoveDrawObjFromPage(
                                *(static_cast<SwAnchoredDrawObject*>(pObj)) );
            }
        }
        // <--
	}
}

SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
{
	if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
		lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );

	SwFrm *pSav;
	if ( 0 == (pSav = pLay->ContainsAny()) )
		return 0;

	if( pSav->IsInFtn() && !pLay->IsInFtn() )
	{
		do
			pSav = pSav->FindNext();
		while( pSav && pSav->IsInFtn() );
		if( !pSav || !pLay->IsAnLower( pSav ) )
			return NULL;
	}

    // Tables should be saved as a whole, expection:
    // The contents of a section or a cell inside a table should be saved
    if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
        while ( !pSav->IsTabFrm() )
            pSav = pSav->GetUpper();

	if( pSav->IsInSct() )
	{ // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
		SwFrm* pSect = pLay->FindSctFrm();
		SwFrm *pTmp = pSav;
		do
		{
			pSav = pTmp;
			pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
		} while ( pTmp != pSect );
	}

	SwFrm *pFloat = pSav;
	if( !pStart )
		pStart = pSav;
	sal_Bool bGo = pStart == pSav;
	do
	{
		if( bGo )
			pFloat->GetUpper()->pLower = 0; 	//Die Teilkette ausklinken.

		//Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
		do
		{
			if( bGo )
			{
				if ( pFloat->IsCntntFrm() )
				{
					if ( pFloat->GetDrawObjs() )
                        ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
				}
				else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
				{
					SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
					if( pCnt )
					{
						do
						{	if ( pCnt->GetDrawObjs() )
                                ::lcl_RemoveObjsFromPage( pCnt );
							pCnt = pCnt->GetNextCntntFrm();
						} while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
					}
				}
				else {
					ASSERT( !pFloat, "Neuer Float-Frame?" );
                }
			}
			if ( pFloat->GetNext()	)
			{
				if( bGo )
					pFloat->pUpper = NULL;
				pFloat = pFloat->GetNext();
				if( !bGo && pFloat == pStart )
				{
					bGo = sal_True;
					pFloat->pPrev->pNext = NULL;
					pFloat->pPrev = NULL;
				}
			}
			else
				break;

		} while ( pFloat );

		//Die naechste Teilkette suchen und die Ketten miteinander verbinden.
		SwFrm *pTmp = pFloat->FindNext();
		if( bGo )
			pFloat->pUpper = NULL;

		if( !pLay->IsInFtn() )
			while( pTmp && pTmp->IsInFtn() )
				pTmp = pTmp->FindNext();

		if ( !pLay->IsAnLower( pTmp ) )
			pTmp = 0;

		if ( pTmp && bGo )
		{
			pFloat->pNext = pTmp;			//Die beiden Ketten verbinden.
			pFloat->pNext->pPrev = pFloat;
		}
		pFloat = pTmp;
		bGo = bGo || ( pStart == pFloat );
	}  while ( pFloat );

	return bGo ? pStart : NULL;
}

// --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
// anchored objects to page
void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
{
    ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
    SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
	for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
	{
        SwAnchoredObject* pObj = rObjs[i];

        // --> OD 2004-11-29 #115759# - unlock position of anchored object
        // in order to get the object's position calculated.
        pObj->UnlockPosition();
        // <--
        // --> OD 2004-11-29 #115759# - add also lower objects of as-character
        // anchored Writer fly frames from page
        if ( pObj->ISA(SwFlyFrm) )
        {
            SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
            if ( pObj->ISA(SwFlyFreeFrm) )
            {
                _pPage->AppendFlyToPage( pFlyFrm );
            }
            pFlyFrm->_InvalidatePos();
            pFlyFrm->_InvalidateSize();
            pFlyFrm->InvalidatePage( _pPage );

            // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
            // to page
            if ( pFlyFrm->GetDrawObjs() )
            {
                ::lcl_AddObjsToPage( pFlyFrm, _pPage );
            }
            // <--

            SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
            while ( pCnt )
            {
                if ( pCnt->GetDrawObjs() )
                    ::lcl_AddObjsToPage( pCnt, _pPage );
                pCnt = pCnt->GetNextCntntFrm();
            }
        }
        // <--
        // --> OD 2004-11-29 #115759# - remove also drawing objects from page
        else if ( pObj->ISA(SwAnchoredDrawObject) )
        {
            if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
            {
                pObj->InvalidateObjPos();
                _pPage->AppendDrawObjToPage(
                                *(static_cast<SwAnchoredDrawObject*>(pObj)) );
            }
        }
        // <--
	}
}

void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
{
	ASSERT( pSav && pParent, "Kein Save oder Parent fuer Restore." );
    SWRECTFN( pParent )

	//Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
	//Kette, beginnend mit pSav,  hinter dem letzten angehaengt.
	//Die Teile werden kurzerhand insertet und geeignet invalidiert.
	//Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.

	SwPageFrm *pPage = pParent->FindPageFrm();

	if ( pPage )
		pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.

	//Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren.
	pSav->pPrev = pSibling;
	SwFrm* pNxt;
	if ( pSibling )
	{
		pNxt = pSibling->pNext;
		pSibling->pNext = pSav;
		pSibling->_InvalidatePrt();
		((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
		if ( ((SwCntntFrm*)pSibling)->GetFollow() )
			pSibling->Prepare( PREP_CLEAR, 0, sal_False );
	}
	else
	{	pNxt = pParent->pLower;
		pParent->pLower = pSav;
		pSav->pUpper = pParent;		//Schon mal setzen, sonst ist fuer das
									//invalidate der Parent (z.B. ein Fly) nicht klar.
		//Invaliden Cntnt anmelden.
		if ( pSav->IsCntntFrm() )
			((SwCntntFrm*)pSav)->InvalidatePage( pPage );
		else
		{   // pSav koennte auch ein leerer SectFrm sein
			SwCntntFrm* pCnt = pParent->ContainsCntnt();
			if( pCnt )
				pCnt->InvalidatePage( pPage );
		}
	}

	//Der Parent muss entsprechend gegrow'ed werden.
	SwTwips nGrowVal = 0;
	SwFrm* pLast;
	do
	{	pSav->pUpper = pParent;
		nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
		pSav->_InvalidateAll();

        //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
		if ( pSav->IsCntntFrm() )
		{
			if ( pSav->IsTxtFrm() &&
				 ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
				((SwTxtFrm*)pSav)->Init();	//Ich bin sein Freund.

			if ( pPage && pSav->GetDrawObjs() )
                ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
		}
		else
		{	SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
			if( pBlub )
			{
				do
				{	if ( pPage && pBlub->GetDrawObjs() )
                        ::lcl_AddObjsToPage( pBlub, pPage );
					if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
				 		((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
						((SwTxtFrm*)pBlub)->Init();	//Ich bin sein Freund.
					pBlub = pBlub->GetNextCntntFrm();
				} while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
			}
		}
		pLast = pSav;
		pSav = pSav->GetNext();

	} while ( pSav );

	if( pNxt )
	{
		pLast->pNext = pNxt;
		pNxt->pPrev = pLast;
	}

    if ( bGrow )
        pParent->Grow( nGrowVal );
}

/*************************************************************************
|*
|*	SqRt()				Berechnung der Quadratwurzel, damit die math.lib
|*		nicht auch noch dazugelinkt werden muss.
|*
|*************************************************************************/

sal_uLong MA_FASTCALL SqRt( BigInt nX )
{
	BigInt nErg = 1;

	if ( !nX.IsNeg() )
	{
		BigInt nOldErg = 1;
		for ( int i = 0; i <= 5; i++ )
		{
			nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
			nOldErg = nErg;
		}
	}
	return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg;
}

/*************************************************************************/

SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
						  sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
						  SwFrm *pSibling )
{
	SwPageFrm *pRet;
	SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
	SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
	//Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
	//eine Leerseite einfuegen.
	if ( !pFmt )
	{
		pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
		ASSERT( pFmt, "Descriptor without any format?!" );
		bInsertEmpty = !bInsertEmpty;
	}
	if( bInsertEmpty )
	{
		SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
				((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
		pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
		pRet->Paste( pUpper, pSibling );
		pRet->PreparePage( bFtn );
	}
	pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
	pRet->Paste( pUpper, pSibling );
	pRet->PreparePage( bFtn );
	if ( pRet->GetNext() )
		((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
	return pRet;
}


/*************************************************************************
|*
|*	RegistFlys(), Regist()	Die beiden folgenden Methoden durchsuchen rekursiv
|*		eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
|*		innerhalb der Struktur als Anker haben bei der Seite an.
|*
|*************************************************************************/

void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
{
    SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
	for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
	{
        SwAnchoredObject* pObj = (*pObjs)[i];
        if ( pObj->ISA(SwFlyFrm) )
		{
            SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
			//Ggf. ummelden, nicht anmelden wenn bereits bekannt.
            // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
            SwPageFrm *pPg = pFly->IsFlyFreeFrm()
                             ? pFly->GetPageFrm() : pFly->FindPageFrm();
			if ( pPg != pPage )
			{
				if ( pPg )
                    pPg->RemoveFlyFromPage( pFly );
                pPage->AppendFlyToPage( pFly );
			}
			::RegistFlys( pPage, pFly );
		}
		else
		{
            // --> OD 2008-04-22 #i87493#
            if ( pPage != pObj->GetPageFrm() )
            {
                // --> OD 2004-07-02 #i28701#
                if ( pObj->GetPageFrm() )
                    pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
                pPage->AppendDrawObjToPage( *pObj );
                // <--
            }
            // <--
		}

        const SwFlyFrm* pFly = pAnch->FindFlyFrm();
        if ( pFly &&
             pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
             pObj->GetDrawObj()->GetPage() )
        {
            //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
            pObj->DrawObj()->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(),
                                                         pObj->GetDrawObj()->GetOrdNumDirect() );
        }
	}
}

void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
{
	if ( pLay->GetDrawObjs() )
		::lcl_Regist( pPage, pLay );
	const SwFrm *pFrm = pLay->Lower();
	while ( pFrm )
	{
		if ( pFrm->IsLayoutFrm() )
			::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
		else if ( pFrm->GetDrawObjs() )
			::lcl_Regist( pPage, pFrm );
		pFrm = pFrm->GetNext();
	}
}

/*************************************************************************
|*
|*	void Notify()
|*
|*	Beschreibung		Benachrichtigt den Hintergrund je nach der
|*		Veraenderung zwischen altem und neuem Rechteckt.
|*
|*************************************************************************/

void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
             const SwRect* pOldPrt )
{
    const SwRect aFrm( pFly->GetObjRectWithSpaces() );
	if ( rOld.Pos() != aFrm.Pos() )
	{	//Positionsaenderung, alten und neuen Bereich invalidieren
		if ( rOld.HasArea() &&
			 rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
		{
			pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
		}
		pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
	}
	else if ( rOld.SSize() != aFrm.SSize() )
	{	//Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
		//ueberdeckt wird invalidieren.
		//Der Einfachheit halber wird hier bewusst jeweils ein Twip
		//unnoetig invalidiert.

		ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
		if( pSh && rOld.HasArea() )
			pSh->InvalidateWindows( rOld );

        // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
        // registered at the old page <pOld>
        SwPageFrm* pPageFrm = pFly->FindPageFrm();
        if ( pOld != pPageFrm )
        {
            pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
        }
        // <--

		if ( rOld.Left() != aFrm.Left() )
        {
            SwRect aTmp( rOld );
			aTmp.Union( aFrm );
			aTmp.Left(	Min(aFrm.Left(), rOld.Left()) );
			aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
		}
		SwTwips nOld = rOld.Right();
		SwTwips nNew = aFrm.Right();
		if ( nOld != nNew )
        {
            SwRect aTmp( rOld );
			aTmp.Union( aFrm );
			aTmp.Left(	Min(nNew, nOld) );
			aTmp.Right( Max(nNew, nOld) );
			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
		}
		if ( rOld.Top() != aFrm.Top() )
        {
            SwRect aTmp( rOld );
			aTmp.Union( aFrm );
			aTmp.Top(	 Min(aFrm.Top(), rOld.Top()) );
			aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
		}
		nOld = rOld.Bottom();
		nNew = aFrm.Bottom();
		if ( nOld != nNew )
        {
            SwRect aTmp( rOld );
			aTmp.Union( aFrm );
			aTmp.Top(	 Min(nNew, nOld) );
			aTmp.Bottom( Max(nNew, nOld) );
			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
		}
	}
    else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
              pFly->GetFmt()->GetSurround().IsContour() )
    {
        // #i24097#
        pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
    }
}

/*************************************************************************/

void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
{
    SwTwips nBottom = rRect.Bottom();
    while( pFrm )
    {
        if( pFrm->IsLayoutFrm() )
        {
            if( rRect.IsOver( pFrm->Frm() ) )
                lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
        }
        else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
        {
            if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
                pFrm->InvalidateSize();
            else
                pFrm->InvalidateNextPos();
        }
        pFrm = pFrm->GetNext();
    }
}

void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
	const SwRect &rRect, const PrepareHint eHint )
{
	if ( pCnt->IsTxtFrm() )
	{
		SwRect aCntPrt( pCnt->Prt() );
		aCntPrt.Pos() += pCnt->Frm().Pos();
		if ( eHint == PREP_FLY_ATTR_CHG )
		{
            // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
            // of current bound rectangle
            if ( aCntPrt.IsOver( rRect ) )
            // <--
				pCnt->Prepare( PREP_FLY_ATTR_CHG );
		}
        // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
        // printing area overlaps with the given rectangle.
        else if ( aCntPrt.IsOver( rRect ) )
        // <--
			pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
		if ( pCnt->GetDrawObjs() )
		{
            const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
			for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
			{
                SwAnchoredObject* pObj = rObjs[i];
                if ( pObj->ISA(SwFlyFrm) )
				{
                    SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
					if ( pFly->IsFlyInCntFrm() )
					{
						SwCntntFrm *pCntnt = pFly->ContainsCntnt();
						while ( pCntnt )
						{
							::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
							pCntnt = pCntnt->GetNextCntntFrm();
						}
					}
				}
			}
		}
	}
}

void Notify_Background( const SdrObject* pObj,
                        SwPageFrm* pPage,
                        const SwRect& rRect,
                        const PrepareHint eHint,
                        const sal_Bool bInva )
{

	//Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
	//alte Bereich nicht benachrichtigt werden.
	if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
		 return;

    SwLayoutFrm* pArea;
	SwFlyFrm *pFlyFrm = 0;
	SwFrm* pAnchor;
	if( pObj->ISA(SwVirtFlyDrawObj) )
	{
		pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
        pAnchor = pFlyFrm->AnchorFrm();
	}
	else
	{
		pFlyFrm = NULL;
        pAnchor = const_cast<SwFrm*>(
                    GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
	}
	if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
		pArea = pAnchor->FindFlyFrm();
	else
        pArea = pPage;
	SwCntntFrm *pCnt = 0;
	if ( pArea )
	{
        if( PREP_FLY_ARRIVE != eHint )
            lcl_CheckFlowBack( pArea, rRect );

		//Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
		//brauchen diese nicht abgeklappert werden.
		//Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
		//"oben" kommen.
		// Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
		// die gesamte Seite abgearbeitet werden. (47722)
        // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
        // on the object positioning, the complete area has to be processed,
        // because content frames before the anchor frame also have to consider
        // the object for the text wrapping.
        // --> OD 2004-08-25 #i3317# - The complete area has always been
        // processed.
        {
			pCnt = pArea->ContainsCntnt();
        }
        // <--
	}
	SwFrm *pLastTab = 0;

    while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
	{
		::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
		if ( pCnt->IsInTab() )
		{
			SwLayoutFrm* pCell = pCnt->GetUpper();
            // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
            // instead of <GetCurrentBoundRect()>, because a recalculation
            // of the bounding rectangle isn't intended here.
            if ( pCell->IsCellFrm() &&
                 ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
                   pCell->Frm().IsOver( rRect ) ) )
            // <--
			{
				const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
                if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
					pCell->InvalidatePrt();
			}
			SwTabFrm *pTab = pCnt->FindTabFrm();
			if ( pTab != pLastTab )
			{
				pLastTab = pTab;
                // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
                // instead of <GetCurrentBoundRect()>, because a recalculation
                // of the bounding rectangle isn't intended here.
                if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
                     pTab->Frm().IsOver( rRect ) )
                // <--
				{
                    if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
						pTab->InvalidatePrt();
				}
			}
		}
		pCnt = pCnt->GetNextCntntFrm();
	}
// #108745# Sorry, but this causes nothing but trouble. I remove these lines
// taking the risk that the footer frame will have a wrong height
//  if( pPage->Lower() )
//  {
//      SwFrm* pFrm = pPage->Lower();
//      while( pFrm->GetNext() )
//          pFrm = pFrm->GetNext();
//      if( pFrm->IsFooterFrm() &&
//          ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
//              pFrm->Frm().IsOver( rRect ) ) ) )
//           pFrm->InvalidateSize();
//  }
    // --> OD 2007-07-24 #128702# - make code robust
    if ( pPage && pPage->GetSortedObjs() )
    // <--
	{
		pObj->GetOrdNum();
        const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
		for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
		{
            SwAnchoredObject* pAnchoredObj = rObjs[i];
            if ( pAnchoredObj->ISA(SwFlyFrm) )
			{
                if( pAnchoredObj->GetDrawObj() == pObj )
					continue;
                SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
				if ( pFly->Frm().Top() == WEIT_WECH )
					continue;

				if ( !pFlyFrm ||
                        (!pFly->IsLowerOf( pFlyFrm ) &&
						pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
				{
					pCnt = pFly->ContainsCntnt();
					while ( pCnt )
					{
						::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
						pCnt = pCnt->GetNextCntntFrm();
					}
				}
				if( pFly->IsFlyLayFrm() )
				{
					if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
						pFly->Frm().Bottom() >= rRect.Top() &&
						pFly->Frm().Top() <= rRect.Bottom() &&
						pFly->Frm().Right() >= rRect.Left() &&
						pFly->Frm().Left() <= rRect.Right() )
					 {
                        pFly->InvalidateSize();
					 }
				}
				//Flys, die ueber mir liegen muessen/mussten evtl.
				//ausweichen, wenn sie eine automatische Ausrichtung haben.
				//das ist unabhaengig von meinem Attribut, weil dies sich
				//gerade geaendert haben kann und eben deshalb
				//umformatiert wurde.
				else if ( pFly->IsFlyAtCntFrm() &&
						pObj->GetOrdNumDirect() <
						pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
                        pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
				{
					const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
                    if ( text::HoriOrientation::NONE != rH.GetHoriOrient()  &&
                            text::HoriOrientation::CENTER != rH.GetHoriOrient()  &&
                            ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
							(pFly->Frm().Bottom() >= rRect.Top() &&
							pFly->Frm().Top() <= rRect.Bottom()) )
						pFly->InvalidatePos();
				}
			}
		}
	}
	if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
		pAnchor->GetUpper()->InvalidateSize();

    // --> OD 2008-01-30 #i82258# - make code robust
    ViewShell* pSh = 0;
    if ( bInva && pPage &&
        0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
    {
        pSh->InvalidateWindows( rRect );
    }
    // <--
}

/*************************************************************************
|*
|*	GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
|*  des Ankers. Falls es sich dabei um verkettete Rahmen oder
|*	Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
|*
|*************************************************************************/

const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
{
	if( pFrm->IsTxtFrm() )
	{
		pFrm = pFrm->GetUpper();
		if( !pFrm->Frm().IsInside( rPos ) )
		{
			if( pFrm->IsFtnFrm() )
			{
				const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
				while( pTmp )
				{
					if( pTmp->Frm().IsInside( rPos ) )
						return pTmp;
					pTmp = pTmp->GetFollow();
				}
			}
			else
			{
				SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
				while( pTmp )
				{
					if( pTmp->Frm().IsInside( rPos ) )
						return pTmp;
					pTmp = pTmp->GetNextLink();
				}
			}
		}
	}
	return pFrm;
}

/*************************************************************************/

sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
{
	Point aPos;
	const SwFrm* pFrm;
	if( pObj->ISA(SwVirtFlyDrawObj) )
	{
		const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
        pFrm = pFly->GetAnchorFrm();
		aPos = pFly->Frm().Pos();
	}
	else
	{
        pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
		aPos = pObj->GetCurrentBoundRect().TopLeft();
	}
	ASSERT( pFrm, "8-( Fly is lost in Space." );
	pFrm = GetVirtualUpper( pFrm, aPos );
	do
	{	if ( pFrm == pCurrFrm )
			return sal_True;
		if( pFrm->IsFlyFrm() )
		{
			aPos = pFrm->Frm().Pos();
            pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
		}
		else
			pFrm = pFrm->GetUpper();
	} while ( pFrm );
	return sal_False;
}

const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
{
	//Liefert die Umgebung des Frm in die kein Fly aus einer anderen
	//Umgebung hineinragen kann.
	const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
						FRM_FTN  | FRM_FLY      |
						FRM_TAB  | FRM_ROW		| FRM_CELL |
						nAdditionalKontextTyp;
	do
	{	if ( pFrm->GetType() & nTyp )
			break;
		pFrm = pFrm->GetUpper();
	} while( pFrm );
	return pFrm;
}

sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
{
	const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );

	const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
						FRM_FTN  | FRM_FLY      |
						FRM_TAB  | FRM_ROW 		| FRM_CELL;
	do
	{	if ( pFrm->GetType() & nTyp )
		{
			if( pFrm == pKontext )
				return sal_True;
			if( pFrm->IsCellFrm() )
				return sal_False;
		}
		if( pFrm->IsFlyFrm() )
		{
			Point aPos( pFrm->Frm().Pos() );
            pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
		}
		else
			pFrm = pFrm->GetUpper();
	} while( pFrm );

	return sal_False;
}


//---------------------------------

SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
{
	if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
	{
		SwFrm *pLow = pCell->Lower();
		long nHeight = 0, nFlyAdd = 0;
		do
		{
			long nLow = pLow->Frm().Height();
			if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
				nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
			else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
				nLow += ((SwSectionFrm*)pLow)->Undersize();
			nFlyAdd = Max( 0L, nFlyAdd - nLow );
			nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
			nHeight += nLow;
			pLow = pLow->GetNext();
		} while ( pLow );
		if ( nFlyAdd )
			nHeight += nFlyAdd;

		//Der Border will natuerlich auch mitspielen, er kann leider nicht
		//aus PrtArea und Frm errechnet werden, da diese in beliebiger
		//Kombination ungueltig sein koennen.
		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
		const SwBorderAttrs &rAttrs = *aAccess.Get();
		nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();

		return pCell->Frm().Height() - nHeight;
	}
	else
	{
		long nRstHeight = 0;
		SwFrm *pLow = pCell->Lower();
		do
		{	nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
			pLow = pLow->GetNext();

		} while ( pLow );

		return nRstHeight;
	}
}

SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
{
	SwTwips nRstHeight = LONG_MAX;
	SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
	while ( pLow )
	{
		nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
		pLow = (SwLayoutFrm*)pLow->GetNext();
	}
	return nRstHeight;
}

const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
{
	if ( !rRect.IsOver( pPage->Frm() ) )
	{
        const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
        const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
        if ( pTmpPage )
            pPage = pTmpPage;
    }

    return pPage;
}

#include <svl/smplhint.hxx>
class SwFrmHolder : private SfxListener
{
    SwFrm* pFrm;
    bool bSet;
    virtual void Notify(  SfxBroadcaster& rBC, const SfxHint& rHint );
public:
    SwFrmHolder() : pFrm(0), bSet(false) {}
    void SetFrm( SwFrm* pHold );
    SwFrm* GetFrm() { return pFrm; }
    void Reset();
    bool IsSet() { return bSet; }
};

void SwFrmHolder::SetFrm( SwFrm* pHold )
{ 
    bSet = true; 
    pFrm = pHold; 
    StartListening(*pHold); 
}

void SwFrmHolder::Reset() 
{ 
    if (pFrm) 
        EndListening(*pFrm); 
    bSet = false; 
    pFrm = 0; 
}

void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    if ( rHint.IsA(TYPE(SfxSimpleHint)) )
    {
        if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
            pFrm = 0;
    }
}

SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
        const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
{
	SwFrm *pMinFrm = 0, *pTmpFrm;
    SwFrmHolder aHolder;
	SwRect aCalcRect;
    bool bClientIterChanged = false;

	SwIterator<SwFrm,SwModify> aIter( rMod );
	do {
		pMinFrm = 0;
        aHolder.Reset();
        sal_uInt64 nMinDist = 0;
        bClientIterChanged = false;

		for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
        {
			if( pTmpFrm->GetType() & nFrmType &&
                ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
				(!pTmpFrm->IsFlowFrm() ||
				 !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
			{
				if( pPoint )
				{
                    // watch for Frm being deleted
                    if ( pMinFrm )
                        aHolder.SetFrm( pMinFrm );
                    else
                        aHolder.Reset();

					if( bCalcFrm )
                    {
                        // --> OD 2005-03-04 #b6234250# - format parent Writer
                        // fly frame, if it isn't been formatted yet.
                        // Note: The Writer fly frame could be the frame itself.
                        SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
                        if ( pFlyFrm &&
                             pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
                             pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
                        {
                            SwObjectFormatter::FormatObj( *pFlyFrm );
                        }
                        // <--
                        pTmpFrm->Calc();
                    }

                    // #127369#
                    // aIter.IsChanged checks if the current pTmpFrm has been deleted while 
                    // it is the current iterator
                    // FrmHolder watches for deletion of the current pMinFrm 
                    if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
                    {
                        // restart iteration
                        bClientIterChanged = true;
                        break;
                    }

					// bei Flys ggfs. ueber den Parent gehen wenn sie selbst
					// nocht nicht "formatiert" sind
					if( !bCalcFrm && nFrmType & FRM_FLY &&
                        ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
						WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
						WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
                        aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
					else
						aCalcRect = pTmpFrm->Frm();

                    if ( aCalcRect.IsInside( *pPoint ) )
                    {
					    pMinFrm = pTmpFrm;
						break;
                    }

                    // Point not in rectangle. Compare distances:
                    const Point aCalcRectCenter = aCalcRect.Center();
                    const Point aDiff = aCalcRectCenter - *pPoint;
                    const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
                    if ( !pMinFrm || nCurrentDist < nMinDist )
                    {
        				pMinFrm = pTmpFrm;
	        			nMinDist = nCurrentDist;
                    }
				}
				else
				{
					// Wenn kein pPoint angegeben ist, dann reichen
					// wir irgendeinen raus: den ersten!
					pMinFrm = pTmpFrm;
					break;
				}
			}
        }
	} while( bClientIterChanged );

	if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
		return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );

	return pMinFrm;
}

sal_Bool IsExtraData( const SwDoc *pDoc )
{
	const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
	return rInf.IsPaintLineNumbers() ||
		   rInf.IsCountInFlys() ||
           ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
			pDoc->GetRedlineTbl().Count());
}

// OD 22.09.2003 #110978#
const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
{
    SwRect aPrtWithoutHeaderFooter( Prt() );
    aPrtWithoutHeaderFooter.Pos() += Frm().Pos();

    const SwFrm* pLowerFrm = Lower();
    while ( pLowerFrm )
    {
        // Note: independent on text direction page header and page footer are
        //       always at top respectively at bottom of the page frame.
        if ( pLowerFrm->IsHeaderFrm() )
        {
            aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
                                         pLowerFrm->Frm().Height() );
        }
        if ( pLowerFrm->IsFooterFrm() )
        {
            aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
                                            pLowerFrm->Frm().Height() );
        }

        pLowerFrm = pLowerFrm->GetNext();
    }

    return aPrtWithoutHeaderFooter;
}

/** method to determine the spacing values of a frame

    OD 2004-03-10 #i28701#
    OD 2009-08-28 #i102458#
    Add output parameter <obIsLineSpacingProportional>

    @author OD
*/
void GetSpacingValuesOfFrm( const SwFrm& rFrm,
                            SwTwips& onLowerSpacing,
                            SwTwips& onLineSpacing,
                            bool& obIsLineSpacingProportional )
{
    if ( !rFrm.IsFlowFrm() )
    {
        onLowerSpacing = 0;
        onLineSpacing = 0;
    }
    else
    {
        const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
        onLowerSpacing = rULSpace.GetLower();

        onLineSpacing = 0;
        obIsLineSpacingProportional = false;
        if ( rFrm.IsTxtFrm() )
        {
            onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
            obIsLineSpacingProportional =
                onLineSpacing != 0 &&
                static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
        }

        ASSERT( onLowerSpacing >= 0 && onLineSpacing >= 0,
                "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
    }
}

/** method to get the content of the table cell, skipping content from nested tables
*/
const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
{
    const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
    const SwTabFrm* pTab = rCell.FindTabFrm();

    while ( pCntnt && rCell.IsAnLower( pCntnt ) )
    {
        const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
        if ( pTmpTab != pTab )
        {
            pCntnt = pTmpTab->FindLastCntnt();
            if ( pCntnt )

                pCntnt = pCntnt->FindNextCnt();

        }
        else
            break;
    }
    return pCntnt;
}

/** Can be used to check if a frame has been deleted
 */
bool SwDeletionChecker::HasBeenDeleted()
{
    if ( !mpFrm || !mpRegIn )
        return false;

    SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
    SwFrm* pLast = aIter.First();
    while ( pLast )
    {
        if ( pLast == mpFrm )
            return false;
        pLast = aIter.Next();
    }

    return true;
}


