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 <svx/xfillit0.hxx>
26 #include <svx/svdocapt.hxx>
27 #include <svx/svdouno.hxx>
28 #include <svx/xbtmpit.hxx>
29 #include <svx/svdpage.hxx>
30 #include <svx/svdogrp.hxx>
31 #include <svx/svdoole2.hxx>
32 #include <svx/fmmodel.hxx>
33 #include <svx/unomodel.hxx>
34 #include <svx/svditer.hxx>
35 #include <svx/svdograf.hxx>
36 #include <tools/stream.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <osl/diagnose.h>
39 #include <fmtanchr.hxx>
40 #include <fmtcntnt.hxx>
41 #include <fmtornt.hxx>
42 #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
.GetNode(),
91 rClpDoc
.GetDfltTextFormatColl() );
95 // also delete surrounding FlyFrames if any
96 for(sw::SpzFrameFormat
* pFly
: *rClpDoc
.GetSpzFrameFormats() )
98 SwFormatAnchor
const*const pAnchor
= &pFly
->GetAnchor();
99 SwNode
const*const pAnchorNode
= pAnchor
->GetAnchorNode();
101 ((RndStdIds::FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
102 (RndStdIds::FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
103 aSttIdx
<= *pAnchorNode
&& *pAnchorNode
<= aEndNdIdx
.GetNode() )
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
, SwContentIndex( 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
.SetContent( 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 sw::SpzFrameFormats
& rSpzFrameFormats
= *rClpDoc
.GetSpzFrameFormats();
148 if( rSpzFrameFormats
[ 0 ] != pFlyFormat
)
153 rSpzFrameFormats
.newDefault(static_cast<sw::SpzFrameFormat
*>(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 TextAttribute should be removed in the node
162 // otherwise it will be recognised as TextSelection
163 const SwPosition
& rPos
= *pFlyFormat
->GetAnchor().GetContentAnchor();
164 SwTextFlyCnt
*const pTextFly
= static_cast<SwTextFlyCnt
*>(
165 pTextNd
->GetTextAttrForCharAt(
166 rPos
.GetContentIndex(), RES_TXTATR_FLYCNT
));
169 const_cast<SwFormatFlyCnt
&>(pTextFly
->GetFlyCnt()).SetFlyFormat();
170 pTextNd
->EraseText( rPos
, 1 );
174 else if ( IsObjSelected() )
176 SwPosition
aPos( aSttIdx
, 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 rtl::Reference
<SdrObject
> xNew
= rClpDoc
.CloneSdrObj( *pObj
);
194 rClpDoc
.getIDocumentContentOperations().InsertDrawObj(aTemp
, *xNew
, aSet
);
198 if (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 );
216 CopySelToDoc(rClpDoc
); // copy the selections
218 rClpDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE
);
219 rClpDoc
.getIDocumentFieldsAccess().UnlockExpFields();
220 if( !rClpDoc
.getIDocumentFieldsAccess().IsExpFieldsLocked() )
221 rClpDoc
.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
224 static const Point
&lcl_FindBasePos( const SwFrame
*pFrame
, const Point
&rPt
)
226 const SwFrame
*pF
= pFrame
;
227 while ( pF
&& !pF
->getFrameArea().Contains( rPt
) )
229 if ( pF
->IsContentFrame() )
230 pF
= static_cast<const SwContentFrame
*>(pF
)->GetFollow();
235 return pF
->getFrameArea().Pos();
237 return pFrame
->getFrameArea().Pos();
240 static bool lcl_SetAnchor( const SwPosition
& rPos
, const SwNode
& rNd
, SwFlyFrame
const * pFly
,
241 const Point
& rInsPt
, SwFEShell
const & rDestShell
, SwFormatAnchor
& rAnchor
,
242 Point
& rNewPos
, bool bCheckFlyRecur
)
245 rAnchor
.SetAnchor( &rPos
);
246 std::pair
<Point
, bool> const tmp(rInsPt
, false);
247 SwContentFrame
*const pTmpFrame
= rNd
.GetContentNode()->getLayoutFrame(
248 rDestShell
.GetLayout(), nullptr, &tmp
);
249 SwFlyFrame
*pTmpFly
= pTmpFrame
->FindFlyFrame();
250 if( pTmpFly
&& bCheckFlyRecur
&& pFly
->IsUpperOf( *pTmpFly
) )
254 else if ( RndStdIds::FLY_AT_FLY
== rAnchor
.GetAnchorId() )
258 const SwNodeIndex
& rIdx
= *pTmpFly
->GetFormat()->GetContent().GetContentIdx();
259 SwPosition
aPos( rIdx
);
260 rAnchor
.SetAnchor( &aPos
);
261 rNewPos
= pTmpFly
->getFrameArea().Pos();
265 rAnchor
.SetType( RndStdIds::FLY_AT_PAGE
);
266 rAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
267 const SwFrame
*pPg
= pTmpFrame
->FindPageFrame();
268 rNewPos
= pPg
->getFrameArea().Pos();
272 rNewPos
= ::lcl_FindBasePos( pTmpFrame
, rInsPt
);
276 bool SwFEShell::CopyDrawSel( SwFEShell
& rDestShell
, const Point
& rSttPt
,
277 const Point
& rInsPt
, bool bIsMove
, bool bSelectInsert
)
281 // The list should be copied, because below new objects will be selected
282 const SdrMarkList
aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() );
283 const size_t nMarkCount
= aMrkList
.GetMarkCount();
284 if( !rDestShell
.Imp()->GetDrawView() )
285 // should create it now
286 rDestShell
.MakeDrawView();
287 else if( bSelectInsert
)
288 rDestShell
.Imp()->GetDrawView()->UnmarkAll();
290 SdrPageView
*pDestPgView
= rDestShell
.Imp()->GetPageView(),
291 *pSrcPgView
= Imp()->GetPageView();
292 SwDrawView
*pDestDrwView
= rDestShell
.Imp()->GetDrawView(),
293 *pSrcDrwView
= Imp()->GetDrawView();
294 SwDoc
* pDestDoc
= rDestShell
.GetDoc();
296 Size
aSiz( rInsPt
.X() - rSttPt
.X(), rInsPt
.Y() - rSttPt
.Y() );
297 for( size_t i
= 0; i
< nMarkCount
; ++i
)
299 SdrObject
*pObj
= aMrkList
.GetMark( i
)->GetMarkedSdrObj();
301 SwDrawContact
*pContact
= static_cast<SwDrawContact
*>(GetUserCall( pObj
));
305 SwFrameFormat
*pFormat
= pContact
->GetFormat();
306 const SwFormatAnchor
& rAnchor
= pFormat
->GetAnchor();
308 bool bInsWithFormat
= true;
310 if( pDestDrwView
->IsGroupEntered() )
312 // insert into the group, when it belongs to an entered group
313 // or when the object is not anchored as a character
314 if( pSrcDrwView
->IsGroupEntered() ||
315 (RndStdIds::FLY_AS_CHAR
!= rAnchor
.GetAnchorId()) )
318 rtl::Reference
<SdrObject
> xNew
= pDestDoc
->CloneSdrObj( *pObj
, bIsMove
&&
319 GetDoc() == pDestDoc
, false );
320 xNew
->NbcMove( aSiz
);
321 pDestDrwView
->InsertObjectAtView( xNew
.get(), *pDestPgView
);
322 bInsWithFormat
= false;
328 SwFormatAnchor
aAnchor( rAnchor
);
331 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
332 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
333 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
334 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
336 if ( this == &rDestShell
)
338 // same shell? Then request the position
339 // from the passed DocumentPosition
340 SwPosition
aPos( *GetCursor()->GetPoint() );
342 aPt
-= rSttPt
- pObj
->GetSnapRect().TopLeft();
343 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
344 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
, &aState
);
346 if( (pNd
= &aPos
.GetNode())->IsNoTextNode() )
349 bRet
= ::lcl_SetAnchor( aPos
, *pNd
, nullptr, rInsPt
,
350 rDestShell
, aAnchor
, aNewAnch
, false );
354 SwPaM
*pCursor
= rDestShell
.GetCursor();
355 if( pCursor
->GetPointNode().IsNoTextNode() )
358 bRet
= ::lcl_SetAnchor( *pCursor
->GetPoint(),
359 pCursor
->GetPointNode(), nullptr, rInsPt
,
364 else if ( RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId() )
366 aAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
367 const SwRootFrame
* pTmpRoot
= rDestShell
.GetLayout();
368 const SwFrame
* pPg
= pTmpRoot
->GetPageAtPos( rInsPt
, nullptr, true );
370 aNewAnch
= pPg
->getFrameArea().Pos();
375 if( pSrcDrwView
->IsGroupEntered() ||
376 ( !pObj
->GetUserCall() && pObj
->getParentSdrObjectFromSdrObject()) )
378 SfxItemSet
aSet( pDestDoc
->GetAttrPool(),aFrameFormatSetRange
);
380 rtl::Reference
<SdrObject
> xNew
= pDestDoc
->CloneSdrObj( *pObj
, bIsMove
&&
381 GetDoc() == pDestDoc
);
382 pFormat
= pDestDoc
->getIDocumentContentOperations().InsertDrawObj( *rDestShell
.GetCursor(), *xNew
, aSet
);
385 pFormat
= pDestDoc
->getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat
, aAnchor
, true, true );
387 // Can be 0, as Draws are not allowed in Headers/Footers
390 // #tdf33692 - drawing object has to be made visible on ctrl+drag copy.
391 pFormat
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING
));
392 SdrObject
* pNew
= pFormat
->FindSdrObject();
393 if ( RndStdIds::FLY_AS_CHAR
!= aAnchor
.GetAnchorId() )
395 Point
aPos( rInsPt
);
397 aPos
-= rSttPt
- pObj
->GetSnapRect().TopLeft();
398 // OD 2004-04-05 #i26791# - change attributes instead of
399 // direct positioning
400 pFormat
->SetFormatAttr( SwFormatHoriOrient( aPos
.getX(), text::HoriOrientation::NONE
, text::RelOrientation::FRAME
) );
401 pFormat
->SetFormatAttr( SwFormatVertOrient( aPos
.getY(), text::VertOrientation::NONE
, text::RelOrientation::FRAME
) );
402 // #i47455# - notify draw frame format
403 // that position attributes are already set.
404 if (SwDrawFrameFormat
*pDrawFormat
= dynamic_cast<SwDrawFrameFormat
*>(pFormat
))
405 pDrawFormat
->PosAttrSet();
407 if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat
, RES_DRAWFRMFMT
, pObj
))
409 SwTextBoxHelper::syncFlyFrameAttr(*pFormat
, pFormat
->GetAttrSet(), pObj
);
413 pDestDrwView
->MarkObj( pNew
, pDestPgView
);
419 if ( bIsMove
&& bRet
)
421 if( &rDestShell
== this )
423 const SdrMarkList
aList( pSrcDrwView
->GetMarkedObjectList() );
424 pSrcDrwView
->UnmarkAll();
426 for ( size_t i
= 0, nMrkCnt
= aMrkList
.GetMarkCount(); i
< nMrkCnt
; ++i
)
428 SdrObject
*pObj
= aMrkList
.GetMark( i
)->GetMarkedSdrObj();
429 pSrcDrwView
->MarkObj( pObj
, pSrcPgView
);
432 for ( size_t i
= 0, nMrkCnt
= aList
.GetMarkCount(); i
< nMrkCnt
; ++i
)
434 SdrObject
*pObj
= aList
.GetMark( i
)->GetMarkedSdrObj();
435 pSrcDrwView
->MarkObj( pObj
, pSrcPgView
);
445 bool SwFEShell::Copy( SwFEShell
& rDestShell
, const Point
& rSttPt
,
446 const Point
& rInsPt
, bool bIsMove
, bool bSelectInsert
)
450 OSL_ENSURE( this == &rDestShell
|| !rDestShell
.IsObjSelected(),
451 "Dest-Shell cannot be in Obj-Mode" );
453 CurrShell
aCurr( &rDestShell
);
455 rDestShell
.StartAllAction();
456 rDestShell
.GetDoc()->getIDocumentFieldsAccess().LockExpFields();
459 bool bCopyIsMove
= mxDoc
->IsCopyIsMove();
461 // set a flag in Doc, handled in TextNodes
462 mxDoc
->SetCopyIsMove( true );
464 RedlineFlags eOldRedlMode
= rDestShell
.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
465 rDestShell
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode
| RedlineFlags::DeleteRedlines
);
467 // If there are table formulas in the area, then display the table first
468 // so that the table formula can calculate a new value first
469 // (individual boxes in the area are retrieved via the layout)
470 SwFieldType
* pTableFieldTyp
= rDestShell
.GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table
);
472 if( IsFrameSelected() )
474 SwFlyFrame
* pFly
= GetSelectedFlyFrame();
475 SwFrameFormat
* pFlyFormat
= pFly
->GetFormat();
476 SwFormatAnchor
aAnchor( pFlyFormat
->GetAnchor() );
480 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
481 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
482 (RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId()) ||
483 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
485 if ( this == &rDestShell
)
487 // same shell? Then request the position
488 // from the passed DocumentPosition
489 SwPosition
aPos( *GetCursor()->GetPoint() );
491 aPt
-= rSttPt
- pFly
->getFrameArea().Pos();
492 SwCursorMoveState
aState( CursorMoveState::SetOnlyText
);
493 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
, &aState
);
495 if( (pNd
= &aPos
.GetNode())->IsNoTextNode() )
499 // do not copy in itself
500 const SwNodeIndex
*pTmp
= pFlyFormat
->GetContent().GetContentIdx();
501 if ( aPos
.GetNodeIndex() > pTmp
->GetIndex() &&
502 aPos
.GetNodeIndex() < pTmp
->GetNode().EndOfSectionIndex() )
507 bRet
= ::lcl_SetAnchor( aPos
, *pNd
, pFly
, rInsPt
,
508 rDestShell
, aAnchor
, aNewAnch
, true );
513 const SwPaM
*pCursor
= rDestShell
.GetCursor();
514 if( pCursor
->GetPointNode().IsNoTextNode() )
517 bRet
= ::lcl_SetAnchor( *pCursor
->GetPoint(), pCursor
->GetPointNode(),
518 pFly
, rInsPt
, rDestShell
, aAnchor
,
519 aNewAnch
, GetDoc() == rDestShell
.GetDoc());
522 else if ( RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId() )
524 aAnchor
.SetPageNum( rDestShell
.GetPageNumber( rInsPt
) );
525 const SwRootFrame
* pTmpRoot
= rDestShell
.GetLayout();
526 const SwFrame
* pPg
= pTmpRoot
->GetPageAtPos( rInsPt
, nullptr, true );
528 aNewAnch
= pPg
->getFrameArea().Pos();
531 OSL_ENSURE( false, "what anchor is it?" );
536 SwFrameFormat
*pOldFormat
= pFlyFormat
;
537 pFlyFormat
= rDestShell
.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat
, aAnchor
, true, true );
539 if ( RndStdIds::FLY_AS_CHAR
!= aAnchor
.GetAnchorId() )
541 Point
aPos( rInsPt
);
543 aPos
-= rSttPt
- pFly
->getFrameArea().Pos();
544 pFlyFormat
->SetFormatAttr( SwFormatHoriOrient( aPos
.getX(),text::HoriOrientation::NONE
, text::RelOrientation::FRAME
) );
545 pFlyFormat
->SetFormatAttr( SwFormatVertOrient( aPos
.getY(),text::VertOrientation::NONE
, text::RelOrientation::FRAME
) );
548 const Point
aPt( rDestShell
.GetCursorDocPos() );
551 GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pOldFormat
);
553 // only select if it can be shifted/copied in the same shell
556 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrameFormat
*>(pFlyFormat
)->GetFrame( &aPt
);
559 //JP 12.05.98: should this be in SelectFlyFrame???
560 rDestShell
.Imp()->GetDrawView()->UnmarkAll();
561 rDestShell
.SelectFlyFrame( *pFlyFrame
);
565 if (this != &rDestShell
&& !rDestShell
.HasShellFocus())
566 rDestShell
.Imp()->GetDrawView()->hideMarkHandles();
569 else if ( IsObjSelected() )
570 bRet
= CopyDrawSel( rDestShell
, rSttPt
, rInsPt
, bIsMove
, bSelectInsert
);
571 else if( IsTableMode() )
573 // Copy parts from a table: create a table with the same
574 // width as the original and copy the selected boxes.
575 // Sizes will be corrected by percentage.
577 // find boxes via the layout
579 GetTableSel( *this, aBoxes
);
580 SwTableNode
const*const pTableNd(
581 aBoxes
.empty() ? nullptr : aBoxes
[0]->GetSttNd()->FindTableNode());
582 if (nullptr != pTableNd
)
584 std::optional
<SwPosition
> oDstPos
;
585 if( this == &rDestShell
)
587 // same shell? Then create new Cursor at the
588 // DocumentPosition passed
589 oDstPos
.emplace( *GetCursor()->GetPoint() );
591 GetLayout()->GetModelPositionForViewPoint( &*oDstPos
, aPt
);
592 if( !oDstPos
->GetNode().IsNoTextNode() )
595 else if( !rDestShell
.GetCursor()->GetPointNode().IsNoTextNode() )
597 oDstPos
.emplace( *rDestShell
.GetCursor()->GetPoint() );
603 if( GetDoc() == rDestShell
.GetDoc() )
606 bRet
= rDestShell
.GetDoc()->InsCopyOfTable( *oDstPos
, aBoxes
,nullptr,
607 bIsMove
&& this == &rDestShell
&&
608 aBoxes
.size() == pTableNd
->GetTable().
609 GetTabSortBoxes().size(),
610 this != &rDestShell
);
612 if( this != &rDestShell
)
613 *rDestShell
.GetCursor()->GetPoint() = *oDstPos
;
615 // create all parked Cursor?
616 if( GetDoc() == rDestShell
.GetDoc() )
619 // JP 16.04.99: Bug 64908 - Set InsPos, to assure the parked
620 // Cursor is positioned at the insert position
621 if( this == &rDestShell
)
622 GetCursorDocPos() = rInsPt
;
629 if( this == &rDestShell
)
631 // same shell? then request the position
632 // at the passed document position
633 SwPosition
aPos( *GetCursor()->GetPoint() );
635 GetLayout()->GetModelPositionForViewPoint( &aPos
, aPt
);
636 bRet
= !aPos
.GetNode().IsNoTextNode();
638 else if( rDestShell
.GetCursor()->GetPointNode().IsNoTextNode() )
642 bRet
= SwEditShell::Copy( rDestShell
);
645 rDestShell
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode
);
646 mxDoc
->SetCopyIsMove( bCopyIsMove
);
648 // have new table formulas been inserted?
649 if( pTableFieldTyp
->HasWriterListeners() )
651 // finish old actions: the table frames are created and
652 // a selection can be made
654 for( nActCnt
= 0; rDestShell
.ActionPend(); ++nActCnt
)
655 rDestShell
.EndAllAction();
657 for( ; nActCnt
; --nActCnt
)
658 rDestShell
.StartAllAction();
660 rDestShell
.GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
661 rDestShell
.GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
663 rDestShell
.EndAllAction();
667 // Paste for the internal clipboard. Copy the content of the clipboard
670 typedef std::shared_ptr
<SwPaM
> PaMPtr
;
671 typedef std::shared_ptr
<SwPosition
> PositionPtr
;
672 typedef std::pair
< PaMPtr
, PositionPtr
> Insertion
;
674 bool PamHasSelection(const SwPaM
& rPaM
)
676 return rPaM
.HasMark() && *rPaM
.GetPoint() != *rPaM
.GetMark();
679 /// Is pFormat anchored in a fly frame which has an associated draw format?
680 bool IsInTextBox(const SwFrameFormat
* pFormat
)
682 const SwFormatAnchor
& rAnchor
= pFormat
->GetAnchor();
683 const SwNode
* pAnchorNode
= rAnchor
.GetAnchorNode();
689 const SwStartNode
* pFlyNode
= pAnchorNode
->FindFlyStartNode();
695 for(const sw::SpzFrameFormat
* pSpzFormat
: *pFormat
->GetDoc()->GetSpzFrameFormats())
697 if (pSpzFormat
->Which() != RES_FLYFRMFMT
)
702 const SwNodeIndex
* pIdx
= pSpzFormat
->GetContent().GetContentIdx();
703 if (!pIdx
|| pFlyNode
!= &pIdx
->GetNode())
708 return SwTextBoxHelper::isTextBox(pSpzFormat
, RES_FLYFRMFMT
);
716 SwFrameFormat
* lcl_PasteFlyOrDrawFormat(SwPaM
& rPaM
, SwFrameFormat
* pCpyFormat
, SwFEShell
& rSh
)
718 auto& rImp
= *rSh
.Imp();
719 auto& rDoc
= *rSh
.GetDoc();
720 auto& rDrawView
= *rImp
.GetDrawView();
721 if(rDrawView
.IsGroupEntered() &&
722 RES_DRAWFRMFMT
== pCpyFormat
->Which() &&
723 (RndStdIds::FLY_AS_CHAR
!= pCpyFormat
->GetAnchor().GetAnchorId()))
725 const SdrObject
* pSdrObj
= pCpyFormat
->FindSdrObject();
728 rtl::Reference
<SdrObject
> xNew
= rDoc
.CloneSdrObj(*pSdrObj
, false, false);
729 // Insert object sets any anchor position to 0.
730 // Therefore we calculate the absolute position here
731 // and after the insert the anchor of the object
732 // is set to the anchor of the group object.
733 tools::Rectangle aSnapRect
= xNew
->GetSnapRect();
734 if(xNew
->GetAnchorPos().X() || xNew
->GetAnchorPos().Y())
736 const Point
aPoint(0, 0);
737 // OD 2004-04-05 #i26791# - direct drawing object
738 // positioning for group members
739 xNew
->NbcSetAnchorPos(aPoint
);
740 xNew
->NbcSetSnapRect(aSnapRect
);
743 rDrawView
.InsertObjectAtView(xNew
.get(), *rImp
.GetPageView());
745 Point
aGrpAnchor(0, 0);
746 SdrObjList
* pList
= xNew
->getParentSdrObjListFromSdrObject();
749 SdrObjGroup
* pOwner(dynamic_cast<SdrObjGroup
*>(pList
->getSdrObjectFromSdrObjList()));
751 if(nullptr != pOwner
)
752 aGrpAnchor
= pOwner
->GetAnchorPos();
755 // OD 2004-04-05 #i26791# - direct drawing object
756 // positioning for group members
757 xNew
->NbcSetAnchorPos(aGrpAnchor
);
758 xNew
->SetSnapRect(aSnapRect
);
762 SwFormatAnchor
aAnchor(pCpyFormat
->GetAnchor());
763 if ((RndStdIds::FLY_AT_PARA
== aAnchor
.GetAnchorId()) ||
764 (RndStdIds::FLY_AT_CHAR
== aAnchor
.GetAnchorId()) ||
765 (RndStdIds::FLY_AS_CHAR
== aAnchor
.GetAnchorId()))
767 SwPosition
* pPos
= rPaM
.GetPoint();
768 // allow shapes (no controls) in header/footer
769 if(RES_DRAWFRMFMT
== pCpyFormat
->Which() && rDoc
.IsInHeaderFooter(pPos
->GetNode()))
771 const SdrObject
*pCpyObj
= pCpyFormat
->FindSdrObject();
772 if(pCpyObj
&& CheckControlLayer(pCpyObj
))
775 else if(pCpyFormat
->Which() == RES_FLYFRMFMT
&& IsInTextBox(pCpyFormat
))
777 // This is a fly frame which is anchored in a TextBox, ignore it as
778 // it's already copied as part of copying the content of the
782 // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
783 if(SwTextBoxHelper::isTextBox(pCpyFormat
, RES_FLYFRMFMT
))
785 aAnchor
.SetAnchor(pPos
);
787 else if(RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId())
789 aAnchor
.SetPageNum(rSh
.GetPhyPageNum());
791 else if(RndStdIds::FLY_AT_FLY
== aAnchor
.GetAnchorId())
794 (void)lcl_SetAnchor(*rPaM
.GetPoint(), rPaM
.GetPointNode(), nullptr, aPt
, rSh
, aAnchor
, aPt
, false);
797 SwFrameFormat
* pNew
= rDoc
.getIDocumentLayoutAccess().CopyLayoutFormat(*pCpyFormat
, aAnchor
, true, true);
801 void lcl_SelectFlyFormat(SwFrameFormat
*const pNew
, SwFEShell
& rSh
)
805 switch(pNew
->Which())
809 assert(dynamic_cast<SwFlyFrameFormat
*>(pNew
));
810 const Point
aPt(rSh
.GetCursorDocPos());
811 SwFlyFrame
* pFlyFrame
= static_cast<SwFlyFrameFormat
*>(pNew
)->GetFrame(&aPt
);
813 rSh
.SelectFlyFrame(*pFlyFrame
);
818 auto& rDrawView
= *rSh
.Imp()->GetDrawView();
819 assert(dynamic_cast<SwDrawFrameFormat
*>(pNew
));
820 SwDrawFrameFormat
* pDrawFormat
= static_cast<SwDrawFrameFormat
*>(pNew
);
821 // #i52780# - drawing object has to be made visible on paste.
822 pDrawFormat
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING
));
823 SdrObject
* pObj
= pDrawFormat
->FindSdrObject();
824 rDrawView
.MarkObj(pObj
, rDrawView
.GetSdrPageView());
825 // #i47455# - notify draw frame format
826 // that position attributes are already set.
827 pDrawFormat
->PosAttrSet();
831 SAL_WARN("sw.core", "unknown fly type");
836 bool SwFEShell::Paste(SwDoc
& rClpDoc
, bool bNestedTable
)
838 CurrShell
aCurr( this );
839 // then till end of the nodes array
840 SwNodeIndex
aIdx( rClpDoc
.GetNodes().GetEndOfExtras(), 2 );
841 // select content section, whatever it may contain
842 SwPaM
aCpyPam(aIdx
, SwNodeIndex(rClpDoc
.GetNodes().GetEndOfContent(), -1));
843 if (SwContentNode
*const pAtEnd
= aCpyPam
.GetPointNode().GetContentNode())
845 aCpyPam
.GetPoint()->AssignEndIndex(*pAtEnd
);
848 // If there are table formulas in the area, then display the table first
849 // so that the table formula can calculate a new value first
850 // (individual boxes in the area are retrieved via the layout)
851 SwFieldType
* pTableFieldTyp
= GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table
);
853 SwTableNode
*const pSrcNd
= aCpyPam
.GetMarkNode().GetTableNode();
857 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSGLOSSARY
, nullptr );
858 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
860 // When the clipboard content has been created by a rectangular selection
861 // the pasting is more sophisticated:
862 // every paragraph will be inserted into another position.
863 // The first positions are given by the actual cursor ring,
864 // if there are more text portions to insert than cursor in this ring,
865 // the additional insert positions will be created by moving the last
866 // cursor position into the next line (like pressing the cursor down key)
867 if( rClpDoc
.IsColumnSelection() && !IsTableMode() )
869 // Creation of the list of insert positions
870 std::vector
< Insertion
> aCopyVector
;
871 // The number of text portions of the rectangular selection
872 const SwNodeOffset nSelCount
= aCpyPam
.GetPoint()->GetNodeIndex()
873 - aCpyPam
.GetMark()->GetNodeIndex();
874 SwNodeOffset nCount
= nSelCount
;
875 SwNodeIndex
aClpIdx( aIdx
);
876 SwPaM
* pStartCursor
= GetCursor();
877 SwPaM
* pCurrCursor
= pStartCursor
;
878 SwNodeOffset
nCursorCount( pStartCursor
->GetRingContainer().size() );
879 // If the target selection is a multi-selection, often the last and first
880 // cursor of the ring points to identical document positions. Then
881 // we should avoid double insertion of text portions...
882 while( nCursorCount
> SwNodeOffset(1) && *pCurrCursor
->GetPoint() ==
883 *(pCurrCursor
->GetPrev()->GetPoint()) )
886 pCurrCursor
= pCurrCursor
->GetNext();
887 pStartCursor
= pCurrCursor
;
889 SwPosition
aStartPos( *pStartCursor
->GetPoint() );
890 SwPosition
aInsertPos( aStartPos
); // first insertion position
891 bool bCompletePara
= false;
892 sal_uInt16 nMove
= 0;
896 OSL_ENSURE( aIdx
.GetNode().GetContentNode(), "Who filled the clipboard?!" );
897 if( aIdx
.GetNode().GetContentNode() ) // robust
899 Insertion
aInsertion( std::make_shared
<SwPaM
>( aIdx
),
900 std::make_shared
<SwPosition
>( aInsertPos
) );
902 aInsertion
.first
->SetMark();
903 if( pStartCursor
== pCurrCursor
->GetNext() )
904 { // Now we have to look for insertion positions...
905 if( !nMove
) // Annotate the last given insert position
906 aStartPos
= aInsertPos
;
907 SwCursor
aCursor( aStartPos
, nullptr);
908 // Check if we find another insert position by moving
909 // down the last given position
910 if (aCursor
.UpDown(false, ++nMove
, nullptr, 0, *GetLayout()))
911 aInsertPos
= *aCursor
.GetPoint();
912 else // if there is no paragraph we have to create it
913 bCompletePara
= nCount
> SwNodeOffset(0);
914 nCursorCount
= SwNodeOffset(0);
916 else // as long as we find more insert positions in the cursor ring
918 pCurrCursor
= pCurrCursor
->GetNext();
919 aInsertPos
= *pCurrCursor
->GetPoint();
922 // If there are no more paragraphs e.g. at the end of a document,
923 // we insert complete paragraphs instead of text portions
925 aInsertion
.first
->GetPoint()->Assign(aIdx
);
927 aInsertion
.first
->GetPoint()->SetContent(
928 aInsertion
.first
->GetPointContentNode()->Len() );
929 aCopyVector
.push_back( aInsertion
);
931 // If there are no text portions left but there are some more
932 // cursor positions to fill we have to restart with the first
934 if( !nCount
&& nCursorCount
)
936 nCount
= min( nSelCount
, nCursorCount
);
937 aIdx
= aClpIdx
; // Start of clipboard content
940 for (auto const& item
: aCopyVector
)
942 SwPosition
& rInsPos
= *item
.second
;
943 SwPaM
& rCopy
= *item
.first
;
944 const SwStartNode
* pBoxNd
= rInsPos
.GetNode().FindTableBoxStartNode();
945 if( pBoxNd
&& SwNodeOffset(2) == pBoxNd
->EndOfSectionIndex() - pBoxNd
->GetIndex() &&
946 rCopy
.GetPoint()->GetNode() != rCopy
.GetMark()->GetNode() )
948 // if more than one node will be copied into a cell
949 // the box attributes have to be removed
950 GetDoc()->ClearBoxNumAttrs( rInsPos
.GetNode() );
953 SwNodeIndex
aIndexBefore(rInsPos
.GetNode());
955 rClpDoc
.getIDocumentContentOperations().CopyRange(rCopy
, rInsPos
, SwCopyFlags::CheckPosInFly
);
958 SwPaM
aPaM(SwPosition(aIndexBefore
),
959 SwPosition(rInsPos
.GetNode()));
960 aPaM
.GetDoc().MakeUniqueNumRules(aPaM
);
963 SaveTableBoxContent( &rInsPos
);
968 bool bDelTable
= true;
970 for(SwPaM
& rPaM
: GetCursor()->GetRingContainer())
973 SwTableNode
*const pDestNd(SwDoc::IsInTable(rPaM
.GetPoint()->GetNode()));
974 if (pSrcNd
&& nullptr != pDestNd
&&
975 // not a forced nested table insertion
977 // Heuristics to allow copying table rows or nesting tables without
978 // using Edit -> Paste Special -> Paste as Nested Table:
979 // Using table cursor, or if the text selection starts in the
980 // first paragraph, or if there is no selection and the text cursor
981 // is there in the first paragraph, overwrite content of the cell(s)
982 // (else insert a nested table later, i.e. if nothing selected and
983 // the cursor is not in the first paragraph, or the selected text
984 // doesn't contain the first paragraph of the cell)
985 rPaM
.GetPointNode().GetIndex() == rPaM
.GetPointNode().FindTableBoxStartNode()->GetIndex() + 1)
987 SwPosition
aDestPos( *rPaM
.GetPoint() );
989 bool bParkTableCursor
= false;
990 const SwStartNode
* pSttNd
= rPaM
.GetPointNode().FindTableBoxStartNode();
992 // TABLE IN TABLE: copy table in table
993 // search boxes via the layout
995 if( IsTableMode() ) // table selection?
997 GetTableSel( *this, aBoxes
);
999 bParkTableCursor
= true;
1001 else if( !PamHasSelection(rPaM
) && rPaM
.GetNext() == &rPaM
&&
1002 ( !pSrcNd
->GetTable().IsTableComplex() ||
1003 pDestNd
->GetTable().IsNewModel() ) )
1005 // make relative table copy
1006 SwTableBox
* pBox
= pDestNd
->GetTable().GetTableBox(
1007 pSttNd
->GetIndex() );
1008 OSL_ENSURE( pBox
, "Box is not in this table" );
1009 aBoxes
.insert( pBox
);
1012 SwNodeIndex
aNdIdx( *pDestNd
->EndOfSectionNode());
1013 if( !bParkTableCursor
)
1015 // exit first the complete table
1016 // ???? what about only table in a frame ?????
1017 SwContentNode
* pCNd
= SwNodes::GoNext(&aNdIdx
);
1018 SwPosition
aPos( aNdIdx
, pCNd
, 0 );
1019 // #i59539: Don't remove all redline
1020 SwPaM
const tmpPaM(*pDestNd
, *pDestNd
->EndOfSectionNode());
1021 ::PaMCorrAbs(tmpPaM
, aPos
);
1024 bRet
= GetDoc()->InsCopyOfTable( aDestPos
, aBoxes
, &pSrcNd
->GetTable() );
1026 if( bParkTableCursor
)
1030 // return to the box
1032 SwContentNode
* pCNd
= SwNodes::GoNext(&aNdIdx
);
1033 SwPosition
aPos( aNdIdx
, pCNd
, 0 );
1034 // #i59539: Don't remove all redline
1035 SwNode
& rNode(rPaM
.GetPoint()->GetNode());
1036 SwContentNode
*const pContentNode( rNode
.GetContentNode() );
1037 SwPaM
const tmpPam(rNode
, 0,
1038 rNode
, pContentNode
? pContentNode
->Len() : 0);
1039 ::PaMCorrAbs(tmpPam
, aPos
);
1042 break; // exit the "while-loop"
1044 else if(*aCpyPam
.GetPoint() == *aCpyPam
.GetMark() && !rClpDoc
.GetSpzFrameFormats()->empty())
1046 // we need a DrawView
1047 if(!Imp()->GetDrawView())
1049 ::std::vector
<SwFrameFormat
*> inserted
;
1050 for (sw::SpzFrameFormat
* pFlyFormat
: *rClpDoc
.GetSpzFrameFormats())
1052 // if anchored inside other fly, will be copied when copying
1053 // top-level fly, so skip here! (other non-body anchor
1054 // shouldn't happen here)
1055 SwFormatAnchor
const& rAnchor(pFlyFormat
->GetAnchor());
1056 if (RndStdIds::FLY_AT_PAGE
== rAnchor
.GetAnchorId()
1057 || rClpDoc
.GetNodes().GetEndOfExtras().GetIndex() < rAnchor
.GetAnchorNode()->GetIndex())
1059 inserted
.emplace_back(
1060 lcl_PasteFlyOrDrawFormat(rPaM
, pFlyFormat
, *this));
1063 for (auto const pFlyFormat
: inserted
)
1065 lcl_SelectFlyFormat(pFlyFormat
, *this);
1070 if( bDelTable
&& IsTableMode() )
1072 SwEditShell::Delete(false);
1076 SwPosition
& rInsPos
= *rPaM
.GetPoint();
1077 const SwStartNode
* pBoxNd
= rInsPos
.GetNode().
1078 FindTableBoxStartNode();
1079 if( pBoxNd
&& SwNodeOffset(2) == pBoxNd
->EndOfSectionIndex() -
1080 pBoxNd
->GetIndex() &&
1081 aCpyPam
.GetPoint()->GetNode() != aCpyPam
.GetMark()->GetNode() )
1083 // Copy more than 1 node in the current box. But
1084 // then the BoxAttribute should be removed
1085 GetDoc()->ClearBoxNumAttrs( rInsPos
.GetNode() );
1089 // ** Update SwDoc::Append, if you change the following code **
1092 SwNodeIndex
aIndexBefore(rInsPos
.GetNode());
1096 // copying to the clipboard, the section is inserted
1097 // at the start of the nodes, followed by empty text node
1098 bool const isSourceSection(aCpyPam
.Start()->GetNode().IsSectionNode()
1099 && aCpyPam
.End()->GetNodeIndex() == aCpyPam
.Start()->GetNode().EndOfSectionIndex() + 1
1100 && aCpyPam
.End()->GetNode().IsTextNode()
1101 && aCpyPam
.End()->GetNode().GetTextNode()->Len() == 0);
1103 rClpDoc
.getIDocumentContentOperations().CopyRange(aCpyPam
, rInsPos
, SwCopyFlags::CheckPosInFly
);
1104 // Note: aCpyPam is invalid now
1107 && aIndexBefore
.GetNode().IsStartNode()
1108 && rInsPos
.GetNode().GetTextNode()->Len() == 0)
1109 { // if there is an empty text node at the start, it
1110 // should be *replaced* by the section, so delete it
1111 GetDoc()->getIDocumentContentOperations().DelFullPara(rPaM
);
1115 SwPaM
aPaM(aIndexBefore
.GetNode(), rInsPos
.GetNode());
1117 aPaM
.GetDoc().MakeUniqueNumRules(aPaM
);
1119 // Update the rsid of each pasted text node.
1120 SwNodes
&rDestNodes
= GetDoc()->GetNodes();
1121 SwNodeOffset
const nEndIdx
= aPaM
.End()->GetNodeIndex();
1123 for (SwNodeOffset nIdx
= aPaM
.Start()->GetNodeIndex();
1124 nIdx
<= nEndIdx
; ++nIdx
)
1126 SwTextNode
*const pTextNode
= rDestNodes
[nIdx
]->GetTextNode();
1129 GetDoc()->UpdateParRsid( pTextNode
);
1134 SaveTableBoxContent( &rInsPos
);
1139 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSGLOSSARY
, nullptr );
1141 // have new table formulas been inserted?
1142 if( pTableFieldTyp
->HasWriterListeners() )
1144 // finish old action: table-frames have been created
1145 // a selection can be made now
1147 for( nActCnt
= 0; ActionPend(); ++nActCnt
)
1150 for( ; nActCnt
; --nActCnt
)
1153 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1154 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1160 void SwFEShell::PastePages( SwFEShell
& rToFill
, sal_uInt16 nStartPage
, sal_uInt16 nEndPage
)
1163 if(!GotoPage(nStartPage
))
1165 Pop(PopMode::DeleteCurrent
);
1168 MovePage( GetThisFrame
, GetFirstSub
);
1169 ::std::optional
<SwPaM
> oSourcePam( *GetCursor()->GetPoint() );
1170 OUString sStartingPageDesc
= GetPageDesc( GetCurPageDesc()).GetName();
1171 SwPageDesc
* pDesc
= rToFill
.FindPageDescByName( sStartingPageDesc
, true );
1173 rToFill
.ChgCurPageDesc( *pDesc
);
1175 if(!GotoPage(nEndPage
))
1177 Pop(PopMode::DeleteCurrent
);
1180 //if the page starts with a table a paragraph has to be inserted before
1181 SwNode
*const pTableNode
= oSourcePam
->GetPointNode().FindTableNode();
1184 //insert a paragraph
1185 StartUndo(SwUndoId::INSERT
);
1186 SwNodeIndex
aTableIdx( *pTableNode
, -1 );
1187 SwPosition
aBefore(aTableIdx
);
1188 if(GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore
))
1190 SwPaM
aTmp(aBefore
);
1193 EndUndo(SwUndoId::INSERT
);
1196 MovePage( GetThisFrame
, GetLastSub
);
1197 oSourcePam
->SetMark();
1198 *oSourcePam
->GetMark() = *GetCursor()->GetPoint();
1200 CurrShell
aCurr( this );
1203 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1204 SetSelection(*oSourcePam
);
1205 // copy the text of the selection
1206 SwEditShell::Copy(rToFill
);
1207 oSourcePam
.reset(); // delete it because Undo will remove its node!
1211 //remove the inserted paragraph
1213 //remove the paragraph in the second doc, too
1214 SwPaM
aPara( rToFill
.GetDoc()->GetNodes().GetEndOfExtras(), SwNodeOffset(2) ); //DocStart
1215 rToFill
.GetDoc()->getIDocumentContentOperations().DelFullPara(aPara
);
1217 // now the page bound objects
1218 // additionally copy page bound frames
1219 if( !GetDoc()->GetSpzFrameFormats()->empty() )
1221 // create a draw view if necessary
1222 if( !rToFill
.Imp()->GetDrawView() )
1223 rToFill
.MakeDrawView();
1225 for(sw::SpzFrameFormat
* pCpyFormat
: *GetDoc()->GetSpzFrameFormats())
1227 SwFormatAnchor
aAnchor( pCpyFormat
->GetAnchor() );
1228 if ((RndStdIds::FLY_AT_PAGE
== aAnchor
.GetAnchorId()) &&
1229 aAnchor
.GetPageNum() >= nStartPage
&& aAnchor
.GetPageNum() <= nEndPage
)
1231 aAnchor
.SetPageNum( aAnchor
.GetPageNum() - nStartPage
+ 1);
1235 rToFill
.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat
, aAnchor
, true, true );
1238 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1239 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1240 Pop(PopMode::DeleteCurrent
);
1244 comphelper::OInterfaceContainerHelper3
<css::text::XPasteListener
>& SwFEShell::GetPasteListeners() { return m_aPasteListeners
; }
1246 bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat
, Graphic
& rGrf
) const
1248 OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
1249 const SdrMarkList
&rMrkList
= Imp()->GetDrawView()->GetMarkedObjectList();
1250 bool bConvert
= true;
1251 if( rMrkList
.GetMarkCount() )
1253 if( rMrkList
.GetMarkCount() == 1 &&
1254 dynamic_cast< const SwVirtFlyDrawObj
* >(rMrkList
.GetMark( 0 )->GetMarkedSdrObj()) != nullptr )
1257 if( CNT_GRF
== GetCntType() )
1259 const Graphic
* pGrf( GetGraphic() );
1262 Graphic
aGrf( *pGrf
);
1263 if( SotClipboardFormatId::GDIMETAFILE
== nFormat
)
1265 if( GraphicType::Bitmap
!= aGrf
.GetType() )
1267 rGrf
= std::move(aGrf
);
1276 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
1277 pVirtDev
->EnableOutput( false );
1279 MapMode
aTmp( GetWin()->GetMapMode() );
1280 aTmp
.SetOrigin( aPt
);
1281 pVirtDev
->SetMapMode( aTmp
);
1284 aMtf
.Record( pVirtDev
.get() );
1285 aGrf
.Draw(*pVirtDev
, aPt
, aSz
);
1287 aMtf
.SetPrefMapMode( aTmp
);
1288 aMtf
.SetPrefSize( aSz
);
1292 else if( GraphicType::Bitmap
== aGrf
.GetType() )
1294 rGrf
= std::move(aGrf
);
1299 // Not the original size, but the current one.
1300 // Otherwise it could happen that for vector graphics
1301 // many MB's of memory are allocated.
1302 const Size
aSz( GetSelectedFlyFrame()->getFramePrintArea().SSize() );
1303 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev(*GetWin()->GetOutDev());
1305 MapMode
aTmp( MapUnit::MapTwip
);
1306 pVirtDev
->SetMapMode( aTmp
);
1307 if( pVirtDev
->SetOutputSize( aSz
) )
1309 aGrf
.Draw(*pVirtDev
, Point(), aSz
);
1310 rGrf
= pVirtDev
->GetBitmapEx( Point(), aSz
);
1314 rGrf
= std::move(aGrf
);
1321 else if( SotClipboardFormatId::GDIMETAFILE
== nFormat
)
1322 rGrf
= Imp()->GetDrawView()->GetMarkedObjMetaFile();
1323 else if( SotClipboardFormatId::BITMAP
== nFormat
|| SotClipboardFormatId::PNG
== nFormat
)
1324 rGrf
= Imp()->GetDrawView()->GetMarkedObjBitmapEx();
1330 // replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1331 static void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel
& _rModel
)
1333 for ( sal_uInt16 nPgNum
= 0; nPgNum
< _rModel
.GetPageCount(); ++nPgNum
)
1335 // setup object iterator in order to iterate through all objects
1336 // including objects in group objects, but exclusive group objects.
1337 SdrObjListIter
aIter(_rModel
.GetPage(nPgNum
));
1338 while( aIter
.IsMore() )
1340 SdrOle2Obj
* pOle2Obj
= dynamic_cast< SdrOle2Obj
* >( aIter
.Next() );
1343 // found an ole2 shape
1344 SdrObjList
* pObjList
= pOle2Obj
->getParentSdrObjListFromSdrObject();
1348 pOle2Obj
->Connect();
1349 const Graphic
* pGraphic
= pOle2Obj
->GetGraphic();
1351 aGraphic
= *pGraphic
;
1352 pOle2Obj
->Disconnect();
1354 // create new graphic shape with the ole graphic and shape size
1355 rtl::Reference
<SdrGrafObj
> pGraphicObj
= new SdrGrafObj(
1358 pOle2Obj
->GetCurrentBoundRect());
1359 // apply layer of ole2 shape at graphic shape
1360 pGraphicObj
->SetLayer( pOle2Obj
->GetLayer() );
1362 // replace ole2 shape with the new graphic object and delete the ol2 shape
1363 pObjList
->ReplaceObject( pGraphicObj
.get(), pOle2Obj
->GetOrdNum() );
1369 void SwFEShell::Paste( SvStream
& rStrm
, SwPasteSdr nAction
, const Point
* pPt
)
1371 CurrShell
aCurr( this );
1375 std::unique_ptr
< FmFormModel
> pModel(
1378 GetDoc()->GetDocShell()));
1382 uno::Reference
< io::XInputStream
> xInputStream( new utl::OInputStreamWrapper( rStrm
) );
1383 SvxDrawingLayerImport( pModel
.get(), xInputStream
);
1385 if ( !Imp()->HasDrawView() )
1386 Imp()->MakeDrawView();
1388 Point
aPos( pPt
? *pPt
: GetCharRect().Pos() );
1389 SdrView
*pView
= Imp()->GetDrawView();
1391 // drop on the existing object: replace object or apply new attributes
1392 if( pModel
->GetPageCount() > 0 &&
1393 1 == pModel
->GetPage(0)->GetObjCount() &&
1394 1 == pView
->GetMarkedObjectList().GetMarkCount() )
1396 // replace a marked 'virtual' drawing object
1397 // by its corresponding 'master' drawing object in the mark list.
1398 SwDrawView::ReplaceMarkedDrawVirtObjs( *pView
);
1400 SdrObject
* pClpObj
= pModel
->GetPage(0)->GetObj(0);
1401 SdrObject
* pOldObj
= pView
->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1404 if( SwPasteSdr::SetAttr
== nAction
&& dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1405 nAction
= SwPasteSdr::Replace
;
1409 case SwPasteSdr::Replace
:
1411 const SwFrameFormat
* pFormat(nullptr);
1412 const SwFrame
* pAnchor(nullptr);
1413 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1415 pFormat
= FindFrameFormat( pOldObj
);
1418 SwFlyFrame
* pFlyFrame
= static_cast<const SwFlyFrameFormat
*>(pFormat
)->GetFrame( &aNullPt
);
1419 pAnchor
= pFlyFrame
? pFlyFrame
->GetAnchorFrame() : nullptr;
1421 if (!pAnchor
|| pAnchor
->FindFooterOrHeader())
1423 // if there is a textframe in the header/footer:
1424 // do not replace but insert
1425 nAction
= SwPasteSdr::Insert
;
1430 rtl::Reference
<SdrObject
> pNewObj(pClpObj
->CloneSdrObject(pOldObj
->getSdrModelFromSdrObject()));
1431 tools::Rectangle
aOldObjRect( pOldObj
->GetCurrentBoundRect() );
1432 Size
aOldObjSize( aOldObjRect
.GetSize() );
1433 tools::Rectangle
aNewRect( pNewObj
->GetCurrentBoundRect() );
1434 Size
aNewSize( aNewRect
.GetSize() );
1436 Fraction
aScaleWidth( aOldObjSize
.Width(), aNewSize
.Width() );
1437 Fraction
aScaleHeight( aOldObjSize
.Height(), aNewSize
.Height());
1438 pNewObj
->NbcResize( aNewRect
.TopLeft(), aScaleWidth
, aScaleHeight
);
1440 Point aVec
= aOldObjRect
.TopLeft() - aNewRect
.TopLeft();
1441 pNewObj
->NbcMove(Size(aVec
.getX(), aVec
.getY()));
1443 if( dynamic_cast<const SdrUnoObj
*>( pNewObj
.get()) != nullptr )
1444 pNewObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1445 else if( dynamic_cast<const SdrUnoObj
*>( pOldObj
) != nullptr )
1446 pNewObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1448 pNewObj
->SetLayer( pOldObj
->GetLayer() );
1450 if( dynamic_cast<const SwVirtFlyDrawObj
*>( pOldObj
) != nullptr )
1452 // store attributes, then set SdrObject
1453 SfxItemSetFixed
<RES_SURROUND
, RES_ANCHOR
> aFrameSet( mxDoc
->GetAttrPool() );
1454 aFrameSet
.Set( pFormat
->GetAttrSet() );
1457 if( pAnchor
->IsTextFrame() && static_cast<const SwTextFrame
*>(pAnchor
)->IsFollow() )
1459 const SwTextFrame
* pTmp
= static_cast<const SwTextFrame
*>(pAnchor
);
1461 pTmp
= pTmp
->FindMaster();
1462 assert(pTmp
&& "Where's my Master?");
1463 } while( pTmp
->IsFollow() );
1466 if( auto pCaptionObj
= dynamic_cast<SdrCaptionObj
*>( pOldObj
))
1467 aNullPt
= pCaptionObj
->GetTailPos();
1469 aNullPt
= aOldObjRect
.TopLeft();
1471 Point aNewAnchor
= pAnchor
->GetFrameAnchorPos( ::HasWrap( pOldObj
) );
1472 // OD 2004-04-05 #i26791# - direct positioning of Writer
1473 // fly frame object for <SwDoc::Insert(..)>
1474 pNewObj
->NbcSetRelativePos( aNullPt
- aNewAnchor
);
1475 pNewObj
->NbcSetAnchorPos( aNewAnchor
);
1477 pOldObj
->GetOrdNum();
1481 GetDoc()->getIDocumentContentOperations().InsertDrawObj( *GetCursor(), *pNewObj
, aFrameSet
);
1485 // #i123922# for handling MasterObject and virtual ones correctly, SW
1486 // wants us to call ReplaceObject at the page, but that also
1487 // triggers the same assertion (I tried it), so stay at the view method
1488 pView
->ReplaceObjectAtView(pOldObj
, *Imp()->GetPageView(), pNewObj
.get());
1493 case SwPasteSdr::SetAttr
:
1495 SfxItemSet
aSet( GetAttrPool() );
1496 const SdrGrafObj
* pSdrGrafObj
= dynamic_cast< const SdrGrafObj
* >(pClpObj
);
1500 SdrObject
* pTarget
= nullptr;
1502 if(0 != pView
->GetMarkedObjectList().GetMarkCount())
1504 // try to get target (if it's at least one, take first)
1505 SdrMark
* pMark
= pView
->GetMarkedObjectList().GetMark(0);
1509 pTarget
= pMark
->GetMarkedSdrObj();
1515 // copy ItemSet from target
1516 aSet
.Set(pTarget
->GetMergedItemSet());
1519 // for SdrGrafObj, use the graphic as fill style argument
1520 const Graphic
& rGraphic
= pSdrGrafObj
->GetGraphic();
1522 if(GraphicType::NONE
!= rGraphic
.GetType() && GraphicType::Default
!= rGraphic
.GetType())
1524 aSet
.Put(XFillBitmapItem(OUString(), rGraphic
));
1525 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1530 aSet
.Put(pClpObj
->GetMergedItemSet());
1533 pView
->SetAttributes( aSet
);
1538 nAction
= SwPasteSdr::Insert
;
1543 nAction
= SwPasteSdr::Insert
;
1545 if( SwPasteSdr::Insert
== nAction
)
1547 ::sw::DrawUndoGuard
drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());
1549 bool bDesignMode
= pView
->IsDesignMode();
1551 pView
->SetDesignMode();
1554 // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1555 lcl_ConvertSdrOle2ObjsToSdrGrafObjs(*pModel
);
1556 pView
->Paste(*pModel
, aPos
, nullptr, SdrInsertFlags::NONE
);
1558 const size_t nCnt
= pView
->GetMarkedObjectList().GetMarkCount();
1561 const Point
aNull( 0, 0 );
1562 for( size_t i
=0; i
< nCnt
; ++i
)
1564 SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMark(i
)->GetMarkedSdrObj();
1565 pObj
->ImpSetAnchorPos( aNull
);
1568 pView
->SetCurrentObj( SdrObjKind::Group
);
1570 pView
->GroupMarked();
1571 SdrObject
*pObj
= pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1573 if( dynamic_cast<const SdrUnoObj
*>( pObj
) != nullptr )
1575 pObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1579 pObj
->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1580 const tools::Rectangle
&rSnap
= pObj
->GetSnapRect();
1581 const Size
aDiff( rSnap
.GetWidth()/2, rSnap
.GetHeight()/2 );
1582 pView
->MoveMarkedObj( aDiff
);
1585 pView
->SetDesignMode( false );
1592 bool SwFEShell::Paste(const Graphic
&rGrf
, const OUString
& rURL
)
1594 CurrShell
aCurr( this );
1595 SdrObject
* pObj
= nullptr;
1596 SdrView
*pView
= Imp()->GetDrawView();
1598 bool bRet
= 1 == pView
->GetMarkedObjectList().GetMarkCount();
1601 pObj
= pView
->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1602 bRet
= pObj
->IsClosedObj() && dynamic_cast<const SdrOle2Obj
*>( pObj
) == nullptr;
1607 // #i123922# added code to handle the two cases of SdrGrafObj and a fillable, non-
1608 // OLE object in focus
1609 SdrObject
* pResult
= pObj
;
1611 if(auto pGrafObj
= dynamic_cast< SdrGrafObj
* >(pObj
))
1613 rtl::Reference
<SdrGrafObj
> pNewGrafObj
= SdrObject::Clone(*pGrafObj
, pGrafObj
->getSdrModelFromSdrObject());
1615 pNewGrafObj
->SetGraphic(rGrf
);
1617 // #i123922# for handling MasterObject and virtual ones correctly, SW
1618 // wants us to call ReplaceObject at the page, but that also
1619 // triggers the same assertion (I tried it), so stay at the view method
1620 pView
->ReplaceObjectAtView(pObj
, *pView
->GetSdrPageView(), pNewGrafObj
.get());
1622 // set in all cases - the Clone() will have copied an existing link (!)
1623 pNewGrafObj
->SetGraphicLink(rURL
);
1625 pResult
= pNewGrafObj
.get();
1629 pView
->AddUndo(std::make_unique
<SdrUndoAttrObj
>(*pObj
));
1631 SfxItemSetFixed
<XATTR_FILLSTYLE
, XATTR_FILLBITMAP
> aSet(pView
->GetModel().GetItemPool());
1633 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
1634 aSet
.Put(XFillBitmapItem(OUString(), rGrf
));
1635 pObj
->SetMergedItemSetAndBroadcast(aSet
);
1638 // we are done; mark the modified/new object
1639 pView
->MarkObj(pResult
, pView
->GetSdrPageView());
1645 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */