File: | home/maarten/src/libreoffice/core/basic/source/classes/sbunoobj.cxx |
Warning: | line 3037, column 1 Potential leak of memory pointed to by 'xUnoObj.pObj' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | #include <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 && mxInvocation.is() ) | |||
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: */ |