1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <hintids.hxx>
23 #include <vcl/graph.hxx>
24 #include <sot/formats.hxx>
25 #include <sfx2/docfile.hxx>
26 #include <svx/xfillit0.hxx>
27 #include <svx/svdocapt.hxx>
28 #include <svx/svdouno.hxx>
29 #include <svx/xbtmpit.hxx>
30 #include <svx/svdpage.hxx>
31 #include <svx/svdogrp.hxx>
32 #include <svx/svdoole2.hxx>
33 #include <svx/fmmodel.hxx>
34 #include <svx/unomodel.hxx>
35 #include <svx/svditer.hxx>
36 #include <svx/svdograf.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtcntnt.hxx>
40 #include <fmtornt.hxx>
41 #include <fmtflcnt.hxx>
45 #include <txtflcnt.hxx>
48 #include <IDocumentUndoRedo.hxx>
49 #include <IDocumentDrawModelAccess.hxx>
50 #include <IDocumentRedlineAccess.hxx>
51 #include <DocumentFieldsManager.hxx>
52 #include <IDocumentLayoutAccess.hxx>
53 #include <rootfrm.hxx>
57 #include <swtable.hxx>
59 #include <pagefrm.hxx>
62 #include <viewimp.hxx>
64 #include <dcontact.hxx>
65 #include <dflyobj.hxx>
67 #include <pagedesc.hxx>
69 #include <textboxhelper.hxx>
70 #include <frameformats.hxx>
71 #include <vcl/virdev.hxx>
72 #include <svx/svdundo.hxx>
74 using namespace ::com::sun::star
;
76 // Copy for the internal clipboard. Copies all selections to the clipboard.
77 void SwFEShell::Copy( SwDoc
& rClpDoc
, const OUString
* pNewClpText
)
79 rClpDoc
.GetIDocumentUndoRedo().DoUndo(false); // always false!
81 // delete content if ClpDocument contains content
82 SwNodeIndex
aSttIdx( rClpDoc
.GetNodes().GetEndOfExtras(), 2 );
83 SwNodeIndex
aEndNdIdx( *aSttIdx
.GetNode().EndOfSectionNode() );
84 SwTextNode
* pTextNd
= aSttIdx
.GetNode().GetTextNode();
85 if (!pTextNd
|| !pTextNd
->GetText().isEmpty() ||
86 aSttIdx
.GetIndex()+1 != rClpDoc
.GetNodes().GetEndOfContent().GetIndex() )
88 rClpDoc
.GetNodes().Delete( aSttIdx
,
89 rClpDoc
.GetNodes().GetEndOfContent().GetIndex() - aSttIdx
.GetIndex() );
90 pTextNd
= rClpDoc
.GetNodes().MakeTextNode( aSttIdx
,
91 rClpDoc
.GetDfltTextFormatColl() );
95 // also delete surrounding FlyFrames if any
96 for( const auto pFly
: *rClpDoc
.GetSpzFrameFormats() )
98 SwFormatAnchor
const*const pAnchor
= &pFly
->GetAnchor();
99 SwPosition
const*const pAPos
= pAnchor
->GetContentAnchor();
101 ((RndStdIds::FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
102 (RndStdIds::FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
103 aSttIdx
<= pAPos
->nNode
&& pAPos
->nNode
<= aEndNdIdx
)
105 rClpDoc
.getIDocumentLayoutAccess().DelLayoutFormat( pFly
);
109 rClpDoc
.GetDocumentFieldsManager().GCFieldTypes(); // delete the FieldTypes
111 // if a string was passed, copy it to the clipboard-
112 // document. Then also the Calculator can use the internal
116 pTextNd
->InsertText( *pNewClpText
, SwIndex( pTextNd
) );
120 rClpDoc
.getIDocumentFieldsAccess().LockExpFields();
121 rClpDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines
);
123 // do we want to copy a FlyFrame?
124 if( IsFrameSelected() )
127 SwFlyFrame
* pFly
= GetSelectedFlyFrame();
128 SwFrameFormat
* pFlyFormat
= pFly
->GetFormat();
129 SwFormatAnchor
aAnchor( pFlyFormat
->GetAnchor() );
131 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
132 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
133 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
134 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
136 SwPosition
aPos( aSttIdx
);
137 if ( RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId() )
139 aPos
.nContent
.Assign( pTextNd
, 0 );
141 aAnchor
.SetAnchor( &aPos
);
143 pFlyFormat
= rClpDoc
.getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat
, aAnchor
, true, true );
145 // assure the "RootFormat" is the first element in Spz-Array
146 // (if necessary Flys were copied in Flys)
147 SwFrameFormats
& rSpzFrameFormats
= *rClpDoc
.GetSpzFrameFormats();
148 if( rSpzFrameFormats
[ 0 ] != pFlyFormat
)
153 rSpzFrameFormats
.newDefault( pFlyFormat
);
154 assert( !inserted
&& "Fly not contained in Spz-Array" );
157 if ( RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId() )
159 // JP 13.02.99 Bug 61863: if a frameselection is passed to the
160 // clipboard, it should be found at pasting. Therefore
161 // the copied TextAttribut should be removed in the node
162 // otherwise it will be recognised as TextSelektion
163 const SwIndex
& rIdx
= pFlyFormat
->GetAnchor().GetContentAnchor()->nContent
;
164 SwTextFlyCnt
*const pTextFly
= static_cast<SwTextFlyCnt
*>(
165 pTextNd
->GetTextAttrForCharAt(
166 rIdx
.GetIndex(), RES_TXTATR_FLYCNT
));
169 const_cast<SwFormatFlyCnt
&>(pTextFly
->GetFlyCnt()).SetFlyFormat();
170 pTextNd
->EraseText( rIdx
, 1 );
174 else if ( IsObjSelected() )
176 SwPosition
aPos( aSttIdx
, SwIndex( pTextNd
, 0 ));
177 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
178 for ( size_t i
= 0; i
< rMrkList
.GetMarkCount(); ++i
)
180 SdrObject
*pObj
= rMrkList
.GetMark( i
)->GetMarkedSdrObj();
182 if( Imp()->GetDrawView()->IsGroupEntered() ||
183 ( !pObj
->GetUserCall() && pObj
->getParentSdrObjectFromSdrObject()) )
185 SfxItemSet
aSet( rClpDoc
.GetAttrPool(), aFrameFormatSetRange
);
187 SwFormatAnchor
aAnchor( RndStdIds::FLY_AT_PARA
);
188 aAnchor
.SetAnchor( &aPos
);
191 SdrObject
*const pNew
=
192 rClpDoc
.CloneSdrObj( *pObj
);
195 rClpDoc
.getIDocumentContentOperations().InsertDrawObj(aTemp
, *pNew
, aSet
);
199 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall( pObj
));
200 SwFrameFormat
*pFormat
= pContact
->GetFormat();
201 SwFormatAnchor
aAnchor( pFormat
->GetAnchor() );
202 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
203 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
204 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
205 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
207 aAnchor
.SetAnchor( &aPos
);
210 rClpDoc
.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat
, aAnchor
, true, true );
215 CopySelToDoc(rClpDoc
); // copy the selections
217 rClpDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE
);
218 rClpDoc
.getIDocumentFieldsAccess().UnlockExpFields();
219 if( !rClpDoc
.getIDocumentFieldsAccess().IsExpFieldsLocked() )
220 rClpDoc
.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
223 static const Point
&lcl_FindBasePos( const SwFrame
*pFrame
, const Point
&rPt
)
225 const SwFrame
*pF
= pFrame
;
226 while ( pF
&& !pF
->getFrameArea().IsInside( rPt
) )
228 if ( pF
->IsContentFrame() )
229 pF
= static_cast<const SwContentFrame
*>(pF
)->GetFollow();
234 return pF
->getFrameArea().Pos();
236 return pFrame
->getFrameArea().Pos();
239 static bool lcl_SetAnchor( const SwPosition
& rPos
, const SwNode
& rNd
, SwFlyFrame
const * pFly
,
240 const Point
& rInsPt
, SwFEShell
const & rDestShell
, SwFormatAnchor
& rAnchor
,
241 Point
& rNewPos
, bool bCheckFlyRecur
)
244 rAnchor
.SetAnchor( &rPos
);
245 std::pair
<Point
, bool> const tmp(rInsPt
, false);
246 SwContentFrame
*const pTmpFrame
= rNd
.GetContentNode()->getLayoutFrame(
247 rDestShell
.GetLayout(), nullptr, &tmp
);
248 SwFlyFrame
*pTmpFly
= pTmpFrame
->FindFlyFrame();
249 if( pTmpFly
&& bCheckFlyRecur
&& pFly
->IsUpperOf( *pTmpFly
) )
253 else if ( RndStdIds::FLY_AT_FLY
== rAnchor
.GetAnchorId() )
257 const SwNodeIndex
& rIdx
= *pTmpFly
->GetFormat()->GetContent().GetContentIdx();
258 SwPosition
aPos( rIdx
);
259 rAnchor
.SetAnchor( &aPos
);
260 rNewPos
= pTmpFly
->getFrameArea().Pos();
264 rAnchor
.SetType( RndStdIds::FLY_AT_PAGE
);
265 rAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
266 const SwFrame
*pPg
= pTmpFrame
->FindPageFrame();
267 rNewPos
= pPg
->getFrameArea().Pos();
271 rNewPos
= ::lcl_FindBasePos( pTmpFrame
, rInsPt
);
275 bool SwFEShell::CopyDrawSel( SwFEShell
& rDestShell
, const Point
& rSttPt
,
276 const Point
& rInsPt
, bool bIsMove
, bool bSelectInsert
)
280 // The list should be copied, because below new objects will be selected
281 const SdrMarkList
aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() );
282 const size_t nMarkCount
= aMrkList
.GetMarkCount();
283 if( !rDestShell
.Imp()->GetDrawView() )
284 // should create it now
285 rDestShell
.MakeDrawView();
286 else if( bSelectInsert
)
287 rDestShell
.Imp()->GetDrawView()->UnmarkAll();
289 SdrPageView
*pDestPgView
= rDestShell
.Imp()->GetPageView(),
290 *pSrcPgView
= Imp()->GetPageView();
291 SwDrawView
*pDestDrwView
= rDestShell
.Imp()->GetDrawView(),
292 *pSrcDrwView
= Imp()->GetDrawView();
293 SwDoc
* pDestDoc
= rDestShell
.GetDoc();
295 Size
aSiz( rInsPt
.X() - rSttPt
.X(), rInsPt
.Y() - rSttPt
.Y() );
296 for( size_t i
= 0; i
< nMarkCount
; ++i
)
298 SdrObject
*pObj
= aMrkList
.GetMark( i
)->GetMarkedSdrObj();
300 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall( pObj
));
301 SwFrameFormat
*pFormat
= pContact
->GetFormat();
302 const SwFormatAnchor
& rAnchor
= pFormat
->GetAnchor();
304 bool bInsWithFormat
= true;
306 if( pDestDrwView
->IsGroupEntered() )
308 // insert into the group, when it belongs to an entered group
309 // or when the object is not anchored as a character
310 if( pSrcDrwView
->IsGroupEntered() ||
311 (RndStdIds::FLY_AS_CHAR
!= rAnchor
.GetAnchorId()) )
314 SdrObject
* pNew
= pDestDoc
->CloneSdrObj( *pObj
, bIsMove
&&
315 GetDoc() == pDestDoc
, false );
316 pNew
->NbcMove( aSiz
);
317 pDestDrwView
->InsertObjectAtView( pNew
, *pDestPgView
);
318 bInsWithFormat
= false;
324 SwFormatAnchor
aAnchor( rAnchor
);
327 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
328 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
329 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
330 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
332 if ( this == &rDestShell
)
334 // same shell? Then request the position
335 // from the passed DocumentPosition
336 SwPosition
aPos( *GetCursor()->GetPoint() );
338 aPt
-= rSttPt
- pObj
->GetSnapRect().TopLeft();
339 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
340 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
, &aState
);
342 if( (pNd
= &aPos
.nNode
.GetNode())->IsNoTextNode() )
345 bRet
= ::lcl_SetAnchor( aPos
, *pNd
, nullptr, rInsPt
,
346 rDestShell
, aAnchor
, aNewAnch
, false );
350 SwPaM
*pCursor
= rDestShell
.GetCursor();
351 if( pCursor
->GetNode().IsNoTextNode() )
354 bRet
= ::lcl_SetAnchor( *pCursor
->GetPoint(),
355 pCursor
->GetNode(), nullptr, rInsPt
,
360 else if ( RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId() )
362 aAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
363 const SwRootFrame
* pTmpRoot
= rDestShell
.GetLayout();
364 const SwFrame
* pPg
= pTmpRoot
->GetPageAtPos( rInsPt
, nullptr, true );
366 aNewAnch
= pPg
->getFrameArea().Pos();
371 if( pSrcDrwView
->IsGroupEntered() ||
372 ( !pObj
->GetUserCall() && pObj
->getParentSdrObjectFromSdrObject()) )
374 SfxItemSet
aSet( pDestDoc
->GetAttrPool(),aFrameFormatSetRange
);
376 SdrObject
* pNew
= pDestDoc
->CloneSdrObj( *pObj
, bIsMove
&&
377 GetDoc() == pDestDoc
);
378 pFormat
= pDestDoc
->getIDocumentContentOperations().InsertDrawObj( *rDestShell
.GetCursor(), *pNew
, aSet
);
381 pFormat
= pDestDoc
->getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat
, aAnchor
, true, true );
383 // Can be 0, as Draws are not allowed in Headers/Footers
386 // #tdf33692 - drawing object has to be made visible on ctrl+drag copy.
387 pFormat
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING
));
388 SdrObject
* pNew
= pFormat
->FindSdrObject();
389 if ( RndStdIds::FLY_AS_CHAR
!= aAnchor
.GetAnchorId() )
391 Point
aPos( rInsPt
);
393 aPos
-= rSttPt
- pObj
->GetSnapRect().TopLeft();
394 // OD 2004-04-05 #i26791# - change attributes instead of
395 // direct positioning
396 pFormat
->SetFormatAttr( SwFormatHoriOrient( aPos
.getX(), text::HoriOrientation::NONE
, text::RelOrientation::FRAME
) );
397 pFormat
->SetFormatAttr( SwFormatVertOrient( aPos
.getY(), text::VertOrientation::NONE
, text::RelOrientation::FRAME
) );
398 // #i47455# - notify draw frame format
399 // that position attributes are already set.
400 if (SwDrawFrameFormat
*pDrawFormat
= dynamic_cast<SwDrawFrameFormat
*>(pFormat
))
401 pDrawFormat
->PosAttrSet();
403 if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_DRAWFRMFMT
))
405 SwTextBoxHelper::syncFlyFrameAttr(*pFormat
, pFormat
->GetAttrSet());
409 pDestDrwView
->MarkObj( pNew
, pDestPgView
);
415 if ( bIsMove
&& bRet
)
417 if( &rDestShell
== this )
419 const SdrMarkList
aList( pSrcDrwView
->GetMarkedObjectList() );
420 pSrcDrwView
->UnmarkAll();
422 for ( size_t i
= 0, nMrkCnt
= aMrkList
.GetMarkCount(); i
< nMrkCnt
; ++i
)
424 SdrObject
*pObj
= aMrkList
.GetMark( i
)->GetMarkedSdrObj();
425 pSrcDrwView
->MarkObj( pObj
, pSrcPgView
);
428 for ( size_t i
= 0, nMrkCnt
= aList
.GetMarkCount(); i
< nMrkCnt
; ++i
)
430 SdrObject
*pObj
= aList
.GetMark( i
)->GetMarkedSdrObj();
431 pSrcDrwView
->MarkObj( pObj
, pSrcPgView
);
441 bool SwFEShell::Copy( SwFEShell
& rDestShell
, const Point
& rSttPt
,
442 const Point
& rInsPt
, bool bIsMove
, bool bSelectInsert
)
446 OSL_ENSURE( this == &rDestShell
|| !rDestShell
.IsObjSelected(),
447 "Dest-Shell cannot be in Obj-Mode" );
449 CurrShell
aCurr( &rDestShell
);
451 rDestShell
.StartAllAction();
452 rDestShell
.GetDoc()->getIDocumentFieldsAccess().LockExpFields();
455 bool bCopyIsMove
= mxDoc
->IsCopyIsMove();
457 // set a flag in Doc, handled in TextNodes
458 mxDoc
->SetCopyIsMove( true );
460 RedlineFlags eOldRedlMode
= rDestShell
.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
461 rDestShell
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode
| RedlineFlags::DeleteRedlines
);
463 // If there are table formulas in the area, then display the table first
464 // so that the table formula can calculate a new value first
465 // (individual boxes in the area are retrieved via the layout)
466 SwFieldType
* pTableFieldTyp
= rDestShell
.GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table
);
468 if( IsFrameSelected() )
470 SwFlyFrame
* pFly
= GetSelectedFlyFrame();
471 SwFrameFormat
* pFlyFormat
= pFly
->GetFormat();
472 SwFormatAnchor
aAnchor( pFlyFormat
->GetAnchor() );
476 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
477 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
478 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
479 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
481 if ( this == &rDestShell
)
483 // same shell? Then request the position
484 // from the passed DocumentPosition
485 SwPosition
aPos( *GetCursor()->GetPoint() );
487 aPt
-= rSttPt
- pFly
->getFrameArea().Pos();
488 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
489 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
, &aState
);
491 if( (pNd
= &aPos
.nNode
.GetNode())->IsNoTextNode() )
495 // do not copy in itself
496 const SwNodeIndex
*pTmp
= pFlyFormat
->GetContent().GetContentIdx();
497 if ( aPos
.nNode
> *pTmp
&& aPos
.nNode
<
498 pTmp
->GetNode().EndOfSectionIndex() )
503 bRet
= ::lcl_SetAnchor( aPos
, *pNd
, pFly
, rInsPt
,
504 rDestShell
, aAnchor
, aNewAnch
, true );
509 const SwPaM
*pCursor
= rDestShell
.GetCursor();
510 if( pCursor
->GetNode().IsNoTextNode() )
513 bRet
= ::lcl_SetAnchor( *pCursor
->GetPoint(), pCursor
->GetNode(),
514 pFly
, rInsPt
, rDestShell
, aAnchor
,
515 aNewAnch
, GetDoc() == rDestShell
.GetDoc());
518 else if ( RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId() )
520 aAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
521 const SwRootFrame
* pTmpRoot
= rDestShell
.GetLayout();
522 const SwFrame
* pPg
= pTmpRoot
->GetPageAtPos( rInsPt
, nullptr, true );
524 aNewAnch
= pPg
->getFrameArea().Pos();
527 OSL_ENSURE( false, "what anchor is it?" );
532 SwFrameFormat
*pOldFormat
= pFlyFormat
;
533 pFlyFormat
= rDestShell
.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat
, aAnchor
, true, true );
535 if ( RndStdIds::FLY_AS_CHAR
!= aAnchor
.GetAnchorId() )
537 Point
aPos( rInsPt
);
539 aPos
-= rSttPt
- pFly
->getFrameArea().Pos();
540 pFlyFormat
->SetFormatAttr( SwFormatHoriOrient( aPos
.getX(),text::HoriOrientation::NONE
, text::RelOrientation::FRAME
) );
541 pFlyFormat
->SetFormatAttr( SwFormatVertOrient( aPos
.getY(),text::VertOrientation::NONE
, text::RelOrientation::FRAME
) );
544 const Point
aPt( rDestShell
.GetCursorDocPos() );
547 GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pOldFormat
);
549 // only select if it can be shifted/copied in the same shell
552 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrameFormat
*>(pFlyFormat
)->GetFrame( &aPt
);
555 //JP 12.05.98: should this be in SelectFlyFrame???
556 rDestShell
.Imp()->GetDrawView()->UnmarkAll();
557 rDestShell
.SelectFlyFrame( *pFlyFrame
);
561 if (this != &rDestShell
&& !rDestShell
.HasShellFocus())
562 rDestShell
.Imp()->GetDrawView()->hideMarkHandles();
565 else if ( IsObjSelected() )
566 bRet
= CopyDrawSel( rDestShell
, rSttPt
, rInsPt
, bIsMove
, bSelectInsert
);
567 else if( IsTableMode() )
569 // Copy parts from a table: create a table with the same
570 // width as the original and copy the selected boxes.
571 // Sizes will be corrected by percentage.
573 // find boxes via the layout
575 GetTableSel( *this, aBoxes
);
576 SwTableNode
const*const pTableNd(
577 aBoxes
.empty() ? nullptr : aBoxes
[0]->GetSttNd()->FindTableNode());
578 if (nullptr != pTableNd
)
580 std::unique_ptr
<SwPosition
> pDstPos
;
581 if( this == &rDestShell
)
583 // same shell? Then create new Cursor at the
584 // DocumentPosition passed
585 pDstPos
.reset(new SwPosition( *GetCursor()->GetPoint() ));
587 GetLayout()->GetModelPositionForViewPoint( pDstPos
.get(), aPt
);
588 if( !pDstPos
->nNode
.GetNode().IsNoTextNode() )
591 else if( !rDestShell
.GetCursor()->GetNode().IsNoTextNode() )
593 pDstPos
.reset(new SwPosition( *rDestShell
.GetCursor()->GetPoint() ));
599 if( GetDoc() == rDestShell
.GetDoc() )
602 bRet
= rDestShell
.GetDoc()->InsCopyOfTable( *pDstPos
, aBoxes
,nullptr,
603 bIsMove
&& this == &rDestShell
&&
604 aBoxes
.size() == pTableNd
->GetTable().
605 GetTabSortBoxes().size(),
606 this != &rDestShell
);
608 if( this != &rDestShell
)
609 *rDestShell
.GetCursor()->GetPoint() = *pDstPos
;
611 // create all parked Cursor?
612 if( GetDoc() == rDestShell
.GetDoc() )
615 // JP 16.04.99: Bug 64908 - Set InsPos, to assure the parked
616 // Cursor is positioned at the insert position
617 if( this == &rDestShell
)
618 GetCursorDocPos() = rInsPt
;
625 if( this == &rDestShell
)
627 // same shell? then request the position
628 // at the passed document position
629 SwPosition
aPos( *GetCursor()->GetPoint() );
631 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
);
632 bRet
= !aPos
.nNode
.GetNode().IsNoTextNode();
634 else if( rDestShell
.GetCursor()->GetNode().IsNoTextNode() )
638 bRet
= SwEditShell::Copy( rDestShell
);
641 rDestShell
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode
);
642 mxDoc
->SetCopyIsMove( bCopyIsMove
);
644 // have new table formulas been inserted?
645 if( pTableFieldTyp
->HasWriterListeners() )
647 // finish old actions: the table frames are created and
648 // a selection can be made
650 for( nActCnt
= 0; rDestShell
.ActionPend(); ++nActCnt
)
651 rDestShell
.EndAllAction();
653 for( ; nActCnt
; --nActCnt
)
654 rDestShell
.StartAllAction();
656 rDestShell
.GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
657 rDestShell
.GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
659 rDestShell
.EndAllAction();
663 // Paste for the internal clipboard. Copy the content of the clipboard
666 typedef std::shared_ptr
<SwPaM
> PaMPtr
;
667 typedef std::shared_ptr
<SwPosition
> PositionPtr
;
668 typedef std::pair
< PaMPtr
, PositionPtr
> Insertion
;
670 bool PamHasSelection(const SwPaM
& rPaM
)
672 return rPaM
.HasMark() && *rPaM
.GetPoint() != *rPaM
.GetMark();
675 /// Is pFormat anchored in a fly frame which has an associated draw format?
676 bool IsInTextBox(const SwFrameFormat
* pFormat
)
678 const SwFormatAnchor
& rAnchor
= pFormat
->GetAnchor();
679 const SwPosition
* pPosition
= rAnchor
.GetContentAnchor();
685 const SwStartNode
* pFlyNode
= pPosition
->nNode
.GetNode().FindFlyStartNode();
691 for ( const auto& pSpzFormat
: *pFormat
->GetDoc()->GetSpzFrameFormats() )
693 if (pSpzFormat
->Which() != RES_FLYFRMFMT
)
698 const SwNodeIndex
* pIdx
= pSpzFormat
->GetContent().GetContentIdx();
699 if (!pIdx
|| pFlyNode
!= &pIdx
->GetNode())
704 return SwTextBoxHelper::isTextBox(pSpzFormat
, RES_FLYFRMFMT
);
711 bool SwFEShell::Paste(SwDoc
& rClpDoc
, bool bNestedTable
)
713 CurrShell
aCurr( this );
714 // then till end of the nodes array
715 SwNodeIndex
aIdx( rClpDoc
.GetNodes().GetEndOfExtras(), 2 );
716 SwPaM
aCpyPam( aIdx
); //DocStart
718 // If there are table formulas in the area, then display the table first
719 // so that the table formula can calculate a new value first
720 // (individual boxes in the area are retrieved via the layout)
721 SwFieldType
* pTableFieldTyp
= GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table
);
723 SwTableNode
*const pSrcNd
= aCpyPam
.GetNode().GetTableNode();
724 if( !pSrcNd
) // table node ?
726 SwContentNode
* pCNd
= aCpyPam
.GetNode().GetContentNode();
728 aCpyPam
.GetPoint()->nContent
.Assign( pCNd
, 0 );
729 else if( !aCpyPam
.Move( fnMoveForward
, GoInNode
))
730 aCpyPam
.Move( fnMoveBackward
, GoInNode
);
734 aCpyPam
.Move( fnMoveForward
, GoInDoc
);
738 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSGLOSSARY
, nullptr );
739 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
741 // When the clipboard content has been created by a rectangular selection
742 // the pasting is more sophisticated:
743 // every paragraph will be inserted into another position.
744 // The first positions are given by the actual cursor ring,
745 // if there are more text portions to insert than cursor in this ring,
746 // the additional insert positions will be created by moving the last
747 // cursor position into the next line (like pressing the cursor down key)
748 if( rClpDoc
.IsColumnSelection() && !IsTableMode() )
750 // Creation of the list of insert positions
751 std::vector
< Insertion
> aCopyVector
;
752 // The number of text portions of the rectangular selection
753 const sal_uInt32 nSelCount
= aCpyPam
.GetPoint()->nNode
.GetIndex()
754 - aCpyPam
.GetMark()->nNode
.GetIndex();
755 sal_uInt32 nCount
= nSelCount
;
756 SwNodeIndex
aClpIdx( aIdx
);
757 SwPaM
* pStartCursor
= GetCursor();
758 SwPaM
* pCurrCursor
= pStartCursor
;
759 sal_uInt32 nCursorCount
= pStartCursor
->GetRingContainer().size();
760 // If the target selection is a multi-selection, often the last and first
761 // cursor of the ring points to identical document positions. Then
762 // we should avoid double insertion of text portions...
763 while( nCursorCount
> 1 && *pCurrCursor
->GetPoint() ==
764 *(pCurrCursor
->GetPrev()->GetPoint()) )
767 pCurrCursor
= pCurrCursor
->GetNext();
768 pStartCursor
= pCurrCursor
;
770 SwPosition
aStartPos( *pStartCursor
->GetPoint() );
771 SwPosition
aInsertPos( aStartPos
); // first insertion position
772 bool bCompletePara
= false;
773 sal_uInt16 nMove
= 0;
777 OSL_ENSURE( aIdx
.GetNode().GetContentNode(), "Who filled the clipboard?!" );
778 if( aIdx
.GetNode().GetContentNode() ) // robust
780 Insertion
aInsertion( std::make_shared
<SwPaM
>( aIdx
),
781 std::make_shared
<SwPosition
>( aInsertPos
) );
783 aInsertion
.first
->SetMark();
784 if( pStartCursor
== pCurrCursor
->GetNext() )
785 { // Now we have to look for insertion positions...
786 if( !nMove
) // Annotate the last given insert position
787 aStartPos
= aInsertPos
;
788 SwCursor
aCursor( aStartPos
, nullptr);
789 // Check if we find another insert position by moving
790 // down the last given position
791 if (aCursor
.UpDown(false, ++nMove
, nullptr, 0, *GetLayout()))
792 aInsertPos
= *aCursor
.GetPoint();
793 else // if there is no paragraph we have to create it
794 bCompletePara
= nCount
> 0;
797 else // as long as we find more insert positions in the cursor ring
799 pCurrCursor
= pCurrCursor
->GetNext();
800 aInsertPos
= *pCurrCursor
->GetPoint();
803 // If there are no more paragraphs e.g. at the end of a document,
804 // we insert complete paragraphs instead of text portions
806 aInsertion
.first
->GetPoint()->nNode
= aIdx
;
808 aInsertion
.first
->GetPoint()->nContent
=
809 aInsertion
.first
->GetContentNode()->Len();
810 aCopyVector
.push_back( aInsertion
);
812 // If there are no text portions left but there are some more
813 // cursor positions to fill we have to restart with the first
815 if( !nCount
&& nCursorCount
)
817 nCount
= std::min( nSelCount
, nCursorCount
);
818 aIdx
= aClpIdx
; // Start of clipboard content
821 for (auto const& item
: aCopyVector
)
823 SwPosition
& rInsPos
= *item
.second
;
824 SwPaM
& rCopy
= *item
.first
;
825 const SwStartNode
* pBoxNd
= rInsPos
.nNode
.GetNode().FindTableBoxStartNode();
826 if( pBoxNd
&& 2 == pBoxNd
->EndOfSectionIndex() - pBoxNd
->GetIndex() &&
827 rCopy
.GetPoint()->nNode
!= rCopy
.GetMark()->nNode
)
829 // if more than one node will be copied into a cell
830 // the box attributes have to be removed
831 GetDoc()->ClearBoxNumAttrs( rInsPos
.nNode
);
834 SwNodeIndex
aIndexBefore(rInsPos
.nNode
);
836 rClpDoc
.getIDocumentContentOperations().CopyRange(rCopy
, rInsPos
, SwCopyFlags::CheckPosInFly
);
839 SwPaM
aPaM(SwPosition(aIndexBefore
),
840 SwPosition(rInsPos
.nNode
));
841 aPaM
.GetDoc().MakeUniqueNumRules(aPaM
);
844 SaveTableBoxContent( &rInsPos
);
849 bool bDelTable
= true;
851 for(SwPaM
& rPaM
: GetCursor()->GetRingContainer())
854 SwTableNode
*const pDestNd(GetDoc()->IsIdxInTable(rPaM
.GetPoint()->nNode
));
855 if (pSrcNd
&& nullptr != pDestNd
&&
856 // not a forced nested table insertion
858 // are we at the beginning of the cell? (if not, we will insert a nested table)
859 // first paragraph of the cell?
860 rPaM
.GetNode().GetIndex() == rPaM
.GetNode().FindTableBoxStartNode()->GetIndex()+1 &&
861 // beginning of the paragraph?
862 !rPaM
.GetPoint()->nContent
.GetIndex())
864 SwPosition
aDestPos( *rPaM
.GetPoint() );
866 bool bParkTableCursor
= false;
867 const SwStartNode
* pSttNd
= rPaM
.GetNode().FindTableBoxStartNode();
869 // TABLE IN TABLE: copy table in table
870 // search boxes via the layout
872 if( IsTableMode() ) // table selection?
874 GetTableSel( *this, aBoxes
);
876 bParkTableCursor
= true;
878 else if( !PamHasSelection(rPaM
) && rPaM
.GetNext() == &rPaM
&&
879 ( !pSrcNd
->GetTable().IsTableComplex() ||
880 pDestNd
->GetTable().IsNewModel() ) )
882 // make relative table copy
883 SwTableBox
* pBox
= pDestNd
->GetTable().GetTableBox(
884 pSttNd
->GetIndex() );
885 OSL_ENSURE( pBox
, "Box is not in this table" );
886 aBoxes
.insert( pBox
);
889 SwNodeIndex
aNdIdx( *pDestNd
->EndOfSectionNode());
890 if( !bParkTableCursor
)
892 // exit first the complete table
893 // ???? what about only table in a frame ?????
894 SwContentNode
* pCNd
= GetDoc()->GetNodes().GoNext( &aNdIdx
);
895 SwPosition
aPos( aNdIdx
, SwIndex( pCNd
, 0 ));
896 // #i59539: Don't remove all redline
897 SwPaM
const tmpPaM(*pDestNd
, *pDestNd
->EndOfSectionNode());
898 ::PaMCorrAbs(tmpPaM
, aPos
);
901 bRet
= GetDoc()->InsCopyOfTable( aDestPos
, aBoxes
, &pSrcNd
->GetTable() );
903 if( bParkTableCursor
)
909 SwContentNode
* pCNd
= GetDoc()->GetNodes().GoNext( &aNdIdx
);
910 SwPosition
aPos( aNdIdx
, SwIndex( pCNd
, 0 ));
911 // #i59539: Don't remove all redline
912 SwNode
& rNode(rPaM
.GetPoint()->nNode
.GetNode());
913 SwContentNode
*const pContentNode( rNode
.GetContentNode() );
914 SwPaM
const tmpPam(rNode
, 0,
915 rNode
, pContentNode
? pContentNode
->Len() : 0);
916 ::PaMCorrAbs(tmpPam
, aPos
);
919 break; // exit the "while-loop"
921 else if( *aCpyPam
.GetPoint() == *aCpyPam
.GetMark() &&
922 !rClpDoc
.GetSpzFrameFormats()->empty() )
924 // we need a DrawView
925 if( !Imp()->GetDrawView() )
928 for ( auto pCpyFormat
: *rClpDoc
.GetSpzFrameFormats() )
930 bool bInsWithFormat
= true;
932 if( Imp()->GetDrawView()->IsGroupEntered() &&
933 RES_DRAWFRMFMT
== pCpyFormat
->Which() &&
934 (RndStdIds::FLY_AS_CHAR
!= pCpyFormat
->GetAnchor().GetAnchorId()) )
936 const SdrObject
* pSdrObj
= pCpyFormat
->FindSdrObject();
939 SdrObject
* pNew
= GetDoc()->CloneSdrObj( *pSdrObj
,
942 // Insert object sets any anchor position to 0.
943 // Therefore we calculate the absolute position here
944 // and after the insert the anchor of the object
945 // is set to the anchor of the group object.
946 tools::Rectangle aSnapRect
= pNew
->GetSnapRect();
947 if( pNew
->GetAnchorPos().X() || pNew
->GetAnchorPos().Y() )
949 const Point
aPoint( 0, 0 );
950 // OD 2004-04-05 #i26791# - direct drawing object
951 // positioning for group members
952 pNew
->NbcSetAnchorPos( aPoint
);
953 pNew
->NbcSetSnapRect( aSnapRect
);
956 Imp()->GetDrawView()->InsertObjectAtView( pNew
, *Imp()->GetPageView() );
958 Point
aGrpAnchor( 0, 0 );
959 SdrObjList
* pList
= pNew
->getParentSdrObjListFromSdrObject();
962 SdrObjGroup
* pOwner(dynamic_cast< SdrObjGroup
* >(pList
->getSdrObjectFromSdrObjList()));
964 if(nullptr != pOwner
)
966 aGrpAnchor
= pOwner
->GetAnchorPos();
970 // OD 2004-04-05 #i26791# - direct drawing object
971 // positioning for group members
972 pNew
->NbcSetAnchorPos( aGrpAnchor
);
973 pNew
->SetSnapRect( aSnapRect
);
975 bInsWithFormat
= false;
981 SwFormatAnchor
aAnchor( pCpyFormat
->GetAnchor() );
982 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
983 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
984 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
986 SwPosition
* pPos
= rPaM
.GetPoint();
987 // allow shapes (no controls) in header/footer
988 if( RES_DRAWFRMFMT
== pCpyFormat
->Which() &&
989 GetDoc()->IsInHeaderFooter( pPos
->nNode
) )
991 const SdrObject
*pCpyObj
= pCpyFormat
->FindSdrObject();
992 if (pCpyObj
&& CheckControlLayer(pCpyObj
))
995 else if (pCpyFormat
->Which() == RES_FLYFRMFMT
&& IsInTextBox(pCpyFormat
))
997 // This is a fly frame which is anchored in a TextBox, ignore it as
998 // it's already copied as part of copying the content of the
1003 // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
1004 if (SwTextBoxHelper::isTextBox(pCpyFormat
, RES_FLYFRMFMT
))
1007 aAnchor
.SetAnchor( pPos
);
1009 else if ( RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId() )
1011 aAnchor
.SetPageNum( GetPhyPageNum() );
1013 else if( RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId() )
1016 (void)lcl_SetAnchor( *rPaM
.GetPoint(), rPaM
.GetNode(),
1017 nullptr, aPt
, *this, aAnchor
, aPt
, false );
1020 SwFrameFormat
* pNew
= GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat
, aAnchor
, true, true );
1024 if( RES_FLYFRMFMT
== pNew
->Which() )
1026 const Point
aPt( GetCursorDocPos() );
1027 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrameFormat
*>(pNew
)->
1030 SelectFlyFrame( *pFlyFrame
);
1031 // always pick the first FlyFrame only; the others
1032 // were copied to the clipboard via Fly in Fly
1037 OSL_ENSURE( RES_DRAWFRMFMT
== pNew
->Which(), "New format.");
1038 // #i52780# - drawing object has to be made visible on paste.
1039 pNew
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING
));
1040 SdrObject
*pObj
= pNew
->FindSdrObject();
1041 SwDrawView
*pDV
= Imp()->GetDrawView();
1042 pDV
->MarkObj( pObj
, pDV
->GetSdrPageView() );
1043 // #i47455# - notify draw frame format
1044 // that position attributes are already set.
1045 if (SwDrawFrameFormat
*pDrawFormat
= dynamic_cast<SwDrawFrameFormat
*>(pNew
))
1046 pDrawFormat
->PosAttrSet();
1054 if( bDelTable
&& IsTableMode() )
1056 SwEditShell::Delete();
1060 SwPosition
& rInsPos
= *rPaM
.GetPoint();
1061 const SwStartNode
* pBoxNd
= rInsPos
.nNode
.GetNode().
1062 FindTableBoxStartNode();
1063 if( pBoxNd
&& 2 == pBoxNd
->EndOfSectionIndex() -
1064 pBoxNd
->GetIndex() &&
1065 aCpyPam
.GetPoint()->nNode
!= aCpyPam
.GetMark()->nNode
)
1067 // Copy more than 1 node in the current box. But
1068 // then the BoxAttribute should be removed
1069 GetDoc()->ClearBoxNumAttrs( rInsPos
.nNode
);
1073 // ** Update SwDoc::Append, if you change the following code **
1076 SwNodeIndex
aIndexBefore(rInsPos
.nNode
);
1080 rClpDoc
.getIDocumentContentOperations().CopyRange(aCpyPam
, rInsPos
, SwCopyFlags::CheckPosInFly
);
1081 // Note: aCpyPam is invalid now
1084 SwPaM
aPaM(SwPosition(aIndexBefore
),
1085 SwPosition(rInsPos
.nNode
));
1087 aPaM
.GetDoc().MakeUniqueNumRules(aPaM
);
1089 // Update the rsid of each pasted text node.
1090 SwNodes
&rDestNodes
= GetDoc()->GetNodes();
1091 sal_uLong
const nEndIdx
= aPaM
.End()->nNode
.GetIndex();
1093 for (sal_uLong nIdx
= aPaM
.Start()->nNode
.GetIndex();
1094 nIdx
<= nEndIdx
; ++nIdx
)
1096 SwTextNode
*const pTextNode
= rDestNodes
[nIdx
]->GetTextNode();
1099 GetDoc()->UpdateParRsid( pTextNode
);
1104 SaveTableBoxContent( &rInsPos
);
1109 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSGLOSSARY
, nullptr );
1111 // have new table formulas been inserted?
1112 if( pTableFieldTyp
->HasWriterListeners() )
1114 // finish old action: table-frames have been created
1115 // a selection can be made now
1117 for( nActCnt
= 0; ActionPend(); ++nActCnt
)
1120 for( ; nActCnt
; --nActCnt
)
1123 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1124 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1130 void SwFEShell::PastePages( SwFEShell
& rToFill
, sal_uInt16 nStartPage
, sal_uInt16 nEndPage
)
1133 if(!GotoPage(nStartPage
))
1135 Pop(PopMode::DeleteCurrent
);
1138 MovePage( GetThisFrame
, GetFirstSub
);
1139 SwPaM
aCpyPam( *GetCursor()->GetPoint() );
1140 OUString sStartingPageDesc
= GetPageDesc( GetCurPageDesc()).GetName();
1141 SwPageDesc
* pDesc
= rToFill
.FindPageDescByName( sStartingPageDesc
, true );
1143 rToFill
.ChgCurPageDesc( *pDesc
);
1145 if(!GotoPage(nEndPage
))
1147 Pop(PopMode::DeleteCurrent
);
1150 //if the page starts with a table a paragraph has to be inserted before
1151 SwNode
* pTableNode
= aCpyPam
.GetNode().FindTableNode();
1154 //insert a paragraph
1155 StartUndo(SwUndoId::INSERT
);
1156 SwNodeIndex
aTableIdx( *pTableNode
, -1 );
1157 SwPosition
aBefore(aTableIdx
);
1158 if(GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore
))
1160 SwPaM
aTmp(aBefore
);
1163 EndUndo(SwUndoId::INSERT
);
1166 MovePage( GetThisFrame
, GetLastSub
);
1168 *aCpyPam
.GetMark() = *GetCursor()->GetPoint();
1170 CurrShell
aCurr( this );
1173 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1174 SetSelection(aCpyPam
);
1175 // copy the text of the selection
1176 SwEditShell::Copy(rToFill
);
1180 //remove the inserted paragraph
1182 //remove the paragraph in the second doc, too
1183 SwNodeIndex
aIdx( rToFill
.GetDoc()->GetNodes().GetEndOfExtras(), 2 );
1184 SwPaM
aPara( aIdx
); //DocStart
1185 rToFill
.GetDoc()->getIDocumentContentOperations().DelFullPara(aPara
);
1187 // now the page bound objects
1188 // additionally copy page bound frames
1189 if( !GetDoc()->GetSpzFrameFormats()->empty() )
1191 // create a draw view if necessary
1192 if( !rToFill
.Imp()->GetDrawView() )
1193 rToFill
.MakeDrawView();
1195 for ( auto pCpyFormat
: *GetDoc()->GetSpzFrameFormats() )
1197 SwFormatAnchor
aAnchor( pCpyFormat
->GetAnchor() );
1198 if ((RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId()) &&
1199 aAnchor
.GetPageNum() >= nStartPage
&& aAnchor
.GetPageNum() <= nEndPage
)
1201 aAnchor
.SetPageNum( aAnchor
.GetPageNum() - nStartPage
+ 1);
1205 rToFill
.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat
, aAnchor
, true, true );
1208 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1209 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1210 Pop(PopMode::DeleteCurrent
);
1214 comphelper::OInterfaceContainerHelper2
& SwFEShell::GetPasteListeners() { return m_aPasteListeners
; }
1216 bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat
, Graphic
& rGrf
) const
1218 OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
1219 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1220 bool bConvert
= true;
1221 if( rMrkList
.GetMarkCount() )
1223 if( rMrkList
.GetMarkCount() == 1 &&
1224 dynamic_cast< const SwVirtFlyDrawObj
* >(rMrkList
.GetMark( 0 )->GetMarkedSdrObj()) != nullptr )
1227 if( CNT_GRF
== GetCntType() )
1229 const Graphic
* pGrf( GetGraphic() );
1232 Graphic
aGrf( *pGrf
);
1233 if( SotClipboardFormatId::GDIMETAFILE
== nFormat
)
1235 if( GraphicType::Bitmap
!= aGrf
.GetType() )
1246 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
1247 pVirtDev
->EnableOutput( false );
1249 MapMode
aTmp( GetWin()->GetMapMode() );
1250 aTmp
.SetOrigin( aPt
);
1251 pVirtDev
->SetMapMode( aTmp
);
1254 aMtf
.Record( pVirtDev
.get() );
1255 aGrf
.Draw( pVirtDev
, aPt
, aSz
);
1257 aMtf
.SetPrefMapMode( aTmp
);
1258 aMtf
.SetPrefSize( aSz
);
1262 else if( GraphicType::Bitmap
== aGrf
.GetType() )
1269 // Not the original size, but the current one.
1270 // Otherwise it could happen that for vector graphics
1271 // many MB's of memory are allocated.
1272 const Size
aSz( GetSelectedFlyFrame()->getFramePrintArea().SSize() );
1273 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev(*GetWin());
1275 MapMode
aTmp( MapUnit::MapTwip
);
1276 pVirtDev
->SetMapMode( aTmp
);
1277 if( pVirtDev
->SetOutputSize( aSz
) )
1279 aGrf
.Draw( pVirtDev
.get(), Point(), aSz
);
1280 rGrf
= pVirtDev
->GetBitmapEx( Point(), aSz
);
1291 else if( SotClipboardFormatId::GDIMETAFILE
== nFormat
)
1292 rGrf
= Imp()->GetDrawView()->GetMarkedObjMetaFile();
1293 else if( SotClipboardFormatId::BITMAP
== nFormat
|| SotClipboardFormatId::PNG
== nFormat
)
1294 rGrf
= Imp()->GetDrawView()->GetMarkedObjBitmapEx();
1300 // replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1301 static void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel
& _rModel
)
1303 for ( sal_uInt16 nPgNum
= 0; nPgNum
< _rModel
.GetPageCount(); ++nPgNum
)
1305 // setup object iterator in order to iterate through all objects
1306 // including objects in group objects, but exclusive group objects.
1307 SdrObjListIter
aIter(_rModel
.GetPage(nPgNum
));
1308 while( aIter
.IsMore() )
1310 SdrOle2Obj
* pOle2Obj
= dynamic_cast< SdrOle2Obj
* >( aIter
.Next() );
1313 // found an ole2 shape
1314 SdrObjList
* pObjList
= pOle2Obj
->getParentSdrObjListFromSdrObject();
1318 pOle2Obj
->Connect();
1319 const Graphic
* pGraphic
= pOle2Obj
->GetGraphic();
1321 aGraphic
= *pGraphic
;
1322 pOle2Obj
->Disconnect();
1324 // create new graphic shape with the ole graphic and shape size
1325 SdrGrafObj
* pGraphicObj
= new SdrGrafObj(
1328 pOle2Obj
->GetCurrentBoundRect());
1329 // apply layer of ole2 shape at graphic shape
1330 pGraphicObj
->SetLayer( pOle2Obj
->GetLayer() );
1332 // replace ole2 shape with the new graphic object and delete the ol2 shape
1333 SdrObject
* pRemovedObject
= pObjList
->ReplaceObject( pGraphicObj
, pOle2Obj
->GetOrdNum() );
1334 SdrObject::Free( pRemovedObject
);
1340 void SwFEShell::Paste( SvStream
& rStrm
, SwPasteSdr nAction
, const Point
* pPt
)
1342 CurrShell
aCurr( this );
1346 std::unique_ptr
< FmFormModel
> pModel(
1349 GetDoc()->GetDocShell()));
1351 pModel
->GetItemPool().FreezeIdRanges();
1355 uno::Reference
< io::XInputStream
> xInputStream( new utl::OInputStreamWrapper( rStrm
) );
1356 SvxDrawingLayerImport( pModel
.get(), xInputStream
);
1358 if ( !Imp()->HasDrawView() )
1359 Imp()->MakeDrawView();
1361 Point
aPos( pPt
? *pPt
: GetCharRect().Pos() );
1362 SdrView
*pView
= Imp()->GetDrawView();
1364 // drop on the existing object: replace object or apply new attributes
1365 if( pModel
->GetPageCount() > 0 &&
1366 1 == pModel
->GetPage(0)->GetObjCount() &&
1367 1 == pView
->GetMarkedObjectList().GetMarkCount() )
1369 // replace a marked 'virtual' drawing object
1370 // by its corresponding 'master' drawing object in the mark list.
1371 SwDrawView::ReplaceMarkedDrawVirtObjs( *pView
);
1373 SdrObject
* pClpObj
= pModel
->GetPage(0)->GetObj(0);
1374 SdrObject
* pOldObj
= pView
->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1376 if( SwPasteSdr::SetAttr
== nAction
&& dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1377 nAction
= SwPasteSdr::Replace
;
1381 case SwPasteSdr::Replace
:
1383 const SwFrameFormat
* pFormat(nullptr);
1384 const SwFrame
* pAnchor(nullptr);
1385 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1387 pFormat
= FindFrameFormat( pOldObj
);
1390 SwFlyFrame
* pFlyFrame
= static_cast<const SwFlyFrameFormat
*>(pFormat
)->GetFrame( &aNullPt
);
1391 pAnchor
= pFlyFrame
? pFlyFrame
->GetAnchorFrame() : nullptr;
1393 if (!pAnchor
|| pAnchor
->FindFooterOrHeader())
1395 // if there is a textframe in the header/footer:
1396 // do not replace but insert
1397 nAction
= SwPasteSdr::Insert
;
1402 SdrObject
* pNewObj(pClpObj
->CloneSdrObject(pOldObj
->getSdrModelFromSdrObject()));
1403 tools::Rectangle
aOldObjRect( pOldObj
->GetCurrentBoundRect() );
1404 Size
aOldObjSize( aOldObjRect
.GetSize() );
1405 tools::Rectangle
aNewRect( pNewObj
->GetCurrentBoundRect() );
1406 Size
aNewSize( aNewRect
.GetSize() );
1408 Fraction
aScaleWidth( aOldObjSize
.Width(), aNewSize
.Width() );
1409 Fraction
aScaleHeight( aOldObjSize
.Height(), aNewSize
.Height());
1410 pNewObj
->NbcResize( aNewRect
.TopLeft(), aScaleWidth
, aScaleHeight
);
1412 Point aVec
= aOldObjRect
.TopLeft() - aNewRect
.TopLeft();
1413 pNewObj
->NbcMove(Size(aVec
.getX(), aVec
.getY()));
1415 if( dynamic_cast<const SdrUnoObj
*>( pNewObj
) != nullptr )
1416 pNewObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1417 else if( dynamic_cast<const SdrUnoObj
*>( pOldObj
) != nullptr )
1418 pNewObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1420 pNewObj
->SetLayer( pOldObj
->GetLayer() );
1422 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1424 // store attributes, then set SdrObject
1425 SfxItemSet
aFrameSet( mxDoc
->GetAttrPool(),
1426 svl::Items
<RES_SURROUND
, RES_ANCHOR
>{} );
1427 aFrameSet
.Set( pFormat
->GetAttrSet() );
1430 if( pAnchor
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnchor
)->IsFollow() )
1432 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnchor
);
1434 pTmp
= pTmp
->FindMaster();
1435 OSL_ENSURE( pTmp
, "Where's my Master?" );
1436 } while( pTmp
->IsFollow() );
1439 if( auto pCaptionObj
= dynamic_cast<SdrCaptionObj
*>( pOldObj
))
1440 aNullPt
= pCaptionObj
->GetTailPos();
1442 aNullPt
= aOldObjRect
.TopLeft();
1444 Point aNewAnchor
= pAnchor
->GetFrameAnchorPos( ::HasWrap( pOldObj
) );
1445 // OD 2004-04-05 #i26791# - direct positioning of Writer
1446 // fly frame object for <SwDoc::Insert(..)>
1447 pNewObj
->NbcSetRelativePos( aNullPt
- aNewAnchor
);
1448 pNewObj
->NbcSetAnchorPos( aNewAnchor
);
1450 pOldObj
->GetOrdNum();
1454 GetDoc()->getIDocumentContentOperations().InsertDrawObj( *GetCursor(), *pNewObj
, aFrameSet
);
1458 // #i123922# for handling MasterObject and virtual ones correctly, SW
1459 // wants us to call ReplaceObject at the page, but that also
1460 // triggers the same assertion (I tried it), so stay at the view method
1461 pView
->ReplaceObjectAtView(pOldObj
, *Imp()->GetPageView(), pNewObj
);
1466 case SwPasteSdr::SetAttr
:
1468 SfxItemSet
aSet( GetAttrPool() );
1469 const SdrGrafObj
* pSdrGrafObj
= dynamic_cast< const SdrGrafObj
* >(pClpObj
);
1473 SdrObject
* pTarget
= nullptr;
1475 if(0 != pView
->GetMarkedObjectList().GetMarkCount())
1477 // try to get target (if it's at least one, take first)
1478 SdrMark
* pMark
= pView
->GetMarkedObjectList().GetMark(0);
1482 pTarget
= pMark
->GetMarkedSdrObj();
1488 // copy ItemSet from target
1489 aSet
.Set(pTarget
->GetMergedItemSet());
1492 // for SdrGrafObj, use the graphic as fill style argument
1493 const Graphic
& rGraphic
= pSdrGrafObj
->GetGraphic();
1495 if(GraphicType::NONE
!= rGraphic
.GetType() && GraphicType::Default
!= rGraphic
.GetType())
1497 aSet
.Put(XFillBitmapItem(OUString(), rGraphic
));
1498 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1503 aSet
.Put(pClpObj
->GetMergedItemSet());
1506 pView
->SetAttributes( aSet
);
1511 nAction
= SwPasteSdr::Insert
;
1516 nAction
= SwPasteSdr::Insert
;
1518 if( SwPasteSdr::Insert
== nAction
)
1520 ::sw::DrawUndoGuard
drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());
1522 bool bDesignMode
= pView
->IsDesignMode();
1524 pView
->SetDesignMode();
1527 // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1528 lcl_ConvertSdrOle2ObjsToSdrGrafObjs(*pModel
);
1529 pView
->Paste(*pModel
, aPos
, nullptr, SdrInsertFlags::NONE
);
1531 const size_t nCnt
= pView
->GetMarkedObjectList().GetMarkCount();
1534 const Point
aNull( 0, 0 );
1535 for( size_t i
=0; i
< nCnt
; ++i
)
1537 SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMark(i
)->GetMarkedSdrObj();
1538 pObj
->ImpSetAnchorPos( aNull
);
1541 pView
->SetCurrentObj( OBJ_GRUP
);
1543 pView
->GroupMarked();
1544 SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1545 if( dynamic_cast<const SdrUnoObj
*>( pObj
) != nullptr )
1547 pObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1551 pObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1552 const tools::Rectangle
&rSnap
= pObj
->GetSnapRect();
1553 const Size
aDiff( rSnap
.GetWidth()/2, rSnap
.GetHeight()/2 );
1554 pView
->MoveMarkedObj( aDiff
);
1557 pView
->SetDesignMode( false );
1564 bool SwFEShell::Paste(const Graphic
&rGrf
, const OUString
& rURL
)
1566 CurrShell
aCurr( this );
1567 SdrObject
* pObj
= nullptr;
1568 SdrView
*pView
= Imp()->GetDrawView();
1570 bool bRet
= 1 == pView
->GetMarkedObjectList().GetMarkCount();
1573 pObj
= pView
->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1574 bRet
= pObj
->IsClosedObj() && dynamic_cast<const SdrOle2Obj
*>( pObj
) == nullptr;
1579 // #i123922# added code to handle the two cases of SdrGrafObj and a fillable, non-
1580 // OLE object in focus
1581 SdrObject
* pResult
= pObj
;
1583 if(dynamic_cast< SdrGrafObj
* >(pObj
))
1585 SdrGrafObj
* pNewGrafObj(static_cast<SdrGrafObj
*>(pObj
->CloneSdrObject(pObj
->getSdrModelFromSdrObject())));
1587 pNewGrafObj
->SetGraphic(rGrf
);
1589 // #i123922# for handling MasterObject and virtual ones correctly, SW
1590 // wants us to call ReplaceObject at the page, but that also
1591 // triggers the same assertion (I tried it), so stay at the view method
1592 pView
->ReplaceObjectAtView(pObj
, *pView
->GetSdrPageView(), pNewGrafObj
);
1594 // set in all cases - the Clone() will have copied an existing link (!)
1595 pNewGrafObj
->SetGraphicLink(rURL
);
1597 pResult
= pNewGrafObj
;
1601 pView
->AddUndo(std::make_unique
<SdrUndoAttrObj
>(*pObj
));
1603 SfxItemSet
aSet(pView
->GetModel()->GetItemPool(), svl::Items
<XATTR_FILLSTYLE
, XATTR_FILLBITMAP
>{});
1605 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1606 aSet
.Put(XFillBitmapItem(OUString(), rGrf
));
1607 pObj
->SetMergedItemSetAndBroadcast(aSet
);
1610 // we are done; mark the modified/new object
1611 pView
->MarkObj(pResult
, pView
->GetSdrPageView());
1617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */