nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / frmedt / fecopy.cxx
blob51d21db7e6784a159b6cba1da706f7f1653cda86
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <memory>
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>
42 #include <frmfmt.hxx>
43 #include <docary.hxx>
44 #include <txtfrm.hxx>
45 #include <txtflcnt.hxx>
46 #include <fesh.hxx>
47 #include <doc.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>
54 #include <ndtxt.hxx>
55 #include <pam.hxx>
56 #include <tblsel.hxx>
57 #include <swtable.hxx>
58 #include <flyfrm.hxx>
59 #include <pagefrm.hxx>
60 #include <fldbas.hxx>
61 #include <swundo.hxx>
62 #include <viewimp.hxx>
63 #include <dview.hxx>
64 #include <dcontact.hxx>
65 #include <dflyobj.hxx>
66 #include <docsh.hxx>
67 #include <pagedesc.hxx>
68 #include <mvsave.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() );
92 --aSttIdx;
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();
100 if (pAPos &&
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
113 // clipboard
114 if( pNewClpText )
116 pTextNd->InsertText( *pNewClpText, SwIndex( pTextNd ) );
117 return; // that's it
120 rClpDoc.getIDocumentFieldsAccess().LockExpFields();
121 rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
123 // do we want to copy a FlyFrame?
124 if( IsFrameSelected() )
126 // get the FlyFormat
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 )
150 #ifndef NDEBUG
151 bool inserted =
152 #endif
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));
167 if( pTextFly )
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 );
189 aSet.Put( aAnchor );
191 SdrObject *const pNew =
192 rClpDoc.CloneSdrObj( *pObj );
194 SwPaM aTemp(aPos);
195 rClpDoc.getIDocumentContentOperations().InsertDrawObj(aTemp, *pNew, aSet );
197 else
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 );
214 else
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();
230 else
231 pF = nullptr;
233 if ( pF )
234 return pF->getFrameArea().Pos();
235 else
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 )
243 bool bRet = true;
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 ) )
251 bRet = false;
253 else if ( RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId() )
255 if( pTmpFly )
257 const SwNodeIndex& rIdx = *pTmpFly->GetFormat()->GetContent().GetContentIdx();
258 SwPosition aPos( rIdx );
259 rAnchor.SetAnchor( &aPos );
260 rNewPos = pTmpFly->getFrameArea().Pos();
262 else
264 rAnchor.SetType( RndStdIds::FLY_AT_PAGE );
265 rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
266 const SwFrame *pPg = pTmpFrame->FindPageFrame();
267 rNewPos = pPg->getFrameArea().Pos();
270 else
271 rNewPos = ::lcl_FindBasePos( pTmpFrame, rInsPt );
272 return bRet;
275 bool SwFEShell::CopyDrawSel( SwFEShell& rDestShell, const Point& rSttPt,
276 const Point& rInsPt, bool bIsMove, bool bSelectInsert )
278 bool bRet = true;
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;
322 if( bInsWithFormat )
324 SwFormatAnchor aAnchor( rAnchor );
325 Point aNewAnch;
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() );
337 Point aPt( rInsPt );
338 aPt -= rSttPt - pObj->GetSnapRect().TopLeft();
339 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
340 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aState );
341 const SwNode *pNd;
342 if( (pNd = &aPos.nNode.GetNode())->IsNoTextNode() )
343 bRet = false;
344 else
345 bRet = ::lcl_SetAnchor( aPos, *pNd, nullptr, rInsPt,
346 rDestShell, aAnchor, aNewAnch, false );
348 else
350 SwPaM *pCursor = rDestShell.GetCursor();
351 if( pCursor->GetNode().IsNoTextNode() )
352 bRet = false;
353 else
354 bRet = ::lcl_SetAnchor( *pCursor->GetPoint(),
355 pCursor->GetNode(), nullptr, rInsPt,
356 rDestShell, aAnchor,
357 aNewAnch, false );
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 );
365 if ( pPg )
366 aNewAnch = pPg->getFrameArea().Pos();
369 if( bRet )
371 if( pSrcDrwView->IsGroupEntered() ||
372 ( !pObj->GetUserCall() && pObj->getParentSdrObjectFromSdrObject()) )
374 SfxItemSet aSet( pDestDoc->GetAttrPool(),aFrameFormatSetRange);
375 aSet.Put( aAnchor );
376 SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
377 GetDoc() == pDestDoc );
378 pFormat = pDestDoc->getIDocumentContentOperations().InsertDrawObj( *rDestShell.GetCursor(), *pNew, aSet );
380 else
381 pFormat = pDestDoc->getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, true, true );
383 // Can be 0, as Draws are not allowed in Headers/Footers
384 if ( pFormat )
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 );
392 aPos -= aNewAnch;
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());
408 if( bSelectInsert )
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 );
427 DelSelectedObj();
428 for ( size_t i = 0, nMrkCnt = aList.GetMarkCount(); i < nMrkCnt; ++i )
430 SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj();
431 pSrcDrwView->MarkObj( pObj, pSrcPgView );
434 else
435 DelSelectedObj();
438 return bRet;
441 bool SwFEShell::Copy( SwFEShell& rDestShell, const Point& rSttPt,
442 const Point& rInsPt, bool bIsMove, bool bSelectInsert )
444 bool bRet = false;
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();
454 // Shift references
455 bool bCopyIsMove = mxDoc->IsCopyIsMove();
456 if( bIsMove )
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() );
473 bRet = true;
474 Point aNewAnch;
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() );
486 Point aPt( rInsPt );
487 aPt -= rSttPt - pFly->getFrameArea().Pos();
488 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
489 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aState );
490 const SwNode *pNd;
491 if( (pNd = &aPos.nNode.GetNode())->IsNoTextNode() )
492 bRet = false;
493 else
495 // do not copy in itself
496 const SwNodeIndex *pTmp = pFlyFormat->GetContent().GetContentIdx();
497 if ( aPos.nNode > *pTmp && aPos.nNode <
498 pTmp->GetNode().EndOfSectionIndex() )
500 bRet = false;
502 else
503 bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt,
504 rDestShell, aAnchor, aNewAnch, true );
507 else
509 const SwPaM *pCursor = rDestShell.GetCursor();
510 if( pCursor->GetNode().IsNoTextNode() )
511 bRet = false;
512 else
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 );
523 if ( pPg )
524 aNewAnch = pPg->getFrameArea().Pos();
526 else {
527 OSL_ENSURE( false, "what anchor is it?" );
530 if( bRet )
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 );
538 aPos -= aNewAnch;
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() );
546 if( bIsMove )
547 GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pOldFormat );
549 // only select if it can be shifted/copied in the same shell
550 if( bSelectInsert )
552 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pFlyFormat)->GetFrame( &aPt );
553 if( pFlyFrame )
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
574 SwSelBoxes aBoxes;
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() ));
586 Point aPt( rInsPt );
587 GetLayout()->GetModelPositionForViewPoint( pDstPos.get(), aPt );
588 if( !pDstPos->nNode.GetNode().IsNoTextNode() )
589 bRet = true;
591 else if( !rDestShell.GetCursor()->GetNode().IsNoTextNode() )
593 pDstPos.reset(new SwPosition( *rDestShell.GetCursor()->GetPoint() ));
594 bRet = true;
597 if( bRet )
599 if( GetDoc() == rDestShell.GetDoc() )
600 ParkTableCursor();
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() )
613 GetCursor();
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;
622 else
624 bRet = true;
625 if( this == &rDestShell )
627 // same shell? then request the position
628 // at the passed document position
629 SwPosition aPos( *GetCursor()->GetPoint() );
630 Point aPt( rInsPt );
631 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
632 bRet = !aPos.nNode.GetNode().IsNoTextNode();
634 else if( rDestShell.GetCursor()->GetNode().IsNoTextNode() )
635 bRet = false;
637 if( bRet )
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
649 sal_uInt16 nActCnt;
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();
660 return bRet;
663 // Paste for the internal clipboard. Copy the content of the clipboard
664 // in the document
665 namespace {
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();
680 if (!pPosition)
682 return false;
685 const SwStartNode* pFlyNode = pPosition->nNode.GetNode().FindFlyStartNode();
686 if (!pFlyNode)
688 return false;
691 for ( const auto& pSpzFormat : *pFormat->GetDoc()->GetSpzFrameFormats() )
693 if (pSpzFormat->Which() != RES_FLYFRMFMT)
695 continue;
698 const SwNodeIndex* pIdx = pSpzFormat->GetContent().GetContentIdx();
699 if (!pIdx || pFlyNode != &pIdx->GetNode())
701 continue;
704 return SwTextBoxHelper::isTextBox(pSpzFormat, RES_FLYFRMFMT);
707 return false;
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 ?
725 { // don't skip !!
726 SwContentNode* pCNd = aCpyPam.GetNode().GetContentNode();
727 if( pCNd )
728 aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 );
729 else if( !aCpyPam.Move( fnMoveForward, GoInNode ))
730 aCpyPam.Move( fnMoveBackward, GoInNode );
733 aCpyPam.SetMark();
734 aCpyPam.Move( fnMoveForward, GoInDoc );
736 bool bRet = true;
737 StartAllAction();
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()) )
766 --nCursorCount;
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;
774 while( nCount )
776 --nCount;
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 ) );
782 ++aIdx;
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;
795 nCursorCount = 0;
797 else // as long as we find more insert positions in the cursor ring
798 { // we'll take them
799 pCurrCursor = pCurrCursor->GetNext();
800 aInsertPos = *pCurrCursor->GetPoint();
801 --nCursorCount;
803 // If there are no more paragraphs e.g. at the end of a document,
804 // we insert complete paragraphs instead of text portions
805 if( bCompletePara )
806 aInsertion.first->GetPoint()->nNode = aIdx;
807 else
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
814 // text portion
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);
835 --aIndexBefore;
836 rClpDoc.getIDocumentContentOperations().CopyRange(rCopy, rInsPos, SwCopyFlags::CheckPosInFly);
838 ++aIndexBefore;
839 SwPaM aPaM(SwPosition(aIndexBefore),
840 SwPosition(rInsPos.nNode));
841 aPaM.GetDoc().MakeUniqueNumRules(aPaM);
844 SaveTableBoxContent( &rInsPos );
847 else
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
857 !bNestedTable &&
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
871 SwSelBoxes aBoxes;
872 if( IsTableMode() ) // table selection?
874 GetTableSel( *this, aBoxes );
875 ParkTableCursor();
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 )
904 GetCursor();
905 else
907 // return to the box
908 aNdIdx = *pSttNd;
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() )
926 MakeDrawView();
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();
937 if( pSdrObj )
939 SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj,
940 false, false );
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();
960 if ( pList )
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;
979 if( bInsWithFormat )
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))
993 continue;
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
999 // TextBox.
1000 continue;
1003 // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
1004 if (SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT))
1005 continue;
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() )
1015 Point aPt;
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 );
1022 if( pNew )
1024 if( RES_FLYFRMFMT == pNew->Which() )
1026 const Point aPt( GetCursorDocPos() );
1027 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pNew)->
1028 GetFrame( &aPt );
1029 if( pFlyFrame )
1030 SelectFlyFrame( *pFlyFrame );
1031 // always pick the first FlyFrame only; the others
1032 // were copied to the clipboard via Fly in Fly
1033 break;
1035 else
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();
1052 else
1054 if( bDelTable && IsTableMode() )
1056 SwEditShell::Delete();
1057 bDelTable = false;
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 );
1072 // **
1073 // ** Update SwDoc::Append, if you change the following code **
1074 // **
1076 SwNodeIndex aIndexBefore(rInsPos.nNode);
1078 --aIndexBefore;
1080 rClpDoc.getIDocumentContentOperations().CopyRange(aCpyPam, rInsPos, SwCopyFlags::CheckPosInFly);
1081 // Note: aCpyPam is invalid now
1083 ++aIndexBefore;
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();
1097 if ( pTextNode )
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
1116 sal_uInt16 nActCnt;
1117 for( nActCnt = 0; ActionPend(); ++nActCnt )
1118 EndAllAction();
1120 for( ; nActCnt; --nActCnt )
1121 StartAllAction();
1123 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1124 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1125 EndAllAction();
1127 return bRet;
1130 void SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage)
1132 Push();
1133 if(!GotoPage(nStartPage))
1135 Pop(PopMode::DeleteCurrent);
1136 return;
1138 MovePage( GetThisFrame, GetFirstSub );
1139 SwPaM aCpyPam( *GetCursor()->GetPoint() );
1140 OUString sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName();
1141 SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, true );
1142 if( pDesc )
1143 rToFill.ChgCurPageDesc( *pDesc );
1145 if(!GotoPage(nEndPage))
1147 Pop(PopMode::DeleteCurrent);
1148 return;
1150 //if the page starts with a table a paragraph has to be inserted before
1151 SwNode* pTableNode = aCpyPam.GetNode().FindTableNode();
1152 if(pTableNode)
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);
1161 aCpyPam = aTmp;
1163 EndUndo(SwUndoId::INSERT);
1166 MovePage( GetThisFrame, GetLastSub );
1167 aCpyPam.SetMark();
1168 *aCpyPam.GetMark() = *GetCursor()->GetPoint();
1170 CurrShell aCurr( this );
1172 StartAllAction();
1173 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1174 SetSelection(aCpyPam);
1175 // copy the text of the selection
1176 SwEditShell::Copy(rToFill);
1178 if(pTableNode)
1180 //remove the inserted paragraph
1181 Undo();
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);
1203 else
1204 continue;
1205 rToFill.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchor, true, true );
1208 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1209 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1210 Pop(PopMode::DeleteCurrent);
1211 EndAllAction();
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 )
1226 // select frame
1227 if( CNT_GRF == GetCntType() )
1229 const Graphic* pGrf( GetGraphic() );
1230 if ( pGrf )
1232 Graphic aGrf( *pGrf );
1233 if( SotClipboardFormatId::GDIMETAFILE == nFormat )
1235 if( GraphicType::Bitmap != aGrf.GetType() )
1237 rGrf = aGrf;
1238 bConvert = false;
1240 else if( GetWin() )
1242 Size aSz;
1243 Point aPt;
1244 GetGrfSize( aSz );
1246 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1247 pVirtDev->EnableOutput( false );
1249 MapMode aTmp( GetWin()->GetMapMode() );
1250 aTmp.SetOrigin( aPt );
1251 pVirtDev->SetMapMode( aTmp );
1253 GDIMetaFile aMtf;
1254 aMtf.Record( pVirtDev.get() );
1255 aGrf.Draw( pVirtDev, aPt, aSz );
1256 aMtf.Stop();
1257 aMtf.SetPrefMapMode( aTmp );
1258 aMtf.SetPrefSize( aSz );
1259 rGrf = aMtf;
1262 else if( GraphicType::Bitmap == aGrf.GetType() )
1264 rGrf = aGrf;
1265 bConvert = false;
1267 else
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 );
1282 else
1284 rGrf = aGrf;
1285 bConvert = false;
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();
1296 return bConvert;
1299 // #i50824#
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() );
1311 if( pOle2Obj )
1313 // found an ole2 shape
1314 SdrObjList* pObjList = pOle2Obj->getParentSdrObjListFromSdrObject();
1316 // get its graphic
1317 Graphic aGraphic;
1318 pOle2Obj->Connect();
1319 const Graphic* pGraphic = pOle2Obj->GetGraphic();
1320 if( pGraphic )
1321 aGraphic = *pGraphic;
1322 pOle2Obj->Disconnect();
1324 // create new graphic shape with the ole graphic and shape size
1325 SdrGrafObj* pGraphicObj = new SdrGrafObj(
1326 _rModel,
1327 aGraphic,
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 );
1343 StartAllAction();
1344 StartUndo();
1346 std::unique_ptr< FmFormModel > pModel(
1347 new FmFormModel(
1348 nullptr,
1349 GetDoc()->GetDocShell()));
1351 pModel->GetItemPool().FreezeIdRanges();
1353 rStrm.Seek(0);
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;
1379 switch( nAction )
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 );
1389 Point aNullPt;
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;
1398 break;
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() );
1419 else
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() );
1429 Point aNullPt;
1430 if( pAnchor->IsTextFrame() && static_cast<const SwTextFrame*>(pAnchor)->IsFollow() )
1432 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnchor);
1433 do {
1434 pTmp = pTmp->FindMaster();
1435 OSL_ENSURE( pTmp, "Where's my Master?" );
1436 } while( pTmp->IsFollow() );
1437 pAnchor = pTmp;
1439 if( auto pCaptionObj = dynamic_cast<SdrCaptionObj*>( pOldObj))
1440 aNullPt = pCaptionObj->GetTailPos();
1441 else
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();
1452 DelSelectedObj();
1454 GetDoc()->getIDocumentContentOperations().InsertDrawObj( *GetCursor(), *pNewObj, aFrameSet );
1456 else
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);
1464 break;
1466 case SwPasteSdr::SetAttr:
1468 SfxItemSet aSet( GetAttrPool() );
1469 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pClpObj);
1471 if(pSdrGrafObj)
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);
1480 if(pMark)
1482 pTarget = pMark->GetMarkedSdrObj();
1486 if(pTarget)
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));
1501 else
1503 aSet.Put(pClpObj->GetMergedItemSet());
1506 pView->SetAttributes( aSet );
1508 break;
1510 default:
1511 nAction = SwPasteSdr::Insert;
1512 break;
1515 else
1516 nAction = SwPasteSdr::Insert;
1518 if( SwPasteSdr::Insert == nAction )
1520 ::sw::DrawUndoGuard drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());
1522 bool bDesignMode = pView->IsDesignMode();
1523 if( !bDesignMode )
1524 pView->SetDesignMode();
1526 // #i50824#
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();
1532 if( nCnt )
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 );
1542 if ( nCnt > 1 )
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() );
1548 bDesignMode = true;
1550 else
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 );
1555 ImpEndCreate();
1556 if( !bDesignMode )
1557 pView->SetDesignMode( false );
1560 EndUndo();
1561 EndAllAction();
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();
1571 if (bRet)
1573 pObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1574 bRet = pObj->IsClosedObj() && dynamic_cast<const SdrOle2Obj*>( pObj) == nullptr;
1577 if( bRet && pObj )
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;
1599 else
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());
1614 return bRet;
1617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */