Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fecopy.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx

/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <hintids.hxx>
22
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>
73
74using namespace ::com::sun::star;
75
76// Copy for the internal clipboard. Copies all selections to the clipboard.
77void SwFEShell::Copy( SwDoc& rClpDoc, const OUString* pNewClpText )
78{
79 rClpDoc.GetIDocumentUndoRedo().DoUndo(false); // always false!
80
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() )
87 {
88 rClpDoc.GetNodes().Delete( aSttIdx,
89 rClpDoc.GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
90 pTextNd = rClpDoc.GetNodes().MakeTextNode( aSttIdx,
91 rClpDoc.GetDfltTextFormatColl() );
92 --aSttIdx;
93 }
94
95 // also delete surrounding FlyFrames if any
96 for( const auto pFly : *rClpDoc.GetSpzFrameFormats() )
97 {
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 )
104 {
105 rClpDoc.getIDocumentLayoutAccess().DelLayoutFormat( pFly );
106 }
107 }
108
109 rClpDoc.GetDocumentFieldsManager().GCFieldTypes(); // delete the FieldTypes
110
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 )
115 {
116 pTextNd->InsertText( *pNewClpText, SwIndex( pTextNd ) );
117 return; // that's it
118 }
119
120 rClpDoc.getIDocumentFieldsAccess().LockExpFields();
121 rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
122
123 // do we want to copy a FlyFrame?
124 if( IsFrameSelected() )
125 {
126 // get the FlyFormat
127 SwFlyFrame* pFly = GetSelectedFlyFrame();
128 SwFrameFormat* pFlyFormat = pFly->GetFormat();
129 SwFormatAnchor aAnchor( pFlyFormat->GetAnchor() );
130
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()))
135 {
136 SwPosition aPos( aSttIdx );
137 if ( RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId() )
138 {
139 aPos.nContent.Assign( pTextNd, 0 );
140 }
141 aAnchor.SetAnchor( &aPos );
142 }
143 pFlyFormat = rClpDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat, aAnchor, true, true );
144
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 )
149 {
150#ifndef NDEBUG
151 bool inserted =
152#endif
153 rSpzFrameFormats.newDefault( pFlyFormat );
154 assert( !inserted && "Fly not contained in Spz-Array" )(static_cast <bool> (!inserted && "Fly not contained in Spz-Array"
) ? void (0) : __assert_fail ("!inserted && \"Fly not contained in Spz-Array\""
, "/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
, 154, __extension__ __PRETTY_FUNCTION__))
;
155 }
156
157 if ( RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId() )
158 {
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 )
168 {
169 const_cast<SwFormatFlyCnt&>(pTextFly->GetFlyCnt()).SetFlyFormat();
170 pTextNd->EraseText( rIdx, 1 );
171 }
172 }
173 }
174 else if ( IsObjSelected() )
175 {
176 SwPosition aPos( aSttIdx, SwIndex( pTextNd, 0 ));
177 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
178 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
179 {
180 SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
181
182 if( Imp()->GetDrawView()->IsGroupEntered() ||
183 ( !pObj->GetUserCall() && pObj->getParentSdrObjectFromSdrObject()) )
184 {
185 SfxItemSet aSet( rClpDoc.GetAttrPool(), aFrameFormatSetRange );
186
187 SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA );
188 aAnchor.SetAnchor( &aPos );
189 aSet.Put( aAnchor );
190
191 SdrObject *const pNew =
192 rClpDoc.CloneSdrObj( *pObj );
193
194 SwPaM aTemp(aPos);
195 rClpDoc.getIDocumentContentOperations().InsertDrawObj(aTemp, *pNew, aSet );
196 }
197 else
198 {
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()))
206 {
207 aAnchor.SetAnchor( &aPos );
208 }
209
210 rClpDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, true, true );
211 }
212 }
213 }
214 else
215 CopySelToDoc(rClpDoc); // copy the selections
216
217 rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
218 rClpDoc.getIDocumentFieldsAccess().UnlockExpFields();
219 if( !rClpDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
220 rClpDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
221}
222
223static const Point &lcl_FindBasePos( const SwFrame *pFrame, const Point &rPt )
224{
225 const SwFrame *pF = pFrame;
226 while ( pF && !pF->getFrameArea().IsInside( rPt ) )
227 {
228 if ( pF->IsContentFrame() )
229 pF = static_cast<const SwContentFrame*>(pF)->GetFollow();
230 else
231 pF = nullptr;
232 }
233 if ( pF )
234 return pF->getFrameArea().Pos();
235 else
236 return pFrame->getFrameArea().Pos();
237}
238
239static 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 )
242{
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 ) )
250 {
251 bRet = false;
252 }
253 else if ( RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId() )
254 {
255 if( pTmpFly )
256 {
257 const SwNodeIndex& rIdx = *pTmpFly->GetFormat()->GetContent().GetContentIdx();
258 SwPosition aPos( rIdx );
259 rAnchor.SetAnchor( &aPos );
260 rNewPos = pTmpFly->getFrameArea().Pos();
261 }
262 else
263 {
264 rAnchor.SetType( RndStdIds::FLY_AT_PAGE );
265 rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
266 const SwFrame *pPg = pTmpFrame->FindPageFrame();
267 rNewPos = pPg->getFrameArea().Pos();
268 }
269 }
270 else
271 rNewPos = ::lcl_FindBasePos( pTmpFrame, rInsPt );
272 return bRet;
273}
274
275bool SwFEShell::CopyDrawSel( SwFEShell& rDestShell, const Point& rSttPt,
276 const Point& rInsPt, bool bIsMove, bool bSelectInsert )
277{
278 bool bRet = true;
279
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();
288
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();
294
295 Size aSiz( rInsPt.X() - rSttPt.X(), rInsPt.Y() - rSttPt.Y() );
296 for( size_t i = 0; i < nMarkCount; ++i )
297 {
298 SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
299
300 SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
301 SwFrameFormat *pFormat = pContact->GetFormat();
302 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
303
304 bool bInsWithFormat = true;
305
306 if( pDestDrwView->IsGroupEntered() )
307 {
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()) )
312
313 {
314 SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
315 GetDoc() == pDestDoc, false );
316 pNew->NbcMove( aSiz );
317 pDestDrwView->InsertObjectAtView( pNew, *pDestPgView );
318 bInsWithFormat = false;
319 }
320 }
321
322 if( bInsWithFormat )
323 {
324 SwFormatAnchor aAnchor( rAnchor );
325 Point aNewAnch;
326
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()))
331 {
332 if ( this == &rDestShell )
333 {
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 );
347 }
348 else
349 {
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 );
358 }
359 }
360 else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
361 {
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();
367 }
368
369 if( bRet )
370 {
371 if( pSrcDrwView->IsGroupEntered() ||
372 ( !pObj->GetUserCall() && pObj->getParentSdrObjectFromSdrObject()) )
373 {
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 );
379 }
380 else
381 pFormat = pDestDoc->getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, true, true );
382
383 // Can be 0, as Draws are not allowed in Headers/Footers
384 if ( pFormat )
385 {
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() )
390 {
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 ( dynamic_cast<const SwDrawFrameFormat*>( pFormat) != nullptr )
401 {
402 static_cast<SwDrawFrameFormat*>(pFormat)->PosAttrSet();
403 }
404 }
405 if( bSelectInsert )
406 pDestDrwView->MarkObj( pNew, pDestPgView );
407 }
408 }
409 }
410 }
411
412 if ( bIsMove && bRet )
413 {
414 if( &rDestShell == this )
415 {
416 const SdrMarkList aList( pSrcDrwView->GetMarkedObjectList() );
417 pSrcDrwView->UnmarkAll();
418
419 for ( size_t i = 0, nMrkCnt = aMrkList.GetMarkCount(); i < nMrkCnt; ++i )
420 {
421 SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
422 pSrcDrwView->MarkObj( pObj, pSrcPgView );
423 }
424 DelSelectedObj();
425 for ( size_t i = 0, nMrkCnt = aList.GetMarkCount(); i < nMrkCnt; ++i )
426 {
427 SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj();
428 pSrcDrwView->MarkObj( pObj, pSrcPgView );
429 }
430 }
431 else
432 DelSelectedObj();
433 }
434
435 return bRet;
436}
437
438bool SwFEShell::Copy( SwFEShell& rDestShell, const Point& rSttPt,
439 const Point& rInsPt, bool bIsMove, bool bSelectInsert )
440{
441 bool bRet = false;
442
443 OSL_ENSURE( this == &rDestShell || !rDestShell.IsObjSelected(),do { if (true && (!(this == &rDestShell || !rDestShell
.IsObjSelected()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "444" ": "), "%s", "Dest-Shell cannot be in Obj-Mode"); }
} while (false)
444 "Dest-Shell cannot be in Obj-Mode" )do { if (true && (!(this == &rDestShell || !rDestShell
.IsObjSelected()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "444" ": "), "%s", "Dest-Shell cannot be in Obj-Mode"); }
} while (false)
;
445
446 CurrShell aCurr( &rDestShell );
447
448 rDestShell.StartAllAction();
449 rDestShell.GetDoc()->getIDocumentFieldsAccess().LockExpFields();
450
451 // Shift references
452 bool bCopyIsMove = mxDoc->IsCopyIsMove();
453 if( bIsMove )
454 // set a flag in Doc, handled in TextNodes
455 mxDoc->SetCopyIsMove( true );
456
457 RedlineFlags eOldRedlMode = rDestShell.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
458 rDestShell.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode | RedlineFlags::DeleteRedlines );
459
460 // If there are table formulas in the area, then display the table first
461 // so that the table formula can calculate a new value first
462 // (individual boxes in the area are retrieved via the layout)
463 SwFieldType* pTableFieldTyp = rDestShell.GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table );
464
465 if( IsFrameSelected() )
466 {
467 SwFlyFrame* pFly = GetSelectedFlyFrame();
468 SwFrameFormat* pFlyFormat = pFly->GetFormat();
469 SwFormatAnchor aAnchor( pFlyFormat->GetAnchor() );
470 bRet = true;
471 Point aNewAnch;
472
473 if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
474 (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
475 (RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId()) ||
476 (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
477 {
478 if ( this == &rDestShell )
479 {
480 // same shell? Then request the position
481 // from the passed DocumentPosition
482 SwPosition aPos( *GetCursor()->GetPoint() );
483 Point aPt( rInsPt );
484 aPt -= rSttPt - pFly->getFrameArea().Pos();
485 SwCursorMoveState aState( CursorMoveState::SetOnlyText );
486 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aState );
487 const SwNode *pNd;
488 if( (pNd = &aPos.nNode.GetNode())->IsNoTextNode() )
489 bRet = false;
490 else
491 {
492 // do not copy in itself
493 const SwNodeIndex *pTmp = pFlyFormat->GetContent().GetContentIdx();
494 if ( aPos.nNode > *pTmp && aPos.nNode <
495 pTmp->GetNode().EndOfSectionIndex() )
496 {
497 bRet = false;
498 }
499 else
500 bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt,
501 rDestShell, aAnchor, aNewAnch, true );
502 }
503 }
504 else
505 {
506 const SwPaM *pCursor = rDestShell.GetCursor();
507 if( pCursor->GetNode().IsNoTextNode() )
508 bRet = false;
509 else
510 bRet = ::lcl_SetAnchor( *pCursor->GetPoint(), pCursor->GetNode(),
511 pFly, rInsPt, rDestShell, aAnchor,
512 aNewAnch, GetDoc() == rDestShell.GetDoc());
513 }
514 }
515 else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
516 {
517 aAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
518 const SwRootFrame* pTmpRoot = rDestShell.GetLayout();
519 const SwFrame* pPg = pTmpRoot->GetPageAtPos( rInsPt, nullptr, true );
520 if ( pPg )
521 aNewAnch = pPg->getFrameArea().Pos();
522 }
523 else {
524 OSL_ENSURE( false, "what anchor is it?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "524" ": "), "%s", "what anchor is it?"); } } while (false
)
;
525 }
526
527 if( bRet )
528 {
529 SwFrameFormat *pOldFormat = pFlyFormat;
530 pFlyFormat = rDestShell.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat, aAnchor, true, true );
531
532 if ( RndStdIds::FLY_AS_CHAR != aAnchor.GetAnchorId() )
533 {
534 Point aPos( rInsPt );
535 aPos -= aNewAnch;
536 aPos -= rSttPt - pFly->getFrameArea().Pos();
537 pFlyFormat->SetFormatAttr( SwFormatHoriOrient( aPos.getX(),text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
538 pFlyFormat->SetFormatAttr( SwFormatVertOrient( aPos.getY(),text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
539 }
540
541 const Point aPt( rDestShell.GetCursorDocPos() );
542
543 if( bIsMove )
544 GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pOldFormat );
545
546 // only select if it can be shifted/copied in the same shell
547 if( bSelectInsert )
548 {
549 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pFlyFormat)->GetFrame( &aPt );
550 if( pFlyFrame )
551 {
552 //JP 12.05.98: should this be in SelectFlyFrame???
553 rDestShell.Imp()->GetDrawView()->UnmarkAll();
554 rDestShell.SelectFlyFrame( *pFlyFrame );
555 }
556 }
557
558 if (this != &rDestShell && !rDestShell.HasShellFocus())
559 rDestShell.Imp()->GetDrawView()->hideMarkHandles();
560 }
561 }
562 else if ( IsObjSelected() )
563 bRet = CopyDrawSel( rDestShell, rSttPt, rInsPt, bIsMove, bSelectInsert );
564 else if( IsTableMode() )
565 {
566 // Copy parts from a table: create a table with the same
567 // width as the original and copy the selected boxes.
568 // Sizes will be corrected by percentage.
569
570 // find boxes via the layout
571 SwSelBoxes aBoxes;
572 GetTableSel( *this, aBoxes );
573 SwTableNode const*const pTableNd(
574 aBoxes.empty() ? nullptr : aBoxes[0]->GetSttNd()->FindTableNode());
575 if (nullptr != pTableNd)
576 {
577 std::unique_ptr<SwPosition> pDstPos;
578 if( this == &rDestShell )
579 {
580 // same shell? Then create new Cursor at the
581 // DocumentPosition passed
582 pDstPos.reset(new SwPosition( *GetCursor()->GetPoint() ));
583 Point aPt( rInsPt );
584 GetLayout()->GetModelPositionForViewPoint( pDstPos.get(), aPt );
585 if( !pDstPos->nNode.GetNode().IsNoTextNode() )
586 bRet = true;
587 }
588 else if( !rDestShell.GetCursor()->GetNode().IsNoTextNode() )
589 {
590 pDstPos.reset(new SwPosition( *rDestShell.GetCursor()->GetPoint() ));
591 bRet = true;
592 }
593
594 if( bRet )
595 {
596 if( GetDoc() == rDestShell.GetDoc() )
597 ParkTableCursor();
598
599 bRet = rDestShell.GetDoc()->InsCopyOfTable( *pDstPos, aBoxes,nullptr,
600 bIsMove && this == &rDestShell &&
601 aBoxes.size() == pTableNd->GetTable().
602 GetTabSortBoxes().size(),
603 this != &rDestShell );
604
605 if( this != &rDestShell )
606 *rDestShell.GetCursor()->GetPoint() = *pDstPos;
607
608 // create all parked Cursor?
609 if( GetDoc() == rDestShell.GetDoc() )
610 GetCursor();
611
612 // JP 16.04.99: Bug 64908 - Set InsPos, to assure the parked
613 // Cursor is positioned at the insert position
614 if( this == &rDestShell )
615 GetCursorDocPos() = rInsPt;
616 }
617 }
618 }
619 else
620 {
621 bRet = true;
622 if( this == &rDestShell )
623 {
624 // same shell? then request the position
625 // at the passed document position
626 SwPosition aPos( *GetCursor()->GetPoint() );
627 Point aPt( rInsPt );
628 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
629 bRet = !aPos.nNode.GetNode().IsNoTextNode();
630 }
631 else if( rDestShell.GetCursor()->GetNode().IsNoTextNode() )
632 bRet = false;
633
634 if( bRet )
635 bRet = SwEditShell::Copy( rDestShell );
636 }
637
638 rDestShell.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode );
639 mxDoc->SetCopyIsMove( bCopyIsMove );
640
641 // have new table formulas been inserted?
642 if( pTableFieldTyp->HasWriterListeners() )
643 {
644 // finish old actions: the table frames are created and
645 // a selection can be made
646 sal_uInt16 nActCnt;
647 for( nActCnt = 0; rDestShell.ActionPend(); ++nActCnt )
648 rDestShell.EndAllAction();
649
650 for( ; nActCnt; --nActCnt )
651 rDestShell.StartAllAction();
652 }
653 rDestShell.GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
654 rDestShell.GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
655
656 rDestShell.EndAllAction();
657 return bRet;
658}
659
660// Paste for the internal clipboard. Copy the content of the clipboard
661// in the document
662namespace {
663 typedef std::shared_ptr<SwPaM> PaMPtr;
664 typedef std::shared_ptr<SwPosition> PositionPtr;
665 typedef std::pair< PaMPtr, PositionPtr > Insertion;
666
667 bool PamHasSelection(const SwPaM& rPaM)
668 {
669 return rPaM.HasMark() && *rPaM.GetPoint() != *rPaM.GetMark();
670 }
671}
672
673bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
674{
675 CurrShell aCurr( this );
676 // then till end of the nodes array
677 SwNodeIndex aIdx( rClpDoc.GetNodes().GetEndOfExtras(), 2 );
678 SwPaM aCpyPam( aIdx ); //DocStart
679
680 // If there are table formulas in the area, then display the table first
681 // so that the table formula can calculate a new value first
682 // (individual boxes in the area are retrieved via the layout)
683 SwFieldType* pTableFieldTyp = GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table );
684
685 SwTableNode *const pSrcNd = aCpyPam.GetNode().GetTableNode();
686 if( !pSrcNd ) // table node ?
687 { // don't skip !!
688 SwContentNode* pCNd = aCpyPam.GetNode().GetContentNode();
689 if( pCNd )
690 aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 );
691 else if( !aCpyPam.Move( fnMoveForward, GoInNode ))
692 aCpyPam.Move( fnMoveBackward, GoInNode );
693 }
694
695 aCpyPam.SetMark();
696 aCpyPam.Move( fnMoveForward, GoInDoc );
697
698 bool bRet = true;
699 StartAllAction();
700 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSGLOSSARY, nullptr );
701 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
702
703 // When the clipboard content has been created by a rectangular selection
704 // the pasting is more sophisticated:
705 // every paragraph will be inserted into another position.
706 // The first positions are given by the actual cursor ring,
707 // if there are more text portions to insert than cursor in this ring,
708 // the additional insert positions will be created by moving the last
709 // cursor position into the next line (like pressing the cursor down key)
710 if( rClpDoc.IsColumnSelection() && !IsTableMode() )
711 {
712 // Creation of the list of insert positions
713 std::vector< Insertion > aCopyVector;
714 // The number of text portions of the rectangular selection
715 const sal_uInt32 nSelCount = aCpyPam.GetPoint()->nNode.GetIndex()
716 - aCpyPam.GetMark()->nNode.GetIndex();
717 sal_uInt32 nCount = nSelCount;
718 SwNodeIndex aClpIdx( aIdx );
719 SwPaM* pStartCursor = GetCursor();
720 SwPaM* pCurrCursor = pStartCursor;
721 sal_uInt32 nCursorCount = pStartCursor->GetRingContainer().size();
722 // If the target selection is a multi-selection, often the last and first
723 // cursor of the ring points to identical document positions. Then
724 // we should avoid double insertion of text portions...
725 while( nCursorCount > 1 && *pCurrCursor->GetPoint() ==
726 *(pCurrCursor->GetPrev()->GetPoint()) )
727 {
728 --nCursorCount;
729 pCurrCursor = pCurrCursor->GetNext();
730 pStartCursor = pCurrCursor;
731 }
732 SwPosition aStartPos( *pStartCursor->GetPoint() );
733 SwPosition aInsertPos( aStartPos ); // first insertion position
734 bool bCompletePara = false;
735 sal_uInt16 nMove = 0;
736 while( nCount )
737 {
738 --nCount;
739 OSL_ENSURE( aIdx.GetNode().GetContentNode(), "Who filled the clipboard?!" )do { if (true && (!(aIdx.GetNode().GetContentNode()))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "739" ": "), "%s", "Who filled the clipboard?!"); } } while
(false)
;
740 if( aIdx.GetNode().GetContentNode() ) // robust
741 {
742 Insertion aInsertion( std::make_shared<SwPaM>( aIdx ),
743 std::make_shared<SwPosition>( aInsertPos ) );
744 ++aIdx;
745 aInsertion.first->SetMark();
746 if( pStartCursor == pCurrCursor->GetNext() )
747 { // Now we have to look for insertion positions...
748 if( !nMove ) // Annotate the last given insert position
749 aStartPos = aInsertPos;
750 SwCursor aCursor( aStartPos, nullptr);
751 // Check if we find another insert position by moving
752 // down the last given position
753 if (aCursor.UpDown(false, ++nMove, nullptr, 0, *GetLayout()))
754 aInsertPos = *aCursor.GetPoint();
755 else // if there is no paragraph we have to create it
756 bCompletePara = nCount > 0;
757 nCursorCount = 0;
758 }
759 else // as long as we find more insert positions in the cursor ring
760 { // we'll take them
761 pCurrCursor = pCurrCursor->GetNext();
762 aInsertPos = *pCurrCursor->GetPoint();
763 --nCursorCount;
764 }
765 // If there are no more paragraphs e.g. at the end of a document,
766 // we insert complete paragraphs instead of text portions
767 if( bCompletePara )
768 aInsertion.first->GetPoint()->nNode = aIdx;
769 else
770 aInsertion.first->GetPoint()->nContent =
771 aInsertion.first->GetContentNode()->Len();
772 aCopyVector.push_back( aInsertion );
773 }
774 // If there are no text portions left but there are some more
775 // cursor positions to fill we have to restart with the first
776 // text portion
777 if( !nCount && nCursorCount )
778 {
779 nCount = std::min( nSelCount, nCursorCount );
780 aIdx = aClpIdx; // Start of clipboard content
781 }
782 }
783 for (auto const& item : aCopyVector)
784 {
785 SwPosition& rInsPos = *item.second;
786 SwPaM& rCopy = *item.first;
787 const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
788 if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex() &&
789 rCopy.GetPoint()->nNode != rCopy.GetMark()->nNode )
790 {
791 // if more than one node will be copied into a cell
792 // the box attributes have to be removed
793 GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
794 }
795 {
796 SwNodeIndex aIndexBefore(rInsPos.nNode);
797 --aIndexBefore;
798 rClpDoc.getIDocumentContentOperations().CopyRange(rCopy, rInsPos, SwCopyFlags::CheckPosInFly);
799 {
800 ++aIndexBefore;
801 SwPaM aPaM(SwPosition(aIndexBefore),
802 SwPosition(rInsPos.nNode));
803 aPaM.GetDoc().MakeUniqueNumRules(aPaM);
804 }
805 }
806 SaveTableBoxContent( &rInsPos );
807 }
808 }
809 else
810 {
811 bool bDelTable = true;
812
813 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
814 {
815
816 SwTableNode *const pDestNd(GetDoc()->IsIdxInTable(rPaM.GetPoint()->nNode));
817 if (pSrcNd && nullptr != pDestNd &&
818 // not a forced nested table insertion
819 !bNestedTable &&
820 // are we at the beginning of the cell? (if not, we will insert a nested table)
821 // first paragraph of the cell?
822 rPaM.GetNode().GetIndex() == rPaM.GetNode().FindTableBoxStartNode()->GetIndex()+1 &&
823 // beginning of the paragraph?
824 !rPaM.GetPoint()->nContent.GetIndex())
825 {
826 SwPosition aDestPos( *rPaM.GetPoint() );
827
828 bool bParkTableCursor = false;
829 const SwStartNode* pSttNd = rPaM.GetNode().FindTableBoxStartNode();
830
831 // TABLE IN TABLE: copy table in table
832 // search boxes via the layout
833 SwSelBoxes aBoxes;
834 if( IsTableMode() ) // table selection?
835 {
836 GetTableSel( *this, aBoxes );
837 ParkTableCursor();
838 bParkTableCursor = true;
839 }
840 else if( !PamHasSelection(rPaM) && rPaM.GetNext() == &rPaM &&
841 ( !pSrcNd->GetTable().IsTableComplex() ||
842 pDestNd->GetTable().IsNewModel() ) )
843 {
844 // make relative table copy
845 SwTableBox* pBox = pDestNd->GetTable().GetTableBox(
846 pSttNd->GetIndex() );
847 OSL_ENSURE( pBox, "Box is not in this table" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "847" ": "), "%s", "Box is not in this table"); } } while
(false)
;
848 aBoxes.insert( pBox );
849 }
850
851 SwNodeIndex aNdIdx( *pDestNd->EndOfSectionNode());
852 if( !bParkTableCursor )
853 {
854 // exit first the complete table
855 // ???? what about only table in a frame ?????
856 SwContentNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
857 SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
858 // #i59539: Don't remove all redline
859 SwPaM const tmpPaM(*pDestNd, *pDestNd->EndOfSectionNode());
860 ::PaMCorrAbs(tmpPaM, aPos);
861 }
862
863 bRet = GetDoc()->InsCopyOfTable( aDestPos, aBoxes, &pSrcNd->GetTable() );
864
865 if( bParkTableCursor )
866 GetCursor();
867 else
868 {
869 // return to the box
870 aNdIdx = *pSttNd;
871 SwContentNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
872 SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
873 // #i59539: Don't remove all redline
874 SwNode & rNode(rPaM.GetPoint()->nNode.GetNode());
875 SwContentNode *const pContentNode( rNode.GetContentNode() );
876 SwPaM const tmpPam(rNode, 0,
877 rNode, pContentNode ? pContentNode->Len() : 0);
878 ::PaMCorrAbs(tmpPam, aPos);
879 }
880
881 break; // exit the "while-loop"
882 }
883 else if( *aCpyPam.GetPoint() == *aCpyPam.GetMark() &&
884 !rClpDoc.GetSpzFrameFormats()->empty() )
885 {
886 // we need a DrawView
887 if( !Imp()->GetDrawView() )
888 MakeDrawView();
889
890 for ( auto pCpyFormat : *rClpDoc.GetSpzFrameFormats() )
891 {
892 bool bInsWithFormat = true;
893
894 if( Imp()->GetDrawView()->IsGroupEntered() &&
895 RES_DRAWFRMFMT == pCpyFormat->Which() &&
896 (RndStdIds::FLY_AS_CHAR != pCpyFormat->GetAnchor().GetAnchorId()) )
897 {
898 const SdrObject* pSdrObj = pCpyFormat->FindSdrObject();
899 if( pSdrObj )
900 {
901 SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj,
902 false, false );
903
904 // Insert object sets any anchor position to 0.
905 // Therefore we calculate the absolute position here
906 // and after the insert the anchor of the object
907 // is set to the anchor of the group object.
908 tools::Rectangle aSnapRect = pNew->GetSnapRect();
909 if( pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y() )
910 {
911 const Point aPoint( 0, 0 );
912 // OD 2004-04-05 #i26791# - direct drawing object
913 // positioning for group members
914 pNew->NbcSetAnchorPos( aPoint );
915 pNew->NbcSetSnapRect( aSnapRect );
916 }
917
918 Imp()->GetDrawView()->InsertObjectAtView( pNew, *Imp()->GetPageView() );
919
920 Point aGrpAnchor( 0, 0 );
921 SdrObjList* pList = pNew->getParentSdrObjListFromSdrObject();
922 if ( pList )
923 {
924 SdrObjGroup* pOwner(dynamic_cast< SdrObjGroup* >(pList->getSdrObjectFromSdrObjList()));
925
926 if(nullptr != pOwner)
927 {
928 aGrpAnchor = pOwner->GetAnchorPos();
929 }
930 }
931
932 // OD 2004-04-05 #i26791# - direct drawing object
933 // positioning for group members
934 pNew->NbcSetAnchorPos( aGrpAnchor );
935 pNew->SetSnapRect( aSnapRect );
936
937 bInsWithFormat = false;
938 }
939 }
940
941 if( bInsWithFormat )
942 {
943 SwFormatAnchor aAnchor( pCpyFormat->GetAnchor() );
944 if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
945 (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
946 (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
947 {
948 SwPosition* pPos = rPaM.GetPoint();
949 // allow shapes (no controls) in header/footer
950 if( RES_DRAWFRMFMT == pCpyFormat->Which() &&
951 GetDoc()->IsInHeaderFooter( pPos->nNode ) )
952 {
953 const SdrObject *pCpyObj = pCpyFormat->FindSdrObject();
954 if (pCpyObj && CheckControlLayer(pCpyObj))
955 continue;
956 }
957
958 // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
959 if (SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT))
960 continue;
961
962 aAnchor.SetAnchor( pPos );
963 }
964 else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
965 {
966 aAnchor.SetPageNum( GetPhyPageNum() );
967 }
968 else if( RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() )
969 {
970 Point aPt;
971 (void)lcl_SetAnchor( *rPaM.GetPoint(), rPaM.GetNode(),
972 nullptr, aPt, *this, aAnchor, aPt, false );
973 }
974
975 SwFrameFormat * pNew = GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchor, true, true );
976
977 if( pNew )
978 {
979 if( RES_FLYFRMFMT == pNew->Which() )
980 {
981 const Point aPt( GetCursorDocPos() );
982 SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pNew)->
983 GetFrame( &aPt );
984 if( pFlyFrame )
985 SelectFlyFrame( *pFlyFrame );
986 // always pick the first FlyFrame only; the others
987 // were copied to the clipboard via Fly in Fly
988 break;
989 }
990 else
991 {
992 OSL_ENSURE( RES_DRAWFRMFMT == pNew->Which(), "New format.")do { if (true && (!(RES_DRAWFRMFMT == pNew->Which(
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "992" ": "), "%s", "New format."); } } while (false)
;
993 // #i52780# - drawing object has to be made visible on paste.
994 pNew->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING));
995 SdrObject *pObj = pNew->FindSdrObject();
996 SwDrawView *pDV = Imp()->GetDrawView();
997 pDV->MarkObj( pObj, pDV->GetSdrPageView() );
998 // #i47455# - notify draw frame format
999 // that position attributes are already set.
1000 if ( dynamic_cast<const SwDrawFrameFormat*>( pNew) != nullptr )
1001 {
1002 static_cast<SwDrawFrameFormat*>(pNew)->PosAttrSet();
1003 }
1004 }
1005 }
1006 }
1007 }
1008 }
1009 else
1010 {
1011 if( bDelTable && IsTableMode() )
1012 {
1013 SwEditShell::Delete();
1014 bDelTable = false;
1015 }
1016
1017 SwPosition& rInsPos = *rPaM.GetPoint();
1018 const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().
1019 FindTableBoxStartNode();
1020 if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() -
1021 pBoxNd->GetIndex() &&
1022 aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode )
1023 {
1024 // Copy more than 1 node in the current box. But
1025 // then the BoxAttribute should be removed
1026 GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
1027 }
1028
1029 // **
1030 // ** Update SwDoc::Append, if you change the following code **
1031 // **
1032 {
1033 SwNodeIndex aIndexBefore(rInsPos.nNode);
1034
1035 --aIndexBefore;
1036
1037 rClpDoc.getIDocumentContentOperations().CopyRange(aCpyPam, rInsPos, SwCopyFlags::CheckPosInFly);
1038 // Note: aCpyPam is invalid now
1039
1040 ++aIndexBefore;
1041 SwPaM aPaM(SwPosition(aIndexBefore),
1042 SwPosition(rInsPos.nNode));
1043
1044 aPaM.GetDoc().MakeUniqueNumRules(aPaM);
1045
1046 // Update the rsid of each pasted text node.
1047 SwNodes &rDestNodes = GetDoc()->GetNodes();
1048 sal_uLong const nEndIdx = aPaM.End()->nNode.GetIndex();
1049
1050 for (sal_uLong nIdx = aPaM.Start()->nNode.GetIndex();
1051 nIdx <= nEndIdx; ++nIdx)
1052 {
1053 SwTextNode *const pTextNode = rDestNodes[nIdx]->GetTextNode();
1054 if ( pTextNode )
1055 {
1056 GetDoc()->UpdateParRsid( pTextNode );
1057 }
1058 }
1059 }
1060
1061 SaveTableBoxContent( &rInsPos );
1062 }
1063 }
1064 }
1065
1066 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSGLOSSARY, nullptr );
1067
1068 // have new table formulas been inserted?
1069 if( pTableFieldTyp->HasWriterListeners() )
1070 {
1071 // finish old action: table-frames have been created
1072 // a selection can be made now
1073 sal_uInt16 nActCnt;
1074 for( nActCnt = 0; ActionPend(); ++nActCnt )
1075 EndAllAction();
1076
1077 for( ; nActCnt; --nActCnt )
1078 StartAllAction();
1079 }
1080 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1081 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1082 EndAllAction();
1083
1084 return bRet;
1085}
1086
1087void SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage)
1088{
1089 Push();
1090 if(!GotoPage(nStartPage))
1091 {
1092 Pop(PopMode::DeleteCurrent);
1093 return;
1094 }
1095 MovePage( GetThisFrame, GetFirstSub );
1096 SwPaM aCpyPam( *GetCursor()->GetPoint() );
1097 OUString sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName();
1098 SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, true );
1099 if( pDesc )
1100 rToFill.ChgCurPageDesc( *pDesc );
1101
1102 if(!GotoPage(nEndPage))
1103 {
1104 Pop(PopMode::DeleteCurrent);
1105 return;
1106 }
1107 //if the page starts with a table a paragraph has to be inserted before
1108 SwNode* pTableNode = aCpyPam.GetNode().FindTableNode();
1109 if(pTableNode)
1110 {
1111 //insert a paragraph
1112 StartUndo(SwUndoId::INSERT);
1113 SwNodeIndex aTableIdx( *pTableNode, -1 );
1114 SwPosition aBefore(aTableIdx);
1115 if(GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore ))
1116 {
1117 SwPaM aTmp(aBefore);
1118 aCpyPam = aTmp;
1119 }
1120 EndUndo(SwUndoId::INSERT);
1121 }
1122
1123 MovePage( GetThisFrame, GetLastSub );
1124 aCpyPam.SetMark();
1125 *aCpyPam.GetMark() = *GetCursor()->GetPoint();
1126
1127 CurrShell aCurr( this );
1128
1129 StartAllAction();
1130 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1131 SetSelection(aCpyPam);
1132 // copy the text of the selection
1133 SwEditShell::Copy(rToFill);
1134
1135 if(pTableNode)
1136 {
1137 //remove the inserted paragraph
1138 Undo();
1139 //remove the paragraph in the second doc, too
1140 SwNodeIndex aIdx( rToFill.GetDoc()->GetNodes().GetEndOfExtras(), 2 );
1141 SwPaM aPara( aIdx ); //DocStart
1142 rToFill.GetDoc()->getIDocumentContentOperations().DelFullPara(aPara);
1143 }
1144 // now the page bound objects
1145 // additionally copy page bound frames
1146 if( !GetDoc()->GetSpzFrameFormats()->empty() )
1147 {
1148 // create a draw view if necessary
1149 if( !rToFill.Imp()->GetDrawView() )
1150 rToFill.MakeDrawView();
1151
1152 for ( auto pCpyFormat : *GetDoc()->GetSpzFrameFormats() )
1153 {
1154 SwFormatAnchor aAnchor( pCpyFormat->GetAnchor() );
1155 if ((RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()) &&
1156 aAnchor.GetPageNum() >= nStartPage && aAnchor.GetPageNum() <= nEndPage)
1157 {
1158 aAnchor.SetPageNum( aAnchor.GetPageNum() - nStartPage + 1);
1159 }
1160 else
1161 continue;
1162 rToFill.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchor, true, true );
1163 }
1164 }
1165 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1166 GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
1167 Pop(PopMode::DeleteCurrent);
1168 EndAllAction();
1169}
1170
1171comphelper::OInterfaceContainerHelper2& SwFEShell::GetPasteListeners() { return m_aPasteListeners; }
1172
1173bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat, Graphic& rGrf ) const
1174{
1175 OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" )do { if (true && (!(Imp()->HasDrawView()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "1175" ": "), "%s", "GetDrawObjGraphic without DrawView?"
); } } while (false)
;
1
Taking false branch
2
Loop condition is false. Exiting loop
1176 const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
1177 bool bConvert = true;
1178 if( rMrkList.GetMarkCount() )
3
Assuming the condition is true
4
Taking true branch
1179 {
1180 if( rMrkList.GetMarkCount() == 1 &&
5
Assuming the condition is true
7
Taking true branch
1181 dynamic_cast< const SwVirtFlyDrawObj* >(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) != nullptr )
6
Assuming the condition is true
1182 {
1183 // select frame
1184 if( CNT_GRF0x0002 == GetCntType() )
8
Assuming the condition is true
9
Taking true branch
1185 {
1186 const Graphic* pGrf( GetGraphic() );
1187 if ( pGrf )
10
Assuming 'pGrf' is non-null
11
Taking true branch
1188 {
1189 Graphic aGrf( *pGrf );
1190 if( SotClipboardFormatId::GDIMETAFILE == nFormat )
12
Assuming 'nFormat' is not equal to GDIMETAFILE
13
Taking false branch
1191 {
1192 if( GraphicType::Bitmap != aGrf.GetType() )
1193 {
1194 rGrf = aGrf;
1195 bConvert = false;
1196 }
1197 else if( GetWin() )
1198 {
1199 Size aSz;
1200 Point aPt;
1201 GetGrfSize( aSz );
1202
1203 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1204 pVirtDev->EnableOutput( false );
1205
1206 MapMode aTmp( GetWin()->GetMapMode() );
1207 aTmp.SetOrigin( aPt );
1208 pVirtDev->SetMapMode( aTmp );
1209
1210 GDIMetaFile aMtf;
1211 aMtf.Record( pVirtDev.get() );
1212 aGrf.Draw( pVirtDev, aPt, aSz );
1213 aMtf.Stop();
1214 aMtf.SetPrefMapMode( aTmp );
1215 aMtf.SetPrefSize( aSz );
1216 rGrf = aMtf;
1217 }
1218 }
1219 else if( GraphicType::Bitmap == aGrf.GetType() )
14
Assuming the condition is false
15
Taking false branch
1220 {
1221 rGrf = aGrf;
1222 bConvert = false;
1223 }
1224 else
1225 {
1226 // Not the original size, but the current one.
1227 // Otherwise it could happen that for vector graphics
1228 // many MB's of memory are allocated.
1229 const Size aSz( GetSelectedFlyFrame()->getFramePrintArea().SSize() );
1230 ScopedVclPtrInstance< VirtualDevice > pVirtDev(*GetWin());
16
Calling constructor for 'ScopedVclPtrInstance<VirtualDevice>'
18
Returning from constructor for 'ScopedVclPtrInstance<VirtualDevice>'
1231
1232 MapMode aTmp( MapUnit::MapTwip );
1233 pVirtDev->SetMapMode( aTmp );
1234 if( pVirtDev->SetOutputSize( aSz ) )
19
Assuming the condition is false
20
Taking false branch
1235 {
1236 aGrf.Draw( pVirtDev.get(), Point(), aSz );
1237 rGrf = pVirtDev->GetBitmapEx( Point(), aSz );
1238 }
1239 else
1240 {
1241 rGrf = aGrf;
1242 bConvert = false;
1243 }
1244 }
21
Calling implicit destructor for 'ScopedVclPtrInstance<VirtualDevice>'
22
Calling '~ScopedVclPtr'
1245 }
1246 }
1247 }
1248 else if( SotClipboardFormatId::GDIMETAFILE == nFormat )
1249 rGrf = Imp()->GetDrawView()->GetMarkedObjMetaFile();
1250 else if( SotClipboardFormatId::BITMAP == nFormat || SotClipboardFormatId::PNG == nFormat )
1251 rGrf = Imp()->GetDrawView()->GetMarkedObjBitmapEx();
1252 }
1253 return bConvert;
1254}
1255
1256// #i50824#
1257// replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1258static void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel& _rModel )
1259{
1260 for ( sal_uInt16 nPgNum = 0; nPgNum < _rModel.GetPageCount(); ++nPgNum )
1261 {
1262 // setup object iterator in order to iterate through all objects
1263 // including objects in group objects, but exclusive group objects.
1264 SdrObjListIter aIter(_rModel.GetPage(nPgNum));
1265 while( aIter.IsMore() )
1266 {
1267 SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() );
1268 if( pOle2Obj )
1269 {
1270 // found an ole2 shape
1271 SdrObjList* pObjList = pOle2Obj->getParentSdrObjListFromSdrObject();
1272
1273 // get its graphic
1274 Graphic aGraphic;
1275 pOle2Obj->Connect();
1276 const Graphic* pGraphic = pOle2Obj->GetGraphic();
1277 if( pGraphic )
1278 aGraphic = *pGraphic;
1279 pOle2Obj->Disconnect();
1280
1281 // create new graphic shape with the ole graphic and shape size
1282 SdrGrafObj* pGraphicObj = new SdrGrafObj(
1283 _rModel,
1284 aGraphic,
1285 pOle2Obj->GetCurrentBoundRect());
1286 // apply layer of ole2 shape at graphic shape
1287 pGraphicObj->SetLayer( pOle2Obj->GetLayer() );
1288
1289 // replace ole2 shape with the new graphic object and delete the ol2 shape
1290 SdrObject* pRemovedObject = pObjList->ReplaceObject( pGraphicObj, pOle2Obj->GetOrdNum() );
1291 SdrObject::Free( pRemovedObject );
1292 }
1293 }
1294 }
1295}
1296
1297void SwFEShell::Paste( SvStream& rStrm, SwPasteSdr nAction, const Point* pPt )
1298{
1299 CurrShell aCurr( this );
1300 StartAllAction();
1301 StartUndo();
1302
1303 std::unique_ptr< FmFormModel > pModel(
1304 new FmFormModel(
1305 nullptr,
1306 GetDoc()->GetDocShell()));
1307
1308 pModel->GetItemPool().FreezeIdRanges();
1309
1310 rStrm.Seek(0);
1311
1312 uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rStrm ) );
1313 SvxDrawingLayerImport( pModel.get(), xInputStream );
1314
1315 if ( !Imp()->HasDrawView() )
1316 Imp()->MakeDrawView();
1317
1318 Point aPos( pPt ? *pPt : GetCharRect().Pos() );
1319 SdrView *pView = Imp()->GetDrawView();
1320
1321 // drop on the existing object: replace object or apply new attributes
1322 if( pModel->GetPageCount() > 0 &&
1323 1 == pModel->GetPage(0)->GetObjCount() &&
1324 1 == pView->GetMarkedObjectList().GetMarkCount() )
1325 {
1326 // replace a marked 'virtual' drawing object
1327 // by its corresponding 'master' drawing object in the mark list.
1328 SwDrawView::ReplaceMarkedDrawVirtObjs( *pView );
1329
1330 SdrObject* pClpObj = pModel->GetPage(0)->GetObj(0);
1331 SdrObject* pOldObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1332
1333 if( SwPasteSdr::SetAttr == nAction && dynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) != nullptr )
1334 nAction = SwPasteSdr::Replace;
1335
1336 switch( nAction )
1337 {
1338 case SwPasteSdr::Replace:
1339 {
1340 const SwFrameFormat* pFormat(nullptr);
1341 const SwFrame* pAnchor(nullptr);
1342 if( dynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) != nullptr )
1343 {
1344 pFormat = FindFrameFormat( pOldObj );
1345
1346 Point aNullPt;
1347 SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrameFormat*>(pFormat)->GetFrame( &aNullPt );
1348 pAnchor = pFlyFrame ? pFlyFrame->GetAnchorFrame() : nullptr;
1349
1350 if (!pAnchor || pAnchor->FindFooterOrHeader())
1351 {
1352 // if there is a textframe in the header/footer:
1353 // do not replace but insert
1354 nAction = SwPasteSdr::Insert;
1355 break;
1356 }
1357 }
1358
1359 SdrObject* pNewObj(pClpObj->CloneSdrObject(pOldObj->getSdrModelFromSdrObject()));
1360 tools::Rectangle aOldObjRect( pOldObj->GetCurrentBoundRect() );
1361 Size aOldObjSize( aOldObjRect.GetSize() );
1362 tools::Rectangle aNewRect( pNewObj->GetCurrentBoundRect() );
1363 Size aNewSize( aNewRect.GetSize() );
1364
1365 Fraction aScaleWidth( aOldObjSize.Width(), aNewSize.Width() );
1366 Fraction aScaleHeight( aOldObjSize.Height(), aNewSize.Height());
1367 pNewObj->NbcResize( aNewRect.TopLeft(), aScaleWidth, aScaleHeight);
1368
1369 Point aVec = aOldObjRect.TopLeft() - aNewRect.TopLeft();
1370 pNewObj->NbcMove(Size(aVec.getX(), aVec.getY()));
1371
1372 if( dynamic_cast<const SdrUnoObj*>( pNewObj) != nullptr )
1373 pNewObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1374 else if( dynamic_cast<const SdrUnoObj*>( pOldObj) != nullptr )
1375 pNewObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1376 else
1377 pNewObj->SetLayer( pOldObj->GetLayer() );
1378
1379 if( dynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) != nullptr )
1380 {
1381 // store attributes, then set SdrObject
1382 SfxItemSet aFrameSet( mxDoc->GetAttrPool(),
1383 svl::Items<RES_SURROUND, RES_ANCHOR>{} );
1384 aFrameSet.Set( pFormat->GetAttrSet() );
1385
1386 Point aNullPt;
1387 if( pAnchor->IsTextFrame() && static_cast<const SwTextFrame*>(pAnchor)->IsFollow() )
1388 {
1389 const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnchor);
1390 do {
1391 pTmp = pTmp->FindMaster();
1392 OSL_ENSURE( pTmp, "Where's my Master?" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/fecopy.cxx"
":" "1392" ": "), "%s", "Where's my Master?"); } } while (false
)
;
1393 } while( pTmp->IsFollow() );
1394 pAnchor = pTmp;
1395 }
1396 if( dynamic_cast<const SdrCaptionObj*>( pOldObj) != nullptr)
1397 aNullPt = static_cast<SdrCaptionObj*>(pOldObj)->GetTailPos();
1398 else
1399 aNullPt = aOldObjRect.TopLeft();
1400
1401 Point aNewAnchor = pAnchor->GetFrameAnchorPos( ::HasWrap( pOldObj ) );
1402 // OD 2004-04-05 #i26791# - direct positioning of Writer
1403 // fly frame object for <SwDoc::Insert(..)>
1404 pNewObj->NbcSetRelativePos( aNullPt - aNewAnchor );
1405 pNewObj->NbcSetAnchorPos( aNewAnchor );
1406
1407 pOldObj->GetOrdNum();
1408
1409 DelSelectedObj();
1410
1411 GetDoc()->getIDocumentContentOperations().InsertDrawObj( *GetCursor(), *pNewObj, aFrameSet );
1412 }
1413 else
1414 {
1415 // #i123922# for handling MasterObject and virtual ones correctly, SW
1416 // wants us to call ReplaceObject at the page, but that also
1417 // triggers the same assertion (I tried it), so stay at the view method
1418 pView->ReplaceObjectAtView(pOldObj, *Imp()->GetPageView(), pNewObj);
1419 }
1420 }
1421 break;
1422
1423 case SwPasteSdr::SetAttr:
1424 {
1425 SfxItemSet aSet( GetAttrPool() );
1426 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pClpObj);
1427
1428 if(pSdrGrafObj)
1429 {
1430 SdrObject* pTarget = nullptr;
1431
1432 if(0 != pView->GetMarkedObjectList().GetMarkCount())
1433 {
1434 // try to get target (if it's at least one, take first)
1435 SdrMark* pMark = pView->GetMarkedObjectList().GetMark(0);
1436
1437 if(pMark)
1438 {
1439 pTarget = pMark->GetMarkedSdrObj();
1440 }
1441 }
1442
1443 if(pTarget)
1444 {
1445 // copy ItemSet from target
1446 aSet.Set(pTarget->GetMergedItemSet());
1447 }
1448
1449 // for SdrGrafObj, use the graphic as fill style argument
1450 const Graphic& rGraphic = pSdrGrafObj->GetGraphic();
1451
1452 if(GraphicType::NONE != rGraphic.GetType() && GraphicType::Default != rGraphic.GetType())
1453 {
1454 aSet.Put(XFillBitmapItem(OUString(), rGraphic));
1455 aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
1456 }
1457 }
1458 else
1459 {
1460 aSet.Put(pClpObj->GetMergedItemSet());
1461 }
1462
1463 pView->SetAttributes( aSet );
1464 }
1465 break;
1466
1467 default:
1468 nAction = SwPasteSdr::Insert;
1469 break;
1470 }
1471 }
1472 else
1473 nAction = SwPasteSdr::Insert;
1474
1475 if( SwPasteSdr::Insert == nAction )
1476 {
1477 ::sw::DrawUndoGuard drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());
1478
1479 bool bDesignMode = pView->IsDesignMode();
1480 if( !bDesignMode )
1481 pView->SetDesignMode();
1482
1483 // #i50824#
1484 // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
1485 lcl_ConvertSdrOle2ObjsToSdrGrafObjs(*pModel);
1486 pView->Paste(*pModel, aPos, nullptr, SdrInsertFlags::NONE);
1487
1488 const size_t nCnt = pView->GetMarkedObjectList().GetMarkCount();
1489 if( nCnt )
1490 {
1491 const Point aNull( 0, 0 );
1492 for( size_t i=0; i < nCnt; ++i )
1493 {
1494 SdrObject *pObj = pView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj();
1495 pObj->ImpSetAnchorPos( aNull );
1496 }
1497
1498 pView->SetCurrentObj( OBJ_GRUP );
1499 if ( nCnt > 1 )
1500 pView->GroupMarked();
1501 SdrObject *pObj = pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
1502 if( dynamic_cast<const SdrUnoObj*>( pObj) != nullptr )
1503 {
1504 pObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
1505 bDesignMode = true;
1506 }
1507 else
1508 pObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
1509 const tools::Rectangle &rSnap = pObj->GetSnapRect();
1510 const Size aDiff( rSnap.GetWidth()/2, rSnap.GetHeight()/2 );
1511 pView->MoveMarkedObj( aDiff );
1512 ImpEndCreate();
1513 if( !bDesignMode )
1514 pView->SetDesignMode( false );
1515 }
1516 }
1517 EndUndo();
1518 EndAllAction();
1519}
1520
1521bool SwFEShell::Paste(const Graphic &rGrf, const OUString& rURL)
1522{
1523 CurrShell aCurr( this );
1524 SdrObject* pObj = nullptr;
1525 SdrView *pView = Imp()->GetDrawView();
1526
1527 bool bRet = 1 == pView->GetMarkedObjectList().GetMarkCount();
1528 if (bRet)
1529 {
1530 pObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
1531 bRet = pObj->IsClosedObj() && dynamic_cast<const SdrOle2Obj*>( pObj) == nullptr;
1532 }
1533
1534 if( bRet && pObj )
1535 {
1536 // #i123922# added code to handle the two cases of SdrGrafObj and a fillable, non-
1537 // OLE object in focus
1538 SdrObject* pResult = pObj;
1539
1540 if(dynamic_cast< SdrGrafObj* >(pObj))
1541 {
1542 SdrGrafObj* pNewGrafObj(static_cast<SdrGrafObj*>(pObj->CloneSdrObject(pObj->getSdrModelFromSdrObject())));
1543
1544 pNewGrafObj->SetGraphic(rGrf);
1545
1546 // #i123922# for handling MasterObject and virtual ones correctly, SW
1547 // wants us to call ReplaceObject at the page, but that also
1548 // triggers the same assertion (I tried it), so stay at the view method
1549 pView->ReplaceObjectAtView(pObj, *pView->GetSdrPageView(), pNewGrafObj);
1550
1551 OUString aReferer;
1552 SwDocShell *pDocShell = GetDoc()->GetDocShell();
1553 if (pDocShell->HasName()) {
1554 aReferer = pDocShell->GetMedium()->GetName();
1555 }
1556
1557 // set in all cases - the Clone() will have copied an existing link (!)
1558 pNewGrafObj->SetGraphicLink(rURL, aReferer, OUString());
1559
1560 pResult = pNewGrafObj;
1561 }
1562 else
1563 {
1564 pView->AddUndo(std::make_unique<SdrUndoAttrObj>(*pObj));
1565
1566 SfxItemSet aSet(pView->GetModel()->GetItemPool(), svl::Items<XATTR_FILLSTYLE, XATTR_FILLBITMAP>{});
1567
1568 aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
1569 aSet.Put(XFillBitmapItem(OUString(), rGrf));
1570 pObj->SetMergedItemSetAndBroadcast(aSet);
1571 }
1572
1573 // we are done; mark the modified/new object
1574 pView->MarkObj(pResult, pView->GetSdrPageView());
1575 }
1576
1577 return bRet;
1578}
1579
1580/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
24
Calling 'Reference::clear'
31
Returning; memory was released
205 if (aTmp.get()) {
32
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
23
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
17
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
24.1
Field 'm_pBody' is non-null
24.1
Field 'm_pBody' is non-null
24.1
Field 'm_pBody' is non-null
24.1
Field 'm_pBody' is non-null
)
25
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
26
Calling 'VclReferenceBase::release'
30
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
33
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
27
Assuming the condition is true
28
Taking true branch
40 delete this;
29
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif