File: | home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx |
Warning: | line 2752, column 5 Use of memory after it is freed |
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 <sal/config.h> | ||||
21 | |||||
22 | #include <o3tl/any.hxx> | ||||
23 | #include <osl/mutex.hxx> | ||||
24 | #include <vcl/svapp.hxx> | ||||
25 | #include <vcl/errcode.hxx> | ||||
26 | #include <svl/hint.hxx> | ||||
27 | |||||
28 | #include <cppuhelper/implbase.hxx> | ||||
29 | #include <cppuhelper/exc_hlp.hxx> | ||||
30 | #include <comphelper/interfacecontainer2.hxx> | ||||
31 | #include <comphelper/extract.hxx> | ||||
32 | #include <comphelper/processfactory.hxx> | ||||
33 | #include <cppuhelper/weakref.hxx> | ||||
34 | |||||
35 | #include <rtl/instance.hxx> | ||||
36 | #include <rtl/ustrbuf.hxx> | ||||
37 | |||||
38 | #include <com/sun/star/script/ArrayWrapper.hpp> | ||||
39 | #include <com/sun/star/script/CannotConvertException.hpp> | ||||
40 | #include <com/sun/star/script/NativeObjectWrapper.hpp> | ||||
41 | |||||
42 | #include <com/sun/star/uno/XComponentContext.hpp> | ||||
43 | #include <com/sun/star/uno/DeploymentException.hpp> | ||||
44 | #include <com/sun/star/lang/XTypeProvider.hpp> | ||||
45 | #include <com/sun/star/lang/XSingleServiceFactory.hpp> | ||||
46 | #include <com/sun/star/lang/XMultiServiceFactory.hpp> | ||||
47 | #include <com/sun/star/lang/XServiceInfo.hpp> | ||||
48 | #include <com/sun/star/beans/PropertyAttribute.hpp> | ||||
49 | #include <com/sun/star/beans/PropertyConcept.hpp> | ||||
50 | #include <com/sun/star/beans/MethodConcept.hpp> | ||||
51 | #include <com/sun/star/beans/XPropertySet.hpp> | ||||
52 | #include <com/sun/star/beans/theIntrospection.hpp> | ||||
53 | #include <com/sun/star/script/BasicErrorException.hpp> | ||||
54 | #include <com/sun/star/script/InvocationAdapterFactory.hpp> | ||||
55 | #include <com/sun/star/script/XAllListener.hpp> | ||||
56 | #include <com/sun/star/script/Converter.hpp> | ||||
57 | #include <com/sun/star/script/XDefaultProperty.hpp> | ||||
58 | #include <com/sun/star/script/XDirectInvocation.hpp> | ||||
59 | #include <com/sun/star/container/XNameAccess.hpp> | ||||
60 | #include <com/sun/star/container/XHierarchicalNameAccess.hpp> | ||||
61 | #include <com/sun/star/reflection/XIdlArray.hpp> | ||||
62 | #include <com/sun/star/reflection/XIdlReflection.hpp> | ||||
63 | #include <com/sun/star/reflection/XServiceConstructorDescription.hpp> | ||||
64 | #include <com/sun/star/reflection/XSingletonTypeDescription.hpp> | ||||
65 | #include <com/sun/star/reflection/theCoreReflection.hpp> | ||||
66 | #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp> | ||||
67 | #include <com/sun/star/bridge/oleautomation/Date.hpp> | ||||
68 | #include <com/sun/star/bridge/oleautomation/Decimal.hpp> | ||||
69 | #include <com/sun/star/bridge/oleautomation/Currency.hpp> | ||||
70 | #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp> | ||||
71 | #include <com/sun/star/script/XAutomationInvocation.hpp> | ||||
72 | |||||
73 | #include <rtlproto.hxx> | ||||
74 | |||||
75 | #include <basic/sbstar.hxx> | ||||
76 | #include <basic/sbuno.hxx> | ||||
77 | #include <basic/sberrors.hxx> | ||||
78 | #include <sbunoobj.hxx> | ||||
79 | #include <sbintern.hxx> | ||||
80 | #include <runtime.hxx> | ||||
81 | |||||
82 | #include <algorithm> | ||||
83 | #include <math.h> | ||||
84 | #include <memory> | ||||
85 | #include <unordered_map> | ||||
86 | #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> | ||||
87 | #include <com/sun/star/reflection/XConstantsTypeDescription.hpp> | ||||
88 | |||||
89 | using com::sun::star::uno::Reference; | ||||
90 | using namespace com::sun::star::uno; | ||||
91 | using namespace com::sun::star::lang; | ||||
92 | using namespace com::sun::star::reflection; | ||||
93 | using namespace com::sun::star::beans; | ||||
94 | using namespace com::sun::star::script; | ||||
95 | using namespace com::sun::star::container; | ||||
96 | using namespace com::sun::star::bridge; | ||||
97 | using namespace cppu; | ||||
98 | |||||
99 | |||||
100 | // Identifiers for creating the strings for dbg_Properties | ||||
101 | char16_t constexpr ID_DBG_SUPPORTEDINTERFACES[] = u"Dbg_SupportedInterfaces"; | ||||
102 | char const ID_DBG_PROPERTIES[] = "Dbg_Properties"; | ||||
103 | char const ID_DBG_METHODS[] = "Dbg_Methods"; | ||||
104 | |||||
105 | char const aSeqLevelStr[] = "[]"; | ||||
106 | |||||
107 | // Gets the default property for a uno object. Note: There is some | ||||
108 | // redirection built in. The property name specifies the name | ||||
109 | // of the default property. | ||||
110 | |||||
111 | bool SbUnoObject::getDefaultPropName( SbUnoObject const * pUnoObj, OUString& sDfltProp ) | ||||
112 | { | ||||
113 | bool bResult = false; | ||||
114 | Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY ); | ||||
115 | if ( xDefaultProp.is() ) | ||||
116 | { | ||||
117 | sDfltProp = xDefaultProp->getDefaultPropertyName(); | ||||
118 | if ( !sDfltProp.isEmpty() ) | ||||
119 | bResult = true; | ||||
120 | } | ||||
121 | return bResult; | ||||
122 | } | ||||
123 | |||||
124 | SbxVariable* getDefaultProp( SbxVariable* pRef ) | ||||
125 | { | ||||
126 | SbxVariable* pDefaultProp = nullptr; | ||||
127 | if ( pRef->GetType() == SbxOBJECT ) | ||||
128 | { | ||||
129 | SbxObject* pObj = dynamic_cast<SbxObject*>(pRef); | ||||
130 | if (!pObj) | ||||
131 | { | ||||
132 | SbxBase* pObjVarObj = pRef->GetObject(); | ||||
133 | pObj = dynamic_cast<SbxObject*>( pObjVarObj ); | ||||
134 | } | ||||
135 | if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) | ||||
136 | { | ||||
137 | pDefaultProp = pUnoObj->GetDfltProperty(); | ||||
138 | } | ||||
139 | } | ||||
140 | return pDefaultProp; | ||||
141 | } | ||||
142 | |||||
143 | void SetSbUnoObjectDfltPropName( SbxObject* pObj ) | ||||
144 | { | ||||
145 | SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj ); | ||||
146 | if ( pUnoObj ) | ||||
147 | { | ||||
148 | OUString sDfltPropName; | ||||
149 | |||||
150 | if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) ) | ||||
151 | { | ||||
152 | pUnoObj->SetDfltProperty( sDfltPropName ); | ||||
153 | } | ||||
154 | } | ||||
155 | } | ||||
156 | |||||
157 | // save CoreReflection statically | ||||
158 | static Reference< XIdlReflection > getCoreReflection_Impl() | ||||
159 | { | ||||
160 | return css::reflection::theCoreReflection::get( | ||||
161 | comphelper::getProcessComponentContext()); | ||||
162 | } | ||||
163 | |||||
164 | // save CoreReflection statically | ||||
165 | static Reference< XHierarchicalNameAccess > const & getCoreReflection_HierarchicalNameAccess_Impl() | ||||
166 | { | ||||
167 | static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess; | ||||
168 | |||||
169 | if( !xCoreReflection_HierarchicalNameAccess.is() ) | ||||
170 | { | ||||
171 | Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); | ||||
172 | if( xCoreReflection.is() ) | ||||
173 | { | ||||
174 | xCoreReflection_HierarchicalNameAccess = | ||||
175 | Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY ); | ||||
176 | } | ||||
177 | } | ||||
178 | return xCoreReflection_HierarchicalNameAccess; | ||||
179 | } | ||||
180 | |||||
181 | // Hold TypeProvider statically | ||||
182 | static Reference< XHierarchicalNameAccess > const & getTypeProvider_Impl() | ||||
183 | { | ||||
184 | static Reference< XHierarchicalNameAccess > xAccess; | ||||
185 | |||||
186 | // Do we have already CoreReflection; if not obtain it | ||||
187 | if( !xAccess.is() ) | ||||
188 | { | ||||
189 | Reference< XComponentContext > xContext( | ||||
190 | comphelper::getProcessComponentContext() ); | ||||
191 | if( xContext.is() ) | ||||
192 | { | ||||
193 | xContext->getValueByName( | ||||
194 | "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) | ||||
195 | >>= xAccess; | ||||
196 | OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" )do { if (true && (!(xAccess.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" ":" "196" ": "), "%s", "### TypeDescriptionManager singleton not accessible!?" ); } } while (false); | ||||
197 | } | ||||
198 | if( !xAccess.is() ) | ||||
199 | { | ||||
200 | throw DeploymentException( | ||||
201 | "/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible" ); | ||||
202 | } | ||||
203 | } | ||||
204 | return xAccess; | ||||
205 | } | ||||
206 | |||||
207 | // Hold TypeConverter statically | ||||
208 | static Reference< XTypeConverter > const & getTypeConverter_Impl() | ||||
209 | { | ||||
210 | static Reference< XTypeConverter > xTypeConverter; | ||||
211 | |||||
212 | // Do we have already CoreReflection; if not obtain it | ||||
213 | if( !xTypeConverter.is() ) | ||||
214 | { | ||||
215 | Reference< XComponentContext > xContext( | ||||
216 | comphelper::getProcessComponentContext() ); | ||||
217 | if( xContext.is() ) | ||||
218 | { | ||||
219 | xTypeConverter = Converter::create(xContext); | ||||
220 | } | ||||
221 | if( !xTypeConverter.is() ) | ||||
222 | { | ||||
223 | throw DeploymentException( | ||||
224 | "com.sun.star.script.Converter service not accessible" ); | ||||
225 | } | ||||
226 | } | ||||
227 | return xTypeConverter; | ||||
228 | } | ||||
229 | |||||
230 | |||||
231 | // #111851 factory function to create an OLE object | ||||
232 | SbUnoObject* createOLEObject_Impl( const OUString& aType ) | ||||
233 | { | ||||
234 | static Reference< XMultiServiceFactory > xOLEFactory; | ||||
235 | static bool bNeedsInit = true; | ||||
236 | |||||
237 | if( bNeedsInit ) | ||||
238 | { | ||||
239 | bNeedsInit = false; | ||||
240 | |||||
241 | Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); | ||||
242 | if( xContext.is() ) | ||||
243 | { | ||||
244 | Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager(); | ||||
245 | xOLEFactory.set( | ||||
246 | xSMgr->createInstanceWithContext( "com.sun.star.bridge.OleObjectFactory", xContext ), | ||||
247 | UNO_QUERY ); | ||||
248 | } | ||||
249 | } | ||||
250 | |||||
251 | SbUnoObject* pUnoObj = nullptr; | ||||
252 | if( xOLEFactory.is() ) | ||||
253 | { | ||||
254 | // some type names available in VBA can not be directly used in COM | ||||
255 | OUString aOLEType = aType; | ||||
256 | if ( aOLEType == "SAXXMLReader30" ) | ||||
257 | { | ||||
258 | aOLEType = "Msxml2.SAXXMLReader.3.0"; | ||||
259 | } | ||||
260 | Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType ); | ||||
261 | if( xOLEObject.is() ) | ||||
262 | { | ||||
263 | pUnoObj = new SbUnoObject( aType, Any(xOLEObject) ); | ||||
264 | OUString sDfltPropName; | ||||
265 | |||||
266 | if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) ) | ||||
267 | pUnoObj->SetDfltProperty( sDfltPropName ); | ||||
268 | } | ||||
269 | } | ||||
270 | return pUnoObj; | ||||
271 | } | ||||
272 | |||||
273 | |||||
274 | namespace | ||||
275 | { | ||||
276 | void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel ) | ||||
277 | { | ||||
278 | while ( _nLevel-- > 0 ) | ||||
279 | { | ||||
280 | _inout_rBuffer.append( " " ); | ||||
281 | } | ||||
282 | } | ||||
283 | } | ||||
284 | |||||
285 | static void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, const OUString& _rExceptionType, sal_Int32 _nLevel ) | ||||
286 | { | ||||
287 | _inout_rBuffer.append( "\n" ); | ||||
288 | lcl_indent( _inout_rBuffer, _nLevel ); | ||||
289 | _inout_rBuffer.append( "Type: " ); | ||||
290 | |||||
291 | if ( _rExceptionType.isEmpty() ) | ||||
292 | _inout_rBuffer.append( "Unknown" ); | ||||
293 | else | ||||
294 | _inout_rBuffer.append( _rExceptionType ); | ||||
295 | |||||
296 | _inout_rBuffer.append( "\n" ); | ||||
297 | lcl_indent( _inout_rBuffer, _nLevel ); | ||||
298 | _inout_rBuffer.append( "Message: " ); | ||||
299 | _inout_rBuffer.append( _e.Message ); | ||||
300 | |||||
301 | } | ||||
302 | |||||
303 | // construct an error message for the exception | ||||
304 | static OUString implGetExceptionMsg( const Exception& e, const OUString& aExceptionType_ ) | ||||
305 | { | ||||
306 | OUStringBuffer aMessageBuf; | ||||
307 | implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 ); | ||||
308 | return aMessageBuf.makeStringAndClear(); | ||||
309 | } | ||||
310 | |||||
311 | static OUString implGetExceptionMsg( const Any& _rCaughtException ) | ||||
312 | { | ||||
313 | auto e = o3tl::tryAccess<Exception>(_rCaughtException); | ||||
314 | OSL_PRECOND( e, "implGetExceptionMsg: illegal argument!" )do { if (true && (!(e))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" ":" "314" ": "), "%s", "implGetExceptionMsg: illegal argument!" ); } } while (false); | ||||
315 | if ( !e ) | ||||
316 | { | ||||
317 | return OUString(); | ||||
318 | } | ||||
319 | return implGetExceptionMsg( *e, _rCaughtException.getValueTypeName() ); | ||||
320 | } | ||||
321 | |||||
322 | static Any convertAny( const Any& rVal, const Type& aDestType ) | ||||
323 | { | ||||
324 | Any aConvertedVal; | ||||
325 | const Reference< XTypeConverter >& xConverter = getTypeConverter_Impl(); | ||||
326 | try | ||||
327 | { | ||||
328 | aConvertedVal = xConverter->convertTo( rVal, aDestType ); | ||||
329 | } | ||||
330 | catch( const IllegalArgumentException& ) | ||||
331 | { | ||||
332 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), | ||||
333 | implGetExceptionMsg( ::cppu::getCaughtException() ) ); | ||||
334 | return aConvertedVal; | ||||
335 | } | ||||
336 | catch( const CannotConvertException& e2 ) | ||||
337 | { | ||||
338 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), | ||||
339 | implGetExceptionMsg( e2, "com.sun.star.lang.IllegalArgumentException" ) ); | ||||
340 | return aConvertedVal; | ||||
341 | } | ||||
342 | return aConvertedVal; | ||||
343 | } | ||||
344 | |||||
345 | |||||
346 | // #105565 Special Object to wrap a strongly typed Uno Any | ||||
347 | |||||
348 | |||||
349 | // TODO: source out later | ||||
350 | static Reference<XIdlClass> TypeToIdlClass( const Type& rType ) | ||||
351 | { | ||||
352 | return getCoreReflection_Impl()->forName(rType.getTypeName()); | ||||
353 | } | ||||
354 | |||||
355 | // Exception type unknown | ||||
356 | template< class EXCEPTION > | ||||
357 | static OUString implGetExceptionMsg( const EXCEPTION& e ) | ||||
358 | { | ||||
359 | return implGetExceptionMsg( e, cppu::UnoType<decltype(e)>::get().getTypeName() ); | ||||
360 | } | ||||
361 | |||||
362 | static void implHandleBasicErrorException( BasicErrorException const & e ) | ||||
363 | { | ||||
364 | ErrCode nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(e.ErrorCode) ); | ||||
365 | StarBASIC::Error( nError, e.ErrorMessageArgument ); | ||||
366 | } | ||||
367 | |||||
368 | static void implHandleWrappedTargetException( const Any& _rWrappedTargetException ) | ||||
369 | { | ||||
370 | Any aExamine( _rWrappedTargetException ); | ||||
371 | |||||
372 | // completely strip the first InvocationTargetException, its error message isn't of any | ||||
373 | // interest to the user, it just says something like "invoking the UNO method went wrong.". | ||||
374 | InvocationTargetException aInvocationError; | ||||
375 | if ( aExamine >>= aInvocationError ) | ||||
376 | aExamine = aInvocationError.TargetException; | ||||
377 | |||||
378 | BasicErrorException aBasicError; | ||||
379 | |||||
380 | ErrCode nError( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ) ); | ||||
381 | OUStringBuffer aMessageBuf; | ||||
382 | |||||
383 | // strip any other WrappedTargetException instances, but this time preserve the error messages. | ||||
384 | WrappedTargetException aWrapped; | ||||
385 | sal_Int32 nLevel = 0; | ||||
386 | while ( aExamine >>= aWrapped ) | ||||
387 | { | ||||
388 | // special handling for BasicErrorException errors | ||||
389 | if ( aWrapped.TargetException >>= aBasicError ) | ||||
390 | { | ||||
391 | nError = StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16>(aBasicError.ErrorCode) ); | ||||
392 | aMessageBuf.append( aBasicError.ErrorMessageArgument ); | ||||
393 | aExamine.clear(); | ||||
394 | break; | ||||
395 | } | ||||
396 | |||||
397 | // append this round's message | ||||
398 | implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel ); | ||||
399 | if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION ) | ||||
400 | // there is a next chain element | ||||
401 | aMessageBuf.append( "\nTargetException:" ); | ||||
402 | |||||
403 | // next round | ||||
404 | aExamine = aWrapped.TargetException; | ||||
405 | ++nLevel; | ||||
406 | } | ||||
407 | |||||
408 | if ( auto e = o3tl::tryAccess<Exception>(aExamine) ) | ||||
409 | { | ||||
410 | // the last element in the chain is still an exception, but no WrappedTargetException | ||||
411 | implAppendExceptionMsg( aMessageBuf, *e, aExamine.getValueTypeName(), nLevel ); | ||||
412 | } | ||||
413 | |||||
414 | StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() ); | ||||
415 | } | ||||
416 | |||||
417 | static void implHandleAnyException( const Any& _rCaughtException ) | ||||
418 | { | ||||
419 | BasicErrorException aBasicError; | ||||
420 | WrappedTargetException aWrappedError; | ||||
421 | |||||
422 | if ( _rCaughtException >>= aBasicError ) | ||||
423 | { | ||||
424 | implHandleBasicErrorException( aBasicError ); | ||||
425 | } | ||||
426 | else if ( _rCaughtException >>= aWrappedError ) | ||||
427 | { | ||||
428 | implHandleWrappedTargetException( _rCaughtException ); | ||||
429 | } | ||||
430 | else | ||||
431 | { | ||||
432 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), implGetExceptionMsg( _rCaughtException ) ); | ||||
433 | } | ||||
434 | } | ||||
435 | |||||
436 | namespace { | ||||
437 | |||||
438 | // NativeObjectWrapper handling | ||||
439 | struct ObjectItem | ||||
440 | { | ||||
441 | SbxObjectRef m_xNativeObj; | ||||
442 | |||||
443 | explicit ObjectItem( SbxObject* pNativeObj ) | ||||
444 | : m_xNativeObj( pNativeObj ) | ||||
445 | {} | ||||
446 | }; | ||||
447 | |||||
448 | } | ||||
449 | |||||
450 | typedef std::vector< ObjectItem > NativeObjectWrapperVector; | ||||
451 | |||||
452 | namespace { | ||||
453 | |||||
454 | class GaNativeObjectWrapperVector : public rtl::Static<NativeObjectWrapperVector, GaNativeObjectWrapperVector> {}; | ||||
455 | |||||
456 | } | ||||
457 | |||||
458 | void clearNativeObjectWrapperVector() | ||||
459 | { | ||||
460 | GaNativeObjectWrapperVector::get().clear(); | ||||
461 | } | ||||
462 | |||||
463 | static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj ) | ||||
464 | { | ||||
465 | NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get(); | ||||
466 | sal_uInt32 nIndex = rNativeObjectWrapperVector.size(); | ||||
467 | rNativeObjectWrapperVector.emplace_back( pNativeObj ); | ||||
468 | return nIndex; | ||||
469 | } | ||||
470 | |||||
471 | static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex ) | ||||
472 | { | ||||
473 | SbxObjectRef xRetObj; | ||||
474 | NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get(); | ||||
475 | if( nIndex < rNativeObjectWrapperVector.size() ) | ||||
476 | { | ||||
477 | ObjectItem& rItem = rNativeObjectWrapperVector[ nIndex ]; | ||||
478 | xRetObj = rItem.m_xNativeObj; | ||||
479 | } | ||||
480 | return xRetObj.get(); | ||||
481 | } | ||||
482 | |||||
483 | // convert from Uno to Sbx | ||||
484 | static SbxDataType unoToSbxType( TypeClass eType ) | ||||
485 | { | ||||
486 | SbxDataType eRetType = SbxVOID; | ||||
487 | |||||
488 | switch( eType ) | ||||
489 | { | ||||
490 | case TypeClass_INTERFACE: | ||||
491 | case TypeClass_TYPE: | ||||
492 | case TypeClass_STRUCT: | ||||
493 | case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break; | ||||
494 | |||||
495 | case TypeClass_ENUM: eRetType = SbxLONG; break; | ||||
496 | case TypeClass_SEQUENCE: | ||||
497 | eRetType = SbxDataType( SbxOBJECT | SbxARRAY ); | ||||
498 | break; | ||||
499 | |||||
500 | |||||
501 | case TypeClass_ANY: eRetType = SbxVARIANT; break; | ||||
502 | case TypeClass_BOOLEAN: eRetType = SbxBOOL; break; | ||||
503 | case TypeClass_CHAR: eRetType = SbxCHAR; break; | ||||
504 | case TypeClass_STRING: eRetType = SbxSTRING; break; | ||||
505 | case TypeClass_FLOAT: eRetType = SbxSINGLE; break; | ||||
506 | case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break; | ||||
507 | case TypeClass_BYTE: eRetType = SbxINTEGER; break; | ||||
508 | case TypeClass_SHORT: eRetType = SbxINTEGER; break; | ||||
509 | case TypeClass_LONG: eRetType = SbxLONG; break; | ||||
510 | case TypeClass_HYPER: eRetType = SbxSALINT64; break; | ||||
511 | case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break; | ||||
512 | case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break; | ||||
513 | case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break; | ||||
514 | default: break; | ||||
515 | } | ||||
516 | return eRetType; | ||||
517 | } | ||||
518 | |||||
519 | static SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass ) | ||||
520 | { | ||||
521 | SbxDataType eRetType = SbxVOID; | ||||
522 | if( xIdlClass.is() ) | ||||
523 | { | ||||
524 | TypeClass eType = xIdlClass->getTypeClass(); | ||||
525 | eRetType = unoToSbxType( eType ); | ||||
526 | } | ||||
527 | return eRetType; | ||||
528 | } | ||||
529 | |||||
530 | static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32 dimension, bool bIsZeroIndex, Type const * pType ) | ||||
531 | { | ||||
532 | const Type& aType = aValue.getValueType(); | ||||
533 | TypeClass eTypeClass = aType.getTypeClass(); | ||||
534 | |||||
535 | sal_Int32 dimCopy = dimension; | ||||
536 | |||||
537 | if ( eTypeClass == TypeClass_SEQUENCE ) | ||||
538 | { | ||||
539 | Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); | ||||
540 | Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); | ||||
541 | typelib_TypeDescription * pTD = nullptr; | ||||
542 | aType.getDescription( &pTD ); | ||||
543 | Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType ); | ||||
544 | ::typelib_typedescription_release( pTD ); | ||||
545 | |||||
546 | sal_Int32 nLen = xIdlArray->getLen( aValue ); | ||||
547 | for ( sal_Int32 index = 0; index < nLen; ++index ) | ||||
548 | { | ||||
549 | Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(index) ); | ||||
550 | // This detects the dimension were currently processing | ||||
551 | if ( dimCopy == dimension ) | ||||
552 | { | ||||
553 | ++dimCopy; | ||||
554 | if ( sizes.getLength() < dimCopy ) | ||||
555 | { | ||||
556 | sizes.realloc( sizes.getLength() + 1 ); | ||||
557 | sizes[ sizes.getLength() - 1 ] = nLen; | ||||
558 | indices.realloc( indices.getLength() + 1 ); | ||||
559 | } | ||||
560 | } | ||||
561 | |||||
562 | if ( bIsZeroIndex ) | ||||
563 | indices[ dimCopy - 1 ] = index; | ||||
564 | else | ||||
565 | indices[ dimCopy - 1] = index + 1; | ||||
566 | |||||
567 | implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType ); | ||||
568 | } | ||||
569 | |||||
570 | } | ||||
571 | else | ||||
572 | { | ||||
573 | if ( !indices.hasElements() ) | ||||
574 | { | ||||
575 | // Should never ever get here ( indices.getLength() | ||||
576 | // should equal number of dimensions in the array ) | ||||
577 | // And that should at least be 1 ! | ||||
578 | // #QUESTION is there a better error? | ||||
579 | StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECTErrCode( ErrCodeArea::Sbx, ErrCodeClass::Access, 17) ); | ||||
580 | return; | ||||
581 | } | ||||
582 | |||||
583 | SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() ); | ||||
584 | if ( !pArray ) | ||||
585 | { | ||||
586 | pArray = new SbxDimArray( eSbxElementType ); | ||||
587 | sal_Int32 nIndexLen = indices.getLength(); | ||||
588 | |||||
589 | // Dimension the array | ||||
590 | for ( sal_Int32 index = 0; index < nIndexLen; ++index ) | ||||
591 | { | ||||
592 | if ( bIsZeroIndex ) | ||||
593 | pArray->unoAddDim32( 0, sizes[ index ] - 1); | ||||
594 | else | ||||
595 | pArray->unoAddDim32( 1, sizes[ index ] ); | ||||
596 | |||||
597 | } | ||||
598 | } | ||||
599 | |||||
600 | if ( pArray ) | ||||
601 | { | ||||
602 | auto xVar = tools::make_ref<SbxVariable>( eSbxElementType ); | ||||
603 | unoToSbxValue( xVar.get(), aValue ); | ||||
604 | |||||
605 | sal_Int32* pIndices = indices.getArray(); | ||||
606 | pArray->Put32( xVar.get(), pIndices ); | ||||
607 | |||||
608 | } | ||||
609 | } | ||||
610 | } | ||||
611 | |||||
612 | void unoToSbxValue( SbxVariable* pVar, const Any& aValue ) | ||||
613 | { | ||||
614 | const Type& aType = aValue.getValueType(); | ||||
615 | TypeClass eTypeClass = aType.getTypeClass(); | ||||
616 | switch( eTypeClass ) | ||||
617 | { | ||||
618 | case TypeClass_TYPE: | ||||
619 | { | ||||
620 | // Map Type to IdlClass | ||||
621 | Type aType_; | ||||
622 | aValue >>= aType_; | ||||
623 | Reference<XIdlClass> xClass = TypeToIdlClass( aType_ ); | ||||
624 | Any aClassAny; | ||||
625 | aClassAny <<= xClass; | ||||
626 | |||||
627 | // instantiate SbUnoObject | ||||
628 | SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aClassAny ); | ||||
629 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); | ||||
630 | |||||
631 | // If the object is invalid deliver null | ||||
632 | if( !pSbUnoObject->getUnoAny().hasValue() ) | ||||
633 | { | ||||
634 | pVar->PutObject( nullptr ); | ||||
635 | } | ||||
636 | else | ||||
637 | { | ||||
638 | pVar->PutObject( xWrapper.get() ); | ||||
639 | } | ||||
640 | } | ||||
641 | break; | ||||
642 | // Interfaces and Structs must be wrapped in a SbUnoObject | ||||
643 | case TypeClass_INTERFACE: | ||||
644 | case TypeClass_STRUCT: | ||||
645 | case TypeClass_EXCEPTION: | ||||
646 | { | ||||
647 | if( eTypeClass == TypeClass_STRUCT ) | ||||
648 | { | ||||
649 | ArrayWrapper aWrap; | ||||
650 | NativeObjectWrapper aNativeObjectWrapper; | ||||
651 | if ( aValue >>= aWrap ) | ||||
652 | { | ||||
653 | SbxDimArray* pArray = nullptr; | ||||
654 | Sequence< sal_Int32 > indices; | ||||
655 | Sequence< sal_Int32 > sizes; | ||||
656 | implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, /*dimension*/0, aWrap.IsZeroIndex, nullptr ); | ||||
657 | if ( pArray ) | ||||
658 | { | ||||
659 | SbxDimArrayRef xArray = pArray; | ||||
660 | SbxFlagBits nFlags = pVar->GetFlags(); | ||||
661 | pVar->ResetFlag( SbxFlagBits::Fixed ); | ||||
662 | pVar->PutObject( xArray.get() ); | ||||
663 | pVar->SetFlags( nFlags ); | ||||
664 | } | ||||
665 | else | ||||
666 | pVar->PutEmpty(); | ||||
667 | break; | ||||
668 | } | ||||
669 | else if ( aValue >>= aNativeObjectWrapper ) | ||||
670 | { | ||||
671 | sal_uInt32 nIndex = 0; | ||||
672 | if( aNativeObjectWrapper.ObjectId >>= nIndex ) | ||||
673 | { | ||||
674 | SbxObject* pObj = lcl_getNativeObject( nIndex ); | ||||
675 | pVar->PutObject( pObj ); | ||||
676 | } | ||||
677 | else | ||||
678 | pVar->PutEmpty(); | ||||
679 | break; | ||||
680 | } | ||||
681 | else | ||||
682 | { | ||||
683 | SbiInstance* pInst = GetSbData()->pInst; | ||||
684 | if( pInst && pInst->IsCompatibility() ) | ||||
685 | { | ||||
686 | oleautomation::Date aDate; | ||||
687 | if( aValue >>= aDate ) | ||||
688 | { | ||||
689 | pVar->PutDate( aDate.Value ); | ||||
690 | break; | ||||
691 | } | ||||
692 | else | ||||
693 | { | ||||
694 | oleautomation::Decimal aDecimal; | ||||
695 | if( aValue >>= aDecimal ) | ||||
696 | { | ||||
697 | pVar->PutDecimal( aDecimal ); | ||||
698 | break; | ||||
699 | } | ||||
700 | else | ||||
701 | { | ||||
702 | oleautomation::Currency aCurrency; | ||||
703 | if( aValue >>= aCurrency ) | ||||
704 | { | ||||
705 | pVar->PutCurrency( aCurrency.Value ); | ||||
706 | break; | ||||
707 | } | ||||
708 | } | ||||
709 | } | ||||
710 | } | ||||
711 | } | ||||
712 | } | ||||
713 | // instantiate a SbUnoObject | ||||
714 | SbUnoObject* pSbUnoObject = new SbUnoObject( OUString(), aValue ); | ||||
715 | //If this is called externally e.g. from the scripting | ||||
716 | //framework then there is no 'active' runtime the default property will not be set up | ||||
717 | //only a vba object will have XDefaultProp set anyway so... this | ||||
718 | //test seems a bit of overkill | ||||
719 | //if ( SbiRuntime::isVBAEnabled() ) | ||||
720 | { | ||||
721 | OUString sDfltPropName; | ||||
722 | |||||
723 | if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) ) | ||||
724 | { | ||||
725 | pSbUnoObject->SetDfltProperty( sDfltPropName ); | ||||
726 | } | ||||
727 | } | ||||
728 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); | ||||
729 | |||||
730 | // If the object is invalid deliver null | ||||
731 | if( !pSbUnoObject->getUnoAny().hasValue() ) | ||||
732 | { | ||||
733 | pVar->PutObject( nullptr ); | ||||
734 | } | ||||
735 | else | ||||
736 | { | ||||
737 | pVar->PutObject( xWrapper.get() ); | ||||
738 | } | ||||
739 | } | ||||
740 | break; | ||||
741 | |||||
742 | |||||
743 | case TypeClass_ENUM: | ||||
744 | { | ||||
745 | sal_Int32 nEnum = 0; | ||||
746 | enum2int( nEnum, aValue ); | ||||
747 | pVar->PutLong( nEnum ); | ||||
748 | } | ||||
749 | break; | ||||
750 | |||||
751 | case TypeClass_SEQUENCE: | ||||
752 | { | ||||
753 | Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType ); | ||||
754 | Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray(); | ||||
755 | sal_Int32 i, nLen = xIdlArray->getLen( aValue ); | ||||
756 | |||||
757 | typelib_TypeDescription * pTD = nullptr; | ||||
758 | aType.getDescription( &pTD ); | ||||
759 | assert( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE )(static_cast <bool> (pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE) ? void (0) : __assert_fail ("pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE" , "/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" , 759, __extension__ __PRETTY_FUNCTION__)); | ||||
760 | Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType ); | ||||
761 | ::typelib_typedescription_release( pTD ); | ||||
762 | |||||
763 | // build an Array in Basic | ||||
764 | SbxDimArrayRef xArray; | ||||
765 | SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() ); | ||||
766 | xArray = new SbxDimArray( eSbxElementType ); | ||||
767 | if( nLen > 0 ) | ||||
768 | { | ||||
769 | xArray->unoAddDim32( 0, nLen - 1 ); | ||||
770 | |||||
771 | // register the elements as variables | ||||
772 | for( i = 0 ; i < nLen ; i++ ) | ||||
773 | { | ||||
774 | // convert elements | ||||
775 | Any aElementAny = xIdlArray->get( aValue, static_cast<sal_uInt32>(i) ); | ||||
776 | auto xVar = tools::make_ref<SbxVariable>( eSbxElementType ); | ||||
777 | unoToSbxValue( xVar.get(), aElementAny ); | ||||
778 | |||||
779 | // put into the Array | ||||
780 | xArray->Put32( xVar.get(), &i ); | ||||
781 | } | ||||
782 | } | ||||
783 | else | ||||
784 | { | ||||
785 | xArray->unoAddDim32( 0, -1 ); | ||||
786 | } | ||||
787 | |||||
788 | // return the Array | ||||
789 | SbxFlagBits nFlags = pVar->GetFlags(); | ||||
790 | pVar->ResetFlag( SbxFlagBits::Fixed ); | ||||
791 | pVar->PutObject( xArray.get() ); | ||||
792 | pVar->SetFlags( nFlags ); | ||||
793 | |||||
794 | } | ||||
795 | break; | ||||
796 | |||||
797 | |||||
798 | case TypeClass_BOOLEAN: pVar->PutBool( *o3tl::forceAccess<bool>(aValue) ); break; | ||||
799 | case TypeClass_CHAR: | ||||
800 | { | ||||
801 | pVar->PutChar( *o3tl::forceAccess<sal_Unicode>(aValue) ); | ||||
802 | break; | ||||
803 | } | ||||
804 | case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( val ); } break; | ||||
805 | case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break; | ||||
806 | case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break; | ||||
807 | case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; | ||||
808 | case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break; | ||||
809 | case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break; | ||||
810 | case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break; | ||||
811 | case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break; | ||||
812 | case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break; | ||||
813 | case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break; | ||||
814 | default: pVar->PutEmpty(); break; | ||||
815 | } | ||||
816 | } | ||||
817 | |||||
818 | // Deliver the reflection for Sbx types | ||||
819 | static Type getUnoTypeForSbxBaseType( SbxDataType eType ) | ||||
820 | { | ||||
821 | Type aRetType = cppu::UnoType<void>::get(); | ||||
822 | switch( eType ) | ||||
823 | { | ||||
824 | case SbxNULL: aRetType = cppu::UnoType<XInterface>::get(); break; | ||||
825 | case SbxINTEGER: aRetType = cppu::UnoType<sal_Int16>::get(); break; | ||||
826 | case SbxLONG: aRetType = cppu::UnoType<sal_Int32>::get(); break; | ||||
827 | case SbxSINGLE: aRetType = cppu::UnoType<float>::get(); break; | ||||
828 | case SbxDOUBLE: aRetType = cppu::UnoType<double>::get(); break; | ||||
829 | case SbxCURRENCY: aRetType = cppu::UnoType<oleautomation::Currency>::get(); break; | ||||
830 | case SbxDECIMAL: aRetType = cppu::UnoType<oleautomation::Decimal>::get(); break; | ||||
831 | case SbxDATE: { | ||||
832 | SbiInstance* pInst = GetSbData()->pInst; | ||||
833 | if( pInst && pInst->IsCompatibility() ) | ||||
834 | aRetType = cppu::UnoType<double>::get(); | ||||
835 | else | ||||
836 | aRetType = cppu::UnoType<oleautomation::Date>::get(); | ||||
837 | } | ||||
838 | break; | ||||
839 | case SbxSTRING: aRetType = cppu::UnoType<OUString>::get(); break; | ||||
840 | case SbxBOOL: aRetType = cppu::UnoType<sal_Bool>::get(); break; | ||||
841 | case SbxVARIANT: aRetType = cppu::UnoType<Any>::get(); break; | ||||
842 | case SbxCHAR: aRetType = cppu::UnoType<cppu::UnoCharType>::get(); break; | ||||
843 | case SbxBYTE: aRetType = cppu::UnoType<sal_Int8>::get(); break; | ||||
844 | case SbxUSHORT: aRetType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); break; | ||||
845 | case SbxULONG: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break; | ||||
846 | // map machine-dependent ones to long for consistency | ||||
847 | case SbxINT: aRetType = ::cppu::UnoType<sal_Int32>::get(); break; | ||||
848 | case SbxUINT: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break; | ||||
849 | default: break; | ||||
850 | } | ||||
851 | return aRetType; | ||||
852 | } | ||||
853 | |||||
854 | // Converting of Sbx to Uno without a know target class for TypeClass_ANY | ||||
855 | static Type getUnoTypeForSbxValue( const SbxValue* pVal ) | ||||
856 | { | ||||
857 | Type aRetType = cppu::UnoType<void>::get(); | ||||
858 | if( !pVal ) | ||||
859 | return aRetType; | ||||
860 | |||||
861 | // convert SbxType to Uno | ||||
862 | SbxDataType eBaseType = pVal->SbxValue::GetType(); | ||||
863 | if( eBaseType == SbxOBJECT ) | ||||
864 | { | ||||
865 | SbxBaseRef xObj = pVal->GetObject(); | ||||
866 | if( !xObj.is() ) | ||||
867 | { | ||||
868 | aRetType = cppu::UnoType<XInterface>::get(); | ||||
869 | return aRetType; | ||||
870 | } | ||||
871 | |||||
872 | if( auto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) ) | ||||
873 | { | ||||
874 | sal_Int32 nDims = pArray->GetDims32(); | ||||
875 | Type aElementType = getUnoTypeForSbxBaseType( static_cast<SbxDataType>(pArray->GetType() & 0xfff) ); | ||||
876 | TypeClass eElementTypeClass = aElementType.getTypeClass(); | ||||
877 | |||||
878 | // Normal case: One dimensional array | ||||
879 | sal_Int32 nLower, nUpper; | ||||
880 | if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) | ||||
881 | { | ||||
882 | if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) | ||||
883 | { | ||||
884 | // If all elements of the arrays are from the same type, take | ||||
885 | // this one - otherwise the whole will be considered as Any-Sequence | ||||
886 | bool bNeedsInit = true; | ||||
887 | |||||
888 | for (sal_Int32 aIdx[1] = { nLower }; aIdx[0] <= nUpper; ++aIdx[0]) | ||||
889 | { | ||||
890 | SbxVariableRef xVar = pArray->Get32(aIdx); | ||||
891 | Type aType = getUnoTypeForSbxValue( xVar.get() ); | ||||
892 | if( bNeedsInit ) | ||||
893 | { | ||||
894 | if( aType.getTypeClass() == TypeClass_VOID ) | ||||
895 | { | ||||
896 | // if only first element is void: different types -> []any | ||||
897 | // if all elements are void: []void is not allowed -> []any | ||||
898 | aElementType = cppu::UnoType<Any>::get(); | ||||
899 | break; | ||||
900 | } | ||||
901 | aElementType = aType; | ||||
902 | bNeedsInit = false; | ||||
903 | } | ||||
904 | else if( aElementType != aType ) | ||||
905 | { | ||||
906 | // different types -> AnySequence | ||||
907 | aElementType = cppu::UnoType<Any>::get(); | ||||
908 | break; | ||||
909 | } | ||||
910 | } | ||||
911 | } | ||||
912 | |||||
913 | OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName(); | ||||
914 | aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName ); | ||||
915 | } | ||||
916 | // #i33795 Map also multi dimensional arrays to corresponding sequences | ||||
917 | else if( nDims > 1 ) | ||||
918 | { | ||||
919 | if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY ) | ||||
920 | { | ||||
921 | // For this check the array's dim structure does not matter | ||||
922 | sal_uInt32 nFlatArraySize = pArray->Count32(); | ||||
923 | |||||
924 | bool bNeedsInit = true; | ||||
925 | for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ ) | ||||
926 | { | ||||
927 | SbxVariableRef xVar = pArray->SbxArray::Get32( i ); | ||||
928 | Type aType = getUnoTypeForSbxValue( xVar.get() ); | ||||
929 | if( bNeedsInit ) | ||||
930 | { | ||||
931 | if( aType.getTypeClass() == TypeClass_VOID ) | ||||
932 | { | ||||
933 | // if only first element is void: different types -> []any | ||||
934 | // if all elements are void: []void is not allowed -> []any | ||||
935 | aElementType = cppu::UnoType<Any>::get(); | ||||
936 | break; | ||||
937 | } | ||||
938 | aElementType = aType; | ||||
939 | bNeedsInit = false; | ||||
940 | } | ||||
941 | else if( aElementType != aType ) | ||||
942 | { | ||||
943 | // different types -> AnySequence | ||||
944 | aElementType = cppu::UnoType<Any>::get(); | ||||
945 | break; | ||||
946 | } | ||||
947 | } | ||||
948 | } | ||||
949 | |||||
950 | OUStringBuffer aSeqTypeName; | ||||
951 | for(sal_Int32 iDim = 0 ; iDim < nDims ; iDim++ ) | ||||
952 | { | ||||
953 | aSeqTypeName.append(aSeqLevelStr); | ||||
954 | } | ||||
955 | aSeqTypeName.append(aElementType.getTypeName()); | ||||
956 | aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() ); | ||||
957 | } | ||||
958 | } | ||||
959 | // No array, but ... | ||||
960 | else if( auto obj = dynamic_cast<SbUnoObject*>( xObj.get() ) ) | ||||
961 | { | ||||
962 | aRetType = obj->getUnoAny().getValueType(); | ||||
963 | } | ||||
964 | // SbUnoAnyObject? | ||||
965 | else if( auto any = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) | ||||
966 | { | ||||
967 | aRetType = any->getValue().getValueType(); | ||||
968 | } | ||||
969 | // Otherwise it is a No-Uno-Basic-Object -> default==deliver void | ||||
970 | } | ||||
971 | // No object, convert basic type | ||||
972 | else | ||||
973 | { | ||||
974 | aRetType = getUnoTypeForSbxBaseType( eBaseType ); | ||||
975 | } | ||||
976 | return aRetType; | ||||
977 | } | ||||
978 | |||||
979 | // converting of Sbx to Uno without known target class for TypeClass_ANY | ||||
980 | static Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType = false ) | ||||
981 | { | ||||
982 | SbxDataType eBaseType = pVar->SbxValue::GetType(); | ||||
983 | if( eBaseType == SbxOBJECT ) | ||||
984 | { | ||||
985 | SbxBaseRef xObj = pVar->GetObject(); | ||||
986 | if( xObj.is() ) | ||||
987 | { | ||||
988 | if( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) | ||||
989 | return obj->getValue(); | ||||
990 | if( auto pClassModuleObj = dynamic_cast<SbClassModuleObject*>( xObj.get() ) ) | ||||
991 | { | ||||
992 | Any aRetAny; | ||||
993 | SbModule* pClassModule = pClassModuleObj->getClassModule(); | ||||
994 | if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) ) | ||||
995 | return aRetAny; | ||||
996 | } | ||||
997 | if( dynamic_cast<const SbUnoObject*>( xObj.get() ) == nullptr ) | ||||
998 | { | ||||
999 | // Create NativeObjectWrapper to identify object in case of callbacks | ||||
1000 | SbxObject* pObj = dynamic_cast<SbxObject*>( pVar->GetObject() ); | ||||
1001 | if( pObj != nullptr ) | ||||
1002 | { | ||||
1003 | NativeObjectWrapper aNativeObjectWrapper; | ||||
1004 | sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj ); | ||||
1005 | aNativeObjectWrapper.ObjectId <<= nIndex; | ||||
1006 | Any aRetAny; | ||||
1007 | aRetAny <<= aNativeObjectWrapper; | ||||
1008 | return aRetAny; | ||||
1009 | } | ||||
1010 | } | ||||
1011 | } | ||||
1012 | } | ||||
1013 | |||||
1014 | Type aType = getUnoTypeForSbxValue( pVar ); | ||||
1015 | TypeClass eType = aType.getTypeClass(); | ||||
1016 | |||||
1017 | if( !bBlockConversionToSmallestType ) | ||||
1018 | { | ||||
1019 | // #79615 Choose "smallest" representation for int values | ||||
1020 | // because up cast is allowed, downcast not | ||||
1021 | switch( eType ) | ||||
1022 | { | ||||
1023 | case TypeClass_FLOAT: | ||||
1024 | case TypeClass_DOUBLE: | ||||
1025 | { | ||||
1026 | double d = pVar->GetDouble(); | ||||
1027 | if( rtl::math::approxEqual(d, floor( d )) ) | ||||
1028 | { | ||||
1029 | if( d >= -128 && d <= 127 ) | ||||
1030 | aType = ::cppu::UnoType<sal_Int8>::get(); | ||||
1031 | else if( d >= SbxMININT && d <= SbxMAXINT ) | ||||
1032 | aType = ::cppu::UnoType<sal_Int16>::get(); | ||||
1033 | else if( d >= -SbxMAXLNG && d <= SbxMAXLNG ) | ||||
1034 | aType = ::cppu::UnoType<sal_Int32>::get(); | ||||
1035 | } | ||||
1036 | break; | ||||
1037 | } | ||||
1038 | case TypeClass_SHORT: | ||||
1039 | { | ||||
1040 | sal_Int16 n = pVar->GetInteger(); | ||||
1041 | if( n >= -128 && n <= 127 ) | ||||
1042 | aType = ::cppu::UnoType<sal_Int8>::get(); | ||||
1043 | break; | ||||
1044 | } | ||||
1045 | case TypeClass_LONG: | ||||
1046 | { | ||||
1047 | sal_Int32 n = pVar->GetLong(); | ||||
1048 | if( n >= -128 && n <= 127 ) | ||||
1049 | aType = ::cppu::UnoType<sal_Int8>::get(); | ||||
1050 | else if( n >= SbxMININT && n <= SbxMAXINT ) | ||||
1051 | aType = ::cppu::UnoType<sal_Int16>::get(); | ||||
1052 | break; | ||||
1053 | } | ||||
1054 | case TypeClass_UNSIGNED_SHORT: | ||||
1055 | { | ||||
1056 | sal_uInt16 n = pVar->GetUShort(); | ||||
1057 | if( n <= 255 ) | ||||
1058 | aType = cppu::UnoType<sal_uInt8>::get(); | ||||
1059 | break; | ||||
1060 | } | ||||
1061 | case TypeClass_UNSIGNED_LONG: | ||||
1062 | { | ||||
1063 | sal_uInt32 n = pVar->GetLong(); | ||||
1064 | if( n <= 255 ) | ||||
1065 | aType = cppu::UnoType<sal_uInt8>::get(); | ||||
1066 | else if( n <= SbxMAXUINT ) | ||||
1067 | aType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); | ||||
1068 | break; | ||||
1069 | } | ||||
1070 | // TODO: need to add hyper types ? | ||||
1071 | default: break; | ||||
1072 | } | ||||
1073 | } | ||||
1074 | |||||
1075 | return sbxToUnoValue( pVar, aType ); | ||||
1076 | } | ||||
1077 | |||||
1078 | |||||
1079 | // Helper function for StepREDIMP | ||||
1080 | static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray, | ||||
1081 | const Type& aElemType, sal_Int32 nMaxDimIndex, sal_Int32 nActualDim, | ||||
1082 | sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds ) | ||||
1083 | { | ||||
1084 | sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1; | ||||
1085 | OUStringBuffer aSeqTypeName; | ||||
1086 | sal_Int32 i; | ||||
1087 | for( i = 0 ; i < nSeqLevel ; i++ ) | ||||
1088 | { | ||||
1089 | aSeqTypeName.append(aSeqLevelStr); | ||||
1090 | } | ||||
1091 | aSeqTypeName.append(aElemType.getTypeName()); | ||||
1092 | Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() ); | ||||
1093 | |||||
1094 | // Create Sequence instance | ||||
1095 | Any aRetVal; | ||||
1096 | Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType ); | ||||
1097 | xIdlTargetClass->createObject( aRetVal ); | ||||
1098 | |||||
1099 | // Alloc sequence according to array bounds | ||||
1100 | sal_Int32 nUpper = pUpperBounds[nActualDim]; | ||||
1101 | sal_Int32 nLower = pLowerBounds[nActualDim]; | ||||
1102 | sal_Int32 nSeqSize = nUpper - nLower + 1; | ||||
1103 | Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); | ||||
1104 | xArray->realloc( aRetVal, nSeqSize ); | ||||
1105 | |||||
1106 | sal_Int32& ri = pActualIndices[nActualDim]; | ||||
1107 | |||||
1108 | for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ ) | ||||
1109 | { | ||||
1110 | Any aElementVal; | ||||
1111 | |||||
1112 | if( nActualDim < nMaxDimIndex ) | ||||
1113 | { | ||||
1114 | aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType, | ||||
1115 | nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds ); | ||||
1116 | } | ||||
1117 | else | ||||
1118 | { | ||||
1119 | SbxVariable* pSource = pArray->Get32( pActualIndices ); | ||||
1120 | aElementVal = sbxToUnoValue( pSource, aElemType ); | ||||
1121 | } | ||||
1122 | |||||
1123 | try | ||||
1124 | { | ||||
1125 | // transfer to the sequence | ||||
1126 | xArray->set( aRetVal, i, aElementVal ); | ||||
1127 | } | ||||
1128 | catch( const IllegalArgumentException& ) | ||||
1129 | { | ||||
1130 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), | ||||
1131 | implGetExceptionMsg( ::cppu::getCaughtException() ) ); | ||||
1132 | } | ||||
1133 | catch (const IndexOutOfBoundsException&) | ||||
1134 | { | ||||
1135 | StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 4) ); | ||||
1136 | } | ||||
1137 | } | ||||
1138 | return aRetVal; | ||||
1139 | } | ||||
1140 | |||||
1141 | // Map old interface | ||||
1142 | Any sbxToUnoValue( const SbxValue* pVar ) | ||||
1143 | { | ||||
1144 | return sbxToUnoValueImpl( pVar ); | ||||
1145 | } | ||||
1146 | |||||
1147 | // function to find a global identifier in | ||||
1148 | // the UnoScope and to wrap it for Sbx | ||||
1149 | static bool implGetTypeByName( const OUString& rName, Type& rRetType ) | ||||
1150 | { | ||||
1151 | bool bSuccess = false; | ||||
1152 | |||||
1153 | const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); | ||||
1154 | if( xTypeAccess->hasByHierarchicalName( rName ) ) | ||||
1155 | { | ||||
1156 | Any aRet = xTypeAccess->getByHierarchicalName( rName ); | ||||
1157 | Reference< XTypeDescription > xTypeDesc; | ||||
1158 | aRet >>= xTypeDesc; | ||||
1159 | |||||
1160 | if( xTypeDesc.is() ) | ||||
1161 | { | ||||
1162 | rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() ); | ||||
1163 | bSuccess = true; | ||||
1164 | } | ||||
1165 | } | ||||
1166 | return bSuccess; | ||||
1167 | } | ||||
1168 | |||||
1169 | |||||
1170 | // converting of Sbx to Uno with known target class | ||||
1171 | Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property const * pUnoProperty ) | ||||
1172 | { | ||||
1173 | Any aRetVal; | ||||
1174 | |||||
1175 | // #94560 No conversion of empty/void for MAYBE_VOID properties | ||||
1176 | if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID ) | ||||
1177 | { | ||||
1178 | if( pVar->IsEmpty() ) | ||||
1179 | return aRetVal; | ||||
1180 | } | ||||
1181 | |||||
1182 | SbxDataType eBaseType = pVar->SbxValue::GetType(); | ||||
1183 | if( eBaseType == SbxOBJECT ) | ||||
1184 | { | ||||
1185 | SbxBaseRef xObj = pVar->GetObject(); | ||||
1186 | if ( auto obj = dynamic_cast<SbUnoAnyObject*>( xObj.get() ) ) | ||||
1187 | { | ||||
1188 | return obj->getValue(); | ||||
1189 | } | ||||
1190 | } | ||||
1191 | |||||
1192 | TypeClass eType = rType.getTypeClass(); | ||||
1193 | switch( eType ) | ||||
1194 | { | ||||
1195 | case TypeClass_INTERFACE: | ||||
1196 | case TypeClass_STRUCT: | ||||
1197 | case TypeClass_EXCEPTION: | ||||
1198 | { | ||||
1199 | Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); | ||||
1200 | |||||
1201 | // null reference? | ||||
1202 | if( pVar->IsNull() && eType == TypeClass_INTERFACE ) | ||||
1203 | { | ||||
1204 | Reference< XInterface > xRef; | ||||
1205 | OUString aClassName = xIdlTargetClass->getName(); | ||||
1206 | Type aClassType( xIdlTargetClass->getTypeClass(), aClassName ); | ||||
1207 | aRetVal.setValue( &xRef, aClassType ); | ||||
1208 | } | ||||
1209 | else | ||||
1210 | { | ||||
1211 | // #112368 Special conversion for Decimal, Currency and Date | ||||
1212 | if( eType == TypeClass_STRUCT ) | ||||
1213 | { | ||||
1214 | SbiInstance* pInst = GetSbData()->pInst; | ||||
1215 | if( pInst && pInst->IsCompatibility() ) | ||||
1216 | { | ||||
1217 | if( rType == cppu::UnoType<oleautomation::Decimal>::get()) | ||||
1218 | { | ||||
1219 | oleautomation::Decimal aDecimal; | ||||
1220 | pVar->fillAutomationDecimal( aDecimal ); | ||||
1221 | aRetVal <<= aDecimal; | ||||
1222 | break; | ||||
1223 | } | ||||
1224 | else if( rType == cppu::UnoType<oleautomation::Currency>::get()) | ||||
1225 | { | ||||
1226 | // assumes per previous code that ole Currency is Int64 | ||||
1227 | aRetVal <<= pVar->GetInt64(); | ||||
1228 | break; | ||||
1229 | } | ||||
1230 | else if( rType == cppu::UnoType<oleautomation::Date>::get()) | ||||
1231 | { | ||||
1232 | oleautomation::Date aDate; | ||||
1233 | aDate.Value = pVar->GetDate(); | ||||
1234 | aRetVal <<= aDate; | ||||
1235 | break; | ||||
1236 | } | ||||
1237 | } | ||||
1238 | } | ||||
1239 | |||||
1240 | SbxBaseRef pObj = pVar->GetObject(); | ||||
1241 | if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) | ||||
1242 | { | ||||
1243 | aRetVal = obj->getUnoAny(); | ||||
1244 | } | ||||
1245 | else if( auto structRef = dynamic_cast<SbUnoStructRefObject*>( pObj.get() ) ) | ||||
1246 | { | ||||
1247 | aRetVal = structRef->getUnoAny(); | ||||
1248 | } | ||||
1249 | else | ||||
1250 | { | ||||
1251 | // null object -> null XInterface | ||||
1252 | Reference<XInterface> xInt; | ||||
1253 | aRetVal <<= xInt; | ||||
1254 | } | ||||
1255 | } | ||||
1256 | } | ||||
1257 | break; | ||||
1258 | |||||
1259 | case TypeClass_TYPE: | ||||
1260 | { | ||||
1261 | if( eBaseType == SbxOBJECT ) | ||||
1262 | { | ||||
1263 | // XIdlClass? | ||||
1264 | Reference< XIdlClass > xIdlClass; | ||||
1265 | |||||
1266 | SbxBaseRef pObj = pVar->GetObject(); | ||||
1267 | if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) | ||||
1268 | { | ||||
1269 | Any aUnoAny = obj->getUnoAny(); | ||||
1270 | aUnoAny >>= xIdlClass; | ||||
1271 | } | ||||
1272 | |||||
1273 | if( xIdlClass.is() ) | ||||
1274 | { | ||||
1275 | OUString aClassName = xIdlClass->getName(); | ||||
1276 | Type aType( xIdlClass->getTypeClass(), aClassName ); | ||||
1277 | aRetVal <<= aType; | ||||
1278 | } | ||||
1279 | } | ||||
1280 | else if( eBaseType == SbxSTRING ) | ||||
1281 | { | ||||
1282 | OUString aTypeName = pVar->GetOUString(); | ||||
1283 | Type aType; | ||||
1284 | bool bSuccess = implGetTypeByName( aTypeName, aType ); | ||||
1285 | if( bSuccess ) | ||||
1286 | { | ||||
1287 | aRetVal <<= aType; | ||||
1288 | } | ||||
1289 | } | ||||
1290 | } | ||||
1291 | break; | ||||
1292 | |||||
1293 | |||||
1294 | case TypeClass_ENUM: | ||||
1295 | { | ||||
1296 | aRetVal = int2enum( pVar->GetLong(), rType ); | ||||
1297 | } | ||||
1298 | break; | ||||
1299 | |||||
1300 | case TypeClass_SEQUENCE: | ||||
1301 | { | ||||
1302 | SbxBaseRef xObj = pVar->GetObject(); | ||||
1303 | if( auto pArray = dynamic_cast<SbxDimArray*>( xObj.get() ) ) | ||||
1304 | { | ||||
1305 | sal_Int32 nDims = pArray->GetDims32(); | ||||
1306 | |||||
1307 | // Normal case: One dimensional array | ||||
1308 | sal_Int32 nLower, nUpper; | ||||
1309 | if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) ) | ||||
1310 | { | ||||
1311 | sal_Int32 nSeqSize = nUpper - nLower + 1; | ||||
1312 | |||||
1313 | // create the instance of the required sequence | ||||
1314 | Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType ); | ||||
1315 | xIdlTargetClass->createObject( aRetVal ); | ||||
1316 | Reference< XIdlArray > xArray = xIdlTargetClass->getArray(); | ||||
1317 | xArray->realloc( aRetVal, nSeqSize ); | ||||
1318 | |||||
1319 | // Element-Type | ||||
1320 | OUString aClassName = xIdlTargetClass->getName(); | ||||
1321 | typelib_TypeDescription * pSeqTD = nullptr; | ||||
1322 | typelib_typedescription_getByName( &pSeqTD, aClassName.pData ); | ||||
1323 | assert( pSeqTD )(static_cast <bool> (pSeqTD) ? void (0) : __assert_fail ("pSeqTD", "/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" , 1323, __extension__ __PRETTY_FUNCTION__)); | ||||
1324 | Type aElemType( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType ); | ||||
1325 | |||||
1326 | // convert all array member and register them | ||||
1327 | sal_Int32 aIdx[1]; | ||||
1328 | aIdx[0] = nLower; | ||||
1329 | for (sal_Int32 i = 0 ; i < nSeqSize; ++i, ++aIdx[0]) | ||||
1330 | { | ||||
1331 | SbxVariableRef xVar = pArray->Get32(aIdx); | ||||
1332 | |||||
1333 | // Convert the value of Sbx to Uno | ||||
1334 | Any aAnyValue = sbxToUnoValue( xVar.get(), aElemType ); | ||||
1335 | |||||
1336 | try | ||||
1337 | { | ||||
1338 | // insert in the sequence | ||||
1339 | xArray->set( aRetVal, i, aAnyValue ); | ||||
1340 | } | ||||
1341 | catch( const IllegalArgumentException& ) | ||||
1342 | { | ||||
1343 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), | ||||
1344 | implGetExceptionMsg( ::cppu::getCaughtException() ) ); | ||||
1345 | } | ||||
1346 | catch (const IndexOutOfBoundsException&) | ||||
1347 | { | ||||
1348 | StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGEErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 4) ); | ||||
1349 | } | ||||
1350 | } | ||||
1351 | } | ||||
1352 | // #i33795 Map also multi dimensional arrays to corresponding sequences | ||||
1353 | else if( nDims > 1 ) | ||||
1354 | { | ||||
1355 | // Element-Type | ||||
1356 | typelib_TypeDescription * pSeqTD = nullptr; | ||||
1357 | Type aCurType( rType ); | ||||
1358 | sal_Int32 nSeqLevel = 0; | ||||
1359 | Type aElemType; | ||||
1360 | do | ||||
1361 | { | ||||
1362 | OUString aTypeName = aCurType.getTypeName(); | ||||
1363 | typelib_typedescription_getByName( &pSeqTD, aTypeName.pData ); | ||||
1364 | assert( pSeqTD )(static_cast <bool> (pSeqTD) ? void (0) : __assert_fail ("pSeqTD", "/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" , 1364, __extension__ __PRETTY_FUNCTION__)); | ||||
1365 | if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE ) | ||||
1366 | { | ||||
1367 | aCurType = Type( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType ); | ||||
1368 | nSeqLevel++; | ||||
1369 | } | ||||
1370 | else | ||||
1371 | { | ||||
1372 | aElemType = aCurType; | ||||
1373 | break; | ||||
1374 | } | ||||
1375 | } | ||||
1376 | while( true ); | ||||
1377 | |||||
1378 | if( nSeqLevel == nDims ) | ||||
1379 | { | ||||
1380 | std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDims]); | ||||
1381 | std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDims]); | ||||
1382 | std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDims]); | ||||
1383 | for(sal_Int32 i = 1 ; i <= nDims ; i++ ) | ||||
1384 | { | ||||
1385 | sal_Int32 lBound, uBound; | ||||
1386 | pArray->GetDim32( i, lBound, uBound ); | ||||
1387 | |||||
1388 | sal_Int32 j = i - 1; | ||||
1389 | pActualIndices[j] = pLowerBounds[j] = lBound; | ||||
1390 | pUpperBounds[j] = uBound; | ||||
1391 | } | ||||
1392 | |||||
1393 | aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType, | ||||
1394 | nDims - 1, 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get() ); | ||||
1395 | } | ||||
1396 | } | ||||
1397 | } | ||||
1398 | } | ||||
1399 | break; | ||||
1400 | |||||
1401 | |||||
1402 | // for Any use the class independent converting routine | ||||
1403 | case TypeClass_ANY: | ||||
1404 | { | ||||
1405 | aRetVal = sbxToUnoValueImpl( pVar ); | ||||
1406 | } | ||||
1407 | break; | ||||
1408 | |||||
1409 | case TypeClass_BOOLEAN: | ||||
1410 | { | ||||
1411 | aRetVal <<= pVar->GetBool(); | ||||
1412 | break; | ||||
1413 | } | ||||
1414 | case TypeClass_CHAR: | ||||
1415 | { | ||||
1416 | aRetVal <<= pVar->GetChar(); | ||||
1417 | break; | ||||
1418 | } | ||||
1419 | case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break; | ||||
1420 | case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break; | ||||
1421 | case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break; | ||||
1422 | |||||
1423 | case TypeClass_BYTE: | ||||
1424 | { | ||||
1425 | sal_Int16 nVal = pVar->GetInteger(); | ||||
1426 | bool bOverflow = false; | ||||
1427 | if( nVal < -128 ) | ||||
1428 | { | ||||
1429 | bOverflow = true; | ||||
1430 | nVal = -128; | ||||
1431 | } | ||||
1432 | else if( nVal > 255 ) // 128..255 map to -128..-1 | ||||
1433 | { | ||||
1434 | bOverflow = true; | ||||
1435 | nVal = 127; | ||||
1436 | } | ||||
1437 | if( bOverflow ) | ||||
1438 | StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOWErrCode( ErrCodeArea::Sbx, ErrCodeClass::Sbx, 3) ); | ||||
1439 | |||||
1440 | sal_Int8 nByteVal = static_cast<sal_Int8>(nVal); | ||||
1441 | aRetVal <<= nByteVal; | ||||
1442 | break; | ||||
1443 | } | ||||
1444 | case TypeClass_SHORT: aRetVal <<= pVar->GetInteger(); break; | ||||
1445 | case TypeClass_LONG: aRetVal <<= pVar->GetLong(); break; | ||||
1446 | case TypeClass_HYPER: aRetVal <<= pVar->GetInt64(); break; | ||||
1447 | case TypeClass_UNSIGNED_SHORT: aRetVal <<= pVar->GetUShort(); break; | ||||
1448 | case TypeClass_UNSIGNED_LONG: aRetVal <<= pVar->GetULong(); break; | ||||
1449 | case TypeClass_UNSIGNED_HYPER: aRetVal <<= pVar->GetUInt64(); break; | ||||
1450 | default: break; | ||||
1451 | } | ||||
1452 | |||||
1453 | return aRetVal; | ||||
1454 | } | ||||
1455 | |||||
1456 | static void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, sal_uInt32 nParamCount ) | ||||
1457 | { | ||||
1458 | AutomationNamedArgsSbxArray* pArgNamesArray = dynamic_cast<AutomationNamedArgsSbxArray*>( pParams ); | ||||
1459 | |||||
1460 | args.realloc( nParamCount ); | ||||
1461 | Any* pAnyArgs = args.getArray(); | ||||
1462 | bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility(); | ||||
1463 | sal_uInt32 i = 0; | ||||
1464 | if( pArgNamesArray ) | ||||
1465 | { | ||||
1466 | Sequence< OUString >& rNameSeq = pArgNamesArray->getNames(); | ||||
1467 | OUString* pNames = rNameSeq.getArray(); | ||||
1468 | Any aValAny; | ||||
1469 | for( i = 0 ; i < nParamCount ; i++ ) | ||||
1470 | { | ||||
1471 | sal_uInt32 iSbx = i + 1; | ||||
1472 | |||||
1473 | aValAny = sbxToUnoValueImpl( pParams->Get32( iSbx ), | ||||
1474 | bBlockConversionToSmallestType ); | ||||
1475 | |||||
1476 | OUString aParamName = pNames[iSbx]; | ||||
1477 | if( !aParamName.isEmpty() ) | ||||
1478 | { | ||||
1479 | oleautomation::NamedArgument aNamedArgument; | ||||
1480 | aNamedArgument.Name = aParamName; | ||||
1481 | aNamedArgument.Value = aValAny; | ||||
1482 | pAnyArgs[i] <<= aNamedArgument; | ||||
1483 | } | ||||
1484 | else | ||||
1485 | { | ||||
1486 | pAnyArgs[i] = aValAny; | ||||
1487 | } | ||||
1488 | } | ||||
1489 | } | ||||
1490 | else | ||||
1491 | { | ||||
1492 | for( i = 0 ; i < nParamCount ; i++ ) | ||||
1493 | { | ||||
1494 | pAnyArgs[i] = sbxToUnoValueImpl(pParams->Get32(i + 1), | ||||
1495 | bBlockConversionToSmallestType ); | ||||
1496 | } | ||||
1497 | } | ||||
1498 | |||||
1499 | } | ||||
1500 | |||||
1501 | namespace { | ||||
1502 | |||||
1503 | enum class INVOKETYPE | ||||
1504 | { | ||||
1505 | GetProp = 0, | ||||
1506 | Func | ||||
1507 | }; | ||||
1508 | |||||
1509 | } | ||||
1510 | |||||
1511 | static Any invokeAutomationMethod( const OUString& Name, Sequence< Any > const & args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation > const & rxInvocation, INVOKETYPE invokeType ) | ||||
1512 | { | ||||
1513 | Sequence< sal_Int16 > OutParamIndex; | ||||
1514 | Sequence< Any > OutParam; | ||||
1515 | |||||
1516 | Any aRetAny; | ||||
1517 | switch( invokeType ) | ||||
1518 | { | ||||
1519 | case INVOKETYPE::Func: | ||||
1520 | aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam ); | ||||
1521 | break; | ||||
1522 | case INVOKETYPE::GetProp: | ||||
1523 | { | ||||
1524 | Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY ); | ||||
1525 | aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam ); | ||||
1526 | break; | ||||
1527 | } | ||||
1528 | default: | ||||
1529 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" , 1529, __extension__ __PRETTY_FUNCTION__)); break; | ||||
1530 | |||||
1531 | } | ||||
1532 | const sal_Int16* pIndices = OutParamIndex.getConstArray(); | ||||
1533 | sal_uInt32 nLen = OutParamIndex.getLength(); | ||||
1534 | if( nLen ) | ||||
1535 | { | ||||
1536 | const Any* pNewValues = OutParam.getConstArray(); | ||||
1537 | for( sal_uInt32 j = 0 ; j < nLen ; j++ ) | ||||
1538 | { | ||||
1539 | sal_Int16 iTarget = pIndices[ j ]; | ||||
1540 | if( iTarget >= static_cast<sal_Int16>(nParamCount) ) | ||||
1541 | break; | ||||
1542 | unoToSbxValue( pParams->Get32(j + 1), pNewValues[ j ] ); | ||||
1543 | } | ||||
1544 | } | ||||
1545 | return aRetAny; | ||||
1546 | } | ||||
1547 | |||||
1548 | // Debugging help method to readout the implemented interfaces of an object | ||||
1549 | static OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel ) | ||||
1550 | { | ||||
1551 | Type aIfaceType = cppu::UnoType<XInterface>::get(); | ||||
1552 | static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType ); | ||||
1553 | |||||
1554 | OUStringBuffer aRetStr; | ||||
1555 | for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ ) | ||||
1556 | aRetStr.append( " " ); | ||||
1557 | aRetStr.append( xClass->getName() ); | ||||
1558 | OUString aClassName = xClass->getName(); | ||||
1559 | Type aClassType( xClass->getTypeClass(), aClassName ); | ||||
1560 | |||||
1561 | // checking if the interface is really supported | ||||
1562 | if( !x->queryInterface( aClassType ).hasValue() ) | ||||
1563 | { | ||||
1564 | aRetStr.append( " (ERROR: Not really supported!)\n" ); | ||||
1565 | } | ||||
1566 | // Are there super interfaces? | ||||
1567 | else | ||||
1568 | { | ||||
1569 | aRetStr.append( "\n" ); | ||||
1570 | |||||
1571 | // get the super interfaces | ||||
1572 | Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses(); | ||||
1573 | const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray(); | ||||
1574 | sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength(); | ||||
1575 | for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ ) | ||||
1576 | { | ||||
1577 | const Reference< XIdlClass >& rxIfaceClass = pClasses[j]; | ||||
1578 | if( !rxIfaceClass->equals( xIfaceClass ) ) | ||||
1579 | aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) ); | ||||
1580 | } | ||||
1581 | } | ||||
1582 | return aRetStr.makeStringAndClear(); | ||||
1583 | } | ||||
1584 | |||||
1585 | static OUString getDbgObjectNameImpl(SbUnoObject& rUnoObj) | ||||
1586 | { | ||||
1587 | OUString aName = rUnoObj.GetClassName(); | ||||
1588 | if( aName.isEmpty() ) | ||||
1589 | { | ||||
1590 | Any aToInspectObj = rUnoObj.getUnoAny(); | ||||
1591 | Reference< XInterface > xObj(aToInspectObj, css::uno::UNO_QUERY); | ||||
1592 | if( xObj.is() ) | ||||
1593 | { | ||||
1594 | Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY ); | ||||
1595 | if( xServiceInfo.is() ) | ||||
1596 | aName = xServiceInfo->getImplementationName(); | ||||
1597 | } | ||||
1598 | } | ||||
1599 | return aName; | ||||
1600 | } | ||||
1601 | |||||
1602 | static OUString getDbgObjectName(SbUnoObject& rUnoObj) | ||||
1603 | { | ||||
1604 | OUString aName = getDbgObjectNameImpl(rUnoObj); | ||||
1605 | if( aName.isEmpty() ) | ||||
1606 | aName += "Unknown"; | ||||
1607 | |||||
1608 | OUStringBuffer aRet; | ||||
1609 | if( aName.getLength() > 20 ) | ||||
1610 | { | ||||
1611 | aRet.append( "\n" ); | ||||
1612 | } | ||||
1613 | aRet.append( "\"" ); | ||||
1614 | aRet.append( aName ); | ||||
1615 | aRet.append( "\":" ); | ||||
1616 | return aRet.makeStringAndClear(); | ||||
1617 | } | ||||
1618 | |||||
1619 | OUString getBasicObjectTypeName( SbxObject* pObj ) | ||||
1620 | { | ||||
1621 | if (pObj) | ||||
1622 | { | ||||
1623 | if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) | ||||
1624 | { | ||||
1625 | return getDbgObjectNameImpl(*pUnoObj); | ||||
1626 | } | ||||
1627 | else if (SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>(pObj)) | ||||
1628 | { | ||||
1629 | return pUnoStructObj->GetClassName(); | ||||
1630 | } | ||||
1631 | } | ||||
1632 | return OUString(); | ||||
1633 | } | ||||
1634 | |||||
1635 | namespace { | ||||
1636 | |||||
1637 | bool matchesBasicTypeName( | ||||
1638 | css::uno::Reference<css::reflection::XIdlClass> const & unoType, OUString const & basicTypeName) | ||||
1639 | { | ||||
1640 | if (unoType->getName().endsWithIgnoreAsciiCase(basicTypeName)) { | ||||
1641 | return true; | ||||
1642 | } | ||||
1643 | auto const sups = unoType->getSuperclasses(); | ||||
1644 | return std::any_of( | ||||
1645 | sups.begin(), sups.end(), | ||||
1646 | [&basicTypeName](auto const & t) { return matchesBasicTypeName(t, basicTypeName); }); | ||||
1647 | } | ||||
1648 | |||||
1649 | } | ||||
1650 | |||||
1651 | bool checkUnoObjectType(SbUnoObject& rUnoObj, const OUString& rClass) | ||||
1652 | { | ||||
1653 | Any aToInspectObj = rUnoObj.getUnoAny(); | ||||
1654 | |||||
1655 | // Return true for XInvocation based objects as interface type names don't count then | ||||
1656 | Reference< XInvocation > xInvocation( aToInspectObj, UNO_QUERY ); | ||||
1657 | if( xInvocation.is() ) | ||||
1658 | { | ||||
1659 | return true; | ||||
1660 | } | ||||
1661 | bool bResult = false; | ||||
1662 | Reference< XTypeProvider > xTypeProvider( aToInspectObj, UNO_QUERY ); | ||||
1663 | if( xTypeProvider.is() ) | ||||
1664 | { | ||||
1665 | /* Although interfaces in the ooo.vba namespace obey the IDL rules and | ||||
1666 | have a leading 'X', in Basic we want to be able to do something | ||||
1667 | like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we | ||||
1668 | add a leading 'X' to the class name and a leading dot to the entire | ||||
1669 | type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel' | ||||
1670 | which matches the interface names 'ooo.vba.excel.XWorkbooks' or | ||||
1671 | 'ooo.vba.msforms.XLabel'. | ||||
1672 | */ | ||||
1673 | OUString aClassName; | ||||
1674 | if ( SbiRuntime::isVBAEnabled() ) | ||||
1675 | { | ||||
1676 | aClassName = "."; | ||||
1677 | sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' ); | ||||
1678 | if( nClassNameDot >= 0 ) | ||||
1679 | { | ||||
1680 | aClassName += rClass.copy( 0, nClassNameDot + 1 ) + "X" + rClass.copy( nClassNameDot + 1 ); | ||||
1681 | } | ||||
1682 | else | ||||
1683 | { | ||||
1684 | aClassName += "X" + rClass; | ||||
1685 | } | ||||
1686 | } | ||||
1687 | else // assume extended type declaration support for basic ( can't get here | ||||
1688 | // otherwise. | ||||
1689 | aClassName = rClass; | ||||
1690 | |||||
1691 | Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); | ||||
1692 | const Type* pTypeArray = aTypeSeq.getConstArray(); | ||||
1693 | sal_uInt32 nIfaceCount = aTypeSeq.getLength(); | ||||
1694 | for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ ) | ||||
1695 | { | ||||
1696 | const Type& rType = pTypeArray[j]; | ||||
1697 | |||||
1698 | Reference<XIdlClass> xClass = TypeToIdlClass( rType ); | ||||
1699 | if( !xClass.is() ) | ||||
1700 | { | ||||
1701 | OSL_FAIL("failed to get XIdlClass for type")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" ":" "1701" ": "), "%s", "failed to get XIdlClass for type"); } } while (false); | ||||
1702 | break; | ||||
1703 | } | ||||
1704 | OUString aInterfaceName = xClass->getName(); | ||||
1705 | if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" ) | ||||
1706 | { | ||||
1707 | // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it | ||||
1708 | // matches | ||||
1709 | Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY ); | ||||
1710 | if ( xInv.is() ) | ||||
1711 | { | ||||
1712 | OUString sTypeName; | ||||
1713 | xInv->getValue( "$GetTypeName" ) >>= sTypeName; | ||||
1714 | if ( sTypeName.isEmpty() || sTypeName == "IDispatch" ) | ||||
1715 | { | ||||
1716 | // can't check type, leave it pass | ||||
1717 | bResult = true; | ||||
1718 | } | ||||
1719 | else | ||||
1720 | { | ||||
1721 | bResult = sTypeName == rClass; | ||||
1722 | } | ||||
1723 | } | ||||
1724 | break; // finished checking automation object | ||||
1725 | } | ||||
1726 | |||||
1727 | if ( matchesBasicTypeName(xClass, aClassName) ) | ||||
1728 | { | ||||
1729 | bResult = true; | ||||
1730 | break; | ||||
1731 | } | ||||
1732 | } | ||||
1733 | } | ||||
1734 | return bResult; | ||||
1735 | } | ||||
1736 | |||||
1737 | // Debugging help method to readout the implemented interfaces of an object | ||||
1738 | static OUString Impl_GetSupportedInterfaces(SbUnoObject& rUnoObj) | ||||
1739 | { | ||||
1740 | Any aToInspectObj = rUnoObj.getUnoAny(); | ||||
1741 | |||||
1742 | // allow only TypeClass interface | ||||
1743 | OUStringBuffer aRet; | ||||
1744 | auto x = o3tl::tryAccess<Reference<XInterface>>(aToInspectObj); | ||||
1745 | if( !x ) | ||||
1746 | { | ||||
1747 | aRet.append( ID_DBG_SUPPORTEDINTERFACES ); | ||||
1748 | aRet.append( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" ); | ||||
1749 | } | ||||
1750 | else | ||||
1751 | { | ||||
1752 | Reference< XTypeProvider > xTypeProvider( *x, UNO_QUERY ); | ||||
1753 | |||||
1754 | aRet.append( "Supported interfaces by object " ); | ||||
1755 | aRet.append(getDbgObjectName(rUnoObj)); | ||||
1756 | aRet.append( "\n" ); | ||||
1757 | if( xTypeProvider.is() ) | ||||
1758 | { | ||||
1759 | // get the interfaces of the implementation | ||||
1760 | Sequence< Type > aTypeSeq = xTypeProvider->getTypes(); | ||||
1761 | const Type* pTypeArray = aTypeSeq.getConstArray(); | ||||
1762 | sal_uInt32 nIfaceCount = aTypeSeq.getLength(); | ||||
1763 | for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ ) | ||||
1764 | { | ||||
1765 | const Type& rType = pTypeArray[j]; | ||||
1766 | |||||
1767 | Reference<XIdlClass> xClass = TypeToIdlClass( rType ); | ||||
1768 | if( xClass.is() ) | ||||
1769 | { | ||||
1770 | aRet.append( Impl_GetInterfaceInfo( *x, xClass, 1 ) ); | ||||
1771 | } | ||||
1772 | else | ||||
1773 | { | ||||
1774 | typelib_TypeDescription * pTD = nullptr; | ||||
1775 | rType.getDescription( &pTD ); | ||||
1776 | |||||
1777 | aRet.append( "*** ERROR: No IdlClass for type \"" ); | ||||
1778 | aRet.append( pTD->pTypeName ); | ||||
1779 | aRet.append( "\"\n*** Please check type library\n" ); | ||||
1780 | } | ||||
1781 | } | ||||
1782 | } | ||||
1783 | } | ||||
1784 | return aRet.makeStringAndClear(); | ||||
1785 | } | ||||
1786 | |||||
1787 | |||||
1788 | // Debugging help method SbxDataType -> String | ||||
1789 | static OUString Dbg_SbxDataType2String( SbxDataType eType ) | ||||
1790 | { | ||||
1791 | OUStringBuffer aRet; | ||||
1792 | switch( +eType ) | ||||
1793 | { | ||||
1794 | case SbxEMPTY: aRet.append("SbxEMPTY"); break; | ||||
1795 | case SbxNULL: aRet.append("SbxNULL"); break; | ||||
1796 | case SbxINTEGER: aRet.append("SbxINTEGER"); break; | ||||
1797 | case SbxLONG: aRet.append("SbxLONG"); break; | ||||
1798 | case SbxSINGLE: aRet.append("SbxSINGLE"); break; | ||||
1799 | case SbxDOUBLE: aRet.append("SbxDOUBLE"); break; | ||||
1800 | case SbxCURRENCY: aRet.append("SbxCURRENCY"); break; | ||||
1801 | case SbxDECIMAL: aRet.append("SbxDECIMAL"); break; | ||||
1802 | case SbxDATE: aRet.append("SbxDATE"); break; | ||||
1803 | case SbxSTRING: aRet.append("SbxSTRING"); break; | ||||
1804 | case SbxOBJECT: aRet.append("SbxOBJECT"); break; | ||||
1805 | case SbxERROR: aRet.append("SbxERROR"); break; | ||||
1806 | case SbxBOOL: aRet.append("SbxBOOL"); break; | ||||
1807 | case SbxVARIANT: aRet.append("SbxVARIANT"); break; | ||||
1808 | case SbxDATAOBJECT: aRet.append("SbxDATAOBJECT"); break; | ||||
1809 | case SbxCHAR: aRet.append("SbxCHAR"); break; | ||||
1810 | case SbxBYTE: aRet.append("SbxBYTE"); break; | ||||
1811 | case SbxUSHORT: aRet.append("SbxUSHORT"); break; | ||||
1812 | case SbxULONG: aRet.append("SbxULONG"); break; | ||||
1813 | case SbxSALINT64: aRet.append("SbxINT64"); break; | ||||
1814 | case SbxSALUINT64: aRet.append("SbxUINT64"); break; | ||||
1815 | case SbxINT: aRet.append("SbxINT"); break; | ||||
1816 | case SbxUINT: aRet.append("SbxUINT"); break; | ||||
1817 | case SbxVOID: aRet.append("SbxVOID"); break; | ||||
1818 | case SbxHRESULT: aRet.append("SbxHRESULT"); break; | ||||
1819 | case SbxPOINTER: aRet.append("SbxPOINTER"); break; | ||||
1820 | case SbxDIMARRAY: aRet.append("SbxDIMARRAY"); break; | ||||
1821 | case SbxCARRAY: aRet.append("SbxCARRAY"); break; | ||||
1822 | case SbxUSERDEF: aRet.append("SbxUSERDEF"); break; | ||||
1823 | case SbxLPSTR: aRet.append("SbxLPSTR"); break; | ||||
1824 | case SbxLPWSTR: aRet.append("SbxLPWSTR"); break; | ||||
1825 | case SbxCoreSTRING: aRet.append("SbxCoreSTRING"); break; | ||||
1826 | case SbxOBJECT | SbxARRAY: aRet.append("SbxARRAY"); break; | ||||
1827 | default: aRet.append("Unknown Sbx-Type!");break; | ||||
1828 | } | ||||
1829 | return aRet.makeStringAndClear(); | ||||
1830 | } | ||||
1831 | |||||
1832 | // Debugging help method to display the properties of a SbUnoObjects | ||||
1833 | static OUString Impl_DumpProperties(SbUnoObject& rUnoObj) | ||||
1834 | { | ||||
1835 | OUStringBuffer aRet; | ||||
1836 | aRet.append("Properties of object "); | ||||
1837 | aRet.append(getDbgObjectName(rUnoObj)); | ||||
1838 | |||||
1839 | // analyse the Uno-Infos to recognise the arrays | ||||
1840 | Reference< XIntrospectionAccess > xAccess = rUnoObj.getIntrospectionAccess(); | ||||
1841 | if( !xAccess.is() ) | ||||
1842 | { | ||||
1843 | Reference< XInvocation > xInvok = rUnoObj.getInvocation(); | ||||
1844 | if( xInvok.is() ) | ||||
1845 | xAccess = xInvok->getIntrospection(); | ||||
1846 | } | ||||
1847 | if( !xAccess.is() ) | ||||
1848 | { | ||||
1849 | aRet.append( "\nUnknown, no introspection available\n" ); | ||||
1850 | return aRet.makeStringAndClear(); | ||||
1851 | } | ||||
1852 | |||||
1853 | Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); | ||||
1854 | sal_uInt32 nUnoPropCount = props.getLength(); | ||||
1855 | const Property* pUnoProps = props.getConstArray(); | ||||
1856 | |||||
1857 | SbxArray* pProps = rUnoObj.GetProperties(); | ||||
1858 | sal_uInt32 nPropCount = pProps->Count32(); | ||||
1859 | sal_uInt32 nPropsPerLine = 1 + nPropCount / 30; | ||||
1860 | for( sal_uInt32 i = 0; i < nPropCount; i++ ) | ||||
1861 | { | ||||
1862 | SbxVariable* pVar = pProps->Get32( i ); | ||||
1863 | if( pVar ) | ||||
1864 | { | ||||
1865 | OUStringBuffer aPropStr; | ||||
1866 | if( (i % nPropsPerLine) == 0 ) | ||||
1867 | aPropStr.append( "\n" ); | ||||
1868 | |||||
1869 | // output the type and name | ||||
1870 | // Is it in Uno a sequence? | ||||
1871 | SbxDataType eType = pVar->GetFullType(); | ||||
1872 | |||||
1873 | bool bMaybeVoid = false; | ||||
1874 | if( i < nUnoPropCount ) | ||||
1875 | { | ||||
1876 | const Property& rProp = pUnoProps[ i ]; | ||||
1877 | |||||
1878 | // For MAYBEVOID freshly convert the type from Uno, | ||||
1879 | // so not just SbxEMPTY is returned. | ||||
1880 | if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) | ||||
1881 | { | ||||
1882 | eType = unoToSbxType( rProp.Type.getTypeClass() ); | ||||
1883 | bMaybeVoid = true; | ||||
1884 | } | ||||
1885 | if( eType == SbxOBJECT ) | ||||
1886 | { | ||||
1887 | Type aType = rProp.Type; | ||||
1888 | if( aType.getTypeClass() == TypeClass_SEQUENCE ) | ||||
1889 | eType = SbxDataType( SbxOBJECT | SbxARRAY ); | ||||
1890 | } | ||||
1891 | } | ||||
1892 | aPropStr.append( Dbg_SbxDataType2String( eType ) ); | ||||
1893 | if( bMaybeVoid ) | ||||
1894 | aPropStr.append( "/void" ); | ||||
1895 | aPropStr.append( " " ); | ||||
1896 | aPropStr.append( pVar->GetName() ); | ||||
1897 | |||||
1898 | if( i == nPropCount - 1 ) | ||||
1899 | aPropStr.append( "\n" ); | ||||
1900 | else | ||||
1901 | aPropStr.append( "; " ); | ||||
1902 | |||||
1903 | aRet.append( aPropStr.makeStringAndClear() ); | ||||
1904 | } | ||||
1905 | } | ||||
1906 | return aRet.makeStringAndClear(); | ||||
1907 | } | ||||
1908 | |||||
1909 | // Debugging help method to display the methods of an SbUnoObjects | ||||
1910 | static OUString Impl_DumpMethods(SbUnoObject& rUnoObj) | ||||
1911 | { | ||||
1912 | OUStringBuffer aRet; | ||||
1913 | aRet.append("Methods of object "); | ||||
1914 | aRet.append(getDbgObjectName(rUnoObj)); | ||||
1915 | |||||
1916 | // XIntrospectionAccess, so that the types of the parameter could be outputted | ||||
1917 | Reference< XIntrospectionAccess > xAccess = rUnoObj.getIntrospectionAccess(); | ||||
1918 | if( !xAccess.is() ) | ||||
1919 | { | ||||
1920 | Reference< XInvocation > xInvok = rUnoObj.getInvocation(); | ||||
1921 | if( xInvok.is() ) | ||||
1922 | xAccess = xInvok->getIntrospection(); | ||||
1923 | } | ||||
1924 | if( !xAccess.is() ) | ||||
1925 | { | ||||
1926 | aRet.append( "\nUnknown, no introspection available\n" ); | ||||
1927 | return aRet.makeStringAndClear(); | ||||
1928 | } | ||||
1929 | Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods | ||||
1930 | ( MethodConcept::ALL - MethodConcept::DANGEROUS ); | ||||
1931 | const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray(); | ||||
1932 | |||||
1933 | SbxArray* pMethods = rUnoObj.GetMethods(); | ||||
1934 | sal_uInt32 nMethodCount = pMethods->Count32(); | ||||
1935 | if( !nMethodCount ) | ||||
1936 | { | ||||
1937 | aRet.append( "\nNo methods found\n" ); | ||||
1938 | return aRet.makeStringAndClear(); | ||||
1939 | } | ||||
1940 | sal_uInt32 nPropsPerLine = 1 + nMethodCount / 30; | ||||
1941 | for( sal_uInt32 i = 0; i < nMethodCount; i++ ) | ||||
1942 | { | ||||
1943 | SbxVariable* pVar = pMethods->Get32( i ); | ||||
1944 | if( pVar ) | ||||
1945 | { | ||||
1946 | if( (i % nPropsPerLine) == 0 ) | ||||
1947 | aRet.append( "\n" ); | ||||
1948 | |||||
1949 | // address the method | ||||
1950 | const Reference< XIdlMethod >& rxMethod = pUnoMethods[i]; | ||||
1951 | |||||
1952 | // Is it in Uno a sequence? | ||||
1953 | SbxDataType eType = pVar->GetFullType(); | ||||
1954 | if( eType == SbxOBJECT ) | ||||
1955 | { | ||||
1956 | Reference< XIdlClass > xClass = rxMethod->getReturnType(); | ||||
1957 | if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE ) | ||||
1958 | eType = SbxDataType( SbxOBJECT | SbxARRAY ); | ||||
1959 | } | ||||
1960 | // output the name and the type | ||||
1961 | aRet.append( Dbg_SbxDataType2String( eType ) ); | ||||
1962 | aRet.append( " " ); | ||||
1963 | aRet.append ( pVar->GetName() ); | ||||
1964 | aRet.append( " ( " ); | ||||
1965 | |||||
1966 | // the get-method mustn't have a parameter | ||||
1967 | Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes(); | ||||
1968 | sal_uInt32 nParamCount = aParamsSeq.getLength(); | ||||
1969 | const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray(); | ||||
1970 | |||||
1971 | if( nParamCount > 0 ) | ||||
1972 | { | ||||
1973 | for( sal_uInt32 j = 0; j < nParamCount; j++ ) | ||||
1974 | { | ||||
1975 | aRet.append ( Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ) ); | ||||
1976 | if( j < nParamCount - 1 ) | ||||
1977 | aRet.append( ", " ); | ||||
1978 | } | ||||
1979 | } | ||||
1980 | else | ||||
1981 | aRet.append( "void" ); | ||||
1982 | |||||
1983 | aRet.append( " ) " ); | ||||
1984 | |||||
1985 | if( i == nMethodCount - 1 ) | ||||
1986 | aRet.append( "\n" ); | ||||
1987 | else | ||||
1988 | aRet.append( "; " ); | ||||
1989 | } | ||||
1990 | } | ||||
1991 | return aRet.makeStringAndClear(); | ||||
1992 | } | ||||
1993 | |||||
1994 | |||||
1995 | // Implementation SbUnoObject | ||||
1996 | void SbUnoObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | ||||
1997 | { | ||||
1998 | if( bNeedIntrospection ) | ||||
1999 | doIntrospection(); | ||||
2000 | |||||
2001 | const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); | ||||
2002 | if( !pHint ) | ||||
2003 | return; | ||||
2004 | |||||
2005 | SbxVariable* pVar = pHint->GetVar(); | ||||
2006 | SbxArray* pParams = pVar->GetParameters(); | ||||
2007 | SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar ); | ||||
2008 | SbUnoMethod* pMeth = dynamic_cast<SbUnoMethod*>( pVar ); | ||||
2009 | if( pProp ) | ||||
2010 | { | ||||
2011 | bool bInvocation = pProp->isInvocationBased(); | ||||
2012 | if( pHint->GetId() == SfxHintId::BasicDataWanted ) | ||||
2013 | { | ||||
2014 | // Test-Properties | ||||
2015 | sal_Int32 nId = pProp->nId; | ||||
2016 | if( nId < 0 ) | ||||
2017 | { | ||||
2018 | // Id == -1: Display implemented interfaces according the ClassProvider | ||||
2019 | if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" | ||||
2020 | { | ||||
2021 | OUString aRetStr = Impl_GetSupportedInterfaces(*this); | ||||
2022 | pVar->PutString( aRetStr ); | ||||
2023 | } | ||||
2024 | // Id == -2: output properties | ||||
2025 | else if( nId == -2 ) // Property ID_DBG_PROPERTIES | ||||
2026 | { | ||||
2027 | // now all properties must be created | ||||
2028 | implCreateAll(); | ||||
2029 | OUString aRetStr = Impl_DumpProperties(*this); | ||||
2030 | pVar->PutString( aRetStr ); | ||||
2031 | } | ||||
2032 | // Id == -3: output the methods | ||||
2033 | else if( nId == -3 ) // Property ID_DBG_METHODS | ||||
2034 | { | ||||
2035 | // now all properties must be created | ||||
2036 | implCreateAll(); | ||||
2037 | OUString aRetStr = Impl_DumpMethods(*this); | ||||
2038 | pVar->PutString( aRetStr ); | ||||
2039 | } | ||||
2040 | return; | ||||
2041 | } | ||||
2042 | |||||
2043 | if( !bInvocation && mxUnoAccess.is() ) | ||||
2044 | { | ||||
2045 | try | ||||
2046 | { | ||||
2047 | if ( maStructInfo ) | ||||
2048 | { | ||||
2049 | StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); | ||||
2050 | if ( aMember.isEmpty() ) | ||||
2051 | { | ||||
2052 | StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 85 ) ); | ||||
2053 | } | ||||
2054 | else | ||||
2055 | { | ||||
2056 | if ( pProp->isUnoStruct() ) | ||||
2057 | { | ||||
2058 | SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMember ); | ||||
2059 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pSbUnoObject); | ||||
2060 | pVar->PutObject( xWrapper.get() ); | ||||
2061 | } | ||||
2062 | else | ||||
2063 | { | ||||
2064 | Any aRetAny = aMember.getValue(); | ||||
2065 | // take over the value from Uno to Sbx | ||||
2066 | unoToSbxValue( pVar, aRetAny ); | ||||
2067 | } | ||||
2068 | return; | ||||
2069 | } | ||||
2070 | } | ||||
2071 | // get the value | ||||
2072 | Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); | ||||
2073 | Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() ); | ||||
2074 | // The use of getPropertyValue (instead of using the index) is | ||||
2075 | // suboptimal, but the refactoring to XInvocation is already pending | ||||
2076 | // Otherwise it is possible to use FastPropertySet | ||||
2077 | |||||
2078 | // take over the value from Uno to Sbx | ||||
2079 | unoToSbxValue( pVar, aRetAny ); | ||||
2080 | } | ||||
2081 | catch( const Exception& ) | ||||
2082 | { | ||||
2083 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2084 | } | ||||
2085 | } | ||||
2086 | else if( bInvocation && mxInvocation.is() ) | ||||
2087 | { | ||||
2088 | try | ||||
2089 | { | ||||
2090 | sal_uInt32 nParamCount = pParams ? (pParams->Count32() - 1) : 0; | ||||
2091 | bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() ); | ||||
2092 | Any aRetAny; | ||||
2093 | if ( bCanBeConsideredAMethod && nParamCount ) | ||||
2094 | { | ||||
2095 | // Automation properties have methods, so... we need to invoke this through | ||||
2096 | // XInvocation | ||||
2097 | Sequence<Any> args; | ||||
2098 | processAutomationParams( pParams, args, nParamCount ); | ||||
2099 | aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, INVOKETYPE::GetProp ); | ||||
2100 | } | ||||
2101 | else | ||||
2102 | aRetAny = mxInvocation->getValue( pProp->GetName() ); | ||||
2103 | // take over the value from Uno to Sbx | ||||
2104 | unoToSbxValue( pVar, aRetAny ); | ||||
2105 | if( pParams && bCanBeConsideredAMethod ) | ||||
2106 | pVar->SetParameters( nullptr ); | ||||
2107 | |||||
2108 | } | ||||
2109 | catch( const Exception& ) | ||||
2110 | { | ||||
2111 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2112 | } | ||||
2113 | } | ||||
2114 | } | ||||
2115 | else if( pHint->GetId() == SfxHintId::BasicDataChanged ) | ||||
2116 | { | ||||
2117 | if( !bInvocation && mxUnoAccess.is() ) | ||||
2118 | { | ||||
2119 | if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY ) | ||||
2120 | { | ||||
2121 | StarBASIC::Error( ERRCODE_BASIC_PROP_READONLYErrCode( ErrCodeArea::Sbx, ErrCodeClass::Read, 15) ); | ||||
2122 | return; | ||||
2123 | } | ||||
2124 | if ( maStructInfo ) | ||||
2125 | { | ||||
2126 | StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() ); | ||||
2127 | if ( aMember.isEmpty() ) | ||||
2128 | { | ||||
2129 | StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 85 ) ); | ||||
2130 | } | ||||
2131 | else | ||||
2132 | { | ||||
2133 | Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); | ||||
2134 | aMember.setValue( aAnyValue ); | ||||
2135 | } | ||||
2136 | return; | ||||
2137 | } | ||||
2138 | // take over the value from Uno to Sbx | ||||
2139 | Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); | ||||
2140 | try | ||||
2141 | { | ||||
2142 | // set the value | ||||
2143 | Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); | ||||
2144 | xPropSet->setPropertyValue( pProp->GetName(), aAnyValue ); | ||||
2145 | // The use of getPropertyValue (instead of using the index) is | ||||
2146 | // suboptimal, but the refactoring to XInvocation is already pending | ||||
2147 | // Otherwise it is possible to use FastPropertySet | ||||
2148 | } | ||||
2149 | catch( const Exception& ) | ||||
2150 | { | ||||
2151 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2152 | } | ||||
2153 | } | ||||
2154 | else if( bInvocation && mxInvocation.is() ) | ||||
2155 | { | ||||
2156 | // take over the value from Uno to Sbx | ||||
2157 | Any aAnyValue = sbxToUnoValueImpl( pVar ); | ||||
2158 | try | ||||
2159 | { | ||||
2160 | // set the value | ||||
2161 | mxInvocation->setValue( pProp->GetName(), aAnyValue ); | ||||
2162 | } | ||||
2163 | catch( const Exception& ) | ||||
2164 | { | ||||
2165 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2166 | } | ||||
2167 | } | ||||
2168 | } | ||||
2169 | } | ||||
2170 | else if( pMeth ) | ||||
2171 | { | ||||
2172 | bool bInvocation = pMeth->isInvocationBased(); | ||||
2173 | if( pHint->GetId() == SfxHintId::BasicDataWanted ) | ||||
2174 | { | ||||
2175 | // number of Parameter -1 because of Param0 == this | ||||
2176 | sal_uInt32 nParamCount = pParams ? (pParams->Count32() - 1) : 0; | ||||
2177 | Sequence<Any> args; | ||||
2178 | bool bOutParams = false; | ||||
2179 | |||||
2180 | if( !bInvocation && mxUnoAccess.is() ) | ||||
2181 | { | ||||
2182 | // get info | ||||
2183 | const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); | ||||
2184 | const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); | ||||
2185 | sal_uInt32 nUnoParamCount = rInfoSeq.getLength(); | ||||
2186 | sal_uInt32 nAllocParamCount = nParamCount; | ||||
2187 | |||||
2188 | // ignore surplus parameter; alternative: throw an error | ||||
2189 | if( nParamCount > nUnoParamCount ) | ||||
2190 | { | ||||
2191 | nParamCount = nUnoParamCount; | ||||
2192 | nAllocParamCount = nParamCount; | ||||
2193 | } | ||||
2194 | else if( nParamCount < nUnoParamCount ) | ||||
2195 | { | ||||
2196 | SbiInstance* pInst = GetSbData()->pInst; | ||||
2197 | if( pInst && pInst->IsCompatibility() ) | ||||
2198 | { | ||||
2199 | // Check types | ||||
2200 | bool bError = false; | ||||
2201 | for( sal_uInt32 i = nParamCount ; i < nUnoParamCount ; i++ ) | ||||
2202 | { | ||||
2203 | const ParamInfo& rInfo = pParamInfos[i]; | ||||
2204 | const Reference< XIdlClass >& rxClass = rInfo.aType; | ||||
2205 | if( rxClass->getTypeClass() != TypeClass_ANY ) | ||||
2206 | { | ||||
2207 | bError = true; | ||||
2208 | StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONALErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 27) ); | ||||
2209 | } | ||||
2210 | } | ||||
2211 | if( !bError ) | ||||
2212 | nAllocParamCount = nUnoParamCount; | ||||
2213 | } | ||||
2214 | } | ||||
2215 | |||||
2216 | if( nAllocParamCount > 0 ) | ||||
2217 | { | ||||
2218 | args.realloc( nAllocParamCount ); | ||||
2219 | Any* pAnyArgs = args.getArray(); | ||||
2220 | for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) | ||||
2221 | { | ||||
2222 | const ParamInfo& rInfo = pParamInfos[i]; | ||||
2223 | const Reference< XIdlClass >& rxClass = rInfo.aType; | ||||
2224 | |||||
2225 | css::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() ); | ||||
2226 | |||||
2227 | // ATTENTION: Don't forget for Sbx-Parameter the offset! | ||||
2228 | pAnyArgs[i] = sbxToUnoValue( pParams->Get32(i + 1), aType ); | ||||
2229 | |||||
2230 | // If it is not certain check whether the out-parameter are available. | ||||
2231 | if( !bOutParams ) | ||||
2232 | { | ||||
2233 | ParamMode aParamMode = rInfo.aMode; | ||||
2234 | if( aParamMode != ParamMode_IN ) | ||||
2235 | bOutParams = true; | ||||
2236 | } | ||||
2237 | } | ||||
2238 | } | ||||
2239 | } | ||||
2240 | else if( bInvocation && pParams && mxInvocation.is() ) | ||||
2241 | { | ||||
2242 | processAutomationParams( pParams, args, nParamCount ); | ||||
2243 | } | ||||
2244 | |||||
2245 | // call the method | ||||
2246 | GetSbData()->bBlockCompilerError = true; // #106433 Block compiler errors for API calls | ||||
2247 | try | ||||
2248 | { | ||||
2249 | if( !bInvocation && mxUnoAccess.is() ) | ||||
2250 | { | ||||
2251 | Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args ); | ||||
2252 | |||||
2253 | // take over the value from Uno to Sbx | ||||
2254 | unoToSbxValue( pVar, aRetAny ); | ||||
2255 | |||||
2256 | // Did we to copy back the Out-Parameter? | ||||
2257 | if( bOutParams ) | ||||
2258 | { | ||||
2259 | const Any* pAnyArgs = args.getConstArray(); | ||||
2260 | |||||
2261 | // get info | ||||
2262 | const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos(); | ||||
2263 | const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); | ||||
2264 | |||||
2265 | sal_uInt32 j; | ||||
2266 | for( j = 0 ; j < nParamCount ; j++ ) | ||||
2267 | { | ||||
2268 | const ParamInfo& rInfo = pParamInfos[j]; | ||||
2269 | ParamMode aParamMode = rInfo.aMode; | ||||
2270 | if( aParamMode != ParamMode_IN ) | ||||
2271 | unoToSbxValue( pParams->Get32(j + 1), pAnyArgs[ j ] ); | ||||
2272 | } | ||||
2273 | } | ||||
2274 | } | ||||
2275 | else if( bInvocation && mxInvocation.is() ) | ||||
2276 | { | ||||
2277 | Any aRetAny = invokeAutomationMethod( pMeth->GetName(), args, pParams, nParamCount, mxInvocation, INVOKETYPE::Func ); | ||||
2278 | unoToSbxValue( pVar, aRetAny ); | ||||
2279 | } | ||||
2280 | |||||
2281 | // remove parameter here, because this was not done anymore in unoToSbxValue() | ||||
2282 | // for arrays | ||||
2283 | if( pParams ) | ||||
2284 | pVar->SetParameters( nullptr ); | ||||
2285 | } | ||||
2286 | catch( const Exception& ) | ||||
2287 | { | ||||
2288 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2289 | } | ||||
2290 | GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors | ||||
2291 | } | ||||
2292 | } | ||||
2293 | else | ||||
2294 | SbxObject::Notify( rBC, rHint ); | ||||
2295 | } | ||||
2296 | |||||
2297 | |||||
2298 | SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ ) | ||||
2299 | : SbxObject( aName_ ) | ||||
2300 | , bNeedIntrospection( true ) | ||||
2301 | , bNativeCOMObject( false ) | ||||
2302 | { | ||||
2303 | // beat out again the default properties of Sbx | ||||
2304 | Remove( "Name", SbxClassType::DontCare ); | ||||
2305 | Remove( "Parent", SbxClassType::DontCare ); | ||||
2306 | |||||
2307 | // check the type of the objects | ||||
2308 | TypeClass eType = aUnoObj_.getValueType().getTypeClass(); | ||||
2309 | Reference< XInterface > x; | ||||
2310 | if( eType == TypeClass_INTERFACE ) | ||||
2311 | { | ||||
2312 | // get the interface from the Any | ||||
2313 | aUnoObj_ >>= x; | ||||
2314 | if( !x.is() ) | ||||
2315 | return; | ||||
2316 | } | ||||
2317 | |||||
2318 | Reference< XTypeProvider > xTypeProvider; | ||||
2319 | // Did the object have an invocation itself? | ||||
2320 | mxInvocation.set( x, UNO_QUERY ); | ||||
2321 | |||||
2322 | xTypeProvider.set( x, UNO_QUERY ); | ||||
2323 | |||||
2324 | if( mxInvocation.is() ) | ||||
2325 | { | ||||
2326 | |||||
2327 | // get the ExactName | ||||
2328 | mxExactNameInvocation.set( mxInvocation, UNO_QUERY ); | ||||
2329 | |||||
2330 | // The remainder refers only to the introspection | ||||
2331 | if( !xTypeProvider.is() ) | ||||
2332 | { | ||||
2333 | bNeedIntrospection = false; | ||||
2334 | return; | ||||
2335 | } | ||||
2336 | |||||
2337 | // Ignore introspection based members for COM objects to avoid | ||||
2338 | // hiding of equally named COM symbols, e.g. XInvocation::getValue | ||||
2339 | Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY ); | ||||
2340 | if( xAutomationObject.is() ) | ||||
2341 | bNativeCOMObject = true; | ||||
2342 | } | ||||
2343 | |||||
2344 | maTmpUnoObj = aUnoObj_; | ||||
2345 | |||||
2346 | |||||
2347 | //*** Define the name *** | ||||
2348 | bool bFatalError = true; | ||||
2349 | |||||
2350 | // Is it an interface or a struct? | ||||
2351 | bool bSetClassName = false; | ||||
2352 | OUString aClassName_; | ||||
2353 | if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION ) | ||||
2354 | { | ||||
2355 | // Struct is Ok | ||||
2356 | bFatalError = false; | ||||
2357 | |||||
2358 | // insert the real name of the class | ||||
2359 | if( aName_.isEmpty() ) | ||||
2360 | { | ||||
2361 | aClassName_ = aUnoObj_.getValueType().getTypeName(); | ||||
2362 | bSetClassName = true; | ||||
2363 | } | ||||
2364 | StructRefInfo aThisStruct( maTmpUnoObj, maTmpUnoObj.getValueType(), 0 ); | ||||
2365 | maStructInfo = std::make_shared<SbUnoStructRefObject>( GetName(), aThisStruct ); | ||||
2366 | } | ||||
2367 | else if( eType == TypeClass_INTERFACE ) | ||||
2368 | { | ||||
2369 | // Interface works always through the type in the Any | ||||
2370 | bFatalError = false; | ||||
2371 | } | ||||
2372 | if( bSetClassName ) | ||||
2373 | SetClassName( aClassName_ ); | ||||
2374 | |||||
2375 | // Neither interface nor Struct -> FatalError | ||||
2376 | if( bFatalError ) | ||||
2377 | { | ||||
2378 | StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ) ); | ||||
2379 | return; | ||||
2380 | } | ||||
2381 | |||||
2382 | // pass the introspection primal on demand | ||||
2383 | } | ||||
2384 | |||||
2385 | SbUnoObject::~SbUnoObject() | ||||
2386 | { | ||||
2387 | } | ||||
2388 | |||||
2389 | |||||
2390 | // pass the introspection on Demand | ||||
2391 | void SbUnoObject::doIntrospection() | ||||
2392 | { | ||||
2393 | if( !bNeedIntrospection ) | ||||
2394 | return; | ||||
2395 | |||||
2396 | Reference<XComponentContext> xContext = comphelper::getProcessComponentContext(); | ||||
2397 | |||||
2398 | if (!xContext.is()) | ||||
2399 | return; | ||||
2400 | |||||
2401 | |||||
2402 | // get the introspection service | ||||
2403 | Reference<XIntrospection> xIntrospection; | ||||
2404 | |||||
2405 | try | ||||
2406 | { | ||||
2407 | xIntrospection = theIntrospection::get(xContext); | ||||
2408 | } | ||||
2409 | catch ( const css::uno::DeploymentException& ) | ||||
2410 | { | ||||
2411 | } | ||||
2412 | |||||
2413 | if (!xIntrospection.is()) | ||||
2414 | return; | ||||
2415 | |||||
2416 | bNeedIntrospection = false; | ||||
2417 | |||||
2418 | // pass the introspection | ||||
2419 | try | ||||
2420 | { | ||||
2421 | mxUnoAccess = xIntrospection->inspect( maTmpUnoObj ); | ||||
2422 | } | ||||
2423 | catch( const RuntimeException& e ) | ||||
2424 | { | ||||
2425 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), implGetExceptionMsg( e ) ); | ||||
2426 | } | ||||
2427 | |||||
2428 | if( !mxUnoAccess.is() ) | ||||
2429 | { | ||||
2430 | // #51475 mark to indicate an invalid object (no mxMaterialHolder) | ||||
2431 | return; | ||||
2432 | } | ||||
2433 | |||||
2434 | // get MaterialHolder from access | ||||
2435 | mxMaterialHolder.set( mxUnoAccess, UNO_QUERY ); | ||||
2436 | |||||
2437 | // get ExactName from access | ||||
2438 | mxExactName.set( mxUnoAccess, UNO_QUERY ); | ||||
2439 | } | ||||
2440 | |||||
2441 | |||||
2442 | // Start of a list of all SbUnoMethod-Instances | ||||
2443 | static SbUnoMethod* pFirst = nullptr; | ||||
2444 | |||||
2445 | void clearUnoMethodsForBasic( StarBASIC const * pBasic ) | ||||
2446 | { | ||||
2447 | SbUnoMethod* pMeth = pFirst; | ||||
2448 | while( pMeth ) | ||||
2449 | { | ||||
2450 | SbxObject* pObject = pMeth->GetParent(); | ||||
2451 | if ( pObject ) | ||||
2452 | { | ||||
2453 | StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() ); | ||||
2454 | if ( pModBasic == pBasic ) | ||||
2455 | { | ||||
2456 | // for now the solution is to remove the method from the list and to clear it, | ||||
2457 | // but in case the element should be correctly transferred to another StarBASIC, | ||||
2458 | // we should either set module parent to NULL without clearing it, or even | ||||
2459 | // set the new StarBASIC as the parent of the module | ||||
2460 | // pObject->SetParent( NULL ); | ||||
2461 | |||||
2462 | if( pMeth == pFirst ) | ||||
2463 | pFirst = pMeth->pNext; | ||||
2464 | else if( pMeth->pPrev ) | ||||
2465 | pMeth->pPrev->pNext = pMeth->pNext; | ||||
2466 | if( pMeth->pNext ) | ||||
2467 | pMeth->pNext->pPrev = pMeth->pPrev; | ||||
2468 | |||||
2469 | pMeth->pPrev = nullptr; | ||||
2470 | pMeth->pNext = nullptr; | ||||
2471 | |||||
2472 | pMeth->SbxValue::Clear(); | ||||
2473 | pObject->SbxValue::Clear(); | ||||
2474 | |||||
2475 | // start from the beginning after object clearing, the cycle will end since the method is removed each time | ||||
2476 | pMeth = pFirst; | ||||
2477 | } | ||||
2478 | else | ||||
2479 | pMeth = pMeth->pNext; | ||||
2480 | } | ||||
2481 | else | ||||
2482 | pMeth = pMeth->pNext; | ||||
2483 | } | ||||
2484 | } | ||||
2485 | |||||
2486 | void clearUnoMethods() | ||||
2487 | { | ||||
2488 | SbUnoMethod* pMeth = pFirst; | ||||
2489 | while( pMeth ) | ||||
2490 | { | ||||
2491 | pMeth->SbxValue::Clear(); | ||||
2492 | pMeth = pMeth->pNext; | ||||
2493 | } | ||||
2494 | } | ||||
2495 | |||||
2496 | |||||
2497 | SbUnoMethod::SbUnoMethod | ||||
2498 | ( | ||||
2499 | const OUString& aName_, | ||||
2500 | SbxDataType eSbxType, | ||||
2501 | Reference< XIdlMethod > const & xUnoMethod_, | ||||
2502 | bool bInvocation | ||||
2503 | ) | ||||
2504 | : SbxMethod( aName_, eSbxType ) | ||||
2505 | , mbInvocation( bInvocation ) | ||||
2506 | { | ||||
2507 | m_xUnoMethod = xUnoMethod_; | ||||
2508 | pParamInfoSeq = nullptr; | ||||
2509 | |||||
2510 | // enregister the method in a list | ||||
2511 | pNext = pFirst; | ||||
2512 | pPrev = nullptr; | ||||
2513 | pFirst = this; | ||||
2514 | if( pNext ) | ||||
2515 | pNext->pPrev = this; | ||||
2516 | } | ||||
2517 | |||||
2518 | SbUnoMethod::~SbUnoMethod() | ||||
2519 | { | ||||
2520 | pParamInfoSeq.reset(); | ||||
2521 | |||||
2522 | if( this == pFirst ) | ||||
2523 | pFirst = pNext; | ||||
2524 | else if( pPrev ) | ||||
2525 | pPrev->pNext = pNext; | ||||
2526 | if( pNext ) | ||||
2527 | pNext->pPrev = pPrev; | ||||
2528 | } | ||||
2529 | |||||
2530 | SbxInfo* SbUnoMethod::GetInfo() | ||||
2531 | { | ||||
2532 | if( !pInfo.is() && m_xUnoMethod.is() ) | ||||
2533 | { | ||||
2534 | SbiInstance* pInst = GetSbData()->pInst; | ||||
2535 | if( pInst && pInst->IsCompatibility() ) | ||||
2536 | { | ||||
2537 | pInfo = new SbxInfo(); | ||||
2538 | |||||
2539 | const Sequence<ParamInfo>& rInfoSeq = getParamInfos(); | ||||
2540 | const ParamInfo* pParamInfos = rInfoSeq.getConstArray(); | ||||
2541 | sal_uInt32 nParamCount = rInfoSeq.getLength(); | ||||
2542 | |||||
2543 | for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) | ||||
2544 | { | ||||
2545 | const ParamInfo& rInfo = pParamInfos[i]; | ||||
2546 | OUString aParamName = rInfo.aName; | ||||
2547 | |||||
2548 | pInfo->AddParam( aParamName, SbxVARIANT, SbxFlagBits::Read ); | ||||
2549 | } | ||||
2550 | } | ||||
2551 | } | ||||
2552 | return pInfo.get(); | ||||
2553 | } | ||||
2554 | |||||
2555 | const Sequence<ParamInfo>& SbUnoMethod::getParamInfos() | ||||
2556 | { | ||||
2557 | if (!pParamInfoSeq) | ||||
2558 | { | ||||
2559 | Sequence<ParamInfo> aTmp; | ||||
2560 | if (m_xUnoMethod.is()) | ||||
2561 | aTmp = m_xUnoMethod->getParameterInfos(); | ||||
2562 | pParamInfoSeq.reset( new Sequence<ParamInfo>(aTmp) ); | ||||
2563 | } | ||||
2564 | return *pParamInfoSeq; | ||||
2565 | } | ||||
2566 | |||||
2567 | SbUnoProperty::SbUnoProperty | ||||
2568 | ( | ||||
2569 | const OUString& aName_, | ||||
2570 | SbxDataType eSbxType, | ||||
2571 | SbxDataType eRealSbxType, | ||||
2572 | const Property& aUnoProp_, | ||||
2573 | sal_Int32 nId_, | ||||
2574 | bool bInvocation, | ||||
2575 | bool bUnoStruct | ||||
2576 | ) | ||||
2577 | : SbxProperty( aName_, eSbxType ) | ||||
2578 | , aUnoProp( aUnoProp_ ) | ||||
2579 | , nId( nId_ ) | ||||
2580 | , mbInvocation( bInvocation ) | ||||
2581 | , mRealType( eRealSbxType ) | ||||
2582 | , mbUnoStruct( bUnoStruct ) | ||||
2583 | { | ||||
2584 | // as needed establish a dummy array so that SbiRuntime::CheckArray() works | ||||
2585 | static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT ); | ||||
2586 | if( eSbxType & SbxARRAY ) | ||||
2587 | PutObject( xDummyArray.get() ); | ||||
2588 | } | ||||
2589 | |||||
2590 | SbUnoProperty::~SbUnoProperty() | ||||
2591 | {} | ||||
2592 | |||||
2593 | |||||
2594 | SbxVariable* SbUnoObject::Find( const OUString& rName, SbxClassType t ) | ||||
2595 | { | ||||
2596 | static Reference< XIdlMethod > xDummyMethod; | ||||
2597 | static Property aDummyProp; | ||||
2598 | |||||
2599 | SbxVariable* pRes = SbxObject::Find( rName, t ); | ||||
2600 | |||||
2601 | if( bNeedIntrospection ) | ||||
| |||||
2602 | doIntrospection(); | ||||
2603 | |||||
2604 | // New 1999-03-04: Create properties on demand. Therefore search now via | ||||
2605 | // IntrospectionAccess if a property or a method of the required name exist | ||||
2606 | if( !pRes ) | ||||
2607 | { | ||||
2608 | OUString aUName( rName ); | ||||
2609 | if( mxUnoAccess.is() && !bNativeCOMObject ) | ||||
2610 | { | ||||
2611 | if( mxExactName.is() ) | ||||
2612 | { | ||||
2613 | OUString aUExactName = mxExactName->getExactName( aUName ); | ||||
2614 | if( !aUExactName.isEmpty() ) | ||||
2615 | { | ||||
2616 | aUName = aUExactName; | ||||
2617 | } | ||||
2618 | } | ||||
2619 | if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) ) | ||||
2620 | { | ||||
2621 | const Property& rProp = mxUnoAccess-> | ||||
2622 | getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); | ||||
2623 | |||||
2624 | // If the property could be void the type had to be set to Variant | ||||
2625 | SbxDataType eSbxType; | ||||
2626 | if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) | ||||
2627 | eSbxType = SbxVARIANT; | ||||
2628 | else | ||||
2629 | eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); | ||||
2630 | |||||
2631 | SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); | ||||
2632 | // create the property and superimpose it | ||||
2633 | auto pProp = tools::make_ref<SbUnoProperty>( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT ) ); | ||||
2634 | QuickInsert( pProp.get() ); | ||||
2635 | pRes = pProp.get(); | ||||
2636 | } | ||||
2637 | else if( mxUnoAccess->hasMethod( aUName, | ||||
2638 | MethodConcept::ALL - MethodConcept::DANGEROUS ) ) | ||||
2639 | { | ||||
2640 | // address the method | ||||
2641 | const Reference< XIdlMethod >& rxMethod = mxUnoAccess-> | ||||
2642 | getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS ); | ||||
2643 | |||||
2644 | // create SbUnoMethod and superimpose it | ||||
2645 | auto xMethRef = tools::make_ref<SbUnoMethod>( rxMethod->getName(), | ||||
2646 | unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); | ||||
2647 | QuickInsert( xMethRef.get() ); | ||||
2648 | pRes = xMethRef.get(); | ||||
2649 | } | ||||
2650 | |||||
2651 | // If nothing was found check via XNameAccess | ||||
2652 | if( !pRes ) | ||||
2653 | { | ||||
2654 | try | ||||
2655 | { | ||||
2656 | Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY ); | ||||
2657 | |||||
2658 | if( xNameAccess.is() && xNameAccess->hasByName( rName ) ) | ||||
2659 | { | ||||
2660 | Any aAny = xNameAccess->getByName( rName ); | ||||
2661 | |||||
2662 | // ATTENTION: Because of XNameAccess, the variable generated here | ||||
2663 | // may not be included as a fixed property in the object and therefore | ||||
2664 | // won't be stored anywhere. | ||||
2665 | // If this leads to problems, it has to be created | ||||
2666 | // synthetically or a class SbUnoNameAccessProperty, | ||||
2667 | // which checks the existence on access and which | ||||
2668 | // is disposed if the name is not found anymore. | ||||
2669 | pRes = new SbxVariable( SbxVARIANT ); | ||||
2670 | unoToSbxValue( pRes, aAny ); | ||||
2671 | } | ||||
2672 | } | ||||
2673 | catch( const NoSuchElementException& e ) | ||||
2674 | { | ||||
2675 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), implGetExceptionMsg( e ) ); | ||||
2676 | } | ||||
2677 | catch( const Exception& ) | ||||
2678 | { | ||||
2679 | // Establish so that the exception error will not be overwritten | ||||
2680 | if( !pRes ) | ||||
2681 | pRes = new SbxVariable( SbxVARIANT ); | ||||
2682 | |||||
2683 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2684 | } | ||||
2685 | } | ||||
2686 | } | ||||
2687 | if( !pRes
| ||||
2688 | { | ||||
2689 | if( mxExactNameInvocation.is() ) | ||||
2690 | { | ||||
2691 | OUString aUExactName = mxExactNameInvocation->getExactName( aUName ); | ||||
2692 | if( !aUExactName.isEmpty() ) | ||||
2693 | { | ||||
2694 | aUName = aUExactName; | ||||
2695 | } | ||||
2696 | } | ||||
2697 | |||||
2698 | try | ||||
2699 | { | ||||
2700 | if( mxInvocation->hasProperty( aUName ) ) | ||||
2701 | { | ||||
2702 | // create a property and superimpose it | ||||
2703 | auto xVarRef = tools::make_ref<SbUnoProperty>( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false ); | ||||
2704 | QuickInsert( xVarRef.get() ); | ||||
2705 | pRes = xVarRef.get(); | ||||
2706 | } | ||||
2707 | else if( mxInvocation->hasMethod( aUName ) ) | ||||
2708 | { | ||||
2709 | // create SbUnoMethode and superimpose it | ||||
2710 | auto xMethRef = tools::make_ref<SbUnoMethod>( aUName, SbxVARIANT, xDummyMethod, true ); | ||||
2711 | QuickInsert( xMethRef.get() ); | ||||
2712 | pRes = xMethRef.get(); | ||||
2713 | } | ||||
2714 | else | ||||
2715 | { | ||||
2716 | Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY ); | ||||
2717 | if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) ) | ||||
2718 | { | ||||
2719 | auto xMethRef = tools::make_ref<SbUnoMethod>( aUName, SbxVARIANT, xDummyMethod, true ); | ||||
2720 | QuickInsert( xMethRef.get() ); | ||||
2721 | pRes = xMethRef.get(); | ||||
2722 | } | ||||
2723 | |||||
2724 | } | ||||
2725 | } | ||||
2726 | catch( const RuntimeException& e ) | ||||
2727 | { | ||||
2728 | // Establish so that the exception error will not be overwritten | ||||
2729 | if( !pRes ) | ||||
2730 | pRes = new SbxVariable( SbxVARIANT ); | ||||
2731 | |||||
2732 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), implGetExceptionMsg( e ) ); | ||||
2733 | } | ||||
2734 | } | ||||
2735 | } | ||||
2736 | |||||
2737 | // At the very end checking if the Dbg_-Properties are meant | ||||
2738 | |||||
2739 | if( !pRes
| ||||
2740 | { | ||||
2741 | if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) || | ||||
2742 | rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) || | ||||
2743 | rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) ) | ||||
2744 | { | ||||
2745 | // Create | ||||
2746 | implCreateDbgProperties(); | ||||
2747 | |||||
2748 | // Now they have to be found regular | ||||
2749 | pRes = SbxObject::Find( rName, SbxClassType::DontCare ); | ||||
2750 | } | ||||
2751 | } | ||||
2752 | return pRes; | ||||
| |||||
2753 | } | ||||
2754 | |||||
2755 | |||||
2756 | // help method to create the dbg_-Properties | ||||
2757 | void SbUnoObject::implCreateDbgProperties() | ||||
2758 | { | ||||
2759 | Property aProp; | ||||
2760 | |||||
2761 | // Id == -1: display the implemented interfaces corresponding the ClassProvider | ||||
2762 | auto xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false ); | ||||
2763 | QuickInsert( xVarRef.get() ); | ||||
2764 | |||||
2765 | // Id == -2: output the properties | ||||
2766 | xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false ); | ||||
2767 | QuickInsert( xVarRef.get() ); | ||||
2768 | |||||
2769 | // Id == -3: output the Methods | ||||
2770 | xVarRef = tools::make_ref<SbUnoProperty>( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false ); | ||||
2771 | QuickInsert( xVarRef.get() ); | ||||
2772 | } | ||||
2773 | |||||
2774 | void SbUnoObject::implCreateAll() | ||||
2775 | { | ||||
2776 | // throw away all existing methods and properties | ||||
2777 | pMethods = tools::make_ref<SbxArray>(); | ||||
2778 | pProps = tools::make_ref<SbxArray>(); | ||||
2779 | |||||
2780 | if( bNeedIntrospection ) doIntrospection(); | ||||
2781 | |||||
2782 | // get introspection | ||||
2783 | Reference< XIntrospectionAccess > xAccess = mxUnoAccess; | ||||
2784 | if( !xAccess.is() || bNativeCOMObject ) | ||||
2785 | { | ||||
2786 | if( mxInvocation.is() ) | ||||
2787 | xAccess = mxInvocation->getIntrospection(); | ||||
2788 | else if( bNativeCOMObject ) | ||||
2789 | return; | ||||
2790 | } | ||||
2791 | if( !xAccess.is() ) | ||||
2792 | return; | ||||
2793 | |||||
2794 | // Establish properties | ||||
2795 | Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); | ||||
2796 | sal_uInt32 nPropCount = props.getLength(); | ||||
2797 | const Property* pProps_ = props.getConstArray(); | ||||
2798 | |||||
2799 | sal_uInt32 i; | ||||
2800 | for( i = 0 ; i < nPropCount ; i++ ) | ||||
2801 | { | ||||
2802 | const Property& rProp = pProps_[ i ]; | ||||
2803 | |||||
2804 | // If the property could be void the type had to be set to Variant | ||||
2805 | SbxDataType eSbxType; | ||||
2806 | if( rProp.Attributes & PropertyAttribute::MAYBEVOID ) | ||||
2807 | eSbxType = SbxVARIANT; | ||||
2808 | else | ||||
2809 | eSbxType = unoToSbxType( rProp.Type.getTypeClass() ); | ||||
2810 | |||||
2811 | SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType ); | ||||
2812 | // Create property and superimpose it | ||||
2813 | auto xVarRef = tools::make_ref<SbUnoProperty>( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT ) ); | ||||
2814 | QuickInsert( xVarRef.get() ); | ||||
2815 | } | ||||
2816 | |||||
2817 | // Create Dbg_-Properties | ||||
2818 | implCreateDbgProperties(); | ||||
2819 | |||||
2820 | // Create methods | ||||
2821 | Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods | ||||
2822 | ( MethodConcept::ALL - MethodConcept::DANGEROUS ); | ||||
2823 | sal_uInt32 nMethCount = aMethodSeq.getLength(); | ||||
2824 | const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray(); | ||||
2825 | for( i = 0 ; i < nMethCount ; i++ ) | ||||
2826 | { | ||||
2827 | // address method | ||||
2828 | const Reference< XIdlMethod >& rxMethod = pMethods_[i]; | ||||
2829 | |||||
2830 | // Create SbUnoMethod and superimpose it | ||||
2831 | auto xMethRef = tools::make_ref<SbUnoMethod> | ||||
2832 | ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false ); | ||||
2833 | QuickInsert( xMethRef.get() ); | ||||
2834 | } | ||||
2835 | } | ||||
2836 | |||||
2837 | |||||
2838 | // output the value | ||||
2839 | Any SbUnoObject::getUnoAny() | ||||
2840 | { | ||||
2841 | Any aRetAny; | ||||
2842 | if( bNeedIntrospection ) doIntrospection(); | ||||
2843 | if ( maStructInfo ) | ||||
2844 | aRetAny = maTmpUnoObj; | ||||
2845 | else if( mxMaterialHolder.is() ) | ||||
2846 | aRetAny = mxMaterialHolder->getMaterial(); | ||||
2847 | else if( mxInvocation.is() ) | ||||
2848 | aRetAny <<= mxInvocation; | ||||
2849 | return aRetAny; | ||||
2850 | } | ||||
2851 | |||||
2852 | // help method to create a Uno-Struct per CoreReflection | ||||
2853 | static SbUnoObject* Impl_CreateUnoStruct( const OUString& aClassName ) | ||||
2854 | { | ||||
2855 | // get CoreReflection | ||||
2856 | Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); | ||||
2857 | if( !xCoreReflection.is() ) | ||||
2858 | return nullptr; | ||||
2859 | |||||
2860 | // search for the class | ||||
2861 | Reference< XIdlClass > xClass; | ||||
2862 | const Reference< XHierarchicalNameAccess >& xHarryName = | ||||
2863 | getCoreReflection_HierarchicalNameAccess_Impl(); | ||||
2864 | if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) ) | ||||
2865 | xClass = xCoreReflection->forName( aClassName ); | ||||
2866 | if( !xClass.is() ) | ||||
2867 | return nullptr; | ||||
2868 | |||||
2869 | // Is it really a struct? | ||||
2870 | TypeClass eType = xClass->getTypeClass(); | ||||
2871 | if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) ) | ||||
2872 | return nullptr; | ||||
2873 | |||||
2874 | // create an instance | ||||
2875 | Any aNewAny; | ||||
2876 | xClass->createObject( aNewAny ); | ||||
2877 | // make a SbUnoObject out of it | ||||
2878 | SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny ); | ||||
2879 | return pUnoObj; | ||||
2880 | } | ||||
2881 | |||||
2882 | |||||
2883 | // Factory-Class to create Uno-Structs per DIM AS NEW | ||||
2884 | SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 ) | ||||
2885 | { | ||||
2886 | // Via SbxId nothing works in Uno | ||||
2887 | return nullptr; | ||||
2888 | } | ||||
2889 | |||||
2890 | SbxObject* SbUnoFactory::CreateObject( const OUString& rClassName ) | ||||
2891 | { | ||||
2892 | return Impl_CreateUnoStruct( rClassName ); | ||||
2893 | } | ||||
2894 | |||||
2895 | |||||
2896 | // Provisional interface for the UNO-Connection | ||||
2897 | // Deliver a SbxObject, that wrap a Uno-Interface | ||||
2898 | SbxObjectRef GetSbUnoObject( const OUString& aName, const Any& aUnoObj_ ) | ||||
2899 | { | ||||
2900 | return new SbUnoObject( aName, aUnoObj_ ); | ||||
2901 | } | ||||
2902 | |||||
2903 | // Force creation of all properties for debugging | ||||
2904 | void createAllObjectProperties( SbxObject* pObj ) | ||||
2905 | { | ||||
2906 | if( !pObj ) | ||||
2907 | return; | ||||
2908 | |||||
2909 | SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj ); | ||||
2910 | SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>( pObj ); | ||||
2911 | if( pUnoObj ) | ||||
2912 | { | ||||
2913 | pUnoObj->createAllProperties(); | ||||
2914 | } | ||||
2915 | else if ( pUnoStructObj ) | ||||
2916 | { | ||||
2917 | pUnoStructObj->createAllProperties(); | ||||
2918 | } | ||||
2919 | } | ||||
2920 | |||||
2921 | |||||
2922 | void RTL_Impl_CreateUnoStruct( SbxArray& rPar ) | ||||
2923 | { | ||||
2924 | // We need 1 parameter minimum | ||||
2925 | if ( rPar.Count32() < 2 ) | ||||
2926 | { | ||||
2927 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
2928 | return; | ||||
2929 | } | ||||
2930 | |||||
2931 | // get the name of the class of the struct | ||||
2932 | OUString aClassName = rPar.Get32(1)->GetOUString(); | ||||
2933 | |||||
2934 | // try to create Struct with the same name | ||||
2935 | SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName ); | ||||
2936 | if( !xUnoObj.is() ) | ||||
2937 | { | ||||
2938 | return; | ||||
2939 | } | ||||
2940 | // return the object | ||||
2941 | SbxVariableRef refVar = rPar.Get32(0); | ||||
2942 | refVar->PutObject( xUnoObj.get() ); | ||||
2943 | } | ||||
2944 | |||||
2945 | void RTL_Impl_CreateUnoService( SbxArray& rPar ) | ||||
2946 | { | ||||
2947 | // We need 1 Parameter minimum | ||||
2948 | if ( rPar.Count32() < 2 ) | ||||
2949 | { | ||||
2950 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
2951 | return; | ||||
2952 | } | ||||
2953 | |||||
2954 | // get the name of the class of the struct | ||||
2955 | OUString aServiceName = rPar.Get32(1)->GetOUString(); | ||||
2956 | |||||
2957 | // search for the service and instantiate it | ||||
2958 | Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); | ||||
2959 | Reference< XInterface > xInterface; | ||||
2960 | try | ||||
2961 | { | ||||
2962 | xInterface = xFactory->createInstance( aServiceName ); | ||||
2963 | } | ||||
2964 | catch( const Exception& ) | ||||
2965 | { | ||||
2966 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
2967 | } | ||||
2968 | |||||
2969 | SbxVariableRef refVar = rPar.Get32(0); | ||||
2970 | if( xInterface.is() ) | ||||
2971 | { | ||||
2972 | // Create a SbUnoObject out of it and return it | ||||
2973 | SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); | ||||
2974 | if( xUnoObj->getUnoAny().hasValue() ) | ||||
2975 | { | ||||
2976 | // return the object | ||||
2977 | refVar->PutObject( xUnoObj.get() ); | ||||
2978 | } | ||||
2979 | else | ||||
2980 | { | ||||
2981 | refVar->PutObject( nullptr ); | ||||
2982 | } | ||||
2983 | } | ||||
2984 | else | ||||
2985 | { | ||||
2986 | refVar->PutObject( nullptr ); | ||||
2987 | } | ||||
2988 | } | ||||
2989 | |||||
2990 | void RTL_Impl_CreateUnoServiceWithArguments( SbxArray& rPar ) | ||||
2991 | { | ||||
2992 | // We need 2 parameter minimum | ||||
2993 | if ( rPar.Count32() < 3 ) | ||||
2994 | { | ||||
2995 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
2996 | return; | ||||
2997 | } | ||||
2998 | |||||
2999 | // get the name of the class of the struct | ||||
3000 | OUString aServiceName = rPar.Get32(1)->GetOUString(); | ||||
3001 | Any aArgAsAny = sbxToUnoValue( rPar.Get32(2), | ||||
3002 | cppu::UnoType<Sequence<Any>>::get() ); | ||||
3003 | Sequence< Any > aArgs; | ||||
3004 | aArgAsAny >>= aArgs; | ||||
3005 | |||||
3006 | // search for the service and instantiate it | ||||
3007 | Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); | ||||
3008 | Reference< XInterface > xInterface; | ||||
3009 | try | ||||
3010 | { | ||||
3011 | xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs ); | ||||
3012 | } | ||||
3013 | catch( const Exception& ) | ||||
3014 | { | ||||
3015 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
3016 | } | ||||
3017 | |||||
3018 | SbxVariableRef refVar = rPar.Get32(0); | ||||
3019 | if( xInterface.is() ) | ||||
3020 | { | ||||
3021 | // Create a SbUnoObject out of it and return it | ||||
3022 | SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, Any(xInterface) ); | ||||
3023 | if( xUnoObj->getUnoAny().hasValue() ) | ||||
3024 | { | ||||
3025 | // return the object | ||||
3026 | refVar->PutObject( xUnoObj.get() ); | ||||
3027 | } | ||||
3028 | else | ||||
3029 | { | ||||
3030 | refVar->PutObject( nullptr ); | ||||
3031 | } | ||||
3032 | } | ||||
3033 | else | ||||
3034 | { | ||||
3035 | refVar->PutObject( nullptr ); | ||||
3036 | } | ||||
3037 | } | ||||
3038 | |||||
3039 | void RTL_Impl_GetProcessServiceManager( SbxArray& rPar ) | ||||
3040 | { | ||||
3041 | SbxVariableRef refVar = rPar.Get32(0); | ||||
3042 | |||||
3043 | // get the global service manager | ||||
3044 | Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() ); | ||||
3045 | |||||
3046 | // Create a SbUnoObject out of it and return it | ||||
3047 | SbUnoObjectRef xUnoObj = new SbUnoObject( "ProcessServiceManager", Any(xFactory) ); | ||||
3048 | refVar->PutObject( xUnoObj.get() ); | ||||
3049 | } | ||||
3050 | |||||
3051 | void RTL_Impl_HasInterfaces( SbxArray& rPar ) | ||||
3052 | { | ||||
3053 | // We need 2 parameter minimum | ||||
3054 | sal_uInt32 nParCount = rPar.Count32(); | ||||
3055 | if( nParCount < 3 ) | ||||
3056 | { | ||||
3057 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
3058 | return; | ||||
3059 | } | ||||
3060 | |||||
3061 | // variable for the return value | ||||
3062 | SbxVariableRef refVar = rPar.Get32(0); | ||||
3063 | refVar->PutBool( false ); | ||||
3064 | |||||
3065 | // get the Uno-Object | ||||
3066 | SbxBaseRef pObj = rPar.Get32( 1 )->GetObject(); | ||||
3067 | auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ); | ||||
3068 | if( obj == nullptr ) | ||||
3069 | { | ||||
3070 | return; | ||||
3071 | } | ||||
3072 | Any aAny = obj->getUnoAny(); | ||||
3073 | auto x = o3tl::tryAccess<Reference<XInterface>>(aAny); | ||||
3074 | if( !x ) | ||||
3075 | { | ||||
3076 | return; | ||||
3077 | } | ||||
3078 | |||||
3079 | // get CoreReflection | ||||
3080 | Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); | ||||
3081 | if( !xCoreReflection.is() ) | ||||
3082 | { | ||||
3083 | return; | ||||
3084 | } | ||||
3085 | for( sal_uInt32 i = 2 ; i < nParCount ; i++ ) | ||||
3086 | { | ||||
3087 | // get the name of the interface of the struct | ||||
3088 | OUString aIfaceName = rPar.Get32( i )->GetOUString(); | ||||
3089 | |||||
3090 | // search for the class | ||||
3091 | Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName ); | ||||
3092 | if( !xClass.is() ) | ||||
3093 | { | ||||
3094 | return; | ||||
3095 | } | ||||
3096 | // check if the interface will be supported | ||||
3097 | OUString aClassName = xClass->getName(); | ||||
3098 | Type aClassType( xClass->getTypeClass(), aClassName ); | ||||
3099 | if( !(*x)->queryInterface( aClassType ).hasValue() ) | ||||
3100 | { | ||||
3101 | return; | ||||
3102 | } | ||||
3103 | } | ||||
3104 | |||||
3105 | // Everything works; then return TRUE | ||||
3106 | refVar->PutBool( true ); | ||||
3107 | } | ||||
3108 | |||||
3109 | void RTL_Impl_IsUnoStruct( SbxArray& rPar ) | ||||
3110 | { | ||||
3111 | // We need 1 parameter minimum | ||||
3112 | if ( rPar.Count32() < 2 ) | ||||
3113 | { | ||||
3114 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
3115 | return; | ||||
3116 | } | ||||
3117 | |||||
3118 | // variable for the return value | ||||
3119 | SbxVariableRef refVar = rPar.Get32(0); | ||||
3120 | refVar->PutBool( false ); | ||||
3121 | |||||
3122 | // get the Uno-Object | ||||
3123 | SbxVariableRef xParam = rPar.Get32( 1 ); | ||||
3124 | if( !xParam->IsObject() ) | ||||
3125 | { | ||||
3126 | return; | ||||
3127 | } | ||||
3128 | SbxBaseRef pObj = xParam->GetObject(); | ||||
3129 | auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ); | ||||
3130 | if( obj == nullptr ) | ||||
3131 | { | ||||
3132 | return; | ||||
3133 | } | ||||
3134 | Any aAny = obj->getUnoAny(); | ||||
3135 | TypeClass eType = aAny.getValueType().getTypeClass(); | ||||
3136 | if( eType == TypeClass_STRUCT ) | ||||
3137 | { | ||||
3138 | refVar->PutBool( true ); | ||||
3139 | } | ||||
3140 | } | ||||
3141 | |||||
3142 | |||||
3143 | void RTL_Impl_EqualUnoObjects( SbxArray& rPar ) | ||||
3144 | { | ||||
3145 | if ( rPar.Count32() < 3 ) | ||||
3146 | { | ||||
3147 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
3148 | return; | ||||
3149 | } | ||||
3150 | |||||
3151 | // variable for the return value | ||||
3152 | SbxVariableRef refVar = rPar.Get32(0); | ||||
3153 | refVar->PutBool( false ); | ||||
3154 | |||||
3155 | // get the Uno-Objects | ||||
3156 | SbxVariableRef xParam1 = rPar.Get32( 1 ); | ||||
3157 | if( !xParam1->IsObject() ) | ||||
3158 | { | ||||
3159 | return; | ||||
3160 | } | ||||
3161 | SbxBaseRef pObj1 = xParam1->GetObject(); | ||||
3162 | auto obj1 = dynamic_cast<SbUnoObject*>( pObj1.get() ); | ||||
3163 | if( obj1 == nullptr ) | ||||
3164 | { | ||||
3165 | return; | ||||
3166 | } | ||||
3167 | Any aAny1 = obj1->getUnoAny(); | ||||
3168 | TypeClass eType1 = aAny1.getValueType().getTypeClass(); | ||||
3169 | if( eType1 != TypeClass_INTERFACE ) | ||||
3170 | { | ||||
3171 | return; | ||||
3172 | } | ||||
3173 | Reference< XInterface > x1; | ||||
3174 | aAny1 >>= x1; | ||||
3175 | |||||
3176 | SbxVariableRef xParam2 = rPar.Get32( 2 ); | ||||
3177 | if( !xParam2->IsObject() ) | ||||
3178 | { | ||||
3179 | return; | ||||
3180 | } | ||||
3181 | SbxBaseRef pObj2 = xParam2->GetObject(); | ||||
3182 | auto obj2 = dynamic_cast<SbUnoObject*>( pObj2.get() ); | ||||
3183 | if( obj2 == nullptr ) | ||||
3184 | { | ||||
3185 | return; | ||||
3186 | } | ||||
3187 | Any aAny2 = obj2->getUnoAny(); | ||||
3188 | TypeClass eType2 = aAny2.getValueType().getTypeClass(); | ||||
3189 | if( eType2 != TypeClass_INTERFACE ) | ||||
3190 | { | ||||
3191 | return; | ||||
3192 | } | ||||
3193 | Reference< XInterface > x2; | ||||
3194 | aAny2 >>= x2; | ||||
3195 | |||||
3196 | if( x1 == x2 ) | ||||
3197 | { | ||||
3198 | refVar->PutBool( true ); | ||||
3199 | } | ||||
3200 | } | ||||
3201 | |||||
3202 | |||||
3203 | // helper wrapper function to interact with TypeProvider and | ||||
3204 | // XTypeDescriptionEnumerationAccess. | ||||
3205 | // if it fails for whatever reason | ||||
3206 | // returned Reference<> be null e.g. .is() will be false | ||||
3207 | |||||
3208 | static Reference< XTypeDescriptionEnumeration > getTypeDescriptorEnumeration( const OUString& sSearchRoot, | ||||
3209 | const Sequence< TypeClass >& types, | ||||
3210 | TypeDescriptionSearchDepth depth ) | ||||
3211 | { | ||||
3212 | Reference< XTypeDescriptionEnumeration > xEnum; | ||||
3213 | Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY ); | ||||
3214 | if ( xTypeEnumAccess.is() ) | ||||
3215 | { | ||||
3216 | try | ||||
3217 | { | ||||
3218 | xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration( | ||||
3219 | sSearchRoot, types, depth ); | ||||
3220 | } | ||||
3221 | catch(const NoSuchTypeNameException& /*nstne*/ ) {} | ||||
3222 | catch(const InvalidTypeNameException& /*nstne*/ ) {} | ||||
3223 | } | ||||
3224 | return xEnum; | ||||
3225 | } | ||||
3226 | |||||
3227 | VBAConstantHelper& | ||||
3228 | VBAConstantHelper::instance() | ||||
3229 | { | ||||
3230 | static VBAConstantHelper aHelper; | ||||
3231 | return aHelper; | ||||
3232 | } | ||||
3233 | |||||
3234 | void VBAConstantHelper::init() | ||||
3235 | { | ||||
3236 | if ( isInited ) | ||||
3237 | return; | ||||
3238 | |||||
3239 | Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( "ooo.vba", {TypeClass_CONSTANTS}, TypeDescriptionSearchDepth_INFINITE ); | ||||
3240 | |||||
3241 | if ( !xEnum.is()) | ||||
3242 | { | ||||
3243 | return; //NULL; | ||||
3244 | } | ||||
3245 | while ( xEnum->hasMoreElements() ) | ||||
3246 | { | ||||
3247 | Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY ); | ||||
3248 | if ( xConstants.is() ) | ||||
3249 | { | ||||
3250 | // store constant group name | ||||
3251 | OUString sFullName = xConstants->getName(); | ||||
3252 | sal_Int32 indexLastDot = sFullName.lastIndexOf('.'); | ||||
3253 | OUString sLeafName( sFullName ); | ||||
3254 | if ( indexLastDot > -1 ) | ||||
3255 | { | ||||
3256 | sLeafName = sFullName.copy( indexLastDot + 1); | ||||
3257 | } | ||||
3258 | aConstCache.push_back( sLeafName ); // assume constant group names are unique | ||||
3259 | const Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants(); | ||||
3260 | for (const auto& ctd : aConsts) | ||||
3261 | { | ||||
3262 | // store constant member name | ||||
3263 | sFullName = ctd->getName(); | ||||
3264 | indexLastDot = sFullName.lastIndexOf('.'); | ||||
3265 | sLeafName = sFullName; | ||||
3266 | if ( indexLastDot > -1 ) | ||||
3267 | { | ||||
3268 | sLeafName = sFullName.copy( indexLastDot + 1); | ||||
3269 | } | ||||
3270 | aConstHash[ sLeafName.toAsciiLowerCase() ] = ctd->getConstantValue(); | ||||
3271 | } | ||||
3272 | } | ||||
3273 | } | ||||
3274 | isInited = true; | ||||
3275 | } | ||||
3276 | |||||
3277 | bool | ||||
3278 | VBAConstantHelper::isVBAConstantType( const OUString& rName ) | ||||
3279 | { | ||||
3280 | init(); | ||||
3281 | bool bConstant = false; | ||||
3282 | |||||
3283 | for (auto const& elem : aConstCache) | ||||
3284 | { | ||||
3285 | if( rName.equalsIgnoreAsciiCase(elem) ) | ||||
3286 | { | ||||
3287 | bConstant = true; | ||||
3288 | break; | ||||
3289 | } | ||||
3290 | } | ||||
3291 | return bConstant; | ||||
3292 | } | ||||
3293 | |||||
3294 | SbxVariable* | ||||
3295 | VBAConstantHelper::getVBAConstant( const OUString& rName ) | ||||
3296 | { | ||||
3297 | SbxVariable* pConst = nullptr; | ||||
3298 | init(); | ||||
3299 | |||||
3300 | auto it = aConstHash.find( rName.toAsciiLowerCase() ); | ||||
3301 | |||||
3302 | if ( it != aConstHash.end() ) | ||||
3303 | { | ||||
3304 | pConst = new SbxVariable( SbxVARIANT ); | ||||
3305 | pConst->SetName( rName ); | ||||
3306 | unoToSbxValue( pConst, it->second ); | ||||
3307 | } | ||||
3308 | |||||
3309 | return pConst; | ||||
3310 | } | ||||
3311 | |||||
3312 | // Function to search for a global identifier in the | ||||
3313 | // UnoScope and to wrap it for Sbx | ||||
3314 | SbUnoClass* findUnoClass( const OUString& rName ) | ||||
3315 | { | ||||
3316 | // #105550 Check if module exists | ||||
3317 | SbUnoClass* pUnoClass = nullptr; | ||||
3318 | |||||
3319 | const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); | ||||
3320 | if( xTypeAccess->hasByHierarchicalName( rName ) ) | ||||
3321 | { | ||||
3322 | Any aRet = xTypeAccess->getByHierarchicalName( rName ); | ||||
3323 | Reference< XTypeDescription > xTypeDesc; | ||||
3324 | aRet >>= xTypeDesc; | ||||
3325 | |||||
3326 | if( xTypeDesc.is() ) | ||||
3327 | { | ||||
3328 | TypeClass eTypeClass = xTypeDesc->getTypeClass(); | ||||
3329 | if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS ) | ||||
3330 | { | ||||
3331 | pUnoClass = new SbUnoClass( rName ); | ||||
3332 | } | ||||
3333 | } | ||||
3334 | } | ||||
3335 | return pUnoClass; | ||||
3336 | } | ||||
3337 | |||||
3338 | SbxVariable* SbUnoClass::Find( const OUString& rName, SbxClassType ) | ||||
3339 | { | ||||
3340 | SbxVariable* pRes = SbxObject::Find( rName, SbxClassType::Variable ); | ||||
3341 | |||||
3342 | // If nothing were located the submodule isn't known yet | ||||
3343 | if( !pRes ) | ||||
3344 | { | ||||
3345 | // If it is already a class, ask for the field | ||||
3346 | if( m_xClass.is() ) | ||||
3347 | { | ||||
3348 | // Is it a field(?) | ||||
3349 | Reference< XIdlField > xField = m_xClass->getField( rName ); | ||||
3350 | if( xField.is() ) | ||||
3351 | { | ||||
3352 | try | ||||
3353 | { | ||||
3354 | Any aAny = xField->get( {} ); //TODO: does this make sense? | ||||
3355 | |||||
3356 | // Convert to Sbx | ||||
3357 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3358 | pRes->SetName( rName ); | ||||
3359 | unoToSbxValue( pRes, aAny ); | ||||
3360 | } | ||||
3361 | catch( const Exception& ) | ||||
3362 | { | ||||
3363 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
3364 | } | ||||
3365 | } | ||||
3366 | } | ||||
3367 | else | ||||
3368 | { | ||||
3369 | // expand fully qualified name | ||||
3370 | OUString aNewName = GetName() | ||||
3371 | + "." | ||||
3372 | + rName; | ||||
3373 | |||||
3374 | // get CoreReflection | ||||
3375 | Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); | ||||
3376 | if( xCoreReflection.is() ) | ||||
3377 | { | ||||
3378 | // Is it a constant? | ||||
3379 | Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY ); | ||||
3380 | if( xHarryName.is() ) | ||||
3381 | { | ||||
3382 | try | ||||
3383 | { | ||||
3384 | Any aValue = xHarryName->getByHierarchicalName( aNewName ); | ||||
3385 | TypeClass eType = aValue.getValueType().getTypeClass(); | ||||
3386 | |||||
3387 | // Interface located? Then it is a class | ||||
3388 | if( eType == TypeClass_INTERFACE ) | ||||
3389 | { | ||||
3390 | Reference< XIdlClass > xClass( aValue, UNO_QUERY ); | ||||
3391 | if( xClass.is() ) | ||||
3392 | { | ||||
3393 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3394 | SbxObjectRef xWrapper = static_cast<SbxObject*>(new SbUnoClass( aNewName, xClass )); | ||||
3395 | pRes->PutObject( xWrapper.get() ); | ||||
3396 | } | ||||
3397 | } | ||||
3398 | else | ||||
3399 | { | ||||
3400 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3401 | unoToSbxValue( pRes, aValue ); | ||||
3402 | } | ||||
3403 | } | ||||
3404 | catch( const NoSuchElementException& ) | ||||
3405 | { | ||||
3406 | } | ||||
3407 | } | ||||
3408 | |||||
3409 | // Otherwise take it again as class | ||||
3410 | if( !pRes ) | ||||
3411 | { | ||||
3412 | SbUnoClass* pNewClass = findUnoClass( aNewName ); | ||||
3413 | if( pNewClass ) | ||||
3414 | { | ||||
3415 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3416 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pNewClass); | ||||
3417 | pRes->PutObject( xWrapper.get() ); | ||||
3418 | } | ||||
3419 | } | ||||
3420 | |||||
3421 | // A UNO service? | ||||
3422 | if( !pRes ) | ||||
3423 | { | ||||
3424 | SbUnoService* pUnoService = findUnoService( aNewName ); | ||||
3425 | if( pUnoService ) | ||||
3426 | { | ||||
3427 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3428 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pUnoService); | ||||
3429 | pRes->PutObject( xWrapper.get() ); | ||||
3430 | } | ||||
3431 | } | ||||
3432 | |||||
3433 | // A UNO singleton? | ||||
3434 | if( !pRes ) | ||||
3435 | { | ||||
3436 | SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName ); | ||||
3437 | if( pUnoSingleton ) | ||||
3438 | { | ||||
3439 | pRes = new SbxVariable( SbxVARIANT ); | ||||
3440 | SbxObjectRef xWrapper = static_cast<SbxObject*>(pUnoSingleton); | ||||
3441 | pRes->PutObject( xWrapper.get() ); | ||||
3442 | } | ||||
3443 | } | ||||
3444 | } | ||||
3445 | } | ||||
3446 | |||||
3447 | if( pRes ) | ||||
3448 | { | ||||
3449 | pRes->SetName( rName ); | ||||
3450 | |||||
3451 | // Insert variable, so that it could be found later | ||||
3452 | QuickInsert( pRes ); | ||||
3453 | |||||
3454 | // Take us out as listener at once, | ||||
3455 | // the values are all constant | ||||
3456 | if( pRes->IsBroadcaster() ) | ||||
3457 | EndListening( pRes->GetBroadcaster(), true ); | ||||
3458 | } | ||||
3459 | } | ||||
3460 | return pRes; | ||||
3461 | } | ||||
3462 | |||||
3463 | |||||
3464 | SbUnoService* findUnoService( const OUString& rName ) | ||||
3465 | { | ||||
3466 | SbUnoService* pSbUnoService = nullptr; | ||||
3467 | |||||
3468 | const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); | ||||
3469 | if( xTypeAccess->hasByHierarchicalName( rName ) ) | ||||
3470 | { | ||||
3471 | Any aRet = xTypeAccess->getByHierarchicalName( rName ); | ||||
3472 | Reference< XTypeDescription > xTypeDesc; | ||||
3473 | aRet >>= xTypeDesc; | ||||
3474 | |||||
3475 | if( xTypeDesc.is() ) | ||||
3476 | { | ||||
3477 | TypeClass eTypeClass = xTypeDesc->getTypeClass(); | ||||
3478 | if( eTypeClass == TypeClass_SERVICE ) | ||||
3479 | { | ||||
3480 | Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY ); | ||||
3481 | if( xServiceTypeDesc.is() ) | ||||
3482 | pSbUnoService = new SbUnoService( rName, xServiceTypeDesc ); | ||||
3483 | } | ||||
3484 | } | ||||
3485 | } | ||||
3486 | return pSbUnoService; | ||||
3487 | } | ||||
3488 | |||||
3489 | SbxVariable* SbUnoService::Find( const OUString& rName, SbxClassType ) | ||||
3490 | { | ||||
3491 | SbxVariable* pRes = SbxObject::Find( rName, SbxClassType::Method ); | ||||
3492 | |||||
3493 | if( !pRes ) | ||||
3494 | { | ||||
3495 | // If it is already a class ask for a field | ||||
3496 | if( m_bNeedsInit && m_xServiceTypeDesc.is() ) | ||||
3497 | { | ||||
3498 | m_bNeedsInit = false; | ||||
3499 | |||||
3500 | Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors(); | ||||
3501 | const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray(); | ||||
3502 | int nCtorCount = aSCDSeq.getLength(); | ||||
3503 | for( int i = 0 ; i < nCtorCount ; ++i ) | ||||
3504 | { | ||||
3505 | Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i]; | ||||
3506 | |||||
3507 | OUString aName( xCtor->getName() ); | ||||
3508 | if( aName.isEmpty() ) | ||||
3509 | { | ||||
3510 | if( xCtor->isDefaultConstructor() ) | ||||
3511 | { | ||||
3512 | aName = "create"; | ||||
3513 | } | ||||
3514 | } | ||||
3515 | |||||
3516 | if( !aName.isEmpty() ) | ||||
3517 | { | ||||
3518 | // Create and insert SbUnoServiceCtor | ||||
3519 | SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor ); | ||||
3520 | QuickInsert( xSbCtorRef.get() ); | ||||
3521 | } | ||||
3522 | } | ||||
3523 | pRes = SbxObject::Find( rName, SbxClassType::Method ); | ||||
3524 | } | ||||
3525 | } | ||||
3526 | |||||
3527 | return pRes; | ||||
3528 | } | ||||
3529 | |||||
3530 | void SbUnoService::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | ||||
3531 | { | ||||
3532 | const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); | ||||
3533 | if( !pHint ) | ||||
3534 | return; | ||||
3535 | |||||
3536 | SbxVariable* pVar = pHint->GetVar(); | ||||
3537 | SbxArray* pParams = pVar->GetParameters(); | ||||
3538 | SbUnoServiceCtor* pUnoCtor = dynamic_cast<SbUnoServiceCtor*>( pVar ); | ||||
3539 | if( pUnoCtor && pHint->GetId() == SfxHintId::BasicDataWanted ) | ||||
3540 | { | ||||
3541 | // Parameter count -1 because of Param0 == this | ||||
3542 | sal_uInt32 nParamCount = pParams ? (pParams->Count32() - 1) : 0; | ||||
3543 | Sequence<Any> args; | ||||
3544 | |||||
3545 | Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc(); | ||||
3546 | Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters(); | ||||
3547 | const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray(); | ||||
3548 | sal_uInt32 nUnoParamCount = aParameterSeq.getLength(); | ||||
3549 | |||||
3550 | // Default: Ignore not needed parameters | ||||
3551 | bool bParameterError = false; | ||||
3552 | |||||
3553 | // Is the last parameter a rest parameter? | ||||
3554 | bool bRestParameterMode = false; | ||||
3555 | if( nUnoParamCount > 0 ) | ||||
3556 | { | ||||
3557 | Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ]; | ||||
3558 | if( xLastParam.is() ) | ||||
3559 | { | ||||
3560 | if( xLastParam->isRestParameter() ) | ||||
3561 | bRestParameterMode = true; | ||||
3562 | } | ||||
3563 | } | ||||
3564 | |||||
3565 | // Too many parameters with context as first parameter? | ||||
3566 | sal_uInt32 nSbxParameterOffset = 1; | ||||
3567 | sal_uInt32 nParameterOffsetByContext = 0; | ||||
3568 | Reference < XComponentContext > xFirstParamContext; | ||||
3569 | if( nParamCount > nUnoParamCount ) | ||||
3570 | { | ||||
3571 | // Check if first parameter is a context and use it | ||||
3572 | // then in createInstanceWithArgumentsAndContext | ||||
3573 | Any aArg0 = sbxToUnoValue( pParams->Get32( nSbxParameterOffset ) ); | ||||
3574 | if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() ) | ||||
3575 | nParameterOffsetByContext = 1; | ||||
3576 | } | ||||
3577 | |||||
3578 | sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext; | ||||
3579 | sal_uInt32 nAllocParamCount = nEffectiveParamCount; | ||||
3580 | if( nEffectiveParamCount > nUnoParamCount ) | ||||
3581 | { | ||||
3582 | if( !bRestParameterMode ) | ||||
3583 | { | ||||
3584 | nEffectiveParamCount = nUnoParamCount; | ||||
3585 | nAllocParamCount = nUnoParamCount; | ||||
3586 | } | ||||
3587 | } | ||||
3588 | // Not enough parameters? | ||||
3589 | else if( nUnoParamCount > nEffectiveParamCount ) | ||||
3590 | { | ||||
3591 | // RestParameterMode only helps if one (the last) parameter is missing | ||||
3592 | int nDiff = nUnoParamCount - nEffectiveParamCount; | ||||
3593 | if( !bRestParameterMode || nDiff > 1 ) | ||||
3594 | { | ||||
3595 | bParameterError = true; | ||||
3596 | StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONALErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 27) ); | ||||
3597 | } | ||||
3598 | } | ||||
3599 | |||||
3600 | if( !bParameterError ) | ||||
3601 | { | ||||
3602 | bool bOutParams = false; | ||||
3603 | if( nAllocParamCount > 0 ) | ||||
3604 | { | ||||
3605 | args.realloc( nAllocParamCount ); | ||||
3606 | Any* pAnyArgs = args.getArray(); | ||||
3607 | for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ ) | ||||
3608 | { | ||||
3609 | sal_uInt32 iSbx = i + nSbxParameterOffset + nParameterOffsetByContext; | ||||
3610 | |||||
3611 | // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount | ||||
3612 | Reference< XParameter > xParam; | ||||
3613 | if( i < nUnoParamCount ) | ||||
3614 | { | ||||
3615 | xParam = pParameterSeq[i]; | ||||
3616 | if( !xParam.is() ) | ||||
3617 | continue; | ||||
3618 | |||||
3619 | Reference< XTypeDescription > xParamTypeDesc = xParam->getType(); | ||||
3620 | if( !xParamTypeDesc.is() ) | ||||
3621 | continue; | ||||
3622 | css::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() ); | ||||
3623 | |||||
3624 | // sbx parameter needs offset 1 | ||||
3625 | pAnyArgs[i] = sbxToUnoValue( pParams->Get32( iSbx ), aType ); | ||||
3626 | |||||
3627 | // Check for out parameter if not already done | ||||
3628 | if( !bOutParams && xParam->isOut() ) | ||||
3629 | bOutParams = true; | ||||
3630 | } | ||||
3631 | else | ||||
3632 | { | ||||
3633 | pAnyArgs[i] = sbxToUnoValue( pParams->Get32( iSbx ) ); | ||||
3634 | } | ||||
3635 | } | ||||
3636 | } | ||||
3637 | |||||
3638 | // "Call" ctor using createInstanceWithArgumentsAndContext | ||||
3639 | Reference < XComponentContext > xContext( | ||||
3640 | xFirstParamContext.is() | ||||
3641 | ? xFirstParamContext | ||||
3642 | : comphelper::getProcessComponentContext() ); | ||||
3643 | Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); | ||||
3644 | |||||
3645 | Any aRetAny; | ||||
3646 | OUString aServiceName = GetName(); | ||||
3647 | Reference < XInterface > xRet; | ||||
3648 | try | ||||
3649 | { | ||||
3650 | xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext ); | ||||
3651 | } | ||||
3652 | catch( const Exception& ) | ||||
3653 | { | ||||
3654 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
3655 | } | ||||
3656 | aRetAny <<= xRet; | ||||
3657 | unoToSbxValue( pVar, aRetAny ); | ||||
3658 | |||||
3659 | // Copy back out parameters? | ||||
3660 | if( bOutParams ) | ||||
3661 | { | ||||
3662 | const Any* pAnyArgs = args.getConstArray(); | ||||
3663 | |||||
3664 | for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ ) | ||||
3665 | { | ||||
3666 | Reference< XParameter > xParam = pParameterSeq[j]; | ||||
3667 | if( !xParam.is() ) | ||||
3668 | continue; | ||||
3669 | |||||
3670 | if( xParam->isOut() ) | ||||
3671 | unoToSbxValue( pParams->Get32(j + 1), pAnyArgs[ j ] ); | ||||
3672 | } | ||||
3673 | } | ||||
3674 | } | ||||
3675 | } | ||||
3676 | else | ||||
3677 | SbxObject::Notify( rBC, rHint ); | ||||
3678 | } | ||||
3679 | |||||
3680 | |||||
3681 | SbUnoServiceCtor::SbUnoServiceCtor( const OUString& aName_, Reference< XServiceConstructorDescription > const & xServiceCtorDesc ) | ||||
3682 | : SbxMethod( aName_, SbxOBJECT ) | ||||
3683 | , m_xServiceCtorDesc( xServiceCtorDesc ) | ||||
3684 | { | ||||
3685 | } | ||||
3686 | |||||
3687 | SbUnoServiceCtor::~SbUnoServiceCtor() | ||||
3688 | { | ||||
3689 | } | ||||
3690 | |||||
3691 | SbxInfo* SbUnoServiceCtor::GetInfo() | ||||
3692 | { | ||||
3693 | return nullptr; | ||||
3694 | } | ||||
3695 | |||||
3696 | |||||
3697 | SbUnoSingleton* findUnoSingleton( const OUString& rName ) | ||||
3698 | { | ||||
3699 | SbUnoSingleton* pSbUnoSingleton = nullptr; | ||||
3700 | |||||
3701 | const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); | ||||
3702 | if( xTypeAccess->hasByHierarchicalName( rName ) ) | ||||
3703 | { | ||||
3704 | Any aRet = xTypeAccess->getByHierarchicalName( rName ); | ||||
3705 | Reference< XTypeDescription > xTypeDesc; | ||||
3706 | aRet >>= xTypeDesc; | ||||
3707 | |||||
3708 | if( xTypeDesc.is() ) | ||||
3709 | { | ||||
3710 | TypeClass eTypeClass = xTypeDesc->getTypeClass(); | ||||
3711 | if( eTypeClass == TypeClass_SINGLETON ) | ||||
3712 | { | ||||
3713 | Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY ); | ||||
3714 | if( xSingletonTypeDesc.is() ) | ||||
3715 | pSbUnoSingleton = new SbUnoSingleton( rName ); | ||||
3716 | } | ||||
3717 | } | ||||
3718 | } | ||||
3719 | return pSbUnoSingleton; | ||||
3720 | } | ||||
3721 | |||||
3722 | SbUnoSingleton::SbUnoSingleton( const OUString& aName_ ) | ||||
3723 | : SbxObject( aName_ ) | ||||
3724 | { | ||||
3725 | SbxVariableRef xGetMethodRef = new SbxMethod( "get", SbxOBJECT ); | ||||
3726 | QuickInsert( xGetMethodRef.get() ); | ||||
3727 | } | ||||
3728 | |||||
3729 | void SbUnoSingleton::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | ||||
3730 | { | ||||
3731 | const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); | ||||
3732 | if( pHint ) | ||||
3733 | { | ||||
3734 | SbxVariable* pVar = pHint->GetVar(); | ||||
3735 | SbxArray* pParams = pVar->GetParameters(); | ||||
3736 | sal_uInt32 nParamCount = pParams ? (pParams->Count32() - 1) : 0; | ||||
3737 | sal_uInt32 nAllowedParamCount = 1; | ||||
3738 | |||||
3739 | Reference < XComponentContext > xContextToUse; | ||||
3740 | if( nParamCount > 0 ) | ||||
3741 | { | ||||
3742 | // Check if first parameter is a context and use it then | ||||
3743 | Reference < XComponentContext > xFirstParamContext; | ||||
3744 | Any aArg1 = sbxToUnoValue( pParams->Get32( 1 ) ); | ||||
3745 | if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() ) | ||||
3746 | xContextToUse = xFirstParamContext; | ||||
3747 | } | ||||
3748 | |||||
3749 | if( !xContextToUse.is() ) | ||||
3750 | { | ||||
3751 | xContextToUse = comphelper::getProcessComponentContext(); | ||||
3752 | --nAllowedParamCount; | ||||
3753 | } | ||||
3754 | |||||
3755 | if( nParamCount > nAllowedParamCount ) | ||||
3756 | { | ||||
3757 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
3758 | return; | ||||
3759 | } | ||||
3760 | |||||
3761 | Any aRetAny; | ||||
3762 | if( xContextToUse.is() ) | ||||
3763 | { | ||||
3764 | OUString aSingletonName = "/singletons/" | ||||
3765 | + GetName(); | ||||
3766 | Reference < XInterface > xRet; | ||||
3767 | xContextToUse->getValueByName( aSingletonName ) >>= xRet; | ||||
3768 | aRetAny <<= xRet; | ||||
3769 | } | ||||
3770 | unoToSbxValue( pVar, aRetAny ); | ||||
3771 | } | ||||
3772 | else | ||||
3773 | { | ||||
3774 | SbxObject::Notify( rBC, rHint ); | ||||
3775 | } | ||||
3776 | } | ||||
3777 | |||||
3778 | namespace { | ||||
3779 | |||||
3780 | // Implementation of an EventAttacher-drawn AllListener, which | ||||
3781 | // solely transmits several events to a general AllListener | ||||
3782 | class BasicAllListener_Impl : public WeakImplHelper< XAllListener > | ||||
3783 | { | ||||
3784 | void firing_impl(const AllEventObject& Event, Any* pRet); | ||||
3785 | |||||
3786 | public: | ||||
3787 | SbxObjectRef xSbxObj; | ||||
3788 | OUString aPrefixName; | ||||
3789 | |||||
3790 | explicit BasicAllListener_Impl( const OUString& aPrefixName ); | ||||
3791 | |||||
3792 | // Methods of XAllListener | ||||
3793 | virtual void SAL_CALL firing(const AllEventObject& Event) override; | ||||
3794 | virtual Any SAL_CALL approveFiring(const AllEventObject& Event) override; | ||||
3795 | |||||
3796 | // Methods of XEventListener | ||||
3797 | virtual void SAL_CALL disposing(const EventObject& Source) override; | ||||
3798 | }; | ||||
3799 | |||||
3800 | } | ||||
3801 | |||||
3802 | BasicAllListener_Impl::BasicAllListener_Impl(const OUString& aPrefixName_) | ||||
3803 | : aPrefixName( aPrefixName_ ) | ||||
3804 | { | ||||
3805 | } | ||||
3806 | |||||
3807 | void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet ) | ||||
3808 | { | ||||
3809 | SolarMutexGuard guard; | ||||
3810 | |||||
3811 | if( !xSbxObj.is() ) | ||||
3812 | return; | ||||
3813 | |||||
3814 | OUString aMethodName = aPrefixName + Event.MethodName; | ||||
3815 | |||||
3816 | SbxVariable * pP = xSbxObj.get(); | ||||
3817 | while( pP->GetParent() ) | ||||
3818 | { | ||||
3819 | pP = pP->GetParent(); | ||||
3820 | StarBASIC * pLib = dynamic_cast<StarBASIC*>( pP ); | ||||
3821 | if( pLib ) | ||||
3822 | { | ||||
3823 | // Create in a Basic Array | ||||
3824 | SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT ); | ||||
3825 | const Any * pArgs = Event.Arguments.getConstArray(); | ||||
3826 | sal_Int32 nCount = Event.Arguments.getLength(); | ||||
3827 | for( sal_Int32 i = 0; i < nCount; i++ ) | ||||
3828 | { | ||||
3829 | // Convert elements | ||||
3830 | SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); | ||||
3831 | unoToSbxValue( xVar.get(), pArgs[i] ); | ||||
3832 | xSbxArray->Put32( xVar.get(), i + 1 ); | ||||
3833 | } | ||||
3834 | |||||
3835 | pLib->Call( aMethodName, xSbxArray.get() ); | ||||
3836 | |||||
3837 | // get the return value from the Param-Array, if requested | ||||
3838 | if( pRet ) | ||||
3839 | { | ||||
3840 | SbxVariable* pVar = xSbxArray->Get32( 0 ); | ||||
3841 | if( pVar ) | ||||
3842 | { | ||||
3843 | // #95792 Avoid a second call | ||||
3844 | SbxFlagBits nFlags = pVar->GetFlags(); | ||||
3845 | pVar->SetFlag( SbxFlagBits::NoBroadcast ); | ||||
3846 | *pRet = sbxToUnoValueImpl( pVar ); | ||||
3847 | pVar->SetFlags( nFlags ); | ||||
3848 | } | ||||
3849 | } | ||||
3850 | break; | ||||
3851 | } | ||||
3852 | } | ||||
3853 | } | ||||
3854 | |||||
3855 | |||||
3856 | // Methods of Listener | ||||
3857 | void BasicAllListener_Impl::firing( const AllEventObject& Event ) | ||||
3858 | { | ||||
3859 | firing_impl( Event, nullptr ); | ||||
3860 | } | ||||
3861 | |||||
3862 | Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) | ||||
3863 | { | ||||
3864 | Any aRetAny; | ||||
3865 | firing_impl( Event, &aRetAny ); | ||||
3866 | return aRetAny; | ||||
3867 | } | ||||
3868 | |||||
3869 | |||||
3870 | // Methods of XEventListener | ||||
3871 | void BasicAllListener_Impl ::disposing(const EventObject& ) | ||||
3872 | { | ||||
3873 | SolarMutexGuard guard; | ||||
3874 | |||||
3875 | xSbxObj.clear(); | ||||
3876 | } | ||||
3877 | |||||
3878 | |||||
3879 | // class InvocationToAllListenerMapper | ||||
3880 | // helper class to map XInvocation to XAllListener (also in project eventattacher!) | ||||
3881 | |||||
3882 | namespace { | ||||
3883 | |||||
3884 | class InvocationToAllListenerMapper : public WeakImplHelper< XInvocation > | ||||
3885 | { | ||||
3886 | public: | ||||
3887 | InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType, | ||||
3888 | const Reference< XAllListener >& AllListener, const Any& Helper ); | ||||
3889 | |||||
3890 | // XInvocation | ||||
3891 | virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override; | ||||
3892 | virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) override; | ||||
3893 | virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) override; | ||||
3894 | virtual Any SAL_CALL getValue(const OUString& PropertyName) override; | ||||
3895 | virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) override; | ||||
3896 | virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) override; | ||||
3897 | |||||
3898 | private: | ||||
3899 | Reference< XAllListener > m_xAllListener; | ||||
3900 | Reference< XIdlClass > m_xListenerType; | ||||
3901 | Any m_Helper; | ||||
3902 | }; | ||||
3903 | |||||
3904 | } | ||||
3905 | |||||
3906 | // Function to replace AllListenerAdapterService::createAllListerAdapter | ||||
3907 | static Reference< XInterface > createAllListenerAdapter | ||||
3908 | ( | ||||
3909 | const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory, | ||||
3910 | const Reference< XIdlClass >& xListenerType, | ||||
3911 | const Reference< XAllListener >& xListener, | ||||
3912 | const Any& Helper | ||||
3913 | ) | ||||
3914 | { | ||||
3915 | Reference< XInterface > xAdapter; | ||||
3916 | if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() ) | ||||
3917 | { | ||||
3918 | Reference< XInvocation > xInvocationToAllListenerMapper = | ||||
3919 | new InvocationToAllListenerMapper(xListenerType, xListener, Helper); | ||||
3920 | Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() ); | ||||
3921 | xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, {aListenerType} ); | ||||
3922 | } | ||||
3923 | return xAdapter; | ||||
3924 | } | ||||
3925 | |||||
3926 | |||||
3927 | // InvocationToAllListenerMapper | ||||
3928 | InvocationToAllListenerMapper::InvocationToAllListenerMapper | ||||
3929 | ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper ) | ||||
3930 | : m_xAllListener( AllListener ) | ||||
3931 | , m_xListenerType( ListenerType ) | ||||
3932 | , m_Helper( Helper ) | ||||
3933 | { | ||||
3934 | } | ||||
3935 | |||||
3936 | |||||
3937 | Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection() | ||||
3938 | { | ||||
3939 | return Reference< XIntrospectionAccess >(); | ||||
3940 | } | ||||
3941 | |||||
3942 | |||||
3943 | Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params, | ||||
3944 | Sequence< sal_Int16 >&, Sequence< Any >&) | ||||
3945 | { | ||||
3946 | Any aRet; | ||||
3947 | |||||
3948 | // Check if to firing or approveFiring has to be called | ||||
3949 | Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName ); | ||||
3950 | bool bApproveFiring = false; | ||||
3951 | if( !xMethod.is() ) | ||||
3952 | return aRet; | ||||
3953 | Reference< XIdlClass > xReturnType = xMethod->getReturnType(); | ||||
3954 | Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes(); | ||||
3955 | if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) || | ||||
3956 | aExceptionSeq.hasElements() ) | ||||
3957 | { | ||||
3958 | bApproveFiring = true; | ||||
3959 | } | ||||
3960 | else | ||||
3961 | { | ||||
3962 | Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos(); | ||||
3963 | sal_uInt32 nParamCount = aParamSeq.getLength(); | ||||
3964 | if( nParamCount > 1 ) | ||||
3965 | { | ||||
3966 | const ParamInfo* pInfo = aParamSeq.getConstArray(); | ||||
3967 | for( sal_uInt32 i = 0 ; i < nParamCount ; i++ ) | ||||
3968 | { | ||||
3969 | if( pInfo[ i ].aMode != ParamMode_IN ) | ||||
3970 | { | ||||
3971 | bApproveFiring = true; | ||||
3972 | break; | ||||
3973 | } | ||||
3974 | } | ||||
3975 | } | ||||
3976 | } | ||||
3977 | |||||
3978 | AllEventObject aAllEvent; | ||||
3979 | aAllEvent.Source = static_cast<OWeakObject*>(this); | ||||
3980 | aAllEvent.Helper = m_Helper; | ||||
3981 | aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() ); | ||||
3982 | aAllEvent.MethodName = FunctionName; | ||||
3983 | aAllEvent.Arguments = Params; | ||||
3984 | if( bApproveFiring ) | ||||
3985 | aRet = m_xAllListener->approveFiring( aAllEvent ); | ||||
3986 | else | ||||
3987 | m_xAllListener->firing( aAllEvent ); | ||||
3988 | return aRet; | ||||
3989 | } | ||||
3990 | |||||
3991 | |||||
3992 | void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString&, const Any&) | ||||
3993 | {} | ||||
3994 | |||||
3995 | |||||
3996 | Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString&) | ||||
3997 | { | ||||
3998 | return Any(); | ||||
3999 | } | ||||
4000 | |||||
4001 | |||||
4002 | sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name) | ||||
4003 | { | ||||
4004 | Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name ); | ||||
4005 | return xMethod.is(); | ||||
4006 | } | ||||
4007 | |||||
4008 | |||||
4009 | sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name) | ||||
4010 | { | ||||
4011 | Reference< XIdlField > xField = m_xListenerType->getField( Name ); | ||||
4012 | return xField.is(); | ||||
4013 | } | ||||
4014 | |||||
4015 | |||||
4016 | // create Uno-Service | ||||
4017 | // 1. Parameter == Prefix-Name of the macro | ||||
4018 | // 2. Parameter == fully qualified name of the listener | ||||
4019 | void SbRtl_CreateUnoListener(StarBASIC * pBasic, SbxArray & rPar, bool) | ||||
4020 | { | ||||
4021 | // We need 2 parameters | ||||
4022 | if ( rPar.Count32() != 3 ) | ||||
4023 | { | ||||
4024 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
4025 | return; | ||||
4026 | } | ||||
4027 | |||||
4028 | // get the name of the class of the struct | ||||
4029 | OUString aPrefixName = rPar.Get32(1)->GetOUString(); | ||||
4030 | OUString aListenerClassName = rPar.Get32(2)->GetOUString(); | ||||
4031 | |||||
4032 | // get the CoreReflection | ||||
4033 | Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl(); | ||||
4034 | if( !xCoreReflection.is() ) | ||||
4035 | return; | ||||
4036 | |||||
4037 | // get the AllListenerAdapterService | ||||
4038 | Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); | ||||
4039 | |||||
4040 | // search the class | ||||
4041 | Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName ); | ||||
4042 | if( !xClass.is() ) | ||||
4043 | return; | ||||
4044 | |||||
4045 | // From 1999-11-30: get the InvocationAdapterFactory | ||||
4046 | Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory = | ||||
4047 | InvocationAdapterFactory::create( xContext ); | ||||
4048 | |||||
4049 | BasicAllListener_Impl * p; | ||||
4050 | Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName ); | ||||
4051 | Any aTmp; | ||||
4052 | Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp ); | ||||
4053 | if( !xLst.is() ) | ||||
4054 | return; | ||||
4055 | |||||
4056 | OUString aClassName = xClass->getName(); | ||||
4057 | Type aClassType( xClass->getTypeClass(), aClassName ); | ||||
4058 | aTmp = xLst->queryInterface( aClassType ); | ||||
4059 | if( !aTmp.hasValue() ) | ||||
4060 | return; | ||||
4061 | |||||
4062 | SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp ); | ||||
4063 | p->xSbxObj = pUnoObj; | ||||
4064 | p->xSbxObj->SetParent( pBasic ); | ||||
4065 | |||||
4066 | // #100326 Register listener object to set Parent NULL in Dtor | ||||
4067 | SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners(); | ||||
4068 | xBasicUnoListeners->Insert32( pUnoObj, xBasicUnoListeners->Count32() ); | ||||
4069 | |||||
4070 | // return the object | ||||
4071 | SbxVariableRef refVar = rPar.Get32(0); | ||||
4072 | refVar->PutObject( p->xSbxObj.get() ); | ||||
4073 | } | ||||
4074 | |||||
4075 | |||||
4076 | // Represents the DefaultContext property of the ProcessServiceManager | ||||
4077 | // in the Basic runtime system. | ||||
4078 | void RTL_Impl_GetDefaultContext( SbxArray& rPar ) | ||||
4079 | { | ||||
4080 | SbxVariableRef refVar = rPar.Get32(0); | ||||
4081 | |||||
4082 | Any aContextAny( comphelper::getProcessComponentContext() ); | ||||
4083 | |||||
4084 | SbUnoObjectRef xUnoObj = new SbUnoObject( "DefaultContext", aContextAny ); | ||||
4085 | refVar->PutObject( xUnoObj.get() ); | ||||
4086 | } | ||||
4087 | |||||
4088 | |||||
4089 | // Creates a Basic wrapper object for a strongly typed Uno value | ||||
4090 | // 1. parameter: Uno type as full qualified type name, e.g. "byte[]" | ||||
4091 | void RTL_Impl_CreateUnoValue( SbxArray& rPar ) | ||||
4092 | { | ||||
4093 | // 2 parameters needed | ||||
4094 | if ( rPar.Count32() != 3 ) | ||||
4095 | { | ||||
4096 | StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENTErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 2) ); | ||||
4097 | return; | ||||
4098 | } | ||||
4099 | |||||
4100 | // get the name of the class of the struct | ||||
4101 | OUString aTypeName = rPar.Get32(1)->GetOUString(); | ||||
4102 | SbxVariable* pVal = rPar.Get32(2); | ||||
4103 | |||||
4104 | if( aTypeName == "type" ) | ||||
4105 | { | ||||
4106 | SbxDataType eBaseType = pVal->SbxValue::GetType(); | ||||
4107 | OUString aValTypeName; | ||||
4108 | if( eBaseType == SbxSTRING ) | ||||
4109 | { | ||||
4110 | aValTypeName = pVal->GetOUString(); | ||||
4111 | } | ||||
4112 | else if( eBaseType == SbxOBJECT ) | ||||
4113 | { | ||||
4114 | // XIdlClass? | ||||
4115 | Reference< XIdlClass > xIdlClass; | ||||
4116 | |||||
4117 | SbxBaseRef pObj = pVal->GetObject(); | ||||
4118 | if( auto obj = dynamic_cast<SbUnoObject*>( pObj.get() ) ) | ||||
4119 | { | ||||
4120 | Any aUnoAny = obj->getUnoAny(); | ||||
4121 | aUnoAny >>= xIdlClass; | ||||
4122 | } | ||||
4123 | |||||
4124 | if( xIdlClass.is() ) | ||||
4125 | { | ||||
4126 | aValTypeName = xIdlClass->getName(); | ||||
4127 | } | ||||
4128 | } | ||||
4129 | Type aType; | ||||
4130 | bool bSuccess = implGetTypeByName( aValTypeName, aType ); | ||||
4131 | if( bSuccess ) | ||||
4132 | { | ||||
4133 | Any aTypeAny( aType ); | ||||
4134 | SbxVariableRef refVar = rPar.Get32(0); | ||||
4135 | SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny ); | ||||
4136 | refVar->PutObject( xUnoAnyObject.get() ); | ||||
4137 | } | ||||
4138 | return; | ||||
4139 | } | ||||
4140 | |||||
4141 | // Check the type | ||||
4142 | const Reference< XHierarchicalNameAccess >& xTypeAccess = getTypeProvider_Impl(); | ||||
4143 | Any aRet; | ||||
4144 | try | ||||
4145 | { | ||||
4146 | aRet = xTypeAccess->getByHierarchicalName( aTypeName ); | ||||
4147 | } | ||||
4148 | catch( const NoSuchElementException& e1 ) | ||||
4149 | { | ||||
4150 | StarBASIC::Error( ERRCODE_BASIC_EXCEPTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 121 ), | ||||
4151 | implGetExceptionMsg( e1, "com.sun.star.container.NoSuchElementException" ) ); | ||||
4152 | return; | ||||
4153 | } | ||||
4154 | Reference< XTypeDescription > xTypeDesc; | ||||
4155 | aRet >>= xTypeDesc; | ||||
4156 | TypeClass eTypeClass = xTypeDesc->getTypeClass(); | ||||
4157 | Type aDestType( eTypeClass, aTypeName ); | ||||
4158 | |||||
4159 | |||||
4160 | // Preconvert value | ||||
4161 | Any aVal = sbxToUnoValueImpl( pVal ); | ||||
4162 | Any aConvertedVal = convertAny( aVal, aDestType ); | ||||
4163 | |||||
4164 | SbxVariableRef refVar = rPar.Get32(0); | ||||
4165 | SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal ); | ||||
4166 | refVar->PutObject( xUnoAnyObject.get() ); | ||||
4167 | } | ||||
4168 | |||||
4169 | namespace { | ||||
4170 | |||||
4171 | class ModuleInvocationProxy : public WeakImplHelper< XInvocation, XComponent > | ||||
4172 | { | ||||
4173 | ::osl::Mutex m_aMutex; | ||||
4174 | OUString m_aPrefix; | ||||
4175 | SbxObjectRef m_xScopeObj; | ||||
4176 | bool m_bProxyIsClassModuleObject; | ||||
4177 | |||||
4178 | ::comphelper::OInterfaceContainerHelper2 m_aListeners; | ||||
4179 | |||||
4180 | public: | ||||
4181 | ModuleInvocationProxy( OUString const & aPrefix, SbxObjectRef const & xScopeObj ); | ||||
4182 | |||||
4183 | // XInvocation | ||||
4184 | virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() override; | ||||
4185 | virtual void SAL_CALL setValue( const OUString& rProperty, const Any& rValue ) override; | ||||
4186 | virtual Any SAL_CALL getValue( const OUString& rProperty ) override; | ||||
4187 | virtual sal_Bool SAL_CALL hasMethod( const OUString& rName ) override; | ||||
4188 | virtual sal_Bool SAL_CALL hasProperty( const OUString& rProp ) override; | ||||
4189 | |||||
4190 | virtual Any SAL_CALL invoke( const OUString& rFunction, | ||||
4191 | const Sequence< Any >& rParams, | ||||
4192 | Sequence< sal_Int16 >& rOutParamIndex, | ||||
4193 | Sequence< Any >& rOutParam ) override; | ||||
4194 | |||||
4195 | // XComponent | ||||
4196 | virtual void SAL_CALL dispose() override; | ||||
4197 | virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) override; | ||||
4198 | virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) override; | ||||
4199 | }; | ||||
4200 | |||||
4201 | } | ||||
4202 | |||||
4203 | ModuleInvocationProxy::ModuleInvocationProxy( OUString const & aPrefix, SbxObjectRef const & xScopeObj ) | ||||
4204 | : m_aMutex() | ||||
4205 | , m_aPrefix( aPrefix + "_" ) | ||||
4206 | , m_xScopeObj( xScopeObj ) | ||||
4207 | , m_aListeners( m_aMutex ) | ||||
4208 | { | ||||
4209 | m_bProxyIsClassModuleObject = xScopeObj.is() && dynamic_cast<const SbClassModuleObject*>( xScopeObj.get() ) != nullptr; | ||||
4210 | } | ||||
4211 | |||||
4212 | Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() | ||||
4213 | { | ||||
4214 | return Reference< XIntrospectionAccess >(); | ||||
4215 | } | ||||
4216 | |||||
4217 | void SAL_CALL ModuleInvocationProxy::setValue(const OUString& rProperty, const Any& rValue) | ||||
4218 | { | ||||
4219 | if( !m_bProxyIsClassModuleObject ) | ||||
4220 | throw UnknownPropertyException(); | ||||
4221 | |||||
4222 | SolarMutexGuard guard; | ||||
4223 | |||||
4224 | OUString aPropertyFunctionName = "Property Set " | ||||
4225 | + m_aPrefix | ||||
4226 | + rProperty; | ||||
4227 | |||||
4228 | SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxClassType::Method ); | ||||
4229 | SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); | ||||
4230 | if( pMeth == nullptr ) | ||||
4231 | { | ||||
4232 | // TODO: Check vba behavior concerning missing function | ||||
4233 | //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); | ||||
4234 | throw UnknownPropertyException(aPropertyFunctionName); | ||||
4235 | } | ||||
4236 | |||||
4237 | // Setup parameter | ||||
4238 | SbxArrayRef xArray = new SbxArray; | ||||
4239 | SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); | ||||
4240 | unoToSbxValue( xVar.get(), rValue ); | ||||
4241 | xArray->Put32( xVar.get(), 1 ); | ||||
4242 | |||||
4243 | // Call property method | ||||
4244 | SbxVariableRef xValue = new SbxVariable; | ||||
4245 | pMeth->SetParameters( xArray.get() ); | ||||
4246 | pMeth->Call( xValue.get() ); | ||||
4247 | pMeth->SetParameters( nullptr ); | ||||
4248 | |||||
4249 | // TODO: OutParameter? | ||||
4250 | |||||
4251 | |||||
4252 | } | ||||
4253 | |||||
4254 | Any SAL_CALL ModuleInvocationProxy::getValue(const OUString& rProperty) | ||||
4255 | { | ||||
4256 | if( !m_bProxyIsClassModuleObject ) | ||||
4257 | { | ||||
4258 | throw UnknownPropertyException(); | ||||
4259 | } | ||||
4260 | SolarMutexGuard guard; | ||||
4261 | |||||
4262 | OUString aPropertyFunctionName = "Property Get " | ||||
4263 | + m_aPrefix | ||||
4264 | + rProperty; | ||||
4265 | |||||
4266 | SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxClassType::Method ); | ||||
4267 | SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); | ||||
4268 | if( pMeth == nullptr ) | ||||
4269 | { | ||||
4270 | // TODO: Check vba behavior concerning missing function | ||||
4271 | //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); | ||||
4272 | throw UnknownPropertyException(aPropertyFunctionName); | ||||
4273 | } | ||||
4274 | |||||
4275 | // Call method | ||||
4276 | SbxVariableRef xValue = new SbxVariable; | ||||
4277 | pMeth->Call( xValue.get() ); | ||||
4278 | Any aRet = sbxToUnoValue( xValue.get() ); | ||||
4279 | return aRet; | ||||
4280 | } | ||||
4281 | |||||
4282 | sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const OUString& ) | ||||
4283 | { | ||||
4284 | return false; | ||||
4285 | } | ||||
4286 | |||||
4287 | sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const OUString& ) | ||||
4288 | { | ||||
4289 | return false; | ||||
4290 | } | ||||
4291 | |||||
4292 | Any SAL_CALL ModuleInvocationProxy::invoke( const OUString& rFunction, | ||||
4293 | const Sequence< Any >& rParams, | ||||
4294 | Sequence< sal_Int16 >&, | ||||
4295 | Sequence< Any >& ) | ||||
4296 | { | ||||
4297 | SolarMutexGuard guard; | ||||
4298 | |||||
4299 | Any aRet; | ||||
4300 | SbxObjectRef xScopeObj = m_xScopeObj; | ||||
4301 | if( !xScopeObj.is() ) | ||||
4302 | { | ||||
4303 | return aRet; | ||||
4304 | } | ||||
4305 | OUString aFunctionName = m_aPrefix | ||||
4306 | + rFunction; | ||||
4307 | |||||
4308 | bool bSetRescheduleBack = false; | ||||
4309 | bool bOldReschedule = true; | ||||
4310 | SbiInstance* pInst = GetSbData()->pInst; | ||||
4311 | if( pInst && pInst->IsCompatibility() ) | ||||
4312 | { | ||||
4313 | bOldReschedule = pInst->IsReschedule(); | ||||
4314 | if ( bOldReschedule ) | ||||
4315 | { | ||||
4316 | pInst->EnableReschedule( false ); | ||||
4317 | bSetRescheduleBack = true; | ||||
4318 | } | ||||
4319 | } | ||||
4320 | |||||
4321 | SbxVariable* p = xScopeObj->Find( aFunctionName, SbxClassType::Method ); | ||||
4322 | SbMethod* pMeth = dynamic_cast<SbMethod*>( p ); | ||||
4323 | if( pMeth == nullptr ) | ||||
4324 | { | ||||
4325 | // TODO: Check vba behavior concerning missing function | ||||
4326 | //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName ); | ||||
4327 | return aRet; | ||||
4328 | } | ||||
4329 | |||||
4330 | // Setup parameters | ||||
4331 | SbxArrayRef xArray; | ||||
4332 | sal_Int32 nParamCount = rParams.getLength(); | ||||
4333 | if( nParamCount ) | ||||
4334 | { | ||||
4335 | xArray = new SbxArray; | ||||
4336 | const Any *pArgs = rParams.getConstArray(); | ||||
4337 | for( sal_Int32 i = 0 ; i < nParamCount ; i++ ) | ||||
4338 | { | ||||
4339 | SbxVariableRef xVar = new SbxVariable( SbxVARIANT ); | ||||
4340 | unoToSbxValue( xVar.get(), pArgs[i] ); | ||||
4341 | xArray->Put32( xVar.get(), sal::static_int_cast< sal_uInt16 >(i+1) ); | ||||
4342 | } | ||||
4343 | } | ||||
4344 | |||||
4345 | // Call method | ||||
4346 | SbxVariableRef xValue = new SbxVariable; | ||||
4347 | if( xArray.is() ) | ||||
4348 | pMeth->SetParameters( xArray.get() ); | ||||
4349 | pMeth->Call( xValue.get() ); | ||||
4350 | aRet = sbxToUnoValue( xValue.get() ); | ||||
4351 | pMeth->SetParameters( nullptr ); | ||||
4352 | |||||
4353 | if( bSetRescheduleBack ) | ||||
4354 | pInst->EnableReschedule( bOldReschedule ); | ||||
4355 | |||||
4356 | // TODO: OutParameter? | ||||
4357 | |||||
4358 | return aRet; | ||||
4359 | } | ||||
4360 | |||||
4361 | void SAL_CALL ModuleInvocationProxy::dispose() | ||||
4362 | { | ||||
4363 | ::osl::MutexGuard aGuard( m_aMutex ); | ||||
4364 | |||||
4365 | EventObject aEvent( static_cast<XComponent*>(this) ); | ||||
4366 | m_aListeners.disposeAndClear( aEvent ); | ||||
4367 | |||||
4368 | m_xScopeObj = nullptr; | ||||
4369 | } | ||||
4370 | |||||
4371 | void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener ) | ||||
4372 | { | ||||
4373 | m_aListeners.addInterface( xListener ); | ||||
4374 | } | ||||
4375 | |||||
4376 | void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener ) | ||||
4377 | { | ||||
4378 | m_aListeners.removeInterface( xListener ); | ||||
4379 | } | ||||
4380 | |||||
4381 | |||||
4382 | Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType, | ||||
4383 | const OUString& aPrefix, const SbxObjectRef& xScopeObj ) | ||||
4384 | { | ||||
4385 | Reference< XInterface > xRet; | ||||
4386 | |||||
4387 | Reference< XComponentContext > xContext( | ||||
4388 | comphelper::getProcessComponentContext() ); | ||||
4389 | Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); | ||||
4390 | |||||
4391 | Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj ); | ||||
4392 | |||||
4393 | Sequence<Any> args( 3 ); | ||||
4394 | args[0] = aControlAny; | ||||
4395 | args[1] <<= aVBAType; | ||||
4396 | args[2] <<= xProxy; | ||||
4397 | |||||
4398 | try | ||||
4399 | { | ||||
4400 | xRet = xServiceMgr->createInstanceWithArgumentsAndContext( | ||||
4401 | "com.sun.star.custom.UnoComListener", | ||||
4402 | args, xContext ); | ||||
4403 | } | ||||
4404 | catch( const Exception& ) | ||||
4405 | { | ||||
4406 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
4407 | } | ||||
4408 | |||||
4409 | return xRet; | ||||
4410 | } | ||||
4411 | |||||
4412 | typedef std::vector< WeakReference< XComponent > > ComponentRefVector; | ||||
4413 | |||||
4414 | namespace { | ||||
4415 | |||||
4416 | struct StarBasicDisposeItem | ||||
4417 | { | ||||
4418 | StarBASIC* m_pBasic; | ||||
4419 | SbxArrayRef m_pRegisteredVariables; | ||||
4420 | ComponentRefVector m_vComImplementsObjects; | ||||
4421 | |||||
4422 | explicit StarBasicDisposeItem( StarBASIC* pBasic ) | ||||
4423 | : m_pBasic( pBasic ) | ||||
4424 | , m_pRegisteredVariables(new SbxArray()) | ||||
4425 | { | ||||
4426 | } | ||||
4427 | }; | ||||
4428 | |||||
4429 | } | ||||
4430 | |||||
4431 | typedef std::vector< StarBasicDisposeItem* > DisposeItemVector; | ||||
4432 | |||||
4433 | static DisposeItemVector GaDisposeItemVector; | ||||
4434 | |||||
4435 | static DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC const * pBasic ) | ||||
4436 | { | ||||
4437 | return std::find_if(GaDisposeItemVector.begin(), GaDisposeItemVector.end(), | ||||
4438 | [&pBasic](StarBasicDisposeItem* pItem) { return pItem->m_pBasic == pBasic; }); | ||||
4439 | } | ||||
4440 | |||||
4441 | static StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic ) | ||||
4442 | { | ||||
4443 | DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); | ||||
4444 | StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : nullptr; | ||||
4445 | if( pItem == nullptr ) | ||||
4446 | { | ||||
4447 | pItem = new StarBasicDisposeItem( pBasic ); | ||||
4448 | GaDisposeItemVector.push_back( pItem ); | ||||
4449 | } | ||||
4450 | return pItem; | ||||
4451 | } | ||||
4452 | |||||
4453 | void registerComponentToBeDisposedForBasic | ||||
4454 | ( const Reference< XComponent >& xComponent, StarBASIC* pBasic ) | ||||
4455 | { | ||||
4456 | StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); | ||||
4457 | pItem->m_vComImplementsObjects.emplace_back(xComponent ); | ||||
4458 | } | ||||
4459 | |||||
4460 | void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic ) | ||||
4461 | { | ||||
4462 | StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic ); | ||||
4463 | SbxArray* pArray = pItem->m_pRegisteredVariables.get(); | ||||
4464 | pArray->Put32( pVar, pArray->Count32() ); | ||||
4465 | } | ||||
4466 | |||||
4467 | void disposeComVariablesForBasic( StarBASIC const * pBasic ) | ||||
4468 | { | ||||
4469 | DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic ); | ||||
4470 | if( it == GaDisposeItemVector.end() ) | ||||
4471 | return; | ||||
4472 | |||||
4473 | StarBasicDisposeItem* pItem = *it; | ||||
4474 | |||||
4475 | SbxArray* pArray = pItem->m_pRegisteredVariables.get(); | ||||
4476 | sal_uInt32 nCount = pArray->Count32(); | ||||
4477 | for( sal_uInt32 i = 0 ; i < nCount ; ++i ) | ||||
4478 | { | ||||
4479 | SbxVariable* pVar = pArray->Get32( i ); | ||||
4480 | pVar->ClearComListener(); | ||||
4481 | } | ||||
4482 | |||||
4483 | ComponentRefVector& rv = pItem->m_vComImplementsObjects; | ||||
4484 | for (auto const& elem : rv) | ||||
4485 | { | ||||
4486 | Reference< XComponent > xComponent( elem.get(), UNO_QUERY ); | ||||
4487 | if (xComponent.is()) | ||||
4488 | xComponent->dispose(); | ||||
4489 | } | ||||
4490 | |||||
4491 | delete pItem; | ||||
4492 | GaDisposeItemVector.erase( it ); | ||||
4493 | } | ||||
4494 | |||||
4495 | |||||
4496 | // Handle module implements mechanism for OLE types | ||||
4497 | bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject ) | ||||
4498 | { | ||||
4499 | // For now: Take first interface that allows to instantiate COM wrapper | ||||
4500 | // TODO: Check if support for multiple interfaces is needed | ||||
4501 | |||||
4502 | Reference< XComponentContext > xContext( | ||||
4503 | comphelper::getProcessComponentContext() ); | ||||
4504 | Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() ); | ||||
4505 | Reference< XSingleServiceFactory > xComImplementsFactory | ||||
4506 | ( | ||||
4507 | xServiceMgr->createInstanceWithContext( "com.sun.star.custom.ComImplementsFactory", xContext ), | ||||
4508 | UNO_QUERY | ||||
4509 | ); | ||||
4510 | if( !xComImplementsFactory.is() ) | ||||
4511 | return false; | ||||
4512 | |||||
4513 | bool bSuccess = false; | ||||
4514 | |||||
4515 | SbxArray* pModIfaces = pClassData->mxIfaces.get(); | ||||
4516 | sal_uInt32 nCount = pModIfaces->Count32(); | ||||
4517 | for( sal_uInt32 i = 0 ; i < nCount ; ++i ) | ||||
4518 | { | ||||
4519 | SbxVariable* pVar = pModIfaces->Get32( i ); | ||||
4520 | const OUString& aIfaceName = pVar->GetName(); | ||||
4521 | |||||
4522 | if( !aIfaceName.isEmpty() ) | ||||
4523 | { | ||||
4524 | OUString aPureIfaceName = aIfaceName; | ||||
4525 | sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.'); | ||||
4526 | if ( indexLastDot > -1 ) | ||||
4527 | { | ||||
4528 | aPureIfaceName = aIfaceName.copy( indexLastDot + 1 ); | ||||
4529 | } | ||||
4530 | Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject ); | ||||
4531 | |||||
4532 | Sequence<Any> args( 2 ); | ||||
4533 | args[0] <<= aIfaceName; | ||||
4534 | args[1] <<= xProxy; | ||||
4535 | |||||
4536 | Reference< XInterface > xRet; | ||||
4537 | try | ||||
4538 | { | ||||
4539 | xRet = xComImplementsFactory->createInstanceWithArguments( args ); | ||||
4540 | bSuccess = true; | ||||
4541 | } | ||||
4542 | catch( const Exception& ) | ||||
4543 | { | ||||
4544 | implHandleAnyException( ::cppu::getCaughtException() ); | ||||
4545 | } | ||||
4546 | |||||
4547 | if( bSuccess ) | ||||
4548 | { | ||||
4549 | Reference< XComponent > xComponent( xProxy, UNO_QUERY ); | ||||
4550 | if( xComponent.is() ) | ||||
4551 | { | ||||
4552 | StarBASIC* pParentBasic = nullptr; | ||||
4553 | SbxObject* pCurObject = this; | ||||
4554 | do | ||||
4555 | { | ||||
4556 | SbxObject* pObjParent = pCurObject->GetParent(); | ||||
4557 | pParentBasic = dynamic_cast<StarBASIC*>( pObjParent ); | ||||
4558 | pCurObject = pObjParent; | ||||
4559 | } | ||||
4560 | while( pParentBasic == nullptr && pCurObject != nullptr ); | ||||
4561 | |||||
4562 | assert( pParentBasic != nullptr )(static_cast <bool> (pParentBasic != nullptr) ? void (0 ) : __assert_fail ("pParentBasic != nullptr", "/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" , 4562, __extension__ __PRETTY_FUNCTION__)); | ||||
4563 | registerComponentToBeDisposedForBasic( xComponent, pParentBasic ); | ||||
4564 | } | ||||
4565 | |||||
4566 | o_rRetAny <<= xRet; | ||||
4567 | break; | ||||
4568 | } | ||||
4569 | } | ||||
4570 | } | ||||
4571 | |||||
4572 | return bSuccess; | ||||
4573 | } | ||||
4574 | |||||
4575 | |||||
4576 | // Due to an incorrect behavior IE returns an object instead of a string | ||||
4577 | // in some scenarios. Calling toString at the object may correct this. | ||||
4578 | // Helper function used in sbxvalue.cxx | ||||
4579 | bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ) | ||||
4580 | { | ||||
4581 | bool bSuccess = false; | ||||
4582 | |||||
4583 | if( auto pUnoObj = dynamic_cast<SbUnoObject*>( pObj) ) | ||||
4584 | { | ||||
4585 | // Only for native COM objects | ||||
4586 | if( pUnoObj->isNativeCOMObject() ) | ||||
4587 | { | ||||
4588 | SbxVariableRef pMeth = pObj->Find( "toString", SbxClassType::Method ); | ||||
4589 | if ( pMeth.is() ) | ||||
4590 | { | ||||
4591 | SbxValues aRes; | ||||
4592 | pMeth->Get( aRes ); | ||||
4593 | pVal->Put( aRes ); | ||||
4594 | bSuccess = true; | ||||
4595 | } | ||||
4596 | } | ||||
4597 | } | ||||
4598 | return bSuccess; | ||||
4599 | } | ||||
4600 | |||||
4601 | Any StructRefInfo::getValue() | ||||
4602 | { | ||||
4603 | Any aRet; | ||||
4604 | uno_any_destruct( | ||||
4605 | &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); | ||||
4606 | typelib_TypeDescription * pTD = nullptr; | ||||
4607 | maType.getDescription(&pTD); | ||||
4608 | uno_any_construct( | ||||
4609 | &aRet, getInst(), pTD, | ||||
4610 | reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); | ||||
4611 | typelib_typedescription_release(pTD); | ||||
4612 | return aRet; | ||||
4613 | } | ||||
4614 | |||||
4615 | void StructRefInfo::setValue( const Any& rValue ) | ||||
4616 | { | ||||
4617 | bool bSuccess = uno_type_assignData( getInst(), | ||||
4618 | maType.getTypeLibType(), | ||||
4619 | const_cast<void*>(rValue.getValue()), | ||||
4620 | rValue.getValueTypeRef(), | ||||
4621 | reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), | ||||
4622 | reinterpret_cast< uno_AcquireFunc >(cpp_acquire), | ||||
4623 | reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); | ||||
4624 | OSL_ENSURE(bSuccess,do { if (true && (!(bSuccess))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" ":" "4625" ": "), "%s", "StructRefInfo::setValue: ooops... the value could not be assigned!" ); } } while (false) | ||||
4625 | "StructRefInfo::setValue: ooops... the value could not be assigned!")do { if (true && (!(bSuccess))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx" ":" "4625" ": "), "%s", "StructRefInfo::setValue: ooops... the value could not be assigned!" ); } } while (false); | ||||
4626 | } | ||||
4627 | |||||
4628 | OUString StructRefInfo::getTypeName() const | ||||
4629 | { | ||||
4630 | return maType.getTypeName(); | ||||
4631 | } | ||||
4632 | |||||
4633 | void* StructRefInfo::getInst() | ||||
4634 | { | ||||
4635 | return const_cast<char *>(static_cast<char const *>(maAny.getValue()) + mnPos); | ||||
4636 | } | ||||
4637 | |||||
4638 | TypeClass StructRefInfo::getTypeClass() const | ||||
4639 | { | ||||
4640 | return maType.getTypeClass(); | ||||
4641 | } | ||||
4642 | |||||
4643 | SbUnoStructRefObject::SbUnoStructRefObject( const OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false ) | ||||
4644 | { | ||||
4645 | SetClassName( maMemberInfo.getTypeName() ); | ||||
4646 | } | ||||
4647 | |||||
4648 | SbUnoStructRefObject::~SbUnoStructRefObject() | ||||
4649 | { | ||||
4650 | } | ||||
4651 | |||||
4652 | void SbUnoStructRefObject::initMemberCache() | ||||
4653 | { | ||||
4654 | if ( mbMemberCacheInit ) | ||||
4655 | return; | ||||
4656 | typelib_TypeDescription * pTD = nullptr; | ||||
4657 | maMemberInfo.getType().getDescription(&pTD); | ||||
4658 | for ( typelib_CompoundTypeDescription * pCompTypeDescr = reinterpret_cast<typelib_CompoundTypeDescription *>(pTD); | ||||
4659 | pCompTypeDescr; | ||||
4660 | pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) | ||||
4661 | { | ||||
4662 | typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs; | ||||
4663 | rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames; | ||||
4664 | sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets; | ||||
4665 | for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; ) | ||||
4666 | { | ||||
4667 | OUString aName( ppNames[nPos] ); | ||||
4668 | maFields[ aName ] = std::make_unique<StructRefInfo>( maMemberInfo.getRootAnyRef(), ppTypeRefs[nPos], maMemberInfo.getPos() + pMemberOffsets[nPos] ); | ||||
4669 | } | ||||
4670 | } | ||||
4671 | typelib_typedescription_release(pTD); | ||||
4672 | mbMemberCacheInit = true; | ||||
4673 | } | ||||
4674 | |||||
4675 | SbxVariable* SbUnoStructRefObject::Find( const OUString& rName, SbxClassType t ) | ||||
4676 | { | ||||
4677 | SbxVariable* pRes = SbxObject::Find( rName, t ); | ||||
4678 | if ( !pRes ) | ||||
4679 | { | ||||
4680 | if ( !mbMemberCacheInit ) | ||||
4681 | initMemberCache(); | ||||
4682 | StructFieldInfo::iterator it = maFields.find( rName ); | ||||
4683 | if ( it != maFields.end() ) | ||||
4684 | { | ||||
4685 | SbxDataType eSbxType; | ||||
4686 | eSbxType = unoToSbxType( it->second->getTypeClass() ); | ||||
4687 | SbxDataType eRealSbxType = eSbxType; | ||||
4688 | Property aProp; | ||||
4689 | aProp.Name = rName; | ||||
4690 | aProp.Type = css::uno::Type( it->second->getTypeClass(), it->second->getTypeName() ); | ||||
4691 | SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT) ); | ||||
4692 | SbxVariableRef xVarRef = pProp; | ||||
4693 | QuickInsert( xVarRef.get() ); | ||||
4694 | pRes = xVarRef.get(); | ||||
4695 | } | ||||
4696 | } | ||||
4697 | |||||
4698 | if( !pRes ) | ||||
4699 | { | ||||
4700 | if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) || | ||||
4701 | rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) || | ||||
4702 | rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) ) | ||||
4703 | { | ||||
4704 | // Create | ||||
4705 | implCreateDbgProperties(); | ||||
4706 | |||||
4707 | // Now they have to be found regular | ||||
4708 | pRes = SbxObject::Find( rName, SbxClassType::DontCare ); | ||||
4709 | } | ||||
4710 | } | ||||
4711 | |||||
4712 | return pRes; | ||||
4713 | } | ||||
4714 | |||||
4715 | // help method to create the dbg_-Properties | ||||
4716 | void SbUnoStructRefObject::implCreateDbgProperties() | ||||
4717 | { | ||||
4718 | Property aProp; | ||||
4719 | |||||
4720 | // Id == -1: display the implemented interfaces corresponding the ClassProvider | ||||
4721 | SbxVariableRef xVarRef = new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES, SbxSTRING, SbxSTRING, aProp, -1, false, false ); | ||||
4722 | QuickInsert( xVarRef.get() ); | ||||
4723 | |||||
4724 | // Id == -2: output the properties | ||||
4725 | xVarRef = new SbUnoProperty( ID_DBG_PROPERTIES, SbxSTRING, SbxSTRING, aProp, -2, false, false ); | ||||
4726 | QuickInsert( xVarRef.get() ); | ||||
4727 | |||||
4728 | // Id == -3: output the Methods | ||||
4729 | xVarRef = new SbUnoProperty( ID_DBG_METHODS, SbxSTRING, SbxSTRING, aProp, -3, false, false ); | ||||
4730 | QuickInsert( xVarRef.get() ); | ||||
4731 | } | ||||
4732 | |||||
4733 | void SbUnoStructRefObject::implCreateAll() | ||||
4734 | { | ||||
4735 | // throw away all existing methods and properties | ||||
4736 | pMethods = new SbxArray; | ||||
4737 | pProps = new SbxArray; | ||||
4738 | |||||
4739 | if (!mbMemberCacheInit) | ||||
4740 | initMemberCache(); | ||||
4741 | |||||
4742 | for (auto const& field : maFields) | ||||
4743 | { | ||||
4744 | const OUString& rName = field.first; | ||||
4745 | SbxDataType eSbxType; | ||||
4746 | eSbxType = unoToSbxType( field.second->getTypeClass() ); | ||||
4747 | SbxDataType eRealSbxType = eSbxType; | ||||
4748 | Property aProp; | ||||
4749 | aProp.Name = rName; | ||||
4750 | aProp.Type = css::uno::Type( field.second->getTypeClass(), field.second->getTypeName() ); | ||||
4751 | SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == css::uno::TypeClass_STRUCT) ); | ||||
4752 | SbxVariableRef xVarRef = pProp; | ||||
4753 | QuickInsert( xVarRef.get() ); | ||||
4754 | } | ||||
4755 | |||||
4756 | // Create Dbg_-Properties | ||||
4757 | implCreateDbgProperties(); | ||||
4758 | } | ||||
4759 | |||||
4760 | // output the value | ||||
4761 | Any SbUnoStructRefObject::getUnoAny() | ||||
4762 | { | ||||
4763 | return maMemberInfo.getValue(); | ||||
4764 | } | ||||
4765 | |||||
4766 | OUString SbUnoStructRefObject::Impl_DumpProperties() | ||||
4767 | { | ||||
4768 | OUStringBuffer aRet; | ||||
4769 | aRet.append("Properties of object "); | ||||
4770 | aRet.append( getDbgObjectName() ); | ||||
4771 | |||||
4772 | sal_uInt32 nPropCount = pProps->Count32(); | ||||
4773 | sal_uInt32 nPropsPerLine = 1 + nPropCount / 30; | ||||
4774 | for( sal_uInt32 i = 0; i < nPropCount; i++ ) | ||||
4775 | { | ||||
4776 | SbxVariable* pVar = pProps->Get32( i ); | ||||
4777 | if( pVar ) | ||||
4778 | { | ||||
4779 | OUStringBuffer aPropStr; | ||||
4780 | if( (i % nPropsPerLine) == 0 ) | ||||
4781 | { | ||||
4782 | aPropStr.append( "\n" ); | ||||
4783 | } | ||||
4784 | // output the type and name | ||||
4785 | // Is it in Uno a sequence? | ||||
4786 | SbxDataType eType = pVar->GetFullType(); | ||||
4787 | |||||
4788 | const OUString& aName( pVar->GetName() ); | ||||
4789 | StructFieldInfo::iterator it = maFields.find( aName ); | ||||
4790 | |||||
4791 | if ( it != maFields.end() ) | ||||
4792 | { | ||||
4793 | const StructRefInfo& rPropInfo = *it->second; | ||||
4794 | |||||
4795 | if( eType == SbxOBJECT ) | ||||
4796 | { | ||||
4797 | if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE ) | ||||
4798 | { | ||||
4799 | eType = SbxDataType( SbxOBJECT | SbxARRAY ); | ||||
4800 | } | ||||
4801 | } | ||||
4802 | } | ||||
4803 | aPropStr.append( Dbg_SbxDataType2String( eType ) ); | ||||
4804 | |||||
4805 | aPropStr.append( " " ); | ||||
4806 | aPropStr.append( pVar->GetName() ); | ||||
4807 | |||||
4808 | if( i == nPropCount - 1 ) | ||||
4809 | { | ||||
4810 | aPropStr.append( "\n" ); | ||||
4811 | } | ||||
4812 | else | ||||
4813 | { | ||||
4814 | aPropStr.append( "; " ); | ||||
4815 | } | ||||
4816 | aRet.append( aPropStr.makeStringAndClear() ); | ||||
4817 | } | ||||
4818 | } | ||||
4819 | return aRet.makeStringAndClear(); | ||||
4820 | } | ||||
4821 | |||||
4822 | void SbUnoStructRefObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) | ||||
4823 | { | ||||
4824 | if ( !mbMemberCacheInit ) | ||||
4825 | initMemberCache(); | ||||
4826 | const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint); | ||||
4827 | if( !pHint ) | ||||
4828 | return; | ||||
4829 | |||||
4830 | SbxVariable* pVar = pHint->GetVar(); | ||||
4831 | SbUnoProperty* pProp = dynamic_cast<SbUnoProperty*>( pVar ); | ||||
4832 | if( pProp ) | ||||
4833 | { | ||||
4834 | StructFieldInfo::iterator it = maFields.find( pProp->GetName() ); | ||||
4835 | // handle get/set of members of struct | ||||
4836 | if( pHint->GetId() == SfxHintId::BasicDataWanted ) | ||||
4837 | { | ||||
4838 | // Test-Properties | ||||
4839 | sal_Int32 nId = pProp->nId; | ||||
4840 | if( nId < 0 ) | ||||
4841 | { | ||||
4842 | // Id == -1: Display implemented interfaces according the ClassProvider | ||||
4843 | if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES" | ||||
4844 | { | ||||
4845 | OUString aRet = OUStringLiteral( ID_DBG_SUPPORTEDINTERFACES ) | ||||
4846 | + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n"; | ||||
4847 | |||||
4848 | pVar->PutString( aRet ); | ||||
4849 | } | ||||
4850 | // Id == -2: output properties | ||||
4851 | else if( nId == -2 ) // Property ID_DBG_PROPERTIES | ||||
4852 | { | ||||
4853 | // by now all properties must be established | ||||
4854 | implCreateAll(); | ||||
4855 | OUString aRetStr = Impl_DumpProperties(); | ||||
4856 | pVar->PutString( aRetStr ); | ||||
4857 | } | ||||
4858 | // Id == -3: output the methods | ||||
4859 | else if( nId == -3 ) // Property ID_DBG_METHODS | ||||
4860 | { | ||||
4861 | // by now all properties must be established | ||||
4862 | implCreateAll(); | ||||
4863 | OUString aRet = "Methods of object " | ||||
4864 | + getDbgObjectName() | ||||
4865 | + "\nNo methods found\n"; | ||||
4866 | pVar->PutString( aRet ); | ||||
4867 | } | ||||
4868 | return; | ||||
4869 | } | ||||
4870 | |||||
4871 | if ( it != maFields.end() ) | ||||
4872 | { | ||||
4873 | Any aRetAny = it->second->getValue(); | ||||
4874 | unoToSbxValue( pVar, aRetAny ); | ||||
4875 | } | ||||
4876 | else | ||||
4877 | StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 85 ) ); | ||||
4878 | } | ||||
4879 | else if( pHint->GetId() == SfxHintId::BasicDataChanged ) | ||||
4880 | { | ||||
4881 | if ( it != maFields.end() ) | ||||
4882 | { | ||||
4883 | // take over the value from Uno to Sbx | ||||
4884 | Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp ); | ||||
4885 | it->second->setValue( aAnyValue ); | ||||
4886 | } | ||||
4887 | else | ||||
4888 | StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUNDErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 85 ) ); | ||||
4889 | } | ||||
4890 | } | ||||
4891 | else | ||||
4892 | SbxObject::Notify( rBC, rHint ); | ||||
4893 | } | ||||
4894 | |||||
4895 | StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName ) | ||||
4896 | { | ||||
4897 | if (!mbMemberCacheInit) | ||||
4898 | { | ||||
4899 | initMemberCache(); | ||||
4900 | } | ||||
4901 | StructFieldInfo::iterator it = maFields.find( rMemberName ); | ||||
4902 | |||||
4903 | css::uno::Type aFoundType; | ||||
4904 | sal_Int32 nFoundPos = -1; | ||||
4905 | |||||
4906 | if ( it != maFields.end() ) | ||||
4907 | { | ||||
4908 | aFoundType = it->second->getType(); | ||||
4909 | nFoundPos = it->second->getPos(); | ||||
4910 | } | ||||
4911 | StructRefInfo aRet( maMemberInfo.getRootAnyRef(), aFoundType, nFoundPos ); | ||||
4912 | return aRet; | ||||
4913 | } | ||||
4914 | |||||
4915 | OUString SbUnoStructRefObject::getDbgObjectName() const | ||||
4916 | { | ||||
4917 | OUString aName = GetClassName(); | ||||
4918 | if( aName.isEmpty() ) | ||||
4919 | { | ||||
4920 | aName += "Unknown"; | ||||
4921 | } | ||||
4922 | OUStringBuffer aRet; | ||||
4923 | if( aName.getLength() > 20 ) | ||||
4924 | { | ||||
4925 | aRet.append( "\n" ); | ||||
4926 | } | ||||
4927 | aRet.append( "\"" ); | ||||
4928 | aRet.append( aName ); | ||||
4929 | aRet.append( "\":" ); | ||||
4930 | return aRet.makeStringAndClear(); | ||||
4931 | } | ||||
4932 | |||||
4933 | /* 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: */ |