/**************************************************************
 * 
 * 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 <vcl/graph.hxx>
#include <sot/formats.hxx>
#include <sot/storage.hxx>
#include <unotools/pathoptions.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewsh.hxx>
#include <svx/xexch.hxx>
#include <svx/xflasit.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflclit.hxx>
#include <editeng/brshitem.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdouno.hxx>
#include <svx/xfillit.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdogrp.hxx>
#include <svx/xoutbmp.hxx>
#include <svx/svdoole2.hxx>
#include <svx/fmmodel.hxx>
#include <svx/unomodel.hxx>
// --> OD 2005-08-03 #i50824#
#include <svx/svditer.hxx>
// <--
// --> OD 2006-03-01 #b6382898#
#include <svx/svdograf.hxx>
// <--
#include <unotools/streamwrap.hxx>
#include <fmtanchr.hxx>
#include <fmtcntnt.hxx>
#include <fmtornt.hxx>
#include <fmtflcnt.hxx>
#include <frmfmt.hxx>
#include <docary.hxx>
#include <txtfrm.hxx>
#include <txtflcnt.hxx>
#include <fesh.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <rootfrm.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <tblsel.hxx>
#include <swtable.hxx>
#include <flyfrm.hxx>
#include <pagefrm.hxx>
#include <fldbas.hxx>
#include <edimp.hxx>
#include <swundo.hxx>
#include <viewimp.hxx>
#include <dview.hxx>
#include <dcontact.hxx>
#include <dflyobj.hxx>
#include <docsh.hxx>
#include <pagedesc.hxx>
#include <mvsave.hxx>
#include <vcl/virdev.hxx>
#include <svx/svdundo.hxx>

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

/*************************************************************************
|*
|*	SwFEShell::Copy()	Copy fuer das Interne Clipboard.
|*		Kopiert alle Selektionen in das Clipboard.
|*
|*	Ersterstellung		JP ??
|*	Letzte Aenderung	MA 22. Feb. 95
|
|*************************************************************************/

sal_Bool SwFEShell::Copy( SwDoc* pClpDoc, const String* pNewClpTxt )
{
	ASSERT( pClpDoc, "kein Clipboard-Dokument"	);

    pClpDoc->GetIDocumentUndoRedo().DoUndo(false); // always false!

	// steht noch Inhalt im ClpDocument, dann muss dieser geloescht werden
	SwNodeIndex aSttIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
	SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
	if( !pTxtNd || pTxtNd->GetTxt().Len() ||
		aSttIdx.GetIndex()+1 != pClpDoc->GetNodes().GetEndOfContent().GetIndex() )
	{
		pClpDoc->GetNodes().Delete( aSttIdx,
			pClpDoc->GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
		pTxtNd = pClpDoc->GetNodes().MakeTxtNode( aSttIdx,
							(SwTxtFmtColl*)pClpDoc->GetDfltTxtFmtColl() );
		aSttIdx--;
	}

	// stehen noch FlyFrames rum, loesche auch diese
	for( sal_uInt16 n = 0; n < pClpDoc->GetSpzFrmFmts()->Count(); ++n )
	{
		SwFlyFrmFmt* pFly = (SwFlyFrmFmt*)(*pClpDoc->GetSpzFrmFmts())[n];
		pClpDoc->DelLayoutFmt( pFly );
	}
	pClpDoc->GCFieldTypes();		// loesche die FieldTypes

	// wurde ein String uebergeben, so kopiere diesen in das Clipboard-
	// Dokument. Somit kann auch der Calculator das interne Clipboard
	// benutzen.
	if( pNewClpTxt )
	{
        pTxtNd->InsertText( *pNewClpTxt, SwIndex( pTxtNd ) );
		return sal_True;				// das wars.
	}

	pClpDoc->LockExpFlds();
	pClpDoc->SetRedlineMode_intern( nsRedlineMode_t::REDLINE_DELETE_REDLINES );
	sal_Bool bRet;

	// soll ein FlyFrame kopiert werden ?
	if( IsFrmSelected() )
	{
		// hole das FlyFormat
		SwFlyFrm* pFly = FindFlyFrm();
		SwFrmFmt* pFlyFmt = pFly->GetFmt();
		SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() );

        if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
            (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
            (FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
            (FLY_AS_CHAR == aAnchor.GetAnchorId()))
        {
            SwPosition aPos( aSttIdx );
            if ( FLY_AS_CHAR == aAnchor.GetAnchorId() )
            {
                aPos.nContent.Assign( pTxtNd, 0 );
            }
			aAnchor.SetAnchor( &aPos );
		}
        pFlyFmt = pClpDoc->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true );

		// sorge dafuer das das "RootFmt" als erstes im SpzArray-steht
		// (Es wurden ggf. Flys in Flys kopiert.
		SwSpzFrmFmts& rSpzFrmFmts = *(SwSpzFrmFmts*)pClpDoc->GetSpzFrmFmts();
		if( rSpzFrmFmts[ 0 ] != pFlyFmt )
		{
			sal_uInt16 nPos = rSpzFrmFmts.GetPos( pFlyFmt );
			ASSERT( nPos != USHRT_MAX, "Fly steht nicht im Spz-Array" );

			rSpzFrmFmts.Remove( nPos );
			rSpzFrmFmts.Insert( pFlyFmt, 0 );
		}

        if ( FLY_AS_CHAR == aAnchor.GetAnchorId() )
        {
			// JP 13.02.99 Bug 61863: wenn eine Rahmenselektion ins Clipboard
			//				gestellt wird, so muss beim Pasten auch wieder
			//				eine solche vorgefunden werden. Also muss im Node
			//				das kopierte TextAttribut wieder entfernt werden,
			//				sonst wird es als TextSelektion erkannt
			const SwIndex& rIdx = pFlyFmt->GetAnchor().GetCntntAnchor()->nContent;
            SwTxtFlyCnt *const pTxtFly = static_cast<SwTxtFlyCnt *>(
                pTxtNd->GetTxtAttrForCharAt(
                    rIdx.GetIndex(), RES_TXTATR_FLYCNT));
			if( pTxtFly )
			{
				((SwFmtFlyCnt&)pTxtFly->GetFlyCnt()).SetFlyFmt( 0 );
                pTxtNd->EraseText( rIdx, 1 );
            }
        }
		bRet = sal_True;
	}
	else if ( IsObjSelected() )
	{
        SwPosition aPos( aSttIdx, SwIndex( pTxtNd, 0 ));
		const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
		for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
		{
			SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();

			if( Imp()->GetDrawView()->IsGroupEntered() ||
				( !pObj->GetUserCall() && pObj->GetUpGroup()) )
			{
				SfxItemSet aSet( pClpDoc->GetAttrPool(), aFrmFmtSetRange );

                SwFmtAnchor aAnchor( FLY_AT_PARA );
				aAnchor.SetAnchor( &aPos );
				aSet.Put( aAnchor );

                SdrObject *const pNew =
                    pClpDoc->CloneSdrObj( *pObj, sal_False, sal_True );

                SwPaM aTemp(aPos);
                pClpDoc->Insert(aTemp, *pNew, &aSet, NULL);
			}
			else
			{
				SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj );
				SwFrmFmt *pFmt = pContact->GetFmt();
				SwFmtAnchor aAnchor( pFmt->GetAnchor() );
                if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
                    (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
                    (FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
                    (FLY_AS_CHAR == aAnchor.GetAnchorId()))
                {
					aAnchor.SetAnchor( &aPos );
				}

                pClpDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true );
			}
		}
		bRet = sal_True;
	}
	else
		bRet = _CopySelToDoc( pClpDoc, 0 );		// kopiere die Selectionen

	pClpDoc->SetRedlineMode_intern((RedlineMode_t)0 );
	pClpDoc->UnlockExpFlds();
	if( !pClpDoc->IsExpFldsLocked() )
		pClpDoc->UpdateExpFlds(NULL, true);

	return bRet;
}

const Point &lcl_FindBasePos( const SwFrm *pFrm, const Point &rPt )
{
	const SwFrm *pF = pFrm;
	while ( pF && !pF->Frm().IsInside( rPt ) )
	{
		if ( pF->IsCntntFrm() )
			pF = ((SwCntntFrm*)pF)->GetFollow();
		else
			pF = 0;
	}
	if ( pF )
		return pF->Frm().Pos();
	else
		return pFrm->Frm().Pos();
}

sal_Bool lcl_SetAnchor( const SwPosition& rPos, const SwNode& rNd, SwFlyFrm* pFly,
				const Point& rInsPt, SwFEShell& rDestShell, SwFmtAnchor& rAnchor,
				Point& rNewPos, sal_Bool bCheckFlyRecur )
{
	sal_Bool bRet = sal_True;
	rAnchor.SetAnchor( &rPos );
	SwCntntFrm* pTmpFrm = rNd.GetCntntNode()->getLayoutFrm( rDestShell.GetLayout(), &rInsPt, 0, sal_False );
	SwFlyFrm *pTmpFly = pTmpFrm->FindFlyFrm();
    if( pTmpFly && bCheckFlyRecur && pFly->IsUpperOf( *pTmpFly ) )
    {
		bRet = sal_False;
    }
    else if ( FLY_AT_FLY == rAnchor.GetAnchorId() )
    {
		if( pTmpFly )
		{
			const SwNodeIndex& rIdx = *pTmpFly->GetFmt()->GetCntnt().GetCntntIdx();
			SwPosition aPos( rIdx );
			rAnchor.SetAnchor( &aPos );
			rNewPos = pTmpFly->Frm().Pos();
		}
		else
		{
            rAnchor.SetType( FLY_AT_PAGE );
			rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
			const SwFrm *pPg = pTmpFrm->FindPageFrm();
			rNewPos = pPg->Frm().Pos();
		}
	}
	else
		rNewPos = ::lcl_FindBasePos( pTmpFrm, rInsPt );
	return bRet;
}

sal_Bool SwFEShell::CopyDrawSel( SwFEShell* pDestShell, const Point& rSttPt,
					const Point& rInsPt, sal_Bool bIsMove, sal_Bool bSelectInsert )
{
	sal_Bool bRet = sal_True;

	//Die Liste muss kopiert werden, weil unten die neuen Objekte
	//selektiert werden.
	const SdrMarkList aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() );
	sal_uLong nMarkCount = aMrkList.GetMarkCount();
	if( !pDestShell->Imp()->GetDrawView() )
		// sollte mal eine erzeugt werden
		pDestShell->MakeDrawView();
	else if( bSelectInsert )
		pDestShell->Imp()->GetDrawView()->UnmarkAll();

	SdrPageView *pDestPgView = pDestShell->Imp()->GetPageView(),
				*pSrcPgView = Imp()->GetPageView();
	SwDrawView *pDestDrwView = pDestShell->Imp()->GetDrawView(),
				*pSrcDrwView = Imp()->GetDrawView();
	SwDoc* pDestDoc = pDestShell->GetDoc();

	Size aSiz( rInsPt.X() - rSttPt.X(), rInsPt.Y() - rSttPt.Y() );
	for( sal_uInt16 i = 0; i < nMarkCount; ++i )
	{
		SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();

		SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj );
		SwFrmFmt *pFmt = pContact->GetFmt();
		const SwFmtAnchor& rAnchor = pFmt->GetAnchor();

		sal_Bool bInsWithFmt = sal_True;

		if( pDestDrwView->IsGroupEntered() )
		{
			// in die Gruppe einfuegen, wenns aus einer betretenen Gruppe
			// kommt oder das Object nicht zeichengebunden ist
			if( pSrcDrwView->IsGroupEntered() ||
                (FLY_AS_CHAR != rAnchor.GetAnchorId()) )

			{
				SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
										GetDoc() == pDestDoc, sal_False );
				pNew->NbcMove( aSiz );
				pDestDrwView->InsertObjectAtView( pNew, *pDestPgView );
				bInsWithFmt = sal_False;
			}
		}

		if( bInsWithFmt )
		{
			SwFmtAnchor aAnchor( rAnchor );
			Point aNewAnch;

            if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
                (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
                (FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
                (FLY_AS_CHAR == aAnchor.GetAnchorId()))
            {
				if ( this == pDestShell )
				{
					//gleiche Shell? Dann erfrage die Position an der
					//uebergebenen DokumentPosition
					SwPosition aPos( *GetCrsr()->GetPoint() );
					Point aPt( rInsPt );
					aPt -= rSttPt - pObj->GetSnapRect().TopLeft();
					SwCrsrMoveState aState( MV_SETONLYTEXT );
					GetLayout()->GetCrsrOfst( &aPos, aPt, &aState );
					const SwNode *pNd;
					if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() )
						bRet = sal_False;
					else
						bRet = ::lcl_SetAnchor( aPos, *pNd, 0, rInsPt,
								*pDestShell, aAnchor, aNewAnch, sal_False );
				}
				else
				{
					SwPaM *pCrsr = pDestShell->GetCrsr();
					if( pCrsr->GetNode()->IsNoTxtNode() )
						bRet = sal_False;
					else
						bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(),
												*pCrsr->GetNode(), 0, rInsPt,
												*pDestShell, aAnchor,
												aNewAnch, sal_False );
				}
			}
            else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
			{
				aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) );
                const SwRootFrm* pTmpRoot = pDestShell->GetLayout();
                const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true );
                if ( pPg )
                    aNewAnch = pPg->Frm().Pos();
			}

			if( bRet )
			{
				if( pSrcDrwView->IsGroupEntered() ||
					( !pObj->GetUserCall() && pObj->GetUpGroup()) )
				{
					SfxItemSet aSet( pDestDoc->GetAttrPool(),aFrmFmtSetRange);
					aSet.Put( aAnchor );
					SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
												GetDoc() == pDestDoc, sal_True );
					pFmt = pDestDoc->Insert( *pDestShell->GetCrsr(),
											*pNew, &aSet, NULL );
				}
				else
                    pFmt = pDestDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true );

				//Kann 0 sein, weil Draws in Kopf-/Fusszeilen nicht erlaubt sind.
				if ( pFmt )
				{
                    SdrObject* pNew = pFmt->FindSdrObject();
                    if ( FLY_AS_CHAR != aAnchor.GetAnchorId() )
                    {
						Point aPos( rInsPt );
						aPos -= aNewAnch;
						aPos -= rSttPt - pObj->GetSnapRect().TopLeft();
                        // OD 2004-04-05 #i26791# - change attributes instead of
                        // direct positioning
                        pFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
                        pFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
                        // --> OD 2005-04-15 #i47455# - notify draw frame format
                        // that position attributes are already set.
                        if ( pFmt->ISA(SwDrawFrmFmt) )
                        {
                            static_cast<SwDrawFrmFmt*>(pFmt)->PosAttrSet();
                        }
                        // <--
                    }
					if( bSelectInsert )
						pDestDrwView->MarkObj( pNew, pDestPgView );
				}
			}
		}
	}

	if ( bIsMove && bRet )
	{
		if( pDestShell == this )
		{
			const SdrMarkList aList( pSrcDrwView->GetMarkedObjectList() );
			pSrcDrwView->UnmarkAll();

            sal_uLong nMrkCnt = aMrkList.GetMarkCount();
			sal_uInt16 i;
            for ( i = 0; i < nMrkCnt; ++i )
			{
				SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
				pSrcDrwView->MarkObj( pObj, pSrcPgView );
			}
			DelSelectedObj();
            nMrkCnt = aList.GetMarkCount();
            for ( i = 0; i < nMrkCnt; ++i )
			{
				SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj();
				pSrcDrwView->MarkObj( pObj, pSrcPgView );
			}
		}
		else
			DelSelectedObj();
	}

	return bRet;
}

sal_Bool SwFEShell::Copy( SwFEShell* pDestShell, const Point& rSttPt,
					const Point& rInsPt, sal_Bool bIsMove, sal_Bool bSelectInsert )
{
	sal_Bool bRet = sal_False;

	ASSERT( pDestShell, "Copy ohne DestShell." );
	ASSERT( this == pDestShell || !pDestShell->IsObjSelected(),
			"Dest-Shell darf nie im Obj-Modus sein" );

	SET_CURR_SHELL( pDestShell );

	pDestShell->StartAllAction();
	pDestShell->GetDoc()->LockExpFlds();

	// Referenzen sollen verschoben werden.
	sal_Bool bCopyIsMove = pDoc->IsCopyIsMove();
	if( bIsMove )
		// am Doc ein Flag setzen, damit in den TextNodes
		pDoc->SetCopyIsMove( sal_True );

	RedlineMode_t eOldRedlMode = pDestShell->GetDoc()->GetRedlineMode();
	pDestShell->GetDoc()->SetRedlineMode_intern( (RedlineMode_t)(eOldRedlMode | nsRedlineMode_t::REDLINE_DELETE_REDLINES));

	// sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle
	// angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen
	// kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen
	// besorgt)
	SwFieldType* pTblFldTyp = pDestShell->GetDoc()->GetSysFldType( RES_TABLEFLD );

	if( IsFrmSelected() )
	{
		SwFlyFrm* pFly = FindFlyFrm();
		SwFrmFmt* pFlyFmt = pFly->GetFmt();
		SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() );
		bRet = sal_True;
		Point aNewAnch;

        if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
            (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
            (FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
            (FLY_AS_CHAR == aAnchor.GetAnchorId()))
        {
			if ( this == pDestShell )
			{
				// gleiche Shell? Dann erfrage die Position an der
				// uebergebenen DokumentPosition
				SwPosition aPos( *GetCrsr()->GetPoint() );
				Point aPt( rInsPt );
				aPt -= rSttPt - pFly->Frm().Pos();
				SwCrsrMoveState aState( MV_SETONLYTEXT );
				GetLayout()->GetCrsrOfst( &aPos, aPt, &aState );
				const SwNode *pNd;
				if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() )
					bRet = sal_False;
				else
				{	//Nicht in sich selbst kopieren
					const SwNodeIndex *pTmp = pFlyFmt->GetCntnt().GetCntntIdx();
					if ( aPos.nNode > *pTmp && aPos.nNode <
						pTmp->GetNode().EndOfSectionIndex() )
					{
						bRet = sal_False;
					}
					else
						bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt,
										*pDestShell, aAnchor, aNewAnch, sal_True );
				}
			}
			else
			{
				const SwPaM *pCrsr = pDestShell->GetCrsr();
				if( pCrsr->GetNode()->IsNoTxtNode() )
					bRet = sal_False;
				else
					bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(), *pCrsr->GetNode(),
											pFly, rInsPt, *pDestShell, aAnchor,
									aNewAnch, GetDoc() == pDestShell->GetDoc());
			}
		}
        else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
        {
			aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) );
            const SwRootFrm* pTmpRoot = pDestShell->GetLayout();
            const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true );
            if ( pPg )
                aNewAnch = pPg->Frm().Pos();
        }
		else {
			ASSERT( !this, "was fuer ein Anchor ist es denn?" );
        }

		if( bRet )
		{
			SwFrmFmt *pOldFmt = pFlyFmt;
            pFlyFmt = pDestShell->GetDoc()->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true );

            if ( FLY_AS_CHAR != aAnchor.GetAnchorId() )
            {
				Point aPos( rInsPt );
				aPos -= aNewAnch;
				aPos -= rSttPt - pFly->Frm().Pos();
                pFlyFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(),text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
                pFlyFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(),text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
			}

			const Point aPt( pDestShell->GetCrsrDocPos() );

			if( bIsMove )
				GetDoc()->DelLayoutFmt( pOldFmt );

			// nur selektieren wenn es in der gleichen Shell verschoben/
			//	kopiert wird
			if( bSelectInsert )
			{
				SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aPt, sal_False );
				if( pFlyFrm )
				{
					//JP 12.05.98: sollte das nicht im SelectFlyFrm stehen???
					pDestShell->Imp()->GetDrawView()->UnmarkAll();
					pDestShell->SelectFlyFrm( *pFlyFrm, sal_True );
				}
			}

			if( this != pDestShell && !pDestShell->HasShFcs() )
				pDestShell->Imp()->GetDrawView()->hideMarkHandles();
		}
	}
	else if ( IsObjSelected() )
		bRet = CopyDrawSel( pDestShell, rSttPt, rInsPt, bIsMove, bSelectInsert );
	else if( IsTableMode() )
	{
		// kopiere Teile aus einer Tabelle: lege eine Tabelle mit der Breite
		// von der Originalen an und kopiere die selectierten Boxen.
		// Die Groessen werden prozentual korrigiert.

		// lasse ueber das Layout die Boxen suchen
		const SwTableNode* pTblNd;
		SwSelBoxes aBoxes;
		GetTblSel( *this, aBoxes );
		if( aBoxes.Count() &&
			0 != (pTblNd = aBoxes[0]->GetSttNd()->FindTableNode()) )
		{
			SwPosition* pDstPos = 0;
			if( this == pDestShell )
			{
				// gleiche Shell? Dann erzeuge einen Crsr an der
				// uebergebenen DokumentPosition
				pDstPos = new SwPosition( *GetCrsr()->GetPoint() );
				Point aPt( rInsPt );
				GetLayout()->GetCrsrOfst( pDstPos, aPt );
				if( !pDstPos->nNode.GetNode().IsNoTxtNode() )
					bRet = sal_True;
			}
			else if( !pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() )
			{
				pDstPos = new SwPosition( *pDestShell->GetCrsr()->GetPoint() );
				bRet = sal_True;
			}

			if( bRet )
			{
				if( GetDoc() == pDestShell->GetDoc() )
					ParkTblCrsr();

				bRet = pDestShell->GetDoc()->InsCopyOfTbl( *pDstPos, aBoxes,0,
										bIsMove && this == pDestShell &&
										aBoxes.Count() == pTblNd->GetTable().
										GetTabSortBoxes().Count(),
										this != pDestShell );

				if( this != pDestShell )
					*pDestShell->GetCrsr()->GetPoint() = *pDstPos;

				// wieder alle geparkten Crsr erzeugen?
				if( GetDoc() == pDestShell->GetDoc() )
					GetCrsr();

				// JP 16.04.99: Bug 64908 - InsPos setzen, damit der geparkte
				//				Cursor auf die EinfuegePos. positioniert wird
				if( this == pDestShell )
					GetCrsrDocPos() = rInsPt;
			}
			delete pDstPos;
		}
	}
	else
	{
		bRet = sal_True;
		if( this == pDestShell )
		{
			// gleiche Shell? Dann erfrage die Position an der
			// uebergebenen DokumentPosition
			SwPosition aPos( *GetCrsr()->GetPoint() );
			Point aPt( rInsPt );
			GetLayout()->GetCrsrOfst( &aPos, aPt );
			bRet = !aPos.nNode.GetNode().IsNoTxtNode();
		}
		else if( pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() )
			bRet = sal_False;

		if( bRet )
			bRet = 0 != SwEditShell::Copy( pDestShell );
	}

	pDestShell->GetDoc()->SetRedlineMode_intern( eOldRedlMode );
	pDoc->SetCopyIsMove( bCopyIsMove );

	// wurden neue Tabellenformeln eingefuegt ?
	if( pTblFldTyp->GetDepends() )
	{
		// alte Actions beenden; die Tabellen-Frames werden angelegt und
		// eine SSelection kann erzeugt werden
		sal_uInt16 nActCnt;
		for( nActCnt = 0; pDestShell->ActionPend(); ++nActCnt )
			pDestShell->EndAllAction();

		for( ; nActCnt; --nActCnt )
			pDestShell->StartAllAction();
	}
	pDestShell->GetDoc()->UnlockExpFlds();
	pDestShell->GetDoc()->UpdateFlds(NULL, false);

	pDestShell->EndAllAction();
	return bRet;
}

/*************************************************************************
|*
|*	SwFEShell::Paste()	Paste fuer das Interne Clipboard.
|*		Kopiert den Inhalt vom Clipboard in das Dokument.
|*
|*	Ersterstellung		JP ??
|*	Letzte Aenderung	MA 22. Feb. 95
|
|*************************************************************************/

namespace {
    typedef boost::shared_ptr<SwPaM> PaMPtr;
    typedef boost::shared_ptr<SwPosition> PositionPtr;
    typedef std::pair< PaMPtr, PositionPtr > Insertion;
}

sal_Bool SwFEShell::Paste( SwDoc* pClpDoc, sal_Bool bIncludingPageFrames )
{
	SET_CURR_SHELL( this );
	ASSERT( pClpDoc, "kein Clipboard-Dokument"	);
    const sal_uInt16 nStartPageNumber = GetPhyPageNum();
	// dann bis zum Ende vom Nodes Array
	SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
	SwPaM aCpyPam( aIdx ); //DocStart

	// sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle
	// angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen
	// kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen
	// besorgt)
	SwFieldType* pTblFldTyp = GetDoc()->GetSysFldType( RES_TABLEFLD );

	SwTableNode *pDestNd, *pSrcNd = aCpyPam.GetNode()->GetTableNode();
	if( !pSrcNd )								// TabellenNode ?
	{											// nicht ueberspringen!!
		SwCntntNode* pCNd = aCpyPam.GetNode()->GetCntntNode();
		if( pCNd )
			aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 );
		else if( !aCpyPam.Move( fnMoveForward, fnGoNode ))
			aCpyPam.Move( fnMoveBackward, fnGoNode );
	}

	aCpyPam.SetMark();
	aCpyPam.Move( fnMoveForward, fnGoDoc );

	sal_Bool bRet = sal_True, bDelTbl = sal_True;
	StartAllAction();
    GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
	GetDoc()->LockExpFlds();

    // When the clipboard content has been created by a rectangular selection
    // the pasting is more sophisticated:
    // every paragraph will be inserted into another position.
    // The first positions are given by the actual cursor ring,
    // if there are more text portions to insert than cursor in this ring,
    // the additional insert positions will be created by moving the last
    // cursor position into the next line (like pressing the cursor down key)
    if( pClpDoc->IsColumnSelection() && !IsTableMode() )
    {
        // Creation of the list of insert positions
        std::list< Insertion > aCopyList;
        // The number of text portions of the rectangular selection
        const sal_uInt32 nSelCount = aCpyPam.GetPoint()->nNode.GetIndex()
                       - aCpyPam.GetMark()->nNode.GetIndex();
        sal_uInt32 nCount = nSelCount;
        SwNodeIndex aClpIdx( aIdx );
        SwPaM* pStartCursor = GetCrsr();
        SwPaM* pCurrCrsr = pStartCursor;
        sal_uInt32 nCursorCount = pStartCursor->numberOf();
        // If the target selection is a multi-selection, often the last and first
        // cursor of the ring points to identical document positions. Then
        // we should avoid double insertion of text portions...
        while( nCursorCount > 1 && *pCurrCrsr->GetPoint() ==
            *(dynamic_cast<SwPaM*>(pCurrCrsr->GetPrev())->GetPoint()) )
        {
            --nCursorCount;
            pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext());
            pStartCursor = pCurrCrsr;
        }
        SwPosition aStartPos( *pStartCursor->GetPoint() );
        SwPosition aInsertPos( aStartPos ); // first insertion position
        bool bCompletePara = false;
        sal_uInt16 nMove = 0;
        while( nCount )
        {
            --nCount;
            ASSERT( aIdx.GetNode().GetCntntNode(), "Who filled the clipboard?!" )
            if( aIdx.GetNode().GetCntntNode() ) // robust
            {
                Insertion aInsertion( PaMPtr( new SwPaM( aIdx ) ),
                    PositionPtr( new SwPosition( aInsertPos ) ) );
                ++aIdx;
                aInsertion.first->SetMark();
                if( pStartCursor == pCurrCrsr->GetNext() )
                {   // Now we have to look for insertion positions...
                    if( !nMove ) // Annotate the last given insert position
                        aStartPos = aInsertPos;
                    SwCursor aCrsr( aStartPos, 0, false);
                    // Check if we find another insert position by moving
                    // down the last given position
                    if( aCrsr.UpDown( sal_False, ++nMove, 0, 0 ) )
                        aInsertPos = *aCrsr.GetPoint();
                    else // if there is no paragraph we have to create it
                        bCompletePara = nCount > 0;
                    nCursorCount = 0;
                }
                else // as long as we find more insert positions in the cursor ring
                {    // we'll take them
                    pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext());
                    aInsertPos = *pCurrCrsr->GetPoint();
                    --nCursorCount;
                }
                // If there are no more paragraphs e.g. at the end of a document,
                // we insert complete paragraphs instead of text portions
                if( bCompletePara )
                    aInsertion.first->GetPoint()->nNode = aIdx;
                else
                    aInsertion.first->GetPoint()->nContent =
                        aInsertion.first->GetCntntNode()->Len();
                aCopyList.push_back( aInsertion );
            }
            // If there are no text portions left but there are some more
            // cursor positions to fill we have to restart with the first
            // text portion
            if( !nCount && nCursorCount )
            {
                nCount = std::min( nSelCount, nCursorCount );
                aIdx = aClpIdx; // Start of clipboard content
            }
        }
        std::list< Insertion >::const_iterator pCurr = aCopyList.begin();
        std::list< Insertion >::const_iterator pEnd = aCopyList.end();
        while( pCurr != pEnd )
        {
            SwPosition& rInsPos = *pCurr->second;
            SwPaM& rCopy = *pCurr->first;
            const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
            if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex() &&
                rCopy.GetPoint()->nNode != rCopy.GetMark()->nNode )
            {
                // if more than one node will be copied into a cell
                // the box attributes have to be removed
                GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
            }
            {
                SwNodeIndex aIndexBefore(rInsPos.nNode);
                aIndexBefore--;
                pClpDoc->CopyRange( rCopy, rInsPos, false );
                {
                    aIndexBefore++;
                    SwPaM aPaM(SwPosition(aIndexBefore),
                               SwPosition(rInsPos.nNode));
                    aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
                }
            }
            SaveTblBoxCntnt( &rInsPos );
            ++pCurr;
        }
    }
    else
    {
        FOREACHPAM_START(this)

        if( pSrcNd &&
			0 != ( pDestNd = GetDoc()->IsIdxInTbl( PCURCRSR->GetPoint()->nNode )))
		{
			SwPosition aDestPos( *PCURCRSR->GetPoint() );

			sal_Bool bParkTblCrsr = sal_False;
			const SwStartNode* pSttNd =  PCURCRSR->GetNode()->FindTableBoxStartNode();

            // TABLE IN TABLE: Tabelle in Tabelle kopieren
			// lasse ueber das Layout die Boxen suchen
			SwSelBoxes aBoxes;
			if( IsTableMode() )		// Tabellen-Selecktion ??
			{
				GetTblSel( *this, aBoxes );
				ParkTblCrsr();
				bParkTblCrsr = sal_True;
			}
			else if( !PCURCRSR->HasMark() && PCURCRSR->GetNext() == PCURCRSR &&
				     ( !pSrcNd->GetTable().IsTblComplex() ||
                       pDestNd->GetTable().IsNewModel() ) )
			{
				// dann die Tabelle "relativ" kopieren
				SwTableBox* pBox = pDestNd->GetTable().GetTblBox(
										pSttNd->GetIndex() );
				ASSERT( pBox, "Box steht nicht in dieser Tabelle" );
				aBoxes.Insert( pBox );
			}

			SwNodeIndex aNdIdx( *pDestNd->EndOfSectionNode());
			if( !bParkTblCrsr )
			{
				// erstmal aus der gesamten Tabelle raus
// ????? was ist mit Tabelle alleine im Rahmen ???????
				SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
				SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
                // #i59539: Don't remove all redline
                SwPaM const tmpPaM(*pDestNd, *pDestNd->EndOfSectionNode());
                ::PaMCorrAbs(tmpPaM, aPos);
			}

			bRet = GetDoc()->InsCopyOfTbl( aDestPos, aBoxes, &pSrcNd->GetTable(),
											sal_False, sal_False );

			if( bParkTblCrsr )
				GetCrsr();
			else
			{
				// und wieder in die Box zurueck
				aNdIdx = *pSttNd;
				SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
				SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
                // #i59539: Don't remove all redline
                SwNode & rNode(PCURCRSR->GetPoint()->nNode.GetNode());
                SwCntntNode *const pCntntNode( rNode.GetCntntNode() );
                SwPaM const tmpPam(rNode, 0,
                                   rNode, (pCntntNode) ? pCntntNode->Len() : 0);
                ::PaMCorrAbs(tmpPam, aPos);
			}

			break;		// aus der "while"-Schleife heraus
		}
        else if( *aCpyPam.GetPoint() == *aCpyPam.GetMark() &&
				 pClpDoc->GetSpzFrmFmts()->Count() )
		{
			// so langsam sollte mal eine DrawView erzeugt werden
			if( !Imp()->GetDrawView() )
				MakeDrawView();

            for ( sal_uInt16 i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i )
			{
				sal_Bool bInsWithFmt = sal_True;
				const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i];

				if( Imp()->GetDrawView()->IsGroupEntered() &&
					RES_DRAWFRMFMT == rCpyFmt.Which() &&
                    (FLY_AS_CHAR != rCpyFmt.GetAnchor().GetAnchorId()) )
                {
					const SdrObject* pSdrObj = rCpyFmt.FindSdrObject();
					if( pSdrObj )
					{
						SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj,
															sal_False, sal_False );

                        // Insert object sets any anchor position to 0.
                        // Therefore we calculate the absolute position here
                        // and after the insert the anchor of the object
                        // is set to the anchor of the group object.
                        Rectangle aSnapRect = pNew->GetSnapRect();
                        if( pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y() )
                        {
                            const Point aPoint( 0, 0 );
                            // OD 2004-04-05 #i26791# - direct drawing object
                            // positioning for group members
                            pNew->NbcSetAnchorPos( aPoint );
                            pNew->NbcSetSnapRect( aSnapRect );
                        }

						Imp()->GetDrawView()->InsertObjectAtView( pNew, *Imp()->GetPageView() );

                        Point aGrpAnchor( 0, 0 );
                        SdrObjList* pList = pNew->GetObjList();
                        if ( pList )
                        {
                            SdrObject* pOwner = pList->GetOwnerObj();
                            if ( pOwner )
                            {
                                SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pOwner);
                                aGrpAnchor = pThisGroup->GetAnchorPos();
                            }
                        }

                        // OD 2004-04-05 #i26791# - direct drawing object
                        // positioning for group members
                        pNew->NbcSetAnchorPos( aGrpAnchor );
                        pNew->SetSnapRect( aSnapRect );

						bInsWithFmt = sal_False;
					}
				}

				if( bInsWithFmt  )
				{
					SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
                    if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
                        (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
                        (FLY_AS_CHAR == aAnchor.GetAnchorId()))
                    {
						SwPosition* pPos = PCURCRSR->GetPoint();
                        // #108784# allow shapes (no controls) in header/footer
                        if( RES_DRAWFRMFMT == rCpyFmt.Which() &&
                            GetDoc()->IsInHeaderFooter( pPos->nNode ) &&
                            CheckControlLayer( rCpyFmt.FindSdrObject() ) )
                            continue;

						aAnchor.SetAnchor( pPos );
                    }
                    else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
                    {
						aAnchor.SetPageNum( GetPhyPageNum() );
					}
					else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
					{
						Point aPt;
						lcl_SetAnchor( *PCURCRSR->GetPoint(), *PCURCRSR->GetNode(),
										0, aPt, *this, aAnchor, aPt, sal_False );
					}

                    SwFrmFmt * pNew = GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );

					if( pNew )
					{
						if( RES_FLYFRMFMT == pNew->Which() )
						{
							const Point aPt( GetCrsrDocPos() );
							SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pNew)->
														GetFrm( &aPt, sal_False );
							if( pFlyFrm )
								SelectFlyFrm( *pFlyFrm, sal_True );
							// immer nur den ersten Fly-Frame nehmen; die anderen
							// wurden ueber Fly in Fly ins ClipBoard kopiert !
							break;
						}
						else
						{
							ASSERT( RES_DRAWFRMFMT == pNew->Which(), "Neues Format.");
                            // --> OD 2005-09-01 #i52780# - drawing object has
                            // to be made visible on paste.
                            {
                                SwDrawContact* pContact =
                                    static_cast<SwDrawContact*>(pNew->FindContactObj());
                                pContact->MoveObjToVisibleLayer( pContact->GetMaster() );
                            }
                            // <--
                            SdrObject *pObj = pNew->FindSdrObject();
							SwDrawView  *pDV = Imp()->GetDrawView();
							pDV->MarkObj( pObj, pDV->GetSdrPageView() );
                            // --> OD 2005-04-15 #i47455# - notify draw frame format
                            // that position attributes are already set.
                            if ( pNew->ISA(SwDrawFrmFmt) )
                            {
                                static_cast<SwDrawFrmFmt*>(pNew)->PosAttrSet();
                            }
                            // <--
						}
					}
				}
			}
		}
		else
		{
			if( bDelTbl && IsTableMode() )
			{
				SwEditShell::Delete();
				bDelTbl = sal_False;
			}

			SwPosition& rInsPos = *PCURCRSR->GetPoint();
			const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().
													FindTableBoxStartNode();
			if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() -
								pBoxNd->GetIndex() &&
				aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode )
			{
				// es wird mehr als 1 Node in die akt. Box kopiert. Dann
				// muessen die BoxAttribute aber entfernt werden.
				GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
			}
            //find out if the clipboard document starts with a table
            bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
            SwPosition aInsertPosition( rInsPos );

            {
                SwNodeIndex aIndexBefore(rInsPos.nNode);

                aIndexBefore--;

                pClpDoc->CopyRange( aCpyPam, rInsPos, false );

                {
                    aIndexBefore++;
                    SwPaM aPaM(SwPosition(aIndexBefore),
                               SwPosition(rInsPos.nNode));

                    aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
                }
            }

			SaveTblBoxCntnt( &rInsPos );
            if(bIncludingPageFrames && bStartWithTable)
            {
                //remove the paragraph in front of the table
                SwPaM aPara(aInsertPosition);
                GetDoc()->DelFullPara(aPara);
            }
            //additionally copy page bound frames
            if( bIncludingPageFrames && pClpDoc->GetSpzFrmFmts()->Count() )
            {
                // create a draw view if necessary
                if( !Imp()->GetDrawView() )
                    MakeDrawView();

                for ( sal_uInt16 i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i )
                {
                    sal_Bool bInsWithFmt = sal_True;
                    const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i];
                    if( bInsWithFmt  )
                    {
                        SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
                        if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
                        {
                            aAnchor.SetPageNum( aAnchor.GetPageNum() + nStartPageNumber - 1 );
                        }
                        else
                            continue;
                        GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
                    }
                }
            }
		}

        FOREACHPAM_END()
    }

    GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );

	// wurden neue Tabellenformeln eingefuegt ?
	if( pTblFldTyp->GetDepends() )
	{
		// alte Actions beenden; die Tabellen-Frames werden angelegt und
		// eine Selection kann erzeugt werden
		sal_uInt16 nActCnt;
		for( nActCnt = 0; ActionPend(); ++nActCnt )
			EndAllAction();

		for( ; nActCnt; --nActCnt )
			StartAllAction();
	}
	GetDoc()->UnlockExpFlds();
	GetDoc()->UpdateFlds(NULL, false);
	EndAllAction();

	return bRet;
}

/*-- 14.06.2004 13:31:17---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage)
{
    Push();
    if(!GotoPage(nStartPage))
    {
        Pop(sal_False);
        return sal_False;
    }
    MovePage( fnPageCurr, fnPageStart );
    SwPaM aCpyPam( *GetCrsr()->GetPoint() );
    String sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName();
    SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, sal_True );
    if( pDesc )
        rToFill.ChgCurPageDesc( *pDesc );

    if(!GotoPage(nEndPage))
    {
        Pop(sal_False);
        return sal_False;
    }
    //if the page starts with a table a paragraph has to be inserted before
    SwNode* pTableNode = aCpyPam.GetNode()->FindTableNode();
    if(pTableNode)
    {
        //insert a paragraph
        StartUndo(UNDO_INSERT);
        SwNodeIndex aTblIdx(  *pTableNode, -1 );
        SwPosition aBefore(aTblIdx);
        if(GetDoc()->AppendTxtNode( aBefore ))
        {
            SwPaM aTmp(aBefore);
            aCpyPam = aTmp;
        }
        EndUndo(UNDO_INSERT);
    }

    MovePage( fnPageCurr, fnPageEnd );
    aCpyPam.SetMark();
    *aCpyPam.GetMark() = *GetCrsr()->GetPoint();

    SET_CURR_SHELL( this );

    StartAllAction();
    GetDoc()->LockExpFlds();
    SetSelection(aCpyPam);
    // copy the text of the selection
    SwEditShell::Copy(&rToFill);

    if(pTableNode)
    {
        //remove the inserted paragraph
        Undo();
        //remove the paragraph in the second doc, too
	    SwNodeIndex aIdx( rToFill.GetDoc()->GetNodes().GetEndOfExtras(), 2 );
	    SwPaM aPara( aIdx ); //DocStart
        rToFill.GetDoc()->DelFullPara(aPara);
    }
    // now the page bound objects
    //additionally copy page bound frames
    if( GetDoc()->GetSpzFrmFmts()->Count() )
    {
        // create a draw view if necessary
        if( !rToFill.Imp()->GetDrawView() )
            rToFill.MakeDrawView();

        for ( sal_uInt16 i = 0; i < GetDoc()->GetSpzFrmFmts()->Count(); ++i )
        {
            const SwFrmFmt& rCpyFmt = *(*GetDoc()->GetSpzFrmFmts())[i];
            SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
            if ((FLY_AT_PAGE == aAnchor.GetAnchorId()) &&
                    aAnchor.GetPageNum() >= nStartPage && aAnchor.GetPageNum() <= nEndPage)
            {
                aAnchor.SetPageNum( aAnchor.GetPageNum() - nStartPage + 1);
            }
            else
                continue;
            rToFill.GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
        }
    }
    GetDoc()->UnlockExpFlds();
    GetDoc()->UpdateFlds(NULL, false);
    Pop(sal_False);
    EndAllAction();

    return sal_True;
}

sal_Bool SwFEShell::GetDrawObjGraphic( sal_uLong nFmt, Graphic& rGrf ) const
{
	ASSERT( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
	const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
	sal_Bool bConvert = sal_True;
	if( rMrkList.GetMarkCount() )
	{
		if( rMrkList.GetMarkCount() == 1 &&
			rMrkList.GetMark( 0 )->GetMarkedSdrObj()->ISA(SwVirtFlyDrawObj) )
		{
			// Rahmen selektiert
			if( CNT_GRF == GetCntType() )
			{
                // --> OD 2005-02-09 #119353# - robust
                const Graphic* pGrf( GetGraphic() );
                if ( pGrf )
                {
                    Graphic aGrf( *pGrf );
                    if( SOT_FORMAT_GDIMETAFILE == nFmt )
                    {
                        if( GRAPHIC_BITMAP != aGrf.GetType() )
                        {
                            rGrf = aGrf;
                            bConvert = sal_False;
                        }
                        else if( GetWin() )
                        {
                            Size aSz;
                            Point aPt;
                            GetGrfSize( aSz );

                            VirtualDevice aVirtDev;
                            aVirtDev.EnableOutput( sal_False );

                            MapMode aTmp( GetWin()->GetMapMode() );
                            aTmp.SetOrigin( aPt );
                            aVirtDev.SetMapMode( aTmp );

                            GDIMetaFile aMtf;
                            aMtf.Record( &aVirtDev );
                            aGrf.Draw( &aVirtDev, aPt, aSz );
                            aMtf.Stop();
                            aMtf.SetPrefMapMode( aTmp );
                            aMtf.SetPrefSize( aSz );
                            rGrf = aMtf;
                        }
                    }
                    else if( GRAPHIC_BITMAP == aGrf.GetType() )
                    {
                        rGrf = aGrf;
                        bConvert = sal_False;
                    }
                    else
                    {
                        //fix(23806): Nicht die Originalgroesse, sondern die
                        //aktuelle. Anderfalls kann es passieren, dass z.B. bei
                        //Vektorgrafiken mal eben zig MB angefordert werden.
                        const Size aSz( FindFlyFrm()->Prt().SSize() );
                        VirtualDevice aVirtDev( *GetWin() );

                        MapMode aTmp( MAP_TWIP );
                        aVirtDev.SetMapMode( aTmp );
                        if( aVirtDev.SetOutputSize( aSz ) )
                        {
                            aGrf.Draw( &aVirtDev, Point(), aSz );
                            rGrf = aVirtDev.GetBitmap( Point(), aSz );
                        }
                        else
                        {
                            rGrf = aGrf;
                            bConvert = sal_False;
                        }
                    }
                }
                // <--
			}
		}
		else if( SOT_FORMAT_GDIMETAFILE == nFmt )
			rGrf = Imp()->GetDrawView()->GetMarkedObjMetaFile();
		else if( SOT_FORMAT_BITMAP == nFmt || SOT_FORMATSTR_ID_PNG == nFmt )
			rGrf = Imp()->GetDrawView()->GetMarkedObjBitmapEx();
	}
	return bConvert;
}

// --> OD 2005-08-03 #i50824#
// --> OD 2006-03-01 #b6382898#
// replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel* _pModel )
{
    for ( sal_uInt16 nPgNum = 0; nPgNum < _pModel->GetPageCount(); ++nPgNum )
    {
        // setup object iterator in order to iterate through all objects
        // including objects in group objects, but exclusive group objects.
        SdrObjListIter aIter(*(_pModel->GetPage( nPgNum )));
        while( aIter.IsMore() )
        {
            SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() );
            if( pOle2Obj )
            {
                // found an ole2 shape
                SdrObjList* pObjList = pOle2Obj->GetObjList();

                // get its graphic
                Graphic aGraphic;
                pOle2Obj->Connect();
                Graphic* pGraphic = pOle2Obj->GetGraphic();
                if( pGraphic )
                    aGraphic = *pGraphic;
                pOle2Obj->Disconnect();

                // create new graphic shape with the ole graphic and shape size
                SdrGrafObj* pGraphicObj = new SdrGrafObj( aGraphic, pOle2Obj->GetCurrentBoundRect() );
                // apply layer of ole2 shape at graphic shape
                pGraphicObj->SetLayer( pOle2Obj->GetLayer() );

                // replace ole2 shape with the new graphic object and delete the ol2 shape
                SdrObject* pRemovedObject = pObjList->ReplaceObject( pGraphicObj, pOle2Obj->GetOrdNum() );
                SdrObject::Free( pRemovedObject );
            }
        }
    }
}
// <--
void SwFEShell::Paste( SvStream& rStrm, sal_uInt16 nAction, const Point* pPt )
{
	SET_CURR_SHELL( this );
	StartAllAction();
	StartUndo();

	SvtPathOptions aPathOpt;
	FmFormModel* pModel = new FmFormModel( aPathOpt.GetPalettePath(),
											0, GetDoc()->GetDocShell() );
	pModel->GetItemPool().FreezeIdRanges();

	rStrm.Seek(0);

    uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rStrm ) );
	SvxDrawingLayerImport( pModel, xInputStream );

	if ( !Imp()->HasDrawView() )
		Imp()->MakeDrawView();

	Point aPos( pPt ? *pPt : GetCharRect().Pos() );
	SdrView *pView = Imp()->GetDrawView();

	//Drop auf bestehendes Objekt: Objekt ersetzen oder neu Attributieren.
	if( pModel->GetPageCount() > 0 &&
        1 == pModel->GetPage(0)->GetObjCount() &&
		1 == pView->GetMarkedObjectList().GetMarkCount() )
	{
        // OD 10.07.2003 #110742# - replace a marked 'virtual' drawing object
        // by its corresponding 'master' drawing object in the mark list.
        SwDrawView::ReplaceMarkedDrawVirtObjs( *pView );

        SdrObject* pClpObj = pModel->GetPage(0)->GetObj(0);
		SdrObject* pOldObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();

		if( SW_PASTESDR_SETATTR == nAction && pOldObj->ISA(SwVirtFlyDrawObj) )
			nAction = SW_PASTESDR_REPLACE;

		switch( nAction )
		{
		case SW_PASTESDR_REPLACE:
			{
				const SwFrmFmt* pFmt(0);
				const SwFrm* pAnchor(0);
				if( pOldObj->ISA(SwVirtFlyDrawObj) )
				{
					pFmt = FindFrmFmt( pOldObj );

					Point aNullPt;
					SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFmt)->GetFrm( &aNullPt );
                    pAnchor = pFlyFrm->GetAnchorFrm();

					if( pAnchor->FindFooterOrHeader() )
					{
						// wenn TextRahmen in der Kopf/Fusszeile steht, dann
						// nicht ersetzen, sondern nur einfuegen
						nAction = SW_PASTESDR_INSERT;
						break;
					}
				}

				SdrObject* pNewObj = pClpObj->Clone();
				Rectangle aOldObjRect( pOldObj->GetCurrentBoundRect() );
				Size aOldObjSize( aOldObjRect.GetSize() );
				Rectangle aNewRect( pNewObj->GetCurrentBoundRect() );
				Size aNewSize( aNewRect.GetSize() );

				Fraction aScaleWidth( aOldObjSize.Width(), aNewSize.Width() );
				Fraction aScaleHeight( aOldObjSize.Height(), aNewSize.Height());
				pNewObj->NbcResize( aNewRect.TopLeft(), aScaleWidth, aScaleHeight);

				Point aVec = aOldObjRect.TopLeft() - aNewRect.TopLeft();
				pNewObj->NbcMove(Size(aVec.X(), aVec.Y()));

                if( pNewObj->ISA( SdrUnoObj ) )
                    pNewObj->SetLayer( GetDoc()->GetControlsId() );
                else if( pOldObj->ISA( SdrUnoObj ) )
                    pNewObj->SetLayer( GetDoc()->GetHeavenId() );
                else
                    pNewObj->SetLayer( pOldObj->GetLayer() );

				if( pOldObj->ISA(SwVirtFlyDrawObj) )
				{
					// Attribute sichern und dam SdrObject setzen
					SfxItemSet aFrmSet( pDoc->GetAttrPool(),
											RES_SURROUND, RES_ANCHOR );
					aFrmSet.Set( pFmt->GetAttrSet() );

					Point aNullPt;
					if( pAnchor->IsTxtFrm() && ((SwTxtFrm*)pAnchor)->IsFollow() )
					{
						const SwTxtFrm* pTmp = (SwTxtFrm*)pAnchor;
						do {
							pTmp = pTmp->FindMaster();
							ASSERT( pTmp, "Where's my Master?" );
						} while( pTmp->IsFollow() );
						pAnchor = pTmp;
					}
					if( pOldObj->ISA( SdrCaptionObj ))
						aNullPt = ((SdrCaptionObj*)pOldObj)->GetTailPos();
					else
						aNullPt = aOldObjRect.TopLeft();

                    Point aNewAnchor = pAnchor->GetFrmAnchorPos( ::HasWrap( pOldObj ) );
                    // OD 2004-04-05 #i26791# - direct positioning of Writer
                    // fly frame object for <SwDoc::Insert(..)>
                    pNewObj->NbcSetRelativePos( aNullPt - aNewAnchor );
                    pNewObj->NbcSetAnchorPos( aNewAnchor );

                    pOldObj->GetOrdNum();

					DelSelectedObj();

					pFmt = GetDoc()->Insert( *GetCrsr(), *pNewObj, &aFrmSet, NULL );
				}
				else
                {
                    // #123922#  for handling MasterObject and virtual ones correctly, SW
                    // wants us to call ReplaceObject at the page, but that also
                    // triggers the same assertion (I tried it), so stay at the view method
                    pView->ReplaceObjectAtView(pOldObj, *Imp()->GetPageView(), pNewObj);
                }
			}
			break;

		case SW_PASTESDR_SETATTR:
			{
				SfxItemSet aSet( GetAttrPool() );
                const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pClpObj);

                if(pSdrGrafObj)
                {
                    SdrObject* pTarget = 0;

                    if(0 != pView->GetMarkedObjectList().GetMarkCount())
                    {
                        // try to get target (if it's at least one, take first)
                        SdrMark* pMark = pView->GetMarkedObjectList().GetMark(0);

                        if(pMark)
                        {
                            pTarget = pMark->GetMarkedSdrObj();
                        }
                    }

                    if(pTarget)
                    {
                        // copy ItemSet from target
                        aSet.Set(pTarget->GetMergedItemSet());
                    }

                    // for SdrGrafObj, use the graphic as fill style argument
                    const Graphic& rGraphic = pSdrGrafObj->GetGraphic();

                    if(GRAPHIC_NONE != rGraphic.GetType() && GRAPHIC_DEFAULT != rGraphic.GetType())
                    {
                        aSet.Put(XFillBitmapItem(String(), rGraphic));
                        aSet.Put(XFillStyleItem(XFILL_BITMAP));
                    }
                }
                else
                {
                    aSet.Put(pClpObj->GetMergedItemSet());
                }

				pView->SetAttributes( aSet, sal_False );
			}
			break;

		default:
			nAction = SW_PASTESDR_INSERT;
			break;
		}
	}
	else
		nAction = SW_PASTESDR_INSERT;

	if( SW_PASTESDR_INSERT == nAction )
    {
        ::sw::DrawUndoGuard drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());

        sal_Bool bDesignMode = pView->IsDesignMode();
        if( !bDesignMode )
            pView->SetDesignMode( sal_True );

        // --> OD 2005-08-03 #i50824#
        // --> OD 2006-03-01 #b6382898#
        // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
        lcl_ConvertSdrOle2ObjsToSdrGrafObjs( pModel );
        // <--
        pView->Paste( *pModel, aPos );

		sal_uLong nCnt = pView->GetMarkedObjectList().GetMarkCount();
		if( nCnt )
		{
			const Point aNull( 0, 0 );
			for( sal_uLong i=0; i < nCnt; ++i )
			{
				SdrObject *pObj = pView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj();
				pObj->ImpSetAnchorPos( aNull );
			}

			pView->SetCurrentObj( OBJ_GRUP, SdrInventor );
			if ( nCnt > 1 )
				pView->GroupMarked();
			SdrObject *pObj = pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
            if( pObj->ISA( SdrUnoObj ) )
            {
                pObj->SetLayer( GetDoc()->GetControlsId() );
                bDesignMode = sal_True;
            }
            else
                pObj->SetLayer( GetDoc()->GetHeavenId() );
			const Rectangle &rSnap = pObj->GetSnapRect();
			const Size aDiff( rSnap.GetWidth()/2, rSnap.GetHeight()/2 );
			pView->MoveMarkedObj( aDiff );
			ImpEndCreate();
            if( !bDesignMode )
                pView->SetDesignMode( sal_False );
		}
	}
	EndUndo();
	EndAllAction();
	delete pModel;
}

bool SwFEShell::Paste( const Graphic &rGrf, const String& rURL )
{
    SET_CURR_SHELL( this );
    SdrObject* pObj = 0;
    SdrView *pView = Imp()->GetDrawView();

    sal_Bool bRet = 1 == pView->GetMarkedObjectList().GetMarkCount() &&
        (pObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj())->IsClosedObj() &&
        !pObj->ISA( SdrOle2Obj );

    if( bRet && pObj )
    {
        // #123922# added code to handle the two cases of SdrGrafObj and a fillable, non-
        // OLE object in focus
        SdrObject* pResult = pObj;

        if(dynamic_cast< SdrGrafObj* >(pObj))
        {
            SdrGrafObj* pNewGrafObj = (SdrGrafObj*)pObj->Clone();

            pNewGrafObj->SetGraphic(rGrf);

            // #123922#  for handling MasterObject and virtual ones correctly, SW
            // wants us to call ReplaceObject at the page, but that also
            // triggers the same assertion (I tried it), so stay at the view method
            pView->ReplaceObjectAtView(pObj, *pView->GetSdrPageView(), pNewGrafObj);

            // set in all cases - the Clone() will have copied an existing link (!)
            pNewGrafObj->SetGraphicLink(rURL, String());

            pResult = pNewGrafObj;
        }
        else
        {
            pView->AddUndo(new SdrUndoAttrObj(*pObj));

            SfxItemSet aSet(pView->GetModel()->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLBITMAP);

            aSet.Put(XFillStyleItem(XFILL_BITMAP));
            aSet.Put(XFillBitmapItem(String(), rGrf));
            pObj->SetMergedItemSetAndBroadcast(aSet);
        }

        // we are done; mark the modified/new object
        pView->MarkObj(pResult, pView->GetSdrPageView());
    }

    return bRet;
}