Bug Summary

File:home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx
Warning:line 2155, column 1
Potential leak of memory pointed to by 'pNewItem.pObj'

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 sb.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 -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 BASIC_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -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/basic/inc -I /home/maarten/src/libreoffice/core/basic/source/inc -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/basic/source/classes/sb.cxx

/home/maarten/src/libreoffice/core/basic/source/classes/sb.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 <sb.hxx>
21#include <tools/stream.hxx>
22#include <tools/debug.hxx>
23#include <vcl/errinf.hxx>
24#include <comphelper/solarmutex.hxx>
25#include <basic/sbx.hxx>
26#include <vcl/svapp.hxx>
27#include <comphelper/processfactory.hxx>
28#include <image.hxx>
29#include <sbunoobj.hxx>
30#include <sbjsmeth.hxx>
31#include <sbjsmod.hxx>
32#include <sbintern.hxx>
33#include <runtime.hxx>
34#include <basic/sberrors.hxx>
35#include <basic/sbuno.hxx>
36#include <sbprop.hxx>
37#include <sbobjmod.hxx>
38#include <stdobj.hxx>
39#include <basic.hrc>
40#include <cppuhelper/implbase.hxx>
41#include <com/sun/star/lang/XMultiServiceFactory.hpp>
42#include <com/sun/star/util/XCloseBroadcaster.hpp>
43#include <com/sun/star/util/XCloseListener.hpp>
44#include <sal/log.hxx>
45#include <errobject.hxx>
46#include <memory>
47#include <unordered_map>
48
49#include <com/sun/star/script/ModuleType.hpp>
50#include <com/sun/star/script/ModuleInfo.hpp>
51
52using namespace ::com::sun::star::script;
53
54#define SB_RTLNAME"@SBRTL" "@SBRTL"
55// i#i68894#
56using namespace ::com::sun::star;
57using namespace ::com::sun::star::uno;
58using com::sun::star::uno::Reference;
59using com::sun::star::uno::Any;
60using com::sun::star::uno::UNO_QUERY;
61using com::sun::star::lang::XMultiServiceFactory;
62
63
64class DocBasicItem : public ::cppu::WeakImplHelper< util::XCloseListener >
65{
66public:
67 explicit DocBasicItem( StarBASIC& rDocBasic );
68 virtual ~DocBasicItem() override;
69
70 const SbxObjectRef& getClassModules() const { return mxClassModules; }
71 bool isDocClosed() const { return mbDocClosed; }
72
73 void clearDependingVarsOnDelete( StarBASIC& rDeletedBasic );
74
75 void startListening();
76 void stopListening();
77
78 void setDisposed( bool bDisposed )
79 {
80 mbDisposed = bDisposed;
81 }
82
83 virtual void SAL_CALL queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership ) override;
84 virtual void SAL_CALL notifyClosing( const lang::EventObject& rSource ) override;
85 virtual void SAL_CALL disposing( const lang::EventObject& rSource ) override;
86
87private:
88 StarBASIC& mrDocBasic;
89 SbxObjectRef mxClassModules;
90 bool mbDocClosed;
91 bool mbDisposed;
92};
93
94
95DocBasicItem::DocBasicItem( StarBASIC& rDocBasic ) :
96 mrDocBasic( rDocBasic ),
97 mxClassModules( new SbxObject( OUString() ) ),
98 mbDocClosed( false ),
99 mbDisposed( false )
100{
101}
102
103DocBasicItem::~DocBasicItem()
104{
105 // tdf#90969 HACK: don't use SolarMutexGuard - there is a horrible global
106 // map GaDocBasicItems holding instances, and these get deleted from exit
107 // handlers, when the SolarMutex is already dead
108 comphelper::SolarMutex *pSolarMutex = comphelper::SolarMutex::get();
109 if ( pSolarMutex )
110 pSolarMutex->acquire();
111
112 try
113 {
114 stopListening();
115 mxClassModules.clear(); // release with SolarMutex locked
116 }
117 catch (...)
118 {
119 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
, 119, __extension__ __PRETTY_FUNCTION__))
;
120 }
121
122 pSolarMutex = comphelper::SolarMutex::get();
123 if ( pSolarMutex )
124 pSolarMutex->release();
125}
126
127void DocBasicItem::clearDependingVarsOnDelete( StarBASIC& rDeletedBasic )
128{
129 mrDocBasic.implClearDependingVarsOnDelete( &rDeletedBasic );
130}
131
132void DocBasicItem::startListening()
133{
134 Any aThisComp;
135 mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp );
136 Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
137 mbDisposed = !xCloseBC.is();
138 if( xCloseBC.is() )
139 {
140 try { xCloseBC->addCloseListener( this ); } catch(const uno::Exception& ) {}
141 }
142}
143
144void DocBasicItem::stopListening()
145{
146 if( mbDisposed ) return;
147 mbDisposed = true;
148 Any aThisComp;
149 if (!mrDocBasic.GetUNOConstant("ThisComponent", aThisComp))
150 return;
151
152 Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
153 if( xCloseBC.is() )
154 {
155 try { xCloseBC->removeCloseListener( this ); } catch(const uno::Exception& ) {}
156 }
157}
158
159void SAL_CALL DocBasicItem::queryClosing( const lang::EventObject& /*rSource*/, sal_Bool /*bGetsOwnership*/ )
160{
161}
162
163void SAL_CALL DocBasicItem::notifyClosing( const lang::EventObject& /*rEvent*/ )
164{
165 stopListening();
166 mbDocClosed = true;
167}
168
169void SAL_CALL DocBasicItem::disposing( const lang::EventObject& /*rEvent*/ )
170{
171 stopListening();
172}
173
174
175namespace {
176
177typedef ::rtl::Reference< DocBasicItem > DocBasicItemRef;
178
179class GaDocBasicItems : public rtl::Static<std::unordered_map< const StarBASIC *, DocBasicItemRef >,GaDocBasicItems> {};
180
181const DocBasicItem* lclFindDocBasicItem( const StarBASIC* pDocBasic )
182{
183 auto it = GaDocBasicItems::get().find( pDocBasic );
184 auto end = GaDocBasicItems::get().end();
185 return (it != end) ? it->second.get() : nullptr;
186}
187
188void lclInsertDocBasicItem( StarBASIC& rDocBasic )
189{
190 DocBasicItemRef& rxDocBasicItem = GaDocBasicItems::get()[ &rDocBasic ];
191 rxDocBasicItem.set( new DocBasicItem( rDocBasic ) );
192 rxDocBasicItem->startListening();
193}
194
195void lclRemoveDocBasicItem( StarBASIC& rDocBasic )
196{
197 auto it = GaDocBasicItems::get().find( &rDocBasic );
198 if( it != GaDocBasicItems::get().end() )
199 {
200 it->second->stopListening();
201 GaDocBasicItems::get().erase( it );
202 }
203 for( auto& rEntry : GaDocBasicItems::get() )
204 {
205 rEntry.second->clearDependingVarsOnDelete( rDocBasic );
206 }
207}
208
209StarBASIC* lclGetDocBasicForModule( SbModule* pModule )
210{
211 StarBASIC* pRetBasic = nullptr;
212 SbxObject* pCurParent = pModule;
213 while( pCurParent->GetParent() != nullptr )
214 {
215 pCurParent = pCurParent->GetParent();
216 StarBASIC* pDocBasic = dynamic_cast<StarBASIC*>( pCurParent );
217 if( pDocBasic != nullptr && pDocBasic->IsDocBasic() )
218 {
219 pRetBasic = pDocBasic;
220 break;
221 }
222 }
223 return pRetBasic;
224}
225
226} // namespace
227
228
229SbxObject* StarBASIC::getVBAGlobals( )
230{
231 if ( !pVBAGlobals.is() )
232 {
233 Any aThisDoc;
234 if ( GetUNOConstant("ThisComponent", aThisDoc) )
235 {
236 Reference< XMultiServiceFactory > xDocFac( aThisDoc, UNO_QUERY );
237 if ( xDocFac.is() )
238 {
239 try
240 {
241 xDocFac->createInstance("ooo.vba.VBAGlobals");
242 }
243 catch(const Exception& )
244 {
245 // Ignore
246 }
247 }
248 }
249 pVBAGlobals = static_cast<SbUnoObject*>(Find( "VBAGlobals" , SbxClassType::DontCare ));
250 }
251 return pVBAGlobals.get();
252}
253
254// i#i68894#
255SbxVariable* StarBASIC::VBAFind( const OUString& rName, SbxClassType t )
256{
257 if( rName == "ThisComponent" )
258 {
259 return nullptr;
260 }
261 // rename to init globals
262 if ( getVBAGlobals( ) )
263 {
264 return pVBAGlobals->Find( rName, t );
265 }
266 return nullptr;
267}
268
269namespace {
270
271// Create array for conversion SFX <-> VB error code
272struct SFX_VB_ErrorItem
273{
274 sal_uInt16 nErrorVB;
275 ErrCode nErrorSFX;
276};
277
278}
279
280const SFX_VB_ErrorItem SFX_VB_ErrorTab[] =
281{
282 { 1, ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ) }, // #87844 Map exception to error code 1
283 { 2, ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) },
284 { 3, ERRCODE_BASIC_NO_GOSUBErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 30 ) },
285 { 4, ERRCODE_BASIC_REDO_FROM_STARTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 31 ) },
286 { 5, ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) },
287 { 6, ERRCODE_BASIC_MATH_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 3) },
288 { 7, ERRCODE_BASIC_NO_MEMORYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 32 ) },
289 { 8, ERRCODE_BASIC_ALREADY_DIMErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 33 ) },
290 { 9, ERRCODE_BASIC_OUT_OF_RANGEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 4) },
291 { 10, ERRCODE_BASIC_DUPLICATE_DEFErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 34 ) },
292 { 11, ERRCODE_BASIC_ZERODIVErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 5) },
293 { 12, ERRCODE_BASIC_VAR_UNDEFINEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 35 ) },
294 { 13, ERRCODE_BASIC_CONVERSIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 6) },
295 { 14, ERRCODE_BASIC_BAD_PARAMETERErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 7) },
296 { 18, ERRCODE_BASIC_USER_ABORTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 36 ) },
297 { 20, ERRCODE_BASIC_BAD_RESUMEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 37 ) },
298 { 28, ERRCODE_BASIC_STACK_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 38 ) },
299 { 35, ERRCODE_BASIC_PROC_UNDEFINEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 8) },
300 { 48, ERRCODE_BASIC_BAD_DLL_LOADErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 39 ) },
301 { 49, ERRCODE_BASIC_BAD_DLL_CALLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 40 ) },
302 { 51, ERRCODE_BASIC_INTERNAL_ERRORErrCode( ErrCodeArea::Sbx, ErrCodeClass::Unknown, 9) },
303 { 52, ERRCODE_BASIC_BAD_CHANNELErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 41 ) },
304 { 53, ERRCODE_BASIC_FILE_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 42 ) },
305 { 54, ERRCODE_BASIC_BAD_FILE_MODEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 43 ) },
306 { 55, ERRCODE_BASIC_FILE_ALREADY_OPENErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 44 ) },
307 { 57, ERRCODE_BASIC_IO_ERRORErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 45 ) },
308 { 58, ERRCODE_BASIC_FILE_EXISTSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 46 ) },
309 { 59, ERRCODE_BASIC_BAD_RECORD_LENGTHErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 47 ) },
310 { 61, ERRCODE_BASIC_DISK_FULLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 48 ) },
311 { 62, ERRCODE_BASIC_READ_PAST_EOFErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 49 ) },
312 { 63, ERRCODE_BASIC_BAD_RECORD_NUMBERErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 50 ) },
313 { 67, ERRCODE_BASIC_TOO_MANY_FILESErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 51 ) },
314 { 68, ERRCODE_BASIC_NO_DEVICEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 52 ) },
315 { 70, ERRCODE_BASIC_ACCESS_DENIEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 53 ) },
316 { 71, ERRCODE_BASIC_NOT_READYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 54 ) },
317 { 73, ERRCODE_BASIC_NOT_IMPLEMENTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 55 ) },
318 { 74, ERRCODE_BASIC_DIFFERENT_DRIVEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 56 ) },
319 { 75, ERRCODE_BASIC_ACCESS_ERRORErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 57 ) },
320 { 76, ERRCODE_BASIC_PATH_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 58 ) },
321 { 91, ERRCODE_BASIC_NO_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 10) },
322 { 93, ERRCODE_BASIC_BAD_PATTERNErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 59 ) },
323 { 94, ERRCODE_BASIC_IS_NULLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 60 ) },
324 { 250, ERRCODE_BASIC_DDE_ERRORErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 61 ) },
325 { 280, ERRCODE_BASIC_DDE_WAITINGACKErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 62 ) },
326 { 281, ERRCODE_BASIC_DDE_OUTOFCHANNELSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 63 ) },
327 { 282, ERRCODE_BASIC_DDE_NO_RESPONSEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 64 ) },
328 { 283, ERRCODE_BASIC_DDE_MULT_RESPONSESErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 65 ) },
329 { 284, ERRCODE_BASIC_DDE_CHANNEL_LOCKEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 66 ) },
330 { 285, ERRCODE_BASIC_DDE_NOTPROCESSEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 67 ) },
331 { 286, ERRCODE_BASIC_DDE_TIMEOUTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 68 ) },
332 { 287, ERRCODE_BASIC_DDE_USER_INTERRUPTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 69 ) },
333 { 288, ERRCODE_BASIC_DDE_BUSYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 70 ) },
334 { 289, ERRCODE_BASIC_DDE_NO_DATAErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 71 ) },
335 { 290, ERRCODE_BASIC_DDE_WRONG_DATA_FORMATErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 72 ) },
336 { 291, ERRCODE_BASIC_DDE_PARTNER_QUITErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 73 ) },
337 { 292, ERRCODE_BASIC_DDE_CONV_CLOSEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 74 ) },
338 { 293, ERRCODE_BASIC_DDE_NO_CHANNELErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 75 ) },
339 { 294, ERRCODE_BASIC_DDE_INVALID_LINKErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 76 ) },
340 { 295, ERRCODE_BASIC_DDE_QUEUE_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 77 ) },
341 { 296, ERRCODE_BASIC_DDE_LINK_ALREADY_ESTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 78 ) },
342 { 297, ERRCODE_BASIC_DDE_LINK_INV_TOPICErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 79 ) },
343 { 298, ERRCODE_BASIC_DDE_DLL_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 80 ) },
344 { 323, ERRCODE_BASIC_CANNOT_LOADErrCode( ErrCodeArea::Sbx, ErrCodeClass::Create, 11) },
345 { 341, ERRCODE_BASIC_BAD_INDEXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 12) },
346 { 366, ERRCODE_BASIC_NO_ACTIVE_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Access, 13) },
347 { 380, ERRCODE_BASIC_BAD_PROP_VALUEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 14) },
348 { 382, ERRCODE_BASIC_PROP_READONLYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Read, 15) },
349 { 394, ERRCODE_BASIC_PROP_WRITEONLYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Write, 16) },
350 { 420, ERRCODE_BASIC_INVALID_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Access, 17) },
351 { 423, ERRCODE_BASIC_NO_METHODErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 18) },
352 { 424, ERRCODE_BASIC_NEEDS_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 81 ) },
353 { 425, ERRCODE_BASIC_INVALID_USAGE_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Access, 19) },
354 { 430, ERRCODE_BASIC_NO_OLEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Access, 20) },
355 { 438, ERRCODE_BASIC_BAD_METHODErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 21) },
356 { 440, ERRCODE_BASIC_OLE_ERRORErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 22) },
357 { 445, ERRCODE_BASIC_BAD_ACTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 23) },
358 { 446, ERRCODE_BASIC_NO_NAMED_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 24) },
359 { 447, ERRCODE_BASIC_BAD_LOCALEErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 25) },
360 { 448, ERRCODE_BASIC_NAMED_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 26) },
361 { 449, ERRCODE_BASIC_NOT_OPTIONALErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 27) },
362 { 450, ERRCODE_BASIC_WRONG_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 28) },
363 { 451, ERRCODE_BASIC_NOT_A_COLLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 29) },
364 { 452, ERRCODE_BASIC_BAD_ORDINALErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 82 ) },
365 { 453, ERRCODE_BASIC_DLLPROC_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 83 ) },
366 { 460, ERRCODE_BASIC_BAD_CLIPBD_FORMATErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 84 ) },
367 { 951, ERRCODE_BASIC_UNEXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 92 ) },
368 { 952, ERRCODE_BASIC_EXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 93 ) },
369 { 953, ERRCODE_BASIC_SYMBOL_EXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 94 ) },
370 { 954, ERRCODE_BASIC_VAR_EXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 95 ) },
371 { 955, ERRCODE_BASIC_LABEL_EXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 96 ) },
372 { 956, ERRCODE_BASIC_LVALUE_EXPECTEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 97 ) },
373 { 957, ERRCODE_BASIC_VAR_DEFINEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 98 ) },
374 { 958, ERRCODE_BASIC_PROC_DEFINEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 99 ) },
375 { 959, ERRCODE_BASIC_LABEL_DEFINEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 100 ) },
376 { 960, ERRCODE_BASIC_UNDEF_VARErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 101 ) },
377 { 961, ERRCODE_BASIC_UNDEF_ARRAYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 102 ) },
378 { 962, ERRCODE_BASIC_UNDEF_PROCErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 103 ) },
379 { 963, ERRCODE_BASIC_UNDEF_LABELErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 104 ) },
380 { 964, ERRCODE_BASIC_UNDEF_TYPEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 105 ) },
381 { 965, ERRCODE_BASIC_BAD_EXITErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 106 ) },
382 { 966, ERRCODE_BASIC_BAD_BLOCKErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 107 ) },
383 { 967, ERRCODE_BASIC_BAD_BRACKETSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 108 ) },
384 { 968, ERRCODE_BASIC_BAD_DECLARATIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 109 ) },
385 { 969, ERRCODE_BASIC_BAD_PARAMETERSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 110 ) },
386 { 970, ERRCODE_BASIC_BAD_CHAR_IN_NUMBERErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 111 ) },
387 { 971, ERRCODE_BASIC_MUST_HAVE_DIMSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 112 ) },
388 { 972, ERRCODE_BASIC_NO_IFErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 113 ) },
389 { 973, ERRCODE_BASIC_NOT_IN_SUBRErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 114 ) },
390 { 974, ERRCODE_BASIC_NOT_IN_MAINErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 115 ) },
391 { 975, ERRCODE_BASIC_WRONG_DIMSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 116 ) },
392 { 976, ERRCODE_BASIC_BAD_OPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 117 ) },
393 { 977, ERRCODE_BASIC_CONSTANT_REDECLAREDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 118 ) },
394 { 978, ERRCODE_BASIC_PROG_TOO_LARGEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 119 ) },
395 { 979, ERRCODE_BASIC_NO_STRINGS_ARRAYSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 120 ) },
396 { 1000, ERRCODE_BASIC_PROPERTY_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 85 ) },
397 { 1001, ERRCODE_BASIC_METHOD_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 86 ) },
398 { 1002, ERRCODE_BASIC_ARG_MISSINGErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 87 ) },
399 { 1003, ERRCODE_BASIC_BAD_NUMBER_OF_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 88 ) },
400 { 1004, ERRCODE_BASIC_METHOD_FAILEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 89 ) },
401 { 1005, ERRCODE_BASIC_SETPROP_FAILEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 90 ) },
402 { 1006, ERRCODE_BASIC_GETPROP_FAILEDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 91 ) },
403 { 1007, ERRCODE_BASIC_COMPATErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 132 ) },
404 { 0xFFFF, ErrCode(0xFFFFFFFFUL) } // End mark
405};
406
407// The StarBASIC factory is a hack. When a SbModule is created, its pointer
408// is saved and given to the following SbProperties/SbMethods. This restores
409// the Module-relationship. But it works only when a module is loaded.
410// Can cause troubles with separately loaded properties!
411
412SbxBase* SbiFactory::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
413{
414 if( nCreator == SBXCR_SBX )
415 {
416 switch( nSbxId )
417 {
418 case SBXID_BASIC0x6273:
419 return new StarBASIC( nullptr );
420 case SBXID_BASICMOD0x6d62:
421 return new SbModule( "" );
422 case SBXID_BASICPROP0x7262:
423 return new SbProperty( "", SbxVARIANT, nullptr );
424 case SBXID_BASICMETHOD0x6d65:
425 return new SbMethod( "", SbxVARIANT, nullptr );
426 case SBXID_JSCRIPTMOD0x6a62:
427 return new SbJScriptModule;
428 case SBXID_JSCRIPTMETH0x6a64:
429 return new SbJScriptMethod( SbxVARIANT );
430 }
431 }
432 return nullptr;
433}
434
435SbxObject* SbiFactory::CreateObject( const OUString& rClass )
436{
437 if( rClass.equalsIgnoreAsciiCase( "StarBASIC" ) )
438 {
439 return new StarBASIC( nullptr );
440 }
441 else if( rClass.equalsIgnoreAsciiCase( "StarBASICModule" ) )
442 {
443 return new SbModule( OUString() );
444 }
445 else if( rClass.equalsIgnoreAsciiCase( "Collection" ) )
446 {
447 return new BasicCollection( "Collection" );
448 }
449 else if( rClass.equalsIgnoreAsciiCase( "FileSystemObject" ) )
450 {
451 try
452 {
453 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory(), UNO_SET_THROW );
454 OUString aServiceName("ooo.vba.FileSystemObject");
455 Reference< XInterface > xInterface( xFactory->createInstance( aServiceName ), UNO_SET_THROW );
456 return new SbUnoObject( aServiceName, uno::Any( xInterface ) );
457 }
458 catch(const Exception& )
459 {
460 }
461 }
462 return nullptr;
463}
464
465
466SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 )
467{
468 // Not supported
469 return nullptr;
470}
471
472SbxObject* SbOLEFactory::CreateObject( const OUString& rClassName )
473{
474 SbxObject* pRet = createOLEObject_Impl( rClassName );
475 return pRet;
476}
477
478
479// SbFormFactory, show user forms by: dim as new <user form name>
480
481SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 )
482{
483 // Not supported
484 return nullptr;
485}
486
487SbxObject* SbFormFactory::CreateObject( const OUString& rClassName )
488{
489 if( SbModule* pMod = GetSbData()->pMod )
490 {
491 if( SbxVariable* pVar = pMod->Find( rClassName, SbxClassType::Object ) )
492 {
493 if( SbUserFormModule* pFormModule = dynamic_cast<SbUserFormModule*>( pVar->GetObject() ) )
494 {
495 bool bInitState = pFormModule->getInitState();
496 if( bInitState )
497 {
498 // Not the first instantiate, reset
499 pFormModule->ResetApiObj( false/*bTriggerTerminateEvent*/ );
500 pFormModule->setInitState( false );
501 }
502 else
503 {
504 pFormModule->Load();
505 }
506 return pFormModule->CreateInstance();
507 }
508 }
509 }
510 return nullptr;
511}
512
513
514// SbTypeFactory
515
516SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj )
517{
518 SbxObject* pRet = new SbxObject( rTypeObj );
519 pRet->PutObject( pRet );
520
521 // Copy the properties, not only the reference to them
522 SbxArray* pProps = pRet->GetProperties();
523 sal_uInt32 nCount = pProps->Count32();
524 for( sal_uInt32 i = 0 ; i < nCount ; i++ )
525 {
526 SbxVariable* pVar = pProps->Get32( i );
527 SbxProperty* pProp = dynamic_cast<SbxProperty*>( pVar );
528 if( pProp )
529 {
530 SbxProperty* pNewProp = new SbxProperty( *pProp );
531 SbxDataType eVarType = pVar->GetType();
532 if( eVarType & SbxARRAY )
533 {
534 SbxBase* pParObj = pVar->GetObject();
535 SbxDimArray* pSource = dynamic_cast<SbxDimArray*>( pParObj );
536 SbxDimArray* pDest = new SbxDimArray( pVar->GetType() );
537
538 pDest->setHasFixedSize( pSource && pSource->hasFixedSize() );
539 if ( pSource && pSource->GetDims32() && pSource->hasFixedSize() )
540 {
541 sal_Int32 lb = 0;
542 sal_Int32 ub = 0;
543 for ( sal_Int32 j = 1 ; j <= pSource->GetDims32(); ++j )
544 {
545 pSource->GetDim32( j, lb, ub );
546 pDest->AddDim32( lb, ub );
547 }
548 }
549 else
550 {
551 pDest->unoAddDim32( 0, -1 ); // variant array
552 }
553 SbxFlagBits nSavFlags = pVar->GetFlags();
554 pNewProp->ResetFlag( SbxFlagBits::Fixed );
555 // need to reset the FIXED flag
556 // when calling PutObject ( because the type will not match Object )
557 pNewProp->PutObject( pDest );
558 pNewProp->SetFlags( nSavFlags );
559 }
560 if( eVarType == SbxOBJECT )
561 {
562 SbxBase* pObjBase = pVar->GetObject();
563 SbxObject* pSrcObj = dynamic_cast<SbxObject*>( pObjBase );
564 SbxObject* pDestObj = nullptr;
565 if( pSrcObj != nullptr )
566 pDestObj = cloneTypeObjectImpl( *pSrcObj );
567 pNewProp->PutObject( pDestObj );
568 }
569 pProps->PutDirect( pNewProp, i );
570 }
571 }
572 return pRet;
573}
574
575SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 )
576{
577 // Not supported
578 return nullptr;
579}
580
581SbxObject* SbTypeFactory::CreateObject( const OUString& rClassName )
582{
583 SbxObject* pRet = nullptr;
584 SbModule* pMod = GetSbData()->pMod;
585 if( pMod )
586 {
587 const SbxObject* pObj = pMod->FindType( rClassName );
588 if( pObj )
589 {
590 pRet = cloneTypeObjectImpl( *pObj );
591 }
592 }
593 return pRet;
594}
595
596SbxObject* createUserTypeImpl( const OUString& rClassName )
597{
598 SbxObject* pRetObj = GetSbData()->pTypeFac->CreateObject( rClassName );
599 return pRetObj;
600}
601
602
603SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule )
604 : SbModule( pClassModule->GetName() )
605 , mpClassModule( pClassModule )
606 , mbInitializeEventDone( false )
607{
608 aOUSource = pClassModule->aOUSource;
609 aComment = pClassModule->aComment;
610 // see comment in destructor about these two
611 pImage = pClassModule->pImage;
612 pBreaks = pClassModule->pBreaks;
613
614 SetClassName( pClassModule->GetName() );
615
616 // Allow search only internally
617 ResetFlag( SbxFlagBits::GlobalSearch );
618
619 // Copy the methods from original class module
620 SbxArray* pClassMethods = pClassModule->GetMethods().get();
621 sal_uInt32 nMethodCount = pClassMethods->Count32();
622 sal_uInt32 i;
623 for( i = 0 ; i < nMethodCount ; i++ )
624 {
625 SbxVariable* pVar = pClassMethods->Get32( i );
626
627 // Exclude SbIfaceMapperMethod to copy them in a second step
628 SbIfaceMapperMethod* pIfaceMethod = dynamic_cast<SbIfaceMapperMethod*>( pVar );
629 if( !pIfaceMethod )
630 {
631 SbMethod* pMethod = dynamic_cast<SbMethod*>( pVar );
632 if( pMethod )
633 {
634 SbxFlagBits nFlags_ = pMethod->GetFlags();
635 pMethod->SetFlag( SbxFlagBits::NoBroadcast );
636 SbMethod* pNewMethod = new SbMethod( *pMethod );
637 pNewMethod->ResetFlag( SbxFlagBits::NoBroadcast );
638 pMethod->SetFlags( nFlags_ );
639 pNewMethod->pMod = this;
640 pNewMethod->SetParent( this );
641 pMethods->PutDirect( pNewMethod, i );
642 StartListening(pNewMethod->GetBroadcaster(), DuplicateHandling::Prevent);
643 }
644 }
645 }
646
647 // Copy SbIfaceMapperMethod in a second step to ensure that
648 // the corresponding base methods have already been copied
649 for( i = 0 ; i < nMethodCount ; i++ )
650 {
651 SbxVariable* pVar = pClassMethods->Get32( i );
652
653 SbIfaceMapperMethod* pIfaceMethod = dynamic_cast<SbIfaceMapperMethod*>( pVar );
654 if( pIfaceMethod )
655 {
656 SbMethod* pImplMethod = pIfaceMethod->getImplMethod();
657 if( !pImplMethod )
658 {
659 OSL_FAIL( "No ImplMethod" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "659" ": "), "%s", "No ImplMethod"); } } while (false)
;
660 continue;
661 }
662
663 // Search for own copy of ImplMethod
664 SbxVariable* p = pMethods->Find( pImplMethod->GetName(), SbxClassType::Method );
665 SbMethod* pImplMethodCopy = dynamic_cast<SbMethod*>( p );
666 if( !pImplMethodCopy )
667 {
668 OSL_FAIL( "Found no ImplMethod copy" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "668" ": "), "%s", "Found no ImplMethod copy"); } } while
(false)
;
669 continue;
670 }
671 SbIfaceMapperMethod* pNewIfaceMethod =
672 new SbIfaceMapperMethod( pIfaceMethod->GetName(), pImplMethodCopy );
673 pMethods->PutDirect( pNewIfaceMethod, i );
674 }
675 }
676
677 // Copy the properties from original class module
678 SbxArray* pClassProps = pClassModule->GetProperties();
679 sal_uInt32 nPropertyCount = pClassProps->Count32();
680 for( i = 0 ; i < nPropertyCount ; i++ )
681 {
682 SbxVariable* pVar = pClassProps->Get32( i );
683 SbProcedureProperty* pProcedureProp = dynamic_cast<SbProcedureProperty*>( pVar );
684 if( pProcedureProp )
685 {
686 SbxFlagBits nFlags_ = pProcedureProp->GetFlags();
687 pProcedureProp->SetFlag( SbxFlagBits::NoBroadcast );
688 SbProcedureProperty* pNewProp = new SbProcedureProperty
689 ( pProcedureProp->GetName(), pProcedureProp->GetType() );
690 pNewProp->SetFlags( nFlags_ ); // Copy flags
691 pNewProp->ResetFlag( SbxFlagBits::NoBroadcast ); // except the Broadcast if it was set
692 pProcedureProp->SetFlags( nFlags_ );
693 pProps->PutDirect( pNewProp, i );
694 StartListening(pNewProp->GetBroadcaster(), DuplicateHandling::Prevent);
695 }
696 else
697 {
698 SbxProperty* pProp = dynamic_cast<SbxProperty*>( pVar );
699 if( pProp )
700 {
701 SbxFlagBits nFlags_ = pProp->GetFlags();
702 pProp->SetFlag( SbxFlagBits::NoBroadcast );
703 SbxProperty* pNewProp = new SbxProperty( *pProp );
704
705 // Special handling for modules instances and collections, they need
706 // to be instantiated, otherwise all refer to the same base object
707 SbxDataType eVarType = pProp->GetType();
708 if( eVarType == SbxOBJECT )
709 {
710 SbxBase* pObjBase = pProp->GetObject();
711 SbxObject* pObj = dynamic_cast<SbxObject*>( pObjBase );
712 if( pObj != nullptr )
713 {
714 const OUString& aObjClass = pObj->GetClassName();
715
716 SbClassModuleObject* pClassModuleObj = dynamic_cast<SbClassModuleObject*>( pObjBase );
717 if( pClassModuleObj != nullptr )
718 {
719 SbModule* pLclClassModule = pClassModuleObj->getClassModule();
720 SbClassModuleObject* pNewObj = new SbClassModuleObject( pLclClassModule );
721 pNewObj->SetName( pProp->GetName() );
722 pNewObj->SetParent( pLclClassModule->pParent );
723 pNewProp->PutObject( pNewObj );
724 }
725 else if( aObjClass.equalsIgnoreAsciiCase( "Collection" ) )
726 {
727 BasicCollection* pNewCollection = new BasicCollection( "Collection" );
728 pNewCollection->SetName( pProp->GetName() );
729 pNewCollection->SetParent( pClassModule->pParent );
730 pNewProp->PutObject( pNewCollection );
731 }
732 }
733 }
734
735 pNewProp->ResetFlag( SbxFlagBits::NoBroadcast );
736 pNewProp->SetParent( this );
737 pProps->PutDirect( pNewProp, i );
738 pProp->SetFlags( nFlags_ );
739 }
740 }
741 }
742 SetModuleType( ModuleType::CLASS );
743 mbVBACompat = pClassModule->mbVBACompat;
744}
745
746SbClassModuleObject::~SbClassModuleObject()
747{
748 // do not trigger termination event when document is already closed
749 if( StarBASIC::IsRunning() )
750 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( this ) )
751 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
752 if( !pDocBasicItem->isDocClosed() )
753 triggerTerminateEvent();
754
755 // prevent the base class destructor from deleting these because
756 // we do not actually own them
757 pImage = nullptr;
758 pBreaks = nullptr;
759}
760
761void SbClassModuleObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
762{
763 handleProcedureProperties( rBC, rHint );
764}
765
766SbxVariable* SbClassModuleObject::Find( const OUString& rName, SbxClassType t )
767{
768 SbxVariable* pRes = SbxObject::Find( rName, t );
769 if( pRes )
770 {
771 triggerInitializeEvent();
772
773 SbIfaceMapperMethod* pIfaceMapperMethod = dynamic_cast<SbIfaceMapperMethod*>( pRes );
774 if( pIfaceMapperMethod )
775 {
776 pRes = pIfaceMapperMethod->getImplMethod();
777 pRes->SetFlag( SbxFlagBits::ExtFound );
778 }
779 }
780 return pRes;
781}
782
783void SbClassModuleObject::triggerInitializeEvent()
784{
785 if( mbInitializeEventDone )
786 {
787 return;
788 }
789
790 mbInitializeEventDone = true;
791
792 // Search method
793 SbxVariable* pMeth = SbxObject::Find("Class_Initialize", SbxClassType::Method);
794 if( pMeth )
795 {
796 SbxValues aVals;
797 pMeth->Get( aVals );
798 }
799}
800
801void SbClassModuleObject::triggerTerminateEvent()
802{
803 if( !mbInitializeEventDone || GetSbData()->bRunInit )
804 {
805 return;
806 }
807 // Search method
808 SbxVariable* pMeth = SbxObject::Find("Class_Terminate", SbxClassType::Method );
809 if( pMeth )
810 {
811 SbxValues aVals;
812 pMeth->Get( aVals );
813 }
814}
815
816
817SbClassData::SbClassData()
818{
819 mxIfaces = new SbxArray();
820}
821
822void SbClassData::clear()
823{
824 mxIfaces->Clear();
825 maRequiredTypes.clear();
826}
827
828SbClassFactory::SbClassFactory()
829{
830 xClassModules = new SbxObject( OUString() );
831}
832
833SbClassFactory::~SbClassFactory()
834{}
835
836void SbClassFactory::AddClassModule( SbModule* pClassModule )
837{
838 SbxObjectRef xToUseClassModules = xClassModules;
839
840 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pClassModule ) )
841 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
842 xToUseClassModules = pDocBasicItem->getClassModules();
843
844 SbxObject* pParent = pClassModule->GetParent();
845 xToUseClassModules->Insert( pClassModule );
846 pClassModule->SetParent( pParent );
847}
848
849void SbClassFactory::RemoveClassModule( SbModule* pClassModule )
850{
851 xClassModules->Remove( pClassModule );
852}
853
854SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 )
855{
856 // Not supported
857 return nullptr;
858}
859
860SbxObject* SbClassFactory::CreateObject( const OUString& rClassName )
861{
862 SbxObjectRef xToUseClassModules = xClassModules;
863
864 if( SbModule* pMod = GetSbData()->pMod )
865 {
866 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pMod ) )
867 {
868 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
869 {
870 xToUseClassModules = pDocBasicItem->getClassModules();
871 }
872 }
873 }
874 SbxVariable* pVar = xToUseClassModules->Find( rClassName, SbxClassType::Object );
875 SbxObject* pRet = nullptr;
876 if( pVar )
877 {
878 SbModule* pVarMod = static_cast<SbModule*>(pVar);
879 pRet = new SbClassModuleObject( pVarMod );
880 }
881 return pRet;
882}
883
884SbModule* SbClassFactory::FindClass( const OUString& rClassName )
885{
886 SbxVariable* pVar = xClassModules->Find( rClassName, SbxClassType::DontCare );
887 SbModule* pMod = pVar ? static_cast<SbModule*>(pVar) : nullptr;
888 return pMod;
889}
890
891StarBASIC::StarBASIC( StarBASIC* p, bool bIsDocBasic )
892 : SbxObject("StarBASIC"), bDocBasic( bIsDocBasic )
893{
894 SetParent( p );
895 bNoRtl = bBreak = false;
896 bVBAEnabled = false;
897
898 if( !GetSbData()->nInst++ )
899 {
900 GetSbData()->pSbFac.reset( new SbiFactory );
901 AddFactory( GetSbData()->pSbFac.get() );
902 GetSbData()->pTypeFac.reset(new SbTypeFactory);
903 AddFactory( GetSbData()->pTypeFac.get() );
904 GetSbData()->pClassFac.reset(new SbClassFactory);
905 AddFactory( GetSbData()->pClassFac.get() );
906 GetSbData()->pOLEFac.reset(new SbOLEFactory);
907 AddFactory( GetSbData()->pOLEFac.get() );
908 GetSbData()->pFormFac.reset(new SbFormFactory);
909 AddFactory( GetSbData()->pFormFac.get() );
910 GetSbData()->pUnoFac.reset( new SbUnoFactory );
911 AddFactory( GetSbData()->pUnoFac.get() );
912 }
913 pRtl = new SbiStdObject(SB_RTLNAME"@SBRTL", this );
914 // Search via StarBasic is always global
915 SetFlag( SbxFlagBits::GlobalSearch );
916 pVBAGlobals = nullptr;
917 bQuit = false;
918
919 if( bDocBasic )
920 {
921 lclInsertDocBasicItem( *this );
922 }
923}
924
925// #51727 Override SetModified so that the modified state
926// is not given to the parent
927void StarBASIC::SetModified( bool b )
928{
929 SbxBase::SetModified( b );
930}
931
932StarBASIC::~StarBASIC()
933{
934 // Needs to be first action as it can trigger events
935 disposeComVariablesForBasic( this );
936
937 if( !--GetSbData()->nInst )
938 {
939 RemoveFactory( GetSbData()->pSbFac.get() );
940 GetSbData()->pSbFac.reset();
941 RemoveFactory( GetSbData()->pUnoFac.get() );
942 GetSbData()->pUnoFac.reset();
943 RemoveFactory( GetSbData()->pTypeFac.get() );
944 GetSbData()->pTypeFac.reset();
945 RemoveFactory( GetSbData()->pClassFac.get() );
946 GetSbData()->pClassFac.reset();
947 RemoveFactory( GetSbData()->pOLEFac.get() );
948 GetSbData()->pOLEFac.reset();
949 RemoveFactory( GetSbData()->pFormFac.get() );
950 GetSbData()->pFormFac.reset();
951
952 if( SbiGlobals::pGlobals )
953 {
954 delete SbiGlobals::pGlobals;
955 SbiGlobals::pGlobals = nullptr;
956 }
957 }
958 else if( bDocBasic )
959 {
960 ErrCode eOld = SbxBase::GetError();
961
962 lclRemoveDocBasicItem( *this );
963
964 SbxBase::ResetError();
965 if( eOld != ERRCODE_NONEErrCode(0) )
966 {
967 SbxBase::SetError( eOld );
968 }
969 }
970
971 // #100326 Set Parent NULL in registered listeners
972 if( xUnoListeners.is() )
973 {
974 sal_uInt32 uCount = xUnoListeners->Count32();
975 for( sal_uInt32 i = 0 ; i < uCount ; i++ )
976 {
977 SbxVariable* pListenerObj = xUnoListeners->Get32( i );
978 pListenerObj->SetParent( nullptr );
979 }
980 xUnoListeners = nullptr;
981 }
982
983 clearUnoMethodsForBasic( this );
984}
985
986void StarBASIC::implClearDependingVarsOnDelete( StarBASIC* pDeletedBasic )
987{
988 if( this != pDeletedBasic )
989 {
990 for( const auto& pModule: pModules)
991 {
992 pModule->ClearVarsDependingOnDeletedBasic( pDeletedBasic );
993 }
994 }
995
996 for( sal_uInt32 nObj = 0; nObj < pObjs->Count32(); nObj++ )
997 {
998 SbxVariable* pVar = pObjs->Get32( nObj );
999 StarBASIC* pBasic = dynamic_cast<StarBASIC*>( pVar );
1000 if( pBasic && pBasic != pDeletedBasic )
1001 {
1002 pBasic->implClearDependingVarsOnDelete( pDeletedBasic );
1003 }
1004 }
1005}
1006
1007
1008SbModule* StarBASIC::MakeModule( const OUString& rName, const OUString& rSrc )
1009{
1010 ModuleInfo aInfo;
1011 aInfo.ModuleType = ModuleType::NORMAL;
1012 return MakeModule( rName, aInfo, rSrc );
1013}
1014SbModule* StarBASIC::MakeModule( const OUString& rName, const ModuleInfo& mInfo, const OUString& rSrc )
1015{
1016
1017 SAL_INFO(do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1018 "basic",do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1019 "create module " << rName << " type mInfo " << mInfo.ModuleType)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "create module " << rName << " type mInfo "
<< mInfo.ModuleType) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "create module " << rName <<
" type mInfo " << mInfo.ModuleType), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"create module " << rName << " type mInfo " <<
mInfo.ModuleType; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1019" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1020 SbModule* p = nullptr;
1021 switch ( mInfo.ModuleType )
1022 {
1023 case ModuleType::DOCUMENT:
1024 // In theory we should be able to create Object modules
1025 // in ordinary basic ( in vba mode thought these are create
1026 // by the application/basic and not by the user )
1027 p = new SbObjModule( rName, mInfo, isVBAEnabled() );
1028 break;
1029 case ModuleType::CLASS:
1030 p = new SbModule( rName, isVBAEnabled() );
1031 p->SetModuleType( ModuleType::CLASS );
1032 break;
1033 case ModuleType::FORM:
1034 p = new SbUserFormModule( rName, mInfo, isVBAEnabled() );
1035 break;
1036 default:
1037 p = new SbModule( rName, isVBAEnabled() );
1038 break;
1039 }
1040 p->SetSource32( rSrc );
1041 p->SetParent( this );
1042 pModules.emplace_back(p);
1043 SetModified( true );
1044 return p;
1045}
1046
1047void StarBASIC::Insert( SbxVariable* pVar )
1048{
1049 if( dynamic_cast<const SbModule*>(pVar) != nullptr)
1050 {
1051 pModules.emplace_back(static_cast<SbModule*>(pVar));
1052 pVar->SetParent( this );
1053 StartListening(pVar->GetBroadcaster(), DuplicateHandling::Prevent);
1054 }
1055 else
1056 {
1057 bool bWasModified = IsModified();
1058 SbxObject::Insert( pVar );
1059 if( !bWasModified && pVar->IsSet( SbxFlagBits::DontStore ) )
1060 {
1061 SetModified( false );
1062 }
1063 }
1064}
1065
1066void StarBASIC::Remove( SbxVariable* pVar )
1067{
1068 SbModule* pModule = dynamic_cast<SbModule*>(pVar);
1069 if( pModule )
1070 {
1071 // #87540 Can be last reference!
1072 SbModuleRef xVar = pModule;
1073 pModules.erase(std::remove(pModules.begin(), pModules.end(), xVar));
1074 pVar->SetParent( nullptr );
1075 EndListening( pVar->GetBroadcaster() );
1076 }
1077 else
1078 {
1079 SbxObject::Remove( pVar );
1080 }
1081}
1082
1083void StarBASIC::Clear()
1084{
1085 pModules.clear();
1086}
1087
1088SbModule* StarBASIC::FindModule( const OUString& rName )
1089{
1090 for (const auto& pModule: pModules)
1091 {
1092 if( pModule->GetName().equalsIgnoreAsciiCase( rName ) )
1093 {
1094 return pModule.get();
1095 }
1096 }
1097 return nullptr;
1098}
1099
1100
1101struct ClassModuleRunInitItem
1102{
1103 SbModule* m_pModule;
1104 bool m_bProcessing;
1105 bool m_bRunInitDone;
1106
1107 ClassModuleRunInitItem()
1108 : m_pModule( nullptr )
1109 , m_bProcessing( false )
1110 , m_bRunInitDone( false )
1111 {}
1112 explicit ClassModuleRunInitItem( SbModule* pModule )
1113 : m_pModule( pModule )
1114 , m_bProcessing( false )
1115 , m_bRunInitDone( false )
1116 {}
1117};
1118
1119// Derive from unordered_map type instead of typedef
1120// to allow forward declaration in sbmod.hxx
1121class ModuleInitDependencyMap : public
1122 std::unordered_map< OUString, ClassModuleRunInitItem >
1123{};
1124
1125void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap& rMap, ClassModuleRunInitItem& rItem )
1126{
1127 rItem.m_bProcessing = true;
1128
1129 SbModule* pModule = rItem.m_pModule;
1130 if( pModule->pClassData != nullptr )
1131 {
1132 std::vector< OUString >& rReqTypes = pModule->pClassData->maRequiredTypes;
1133 for( const auto& rStr : rReqTypes )
1134 {
1135 // Is required type a class module?
1136 ModuleInitDependencyMap::iterator itFind = rMap.find( rStr );
1137 if( itFind != rMap.end() )
1138 {
1139 ClassModuleRunInitItem& rParentItem = itFind->second;
1140 if( rParentItem.m_bProcessing )
1141 {
1142 // TODO: raise error?
1143 OSL_FAIL( "Cyclic module dependency detected" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1143" ": "), "%s", "Cyclic module dependency detected")
; } } while (false)
;
1144 continue;
1145 }
1146
1147 if( !rParentItem.m_bRunInitDone )
1148 {
1149 implProcessModuleRunInit( rMap, rParentItem );
1150 }
1151 }
1152 }
1153 }
1154
1155 pModule->RunInit();
1156 rItem.m_bRunInitDone = true;
1157 rItem.m_bProcessing = false;
1158}
1159
1160// Run Init-Code of all modules (including inserted libraries)
1161void StarBASIC::InitAllModules( StarBASIC const * pBasicNotToInit )
1162{
1163 SolarMutexGuard guard;
1164
1165 // Init own modules
1166 for (const auto& pModule: pModules)
1167 {
1168 pModule->Compile();
1169 }
1170 // compile modules first then RunInit ( otherwise there is
1171 // can be order dependency, e.g. classmodule A has a member
1172 // of type classmodule B and classmodule B hasn't been compiled yet )
1173
1174 // Consider required types to init in right order. Class modules
1175 // that are required by other modules have to be initialized first.
1176 ModuleInitDependencyMap aMIDMap;
1177 for (const auto& pModule: pModules)
1178 {
1179 OUString aModuleName = pModule->GetName();
1180 if( pModule->isProxyModule() )
1181 {
1182 aMIDMap[aModuleName] = ClassModuleRunInitItem( pModule.get() );
1183 }
1184 }
1185
1186 for (auto & elem : aMIDMap)
1187 {
1188 ClassModuleRunInitItem& rItem = elem.second;
1189 SbModule::implProcessModuleRunInit( aMIDMap, rItem );
1190 }
1191
1192 // Call RunInit on standard modules
1193 for (const auto& pModule: pModules)
1194 {
1195 if( !pModule->isProxyModule() )
1196 {
1197 pModule->RunInit();
1198 }
1199 }
1200
1201 // Check all objects if they are BASIC,
1202 // if yes initialize
1203 for ( sal_uInt32 nObj = 0; nObj < pObjs->Count32(); nObj++ )
1204 {
1205 SbxVariable* pVar = pObjs->Get32( nObj );
1206 StarBASIC* pBasic = dynamic_cast<StarBASIC*>( pVar );
1207 if( pBasic && pBasic != pBasicNotToInit )
1208 {
1209 pBasic->InitAllModules();
1210 }
1211 }
1212}
1213
1214// #88329 Put modules back to not initialised state to
1215// force reinitialisation at next start
1216void StarBASIC::DeInitAllModules()
1217{
1218 // Deinit own modules
1219 for (const auto& pModule: pModules)
1220 {
1221 if( pModule->pImage && !pModule->isProxyModule() && dynamic_cast<SbObjModule*>( pModule.get()) == nullptr )
1222 {
1223 pModule->pImage->bInit = false;
1224 }
1225 }
1226
1227 for ( sal_uInt32 nObj = 0; nObj < pObjs->Count32(); nObj++ )
1228 {
1229 SbxVariable* pVar = pObjs->Get32( nObj );
1230 StarBASIC* pBasic = dynamic_cast<StarBASIC*>( pVar );
1231 if( pBasic )
1232 {
1233 pBasic->DeInitAllModules();
1234 }
1235 }
1236}
1237
1238// This implementation at first searches within the runtime library,
1239// then it looks for an element within one module. This module can be
1240// a public var or an entrypoint. If it is not found and we look for a
1241// method and a module with the given name is found the search continues
1242// for entrypoint "Main".
1243// If this fails again a conventional search over objects is performend.
1244SbxVariable* StarBASIC::Find( const OUString& rName, SbxClassType t )
1245{
1246 SbxVariable* pRes = nullptr;
1247 SbModule* pNamed = nullptr;
1248 // "Extended" search in Runtime Lib
1249 // but only if SbiRuntime has not set the flag
1250 if( !bNoRtl )
1251 {
1252 if( t == SbxClassType::DontCare || t == SbxClassType::Object )
1253 {
1254 if( rName.equalsIgnoreAsciiCase( SB_RTLNAME"@SBRTL" ) )
1255 {
1256 pRes = pRtl.get();
1257 }
1258 }
1259 if( !pRes )
1260 {
1261 pRes = static_cast<SbiStdObject*>(pRtl.get())->Find( rName, t );
1262 }
1263 if( pRes )
1264 {
1265 pRes->SetFlag( SbxFlagBits::ExtFound );
1266 }
1267 }
1268 // Search module
1269 if( !pRes )
1270 {
1271 for (const auto& pModule: pModules)
1272 {
1273 if( pModule->IsVisible() )
1274 {
1275 // Remember module for Main() call
1276 // or is the name equal?!?
1277 if( pModule->GetName().equalsIgnoreAsciiCase( rName ) )
1278 {
1279 if( t == SbxClassType::Object || t == SbxClassType::DontCare )
1280 {
1281 pRes = pModule.get(); break;
1282 }
1283 pNamed = pModule.get();
1284 }
1285 // Only variables qualified by the Module Name e.g. Sheet1.foo
1286 // should work for Document && Class type Modules
1287 sal_Int32 nType = pModule->GetModuleType();
1288 if ( nType == ModuleType::DOCUMENT || nType == ModuleType::FORM )
1289 {
1290 continue;
1291 }
1292 // otherwise check if the element is available
1293 // unset GBLSEARCH-Flag (due to recursion)
1294 SbxFlagBits nGblFlag = pModule->GetFlags() & SbxFlagBits::GlobalSearch;
1295 pModule->ResetFlag( SbxFlagBits::GlobalSearch );
1296 pRes = pModule->Find( rName, t );
1297 pModule->SetFlag( nGblFlag );
1298 if( pRes )
1299 {
1300 break;
1301 }
1302 }
1303 }
1304 }
1305 OUString aMainStr("Main");
1306 if( !pRes && pNamed && ( t == SbxClassType::Method || t == SbxClassType::DontCare ) &&
1307 !pNamed->GetName().equalsIgnoreAsciiCase( aMainStr ) )
1308 {
1309 pRes = pNamed->Find( aMainStr, SbxClassType::Method );
1310 }
1311 if( !pRes )
1312 {
1313 pRes = SbxObject::Find( rName, t );
1314 }
1315 return pRes;
1316}
1317
1318bool StarBASIC::Call( const OUString& rName, SbxArray* pParam )
1319{
1320 bool bRes = SbxObject::Call( rName, pParam );
1321 if( !bRes )
1322 {
1323 ErrCode eErr = SbxBase::GetError();
1324 SbxBase::ResetError();
1325 if( eErr != ERRCODE_NONEErrCode(0) )
1326 {
1327 RTError( eErr, OUString(), 0, 0, 0 );
1328 }
1329 }
1330 return bRes;
1331}
1332
1333// Find method via name (e.g. query via BASIC IDE)
1334SbxBase* StarBASIC::FindSBXInCurrentScope( const OUString& rName )
1335{
1336 if( !GetSbData()->pInst )
1337 {
1338 return nullptr;
1339 }
1340 if( !GetSbData()->pInst->pRun )
1341 {
1342 return nullptr;
1343 }
1344 return GetSbData()->pInst->pRun->FindElementExtern( rName );
1345}
1346
1347void StarBASIC::QuitAndExitApplication()
1348{
1349 Stop();
1350 bQuit = true;
1351}
1352
1353void StarBASIC::Stop()
1354{
1355 SbiInstance* p = GetSbData()->pInst;
1356 if( p )
1357 p->Stop();
1358}
1359
1360bool StarBASIC::IsRunning()
1361{
1362 return GetSbData()->pInst != nullptr;
1363}
1364
1365SbMethod* StarBASIC::GetActiveMethod( sal_uInt16 nLevel )
1366{
1367 if( GetSbData()->pInst )
1368 {
1369 return GetSbData()->pInst->GetCaller( nLevel );
1370 }
1371 else
1372 {
1373 return nullptr;
1374 }
1375}
1376
1377SbModule* StarBASIC::GetActiveModule()
1378{
1379 if( GetSbData()->pInst && !GetSbData()->bCompilerError )
1380 {
1381 return GetSbData()->pInst->GetActiveModule();
1382 }
1383 else
1384 {
1385 return GetSbData()->pCompMod;
1386 }
1387}
1388
1389BasicDebugFlags StarBASIC::BreakPoint( sal_Int32 l, sal_Int32 c1, sal_Int32 c2 )
1390{
1391 SetErrorData( ERRCODE_NONEErrCode(0), l, c1, c2 );
1392 bBreak = true;
1393 if( GetSbData()->aBreakHdl.IsSet() )
1394 {
1395 return GetSbData()->aBreakHdl.Call( this );
1396 }
1397 else
1398 {
1399 return BreakHdl();
1400 }
1401}
1402
1403BasicDebugFlags StarBASIC::StepPoint( sal_Int32 l, sal_Int32 c1, sal_Int32 c2 )
1404{
1405 SetErrorData( ERRCODE_NONEErrCode(0), l, c1, c2 );
1406 bBreak = false;
1407 if( GetSbData()->aBreakHdl.IsSet() )
1408 {
1409 return GetSbData()->aBreakHdl.Call( this );
1410 }
1411 else
1412 {
1413 return BreakHdl();
1414 }
1415}
1416
1417BasicDebugFlags StarBASIC::BreakHdl()
1418{
1419 return aBreakHdl.IsSet() ? aBreakHdl.Call( this ) : BasicDebugFlags::Continue;
1420}
1421
1422// Calls for error handler and break handler
1423sal_uInt16 StarBASIC::GetLine() { return GetSbData()->nLine; }
1424sal_uInt16 StarBASIC::GetCol1() { return GetSbData()->nCol1; }
1425sal_uInt16 StarBASIC::GetCol2() { return GetSbData()->nCol2; }
1426
1427// Specific to error handler
1428ErrCode const & StarBASIC::GetErrorCode() { return GetSbData()->nCode; }
1429const OUString& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg; }
1430
1431// From 1996-03-29:
1432// The mapping between the old and the new error codes take place by searching
1433// through the table SFX_VB_ErrorTab[]. This is indeed not with good performance,
1434// but it consumes much less memory than corresponding switch blocks.
1435// Because the conversion of error codes has not to be fast. There is no
1436// binary search by VB Error -> Error SFX.
1437
1438// Map back new error codes to old, Sbx-compatible
1439sal_uInt16 StarBASIC::GetVBErrorCode( ErrCode nError )
1440{
1441 sal_uInt16 nRet = 0;
1442
1443 if( SbiRuntime::isVBAEnabled() )
1444 {
1445 if ( nError == ERRCODE_BASIC_ARRAY_FIXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 133 ) )
1446 return 10;
1447 else if ( nError == ERRCODE_BASIC_STRING_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 134 ) )
1448 return 14;
1449 else if ( nError == ERRCODE_BASIC_EXPR_TOO_COMPLEXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 135 ) )
1450 return 16;
1451 else if ( nError == ERRCODE_BASIC_OPER_NOT_PERFORMErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 136 ) )
1452 return 17;
1453 else if ( nError == ERRCODE_BASIC_TOO_MANY_DLLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 137 ) )
1454 return 47;
1455 else if ( nError == ERRCODE_BASIC_LOOP_NOT_INITErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 138 ) )
1456 return 92;
1457 else
1458 nRet = 0;
1459 }
1460
1461 // search loop
1462 const SFX_VB_ErrorItem* pErrItem;
1463 sal_uInt16 nIndex = 0;
1464 do
1465 {
1466 pErrItem = SFX_VB_ErrorTab + nIndex;
1467 if( pErrItem->nErrorSFX == nError )
1468 {
1469 nRet = pErrItem->nErrorVB;
1470 break;
1471 }
1472 nIndex++;
1473 }
1474 while( pErrItem->nErrorVB != 0xFFFF ); // up to end mark
1475 return nRet;
1476}
1477
1478ErrCode StarBASIC::GetSfxFromVBError( sal_uInt16 nError )
1479{
1480 ErrCode nRet = ERRCODE_NONEErrCode(0);
1481
1482 if( SbiRuntime::isVBAEnabled() )
1483 {
1484 switch( nError )
1485 {
1486 case 1:
1487 case 2:
1488 case 4:
1489 case 8:
1490 case 12:
1491 case 73:
1492 return ERRCODE_NONEErrCode(0);
1493 case 10:
1494 return ERRCODE_BASIC_ARRAY_FIXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 133 );
1495 case 14:
1496 return ERRCODE_BASIC_STRING_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 134 );
1497 case 16:
1498 return ERRCODE_BASIC_EXPR_TOO_COMPLEXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 135 );
1499 case 17:
1500 return ERRCODE_BASIC_OPER_NOT_PERFORMErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 136 );
1501 case 47:
1502 return ERRCODE_BASIC_TOO_MANY_DLLErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 137 );
1503 case 92:
1504 return ERRCODE_BASIC_LOOP_NOT_INITErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 138 );
1505 default:
1506 nRet = ERRCODE_NONEErrCode(0);
1507 }
1508 }
1509 const SFX_VB_ErrorItem* pErrItem;
1510 sal_uInt16 nIndex = 0;
1511 do
1512 {
1513 pErrItem = SFX_VB_ErrorTab + nIndex;
1514 if( pErrItem->nErrorVB == nError )
1515 {
1516 nRet = pErrItem->nErrorSFX;
1517 break;
1518 }
1519 else if( pErrItem->nErrorVB > nError )
1520 {
1521 break; // couldn't found anymore
1522 }
1523 nIndex++;
1524 }
1525 while( pErrItem->nErrorVB != 0xFFFF ); // up to end mark
1526 return nRet;
1527}
1528
1529// set Error- / Break-data
1530void StarBASIC::SetErrorData( ErrCode nCode, sal_uInt16 nLine,
1531 sal_uInt16 nCol1, sal_uInt16 nCol2 )
1532{
1533 SbiGlobals& aGlobals = *GetSbData();
1534 aGlobals.nCode = nCode;
1535 aGlobals.nLine = nLine;
1536 aGlobals.nCol1 = nCol1;
1537 aGlobals.nCol2 = nCol2;
1538}
1539
1540void StarBASIC::MakeErrorText( ErrCode nId, const OUString& aMsg )
1541{
1542 SolarMutexGuard aSolarGuard;
1543 sal_uInt16 nOldID = GetVBErrorCode( nId );
1544
1545 const char* pErrorMsg = nullptr;
1546 for (std::pair<const char *, ErrCode> const *pItem = RID_BASIC_START; pItem->second; ++pItem)
1547 {
1548 if (nId == pItem->second)
1549 {
1550 pErrorMsg = pItem->first;
1551 break;
1552 }
1553 }
1554
1555 if (pErrorMsg)
1556 {
1557 // merge message with additional text
1558 OUString sError = BasResId(pErrorMsg);
1559 OUStringBuffer aMsg1(sError);
1560 // replace argument placeholder with %s
1561 OUString aSrgStr( "$(ARG1)" );
1562 sal_Int32 nResult = sError.indexOf(aSrgStr);
1563
1564 if( nResult >= 0 )
1565 {
1566 aMsg1.remove(nResult, aSrgStr.getLength());
1567 aMsg1.insert(nResult, aMsg);
1568 }
1569 GetSbData()->aErrMsg = aMsg1.makeStringAndClear();
1570 }
1571 else if( nOldID != 0 )
1572 {
1573 OUString aStdMsg = "Error " + OUString::number(nOldID) +
1574 ": No error text available!";
1575 GetSbData()->aErrMsg = aStdMsg;
1576 }
1577 else
1578 {
1579 GetSbData()->aErrMsg.clear();
1580 }
1581}
1582
1583bool StarBASIC::CError( ErrCode code, const OUString& rMsg,
1584 sal_Int32 l, sal_Int32 c1, sal_Int32 c2 )
1585{
1586 SolarMutexGuard aSolarGuard;
1587
1588 // compiler error during runtime -> stop program
1589 if( IsRunning() )
1590 {
1591 // #109018 Check if running Basic is affected
1592 StarBASIC* pStartedBasic = GetSbData()->pInst->GetBasic();
1593 if( pStartedBasic != this )
1594 {
1595 return false;
1596 }
1597 Stop();
1598 }
1599
1600 // set flag, so that GlobalRunInit notice the error
1601 GetSbData()->bGlobalInitErr = true;
1602
1603 // tinker the error message
1604 MakeErrorText( code, rMsg );
1605
1606 // Implementation of the code for the string transport to SFX-Error
1607 if( !rMsg.isEmpty() )
1608 {
1609 code = *new StringErrorInfo( code, rMsg );
1610 }
1611 SetErrorData( code, l, c1, c2 );
1612 GetSbData()->bCompilerError = true;
1613 bool bRet;
1614 if( GetSbData()->aErrHdl.IsSet() )
1615 {
1616 bRet = GetSbData()->aErrHdl.Call( this );
1617 }
1618 else
1619 {
1620 bRet = ErrorHdl();
1621 }
1622 GetSbData()->bCompilerError = false; // only true for error handler
1623 return bRet;
1624}
1625
1626bool StarBASIC::RTError( ErrCode code, const OUString& rMsg, sal_Int32 l, sal_Int32 c1, sal_Int32 c2 )
1627{
1628 SolarMutexGuard aSolarGuard;
1629
1630 ErrCode c = code;
1631 if( c.GetClass() == ErrCodeClass::Compiler )
1632 {
1633 c = ERRCODE_NONEErrCode(0);
1634 }
1635 MakeErrorText( c, rMsg );
1636
1637 // Implementation of the code for the string transport to SFX-Error
1638 if( !rMsg.isEmpty() )
1639 {
1640 // very confusing, even though MakeErrorText sets up the error text
1641 // seems that this is not used ( if rMsg already has content )
1642 // In the case of VBA MakeErrorText also formats the error to be a little more
1643 // like vba ( adds an error number etc )
1644 if ( SbiRuntime::isVBAEnabled() && ( code == ERRCODE_BASIC_COMPATErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 132 ) ) )
1645 {
1646 OUString aTmp = "\'" + OUString::number(SbxErrObject::getUnoErrObject()->getNumber()) +
1647 "\'\n" + (!GetSbData()->aErrMsg.isEmpty() ? GetSbData()->aErrMsg : rMsg);
1648 code = *new StringErrorInfo( code, aTmp );
1649 }
1650 else
1651 {
1652 code = *new StringErrorInfo( code, rMsg );
1653 }
1654 }
1655
1656 SetErrorData( code, l, c1, c2 );
1657 if( GetSbData()->aErrHdl.IsSet() )
1658 {
1659 return GetSbData()->aErrHdl.Call( this );
1660 }
1661 else
1662 {
1663 return ErrorHdl();
1664 }
1665}
1666
1667void StarBASIC::Error( ErrCode n )
1668{
1669 Error( n, OUString() );
1670}
1671
1672void StarBASIC::Error( ErrCode n, const OUString& rMsg )
1673{
1674 if( GetSbData()->pInst )
1675 {
1676 GetSbData()->pInst->Error( n, rMsg );
1677 }
1678}
1679
1680void StarBASIC::FatalError( ErrCode n )
1681{
1682 if( GetSbData()->pInst )
1683 {
1684 GetSbData()->pInst->FatalError( n );
1685 }
1686}
1687
1688void StarBASIC::FatalError( ErrCode _errCode, const OUString& _details )
1689{
1690 if( GetSbData()->pInst )
1691 {
1692 GetSbData()->pInst->FatalError( _errCode, _details );
1693 }
1694}
1695
1696ErrCode StarBASIC::GetErrBasic()
1697{
1698 if( GetSbData()->pInst )
1699 {
1700 return GetSbData()->pInst->GetErr();
1701 }
1702 else
1703 {
1704 return ERRCODE_NONEErrCode(0);
1705 }
1706}
1707
1708// make the additional message for the RTL function error accessible
1709OUString StarBASIC::GetErrorMsg()
1710{
1711 if( GetSbData()->pInst )
1712 {
1713 return GetSbData()->pInst->GetErrorMsg();
1714 }
1715 else
1716 {
1717 return OUString();
1718 }
1719}
1720
1721sal_Int32 StarBASIC::GetErl()
1722{
1723 if( GetSbData()->pInst )
1724 {
1725 return GetSbData()->pInst->GetErl();
1726 }
1727 else
1728 {
1729 return 0;
1730 }
1731}
1732
1733bool StarBASIC::ErrorHdl()
1734{
1735 return aErrorHdl.Call( this );
1736}
1737
1738Link<StarBASIC*,bool> const & StarBASIC::GetGlobalErrorHdl()
1739{
1740 return GetSbData()->aErrHdl;
1741}
1742
1743void StarBASIC::SetGlobalErrorHdl( const Link<StarBASIC*,bool>& rLink )
1744{
1745 GetSbData()->aErrHdl = rLink;
1746}
1747
1748void StarBASIC::SetGlobalBreakHdl( const Link<StarBASIC*,BasicDebugFlags>& rLink )
1749{
1750 GetSbData()->aBreakHdl = rLink;
1751}
1752
1753SbxArrayRef const & StarBASIC::getUnoListeners()
1754{
1755 if( !xUnoListeners.is() )
1756 {
1757 xUnoListeners = new SbxArray();
1758 }
1759 return xUnoListeners;
1760}
1761
1762
1763bool StarBASIC::LoadData( SvStream& r, sal_uInt16 nVer )
1764{
1765 if( !SbxObject::LoadData( r, nVer ) )
1766 {
1767 return false;
1768 }
1769 // #95459 Delete dialogs, otherwise endless recursion
1770 // in SbxVariable::GetType() if dialogs are accessed
1771 sal_uInt32 nObjCount = pObjs->Count32();
1772 std::unique_ptr<SbxVariable*[]> ppDeleteTab(new SbxVariable*[ nObjCount ]);
1773 sal_uInt32 nObj;
1774
1775 for( nObj = 0 ; nObj < nObjCount ; nObj++ )
1776 {
1777 SbxVariable* pVar = pObjs->Get32( nObj );
1778 StarBASIC* pBasic = dynamic_cast<StarBASIC*>( pVar );
1779 ppDeleteTab[nObj] = pBasic ? nullptr : pVar;
1780 }
1781 for( nObj = 0 ; nObj < nObjCount ; nObj++ )
1782 {
1783 SbxVariable* pVar = ppDeleteTab[nObj];
1784 if( pVar )
1785 {
1786 pObjs->Remove( pVar );
1787 }
1788 }
1789 ppDeleteTab.reset();
1790
1791 sal_uInt16 nMod(0);
1792 pModules.clear();
1793 r.ReadUInt16( nMod );
1794 const size_t nMinSbxSize(14);
1795 const size_t nMaxPossibleEntries = r.remainingSize() / nMinSbxSize;
1796 if (nMod > nMaxPossibleEntries)
1797 {
1798 nMod = nMaxPossibleEntries;
1799 SAL_WARN("basic", "Parsing error: " << nMaxPossibleEntries <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPossibleEntries <<
" max possible entries, but " << nMod << " claimed, truncating"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"
), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPossibleEntries <<
" max possible entries, but " << nMod << " claimed, truncating"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"
), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1800 " max possible entries, but " << nMod << " claimed, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPossibleEntries <<
" max possible entries, but " << nMod << " claimed, truncating"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"
), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPossibleEntries <<
" max possible entries, but " << nMod << " claimed, truncating"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"
), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPossibleEntries
<< " max possible entries, but " << nMod <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1800" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1801 }
1802 for (sal_uInt16 i = 0; i < nMod; ++i)
1803 {
1804 SbxBase* pBase = SbxBase::Load( r );
1805 SbModule* pMod = dynamic_cast<SbModule*>(pBase);
1806 if( !pMod )
1807 {
1808 return false;
1809 }
1810 else if( dynamic_cast<const SbJScriptModule*>( pMod) != nullptr )
1811 {
1812 // assign Ref, so that pMod will be deleted
1813 SbModuleRef xDeleteRef = pMod;
1814 }
1815 else
1816 {
1817 pMod->SetParent( this );
1818 pModules.emplace_back(pMod );
1819 }
1820 }
1821 // HACK for SFX-Bullshit!
1822 SbxVariable* p = Find( "FALSE", SbxClassType::Property );
1823 if( p )
1824 {
1825 Remove( p );
1826 }
1827 p = Find( "TRUE", SbxClassType::Property );
1828 if( p )
1829 {
1830 Remove( p );
1831 }
1832 // End of the hacks!
1833 // Search via StarBASIC is at all times global
1834 DBG_ASSERT( IsSet( SbxFlagBits::GlobalSearch ), "Basic loaded without GBLSEARCH" )do { if (true && (!(IsSet( SbxFlagBits::GlobalSearch )
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1834" ": "), "%s", "Basic loaded without GBLSEARCH"); }
} while (false)
;
1835 SetFlag( SbxFlagBits::GlobalSearch );
1836 return true;
1837}
1838
1839bool StarBASIC::StoreData( SvStream& r ) const
1840{
1841 if( !SbxObject::StoreData( r ) )
1842 {
1843 return false;
1844 }
1845 assert(pModules.size() < SAL_MAX_UINT16)(static_cast <bool> (pModules.size() < ((sal_uInt16)
0xFFFF)) ? void (0) : __assert_fail ("pModules.size() < SAL_MAX_UINT16"
, "/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
, 1845, __extension__ __PRETTY_FUNCTION__))
;
1846 r.WriteUInt16( static_cast<sal_uInt16>(pModules.size()));
1847 for( const auto& rpModule: pModules )
1848 {
1849 if( !rpModule->Store( r ) )
1850 {
1851 return false;
1852 }
1853 }
1854 return true;
1855}
1856
1857bool StarBASIC::GetUNOConstant( const OUString& rName, css::uno::Any& aOut )
1858{
1859 bool bRes = false;
1860 SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( Find( rName, SbxClassType::DontCare ) );
1861 if ( pGlobs )
1862 {
1863 aOut = pGlobs->getUnoAny();
1864 bRes = true;
1865 }
1866 return bRes;
1867}
1868
1869Reference< frame::XModel > StarBASIC::GetModelFromBasic( SbxObject* pBasic )
1870{
1871 OSL_PRECOND( pBasic != nullptr, "getModelFromBasic: illegal call!" )do { if (true && (!(pBasic != nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1871" ": "), "%s", "getModelFromBasic: illegal call!");
} } while (false)
;
1872 if ( !pBasic )
1873 {
1874 return nullptr;
1875 }
1876 // look for the ThisComponent variable, first in the parent (which
1877 // might be the document's Basic), then in the parent's parent (which might be
1878 // the application Basic)
1879 const OUString sThisComponent( "ThisComponent");
1880 SbxVariable* pThisComponent = nullptr;
1881
1882 SbxObject* pLookup = pBasic->GetParent();
1883 while ( pLookup && !pThisComponent )
1884 {
1885 pThisComponent = pLookup->Find( sThisComponent, SbxClassType::Object );
1886 pLookup = pLookup->GetParent();
1887 }
1888 if ( !pThisComponent )
1889 {
1890 SAL_WARN("basic", "Failed to get ThisComponent")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Failed to get ThisComponent") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1890" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Failed to get ThisComponent"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Failed to get ThisComponent"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1890" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Failed to get ThisComponent") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1890" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Failed to get ThisComponent"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Failed to get ThisComponent"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sb.cxx"
":" "1890" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1891 // the application Basic, at the latest, should have this variable
1892 return nullptr;
1893 }
1894
1895 Any aThisComponentAny( sbxToUnoValue( pThisComponent ) );
1896 Reference< frame::XModel > xModel( aThisComponentAny, UNO_QUERY );
1897 if ( !xModel.is() )
1898 {
1899 // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller.
1900 Reference< frame::XController > xController( aThisComponentAny, UNO_QUERY );
1901 if ( xController.is() )
1902 {
1903 xModel = xController->getModel();
1904 }
1905 }
1906 if ( !xModel.is() )
1907 {
1908 return nullptr;
1909 }
1910
1911 return xModel;
1912}
1913
1914void StarBASIC::DetachAllDocBasicItems()
1915{
1916 std::unordered_map< const StarBASIC *, DocBasicItemRef >& rItems = GaDocBasicItems::get();
1917 for (auto const& item : rItems)
1918 {
1919 DocBasicItemRef xItem = item.second;
1920 xItem->setDisposed(true);
1921 }
1922}
1923
1924// #118116 Implementation Collection object
1925
1926
1927const char pCountStr[] = "Count";
1928const char pAddStr[] = "Add";
1929const char pItemStr[] = "Item";
1930const char pRemoveStr[] = "Remove";
1931static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, nRemoveHash;
1932
1933SbxInfoRef BasicCollection::xAddInfo;
1934SbxInfoRef BasicCollection::xItemInfo;
1935
1936BasicCollection::BasicCollection( const OUString& rClass )
1937 : SbxObject( rClass )
1938{
1939 if( !nCountHash )
1940 {
1941 nCountHash = MakeHashCode( pCountStr );
1942 nAddHash = MakeHashCode( pAddStr );
1943 nItemHash = MakeHashCode( pItemStr );
1944 nRemoveHash = MakeHashCode( pRemoveStr );
1945 }
1946 Initialize();
1947
1948}
1949
1950BasicCollection::~BasicCollection()
1951{}
1952
1953void BasicCollection::Clear()
1954{
1955 SbxObject::Clear();
1956 Initialize();
1957}
1958
1959void BasicCollection::Initialize()
1960{
1961 xItemArray = new SbxArray();
1962 SetType( SbxOBJECT );
1963 SetFlag( SbxFlagBits::Fixed );
1964 ResetFlag( SbxFlagBits::Write );
1965 SbxVariable* p;
1966 p = Make( pCountStr, SbxClassType::Property, SbxINTEGER );
1967 p->ResetFlag( SbxFlagBits::Write );
1968 p->SetFlag( SbxFlagBits::DontStore );
1969 p = Make( pAddStr, SbxClassType::Method, SbxEMPTY );
1970 p->SetFlag( SbxFlagBits::DontStore );
1971 p = Make( pItemStr, SbxClassType::Method, SbxVARIANT );
1972 p->SetFlag( SbxFlagBits::DontStore );
1973 p = Make( pRemoveStr, SbxClassType::Method, SbxEMPTY );
1974 p->SetFlag( SbxFlagBits::DontStore );
1975 if ( !xAddInfo.is() )
1976 {
1977 xAddInfo = new SbxInfo;
1978 xAddInfo->AddParam( "Item", SbxVARIANT );
1979 xAddInfo->AddParam( "Key", SbxVARIANT, SbxFlagBits::Read | SbxFlagBits::Optional );
1980 xAddInfo->AddParam( "Before", SbxVARIANT, SbxFlagBits::Read | SbxFlagBits::Optional );
1981 xAddInfo->AddParam( "After", SbxVARIANT, SbxFlagBits::Read | SbxFlagBits::Optional );
1982 }
1983 if ( !xItemInfo.is() )
1984 {
1985 xItemInfo = new SbxInfo;
1986 xItemInfo->AddParam( "Index", SbxVARIANT, SbxFlagBits::Read | SbxFlagBits::Optional);
1987 }
1988}
1989
1990void BasicCollection::Notify( SfxBroadcaster& rCst, const SfxHint& rHint )
1991{
1992 const SbxHint* p = dynamic_cast<const SbxHint*>(&rHint);
1993 if( p
0.1
'p' is non-null
0.1
'p' is non-null
)
1
Taking true branch
1994 {
1995 const SfxHintId nId = p->GetId();
1996 bool bRead = nId == SfxHintId::BasicDataWanted;
2
Assuming 'nId' is equal to BasicDataWanted
1997 bool bWrite = nId == SfxHintId::BasicDataChanged;
1998 bool bRequestInfo = nId == SfxHintId::BasicInfoWanted;
1999 SbxVariable* pVar = p->GetVar();
2000 SbxArray* pArg = pVar->GetParameters();
2001 OUString aVarName( pVar->GetName() );
2002 if( bRead
2.1
'bRead' is true
2.1
'bRead' is true
|| bWrite )
2003 {
2004 if( pVar->GetHashCode() == nCountHash
3
Assuming the condition is false
2005 && aVarName.equalsIgnoreAsciiCase( pCountStr ) )
2006 {
2007 pVar->PutLong( xItemArray->Count32() );
2008 }
2009 else if( pVar->GetHashCode() == nAddHash
4
Assuming the condition is true
5
Taking true branch
2010 && aVarName.equalsIgnoreAsciiCase( pAddStr ) )
2011 {
2012 CollAdd( pArg );
6
Calling 'BasicCollection::CollAdd'
2013 }
2014 else if( pVar->GetHashCode() == nItemHash
2015 && aVarName.equalsIgnoreAsciiCase( pItemStr ) )
2016 {
2017 CollItem( pArg );
2018 }
2019 else if( pVar->GetHashCode() == nRemoveHash
2020 && aVarName.equalsIgnoreAsciiCase( pRemoveStr ) )
2021 {
2022 CollRemove( pArg );
2023 }
2024 else
2025 {
2026 SbxObject::Notify( rCst, rHint );
2027 }
2028 return;
2029 }
2030 else if ( bRequestInfo )
2031 {
2032 if( pVar->GetHashCode() == nAddHash
2033 && aVarName.equalsIgnoreAsciiCase( pAddStr ) )
2034 {
2035 pVar->SetInfo( xAddInfo.get() );
2036 }
2037 else if( pVar->GetHashCode() == nItemHash
2038 && aVarName.equalsIgnoreAsciiCase( pItemStr ) )
2039 {
2040 pVar->SetInfo( xItemInfo.get() );
2041 }
2042 }
2043 }
2044 SbxObject::Notify( rCst, rHint );
2045}
2046
2047sal_Int32 BasicCollection::implGetIndex( SbxVariable const * pIndexVar )
2048{
2049 sal_Int32 nIndex = -1;
2050 if( pIndexVar->GetType() == SbxSTRING )
2051 {
2052 nIndex = implGetIndexForName( pIndexVar->GetOUString() );
2053 }
2054 else
2055 {
2056 nIndex = pIndexVar->GetLong() - 1;
2057 }
2058 return nIndex;
2059}
2060
2061sal_Int32 BasicCollection::implGetIndexForName( const OUString& rName )
2062{
2063 sal_Int32 nIndex = -1;
2064 sal_Int32 nCount = xItemArray->Count32();
2065 sal_Int32 nNameHash = MakeHashCode( rName );
2066 for( sal_Int32 i = 0 ; i < nCount ; i++ )
2067 {
2068 SbxVariable* pVar = xItemArray->Get32( i );
2069 if( pVar->GetHashCode() == nNameHash &&
2070 pVar->GetName().equalsIgnoreAsciiCase( rName ) )
2071 {
2072 nIndex = i;
2073 break;
2074 }
2075 }
2076 return nIndex;
2077}
2078
2079void BasicCollection::CollAdd( SbxArray* pPar_ )
2080{
2081 sal_uInt32 nCount = pPar_->Count32();
2082 if( nCount < 2 || nCount > 5 )
7
Assuming 'nCount' is >= 2
8
Assuming 'nCount' is <= 5
9
Taking false branch
2083 {
2084 SetError( ERRCODE_BASIC_WRONG_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 28) );
2085 return;
2086 }
2087
2088 SbxVariable* pItem = pPar_->Get32(1);
2089 if( pItem )
10
Assuming 'pItem' is non-null
11
Taking true branch
2090 {
2091 sal_uInt32 nNextIndex;
2092 if( nCount < 4 )
12
Assuming 'nCount' is < 4
13
Taking true branch
2093 {
2094 nNextIndex = xItemArray->Count32();
2095 }
2096 else
2097 {
2098 SbxVariable* pBefore = pPar_->Get32(3);
2099 if( nCount == 5 )
2100 {
2101 if( !( pBefore->IsErr() || ( pBefore->GetType() == SbxEMPTY ) ) )
2102 {
2103 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2104 return;
2105 }
2106 SbxVariable* pAfter = pPar_->Get32(4);
2107 sal_Int32 nAfterIndex = implGetIndex( pAfter );
2108 if( nAfterIndex == -1 )
2109 {
2110 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2111 return;
2112 }
2113 nNextIndex = sal::static_int_cast<sal_uInt32>(nAfterIndex + 1);
2114 }
2115 else // if( nCount == 4 )
2116 {
2117 sal_Int32 nBeforeIndex = implGetIndex( pBefore );
2118 if( nBeforeIndex == -1 )
2119 {
2120 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2121 return;
2122 }
2123 nNextIndex = sal::static_int_cast<sal_uInt32>(nBeforeIndex);
2124 }
2125 }
2126
2127 auto pNewItem = tools::make_ref<SbxVariable>( *pItem );
14
Calling 'make_ref<SbxVariable, SbxVariable &>'
16
Returned allocated memory
2128 if( nCount >= 3 )
17
Assuming 'nCount' is >= 3
18
Taking true branch
2129 {
2130 SbxVariable* pKey = pPar_->Get32(2);
2131 if( !( pKey->IsErr() || ( pKey->GetType() == SbxEMPTY ) ) )
19
Assuming the condition is false
20
Taking true branch
2132 {
2133 if( pKey->GetType() != SbxSTRING )
21
Assuming the condition is true
22
Taking true branch
2134 {
2135 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2136 return;
2137 }
2138 OUString aKey = pKey->GetOUString();
2139 if( implGetIndexForName( aKey ) != -1 )
2140 {
2141 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2142 return;
2143 }
2144 pNewItem->SetName( aKey );
2145 }
2146 }
2147 pNewItem->SetFlag( SbxFlagBits::ReadWrite );
2148 xItemArray->Insert32( pNewItem.get(), nNextIndex );
2149 }
2150 else
2151 {
2152 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2153 return;
2154 }
2155}
23
Potential leak of memory pointed to by 'pNewItem.pObj'
2156
2157void BasicCollection::CollItem( SbxArray* pPar_ )
2158{
2159 if( pPar_->Count32() != 2 )
2160 {
2161 SetError( ERRCODE_BASIC_WRONG_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 28) );
2162 return;
2163 }
2164 SbxVariable* pRes = nullptr;
2165 SbxVariable* p = pPar_->Get32( 1 );
2166 sal_Int32 nIndex = implGetIndex( p );
2167 if( nIndex >= 0 && nIndex < static_cast<sal_Int32>(xItemArray->Count32()) )
2168 {
2169 pRes = xItemArray->Get32( nIndex );
2170 }
2171 if( !pRes )
2172 {
2173 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2174 }
2175 else
2176 {
2177 *(pPar_->Get32(0)) = *pRes;
2178 }
2179}
2180
2181void BasicCollection::CollRemove( SbxArray* pPar_ )
2182{
2183 if( pPar_ == nullptr || pPar_->Count32() != 2 )
2184 {
2185 SetError( ERRCODE_BASIC_WRONG_ARGSErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 28) );
2186 return;
2187 }
2188
2189 SbxVariable* p = pPar_->Get32( 1 );
2190 sal_Int32 nIndex = implGetIndex( p );
2191 if( nIndex >= 0 && nIndex < static_cast<sal_Int32>(xItemArray->Count32()) )
2192 {
2193 xItemArray->Remove( nIndex );
2194
2195 // Correct for stack if necessary
2196 SbiInstance* pInst = GetSbData()->pInst;
2197 SbiRuntime* pRT = pInst ? pInst->pRun : nullptr;
2198 if( pRT )
2199 {
2200 SbiForStack* pStack = pRT->FindForStackItemForCollection( this );
2201 if( pStack != nullptr )
2202 {
2203 if( pStack->nCurCollectionIndex >= nIndex )
2204 {
2205 --pStack->nCurCollectionIndex;
2206 }
2207 }
2208 }
2209 }
2210 else
2211 {
2212 SetError( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) );
2213 }
2214}
2215
2216/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

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