Bug Summary

File:home/maarten/src/libreoffice/core/include/tools/ref.hxx
Warning:line 56, column 30
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 drawvie4.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 SC_DLLIMPLEMENTATION -D SC_INFO_OSVERSION="LINUX" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -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/clew/source/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sc/source/core/inc -I /home/maarten/src/libreoffice/core/sc/source/filter/inc -I /home/maarten/src/libreoffice/core/sc/source/ui/inc -I /home/maarten/src/libreoffice/core/sc/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sc/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/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/sc/source/ui/view/drawvie4.cxx

/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.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 <svx/svditer.hxx>
21#include <svx/svdograf.hxx>
22#include <svx/svdogrp.hxx>
23#include <svx/svdoole2.hxx>
24#include <svx/svdundo.hxx>
25#include <sfx2/docfile.hxx>
26#include <tools/urlobj.hxx>
27#include <toolkit/helper/vclunohelper.hxx>
28#include <sal/log.hxx>
29
30#include <drawview.hxx>
31#include <global.hxx>
32#include <drwlayer.hxx>
33#include <viewdata.hxx>
34#include <document.hxx>
35#include <docsh.hxx>
36#include <drwtrans.hxx>
37#include <transobj.hxx>
38#include <drawutil.hxx>
39#include <scmod.hxx>
40#include <globstr.hrc>
41#include <scresid.hxx>
42#include <gridwin.hxx>
43#include <userdat.hxx>
44
45#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
46#include <com/sun/star/embed/Aspects.hpp>
47#include <com/sun/star/embed/XEmbeddedObject.hpp>
48#include <com/sun/star/chart2/XChartTypeContainer.hpp>
49#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
50#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
51#include <com/sun/star/chart2/XChartDocument.hpp>
52
53using namespace com::sun::star;
54
55Point aDragStartDiff;
56
57void ScDrawView::BeginDrag( vcl::Window* pWindow, const Point& rStartPos )
58{
59 if ( !AreObjectsMarked() )
1
Taking false branch
60 return;
61
62 BrkAction();
63
64 tools::Rectangle aMarkedRect = GetAllMarkedRect();
65
66 aDragStartDiff = rStartPos - aMarkedRect.TopLeft();
67
68 bool bAnyOle, bOneOle;
69 const SdrMarkList& rMarkList = GetMarkedObjectList();
70 CheckOle( rMarkList, bAnyOle, bOneOle );
71
72 ScDocShellRef aDragShellRef;
73 if (bAnyOle)
2
Assuming 'bAnyOle' is true
3
Taking true branch
74 {
75 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
4
Memory is allocated
76 aDragShellRef->DoInitNew();
77 }
78 ScDrawLayer::SetGlobalDrawPersist( aDragShellRef.get() );
79 std::unique_ptr<SdrModel> pModel(CreateMarkedObjModel());
80 ScDrawLayer::SetGlobalDrawPersist(nullptr);
81
82 // Charts now always copy their data in addition to the source reference, so
83 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
84 // Update with the data (including NumberFormatter) from the live document would
85 // also store the NumberFormatter in the clipboard chart (#88749#)
86
87 ScDocShell* pDocSh = pViewData->GetDocShell();
88
89 TransferableObjectDescriptor aObjDesc;
90 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
91 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
92 // maSize is set in ScDrawTransferObj ctor
93
94 rtl::Reference<ScDrawTransferObj> pTransferObj = new ScDrawTransferObj( std::move(pModel), pDocSh, aObjDesc );
95
96 pTransferObj->SetDrawPersist( aDragShellRef.get() ); // keep persist for ole objects alive
5
Calling '~SvRef'
15
Returning from '~SvRef'
97 pTransferObj->SetDragSource( this ); // copies selection
98
99 SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->SetDragObject( nullptr, pTransferObj.get() ); // for internal D&D
100 pTransferObj->StartDrag( pWindow, DND_ACTION_COPYMOVEcss::datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE | DND_ACTION_LINKcss::datatransfer::dnd::DNDConstants::ACTION_LINK );
101}
16
Calling '~SvRef'
102
103namespace {
104
105void getRangeFromDataSource( uno::Reference< chart2::data::XDataSource > const & xDataSource, std::vector<OUString>& rRangeRep)
106{
107 const uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence> > xSeqs = xDataSource->getDataSequences();
108 for (const uno::Reference<chart2::data::XLabeledDataSequence>& xLS : xSeqs)
109 {
110 uno::Reference<chart2::data::XDataSequence> xSeq = xLS->getValues();
111 if (xSeq.is())
112 {
113 OUString aRep = xSeq->getSourceRangeRepresentation();
114 rRangeRep.push_back(aRep);
115 }
116 xSeq = xLS->getLabel();
117 if (xSeq.is())
118 {
119 OUString aRep = xSeq->getSourceRangeRepresentation();
120 rRangeRep.push_back(aRep);
121 }
122 }
123}
124
125void getRangeFromErrorBar(const uno::Reference< chart2::XChartDocument >& rChartDoc, std::vector<OUString>& rRangeRep)
126{
127 uno::Reference <chart2::XDiagram > xDiagram = rChartDoc->getFirstDiagram();
128 if(!xDiagram.is())
129 return;
130
131 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY);
132 if(!xCooSysContainer.is())
133 return;
134
135 const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems());
136 for(const auto& rCooSys : xCooSysSequence)
137 {
138 uno::Reference< chart2::XChartTypeContainer > xChartTypeContainer( rCooSys, uno::UNO_QUERY);
139 if(!xChartTypeContainer.is())
140 continue;
141
142 const uno::Sequence< uno::Reference< chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() );
143 for(const auto& rChartType : xChartTypeSequence)
144 {
145 uno::Reference< chart2::XDataSeriesContainer > xDataSequenceContainer( rChartType, uno::UNO_QUERY);
146 if(!xDataSequenceContainer.is())
147 continue;
148
149 const uno::Sequence< uno::Reference< chart2::XDataSeries > > xSeriesSequence( xDataSequenceContainer->getDataSeries() );
150 for(const uno::Reference<chart2::XDataSeries>& xSeries : xSeriesSequence)
151 {
152 uno::Reference< beans::XPropertySet > xPropSet( xSeries, uno::UNO_QUERY);
153 uno::Reference< chart2::data::XDataSource > xErrorBarY;
154 xPropSet->getPropertyValue("ErrorBarY") >>= xErrorBarY;
155 if(xErrorBarY.is())
156 getRangeFromDataSource(xErrorBarY, rRangeRep);
157 uno::Reference< chart2::data::XDataSource > xErrorBarX;
158 xPropSet->getPropertyValue("ErrorBarX") >>= xErrorBarX;
159 if(xErrorBarX.is())
160 getRangeFromDataSource(xErrorBarX, rRangeRep);
161 }
162 }
163 }
164}
165
166void getRangeFromOle2Object(const SdrOle2Obj& rObj, std::vector<OUString>& rRangeRep)
167{
168 if (!rObj.IsChart())
169 // not a chart object.
170 return;
171
172 const uno::Reference<embed::XEmbeddedObject>& xObj = rObj.GetObjRef();
173 if (!xObj.is())
174 return;
175
176 uno::Reference<chart2::XChartDocument> xChartDoc(xObj->getComponent(), uno::UNO_QUERY);
177 if (!xChartDoc.is())
178 return;
179
180 if(xChartDoc->hasInternalDataProvider())
181 return;
182
183 getRangeFromErrorBar(xChartDoc, rRangeRep);
184
185 uno::Reference<chart2::data::XDataSource> xDataSource(xChartDoc, uno::UNO_QUERY);
186 if (!xDataSource.is())
187 return;
188
189 // Get all data sources used in this chart.
190 getRangeFromDataSource(xDataSource, rRangeRep);
191
192 return;
193}
194
195// Get all cell ranges that are referenced by the selected chart objects.
196void getOleSourceRanges(const SdrMarkList& rMarkList, bool& rAnyOle, bool& rOneOle, std::vector<ScRange>* pRanges = nullptr, const ScDocument* pDoc = nullptr )
197{
198 bool bCalcSourceRanges = pRanges && pDoc;
199 std::vector<OUString> aRangeReps;
200 rAnyOle = rOneOle = false;
201 const size_t nCount = rMarkList.GetMarkCount();
202 for (size_t i=0; i<nCount; ++i)
203 {
204 SdrMark* pMark = rMarkList.GetMark(i);
205 if ( !pMark )
206 continue;
207
208 SdrObject* pObj = pMark->GetMarkedSdrObj();
209 if ( !pObj )
210 continue;
211
212 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
213 if (nSdrObjKind == OBJ_OLE2)
214 {
215 rAnyOle = true;
216 rOneOle = (nCount == 1);
217 if ( bCalcSourceRanges )
218 getRangeFromOle2Object( static_cast<const SdrOle2Obj&>( *pObj ), aRangeReps );
219 else
220 break;
221 }
222 else if ( dynamic_cast<const SdrObjGroup*>( pObj) != nullptr )
223 {
224 SdrObjListIter aIter( *pObj, SdrIterMode::DeepNoGroups );
225 SdrObject* pSubObj = aIter.Next();
226 while (pSubObj)
227 {
228 if ( pSubObj->GetObjIdentifier() == OBJ_OLE2 )
229 {
230 rAnyOle = true;
231 // rOneOle remains false - a group isn't treated like a single OLE object
232 if ( !bCalcSourceRanges )
233 return;
234
235 getRangeFromOle2Object( static_cast<const SdrOle2Obj&>( *pSubObj ), aRangeReps );
236 }
237 pSubObj = aIter.Next();
238 }
239 }
240 }
241
242 if (!bCalcSourceRanges)
243 return;
244
245 // Compile all range representation strings into ranges.
246 for (const auto& rRangeRep : aRangeReps)
247 {
248 ScRangeList aRange;
249 ScAddress aAddr;
250 if (aRange.Parse(rRangeRep, *pDoc, pDoc->GetAddressConvention()) & ScRefFlags::VALID)
251 {
252 for(size_t i = 0; i < aRange.size(); ++i)
253 pRanges->push_back(aRange[i]);
254 }
255 else if (aAddr.Parse(rRangeRep, *pDoc, pDoc->GetAddressConvention()) & ScRefFlags::VALID)
256 pRanges->push_back(aAddr);
257 }
258
259 return;
260}
261
262class InsertTabIndex
263{
264 std::vector<SCTAB>& mrTabs;
265public:
266 explicit InsertTabIndex(std::vector<SCTAB>& rTabs) : mrTabs(rTabs) {}
267 void operator() (const ScRange& rRange)
268 {
269 mrTabs.push_back(rRange.aStart.Tab());
270 }
271};
272
273class CopyRangeData
274{
275 ScDocument& mrSrc;
276 ScDocument& mrDest;
277public:
278 CopyRangeData(ScDocument& rSrc, ScDocument& rDest) : mrSrc(rSrc), mrDest(rDest) {}
279
280 void operator() (const ScRange& rRange)
281 {
282 OUString aTabName;
283 mrSrc.GetName(rRange.aStart.Tab(), aTabName);
284
285 SCTAB nTab;
286 if (!mrDest.GetTable(aTabName, nTab))
287 // Sheet by this name doesn't exist.
288 return;
289
290 mrSrc.CopyStaticToDocument(rRange, nTab, mrDest);
291 }
292};
293
294void copyChartRefDataToClipDoc(ScDocument& rSrcDoc, ScDocument& rClipDoc, const std::vector<ScRange>& rRanges)
295{
296 // Get a list of referenced table indices.
297 std::vector<SCTAB> aTabs;
298 std::for_each(rRanges.begin(), rRanges.end(), InsertTabIndex(aTabs));
299 std::sort(aTabs.begin(), aTabs.end());
300 aTabs.erase(std::unique(aTabs.begin(), aTabs.end()), aTabs.end());
301
302 // Get table names.
303 if (aTabs.empty())
304 return;
305
306 // Create sheets only for referenced source sheets.
307 OUString aName;
308 std::vector<SCTAB>::const_iterator it = aTabs.begin(), itEnd = aTabs.end();
309 if (!rSrcDoc.GetName(*it, aName))
310 return;
311
312 rClipDoc.SetTabNameOnLoad(0, aName); // document initially has one sheet.
313
314 for (++it; it != itEnd; ++it)
315 {
316 if (!rSrcDoc.GetName(*it, aName))
317 return;
318
319 rClipDoc.AppendTabOnLoad(aName);
320 }
321
322 std::for_each(rRanges.begin(), rRanges.end(), CopyRangeData(rSrcDoc, rClipDoc));
323}
324
325}
326
327void ScDrawView::CheckOle( const SdrMarkList& rMarkList, bool& rAnyOle, bool& rOneOle )
328{
329 getOleSourceRanges( rMarkList, rAnyOle, rOneOle );
330}
331
332void ScDrawView::DoCopy()
333{
334 const SdrMarkList& rMarkList = GetMarkedObjectList();
335 std::vector<ScRange> aRanges;
336 bool bAnyOle = false, bOneOle = false;
337 getOleSourceRanges( rMarkList, bAnyOle, bOneOle, &aRanges, &rDoc );
338
339 // update ScGlobal::xDrawClipDocShellRef
340 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
341 if (ScGlobal::xDrawClipDocShellRef.is() && !aRanges.empty())
342 {
343 // Copy data referenced by the chart objects to the draw clip
344 // document. We need to do this before CreateMarkedObjModel() below.
345 ScDocShellRef xDocSh = ScGlobal::xDrawClipDocShellRef;
346 ScDocument& rClipDoc = xDocSh->GetDocument();
347 copyChartRefDataToClipDoc(rDoc, rClipDoc, aRanges);
348 }
349 std::unique_ptr<SdrModel> pModel(CreateMarkedObjModel());
350 ScDrawLayer::SetGlobalDrawPersist(nullptr);
351
352 // Charts now always copy their data in addition to the source reference, so
353 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
354 // Update with the data (including NumberFormatter) from the live document would
355 // also store the NumberFormatter in the clipboard chart (#88749#)
356
357 ScDocShell* pDocSh = pViewData->GetDocShell();
358
359 TransferableObjectDescriptor aObjDesc;
360 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
361 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
362 // maSize is set in ScDrawTransferObj ctor
363
364 rtl::Reference<ScDrawTransferObj> pTransferObj(new ScDrawTransferObj( std::move(pModel), pDocSh, aObjDesc ));
365
366 if ( ScGlobal::xDrawClipDocShellRef.is() )
367 {
368 pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef.get() ); // keep persist for ole objects alive
369 }
370
371 pTransferObj->CopyToClipboard( pViewData->GetActiveWin() ); // system clipboard
372}
373
374uno::Reference<datatransfer::XTransferable> ScDrawView::CopyToTransferable()
375{
376 bool bAnyOle, bOneOle;
377 const SdrMarkList& rMarkList = GetMarkedObjectList();
378 CheckOle( rMarkList, bAnyOle, bOneOle );
379
380 // update ScGlobal::xDrawClipDocShellRef
381 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
382 std::unique_ptr<SdrModel> pModel( CreateMarkedObjModel() );
383 ScDrawLayer::SetGlobalDrawPersist(nullptr);
384
385 // Charts now always copy their data in addition to the source reference, so
386 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
387 // Update with the data (including NumberFormatter) from the live document would
388 // also store the NumberFormatter in the clipboard chart (#88749#)
389 // lcl_RefreshChartData( pModel, pViewData->GetDocument() );
390
391 ScDocShell* pDocSh = pViewData->GetDocShell();
392
393 TransferableObjectDescriptor aObjDesc;
394 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
395 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
396 // maSize is set in ScDrawTransferObj ctor
397
398 ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( std::move(pModel), pDocSh, aObjDesc );
399 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
400
401 if ( ScGlobal::xDrawClipDocShellRef.is() )
402 {
403 pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef.get() ); // keep persist for ole objects alive
404 }
405
406 return xTransferable;
407}
408
409// Calculate correction for 100%, regardless of current settings
410
411void ScDrawView::CalcNormScale( Fraction& rFractX, Fraction& rFractY ) const
412{
413 double nPPTX = ScGlobal::nScreenPPTX;
414 double nPPTY = ScGlobal::nScreenPPTY;
415
416 if (pViewData)
417 nPPTX /= pViewData->GetDocShell()->GetOutputFactor();
418
419 SCCOL nEndCol = 0;
420 SCROW nEndRow = 0;
421 rDoc.GetTableArea( nTab, nEndCol, nEndRow );
422 if (nEndCol<20)
423 nEndCol = 20;
424 if (nEndRow<20)
425 nEndRow = 1000;
426
427 Fraction aZoom(1,1);
428 ScDrawUtil::CalcScale( rDoc, nTab, 0,0, nEndCol,nEndRow, pDev, aZoom,aZoom,
429 nPPTX, nPPTY, rFractX,rFractY );
430}
431
432void ScDrawView::SetMarkedOriginalSize()
433{
434 std::unique_ptr<SdrUndoGroup> pUndoGroup(new SdrUndoGroup(*GetModel()));
435
436 const SdrMarkList& rMarkList = GetMarkedObjectList();
437 long nDone = 0;
438 const size_t nCount = rMarkList.GetMarkCount();
439 for (size_t i=0; i<nCount; ++i)
440 {
441 SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
442 sal_uInt16 nIdent = pObj->GetObjIdentifier();
443 bool bDo = false;
444 Size aOriginalSize;
445 if (nIdent == OBJ_OLE2)
446 {
447 // TODO/LEAN: working with visual area can switch object to running state
448 uno::Reference < embed::XEmbeddedObject > xObj = static_cast<SdrOle2Obj*>(pObj)->GetObjRef();
449 if ( xObj.is() ) // NULL for an invalid object that couldn't be loaded
450 {
451 sal_Int64 nAspect = static_cast<SdrOle2Obj*>(pObj)->GetAspect();
452
453 if ( nAspect == embed::Aspects::MSOLE_ICON )
454 {
455 MapMode aMapMode( MapUnit::Map100thMM );
456 aOriginalSize = static_cast<SdrOle2Obj*>(pObj)->GetOrigObjSize( &aMapMode );
457 bDo = true;
458 }
459 else
460 {
461 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( static_cast<SdrOle2Obj*>(pObj)->GetAspect() ) );
462 try
463 {
464 awt::Size aSz = xObj->getVisualAreaSize( static_cast<SdrOle2Obj*>(pObj)->GetAspect() );
465 aOriginalSize = OutputDevice::LogicToLogic(
466 Size( aSz.Width, aSz.Height ),
467 MapMode(aUnit),
468 MapMode(MapUnit::Map100thMM));
469 bDo = true;
470 } catch( embed::NoVisualAreaSizeException& )
471 {
472 OSL_ENSURE( false, "Can't get the original size of the object!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "472" ": "), "%s", "Can't get the original size of the object!"
); } } while (false)
;
473 }
474 }
475 }
476 }
477 else if (nIdent == OBJ_GRAF)
478 {
479 const Graphic& rGraphic = static_cast<SdrGrafObj*>(pObj)->GetGraphic();
480
481 MapMode aSourceMap = rGraphic.GetPrefMapMode();
482 MapMode aDestMap( MapUnit::Map100thMM );
483 if (aSourceMap.GetMapUnit() == MapUnit::MapPixel)
484 {
485 // consider pixel correction, so that the bitmap is correct on the screen
486 Fraction aNormScaleX, aNormScaleY;
487 CalcNormScale( aNormScaleX, aNormScaleY );
488 aDestMap.SetScaleX(aNormScaleX);
489 aDestMap.SetScaleY(aNormScaleY);
490 }
491 if (pViewData)
492 {
493 vcl::Window* pActWin = pViewData->GetActiveWin();
494 if (pActWin)
495 {
496 aOriginalSize = pActWin->LogicToLogic(
497 rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
498 bDo = true;
499 }
500 }
501 }
502
503 if ( bDo )
504 {
505 tools::Rectangle aDrawRect = pObj->GetLogicRect();
506
507 pUndoGroup->AddAction( std::make_unique<SdrUndoGeoObj>( *pObj ) );
508 pObj->Resize( aDrawRect.TopLeft(), Fraction( aOriginalSize.Width(), aDrawRect.GetWidth() ),
509 Fraction( aOriginalSize.Height(), aDrawRect.GetHeight() ) );
510 ++nDone;
511 }
512 }
513
514 if (nDone && pViewData)
515 {
516 pUndoGroup->SetComment(ScResId( STR_UNDO_ORIGINALSIZEreinterpret_cast<char const *>("STR_UNDO_ORIGINALSIZE" "\004"
u8"Original Size")
));
517 ScDocShell* pDocSh = pViewData->GetDocShell();
518 pDocSh->GetUndoManager()->AddUndoAction(std::move(pUndoGroup));
519 pDocSh->SetDrawModified();
520 }
521}
522
523void ScDrawView::FitToCellSize()
524{
525 const SdrMarkList& rMarkList = GetMarkedObjectList();
526
527 if (rMarkList.GetMarkCount() != 1)
528 {
529 SAL_WARN("sc.ui", "Fit to cell only works with one graphic!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fit to cell only works with one graphic!") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui")
, ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "529" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Fit to cell only works with one graphic!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Fit to cell only works with one graphic!"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "529" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fit to cell only works with one graphic!") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui")
, ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "529" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Fit to cell only works with one graphic!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Fit to cell only works with one graphic!"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "529" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
530 return;
531 }
532
533 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
534
535 ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType(*pObj);
536 if (aAnchorType != SCA_CELL && aAnchorType != SCA_CELL_RESIZE)
537 {
538 SAL_WARN("sc.ui", "Fit to cell only works with cell anchored graphics!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fit to cell only works with cell anchored graphics!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"
), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "538" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Fit to cell only works with cell anchored graphics!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Fit to cell only works with cell anchored graphics!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"
), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "538" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fit to cell only works with cell anchored graphics!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"
), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "538" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Fit to cell only works with cell anchored graphics!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Fit to cell only works with cell anchored graphics!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"
), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "538" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
539 return;
540 }
541
542 ScDrawObjData* pObjData = ScDrawLayer::GetObjData(pObj);
543 if (!pObjData)
544 {
545 SAL_WARN("sc.ui", "Missing ScDrawObjData!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc.ui")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Missing ScDrawObjData!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "545" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Missing ScDrawObjData!"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Missing ScDrawObjData!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "545" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Missing ScDrawObjData!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "545" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Missing ScDrawObjData!"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Missing ScDrawObjData!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc.ui"), ("/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
":" "545" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
546 return;
547 }
548
549 std::unique_ptr<SdrUndoGroup> pUndoGroup(new SdrUndoGroup(*GetModel()));
550 tools::Rectangle aGraphicRect = pObj->GetSnapRect();
551 tools::Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, pObjData->maStart, true);
552
553 // For graphic objects, we want to keep the aspect ratio
554 if (pObj->shouldKeepAspectRatio())
555 {
556 long nWidth = aGraphicRect.GetWidth();
557 assert(nWidth && "div-by-zero")(static_cast <bool> (nWidth && "div-by-zero") ?
void (0) : __assert_fail ("nWidth && \"div-by-zero\""
, "/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
, 557, __extension__ __PRETTY_FUNCTION__))
;
558 double fScaleX = static_cast<double>(aCellRect.GetWidth()) / static_cast<double>(nWidth);
559 long nHeight = aGraphicRect.GetHeight();
560 assert(nHeight && "div-by-zero")(static_cast <bool> (nHeight && "div-by-zero") ?
void (0) : __assert_fail ("nHeight && \"div-by-zero\""
, "/home/maarten/src/libreoffice/core/sc/source/ui/view/drawvie4.cxx"
, 560, __extension__ __PRETTY_FUNCTION__))
;
561 double fScaleY = static_cast<double>(aCellRect.GetHeight()) / static_cast<double>(nHeight);
562 double fScaleMin = std::min(fScaleX, fScaleY);
563
564 aCellRect.setWidth(static_cast<double>(aGraphicRect.GetWidth()) * fScaleMin);
565 aCellRect.setHeight(static_cast<double>(aGraphicRect.GetHeight()) * fScaleMin);
566 }
567
568 pUndoGroup->AddAction( std::make_unique<SdrUndoGeoObj>( *pObj ) );
569 if (pObj->GetObjIdentifier() == OBJ_CUSTOMSHAPE)
570 pObj->AdjustToMaxRect(aCellRect);
571 else
572 pObj->SetSnapRect(aCellRect);
573
574 pUndoGroup->SetComment(ScResId( STR_UNDO_FITCELLSIZEreinterpret_cast<char const *>("STR_UNDO_FITCELLSIZE" "\004"
u8"Fit to Cell Size")
));
575 ScDocShell* pDocSh = pViewData->GetDocShell();
576 pDocSh->GetUndoManager()->AddUndoAction(std::move(pUndoGroup));
577
578}
579
580/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/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#ifndef INCLUDED_TOOLS_REF_HXX
20#define INCLUDED_TOOLS_REF_HXX
21
22#include <sal/config.h>
23#include <cassert>
24#include <tools/toolsdllapi.h>
25#include <utility>
26
27/**
28 This implements similar functionality to boost::intrusive_ptr
29*/
30
31namespace tools {
32
33/** T must be a class that extends SvRefBase */
34template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final {
35public:
36 SvRef(): pObj(nullptr) {}
37
38 SvRef(SvRef&& rObj) noexcept
39 {
40 pObj = rObj.pObj;
41 rObj.pObj = nullptr;
42 }
43
44 SvRef(SvRef const & rObj): pObj(rObj.pObj)
45 {
46 if (pObj != nullptr) pObj->AddNextRef();
47 }
48
49 SvRef(T * pObjP): pObj(pObjP)
50 {
51 if (pObj != nullptr) pObj->AddFirstRef();
52 }
53
54 ~SvRef()
55 {
56 if (pObj != nullptr) pObj->ReleaseRef();
6
Taking true branch
7
Calling 'SvRefBase::ReleaseRef'
14
Returning; memory was released
17
Taking true branch
18
Use of memory after it is freed
57 }
58
59 void clear()
60 {
61 if (pObj != nullptr) {
62 T * pRefObj = pObj;
63 pObj = nullptr;
64 pRefObj->ReleaseRef();
65 }
66 }
67
68 SvRef & operator =(SvRef const & rObj)
69 {
70 if (rObj.pObj != nullptr) {
71 rObj.pObj->AddNextRef();
72 }
73 T * pRefObj = pObj;
74 pObj = rObj.pObj;
75 if (pRefObj != nullptr) {
76 pRefObj->ReleaseRef();
77 }
78 return *this;
79 }
80
81 SvRef & operator =(SvRef && rObj)
82 {
83 if (pObj != nullptr) {
84 pObj->ReleaseRef();
85 }
86 pObj = rObj.pObj;
87 rObj.pObj = nullptr;
88 return *this;
89 }
90
91 bool is() const { return pObj != nullptr; }
92
93 explicit operator bool() const { return is(); }
94
95 T * get() const { return pObj; }
96
97 T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 97, __extension__ __PRETTY_FUNCTION__))
; return pObj; }
98
99 T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 99, __extension__ __PRETTY_FUNCTION__))
; return *pObj; }
100
101 bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; }
102 bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); }
103
104private:
105 T * pObj;
106};
107
108/**
109 * This implements similar functionality to std::make_shared.
110 */
111template<typename T, typename... Args>
112SvRef<T> make_ref(Args&& ... args)
113{
114 return SvRef<T>(new T(std::forward<Args>(args)...));
115}
116
117}
118
119/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */
120class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase
121{
122 // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
123 // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
124 unsigned int nRefCount : 31;
125 // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
126 unsigned int bNoDelete : 1;
127
128protected:
129 virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE;
130
131public:
132 SvRefBase() : nRefCount(0), bNoDelete(1) {}
133 SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {}
134
135 SvRefBase & operator=(const SvRefBase &) { return *this; }
136
137 void RestoreNoDelete()
138 { bNoDelete = 1; }
139
140 void AddNextRef()
141 {
142 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
142, __extension__ __PRETTY_FUNCTION__))
;
143 ++nRefCount;
144 }
145
146 void AddFirstRef()
147 {
148 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
148, __extension__ __PRETTY_FUNCTION__))
;
149 if( bNoDelete )
150 bNoDelete = 0;
151 ++nRefCount;
152 }
153
154 void ReleaseRef()
155 {
156 assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail
("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 156, __extension__ __PRETTY_FUNCTION__))
;
8
Assuming field 'nRefCount' is >= 1
9
'?' condition is true
157 if( --nRefCount == 0 && !bNoDelete)
10
Assuming the condition is true
11
Assuming field 'bNoDelete' is 0
12
Taking true branch
158 {
159 // I'm not sure about the original purpose of this line, but right now
160 // it serves the purpose that anything that attempts to do an AddRef()
161 // after an object is deleted will trip an assert.
162 nRefCount = 1 << 30;
163 delete this;
13
Memory is released
164 }
165 }
166
167 unsigned int GetRefCount() const
168 { return nRefCount; }
169};
170
171template<typename T>
172class SvCompatWeakBase;
173
174/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T.
175*/
176template<typename T>
177class SvCompatWeakHdl final : public SvRefBase
178{
179 friend class SvCompatWeakBase<T>;
180 T* _pObj;
181
182 SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
183
184public:
185 void ResetWeakBase( ) { _pObj = nullptr; }
186 T* GetObj() { return _pObj; }
187};
188
189/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame.
190 Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted.
191*/
192template<typename T>
193class SvCompatWeakBase
194{
195 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
196
197public:
198 /** Does not use initializer due to compiler warnings,
199 because the lifetime of the _xHdl object can exceed the lifetime of this class.
200 */
201 SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); }
202
203 ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); }
204
205 SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); }
206};
207
208/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak.
209*/
210template<typename T>
211class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef
212{
213 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
214public:
215 SvCompatWeakRef( ) {}
216 SvCompatWeakRef( T* pObj )
217 { if( pObj ) _xHdl = pObj->GetHdl(); }
218#if defined(__COVERITY__)
219 ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {}
220#endif
221 SvCompatWeakRef& operator = ( T * pObj )
222 { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; }
223 bool is() const
224 { return _xHdl.is() && _xHdl->GetObj(); }
225 explicit operator bool() const { return is(); }
226 T* operator -> () const
227 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
228 operator T* () const
229 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
230};
231
232#endif
233
234/* vim:set shiftwidth=4 softtabstop=4 expandtab: */