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



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

#include <hintids.hxx>
#include <svl/itemiter.hxx>
#include <svtools/imapobj.hxx>
#include <svtools/soerr.hxx>
#include <editeng/protitem.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdouno.hxx>
#include <svx/fmglob.hxx>
#include <com/sun/star/form/FormButtonType.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <fmtanchr.hxx>
#include <txtflcnt.hxx>
#include <fmtcntnt.hxx>
#include <fmtornt.hxx>
#include <fmtflcnt.hxx>
#include <fmturl.hxx>
#include <fmtclds.hxx>
#include <fmtfsize.hxx>
#include <docary.hxx>
#include <fesh.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <cntfrm.hxx>
#include <txtfrm.hxx>
#include <viewimp.hxx>
#include <viscrs.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <dview.hxx>
#include <dflyobj.hxx>
#include <dcontact.hxx>
#include <frmfmt.hxx>
#include <flyfrm.hxx>
#include <ndtxt.hxx>
#include <edimp.hxx>
#include <swtable.hxx>
#include <mvsave.hxx>		// Strukturen zum Sichern beim Move/Delete
#include <ndgrf.hxx>
#include <flyfrms.hxx>
#include <flypos.hxx>
#include <fldbas.hxx>
#include <fmtfld.hxx>
#include <swundo.hxx>
#include <frame.hxx>
#include <notxtfrm.hxx>
// --> OD 2006-03-06 #125892#
#include <HandleAnchorNodeChg.hxx>
// <--
#include <frmatr.hxx>
// --> 3.7.2010 #i972#
#include <ndole.hxx>
// <--
// --> OD 2009-12-29 #i89920#
#include <fmtsrnd.hxx>
#include <editeng/opaqitem.hxx>
// <--

using ::rtl::OUString;
using namespace ::com::sun::star;

//Zum anmelden von Flys in Flys in ...
//definiert in layout/frmtool.cxx
void RegistFlys( SwPageFrm*, const SwLayoutFrm* );

/***********************************************************************
#*	Class	   	:  SwDoc
#*	Methode	   	:  UseSpzLayoutFmt
#*	Beschreibung:  Anhand des Request werden zu dem Format entsprechende
#*		Aenderungen an den Spezifischen Layouts vorgenommen.
#*	Datum	   	:  MA 23. Sep. 92
#*	Update	   	:  JP 09.03.98
#***********************************************************************/

sal_Bool lcl_SetNewFlyPos( const SwNode& rNode, SwFmtAnchor& rAnchor,
						const Point& rPt )
{
	sal_Bool bRet = sal_False;
	const SwStartNode* pStNode = rNode.FindFlyStartNode();
	if( pStNode )
	{
		SwPosition aPos( *pStNode );
		rAnchor.SetAnchor( &aPos );
		bRet = sal_True;
	}
	else
	{
        const SwCntntNode *pCntNd = rNode.GetCntntNode();
		const SwCntntFrm* pCFrm = pCntNd ? pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False ) : 0;
		const SwPageFrm *pPg = pCFrm ? pCFrm->FindPageFrm() : 0;

		rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 );
        rAnchor.SetType( FLY_AT_PAGE );
	}
	return bRet;
}

sal_Bool lcl_FindAnchorPos(
    SwEditShell& rEditShell,
    SwDoc& rDoc,
    const Point& rPt,
    const SwFrm& rFrm,
    SfxItemSet& rSet )
{
	sal_Bool bRet = sal_True;
	SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
	RndStdIds nNew = aNewAnch.GetAnchorId();
	const SwFrm *pNewAnch;

	//Neuen Anker ermitteln
	Point aTmpPnt( rPt );
	switch( nNew )
	{
    case FLY_AS_CHAR:  // sollte der nicht auch mit hinein?
    case FLY_AT_PARA:
    case FLY_AT_CHAR: // LAYER_IMPL
        {
			//Ausgehend von der linken oberen Ecke des Fly den
			//dichtesten CntntFrm suchen.
            const SwFrm* pFrm = rFrm.IsFlyFrm() ? ((SwFlyFrm&)rFrm).GetAnchorFrm()
												: &rFrm;
			pNewAnch = ::FindAnchor( pFrm, aTmpPnt );
			if( pNewAnch->IsProtected() )
			{
				bRet = sal_False;
				break;
			}

            SwPosition aPos( *((SwCntntFrm*)pNewAnch)->GetNode() );
            if ((FLY_AT_CHAR == nNew) || (FLY_AS_CHAR == nNew))
            {
                // es muss ein TextNode gefunden werden, denn nur in diesen
                // ist ein Inhaltsgebundene Frames zu verankern
                SwCrsrMoveState aState( MV_SETONLYTEXT );
                aTmpPnt.X() -= 1;					//nicht im Fly landen!!
                if( !pNewAnch->GetCrsrOfst( &aPos, aTmpPnt, &aState ) )
                {
                    SwCntntNode* pCNd = ((SwCntntFrm*)pNewAnch)->GetNode();
                    if( pNewAnch->Frm().Bottom() < aTmpPnt.Y() )
                        pCNd->MakeStartIndex( &aPos.nContent );
                    else
                        pCNd->MakeEndIndex( &aPos.nContent );
                }
                else
                {
                    if ( rEditShell.PosInsideInputFld( aPos ) )
                    {
                        aPos.nContent = rEditShell.StartOfInputFldAtPos( aPos );
                    }
                }
            }
            aNewAnch.SetAnchor( &aPos );
        }
        break;

	case FLY_AT_FLY: // LAYER_IMPL
		{
			//Ausgehend von der linken oberen Ecke des Fly den
			//dichtesten SwFlyFrm suchen.
			SwCrsrMoveState aState( MV_SETONLYTEXT );
			SwPosition aPos( rDoc.GetNodes() );
			aTmpPnt.X() -= 1;					//nicht im Fly landen!!
			rDoc.GetCurrentLayout()->GetCrsrOfst( &aPos, aTmpPnt, &aState );	//swmod 071108//swmod 071225
			pNewAnch = ::FindAnchor(
				aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( rFrm.getRootFrm(), 0, 0, sal_False ),
				aTmpPnt )->FindFlyFrm();

			if( pNewAnch && &rFrm != pNewAnch && !pNewAnch->IsProtected() )
			{
				aPos.nNode = *((SwFlyFrm*)pNewAnch)->GetFmt()->GetCntnt().
								GetCntntIdx();
				aNewAnch.SetAnchor( &aPos );
				break;
			}
		}

        aNewAnch.SetType( nNew = FLY_AT_PAGE );
		// no break

    case FLY_AT_PAGE:
		pNewAnch = rFrm.FindPageFrm();
		aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() );
		break;

	default:
		ASSERT( !&rDoc, "Falsche ID fuer neuen Anker." );
	}

	rSet.Put( aNewAnch );
	return bRet;
}

//
//! also used in unoframe.cxx
//
sal_Bool lcl_ChkAndSetNewAnchor(
    SwEditShell& rEditShell,
    const SwFlyFrm& rFly,
    SfxItemSet& rSet )
{
	const SwFrmFmt& rFmt = *rFly.GetFmt();
	const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
	const RndStdIds nOld = rOldAnch.GetAnchorId();

	RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId();

	if( nOld == nNew )
		return sal_False;

	SwDoc* pDoc = (SwDoc*)rFmt.GetDoc();

#ifdef DBG_UTIL
    ASSERT( !(nNew == FLY_AT_PAGE &&
        (FLY_AT_PARA==nOld || FLY_AT_CHAR==nOld || FLY_AS_CHAR==nOld ) &&
		pDoc->IsInHeaderFooter( rOldAnch.GetCntntAnchor()->nNode )),
			"Unerlaubter Ankerwechsel in Head/Foot." );
#endif

	return ::lcl_FindAnchorPos( rEditShell, *pDoc, rFly.Frm().Pos(), rFly, rSet );
}

void SwFEShell::SelectFlyFrm( SwFlyFrm& rFrm, sal_Bool bNew )
{
	SET_CURR_SHELL( this );

	//	Wenn es ein neuer Rahmen ist, so soll er selektiert sein.
	//	!!Rahmen immer selektieren, wenn sie nicht selektiert sind.
	// 	- Es kann ein neuer 'alter' sein weil der Anker gewechselt wurde.
	//	- 'alte' Rahmen sind vorher immer selektiert denn sonst wird nix
	//	  an ihnen veraendert.
	//	Der Rahmen darf nicht per Dokumentposition selektiert werden, weil er
	//	auf jedenfall selektiert sein muss!
    SwViewImp *pImpl = Imp();
    if( GetWin() && (bNew || !pImpl->GetDrawView()->AreObjectsMarked()) )
	{
		ASSERT( rFrm.IsFlyFrm(), "SelectFlyFrm will einen Fly" );

		//Wenn der Fly bereits selektiert ist gibt es hier ja wohl nichts
		//zu tun.
		if ( FindFlyFrm() == &rFrm )
			return;

		//Damit der Anker ueberhaupt noch gepaintet wird.
        if( rFrm.IsFlyInCntFrm() && rFrm.GetAnchorFrm() )
             rFrm.GetAnchorFrm()->SetCompletePaint();

        // --> OD 2004-06-11 #i28701# - no format at all.
//        //Hier wurde immer kalkuliert. Leider ist der Sonderfall Fly in Fly mit
//        //Spalten u.U. sehr kritisch wenn der innenliegende zuerst formatiert
//        //wird. Um kein Risiko einzugehen entschaerfen wir nur diesen Sonderfall.
//        if( !rFrm.GetAnchorFrm()->IsInFly() )
//            rFrm.Calc();

        if( pImpl->GetDrawView()->AreObjectsMarked() )
            pImpl->GetDrawView()->UnmarkAll();

        pImpl->GetDrawView()->MarkObj( rFrm.GetVirtDrawObj(),
                                      pImpl->GetPageView(), sal_False, sal_False );
		KillPams();
		ClearMark();
		SelFlyGrabCrsr();
	}
}

/*************************************************************************
|*
|*	SwFEShell::FindFlyFrm()
|*
|* 	Beschreibung		Liefert den Fly wenn einer Selektiert ist.
|*	Ersterstellung		MA 03. Nov. 92
|*	Letzte Aenderung	MA 05. Mar. 96
|*
*************************************************************************/

SwFlyFrm *SwFEShell::FindFlyFrm() const
{
	if ( Imp()->HasDrawView() )
	{
		// Ein Fly ist genau dann erreichbar, wenn er selektiert ist.
		const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
		if( rMrkList.GetMarkCount() != 1 )
			return 0;

		SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
		return ( pO && pO->ISA(SwVirtFlyDrawObj) ) ? ((SwVirtFlyDrawObj*)pO)->GetFlyFrm() : 0;
	}
	return 0;
}

/*************************************************************************
|*
|*	SwFEShell::IsFlyInFly()
|*
|* 	Beschreibung		Liefert sal_True, wenn der aktuelle Fly an einem anderen
|*						verankert werden koennte (also innerhalb ist)
|*	Ersterstellung		AMA 11. Sep. 97
|*	Letzte Aenderung	AMA 14. Jan. 98
|*
*************************************************************************/

const SwFrmFmt* SwFEShell::IsFlyInFly()
{
	SET_CURR_SHELL( this );

	if ( !Imp()->HasDrawView() )
		return NULL;

	const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
	if ( !rMrkList.GetMarkCount() )
	{
		SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
		if( !pCntnt )
			return NULL;
		SwFlyFrm *pFly = pCntnt->FindFlyFrm();
		if ( !pFly )
			return NULL;
		return pFly->GetFmt();
	}
	else if ( rMrkList.GetMarkCount() != 1 ||
		 !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) )
		return NULL;

	SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();

	SwFrmFmt *pFmt = FindFrmFmt( pObj );
	if( pFmt && FLY_AT_FLY == pFmt->GetAnchor().GetAnchorId() )
	{
        const SwFrm* pFly = pObj->ISA(SwVirtFlyDrawObj) ?
            ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm() :
            ((SwDrawContact*)GetUserCall(pObj))->GetAnchorFrm( pObj );
		ASSERT( pFly, "IsFlyInFly: Where's my anchor?" );
		ASSERT( pFly->IsFlyFrm(), "IsFlyInFly: Funny anchor!" );
		return ((SwFlyFrm*)pFly)->GetFmt();
	}

	Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft();

	SwFrm *pTxtFrm;
	{
		SwCrsrMoveState aState( MV_SETONLYTEXT );
		SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() );
		SwPosition aPos( aSwNodeIndex );
		Point aPoint( aTmpPos );
		aPoint.X() -= 1;					//nicht im Fly landen!!
		GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
        // OD 01.07.2003 #108784# - determine text frame by left-top-corner
        // of object
        //pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->GetFrm( 0, 0, sal_False );
        pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aTmpPos, 0, sal_False );
	}
	const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aTmpPos );
	const SwFlyFrm *pFly = pTmp->FindFlyFrm();
	if( pFly )
		return pFly->GetFmt();
	return NULL;
}

/*************************************************************************
|*
|*	SwFEShell::SetFlyPos
|*
|*	Ersterstellung		MA 14. Jan. 93
|*	Letzte Aenderung	MA 14. Feb. 95
|*
*************************************************************************/

void SwFEShell::SetFlyPos( const Point& rAbsPos )
{
	SET_CURR_SHELL( this );

	//Bezugspunkt in Dokumentkoordinaten bestimmen
	SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
	if( !pCntnt )
		return;
	SwFlyFrm *pFly = pCntnt->FindFlyFrm();
	if ( !pFly )
		return;

	//SwSaveHdl aSaveX( Imp() );

	//Bei Absatzgebundenen Flys muss ausgehend von der absoluten
	//Position ein neuer Anker gesetzt werden. Anker und neue RelPos werden
	//vom Fly selbst berechnet und gesetzt.
	if ( pFly->IsFlyAtCntFrm() )
		((SwFlyAtCntFrm*)pFly)->SetAbsPos( rAbsPos );
	else
	{
            const SwFrm *pAnch = pFly->GetAnchorFrm();
            // --> OD 2004-06-11 #i28701# - no format here
//          pAnch->Calc();
            Point aOrient( pAnch->Frm().Pos() );

		if ( pFly->IsFlyInCntFrm() )
			aOrient.X() = rAbsPos.X();

		//RelPos errechnen.
		aOrient.X() = rAbsPos.X() - aOrient.X();
		aOrient.Y() = rAbsPos.Y() - aOrient.Y();
		pFly->ChgRelPos( aOrient );
	}
    // --> OD 2004-06-11 #i28701# - no format here
//    pFly->Calc();
	CallChgLnk();		// rufe das AttrChangeNotify auf der UI-Seite.
}

/*************************************************************************
|*
|*	SwFEShell::FindAnchorPos
|*
|*	Ersterstellung		AMA 24. Sep. 97
|*	Letzte Aenderung	AMA 24. Sep. 97
|*
*************************************************************************/

Point SwFEShell::FindAnchorPos( const Point& rAbsPos, sal_Bool bMoveIt )
{
    Point aRet;

	SET_CURR_SHELL( this );

	if ( !Imp()->HasDrawView() )
		return aRet;

	const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
	if ( rMrkList.GetMarkCount() != 1 ||
		 !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) )
		return aRet;

    SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
    // --> OD 2004-07-16 #i28701#
    SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
    SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
    const RndStdIds nAnchorId = rFmt.GetAnchor().GetAnchorId();

    if ( FLY_AS_CHAR == nAnchorId )
		return aRet;

	sal_Bool bFlyFrame = pObj->ISA(SwVirtFlyDrawObj);

    SwFlyFrm* pFly = 0L;
    const SwFrm* pOldAnch;
	const SwFrm* pFooterOrHeader = NULL;

	if( bFlyFrame )
	{
		//Bezugspunkt in Dokumentkoordinaten bestimmen
		SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
		if( !pCntnt )
			return aRet;
		pFly = pCntnt->FindFlyFrm();
		if ( !pFly )
			return aRet;
        pOldAnch = pFly->GetAnchorFrm();
		if( !pOldAnch )
			return aRet;
        if ( FLY_AT_PAGE != nAnchorId )
        {
			pFooterOrHeader = pCntnt->FindFooterOrHeader();
        }
	}
    // OD 26.06.2003 #108784# - set <pFooterOrHeader> also for drawing
    // objects, but not for control objects.
    // Necessary for moving 'anchor symbol' at the user interface inside header/footer.
    else if ( !::CheckControlLayer( pObj ) )
    {
        SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
        if( !pCntnt )
            return aRet;
        pFooterOrHeader = pCntnt->FindFooterOrHeader();
    }

    SwCntntFrm *pTxtFrm = NULL;
    {
        SwCrsrMoveState aState( MV_SETONLYTEXT );
        SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() );
        Point aTmpPnt( rAbsPos );
        GetLayout()->GetCrsrOfst( &aPos, aTmpPnt, &aState );
        if ( nAnchorId != FLY_AT_CHAR
             || !PosInsideInputFld( aPos ) )
        {
            pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(),0,&aPos,sal_False );
        }
    }
    const SwFrm *pNewAnch = NULL;
    if( pTxtFrm != NULL )
    {
        if ( FLY_AT_PAGE == nAnchorId )
        {
            pNewAnch = pTxtFrm->FindPageFrm();
        }
        else
        {
            pNewAnch = ::FindAnchor( pTxtFrm, rAbsPos );

            if( FLY_AT_FLY == nAnchorId ) // LAYER_IMPL
            {
                pNewAnch = pNewAnch->FindFlyFrm();
            }
        }
    }

	if( pNewAnch && !pNewAnch->IsProtected() )
	{
		const SwFlyFrm* pCheck = bFlyFrame ? pNewAnch->FindFlyFrm() : 0;
		// Falls wir innerhalb eines Rahmens landen, muss sichergestellt werden,
		// dass der Rahmen nicht in seinem eigenen Inhalt landet!
		while( pCheck )
		{
			if( pCheck == pFly )
				break;
            const SwFrm *pTmp = pCheck->GetAnchorFrm();
			pCheck = pTmp ? pTmp->FindFlyFrm() : NULL;
		}
		// Es darf nicht aus einer Kopf-/Fusszeile in einen anderen Bereich
		// gewechselt werden, es darf nicht in eine Kopf-/Fusszeile hinein-
		// gewechselt werden.
		if( !pCheck &&
			pFooterOrHeader == pNewAnch->FindFooterOrHeader() )
		{
            aRet = pNewAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );

            if ( bMoveIt || (nAnchorId == FLY_AT_CHAR) )
            {
                SwFmtAnchor aAnch( rFmt.GetAnchor() );
				switch ( nAnchorId )
                {
                    case FLY_AT_PARA:
                    {
						SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
						pPos->nNode = *pTxtFrm->GetNode();
						pPos->nContent.Assign(0,0);
						break;
                    }
                    case FLY_AT_PAGE:
                    {
						aAnch.SetPageNum( ((const SwPageFrm*)pNewAnch)->
										  GetPhyPageNum() );
						break;
					}

					case FLY_AT_FLY:
					{
						SwPosition aPos( *((SwFlyFrm*)pNewAnch)->GetFmt()->
												  GetCntnt().GetCntntIdx() );
						aAnch.SetAnchor( &aPos );
						break;
                    }

                    case FLY_AT_CHAR:
                        {
                            SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
                            Point aTmpPnt( rAbsPos );
                            if( pTxtFrm->GetCrsrOfst( pPos, aTmpPnt, NULL ) )
                            {
                                SwRect aTmpRect;
                                pTxtFrm->GetCharRect( aTmpRect, *pPos );
                                aRet = aTmpRect.Pos();
                            }
                            else
                            {
                                pPos->nNode = *pTxtFrm->GetNode();
                                pPos->nContent.Assign(0,0);
                            }
                            break;
                        }
                    default:
                        break;

                }

                if( bMoveIt )
                {
                    StartAllAction();
                    // --> OD 2006-02-28 #125892#
                    // handle change of anchor node:
                    // if count of the anchor frame also change, the fly frames have to be
                    // re-created. Thus, delete all fly frames except the <this> before the
                    // anchor attribute is change and re-create them afterwards.
                    {
                        SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L );
                        SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) );
                        if ( pFlyFrmFmt )
                        {
                            pHandleAnchorNodeChg =
                                new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch );
                        }
                        rFmt.GetDoc()->SetAttr( aAnch, rFmt );
                        delete pHandleAnchorNodeChg;
                    }
                    // <--
                    // --> OD 2004-06-24 #i28701# - no call of method
                    // <CheckCharRectAndTopOfLine()> for to-character anchored
                    // Writer fly frame needed. This method call can cause a
                    // format of the anchor frame, which is no longer intended.
                    // Instead clear the anchor character rectangle and
                    // the top of line values for all to-character anchored objects.
                    pAnchoredObj->ClearCharRectAndTopOfLine();
                    // <--
					EndAllAction();
				}
			}

			SwRect aTmpRect( aRet, rAbsPos );
			if( aTmpRect.HasArea() )
				MakeVisible( aTmpRect );
#ifdef DBG_UTIL
			//TODO: That doesn't seem to be intended
			if( Color(COL_TRANSPARENT) != GetOut()->GetLineColor() )
			{
				ASSERT( sal_False, "Hey, Joe: Where's my Null Pen?" );
				GetOut()->SetLineColor( Color(COL_TRANSPARENT) );
			}
#endif
		}
	}

	return aRet;
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  NewFlyFrm
#*	Beschreibung:
#*	Datum	   	:  MA 03. Nov. 92
#*	Update	   	:  JP 11. Aug. 93
#***********************************************************************/

const SwFrmFmt *SwFEShell::NewFlyFrm( const SfxItemSet& rSet, sal_Bool bAnchValid,
						   SwFrmFmt *pParent )
{
	SET_CURR_SHELL( this );
	StartAllAction();

	SwPaM* pCrsr = GetCrsr();
    const Point aPt( GetCrsrDocPos() );

	SwSelBoxes aBoxes;
	sal_Bool bMoveCntnt = sal_True;
	if( IsTableMode() )
	{
		GetTblSel( *this, aBoxes );
		if( aBoxes.Count() )
		{
			// die Crsr muessen noch aus dem Loeschbereich entfernt
			// werden. Setze sie immer hinter/auf die Tabelle; ueber die
			// Dokument-Position werden sie dann immer an die alte
			// Position gesetzt.
			ParkCrsr( SwNodeIndex( *aBoxes[0]->GetSttNd() ));

            // --> FME 2005-12-01 #i127787# pCurCrsr will be deleted in ParkCrsr,
            // we better get the current pCurCrsr instead of working with the
            // deleted one:
            pCrsr = GetCrsr();
            // <--

//          KillPams();
		}
		else
			bMoveCntnt = sal_False;
	}
	else if( !pCrsr->HasMark() && pCrsr->GetNext() == pCrsr )
		bMoveCntnt = sal_False;

    const SwPosition& rPos = *pCrsr->Start();

    SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
	RndStdIds eRndId = rAnch.GetAnchorId();
	switch( eRndId )
	{
    case FLY_AT_PAGE:
		if( !rAnch.GetPageNum() )		//HotFix: Bug in UpdateByExample
			rAnch.SetPageNum( 1 );
		break;

    case FLY_AT_FLY:
    case FLY_AT_PARA:
    case FLY_AT_CHAR:
    case FLY_AS_CHAR:
		if( !bAnchValid )
		{
			if( FLY_AT_FLY != eRndId )
            {
				rAnch.SetAnchor( &rPos );
            }
			else if( lcl_SetNewFlyPos( rPos.nNode.GetNode(), rAnch, aPt ) )
            {
                eRndId = FLY_AT_PAGE;
            }
		}
		break;

    default:
        ASSERT( !this, "Was sollte das fuer ein Fly werden?" )
        break;
    }

	SwFlyFrmFmt *pRet;
	if( bMoveCntnt )
	{
        GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
		SwFmtAnchor* pOldAnchor = 0;
		sal_Bool bHOriChgd = sal_False, bVOriChgd = sal_False;
		SwFmtVertOrient aOldV;
		SwFmtHoriOrient aOldH;

        if ( FLY_AT_PAGE != eRndId )
        {
			// erstmal als mit Seitenbindung, Absatz/Zeichenbindung erst wenn
			// alles verschoben ist. Dann ist die Position gueltig!
			// JP 13.05.98: ggfs. auch noch die Hori/Vert-Orientierung
			//				umsetzen, damit diese beim Umanker NICHT
			//				korrigiert wird
			pOldAnchor = new SwFmtAnchor( rAnch );
            const_cast<SfxItemSet&>(rSet).Put( SwFmtAnchor( FLY_AT_PAGE, 1 ) );

			const SfxPoolItem* pItem;
			if( SFX_ITEM_SET == rSet.GetItemState( RES_HORI_ORIENT, sal_False, &pItem )
                && text::HoriOrientation::NONE == ((SwFmtHoriOrient*)pItem)->GetHoriOrient() )
			{
				bHOriChgd = sal_True;
				aOldH = *((SwFmtHoriOrient*)pItem);
                ((SfxItemSet&)rSet).Put( SwFmtHoriOrient( 0, text::HoriOrientation::LEFT ) );
			}
			if( SFX_ITEM_SET == rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem )
                && text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() )
			{
				bVOriChgd = sal_True;
				aOldV = *((SwFmtVertOrient*)pItem);
                ((SfxItemSet&)rSet).Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ) );
			}
		}

		pRet = GetDoc()->MakeFlyAndMove( *pCrsr, rSet, &aBoxes, pParent );

		KillPams();

		if( pOldAnchor )
		{
			if( pRet )
			{
				// neue Position bestimmen
				//JP 24.03.97: immer ueber die Seitenbindung gehen - der
				//			 chaos::Anchor darf nie	im verschobenen Bereich
				//				liegen
				pRet->DelFrms();

				const SwFrm* pAnch = ::FindAnchor( GetLayout(), aPt, sal_False );
				SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() );
                if ( FLY_AS_CHAR == eRndId )
                {
					aPos.nContent.Assign( ((SwCntntFrm*)pAnch)->GetNode(), 0 );
                }
				pOldAnchor->SetAnchor( &aPos );

				// das verschieben von TabelleSelektion ist noch nicht
				// Undofaehig - also darf das UmAnkern auch nicht
				// aufgezeichnet werden.
                bool const bDoesUndo =
                    GetDoc()->GetIDocumentUndoRedo().DoesUndo();
                SwUndoId nLastUndoId(UNDO_EMPTY);
                if (bDoesUndo &&
                    GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(0,
                        & nLastUndoId))
                {
                    if (UNDO_INSLAYFMT == nLastUndoId)
                    {
                        GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
                    }
                }

				((SfxItemSet&)rSet).Put( *pOldAnchor );

				if( bHOriChgd )
					((SfxItemSet&)rSet).Put( aOldH );
				if( bVOriChgd )
					((SfxItemSet&)rSet).Put( aOldV );

				GetDoc()->SetFlyFrmAttr( *pRet, (SfxItemSet&)rSet );
                GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
            }
			delete pOldAnchor;
		}
        GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
    }
    else
        /* #109161# If called from a shell try to propagate an
            existing adjust item from rPos to the content node of the
            new frame. */
		pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, sal_True );

	if( pRet )
	{
		SwFlyFrm* pFrm = pRet->GetFrm( &aPt );
		if( pFrm )
			SelectFlyFrm( *pFrm, sal_True );
		else
		{
			GetLayout()->SetAssertFlyPages();
			pRet = 0;
		}
	}
	EndAllActionAndCall();

	return pRet;
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  Insert
#*	Datum	   	:  ??
#*	Update	   	:  MA 12. Sep. 94
#***********************************************************************/

void SwFEShell::Insert( const String& rGrfName, const String& rFltName,
						const Graphic* pGraphic,
						const SfxItemSet* pFlyAttrSet,
						const SfxItemSet* pGrfAttrSet,
						SwFrmFmt* pFrmFmt )
{
	SwFlyFrmFmt* pFmt = 0;
	SET_CURR_SHELL( this );
	StartAllAction();
    SwShellCrsr *pStartCursor = dynamic_cast<SwShellCrsr*>(this->GetSwCrsr());
    SwShellCrsr *pCursor = pStartCursor;
    do {

		// Anker noch nicht oder unvollstaendig gesetzt ?
		if( pFlyAttrSet )
		{
			const SfxPoolItem* pItem;
			if( SFX_ITEM_SET == pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
					&pItem ) )
			{
				SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
				switch( pAnchor->GetAnchorId())
				{
                case FLY_AT_PARA:
                case FLY_AT_CHAR: // LAYER_IMPL
                case FLY_AS_CHAR:
					if( !pAnchor->GetCntntAnchor() )
                    {
                        pAnchor->SetAnchor( pCursor->GetPoint() );
                    }
					break;
				case FLY_AT_FLY:
					if( !pAnchor->GetCntntAnchor() )
                    {
                        lcl_SetNewFlyPos( *pCursor->GetNode(),
                                *pAnchor, GetCrsrDocPos() );
                    }
					break;
                case FLY_AT_PAGE:
					if( !pAnchor->GetPageNum() )
					{
                        pAnchor->SetPageNum( pCursor->GetPageNum(
                                sal_True, &pCursor->GetPtPos() ) );
					}
					break;
                default :
                    break;
                }
            }
		}
        pFmt = GetDoc()->Insert(*pCursor, rGrfName,
								rFltName, pGraphic,
								pFlyAttrSet,
								pGrfAttrSet, pFrmFmt );
		ASSERT( pFmt, "Doc->Insert(notxt) failed." );

    } while( (pCursor = dynamic_cast<SwShellCrsr*>(pCursor->GetNext()))
             != pStartCursor );

	EndAllAction();

	if( pFmt )
	{
		const Point aPt( GetCrsrDocPos() );
		SwFlyFrm* pFrm = pFmt->GetFrm( &aPt );

		if( pFrm )
			SelectFlyFrm( *pFrm, sal_True );
		else
			GetLayout()->SetAssertFlyPages();
	}
}

SwFlyFrmFmt* SwFEShell::InsertObject( const svt::EmbeddedObjectRef&  xObj,
						const SfxItemSet* pFlyAttrSet,
						const SfxItemSet* pGrfAttrSet,
						SwFrmFmt* pFrmFmt )
{
	SwFlyFrmFmt* pFmt = 0;
	SET_CURR_SHELL( this );
	StartAllAction();
		FOREACHPAM_START( this )
            pFmt = GetDoc()->Insert(*PCURCRSR, xObj,
									pFlyAttrSet, pGrfAttrSet, pFrmFmt );
			ASSERT( pFmt, "Doc->Insert(notxt) failed." );

		FOREACHPAM_END()
	EndAllAction();

	if( pFmt )
	{
		const Point aPt( GetCrsrDocPos() );
		SwFlyFrm* pFrm = pFmt->GetFrm( &aPt );

		if( pFrm )
			SelectFlyFrm( *pFrm, sal_True );
		else
			GetLayout()->SetAssertFlyPages();
	}

    return pFmt;
}


void SwFEShell::InsertDrawObj( SdrObject& rDrawObj,
                               const Point& rInsertPosition )
{
	SET_CURR_SHELL( this );

    SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange );
    rFlyAttrSet.Put( SwFmtAnchor( FLY_AT_PARA ));
    // --> OD 2009-12-29 #i89920#
    rFlyAttrSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
    rDrawObj.SetLayer( getIDocumentDrawModelAccess()->GetHeavenId() );
    // <--

    // find anchor position
    SwPaM aPam( pDoc->GetNodes() );
    {
        SwCrsrMoveState aState( MV_SETONLYTEXT );
        Point aTmpPt( rInsertPosition );
        GetLayout()->GetCrsrOfst( aPam.GetPoint(), aTmpPt, &aState );
        const SwFrm* pFrm = aPam.GetCntntNode()->getLayoutFrm( GetLayout(), 0, 0, sal_False );
        const Point aRelPos( rInsertPosition.X() - pFrm->Frm().Left(),
                             rInsertPosition.Y() - pFrm->Frm().Top() );
        rDrawObj.SetRelativePos( aRelPos );
        ::lcl_FindAnchorPos( *this, *GetDoc(), rInsertPosition, *pFrm, rFlyAttrSet );
    }
    // insert drawing object into the document creating a new <SwDrawFrmFmt> instance
    SwDrawFrmFmt* pFmt = GetDoc()->InsertDrawObj( aPam, rDrawObj, rFlyAttrSet );

    // move object to visible layer
    SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall());
    if ( pContact )
    {
        pContact->MoveObjToVisibleLayer( &rDrawObj );
    }

    if ( pFmt )
    {
        // select drawing object
		Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView(),
                                       sal_False, sal_False );
    }
	else
    {
		GetLayout()->SetAssertFlyPages();
    }
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  GetPageObjs
#*	Datum	   	:  ??
#*	Update	   	:  MA 11. Jan. 95
#***********************************************************************/

void SwFEShell::GetPageObjs( SvPtrarr& rFillArr )
{
	if( rFillArr.Count() )
		rFillArr.Remove( 0, rFillArr.Count() );

	const SwFrmFmt* pFmt;
	for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
	{
		pFmt = (const SwFrmFmt*)(*pDoc->GetSpzFrmFmts())[n];
        if (FLY_AT_PAGE == pFmt->GetAnchor().GetAnchorId())
        {
			rFillArr.Insert( (VoidPtr)pFmt, rFillArr.Count() );
        }
	}
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  SetPageFlysNewPage
#*	Datum	   	:  ??
#*	Update	   	:  MA 14. Feb. 95
#***********************************************************************/

void SwFEShell::SetPageObjsNewPage( SvPtrarr& rFillArr, int nOffset )
{
	if( !rFillArr.Count() || !nOffset )
		return;

	StartAllAction();
	StartUndo();

	SwFrmFmt* pFmt;
	long nNewPage;
    SwRootFrm* pTmpRootFrm = GetLayout();//swmod 080317
    sal_uInt16 nMaxPage = pTmpRootFrm->GetPageNum();
	sal_Bool bTmpAssert = sal_False;
	for( sal_uInt16 n = 0; n < rFillArr.Count(); ++n )
	{
		pFmt = (SwFrmFmt*)rFillArr[n];
		if( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( pFmt ))
		{
			// FlyFmt ist noch gueltig, also behandeln
			SwFmtAnchor aNewAnchor( pFmt->GetAnchor() );
            if ((FLY_AT_PAGE != aNewAnchor.GetAnchorId()) ||
				0 >= ( nNewPage = aNewAnchor.GetPageNum() + nOffset ) )
				// chaos::Anchor wurde veraendert oder ungueltige SeitenNummer,
				// also nicht veraendern !!
				continue;

			if( sal_uInt16(nNewPage) > nMaxPage )
			{
				if ( RES_DRAWFRMFMT == pFmt->Which() )
				{
					SwContact *pCon = pFmt->FindContactObj();
					if( pCon )
						((SwDrawContact*)pCon)->DisconnectFromLayout();
				}
				else
					pFmt->DelFrms();
				bTmpAssert = sal_True;
			}
			aNewAnchor.SetPageNum( sal_uInt16(nNewPage) );
			pDoc->SetAttr( aNewAnchor, *pFmt );
		}
	}

	if( bTmpAssert )
        pTmpRootFrm->SetAssertFlyPages();

	EndUndo();
	EndAllAction();
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  GetFlyFrmAttr
#*	Beschreibung:  Alle Attribute in dem 'Koerbchen' werden mit den
#*				   Attributen des aktuellen FlyFrms gefuellt.
#*				   Sind Attribute nicht zu fuellen weil fehl am Platz oder
#* 				   uneindeutig (Mehrfachtselektionen) so werden sie entfernt.
#*	Datum	   	:  MA 03. Nov. 92
#*	Update	   	:  MA 03. Feb. 94
#***********************************************************************/

sal_Bool SwFEShell::GetFlyFrmAttr( SfxItemSet &rSet ) const
{
	SwFlyFrm *pFly = FindFlyFrm();
	if ( !pFly )
	{
        // --> OD 2006-11-08 #139670# - make code robust
        SwFrm* pCurrFrm( GetCurrFrm() );
        if ( !pCurrFrm )
        {
            ASSERT( false,
                    "<SwFEShell::GetFlyFrmAttr(..)> - missing current frame. This is a serious defect, please inform OD." );
            return sal_False;
        }
        // <--
		pFly = GetCurrFrm()->FindFlyFrm();
		if ( !pFly )
		{
			ASSERT( !this, "GetFlyFrmAttr, no Fly selected." );
			return sal_False;
		}
	}

	SET_CURR_SHELL( (ViewShell*)this );

	if( !rSet.Set( pFly->GetFmt()->GetAttrSet(), sal_True ) )
		return sal_False;

	//Und die Attribute durchschaufeln. Unerlaubte Attribute entfernen, dann
	//alle restlichen Attribute besorgen und eintragen.
	const SfxPoolItem* pItem;
	if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False, &pItem ) )
	{
		SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
		RndStdIds eType = pAnchor->GetAnchorId();

        if ( FLY_AT_PAGE != eType )
        {
            // OD 12.11.2003 #i22341# - content anchor of anchor item is needed.
            // Thus, don't overwrite anchor item by default contructed anchor item.
            //rSet.Put( SwFmtAnchor( eType ) );
            if ( FLY_AS_CHAR == eType )
            {
				rSet.ClearItem( RES_OPAQUE );
				rSet.ClearItem( RES_SURROUND );
			}
		}
	}
	rSet.SetParent( pFly->GetFmt()->GetAttrSet().GetParent() );
	//JP 11.02.97: Bug #35894#: die Attribute MUESSEN entfern werden!
	rSet.ClearItem( RES_FILL_ORDER );
	rSet.ClearItem( RES_CNTNT );
	//MA: Ersteinmal entfernen (Template by example usw.)
	rSet.ClearItem( RES_CHAIN );
	return sal_True;
}
/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  SetFlyFrmAttr
#*	Beschreibung:  Die Attribute des aktuellen Flys aendern sich.
#*	Datum	   	:  MA 03. Nov. 92
#*	Update	   	:  MA 01. Aug. 95
#***********************************************************************/

sal_Bool SwFEShell::SetFlyFrmAttr( SfxItemSet& rSet )
{
	SET_CURR_SHELL( this );
	sal_Bool bRet = sal_False;

	if( rSet.Count() )
	{
		SwFlyFrm *pFly = FindFlyFrm();
		if( !pFly )
		{
			ASSERT( GetCurrFrm(), "Crsr in parking zone" );
			pFly = GetCurrFrm()->FindFlyFrm();
			ASSERT( pFly, "SetFlyFrmAttr, no Fly selected." );
		}
		if( pFly )
		{
			StartAllAction();
			const Point aPt( pFly->Frm().Pos() );

			if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
				::lcl_ChkAndSetNewAnchor( *this, *pFly, rSet );
			SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt();

			if( GetDoc()->SetFlyFrmAttr( *pFlyFmt, rSet ))
			{
				bRet = sal_True;
				SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt );
				if( pFrm )
					SelectFlyFrm( *pFrm, sal_True );
				else
					GetLayout()->SetAssertFlyPages();
			}

			EndAllActionAndCall();
		}
	}
	return bRet;
}
/*-- 30.03.2004 15:05:07---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet )
{
    sal_Bool bRet = sal_False;
    SET_CURR_SHELL( this );
    if ( !rSet.Count() ||
            !Imp()->HasDrawView() )
        return bRet;

    const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
    if ( rMrkList.GetMarkCount() != 1 )
        return bRet;

    StartUndo();
    SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
    SwFrmFmt *pFmt = FindFrmFmt( pObj );
    StartAllAction();
    if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
    {
        RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId();
        if ( nNew != pFmt->GetAnchor().GetAnchorId() )
        {
            ChgAnchor( nNew );
            // --> OD 2004-06-17 #i26791# - clear anchor attribute in item set,
            // because method <ChgAnchor(..)> takes care of it.
            rSet.ClearItem( RES_ANCHOR );
        }
    }

    if( GetDoc()->SetFlyFrmAttr( *pFmt, rSet ))
    {
        bRet = sal_True;
        Point aTmp;
        SelectObj( aTmp, 0, pObj );
    }
    EndAllActionAndCall();
    EndUndo();
    return bRet;
}


/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  ResetFlyFrmAttr
#*	Beschreibung:  Das gewuenschte Attribut oder die im Set befindlichen
#*					werden zurueckgesetzt.
#*	Datum	   	:  MA 14. Mar. 97
#*	Update	   	:  MA 14. Mar. 97
#***********************************************************************/

sal_Bool SwFEShell::ResetFlyFrmAttr( sal_uInt16 nWhich, const SfxItemSet* pSet )
{
	sal_Bool bRet = sal_False;

	if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich )
	{
		SET_CURR_SHELL( this );

		SwFlyFrm *pFly = FindFlyFrm();
		if( !pFly )
		{
			ASSERT( GetCurrFrm(), "Crsr in parking zone" );
			pFly = GetCurrFrm()->FindFlyFrm();
			ASSERT( pFly, "SetFlyFrmAttr, no Fly selected." );
		}

		if( pFly )
		{
			StartAllAction();

			if( pSet )
			{
				SfxItemIter aIter( *pSet );
				const SfxPoolItem* pItem = aIter.FirstItem();
				while( pItem )
				{
					if( !IsInvalidItem( pItem ) &&
						RES_ANCHOR != ( nWhich = pItem->Which() ) &&
						RES_CHAIN != nWhich && RES_CNTNT != nWhich )
                        pFly->GetFmt()->ResetFmtAttr( nWhich );
					pItem = aIter.NextItem();
				}
			}
			else
                pFly->GetFmt()->ResetFmtAttr( nWhich );

			bRet = sal_True;
			EndAllActionAndCall();
			GetDoc()->SetModified();
		}
	}
	return bRet;
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  GetCurFrmFmt
#*	Beschreibung:  liefert wenn Rahmen, dann Rahmenvorlage, sonst 0
#*	Datum	   	:  ST 04. Jun. 93
#*	Update	   	:
#***********************************************************************/

SwFrmFmt* SwFEShell::GetCurFrmFmt() const
{
	SwFrmFmt* pRet = 0;
	SwLayoutFrm *pFly = FindFlyFrm();
	if( pFly && ( pRet = (SwFrmFmt*)pFly->GetFmt()->DerivedFrom() ) ==
											GetDoc()->GetDfltFrmFmt() )
		pRet = 0;
	return pRet;
}

/******************************************************************************
 *	Methode		:	void SwFEShell::SetFrmFmt(SwFrmFmt *pNewFmt)
 *	Beschreibung:
 *	Erstellt	:	OK 14.04.94 15:40
 *	Aenderung	:	MA 23. Apr. 97
 ******************************************************************************/

void SwFEShell::SetFrmFmt( SwFrmFmt *pNewFmt, sal_Bool bKeepOrient, Point* pDocPos )
{
	SwFlyFrm *pFly = 0;
	if(pDocPos)
	{
		const SwFrmFmt* pFmt = GetFmtFromObj( *pDocPos );

		if(PTR_CAST(SwFlyFrmFmt, pFmt))
			pFly = ((SwFlyFrmFmt*)pFmt)->GetFrm();
	}
	else
		pFly = FindFlyFrm();
	ASSERT( pFly, "SetFrmFmt: kein Frame" );
	if( pFly )
	{
		StartAllAction();
		SET_CURR_SHELL( this );

		SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt();
		const Point aPt( pFly->Frm().Pos() );

		SfxItemSet* pSet = 0;
		const SfxPoolItem* pItem;
		if( SFX_ITEM_SET == pNewFmt->GetItemState( RES_ANCHOR, sal_False, &pItem ))
		{
			pSet = new SfxItemSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange );
			pSet->Put( *pItem );
			if( !::lcl_ChkAndSetNewAnchor( *this, *pFly, *pSet ))
				delete pSet, pSet = 0;
		}

		if( GetDoc()->SetFrmFmtToFly( *pFlyFmt, *pNewFmt, pSet, bKeepOrient ))
		{
			SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt );
			if( pFrm )
				SelectFlyFrm( *pFrm, sal_True );
			else
				GetLayout()->SetAssertFlyPages();
		}
		if( pSet )
			delete pSet;

		EndAllActionAndCall();
	}
}

/*************************************************************************
|*
|*	SwFEShell::GetFlyFrmFmt()
|*
|*	Ersterstellung		OK 23.06.93 13:15
|*	Letzte Aenderung	OK 23.06.93 13:15
|*
*************************************************************************/

const SwFrmFmt* SwFEShell::GetFlyFrmFmt() const
{
	const SwFlyFrm* pFly = FindFlyFrm();
	if ( !pFly )
    {
        SwFrm* pCurrFrm = GetCurrFrm();
		pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0;
    }
	if( pFly )
		return pFly->GetFmt();
	return 0;
}

SwFrmFmt* SwFEShell::GetFlyFrmFmt()
{
	SwFlyFrm* pFly = FindFlyFrm();
	if ( !pFly )
    {
        SwFrm* pCurrFrm = GetCurrFrm();
		pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0;
    }
	if( pFly )
		return pFly->GetFmt();
	return 0;
}

/*************************************************************************
|*
|*	SwFEShell::GetFlyRect()
|*
|*	Ersterstellung		AMA 6. Mae. 97
|*	Letzte Aenderung	AMA 6. Mae. 97
|*
*************************************************************************/

SwRect SwFEShell::GetFlyRect() const
{
	SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
	SwFlyFrm *pFly = pCntnt ? pCntnt->FindFlyFrm() : 0;
	if ( !pFly )
	{
		SwRect aRect;
		return aRect;
	}
	else
		return pFly->Frm();
}

/*************************************************************************
|*
|*	SwFEShell::GetObjRect()
|*
|*	Ersterstellung		MA 22. Aug. 93
|*	Letzte Aenderung	MA 11. Jan. 95
|*
*************************************************************************/

SwRect SwFEShell::GetObjRect() const
{
	if( Imp()->HasDrawView() )
		return Imp()->GetDrawView()->GetAllMarkedRect();
	else
	{
		SwRect aRect;
		return aRect;
	}
}

void SwFEShell::SetObjRect( const SwRect& rRect )
{
	if ( Imp()->HasDrawView() )
	{
		Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() );
		CallChgLnk();	// rufe das AttrChangeNotify auf der UI-Seite.
	}
}

/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  RequestObjectResize()
#*	Datum	   	:  MA 10. Feb. 95
#*	Update	   	:  MA 13. Jul. 95
#***********************************************************************/

Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj )
{
	Size aResult;

    SwFlyFrm *pFly = FindFlyFrm( xObj );
	if ( !pFly )
	{
		aResult = rRect.SSize();
		return aResult;
	}

	aResult = pFly->Prt().SSize();

	sal_Bool bPosProt = pFly->GetFmt()->GetProtect().IsPosProtected();
	sal_Bool bSizeProt = pFly->GetFmt()->GetProtect().IsSizeProtected();

	StartAllAction();

	//MA wir lassen den Fly nicht Clippen, damit die Ole-Server mit
	//beliebigen Wuenschen kommen koennen. Die Formatierung uebernimmt das
	//Clippen. Die richtige Darstellung wird per Scalierung erledigt.
	//Die Scalierung wird von SwNoTxtFrm::Format durch einen Aufruf von
	//SwWrtShell::CalcAndSetScale() erledigt.
	if ( rRect.SSize() != pFly->Prt().SSize() && !bSizeProt )
	{
	 	Size aSz( rRect.SSize() );

		//JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size
		//
		const SwFrm* pAnchor;
		const SwTxtNode* pTNd;
		const SwpHints* pHts;
		const SwFmtFrmSize& rFrmSz = pFly->GetFmt()->GetFrmSize();
		if( bCheckForOLEInCaption &&
			0 != rFrmSz.GetWidthPercent() &&
            0 != (pAnchor = pFly->GetAnchorFrm()) &&
			pAnchor->IsTxtFrm() &&
			!pAnchor->GetNext() && !pAnchor->GetPrev() &&
			pAnchor->GetUpper()->IsFlyFrm() &&
			0 != ( pTNd = ((SwTxtFrm*)pAnchor)->GetNode()->GetTxtNode()) &&
			0 != ( pHts = pTNd->GetpSwpHints() ))
		{
			// search for a sequence field:
			const SfxPoolItem* pItem;
			for( sal_uInt16 n = 0, nEnd = pHts->Count(); n < nEnd; ++n )
				if( RES_TXTATR_FIELD == ( pItem = &(*pHts)[ n ]->GetAttr())->Which()
                    && TYP_SEQFLD == ((SwFmtFld*)pItem)->GetField()->GetTypeId() )
				{
					// sequence field found
					SwFlyFrm* pChgFly = (SwFlyFrm*)pAnchor->GetUpper();
					// calculate the changed size:
					// width must change, height can change
					Size aNewSz( aSz.Width() + pChgFly->Frm().Width() -
								   pFly->Prt().Width(), aSz.Height() );

					SwFrmFmt *pFmt = pChgFly->GetFmt();
					SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
					aFrmSz.SetWidth( aNewSz.Width() );
                    if( ATT_MIN_SIZE != aFrmSz.GetHeightSizeType() )
					{
						aNewSz.Height() += pChgFly->Frm().Height() -
								   			pFly->Prt().Height();
						if( Abs( aNewSz.Height() - pChgFly->Frm().Height()) > 1 )
							aFrmSz.SetHeight( aNewSz.Height() );
					}
					// uebers Doc fuers Undo!
					pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
					break;
				}
		}

		// set the new Size at the fly themself
		if ( pFly->Prt().Height() > 0 && pFly->Prt().Width() > 0 )
		{
			aSz.Width() += pFly->Frm().Width() - pFly->Prt().Width();
			aSz.Height()+= pFly->Frm().Height()- pFly->Prt().Height();
		}
		aResult = pFly->ChgSize( aSz );

		//Wenn sich das Objekt aendert ist die Kontur hoechstwahrscheinlich daneben.
		ASSERT( pFly->Lower()->IsNoTxtFrm(), "Request ohne NoTxt" );
		SwNoTxtNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetNoTxtNode();
		ASSERT( pNd, "Request ohne Node" );
		pNd->SetContour( 0 );
		ClrContourCache();
	}

	//Wenn nur die Size angepasst werden soll, so wird eine Pos mit
	//ausgezeichneten Werten transportiert.
	Point aPt( pFly->Prt().Pos() );
	aPt += pFly->Frm().Pos();
	if ( rRect.Top() != LONG_MIN && rRect.Pos() != aPt && !bPosProt )
	{
		aPt = rRect.Pos();
		aPt.X() -= pFly->Prt().Left();
		aPt.Y() -= pFly->Prt().Top();
		//Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein
		//neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly
		//selbst berechnet und gesetzt.
		if( pFly->IsFlyAtCntFrm() )
			((SwFlyAtCntFrm*)pFly)->SetAbsPos( aPt );
		else
		{
			const SwFrmFmt *pFmt = pFly->GetFmt();
			const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
			const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
			const long lXDiff = aPt.X() - pFly->Frm().Left();
			const long lYDiff = aPt.Y() - pFly->Frm().Top();
			const Point aTmp( rHori.GetPos() + lXDiff,
							  rVert.GetPos() + lYDiff );
			pFly->ChgRelPos( aTmp );
		}
	}

    SwFlyFrmFmt *pFlyFrmFmt = pFly->GetFmt();
    ASSERT( pFlyFrmFmt, "fly frame format missing!" );
    if ( pFlyFrmFmt )
        pFlyFrmFmt->SetLastFlyFrmPrtRectPos( pFly->Prt().Pos() ); //stores the value of last Prt rect

    EndAllAction();

	return aResult;
}


/***********************************************************************
#*	Class	   	:  SwFEShell
#*	Methode	   	:  WizzardFindCurFrmFmt
#*	Datum	   	:  JP 31.07.95
#*	Update	   	:  JP 31.07.95
#***********************************************************************/

SwFrmFmt* SwFEShell::WizzardGetFly()
{
	// mal nicht uebers Layout den Fly suchen. Dann kann auch ohne gueltiges
	// Layout ein Rahmen geloescht werden. ( z.B.: fuer die Wizard's )
	SwSpzFrmFmts& rSpzArr = *pDoc->GetSpzFrmFmts();
	sal_uInt16 nCnt = rSpzArr.Count();
	if( nCnt )
	{
		SwNodeIndex& rCrsrNd = GetCrsr()->GetPoint()->nNode;
		if( rCrsrNd.GetIndex() > pDoc->GetNodes().GetEndOfExtras().GetIndex() )
			// Cusor steht im Body-Bereich!
			return 0;

		for( sal_uInt16 n = 0; n < nCnt; ++n )
		{
			SwFrmFmt* pFmt = rSpzArr[ n ];
			const SwNodeIndex* pIdx = pFmt->GetCntnt( sal_False ).GetCntntIdx();
			SwStartNode* pSttNd;
			if( pIdx &&
				0 != ( pSttNd = pIdx->GetNode().GetStartNode() ) &&
				pSttNd->GetIndex() < rCrsrNd.GetIndex() &&
				rCrsrNd.GetIndex() < pSttNd->EndOfSectionIndex() )
			{
				// gefunden: also raus damit
				return pFmt;
			}
		}
	}
	return 0;
}

void SwFEShell::SetFlyName( const String& rName )
{
	SwLayoutFrm *pFly = FindFlyFrm();
	if( pFly )
		GetDoc()->SetFlyName( *(SwFlyFrmFmt*)pFly->GetFmt(), rName );
	else {
		ASSERT( !this, "kein FlyFrame selektiert" )
    }
}

const String& SwFEShell::GetFlyName() const
{
	SwLayoutFrm *pFly = FindFlyFrm();
	if( pFly )
		return pFly->GetFmt()->GetName();

	ASSERT( !this, "kein FlyFrame selektiert" )
	return aEmptyStr;
}


const uno::Reference < embed::XEmbeddedObject > SwFEShell::GetOleRef() const
{
    uno::Reference < embed::XEmbeddedObject > xObj;
    SwFlyFrm * pFly = FindFlyFrm();
    if (pFly && pFly->Lower() && pFly->Lower()->IsNoTxtFrm())
    {
        SwOLENode *pNd = ((SwNoTxtFrm*)pFly->Lower())->GetNode()->GetOLENode();
        if (pNd)
            xObj = pNd->GetOLEObj().GetOleRef();
    }
    return xObj;
}    


String SwFEShell::GetUniqueGrfName() const
{
	return GetDoc()->GetUniqueGrfName();
}

const SwFrmFmt* SwFEShell::IsURLGrfAtPos( const Point& rPt, String* pURL,
										String *pTargetFrameName,
										String *pDescription ) const
{
	if( !Imp()->HasDrawView() )
		return 0;

	SdrObject* pObj;
	SdrPageView* pPV;
	const SwFrmFmt* pRet = 0;
	SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();

	sal_uInt16 nOld = pDView->GetHitTolerancePixel();
	pDView->SetHitTolerancePixel( 2 );

	if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV,SDRSEARCH_PICKMACRO ) &&
		pObj->ISA(SwVirtFlyDrawObj) )
	{
		SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
		const SwFmtURL &rURL = pFly->GetFmt()->GetURL();
		if( rURL.GetURL().Len() || rURL.GetMap() )
		{
			sal_Bool bSetTargetFrameName = pTargetFrameName != 0;
			sal_Bool bSetDescription = pDescription != 0;
			if ( rURL.GetMap() )
			{
                IMapObject *pObject = pFly->GetFmt()->GetIMapObject( rPt, pFly );
                if ( pObject && pObject->GetURL().Len() )
				{
					if( pURL )
                        *pURL = pObject->GetURL();
                    if ( bSetTargetFrameName && pObject->GetTarget().Len() )
					{
						bSetTargetFrameName = sal_False;
                        *pTargetFrameName = pObject->GetTarget();
					}
					if ( bSetDescription )
					{
						bSetDescription = sal_False;
                        *pDescription = pObject->GetAltText();
					}
					pRet = pFly->GetFmt();
				}
			}
			else
			{
				if( pURL )
				{
					*pURL = rURL.GetURL();
					if( rURL.IsServerMap() )
					{
						// dann die rel. Pixel Position anhaengen !!
						Point aPt( rPt );
						aPt -= pFly->Frm().Pos();
						// ohne MapMode-Offset, ohne Offset, o ... !!!!!
						aPt = GetOut()->LogicToPixel(
								aPt, MapMode( MAP_TWIP ) );
						((( *pURL += '?' ) += String::CreateFromInt32( aPt.X() ))
								  += ',' ) += String::CreateFromInt32(aPt.Y() );
					}
				}
				pRet = pFly->GetFmt();
			}
			if ( bSetTargetFrameName )
				*pTargetFrameName = rURL.GetTargetFrameName();
			if ( bSetDescription )
				*pDescription = pFly->GetFmt()->GetName();
		}
	}
	pDView->SetHitTolerancePixel( nOld );
	return pRet;
}

const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt,
									   String &rName, sal_Bool &rbLink ) const
{
	if( !Imp()->HasDrawView() )
		return 0;

	SdrObject* pObj;
	SdrPageView* pPV;
	SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();

	if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV ) && pObj->ISA(SwVirtFlyDrawObj) )
	{
		SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
		if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
		{
			SwGrfNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode();
			if ( pNd )
			{
				if ( pNd->IsGrfLink() )
				{
					//Halbfertige Grafik?
                    ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj();
					if( pLnkObj && pLnkObj->IsPending() )
						return 0;
					rbLink = sal_True;
				}

				pNd->GetFileFilterNms( &rName, 0 );
				if ( !rName.Len() )
					rName = pFly->GetFmt()->GetName();
				pNd->SwapIn( sal_True );
				return &pNd->GetGrf();
			}
		}
	}
	return 0;
}


const SwFrmFmt* SwFEShell::GetFmtFromObj( const Point& rPt, SwRect** pRectToFill ) const
{
	SwFrmFmt* pRet = 0;

	if( Imp()->HasDrawView() )
	{
		SdrObject* pObj;
		SdrPageView* pPView;

		SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();

		sal_uInt16 nOld = pDView->GetHitTolerancePixel();
		// Tattergrenze fuer Drawing-SS
		pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );

		if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) )
		{
			// dann teste mal was es ist:
			if ( pObj->ISA(SwVirtFlyDrawObj) )
				pRet = ((SwVirtFlyDrawObj*)pObj)->GetFmt();
			else if ( pObj->GetUserCall() ) //nicht fuer Gruppenobjekte
				pRet = ((SwDrawContact*)pObj->GetUserCall())->GetFmt();
			if(pRet && pRectToFill)
				**pRectToFill = pObj->GetCurrentBoundRect();
		}
		pDView->SetHitTolerancePixel( nOld );
	}
	return pRet;
}

// returns a format too, if the point is over the text of any fly
const SwFrmFmt* SwFEShell::GetFmtFromAnyObj( const Point& rPt ) const
{
	const SwFrmFmt* pRet = GetFmtFromObj( rPt );
	if( !pRet || RES_FLYFRMFMT == pRet->Which() )
	{
		SwPosition aPos( *GetCrsr()->GetPoint() );
		Point aPt( rPt );
		GetLayout()->GetCrsrOfst( &aPos, aPt );
		SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
		SwFrm* pFrm = pNd->getLayoutFrm( GetLayout(), &rPt, 0, sal_False )->FindFlyFrm();
		pRet = pFrm ? ((SwLayoutFrm*)pFrm)->GetFmt() : 0;
	}
	return pRet;
}

ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj ) const
{
    ObjCntType eType = OBJCNT_NONE;

    // OD 23.06.2003 #108784# - investigate 'master' drawing object, if method
    // is called for a 'virtual' drawing object.
    const SdrObject* pInvestigatedObj;
    if ( rObj.ISA(SwDrawVirtObj) )
    {
        const SwDrawVirtObj* pDrawVirtObj = static_cast<const SwDrawVirtObj*>(&rObj);
        pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj());
    }
    else
    {
        pInvestigatedObj = &rObj;
    }

    if( FmFormInventor == pInvestigatedObj->GetObjInventor() )
	{
		eType = OBJCNT_CONTROL;
        uno::Reference< awt::XControlModel >  xModel =
                ((SdrUnoObj&)(*pInvestigatedObj)).GetUnoControlModel();
		if( xModel.is() )
		{
			uno::Any aVal;
			OUString sName = OUString::createFromAscii("ButtonType");
			uno::Reference< beans::XPropertySet >  xSet(xModel, uno::UNO_QUERY);

			uno::Reference< beans::XPropertySetInfo >  xInfo = xSet->getPropertySetInfo();
			if(xInfo->hasPropertyByName( sName ))
			{
				beans::Property xProperty = xInfo->getPropertyByName( sName );
				aVal = xSet->getPropertyValue( sName );
				if( aVal.getValue() && form::FormButtonType_URL == *((form::FormButtonType*)aVal.getValue()) )
					eType = OBJCNT_URLBUTTON;
			}
		}
	}
    else if( pInvestigatedObj->ISA(SwVirtFlyDrawObj) )
	{
        SwFlyFrm *pFly = ((SwVirtFlyDrawObj&)(*pInvestigatedObj)).GetFlyFrm();
		if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
		{
			if ( ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode() )
				eType = OBJCNT_GRF;
			else
				eType = OBJCNT_OLE;
		}
		else
			eType = OBJCNT_FLY;
	}
    else if ( pInvestigatedObj->ISA( SdrObjGroup ) )
    {
        SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) );
        if ( !pDrawContact )
        {
            ASSERT( false,
                    "<SwFEShell::GetObjCntType(..)> - missing draw contact object" );
            eType = OBJCNT_NONE;
        }
        else
        {
            SwFrmFmt* pFrmFmt( pDrawContact->GetFmt() );
            if ( !pFrmFmt )
            {
                ASSERT( false,
                        "<SwFEShell::GetObjCntType(..)> - missing frame format" );
                eType = OBJCNT_NONE;
            }
            else if ( FLY_AS_CHAR != pFrmFmt->GetAnchor().GetAnchorId() )
            {
                eType = OBJCNT_GROUPOBJ;
            }
        }
    }
	else
		eType = OBJCNT_SIMPLE;
	return eType;
}

ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const
{
	ObjCntType eType = OBJCNT_NONE;

	if( Imp()->HasDrawView() )
	{
		SdrObject* pObj;
		SdrPageView* pPView;

		SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();

		sal_uInt16 nOld = pDView->GetHitTolerancePixel();
		// Tattergrenze fuer Drawing-SS
		pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );

		if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) )
			eType = GetObjCntType( *(rpObj = pObj) );

		pDView->SetHitTolerancePixel( nOld );
	}
	return eType;
}

ObjCntType SwFEShell::GetObjCntTypeOfSelection( SdrObject** ppObj ) const
{
	ObjCntType eType = OBJCNT_NONE;

	if( Imp()->HasDrawView() )
	{
		const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
		for( sal_uInt32 i = 0, nE = rMrkList.GetMarkCount(); i < nE; ++i )
		{
			SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
            if( !pObj )
                continue;
			ObjCntType eTmp = GetObjCntType( *pObj );
			if( !i )
			{
				eType = eTmp;
				if( ppObj ) *ppObj = pObj;
			}
			else if( eTmp != eType )
			{
				eType = OBJCNT_DONTCARE;
				// einmal DontCare, immer DontCare!
				break;
			}
		}
	}
	return eType;
}


sal_Bool SwFEShell::ReplaceSdrObj( const String& rGrfName, const String& rFltName,
								const Graphic* pGrf )
{
	SET_CURR_SHELL( this );

	sal_Bool bRet = sal_False;
	const SdrMarkList *pMrkList;
	if( Imp()->HasDrawView() &&  1 ==
		( pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount() )
	{
		SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
		SwFrmFmt *pFmt = FindFrmFmt( pObj );

		// Attribute sichern und dann an der Grafik setzen
		SfxItemSet aFrmSet( pDoc->GetAttrPool(),
							pFmt->GetAttrSet().GetRanges() );
		aFrmSet.Set( pFmt->GetAttrSet() );

		// Groesse und Position setzen ??
		if( !pObj->ISA(SwVirtFlyDrawObj) )
		{
			// dann mal los:
			const Rectangle &rBound = pObj->GetSnapRect();
			Point aRelPos( pObj->GetRelativePos() );

			const long nWidth = rBound.Right()	- rBound.Left();
			const long nHeight=	rBound.Bottom() - rBound.Top();
			aFrmSet.Put( SwFmtFrmSize( ATT_MIN_SIZE,
								Max( nWidth,  long(MINFLY) ),
								Max( nHeight, long(MINFLY) )));

			if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_HORI_ORIENT ))
                aFrmSet.Put( SwFmtHoriOrient( aRelPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ));

			if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_VERT_ORIENT ))
                aFrmSet.Put( SwFmtVertOrient( aRelPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME ));

		}

        pObj->GetOrdNum();

		StartAllAction();
		StartUndo();

		// das "Sdr-Object" loeschen und dafuer die Grafik einfuegen
		DelSelectedObj();

		pFmt = GetDoc()->Insert( *GetCrsr(), rGrfName, rFltName, pGrf, &aFrmSet, NULL, NULL );

		// die Ordnungsnummer (Z-Order) noch uebertragen
		// JP 04.07.98: klappt aber nicht richtig!
		//SdrObject* pNewObj = ::FindSdrObject( pFmt );
		//pNewObj->SetOrdNum( nOrdNum );

		EndUndo();
		EndAllAction();
		bRet = sal_True;
	}
	return bRet;
}

static sal_uInt16 SwFmtGetPageNum(const SwFlyFrmFmt * pFmt)
{
    ASSERT(pFmt != NULL, "invalid argument");

    SwFlyFrm * pFrm = pFmt->GetFrm();

    sal_uInt16 aResult;

    if (pFrm != NULL)
        aResult = pFrm->GetPhyPageNum();
    else
        aResult = pFmt->GetAnchor().GetPageNum();

    return aResult;
}

#include <fmtcnct.hxx>

void SwFEShell::GetConnectableFrmFmts(SwFrmFmt & rFmt,
                                      const String & rReference,
                                      sal_Bool bSuccessors,
                                      ::std::vector< String > & aPrevPageVec,
                                      ::std::vector< String > & aThisPageVec,
                                      ::std::vector< String > & aNextPageVec,
                                      ::std::vector< String > & aRestVec)
{
    StartAction();

    SwFmtChain rChain = rFmt.GetChain();
    SwFrmFmt * pOldChainNext = (SwFrmFmt *) rChain.GetNext();
    SwFrmFmt * pOldChainPrev = (SwFrmFmt *) rChain.GetPrev();

    if (pOldChainNext)
        pDoc->Unchain(rFmt);

    if (pOldChainPrev)
        pDoc->Unchain(*pOldChainPrev);

    sal_uInt16 nCnt = pDoc->GetFlyCount(FLYCNTTYPE_FRM);

    /* potential successors resp. predecessors */
    ::std::vector< const SwFrmFmt * > aTmpSpzArray;

    (SwFrmFmt *) pDoc->FindFlyByName(rReference);

    for (sal_uInt16 n = 0; n < nCnt; n++)
    {
        const SwFrmFmt & rFmt1 = *(pDoc->GetFlyNum(n, FLYCNTTYPE_FRM));

        /*
           pFmt is a potential successor of rFmt if it is chainable after
           rFmt.

           pFmt is a potential predecessor of rFmt if rFmt is chainable
           after pFmt.
        */

        int nChainState;

        if (bSuccessors)
            nChainState = pDoc->Chainable(rFmt, rFmt1);
        else
            nChainState = pDoc->Chainable(rFmt1, rFmt);

        if (nChainState == SW_CHAIN_OK)
        {
            aTmpSpzArray.push_back(&rFmt1);

        }

    }

    if  (aTmpSpzArray.size() > 0)
    {
        aPrevPageVec.clear();
        aThisPageVec.clear();
        aNextPageVec.clear();
        aRestVec.clear();

        /* number of page rFmt resides on */
        sal_uInt16 nPageNum = SwFmtGetPageNum((SwFlyFrmFmt *) &rFmt);

        ::std::vector< const SwFrmFmt * >::const_iterator aIt;

        for (aIt = aTmpSpzArray.begin(); aIt != aTmpSpzArray.end(); aIt++)
        {
            String  aString = (*aIt)->GetName();

            /* rFmt is not a vaild successor or predecessor of
               itself */
            if (aString != rReference && aString != rFmt.GetName())
            {
                sal_uInt16 nNum1 =
                    SwFmtGetPageNum((SwFlyFrmFmt *) *aIt);

                if (nNum1 == nPageNum -1)
                    aPrevPageVec.push_back(aString);
                else if (nNum1 == nPageNum)
                    aThisPageVec.push_back(aString);
                else if (nNum1 == nPageNum + 1)
                    aNextPageVec.push_back(aString);
                else
                    aRestVec.push_back(aString);
            }
        }

    }

    if (pOldChainNext)
        pDoc->Chain(rFmt, *pOldChainNext);

    if (pOldChainPrev)
        pDoc->Chain(*pOldChainPrev, rFmt);

    EndAction();
}

// --> OD 2009-07-13 #i73249#
const String SwFEShell::GetObjTitle() const
{
    String aTitle;

    if ( Imp()->HasDrawView() )
    {
        const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
        if ( pMrkList->GetMarkCount() == 1 )
        {
            const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
            const SwFrmFmt* pFmt = FindFrmFmt( pObj );
            if ( pFmt->Which() == RES_FLYFRMFMT )
            {
                aTitle = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjTitle();
            }
            else
            {
                aTitle = pObj->GetTitle();
            }
        }
    }

    return aTitle;
}

void SwFEShell::SetObjTitle( const String& rTitle )
{
    if ( Imp()->HasDrawView() )
    {
        const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
        if ( pMrkList->GetMarkCount() == 1 )
        {
            SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
            SwFrmFmt* pFmt = FindFrmFmt( pObj );
            if ( pFmt->Which() == RES_FLYFRMFMT )
            {
                GetDoc()->SetFlyFrmTitle( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)),
                                          rTitle );
            }
            else
            {
                pObj->SetTitle( rTitle );
            }
        }
    }
}

const String SwFEShell::GetObjDescription() const
{
    String aDescription;

    if ( Imp()->HasDrawView() )
    {
        const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
        if ( pMrkList->GetMarkCount() == 1 )
        {
            const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
            const SwFrmFmt* pFmt = FindFrmFmt( pObj );
            if ( pFmt->Which() == RES_FLYFRMFMT )
            {
                aDescription = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjDescription();
            }
            else
            {
                aDescription = pObj->GetDescription();
            }
        }
    }

    return aDescription;
}

void SwFEShell::SetObjDescription( const String& rDescription )
{
    if ( Imp()->HasDrawView() )
    {
        const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
        if ( pMrkList->GetMarkCount() == 1 )
        {
            SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
            SwFrmFmt* pFmt = FindFrmFmt( pObj );
            if ( pFmt->Which() == RES_FLYFRMFMT )
            {
                GetDoc()->SetFlyFrmDescription( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)),
                                                rDescription );
            }
            else
            {
                pObj->SetDescription( rDescription );
            }
        }
    }
}


void SwFEShell::AlignFormulaToBaseline( const uno::Reference < embed::XEmbeddedObject >& xObj, SwFlyFrm * pFly )
{
#if OSL_DEBUG_LEVEL > 1    
    SvGlobalName aCLSID( xObj->getClassID() );
    const bool bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
    ASSERT( bStarMath, "AlignFormulaToBaseline should only be called for Math objects" );

    if ( !bStarMath )
        return;
#endif

    if (!pFly)
        pFly = FindFlyFrm( xObj );
    ASSERT( pFly , "No fly frame!" );
    SwFrmFmt * pFrmFmt = pFly ? pFly->GetFmt() : 0;

    // baseline to baseline alignment should only be applied to formulas anchored as char
    if ( pFly && pFrmFmt && FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
    {
        // get baseline from Math object
        uno::Any aBaseline;  
        if( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
        {
            uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
            if ( xSet.is() )
            {
                try
                {
                    aBaseline = xSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BaseLine") ) );
                }
                catch ( uno::Exception& )
                {
                    ASSERT( sal_False , "Baseline could not be retrieved from Starmath!" );
                }
            }
        }

        sal_Int32 nBaseline = ::comphelper::getINT32(aBaseline);
        const MapMode aSourceMapMode( MAP_100TH_MM );
        const MapMode aTargetMapMode( MAP_TWIP );
        nBaseline = OutputDevice::LogicToLogic( nBaseline, aSourceMapMode.GetMapUnit(), aTargetMapMode.GetMapUnit() );

        ASSERT( nBaseline > 0, "Wrong value of Baseline while retrieving from Starmath!" );
        //nBaseline must be moved by aPrt position
        const SwFlyFrmFmt *pFlyFrmFmt = pFly->GetFmt();
        ASSERT( pFlyFrmFmt, "fly frame format missing!" );
        if ( pFlyFrmFmt )
            nBaseline += pFlyFrmFmt->GetLastFlyFrmPrtRectPos().Y();

        const SwFmtVertOrient &rVert = pFrmFmt->GetVertOrient();
        SwFmtVertOrient aVert( rVert );
        aVert.SetPos( -nBaseline );
        aVert.SetVertOrient( com::sun::star::text::VertOrientation::NONE );
        
        pFrmFmt->LockModify();
        pFrmFmt->SetFmtAttr( aVert );
        pFrmFmt->UnlockModify();
        pFly->InvalidatePos();
    }
}


void SwFEShell::AlignAllFormulasToBaseline()
{
    StartAllAction();

    SwStartNode *pStNd;
    SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
    while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
    {
        ++aIdx;
        SwOLENode *pOleNode = dynamic_cast< SwOLENode * >( &aIdx.GetNode() );
        if ( pOleNode )
        {
            const uno::Reference < embed::XEmbeddedObject > & xObj( pOleNode->GetOLEObj().GetOleRef() );
            if (xObj.is())
            {
                SvGlobalName aCLSID( xObj->getClassID() );
                if ( SotExchange::IsMath( aCLSID ) )
                    AlignFormulaToBaseline( xObj );
            }
        }

        aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
    }

    EndAllAction();
}