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 documen2.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/documen2.cxx

/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.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 <scextopt.hxx>
21#include <autonamecache.hxx>
22
23#include <o3tl/safeint.hxx>
24#include <osl/thread.h>
25#include <svx/xtable.hxx>
26#include <sfx2/bindings.hxx>
27#include <sfx2/objsh.hxx>
28#include <sfx2/docfile.hxx>
29#include <sfx2/printer.hxx>
30#include <svl/asiancfg.hxx>
31#include <vcl/virdev.hxx>
32#include <svl/sharedstringpool.hxx>
33#include <tools/urlobj.hxx>
34#include <rtl/crc.h>
35#include <basic/basmgr.hxx>
36#include <comphelper/threadpool.hxx>
37#include <sal/log.hxx>
38
39#include <scmod.hxx>
40#include <document.hxx>
41#include <table.hxx>
42#include <patattr.hxx>
43#include <rangenam.hxx>
44#include <dbdata.hxx>
45#include <chartlock.hxx>
46#include <rechead.hxx>
47#include <global.hxx>
48#include <bcaslot.hxx>
49#include <adiasync.hxx>
50#include <addinlis.hxx>
51#include <chartlis.hxx>
52#include <markdata.hxx>
53#include <validat.hxx>
54#include <detdata.hxx>
55#include <defaultsoptions.hxx>
56#include <sc.hrc>
57#include <ddelink.hxx>
58#include <chgtrack.hxx>
59#include <chgviset.hxx>
60#include <editutil.hxx>
61#include <hints.hxx>
62#include <dpobject.hxx>
63#include <scrdata.hxx>
64#include <poolhelp.hxx>
65#include <unoreflist.hxx>
66#include <listenercalls.hxx>
67#include <recursionhelper.hxx>
68#include <lookupcache.hxx>
69#include <externalrefmgr.hxx>
70#include <viewdata.hxx>
71#include <viewutil.hxx>
72#include <tabprotection.hxx>
73#include <formulaparserpool.hxx>
74#include <clipparam.hxx>
75#include <macromgr.hxx>
76#include <formulacell.hxx>
77#include <clipcontext.hxx>
78#include <refupdatecontext.hxx>
79#include <refreshtimerprotector.hxx>
80#include <scopetools.hxx>
81#include <documentlinkmgr.hxx>
82#include <interpre.hxx>
83#include <tokenstringcontext.hxx>
84#include <docsh.hxx>
85#include <clipoptions.hxx>
86#include <listenercontext.hxx>
87#include <datamapper.hxx>
88#include <drwlayer.hxx>
89
90using namespace com::sun::star;
91
92const sal_uInt16 ScDocument::nSrcVer = SC_CURRENT_VERSION0x0205;
93
94static ScSheetLimits* CreateSheetLimits()
95{
96 const ScDefaultsOptions& rOpt = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->GetDefaultsOptions();
97 if (rOpt.GetInitJumboSheets())
98 return new ScSheetLimits(MAXCOL_JUMBO, MAXROW_JUMBO);
99 else
100 return new ScSheetLimits(MAXCOL, MAXROW);
101}
102
103ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) :
104 mpCellStringPool(std::make_shared<svl::SharedStringPool>(*ScGlobal::getCharClassPtr())),
105 mpDocLinkMgr(new sc::DocumentLinkManager(pDocShell)),
106 mbFormulaGroupCxtBlockDiscard(false),
107 maCalcConfig( ScInterpreter::GetGlobalConfig()),
108 mpUndoManager( nullptr ),
109 mpShell( pDocShell ),
110 mpPrinter( nullptr ),
111 mpVirtualDevice_100th_mm( nullptr ),
112 pFormatExchangeList( nullptr ),
113 mxSheetLimits(CreateSheetLimits()),
114 pFormulaTree( nullptr ),
115 pEOFormulaTree( nullptr ),
116 pFormulaTrack( nullptr ),
117 pEOFormulaTrack( nullptr ),
118 pPreviewCellStyle( nullptr ),
119 maPreviewSelection(*mxSheetLimits),
120 nUnoObjectId( 0 ),
121 nRangeOverflowType( 0 ),
122 aCurTextWidthCalcPos(MaxCol(),0,0),
123 nFormulaCodeInTree(0),
124 nXMLImportedFormulaCount( 0 ),
125 nInterpretLevel(0),
126 nMacroInterpretLevel(0),
127 nInterpreterTableOpLevel(0),
128 maInterpreterContext( *this, nullptr ),
129 nFormulaTrackCount(0),
130 eHardRecalcState(HardRecalcState::OFF),
131 nVisibleTab( 0 ),
132 nPosLeft( 0 ),
133 nPosTop( 0 ),
134 eLinkMode(LM_UNKNOWN),
135 bAutoCalc( eMode == SCDOCMODE_DOCUMENT || eMode == SCDOCMODE_FUNCTIONACCESS ),
136 bAutoCalcShellDisabled( false ),
137 bForcedFormulaPending( false ),
138 bCalculatingFormulaTree( false ),
139 bIsClip( eMode == SCDOCMODE_CLIP ),
140 bIsUndo( eMode == SCDOCMODE_UNDO ),
141 bIsFunctionAccess( eMode == SCDOCMODE_FUNCTIONACCESS ),
142 bIsVisible( false ),
143 bIsEmbedded( false ),
144 bInsertingFromOtherDoc( false ),
145 bLoadingMedium( false ),
146 bImportingXML( false ),
147 bCalcingAfterLoad( false ),
148 bNoListening( false ),
149 mbIdleEnabled(true),
150 bInLinkUpdate( false ),
151 bChartListenerCollectionNeedsUpdate( false ),
152 bHasForcedFormulas( false ),
153 bInDtorClear( false ),
154 bExpandRefs( false ),
155 bDetectiveDirty( false ),
156 bLinkFormulaNeedingCheck( false ),
157 nAsianCompression(CharCompressType::Invalid),
158 nAsianKerning(SC_ASIANKERNING_INVALID0xff),
159 bPastingDrawFromOtherDoc( false ),
160 nInDdeLinkUpdate( 0 ),
161 bInUnoBroadcast( false ),
162 bInUnoListenerCall( false ),
163 nAdjustHeightLock(0),
164 eGrammar( formula::FormulaGrammar::GRAM_NATIVE ),
165 bStyleSheetUsageInvalid( true ),
166 mbUndoEnabled( true ),
167 mbExecuteLinkEnabled( true ),
168 mbChangeReadOnlyEnabled( false ),
169 mbStreamValidLocked( false ),
170 mbUserInteractionEnabled(true),
171 mnNamedRangesLockCount(0),
172 mbEmbedFonts(false),
173 mbEmbedUsedFontsOnly(false),
174 mbEmbedFontScriptLatin(true),
175 mbEmbedFontScriptAsian(true),
176 mbEmbedFontScriptComplex(true),
177 mbTrackFormulasPending(false),
178 mbFinalTrackFormulas(false),
179 mbDocShellRecalc(false),
180 mnMutationGuardFlags(0)
181{
182 maPreviewSelection = { *mxSheetLimits };
183 aCurTextWidthCalcPos = { MaxCol(), 0, 0 };
184
185 SetStorageGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT);
186
187 eSrcSet = osl_getThreadTextEncoding();
188
189 /* TODO: for SCDOCMODE_FUNCTIONACCESS it might not even be necessary to
190 * have all of these available. */
191 if ( eMode == SCDOCMODE_DOCUMENT || eMode == SCDOCMODE_FUNCTIONACCESS )
192 {
193 mxPoolHelper = new ScPoolHelper( *this );
194
195 pBASM.reset( new ScBroadcastAreaSlotMachine( this ) );
196 pChartListenerCollection.reset( new ScChartListenerCollection( *this ) );
197 pRefreshTimerControl.reset( new ScRefreshTimerControl );
198 }
199 else
200 {
201 pChartListenerCollection = nullptr;
202 }
203 pDBCollection.reset( new ScDBCollection(*this) );
204 pSelectionAttr = nullptr;
205 apTemporaryChartLock.reset( new ScTemporaryChartLock(this) );
206 xColNameRanges = new ScRangePairList;
207 xRowNameRanges = new ScRangePairList;
208 ImplCreateOptions();
209 // languages for a visible document are set by docshell later (from options)
210 SetLanguage( ScGlobal::eLnge, ScGlobal::eLnge, ScGlobal::eLnge );
211
212 aTrackIdle.SetInvokeHandler( LINK( this, ScDocument, TrackTimeHdl )::tools::detail::makeLink( ::tools::detail::castTo<ScDocument
*>(this), &ScDocument::LinkStubTrackTimeHdl)
);
213}
214
215sfx2::LinkManager* ScDocument::GetLinkManager()
216{
217 return GetDocLinkManager().getLinkManager();
218}
219
220const sfx2::LinkManager* ScDocument::GetLinkManager() const
221{
222 return GetDocLinkManager().getExistingLinkManager();
223}
224
225sc::DocumentLinkManager& ScDocument::GetDocLinkManager()
226{
227 return *mpDocLinkMgr;
228}
229
230const sc::DocumentLinkManager& ScDocument::GetDocLinkManager() const
231{
232 return const_cast<ScDocument*>(this)->GetDocLinkManager();
233}
234
235void ScDocument::SetStorageGrammar( formula::FormulaGrammar::Grammar eGram )
236{
237 OSL_PRECOND(do { if (true && (!(eGram == formula::FormulaGrammar::
GRAM_ODFF || eGram == formula::FormulaGrammar::GRAM_PODF))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "240" ": "), "%s", "ScDocument::SetStorageGrammar: wrong storage grammar"
); } } while (false)
238 eGram == formula::FormulaGrammar::GRAM_ODFF ||do { if (true && (!(eGram == formula::FormulaGrammar::
GRAM_ODFF || eGram == formula::FormulaGrammar::GRAM_PODF))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "240" ": "), "%s", "ScDocument::SetStorageGrammar: wrong storage grammar"
); } } while (false)
239 eGram == formula::FormulaGrammar::GRAM_PODF,do { if (true && (!(eGram == formula::FormulaGrammar::
GRAM_ODFF || eGram == formula::FormulaGrammar::GRAM_PODF))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "240" ": "), "%s", "ScDocument::SetStorageGrammar: wrong storage grammar"
); } } while (false)
240 "ScDocument::SetStorageGrammar: wrong storage grammar")do { if (true && (!(eGram == formula::FormulaGrammar::
GRAM_ODFF || eGram == formula::FormulaGrammar::GRAM_PODF))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "240" ": "), "%s", "ScDocument::SetStorageGrammar: wrong storage grammar"
); } } while (false)
;
241
242 eStorageGrammar = eGram;
243}
244
245void ScDocument::SetDocVisible( bool bSet )
246{
247 // called from view ctor - only for a visible document,
248 // each new sheet's RTL flag is initialized from the locale
249 bIsVisible = bSet;
250}
251
252sal_uInt32 ScDocument::GetDocumentID() const
253{
254 const ScDocument* pThis = this;
255 sal_uInt32 nCrc = rtl_crc32( 0, &pThis, sizeof(ScDocument*) );
256 // the this pointer only might not be sufficient
257 nCrc = rtl_crc32( nCrc, &mpShell, sizeof(SfxObjectShell*) );
258 return nCrc;
259}
260
261void ScDocument::StartChangeTracking()
262{
263 if (!pChangeTrack)
264 pChangeTrack.reset( new ScChangeTrack( *this ) );
265}
266
267void ScDocument::EndChangeTracking()
268{
269 pChangeTrack.reset();
270}
271
272void ScDocument::SetChangeTrack( std::unique_ptr<ScChangeTrack> pTrack )
273{
274 OSL_ENSURE( &pTrack->GetDocument() == this, "SetChangeTrack: different documents" )do { if (true && (!(&pTrack->GetDocument() == this
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "274" ": "), "%s", "SetChangeTrack: different documents"
); } } while (false)
;
275 if ( !pTrack || pTrack == pChangeTrack || &pTrack->GetDocument() != this )
276 return ;
277 EndChangeTracking();
278 pChangeTrack = std::move(pTrack);
279}
280
281IMPL_LINK_NOARG(ScDocument, TrackTimeHdl, Timer *, void)void ScDocument::LinkStubTrackTimeHdl(void * instance, Timer *
data) { return static_cast<ScDocument *>(instance)->
TrackTimeHdl(data); } void ScDocument::TrackTimeHdl(__attribute__
((unused)) Timer *)
282{
283 if ( ScDdeLink::IsInUpdate() ) // do not nest
284 {
285 aTrackIdle.Start(); // try again later
286 }
287 else if (mpShell) // execute
288 {
289 TrackFormulas();
290 mpShell->Broadcast( SfxHint( SfxHintId::ScDataChanged ) );
291
292 if (!mpShell->IsModified())
293 {
294 mpShell->SetModified();
295 SfxBindings* pBindings = GetViewBindings();
296 if (pBindings)
297 {
298 pBindings->Invalidate( SID_SAVEDOC(5000 + 505) );
299 pBindings->Invalidate( SID_DOC_MODIFIED(5000 + 584) );
300 }
301 }
302 }
303}
304
305void ScDocument::SetExpandRefs( bool bVal )
306{
307 bExpandRefs = bVal;
308}
309
310void ScDocument::StartTrackTimer()
311{
312 if (!aTrackIdle.IsActive()) // do not postpone for forever
313 aTrackIdle.Start();
314}
315
316void ScDocument::ClosingClipboardSource()
317{
318 if (!bIsClip)
319 return;
320
321 ForgetNoteCaptions( ScRangeList( ScRange( 0,0,0, MaxCol(), MaxRow(), GetTableCount()-1)), true);
322}
323
324ScDocument::~ScDocument()
325{
326 OSL_PRECOND( !bInLinkUpdate, "bInLinkUpdate in dtor" )do { if (true && (!(!bInLinkUpdate))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "326" ": "), "%s", "bInLinkUpdate in dtor"); } } while (
false)
;
1
Assuming field 'bInLinkUpdate' is true
2
Taking true branch
3
Loop condition is false. Exiting loop
327
328 // Join any pending(recalc) threads in global threadpool
329 comphelper::ThreadPool::getSharedOptimalPool().joinAll();
330
331 bInDtorClear = true;
332
333 // first of all disable all refresh timers by deleting the control
334 if ( pRefreshTimerControl )
4
Taking true branch
335 { // To be sure there isn't anything running do it with a protector,
336 // this ensures also that nothing needs the control anymore.
337 ScRefreshTimerProtector aProt( GetRefreshTimerControlAddress() );
338 pRefreshTimerControl.reset();
339 }
340
341 mxFormulaParserPool.reset();
342 // Destroy the external ref mgr instance here because it has a timer
343 // which needs to be stopped before the app closes.
344 pExternalRefMgr.reset();
345
346 ScAddInAsync::RemoveDocument( this );
347 ScAddInListener::RemoveDocument( this );
348 pChartListenerCollection.reset(); // before pBASM because of potential Listener!
349
350 ClearLookupCaches(); // before pBASM because of listeners
351
352 // destroy BroadcastAreas first to avoid un-needed Single-EndListenings of Formula-Cells
353 pBASM.reset(); // BroadcastAreaSlotMachine
354
355 pUnoBroadcaster.reset(); // broadcasts SfxHintId::Dying again
356
357 pUnoRefUndoList.reset();
358 pUnoListenerCalls.reset();
359
360 Clear( true ); // true = from destructor (needed for SdrModel::ClearModel)
361
362 pValidationList.reset();
363 pRangeName.reset();
364 pDBCollection.reset();
365 pSelectionAttr.reset();
366 apTemporaryChartLock.reset();
367 DeleteDrawLayer();
368 mpPrinter.disposeAndClear();
369 ImplDeleteOptions();
370 pConsolidateDlgData.reset();
371 pClipData.reset();
372 pDetOpList.reset(); // also deletes entries
373 pChangeTrack.reset();
374 mpEditEngine.reset();
375 mpNoteEngine.reset();
376 pChangeViewSettings.reset(); // and delete
377 mpVirtualDevice_100th_mm.disposeAndClear();
5
Calling 'VclPtr::disposeAndClear'
378
379 pDPCollection.reset();
380 mpAnonymousDBData.reset();
381
382 // delete the EditEngine before destroying the mxPoolHelper
383 pCacheFieldEditEngine.reset();
384
385 if ( mxPoolHelper.is() && !bIsClip && !bIsUndo)
386 mxPoolHelper->SourceDocumentGone();
387 mxPoolHelper.clear();
388
389 pScriptTypeData.reset();
390 maNonThreaded.xRecursionHelper.reset();
391 maThreadSpecific.xRecursionHelper.reset();
392
393 pPreviewFont.reset();
394 SAL_WARN_IF( pAutoNameCache, "sc.core", "AutoNameCache still set in dtor" )do { if (true && (pAutoNameCache)) { 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() << "AutoNameCache still set in dtor"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"
), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "394" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "AutoNameCache still set in dtor"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "AutoNameCache still set in dtor"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "394" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "AutoNameCache still set in dtor") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "394" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "AutoNameCache still set in dtor"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "AutoNameCache still set in dtor"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc.core"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "394" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
395
396 mpFormulaGroupCxt.reset();
397 // Purge unused items if the string pool will be still used (e.g. by undo history).
398 if(mpCellStringPool.use_count() > 1)
399 mpCellStringPool->purge();
400 mpCellStringPool.reset();
401
402 assert( pDelayedFormulaGrouping == nullptr )(static_cast <bool> (pDelayedFormulaGrouping == nullptr
) ? void (0) : __assert_fail ("pDelayedFormulaGrouping == nullptr"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 402, __extension__ __PRETTY_FUNCTION__))
;
403 assert( pDelayedStartListeningFormulaCells.empty())(static_cast <bool> (pDelayedStartListeningFormulaCells
.empty()) ? void (0) : __assert_fail ("pDelayedStartListeningFormulaCells.empty()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 403, __extension__ __PRETTY_FUNCTION__))
;
404}
405
406void ScDocument::InitClipPtrs( ScDocument* pSourceDoc )
407{
408 OSL_ENSURE(bIsClip, "InitClipPtrs and not bIsClip")do { if (true && (!(bIsClip))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "408" ": "), "%s", "InitClipPtrs and not bIsClip"); } } while
(false)
;
409
410 ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE);
411
412 pValidationList.reset();
413
414 Clear();
415
416 SharePooledResources(pSourceDoc);
417
418 // conditional Formats / validations
419 // TODO: Copy Templates?
420 const ScValidationDataList* pSourceValid = pSourceDoc->pValidationList.get();
421 if ( pSourceValid )
422 pValidationList.reset(new ScValidationDataList(*this, *pSourceValid));
423
424 // store Links in Stream
425 pClipData.reset();
426 if (pSourceDoc->GetDocLinkManager().hasDdeLinks())
427 {
428 pClipData.reset( new SvMemoryStream );
429 pSourceDoc->SaveDdeLinks(*pClipData);
430 }
431
432 // Options pointers exist (ImplCreateOptions) for any document.
433 // Must be copied for correct results in OLE objects (#i42666#).
434 SetDocOptions( pSourceDoc->GetDocOptions() );
435 SetViewOptions( pSourceDoc->GetViewOptions() );
436}
437
438SvNumberFormatter* ScDocument::GetFormatTable() const
439{
440 assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 440, __extension__ __PRETTY_FUNCTION__))
;
441 return mxPoolHelper->GetFormTable();
442}
443
444SfxItemPool* ScDocument::GetEditPool() const
445{
446 return mxPoolHelper->GetEditPool();
447}
448
449SfxItemPool* ScDocument::GetEnginePool() const
450{
451 return mxPoolHelper->GetEnginePool();
452}
453
454ScFieldEditEngine& ScDocument::GetEditEngine()
455{
456 if ( !mpEditEngine )
457 {
458 mpEditEngine.reset( new ScFieldEditEngine(this, GetEnginePool(), GetEditPool()) );
459 mpEditEngine->SetUpdateMode( false );
460 mpEditEngine->EnableUndo( false );
461 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
462 ApplyAsianEditSettings( *mpEditEngine );
463 }
464 return *mpEditEngine;
465}
466
467ScNoteEditEngine& ScDocument::GetNoteEngine()
468{
469 if ( !mpNoteEngine )
470 {
471 ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE);
472 mpNoteEngine.reset( new ScNoteEditEngine( GetEnginePool(), GetEditPool() ) );
473 mpNoteEngine->SetUpdateMode( false );
474 mpNoteEngine->EnableUndo( false );
475 mpNoteEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
476 ApplyAsianEditSettings( *mpNoteEngine );
477 const SfxItemSet& rItemSet = GetDefPattern()->GetItemSet();
478 std::unique_ptr<SfxItemSet> pEEItemSet(new SfxItemSet( mpNoteEngine->GetEmptyItemSet() ));
479 ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
480 mpNoteEngine->SetDefaults( std::move(pEEItemSet) ); // edit engine takes ownership
481 }
482 return *mpNoteEngine;
483}
484
485void ScDocument::ResetClip( ScDocument* pSourceDoc, const ScMarkData* pMarks )
486{
487 if (bIsClip)
488 {
489 InitClipPtrs(pSourceDoc);
490
491 for (SCTAB i = 0; i < static_cast<SCTAB>(pSourceDoc->maTabs.size()); i++)
492 if (pSourceDoc->maTabs[i])
493 if (!pMarks || pMarks->GetTableSelect(i))
494 {
495 OUString aString = pSourceDoc->maTabs[i]->GetName();
496 if ( i < static_cast<SCTAB>(maTabs.size()) )
497 {
498 maTabs[i].reset( new ScTable(*this, i, aString) );
499
500 }
501 else
502 {
503 if( i > static_cast<SCTAB>(maTabs.size()) )
504 {
505 maTabs.resize(i);
506 }
507 maTabs.emplace_back(new ScTable(*this, i, aString));
508 }
509 maTabs[i]->SetLayoutRTL( pSourceDoc->maTabs[i]->IsLayoutRTL() );
510 }
511 }
512 else
513 {
514 OSL_FAIL("ResetClip")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/documen2.cxx"
":" "514" ": "), "%s", "ResetClip"); } } while (false)
;
515 }
516}
517
518void ScDocument::ResetClip( ScDocument* pSourceDoc, SCTAB nTab )
519{
520 if (bIsClip)
521 {
522 InitClipPtrs(pSourceDoc);
523 if (nTab >= static_cast<SCTAB>(maTabs.size()))
524 {
525 maTabs.resize(nTab+1);
526 }
527 maTabs[nTab].reset( new ScTable(*this, nTab, "baeh") );
528 if (nTab < static_cast<SCTAB>(pSourceDoc->maTabs.size()) && pSourceDoc->maTabs[nTab])
529 maTabs[nTab]->SetLayoutRTL( pSourceDoc->maTabs[nTab]->IsLayoutRTL() );
530 }
531 else
532 {
533 OSL_FAIL("ResetClip")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/documen2.cxx"
":" "533" ": "), "%s", "ResetClip"); } } while (false)
;
534 }
535}
536
537void ScDocument::EnsureTable( SCTAB nTab )
538{
539 bool bExtras = !bIsUndo; // Column-Widths, Row-Heights, Flags
540 if (o3tl::make_unsigned(nTab) >= maTabs.size())
541 maTabs.resize(nTab+1);
542
543 if (!maTabs[nTab])
544 maTabs[nTab].reset( new ScTable(*this, nTab, "temp", bExtras, bExtras) );
545}
546
547ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos )
548{
549 if (!TableExists(rPos.Tab()))
550 return ScRefCellValue(); // empty
551
552 return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row());
553}
554
555ScRefCellValue ScDocument::GetRefCellValue( const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
556{
557 if (!TableExists(rPos.Tab()))
558 return ScRefCellValue(); // empty
559
560 return maTabs[rPos.Tab()]->GetRefCellValue(rPos.Col(), rPos.Row(), rBlockPos);
561}
562
563svl::SharedStringPool& ScDocument::GetSharedStringPool()
564{
565 return *mpCellStringPool;
566}
567
568const svl::SharedStringPool& ScDocument::GetSharedStringPool() const
569{
570 return *mpCellStringPool;
571}
572
573bool ScDocument::GetPrintArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow,
574 bool bNotes ) const
575{
576 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
577 {
578 bool bAny = maTabs[nTab]->GetPrintArea( rEndCol, rEndRow, bNotes );
579 if (mpDrawLayer)
580 {
581 ScRange aDrawRange(0,0,nTab, MaxCol(),MaxRow(),nTab);
582 if (DrawGetPrintArea( aDrawRange, true, true ))
583 {
584 if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
585 if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
586 bAny = true;
587 }
588 }
589 return bAny;
590 }
591
592 rEndCol = 0;
593 rEndRow = 0;
594 return false;
595}
596
597bool ScDocument::GetPrintAreaHor( SCTAB nTab, SCROW nStartRow, SCROW nEndRow,
598 SCCOL& rEndCol ) const
599{
600 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
601 {
602 bool bAny = maTabs[nTab]->GetPrintAreaHor( nStartRow, nEndRow, rEndCol );
603 if (mpDrawLayer)
604 {
605 ScRange aDrawRange(0,nStartRow,nTab, MaxCol(),nEndRow,nTab);
606 if (DrawGetPrintArea( aDrawRange, true, false ))
607 {
608 if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
609 bAny = true;
610 }
611 }
612 return bAny;
613 }
614
615 rEndCol = 0;
616 return false;
617}
618
619bool ScDocument::GetPrintAreaVer( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol,
620 SCROW& rEndRow, bool bNotes ) const
621{
622 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
623 {
624 bool bAny = maTabs[nTab]->GetPrintAreaVer( nStartCol, nEndCol, rEndRow, bNotes );
625 if (mpDrawLayer)
626 {
627 ScRange aDrawRange(nStartCol,0,nTab, nEndCol,MaxRow(),nTab);
628 if (DrawGetPrintArea( aDrawRange, false, true ))
629 {
630 if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
631 bAny = true;
632 }
633 }
634 return bAny;
635 }
636
637 rEndRow = 0;
638 return false;
639}
640
641bool ScDocument::GetDataStart( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow ) const
642{
643 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
644 {
645 bool bAny = maTabs[nTab]->GetDataStart( rStartCol, rStartRow );
646 if (mpDrawLayer)
647 {
648 ScRange aDrawRange(0,0,nTab, MaxCol(),MaxRow(),nTab);
649 if (DrawGetPrintArea( aDrawRange, true, true ))
650 {
651 if (aDrawRange.aStart.Col()<rStartCol) rStartCol=aDrawRange.aStart.Col();
652 if (aDrawRange.aStart.Row()<rStartRow) rStartRow=aDrawRange.aStart.Row();
653 bAny = true;
654 }
655 }
656 return bAny;
657 }
658
659 rStartCol = 0;
660 rStartRow = 0;
661 return false;
662}
663
664void ScDocument::GetTiledRenderingArea(SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow) const
665{
666 bool bHasPrintArea = GetPrintArea(nTab, rEndCol, rEndRow, false);
667
668 // we need some reasonable minimal document size
669 ScViewData* pViewData = ScDocShell::GetViewData();
670 if (!pViewData)
671 {
672 if (!bHasPrintArea)
673 {
674 rEndCol = 20;
675 rEndRow = 50;
676 }
677 else
678 {
679 rEndCol += 20;
680 rEndRow += 50;
681 }
682 }
683 else if (!bHasPrintArea)
684 {
685 rEndCol = pViewData->GetMaxTiledCol();
686 rEndRow = pViewData->GetMaxTiledRow();
687 }
688 else
689 {
690 rEndCol = std::max(rEndCol, pViewData->GetMaxTiledCol());
691 rEndRow = std::max(rEndRow, pViewData->GetMaxTiledRow());
692 }
693}
694
695bool ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos, ScProgress* pProgress )
696{
697 if (nOldPos == nNewPos)
698 return false;
699
700 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
701 if(nTabCount < 2)
702 return false;
703
704 bool bValid = false;
705 if (ValidTab(nOldPos) && nOldPos < nTabCount )
706 {
707 if (maTabs[nOldPos])
708 {
709 sc::AutoCalcSwitch aACSwitch(*this, false);
710
711 SetNoListening( true );
712 if (nNewPos == SC_TAB_APPEND || nNewPos >= nTabCount)
713 nNewPos = nTabCount-1;
714
715 // Update Reference
716 // TODO: combine with UpdateReference!
717
718 sc::RefUpdateMoveTabContext aCxt( *this, nOldPos, nNewPos);
719
720 SCTAB nDz = nNewPos - nOldPos;
721 ScRange aSourceRange( 0,0,nOldPos, MaxCol(),MaxRow(),nOldPos );
722 if (pRangeName)
723 pRangeName->UpdateMoveTab(aCxt);
724
725 pDBCollection->UpdateMoveTab( nOldPos, nNewPos );
726 xColNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
727 xRowNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
728 if (pDPCollection)
729 pDPCollection->UpdateReference( URM_REORDER, aSourceRange, 0,0,nDz );
730 if (pDetOpList)
731 pDetOpList->UpdateReference( this, URM_REORDER, aSourceRange, 0,0,nDz );
732 UpdateChartRef( URM_REORDER,
733 0,0,nOldPos, MaxCol(),MaxRow(),nOldPos, 0,0,nDz );
734 UpdateRefAreaLinks( URM_REORDER, aSourceRange, 0,0,nDz );
735 if ( pValidationList )
736 pValidationList->UpdateMoveTab(aCxt);
737 if ( pUnoBroadcaster )
738 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_REORDER,
739 aSourceRange, 0,0,nDz ) );
740
741 ScTableUniquePtr pSaveTab = std::move(maTabs[nOldPos]);
742 maTabs.erase(maTabs.begin()+nOldPos);
743 maTabs.insert(maTabs.begin()+nNewPos, std::move(pSaveTab));
744 for (SCTAB i = 0; i < nTabCount; i++)
745 if (maTabs[i])
746 maTabs[i]->UpdateMoveTab(aCxt, i, pProgress);
747 for (auto& rxTab : maTabs)
748 if (rxTab)
749 rxTab->UpdateCompile();
750 SetNoListening( false );
751 StartAllListeners();
752
753 sc::SetFormulaDirtyContext aFormulaDirtyCxt;
754 SetAllFormulasDirty(aFormulaDirtyCxt);
755
756 if (mpDrawLayer)
757 mpDrawLayer->ScMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
758
759 bValid = true;
760 }
761 }
762 return bValid;
763}
764
765bool ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyMarked )
766{
767 if (SC_TAB_APPEND == nNewPos || nNewPos >= static_cast<SCTAB>(maTabs.size()))
768 nNewPos = static_cast<SCTAB>(maTabs.size());
769 OUString aName;
770 GetName(nOldPos, aName);
771
772 // check first if Prefix is valid; if not, then only avoid duplicates
773 bool bPrefix = ValidTabName( aName );
774 OSL_ENSURE(bPrefix, "invalid table name")do { if (true && (!(bPrefix))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
":" "774" ": "), "%s", "invalid table name"); } } while (false
)
;
775 SCTAB nDummy;
776
777 CreateValidTabName(aName);
778
779 bool bValid;
780 if (bPrefix)
781 bValid = ValidNewTabName(aName);
782 else
783 bValid = !GetTable( aName, nDummy );
784
785 sc::AutoCalcSwitch aACSwitch(*this, false);
786 sc::RefUpdateInsertTabContext aCxt( *this, nNewPos, 1);
787
788 if (bValid)
789 {
790 if (nNewPos >= static_cast<SCTAB>(maTabs.size()))
791 {
792 nNewPos = static_cast<SCTAB>(maTabs.size());
793 maTabs.emplace_back(new ScTable(*this, nNewPos, aName));
794 }
795 else
796 {
797 if (ValidTab(nNewPos) && (nNewPos < static_cast<SCTAB>(maTabs.size())))
798 {
799 SetNoListening( true );
800
801 ScRange aRange( 0,0,nNewPos, MaxCol(),MaxRow(),MAXTAB );
802 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
803 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
804 if (pRangeName)
805 pRangeName->UpdateInsertTab(aCxt);
806
807 pDBCollection->UpdateReference(
808 URM_INSDEL, 0,0,nNewPos, MaxCol(),MaxRow(),MAXTAB, 0,0,1 );
809 if (pDPCollection)
810 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
811 if (pDetOpList)
812 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
813 UpdateChartRef( URM_INSDEL, 0,0,nNewPos, MaxCol(),MaxRow(),MAXTAB, 0,0,1 );
814 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
815 if ( pUnoBroadcaster )
816 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
817
818 for (TableContainer::iterator it = maTabs.begin(); it != maTabs.end(); ++it)
819 if (*it && it != (maTabs.begin() + nOldPos))
820 (*it)->UpdateInsertTab(aCxt);
821 if (nNewPos <= nOldPos)
822 nOldPos++;
823 maTabs.emplace(maTabs.begin() + nNewPos, new ScTable(*this, nNewPos, aName));
824 bValid = true;
825 for (TableContainer::iterator it = maTabs.begin(); it != maTabs.end(); ++it)
826 if (*it && it != maTabs.begin()+nOldPos && it != maTabs.begin() + nNewPos)
827 (*it)->UpdateCompile();
828 SetNoListening( false );
829 sc::StartListeningContext aSLCxt(*this);
830 for (TableContainer::iterator it = maTabs.begin(); it != maTabs.end(); ++it)
831 if (*it && it != maTabs.begin()+nOldPos && it != maTabs.begin()+nNewPos)
832 (*it)->StartListeners(aSLCxt, true);
833
834 if (pValidationList)
835 pValidationList->UpdateInsertTab(aCxt);
836 }
837 else
838 bValid = false;
839 }
840 }
841
842 if (bValid)
843 {
844 SetNoListening( true ); // not yet at CopyToTable/Insert
845
846 const bool bGlobalNamesToLocal = true;
847 const SCTAB nRealOldPos = (nNewPos < nOldPos) ? nOldPos - 1 : nOldPos;
848 const ScRangeName* pNames = GetRangeName( nOldPos);
849 if (pNames)
850 pNames->CopyUsedNames( nOldPos, nRealOldPos, nNewPos, *this, *this, bGlobalNamesToLocal);
851 GetRangeName()->CopyUsedNames( -1, nRealOldPos, nNewPos, *this, *this, bGlobalNamesToLocal);
852
853 sc::CopyToDocContext aCopyDocCxt(*this);
854 maTabs[nOldPos]->CopyToTable(aCopyDocCxt, 0, 0, MaxCol(), MaxRow(), InsertDeleteFlags::ALL,
855 (pOnlyMarked != nullptr), maTabs[nNewPos].get(), pOnlyMarked,
856 false /*bAsLink*/, true /*bColRowFlags*/, bGlobalNamesToLocal, false /*bCopyCaptions*/ );
857 maTabs[nNewPos]->SetTabBgColor(maTabs[nOldPos]->GetTabBgColor());
858
859 SCTAB nDz = nNewPos - nOldPos;
860 sc::RefUpdateContext aRefCxt(*this);
861 aRefCxt.meMode = URM_COPY;
862 aRefCxt.maRange = ScRange(0, 0, nNewPos, MaxCol(), MaxRow(), nNewPos);
863 aRefCxt.mnTabDelta = nDz;
864 maTabs[nNewPos]->UpdateReference(aRefCxt);
865
866 maTabs[nNewPos]->UpdateInsertTabAbs(nNewPos); // move all paragraphs up by one!!
867 maTabs[nOldPos]->UpdateInsertTab(aCxt);
868
869 maTabs[nOldPos]->UpdateCompile();
870 maTabs[nNewPos]->UpdateCompile( true ); // maybe already compiled in Clone, but used names need recompilation
871 SetNoListening( false );
872 sc::StartListeningContext aSLCxt(*this);
873 maTabs[nOldPos]->StartListeners(aSLCxt, true);
874 maTabs[nNewPos]->StartListeners(aSLCxt, true);
875
876 sc::SetFormulaDirtyContext aFormulaDirtyCxt;
877 SetAllFormulasDirty(aFormulaDirtyCxt);
878
879 if (mpDrawLayer) // Skip cloning Note caption object
880 // page is already created in ScTable ctor
881 mpDrawLayer->ScCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
882
883 if (pDPCollection)
884 pDPCollection->CopyToTab(nOldPos, nNewPos);
885
886 maTabs[nNewPos]->SetPageStyle( maTabs[nOldPos]->GetPageStyle() );
887 maTabs[nNewPos]->SetPendingRowHeights( maTabs[nOldPos]->IsPendingRowHeights() );
888
889 // Copy the custom print range if exists.
890 maTabs[nNewPos]->CopyPrintRange(*maTabs[nOldPos]);
891
892 // Copy the RTL settings
893 maTabs[nNewPos]->SetLayoutRTL(maTabs[nOldPos]->IsLayoutRTL());
894 maTabs[nNewPos]->SetLoadingRTL(maTabs[nOldPos]->IsLoadingRTL());
895
896 // Finally copy the note captions, which need
897 // 1. the updated source ScColumn::nTab members if nNewPos <= nOldPos
898 // 2. row heights and column widths of the destination
899 // 3. RTL settings of the destination
900 maTabs[nOldPos]->CopyCaptionsToTable( 0, 0, MaxCol(), MaxRow(), maTabs[nNewPos].get(), true /*bCloneCaption*/);
901 }
902
903 return bValid;
904}
905
906sal_uLong ScDocument::TransferTab( ScDocument& rSrcDoc, SCTAB nSrcPos,
907 SCTAB nDestPos, bool bInsertNew,
908 bool bResultsOnly )
909{
910 sal_uLong nRetVal = 1; // 0 => error 1 = ok
911 // 3 => NameBox
912 // 4 => both
913
914 if (rSrcDoc.mpShell->GetMedium())
915 {
916 rSrcDoc.maFileURL = rSrcDoc.mpShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
917 // for unsaved files use the title name and adjust during save of file
918 if (rSrcDoc.maFileURL.isEmpty())
919 rSrcDoc.maFileURL = rSrcDoc.mpShell->GetName();
920 }
921 else
922 {
923 rSrcDoc.maFileURL = rSrcDoc.mpShell->GetName();
924 }
925
926 bool bValid = true;
927 if (bInsertNew) // re-insert
928 {
929 OUString aName;
930 rSrcDoc.GetName(nSrcPos, aName);
931 CreateValidTabName(aName);
932 bValid = InsertTab(nDestPos, aName);
933
934 // Copy the RTL settings
935 maTabs[nDestPos]->SetLayoutRTL(rSrcDoc.maTabs[nSrcPos]->IsLayoutRTL());
936 maTabs[nDestPos]->SetLoadingRTL(rSrcDoc.maTabs[nSrcPos]->IsLoadingRTL());
937 }
938 else // replace existing tables
939 {
940 if (ValidTab(nDestPos) && nDestPos < static_cast<SCTAB>(maTabs.size()) && maTabs[nDestPos])
941 {
942 maTabs[nDestPos]->DeleteArea( 0,0, MaxCol(),MaxRow(), InsertDeleteFlags::ALL );
943 }
944 else
945 bValid = false;
946 }
947
948 if (bValid)
949 {
950 bool bOldAutoCalcSrc = false;
951 bool bOldAutoCalc = GetAutoCalc();
952 SetAutoCalc( false ); // avoid repeated calculations
953 SetNoListening( true );
954 if ( bResultsOnly )
955 {
956 bOldAutoCalcSrc = rSrcDoc.GetAutoCalc();
957 rSrcDoc.SetAutoCalc( true ); // in case something needs calculation
958 }
959
960 {
961 NumFmtMergeHandler aNumFmtMergeHdl(*this, rSrcDoc);
962
963 sc::CopyToDocContext aCxt(*this);
964 nDestPos = std::min(nDestPos, static_cast<SCTAB>(GetTableCount() - 1));
965 { // scope for bulk broadcast
966 ScBulkBroadcast aBulkBroadcast( pBASM.get(), SfxHintId::ScDataChanged);
967 if (!bResultsOnly)
968 {
969 const bool bGlobalNamesToLocal = false;
970 const ScRangeName* pNames = rSrcDoc.GetRangeName( nSrcPos);
971 if (pNames)
972 pNames->CopyUsedNames( nSrcPos, nSrcPos, nDestPos, rSrcDoc, *this, bGlobalNamesToLocal);
973 rSrcDoc.GetRangeName()->CopyUsedNames( -1, nSrcPos, nDestPos, rSrcDoc, *this, bGlobalNamesToLocal);
974 }
975 rSrcDoc.maTabs[nSrcPos]->CopyToTable(aCxt, 0, 0, MaxCol(), MaxRow(),
976 ( bResultsOnly ? InsertDeleteFlags::ALL & ~InsertDeleteFlags::FORMULA : InsertDeleteFlags::ALL),
977 false, maTabs[nDestPos].get(), /*pMarkData*/nullptr, /*bAsLink*/false, /*bColRowFlags*/true,
978 /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true );
979 }
980 }
981 maTabs[nDestPos]->SetTabNo(nDestPos);
982 maTabs[nDestPos]->SetTabBgColor(rSrcDoc.maTabs[nSrcPos]->GetTabBgColor());
983
984 if ( !bResultsOnly )
985 {
986 sc::RefUpdateContext aRefCxt(*this);
987 aRefCxt.meMode = URM_COPY;
988 aRefCxt.maRange = ScRange(0, 0, nDestPos, MaxCol(), MaxRow(), nDestPos);
989 aRefCxt.mnTabDelta = nDestPos - nSrcPos;
990 maTabs[nDestPos]->UpdateReference(aRefCxt);
991
992 // Readjust self-contained absolute references to this sheet
993 maTabs[nDestPos]->TestTabRefAbs(nSrcPos);
994 sc::CompileFormulaContext aFormulaCxt(*this);
995 maTabs[nDestPos]->CompileAll(aFormulaCxt);
996 }
997
998 SetNoListening( false );
999 if ( !bResultsOnly )
1000 {
1001 sc::StartListeningContext aSLCxt(*this);
1002 maTabs[nDestPos]->StartListeners(aSLCxt, true);
1003 }
1004 SetDirty( ScRange( 0, 0, nDestPos, MaxCol(), MaxRow(), nDestPos), false);
1005
1006 if ( bResultsOnly )
1007 rSrcDoc.SetAutoCalc( bOldAutoCalcSrc );
1008 SetAutoCalc( bOldAutoCalc );
1009
1010 // copy Drawing
1011
1012 if (bInsertNew)
1013 TransferDrawPage( rSrcDoc, nSrcPos, nDestPos );
1014
1015 maTabs[nDestPos]->SetPendingRowHeights( rSrcDoc.maTabs[nSrcPos]->IsPendingRowHeights() );
1016 }
1017 if (!bValid)
1018 nRetVal = 0;
1019 bool bVbaEnabled = IsInVBAMode();
1020
1021 if ( bVbaEnabled )
1022 {
1023 SfxObjectShell* pSrcShell = rSrcDoc.GetDocumentShell();
1024 if ( pSrcShell )
1025 {
1026 OUString aLibName("Standard");
1027 const BasicManager *pBasicManager = pSrcShell->GetBasicManager();
1028 if (pBasicManager && !pBasicManager->GetName().isEmpty())
1029 {
1030 aLibName = pSrcShell->GetBasicManager()->GetName();
1031 }
1032 OUString sSource;
1033 uno::Reference< script::XLibraryContainer > xLibContainer = pSrcShell->GetBasicContainer();
1034 uno::Reference< container::XNameContainer > xLib;
1035 if( xLibContainer.is() )
1036 {
1037 uno::Any aLibAny = xLibContainer->getByName(aLibName);
1038 aLibAny >>= xLib;
1039 }
1040
1041 if( xLib.is() )
1042 {
1043 OUString sSrcCodeName;
1044 rSrcDoc.GetCodeName( nSrcPos, sSrcCodeName );
1045 OUString sRTLSource;
1046 xLib->getByName( sSrcCodeName ) >>= sRTLSource;
1047 sSource = sRTLSource;
1048 }
1049 VBA_InsertModule( *this, nDestPos, sSource );
1050 }
1051 }
1052
1053 return nRetVal;
1054}
1055
1056void ScDocument::SetError( SCCOL nCol, SCROW nRow, SCTAB nTab, const FormulaError nError)
1057{
1058 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
1059 if (maTabs[nTab])
1060 maTabs[nTab]->SetError( nCol, nRow, nError );
1061}
1062
1063void ScDocument::SetFormula(
1064 const ScAddress& rPos, const ScTokenArray& rArray )
1065{
1066 if (!TableExists(rPos.Tab()))
1067 return;
1068
1069 maTabs[rPos.Tab()]->SetFormula(rPos.Col(), rPos.Row(), rArray, formula::FormulaGrammar::GRAM_DEFAULT);
1070}
1071
1072void ScDocument::SetFormula(
1073 const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
1074{
1075 if (!TableExists(rPos.Tab()))
1076 return;
1077
1078 maTabs[rPos.Tab()]->SetFormula(rPos.Col(), rPos.Row(), rFormula, eGram);
1079}
1080
1081ScFormulaCell* ScDocument::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell )
1082{
1083 if (!TableExists(rPos.Tab()))
1084 {
1085 delete pCell;
1086 return nullptr;
1087 }
1088
1089 return maTabs[rPos.Tab()]->SetFormulaCell(rPos.Col(), rPos.Row(), pCell);
1090}
1091
1092bool ScDocument::SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells )
1093{
1094 if (rCells.empty())
1095 return false;
1096
1097 ScTable* pTab = FetchTable(rPos.Tab());
1098 if (!pTab)
1099 return false;
1100
1101 return pTab->SetFormulaCells(rPos.Col(), rPos.Row(), rCells);
1102}
1103
1104void ScDocument::SetConsolidateDlgData( std::unique_ptr<ScConsolidateParam> pData )
1105{
1106 pConsolidateDlgData = std::move(pData);
1107}
1108
1109void ScDocument::SetChangeViewSettings(const ScChangeViewSettings& rNew)
1110{
1111 if (pChangeViewSettings==nullptr)
1112 pChangeViewSettings.reset( new ScChangeViewSettings );
1113
1114 *pChangeViewSettings=rNew;
1115}
1116
1117std::unique_ptr<ScFieldEditEngine> ScDocument::CreateFieldEditEngine()
1118{
1119 std::unique_ptr<ScFieldEditEngine> pNewEditEngine;
1120 if (!pCacheFieldEditEngine)
1121 {
1122 pNewEditEngine.reset( new ScFieldEditEngine(
1123 this, GetEnginePool(), GetEditPool(), false) );
1124 }
1125 else
1126 {
1127 if ( !bImportingXML )
1128 {
1129 // #i66209# previous use might not have restored update mode,
1130 // ensure same state as for a new EditEngine (UpdateMode = true)
1131 if ( !pCacheFieldEditEngine->GetUpdateMode() )
1132 pCacheFieldEditEngine->SetUpdateMode(true);
1133 }
1134
1135 pNewEditEngine = std::move(pCacheFieldEditEngine);
1136 }
1137 return pNewEditEngine;
1138}
1139
1140void ScDocument::DisposeFieldEditEngine(std::unique_ptr<ScFieldEditEngine>& rpEditEngine)
1141{
1142 if (!pCacheFieldEditEngine && rpEditEngine)
1143 {
1144 pCacheFieldEditEngine = std::move( rpEditEngine );
1145 pCacheFieldEditEngine->Clear();
1146 }
1147 else
1148 rpEditEngine.reset();
1149}
1150
1151ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange, ScInterpreterContext* pContext )
1152{
1153 ScLookupCache* pCache = nullptr;
1154 if (!pContext->mxScLookupCache)
1155 pContext->mxScLookupCache.reset(new ScLookupCacheMap);
1156 ScLookupCacheMap* pCacheMap = pContext->mxScLookupCache.get();
1157 // insert with temporary value to avoid doing two lookups
1158 auto [findIt, bInserted] = pCacheMap->aCacheMap.emplace(rRange, nullptr);
1159 if (bInserted)
1160 {
1161 findIt->second = std::make_unique<ScLookupCache>(this, rRange, *pCacheMap);
1162 pCache = findIt->second.get();
1163 // The StartListeningArea() call is not thread-safe, as all threads
1164 // would access the same SvtBroadcaster.
1165 osl::MutexGuard guard( mScLookupMutex );
1166 StartListeningArea(rRange, false, pCache);
1167 }
1168 else
1169 pCache = (*findIt).second.get();
1170
1171 return *pCache;
1172}
1173
1174void ScDocument::RemoveLookupCache( ScLookupCache & rCache )
1175{
1176 // Data changes leading to this should never happen during calculation (they are either
1177 // a result of user input or recalc). If it turns out this can be the case, locking is needed
1178 // here and also in ScLookupCache::Notify().
1179 assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 1179, __extension__ __PRETTY_FUNCTION__))
;
1180 auto & cacheMap = rCache.getCacheMap();
1181 auto it(cacheMap.aCacheMap.find(rCache.getRange()));
1182 if (it != cacheMap.aCacheMap.end())
1183 {
1184 ScLookupCache* pCache = (*it).second.release();
1185 cacheMap.aCacheMap.erase(it);
1186 assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 1186, __extension__ __PRETTY_FUNCTION__))
; // EndListeningArea() is not thread-safe
1187 EndListeningArea(pCache->getRange(), false, &rCache);
1188 return;
1189 }
1190 OSL_FAIL( "ScDocument::RemoveLookupCache: range not found in hash map")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/documen2.cxx"
":" "1190" ": "), "%s", "ScDocument::RemoveLookupCache: range not found in hash map"
); } } while (false)
;
1191}
1192
1193void ScDocument::ClearLookupCaches()
1194{
1195 assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ?
void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()"
, "/home/maarten/src/libreoffice/core/sc/source/core/data/documen2.cxx"
, 1195, __extension__ __PRETTY_FUNCTION__))
;
1196 GetNonThreadedContext().mxScLookupCache.reset();
1197 // Clear lookup cache in all interpreter-contexts in the (threaded/non-threaded) pools.
1198 ScInterpreterContextPool::ClearLookupCaches();
1199}
1200
1201bool ScDocument::IsCellInChangeTrack(const ScAddress &cell,Color *pColCellBorder)
1202{
1203 ScChangeTrack* pTrack = GetChangeTrack();
1204 ScChangeViewSettings* pSettings = GetChangeViewSettings();
1205 if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() )
1206 return false; // missing or turned-off
1207 ScActionColorChanger aColorChanger(*pTrack);
1208 // Clipping happens from outside
1209 //! TODO: without Clipping; only paint affected cells ??!??!?
1210 const ScChangeAction* pAction = pTrack->GetFirst();
1211 while (pAction)
1212 {
1213 if ( pAction->IsVisible() )
1214 {
1215 ScChangeActionType eType = pAction->GetType();
1216 const ScBigRange& rBig = pAction->GetBigRange();
1217 if ( rBig.aStart.Tab() == cell.Tab())
1218 {
1219 ScRange aRange = rBig.MakeRange();
1220 if ( eType == SC_CAT_DELETE_ROWS )
1221 aRange.aEnd.SetRow( aRange.aStart.Row() );
1222 else if ( eType == SC_CAT_DELETE_COLS )
1223 aRange.aEnd.SetCol( aRange.aStart.Col() );
1224 if (ScViewUtil::IsActionShown( *pAction, *pSettings, *this ) )
1225 {
1226 if (aRange.In(cell))
1227 {
1228 if (pColCellBorder != nullptr)
1229 {
1230 aColorChanger.Update( *pAction );
1231 Color aColor( aColorChanger.GetColor() );
1232 *pColCellBorder = aColor;
1233 }
1234 return true;
1235 }
1236 }
1237 }
1238 if ( eType == SC_CAT_MOVE &&
1239 static_cast<const ScChangeActionMove*>(pAction)->
1240 GetFromRange().aStart.Tab() == cell.Col() )
1241 {
1242 ScRange aRange = static_cast<const ScChangeActionMove*>(pAction)->
1243 GetFromRange().MakeRange();
1244 if (ScViewUtil::IsActionShown( *pAction, *pSettings, *this ) )
1245 {
1246 if (aRange.In(cell))
1247 {
1248 if (pColCellBorder != nullptr)
1249 {
1250 aColorChanger.Update( *pAction );
1251 Color aColor( aColorChanger.GetColor() );
1252 *pColCellBorder = aColor;
1253 }
1254 return true;
1255 }
1256 }
1257 }
1258 }
1259 pAction = pAction->GetNext();
1260 }
1261 return false;
1262}
1263
1264void ScDocument::GetCellChangeTrackNote( const ScAddress &aCellPos, OUString &aTrackText,bool &bLeftEdge)
1265{
1266 aTrackText.clear();
1267 // Change-Tracking
1268 ScChangeTrack* pTrack = GetChangeTrack();
1269 ScChangeViewSettings* pSettings = GetChangeViewSettings();
1270 if ( !(pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges()))
1271 return;
1272
1273 const ScChangeAction* pFound = nullptr;
1274 const ScChangeAction* pFoundContent = nullptr;
1275 const ScChangeAction* pFoundMove = nullptr;
1276 const ScChangeAction* pAction = pTrack->GetFirst();
1277 while (pAction)
1278 {
1279 if ( pAction->IsVisible() &&
1280 ScViewUtil::IsActionShown( *pAction, *pSettings, *this ) )
1281 {
1282 ScChangeActionType eType = pAction->GetType();
1283 const ScBigRange& rBig = pAction->GetBigRange();
1284 if ( rBig.aStart.Tab() == aCellPos.Tab())
1285 {
1286 ScRange aRange = rBig.MakeRange();
1287 if ( eType == SC_CAT_DELETE_ROWS )
1288 aRange.aEnd.SetRow( aRange.aStart.Row() );
1289 else if ( eType == SC_CAT_DELETE_COLS )
1290 aRange.aEnd.SetCol( aRange.aStart.Col() );
1291 if ( aRange.In( aCellPos ) )
1292 {
1293 pFound = pAction; // the last wins
1294 switch ( eType )
1295 {
1296 case SC_CAT_CONTENT :
1297 pFoundContent = pAction;
1298 break;
1299 case SC_CAT_MOVE :
1300 pFoundMove = pAction;
1301 break;
1302 default:
1303 break;
1304 }
1305 }
1306 }
1307 if ( eType == SC_CAT_MOVE )
1308 {
1309 ScRange aRange =
1310 static_cast<const ScChangeActionMove*>(pAction)->
1311 GetFromRange().MakeRange();
1312 if ( aRange.In( aCellPos ) )
1313 {
1314 pFound = pAction;
1315 }
1316 }
1317 }
1318 pAction = pAction->GetNext();
1319 }
1320 if ( !pFound )
1321 return;
1322
1323 if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT )
1324 pFound = pFoundContent; // Content wins
1325 if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE &&
1326 pFoundMove->GetActionNumber() >
1327 pFound->GetActionNumber() )
1328 pFound = pFoundMove; // Move wins
1329 // for deleted columns: arrow on left side of row
1330 if ( pFound->GetType() == SC_CAT_DELETE_COLS )
1331 bLeftEdge = true;
1332 DateTime aDT = pFound->GetDateTime();
1333 aTrackText = pFound->GetUser();
1334 aTrackText += ", ";
1335 aTrackText += ScGlobal::getLocaleDataPtr()->getDate(aDT);
1336 aTrackText += " ";
1337 aTrackText += ScGlobal::getLocaleDataPtr()->getTime(aDT);
1338 aTrackText += ":\n";
1339 OUString aComStr = pFound->GetComment();
1340 if(!aComStr.isEmpty())
1341 {
1342 aTrackText += aComStr;
1343 aTrackText += "\n( ";
1344 }
1345 pFound->GetDescription( aTrackText, *this );
1346 if (!aComStr.isEmpty())
1347 {
1348 aTrackText += ")";
1349 }
1350}
1351
1352void ScDocument::SetPreviewFont( std::unique_ptr<SfxItemSet> pFont )
1353{
1354 pPreviewFont = std::move(pFont);
1355}
1356
1357void ScDocument::SetPreviewSelection( const ScMarkData& rSel )
1358{
1359 maPreviewSelection = rSel;
1360}
1361
1362SfxItemSet* ScDocument::GetPreviewFont( SCCOL nCol, SCROW nRow, SCTAB nTab )
1363{
1364 SfxItemSet* pRet = nullptr;
1365 if ( pPreviewFont )
1366 {
1367 ScMarkData aSel = GetPreviewSelection();
1368 if ( aSel.IsCellMarked( nCol, nRow ) && aSel.GetFirstSelected() == nTab )
1369 pRet = pPreviewFont.get();
1370 }
1371 return pRet;
1372}
1373
1374ScStyleSheet* ScDocument::GetPreviewCellStyle( SCCOL nCol, SCROW nRow, SCTAB nTab )
1375{
1376 ScStyleSheet* pRet = nullptr;
1377 ScMarkData aSel = GetPreviewSelection();
1378 if ( pPreviewCellStyle && aSel.IsCellMarked( nCol, nRow ) && aSel.GetFirstSelected() == nTab )
1379 pRet = pPreviewCellStyle;
1380 return pRet;
1381}
1382
1383sc::IconSetBitmapMap& ScDocument::GetIconSetBitmapMap()
1384{
1385 if (!m_pIconSetBitmapMap)
1386 {
1387 m_pIconSetBitmapMap.reset(new sc::IconSetBitmapMap);
1388 }
1389 return *m_pIconSetBitmapMap;
1390}
1391
1392/* 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);
6
Calling copy constructor for 'Reference<VirtualDevice>'
9
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
10
Calling 'Reference::clear'
17
Returning; memory was released
205 if (aTmp.get()) {
18
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
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)
7
Assuming field 'm_pBody' is non-null
8
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
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
)
11
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
12
Calling 'VclReferenceBase::release'
16
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;
19
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)
13
Assuming the condition is true
14
Taking true branch
40 delete this;
15
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