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 documen8.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/core/data/documen8.cxx

/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.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 <scitems.hxx>
21#include <comphelper/fileformat.h>
22#include <comphelper/processfactory.hxx>
23#include <comphelper/servicehelper.hxx>
24#include <officecfg/Office/Common.hxx>
25#include <tools/urlobj.hxx>
26#include <editeng/editobj.hxx>
27#include <editeng/frmdiritem.hxx>
28#include <editeng/langitem.hxx>
29#include <sfx2/linkmgr.hxx>
30#include <sfx2/bindings.hxx>
31#include <sfx2/objsh.hxx>
32#include <sfx2/printer.hxx>
33#include <sfx2/viewfrm.hxx>
34#include <sfx2/viewsh.hxx>
35#include <svl/flagitem.hxx>
36#include <svl/intitem.hxx>
37#include <svl/zforlist.hxx>
38#include <svl/zformat.hxx>
39#include <unotools/transliterationwrapper.hxx>
40#include <sal/log.hxx>
41
42#include <vcl/svapp.hxx>
43#include <vcl/virdev.hxx>
44#include <vcl/weld.hxx>
45#include <vcl/TaskStopwatch.hxx>
46
47#include <inputopt.hxx>
48#include <global.hxx>
49#include <table.hxx>
50#include <column.hxx>
51#include <poolhelp.hxx>
52#include <docpool.hxx>
53#include <stlpool.hxx>
54#include <stlsheet.hxx>
55#include <docoptio.hxx>
56#include <viewopti.hxx>
57#include <scextopt.hxx>
58#include <rechead.hxx>
59#include <ddelink.hxx>
60#include <scmatrix.hxx>
61#include <arealink.hxx>
62#include <patattr.hxx>
63#include <editutil.hxx>
64#include <progress.hxx>
65#include <document.hxx>
66#include <chartlis.hxx>
67#include <chartlock.hxx>
68#include <refupdat.hxx>
69#include <markdata.hxx>
70#include <scmod.hxx>
71#include <externalrefmgr.hxx>
72#include <globstr.hrc>
73#include <strings.hrc>
74#include <sc.hrc>
75#include <charthelper.hxx>
76#include <macromgr.hxx>
77#include <docuno.hxx>
78#include <scresid.hxx>
79#include <columniterator.hxx>
80#include <globalnames.hxx>
81#include <stringutil.hxx>
82#include <documentlinkmgr.hxx>
83#include <scopetools.hxx>
84#include <tokenarray.hxx>
85
86#include <memory>
87#include <utility>
88
89using namespace com::sun::star;
90
91namespace {
92
93sal_uInt16 getScaleValue(SfxStyleSheetBase& rStyle, sal_uInt16 nWhich)
94{
95 return static_cast<const SfxUInt16Item&>(rStyle.GetItemSet().Get(nWhich)).GetValue();
96}
97
98}
99
100void ScDocument::ImplCreateOptions()
101{
102 pDocOptions.reset( new ScDocOptions() );
103 pViewOptions.reset( new ScViewOptions() );
104}
105
106void ScDocument::ImplDeleteOptions()
107{
108 pDocOptions.reset();
109 pViewOptions.reset();
110 pExtDocOptions.reset();
111}
112
113SfxPrinter* ScDocument::GetPrinter(bool bCreateIfNotExist)
114{
115 if ( !mpPrinter && bCreateIfNotExist )
116 {
117 auto pSet =
118 std::make_unique<SfxItemSet>( *mxPoolHelper->GetDocPool(),
119 svl::Items<SID_PRINTER_NOTFOUND_WARN(5000 + 320), SID_PRINTER_NOTFOUND_WARN(5000 + 320),
120 SID_PRINTER_CHANGESTODOC(5000 + 324), SID_PRINTER_CHANGESTODOC(5000 + 324),
121 SID_PRINT_SELECTEDSHEET(5000 + 1712), SID_PRINT_SELECTEDSHEET(5000 + 1712),
122 SID_SCPRINTOPTIONS((26000) + 68), SID_SCPRINTOPTIONS((26000) + 68)>{} );
123
124 SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
125 if (officecfg::Office::Common::Print::Warning::PaperOrientation::get())
126 nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
127 if (officecfg::Office::Common::Print::Warning::PaperSize::get())
128 nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
129 pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC(5000 + 324), static_cast<int>(nFlags) ) );
130 pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN(5000 + 320), officecfg::Office::Common::Print::Warning::NotFound::get() ) );
131
132 mpPrinter = VclPtr<SfxPrinter>::Create( std::move(pSet) );
133 mpPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
134 UpdateDrawPrinter();
135 mpPrinter->SetDigitLanguage( SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->GetOptDigitLanguage() );
136 }
137
138 return mpPrinter;
139}
140
141void ScDocument::SetPrinter( VclPtr<SfxPrinter> const & pNewPrinter )
142{
143 if ( pNewPrinter == mpPrinter.get() )
1
Taking false branch
144 {
145 // #i6706# SetPrinter is called with the same printer again if
146 // the JobSetup has changed. In that case just call UpdateDrawPrinter
147 // (SetRefDevice for drawing layer) because of changed text sizes.
148 UpdateDrawPrinter();
149 }
150 else
151 {
152 ScopedVclPtr<SfxPrinter> xKeepAlive( mpPrinter );
2
Calling constructor for 'ScopedVclPtr<SfxPrinter>'
9
Returning from constructor for 'ScopedVclPtr<SfxPrinter>'
153 mpPrinter = pNewPrinter;
154 UpdateDrawPrinter();
155 mpPrinter->SetDigitLanguage( SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->GetOptDigitLanguage() );
156 }
10
Calling '~ScopedVclPtr'
157 InvalidateTextWidth(nullptr, nullptr, false); // in both cases
158}
159
160void ScDocument::SetPrintOptions()
161{
162 if ( !mpPrinter ) GetPrinter(); // this sets mpPrinter
163 OSL_ENSURE( mpPrinter, "Error in printer creation :-/" )do { if (true && (!(mpPrinter))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "163" ": "), "%s", "Error in printer creation :-/"); } }
while (false)
;
164
165 if ( !mpPrinter )
166 return;
167
168 SfxItemSet aOptSet( mpPrinter->GetOptions() );
169
170 SfxPrinterChangeFlags nFlags = SfxPrinterChangeFlags::NONE;
171 if (officecfg::Office::Common::Print::Warning::PaperOrientation::get())
172 nFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
173 if (officecfg::Office::Common::Print::Warning::PaperSize::get())
174 nFlags |= SfxPrinterChangeFlags::CHG_SIZE;
175 aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC(5000 + 324), static_cast<int>(nFlags) ) );
176 aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN(5000 + 320), officecfg::Office::Common::Print::Warning::NotFound::get() ) );
177
178 mpPrinter->SetOptions( aOptSet );
179}
180
181VirtualDevice* ScDocument::GetVirtualDevice_100th_mm()
182{
183 if (!mpVirtualDevice_100th_mm)
184 {
185#ifdef IOS
186 mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::GRAYSCALE);
187#else
188 mpVirtualDevice_100th_mm = VclPtr<VirtualDevice>::Create(DeviceFormat::BITMASK);
189#endif
190 mpVirtualDevice_100th_mm->SetReferenceDevice(VirtualDevice::RefDevMode::MSO1);
191 MapMode aMapMode( mpVirtualDevice_100th_mm->GetMapMode() );
192 aMapMode.SetMapUnit( MapUnit::Map100thMM );
193 mpVirtualDevice_100th_mm->SetMapMode( aMapMode );
194 }
195 return mpVirtualDevice_100th_mm;
196}
197
198OutputDevice* ScDocument::GetRefDevice()
199{
200 // Create printer like ref device, see Writer...
201 OutputDevice* pRefDevice = nullptr;
202 if ( SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->GetInputOptions().GetTextWysiwyg() )
203 pRefDevice = GetPrinter();
204 else
205 pRefDevice = GetVirtualDevice_100th_mm();
206 return pRefDevice;
207}
208
209void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
210 const SfxItemSet& rChanges )
211{
212 SfxItemSet& rSet = rStyleSheet.GetItemSet();
213
214 switch ( rStyleSheet.GetFamily() )
215 {
216 case SfxStyleFamily::Page:
217 {
218 const sal_uInt16 nOldScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
219 const sal_uInt16 nOldScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
220 rSet.Put( rChanges );
221 const sal_uInt16 nNewScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
222 const sal_uInt16 nNewScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
223
224 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
225 InvalidateTextWidth( rStyleSheet.GetName() );
226
227 if( SvtLanguageOptions().IsCTLFontEnabled() )
228 {
229 const SfxPoolItem *pItem = nullptr;
230 if( rChanges.GetItemState(ATTR_WRITINGDIR, true, &pItem ) == SfxItemState::SET )
231 ScChartHelper::DoUpdateAllCharts( *this );
232 }
233 }
234 break;
235
236 case SfxStyleFamily::Para:
237 {
238 bool bNumFormatChanged;
239 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
240 rSet, rChanges ) )
241 InvalidateTextWidth( nullptr, nullptr, bNumFormatChanged );
242
243 for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab)
244 if (maTabs[nTab])
245 maTabs[nTab]->SetStreamValid( false );
246
247 sal_uLong nOldFormat =
248 rSet.Get( ATTR_VALUE_FORMAT ).GetValue();
249 sal_uLong nNewFormat =
250 rChanges.Get( ATTR_VALUE_FORMAT ).GetValue();
251 LanguageType eNewLang, eOldLang;
252 eNewLang = eOldLang = LANGUAGE_DONTKNOWLanguageType(0x03FF);
253 if ( nNewFormat != nOldFormat )
254 {
255 SvNumberFormatter* pFormatter = GetFormatTable();
256 eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
257 eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
258 }
259
260 // Explanation to Items in rChanges:
261 // Set Item - take over change
262 // Dontcare - Set Default
263 // Default - No change
264 // ("no change" is not possible with PutExtended, thus the loop)
265 for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
266 {
267 const SfxPoolItem* pItem;
268 SfxItemState eState = rChanges.GetItemState( nWhich, false, &pItem );
269 if ( eState == SfxItemState::SET )
270 rSet.Put( *pItem );
271 else if ( eState == SfxItemState::DONTCARE )
272 rSet.ClearItem( nWhich );
273 // when Default nothing
274 }
275
276 if ( eNewLang != eOldLang )
277 rSet.Put(
278 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
279 }
280 break;
281 default:
282 {
283 // added to avoid warnings
284 }
285 }
286}
287
288void ScDocument::CopyStdStylesFrom( const ScDocument& rSrcDoc )
289{
290 // number format exchange list has to be handled here, too
291 NumFmtMergeHandler aNumFmtMergeHdl(*this, rSrcDoc);
292 mxPoolHelper->GetStylePool()->CopyStdStylesFrom( rSrcDoc.mxPoolHelper->GetStylePool() );
293}
294
295void ScDocument::InvalidateTextWidth( const OUString& rStyleName )
296{
297 const SCTAB nCount = GetTableCount();
298 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
299 if ( maTabs[i]->GetPageStyle() == rStyleName )
300 InvalidateTextWidth( i );
301}
302
303void ScDocument::InvalidateTextWidth( SCTAB nTab )
304{
305 ScAddress aAdrFrom( 0, 0, nTab );
306 ScAddress aAdrTo ( MaxCol(), MaxRow(), nTab );
307 InvalidateTextWidth( &aAdrFrom, &aAdrTo, false );
308}
309
310bool ScDocument::IsPageStyleInUse( const OUString& rStrPageStyle, SCTAB* pInTab )
311{
312 bool bInUse = false;
313 const SCTAB nCount = GetTableCount();
314 SCTAB i;
315
316 for ( i = 0; !bInUse && i < nCount && maTabs[i]; i++ )
317 bInUse = ( maTabs[i]->GetPageStyle() == rStrPageStyle );
318
319 if ( pInTab )
320 *pInTab = i-1;
321
322 return bInUse;
323}
324
325bool ScDocument::RemovePageStyleInUse( const OUString& rStyle )
326{
327 bool bWasInUse = false;
328 const SCTAB nCount = GetTableCount();
329
330 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
331 if ( maTabs[i]->GetPageStyle() == rStyle )
332 {
333 bWasInUse = true;
334 maTabs[i]->SetPageStyle( ScResId(STR_STYLENAME_STANDARD_PAGEreinterpret_cast<char const *>("STR_STYLENAME_STANDARD"
"\004" u8"Default Page Style")
) );
335 }
336
337 return bWasInUse;
338}
339
340bool ScDocument::RenamePageStyleInUse( const OUString& rOld, const OUString& rNew )
341{
342 bool bWasInUse = false;
343 const SCTAB nCount = GetTableCount();
344
345 for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
346 if ( maTabs[i]->GetPageStyle() == rOld )
347 {
348 bWasInUse = true;
349 maTabs[i]->SetPageStyle( rNew );
350 }
351
352 return bWasInUse;
353}
354
355EEHorizontalTextDirection ScDocument::GetEditTextDirection(SCTAB nTab) const
356{
357 EEHorizontalTextDirection eRet = EEHorizontalTextDirection::Default;
358
359 OUString aStyleName = GetPageStyle( nTab );
360 SfxStyleSheetBase* pStyle = mxPoolHelper->GetStylePool()->Find( aStyleName, SfxStyleFamily::Page );
361 if ( pStyle )
362 {
363 SfxItemSet& rStyleSet = pStyle->GetItemSet();
364 SvxFrameDirection eDirection =
365 rStyleSet.Get( ATTR_WRITINGDIR ).GetValue();
366
367 if ( eDirection == SvxFrameDirection::Horizontal_LR_TB )
368 eRet = EEHorizontalTextDirection::L2R;
369 else if ( eDirection == SvxFrameDirection::Horizontal_RL_TB )
370 eRet = EEHorizontalTextDirection::R2L;
371 // else (invalid for EditEngine): keep "default"
372 }
373
374 return eRet;
375}
376
377ScMacroManager* ScDocument::GetMacroManager()
378{
379 if (!mpMacroMgr)
380 mpMacroMgr.reset(new ScMacroManager(*this));
381 return mpMacroMgr.get();
382}
383
384void ScDocument::FillMatrix(
385 ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, svl::SharedStringPool* pPool ) const
386{
387 const ScTable* pTab = FetchTable(nTab);
388 if (!pTab)
389 return;
390
391 if (nCol1 > nCol2 || nRow1 > nRow2)
392 return;
393
394 SCSIZE nC, nR;
395 rMat.GetDimensions(nC, nR);
396 if (static_cast<SCROW>(nR) != nRow2 - nRow1 + 1 || static_cast<SCCOL>(nC) != nCol2 - nCol1 + 1)
397 return;
398
399 pTab->FillMatrix(rMat, nCol1, nRow1, nCol2, nRow2, pPool);
400}
401
402void ScDocument::SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen )
403{
404 ScTable* pTab = FetchTable(rTopPos.Tab());
405 if (!pTab)
406 return;
407
408 pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
409}
410
411const ScDocumentThreadSpecific& ScDocument::CalculateInColumnInThread( ScInterpreterContext& rContext, const ScRange& rCalcRange, unsigned nThisThread, unsigned nThreadsTotal)
412{
413 ScTable* pTab = FetchTable(rCalcRange.aStart.Tab());
414 if (!pTab)
415 return maNonThreaded;
416
417 assert(IsThreadedGroupCalcInProgress())(static_cast <bool> (IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("IsThreadedGroupCalcInProgress()",
"/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
, 417, __extension__ __PRETTY_FUNCTION__))
;
418
419 maThreadSpecific.pContext = &rContext;
420 ScDocumentThreadSpecific::SetupFromNonThreadedData(maNonThreaded);
421 pTab->CalculateInColumnInThread(rContext, rCalcRange.aStart.Col(), rCalcRange.aEnd.Col(), rCalcRange.aStart.Row(), rCalcRange.aEnd.Row(), nThisThread, nThreadsTotal);
422
423 assert(IsThreadedGroupCalcInProgress())(static_cast <bool> (IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("IsThreadedGroupCalcInProgress()",
"/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
, 423, __extension__ __PRETTY_FUNCTION__))
;
424 maThreadSpecific.pContext = nullptr;
425
426 return maThreadSpecific;
427}
428
429void ScDocument::HandleStuffAfterParallelCalculation( SCCOL nColStart, SCCOL nColEnd, SCROW nRow, size_t nLen, SCTAB nTab, ScInterpreter* pInterpreter )
430{
431 assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
, 431, __extension__ __PRETTY_FUNCTION__))
;
432 for( const DelayedSetNumberFormat& data : GetNonThreadedContext().maDelayedSetNumberFormat)
433 SetNumberFormat( ScAddress( data.mCol, data.mRow, nTab ), data.mnNumberFormat );
434 GetNonThreadedContext().maDelayedSetNumberFormat.clear();
435
436 ScTable* pTab = FetchTable(nTab);
437 if (!pTab)
438 return;
439
440 pTab->HandleStuffAfterParallelCalculation(nColStart, nColEnd, nRow, nLen, pInterpreter);
441}
442
443void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
444 bool bNumFormatChanged )
445{
446 bool bBroadcast = (bNumFormatChanged && GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
447 if ( pAdrFrom && !pAdrTo )
448 {
449 const SCTAB nTab = pAdrFrom->Tab();
450
451 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
452 maTabs[nTab]->InvalidateTextWidth( pAdrFrom, nullptr, bNumFormatChanged, bBroadcast );
453 }
454 else
455 {
456 const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
457 const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
458
459 for ( SCTAB nTab=nTabStart; nTab<=nTabEnd && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
460 if ( maTabs[nTab] )
461 maTabs[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bNumFormatChanged, bBroadcast );
462 }
463}
464
465#define CALCMAX1000 1000 // Calculations
466
467namespace {
468
469class IdleCalcTextWidthScope : public TaskStopwatch
470{
471 ScDocument& mrDoc;
472 ScAddress& mrCalcPos;
473 MapMode maOldMapMode;
474 ScStyleSheetPool* mpStylePool;
475 bool mbNeedMore;
476 bool mbProgress;
477
478public:
479 IdleCalcTextWidthScope(ScDocument& rDoc, ScAddress& rCalcPos) :
480 mrDoc(rDoc),
481 mrCalcPos(rCalcPos),
482 mpStylePool(rDoc.GetStyleSheetPool()),
483 mbNeedMore(false),
484 mbProgress(false)
485 {
486 mrDoc.EnableIdle(false);
487 }
488
489 ~IdleCalcTextWidthScope() COVERITY_NOEXCEPT_FALSE
490 {
491 SfxPrinter* pDev = mrDoc.GetPrinter();
492 if (pDev)
493 pDev->SetMapMode(maOldMapMode);
494
495 if (mbProgress)
496 ScProgress::DeleteInterpretProgress();
497
498 mrDoc.EnableIdle(true);
499 }
500
501 SCTAB Tab() const { return mrCalcPos.Tab(); }
502 SCCOL Col() const { return mrCalcPos.Col(); }
503 SCROW Row() const { return mrCalcPos.Row(); }
504
505 void setTab(SCTAB nTab) { mrCalcPos.SetTab(nTab); }
506 void setCol(SCCOL nCol) { mrCalcPos.SetCol(nCol); }
507 void setRow(SCROW nRow) { mrCalcPos.SetRow(nRow); }
508
509 void incTab() { mrCalcPos.IncTab(); }
510 void incCol(SCCOL nInc) { mrCalcPos.IncCol(nInc); }
511
512 void setOldMapMode(const MapMode& rOldMapMode) { maOldMapMode = rOldMapMode; }
513
514 void setNeedMore(bool b) { mbNeedMore = b; }
515 bool getNeedMore() const { return mbNeedMore; }
516
517 void createProgressBar()
518 {
519 ScProgress::CreateInterpretProgress(&mrDoc, false);
520 mbProgress = true;
521 }
522
523 bool hasProgressBar() const { return mbProgress; }
524
525 ScStyleSheetPool* getStylePool() { return mpStylePool; }
526};
527
528}
529
530bool ScDocument::IdleCalcTextWidth() // true = try next again
531{
532 // #i75610# if a printer hasn't been set or created yet, don't create one for this
533 if (!mbIdleEnabled || IsInLinkUpdate() || GetPrinter(false) == nullptr)
534 return false;
535
536 IdleCalcTextWidthScope aScope(*this, aCurTextWidthCalcPos);
537
538 if (!ValidRow(aScope.Row()))
539 {
540 aScope.setRow(0);
541 aScope.incCol(-1);
542 }
543
544 if (aScope.Col() < 0)
545 {
546 aScope.setCol(MaxCol());
547 aScope.incTab();
548 }
549
550 if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()])
551 aScope.setTab(0);
552
553 ScTable* pTab = maTabs[aScope.Tab()].get();
554 ScStyleSheet* pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(pTab->aPageStyle, SfxStyleFamily::Page));
555 OSL_ENSURE( pStyle, "Missing StyleSheet :-/" )do { if (true && (!(pStyle))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "555" ": "), "%s", "Missing StyleSheet :-/"); } } while (
false)
;
556
557 if (!pStyle || getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
558 {
559 // Move to the next sheet as the current one has scale-to-pages set,
560 // and bail out.
561 aScope.incTab();
562 return false;
563 }
564
565 sal_uInt16 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
566 Fraction aZoomFract(nZoom, 100);
567
568 aScope.setCol(pTab->ClampToAllocatedColumns(aScope.Col()));
569 // Start at specified cell position (nCol, nRow, nTab).
570 ScColumn* pCol = &pTab->aCol[aScope.Col()];
571 std::unique_ptr<ScColumnTextWidthIterator> pColIter(new ScColumnTextWidthIterator(*this, *pCol, aScope.Row(), MaxRow()));
572
573 OutputDevice* pDev = nullptr;
574 sal_uInt16 nRestart = 0;
575 sal_uInt16 nCount = 0;
576 while ( (nZoom > 0) && (nCount < CALCMAX1000) && (nRestart < 2) )
577 {
578 if (pColIter->hasCell())
579 {
580 // More cell in this column.
581 SCROW nRow = pColIter->getPos();
582 aScope.setRow(nRow);
583
584 if (pColIter->getValue() == TEXTWIDTH_DIRTY0xffff)
585 {
586 // Calculate text width for this cell.
587 double nPPTX = 0.0;
588 double nPPTY = 0.0;
589 if (!pDev)
590 {
591 pDev = GetPrinter();
592 aScope.setOldMapMode(pDev->GetMapMode());
593 pDev->SetMapMode(MapMode(MapUnit::MapPixel)); // Important for GetNeededSize
594
595 Point aPix1000 = pDev->LogicToPixel(Point(1000,1000), MapMode(MapUnit::MapTwip));
596 nPPTX = aPix1000.X() / 1000.0;
597 nPPTY = aPix1000.Y() / 1000.0;
598 }
599
600 if (!aScope.hasProgressBar() && pCol->IsFormulaDirty(nRow))
601 aScope.createProgressBar();
602
603 sal_uInt16 nNewWidth = static_cast<sal_uInt16>(GetNeededSize(
604 aScope.Col(), aScope.Row(), aScope.Tab(),
605 pDev, nPPTX, nPPTY, aZoomFract,aZoomFract, true, true)); // bTotalSize
606
607 pColIter->setValue(nNewWidth);
608 aScope.setNeedMore(true);
609 }
610 pColIter->next();
611 }
612 else
613 {
614 // No more cell in this column. Move to the left column and start at row 0.
615
616 bool bNewTab = false;
617
618 aScope.setRow(0);
619 aScope.incCol(-1);
620
621 if (aScope.Col() < 0)
622 {
623 // No more column to the left. Move to the right-most column of the next sheet.
624 aScope.setCol(MaxCol());
625 aScope.incTab();
626 bNewTab = true;
627 }
628
629 if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()] )
630 {
631 // Sheet doesn't exist at specified sheet position. Restart at sheet 0.
632 aScope.setTab(0);
633 nRestart++;
634 bNewTab = true;
635 }
636
637 if ( nRestart < 2 )
638 {
639 if ( bNewTab )
640 {
641 pTab = maTabs[aScope.Tab()].get();
642 aScope.setCol(pTab->ClampToAllocatedColumns(aScope.Col()));
643 pStyle = static_cast<ScStyleSheet*>(aScope.getStylePool()->Find(
644 pTab->aPageStyle, SfxStyleFamily::Page));
645
646 if ( pStyle )
647 {
648 // Check if the scale-to-pages setting is set. If
649 // set, we exit the loop. If not, get the page
650 // scale factor of the new sheet.
651 if (getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
652 {
653 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
654 aZoomFract = Fraction(nZoom, 100);
655 }
656 else
657 nZoom = 0;
658 }
659 else
660 {
661 OSL_FAIL( "Missing StyleSheet :-/" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "661" ": "), "%s", "Missing StyleSheet :-/"); } } while (
false)
;
662 }
663 }
664
665 if ( nZoom > 0 )
666 {
667 pCol = &pTab->aCol[aScope.Col()];
668 pColIter.reset(new ScColumnTextWidthIterator(*this, *pCol, aScope.Row(), MaxRow()));
669 }
670 else
671 {
672 aScope.incTab(); // Move to the next sheet as the current one has scale-to-pages set.
673 return false;
674 }
675 }
676 }
677
678 ++nCount;
679
680 if (!aScope.continueIter())
681 break;
682 }
683
684 return aScope.getNeedMore();
685}
686
687void ScDocument::RepaintRange( const ScRange& rRange )
688{
689 if ( bIsVisible && mpShell )
690 {
691 ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>( mpShell->GetModel() );
692 if ( pModel )
693 pModel->RepaintRange( rRange ); // locked repaints are checked there
694 }
695}
696
697void ScDocument::RepaintRange( const ScRangeList& rRange )
698{
699 if ( bIsVisible && mpShell )
700 {
701 ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>( mpShell->GetModel() );
702 if ( pModel )
703 pModel->RepaintRange( rRange ); // locked repaints are checked there
704 }
705}
706
707void ScDocument::SaveDdeLinks(SvStream& rStream) const
708{
709 // when 4.0-Export, remove all with mode != DEFAULT
710 bool bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_403580 );
711
712 const ::sfx2::SvBaseLinks& rLinks = GetLinkManager()->GetLinks();
713 sal_uInt16 nCount = rLinks.size();
714
715 // Count them first
716
717 sal_uInt16 nDdeCount = 0;
718 sal_uInt16 i;
719 for (i=0; i<nCount; i++)
720 {
721 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
722 if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
723 if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
724 ++nDdeCount;
725 }
726
727 // Header
728
729 ScMultipleWriteHeader aHdr( rStream );
730 rStream.WriteUInt16( nDdeCount );
731
732 // Save links
733
734 for (i=0; i<nCount; i++)
735 {
736 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
737 if (ScDdeLink* pLink = dynamic_cast<ScDdeLink*>(pBase))
738 {
739 if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
740 pLink->Store( rStream, aHdr );
741 }
742 }
743}
744
745void ScDocument::LoadDdeLinks(SvStream& rStream)
746{
747 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
748 if (!pMgr)
749 return;
750
751 ScMultipleReadHeader aHdr( rStream );
752
753 sal_uInt16 nCount(0);
754 rStream.ReadUInt16( nCount );
755
756 const rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
757 const size_t nMinStringSize = eCharSet == RTL_TEXTENCODING_UNICODE(((rtl_TextEncoding) 0xFFFF)) ? sizeof(sal_uInt32) : sizeof(sal_uInt16);
758 const size_t nMinRecordSize = 1 + nMinStringSize*3;
759 const size_t nMaxRecords = rStream.remainingSize() / nMinRecordSize;
760 if (nCount > nMaxRecords)
761 {
762 SAL_WARN("sc", "Parsing error: " << nMaxRecords <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
763 " max possible entries, but " << nCount << " claimed, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "763" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
764 nCount = nMaxRecords;
765 }
766
767 for (sal_uInt16 i=0; i<nCount; ++i)
768 {
769 ScDdeLink* pLink = new ScDdeLink( *this, rStream, aHdr );
770 pMgr->InsertDDELink(pLink, pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem());
771 }
772}
773
774void ScDocument::SetInLinkUpdate(bool bSet)
775{
776 // called from TableLink and AreaLink
777
778 OSL_ENSURE( bInLinkUpdate != bSet, "SetInLinkUpdate twice" )do { if (true && (!(bInLinkUpdate != bSet))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "778" ": "), "%s", "SetInLinkUpdate twice"); } } while (
false)
;
779 bInLinkUpdate = bSet;
780}
781
782bool ScDocument::IsInLinkUpdate() const
783{
784 return bInLinkUpdate || IsInDdeLinkUpdate();
785}
786
787void ScDocument::UpdateExternalRefLinks(weld::Window* pWin)
788{
789 if (!pExternalRefMgr)
790 return;
791
792 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
793 if (!pMgr)
794 return;
795
796 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
797 sal_uInt16 nCount = rLinks.size();
798
799 bool bAny = false;
800
801 // Collect all the external ref links first.
802 std::vector<ScExternalRefLink*> aRefLinks;
803 for (sal_uInt16 i = 0; i < nCount; ++i)
804 {
805 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
806 ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
807 if (pRefLink)
808 aRefLinks.push_back(pRefLink);
809 }
810
811 weld::WaitObject aWaitSwitch(pWin);
812
813 pExternalRefMgr->enableDocTimer(false);
814 ScProgress aProgress(GetDocumentShell(), ScResId(SCSTR_UPDATE_EXTDOCSreinterpret_cast<char const *>("SCSTR_UPDATE_EXTDOCS" "\004"
u8"Updating external links.")
), aRefLinks.size(), true);
815 for (size_t i = 0, n = aRefLinks.size(); i < n; ++i)
816 {
817 aProgress.SetState(i+1);
818
819 ScExternalRefLink* pRefLink = aRefLinks[i];
820 if (pRefLink->Update())
821 {
822 bAny = true;
823 continue;
824 }
825
826 // Update failed. Notify the user.
827
828 OUString aFile;
829 sfx2::LinkManager::GetDisplayNames(pRefLink, nullptr, &aFile);
830 // Decode encoded URL for display friendliness.
831 INetURLObject aUrl(aFile,INetURLObject::EncodeMechanism::WasEncoded);
832 aFile = aUrl.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
833
834 OUString sMessage = ScResId(SCSTR_EXTDOC_NOT_LOADEDreinterpret_cast<char const *>("SCSTR_EXTDOC_NOT_LOADED"
"\004" u8"The following external file could not be loaded. Data linked from this file did not get updated."
)
) +
835 "\n\n" +
836 aFile;
837 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin,
838 VclMessageType::Warning, VclButtonsType::Ok,
839 sMessage));
840 xBox->run();
841 }
842
843 pExternalRefMgr->enableDocTimer(true);
844
845 if (!bAny)
846 return;
847
848 TrackFormulas();
849 mpShell->Broadcast( SfxHint(SfxHintId::ScDataChanged) );
850
851 // #i101960# set document modified, as in TrackTimeHdl for DDE links
852 if (!mpShell->IsModified())
853 {
854 mpShell->SetModified();
855 SfxBindings* pBindings = GetViewBindings();
856 if (pBindings)
857 {
858 pBindings->Invalidate( SID_SAVEDOC(5000 + 505) );
859 pBindings->Invalidate( SID_DOC_MODIFIED(5000 + 584) );
860 }
861 }
862}
863
864void ScDocument::CopyDdeLinks( ScDocument& rDestDoc ) const
865{
866 if (bIsClip) // Create from Stream
867 {
868 if (pClipData)
869 {
870 pClipData->Seek(0);
871 rDestDoc.LoadDdeLinks(*pClipData);
872 }
873
874 return;
875 }
876
877 const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
878 if (!pMgr)
879 return;
880
881 sfx2::LinkManager* pDestMgr = rDestDoc.GetDocLinkManager().getLinkManager(rDestDoc.bAutoCalc);
882 if (!pDestMgr)
883 return;
884
885 const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
886 for (const auto & rLink : rLinks)
887 {
888 const sfx2::SvBaseLink* pBase = rLink.get();
889 if (const ScDdeLink* p = dynamic_cast<const ScDdeLink*>(pBase))
890 {
891 ScDdeLink* pNew = new ScDdeLink(rDestDoc, *p);
892 pDestMgr->InsertDDELink(
893 pNew, pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem());
894 }
895 }
896}
897
898namespace {
899
900/** Tries to find the specified DDE link.
901 @param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
902 (does not include other links from link manager).
903 @return The DDE link, if it exists, otherwise 0. */
904ScDdeLink* lclGetDdeLink(
905 const sfx2::LinkManager* pLinkManager,
906 const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode,
907 size_t* pnDdePos = nullptr )
908{
909 if( pLinkManager )
910 {
911 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
912 size_t nCount = rLinks.size();
913 if( pnDdePos ) *pnDdePos = 0;
914 for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
915 {
916 ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
917 if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
918 {
919 if( (pDdeLink->GetAppl() == rAppl) &&
920 (pDdeLink->GetTopic() == rTopic) &&
921 (pDdeLink->GetItem() == rItem) &&
922 ((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
923 return pDdeLink;
924 if( pnDdePos ) ++*pnDdePos;
925 }
926 }
927 }
928 return nullptr;
929}
930
931/** Returns a pointer to the specified DDE link.
932 @param nDdePos Index of the DDE link (does not include other links from link manager).
933 @return The DDE link, if it exists, otherwise 0. */
934ScDdeLink* lclGetDdeLink( const sfx2::LinkManager* pLinkManager, size_t nDdePos )
935{
936 if( pLinkManager )
937 {
938 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
939 size_t nCount = rLinks.size();
940 size_t nDdeIndex = 0; // counts only the DDE links
941 for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
942 {
943 ::sfx2::SvBaseLink* pLink = rLinks[ nIndex ].get();
944 if( ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>( pLink ) )
945 {
946 if( nDdeIndex == nDdePos )
947 return pDdeLink;
948 ++nDdeIndex;
949 }
950 }
951 }
952 return nullptr;
953}
954
955} // namespace
956
957bool ScDocument::FindDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem,
958 sal_uInt8 nMode, size_t& rnDdePos )
959{
960 return lclGetDdeLink( GetLinkManager(), rAppl, rTopic, rItem, nMode, &rnDdePos ) != nullptr;
961}
962
963bool ScDocument::GetDdeLinkData( size_t nDdePos, OUString& rAppl, OUString& rTopic, OUString& rItem ) const
964{
965 if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
966 {
967 rAppl = pDdeLink->GetAppl();
968 rTopic = pDdeLink->GetTopic();
969 rItem = pDdeLink->GetItem();
970 return true;
971 }
972 return false;
973}
974
975bool ScDocument::GetDdeLinkMode( size_t nDdePos, sal_uInt8& rnMode ) const
976{
977 if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
978 {
979 rnMode = pDdeLink->GetMode();
980 return true;
981 }
982 return false;
983}
984
985const ScMatrix* ScDocument::GetDdeLinkResultMatrix( size_t nDdePos ) const
986{
987 const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos );
988 return pDdeLink ? pDdeLink->GetResult() : nullptr;
989}
990
991bool ScDocument::CreateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode, const ScMatrixRef& pResults )
992{
993 /* Create a DDE link without updating it (i.e. for Excel import), to prevent
994 unwanted connections. First try to find existing link. Set result array
995 on existing and new links. */
996 //TODO: store DDE links additionally at document (for efficiency)?
997 OSL_ENSURE( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" )do { if (true && (!(nMode != SC_DDE_IGNOREMODE))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "997" ": "), "%s", "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here"
); } } while (false)
;
998
999 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(bAutoCalc);
1000 if (!pMgr)
1001 return false;
1002
1003 if (nMode != SC_DDE_IGNOREMODE)
1004 {
1005 ScDdeLink* pDdeLink = lclGetDdeLink(pMgr, rAppl, rTopic, rItem, nMode);
1006 if( !pDdeLink )
1007 {
1008 // create a new DDE link, but without TryUpdate
1009 pDdeLink = new ScDdeLink( *this, rAppl, rTopic, rItem, nMode );
1010 pMgr->InsertDDELink(pDdeLink, rAppl, rTopic, rItem);
1011 }
1012
1013 // insert link results
1014 if( pResults )
1015 pDdeLink->SetResult( pResults );
1016
1017 return true;
1018 }
1019 return false;
1020}
1021
1022bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos, const ScMatrixRef& pResults )
1023{
1024 if( ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1025 {
1026 pDdeLink->SetResult( pResults );
1027 return true;
1028 }
1029 return false;
1030}
1031
1032bool ScDocument::HasAreaLinks() const
1033{
1034 const sfx2::LinkManager* pMgr = GetDocLinkManager().getExistingLinkManager();
1035 if (!pMgr)
1036 return false;
1037
1038 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1039 sal_uInt16 nCount = rLinks.size();
1040 for (sal_uInt16 i=0; i<nCount; i++)
1041 if (nullptr != dynamic_cast<const ScAreaLink* >(rLinks[i].get()))
1042 return true;
1043
1044 return false;
1045}
1046
1047void ScDocument::UpdateAreaLinks()
1048{
1049 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1050 if (!pMgr)
1051 return;
1052
1053 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1054 for (const auto & rLink : rLinks)
1055 {
1056 ::sfx2::SvBaseLink* pBase = rLink.get();
1057 if (dynamic_cast<const ScAreaLink*>( pBase) != nullptr)
1058 pBase->Update();
1059 }
1060}
1061
1062void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab )
1063{
1064 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1065 if (!pMgr)
1066 return;
1067
1068 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1069 sfx2::SvBaseLinks::size_type nPos = 0;
1070 while ( nPos < rLinks.size() )
1071 {
1072 const ::sfx2::SvBaseLink* pBase = rLinks[nPos].get();
1073 const ScAreaLink* pLink = dynamic_cast<const ScAreaLink*>(pBase);
1074 if (pLink && pLink->GetDestArea().aStart.Tab() == nTab)
1075 pMgr->Remove(nPos);
1076 else
1077 ++nPos;
1078 }
1079}
1080
1081void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
1082 const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz )
1083{
1084 sfx2::LinkManager* pMgr = GetDocLinkManager().getLinkManager(false);
1085 if (!pMgr)
1086 return;
1087
1088 bool bAnyUpdate = false;
1089
1090 const ::sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
1091 sal_uInt16 nCount = rLinks.size();
1092 for (sal_uInt16 i=0; i<nCount; i++)
1093 {
1094 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
1095 if (ScAreaLink* pLink = dynamic_cast<ScAreaLink*>(pBase))
1096 {
1097 ScRange aOutRange = pLink->GetDestArea();
1098
1099 SCCOL nCol1 = aOutRange.aStart.Col();
1100 SCROW nRow1 = aOutRange.aStart.Row();
1101 SCTAB nTab1 = aOutRange.aStart.Tab();
1102 SCCOL nCol2 = aOutRange.aEnd.Col();
1103 SCROW nRow2 = aOutRange.aEnd.Row();
1104 SCTAB nTab2 = aOutRange.aEnd.Tab();
1105
1106 ScRefUpdateRes eRes =
1107 ScRefUpdate::Update( this, eUpdateRefMode,
1108 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1109 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1110 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1111 if ( eRes != UR_NOTHING )
1112 {
1113 pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1114 bAnyUpdate = true;
1115 }
1116 }
1117 }
1118
1119 if ( !bAnyUpdate )
1120 return;
1121
1122 // #i52120# Look for duplicates (after updating all positions).
1123 // If several links start at the same cell, the one with the lower index is removed
1124 // (file format specifies only one link definition for a cell).
1125
1126 sal_uInt16 nFirstIndex = 0;
1127 while ( nFirstIndex < nCount )
1128 {
1129 bool bFound = false;
1130 ::sfx2::SvBaseLink* pFirst = rLinks[nFirstIndex].get();
1131 if (ScAreaLink* pFirstLink = dynamic_cast<ScAreaLink*>(pFirst))
1132 {
1133 ScAddress aFirstPos = pFirstLink->GetDestArea().aStart;
1134 for ( sal_uInt16 nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
1135 {
1136 ::sfx2::SvBaseLink* pSecond = rLinks[nSecondIndex].get();
1137 ScAreaLink* pSecondLink = dynamic_cast<ScAreaLink*>(pSecond);
1138 if (pSecondLink && pSecondLink->GetDestArea().aStart == aFirstPos)
1139 {
1140 // remove the first link, exit the inner loop, don't increment nFirstIndex
1141 pMgr->Remove(pFirst);
1142 nCount = rLinks.size();
1143 bFound = true;
1144 }
1145 }
1146 }
1147 if (!bFound)
1148 ++nFirstIndex;
1149 }
1150}
1151
1152void ScDocument::CheckLinkFormulaNeedingCheck( const ScTokenArray& rCode )
1153{
1154 if (HasLinkFormulaNeedingCheck())
1155 return;
1156
1157 // Prefer RPN over tokenized formula if available.
1158 if (rCode.GetCodeLen())
1159 {
1160 if (rCode.HasOpCodeRPN(ocDde) || rCode.HasOpCodeRPN(ocWebservice))
1161 SetLinkFormulaNeedingCheck(true);
1162 }
1163 else if (rCode.GetLen())
1164 {
1165 if (rCode.HasOpCode(ocDde) || rCode.HasOpCode(ocWebservice))
1166 SetLinkFormulaNeedingCheck(true);
1167 }
1168 else
1169 {
1170 // Possible with named expression without expression like Excel
1171 // internal print ranges, obscure user define names, ... formula error
1172 // cells without formula ...
1173 SAL_WARN("sc.core","ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sc.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "1173" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "1173" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "1173" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ScDocument::CheckLinkFormulaNeedingCheck - called with empty ScTokenArray"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "1173" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1174 }
1175}
1176
1177// TimerDelays etc.
1178void ScDocument::KeyInput()
1179{
1180 if ( pChartListenerCollection->hasListeners() )
1181 pChartListenerCollection->StartTimer();
1182 if (apTemporaryChartLock)
1183 apTemporaryChartLock->StartOrContinueLocking();
1184}
1185
1186SfxBindings* ScDocument::GetViewBindings()
1187{
1188 // used to invalidate slots after changes to this document
1189
1190 if ( !mpShell )
1191 return nullptr; // no ObjShell -> no view
1192
1193 // first check current view
1194 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1195 if ( pViewFrame && pViewFrame->GetObjectShell() != mpShell ) // wrong document?
1196 pViewFrame = nullptr;
1197
1198 // otherwise use first view for this doc
1199 if ( !pViewFrame )
1200 pViewFrame = SfxViewFrame::GetFirst( mpShell );
1201
1202 if (pViewFrame)
1203 return &pViewFrame->GetBindings();
1204 else
1205 return nullptr;
1206}
1207
1208void ScDocument::TransliterateText( const ScMarkData& rMultiMark, TransliterationFlags nType )
1209{
1210 OSL_ENSURE( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" )do { if (true && (!(rMultiMark.IsMultiMarked()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen8.cxx"
":" "1210" ": "), "%s", "TransliterateText: no selection"); }
} while (false)
;
1211
1212 utl::TransliterationWrapper aTransliterationWrapper( comphelper::getProcessComponentContext(), nType );
1213 bool bConsiderLanguage = aTransliterationWrapper.needLanguageForTheMode();
1214 LanguageType nLanguage = LANGUAGE_SYSTEMLanguageType(0x0000);
1215
1216 std::unique_ptr<ScEditEngineDefaulter> pEngine; // not using mpEditEngine member because of defaults
1217
1218 SCTAB nCount = GetTableCount();
1219 for (const SCTAB& nTab : rMultiMark)
1220 {
1221 if (nTab >= nCount)
1222 break;
1223
1224 if ( maTabs[nTab] )
1225 {
1226 SCCOL nCol = 0;
1227 SCROW nRow = 0;
1228
1229 bool bFound = rMultiMark.IsCellMarked( nCol, nRow );
1230 if (!bFound)
1231 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1232
1233 while (bFound)
1234 {
1235 ScRefCellValue aCell(*this, ScAddress(nCol, nRow, nTab));
1236
1237 // fdo#32786 TITLE_CASE/SENTENCE_CASE need the extra handling in EditEngine (loop over words/sentences).
1238 // Still use TransliterationWrapper directly for text cells with other transliteration types,
1239 // for performance reasons.
1240 if (aCell.meType == CELLTYPE_EDIT ||
1241 (aCell.meType == CELLTYPE_STRING &&
1242 ( nType == TransliterationFlags::SENTENCE_CASE || nType == TransliterationFlags::TITLE_CASE)))
1243 {
1244 if (!pEngine)
1245 pEngine.reset(new ScFieldEditEngine(this, GetEnginePool(), GetEditPool()));
1246
1247 // defaults from cell attributes must be set so right language is used
1248 const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
1249 std::unique_ptr<SfxItemSet> pDefaults(new SfxItemSet( pEngine->GetEmptyItemSet() ));
1250 if ( ScStyleSheet* pPreviewStyle = GetPreviewCellStyle( nCol, nRow, nTab ) )
1251 {
1252 std::unique_ptr<ScPatternAttr> pPreviewPattern(new ScPatternAttr( *pPattern ));
1253 pPreviewPattern->SetStyleSheet(pPreviewStyle);
1254 pPreviewPattern->FillEditItemSet( pDefaults.get() );
1255 }
1256 else
1257 {
1258 SfxItemSet* pFontSet = GetPreviewFont( nCol, nRow, nTab );
1259 pPattern->FillEditItemSet( pDefaults.get(), pFontSet );
1260 }
1261 pEngine->SetDefaults( std::move(pDefaults) );
1262 if (aCell.meType == CELLTYPE_STRING)
1263 pEngine->SetTextCurrentDefaults(aCell.mpString->getString());
1264 else if (aCell.mpEditText)
1265 pEngine->SetTextCurrentDefaults(*aCell.mpEditText);
1266
1267 pEngine->ClearModifyFlag();
1268
1269 sal_Int32 nLastPar = pEngine->GetParagraphCount();
1270 if (nLastPar)
1271 --nLastPar;
1272 sal_Int32 nTxtLen = pEngine->GetTextLen(nLastPar);
1273 ESelection aSelAll( 0, 0, nLastPar, nTxtLen );
1274
1275 pEngine->TransliterateText( aSelAll, nType );
1276
1277 if ( pEngine->IsModified() )
1278 {
1279 ScEditAttrTester aTester( pEngine.get() );
1280 if ( aTester.NeedsObject() )
1281 {
1282 // remove defaults (paragraph attributes) before creating text object
1283 pEngine->SetDefaults( std::make_unique<SfxItemSet>( pEngine->GetEmptyItemSet() ) );
1284
1285 // The cell will take ownership of the text object instance.
1286 SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
1287 }
1288 else
1289 {
1290 ScSetStringParam aParam;
1291 aParam.setTextInput();
1292 SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
1293 }
1294 }
1295 }
1296
1297 else if (aCell.meType == CELLTYPE_STRING)
1298 {
1299 OUString aOldStr = aCell.mpString->getString();
1300 sal_Int32 nOldLen = aOldStr.getLength();
1301
1302 if ( bConsiderLanguage )
1303 {
1304 SvtScriptType nScript = GetStringScriptType( aOldStr ); //TODO: cell script type?
1305 sal_uInt16 nWhich = ( nScript == SvtScriptType::ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
1306 ( ( nScript == SvtScriptType::COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE :
1307 ATTR_FONT_LANGUAGE );
1308 nLanguage = static_cast<const SvxLanguageItem*>(GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
1309 }
1310
1311 uno::Sequence<sal_Int32> aOffsets;
1312 OUString aNewStr = aTransliterationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
1313
1314 if ( aNewStr != aOldStr )
1315 {
1316 ScSetStringParam aParam;
1317 aParam.setTextInput();
1318 SetString(ScAddress(nCol,nRow,nTab), aNewStr, &aParam);
1319 }
1320 }
1321 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1322 }
1323 }
1324 }
1325}
1326
1327/* 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 ;-)
12
Calling 'Reference::clear'
19
Returning; memory was released
205 if (aTmp.get()) {
20
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)
3
Calling implicit copy constructor for 'VclPtr<SfxPrinter>'
4
Calling copy constructor for 'Reference<SfxPrinter>'
7
Returning from copy constructor for 'Reference<SfxPrinter>'
8
Returning from copy constructor for 'VclPtr<SfxPrinter>'
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();
11
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 )
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)
5
Assuming field 'm_pBody' is non-null
6
Taking true branch
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
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
12.1
Field 'm_pBody' is non-null
)
13
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
14
Calling 'VclReferenceBase::release'
18
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;
21
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)
15
Assuming the condition is true
16
Taking true branch
40 delete this;
17
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