1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
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>
35 #include <rtl/instance.hxx>
36 #include <rtl/ustrbuf.hxx>
38 #include <com/sun/star/script/ArrayWrapper.hpp>
39 #include <com/sun/star/script/CannotConvertException.hpp>
40 #include <com/sun/star/script/NativeObjectWrapper.hpp>
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>
73 #include <rtlproto.hxx>
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>
85 #include <unordered_map>
86 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
87 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
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
;
100 // Identifiers for creating the strings for dbg_Properties
101 static char const ID_DBG_SUPPORTEDINTERFACES
[] = "Dbg_SupportedInterfaces";
102 static char const ID_DBG_PROPERTIES
[] = "Dbg_Properties";
103 static char const ID_DBG_METHODS
[] = "Dbg_Methods";
105 static char const aSeqLevelStr
[] = "[]";
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.
111 bool SbUnoObject::getDefaultPropName( SbUnoObject
const * pUnoObj
, OUString
& sDfltProp
)
113 bool bResult
= false;
114 Reference
< XDefaultProperty
> xDefaultProp( pUnoObj
->maTmpUnoObj
, UNO_QUERY
);
115 if ( xDefaultProp
.is() )
117 sDfltProp
= xDefaultProp
->getDefaultPropertyName();
118 if ( !sDfltProp
.isEmpty() )
124 SbxVariable
* getDefaultProp( SbxVariable
* pRef
)
126 SbxVariable
* pDefaultProp
= nullptr;
127 if ( pRef
->GetType() == SbxOBJECT
)
129 SbxObject
* pObj
= dynamic_cast<SbxObject
*>(pRef
);
132 SbxBase
* pObjVarObj
= pRef
->GetObject();
133 pObj
= dynamic_cast<SbxObject
*>( pObjVarObj
);
135 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
137 pDefaultProp
= pUnoObj
->GetDfltProperty();
143 void SetSbUnoObjectDfltPropName( SbxObject
* pObj
)
145 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
148 OUString sDfltPropName
;
150 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
152 pUnoObj
->SetDfltProperty( sDfltPropName
);
157 // save CoreReflection statically
158 static Reference
< XIdlReflection
> getCoreReflection_Impl()
160 return css::reflection::theCoreReflection::get(
161 comphelper::getProcessComponentContext());
164 // save CoreReflection statically
165 static Reference
< XHierarchicalNameAccess
> const & getCoreReflection_HierarchicalNameAccess_Impl()
167 static Reference
< XHierarchicalNameAccess
> xCoreReflection_HierarchicalNameAccess
;
169 if( !xCoreReflection_HierarchicalNameAccess
.is() )
171 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
172 if( xCoreReflection
.is() )
174 xCoreReflection_HierarchicalNameAccess
=
175 Reference
< XHierarchicalNameAccess
>( xCoreReflection
, UNO_QUERY
);
178 return xCoreReflection_HierarchicalNameAccess
;
181 // Hold TypeProvider statically
182 static Reference
< XHierarchicalNameAccess
> const & getTypeProvider_Impl()
184 static Reference
< XHierarchicalNameAccess
> xAccess
;
186 // Do we have already CoreReflection; if not obtain it
189 Reference
< XComponentContext
> xContext(
190 comphelper::getProcessComponentContext() );
193 xContext
->getValueByName(
194 "/singletons/com.sun.star.reflection.theTypeDescriptionManager" )
196 OSL_ENSURE( xAccess
.is(), "### TypeDescriptionManager singleton not accessible!?" );
200 throw DeploymentException(
201 "/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible" );
207 // Hold TypeConverter statically
208 static Reference
< XTypeConverter
> const & getTypeConverter_Impl()
210 static Reference
< XTypeConverter
> xTypeConverter
;
212 // Do we have already CoreReflection; if not obtain it
213 if( !xTypeConverter
.is() )
215 Reference
< XComponentContext
> xContext(
216 comphelper::getProcessComponentContext() );
219 xTypeConverter
= Converter::create(xContext
);
221 if( !xTypeConverter
.is() )
223 throw DeploymentException(
224 "com.sun.star.script.Converter service not accessible" );
227 return xTypeConverter
;
231 // #111851 factory function to create an OLE object
232 SbUnoObject
* createOLEObject_Impl( const OUString
& aType
)
234 static Reference
< XMultiServiceFactory
> xOLEFactory
;
235 static bool bNeedsInit
= true;
241 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
244 Reference
<XMultiComponentFactory
> xSMgr
= xContext
->getServiceManager();
246 xSMgr
->createInstanceWithContext( "com.sun.star.bridge.OleObjectFactory", xContext
),
251 SbUnoObject
* pUnoObj
= nullptr;
252 if( xOLEFactory
.is() )
254 // some type names available in VBA can not be directly used in COM
255 OUString aOLEType
= aType
;
256 if ( aOLEType
== "SAXXMLReader30" )
258 aOLEType
= "Msxml2.SAXXMLReader.3.0";
260 Reference
< XInterface
> xOLEObject
= xOLEFactory
->createInstance( aOLEType
);
261 if( xOLEObject
.is() )
263 pUnoObj
= new SbUnoObject( aType
, Any(xOLEObject
) );
264 OUString sDfltPropName
;
266 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
267 pUnoObj
->SetDfltProperty( sDfltPropName
);
276 void lcl_indent( OUStringBuffer
& _inout_rBuffer
, sal_Int32 _nLevel
)
278 while ( _nLevel
-- > 0 )
280 _inout_rBuffer
.append( " " );
285 static void implAppendExceptionMsg( OUStringBuffer
& _inout_rBuffer
, const Exception
& _e
, const OUString
& _rExceptionType
, sal_Int32 _nLevel
)
287 _inout_rBuffer
.append( "\n" );
288 lcl_indent( _inout_rBuffer
, _nLevel
);
289 _inout_rBuffer
.append( "Type: " );
291 if ( _rExceptionType
.isEmpty() )
292 _inout_rBuffer
.append( "Unknown" );
294 _inout_rBuffer
.append( _rExceptionType
);
296 _inout_rBuffer
.append( "\n" );
297 lcl_indent( _inout_rBuffer
, _nLevel
);
298 _inout_rBuffer
.append( "Message: " );
299 _inout_rBuffer
.append( _e
.Message
);
303 // construct an error message for the exception
304 static OUString
implGetExceptionMsg( const Exception
& e
, const OUString
& aExceptionType_
)
306 OUStringBuffer aMessageBuf
;
307 implAppendExceptionMsg( aMessageBuf
, e
, aExceptionType_
, 0 );
308 return aMessageBuf
.makeStringAndClear();
311 static OUString
implGetExceptionMsg( const Any
& _rCaughtException
)
313 auto e
= o3tl::tryAccess
<Exception
>(_rCaughtException
);
314 OSL_PRECOND( e
, "implGetExceptionMsg: illegal argument!" );
319 return implGetExceptionMsg( *e
, _rCaughtException
.getValueTypeName() );
322 static Any
convertAny( const Any
& rVal
, const Type
& aDestType
)
325 const Reference
< XTypeConverter
>& xConverter
= getTypeConverter_Impl();
328 aConvertedVal
= xConverter
->convertTo( rVal
, aDestType
);
330 catch( const IllegalArgumentException
& )
332 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
333 implGetExceptionMsg( ::cppu::getCaughtException() ) );
334 return aConvertedVal
;
336 catch( const CannotConvertException
& e2
)
338 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
339 implGetExceptionMsg( e2
, "com.sun.star.lang.IllegalArgumentException" ) );
340 return aConvertedVal
;
342 return aConvertedVal
;
346 // #105565 Special Object to wrap a strongly typed Uno Any
349 // TODO: source out later
350 static Reference
<XIdlClass
> TypeToIdlClass( const Type
& rType
)
352 return getCoreReflection_Impl()->forName(rType
.getTypeName());
355 // Exception type unknown
356 template< class EXCEPTION
>
357 static OUString
implGetExceptionMsg( const EXCEPTION
& e
)
359 return implGetExceptionMsg( e
, cppu::UnoType
<decltype(e
)>::get().getTypeName() );
362 static void implHandleBasicErrorException( BasicErrorException
const & e
)
364 ErrCode nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(e
.ErrorCode
) );
365 StarBASIC::Error( nError
, e
.ErrorMessageArgument
);
368 static void implHandleWrappedTargetException( const Any
& _rWrappedTargetException
)
370 Any
aExamine( _rWrappedTargetException
);
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
;
378 BasicErrorException aBasicError
;
380 ErrCode
nError( ERRCODE_BASIC_EXCEPTION
);
381 OUStringBuffer aMessageBuf
;
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
)
388 // special handling for BasicErrorException errors
389 if ( aWrapped
.TargetException
>>= aBasicError
)
391 nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(aBasicError
.ErrorCode
) );
392 aMessageBuf
.append( aBasicError
.ErrorMessageArgument
);
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:" );
404 aExamine
= aWrapped
.TargetException
;
408 if ( auto e
= o3tl::tryAccess
<Exception
>(aExamine
) )
410 // the last element in the chain is still an exception, but no WrappedTargetException
411 implAppendExceptionMsg( aMessageBuf
, *e
, aExamine
.getValueTypeName(), nLevel
);
414 StarBASIC::Error( nError
, aMessageBuf
.makeStringAndClear() );
417 static void implHandleAnyException( const Any
& _rCaughtException
)
419 BasicErrorException aBasicError
;
420 WrappedTargetException aWrappedError
;
422 if ( _rCaughtException
>>= aBasicError
)
424 implHandleBasicErrorException( aBasicError
);
426 else if ( _rCaughtException
>>= aWrappedError
)
428 implHandleWrappedTargetException( _rCaughtException
);
432 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( _rCaughtException
) );
436 // NativeObjectWrapper handling
439 SbxObjectRef m_xNativeObj
;
441 explicit ObjectItem( SbxObject
* pNativeObj
)
442 : m_xNativeObj( pNativeObj
)
446 typedef std::vector
< ObjectItem
> NativeObjectWrapperVector
;
447 class GaNativeObjectWrapperVector
: public rtl::Static
<NativeObjectWrapperVector
, GaNativeObjectWrapperVector
> {};
449 void clearNativeObjectWrapperVector()
451 GaNativeObjectWrapperVector::get().clear();
454 static sal_uInt32
lcl_registerNativeObjectWrapper( SbxObject
* pNativeObj
)
456 NativeObjectWrapperVector
&rNativeObjectWrapperVector
= GaNativeObjectWrapperVector::get();
457 sal_uInt32 nIndex
= rNativeObjectWrapperVector
.size();
458 rNativeObjectWrapperVector
.emplace_back( pNativeObj
);
462 static SbxObject
* lcl_getNativeObject( sal_uInt32 nIndex
)
464 SbxObjectRef xRetObj
;
465 NativeObjectWrapperVector
&rNativeObjectWrapperVector
= GaNativeObjectWrapperVector::get();
466 if( nIndex
< rNativeObjectWrapperVector
.size() )
468 ObjectItem
& rItem
= rNativeObjectWrapperVector
[ nIndex
];
469 xRetObj
= rItem
.m_xNativeObj
;
471 return xRetObj
.get();
474 // convert from Uno to Sbx
475 static SbxDataType
unoToSbxType( TypeClass eType
)
477 SbxDataType eRetType
= SbxVOID
;
481 case TypeClass_INTERFACE
:
483 case TypeClass_STRUCT
:
484 case TypeClass_EXCEPTION
: eRetType
= SbxOBJECT
; break;
486 case TypeClass_ENUM
: eRetType
= SbxLONG
; break;
487 case TypeClass_SEQUENCE
:
488 eRetType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
492 case TypeClass_ANY
: eRetType
= SbxVARIANT
; break;
493 case TypeClass_BOOLEAN
: eRetType
= SbxBOOL
; break;
494 case TypeClass_CHAR
: eRetType
= SbxCHAR
; break;
495 case TypeClass_STRING
: eRetType
= SbxSTRING
; break;
496 case TypeClass_FLOAT
: eRetType
= SbxSINGLE
; break;
497 case TypeClass_DOUBLE
: eRetType
= SbxDOUBLE
; break;
498 case TypeClass_BYTE
: eRetType
= SbxINTEGER
; break;
499 case TypeClass_SHORT
: eRetType
= SbxINTEGER
; break;
500 case TypeClass_LONG
: eRetType
= SbxLONG
; break;
501 case TypeClass_HYPER
: eRetType
= SbxSALINT64
; break;
502 case TypeClass_UNSIGNED_SHORT
: eRetType
= SbxUSHORT
; break;
503 case TypeClass_UNSIGNED_LONG
: eRetType
= SbxULONG
; break;
504 case TypeClass_UNSIGNED_HYPER
: eRetType
= SbxSALUINT64
;break;
510 static SbxDataType
unoToSbxType( const Reference
< XIdlClass
>& xIdlClass
)
512 SbxDataType eRetType
= SbxVOID
;
515 TypeClass eType
= xIdlClass
->getTypeClass();
516 eRetType
= unoToSbxType( eType
);
521 static void implSequenceToMultiDimArray( SbxDimArray
*& pArray
, Sequence
< sal_Int32
>& indices
, Sequence
< sal_Int32
>& sizes
, const Any
& aValue
, sal_Int32 dimension
, bool bIsZeroIndex
, Type
const * pType
)
523 const Type
& aType
= aValue
.getValueType();
524 TypeClass eTypeClass
= aType
.getTypeClass();
526 sal_Int32 dimCopy
= dimension
;
528 if ( eTypeClass
== TypeClass_SEQUENCE
)
530 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
531 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
532 typelib_TypeDescription
* pTD
= nullptr;
533 aType
.getDescription( &pTD
);
534 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
535 ::typelib_typedescription_release( pTD
);
537 sal_Int32 nLen
= xIdlArray
->getLen( aValue
);
538 for ( sal_Int32 index
= 0; index
< nLen
; ++index
)
540 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(index
) );
541 // This detects the dimension were currently processing
542 if ( dimCopy
== dimension
)
545 if ( sizes
.getLength() < dimCopy
)
547 sizes
.realloc( sizes
.getLength() + 1 );
548 sizes
[ sizes
.getLength() - 1 ] = nLen
;
549 indices
.realloc( indices
.getLength() + 1 );
554 indices
[ dimCopy
- 1 ] = index
;
556 indices
[ dimCopy
- 1] = index
+ 1;
558 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aElementAny
, dimCopy
, bIsZeroIndex
, &aElementType
);
564 if ( !indices
.hasElements() )
566 // Should never ever get here ( indices.getLength()
567 // should equal number of dimensions in the array )
568 // And that should at least be 1 !
569 // #QUESTION is there a better error?
570 StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT
);
574 SbxDataType eSbxElementType
= unoToSbxType( pType
? pType
->getTypeClass() : aValue
.getValueTypeClass() );
577 pArray
= new SbxDimArray( eSbxElementType
);
578 sal_Int32 nIndexLen
= indices
.getLength();
580 // Dimension the array
581 for ( sal_Int32 index
= 0; index
< nIndexLen
; ++index
)
584 pArray
->unoAddDim32( 0, sizes
[ index
] - 1);
586 pArray
->unoAddDim32( 1, sizes
[ index
] );
593 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
594 unoToSbxValue( xVar
.get(), aValue
);
596 sal_Int32
* pIndices
= indices
.getArray();
597 pArray
->Put32( xVar
.get(), pIndices
);
603 void unoToSbxValue( SbxVariable
* pVar
, const Any
& aValue
)
605 const Type
& aType
= aValue
.getValueType();
606 TypeClass eTypeClass
= aType
.getTypeClass();
611 // Map Type to IdlClass
614 Reference
<XIdlClass
> xClass
= TypeToIdlClass( aType_
);
616 aClassAny
<<= xClass
;
618 // instantiate SbUnoObject
619 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aClassAny
);
620 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
622 // If the object is invalid deliver null
623 if( !pSbUnoObject
->getUnoAny().hasValue() )
625 pVar
->PutObject( nullptr );
629 pVar
->PutObject( xWrapper
.get() );
633 // Interfaces and Structs must be wrapped in a SbUnoObject
634 case TypeClass_INTERFACE
:
635 case TypeClass_STRUCT
:
636 case TypeClass_EXCEPTION
:
638 if( eTypeClass
== TypeClass_STRUCT
)
641 NativeObjectWrapper aNativeObjectWrapper
;
642 if ( aValue
>>= aWrap
)
644 SbxDimArray
* pArray
= nullptr;
645 Sequence
< sal_Int32
> indices
;
646 Sequence
< sal_Int32
> sizes
;
647 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aWrap
.Array
, /*dimension*/0, aWrap
.IsZeroIndex
, nullptr );
650 SbxDimArrayRef xArray
= pArray
;
651 SbxFlagBits nFlags
= pVar
->GetFlags();
652 pVar
->ResetFlag( SbxFlagBits::Fixed
);
653 pVar
->PutObject( xArray
.get() );
654 pVar
->SetFlags( nFlags
);
660 else if ( aValue
>>= aNativeObjectWrapper
)
662 sal_uInt32 nIndex
= 0;
663 if( aNativeObjectWrapper
.ObjectId
>>= nIndex
)
665 SbxObject
* pObj
= lcl_getNativeObject( nIndex
);
666 pVar
->PutObject( pObj
);
674 SbiInstance
* pInst
= GetSbData()->pInst
;
675 if( pInst
&& pInst
->IsCompatibility() )
677 oleautomation::Date aDate
;
678 if( aValue
>>= aDate
)
680 pVar
->PutDate( aDate
.Value
);
685 oleautomation::Decimal aDecimal
;
686 if( aValue
>>= aDecimal
)
688 pVar
->PutDecimal( aDecimal
);
693 oleautomation::Currency aCurrency
;
694 if( aValue
>>= aCurrency
)
696 pVar
->PutCurrency( aCurrency
.Value
);
704 // instantiate a SbUnoObject
705 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aValue
);
706 //If this is called externally e.g. from the scripting
707 //framework then there is no 'active' runtime the default property will not be set up
708 //only a vba object will have XDefaultProp set anyway so... this
709 //test seems a bit of overkill
710 //if ( SbiRuntime::isVBAEnabled() )
712 OUString sDfltPropName
;
714 if ( SbUnoObject::getDefaultPropName( pSbUnoObject
, sDfltPropName
) )
716 pSbUnoObject
->SetDfltProperty( sDfltPropName
);
719 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
721 // If the object is invalid deliver null
722 if( !pSbUnoObject
->getUnoAny().hasValue() )
724 pVar
->PutObject( nullptr );
728 pVar
->PutObject( xWrapper
.get() );
737 enum2int( nEnum
, aValue
);
738 pVar
->PutLong( nEnum
);
742 case TypeClass_SEQUENCE
:
744 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
745 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
746 sal_Int32 i
, nLen
= xIdlArray
->getLen( aValue
);
748 typelib_TypeDescription
* pTD
= nullptr;
749 aType
.getDescription( &pTD
);
750 OSL_ASSERT( pTD
&& pTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
);
751 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
752 ::typelib_typedescription_release( pTD
);
754 // build an Array in Basic
755 SbxDimArrayRef xArray
;
756 SbxDataType eSbxElementType
= unoToSbxType( aElementType
.getTypeClass() );
757 xArray
= new SbxDimArray( eSbxElementType
);
760 xArray
->unoAddDim32( 0, nLen
- 1 );
762 // register the elements as variables
763 for( i
= 0 ; i
< nLen
; i
++ )
766 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(i
) );
767 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
768 unoToSbxValue( xVar
.get(), aElementAny
);
770 // put into the Array
771 xArray
->Put32( xVar
.get(), &i
);
776 xArray
->unoAddDim( 0, -1 );
780 SbxFlagBits nFlags
= pVar
->GetFlags();
781 pVar
->ResetFlag( SbxFlagBits::Fixed
);
782 pVar
->PutObject( xArray
.get() );
783 pVar
->SetFlags( nFlags
);
789 case TypeClass_BOOLEAN
: pVar
->PutBool( *o3tl::forceAccess
<bool>(aValue
) ); break;
792 pVar
->PutChar( *o3tl::forceAccess
<sal_Unicode
>(aValue
) );
795 case TypeClass_STRING
: { OUString val
; aValue
>>= val
; pVar
->PutString( val
); } break;
796 case TypeClass_FLOAT
: { float val
= 0; aValue
>>= val
; pVar
->PutSingle( val
); } break;
797 case TypeClass_DOUBLE
: { double val
= 0; aValue
>>= val
; pVar
->PutDouble( val
); } break;
798 case TypeClass_BYTE
: { sal_Int8 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
799 case TypeClass_SHORT
: { sal_Int16 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
800 case TypeClass_LONG
: { sal_Int32 val
= 0; aValue
>>= val
; pVar
->PutLong( val
); } break;
801 case TypeClass_HYPER
: { sal_Int64 val
= 0; aValue
>>= val
; pVar
->PutInt64( val
); } break;
802 case TypeClass_UNSIGNED_SHORT
: { sal_uInt16 val
= 0; aValue
>>= val
; pVar
->PutUShort( val
); } break;
803 case TypeClass_UNSIGNED_LONG
: { sal_uInt32 val
= 0; aValue
>>= val
; pVar
->PutULong( val
); } break;
804 case TypeClass_UNSIGNED_HYPER
: { sal_uInt64 val
= 0; aValue
>>= val
; pVar
->PutUInt64( val
); } break;
805 default: pVar
->PutEmpty(); break;
809 // Deliver the reflection for Sbx types
810 static Type
getUnoTypeForSbxBaseType( SbxDataType eType
)
812 Type aRetType
= cppu::UnoType
<void>::get();
815 case SbxNULL
: aRetType
= cppu::UnoType
<XInterface
>::get(); break;
816 case SbxINTEGER
: aRetType
= cppu::UnoType
<sal_Int16
>::get(); break;
817 case SbxLONG
: aRetType
= cppu::UnoType
<sal_Int32
>::get(); break;
818 case SbxSINGLE
: aRetType
= cppu::UnoType
<float>::get(); break;
819 case SbxDOUBLE
: aRetType
= cppu::UnoType
<double>::get(); break;
820 case SbxCURRENCY
: aRetType
= cppu::UnoType
<oleautomation::Currency
>::get(); break;
821 case SbxDECIMAL
: aRetType
= cppu::UnoType
<oleautomation::Decimal
>::get(); break;
823 SbiInstance
* pInst
= GetSbData()->pInst
;
824 if( pInst
&& pInst
->IsCompatibility() )
825 aRetType
= cppu::UnoType
<double>::get();
827 aRetType
= cppu::UnoType
<oleautomation::Date
>::get();
830 case SbxSTRING
: aRetType
= cppu::UnoType
<OUString
>::get(); break;
831 case SbxBOOL
: aRetType
= cppu::UnoType
<sal_Bool
>::get(); break;
832 case SbxVARIANT
: aRetType
= cppu::UnoType
<Any
>::get(); break;
833 case SbxCHAR
: aRetType
= cppu::UnoType
<cppu::UnoCharType
>::get(); break;
834 case SbxBYTE
: aRetType
= cppu::UnoType
<sal_Int8
>::get(); break;
835 case SbxUSHORT
: aRetType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get(); break;
836 case SbxULONG
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
837 // map machine-dependent ones to long for consistency
838 case SbxINT
: aRetType
= ::cppu::UnoType
<sal_Int32
>::get(); break;
839 case SbxUINT
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
845 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
846 static Type
getUnoTypeForSbxValue( const SbxValue
* pVal
)
848 Type aRetType
= cppu::UnoType
<void>::get();
852 // convert SbxType to Uno
853 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
854 if( eBaseType
== SbxOBJECT
)
856 SbxBaseRef xObj
= pVal
->GetObject();
859 aRetType
= cppu::UnoType
<XInterface
>::get();
863 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
865 short nDims
= pArray
->GetDims();
866 Type aElementType
= getUnoTypeForSbxBaseType( static_cast<SbxDataType
>(pArray
->GetType() & 0xfff) );
867 TypeClass eElementTypeClass
= aElementType
.getTypeClass();
869 // Normal case: One dimensional array
870 sal_Int32 nLower
, nUpper
;
871 if( nDims
== 1 && pArray
->GetDim32( 1, nLower
, nUpper
) )
873 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
875 // If all elements of the arrays are from the same type, take
876 // this one - otherwise the whole will be considered as Any-Sequence
877 bool bNeedsInit
= true;
879 for (sal_Int32 aIdx
[1] = { nLower
}; aIdx
[0] <= nUpper
; ++aIdx
[0])
881 SbxVariableRef xVar
= pArray
->Get32(aIdx
);
882 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
885 if( aType
.getTypeClass() == TypeClass_VOID
)
887 // if only first element is void: different types -> []any
888 // if all elements are void: []void is not allowed -> []any
889 aElementType
= cppu::UnoType
<Any
>::get();
892 aElementType
= aType
;
895 else if( aElementType
!= aType
)
897 // different types -> AnySequence
898 aElementType
= cppu::UnoType
<Any
>::get();
904 OUString aSeqTypeName
= aSeqLevelStr
+ aElementType
.getTypeName();
905 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
);
907 // #i33795 Map also multi dimensional arrays to corresponding sequences
910 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
912 // For this check the array's dim structure does not matter
913 sal_uInt32 nFlatArraySize
= pArray
->Count32();
915 bool bNeedsInit
= true;
916 for( sal_uInt32 i
= 0 ; i
< nFlatArraySize
; i
++ )
918 SbxVariableRef xVar
= pArray
->SbxArray::Get32( i
);
919 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
922 if( aType
.getTypeClass() == TypeClass_VOID
)
924 // if only first element is void: different types -> []any
925 // if all elements are void: []void is not allowed -> []any
926 aElementType
= cppu::UnoType
<Any
>::get();
929 aElementType
= aType
;
932 else if( aElementType
!= aType
)
934 // different types -> AnySequence
935 aElementType
= cppu::UnoType
<Any
>::get();
941 OUStringBuffer aSeqTypeName
;
942 for( short iDim
= 0 ; iDim
< nDims
; iDim
++ )
944 aSeqTypeName
.append(aSeqLevelStr
);
946 aSeqTypeName
.append(aElementType
.getTypeName());
947 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
951 else if( auto obj
= dynamic_cast<SbUnoObject
*>( xObj
.get() ) )
953 aRetType
= obj
->getUnoAny().getValueType();
956 else if( auto any
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
958 aRetType
= any
->getValue().getValueType();
960 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
962 // No object, convert basic type
965 aRetType
= getUnoTypeForSbxBaseType( eBaseType
);
970 // converting of Sbx to Uno without known target class for TypeClass_ANY
971 static Any
sbxToUnoValueImpl( const SbxValue
* pVar
, bool bBlockConversionToSmallestType
= false )
973 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
974 if( eBaseType
== SbxOBJECT
)
976 SbxBaseRef xObj
= pVar
->GetObject();
979 if( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
980 return obj
->getValue();
981 if( auto pClassModuleObj
= dynamic_cast<SbClassModuleObject
*>( xObj
.get() ) )
984 SbModule
* pClassModule
= pClassModuleObj
->getClassModule();
985 if( pClassModule
->createCOMWrapperForIface( aRetAny
, pClassModuleObj
) )
988 if( dynamic_cast<const SbUnoObject
*>( xObj
.get() ) == nullptr )
990 // Create NativeObjectWrapper to identify object in case of callbacks
991 SbxObject
* pObj
= dynamic_cast<SbxObject
*>( pVar
->GetObject() );
992 if( pObj
!= nullptr )
994 NativeObjectWrapper aNativeObjectWrapper
;
995 sal_uInt32 nIndex
= lcl_registerNativeObjectWrapper( pObj
);
996 aNativeObjectWrapper
.ObjectId
<<= nIndex
;
998 aRetAny
<<= aNativeObjectWrapper
;
1005 Type aType
= getUnoTypeForSbxValue( pVar
);
1006 TypeClass eType
= aType
.getTypeClass();
1008 if( !bBlockConversionToSmallestType
)
1010 // #79615 Choose "smallest" representation for int values
1011 // because up cast is allowed, downcast not
1014 case TypeClass_FLOAT
:
1015 case TypeClass_DOUBLE
:
1017 double d
= pVar
->GetDouble();
1018 if( rtl::math::approxEqual(d
, floor( d
)) )
1020 if( d
>= -128 && d
<= 127 )
1021 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1022 else if( d
>= SbxMININT
&& d
<= SbxMAXINT
)
1023 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1024 else if( d
>= -SbxMAXLNG
&& d
<= SbxMAXLNG
)
1025 aType
= ::cppu::UnoType
<sal_Int32
>::get();
1029 case TypeClass_SHORT
:
1031 sal_Int16 n
= pVar
->GetInteger();
1032 if( n
>= -128 && n
<= 127 )
1033 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1036 case TypeClass_LONG
:
1038 sal_Int32 n
= pVar
->GetLong();
1039 if( n
>= -128 && n
<= 127 )
1040 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1041 else if( n
>= SbxMININT
&& n
<= SbxMAXINT
)
1042 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1045 case TypeClass_UNSIGNED_SHORT
:
1047 sal_uInt16 n
= pVar
->GetUShort();
1049 aType
= cppu::UnoType
<sal_uInt8
>::get();
1052 case TypeClass_UNSIGNED_LONG
:
1054 sal_uInt32 n
= pVar
->GetLong();
1056 aType
= cppu::UnoType
<sal_uInt8
>::get();
1057 else if( n
<= SbxMAXUINT
)
1058 aType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get();
1061 // TODO: need to add hyper types ?
1066 return sbxToUnoValue( pVar
, aType
);
1070 // Helper function for StepREDIMP
1071 static Any
implRekMultiDimArrayToSequence( SbxDimArray
* pArray
,
1072 const Type
& aElemType
, short nMaxDimIndex
, short nActualDim
,
1073 sal_Int32
* pActualIndices
, sal_Int32
* pLowerBounds
, sal_Int32
* pUpperBounds
)
1075 sal_Int32 nSeqLevel
= nMaxDimIndex
- nActualDim
+ 1;
1076 OUStringBuffer aSeqTypeName
;
1078 for( i
= 0 ; i
< nSeqLevel
; i
++ )
1080 aSeqTypeName
.append(aSeqLevelStr
);
1082 aSeqTypeName
.append(aElemType
.getTypeName());
1083 Type
aSeqType( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
1085 // Create Sequence instance
1087 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aSeqType
);
1088 xIdlTargetClass
->createObject( aRetVal
);
1090 // Alloc sequence according to array bounds
1091 sal_Int32 nUpper
= pUpperBounds
[nActualDim
];
1092 sal_Int32 nLower
= pLowerBounds
[nActualDim
];
1093 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1094 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1095 xArray
->realloc( aRetVal
, nSeqSize
);
1097 sal_Int32
& ri
= pActualIndices
[nActualDim
];
1099 for( ri
= nLower
,i
= 0 ; ri
<= nUpper
; ri
++,i
++ )
1103 if( nActualDim
< nMaxDimIndex
)
1105 aElementVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1106 nMaxDimIndex
, nActualDim
+ 1, pActualIndices
, pLowerBounds
, pUpperBounds
);
1110 SbxVariable
* pSource
= pArray
->Get32( pActualIndices
);
1111 aElementVal
= sbxToUnoValue( pSource
, aElemType
);
1116 // transfer to the sequence
1117 xArray
->set( aRetVal
, i
, aElementVal
);
1119 catch( const IllegalArgumentException
& )
1121 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1122 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1124 catch (const IndexOutOfBoundsException
&)
1126 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1132 // Map old interface
1133 Any
sbxToUnoValue( const SbxValue
* pVar
)
1135 return sbxToUnoValueImpl( pVar
);
1138 // function to find a global identifier in
1139 // the UnoScope and to wrap it for Sbx
1140 static bool implGetTypeByName( const OUString
& rName
, Type
& rRetType
)
1142 bool bSuccess
= false;
1144 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
1145 if( xTypeAccess
->hasByHierarchicalName( rName
) )
1147 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
1148 Reference
< XTypeDescription
> xTypeDesc
;
1151 if( xTypeDesc
.is() )
1153 rRetType
= Type( xTypeDesc
->getTypeClass(), xTypeDesc
->getName() );
1161 // converting of Sbx to Uno with known target class
1162 Any
sbxToUnoValue( const SbxValue
* pVar
, const Type
& rType
, Property
const * pUnoProperty
)
1166 // #94560 No conversion of empty/void for MAYBE_VOID properties
1167 if( pUnoProperty
&& pUnoProperty
->Attributes
& PropertyAttribute::MAYBEVOID
)
1169 if( pVar
->IsEmpty() )
1173 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
1174 if( eBaseType
== SbxOBJECT
)
1176 SbxBaseRef xObj
= pVar
->GetObject();
1177 if ( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
1179 return obj
->getValue();
1183 TypeClass eType
= rType
.getTypeClass();
1186 case TypeClass_INTERFACE
:
1187 case TypeClass_STRUCT
:
1188 case TypeClass_EXCEPTION
:
1190 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1193 if( pVar
->IsNull() && eType
== TypeClass_INTERFACE
)
1195 Reference
< XInterface
> xRef
;
1196 OUString aClassName
= xIdlTargetClass
->getName();
1197 Type
aClassType( xIdlTargetClass
->getTypeClass(), aClassName
);
1198 aRetVal
.setValue( &xRef
, aClassType
);
1202 // #112368 Special conversion for Decimal, Currency and Date
1203 if( eType
== TypeClass_STRUCT
)
1205 SbiInstance
* pInst
= GetSbData()->pInst
;
1206 if( pInst
&& pInst
->IsCompatibility() )
1208 if( rType
== cppu::UnoType
<oleautomation::Decimal
>::get())
1210 oleautomation::Decimal aDecimal
;
1211 pVar
->fillAutomationDecimal( aDecimal
);
1212 aRetVal
<<= aDecimal
;
1215 else if( rType
== cppu::UnoType
<oleautomation::Currency
>::get())
1217 // assumes per previous code that ole Currency is Int64
1218 aRetVal
<<= pVar
->GetInt64();
1221 else if( rType
== cppu::UnoType
<oleautomation::Date
>::get())
1223 oleautomation::Date aDate
;
1224 aDate
.Value
= pVar
->GetDate();
1231 SbxBaseRef pObj
= pVar
->GetObject();
1232 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1234 aRetVal
= obj
->getUnoAny();
1236 else if( auto structRef
= dynamic_cast<SbUnoStructRefObject
*>( pObj
.get() ) )
1238 aRetVal
= structRef
->getUnoAny();
1242 // null object -> null XInterface
1243 Reference
<XInterface
> xInt
;
1250 case TypeClass_TYPE
:
1252 if( eBaseType
== SbxOBJECT
)
1255 Reference
< XIdlClass
> xIdlClass
;
1257 SbxBaseRef pObj
= pVar
->GetObject();
1258 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1260 Any aUnoAny
= obj
->getUnoAny();
1261 aUnoAny
>>= xIdlClass
;
1264 if( xIdlClass
.is() )
1266 OUString aClassName
= xIdlClass
->getName();
1267 Type
aType( xIdlClass
->getTypeClass(), aClassName
);
1271 else if( eBaseType
== SbxSTRING
)
1273 OUString aTypeName
= pVar
->GetOUString();
1275 bool bSuccess
= implGetTypeByName( aTypeName
, aType
);
1285 case TypeClass_ENUM
:
1287 aRetVal
= int2enum( pVar
->GetLong(), rType
);
1291 case TypeClass_SEQUENCE
:
1293 SbxBaseRef xObj
= pVar
->GetObject();
1294 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
1296 short nDims
= pArray
->GetDims();
1298 // Normal case: One dimensional array
1299 sal_Int32 nLower
, nUpper
;
1300 if( nDims
== 1 && pArray
->GetDim32( 1, nLower
, nUpper
) )
1302 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1304 // create the instance of the required sequence
1305 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1306 xIdlTargetClass
->createObject( aRetVal
);
1307 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1308 xArray
->realloc( aRetVal
, nSeqSize
);
1311 OUString aClassName
= xIdlTargetClass
->getName();
1312 typelib_TypeDescription
* pSeqTD
= nullptr;
1313 typelib_typedescription_getByName( &pSeqTD
, aClassName
.pData
);
1314 OSL_ASSERT( pSeqTD
);
1315 Type
aElemType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1317 // convert all array member and register them
1320 for (sal_Int32 i
= 0 ; i
< nSeqSize
; ++i
, ++aIdx
[0])
1322 SbxVariableRef xVar
= pArray
->Get32(aIdx
);
1324 // Convert the value of Sbx to Uno
1325 Any aAnyValue
= sbxToUnoValue( xVar
.get(), aElemType
);
1329 // insert in the sequence
1330 xArray
->set( aRetVal
, i
, aAnyValue
);
1332 catch( const IllegalArgumentException
& )
1334 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1335 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1337 catch (const IndexOutOfBoundsException
&)
1339 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1343 // #i33795 Map also multi dimensional arrays to corresponding sequences
1344 else if( nDims
> 1 )
1347 typelib_TypeDescription
* pSeqTD
= nullptr;
1348 Type
aCurType( rType
);
1349 sal_Int32 nSeqLevel
= 0;
1353 OUString aTypeName
= aCurType
.getTypeName();
1354 typelib_typedescription_getByName( &pSeqTD
, aTypeName
.pData
);
1355 OSL_ASSERT( pSeqTD
);
1356 if( pSeqTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
)
1358 aCurType
= Type( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1363 aElemType
= aCurType
;
1369 if( nSeqLevel
== nDims
)
1371 std::unique_ptr
<sal_Int32
[]> pLowerBounds(new sal_Int32
[nDims
]);
1372 std::unique_ptr
<sal_Int32
[]> pUpperBounds(new sal_Int32
[nDims
]);
1373 std::unique_ptr
<sal_Int32
[]> pActualIndices(new sal_Int32
[nDims
]);
1374 for( short i
= 1 ; i
<= nDims
; i
++ )
1376 sal_Int32 lBound
, uBound
;
1377 pArray
->GetDim32( i
, lBound
, uBound
);
1380 pActualIndices
[j
] = pLowerBounds
[j
] = lBound
;
1381 pUpperBounds
[j
] = uBound
;
1384 aRetVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1385 nDims
- 1, 0, pActualIndices
.get(), pLowerBounds
.get(), pUpperBounds
.get() );
1393 // for Any use the class independent converting routine
1396 aRetVal
= sbxToUnoValueImpl( pVar
);
1400 case TypeClass_BOOLEAN
:
1402 aRetVal
<<= pVar
->GetBool();
1405 case TypeClass_CHAR
:
1407 aRetVal
<<= pVar
->GetChar();
1410 case TypeClass_STRING
: aRetVal
<<= pVar
->GetOUString(); break;
1411 case TypeClass_FLOAT
: aRetVal
<<= pVar
->GetSingle(); break;
1412 case TypeClass_DOUBLE
: aRetVal
<<= pVar
->GetDouble(); break;
1414 case TypeClass_BYTE
:
1416 sal_Int16 nVal
= pVar
->GetInteger();
1417 bool bOverflow
= false;
1423 else if( nVal
> 255 ) // 128..255 map to -128..-1
1429 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW
);
1431 sal_Int8 nByteVal
= static_cast<sal_Int8
>(nVal
);
1432 aRetVal
<<= nByteVal
;
1435 case TypeClass_SHORT
: aRetVal
<<= pVar
->GetInteger(); break;
1436 case TypeClass_LONG
: aRetVal
<<= pVar
->GetLong(); break;
1437 case TypeClass_HYPER
: aRetVal
<<= pVar
->GetInt64(); break;
1438 case TypeClass_UNSIGNED_SHORT
: aRetVal
<<= pVar
->GetUShort(); break;
1439 case TypeClass_UNSIGNED_LONG
: aRetVal
<<= pVar
->GetULong(); break;
1440 case TypeClass_UNSIGNED_HYPER
: aRetVal
<<= pVar
->GetUInt64(); break;
1447 static void processAutomationParams( SbxArray
* pParams
, Sequence
< Any
>& args
, sal_uInt32 nParamCount
)
1449 AutomationNamedArgsSbxArray
* pArgNamesArray
= dynamic_cast<AutomationNamedArgsSbxArray
*>( pParams
);
1451 args
.realloc( nParamCount
);
1452 Any
* pAnyArgs
= args
.getArray();
1453 bool bBlockConversionToSmallestType
= GetSbData()->pInst
->IsCompatibility();
1455 if( pArgNamesArray
)
1457 Sequence
< OUString
>& rNameSeq
= pArgNamesArray
->getNames();
1458 OUString
* pNames
= rNameSeq
.getArray();
1460 for( i
= 0 ; i
< nParamCount
; i
++ )
1462 sal_uInt16 iSbx
= static_cast<sal_uInt16
>(i
+1);
1464 aValAny
= sbxToUnoValueImpl( pParams
->Get( iSbx
),
1465 bBlockConversionToSmallestType
);
1467 OUString aParamName
= pNames
[iSbx
];
1468 if( !aParamName
.isEmpty() )
1470 oleautomation::NamedArgument aNamedArgument
;
1471 aNamedArgument
.Name
= aParamName
;
1472 aNamedArgument
.Value
= aValAny
;
1473 pAnyArgs
[i
] <<= aNamedArgument
;
1477 pAnyArgs
[i
] = aValAny
;
1483 for( i
= 0 ; i
< nParamCount
; i
++ )
1485 pAnyArgs
[i
] = sbxToUnoValueImpl( pParams
->Get( static_cast<sal_uInt16
>(i
+1) ),
1486 bBlockConversionToSmallestType
);
1491 enum class INVOKETYPE
1496 static Any
invokeAutomationMethod( const OUString
& Name
, Sequence
< Any
> const & args
, SbxArray
* pParams
, sal_uInt32 nParamCount
, Reference
< XInvocation
> const & rxInvocation
, INVOKETYPE invokeType
)
1498 Sequence
< sal_Int16
> OutParamIndex
;
1499 Sequence
< Any
> OutParam
;
1502 switch( invokeType
)
1504 case INVOKETYPE::Func
:
1505 aRetAny
= rxInvocation
->invoke( Name
, args
, OutParamIndex
, OutParam
);
1507 case INVOKETYPE::GetProp
:
1509 Reference
< XAutomationInvocation
> xAutoInv( rxInvocation
, UNO_QUERY
);
1510 aRetAny
= xAutoInv
->invokeGetProperty( Name
, args
, OutParamIndex
, OutParam
);
1514 assert(false); break;
1517 const sal_Int16
* pIndices
= OutParamIndex
.getConstArray();
1518 sal_uInt32 nLen
= OutParamIndex
.getLength();
1521 const Any
* pNewValues
= OutParam
.getConstArray();
1522 for( sal_uInt32 j
= 0 ; j
< nLen
; j
++ )
1524 sal_Int16 iTarget
= pIndices
[ j
];
1525 if( iTarget
>= static_cast<sal_Int16
>(nParamCount
) )
1527 unoToSbxValue( pParams
->Get( static_cast<sal_uInt16
>(j
+1) ), pNewValues
[ j
] );
1533 // Debugging help method to readout the imlemented interfaces of an object
1534 static OUString
Impl_GetInterfaceInfo( const Reference
< XInterface
>& x
, const Reference
< XIdlClass
>& xClass
, sal_uInt16 nRekLevel
)
1536 Type aIfaceType
= cppu::UnoType
<XInterface
>::get();
1537 static Reference
< XIdlClass
> xIfaceClass
= TypeToIdlClass( aIfaceType
);
1539 OUStringBuffer aRetStr
;
1540 for( sal_uInt16 i
= 0 ; i
< nRekLevel
; i
++ )
1541 aRetStr
.append( " " );
1542 aRetStr
.append( xClass
->getName() );
1543 OUString aClassName
= xClass
->getName();
1544 Type
aClassType( xClass
->getTypeClass(), aClassName
);
1546 // checking if the interface is really supported
1547 if( !x
->queryInterface( aClassType
).hasValue() )
1549 aRetStr
.append( " (ERROR: Not really supported!)\n" );
1551 // Are there super interfaces?
1554 aRetStr
.append( "\n" );
1556 // get the super interfaces
1557 Sequence
< Reference
< XIdlClass
> > aSuperClassSeq
= xClass
->getSuperclasses();
1558 const Reference
< XIdlClass
>* pClasses
= aSuperClassSeq
.getConstArray();
1559 sal_uInt32 nSuperIfaceCount
= aSuperClassSeq
.getLength();
1560 for( sal_uInt32 j
= 0 ; j
< nSuperIfaceCount
; j
++ )
1562 const Reference
< XIdlClass
>& rxIfaceClass
= pClasses
[j
];
1563 if( !rxIfaceClass
->equals( xIfaceClass
) )
1564 aRetStr
.append( Impl_GetInterfaceInfo( x
, rxIfaceClass
, nRekLevel
+ 1 ) );
1567 return aRetStr
.makeStringAndClear();
1570 static OUString
getDbgObjectNameImpl(SbUnoObject
& rUnoObj
)
1572 OUString aName
= rUnoObj
.GetClassName();
1573 if( aName
.isEmpty() )
1575 Any aToInspectObj
= rUnoObj
.getUnoAny();
1576 Reference
< XInterface
> xObj(aToInspectObj
, css::uno::UNO_QUERY
);
1579 Reference
< XServiceInfo
> xServiceInfo( xObj
, UNO_QUERY
);
1580 if( xServiceInfo
.is() )
1581 aName
= xServiceInfo
->getImplementationName();
1587 static OUString
getDbgObjectName(SbUnoObject
& rUnoObj
)
1589 OUString aName
= getDbgObjectNameImpl(rUnoObj
);
1590 if( aName
.isEmpty() )
1593 OUStringBuffer aRet
;
1594 if( aName
.getLength() > 20 )
1596 aRet
.append( "\n" );
1598 aRet
.append( "\"" );
1599 aRet
.append( aName
);
1600 aRet
.append( "\":" );
1601 return aRet
.makeStringAndClear();
1604 OUString
getBasicObjectTypeName( SbxObject
* pObj
)
1608 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
1610 return getDbgObjectNameImpl(*pUnoObj
);
1612 else if (SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>(pObj
))
1614 return pUnoStructObj
->GetClassName();
1622 bool matchesBasicTypeName(
1623 css::uno::Reference
<css::reflection::XIdlClass
> const & unoType
, OUString
const & basicTypeName
)
1625 if (unoType
->getName().endsWithIgnoreAsciiCase(basicTypeName
)) {
1628 auto const sups
= unoType
->getSuperclasses();
1630 sups
.begin(), sups
.end(),
1631 [&basicTypeName
](auto const & t
) { return matchesBasicTypeName(t
, basicTypeName
); });
1636 bool checkUnoObjectType(SbUnoObject
& rUnoObj
, const OUString
& rClass
)
1638 Any aToInspectObj
= rUnoObj
.getUnoAny();
1640 // Return true for XInvocation based objects as interface type names don't count then
1641 Reference
< XInvocation
> xInvocation( aToInspectObj
, UNO_QUERY
);
1642 if( xInvocation
.is() )
1646 bool bResult
= false;
1647 Reference
< XTypeProvider
> xTypeProvider( aToInspectObj
, UNO_QUERY
);
1648 if( xTypeProvider
.is() )
1650 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1651 have a leading 'X', in Basic we want to be able to do something
1652 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1653 add a leading 'X' to the class name and a leading dot to the entire
1654 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1655 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1656 'ooo.vba.msforms.XLabel'.
1658 OUString aClassName
;
1659 if ( SbiRuntime::isVBAEnabled() )
1662 sal_Int32 nClassNameDot
= rClass
.lastIndexOf( '.' );
1663 if( nClassNameDot
>= 0 )
1665 aClassName
+= rClass
.copy( 0, nClassNameDot
+ 1 ) + "X" + rClass
.copy( nClassNameDot
+ 1 );
1669 aClassName
+= "X" + rClass
;
1672 else // assume extended type declaration support for basic ( can't get here
1674 aClassName
= rClass
;
1676 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1677 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1678 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1679 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1681 const Type
& rType
= pTypeArray
[j
];
1683 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1686 OSL_FAIL("failed to get XIdlClass for type");
1689 OUString aInterfaceName
= xClass
->getName();
1690 if ( aInterfaceName
== "com.sun.star.bridge.oleautomation.XAutomationObject" )
1692 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1694 Reference
< XInvocation
> xInv( aToInspectObj
, UNO_QUERY
);
1698 xInv
->getValue( "$GetTypeName" ) >>= sTypeName
;
1699 if ( sTypeName
.isEmpty() || sTypeName
== "IDispatch" )
1701 // can't check type, leave it pass
1706 bResult
= sTypeName
== rClass
;
1709 break; // finished checking automation object
1712 if ( matchesBasicTypeName(xClass
, aClassName
) )
1722 // Debugging help method to readout the imlemented interfaces of an object
1723 static OUString
Impl_GetSupportedInterfaces(SbUnoObject
& rUnoObj
)
1725 Any aToInspectObj
= rUnoObj
.getUnoAny();
1727 // allow only TypeClass interface
1728 OUStringBuffer aRet
;
1729 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aToInspectObj
);
1732 aRet
.append( ID_DBG_SUPPORTEDINTERFACES
);
1733 aRet
.append( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1737 Reference
< XTypeProvider
> xTypeProvider( *x
, UNO_QUERY
);
1739 aRet
.append( "Supported interfaces by object " );
1740 aRet
.append(getDbgObjectName(rUnoObj
));
1741 aRet
.append( "\n" );
1742 if( xTypeProvider
.is() )
1744 // get the interfaces of the implementation
1745 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1746 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1747 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1748 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1750 const Type
& rType
= pTypeArray
[j
];
1752 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1755 aRet
.append( Impl_GetInterfaceInfo( *x
, xClass
, 1 ) );
1759 typelib_TypeDescription
* pTD
= nullptr;
1760 rType
.getDescription( &pTD
);
1762 aRet
.append( "*** ERROR: No IdlClass for type \"" );
1763 aRet
.append( pTD
->pTypeName
);
1764 aRet
.append( "\"\n*** Please check type library\n" );
1769 return aRet
.makeStringAndClear();
1773 // Debugging help method SbxDataType -> String
1774 static OUString
Dbg_SbxDataType2String( SbxDataType eType
)
1776 OUStringBuffer aRet
;
1779 case SbxEMPTY
: aRet
.append("SbxEMPTY"); break;
1780 case SbxNULL
: aRet
.append("SbxNULL"); break;
1781 case SbxINTEGER
: aRet
.append("SbxINTEGER"); break;
1782 case SbxLONG
: aRet
.append("SbxLONG"); break;
1783 case SbxSINGLE
: aRet
.append("SbxSINGLE"); break;
1784 case SbxDOUBLE
: aRet
.append("SbxDOUBLE"); break;
1785 case SbxCURRENCY
: aRet
.append("SbxCURRENCY"); break;
1786 case SbxDECIMAL
: aRet
.append("SbxDECIMAL"); break;
1787 case SbxDATE
: aRet
.append("SbxDATE"); break;
1788 case SbxSTRING
: aRet
.append("SbxSTRING"); break;
1789 case SbxOBJECT
: aRet
.append("SbxOBJECT"); break;
1790 case SbxERROR
: aRet
.append("SbxERROR"); break;
1791 case SbxBOOL
: aRet
.append("SbxBOOL"); break;
1792 case SbxVARIANT
: aRet
.append("SbxVARIANT"); break;
1793 case SbxDATAOBJECT
: aRet
.append("SbxDATAOBJECT"); break;
1794 case SbxCHAR
: aRet
.append("SbxCHAR"); break;
1795 case SbxBYTE
: aRet
.append("SbxBYTE"); break;
1796 case SbxUSHORT
: aRet
.append("SbxUSHORT"); break;
1797 case SbxULONG
: aRet
.append("SbxULONG"); break;
1798 case SbxSALINT64
: aRet
.append("SbxINT64"); break;
1799 case SbxSALUINT64
: aRet
.append("SbxUINT64"); break;
1800 case SbxINT
: aRet
.append("SbxINT"); break;
1801 case SbxUINT
: aRet
.append("SbxUINT"); break;
1802 case SbxVOID
: aRet
.append("SbxVOID"); break;
1803 case SbxHRESULT
: aRet
.append("SbxHRESULT"); break;
1804 case SbxPOINTER
: aRet
.append("SbxPOINTER"); break;
1805 case SbxDIMARRAY
: aRet
.append("SbxDIMARRAY"); break;
1806 case SbxCARRAY
: aRet
.append("SbxCARRAY"); break;
1807 case SbxUSERDEF
: aRet
.append("SbxUSERDEF"); break;
1808 case SbxLPSTR
: aRet
.append("SbxLPSTR"); break;
1809 case SbxLPWSTR
: aRet
.append("SbxLPWSTR"); break;
1810 case SbxCoreSTRING
: aRet
.append("SbxCoreSTRING"); break;
1811 case SbxOBJECT
| SbxARRAY
: aRet
.append("SbxARRAY"); break;
1812 default: aRet
.append("Unknown Sbx-Type!");break;
1814 return aRet
.makeStringAndClear();
1817 // Debugging help method to display the properties of a SbUnoObjects
1818 static OUString
Impl_DumpProperties(SbUnoObject
& rUnoObj
)
1820 OUStringBuffer aRet
;
1821 aRet
.append("Properties of object ");
1822 aRet
.append(getDbgObjectName(rUnoObj
));
1824 // analyse the Uno-Infos to recognise the arrays
1825 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1828 Reference
< XInvocation
> xInvok
= rUnoObj
.getInvocation();
1830 xAccess
= xInvok
->getIntrospection();
1834 aRet
.append( "\nUnknown, no introspection available\n" );
1835 return aRet
.makeStringAndClear();
1838 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
1839 sal_uInt32 nUnoPropCount
= props
.getLength();
1840 const Property
* pUnoProps
= props
.getConstArray();
1842 SbxArray
* pProps
= rUnoObj
.GetProperties();
1843 sal_uInt16 nPropCount
= pProps
->Count();
1844 sal_uInt16 nPropsPerLine
= 1 + nPropCount
/ 30;
1845 for( sal_uInt16 i
= 0; i
< nPropCount
; i
++ )
1847 SbxVariable
* pVar
= pProps
->Get( i
);
1850 OUStringBuffer aPropStr
;
1851 if( (i
% nPropsPerLine
) == 0 )
1852 aPropStr
.append( "\n" );
1854 // output the type and name
1855 // Is it in Uno a sequence?
1856 SbxDataType eType
= pVar
->GetFullType();
1858 bool bMaybeVoid
= false;
1859 if( i
< nUnoPropCount
)
1861 const Property
& rProp
= pUnoProps
[ i
];
1863 // For MAYBEVOID freshly convert the type from Uno,
1864 // so not just SbxEMPTY is returned.
1865 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
1867 eType
= unoToSbxType( rProp
.Type
.getTypeClass() );
1870 if( eType
== SbxOBJECT
)
1872 Type aType
= rProp
.Type
;
1873 if( aType
.getTypeClass() == TypeClass_SEQUENCE
)
1874 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1877 aPropStr
.append( Dbg_SbxDataType2String( eType
) );
1879 aPropStr
.append( "/void" );
1880 aPropStr
.append( " " );
1881 aPropStr
.append( pVar
->GetName() );
1883 if( i
== nPropCount
- 1 )
1884 aPropStr
.append( "\n" );
1886 aPropStr
.append( "; " );
1888 aRet
.append( aPropStr
.makeStringAndClear() );
1891 return aRet
.makeStringAndClear();
1894 // Debugging help method to display the methods of an SbUnoObjects
1895 static OUString
Impl_DumpMethods(SbUnoObject
& rUnoObj
)
1897 OUStringBuffer aRet
;
1898 aRet
.append("Methods of object ");
1899 aRet
.append(getDbgObjectName(rUnoObj
));
1901 // XIntrospectionAccess, so that the types of the parameter could be outputted
1902 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1905 Reference
< XInvocation
> xInvok
= rUnoObj
.getInvocation();
1907 xAccess
= xInvok
->getIntrospection();
1911 aRet
.append( "\nUnknown, no introspection available\n" );
1912 return aRet
.makeStringAndClear();
1914 Sequence
< Reference
< XIdlMethod
> > methods
= xAccess
->getMethods
1915 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
1916 const Reference
< XIdlMethod
>* pUnoMethods
= methods
.getConstArray();
1918 SbxArray
* pMethods
= rUnoObj
.GetMethods();
1919 sal_uInt16 nMethodCount
= pMethods
->Count();
1922 aRet
.append( "\nNo methods found\n" );
1923 return aRet
.makeStringAndClear();
1925 sal_uInt16 nPropsPerLine
= 1 + nMethodCount
/ 30;
1926 for( sal_uInt16 i
= 0; i
< nMethodCount
; i
++ )
1928 SbxVariable
* pVar
= pMethods
->Get( i
);
1931 if( (i
% nPropsPerLine
) == 0 )
1932 aRet
.append( "\n" );
1934 // address the method
1935 const Reference
< XIdlMethod
>& rxMethod
= pUnoMethods
[i
];
1937 // Is it in Uno a sequence?
1938 SbxDataType eType
= pVar
->GetFullType();
1939 if( eType
== SbxOBJECT
)
1941 Reference
< XIdlClass
> xClass
= rxMethod
->getReturnType();
1942 if( xClass
.is() && xClass
->getTypeClass() == TypeClass_SEQUENCE
)
1943 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1945 // output the name and the type
1946 aRet
.append( Dbg_SbxDataType2String( eType
) );
1948 aRet
.append ( pVar
->GetName() );
1949 aRet
.append( " ( " );
1951 // the get-method mustn't have a parameter
1952 Sequence
< Reference
< XIdlClass
> > aParamsSeq
= rxMethod
->getParameterTypes();
1953 sal_uInt32 nParamCount
= aParamsSeq
.getLength();
1954 const Reference
< XIdlClass
>* pParams
= aParamsSeq
.getConstArray();
1956 if( nParamCount
> 0 )
1958 for( sal_uInt32 j
= 0; j
< nParamCount
; j
++ )
1960 aRet
.append ( Dbg_SbxDataType2String( unoToSbxType( pParams
[ j
] ) ) );
1961 if( j
< nParamCount
- 1 )
1962 aRet
.append( ", " );
1966 aRet
.append( "void" );
1968 aRet
.append( " ) " );
1970 if( i
== nMethodCount
- 1 )
1971 aRet
.append( "\n" );
1973 aRet
.append( "; " );
1976 return aRet
.makeStringAndClear();
1980 // Implementation SbUnoObject
1981 void SbUnoObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1983 if( bNeedIntrospection
)
1986 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
1989 SbxVariable
* pVar
= pHint
->GetVar();
1990 SbxArray
* pParams
= pVar
->GetParameters();
1991 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
1992 SbUnoMethod
* pMeth
= dynamic_cast<SbUnoMethod
*>( pVar
);
1995 bool bInvocation
= pProp
->isInvocationBased();
1996 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
1999 sal_Int32 nId
= pProp
->nId
;
2002 // Id == -1: Display implemented interfaces according the ClassProvider
2003 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2005 OUString aRetStr
= Impl_GetSupportedInterfaces(*this);
2006 pVar
->PutString( aRetStr
);
2008 // Id == -2: output properties
2009 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
2011 // now all properties must be created
2013 OUString aRetStr
= Impl_DumpProperties(*this);
2014 pVar
->PutString( aRetStr
);
2016 // Id == -3: output the methods
2017 else if( nId
== -3 ) // Property ID_DBG_METHODS
2019 // now all properties must be created
2021 OUString aRetStr
= Impl_DumpMethods(*this);
2022 pVar
->PutString( aRetStr
);
2027 if( !bInvocation
&& mxUnoAccess
.is() )
2031 if ( maStructInfo
.get() )
2033 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2034 if ( aMember
.isEmpty() )
2036 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2040 if ( pProp
->isUnoStruct() )
2042 SbUnoStructRefObject
* pSbUnoObject
= new SbUnoStructRefObject( pProp
->GetName(), aMember
);
2043 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
2044 pVar
->PutObject( xWrapper
.get() );
2048 Any aRetAny
= aMember
.getValue();
2049 // take over the value from Uno to Sbx
2050 unoToSbxValue( pVar
, aRetAny
);
2056 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2057 Any aRetAny
= xPropSet
->getPropertyValue( pProp
->GetName() );
2058 // The use of getPropertyValue (instead of using the index) is
2059 // suboptimal, but the refactoring to XInvocation is already pending
2060 // Otherwise it is possible to use FastPropertySet
2062 // take over the value from Uno to Sbx
2063 unoToSbxValue( pVar
, aRetAny
);
2065 catch( const Exception
& )
2067 implHandleAnyException( ::cppu::getCaughtException() );
2070 else if( bInvocation
&& mxInvocation
.is() )
2074 sal_uInt32 nParamCount
= pParams
? (static_cast<sal_uInt32
>(pParams
->Count()) - 1) : 0;
2075 bool bCanBeConsideredAMethod
= mxInvocation
->hasMethod( pProp
->GetName() );
2077 if ( bCanBeConsideredAMethod
&& nParamCount
)
2079 // Automation properties have methods, so... we need to invoke this through
2082 processAutomationParams( pParams
, args
, nParamCount
);
2083 aRetAny
= invokeAutomationMethod( pProp
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::GetProp
);
2086 aRetAny
= mxInvocation
->getValue( pProp
->GetName() );
2087 // take over the value from Uno to Sbx
2088 unoToSbxValue( pVar
, aRetAny
);
2089 if( pParams
&& bCanBeConsideredAMethod
)
2090 pVar
->SetParameters( nullptr );
2093 catch( const Exception
& )
2095 implHandleAnyException( ::cppu::getCaughtException() );
2099 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
2101 if( !bInvocation
&& mxUnoAccess
.is() )
2103 if( pProp
->aUnoProp
.Attributes
& PropertyAttribute::READONLY
)
2105 StarBASIC::Error( ERRCODE_BASIC_PROP_READONLY
);
2108 if ( maStructInfo
.get() )
2110 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2111 if ( aMember
.isEmpty() )
2113 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2117 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2118 aMember
.setValue( aAnyValue
);
2122 // take over the value from Uno to Sbx
2123 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2127 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2128 xPropSet
->setPropertyValue( pProp
->GetName(), aAnyValue
);
2129 // The use of getPropertyValue (instead of using the index) is
2130 // suboptimal, but the refactoring to XInvocation is already pending
2131 // Otherwise it is possible to use FastPropertySet
2133 catch( const Exception
& )
2135 implHandleAnyException( ::cppu::getCaughtException() );
2138 else if( bInvocation
&& mxInvocation
.is() )
2140 // take over the value from Uno to Sbx
2141 Any aAnyValue
= sbxToUnoValueImpl( pVar
);
2145 mxInvocation
->setValue( pProp
->GetName(), aAnyValue
);
2147 catch( const Exception
& )
2149 implHandleAnyException( ::cppu::getCaughtException() );
2156 bool bInvocation
= pMeth
->isInvocationBased();
2157 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
2159 // number of Parameter -1 because of Param0 == this
2160 sal_uInt32 nParamCount
= pParams
? (static_cast<sal_uInt32
>(pParams
->Count()) - 1) : 0;
2162 bool bOutParams
= false;
2164 if( !bInvocation
&& mxUnoAccess
.is() )
2167 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2168 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2169 sal_uInt32 nUnoParamCount
= rInfoSeq
.getLength();
2170 sal_uInt32 nAllocParamCount
= nParamCount
;
2172 // ignore surplus parameter; alternative: throw an error
2173 if( nParamCount
> nUnoParamCount
)
2175 nParamCount
= nUnoParamCount
;
2176 nAllocParamCount
= nParamCount
;
2178 else if( nParamCount
< nUnoParamCount
)
2180 SbiInstance
* pInst
= GetSbData()->pInst
;
2181 if( pInst
&& pInst
->IsCompatibility() )
2184 bool bError
= false;
2185 for( sal_uInt32 i
= nParamCount
; i
< nUnoParamCount
; i
++ )
2187 const ParamInfo
& rInfo
= pParamInfos
[i
];
2188 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2189 if( rxClass
->getTypeClass() != TypeClass_ANY
)
2192 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
2196 nAllocParamCount
= nUnoParamCount
;
2200 if( nAllocParamCount
> 0 )
2202 args
.realloc( nAllocParamCount
);
2203 Any
* pAnyArgs
= args
.getArray();
2204 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2206 const ParamInfo
& rInfo
= pParamInfos
[i
];
2207 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2209 css::uno::Type
aType( rxClass
->getTypeClass(), rxClass
->getName() );
2211 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2212 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get( static_cast<sal_uInt16
>(i
+1) ), aType
);
2214 // If it is not certain check whether the out-parameter are available.
2217 ParamMode aParamMode
= rInfo
.aMode
;
2218 if( aParamMode
!= ParamMode_IN
)
2224 else if( bInvocation
&& pParams
&& mxInvocation
.is() )
2226 processAutomationParams( pParams
, args
, nParamCount
);
2230 GetSbData()->bBlockCompilerError
= true; // #106433 Block compiler errors for API calls
2233 if( !bInvocation
&& mxUnoAccess
.is() )
2235 Any aRetAny
= pMeth
->m_xUnoMethod
->invoke( getUnoAny(), args
);
2237 // take over the value from Uno to Sbx
2238 unoToSbxValue( pVar
, aRetAny
);
2240 // Did we to copy back the Out-Parameter?
2243 const Any
* pAnyArgs
= args
.getConstArray();
2246 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2247 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2250 for( j
= 0 ; j
< nParamCount
; j
++ )
2252 const ParamInfo
& rInfo
= pParamInfos
[j
];
2253 ParamMode aParamMode
= rInfo
.aMode
;
2254 if( aParamMode
!= ParamMode_IN
)
2255 unoToSbxValue( pParams
->Get( static_cast<sal_uInt16
>(j
+1) ), pAnyArgs
[ j
] );
2259 else if( bInvocation
&& mxInvocation
.is() )
2261 Any aRetAny
= invokeAutomationMethod( pMeth
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::Func
);
2262 unoToSbxValue( pVar
, aRetAny
);
2265 // remove parameter here, because this was not done anymore in unoToSbxValue()
2268 pVar
->SetParameters( nullptr );
2270 catch( const Exception
& )
2272 implHandleAnyException( ::cppu::getCaughtException() );
2274 GetSbData()->bBlockCompilerError
= false; // #106433 Unblock compiler errors
2278 SbxObject::Notify( rBC
, rHint
);
2283 SbUnoObject::SbUnoObject( const OUString
& aName_
, const Any
& aUnoObj_
)
2284 : SbxObject( aName_
)
2285 , bNeedIntrospection( true )
2286 , bNativeCOMObject( false )
2288 // beat out again the default properties of Sbx
2289 Remove( "Name", SbxClassType::DontCare
);
2290 Remove( "Parent", SbxClassType::DontCare
);
2292 // check the type of the objects
2293 TypeClass eType
= aUnoObj_
.getValueType().getTypeClass();
2294 Reference
< XInterface
> x
;
2295 if( eType
== TypeClass_INTERFACE
)
2297 // get the interface from the Any
2303 Reference
< XTypeProvider
> xTypeProvider
;
2304 // Did the object have an invocation itself?
2305 mxInvocation
.set( x
, UNO_QUERY
);
2307 xTypeProvider
.set( x
, UNO_QUERY
);
2309 if( mxInvocation
.is() )
2312 // get the ExactName
2313 mxExactNameInvocation
.set( mxInvocation
, UNO_QUERY
);
2315 // The remainder refers only to the introspection
2316 if( !xTypeProvider
.is() )
2318 bNeedIntrospection
= false;
2322 // Ignore introspection based members for COM objects to avoid
2323 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2324 Reference
< oleautomation::XAutomationObject
> xAutomationObject( aUnoObj_
, UNO_QUERY
);
2325 if( xAutomationObject
.is() )
2326 bNativeCOMObject
= true;
2329 maTmpUnoObj
= aUnoObj_
;
2332 //*** Define the name ***
2333 bool bFatalError
= true;
2335 // Is it an interface or a struct?
2336 bool bSetClassName
= false;
2337 OUString aClassName_
;
2338 if( eType
== TypeClass_STRUCT
|| eType
== TypeClass_EXCEPTION
)
2341 bFatalError
= false;
2343 // insert the real name of the class
2344 if( aName_
.isEmpty() )
2346 aClassName_
= aUnoObj_
.getValueType().getTypeName();
2347 bSetClassName
= true;
2349 StructRefInfo
aThisStruct( maTmpUnoObj
, maTmpUnoObj
.getValueType(), 0 );
2350 maStructInfo
.reset( new SbUnoStructRefObject( GetName(), aThisStruct
) );
2352 else if( eType
== TypeClass_INTERFACE
)
2354 // Interface works always through the type in the Any
2355 bFatalError
= false;
2358 SetClassName( aClassName_
);
2360 // Neither interface nor Struct -> FatalError
2363 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION
);
2367 // pass the introspection primal on demand
2370 SbUnoObject::~SbUnoObject()
2375 // pass the introspection on Demand
2376 void SbUnoObject::doIntrospection()
2378 if( !bNeedIntrospection
)
2381 Reference
<XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2387 // get the introspection service
2388 Reference
<XIntrospection
> xIntrospection
;
2392 xIntrospection
= theIntrospection::get(xContext
);
2394 catch ( const css::uno::DeploymentException
& )
2398 if (!xIntrospection
.is())
2401 bNeedIntrospection
= false;
2403 // pass the introspection
2406 mxUnoAccess
= xIntrospection
->inspect( maTmpUnoObj
);
2408 catch( const RuntimeException
& e
)
2410 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2413 if( !mxUnoAccess
.is() )
2415 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2419 // get MaterialHolder from access
2420 mxMaterialHolder
.set( mxUnoAccess
, UNO_QUERY
);
2422 // get ExactName from access
2423 mxExactName
.set( mxUnoAccess
, UNO_QUERY
);
2427 // Start of a list of all SbUnoMethod-Instances
2428 static SbUnoMethod
* pFirst
= nullptr;
2430 void clearUnoMethodsForBasic( StarBASIC
const * pBasic
)
2432 SbUnoMethod
* pMeth
= pFirst
;
2435 SbxObject
* pObject
= pMeth
->GetParent();
2438 StarBASIC
* pModBasic
= dynamic_cast< StarBASIC
* >( pObject
->GetParent() );
2439 if ( pModBasic
== pBasic
)
2441 // for now the solution is to remove the method from the list and to clear it,
2442 // but in case the element should be correctly transferred to another StarBASIC,
2443 // we should either set module parent to NULL without clearing it, or even
2444 // set the new StarBASIC as the parent of the module
2445 // pObject->SetParent( NULL );
2447 if( pMeth
== pFirst
)
2448 pFirst
= pMeth
->pNext
;
2449 else if( pMeth
->pPrev
)
2450 pMeth
->pPrev
->pNext
= pMeth
->pNext
;
2452 pMeth
->pNext
->pPrev
= pMeth
->pPrev
;
2454 pMeth
->pPrev
= nullptr;
2455 pMeth
->pNext
= nullptr;
2457 pMeth
->SbxValue::Clear();
2458 pObject
->SbxValue::Clear();
2460 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2464 pMeth
= pMeth
->pNext
;
2467 pMeth
= pMeth
->pNext
;
2471 void clearUnoMethods()
2473 SbUnoMethod
* pMeth
= pFirst
;
2476 pMeth
->SbxValue::Clear();
2477 pMeth
= pMeth
->pNext
;
2482 SbUnoMethod::SbUnoMethod
2484 const OUString
& aName_
,
2485 SbxDataType eSbxType
,
2486 Reference
< XIdlMethod
> const & xUnoMethod_
,
2489 : SbxMethod( aName_
, eSbxType
)
2490 , mbInvocation( bInvocation
)
2492 m_xUnoMethod
= xUnoMethod_
;
2493 pParamInfoSeq
= nullptr;
2495 // enregister the method in a list
2500 pNext
->pPrev
= this;
2503 SbUnoMethod::~SbUnoMethod()
2505 pParamInfoSeq
.reset();
2507 if( this == pFirst
)
2510 pPrev
->pNext
= pNext
;
2512 pNext
->pPrev
= pPrev
;
2515 SbxInfo
* SbUnoMethod::GetInfo()
2517 if( !pInfo
.is() && m_xUnoMethod
.is() )
2519 SbiInstance
* pInst
= GetSbData()->pInst
;
2520 if( pInst
&& pInst
->IsCompatibility() )
2522 pInfo
= new SbxInfo();
2524 const Sequence
<ParamInfo
>& rInfoSeq
= getParamInfos();
2525 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2526 sal_uInt32 nParamCount
= rInfoSeq
.getLength();
2528 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2530 const ParamInfo
& rInfo
= pParamInfos
[i
];
2531 OUString aParamName
= rInfo
.aName
;
2533 pInfo
->AddParam( aParamName
, SbxVARIANT
, SbxFlagBits::Read
);
2540 const Sequence
<ParamInfo
>& SbUnoMethod::getParamInfos()
2544 Sequence
<ParamInfo
> aTmp
;
2545 if (m_xUnoMethod
.is())
2546 aTmp
= m_xUnoMethod
->getParameterInfos();
2547 pParamInfoSeq
.reset( new Sequence
<ParamInfo
>(aTmp
) );
2549 return *pParamInfoSeq
;
2552 SbUnoProperty::SbUnoProperty
2554 const OUString
& aName_
,
2555 SbxDataType eSbxType
,
2556 SbxDataType eRealSbxType
,
2557 const Property
& aUnoProp_
,
2562 : SbxProperty( aName_
, eSbxType
)
2563 , aUnoProp( aUnoProp_
)
2565 , mbInvocation( bInvocation
)
2566 , mRealType( eRealSbxType
)
2567 , mbUnoStruct( bUnoStruct
)
2569 // as needed establish a dummy array so that SbiRuntime::CheckArray() works
2570 static SbxArrayRef xDummyArray
= new SbxArray( SbxVARIANT
);
2571 if( eSbxType
& SbxARRAY
)
2572 PutObject( xDummyArray
.get() );
2575 SbUnoProperty::~SbUnoProperty()
2579 SbxVariable
* SbUnoObject::Find( const OUString
& rName
, SbxClassType t
)
2581 static Reference
< XIdlMethod
> xDummyMethod
;
2582 static Property aDummyProp
;
2584 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
2586 if( bNeedIntrospection
)
2589 // New 1999-03-04: Create properties on demand. Therefore search now via
2590 // IntrospectionAccess if a property or a method of the required name exist
2593 OUString
aUName( rName
);
2594 if( mxUnoAccess
.is() && !bNativeCOMObject
)
2596 if( mxExactName
.is() )
2598 OUString aUExactName
= mxExactName
->getExactName( aUName
);
2599 if( !aUExactName
.isEmpty() )
2601 aUName
= aUExactName
;
2604 if( mxUnoAccess
->hasProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
) )
2606 const Property
& rProp
= mxUnoAccess
->
2607 getProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2609 // If the property could be void the type had to be set to Variant
2610 SbxDataType eSbxType
;
2611 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2612 eSbxType
= SbxVARIANT
;
2614 eSbxType
= unoToSbxType( rProp
.Type
.getTypeClass() );
2616 SbxDataType eRealSbxType
= ( ( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( rProp
.Type
.getTypeClass() ) : eSbxType
);
2617 // create the property and superimpose it
2618 auto pProp
= tools::make_ref
<SbUnoProperty
>( rProp
.Name
, eSbxType
, eRealSbxType
, rProp
, 0, false, ( rProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2619 QuickInsert( pProp
.get() );
2622 else if( mxUnoAccess
->hasMethod( aUName
,
2623 MethodConcept::ALL
- MethodConcept::DANGEROUS
) )
2625 // address the method
2626 const Reference
< XIdlMethod
>& rxMethod
= mxUnoAccess
->
2627 getMethod( aUName
, MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2629 // create SbUnoMethod and superimpose it
2630 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( rxMethod
->getName(),
2631 unoToSbxType( rxMethod
->getReturnType() ), rxMethod
, false );
2632 QuickInsert( xMethRef
.get() );
2633 pRes
= xMethRef
.get();
2636 // If nothing was found check via XNameAccess
2641 Reference
< XNameAccess
> xNameAccess( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2643 if( xNameAccess
.is() && xNameAccess
->hasByName( rName
) )
2645 Any aAny
= xNameAccess
->getByName( rName
);
2647 // ATTENTION: Because of XNameAccess, the variable generated here
2648 // may not be included as a fixed property in the object and therefore
2649 // won't be stored anywhere.
2650 // If this leads to problems, it has to be created
2651 // synthetically or a class SbUnoNameAccessProperty,
2652 // which checks the existence on access and which
2653 // is disposed if the name is not found anymore.
2654 pRes
= new SbxVariable( SbxVARIANT
);
2655 unoToSbxValue( pRes
, aAny
);
2658 catch( const NoSuchElementException
& e
)
2660 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2662 catch( const Exception
& )
2664 // Establish so that the exception error will not be overwritten
2666 pRes
= new SbxVariable( SbxVARIANT
);
2668 implHandleAnyException( ::cppu::getCaughtException() );
2672 if( !pRes
&& mxInvocation
.is() )
2674 if( mxExactNameInvocation
.is() )
2676 OUString aUExactName
= mxExactNameInvocation
->getExactName( aUName
);
2677 if( !aUExactName
.isEmpty() )
2679 aUName
= aUExactName
;
2685 if( mxInvocation
->hasProperty( aUName
) )
2687 // create a property and superimpose it
2688 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( aUName
, SbxVARIANT
, SbxVARIANT
, aDummyProp
, 0, true, false );
2689 QuickInsert( xVarRef
.get() );
2690 pRes
= xVarRef
.get();
2692 else if( mxInvocation
->hasMethod( aUName
) )
2694 // create SbUnoMethode and superimpose it
2695 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2696 QuickInsert( xMethRef
.get() );
2697 pRes
= xMethRef
.get();
2701 Reference
< XDirectInvocation
> xDirectInvoke( mxInvocation
, UNO_QUERY
);
2702 if ( xDirectInvoke
.is() && xDirectInvoke
->hasMember( aUName
) )
2704 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2705 QuickInsert( xMethRef
.get() );
2706 pRes
= xMethRef
.get();
2711 catch( const RuntimeException
& e
)
2713 // Establish so that the exception error will not be overwritten
2715 pRes
= new SbxVariable( SbxVARIANT
);
2717 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2722 // At the very end checking if the Dbg_-Properties are meant
2726 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
2727 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
2728 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
2731 implCreateDbgProperties();
2733 // Now they have to be found regular
2734 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
2741 // help method to create the dbg_-Properties
2742 void SbUnoObject::implCreateDbgProperties()
2746 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2747 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_SUPPORTEDINTERFACES
), SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
2748 QuickInsert( xVarRef
.get() );
2750 // Id == -2: output the properties
2751 xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_PROPERTIES
), SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
2752 QuickInsert( xVarRef
.get() );
2754 // Id == -3: output the Methods
2755 xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_METHODS
), SbxSTRING
, SbxSTRING
, aProp
, -3, false, false );
2756 QuickInsert( xVarRef
.get() );
2759 void SbUnoObject::implCreateAll()
2761 // throw away all existing methods and properties
2762 pMethods
= tools::make_ref
<SbxArray
>();
2763 pProps
= tools::make_ref
<SbxArray
>();
2765 if( bNeedIntrospection
) doIntrospection();
2767 // get introspection
2768 Reference
< XIntrospectionAccess
> xAccess
= mxUnoAccess
;
2769 if( !xAccess
.is() || bNativeCOMObject
)
2771 if( mxInvocation
.is() )
2772 xAccess
= mxInvocation
->getIntrospection();
2773 else if( bNativeCOMObject
)
2779 // Establish properties
2780 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2781 sal_uInt32 nPropCount
= props
.getLength();
2782 const Property
* pProps_
= props
.getConstArray();
2785 for( i
= 0 ; i
< nPropCount
; i
++ )
2787 const Property
& rProp
= pProps_
[ i
];
2789 // If the property could be void the type had to be set to Variant
2790 SbxDataType eSbxType
;
2791 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2792 eSbxType
= SbxVARIANT
;
2794 eSbxType
= unoToSbxType( rProp
.Type
.getTypeClass() );
2796 SbxDataType eRealSbxType
= ( ( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( rProp
.Type
.getTypeClass() ) : eSbxType
);
2797 // Create property and superimpose it
2798 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( rProp
.Name
, eSbxType
, eRealSbxType
, rProp
, i
, false, ( rProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2799 QuickInsert( xVarRef
.get() );
2802 // Create Dbg_-Properties
2803 implCreateDbgProperties();
2806 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods
2807 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2808 sal_uInt32 nMethCount
= aMethodSeq
.getLength();
2809 const Reference
< XIdlMethod
>* pMethods_
= aMethodSeq
.getConstArray();
2810 for( i
= 0 ; i
< nMethCount
; i
++ )
2813 const Reference
< XIdlMethod
>& rxMethod
= pMethods_
[i
];
2815 // Create SbUnoMethod and superimpose it
2816 auto xMethRef
= tools::make_ref
<SbUnoMethod
>
2817 ( rxMethod
->getName(), unoToSbxType( rxMethod
->getReturnType() ), rxMethod
, false );
2818 QuickInsert( xMethRef
.get() );
2824 Any
SbUnoObject::getUnoAny()
2827 if( bNeedIntrospection
) doIntrospection();
2828 if ( maStructInfo
.get() )
2829 aRetAny
= maTmpUnoObj
;
2830 else if( mxMaterialHolder
.is() )
2831 aRetAny
= mxMaterialHolder
->getMaterial();
2832 else if( mxInvocation
.is() )
2833 aRetAny
<<= mxInvocation
;
2837 // help method to create a Uno-Struct per CoreReflection
2838 static SbUnoObject
* Impl_CreateUnoStruct( const OUString
& aClassName
)
2840 // get CoreReflection
2841 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
2842 if( !xCoreReflection
.is() )
2845 // search for the class
2846 Reference
< XIdlClass
> xClass
;
2847 const Reference
< XHierarchicalNameAccess
>& xHarryName
=
2848 getCoreReflection_HierarchicalNameAccess_Impl();
2849 if( xHarryName
.is() && xHarryName
->hasByHierarchicalName( aClassName
) )
2850 xClass
= xCoreReflection
->forName( aClassName
);
2854 // Is it really a struct?
2855 TypeClass eType
= xClass
->getTypeClass();
2856 if ( ( eType
!= TypeClass_STRUCT
) && ( eType
!= TypeClass_EXCEPTION
) )
2859 // create an instance
2861 xClass
->createObject( aNewAny
);
2862 // make a SbUnoObject out of it
2863 SbUnoObject
* pUnoObj
= new SbUnoObject( aClassName
, aNewAny
);
2868 // Factory-Class to create Uno-Structs per DIM AS NEW
2869 SbxBase
* SbUnoFactory::Create( sal_uInt16
, sal_uInt32
)
2871 // Via SbxId nothing works in Uno
2875 SbxObject
* SbUnoFactory::CreateObject( const OUString
& rClassName
)
2877 return Impl_CreateUnoStruct( rClassName
);
2881 // Provisional interface for the UNO-Connection
2882 // Deliver a SbxObject, that wrap a Uno-Interface
2883 SbxObjectRef
GetSbUnoObject( const OUString
& aName
, const Any
& aUnoObj_
)
2885 return new SbUnoObject( aName
, aUnoObj_
);
2888 // Force creation of all properties for debugging
2889 void createAllObjectProperties( SbxObject
* pObj
)
2894 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
2895 SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>( pObj
);
2898 pUnoObj
->createAllProperties();
2900 else if ( pUnoStructObj
)
2902 pUnoStructObj
->createAllProperties();
2907 void RTL_Impl_CreateUnoStruct( SbxArray
& rPar
)
2909 // We need 1 parameter minimum
2910 if ( rPar
.Count() < 2 )
2912 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2916 // get the name of the class of the struct
2917 OUString aClassName
= rPar
.Get(1)->GetOUString();
2919 // try to create Struct with the same name
2920 SbUnoObjectRef xUnoObj
= Impl_CreateUnoStruct( aClassName
);
2925 // return the object
2926 SbxVariableRef refVar
= rPar
.Get(0);
2927 refVar
->PutObject( xUnoObj
.get() );
2930 void RTL_Impl_CreateUnoService( SbxArray
& rPar
)
2932 // We need 1 Parameter minimum
2933 if ( rPar
.Count() < 2 )
2935 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2939 // get the name of the class of the struct
2940 OUString aServiceName
= rPar
.Get(1)->GetOUString();
2942 // search for the service and instantiate it
2943 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
2944 Reference
< XInterface
> xInterface
;
2947 xInterface
= xFactory
->createInstance( aServiceName
);
2949 catch( const Exception
& )
2951 implHandleAnyException( ::cppu::getCaughtException() );
2954 SbxVariableRef refVar
= rPar
.Get(0);
2955 if( xInterface
.is() )
2957 // Create a SbUnoObject out of it and return it
2958 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
2959 if( xUnoObj
->getUnoAny().hasValue() )
2961 // return the object
2962 refVar
->PutObject( xUnoObj
.get() );
2966 refVar
->PutObject( nullptr );
2971 refVar
->PutObject( nullptr );
2975 void RTL_Impl_CreateUnoServiceWithArguments( SbxArray
& rPar
)
2977 // We need 2 parameter minimum
2978 if ( rPar
.Count() < 3 )
2980 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2984 // get the name of the class of the struct
2985 OUString aServiceName
= rPar
.Get(1)->GetOUString();
2986 Any aArgAsAny
= sbxToUnoValue( rPar
.Get(2),
2987 cppu::UnoType
<Sequence
<Any
>>::get() );
2988 Sequence
< Any
> aArgs
;
2989 aArgAsAny
>>= aArgs
;
2991 // search for the service and instantiate it
2992 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
2993 Reference
< XInterface
> xInterface
;
2996 xInterface
= xFactory
->createInstanceWithArguments( aServiceName
, aArgs
);
2998 catch( const Exception
& )
3000 implHandleAnyException( ::cppu::getCaughtException() );
3003 SbxVariableRef refVar
= rPar
.Get(0);
3004 if( xInterface
.is() )
3006 // Create a SbUnoObject out of it and return it
3007 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
3008 if( xUnoObj
->getUnoAny().hasValue() )
3010 // return the object
3011 refVar
->PutObject( xUnoObj
.get() );
3015 refVar
->PutObject( nullptr );
3020 refVar
->PutObject( nullptr );
3024 void RTL_Impl_GetProcessServiceManager( SbxArray
& rPar
)
3026 SbxVariableRef refVar
= rPar
.Get(0);
3028 // get the global service manager
3029 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
3031 // Create a SbUnoObject out of it and return it
3032 SbUnoObjectRef xUnoObj
= new SbUnoObject( "ProcessServiceManager", Any(xFactory
) );
3033 refVar
->PutObject( xUnoObj
.get() );
3036 void RTL_Impl_HasInterfaces( SbxArray
& rPar
)
3038 // We need 2 parameter minimum
3039 sal_uInt16 nParCount
= rPar
.Count();
3042 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3046 // variable for the return value
3047 SbxVariableRef refVar
= rPar
.Get(0);
3048 refVar
->PutBool( false );
3050 // get the Uno-Object
3051 SbxBaseRef pObj
= rPar
.Get( 1 )->GetObject();
3052 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3053 if( obj
== nullptr )
3057 Any aAny
= obj
->getUnoAny();
3058 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aAny
);
3064 // get CoreReflection
3065 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3066 if( !xCoreReflection
.is() )
3070 for( sal_uInt16 i
= 2 ; i
< nParCount
; i
++ )
3072 // get the name of the interface of the struct
3073 OUString aIfaceName
= rPar
.Get( i
)->GetOUString();
3075 // search for the class
3076 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aIfaceName
);
3081 // check if the interface will be supported
3082 OUString aClassName
= xClass
->getName();
3083 Type
aClassType( xClass
->getTypeClass(), aClassName
);
3084 if( !(*x
)->queryInterface( aClassType
).hasValue() )
3090 // Everything works; then return TRUE
3091 refVar
->PutBool( true );
3094 void RTL_Impl_IsUnoStruct( SbxArray
& rPar
)
3096 // We need 1 parameter minimum
3097 if ( rPar
.Count() < 2 )
3099 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3103 // variable for the return value
3104 SbxVariableRef refVar
= rPar
.Get(0);
3105 refVar
->PutBool( false );
3107 // get the Uno-Object
3108 SbxVariableRef xParam
= rPar
.Get( 1 );
3109 if( !xParam
->IsObject() )
3113 SbxBaseRef pObj
= rPar
.Get( 1 )->GetObject();
3114 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3115 if( obj
== nullptr )
3119 Any aAny
= obj
->getUnoAny();
3120 TypeClass eType
= aAny
.getValueType().getTypeClass();
3121 if( eType
== TypeClass_STRUCT
)
3123 refVar
->PutBool( true );
3128 void RTL_Impl_EqualUnoObjects( SbxArray
& rPar
)
3130 if ( rPar
.Count() < 3 )
3132 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3136 // variable for the return value
3137 SbxVariableRef refVar
= rPar
.Get(0);
3138 refVar
->PutBool( false );
3140 // get the Uno-Objects
3141 SbxVariableRef xParam1
= rPar
.Get( 1 );
3142 if( !xParam1
->IsObject() )
3146 SbxBaseRef pObj1
= xParam1
->GetObject();
3147 auto obj1
= dynamic_cast<SbUnoObject
*>( pObj1
.get() );
3148 if( obj1
== nullptr )
3152 Any aAny1
= obj1
->getUnoAny();
3153 TypeClass eType1
= aAny1
.getValueType().getTypeClass();
3154 if( eType1
!= TypeClass_INTERFACE
)
3158 Reference
< XInterface
> x1
;
3161 SbxVariableRef xParam2
= rPar
.Get( 2 );
3162 if( !xParam2
->IsObject() )
3166 SbxBaseRef pObj2
= xParam2
->GetObject();
3167 auto obj2
= dynamic_cast<SbUnoObject
*>( pObj2
.get() );
3168 if( obj2
== nullptr )
3172 Any aAny2
= obj2
->getUnoAny();
3173 TypeClass eType2
= aAny2
.getValueType().getTypeClass();
3174 if( eType2
!= TypeClass_INTERFACE
)
3178 Reference
< XInterface
> x2
;
3183 refVar
->PutBool( true );
3188 // helper wrapper function to interact with TypeProvider and
3189 // XTypeDescriptionEnumerationAccess.
3190 // if it fails for whatever reason
3191 // returned Reference<> be null e.g. .is() will be false
3193 static Reference
< XTypeDescriptionEnumeration
> getTypeDescriptorEnumeration( const OUString
& sSearchRoot
,
3194 const Sequence
< TypeClass
>& types
,
3195 TypeDescriptionSearchDepth depth
)
3197 Reference
< XTypeDescriptionEnumeration
> xEnum
;
3198 Reference
< XTypeDescriptionEnumerationAccess
> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY
);
3199 if ( xTypeEnumAccess
.is() )
3203 xEnum
= xTypeEnumAccess
->createTypeDescriptionEnumeration(
3204 sSearchRoot
, types
, depth
);
3206 catch(const NoSuchTypeNameException
& /*nstne*/ ) {}
3207 catch(const InvalidTypeNameException
& /*nstne*/ ) {}
3213 VBAConstantHelper::instance()
3215 static VBAConstantHelper aHelper
;
3219 void VBAConstantHelper::init()
3223 Sequence
< TypeClass
> types(1);
3224 types
[ 0 ] = TypeClass_CONSTANTS
;
3225 Reference
< XTypeDescriptionEnumeration
> xEnum
= getTypeDescriptorEnumeration( "ooo.vba", types
, TypeDescriptionSearchDepth_INFINITE
);
3231 while ( xEnum
->hasMoreElements() )
3233 Reference
< XConstantsTypeDescription
> xConstants( xEnum
->nextElement(), UNO_QUERY
);
3234 if ( xConstants
.is() )
3236 // store constant group name
3237 OUString sFullName
= xConstants
->getName();
3238 sal_Int32 indexLastDot
= sFullName
.lastIndexOf('.');
3239 OUString
sLeafName( sFullName
);
3240 if ( indexLastDot
> -1 )
3242 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3244 aConstCache
.push_back( sLeafName
); // assume constant group names are unique
3245 Sequence
< Reference
< XConstantTypeDescription
> > aConsts
= xConstants
->getConstants();
3246 for (sal_Int32 i
= 0; i
!= aConsts
.getLength(); ++i
)
3248 // store constant member name
3249 sFullName
= aConsts
[i
]->getName();
3250 indexLastDot
= sFullName
.lastIndexOf('.');
3251 sLeafName
= sFullName
;
3252 if ( indexLastDot
> -1 )
3254 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3256 aConstHash
[ sLeafName
.toAsciiLowerCase() ] = aConsts
[i
]->getConstantValue();
3265 VBAConstantHelper::isVBAConstantType( const OUString
& rName
)
3268 bool bConstant
= false;
3270 for (auto const& elem
: aConstCache
)
3272 if( rName
.equalsIgnoreAsciiCase(elem
) )
3282 VBAConstantHelper::getVBAConstant( const OUString
& rName
)
3284 SbxVariable
* pConst
= nullptr;
3287 auto it
= aConstHash
.find( rName
.toAsciiLowerCase() );
3289 if ( it
!= aConstHash
.end() )
3291 pConst
= new SbxVariable( SbxVARIANT
);
3292 pConst
->SetName( rName
);
3293 unoToSbxValue( pConst
, it
->second
);
3299 // Function to search for a global identifier in the
3300 // UnoScope and to wrap it for Sbx
3301 SbUnoClass
* findUnoClass( const OUString
& rName
)
3303 // #105550 Check if module exists
3304 SbUnoClass
* pUnoClass
= nullptr;
3306 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3307 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3309 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3310 Reference
< XTypeDescription
> xTypeDesc
;
3313 if( xTypeDesc
.is() )
3315 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3316 if( eTypeClass
== TypeClass_MODULE
|| eTypeClass
== TypeClass_CONSTANTS
)
3318 pUnoClass
= new SbUnoClass( rName
);
3325 SbxVariable
* SbUnoClass::Find( const OUString
& rName
, SbxClassType
)
3327 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Variable
);
3329 // If nothing were located the submodule isn't known yet
3332 // If it is already a class, ask for the field
3336 Reference
< XIdlField
> xField
= m_xClass
->getField( rName
);
3341 Any aAny
= xField
->get( {} ); //TODO: does this make sense?
3344 pRes
= new SbxVariable( SbxVARIANT
);
3345 pRes
->SetName( rName
);
3346 unoToSbxValue( pRes
, aAny
);
3348 catch( const Exception
& )
3350 implHandleAnyException( ::cppu::getCaughtException() );
3356 // expand fully qualified name
3357 OUString aNewName
= GetName()
3361 // get CoreReflection
3362 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3363 if( xCoreReflection
.is() )
3365 // Is it a constant?
3366 Reference
< XHierarchicalNameAccess
> xHarryName( xCoreReflection
, UNO_QUERY
);
3367 if( xHarryName
.is() )
3371 Any aValue
= xHarryName
->getByHierarchicalName( aNewName
);
3372 TypeClass eType
= aValue
.getValueType().getTypeClass();
3374 // Interface located? Then it is a class
3375 if( eType
== TypeClass_INTERFACE
)
3377 Reference
< XIdlClass
> xClass( aValue
, UNO_QUERY
);
3380 pRes
= new SbxVariable( SbxVARIANT
);
3381 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(new SbUnoClass( aNewName
, xClass
));
3382 pRes
->PutObject( xWrapper
.get() );
3387 pRes
= new SbxVariable( SbxVARIANT
);
3388 unoToSbxValue( pRes
, aValue
);
3391 catch( const NoSuchElementException
& )
3396 // Otherwise take it again as class
3399 SbUnoClass
* pNewClass
= findUnoClass( aNewName
);
3402 pRes
= new SbxVariable( SbxVARIANT
);
3403 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pNewClass
);
3404 pRes
->PutObject( xWrapper
.get() );
3411 SbUnoService
* pUnoService
= findUnoService( aNewName
);
3414 pRes
= new SbxVariable( SbxVARIANT
);
3415 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoService
);
3416 pRes
->PutObject( xWrapper
.get() );
3423 SbUnoSingleton
* pUnoSingleton
= findUnoSingleton( aNewName
);
3426 pRes
= new SbxVariable( SbxVARIANT
);
3427 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoSingleton
);
3428 pRes
->PutObject( xWrapper
.get() );
3436 pRes
->SetName( rName
);
3438 // Insert variable, so that it could be found later
3439 QuickInsert( pRes
);
3441 // Take us out as listener at once,
3442 // the values are all constant
3443 if( pRes
->IsBroadcaster() )
3444 EndListening( pRes
->GetBroadcaster(), true );
3451 SbUnoService
* findUnoService( const OUString
& rName
)
3453 SbUnoService
* pSbUnoService
= nullptr;
3455 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3456 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3458 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3459 Reference
< XTypeDescription
> xTypeDesc
;
3462 if( xTypeDesc
.is() )
3464 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3465 if( eTypeClass
== TypeClass_SERVICE
)
3467 Reference
< XServiceTypeDescription2
> xServiceTypeDesc( xTypeDesc
, UNO_QUERY
);
3468 if( xServiceTypeDesc
.is() )
3469 pSbUnoService
= new SbUnoService( rName
, xServiceTypeDesc
);
3473 return pSbUnoService
;
3476 SbxVariable
* SbUnoService::Find( const OUString
& rName
, SbxClassType
)
3478 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3482 // If it is already a class ask for a field
3483 if( m_bNeedsInit
&& m_xServiceTypeDesc
.is() )
3485 m_bNeedsInit
= false;
3487 Sequence
< Reference
< XServiceConstructorDescription
> > aSCDSeq
= m_xServiceTypeDesc
->getConstructors();
3488 const Reference
< XServiceConstructorDescription
>* pCtorSeq
= aSCDSeq
.getConstArray();
3489 int nCtorCount
= aSCDSeq
.getLength();
3490 for( int i
= 0 ; i
< nCtorCount
; ++i
)
3492 Reference
< XServiceConstructorDescription
> xCtor
= pCtorSeq
[i
];
3494 OUString
aName( xCtor
->getName() );
3495 if( aName
.isEmpty() )
3497 if( xCtor
->isDefaultConstructor() )
3503 if( !aName
.isEmpty() )
3505 // Create and insert SbUnoServiceCtor
3506 SbxVariableRef xSbCtorRef
= new SbUnoServiceCtor( aName
, xCtor
);
3507 QuickInsert( xSbCtorRef
.get() );
3510 pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3517 void SbUnoService::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3519 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3522 SbxVariable
* pVar
= pHint
->GetVar();
3523 SbxArray
* pParams
= pVar
->GetParameters();
3524 SbUnoServiceCtor
* pUnoCtor
= dynamic_cast<SbUnoServiceCtor
*>( pVar
);
3525 if( pUnoCtor
&& pHint
->GetId() == SfxHintId::BasicDataWanted
)
3527 // Parameter count -1 because of Param0 == this
3528 sal_uInt32 nParamCount
= pParams
? (static_cast<sal_uInt32
>(pParams
->Count()) - 1) : 0;
3531 Reference
< XServiceConstructorDescription
> xCtor
= pUnoCtor
->getServiceCtorDesc();
3532 Sequence
< Reference
< XParameter
> > aParameterSeq
= xCtor
->getParameters();
3533 const Reference
< XParameter
>* pParameterSeq
= aParameterSeq
.getConstArray();
3534 sal_uInt32 nUnoParamCount
= aParameterSeq
.getLength();
3536 // Default: Ignore not needed parameters
3537 bool bParameterError
= false;
3539 // Is the last parameter a rest parameter?
3540 bool bRestParameterMode
= false;
3541 if( nUnoParamCount
> 0 )
3543 Reference
< XParameter
> xLastParam
= pParameterSeq
[ nUnoParamCount
- 1 ];
3544 if( xLastParam
.is() )
3546 if( xLastParam
->isRestParameter() )
3547 bRestParameterMode
= true;
3551 // Too many parameters with context as first parameter?
3552 sal_uInt16 nSbxParameterOffset
= 1;
3553 sal_uInt16 nParameterOffsetByContext
= 0;
3554 Reference
< XComponentContext
> xFirstParamContext
;
3555 if( nParamCount
> nUnoParamCount
)
3557 // Check if first parameter is a context and use it
3558 // then in createInstanceWithArgumentsAndContext
3559 Any aArg0
= sbxToUnoValue( pParams
->Get( nSbxParameterOffset
) );
3560 if( (aArg0
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3561 nParameterOffsetByContext
= 1;
3564 sal_uInt32 nEffectiveParamCount
= nParamCount
- nParameterOffsetByContext
;
3565 sal_uInt32 nAllocParamCount
= nEffectiveParamCount
;
3566 if( nEffectiveParamCount
> nUnoParamCount
)
3568 if( !bRestParameterMode
)
3570 nEffectiveParamCount
= nUnoParamCount
;
3571 nAllocParamCount
= nUnoParamCount
;
3574 // Not enough parameters?
3575 else if( nUnoParamCount
> nEffectiveParamCount
)
3577 // RestParameterMode only helps if one (the last) parameter is missing
3578 int nDiff
= nUnoParamCount
- nEffectiveParamCount
;
3579 if( !bRestParameterMode
|| nDiff
> 1 )
3581 bParameterError
= true;
3582 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
3586 if( !bParameterError
)
3588 bool bOutParams
= false;
3589 if( nAllocParamCount
> 0 )
3591 args
.realloc( nAllocParamCount
);
3592 Any
* pAnyArgs
= args
.getArray();
3593 for( sal_uInt32 i
= 0 ; i
< nEffectiveParamCount
; i
++ )
3595 sal_uInt16 iSbx
= static_cast<sal_uInt16
>(i
+ nSbxParameterOffset
+ nParameterOffsetByContext
);
3597 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3598 Reference
< XParameter
> xParam
;
3599 if( i
< nUnoParamCount
)
3601 xParam
= pParameterSeq
[i
];
3605 Reference
< XTypeDescription
> xParamTypeDesc
= xParam
->getType();
3606 if( !xParamTypeDesc
.is() )
3608 css::uno::Type
aType( xParamTypeDesc
->getTypeClass(), xParamTypeDesc
->getName() );
3610 // sbx parameter needs offset 1
3611 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get( iSbx
), aType
);
3613 // Check for out parameter if not already done
3614 if( !bOutParams
&& xParam
->isOut() )
3619 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get( iSbx
) );
3624 // "Call" ctor using createInstanceWithArgumentsAndContext
3625 Reference
< XComponentContext
> xContext(
3626 xFirstParamContext
.is()
3627 ? xFirstParamContext
3628 : comphelper::getProcessComponentContext() );
3629 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
3632 OUString aServiceName
= GetName();
3633 Reference
< XInterface
> xRet
;
3636 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext( aServiceName
, args
, xContext
);
3638 catch( const Exception
& )
3640 implHandleAnyException( ::cppu::getCaughtException() );
3643 unoToSbxValue( pVar
, aRetAny
);
3645 // Copy back out parameters?
3648 const Any
* pAnyArgs
= args
.getConstArray();
3650 for( sal_uInt32 j
= 0 ; j
< nUnoParamCount
; j
++ )
3652 Reference
< XParameter
> xParam
= pParameterSeq
[j
];
3656 if( xParam
->isOut() )
3657 unoToSbxValue( pParams
->Get( static_cast<sal_uInt16
>(j
+1) ), pAnyArgs
[ j
] );
3663 SbxObject::Notify( rBC
, rHint
);
3668 SbUnoServiceCtor::SbUnoServiceCtor( const OUString
& aName_
, Reference
< XServiceConstructorDescription
> const & xServiceCtorDesc
)
3669 : SbxMethod( aName_
, SbxOBJECT
)
3670 , m_xServiceCtorDesc( xServiceCtorDesc
)
3674 SbUnoServiceCtor::~SbUnoServiceCtor()
3678 SbxInfo
* SbUnoServiceCtor::GetInfo()
3680 SbxInfo
* pRet
= nullptr;
3686 SbUnoSingleton
* findUnoSingleton( const OUString
& rName
)
3688 SbUnoSingleton
* pSbUnoSingleton
= nullptr;
3690 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3691 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3693 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3694 Reference
< XTypeDescription
> xTypeDesc
;
3697 if( xTypeDesc
.is() )
3699 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3700 if( eTypeClass
== TypeClass_SINGLETON
)
3702 Reference
< XSingletonTypeDescription
> xSingletonTypeDesc( xTypeDesc
, UNO_QUERY
);
3703 if( xSingletonTypeDesc
.is() )
3704 pSbUnoSingleton
= new SbUnoSingleton( rName
);
3708 return pSbUnoSingleton
;
3711 SbUnoSingleton::SbUnoSingleton( const OUString
& aName_
)
3712 : SbxObject( aName_
)
3714 SbxVariableRef xGetMethodRef
= new SbxMethod( "get", SbxOBJECT
);
3715 QuickInsert( xGetMethodRef
.get() );
3718 void SbUnoSingleton::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3720 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3723 SbxVariable
* pVar
= pHint
->GetVar();
3724 SbxArray
* pParams
= pVar
->GetParameters();
3725 sal_uInt32 nParamCount
= pParams
? (static_cast<sal_uInt32
>(pParams
->Count()) - 1) : 0;
3726 sal_uInt32 nAllowedParamCount
= 1;
3728 Reference
< XComponentContext
> xContextToUse
;
3729 if( nParamCount
> 0 )
3731 // Check if first parameter is a context and use it then
3732 Reference
< XComponentContext
> xFirstParamContext
;
3733 Any aArg1
= sbxToUnoValue( pParams
->Get( 1 ) );
3734 if( (aArg1
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3735 xContextToUse
= xFirstParamContext
;
3738 if( !xContextToUse
.is() )
3740 xContextToUse
= comphelper::getProcessComponentContext();
3741 --nAllowedParamCount
;
3744 if( nParamCount
> nAllowedParamCount
)
3746 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3751 if( xContextToUse
.is() )
3753 OUString aSingletonName
= "/singletons/"
3755 Reference
< XInterface
> xRet
;
3756 xContextToUse
->getValueByName( aSingletonName
) >>= xRet
;
3759 unoToSbxValue( pVar
, aRetAny
);
3763 SbxObject::Notify( rBC
, rHint
);
3768 // Implementation of an EventAttacher-drawn AllListener, which
3769 // solely transmits several events to a general AllListener
3770 class BasicAllListener_Impl
: public WeakImplHelper
< XAllListener
>
3772 void firing_impl(const AllEventObject
& Event
, Any
* pRet
);
3775 SbxObjectRef xSbxObj
;
3776 OUString aPrefixName
;
3778 explicit BasicAllListener_Impl( const OUString
& aPrefixName
);
3780 // Methods of XAllListener
3781 virtual void SAL_CALL
firing(const AllEventObject
& Event
) override
;
3782 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) override
;
3784 // Methods of XEventListener
3785 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
3789 BasicAllListener_Impl::BasicAllListener_Impl(const OUString
& aPrefixName_
)
3790 : aPrefixName( aPrefixName_
)
3794 void BasicAllListener_Impl::firing_impl( const AllEventObject
& Event
, Any
* pRet
)
3796 SolarMutexGuard guard
;
3800 OUString aMethodName
= aPrefixName
+ Event
.MethodName
;
3802 SbxVariable
* pP
= xSbxObj
.get();
3803 while( pP
->GetParent() )
3805 pP
= pP
->GetParent();
3806 StarBASIC
* pLib
= dynamic_cast<StarBASIC
*>( pP
);
3809 // Create in a Basic Array
3810 SbxArrayRef xSbxArray
= new SbxArray( SbxVARIANT
);
3811 const Any
* pArgs
= Event
.Arguments
.getConstArray();
3812 sal_Int32 nCount
= Event
.Arguments
.getLength();
3813 for( sal_Int32 i
= 0; i
< nCount
; i
++ )
3816 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
3817 unoToSbxValue( xVar
.get(), pArgs
[i
] );
3818 xSbxArray
->Put( xVar
.get(), sal::static_int_cast
< sal_uInt16
>(i
+1) );
3821 pLib
->Call( aMethodName
, xSbxArray
.get() );
3823 // get the return value from the Param-Array, if requested
3826 SbxVariable
* pVar
= xSbxArray
->Get( 0 );
3829 // #95792 Avoid a second call
3830 SbxFlagBits nFlags
= pVar
->GetFlags();
3831 pVar
->SetFlag( SbxFlagBits::NoBroadcast
);
3832 *pRet
= sbxToUnoValueImpl( pVar
);
3833 pVar
->SetFlags( nFlags
);
3843 // Methods of Listener
3844 void BasicAllListener_Impl::firing( const AllEventObject
& Event
)
3846 firing_impl( Event
, nullptr );
3849 Any
BasicAllListener_Impl::approveFiring( const AllEventObject
& Event
)
3852 firing_impl( Event
, &aRetAny
);
3857 // Methods of XEventListener
3858 void BasicAllListener_Impl ::disposing(const EventObject
& )
3860 SolarMutexGuard guard
;
3866 // class InvocationToAllListenerMapper
3867 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
3869 class InvocationToAllListenerMapper
: public WeakImplHelper
< XInvocation
>
3872 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
3873 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
);
3876 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
3877 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
) override
;
3878 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
) override
;
3879 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) override
;
3880 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) override
;
3881 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) override
;
3884 Reference
< XAllListener
> m_xAllListener
;
3885 Reference
< XIdlClass
> m_xListenerType
;
3890 // Function to replace AllListenerAdapterService::createAllListerAdapter
3891 static Reference
< XInterface
> createAllListenerAdapter
3893 const Reference
< XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
3894 const Reference
< XIdlClass
>& xListenerType
,
3895 const Reference
< XAllListener
>& xListener
,
3899 Reference
< XInterface
> xAdapter
;
3900 if( xInvocationAdapterFactory
.is() && xListenerType
.is() && xListener
.is() )
3902 Reference
< XInvocation
> xInvocationToAllListenerMapper
=
3903 new InvocationToAllListenerMapper(xListenerType
, xListener
, Helper
);
3904 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName() );
3905 Sequence
<Type
> arg2(1);
3906 arg2
[0] = aListenerType
;
3907 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, arg2
);
3913 // InvocationToAllListenerMapper
3914 InvocationToAllListenerMapper::InvocationToAllListenerMapper
3915 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, const Any
& Helper
)
3916 : m_xAllListener( AllListener
)
3917 , m_xListenerType( ListenerType
)
3918 , m_Helper( Helper
)
3923 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection()
3925 return Reference
< XIntrospectionAccess
>();
3929 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
3930 Sequence
< sal_Int16
>&, Sequence
< Any
>&)
3934 // Check if to firing or approveFiring has to be called
3935 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
3936 bool bApproveFiring
= false;
3939 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
3940 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
3941 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
3942 aExceptionSeq
.hasElements() )
3944 bApproveFiring
= true;
3948 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
3949 sal_uInt32 nParamCount
= aParamSeq
.getLength();
3950 if( nParamCount
> 1 )
3952 const ParamInfo
* pInfo
= aParamSeq
.getConstArray();
3953 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
3955 if( pInfo
[ i
].aMode
!= ParamMode_IN
)
3957 bApproveFiring
= true;
3964 AllEventObject aAllEvent
;
3965 aAllEvent
.Source
= static_cast<OWeakObject
*>(this);
3966 aAllEvent
.Helper
= m_Helper
;
3967 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName() );
3968 aAllEvent
.MethodName
= FunctionName
;
3969 aAllEvent
.Arguments
= Params
;
3970 if( bApproveFiring
)
3971 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
3973 m_xAllListener
->firing( aAllEvent
);
3978 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
&, const Any
&)
3982 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
&)
3988 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
3990 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
3991 return xMethod
.is();
3995 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
3997 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
4002 // create Uno-Service
4003 // 1. Parameter == Prefix-Name of the macro
4004 // 2. Parameter == fully qualified name of the listener
4005 void SbRtl_CreateUnoListener(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
4007 // We need 2 parameters
4008 if ( rPar
.Count() != 3 )
4010 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4014 // get the name of the class of the struct
4015 OUString aPrefixName
= rPar
.Get(1)->GetOUString();
4016 OUString aListenerClassName
= rPar
.Get(2)->GetOUString();
4018 // get the CoreReflection
4019 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
4020 if( !xCoreReflection
.is() )
4023 // get the AllListenerAdapterService
4024 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
4027 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aListenerClassName
);
4031 // From 1999-11-30: get the InvocationAdapterFactory
4032 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
=
4033 InvocationAdapterFactory::create( xContext
);
4035 BasicAllListener_Impl
* p
;
4036 Reference
< XAllListener
> xAllLst
= p
= new BasicAllListener_Impl( aPrefixName
);
4038 Reference
< XInterface
> xLst
= createAllListenerAdapter( xInvocationAdapterFactory
, xClass
, xAllLst
, aTmp
);
4042 OUString aClassName
= xClass
->getName();
4043 Type
aClassType( xClass
->getTypeClass(), aClassName
);
4044 aTmp
= xLst
->queryInterface( aClassType
);
4045 if( !aTmp
.hasValue() )
4048 SbUnoObject
* pUnoObj
= new SbUnoObject( aListenerClassName
, aTmp
);
4049 p
->xSbxObj
= pUnoObj
;
4050 p
->xSbxObj
->SetParent( pBasic
);
4052 // #100326 Register listener object to set Parent NULL in Dtor
4053 SbxArrayRef xBasicUnoListeners
= pBasic
->getUnoListeners();
4054 xBasicUnoListeners
->Insert( pUnoObj
, xBasicUnoListeners
->Count() );
4056 // return the object
4057 SbxVariableRef refVar
= rPar
.Get(0);
4058 refVar
->PutObject( p
->xSbxObj
.get() );
4062 // Represents the DefaultContext property of the ProcessServiceManager
4063 // in the Basic runtime system.
4064 void RTL_Impl_GetDefaultContext( SbxArray
& rPar
)
4066 SbxVariableRef refVar
= rPar
.Get(0);
4068 Any
aContextAny( comphelper::getProcessComponentContext() );
4070 SbUnoObjectRef xUnoObj
= new SbUnoObject( "DefaultContext", aContextAny
);
4071 refVar
->PutObject( xUnoObj
.get() );
4075 // Creates a Basic wrapper object for a strongly typed Uno value
4076 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4077 void RTL_Impl_CreateUnoValue( SbxArray
& rPar
)
4079 // 2 parameters needed
4080 if ( rPar
.Count() != 3 )
4082 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4086 // get the name of the class of the struct
4087 OUString aTypeName
= rPar
.Get(1)->GetOUString();
4088 SbxVariable
* pVal
= rPar
.Get(2);
4090 if( aTypeName
== "type" )
4092 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
4093 OUString aValTypeName
;
4094 if( eBaseType
== SbxSTRING
)
4096 aValTypeName
= pVal
->GetOUString();
4098 else if( eBaseType
== SbxOBJECT
)
4101 Reference
< XIdlClass
> xIdlClass
;
4103 SbxBaseRef pObj
= pVal
->GetObject();
4104 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
4106 Any aUnoAny
= obj
->getUnoAny();
4107 aUnoAny
>>= xIdlClass
;
4110 if( xIdlClass
.is() )
4112 aValTypeName
= xIdlClass
->getName();
4116 bool bSuccess
= implGetTypeByName( aValTypeName
, aType
);
4119 Any
aTypeAny( aType
);
4120 SbxVariableRef refVar
= rPar
.Get(0);
4121 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject( aTypeAny
);
4122 refVar
->PutObject( xUnoAnyObject
.get() );
4128 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
4132 aRet
= xTypeAccess
->getByHierarchicalName( aTypeName
);
4134 catch( const NoSuchElementException
& e1
)
4136 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
4137 implGetExceptionMsg( e1
, "com.sun.star.container.NoSuchElementException" ) );
4140 Reference
< XTypeDescription
> xTypeDesc
;
4142 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
4143 Type
aDestType( eTypeClass
, aTypeName
);
4147 Any aVal
= sbxToUnoValueImpl( pVal
);
4148 Any aConvertedVal
= convertAny( aVal
, aDestType
);
4150 SbxVariableRef refVar
= rPar
.Get(0);
4151 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject( aConvertedVal
);
4152 refVar
->PutObject( xUnoAnyObject
.get() );
4156 class ModuleInvocationProxy
: public WeakImplHelper
< XInvocation
, XComponent
>
4158 ::osl::Mutex m_aMutex
;
4160 SbxObjectRef m_xScopeObj
;
4161 bool m_bProxyIsClassModuleObject
;
4163 ::comphelper::OInterfaceContainerHelper2 m_aListeners
;
4166 ModuleInvocationProxy( OUString
const & aPrefix
, SbxObjectRef
const & xScopeObj
);
4169 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
4170 virtual void SAL_CALL
setValue( const OUString
& rProperty
, const Any
& rValue
) override
;
4171 virtual Any SAL_CALL
getValue( const OUString
& rProperty
) override
;
4172 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& rName
) override
;
4173 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& rProp
) override
;
4175 virtual Any SAL_CALL
invoke( const OUString
& rFunction
,
4176 const Sequence
< Any
>& rParams
,
4177 Sequence
< sal_Int16
>& rOutParamIndex
,
4178 Sequence
< Any
>& rOutParam
) override
;
4181 virtual void SAL_CALL
dispose() override
;
4182 virtual void SAL_CALL
addEventListener( const Reference
< XEventListener
>& xListener
) override
;
4183 virtual void SAL_CALL
removeEventListener( const Reference
< XEventListener
>& aListener
) override
;
4186 ModuleInvocationProxy::ModuleInvocationProxy( OUString
const & aPrefix
, SbxObjectRef
const & xScopeObj
)
4188 , m_aPrefix( aPrefix
+ "_" )
4189 , m_xScopeObj( xScopeObj
)
4190 , m_aListeners( m_aMutex
)
4192 m_bProxyIsClassModuleObject
= xScopeObj
.is() && dynamic_cast<const SbClassModuleObject
*>( xScopeObj
.get() ) != nullptr;
4195 Reference
< XIntrospectionAccess
> SAL_CALL
ModuleInvocationProxy::getIntrospection()
4197 return Reference
< XIntrospectionAccess
>();
4200 void SAL_CALL
ModuleInvocationProxy::setValue(const OUString
& rProperty
, const Any
& rValue
)
4202 if( !m_bProxyIsClassModuleObject
)
4203 throw UnknownPropertyException();
4205 SolarMutexGuard guard
;
4207 OUString aPropertyFunctionName
= "Property Set "
4211 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4212 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4213 if( pMeth
== nullptr )
4215 // TODO: Check vba behavior concerning missing function
4216 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4217 throw UnknownPropertyException(aPropertyFunctionName
);
4221 SbxArrayRef xArray
= new SbxArray
;
4222 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4223 unoToSbxValue( xVar
.get(), rValue
);
4224 xArray
->Put( xVar
.get(), 1 );
4226 // Call property method
4227 SbxVariableRef xValue
= new SbxVariable
;
4228 pMeth
->SetParameters( xArray
.get() );
4229 pMeth
->Call( xValue
.get() );
4230 pMeth
->SetParameters( nullptr );
4232 // TODO: OutParameter?
4237 Any SAL_CALL
ModuleInvocationProxy::getValue(const OUString
& rProperty
)
4239 if( !m_bProxyIsClassModuleObject
)
4241 throw UnknownPropertyException();
4243 SolarMutexGuard guard
;
4245 OUString aPropertyFunctionName
= "Property Get "
4249 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4250 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4251 if( pMeth
== nullptr )
4253 // TODO: Check vba behavior concerning missing function
4254 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4255 throw UnknownPropertyException(aPropertyFunctionName
);
4259 SbxVariableRef xValue
= new SbxVariable
;
4260 pMeth
->Call( xValue
.get() );
4261 Any aRet
= sbxToUnoValue( xValue
.get() );
4265 sal_Bool SAL_CALL
ModuleInvocationProxy::hasMethod( const OUString
& )
4270 sal_Bool SAL_CALL
ModuleInvocationProxy::hasProperty( const OUString
& )
4275 Any SAL_CALL
ModuleInvocationProxy::invoke( const OUString
& rFunction
,
4276 const Sequence
< Any
>& rParams
,
4277 Sequence
< sal_Int16
>&,
4280 SolarMutexGuard guard
;
4283 SbxObjectRef xScopeObj
= m_xScopeObj
;
4284 if( !xScopeObj
.is() )
4288 OUString aFunctionName
= m_aPrefix
4291 bool bSetRescheduleBack
= false;
4292 bool bOldReschedule
= true;
4293 SbiInstance
* pInst
= GetSbData()->pInst
;
4294 if( pInst
&& pInst
->IsCompatibility() )
4296 bOldReschedule
= pInst
->IsReschedule();
4297 if ( bOldReschedule
)
4299 pInst
->EnableReschedule( false );
4300 bSetRescheduleBack
= true;
4304 SbxVariable
* p
= xScopeObj
->Find( aFunctionName
, SbxClassType::Method
);
4305 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4306 if( pMeth
== nullptr )
4308 // TODO: Check vba behavior concerning missing function
4309 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4315 sal_Int32 nParamCount
= rParams
.getLength();
4318 xArray
= new SbxArray
;
4319 const Any
*pArgs
= rParams
.getConstArray();
4320 for( sal_Int32 i
= 0 ; i
< nParamCount
; i
++ )
4322 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4323 unoToSbxValue( xVar
.get(), pArgs
[i
] );
4324 xArray
->Put( xVar
.get(), sal::static_int_cast
< sal_uInt16
>(i
+1) );
4329 SbxVariableRef xValue
= new SbxVariable
;
4331 pMeth
->SetParameters( xArray
.get() );
4332 pMeth
->Call( xValue
.get() );
4333 aRet
= sbxToUnoValue( xValue
.get() );
4334 pMeth
->SetParameters( nullptr );
4336 if( bSetRescheduleBack
)
4337 pInst
->EnableReschedule( bOldReschedule
);
4339 // TODO: OutParameter?
4344 void SAL_CALL
ModuleInvocationProxy::dispose()
4346 ::osl::MutexGuard
aGuard( m_aMutex
);
4348 EventObject
aEvent( static_cast<XComponent
*>(this) );
4349 m_aListeners
.disposeAndClear( aEvent
);
4351 m_xScopeObj
= nullptr;
4354 void SAL_CALL
ModuleInvocationProxy::addEventListener( const Reference
< XEventListener
>& xListener
)
4356 m_aListeners
.addInterface( xListener
);
4359 void SAL_CALL
ModuleInvocationProxy::removeEventListener( const Reference
< XEventListener
>& xListener
)
4361 m_aListeners
.removeInterface( xListener
);
4365 Reference
< XInterface
> createComListener( const Any
& aControlAny
, const OUString
& aVBAType
,
4366 const OUString
& aPrefix
, const SbxObjectRef
& xScopeObj
)
4368 Reference
< XInterface
> xRet
;
4370 Reference
< XComponentContext
> xContext(
4371 comphelper::getProcessComponentContext() );
4372 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4374 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPrefix
, xScopeObj
);
4376 Sequence
<Any
> args( 3 );
4377 args
[0] = aControlAny
;
4378 args
[1] <<= aVBAType
;
4383 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext(
4384 "com.sun.star.custom.UnoComListener",
4387 catch( const Exception
& )
4389 implHandleAnyException( ::cppu::getCaughtException() );
4395 typedef std::vector
< WeakReference
< XComponent
> > ComponentRefVector
;
4397 struct StarBasicDisposeItem
4399 StarBASIC
* m_pBasic
;
4400 SbxArrayRef m_pRegisteredVariables
;
4401 ComponentRefVector m_vComImplementsObjects
;
4403 explicit StarBasicDisposeItem( StarBASIC
* pBasic
)
4404 : m_pBasic( pBasic
)
4405 , m_pRegisteredVariables(new SbxArray())
4410 typedef std::vector
< StarBasicDisposeItem
* > DisposeItemVector
;
4412 static DisposeItemVector GaDisposeItemVector
;
4414 static DisposeItemVector::iterator
lcl_findItemForBasic( StarBASIC
const * pBasic
)
4416 return std::find_if(GaDisposeItemVector
.begin(), GaDisposeItemVector
.end(),
4417 [&pBasic
](StarBasicDisposeItem
* pItem
) { return pItem
->m_pBasic
== pBasic
; });
4420 static StarBasicDisposeItem
* lcl_getOrCreateItemForBasic( StarBASIC
* pBasic
)
4422 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4423 StarBasicDisposeItem
* pItem
= (it
!= GaDisposeItemVector
.end()) ? *it
: nullptr;
4424 if( pItem
== nullptr )
4426 pItem
= new StarBasicDisposeItem( pBasic
);
4427 GaDisposeItemVector
.push_back( pItem
);
4432 void registerComponentToBeDisposedForBasic
4433 ( const Reference
< XComponent
>& xComponent
, StarBASIC
* pBasic
)
4435 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4436 pItem
->m_vComImplementsObjects
.emplace_back(xComponent
);
4439 void registerComListenerVariableForBasic( SbxVariable
* pVar
, StarBASIC
* pBasic
)
4441 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4442 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4443 pArray
->Put( pVar
, pArray
->Count() );
4446 void disposeComVariablesForBasic( StarBASIC
const * pBasic
)
4448 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4449 if( it
!= GaDisposeItemVector
.end() )
4451 StarBasicDisposeItem
* pItem
= *it
;
4453 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4454 sal_uInt16 nCount
= pArray
->Count();
4455 for( sal_uInt16 i
= 0 ; i
< nCount
; ++i
)
4457 SbxVariable
* pVar
= pArray
->Get( i
);
4458 pVar
->ClearComListener();
4461 ComponentRefVector
& rv
= pItem
->m_vComImplementsObjects
;
4462 for (auto const& elem
: rv
)
4464 Reference
< XComponent
> xComponent( elem
.get(), UNO_QUERY
);
4465 if (xComponent
.is())
4466 xComponent
->dispose();
4470 GaDisposeItemVector
.erase( it
);
4475 // Handle module implements mechanism for OLE types
4476 bool SbModule::createCOMWrapperForIface( Any
& o_rRetAny
, SbClassModuleObject
* pProxyClassModuleObject
)
4478 // For now: Take first interface that allows to instantiate COM wrapper
4479 // TODO: Check if support for multiple interfaces is needed
4481 Reference
< XComponentContext
> xContext(
4482 comphelper::getProcessComponentContext() );
4483 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4484 Reference
< XSingleServiceFactory
> xComImplementsFactory
4486 xServiceMgr
->createInstanceWithContext( "com.sun.star.custom.ComImplementsFactory", xContext
),
4489 if( !xComImplementsFactory
.is() )
4492 bool bSuccess
= false;
4494 SbxArray
* pModIfaces
= pClassData
->mxIfaces
.get();
4495 sal_uInt16 nCount
= pModIfaces
->Count();
4496 for( sal_uInt16 i
= 0 ; i
< nCount
; ++i
)
4498 SbxVariable
* pVar
= pModIfaces
->Get( i
);
4499 const OUString
& aIfaceName
= pVar
->GetName();
4501 if( !aIfaceName
.isEmpty() )
4503 OUString aPureIfaceName
= aIfaceName
;
4504 sal_Int32 indexLastDot
= aIfaceName
.lastIndexOf('.');
4505 if ( indexLastDot
> -1 )
4507 aPureIfaceName
= aIfaceName
.copy( indexLastDot
+ 1 );
4509 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPureIfaceName
, pProxyClassModuleObject
);
4511 Sequence
<Any
> args( 2 );
4512 args
[0] <<= aIfaceName
;
4515 Reference
< XInterface
> xRet
;
4518 xRet
= xComImplementsFactory
->createInstanceWithArguments( args
);
4521 catch( const Exception
& )
4523 implHandleAnyException( ::cppu::getCaughtException() );
4528 Reference
< XComponent
> xComponent( xProxy
, UNO_QUERY
);
4529 if( xComponent
.is() )
4531 StarBASIC
* pParentBasic
= nullptr;
4532 SbxObject
* pCurObject
= this;
4535 SbxObject
* pObjParent
= pCurObject
->GetParent();
4536 pParentBasic
= dynamic_cast<StarBASIC
*>( pObjParent
);
4537 pCurObject
= pObjParent
;
4539 while( pParentBasic
== nullptr && pCurObject
!= nullptr );
4541 OSL_ASSERT( pParentBasic
!= nullptr );
4542 registerComponentToBeDisposedForBasic( xComponent
, pParentBasic
);
4555 // Due to an incorrect behavior IE returns an object instead of a string
4556 // in some scenarios. Calling toString at the object may correct this.
4557 // Helper function used in sbxvalue.cxx
4558 bool handleToStringForCOMObjects( SbxObject
* pObj
, SbxValue
* pVal
)
4560 bool bSuccess
= false;
4562 if( auto pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
) )
4564 // Only for native COM objects
4565 if( pUnoObj
->isNativeCOMObject() )
4567 SbxVariableRef pMeth
= pObj
->Find( "toString", SbxClassType::Method
);
4580 Any
StructRefInfo::getValue()
4584 &aRet
, reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4585 typelib_TypeDescription
* pTD
= nullptr;
4586 maType
.getDescription(&pTD
);
4588 &aRet
, getInst(), pTD
,
4589 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
) );
4590 typelib_typedescription_release(pTD
);
4594 void StructRefInfo::setValue( const Any
& rValue
)
4596 bool bSuccess
= uno_type_assignData( getInst(),
4597 maType
.getTypeLibType(),
4598 const_cast<void*>(rValue
.getValue()),
4599 rValue
.getValueTypeRef(),
4600 reinterpret_cast< uno_QueryInterfaceFunc
>(cpp_queryInterface
),
4601 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
),
4602 reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4603 OSL_ENSURE(bSuccess
,
4604 "StructRefInfo::setValue: ooops... the value could not be assigned!");
4607 OUString
StructRefInfo::getTypeName() const
4609 return maType
.getTypeName();
4612 void* StructRefInfo::getInst()
4614 return const_cast<char *>(static_cast<char const *>(maAny
.getValue()) + mnPos
);
4617 TypeClass
StructRefInfo::getTypeClass() const
4619 return maType
.getTypeClass();
4622 SbUnoStructRefObject::SbUnoStructRefObject( const OUString
& aName_
, const StructRefInfo
& rMemberInfo
) : SbxObject( aName_
), maMemberInfo( rMemberInfo
), mbMemberCacheInit( false )
4624 SetClassName( maMemberInfo
.getTypeName() );
4627 SbUnoStructRefObject::~SbUnoStructRefObject()
4631 void SbUnoStructRefObject::initMemberCache()
4633 if ( mbMemberCacheInit
)
4635 typelib_TypeDescription
* pTD
= nullptr;
4636 maMemberInfo
.getType().getDescription(&pTD
);
4637 typelib_CompoundTypeDescription
* pCompTypeDescr
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTD
);
4638 for ( pCompTypeDescr
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTD
); pCompTypeDescr
;
4639 pCompTypeDescr
= pCompTypeDescr
->pBaseTypeDescription
)
4641 typelib_TypeDescriptionReference
** ppTypeRefs
= pCompTypeDescr
->ppTypeRefs
;
4642 rtl_uString
** ppNames
= pCompTypeDescr
->ppMemberNames
;
4643 sal_Int32
* pMemberOffsets
= pCompTypeDescr
->pMemberOffsets
;
4644 for ( sal_Int32 nPos
= pCompTypeDescr
->nMembers
; nPos
--; )
4646 OUString
aName( ppNames
[nPos
] );
4647 maFields
[ aName
] = std::make_unique
<StructRefInfo
>( maMemberInfo
.getRootAnyRef(), ppTypeRefs
[nPos
], maMemberInfo
.getPos() + pMemberOffsets
[nPos
] );
4650 typelib_typedescription_release(pTD
);
4651 mbMemberCacheInit
= true;
4654 SbxVariable
* SbUnoStructRefObject::Find( const OUString
& rName
, SbxClassType t
)
4656 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
4659 if ( !mbMemberCacheInit
)
4661 StructFieldInfo::iterator it
= maFields
.find( rName
);
4662 if ( it
!= maFields
.end() )
4664 SbxDataType eSbxType
;
4665 eSbxType
= unoToSbxType( it
->second
->getTypeClass() );
4666 SbxDataType eRealSbxType
= eSbxType
;
4669 aProp
.Type
= css::uno::Type( it
->second
->getTypeClass(), it
->second
->getTypeName() );
4670 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, aProp
, 0, false, ( aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
4671 SbxVariableRef xVarRef
= pProp
;
4672 QuickInsert( xVarRef
.get() );
4673 pRes
= xVarRef
.get();
4679 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
4680 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
4681 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
4684 implCreateDbgProperties();
4686 // Now they have to be found regular
4687 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
4694 // help method to create the dbg_-Properties
4695 void SbUnoStructRefObject::implCreateDbgProperties()
4699 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4700 SbxVariableRef xVarRef
= new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES
, SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
4701 QuickInsert( xVarRef
.get() );
4703 // Id == -2: output the properties
4704 xVarRef
= new SbUnoProperty( ID_DBG_PROPERTIES
, SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
4705 QuickInsert( xVarRef
.get() );
4707 // Id == -3: output the Methods
4708 xVarRef
= new SbUnoProperty( ID_DBG_METHODS
, SbxSTRING
, SbxSTRING
, aProp
, -3, false, false );
4709 QuickInsert( xVarRef
.get() );
4712 void SbUnoStructRefObject::implCreateAll()
4714 // throw away all existing methods and properties
4715 pMethods
= new SbxArray
;
4716 pProps
= new SbxArray
;
4718 if (!mbMemberCacheInit
)
4721 for (auto const& field
: maFields
)
4723 const OUString
& rName
= field
.first
;
4724 SbxDataType eSbxType
;
4725 eSbxType
= unoToSbxType( field
.second
->getTypeClass() );
4726 SbxDataType eRealSbxType
= eSbxType
;
4729 aProp
.Type
= css::uno::Type( field
.second
->getTypeClass(), field
.second
->getTypeName() );
4730 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, aProp
, 0, false, ( aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
4731 SbxVariableRef xVarRef
= pProp
;
4732 QuickInsert( xVarRef
.get() );
4735 // Create Dbg_-Properties
4736 implCreateDbgProperties();
4740 Any
SbUnoStructRefObject::getUnoAny()
4742 return maMemberInfo
.getValue();
4745 OUString
SbUnoStructRefObject::Impl_DumpProperties()
4747 OUStringBuffer aRet
;
4748 aRet
.append("Properties of object ");
4749 aRet
.append( getDbgObjectName() );
4751 sal_uInt16 nPropCount
= pProps
->Count();
4752 sal_uInt16 nPropsPerLine
= 1 + nPropCount
/ 30;
4753 for( sal_uInt16 i
= 0; i
< nPropCount
; i
++ )
4755 SbxVariable
* pVar
= pProps
->Get( i
);
4758 OUStringBuffer aPropStr
;
4759 if( (i
% nPropsPerLine
) == 0 )
4761 aPropStr
.append( "\n" );
4763 // output the type and name
4764 // Is it in Uno a sequence?
4765 SbxDataType eType
= pVar
->GetFullType();
4767 const OUString
& aName( pVar
->GetName() );
4768 StructFieldInfo::iterator it
= maFields
.find( aName
);
4770 if ( it
!= maFields
.end() )
4772 const StructRefInfo
& rPropInfo
= *it
->second
;
4774 if( eType
== SbxOBJECT
)
4776 if( rPropInfo
.getTypeClass() == TypeClass_SEQUENCE
)
4778 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
4782 aPropStr
.append( Dbg_SbxDataType2String( eType
) );
4784 aPropStr
.append( " " );
4785 aPropStr
.append( pVar
->GetName() );
4787 if( i
== nPropCount
- 1 )
4789 aPropStr
.append( "\n" );
4793 aPropStr
.append( "; " );
4795 aRet
.append( aPropStr
.makeStringAndClear() );
4798 return aRet
.makeStringAndClear();
4801 void SbUnoStructRefObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
4803 if ( !mbMemberCacheInit
)
4805 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
4808 SbxVariable
* pVar
= pHint
->GetVar();
4809 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
4812 StructFieldInfo::iterator it
= maFields
.find( pProp
->GetName() );
4813 // handle get/set of members of struct
4814 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
4817 sal_Int32 nId
= pProp
->nId
;
4820 // Id == -1: Display implemented interfaces according the ClassProvider
4821 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
4823 OUString aRet
= OUStringLiteral( ID_DBG_SUPPORTEDINTERFACES
)
4824 + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n";
4826 pVar
->PutString( aRet
);
4828 // Id == -2: output properties
4829 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
4831 // by now all properties must be established
4833 OUString aRetStr
= Impl_DumpProperties();
4834 pVar
->PutString( aRetStr
);
4836 // Id == -3: output the methods
4837 else if( nId
== -3 ) // Property ID_DBG_METHODS
4839 // by now all properties must be established
4841 OUString aRet
= "Methods of object "
4842 + getDbgObjectName()
4843 + "\nNo methods found\n";
4844 pVar
->PutString( aRet
);
4849 if ( it
!= maFields
.end() )
4851 Any aRetAny
= it
->second
->getValue();
4852 unoToSbxValue( pVar
, aRetAny
);
4855 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4857 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
4859 if ( it
!= maFields
.end() )
4861 // take over the value from Uno to Sbx
4862 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
4863 it
->second
->setValue( aAnyValue
);
4866 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4870 SbxObject::Notify( rBC
, rHint
);
4874 StructRefInfo
SbUnoStructRefObject::getStructMember( const OUString
& rMemberName
)
4876 if (!mbMemberCacheInit
)
4880 StructFieldInfo::iterator it
= maFields
.find( rMemberName
);
4882 css::uno::Type aFoundType
;
4883 sal_Int32 nFoundPos
= -1;
4885 if ( it
!= maFields
.end() )
4887 aFoundType
= it
->second
->getType();
4888 nFoundPos
= it
->second
->getPos();
4890 StructRefInfo
aRet( maMemberInfo
.getRootAnyRef(), aFoundType
, nFoundPos
);
4894 OUString
SbUnoStructRefObject::getDbgObjectName() const
4896 OUString aName
= GetClassName();
4897 if( aName
.isEmpty() )
4901 OUStringBuffer aRet
;
4902 if( aName
.getLength() > 20 )
4904 aRet
.append( "\n" );
4906 aRet
.append( "\"" );
4907 aRet
.append( aName
);
4908 aRet
.append( "\":" );
4909 return aRet
.makeStringAndClear();
4912 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */