blob: 6f369ef12d0558f370d7df794cba4f214a7e9431 [file] [log] [blame]
/**************************************************************
*
* 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->InsertDrawObj(aTemp, *pNew, aSet );
}
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->InsertDrawObj( *pDestShell->GetCrsr(), *pNew, aSet );
}
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()->InsertDrawObj( *GetCrsr(), *pNewObj, aFrmSet );
}
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;
}