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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
52 | using namespace ::com::sun::star::script; | ||||
53 | |||||
54 | #define SB_RTLNAME"@SBRTL" "@SBRTL" | ||||
55 | // i#i68894# | ||||
56 | using namespace ::com::sun::star; | ||||
57 | using namespace ::com::sun::star::uno; | ||||
58 | using com::sun::star::uno::Reference; | ||||
59 | using com::sun::star::uno::Any; | ||||
60 | using com::sun::star::uno::UNO_QUERY; | ||||
61 | using com::sun::star::lang::XMultiServiceFactory; | ||||
62 | |||||
63 | |||||
64 | class DocBasicItem : public ::cppu::WeakImplHelper< util::XCloseListener > | ||||
65 | { | ||||
66 | public: | ||||
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 | |||||
87 | private: | ||||
88 | StarBASIC& mrDocBasic; | ||||
89 | SbxObjectRef mxClassModules; | ||||
90 | bool mbDocClosed; | ||||
91 | bool mbDisposed; | ||||
92 | }; | ||||
93 | |||||
94 | |||||
95 | DocBasicItem::DocBasicItem( StarBASIC& rDocBasic ) : | ||||
96 | mrDocBasic( rDocBasic ), | ||||
97 | mxClassModules( new SbxObject( OUString() ) ), | ||||
98 | mbDocClosed( false ), | ||||
99 | mbDisposed( false ) | ||||
100 | { | ||||
101 | } | ||||
102 | |||||
103 | DocBasicItem::~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 | |||||
127 | void DocBasicItem::clearDependingVarsOnDelete( StarBASIC& rDeletedBasic ) | ||||
128 | { | ||||
129 | mrDocBasic.implClearDependingVarsOnDelete( &rDeletedBasic ); | ||||
130 | } | ||||
131 | |||||
132 | void 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 | |||||
144 | void 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 | |||||
159 | void SAL_CALL DocBasicItem::queryClosing( const lang::EventObject& /*rSource*/, sal_Bool /*bGetsOwnership*/ ) | ||||
160 | { | ||||
161 | } | ||||
162 | |||||
163 | void SAL_CALL DocBasicItem::notifyClosing( const lang::EventObject& /*rEvent*/ ) | ||||
164 | { | ||||
165 | stopListening(); | ||||
166 | mbDocClosed = true; | ||||
167 | } | ||||
168 | |||||
169 | void SAL_CALL DocBasicItem::disposing( const lang::EventObject& /*rEvent*/ ) | ||||
170 | { | ||||
171 | stopListening(); | ||||
172 | } | ||||
173 | |||||
174 | |||||
175 | namespace { | ||||
176 | |||||
177 | typedef ::rtl::Reference< DocBasicItem > DocBasicItemRef; | ||||
178 | |||||
179 | class GaDocBasicItems : public rtl::Static<std::unordered_map< const StarBASIC *, DocBasicItemRef >,GaDocBasicItems> {}; | ||||
180 | |||||
181 | const 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 | |||||
188 | void lclInsertDocBasicItem( StarBASIC& rDocBasic ) | ||||
189 | { | ||||
190 | DocBasicItemRef& rxDocBasicItem = GaDocBasicItems::get()[ &rDocBasic ]; | ||||
191 | rxDocBasicItem.set( new DocBasicItem( rDocBasic ) ); | ||||
192 | rxDocBasicItem->startListening(); | ||||
193 | } | ||||
194 | |||||
195 | void 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 | |||||
209 | StarBASIC* 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 | |||||
229 | SbxObject* 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# | ||||
255 | SbxVariable* 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 | |||||
269 | namespace { | ||||
270 | |||||
271 | // Create array for conversion SFX <-> VB error code | ||||
272 | struct SFX_VB_ErrorItem | ||||
273 | { | ||||
274 | sal_uInt16 nErrorVB; | ||||
275 | ErrCode nErrorSFX; | ||||
276 | }; | ||||
277 | |||||
278 | } | ||||
279 | |||||
280 | const 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 | |||||
412 | SbxBase* 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 | |||||
435 | SbxObject* 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 | |||||
466 | SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 ) | ||||
467 | { | ||||
468 | // Not supported | ||||
469 | return nullptr; | ||||
470 | } | ||||
471 | |||||
472 | SbxObject* 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 | |||||
481 | SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 ) | ||||
482 | { | ||||
483 | // Not supported | ||||
484 | return nullptr; | ||||
485 | } | ||||
486 | |||||
487 | SbxObject* 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 | |||||
516 | SbxObject* 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 | |||||
575 | SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 ) | ||||
576 | { | ||||
577 | // Not supported | ||||
578 | return nullptr; | ||||
579 | } | ||||
580 | |||||
581 | SbxObject* 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 | |||||
596 | SbxObject* createUserTypeImpl( const OUString& rClassName ) | ||||
597 | { | ||||
598 | SbxObject* pRetObj = GetSbData()->pTypeFac->CreateObject( rClassName ); | ||||
599 | return pRetObj; | ||||
600 | } | ||||
601 | |||||
602 | |||||
603 | SbClassModuleObject::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 | |||||
746 | SbClassModuleObject::~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 | |||||
761 | void SbClassModuleObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | ||||
762 | { | ||||
763 | handleProcedureProperties( rBC, rHint ); | ||||
764 | } | ||||
765 | |||||
766 | SbxVariable* 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 | |||||
783 | void 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 | |||||
801 | void 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 | |||||
817 | SbClassData::SbClassData() | ||||
818 | { | ||||
819 | mxIfaces = new SbxArray(); | ||||
820 | } | ||||
821 | |||||
822 | void SbClassData::clear() | ||||
823 | { | ||||
824 | mxIfaces->Clear(); | ||||
825 | maRequiredTypes.clear(); | ||||
826 | } | ||||
827 | |||||
828 | SbClassFactory::SbClassFactory() | ||||
829 | { | ||||
830 | xClassModules = new SbxObject( OUString() ); | ||||
831 | } | ||||
832 | |||||
833 | SbClassFactory::~SbClassFactory() | ||||
834 | {} | ||||
835 | |||||
836 | void 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 | |||||
849 | void SbClassFactory::RemoveClassModule( SbModule* pClassModule ) | ||||
850 | { | ||||
851 | xClassModules->Remove( pClassModule ); | ||||
852 | } | ||||
853 | |||||
854 | SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 ) | ||||
855 | { | ||||
856 | // Not supported | ||||
857 | return nullptr; | ||||
858 | } | ||||
859 | |||||
860 | SbxObject* 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 | |||||
884 | SbModule* 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 | |||||
891 | StarBASIC::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 | ||||
927 | void StarBASIC::SetModified( bool b ) | ||||
928 | { | ||||
929 | SbxBase::SetModified( b ); | ||||
930 | } | ||||
931 | |||||
932 | StarBASIC::~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 | |||||
986 | void 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 | |||||
1008 | SbModule* StarBASIC::MakeModule( const OUString& rName, const OUString& rSrc ) | ||||
1009 | { | ||||
1010 | ModuleInfo aInfo; | ||||
1011 | aInfo.ModuleType = ModuleType::NORMAL; | ||||
1012 | return MakeModule( rName, aInfo, rSrc ); | ||||
1013 | } | ||||
1014 | SbModule* 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 | |||||
1047 | void 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 | |||||
1066 | void 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 | |||||
1083 | void StarBASIC::Clear() | ||||
1084 | { | ||||
1085 | pModules.clear(); | ||||
1086 | } | ||||
1087 | |||||
1088 | SbModule* 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 | |||||
1101 | struct 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 | ||||
1121 | class ModuleInitDependencyMap : public | ||||
1122 | std::unordered_map< OUString, ClassModuleRunInitItem > | ||||
1123 | {}; | ||||
1124 | |||||
1125 | void 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) | ||||
1161 | void 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 | ||||
1216 | void 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. | ||||
1244 | SbxVariable* 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 | |||||
1318 | bool 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) | ||||
1334 | SbxBase* 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 | |||||
1347 | void StarBASIC::QuitAndExitApplication() | ||||
1348 | { | ||||
1349 | Stop(); | ||||
1350 | bQuit = true; | ||||
1351 | } | ||||
1352 | |||||
1353 | void StarBASIC::Stop() | ||||
1354 | { | ||||
1355 | SbiInstance* p = GetSbData()->pInst; | ||||
1356 | if( p ) | ||||
1357 | p->Stop(); | ||||
1358 | } | ||||
1359 | |||||
1360 | bool StarBASIC::IsRunning() | ||||
1361 | { | ||||
1362 | return GetSbData()->pInst != nullptr; | ||||
1363 | } | ||||
1364 | |||||
1365 | SbMethod* 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 | |||||
1377 | SbModule* 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 | |||||
1389 | BasicDebugFlags 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 | |||||
1403 | BasicDebugFlags 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 | |||||
1417 | BasicDebugFlags StarBASIC::BreakHdl() | ||||
1418 | { | ||||
1419 | return aBreakHdl.IsSet() ? aBreakHdl.Call( this ) : BasicDebugFlags::Continue; | ||||
1420 | } | ||||
1421 | |||||
1422 | // Calls for error handler and break handler | ||||
1423 | sal_uInt16 StarBASIC::GetLine() { return GetSbData()->nLine; } | ||||
1424 | sal_uInt16 StarBASIC::GetCol1() { return GetSbData()->nCol1; } | ||||
1425 | sal_uInt16 StarBASIC::GetCol2() { return GetSbData()->nCol2; } | ||||
1426 | |||||
1427 | // Specific to error handler | ||||
1428 | ErrCode const & StarBASIC::GetErrorCode() { return GetSbData()->nCode; } | ||||
1429 | const 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 | ||||
1439 | sal_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 | |||||
1478 | ErrCode 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 | ||||
1530 | void 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 | |||||
1540 | void 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 | |||||
1583 | bool 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 | |||||
1626 | bool 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 | |||||
1667 | void StarBASIC::Error( ErrCode n ) | ||||
1668 | { | ||||
1669 | Error( n, OUString() ); | ||||
1670 | } | ||||
1671 | |||||
1672 | void StarBASIC::Error( ErrCode n, const OUString& rMsg ) | ||||
1673 | { | ||||
1674 | if( GetSbData()->pInst ) | ||||
1675 | { | ||||
1676 | GetSbData()->pInst->Error( n, rMsg ); | ||||
1677 | } | ||||
1678 | } | ||||
1679 | |||||
1680 | void StarBASIC::FatalError( ErrCode n ) | ||||
1681 | { | ||||
1682 | if( GetSbData()->pInst ) | ||||
1683 | { | ||||
1684 | GetSbData()->pInst->FatalError( n ); | ||||
1685 | } | ||||
1686 | } | ||||
1687 | |||||
1688 | void StarBASIC::FatalError( ErrCode _errCode, const OUString& _details ) | ||||
1689 | { | ||||
1690 | if( GetSbData()->pInst ) | ||||
1691 | { | ||||
1692 | GetSbData()->pInst->FatalError( _errCode, _details ); | ||||
1693 | } | ||||
1694 | } | ||||
1695 | |||||
1696 | ErrCode 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 | ||||
1709 | OUString StarBASIC::GetErrorMsg() | ||||
1710 | { | ||||
1711 | if( GetSbData()->pInst ) | ||||
1712 | { | ||||
1713 | return GetSbData()->pInst->GetErrorMsg(); | ||||
1714 | } | ||||
1715 | else | ||||
1716 | { | ||||
1717 | return OUString(); | ||||
1718 | } | ||||
1719 | } | ||||
1720 | |||||
1721 | sal_Int32 StarBASIC::GetErl() | ||||
1722 | { | ||||
1723 | if( GetSbData()->pInst ) | ||||
1724 | { | ||||
1725 | return GetSbData()->pInst->GetErl(); | ||||
1726 | } | ||||
1727 | else | ||||
1728 | { | ||||
1729 | return 0; | ||||
1730 | } | ||||
1731 | } | ||||
1732 | |||||
1733 | bool StarBASIC::ErrorHdl() | ||||
1734 | { | ||||
1735 | return aErrorHdl.Call( this ); | ||||
1736 | } | ||||
1737 | |||||
1738 | Link<StarBASIC*,bool> const & StarBASIC::GetGlobalErrorHdl() | ||||
1739 | { | ||||
1740 | return GetSbData()->aErrHdl; | ||||
1741 | } | ||||
1742 | |||||
1743 | void StarBASIC::SetGlobalErrorHdl( const Link<StarBASIC*,bool>& rLink ) | ||||
1744 | { | ||||
1745 | GetSbData()->aErrHdl = rLink; | ||||
1746 | } | ||||
1747 | |||||
1748 | void StarBASIC::SetGlobalBreakHdl( const Link<StarBASIC*,BasicDebugFlags>& rLink ) | ||||
1749 | { | ||||
1750 | GetSbData()->aBreakHdl = rLink; | ||||
1751 | } | ||||
1752 | |||||
1753 | SbxArrayRef const & StarBASIC::getUnoListeners() | ||||
1754 | { | ||||
1755 | if( !xUnoListeners.is() ) | ||||
1756 | { | ||||
1757 | xUnoListeners = new SbxArray(); | ||||
1758 | } | ||||
1759 | return xUnoListeners; | ||||
1760 | } | ||||
1761 | |||||
1762 | |||||
1763 | bool 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 | |||||
1839 | bool 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 | |||||
1857 | bool 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 | |||||
1869 | Reference< 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 | |||||
1914 | void 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 | |||||
1927 | const char pCountStr[] = "Count"; | ||||
1928 | const char pAddStr[] = "Add"; | ||||
1929 | const char pItemStr[] = "Item"; | ||||
1930 | const char pRemoveStr[] = "Remove"; | ||||
1931 | static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, nRemoveHash; | ||||
1932 | |||||
1933 | SbxInfoRef BasicCollection::xAddInfo; | ||||
1934 | SbxInfoRef BasicCollection::xItemInfo; | ||||
1935 | |||||
1936 | BasicCollection::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 | |||||
1950 | BasicCollection::~BasicCollection() | ||||
1951 | {} | ||||
1952 | |||||
1953 | void BasicCollection::Clear() | ||||
1954 | { | ||||
1955 | SbxObject::Clear(); | ||||
1956 | Initialize(); | ||||
1957 | } | ||||
1958 | |||||
1959 | void 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 | |||||
1990 | void BasicCollection::Notify( SfxBroadcaster& rCst, const SfxHint& rHint ) | ||||
1991 | { | ||||
1992 | const SbxHint* p = dynamic_cast<const SbxHint*>(&rHint); | ||||
1993 | if( p
| ||||
| |||||
1994 | { | ||||
1995 | const SfxHintId nId = p->GetId(); | ||||
1996 | bool bRead = nId == SfxHintId::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
| ||||
2003 | { | ||||
2004 | if( pVar->GetHashCode() == nCountHash | ||||
2005 | && aVarName.equalsIgnoreAsciiCase( pCountStr ) ) | ||||
2006 | { | ||||
2007 | pVar->PutLong( xItemArray->Count32() ); | ||||
2008 | } | ||||
2009 | else if( pVar->GetHashCode() == nAddHash | ||||
2010 | && aVarName.equalsIgnoreAsciiCase( pAddStr ) ) | ||||
2011 | { | ||||
2012 | CollAdd( pArg ); | ||||
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 | |||||
2047 | sal_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 | |||||
2061 | sal_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 | |||||
2079 | void BasicCollection::CollAdd( SbxArray* pPar_ ) | ||||
2080 | { | ||||
2081 | sal_uInt32 nCount = pPar_->Count32(); | ||||
2082 | if( nCount < 2 || nCount > 5 ) | ||||
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 ) | ||||
2090 | { | ||||
2091 | sal_uInt32 nNextIndex; | ||||
2092 | if( nCount < 4 ) | ||||
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 ); | ||||
2128 | if( nCount >= 3 ) | ||||
2129 | { | ||||
2130 | SbxVariable* pKey = pPar_->Get32(2); | ||||
2131 | if( !( pKey->IsErr() || ( pKey->GetType() == SbxEMPTY ) ) ) | ||||
2132 | { | ||||
2133 | if( pKey->GetType() != SbxSTRING ) | ||||
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 | } | ||||
| |||||
2156 | |||||
2157 | void 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 | |||||
2181 | void 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: */ |
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 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
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 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class 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 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
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 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
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 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
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 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
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: */ |