/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include "hintids.hxx"
#include <svl/itemiter.hxx>
#include <svtools/imap.hxx>
#include <vcl/graph.hxx>
#include <tools/poly.hxx>
#include <svx/contdlg.hxx>
#include <editeng/protitem.hxx>
#include <editeng/opaqitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/keepitem.hxx>
#include <fmtanchr.hxx>
#include <fmtfsize.hxx>
#include <fmtclds.hxx>
#include <fmtcntnt.hxx>
#include <fmturl.hxx>
#include <fmtsrnd.hxx>
#include <fmtornt.hxx>
#include <fmtpdsc.hxx>
#include <fmtcnct.hxx>
#include <layhelp.hxx>
#include <ndtxt.hxx>
#include <svx/svdogrp.hxx>
#include <ndgrf.hxx>
#include <tolayoutanchoredobjectposition.hxx>
#include <fmtfollowtextflow.hxx>
#include <sortedobjs.hxx>
#include <objectformatter.hxx>
#include <anchoredobject.hxx>
#include <ndole.hxx>
#include <swtable.hxx>
#include <svx/svdpage.hxx>
#include "doc.hxx"
#include "viewsh.hxx"
#include "layouter.hxx"
#include "pagefrm.hxx"
#include "rootfrm.hxx"
#include "cntfrm.hxx"
#include "pam.hxx"
#include "frmatr.hxx"
#include "viewimp.hxx"
#include "viewopt.hxx"
#include "errhdl.hxx"
#include "dcontact.hxx"
#include "dflyobj.hxx"
#include "dview.hxx"
#include "flyfrm.hxx"
#include "frmtool.hxx"
#include "frmfmt.hxx"
#include "hints.hxx"
#include "swregion.hxx"
#include "tabfrm.hxx"
#include "txtfrm.hxx"
#include "ndnotxt.hxx"
#include "notxtfrm.hxx"   // GetGrfArea
#include "flyfrms.hxx"
#include "ndindex.hxx"   // GetGrfArea
#include "sectfrm.hxx"
#include <vcl/svapp.hxx>
#include <vcl/salbtype.hxx>		// FRound
#include "switerator.hxx"

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


// OD 2004-03-23 #i26791
TYPEINIT2(SwFlyFrm,SwLayoutFrm,SwAnchoredObject);

/*************************************************************************
|*
|*	SwFlyFrm::SwFlyFrm()
|*
|*	Ersterstellung		MA 28. Sep. 92
|*	Letzte Aenderung	MA 09. Apr. 99
|*
|*************************************************************************/

SwFlyFrm::SwFlyFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
	SwLayoutFrm( pFmt, pSib ),
    // OD 2004-03-22 #i26791#
    SwAnchoredObject(),
    // OD 2004-05-27 #i26791# - moved to <SwAnchoredObject>
//    aRelPos(),
	pPrevLink( 0 ),
	pNextLink( 0 ),
	bInCnt( sal_False ),
	bAtCnt( sal_False ),
	bLayout( sal_False ),
    bAutoPosition( sal_False ),
    bNoShrink( sal_False ),
    bLockDeleteContent( sal_False )
{
    nType = FRMC_FLY;

	bInvalid = bNotifyBack = sal_True;
	bLocked  = bMinHeight =
	bHeightClipped = bWidthClipped = bFormatHeightOnly = sal_False;

	//Grosseneinstellung, Fixe groesse ist immer die Breite
	const SwFmtFrmSize &rFrmSize = pFmt->GetFrmSize();
    sal_Bool bVert = sal_False;
    sal_uInt16 nDir =
        ((SvxFrameDirectionItem&)pFmt->GetFmtAttr( RES_FRAMEDIR )).GetValue();
    if( FRMDIR_ENVIRONMENT == nDir )
    {
        bDerivedVert = 1;
        bDerivedR2L = 1;
        if( pAnch && pAnch->IsVertical() )
            bVert = sal_True;
    }
    else
    {
        bInvalidVert = 0;
        bDerivedVert = 0;
        bDerivedR2L = 0;
        if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
        {
            //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
            bVertLR = 0;
            bVertical = 0;
		}
        else 
        {
            const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
            if( pSh && pSh->GetViewOptions()->getBrowseMode() )
            {
                //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
                bVertLR = 0;
                bVertical = 0;
            }
            else
            {
                bVertical = 1;
                //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
            	if ( FRMDIR_VERT_TOP_LEFT == nDir )
                	bVertLR = 1;
                else
                	bVertLR = 0;
            }
        }
        
        bVert = bVertical;
        bInvalidR2L = 0;
        if( FRMDIR_HORI_RIGHT_TOP == nDir )
            bRightToLeft = 1;
        else
            bRightToLeft = 0;
    }

    Frm().Width( rFrmSize.GetWidth() );
    Frm().Height( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrmSize.GetHeight() );

	//Hoehe Fix oder Variabel oder was?
    if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
		bMinHeight = sal_True;
    else if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
        bFixSize = sal_True;

    // OD 2004-02-12 #110582#-2 - insert columns, if necessary
    InsertColumns();

	//Erst das Init, dann den Inhalt, denn zum Inhalt koennen  widerum
	//Objekte/Rahmen gehoeren die dann angemeldet werden.
    InitDrawObj( sal_False );

    // OD 2004-01-19 #110582#
    Chain( pAnch );

    // OD 2004-01-19 #110582#
    InsertCnt();

	//Und erstmal in den Wald stellen die Kiste, damit bei neuen Dokument nicht
	//unnoetig viel formatiert wird.
	Frm().Pos().X() = Frm().Pos().Y() = WEIT_WECH;
}

// OD 2004-01-19 #110582#
void SwFlyFrm::Chain( SwFrm* _pAnch )
{
    // Connect to chain neighboors.
    // No problem, if a neighboor doesn't exist - the construction of the
    // neighboor will make the connection
    const SwFmtChain& rChain = GetFmt()->GetChain();
    if ( rChain.GetPrev() || rChain.GetNext() )
    {
        if ( rChain.GetNext() )
        {
            SwFlyFrm* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
            if ( pFollow )
            {
                ASSERT( !pFollow->GetPrevLink(), "wrong chain detected" );
                if ( !pFollow->GetPrevLink() )
                    SwFlyFrm::ChainFrames( this, pFollow );
            }
        }
        if ( rChain.GetPrev() )
        {
            SwFlyFrm *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
            if ( pMaster )
            {
                ASSERT( !pMaster->GetNextLink(), "wrong chain detected" );
                if ( !pMaster->GetNextLink() )
                    SwFlyFrm::ChainFrames( pMaster, this );
            }
        }
    }
}

// OD 2004-01-19 #110582#
void SwFlyFrm::InsertCnt()
{
    if ( !GetPrevLink() )
    {
        const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
        ASSERT( rCntnt.GetCntntIdx(), ":-( no content prepared." );
        sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
        // Lower() bedeutet SwColumnFrm, eingefuegt werden muss der Inhalt dann in den (Column)BodyFrm
        ::_InsertCnt( Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower() : (SwLayoutFrm*)this,
                      GetFmt()->GetDoc(), nIndex );

        //NoTxt haben immer eine FixHeight.
        if ( Lower() && Lower()->IsNoTxtFrm() )
        {
            bFixSize = sal_True;
            bMinHeight = sal_False;
        }
    }
}

 // OD 2004-02-12 #110582#-2
 void SwFlyFrm::InsertColumns()
 {
    // --> OD 2009-08-12 #i97379#
    // Check, if column are allowed.
    // Columns are not allowed for fly frames, which represent graphics or embedded objects.
    const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
    ASSERT( rCntnt.GetCntntIdx(), "<SwFlyFrm::InsertColumns()> - no content prepared." );
    SwNodeIndex aFirstCntnt( *(rCntnt.GetCntntIdx()), 1 );
    if ( aFirstCntnt.GetNode().IsNoTxtNode() )
    {
        return;
    }
    // <--

    const SwFmtCol &rCol = GetFmt()->GetCol();
    if ( rCol.GetNumCols() > 1 )
    {
        //PrtArea ersteinmal so gross wie der Frm, damit die Spalten
        //vernuenftig eingesetzt werden koennen; das schaukelt sich dann
        //schon zurecht.
        Prt().Width( Frm().Width() );
        Prt().Height( Frm().Height() );
        const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass auch ein
                             //Old-Wert hereingereicht wird.
        ChgColumns( aOld, rCol );
    }
 }

/*************************************************************************
|*
|*	SwFlyFrm::~SwFlyFrm()
|*
|*	Ersterstellung		MA 28. Sep. 92
|*	Letzte Aenderung	MA 07. Jul. 95
|*
|*************************************************************************/

SwFlyFrm::~SwFlyFrm()
{
	// Accessible objects for fly frames will be destroyed in this destructor.
	// For frames bound as char or frames that don't have an anchor we have
	// to do that ourselves. For any other frame the call RemoveFly at the
	// anchor will do that.
    if( IsAccessibleFrm() && GetFmt() && (IsFlyInCntFrm() || !GetAnchorFrm()) )
	{
		SwRootFrm *pRootFrm = getRootFrm();
		if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
		{
			ViewShell *pVSh = pRootFrm->GetCurrShell();
			if( pVSh && pVSh->Imp() )
			{
				// Lowers aren't disposed already, so we have to do a recursive
				// dispose
				pVSh->Imp()->DisposeAccessibleFrm( this, sal_True );
			}
		}
	}

	if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
	{
        // OD 2004-01-19 #110582#
        Unchain();

        // OD 2004-01-19 #110582#
        DeleteCnt();

		//Tschuess sagen.
        if ( GetAnchorFrm() )
            AnchorFrm()->RemoveFly( this );
	}

    FinitDrawObj();
}

// OD 2004-01-19 #110582#
void SwFlyFrm::Unchain()
{
    if ( GetPrevLink() )
        UnchainFrames( GetPrevLink(), this );
    if ( GetNextLink() )
        UnchainFrames( this, GetNextLink() );
}

// OD 2004-01-19 #110582#
void SwFlyFrm::DeleteCnt()
{
    // #110582#-2
    if ( IsLockDeleteContent() )
        return;

    SwFrm* pFrm = pLower;
    while ( pFrm )
    {
        while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
        {
            SwAnchoredObject *pAnchoredObj = (*pFrm->GetDrawObjs())[0];
            if ( pAnchoredObj->ISA(SwFlyFrm) )
                delete pAnchoredObj;
            else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
            {
                // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
                SdrObject* pObj = pAnchoredObj->DrawObj();
                if ( pObj->ISA(SwDrawVirtObj) )
                {
                    SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
                    pDrawVirtObj->RemoveFromWriterLayout();
                    pDrawVirtObj->RemoveFromDrawingPage();
                }
                else
                {
                    SwDrawContact* pContact =
                            static_cast<SwDrawContact*>(::GetUserCall( pObj ));
                    if ( pContact )
                    {
                        pContact->DisconnectFromLayout();
                    }
                }
            }
        }

        pFrm->Remove();
        delete pFrm;
        pFrm = pLower;
    }

    InvalidatePage();
}

/*************************************************************************
|*
|*	SwFlyFrm::InitDrawObj()
|*
|*	Ersterstellung		MA 02. Dec. 94
|*	Letzte Aenderung	MA 30. Nov. 95
|*
|*************************************************************************/

sal_uInt32 SwFlyFrm::_GetOrdNumForNewRef( const SwFlyDrawContact* pContact )
{
    sal_uInt32 nOrdNum( 0L );

    // search for another Writer fly frame registered at same frame format
    SwIterator<SwFlyFrm,SwFmt> aIter( *pContact->GetFmt() );
    const SwFlyFrm* pFlyFrm( 0L );
    for ( pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
    {
        if ( pFlyFrm != this )
        {
            break;
        }
    }

    if ( pFlyFrm )
    {
        // another Writer fly frame found. Take its order number
        nOrdNum = pFlyFrm->GetVirtDrawObj()->GetOrdNum();
    }
    else
    {
        // no other Writer fly frame found. Take order number of 'master' object
        // --> OD 2004-11-11 #i35748# - use method <GetOrdNumDirect()> instead
        // of method <GetOrdNum()> to avoid a recalculation of the order number,
        // which isn't intended.
        nOrdNum = pContact->GetMaster()->GetOrdNumDirect();
        // <--
    }

    return nOrdNum;
}

SwVirtFlyDrawObj* SwFlyFrm::CreateNewRef( SwFlyDrawContact *pContact )
{
	SwVirtFlyDrawObj *pDrawObj = new SwVirtFlyDrawObj( *pContact->GetMaster(), this );
	pDrawObj->SetModel( pContact->GetMaster()->GetModel() );
	pDrawObj->SetUserCall( pContact );

    //Der Reader erzeugt die Master und setzt diese, um die Z-Order zu
	//transportieren, in die Page ein. Beim erzeugen der ersten Referenz werden
	//die Master aus der Liste entfernt und fuehren von da an ein
	//Schattendasein.
    SdrPage* pPg( 0L );
	if ( 0 != ( pPg = pContact->GetMaster()->GetPage() ) )
	{
		const sal_uInt32 nOrdNum = pContact->GetMaster()->GetOrdNum();
		pPg->ReplaceObject( pDrawObj, nOrdNum );
	}
    // --> OD 2004-08-16 #i27030# - insert new <SwVirtFlyDrawObj> instance
    // into drawing page with correct order number
    else
    {
        pContact->GetFmt()->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 )->
                        InsertObject( pDrawObj, _GetOrdNumForNewRef( pContact ) );
    }
    // <--
    // --> OD 2004-12-13 #i38889# - assure, that new <SwVirtFlyDrawObj> instance
    // is in a visible layer.
    pContact->MoveObjToVisibleLayer( pDrawObj );
    // <--
    return pDrawObj;
}



void SwFlyFrm::InitDrawObj( sal_Bool bNotify )
{
	//ContactObject aus dem Format suchen. Wenn bereits eines existiert, so
	//braucht nur eine neue Ref erzeugt werden, anderfalls ist es jetzt an
	//der Zeit das Contact zu erzeugen.
	
    IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
	SwFlyDrawContact *pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
	if ( !pContact )
    {
        // --> OD 2005-08-08 #i52858# - method name changed
		pContact = new SwFlyDrawContact( (SwFlyFrmFmt*)GetFmt(),
                                          pIDDMA->GetOrCreateDrawModel() );
        // <--
    }
	ASSERT( pContact, "InitDrawObj failed" );
    // OD 2004-03-22 #i26791#
    SetDrawObj( *(CreateNewRef( pContact )) );

    //Den richtigen Layer setzen.
    // OD 2004-01-19 #110582#
    SdrLayerID nHeavenId = pIDDMA->GetHeavenId();
    SdrLayerID nHellId = pIDDMA->GetHellId();
    // OD 2004-03-22 #i26791#
    GetVirtDrawObj()->SetLayer( GetFmt()->GetOpaque().GetValue()
                                ? nHeavenId
                                : nHellId );
	if ( bNotify )
		NotifyDrawObj();
}

/*************************************************************************
|*
|*	SwFlyFrm::FinitDrawObj()
|*
|*	Ersterstellung		MA 12. Dec. 94
|*	Letzte Aenderung	MA 15. May. 95
|*
|*************************************************************************/

void SwFlyFrm::FinitDrawObj()
{
    if ( !GetVirtDrawObj() )
		return;

	//Bei den SdrPageViews abmelden falls das Objekt dort noch selektiert ist.
	if ( !GetFmt()->GetDoc()->IsInDtor() )
	{
		ViewShell *p1St = getRootFrm()->GetCurrShell();
		if ( p1St )
		{
			ViewShell *pSh = p1St;
			do
			{	//z.Zt. kann das Drawing nur ein Unmark auf alles, weil das
				//Objekt bereits Removed wurde.
				if( pSh->HasDrawView() )
					pSh->Imp()->GetDrawView()->UnmarkAll();
				pSh = (ViewShell*)pSh->GetNext();

			} while ( pSh != p1St );
		}
	}

	//VirtObject mit in das Grab nehmen. Wenn das letzte VirObject
	//zerstoert wird, mussen das DrawObject und DrawContact ebenfalls
	//zerstoert werden.
	SwFlyDrawContact *pMyContact = 0;
	if ( GetFmt() )
	{
        bool bContinue = true;
        SwIterator<SwFrm,SwFmt> aFrmIter( *GetFmt() );
        for ( SwFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
            if ( pFrm != this )
            {
                // don't delete Contact if there is still a Frm
                bContinue = false;
                break;
            }

        if ( bContinue )
            // no Frm left, find Contact object to destroy
            pMyContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
	}

    // OD, OS 2004-03-31 #116203# - clear user call of Writer fly frame 'master'
    // <SdrObject> to assure, that a <SwXFrame::dispose()> doesn't delete the
    // Writer fly frame again.
    if ( pMyContact )
    {
        pMyContact->GetMaster()->SetUserCall( 0 );
    }
    GetVirtDrawObj()->SetUserCall( 0 ); //Ruft sonst Delete des ContactObj
    delete GetVirtDrawObj();			//Meldet sich selbst beim Master ab.
	if ( pMyContact )
		delete pMyContact;		//zerstoert den Master selbst.
}

/*************************************************************************
|*
|*	SwFlyFrm::ChainFrames()
|*
|*	Ersterstellung		MA 29. Oct. 97
|*	Letzte Aenderung	MA 20. Jan. 98
|*
|*************************************************************************/

void SwFlyFrm::ChainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
{
	ASSERT( pMaster && pFollow, "uncomplete chain" );
	ASSERT( !pMaster->GetNextLink(), "link can not be changed" );
	ASSERT( !pFollow->GetPrevLink(), "link can not be changed" );

	pMaster->pNextLink = pFollow;
	pFollow->pPrevLink = pMaster;

	if ( pMaster->ContainsCntnt() )
	{
		//Damit ggf. ein Textfluss zustande kommt muss invalidiert werden.
		SwFrm *pInva = pMaster->FindLastLower();
        SWRECTFN( pMaster )
        const long nBottom = (pMaster->*fnRect->fnGetPrtBottom)();
		while ( pInva )
		{
            if( (pInva->Frm().*fnRect->fnBottomDist)( nBottom ) <= 0 )
			{
				pInva->InvalidateSize();
				pInva->Prepare( PREP_CLEAR );
				pInva = pInva->FindPrev();
			}
			else
				pInva = 0;
		}
	}

	if ( pFollow->ContainsCntnt() )
	{
		//Es gibt nur noch den Inhalt des Masters, der Inhalt vom Follow
		//hat keine Frames mehr (sollte immer nur genau ein leerer TxtNode sein).
		SwFrm *pFrm = pFollow->ContainsCntnt();
		ASSERT( !pFrm->IsTabFrm() && !pFrm->FindNext(), "follow in chain contains content" );
		pFrm->Cut();
		delete pFrm;
	}

    // invalidate accessible relation set (accessibility wrapper)
    ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
    if( pSh )
    {
        SwRootFrm* pLayout = pMaster->getRootFrm();
        if( pLayout && pLayout->IsAnyShellAccessible() )
        pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
    }
}

void SwFlyFrm::UnchainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
{
	pMaster->pNextLink = 0;
	pFollow->pPrevLink = 0;

	if ( pFollow->ContainsCntnt() )
	{
		//Der Master saugt den Inhalt vom Follow auf
		SwLayoutFrm *pUpper = pMaster;
		if ( pUpper->Lower()->IsColumnFrm() )
		{
            pUpper = static_cast<SwLayoutFrm*>(pUpper->GetLastLower());
            pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower()); // der (Column)BodyFrm
			ASSERT( pUpper && pUpper->IsColBodyFrm(), "Missing ColumnBody" );
		}
		SwFlyFrm *pFoll = pFollow;
		while ( pFoll )
		{
			SwFrm *pTmp = ::SaveCntnt( pFoll );
			if ( pTmp )
                ::RestoreCntnt( pTmp, pUpper, pMaster->FindLastLower(), true );
            pFoll->SetCompletePaint();
			pFoll->InvalidateSize();
			pFoll = pFoll->GetNextLink();
		}
	}

	//Der Follow muss mit seinem eigenen Inhalt versorgt werden.
	const SwFmtCntnt &rCntnt = pFollow->GetFmt()->GetCntnt();
	ASSERT( rCntnt.GetCntntIdx(), ":-( Kein Inhalt vorbereitet." );
	sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
	// Lower() bedeutet SwColumnFrm, dieser beinhaltet wieder einen SwBodyFrm
	::_InsertCnt( pFollow->Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)pFollow->Lower())->Lower()
								   : (SwLayoutFrm*)pFollow,
				  pFollow->GetFmt()->GetDoc(), ++nIndex );

    // invalidate accessible relation set (accessibility wrapper)
    ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
    if( pSh )
    {
        SwRootFrm* pLayout = pMaster->getRootFrm();
        if( pLayout && pLayout->IsAnyShellAccessible() )
        pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
}
}

/*************************************************************************
|*
|*	SwFlyFrm::FindChainNeighbour()
|*
|*	Ersterstellung		MA 11. Nov. 97
|*	Letzte Aenderung	MA 09. Apr. 99
|*
|*************************************************************************/

SwFlyFrm *SwFlyFrm::FindChainNeighbour( SwFrmFmt &rChain, SwFrm *pAnch )
{
	//Wir suchen denjenigen Fly, der in dem selben Bereich steht.
	//Bereiche koennen zunaechst nur Kopf-/Fusszeilen oder Flys sein.

	if ( !pAnch )			//Wenn ein Anchor uebergeben Wurde zaehlt dieser: Ctor!
        pAnch = AnchorFrm();

	SwLayoutFrm *pLay;
	if ( pAnch->IsInFly() )
		pLay = pAnch->FindFlyFrm();
	else
	{
		//FindFooterOrHeader taugt hier nicht, weil evtl. noch keine Verbindung
		//zum Anker besteht.
		pLay = pAnch->GetUpper();
		while ( pLay && !(pLay->GetType() & (FRM_HEADER|FRM_FOOTER)) )
			pLay = pLay->GetUpper();
	}

	SwIterator<SwFlyFrm,SwFmt> aIter( rChain );
	SwFlyFrm *pFly = aIter.First();
	if ( pLay )
	{
		while ( pFly )
		{
            if ( pFly->GetAnchorFrm() )
			{
                if ( pFly->GetAnchorFrm()->IsInFly() )
				{
                    if ( pFly->AnchorFrm()->FindFlyFrm() == pLay )
						break;
				}
				else if ( pLay == pFly->FindFooterOrHeader() )
					break;
			}
			pFly = aIter.Next();
		}
	}
	else if ( pFly )
	{
		ASSERT( !aIter.Next(), "chain with more than one inkarnation" );
	}
	return pFly;
}


/*************************************************************************
|*
|*	SwFlyFrm::FindLastLower()
|*
|*	Ersterstellung		MA 29. Oct. 97
|*	Letzte Aenderung	MA 29. Oct. 97
|*
|*************************************************************************/

SwFrm *SwFlyFrm::FindLastLower()
{
	SwFrm *pRet = ContainsAny();
	if ( pRet && pRet->IsInTab() )
		pRet = pRet->FindTabFrm();
	SwFrm *pNxt = pRet;
	while ( pNxt && IsAnLower( pNxt ) )
	{	pRet = pNxt;
		pNxt = pNxt->FindNext();
	}
	return pRet;
}


/*************************************************************************
|*
|*	SwFlyFrm::FrmSizeChg()
|*
|*	Ersterstellung		MA 17. Dec. 92
|*	Letzte Aenderung	MA 24. Jul. 96
|*
|*************************************************************************/

sal_Bool SwFlyFrm::FrmSizeChg( const SwFmtFrmSize &rFrmSize )
{
	sal_Bool bRet = sal_False;
	SwTwips nDiffHeight = Frm().Height();
    if ( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE )
        bFixSize = bMinHeight = sal_False;
	else
	{
        if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
        {
            bFixSize = sal_True;
			bMinHeight = sal_False;
		}
        else if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
        {
            bFixSize = sal_False;
			bMinHeight = sal_True;
		}
		nDiffHeight -= rFrmSize.GetHeight();
	}
	//Wenn der Fly Spalten enthaehlt muessen der Fly und
	//die Spalten schon einmal auf die Wunschwerte gebracht
	//werden, sonst haben wir ein kleines Problem.
	if ( Lower() )
	{
		if ( Lower()->IsColumnFrm() )
		{
            const SwRect aOld( GetObjRectWithSpaces() );
			const Size	 aOldSz( Prt().SSize() );
			const SwTwips nDiffWidth = Frm().Width() - rFrmSize.GetWidth();
			aFrm.Height( aFrm.Height() - nDiffHeight );
			aFrm.Width ( aFrm.Width()  - nDiffWidth  );
            // --> OD 2006-08-16 #i68520#
            InvalidateObjRectWithSpaces();
            // <--
			aPrt.Height( aPrt.Height() - nDiffHeight );
			aPrt.Width ( aPrt.Width()  - nDiffWidth  );
			ChgLowersProp( aOldSz );
			::Notify( this, FindPageFrm(), aOld );
			bValidPos = sal_False;
			bRet = sal_True;
		}
		else if ( Lower()->IsNoTxtFrm() )
		{
            bFixSize = sal_True;
			bMinHeight = sal_False;
		}
	}
	return bRet;
}

/*************************************************************************
|*
|*	SwFlyFrm::Modify()
|*
|*	Ersterstellung		MA 17. Dec. 92
|*	Letzte Aenderung	MA 17. Jan. 97
|*
|*************************************************************************/

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

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

	if ( nInvFlags != 0 )
	{
		_Invalidate();
		if ( nInvFlags & 0x01 )
        {
			_InvalidatePos();
            // --> OD 2006-08-16 #i68520#
            InvalidateObjRectWithSpaces();
            // <--
        }
		if ( nInvFlags & 0x02 )
        {
			_InvalidateSize();
            // --> OD 2006-08-16 #i68520#
            InvalidateObjRectWithSpaces();
            // <--
        }
        if ( nInvFlags & 0x04 )
			_InvalidatePrt();
		if ( nInvFlags & 0x08 )
			SetNotifyBack();
		if ( nInvFlags & 0x10 )
			SetCompletePaint();
		if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTxtFrm() )
            ClrContourCache( GetVirtDrawObj() );
		SwRootFrm *pRoot;
		if ( nInvFlags & 0x20 && 0 != (pRoot = getRootFrm()) )
			pRoot->InvalidateBrowseWidth();
        // --> OD 2004-06-28 #i28701#
        if ( nInvFlags & 0x80 )
        {
            // update sorted object lists, the Writer fly frame is registered at.
            UpdateObjInSortedList();
        }
        // <--
        // --> OD #i87645# - reset flags for the layout process (only if something has been invalidated)
        ResetLayoutProcessBools();
        // <--
	}
}

void SwFlyFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
							sal_uInt8 &rInvFlags,
							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
{
	sal_Bool bClear = sal_True;
	const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
	ViewShell *pSh = getRootFrm()->GetCurrShell();
	switch( nWhich )
	{
        case RES_VERT_ORIENT:
		case RES_HORI_ORIENT:
        // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
        case RES_FOLLOW_TEXT_FLOW:
        {
            //Achtung! _immer_ Aktion in ChgRePos() mitpflegen.
			rInvFlags |= 0x09;
        }
        break;
        // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
        case RES_WRAP_INFLUENCE_ON_OBJPOS:
        {
            rInvFlags |= 0x89;
        }
        break;
        case RES_SURROUND:
        {
            // OD 2004-05-13 #i28701# - invalidate position on change of
            // wrapping style.
            //rInvFlags |= 0x40;
            rInvFlags |= 0x41;
			//Der Hintergrund muss benachrichtigt und Invalidiert werden.
            const SwRect aTmp( GetObjRectWithSpaces() );
			NotifyBackground( FindPageFrm(), aTmp, PREP_FLY_ATTR_CHG );

			// Durch eine Umlaufaenderung von rahmengebundenen Rahmen kann eine
			// vertikale Ausrichtung aktiviert/deaktiviert werden => MakeFlyPos
			if( FLY_AT_FLY == GetFmt()->GetAnchor().GetAnchorId() )
				rInvFlags |= 0x09;

			//Ggf. die Kontur am Node loeschen.
			if ( Lower() && Lower()->IsNoTxtFrm() &&
				 !GetFmt()->GetSurround().IsContour() )
			{
				SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
				if ( pNd->HasContour() )
					pNd->SetContour( 0 );
			}
            // --> OD 2004-06-28 #i28701# - perform reorder of object lists
            // at anchor frame and at page frame.
            rInvFlags |= 0x80;
        }
        break;

		case RES_PROTECT:
			{
			const SvxProtectItem *pP = (SvxProtectItem*)pNew;
            GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected()   );
            GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
            if( pSh )
            {
                SwRootFrm* pLayout = getRootFrm();
                if( pLayout && pLayout->IsAnyShellAccessible() )
				pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
            }
			break;
			}

		case RES_COL:
			{
				ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
				const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
				if ( FrmSizeChg( rNew ) )
					NotifyDrawObj();
				rInvFlags |= 0x1A;
				break;
			}

		case RES_FRM_SIZE:
		case RES_FMT_CHG:
		{
			const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
			if ( FrmSizeChg( rNew ) )
				NotifyDrawObj();
			rInvFlags |= 0x7F;
			if ( RES_FMT_CHG == nWhich )
			{
                SwRect aNew( GetObjRectWithSpaces() );
				SwRect aOld( aFrm );
				const SvxULSpaceItem &rUL = ((SwFmtChg*)pOld)->pChangedFmt->GetULSpace();
				aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
				aOld.SSize().Height()+= rUL.GetLower();
				const SvxLRSpaceItem &rLR = ((SwFmtChg*)pOld)->pChangedFmt->GetLRSpace();
				aOld.Left  ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
				aOld.SSize().Width() += rLR.GetRight();
				aNew.Union( aOld );
				NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );

				//Dummer Fall. Bei der Zusweisung einer Vorlage k?nnen wir uns
				//nicht auf das alte Spaltenattribut verlassen. Da diese
				//wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
				//bleibt uns nur einen temporaeres Attribut zu basteln.
				SwFmtCol aCol;
				if ( Lower() && Lower()->IsColumnFrm() )
				{
					sal_uInt16 nCol = 0;
					SwFrm *pTmp = Lower();
					do
					{	++nCol;
						pTmp = pTmp->GetNext();
					} while ( pTmp );
					aCol.Init( nCol, 0, 1000 );
				}
				ChgColumns( aCol, GetFmt()->GetCol() );
			}

			SwFmtURL aURL( GetFmt()->GetURL() );
			if ( aURL.GetMap() )
			{
				const SwFmtFrmSize &rOld = nWhich == RES_FRM_SIZE ?
								*(SwFmtFrmSize*)pNew :
								((SwFmtChg*)pOld)->pChangedFmt->GetFrmSize();
				//#35091# Kann beim Laden von Vorlagen mal 0 sein
				if ( rOld.GetWidth() && rOld.GetHeight() )
				{

					Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
					Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
					aURL.GetMap()->Scale( aScaleX, aScaleY );
					SwFrmFmt *pFmt = GetFmt();
					pFmt->LockModify();
                    pFmt->SetFmtAttr( aURL );
					pFmt->UnlockModify();
				}
			}
			const SvxProtectItem &rP = GetFmt()->GetProtect();
            GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected()    );
            GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );

			if ( pSh )
				pSh->InvalidateWindows( Frm() );
            const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
			const sal_uInt8 nId = GetFmt()->GetOpaque().GetValue() ?
                             pIDDMA->GetHeavenId() :
                             pIDDMA->GetHellId();
            GetVirtDrawObj()->SetLayer( nId );

			if ( Lower() )
			{
				//Ggf. die Kontur am Node loeschen.
				if( Lower()->IsNoTxtFrm() &&
					 !GetFmt()->GetSurround().IsContour() )
				{
					SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
					if ( pNd->HasContour() )
						pNd->SetContour( 0 );
				}
				else if( !Lower()->IsColumnFrm() )
				{
                    SwFrm* pFrm = GetLastLower();
                    if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
						pFrm->Prepare( PREP_ADJUST_FRM );
				}
			}

            // --> OD 2004-06-28 #i28701# - perform reorder of object lists
            // at anchor frame and at page frame.
            rInvFlags |= 0x80;

            break;
		}
		case RES_UL_SPACE:
		case RES_LR_SPACE:
        {
            rInvFlags |= 0x41;
            if( pSh && pSh->GetViewOptions()->getBrowseMode() )
				getRootFrm()->InvalidateBrowseWidth();
            SwRect aNew( GetObjRectWithSpaces() );
			SwRect aOld( aFrm );
			if ( RES_UL_SPACE == nWhich )
			{
				const SvxULSpaceItem &rUL = *(SvxULSpaceItem*)pNew;
				aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
				aOld.SSize().Height()+= rUL.GetLower();
			}
			else
			{
				const SvxLRSpaceItem &rLR = *(SvxLRSpaceItem*)pNew;
				aOld.Left  ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
				aOld.SSize().Width() += rLR.GetRight();
			}
			aNew.Union( aOld );
			NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );
        }
        break;

		case RES_BOX:
		case RES_SHADOW:
			rInvFlags |= 0x17;
			break;

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

        case RES_OPAQUE:
            {
                if ( pSh )
                    pSh->InvalidateWindows( Frm() );

                const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
                const sal_uInt8 nId = ((SvxOpaqueItem*)pNew)->GetValue() ?
                                    pIDDMA->GetHeavenId() :
                                    pIDDMA->GetHellId();
                GetVirtDrawObj()->SetLayer( nId );
                if( pSh )
                {
                    SwRootFrm* pLayout = getRootFrm();
                    if( pLayout && pLayout->IsAnyShellAccessible() )
                {
                    pSh->Imp()->DisposeAccessibleFrm( this );
                    pSh->Imp()->AddAccessibleFrm( this );
                }
                }
                // --> OD 2004-06-28 #i28701# - perform reorder of object lists
                // at anchor frame and at page frame.
                rInvFlags |= 0x80;
            }
			break;

		case RES_URL:
			//Das Interface arbeitet bei Textrahmen auf der Rahmengroesse,
			//die Map muss sich aber auf die FrmSize beziehen
			if ( (!Lower() || !Lower()->IsNoTxtFrm()) &&
				 ((SwFmtURL*)pNew)->GetMap() && ((SwFmtURL*)pOld)->GetMap() )
			{
				const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
				if ( rSz.GetHeight() != Frm().Height() ||
					 rSz.GetWidth()  != Frm().Width() )
				{
					SwFmtURL aURL( GetFmt()->GetURL() );
					Fraction aScaleX( Frm().Width(),  rSz.GetWidth() );
					Fraction aScaleY( Frm().Height(), rSz.GetHeight() );
					aURL.GetMap()->Scale( aScaleX, aScaleY );
					SwFrmFmt *pFmt = GetFmt();
					pFmt->LockModify();
                    pFmt->SetFmtAttr( aURL );
					pFmt->UnlockModify();
				}
			}
			/* Keine Invalidierung notwendig */
			break;

		case RES_CHAIN:
			{
				SwFmtChain *pChain = (SwFmtChain*)pNew;
				if ( pChain->GetNext() )
				{
					SwFlyFrm *pFollow = FindChainNeighbour( *pChain->GetNext() );
					if ( GetNextLink() && pFollow != GetNextLink() )
						SwFlyFrm::UnchainFrames( this, GetNextLink());
					if ( pFollow )
					{
						if ( pFollow->GetPrevLink() &&
							 pFollow->GetPrevLink() != this )
							SwFlyFrm::UnchainFrames( pFollow->GetPrevLink(),
													 pFollow );
						if ( !GetNextLink() )
							SwFlyFrm::ChainFrames( this, pFollow );
					}
				}
				else if ( GetNextLink() )
					SwFlyFrm::UnchainFrames( this, GetNextLink() );
				if ( pChain->GetPrev() )
				{
					SwFlyFrm *pMaster = FindChainNeighbour( *pChain->GetPrev() );
					if ( GetPrevLink() && pMaster != GetPrevLink() )
						SwFlyFrm::UnchainFrames( GetPrevLink(), this );
					if ( pMaster )
					{
						if ( pMaster->GetNextLink() &&
							 pMaster->GetNextLink() != this )
							SwFlyFrm::UnchainFrames( pMaster,
													 pMaster->GetNextLink() );
						if ( !GetPrevLink() )
							SwFlyFrm::ChainFrames( pMaster, this );
					}
				}
				else if ( GetPrevLink() )
					SwFlyFrm::UnchainFrames( GetPrevLink(), this );
			}

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

/*************************************************************************
|*
|*				  SwFlyFrm::GetInfo()
|*
|*	  Beschreibung		erfragt Informationen
|*	  Ersterstellung	JP 31.03.94
|*	  Letzte Aenderung	JP 31.03.94
|*
*************************************************************************/

	// erfrage vom Modify Informationen
sal_Bool SwFlyFrm::GetInfo( SfxPoolItem & rInfo ) const
{
	if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
		return sal_False;	// es gibt einen FlyFrm also wird er benutzt
	return sal_True;		// weiter suchen
}

/*************************************************************************
|*
|*	SwFlyFrm::_Invalidate()
|*
|*	Ersterstellung		MA 15. Oct. 92
|*	Letzte Aenderung	MA 26. Jun. 96
|*
|*************************************************************************/

void SwFlyFrm::_Invalidate( SwPageFrm *pPage )
{
	InvalidatePage( pPage );
	bNotifyBack = bInvalid = sal_True;

	SwFlyFrm *pFrm;
    if ( GetAnchorFrm() && 0 != (pFrm = AnchorFrm()->FindFlyFrm()) )
	{
		//Gaanz dumm: Wenn der Fly innerhalb eines Fly gebunden ist, der
		//Spalten enthaehlt, sollte das Format von diesem ausgehen.
		if ( !pFrm->IsLocked() && !pFrm->IsColLocked() &&
			 pFrm->Lower() && pFrm->Lower()->IsColumnFrm() )
			pFrm->InvalidateSize();
	}

    // --> OD 2008-01-21 #i85216#
    // if vertical position is oriented at a layout frame inside a ghost section,
    // assure that the position is invalidated and that the information about
    // the vertical position oriented frame is cleared
    if ( GetVertPosOrientFrm() && GetVertPosOrientFrm()->IsLayoutFrm() )
    {
        const SwSectionFrm* pSectFrm( GetVertPosOrientFrm()->FindSctFrm() );
        if ( pSectFrm && pSectFrm->GetSection() == 0 )
        {
            InvalidatePos();
            ClearVertPosOrientFrm();
        }
    }
    // <--
}

/*************************************************************************
|*
|*	SwFlyFrm::ChgRelPos()
|*
|*	Beschreibung		Aenderung der relativen Position, die Position wird
|*		damit automatisch Fix, das Attribut wird entprechend angepasst.
|*	Ersterstellung		MA 25. Aug. 92
|*	Letzte Aenderung	MA 09. Aug. 95
|*
|*************************************************************************/

void SwFlyFrm::ChgRelPos( const Point &rNewPos )
{
    if ( GetCurrRelPos() != rNewPos )
	{
		SwFrmFmt *pFmt = GetFmt();
        const bool bVert = GetAnchorFrm()->IsVertical();
        const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
        SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
        if( bVert )
            nTmpY = -nTmpY;
		SfxItemSet aSet( pFmt->GetDoc()->GetAttrPool(),
						 RES_VERT_ORIENT, RES_HORI_ORIENT);

		SwFmtVertOrient aVert( pFmt->GetVertOrient() );
		SwTxtFrm *pAutoFrm = NULL;
        // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
        // Writer fly frames
        const RndStdIds eAnchorType = GetFrmFmt().GetAnchor().GetAnchorId();
        if ( eAnchorType == FLY_AT_PAGE )
        {
            aVert.SetVertOrient( text::VertOrientation::NONE );
            aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
        }
        else if ( eAnchorType == FLY_AT_FLY )
        {
            aVert.SetVertOrient( text::VertOrientation::NONE );
            aVert.SetRelationOrient( text::RelOrientation::FRAME );
        }
        // <--
        else if ( IsFlyAtCntFrm() || text::VertOrientation::NONE != aVert.GetVertOrient() )
		{
            if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
			{
                if( LONG_MAX != nNewY )
				{
                    aVert.SetVertOrient( text::VertOrientation::NONE );
					xub_StrLen nOfs =
						pFmt->GetAnchor().GetCntntAnchor()->nContent.GetIndex();
                    ASSERT( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected" );
                    pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
					while( pAutoFrm->GetFollow() &&
						   pAutoFrm->GetFollow()->GetOfst() <= nOfs )
					{
                        if( pAutoFrm == GetAnchorFrm() )
							nTmpY += pAutoFrm->GetRelPos().Y();
						nTmpY -= pAutoFrm->GetUpper()->Prt().Height();
						pAutoFrm = pAutoFrm->GetFollow();
					}
					nTmpY = ((SwFlyAtCntFrm*)this)->GetRelCharY(pAutoFrm)-nTmpY;
				}
				else
                    aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
			}
			else
			{
                aVert.SetVertOrient( text::VertOrientation::NONE );
                aVert.SetRelationOrient( text::RelOrientation::FRAME );
			}
		}
		aVert.SetPos( nTmpY );
		aSet.Put( aVert );

        //Fuer Flys im Cnt ist die horizontale Ausrichtung uninteressant,
		//den sie ist stets 0.
		if ( !IsFlyInCntFrm() )
		{
            const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
            SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
			SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
            // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
            // Writer fly frames
            if ( eAnchorType == FLY_AT_PAGE )
            {
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
                aHori.SetPosToggle( sal_False );
            }
            else if ( eAnchorType == FLY_AT_FLY )
            {
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                aHori.SetRelationOrient( text::RelOrientation::FRAME );
                aHori.SetPosToggle( sal_False );
            }
            // <--
            else if ( IsFlyAtCntFrm() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
			{
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
				{
                    if( LONG_MAX != nNewX )
					{
						if( !pAutoFrm )
						{
							xub_StrLen nOfs = pFmt->GetAnchor().GetCntntAnchor()
										  ->nContent.GetIndex();
                            ASSERT( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected");
                            pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
							while( pAutoFrm->GetFollow() &&
								   pAutoFrm->GetFollow()->GetOfst() <= nOfs )
								pAutoFrm = pAutoFrm->GetFollow();
						}
						nTmpX -= ((SwFlyAtCntFrm*)this)->GetRelCharX(pAutoFrm);
					}
				}
				else
                    aHori.SetRelationOrient( text::RelOrientation::FRAME );
				aHori.SetPosToggle( sal_False );
			}
			aHori.SetPos( nTmpX );
			aSet.Put( aHori );
		}
        SetCurrRelPos( rNewPos );
		pFmt->GetDoc()->SetAttr( aSet, *pFmt );
	}
}
/*************************************************************************
|*
|*	SwFlyFrm::Format()
|*
|*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea.
|*						Die Fixsize wird hier nicht eingestellt.
|*	Ersterstellung		MA 14. Jun. 93
|*	Letzte Aenderung	MA 13. Jun. 96
|*
|*************************************************************************/

void SwFlyFrm::Format( const SwBorderAttrs *pAttrs )
{
	ASSERT( pAttrs, "FlyFrm::Format, pAttrs ist 0." );

	ColLock();

	if ( !bValidSize )
	{
		if ( Frm().Top() == WEIT_WECH && Frm().Left() == WEIT_WECH )
        {
			//Sicherheitsschaltung wegnehmen (siehe SwFrm::CTor)
			Frm().Pos().X() = Frm().Pos().Y() = 0;
            // --> OD 2006-08-16 #i68520#
            InvalidateObjRectWithSpaces();
            // <--
        }

		//Breite der Spalten pruefen und ggf. einstellen.
		if ( Lower() && Lower()->IsColumnFrm() )
			AdjustColumns( 0, sal_False );

		bValidSize = sal_True;

        const SwTwips nUL = pAttrs->CalcTopLine()  + pAttrs->CalcBottomLine();
        const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
        const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize();
              Size aRelSize( CalcRel( rFrmSz ) );

        ASSERT( pAttrs->GetSize().Height() != 0 || rFrmSz.GetHeightPercent(), "Hoehe des RahmenAttr ist 0." );
        ASSERT( pAttrs->GetSize().Width()  != 0 || rFrmSz.GetWidthPercent(), "Breite des RahmenAttr ist 0." );

        SWRECTFN( this )
        if( !HasFixSize() )
		{
            SwTwips nRemaining = 0;

            long nMinHeight = 0;
            if( IsMinHeight() )
                nMinHeight = bVert ? aRelSize.Width() : aRelSize.Height();

            if ( Lower() )
			{
				if ( Lower()->IsColumnFrm() )
				{
					FormatWidthCols( *pAttrs, nUL, nMinHeight );
                    nRemaining = (Lower()->Frm().*fnRect->fnGetHeight)();
				}
				else
				{
					SwFrm *pFrm = Lower();
					while ( pFrm )
                    {
                        nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
						if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
							// Dieser TxtFrm waere gern ein bisschen groesser
							nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
                                    - (pFrm->Prt().*fnRect->fnGetHeight)();
						else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
							nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
						pFrm = pFrm->GetNext();
					}
                    // --> OD 2006-02-09 #130878#
                    // Do not keep old height, if content has no height.
                    // The old height could be wrong due to wrong layout cache
                    // and isn't corrected in the further formatting, because
                    // the fly frame doesn't become invalid anymore.
//                    if( !nRemaining )
//                        nRemaining = nOldHeight - nUL;
                    // <--
				}
				if ( GetDrawObjs() )
				{
                    sal_uInt32 nCnt = GetDrawObjs()->Count();
                    SwTwips nTop = (Frm().*fnRect->fnGetTop)();
                    SwTwips nBorder = (Frm().*fnRect->fnGetHeight)() -
                                      (Prt().*fnRect->fnGetHeight)();
					for ( sal_uInt16 i = 0; i < nCnt; ++i )
					{
                        SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
                        if ( pAnchoredObj->ISA(SwFlyFrm) )
						{
                            SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
                            // OD 06.11.2003 #i22305# - consider
                            // only Writer fly frames, which follow the text flow.
                            if ( pFly->IsFlyLayFrm() &&
                                 pFly->Frm().Top() != WEIT_WECH &&
                                 pFly->GetFmt()->GetFollowTextFlow().GetValue() )
							{
                                SwTwips nDist = -(pFly->Frm().*fnRect->
                                    fnBottomDist)( nTop );
                                if( nDist > nBorder + nRemaining )
                                    nRemaining = nDist - nBorder;
							}
						}
					}
				}
			}

            if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
				nRemaining = nMinHeight - nUL;
			//Weil das Grow/Shrink der Flys die Groessen nicht direkt
			//einstellt, sondern indirekt per Invalidate ein Format
			//ausloesst, muessen die Groessen hier direkt eingestellt
			//werden. Benachrichtung laeuft bereits mit.
			//Weil bereits haeufiger 0en per Attribut hereinkamen wehre
			//ich mich ab sofort dagegen.
			if ( nRemaining < MINFLY )
				nRemaining = MINFLY;
            (Prt().*fnRect->fnSetHeight)( nRemaining );
            nRemaining -= (Frm().*fnRect->fnGetHeight)();
            (Frm().*fnRect->fnAddBottom)( nRemaining + nUL );
            // --> OD 2006-08-16 #i68520#
            if ( nRemaining + nUL != 0 )
            {
                InvalidateObjRectWithSpaces();
            }
            // <--
			bValidSize = sal_True;
		}
		else
		{
			bValidSize = sal_True;	//Fixe Frms formatieren sich nicht.
								//Flys stellen ihre Groesse anhand des Attr ein.
            SwTwips nNewSize = bVert ? aRelSize.Width() : aRelSize.Height();
            nNewSize -= nUL;
            if( nNewSize < MINFLY )
                nNewSize = MINFLY;
            (Prt().*fnRect->fnSetHeight)( nNewSize );
            nNewSize += nUL - (Frm().*fnRect->fnGetHeight)();
            (Frm().*fnRect->fnAddBottom)( nNewSize );
            // --> OD 2006-08-16 #i68520#
            if ( nNewSize != 0 )
            {
                InvalidateObjRectWithSpaces();
            }
            // <--
        }

		if ( !bFormatHeightOnly )
		{
            ASSERT( aRelSize == CalcRel( rFrmSz ), "SwFlyFrm::Format CalcRel problem" )
            SwTwips nNewSize = bVert ? aRelSize.Height() : aRelSize.Width();

            if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
            {
                // #i9046# Autowidth for fly frames
                const SwTwips nAutoWidth = CalcAutoWidth();
                if ( nAutoWidth )
                {
                    if( ATT_MIN_SIZE == rFrmSz.GetWidthSizeType() )
                        nNewSize = Max( nNewSize - nLR, nAutoWidth );
                    else
                        nNewSize = nAutoWidth;
                }
            }
            else
                nNewSize -= nLR;

            if( nNewSize < MINFLY )
                nNewSize = MINFLY;
            (Prt().*fnRect->fnSetWidth)( nNewSize );
            nNewSize += nLR - (Frm().*fnRect->fnGetWidth)();
            (Frm().*fnRect->fnAddRight)( nNewSize );
            // --> OD 2006-08-16 #i68520#
            if ( nNewSize != 0 )
            {
                InvalidateObjRectWithSpaces();
            }
            // <--
        }
	}
	ColUnlock();
}

// OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
//                          default value = false.
// OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
//                          default value = false.
// OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
//                          <FormatWidthCols(..)> to avoid follow formatting
//                          for text frames. But, unformatted follows causes
//                          problems in method <SwCntntFrm::_WouldFit(..)>,
//                          which assumes that the follows are formatted.
//                          Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
//void CalcCntnt( SwLayoutFrm *pLay, sal_Bool bNoColl )
void CalcCntnt( SwLayoutFrm *pLay,
                bool bNoColl,
                bool bNoCalcFollow )
{
	SwSectionFrm* pSect;
	sal_Bool bCollect = sal_False;
	if( pLay->IsSctFrm() )
	{
		pSect = (SwSectionFrm*)pLay;
		if( pSect->IsEndnAtEnd() && !bNoColl )
		{
			bCollect = sal_True;
			SwLayouter::CollectEndnotes( pLay->GetFmt()->GetDoc(), pSect );
		}
		pSect->CalcFtnCntnt();
	}
	else
		pSect = NULL;
	SwFrm *pFrm = pLay->ContainsAny();
	if ( !pFrm )
	{
		if( pSect )
		{
			if( pSect->HasFollow() )
				pFrm = pSect->GetFollow()->ContainsAny();
			if( !pFrm )
			{
				if( pSect->IsEndnAtEnd() )
				{
					if( bCollect )
						pLay->GetFmt()->GetDoc()->GetLayouter()->
							InsertEndnotes( pSect );
					sal_Bool bLock = pSect->IsFtnLock();
					pSect->SetFtnLock( sal_True );
					pSect->CalcFtnCntnt();
					pSect->CalcFtnCntnt();
					pSect->SetFtnLock( bLock );
				}
				return;
			}
			pFrm->_InvalidatePos();
		}
		else
			return;
	}
	pFrm->InvalidatePage();

	do
	{
        // local variables to avoid loops caused by anchored object positioning
        SwAnchoredObject* pAgainObj1 = 0;
        SwAnchoredObject* pAgainObj2 = 0;

        // FME 2007-08-30 #i81146# new loop control
        sal_uInt16 nLoopControlRuns = 0;
        const sal_uInt16 nLoopControlMax = 20;
        const SwFrm* pLoopControlCond = 0;

        SwFrm* pLast;
		do
		{
			pLast = pFrm;
            if( pFrm->IsVertical() ?
                ( pFrm->GetUpper()->Prt().Height() != pFrm->Frm().Height() )
                : ( pFrm->GetUpper()->Prt().Width() != pFrm->Frm().Width() ) )
			{
				pFrm->Prepare( PREP_FIXSIZE_CHG );
				pFrm->_InvalidateSize();
			}

			if ( pFrm->IsTabFrm() )
			{
				((SwTabFrm*)pFrm)->bCalcLowers = sal_True;
                // OD 26.08.2003 #i18103# - lock move backward of follow table,
                // if no section content is formatted or follow table belongs
                // to the section, which content is formatted.
                if ( ((SwTabFrm*)pFrm)->IsFollow() &&
                     ( !pSect || pSect == pFrm->FindSctFrm() ) )
                {
					((SwTabFrm*)pFrm)->bLockBackMove = sal_True;
                }
			}

            // OD 14.03.2003 #i11760# - forbid format of follow, if requested.
            if ( bNoCalcFollow && pFrm->IsTxtFrm() )
                static_cast<SwTxtFrm*>(pFrm)->ForbidFollowFormat();

            pFrm->Calc();

            // OD 14.03.2003 #i11760# - reset control flag for follow format.
            if ( pFrm->IsTxtFrm() )
            {
                static_cast<SwTxtFrm*>(pFrm)->AllowFollowFormat();
            }

            // #111937# The keep-attribute can cause the position
            // of the prev to be invalid:
            // OD 2004-03-15 #116560# - Do not consider invalid previous frame
            // due to its keep-attribute, if current frame is a follow or is locked.
            // --> OD 2005-03-08 #i44049# - do not consider invalid previous
            // frame due to its keep-attribute, if it can't move forward.
            // --> OD 2006-01-27 #i57765# - do not consider invalid previous
            // frame, if current frame has a column/page break before attribute.
            SwFrm* pTmpPrev = pFrm->FindPrev();
            SwFlowFrm* pTmpPrevFlowFrm = pTmpPrev && pTmpPrev->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pTmpPrev) : 0;
            SwFlowFrm* pTmpFlowFrm     = pFrm->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pFrm) : 0;

            bool bPrevInvalid = pTmpPrevFlowFrm && pTmpFlowFrm &&
                               !pTmpFlowFrm->IsFollow() &&
                               !StackHack::IsLocked() && // #i76382#
                               !pTmpFlowFrm->IsJoinLocked() &&
                               !pTmpPrev->GetValidPosFlag() &&
                                pLay->IsAnLower( pTmpPrev ) &&
                                pTmpPrevFlowFrm->IsKeep( *pTmpPrev->GetAttrSet() ) &&
                                pTmpPrevFlowFrm->IsKeepFwdMoveAllowed();
            // <--

            // format floating screen objects anchored to the frame.
            bool bRestartLayoutProcess = false;
            if ( !bPrevInvalid && pFrm->GetDrawObjs() && pLay->IsAnLower( pFrm ) )
			{
                bool bAgain = false;
                SwPageFrm* pPageFrm = pFrm->FindPageFrm();
                sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
				for ( sal_uInt16 i = 0; i < nCnt; ++i )
				{
                    // --> OD 2004-07-01 #i28701#
                    SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
                    // determine, if anchored object has to be formatted.
                    if ( pAnchoredObj->PositionLocked() )
                    {
                        continue;
                    }

                    // format anchored object
                    if ( pAnchoredObj->IsFormatPossible() )
                    {
                        // --> OD 2005-05-17 #i43737# - no invalidation of
                        // anchored object needed - causes loops for as-character
                        // anchored objects.
                        //pAnchoredObj->InvalidateObjPos();
                        // <--
                        SwRect aRect( pAnchoredObj->GetObjRect() );
                        if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrm, pPageFrm ) )
                        {
                            bRestartLayoutProcess = true;
                            break;
                        }
                        // --> OD 2004-08-25 #i3317# - restart layout process,
                        // if the position of the anchored object is locked now.
                        if ( pAnchoredObj->PositionLocked() )
                        {
                            bRestartLayoutProcess = true;
                            break;
                        }
                        // <--

                        if ( aRect != pAnchoredObj->GetObjRect() )
                        {
                            bAgain = true;
                            if ( pAgainObj2 == pAnchoredObj )
                            {
                                ASSERT( false,
                                        "::CalcCntnt(..) - loop detected, perform attribute changes to avoid the loop" );
                                //Oszillation unterbinden.
                                SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
                                SwFmtSurround aAttr( rFmt.GetSurround() );
                                if( SURROUND_THROUGHT != aAttr.GetSurround() )
                                {
                                    // Bei autopositionierten hilft manchmal nur
                                    // noch, auf Durchlauf zu schalten
                                    if ((rFmt.GetAnchor().GetAnchorId() ==
                                            FLY_AT_CHAR) &&
                                        (SURROUND_PARALLEL ==
                                            aAttr.GetSurround()))
                                    {
                                        aAttr.SetSurround( SURROUND_THROUGHT );
                                    }
                                    else
                                    {
                                        aAttr.SetSurround( SURROUND_PARALLEL );
                                    }
                                    rFmt.LockModify();
                                    rFmt.SetFmtAttr( aAttr );
                                    rFmt.UnlockModify();
                                }
                            }
                            else
                            {
                                if ( pAgainObj1 == pAnchoredObj )
                                    pAgainObj2 = pAnchoredObj;
                                pAgainObj1 = pAnchoredObj;
                            }
                        }

                        if ( !pFrm->GetDrawObjs() )
                            break;
                        if ( pFrm->GetDrawObjs()->Count() < nCnt )
                        {
                            --i;
                            --nCnt;
                        }
                    }
				}

                // --> OD 2004-06-11 #i28701# - restart layout process, if
                // requested by floating screen object formatting
                if ( bRestartLayoutProcess )
                {
                    pFrm = pLay->ContainsAny();
                    pAgainObj1 = 0L;
                    pAgainObj2 = 0L;
                    continue;
                }

                // OD 2004-05-17 #i28701# - format anchor frame after its objects
                // are formatted, if the wrapping style influence has to be considered.
                if ( pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
                {
                    pFrm->Calc();
                }
                // <--

                if ( bAgain )
				{
					pFrm = pLay->ContainsCntnt();
					if ( pFrm && pFrm->IsInTab() )
						pFrm = pFrm->FindTabFrm();
					if( pFrm && pFrm->IsInSct() )
					{
						SwSectionFrm* pTmp = pFrm->FindSctFrm();
						if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
							pFrm = pTmp;
					}

                    if ( pFrm == pLoopControlCond )
                        ++nLoopControlRuns;
                    else
                    {
                        nLoopControlRuns = 0;
                        pLoopControlCond = pFrm;
                    }

                    if ( nLoopControlRuns < nLoopControlMax )
                        continue;

#if OSL_DEBUG_LEVEL > 1
                    ASSERT( false, "LoopControl in CalcCntnt" )
#endif
				}
			}
			if ( pFrm->IsTabFrm() )
			{
				if ( ((SwTabFrm*)pFrm)->IsFollow() )
					((SwTabFrm*)pFrm)->bLockBackMove = sal_False;
			}

            pFrm = bPrevInvalid ? pTmpPrev : pFrm->FindNext();
            if( !bPrevInvalid && pFrm && pFrm->IsSctFrm() && pSect )
			{
				// Es koennen hier leere SectionFrms herumspuken
				while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
					pFrm = pFrm->FindNext();
				// Wenn FindNext den Follow des urspruenglichen Bereichs liefert,
				// wollen wir mit dessen Inhalt weitermachen, solange dieser
				// zurueckfliesst.
				if( pFrm && pFrm->IsSctFrm() && ( pFrm == pSect->GetFollow() ||
					((SwSectionFrm*)pFrm)->IsAnFollow( pSect ) ) )
				{
					pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
					if( pFrm )
						pFrm->_InvalidatePos();
				}
			}
			// Im pLay bleiben, Ausnahme, bei SectionFrms mit Follow wird der erste
			// CntntFrm des Follows anformatiert, damit er die Chance erhaelt, in
			// pLay zu landen. Solange diese Frames in pLay landen, geht's weiter.
        } while ( pFrm &&
                  ( pLay->IsAnLower( pFrm ) ||
                    ( pSect &&
                      ( ( pSect->HasFollow() &&
                          ( pLay->IsAnLower( pLast ) ||
                            ( pLast->IsInSct() &&
                              pLast->FindSctFrm()->IsAnFollow(pSect) ) ) &&
                          pSect->GetFollow()->IsAnLower( pFrm )  ) ||
                        ( pFrm->IsInSct() &&
                          pFrm->FindSctFrm()->IsAnFollow( pSect ) ) ) ) ) );
		if( pSect )
		{
			if( bCollect )
			{
				pLay->GetFmt()->GetDoc()->GetLayouter()->InsertEndnotes(pSect);
				pSect->CalcFtnCntnt();
			}
			if( pSect->HasFollow() )
			{
				SwSectionFrm* pNxt = pSect->GetFollow();
				while( pNxt && !pNxt->ContainsCntnt() )
					pNxt = pNxt->GetFollow();
				if( pNxt )
					pNxt->CalcFtnCntnt();
			}
			if( bCollect )
			{
				pFrm = pLay->ContainsAny();
				bCollect = sal_False;
				if( pFrm )
					continue;
			}
		}
		break;
	}
	while( sal_True );
}

/*************************************************************************
|*
|*	SwFlyFrm::MakeFlyPos()
|*
|*	Ersterstellung		MA ??
|*	Letzte Aenderung	MA 14. Nov. 96
|*
|*************************************************************************/
// OD 2004-03-23 #i26791#
//void SwFlyFrm::MakeFlyPos()
void SwFlyFrm::MakeObjPos()
{
    if ( !bValidPos )
    {
        bValidPos = sal_True;

        // OD 29.10.2003 #113049# - use new class to position object
        GetAnchorFrm()->Calc();
        objectpositioning::SwToLayoutAnchoredObjectPosition
                aObjPositioning( *GetVirtDrawObj() );
        aObjPositioning.CalcPosition();

        // --> OD 2006-10-05 #i58280#
        // update relative position
        SetCurrRelPos( aObjPositioning.GetRelPos() );
        // <--

        SWRECTFN( GetAnchorFrm() );
        aFrm.Pos( aObjPositioning.GetRelPos() );
        aFrm.Pos() += (GetAnchorFrm()->Frm().*fnRect->fnGetPos)();
        // --> OD 2006-09-11 #i69335#
        InvalidateObjRectWithSpaces();
        // <--
    }
}

/*************************************************************************
|*
|*	SwFlyFrm::MakePrtArea()
|*
|*	Ersterstellung		MA 23. Jun. 93
|*	Letzte Aenderung	MA 23. Jun. 93
|*
|*************************************************************************/
void SwFlyFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
{

	if ( !bValidPrtArea )
	{
		bValidPrtArea = sal_True;

        // OD 31.07.2003 #110978# - consider vertical layout
        SWRECTFN( this )
        (this->*fnRect->fnSetXMargins)( rAttrs.CalcLeftLine(),
                                        rAttrs.CalcRightLine() );
        (this->*fnRect->fnSetYMargins)( rAttrs.CalcTopLine(),
                                        rAttrs.CalcBottomLine() );
	}
}

/*************************************************************************
|*
|*	SwFlyFrm::_Grow(), _Shrink()
|*
|*	Ersterstellung		MA 05. Oct. 92
|*	Letzte Aenderung	MA 05. Sep. 96
|*
|*************************************************************************/

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

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

		if ( Lower()->IsColumnFrm() )
		{	//Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
			//das Wachstum (wg. des Ausgleichs).
			if ( !bTst )
            {
                // --> OD 2004-06-09 #i28701# - unlock position of Writer fly frame
                UnlockPosition();
                _InvalidatePos();
				InvalidateSize();
			}
			return 0L;
		}

		if ( !bTst )
		{
            const SwRect aOld( GetObjRectWithSpaces() );
			_InvalidateSize();
			const sal_Bool bOldLock = bLocked;
			Unlock();
            if ( IsFlyFreeFrm() )
            {
                // --> OD 2004-11-12 #i37068# - no format of position here
                // and prevent move in method <CheckClip(..)>.
                // This is needed to prevent layout loop caused by nested
                // Writer fly frames - inner Writer fly frames format its
                // anchor, which grows/shrinks the outer Writer fly frame.
                // Note: position will be invalidated below.
                bValidPos = sal_True;
                // --> OD 2005-10-10 #i55416#
                // Suppress format of width for autowidth frame, because the
                // format of the width would call <SwTxtFrm::CalcFitToContent()>
                // for the lower frame, which initiated this grow.
                const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
                const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
                if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
                {
                    bFormatHeightOnly = sal_True;
                }
                // <--
                static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
                ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
                static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
                // --> OD 2005-10-10 #i55416#
                if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
                {
                    bFormatHeightOnly = bOldFormatHeightOnly;
                }
                // <--
                // <--
            }
            else
				MakeAll();
			_InvalidateSize();
			InvalidatePos();
			if ( bOldLock )
				Lock();
            const SwRect aNew( GetObjRectWithSpaces() );
			if ( aOld != aNew )
				::Notify( this, FindPageFrm(), aOld );
            return (aNew.*fnRect->fnGetHeight)()-(aOld.*fnRect->fnGetHeight)();
		}
		return nDist;
	}
	return 0L;
}

SwTwips SwFlyFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
{
    if( Lower() && !IsColLocked() && !HasFixSize() && !IsNoShrink() )
	{
        SWRECTFN( this )
        SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
        if ( nDist > nHeight )
            nDist = nHeight;

        SwTwips nVal = nDist;
		if ( IsMinHeight() )
		{
            const SwFmtFrmSize& rFmtSize = GetFmt()->GetFrmSize();
            SwTwips nFmtHeight = bVert ? rFmtSize.GetWidth() : rFmtSize.GetHeight();

            nVal = Min( nDist, nHeight - nFmtHeight );
		}

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

		if ( Lower()->IsColumnFrm() )
		{	//Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
			//das Wachstum (wg. des Ausgleichs).
			if ( !bTst )
			{
                SwRect aOld( GetObjRectWithSpaces() );
                (Frm().*fnRect->fnSetHeight)( nHeight - nVal );
                // --> OD 2006-08-16 #i68520#
                if ( nHeight - nVal != 0 )
                {
                    InvalidateObjRectWithSpaces();
                }
                // <--
                nHeight = (Prt().*fnRect->fnGetHeight)();
                (Prt().*fnRect->fnSetHeight)( nHeight - nVal );
				_InvalidatePos();
				InvalidateSize();
				::Notify( this, FindPageFrm(), aOld );
				NotifyDrawObj();
                if ( GetAnchorFrm()->IsInFly() )
                    AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
			}
			return 0L;
		}

		if ( !bTst )
		{
            const SwRect aOld( GetObjRectWithSpaces() );
			_InvalidateSize();
			const sal_Bool bOldLocked = bLocked;
			Unlock();
            if ( IsFlyFreeFrm() )
            {
                // --> OD 2004-11-12 #i37068# - no format of position here
                // and prevent move in method <CheckClip(..)>.
                // This is needed to prevent layout loop caused by nested
                // Writer fly frames - inner Writer fly frames format its
                // anchor, which grows/shrinks the outer Writer fly frame.
                // Note: position will be invalidated below.
                bValidPos = sal_True;
                // --> OD 2005-10-10 #i55416#
                // Suppress format of width for autowidth frame, because the
                // format of the width would call <SwTxtFrm::CalcFitToContent()>
                // for the lower frame, which initiated this shrink.
                const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
                const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
                if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
                {
                    bFormatHeightOnly = sal_True;
                }
                // <--
                static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
                ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
                static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
                // --> OD 2005-10-10 #i55416#
                if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
                {
                    bFormatHeightOnly = bOldFormatHeightOnly;
                }
                // <--
                // <--
            }
            else
				MakeAll();
			_InvalidateSize();
			InvalidatePos();
			if ( bOldLocked )
				Lock();
            const SwRect aNew( GetObjRectWithSpaces() );
			if ( aOld != aNew )
			{
				::Notify( this, FindPageFrm(), aOld );
                if ( GetAnchorFrm()->IsInFly() )
                    AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
			}
            return (aOld.*fnRect->fnGetHeight)() -
                   (aNew.*fnRect->fnGetHeight)();
		}
		return nVal;
	}
	return 0L;
}

/*************************************************************************
|*
|*	SwFlyFrm::ChgSize()
|*
|*	Ersterstellung		MA 05. Oct. 92
|*	Letzte Aenderung	MA 04. Sep. 96
|*
|*************************************************************************/

Size SwFlyFrm::ChgSize( const Size& aNewSize )
{
    // --> OD 2006-01-19 #i53298#
    // If the fly frame anchored at-paragraph or at-character contains an OLE
    // object, assure that the new size fits into the current clipping area
    // of the fly frame
    Size aAdjustedNewSize( aNewSize );
    {
        if ( dynamic_cast<SwFlyAtCntFrm*>(this) &&
             Lower() && dynamic_cast<SwNoTxtFrm*>(Lower()) &&
             static_cast<SwNoTxtFrm*>(Lower())->GetNode()->GetOLENode() )
        {
            SwRect aClipRect;
            ::CalcClipRect( GetVirtDrawObj(), aClipRect, sal_False );
            if ( aAdjustedNewSize.Width() > aClipRect.Width() )
            {
                aAdjustedNewSize.setWidth( aClipRect.Width() );
            }
            if ( aAdjustedNewSize.Height() > aClipRect.Height() )
            {
                aAdjustedNewSize.setWidth( aClipRect.Height() );
            }
        }
    }
    // <--
    if ( aAdjustedNewSize != Frm().SSize() )
	{
		SwFrmFmt *pFmt = GetFmt();
		SwFmtFrmSize aSz( pFmt->GetFrmSize() );
        aSz.SetWidth( aAdjustedNewSize.Width() );
        // --> OD 2006-01-19 #i53298# - no tolerance any more.
        // If it reveals that the tolerance is still needed, then suppress a
        // <SetAttr> call, if <aSz> equals the current <SwFmtFrmSize> attribute.
//        if ( Abs(aAdjustedNewSize.Height() - aSz.GetHeight()) > 1 )
        aSz.SetHeight( aAdjustedNewSize.Height() );
        // <--
		// uebers Doc fuers Undo!
		pFmt->GetDoc()->SetAttr( aSz, *pFmt );
		return aSz.GetSize();
	}
	else
		return Frm().SSize();
}

/*************************************************************************
|*
|*	SwFlyFrm::IsLowerOf()
|*
|*	Ersterstellung		MA 27. Dec. 93
|*	Letzte Aenderung	MA 27. Dec. 93
|*
|*************************************************************************/

sal_Bool SwFlyFrm::IsLowerOf( const SwLayoutFrm* pUpperFrm ) const
{
    ASSERT( GetAnchorFrm(), "8-( Fly is lost in Space." );
    const SwFrm* pFrm = GetAnchorFrm();
    do
    {
        if ( pFrm == pUpperFrm )
            return sal_True;
        pFrm = pFrm->IsFlyFrm()
               ? ((const SwFlyFrm*)pFrm)->GetAnchorFrm()
               : pFrm->GetUpper();
    } while ( pFrm );
    return sal_False;
}

/*************************************************************************
|*
|*	SwFlyFrm::Cut()
|*
|*	Ersterstellung		MA 23. Feb. 94
|*	Letzte Aenderung	MA 23. Feb. 94
|*
|*************************************************************************/

void SwFlyFrm::Cut()
{
}

/*************************************************************************
|*
|*	SwFrm::AppendFly(), RemoveFly()
|*
|*	Ersterstellung		MA 25. Aug. 92
|*	Letzte Aenderung	MA 09. Jun. 95
|*
|*************************************************************************/

void SwFrm::AppendFly( SwFlyFrm *pNew )
{
    if ( !pDrawObjs )
        pDrawObjs = new SwSortedObjs();
    pDrawObjs->Insert( *pNew );
    pNew->ChgAnchorFrm( this );

	//Bei der Seite anmelden; kann sein, dass noch keine da ist - die
	//Anmeldung wird dann in SwPageFrm::PreparePage durch gefuehrt.
	SwPageFrm *pPage = FindPageFrm();
	if ( pPage )
	{
		if ( pNew->IsFlyAtCntFrm() && pNew->Frm().Top() == WEIT_WECH )
		{
			//Versuch die Seitenformatierung von neuen Dokumenten etwas
			//guenstiger zu gestalten.
			//Wir haengen die Flys erstenmal nach hinten damit sie bei heftigem
			//Fluss der Anker nicht unoetig oft formatiert werden.
			//Damit man noch brauchbar an das Ende des Dokumentes springen
			//kann werden die Flys nicht ganz an das Ende gehaengt.
			SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
            if( !SwLayHelper::CheckPageFlyCache( pPage, pNew ) )
            {
                SwPageFrm *pTmp = pRoot->GetLastPage();
                if ( pTmp->GetPhyPageNum() > 30 )
                {
                    for ( sal_uInt16 i = 0; i < 10; ++i )
                    {
                        pTmp = (SwPageFrm*)pTmp->GetPrev();
                        if( pTmp->GetPhyPageNum() <= pPage->GetPhyPageNum() )
                            break; // damit wir nicht vor unserem Anker landen
                    }
                    if ( pTmp->IsEmptyPage() )
                        pTmp = (SwPageFrm*)pTmp->GetPrev();
                    pPage = pTmp;
                }
			}
            pPage->AppendFlyToPage( pNew );
		}
		else
            pPage->AppendFlyToPage( pNew );
    }
}

void SwFrm::RemoveFly( SwFlyFrm *pToRemove )
{
	//Bei der Seite Abmelden - kann schon passiert sein weil die Seite
	//bereits destruiert wurde.
	SwPageFrm *pPage = pToRemove->FindPageFrm();
	if ( pPage && pPage->GetSortedObjs() )
    {
        pPage->RemoveFlyFromPage( pToRemove );
    }
    // --> OD 2008-05-19 #i73201#
    else
    {
        if ( pToRemove->IsAccessibleFrm() &&
             pToRemove->GetFmt() &&
             !pToRemove->IsFlyInCntFrm() )
        {
            SwRootFrm *pRootFrm = getRootFrm();
            if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
            {
                ViewShell *pVSh = pRootFrm->GetCurrShell();
                if( pVSh && pVSh->Imp() )
                {
                    pVSh->Imp()->DisposeAccessibleFrm( pToRemove );
                }
            }
        }
    }
    // <--

    pDrawObjs->Remove( *pToRemove );
	if ( !pDrawObjs->Count() )
		DELETEZ( pDrawObjs );

    pToRemove->ChgAnchorFrm( 0 );

	if ( !pToRemove->IsFlyInCntFrm() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
		GetUpper()->InvalidateSize();
}

/*************************************************************************
|*
|*	SwFrm::AppendDrawObj(), RemoveDrawObj()
|*
|*  --> OD 2004-07-06 #i28701# - new methods
|*
|*************************************************************************/
void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
{
    if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
    {
        ASSERT( false,
                "SwFrm::AppendDrawObj(..) - anchored object of unexcepted type -> object not appended" );
        return;
    }

    if ( !_rNewObj.GetDrawObj()->ISA(SwDrawVirtObj) &&
         _rNewObj.GetAnchorFrm() && _rNewObj.GetAnchorFrm() != this )
    {
        // perform disconnect from layout, if 'master' drawing object is appended
        // to a new frame.
        static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
                                                DisconnectFromLayout( false );
    }

    if ( _rNewObj.GetAnchorFrm() != this )
    {
        if ( !pDrawObjs )
            pDrawObjs = new SwSortedObjs();
        pDrawObjs->Insert( _rNewObj );
        _rNewObj.ChgAnchorFrm( this );
    }

    // --> OD 2010-09-14 #i113730#
    // Assure the control objects and group objects containing controls are on the control layer
    if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
    {
        const IDocumentDrawModelAccess* pIDDMA = (IsFlyFrm())
            ? static_cast<SwFlyFrm*>(this)->GetFmt()->
                    getIDocumentDrawModelAccess()
            : GetUpper()->GetFmt()->getIDocumentDrawModelAccess();
        const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
        const SdrLayerID aControlLayerID(pIDDMA->GetControlsId());
        const SdrLayerID aInvisibleControlLayerID(pIDDMA->GetInvisibleControlsId());

        if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
        {
            if ( aCurrentLayer == pIDDMA->GetInvisibleHellId() ||
                 aCurrentLayer == pIDDMA->GetInvisibleHeavenId() )
            {
                _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
            }
            else
            {        
                _rNewObj.DrawObj()->SetLayer(aControlLayerID);
            }
        }
    }
    // <--

    // no direct positioning needed, but invalidate the drawing object position
    _rNewObj.InvalidateObjPos();

    // register at page frame
    SwPageFrm* pPage = FindPageFrm();
    if ( pPage )
    {
        pPage->AppendDrawObjToPage( _rNewObj );
    }

    // Notify accessible layout.
    ViewShell* pSh = getRootFrm()->GetCurrShell();
    if( pSh )
    {
        SwRootFrm* pLayout = getRootFrm();
        if( pLayout && pLayout->IsAnyShellAccessible() )
        pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
    }
}

void SwFrm::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
{
    // Notify accessible layout.
    ViewShell* pSh = getRootFrm()->GetCurrShell();
    if( pSh )
    {
        SwRootFrm* pLayout = getRootFrm();
        if( pLayout && pLayout->IsAnyShellAccessible() )
        pSh->Imp()->DisposeAccessibleObj( _rToRemoveObj.GetDrawObj() );
    }

    // deregister from page frame
    SwPageFrm* pPage = _rToRemoveObj.GetPageFrm();
    if ( pPage && pPage->GetSortedObjs() )
        pPage->RemoveDrawObjFromPage( _rToRemoveObj );

    pDrawObjs->Remove( _rToRemoveObj );
    if ( !pDrawObjs->Count() )
        DELETEZ( pDrawObjs );

    _rToRemoveObj.ChgAnchorFrm( 0 );
}

/*************************************************************************
|*
|*  SwFrm::InvalidateObjs()
|*
|*	Ersterstellung		MA 29. Nov. 96
|*	Letzte Aenderung	MA 29. Nov. 96
|*
|*************************************************************************/
// --> OD 2004-07-01 #i28701# - change purpose of method and adjust its name
void SwFrm::InvalidateObjs( const bool _bInvaPosOnly,
                            const bool _bNoInvaOfAsCharAnchoredObjs )
{
	if ( GetDrawObjs() )
	{
        // --> OD 2004-10-08 #i26945# - determine page the frame is on,
        // in order to check, if anchored object is registered at the same
        // page.
        const SwPageFrm* pPageFrm = FindPageFrm();
        // <--
        // --> OD 2004-07-01 #i28701# - re-factoring
        sal_uInt32 i = 0;
        for ( ; i < GetDrawObjs()->Count(); ++i )
        {
            SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
            if ( _bNoInvaOfAsCharAnchoredObjs &&
                 (pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
                    == FLY_AS_CHAR) )
            {
                continue;
            }
            // --> OD 2004-10-08 #i26945# - no invalidation, if anchored object
            // isn't registered at the same page and instead is registered at
            // the page, where its anchor character text frame is on.
            if ( pAnchoredObj->GetPageFrm() &&
                 pAnchoredObj->GetPageFrm() != pPageFrm )
            {
                SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
                if ( pAnchorCharFrm &&
                     pAnchoredObj->GetPageFrm() == pAnchorCharFrm->FindPageFrm() )
                {
                    continue;
                }
                // --> OD 2004-11-24 #115759# - unlock its position, if anchored
                // object isn't registered at the page, where its anchor
                // character text frame is on, respectively if it has no
                // anchor character text frame.
                else
                {
                    pAnchoredObj->UnlockPosition();
                }
                // <--
            }
            // <--
            // --> OD 2005-07-18 #i51474# - reset flag, that anchored object
            // has cleared environment, and unlock its position, if the anchored
            // object is registered at the same page as the anchor frame is on.
            if ( pAnchoredObj->ClearedEnvironment() &&
                 pAnchoredObj->GetPageFrm() &&
                 pAnchoredObj->GetPageFrm() == pPageFrm )
            {
                pAnchoredObj->UnlockPosition();
                pAnchoredObj->SetClearedEnvironment( false );
            }
            // <--
            // distinguish between writer fly frames and drawing objects
            if ( pAnchoredObj->ISA(SwFlyFrm) )
            {
                SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
                pFly->_Invalidate();
                pFly->_InvalidatePos();
                if ( !_bInvaPosOnly )
                    pFly->_InvalidateSize();
            }
            else
            {
                pAnchoredObj->InvalidateObjPos();
            } // end of distinction between writer fly frames and drawing objects

        } // end of loop on objects, which are connected to the frame
	}
}

/*************************************************************************
|*
|*  SwLayoutFrm::NotifyLowerObjs()
|*
|*************************************************************************/
// --> OD 2004-07-01 #i28701# - change purpose of method and its name
// --> OD 2004-10-08 #i26945# - correct check, if anchored object is a lower
// of the layout frame. E.g., anchor character text frame can be a follow text
// frame.
// --> OD 2005-03-11 #i44016# - add parameter <_bUnlockPosOfObjs> to
// force an unlockposition call for the lower objects.
void SwLayoutFrm::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
{
    // invalidate lower floating screen objects
    SwPageFrm* pPageFrm = FindPageFrm();
    if ( pPageFrm && pPageFrm->GetSortedObjs() )
	{
        SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
        for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
		{
            SwAnchoredObject* pObj = rObjs[i];
            // --> OD 2004-10-08 #i26945# - check, if anchored object is a lower
            // of the layout frame is changed to check, if its anchor frame
            // is a lower of the layout frame.
            // determine the anchor frame - usually it's the anchor frame,
            // for at-character/as-character anchored objects the anchor character
            // text frame is taken.
            const SwFrm* pAnchorFrm = pObj->GetAnchorFrmContainingAnchPos();
            // <--
            if ( pObj->ISA(SwFlyFrm) )
			{
                SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);

				if ( pFly->Frm().Left() == WEIT_WECH )
					continue;

                if ( pFly->IsAnLower( this ) )
					continue;

                // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
                // fly frame is lower of layout frame resp. if fly frame is
                // at a different page registered as its anchor frame is on.
                const bool bLow = IsAnLower( pAnchorFrm );
                if ( bLow || pAnchorFrm->FindPageFrm() != pPageFrm )
                // <--
				{
                    pFly->_Invalidate( pPageFrm );
					if ( !bLow || pFly->IsFlyAtCntFrm() )
                    {
                        // --> OD 2005-03-11 #i44016#
                        if ( _bUnlockPosOfObjs )
                        {
                            pFly->UnlockPosition();
                        }
                        // <--
                        pFly->_InvalidatePos();
                    }
					else
						pFly->_InvalidatePrt();
				}
			}
            else
            {
                ASSERT( pObj->ISA(SwAnchoredDrawObject),
                        "<SwLayoutFrm::NotifyFlys() - anchored object of unexcepted type" );
                // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
                // fly frame is lower of layout frame resp. if fly frame is
                // at a different page registered as its anchor frame is on.
                if ( IsAnLower( pAnchorFrm ) ||
                     pAnchorFrm->FindPageFrm() != pPageFrm )
                // <--
                {
                    // --> OD 2005-03-11 #i44016#
                    if ( _bUnlockPosOfObjs )
                    {
                        pObj->UnlockPosition();
                    }
                    // <--
                    pObj->InvalidateObjPos();
                }
            }
		}
	}
}

/*************************************************************************
|*
|*	SwFlyFrm::NotifyDrawObj()
|*
|*	Ersterstellung		OK 22. Nov. 94
|*	Letzte Aenderung	MA 10. Jan. 97
|*
|*************************************************************************/

void SwFlyFrm::NotifyDrawObj()
{
    SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
    pObj->SetRect();
    pObj->SetRectsDirty();
    pObj->SetChanged();
    pObj->BroadcastObjectChange();
	if ( GetFmt()->GetSurround().IsContour() )
        ClrContourCache( pObj );
}

/*************************************************************************
|*
|*  SwFlyFrm::CalcRel()
|*
|*	Ersterstellung		MA 13. Jun. 96
|*	Letzte Aenderung	MA 10. Oct. 96
|*
|*************************************************************************/

Size SwFlyFrm::CalcRel( const SwFmtFrmSize &rSz ) const
{
	Size aRet( rSz.GetSize() );

    const SwFrm *pRel = IsFlyLayFrm() ? GetAnchorFrm() : GetAnchorFrm()->GetUpper();
	if( pRel ) // LAYER_IMPL
	{
		long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
		const ViewShell *pSh = getRootFrm()->GetCurrShell();
		if ( ( pRel->IsBodyFrm() || pRel->IsPageFrm() ) &&
             pSh && pSh->GetViewOptions()->getBrowseMode() &&
			 pSh->VisArea().HasArea() )
		{
			nRelWidth  = pSh->GetBrowseWidth();
			nRelHeight = pSh->VisArea().Height();
			Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
			long nDiff = nRelWidth - pRel->Prt().Width();
			if ( nDiff > 0 )
				nRelWidth -= nDiff;
			nRelHeight -= 2*aBorder.Height();
			nDiff = nRelHeight - pRel->Prt().Height();
			if ( nDiff > 0 )
				nRelHeight -= nDiff;
		}
		nRelWidth  = Min( nRelWidth,  pRel->Prt().Width() );
		nRelHeight = Min( nRelHeight, pRel->Prt().Height() );
        if( !pRel->IsPageFrm() )
        {
            const SwPageFrm* pPage = FindPageFrm();
            if( pPage )
            {
                nRelWidth  = Min( nRelWidth,  pPage->Prt().Width() );
                nRelHeight = Min( nRelHeight, pPage->Prt().Height() );
            }
        }

		if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != 0xFF )
			aRet.Width() = nRelWidth * rSz.GetWidthPercent() / 100;
		if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != 0xFF )
			aRet.Height() = nRelHeight * rSz.GetHeightPercent() / 100;

		if ( rSz.GetWidthPercent() == 0xFF )
		{
			aRet.Width() *= aRet.Height();
			aRet.Width() /= rSz.GetHeight();
		}
		else if ( rSz.GetHeightPercent() == 0xFF )
		{
			aRet.Height() *= aRet.Width();
			aRet.Height() /= rSz.GetWidth();
		}
    }
	return aRet;
}

/*************************************************************************
|*
|*  SwFlyFrm::CalcAutoWidth()
|*
|*************************************************************************/

SwTwips lcl_CalcAutoWidth( const SwLayoutFrm& rFrm )
{
    SwTwips nRet = 0;
    SwTwips nMin = 0;
    const SwFrm* pFrm = rFrm.Lower();

    // No autowidth defined for columned frames
    if ( !pFrm || pFrm->IsColumnFrm() )
        return nRet;

    while ( pFrm )
    {
        if ( pFrm->IsSctFrm() )
        {
            nMin = lcl_CalcAutoWidth( *(SwSectionFrm*)pFrm );
        }
        if ( pFrm->IsTxtFrm() )
        {
            nMin = ((SwTxtFrm*)pFrm)->CalcFitToContent();
            const SvxLRSpaceItem &rSpace =
                ((SwTxtFrm*)pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
            nMin += rSpace.GetRight() + rSpace.GetTxtLeft() + rSpace.GetTxtFirstLineOfst();
        }
        else if ( pFrm->IsTabFrm() )
        {
            const SwFmtFrmSize& rTblFmtSz = ((SwTabFrm*)pFrm)->GetTable()->GetFrmFmt()->GetFrmSize();
            if ( USHRT_MAX == rTblFmtSz.GetSize().Width() ||
                 text::HoriOrientation::NONE == ((SwTabFrm*)pFrm)->GetFmt()->GetHoriOrient().GetHoriOrient() )
            {
                const SwPageFrm* pPage = rFrm.FindPageFrm();
                // auto width table
                nMin = pFrm->GetUpper()->IsVertical() ?
                    pPage->Prt().Height() :
                    pPage->Prt().Width();
            }
            else
            {
                nMin = rTblFmtSz.GetSize().Width();
            }
        }

        if ( nMin > nRet )
            nRet = nMin;

        pFrm = pFrm->GetNext();
    }

    return nRet;
}

SwTwips SwFlyFrm::CalcAutoWidth() const
{
    return lcl_CalcAutoWidth( *this );
}

/*************************************************************************
|*
|*	SwFlyFrm::AddSpacesToFrm
|*
|*	Ersterstellung		MA 11. Nov. 96
|*	Letzte Aenderung	MA 10. Mar. 97
|*
|*************************************************************************/

//SwRect SwFlyFrm::AddSpacesToFrm() const
//{
//  SwRect aRect( Frm() );
//  const SvxULSpaceItem &rUL = GetFmt()->GetULSpace();
//  const SvxLRSpaceItem &rLR = GetFmt()->GetLRSpace();
//  aRect.Left( Max( aRect.Left() - long(rLR.GetLeft()), 0L ) );
//  aRect.SSize().Width() += rLR.GetRight();
//  aRect.Top( Max( aRect.Top() - long(rUL.GetUpper()), 0L ) );
//  aRect.SSize().Height()+= rUL.GetLower();
//  return aRect;
//}

/*************************************************************************
|*
|*	SwFlyFrm::GetContour()
|*
|*	Ersterstellung		MA 09. Jan. 97
|*	Letzte Aenderung	MA 10. Jan. 97
|*
|*************************************************************************/
/// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTxtFrm> contains
/// a graphic, load of intrinsic graphic has to be avoided.
sal_Bool SwFlyFrm::GetContour( PolyPolygon&   rContour,
                           const sal_Bool _bForPaint ) const
{
	sal_Bool bRet = sal_False;
	if( GetFmt()->GetSurround().IsContour() && Lower() &&
		Lower()->IsNoTxtFrm() )
	{
		SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
        // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
        // in order to avoid load of graphic, if <SwNoTxtNode> contains a graphic
        // node and method is called for paint.
        const GraphicObject* pGrfObj = NULL;
        sal_Bool bGrfObjCreated = sal_False;
        const SwGrfNode* pGrfNd = pNd->GetGrfNode();
        if ( pGrfNd && _bForPaint )
        {
            pGrfObj = &(pGrfNd->GetGrfObj());
        }
        else
        {
            pGrfObj = new GraphicObject( pNd->GetGraphic() );
            bGrfObjCreated = sal_True;
        }
        ASSERT( pGrfObj, "SwFlyFrm::GetContour() - No Graphic/GraphicObject found at <SwNoTxtNode>." );
        if ( pGrfObj && pGrfObj->GetType() != GRAPHIC_NONE )
        {
            if( !pNd->HasContour() )
            {
                // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
                // during paint. Thus, return (value of <bRet> should be <sal_False>).
                if ( pGrfNd && _bForPaint )
                {
                    ASSERT( false, "SwFlyFrm::GetContour() - No Contour found at <SwNoTxtNode> during paint." );
                    return bRet;
                }
                pNd->CreateContour();
            }
            pNd->GetContour( rContour );
			//Der Node haelt das Polygon passend zur Originalgroesse der Grafik
			//hier muss die Skalierung einkalkuliert werden.
			SwRect aClip;
			SwRect aOrig;
			Lower()->Calc();
			((SwNoTxtFrm*)Lower())->GetGrfArea( aClip, &aOrig, sal_False );
            // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
            // in order to avoid that graphic has to be loaded for contour scale.
            //SvxContourDlg::ScaleContour( rContour, aGrf, MAP_TWIP, aOrig.SSize() );
            {
                OutputDevice*   pOutDev = Application::GetDefaultDevice();
                const MapMode   aDispMap( MAP_TWIP );
                const MapMode   aGrfMap( pGrfObj->GetPrefMapMode() );
                const Size      aGrfSize( pGrfObj->GetPrefSize() );
                double          fScaleX;
                double          fScaleY;
                Size            aOrgSize;
                Point           aNewPoint;
                sal_Bool            bPixelMap = aGrfMap.GetMapUnit() == MAP_PIXEL;

                if ( bPixelMap )
                    aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
                else
                    aOrgSize = pOutDev->LogicToLogic( aGrfSize, aGrfMap, aDispMap );

                if ( aOrgSize.Width() && aOrgSize.Height() )
                {
                    fScaleX = (double) aOrig.Width() / aOrgSize.Width();
                    fScaleY = (double) aOrig.Height() / aOrgSize.Height();

                    for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
                    {
                        Polygon& rPoly = rContour[ j ];

                        for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
                        {
                            if ( bPixelMap )
                                aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap  );
                            else
                                aNewPoint = pOutDev->LogicToLogic( rPoly[ i ], aGrfMap, aDispMap  );

                            rPoly[ i ] = Point( FRound( aNewPoint.X() * fScaleX ), FRound( aNewPoint.Y() * fScaleY ) );
                        }
                    }
                }
            }
            // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
            if ( bGrfObjCreated )
            {
                delete pGrfObj;
            }
            rContour.Move( aOrig.Left(), aOrig.Top() );
            if( !aClip.Width() )
                aClip.Width( 1 );
            if( !aClip.Height() )
                aClip.Height( 1 );
            rContour.Clip( aClip.SVRect() );
			rContour.Optimize(POLY_OPTIMIZE_CLOSE);
			bRet = sal_True;
		}
	}
	return bRet;
}

// OD 2004-03-25 #i26791#
const SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj() const
{
    return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
}
SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj()
{
    return static_cast<SwVirtFlyDrawObj*>(DrawObj());
}

// =============================================================================
// OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
// base class <SwAnchoredObject>
// =============================================================================
void SwFlyFrm::InvalidateObjPos()
{
    InvalidatePos();
    // --> OD 2006-08-10 #i68520#
    InvalidateObjRectWithSpaces();
    // <--
}

SwFrmFmt& SwFlyFrm::GetFrmFmt()
{
    ASSERT( GetFmt(),
            "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
    return *GetFmt();
}
const SwFrmFmt& SwFlyFrm::GetFrmFmt() const
{
    ASSERT( GetFmt(),
            "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
    return *GetFmt();
}

const SwRect SwFlyFrm::GetObjRect() const
{
    return Frm();
}

// --> OD 2006-10-05 #i70122#
// for Writer fly frames the bounding rectangle equals the object rectangles
const SwRect SwFlyFrm::GetObjBoundRect() const
{
    return GetObjRect();
}
// <--

// --> OD 2006-08-10 #i68520#
bool SwFlyFrm::_SetObjTop( const SwTwips _nTop )
{
    const bool bChanged( Frm().Pos().Y() != _nTop );

    Frm().Pos().Y() = _nTop;

    return bChanged;
}
bool SwFlyFrm::_SetObjLeft( const SwTwips _nLeft )
{
    const bool bChanged( Frm().Pos().X() != _nLeft );

    Frm().Pos().X() = _nLeft;

    return bChanged;
}
// <--

/** method to assure that anchored object is registered at the correct
    page frame

    OD 2004-07-02 #i28701#

    @author OD
*/
void SwFlyFrm::RegisterAtCorrectPage()
{
    // default behaviour is to do nothing.
}

/** method to determine, if a <MakeAll()> on the Writer fly frame is possible

    OD 2004-05-11 #i28701#

    @author OD
*/
bool SwFlyFrm::IsFormatPossible() const
{
    return SwAnchoredObject::IsFormatPossible() &&
           !IsLocked() && !IsColLocked();
}

void SwFlyFrm::GetAnchoredObjects( std::list<SwAnchoredObject*>& aList, const SwFmt& rFmt )
{
    SwIterator<SwFlyFrm,SwFmt> aIter( rFmt );
    for( SwFlyFrm* pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
        aList.push_back( pFlyFrm );
}

const SwFlyFrmFmt * SwFlyFrm::GetFmt() const
{
    return static_cast< const SwFlyFrmFmt * >( GetDep() );
}
    
SwFlyFrmFmt * SwFlyFrm::GetFmt()
{
    return static_cast< SwFlyFrmFmt * >( GetDep() );
}

