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/math.hxx>
37 #include <rtl/ustrbuf.hxx>
39 #include <com/sun/star/script/ArrayWrapper.hpp>
40 #include <com/sun/star/script/CannotConvertException.hpp>
41 #include <com/sun/star/script/NativeObjectWrapper.hpp>
43 #include <com/sun/star/uno/XComponentContext.hpp>
44 #include <com/sun/star/uno/DeploymentException.hpp>
45 #include <com/sun/star/lang/XTypeProvider.hpp>
46 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/lang/XServiceInfo.hpp>
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/beans/PropertyConcept.hpp>
51 #include <com/sun/star/beans/MethodConcept.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/theIntrospection.hpp>
54 #include <com/sun/star/script/BasicErrorException.hpp>
55 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
56 #include <com/sun/star/script/XAllListener.hpp>
57 #include <com/sun/star/script/Converter.hpp>
58 #include <com/sun/star/script/XDefaultProperty.hpp>
59 #include <com/sun/star/script/XDirectInvocation.hpp>
60 #include <com/sun/star/container/XNameAccess.hpp>
61 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
62 #include <com/sun/star/reflection/XIdlArray.hpp>
63 #include <com/sun/star/reflection/XIdlReflection.hpp>
64 #include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
65 #include <com/sun/star/reflection/XSingletonTypeDescription.hpp>
66 #include <com/sun/star/reflection/theCoreReflection.hpp>
67 #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp>
68 #include <com/sun/star/bridge/oleautomation/Date.hpp>
69 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
70 #include <com/sun/star/bridge/oleautomation/Currency.hpp>
71 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
72 #include <com/sun/star/script/XAutomationInvocation.hpp>
74 #include <rtlproto.hxx>
76 #include <basic/sbstar.hxx>
77 #include <basic/sbuno.hxx>
78 #include <basic/sberrors.hxx>
79 #include <sbunoobj.hxx>
80 #include <sbintern.hxx>
81 #include <runtime.hxx>
86 #include <unordered_map>
87 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
88 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
90 using com::sun::star::uno::Reference
;
91 using namespace com::sun::star::uno
;
92 using namespace com::sun::star::lang
;
93 using namespace com::sun::star::reflection
;
94 using namespace com::sun::star::beans
;
95 using namespace com::sun::star::script
;
96 using namespace com::sun::star::container
;
97 using namespace com::sun::star::bridge
;
101 // Identifiers for creating the strings for dbg_Properties
102 char16_t
constexpr ID_DBG_SUPPORTEDINTERFACES
[] = u
"Dbg_SupportedInterfaces";
103 char const ID_DBG_PROPERTIES
[] = "Dbg_Properties";
104 char const ID_DBG_METHODS
[] = "Dbg_Methods";
106 char const aSeqLevelStr
[] = "[]";
108 // Gets the default property for a uno object. Note: There is some
109 // redirection built in. The property name specifies the name
110 // of the default property.
112 bool SbUnoObject::getDefaultPropName( SbUnoObject
const * pUnoObj
, OUString
& sDfltProp
)
114 bool bResult
= false;
115 Reference
< XDefaultProperty
> xDefaultProp( pUnoObj
->maTmpUnoObj
, UNO_QUERY
);
116 if ( xDefaultProp
.is() )
118 sDfltProp
= xDefaultProp
->getDefaultPropertyName();
119 if ( !sDfltProp
.isEmpty() )
125 SbxVariable
* getDefaultProp( SbxVariable
* pRef
)
127 SbxVariable
* pDefaultProp
= nullptr;
128 if ( pRef
->GetType() == SbxOBJECT
)
130 SbxObject
* pObj
= dynamic_cast<SbxObject
*>(pRef
);
133 SbxBase
* pObjVarObj
= pRef
->GetObject();
134 pObj
= dynamic_cast<SbxObject
*>( pObjVarObj
);
136 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
138 pDefaultProp
= pUnoObj
->GetDfltProperty();
144 void SetSbUnoObjectDfltPropName( SbxObject
* pObj
)
146 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
149 OUString sDfltPropName
;
151 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
153 pUnoObj
->SetDfltProperty( sDfltPropName
);
158 // save CoreReflection statically
159 static Reference
< XIdlReflection
> getCoreReflection_Impl()
161 return css::reflection::theCoreReflection::get(
162 comphelper::getProcessComponentContext());
165 // save CoreReflection statically
166 static Reference
< XHierarchicalNameAccess
> const & getCoreReflection_HierarchicalNameAccess_Impl()
168 static Reference
< XHierarchicalNameAccess
> xCoreReflection_HierarchicalNameAccess
;
170 if( !xCoreReflection_HierarchicalNameAccess
.is() )
172 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
173 if( xCoreReflection
.is() )
175 xCoreReflection_HierarchicalNameAccess
=
176 Reference
< XHierarchicalNameAccess
>( xCoreReflection
, UNO_QUERY
);
179 return xCoreReflection_HierarchicalNameAccess
;
182 // Hold TypeProvider statically
183 static Reference
< XHierarchicalNameAccess
> const & getTypeProvider_Impl()
185 static Reference
< XHierarchicalNameAccess
> xAccess
;
187 // Do we have already CoreReflection; if not obtain it
190 Reference
< XComponentContext
> xContext(
191 comphelper::getProcessComponentContext() );
194 xContext
->getValueByName(
195 "/singletons/com.sun.star.reflection.theTypeDescriptionManager" )
197 OSL_ENSURE( xAccess
.is(), "### TypeDescriptionManager singleton not accessible!?" );
201 throw DeploymentException(
202 "/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible" );
208 // Hold TypeConverter statically
209 static Reference
< XTypeConverter
> const & getTypeConverter_Impl()
211 static Reference
< XTypeConverter
> xTypeConverter
;
213 // Do we have already CoreReflection; if not obtain it
214 if( !xTypeConverter
.is() )
216 Reference
< XComponentContext
> xContext(
217 comphelper::getProcessComponentContext() );
220 xTypeConverter
= Converter::create(xContext
);
222 if( !xTypeConverter
.is() )
224 throw DeploymentException(
225 "com.sun.star.script.Converter service not accessible" );
228 return xTypeConverter
;
232 // #111851 factory function to create an OLE object
233 SbUnoObject
* createOLEObject_Impl( const OUString
& aType
)
235 static Reference
< XMultiServiceFactory
> xOLEFactory
;
236 static bool bNeedsInit
= true;
242 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
245 Reference
<XMultiComponentFactory
> xSMgr
= xContext
->getServiceManager();
247 xSMgr
->createInstanceWithContext( "com.sun.star.bridge.OleObjectFactory", xContext
),
252 SbUnoObject
* pUnoObj
= nullptr;
253 if( xOLEFactory
.is() )
255 // some type names available in VBA can not be directly used in COM
256 OUString aOLEType
= aType
;
257 if ( aOLEType
== "SAXXMLReader30" )
259 aOLEType
= "Msxml2.SAXXMLReader.3.0";
261 Reference
< XInterface
> xOLEObject
= xOLEFactory
->createInstance( aOLEType
);
262 if( xOLEObject
.is() )
264 pUnoObj
= new SbUnoObject( aType
, Any(xOLEObject
) );
265 OUString sDfltPropName
;
267 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
268 pUnoObj
->SetDfltProperty( sDfltPropName
);
277 void lcl_indent( OUStringBuffer
& _inout_rBuffer
, sal_Int32 _nLevel
)
279 while ( _nLevel
-- > 0 )
281 _inout_rBuffer
.append( " " );
286 static void implAppendExceptionMsg( OUStringBuffer
& _inout_rBuffer
, const Exception
& _e
, const OUString
& _rExceptionType
, sal_Int32 _nLevel
)
288 _inout_rBuffer
.append( "\n" );
289 lcl_indent( _inout_rBuffer
, _nLevel
);
290 _inout_rBuffer
.append( "Type: " );
292 if ( _rExceptionType
.isEmpty() )
293 _inout_rBuffer
.append( "Unknown" );
295 _inout_rBuffer
.append( _rExceptionType
);
297 _inout_rBuffer
.append( "\n" );
298 lcl_indent( _inout_rBuffer
, _nLevel
);
299 _inout_rBuffer
.append( "Message: " );
300 _inout_rBuffer
.append( _e
.Message
);
304 // construct an error message for the exception
305 static OUString
implGetExceptionMsg( const Exception
& e
, const OUString
& aExceptionType_
)
307 OUStringBuffer aMessageBuf
;
308 implAppendExceptionMsg( aMessageBuf
, e
, aExceptionType_
, 0 );
309 return aMessageBuf
.makeStringAndClear();
312 static OUString
implGetExceptionMsg( const Any
& _rCaughtException
)
314 auto e
= o3tl::tryAccess
<Exception
>(_rCaughtException
);
315 OSL_PRECOND( e
, "implGetExceptionMsg: illegal argument!" );
320 return implGetExceptionMsg( *e
, _rCaughtException
.getValueTypeName() );
323 static Any
convertAny( const Any
& rVal
, const Type
& aDestType
)
326 const Reference
< XTypeConverter
>& xConverter
= getTypeConverter_Impl();
329 aConvertedVal
= xConverter
->convertTo( rVal
, aDestType
);
331 catch( const IllegalArgumentException
& )
333 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
334 implGetExceptionMsg( ::cppu::getCaughtException() ) );
335 return aConvertedVal
;
337 catch( const CannotConvertException
& e2
)
339 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
340 implGetExceptionMsg( e2
, "com.sun.star.lang.IllegalArgumentException" ) );
341 return aConvertedVal
;
343 return aConvertedVal
;
347 // #105565 Special Object to wrap a strongly typed Uno Any
350 // TODO: source out later
351 static Reference
<XIdlClass
> TypeToIdlClass( const Type
& rType
)
353 return getCoreReflection_Impl()->forName(rType
.getTypeName());
356 // Exception type unknown
357 template< class EXCEPTION
>
358 static OUString
implGetExceptionMsg( const EXCEPTION
& e
)
360 return implGetExceptionMsg( e
, cppu::UnoType
<decltype(e
)>::get().getTypeName() );
363 static void implHandleBasicErrorException( BasicErrorException
const & e
)
365 ErrCode nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(e
.ErrorCode
) );
366 StarBASIC::Error( nError
, e
.ErrorMessageArgument
);
369 static void implHandleWrappedTargetException( const Any
& _rWrappedTargetException
)
371 Any
aExamine( _rWrappedTargetException
);
373 // completely strip the first InvocationTargetException, its error message isn't of any
374 // interest to the user, it just says something like "invoking the UNO method went wrong.".
375 InvocationTargetException aInvocationError
;
376 if ( aExamine
>>= aInvocationError
)
377 aExamine
= aInvocationError
.TargetException
;
379 BasicErrorException aBasicError
;
381 ErrCode
nError( ERRCODE_BASIC_EXCEPTION
);
382 OUStringBuffer aMessageBuf
;
384 // strip any other WrappedTargetException instances, but this time preserve the error messages.
385 WrappedTargetException aWrapped
;
386 sal_Int32 nLevel
= 0;
387 while ( aExamine
>>= aWrapped
)
389 // special handling for BasicErrorException errors
390 if ( aWrapped
.TargetException
>>= aBasicError
)
392 nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(aBasicError
.ErrorCode
) );
393 aMessageBuf
.append( aBasicError
.ErrorMessageArgument
);
398 // append this round's message
399 implAppendExceptionMsg( aMessageBuf
, aWrapped
, aExamine
.getValueTypeName(), nLevel
);
400 if ( aWrapped
.TargetException
.getValueTypeClass() == TypeClass_EXCEPTION
)
401 // there is a next chain element
402 aMessageBuf
.append( "\nTargetException:" );
405 aExamine
= aWrapped
.TargetException
;
409 if ( auto e
= o3tl::tryAccess
<Exception
>(aExamine
) )
411 // the last element in the chain is still an exception, but no WrappedTargetException
412 implAppendExceptionMsg( aMessageBuf
, *e
, aExamine
.getValueTypeName(), nLevel
);
415 StarBASIC::Error( nError
, aMessageBuf
.makeStringAndClear() );
418 static void implHandleAnyException( const Any
& _rCaughtException
)
420 BasicErrorException aBasicError
;
421 WrappedTargetException aWrappedError
;
423 if ( _rCaughtException
>>= aBasicError
)
425 implHandleBasicErrorException( aBasicError
);
427 else if ( _rCaughtException
>>= aWrappedError
)
429 implHandleWrappedTargetException( _rCaughtException
);
433 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( _rCaughtException
) );
439 // NativeObjectWrapper handling
442 SbxObjectRef m_xNativeObj
;
444 explicit ObjectItem( SbxObject
* pNativeObj
)
445 : m_xNativeObj( pNativeObj
)
451 typedef std::vector
< ObjectItem
> NativeObjectWrapperVector
;
455 class GaNativeObjectWrapperVector
: public rtl::Static
<NativeObjectWrapperVector
, GaNativeObjectWrapperVector
> {};
459 void clearNativeObjectWrapperVector()
461 GaNativeObjectWrapperVector::get().clear();
464 static sal_uInt32
lcl_registerNativeObjectWrapper( SbxObject
* pNativeObj
)
466 NativeObjectWrapperVector
&rNativeObjectWrapperVector
= GaNativeObjectWrapperVector::get();
467 sal_uInt32 nIndex
= rNativeObjectWrapperVector
.size();
468 rNativeObjectWrapperVector
.emplace_back( pNativeObj
);
472 static SbxObject
* lcl_getNativeObject( sal_uInt32 nIndex
)
474 SbxObjectRef xRetObj
;
475 NativeObjectWrapperVector
&rNativeObjectWrapperVector
= GaNativeObjectWrapperVector::get();
476 if( nIndex
< rNativeObjectWrapperVector
.size() )
478 ObjectItem
& rItem
= rNativeObjectWrapperVector
[ nIndex
];
479 xRetObj
= rItem
.m_xNativeObj
;
481 return xRetObj
.get();
484 // convert from Uno to Sbx
485 static SbxDataType
unoToSbxType( TypeClass eType
)
487 SbxDataType eRetType
= SbxVOID
;
491 case TypeClass_INTERFACE
:
493 case TypeClass_STRUCT
:
494 case TypeClass_EXCEPTION
: eRetType
= SbxOBJECT
; break;
496 case TypeClass_ENUM
: eRetType
= SbxLONG
; break;
497 case TypeClass_SEQUENCE
:
498 eRetType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
502 case TypeClass_ANY
: eRetType
= SbxVARIANT
; break;
503 case TypeClass_BOOLEAN
: eRetType
= SbxBOOL
; break;
504 case TypeClass_CHAR
: eRetType
= SbxCHAR
; break;
505 case TypeClass_STRING
: eRetType
= SbxSTRING
; break;
506 case TypeClass_FLOAT
: eRetType
= SbxSINGLE
; break;
507 case TypeClass_DOUBLE
: eRetType
= SbxDOUBLE
; break;
508 case TypeClass_BYTE
: eRetType
= SbxINTEGER
; break;
509 case TypeClass_SHORT
: eRetType
= SbxINTEGER
; break;
510 case TypeClass_LONG
: eRetType
= SbxLONG
; break;
511 case TypeClass_HYPER
: eRetType
= SbxSALINT64
; break;
512 case TypeClass_UNSIGNED_SHORT
: eRetType
= SbxUSHORT
; break;
513 case TypeClass_UNSIGNED_LONG
: eRetType
= SbxULONG
; break;
514 case TypeClass_UNSIGNED_HYPER
: eRetType
= SbxSALUINT64
;break;
520 static SbxDataType
unoToSbxType( const Reference
< XIdlClass
>& xIdlClass
)
522 SbxDataType eRetType
= SbxVOID
;
525 TypeClass eType
= xIdlClass
->getTypeClass();
526 eRetType
= unoToSbxType( eType
);
531 static void implSequenceToMultiDimArray( SbxDimArray
*& pArray
, Sequence
< sal_Int32
>& indices
, Sequence
< sal_Int32
>& sizes
, const Any
& aValue
, sal_Int32 dimension
, bool bIsZeroIndex
, Type
const * pType
)
533 const Type
& aType
= aValue
.getValueType();
534 TypeClass eTypeClass
= aType
.getTypeClass();
536 sal_Int32 dimCopy
= dimension
;
538 if ( eTypeClass
== TypeClass_SEQUENCE
)
540 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
541 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
542 typelib_TypeDescription
* pTD
= nullptr;
543 aType
.getDescription( &pTD
);
544 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
545 ::typelib_typedescription_release( pTD
);
547 sal_Int32 nLen
= xIdlArray
->getLen( aValue
);
548 for ( sal_Int32 index
= 0; index
< nLen
; ++index
)
550 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(index
) );
551 // This detects the dimension were currently processing
552 if ( dimCopy
== dimension
)
555 if ( sizes
.getLength() < dimCopy
)
557 sizes
.realloc( sizes
.getLength() + 1 );
558 sizes
[ sizes
.getLength() - 1 ] = nLen
;
559 indices
.realloc( indices
.getLength() + 1 );
564 indices
[ dimCopy
- 1 ] = index
;
566 indices
[ dimCopy
- 1] = index
+ 1;
568 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aElementAny
, dimCopy
, bIsZeroIndex
, &aElementType
);
574 if ( !indices
.hasElements() )
576 // Should never ever get here ( indices.getLength()
577 // should equal number of dimensions in the array )
578 // And that should at least be 1 !
579 // #QUESTION is there a better error?
580 StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT
);
584 SbxDataType eSbxElementType
= unoToSbxType( pType
? pType
->getTypeClass() : aValue
.getValueTypeClass() );
587 pArray
= new SbxDimArray( eSbxElementType
);
588 sal_Int32 nIndexLen
= indices
.getLength();
590 // Dimension the array
591 for ( sal_Int32 index
= 0; index
< nIndexLen
; ++index
)
594 pArray
->unoAddDim32( 0, sizes
[ index
] - 1);
596 pArray
->unoAddDim32( 1, sizes
[ index
] );
603 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
604 unoToSbxValue( xVar
.get(), aValue
);
606 sal_Int32
* pIndices
= indices
.getArray();
607 pArray
->Put32( xVar
.get(), pIndices
);
613 void unoToSbxValue( SbxVariable
* pVar
, const Any
& aValue
)
615 const Type
& aType
= aValue
.getValueType();
616 TypeClass eTypeClass
= aType
.getTypeClass();
621 // Map Type to IdlClass
624 Reference
<XIdlClass
> xClass
= TypeToIdlClass( aType_
);
626 aClassAny
<<= xClass
;
628 // instantiate SbUnoObject
629 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aClassAny
);
630 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
632 // If the object is invalid deliver null
633 if( !pSbUnoObject
->getUnoAny().hasValue() )
635 pVar
->PutObject( nullptr );
639 pVar
->PutObject( xWrapper
.get() );
643 // Interfaces and Structs must be wrapped in a SbUnoObject
644 case TypeClass_INTERFACE
:
645 case TypeClass_STRUCT
:
646 case TypeClass_EXCEPTION
:
648 if( eTypeClass
== TypeClass_STRUCT
)
651 NativeObjectWrapper aNativeObjectWrapper
;
652 if ( aValue
>>= aWrap
)
654 SbxDimArray
* pArray
= nullptr;
655 Sequence
< sal_Int32
> indices
;
656 Sequence
< sal_Int32
> sizes
;
657 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aWrap
.Array
, /*dimension*/0, aWrap
.IsZeroIndex
, nullptr );
660 SbxDimArrayRef xArray
= pArray
;
661 SbxFlagBits nFlags
= pVar
->GetFlags();
662 pVar
->ResetFlag( SbxFlagBits::Fixed
);
663 pVar
->PutObject( xArray
.get() );
664 pVar
->SetFlags( nFlags
);
670 else if ( aValue
>>= aNativeObjectWrapper
)
672 sal_uInt32 nIndex
= 0;
673 if( aNativeObjectWrapper
.ObjectId
>>= nIndex
)
675 SbxObject
* pObj
= lcl_getNativeObject( nIndex
);
676 pVar
->PutObject( pObj
);
684 SbiInstance
* pInst
= GetSbData()->pInst
;
685 if( pInst
&& pInst
->IsCompatibility() )
687 oleautomation::Date aDate
;
688 if( aValue
>>= aDate
)
690 pVar
->PutDate( aDate
.Value
);
695 oleautomation::Decimal aDecimal
;
696 if( aValue
>>= aDecimal
)
698 pVar
->PutDecimal( aDecimal
);
703 oleautomation::Currency aCurrency
;
704 if( aValue
>>= aCurrency
)
706 pVar
->PutCurrency( aCurrency
.Value
);
714 // instantiate a SbUnoObject
715 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aValue
);
716 //If this is called externally e.g. from the scripting
717 //framework then there is no 'active' runtime the default property will not be set up
718 //only a vba object will have XDefaultProp set anyway so... this
719 //test seems a bit of overkill
720 //if ( SbiRuntime::isVBAEnabled() )
722 OUString sDfltPropName
;
724 if ( SbUnoObject::getDefaultPropName( pSbUnoObject
, sDfltPropName
) )
726 pSbUnoObject
->SetDfltProperty( sDfltPropName
);
729 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
731 // If the object is invalid deliver null
732 if( !pSbUnoObject
->getUnoAny().hasValue() )
734 pVar
->PutObject( nullptr );
738 pVar
->PutObject( xWrapper
.get() );
747 enum2int( nEnum
, aValue
);
748 pVar
->PutLong( nEnum
);
752 case TypeClass_SEQUENCE
:
754 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
755 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
756 sal_Int32 i
, nLen
= xIdlArray
->getLen( aValue
);
758 typelib_TypeDescription
* pTD
= nullptr;
759 aType
.getDescription( &pTD
);
760 assert( pTD
&& pTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
);
761 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
762 ::typelib_typedescription_release( pTD
);
764 // build an Array in Basic
765 SbxDimArrayRef xArray
;
766 SbxDataType eSbxElementType
= unoToSbxType( aElementType
.getTypeClass() );
767 xArray
= new SbxDimArray( eSbxElementType
);
770 xArray
->unoAddDim32( 0, nLen
- 1 );
772 // register the elements as variables
773 for( i
= 0 ; i
< nLen
; i
++ )
776 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(i
) );
777 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
778 unoToSbxValue( xVar
.get(), aElementAny
);
780 // put into the Array
781 xArray
->Put32( xVar
.get(), &i
);
786 xArray
->unoAddDim32( 0, -1 );
790 SbxFlagBits nFlags
= pVar
->GetFlags();
791 pVar
->ResetFlag( SbxFlagBits::Fixed
);
792 pVar
->PutObject( xArray
.get() );
793 pVar
->SetFlags( nFlags
);
799 case TypeClass_BOOLEAN
: pVar
->PutBool( *o3tl::forceAccess
<bool>(aValue
) ); break;
802 pVar
->PutChar( *o3tl::forceAccess
<sal_Unicode
>(aValue
) );
805 case TypeClass_STRING
: { OUString val
; aValue
>>= val
; pVar
->PutString( val
); } break;
806 case TypeClass_FLOAT
: { float val
= 0; aValue
>>= val
; pVar
->PutSingle( val
); } break;
807 case TypeClass_DOUBLE
: { double val
= 0; aValue
>>= val
; pVar
->PutDouble( val
); } break;
808 case TypeClass_BYTE
: { sal_Int8 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
809 case TypeClass_SHORT
: { sal_Int16 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
810 case TypeClass_LONG
: { sal_Int32 val
= 0; aValue
>>= val
; pVar
->PutLong( val
); } break;
811 case TypeClass_HYPER
: { sal_Int64 val
= 0; aValue
>>= val
; pVar
->PutInt64( val
); } break;
812 case TypeClass_UNSIGNED_SHORT
: { sal_uInt16 val
= 0; aValue
>>= val
; pVar
->PutUShort( val
); } break;
813 case TypeClass_UNSIGNED_LONG
: { sal_uInt32 val
= 0; aValue
>>= val
; pVar
->PutULong( val
); } break;
814 case TypeClass_UNSIGNED_HYPER
: { sal_uInt64 val
= 0; aValue
>>= val
; pVar
->PutUInt64( val
); } break;
815 default: pVar
->PutEmpty(); break;
819 // Deliver the reflection for Sbx types
820 static Type
getUnoTypeForSbxBaseType( SbxDataType eType
)
822 Type aRetType
= cppu::UnoType
<void>::get();
825 case SbxNULL
: aRetType
= cppu::UnoType
<XInterface
>::get(); break;
826 case SbxINTEGER
: aRetType
= cppu::UnoType
<sal_Int16
>::get(); break;
827 case SbxLONG
: aRetType
= cppu::UnoType
<sal_Int32
>::get(); break;
828 case SbxSINGLE
: aRetType
= cppu::UnoType
<float>::get(); break;
829 case SbxDOUBLE
: aRetType
= cppu::UnoType
<double>::get(); break;
830 case SbxCURRENCY
: aRetType
= cppu::UnoType
<oleautomation::Currency
>::get(); break;
831 case SbxDECIMAL
: aRetType
= cppu::UnoType
<oleautomation::Decimal
>::get(); break;
833 SbiInstance
* pInst
= GetSbData()->pInst
;
834 if( pInst
&& pInst
->IsCompatibility() )
835 aRetType
= cppu::UnoType
<double>::get();
837 aRetType
= cppu::UnoType
<oleautomation::Date
>::get();
840 case SbxSTRING
: aRetType
= cppu::UnoType
<OUString
>::get(); break;
841 case SbxBOOL
: aRetType
= cppu::UnoType
<sal_Bool
>::get(); break;
842 case SbxVARIANT
: aRetType
= cppu::UnoType
<Any
>::get(); break;
843 case SbxCHAR
: aRetType
= cppu::UnoType
<cppu::UnoCharType
>::get(); break;
844 case SbxBYTE
: aRetType
= cppu::UnoType
<sal_Int8
>::get(); break;
845 case SbxUSHORT
: aRetType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get(); break;
846 case SbxULONG
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
847 // map machine-dependent ones to long for consistency
848 case SbxINT
: aRetType
= ::cppu::UnoType
<sal_Int32
>::get(); break;
849 case SbxUINT
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
855 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
856 static Type
getUnoTypeForSbxValue( const SbxValue
* pVal
)
858 Type aRetType
= cppu::UnoType
<void>::get();
862 // convert SbxType to Uno
863 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
864 if( eBaseType
== SbxOBJECT
)
866 SbxBaseRef xObj
= pVal
->GetObject();
869 aRetType
= cppu::UnoType
<XInterface
>::get();
873 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
875 sal_Int32 nDims
= pArray
->GetDims32();
876 Type aElementType
= getUnoTypeForSbxBaseType( static_cast<SbxDataType
>(pArray
->GetType() & 0xfff) );
877 TypeClass eElementTypeClass
= aElementType
.getTypeClass();
879 // Normal case: One dimensional array
880 sal_Int32 nLower
, nUpper
;
881 if( nDims
== 1 && pArray
->GetDim32( 1, nLower
, nUpper
) )
883 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
885 // If all elements of the arrays are from the same type, take
886 // this one - otherwise the whole will be considered as Any-Sequence
887 bool bNeedsInit
= true;
889 for (sal_Int32 aIdx
[1] = { nLower
}; aIdx
[0] <= nUpper
; ++aIdx
[0])
891 SbxVariableRef xVar
= pArray
->Get32(aIdx
);
892 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
895 if( aType
.getTypeClass() == TypeClass_VOID
)
897 // if only first element is void: different types -> []any
898 // if all elements are void: []void is not allowed -> []any
899 aElementType
= cppu::UnoType
<Any
>::get();
902 aElementType
= aType
;
905 else if( aElementType
!= aType
)
907 // different types -> AnySequence
908 aElementType
= cppu::UnoType
<Any
>::get();
914 OUString aSeqTypeName
= aSeqLevelStr
+ aElementType
.getTypeName();
915 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
);
917 // #i33795 Map also multi dimensional arrays to corresponding sequences
920 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
922 // For this check the array's dim structure does not matter
923 sal_uInt32 nFlatArraySize
= pArray
->Count32();
925 bool bNeedsInit
= true;
926 for( sal_uInt32 i
= 0 ; i
< nFlatArraySize
; i
++ )
928 SbxVariableRef xVar
= pArray
->SbxArray::Get32( i
);
929 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
932 if( aType
.getTypeClass() == TypeClass_VOID
)
934 // if only first element is void: different types -> []any
935 // if all elements are void: []void is not allowed -> []any
936 aElementType
= cppu::UnoType
<Any
>::get();
939 aElementType
= aType
;
942 else if( aElementType
!= aType
)
944 // different types -> AnySequence
945 aElementType
= cppu::UnoType
<Any
>::get();
951 OUStringBuffer aSeqTypeName
;
952 for(sal_Int32 iDim
= 0 ; iDim
< nDims
; iDim
++ )
954 aSeqTypeName
.append(aSeqLevelStr
);
956 aSeqTypeName
.append(aElementType
.getTypeName());
957 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
961 else if( auto obj
= dynamic_cast<SbUnoObject
*>( xObj
.get() ) )
963 aRetType
= obj
->getUnoAny().getValueType();
966 else if( auto any
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
968 aRetType
= any
->getValue().getValueType();
970 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
972 // No object, convert basic type
975 aRetType
= getUnoTypeForSbxBaseType( eBaseType
);
980 // converting of Sbx to Uno without known target class for TypeClass_ANY
981 static Any
sbxToUnoValueImpl( const SbxValue
* pVar
, bool bBlockConversionToSmallestType
= false )
983 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
984 if( eBaseType
== SbxOBJECT
)
986 SbxBaseRef xObj
= pVar
->GetObject();
989 if( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
990 return obj
->getValue();
991 if( auto pClassModuleObj
= dynamic_cast<SbClassModuleObject
*>( xObj
.get() ) )
994 SbModule
* pClassModule
= pClassModuleObj
->getClassModule();
995 if( pClassModule
->createCOMWrapperForIface( aRetAny
, pClassModuleObj
) )
998 if( dynamic_cast<const SbUnoObject
*>( xObj
.get() ) == nullptr )
1000 // Create NativeObjectWrapper to identify object in case of callbacks
1001 SbxObject
* pObj
= dynamic_cast<SbxObject
*>( pVar
->GetObject() );
1002 if( pObj
!= nullptr )
1004 NativeObjectWrapper aNativeObjectWrapper
;
1005 sal_uInt32 nIndex
= lcl_registerNativeObjectWrapper( pObj
);
1006 aNativeObjectWrapper
.ObjectId
<<= nIndex
;
1008 aRetAny
<<= aNativeObjectWrapper
;
1015 Type aType
= getUnoTypeForSbxValue( pVar
);
1016 TypeClass eType
= aType
.getTypeClass();
1018 if( !bBlockConversionToSmallestType
)
1020 // #79615 Choose "smallest" representation for int values
1021 // because up cast is allowed, downcast not
1024 case TypeClass_FLOAT
:
1025 case TypeClass_DOUBLE
:
1027 double d
= pVar
->GetDouble();
1028 if( rtl::math::approxEqual(d
, floor( d
)) )
1030 if( d
>= -128 && d
<= 127 )
1031 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1032 else if( d
>= SbxMININT
&& d
<= SbxMAXINT
)
1033 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1034 else if( d
>= -SbxMAXLNG
&& d
<= SbxMAXLNG
)
1035 aType
= ::cppu::UnoType
<sal_Int32
>::get();
1039 case TypeClass_SHORT
:
1041 sal_Int16 n
= pVar
->GetInteger();
1042 if( n
>= -128 && n
<= 127 )
1043 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1046 case TypeClass_LONG
:
1048 sal_Int32 n
= pVar
->GetLong();
1049 if( n
>= -128 && n
<= 127 )
1050 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1051 else if( n
>= SbxMININT
&& n
<= SbxMAXINT
)
1052 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1055 case TypeClass_UNSIGNED_SHORT
:
1057 sal_uInt16 n
= pVar
->GetUShort();
1059 aType
= cppu::UnoType
<sal_uInt8
>::get();
1062 case TypeClass_UNSIGNED_LONG
:
1064 sal_uInt32 n
= pVar
->GetLong();
1066 aType
= cppu::UnoType
<sal_uInt8
>::get();
1067 else if( n
<= SbxMAXUINT
)
1068 aType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get();
1071 // TODO: need to add hyper types ?
1076 return sbxToUnoValue( pVar
, aType
);
1080 // Helper function for StepREDIMP
1081 static Any
implRekMultiDimArrayToSequence( SbxDimArray
* pArray
,
1082 const Type
& aElemType
, sal_Int32 nMaxDimIndex
, sal_Int32 nActualDim
,
1083 sal_Int32
* pActualIndices
, sal_Int32
* pLowerBounds
, sal_Int32
* pUpperBounds
)
1085 sal_Int32 nSeqLevel
= nMaxDimIndex
- nActualDim
+ 1;
1086 OUStringBuffer aSeqTypeName
;
1088 for( i
= 0 ; i
< nSeqLevel
; i
++ )
1090 aSeqTypeName
.append(aSeqLevelStr
);
1092 aSeqTypeName
.append(aElemType
.getTypeName());
1093 Type
aSeqType( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
1095 // Create Sequence instance
1097 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aSeqType
);
1098 xIdlTargetClass
->createObject( aRetVal
);
1100 // Alloc sequence according to array bounds
1101 sal_Int32 nUpper
= pUpperBounds
[nActualDim
];
1102 sal_Int32 nLower
= pLowerBounds
[nActualDim
];
1103 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1104 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1105 xArray
->realloc( aRetVal
, nSeqSize
);
1107 sal_Int32
& ri
= pActualIndices
[nActualDim
];
1109 for( ri
= nLower
,i
= 0 ; ri
<= nUpper
; ri
++,i
++ )
1113 if( nActualDim
< nMaxDimIndex
)
1115 aElementVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1116 nMaxDimIndex
, nActualDim
+ 1, pActualIndices
, pLowerBounds
, pUpperBounds
);
1120 SbxVariable
* pSource
= pArray
->Get32( pActualIndices
);
1121 aElementVal
= sbxToUnoValue( pSource
, aElemType
);
1126 // transfer to the sequence
1127 xArray
->set( aRetVal
, i
, aElementVal
);
1129 catch( const IllegalArgumentException
& )
1131 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1132 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1134 catch (const IndexOutOfBoundsException
&)
1136 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1142 // Map old interface
1143 Any
sbxToUnoValue( const SbxValue
* pVar
)
1145 return sbxToUnoValueImpl( pVar
);
1148 // function to find a global identifier in
1149 // the UnoScope and to wrap it for Sbx
1150 static bool implGetTypeByName( const OUString
& rName
, Type
& rRetType
)
1152 bool bSuccess
= false;
1154 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
1155 if( xTypeAccess
->hasByHierarchicalName( rName
) )
1157 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
1158 Reference
< XTypeDescription
> xTypeDesc
;
1161 if( xTypeDesc
.is() )
1163 rRetType
= Type( xTypeDesc
->getTypeClass(), xTypeDesc
->getName() );
1171 // converting of Sbx to Uno with known target class
1172 Any
sbxToUnoValue( const SbxValue
* pVar
, const Type
& rType
, Property
const * pUnoProperty
)
1176 // #94560 No conversion of empty/void for MAYBE_VOID properties
1177 if( pUnoProperty
&& pUnoProperty
->Attributes
& PropertyAttribute::MAYBEVOID
)
1179 if( pVar
->IsEmpty() )
1183 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
1184 if( eBaseType
== SbxOBJECT
)
1186 SbxBaseRef xObj
= pVar
->GetObject();
1187 if ( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
1189 return obj
->getValue();
1193 TypeClass eType
= rType
.getTypeClass();
1196 case TypeClass_INTERFACE
:
1197 case TypeClass_STRUCT
:
1198 case TypeClass_EXCEPTION
:
1200 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1203 if( pVar
->IsNull() && eType
== TypeClass_INTERFACE
)
1205 Reference
< XInterface
> xRef
;
1206 OUString aClassName
= xIdlTargetClass
->getName();
1207 Type
aClassType( xIdlTargetClass
->getTypeClass(), aClassName
);
1208 aRetVal
.setValue( &xRef
, aClassType
);
1212 // #112368 Special conversion for Decimal, Currency and Date
1213 if( eType
== TypeClass_STRUCT
)
1215 SbiInstance
* pInst
= GetSbData()->pInst
;
1216 if( pInst
&& pInst
->IsCompatibility() )
1218 if( rType
== cppu::UnoType
<oleautomation::Decimal
>::get())
1220 oleautomation::Decimal aDecimal
;
1221 pVar
->fillAutomationDecimal( aDecimal
);
1222 aRetVal
<<= aDecimal
;
1225 else if( rType
== cppu::UnoType
<oleautomation::Currency
>::get())
1227 // assumes per previous code that ole Currency is Int64
1228 aRetVal
<<= pVar
->GetInt64();
1231 else if( rType
== cppu::UnoType
<oleautomation::Date
>::get())
1233 oleautomation::Date aDate
;
1234 aDate
.Value
= pVar
->GetDate();
1241 SbxBaseRef pObj
= pVar
->GetObject();
1242 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1244 aRetVal
= obj
->getUnoAny();
1246 else if( auto structRef
= dynamic_cast<SbUnoStructRefObject
*>( pObj
.get() ) )
1248 aRetVal
= structRef
->getUnoAny();
1252 // null object -> null XInterface
1253 Reference
<XInterface
> xInt
;
1260 case TypeClass_TYPE
:
1262 if( eBaseType
== SbxOBJECT
)
1265 Reference
< XIdlClass
> xIdlClass
;
1267 SbxBaseRef pObj
= pVar
->GetObject();
1268 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1270 Any aUnoAny
= obj
->getUnoAny();
1271 aUnoAny
>>= xIdlClass
;
1274 if( xIdlClass
.is() )
1276 OUString aClassName
= xIdlClass
->getName();
1277 Type
aType( xIdlClass
->getTypeClass(), aClassName
);
1281 else if( eBaseType
== SbxSTRING
)
1283 OUString aTypeName
= pVar
->GetOUString();
1285 bool bSuccess
= implGetTypeByName( aTypeName
, aType
);
1295 case TypeClass_ENUM
:
1297 aRetVal
= int2enum( pVar
->GetLong(), rType
);
1301 case TypeClass_SEQUENCE
:
1303 SbxBaseRef xObj
= pVar
->GetObject();
1304 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
1306 sal_Int32 nDims
= pArray
->GetDims32();
1308 // Normal case: One dimensional array
1309 sal_Int32 nLower
, nUpper
;
1310 if( nDims
== 1 && pArray
->GetDim32( 1, nLower
, nUpper
) )
1312 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1314 // create the instance of the required sequence
1315 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1316 xIdlTargetClass
->createObject( aRetVal
);
1317 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1318 xArray
->realloc( aRetVal
, nSeqSize
);
1321 OUString aClassName
= xIdlTargetClass
->getName();
1322 typelib_TypeDescription
* pSeqTD
= nullptr;
1323 typelib_typedescription_getByName( &pSeqTD
, aClassName
.pData
);
1325 Type
aElemType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1327 // convert all array member and register them
1330 for (sal_Int32 i
= 0 ; i
< nSeqSize
; ++i
, ++aIdx
[0])
1332 SbxVariableRef xVar
= pArray
->Get32(aIdx
);
1334 // Convert the value of Sbx to Uno
1335 Any aAnyValue
= sbxToUnoValue( xVar
.get(), aElemType
);
1339 // insert in the sequence
1340 xArray
->set( aRetVal
, i
, aAnyValue
);
1342 catch( const IllegalArgumentException
& )
1344 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1345 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1347 catch (const IndexOutOfBoundsException
&)
1349 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1353 // #i33795 Map also multi dimensional arrays to corresponding sequences
1354 else if( nDims
> 1 )
1357 typelib_TypeDescription
* pSeqTD
= nullptr;
1358 Type
aCurType( rType
);
1359 sal_Int32 nSeqLevel
= 0;
1363 OUString aTypeName
= aCurType
.getTypeName();
1364 typelib_typedescription_getByName( &pSeqTD
, aTypeName
.pData
);
1366 if( pSeqTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
)
1368 aCurType
= Type( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1373 aElemType
= aCurType
;
1379 if( nSeqLevel
== nDims
)
1381 std::unique_ptr
<sal_Int32
[]> pLowerBounds(new sal_Int32
[nDims
]);
1382 std::unique_ptr
<sal_Int32
[]> pUpperBounds(new sal_Int32
[nDims
]);
1383 std::unique_ptr
<sal_Int32
[]> pActualIndices(new sal_Int32
[nDims
]);
1384 for(sal_Int32 i
= 1 ; i
<= nDims
; i
++ )
1386 sal_Int32 lBound
, uBound
;
1387 pArray
->GetDim32( i
, lBound
, uBound
);
1389 sal_Int32 j
= i
- 1;
1390 pActualIndices
[j
] = pLowerBounds
[j
] = lBound
;
1391 pUpperBounds
[j
] = uBound
;
1394 aRetVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1395 nDims
- 1, 0, pActualIndices
.get(), pLowerBounds
.get(), pUpperBounds
.get() );
1403 // for Any use the class independent converting routine
1406 aRetVal
= sbxToUnoValueImpl( pVar
);
1410 case TypeClass_BOOLEAN
:
1412 aRetVal
<<= pVar
->GetBool();
1415 case TypeClass_CHAR
:
1417 aRetVal
<<= pVar
->GetChar();
1420 case TypeClass_STRING
: aRetVal
<<= pVar
->GetOUString(); break;
1421 case TypeClass_FLOAT
: aRetVal
<<= pVar
->GetSingle(); break;
1422 case TypeClass_DOUBLE
: aRetVal
<<= pVar
->GetDouble(); break;
1424 case TypeClass_BYTE
:
1426 sal_Int16 nVal
= pVar
->GetInteger();
1427 bool bOverflow
= false;
1433 else if( nVal
> 255 ) // 128..255 map to -128..-1
1439 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW
);
1441 sal_Int8 nByteVal
= static_cast<sal_Int8
>(nVal
);
1442 aRetVal
<<= nByteVal
;
1445 case TypeClass_SHORT
: aRetVal
<<= pVar
->GetInteger(); break;
1446 case TypeClass_LONG
: aRetVal
<<= pVar
->GetLong(); break;
1447 case TypeClass_HYPER
: aRetVal
<<= pVar
->GetInt64(); break;
1448 case TypeClass_UNSIGNED_SHORT
: aRetVal
<<= pVar
->GetUShort(); break;
1449 case TypeClass_UNSIGNED_LONG
: aRetVal
<<= pVar
->GetULong(); break;
1450 case TypeClass_UNSIGNED_HYPER
: aRetVal
<<= pVar
->GetUInt64(); break;
1457 static void processAutomationParams( SbxArray
* pParams
, Sequence
< Any
>& args
, sal_uInt32 nParamCount
)
1459 AutomationNamedArgsSbxArray
* pArgNamesArray
= dynamic_cast<AutomationNamedArgsSbxArray
*>( pParams
);
1461 args
.realloc( nParamCount
);
1462 Any
* pAnyArgs
= args
.getArray();
1463 bool bBlockConversionToSmallestType
= GetSbData()->pInst
->IsCompatibility();
1465 if( pArgNamesArray
)
1467 Sequence
< OUString
>& rNameSeq
= pArgNamesArray
->getNames();
1468 OUString
* pNames
= rNameSeq
.getArray();
1470 for( i
= 0 ; i
< nParamCount
; i
++ )
1472 sal_uInt32 iSbx
= i
+ 1;
1474 aValAny
= sbxToUnoValueImpl( pParams
->Get32( iSbx
),
1475 bBlockConversionToSmallestType
);
1477 OUString aParamName
= pNames
[iSbx
];
1478 if( !aParamName
.isEmpty() )
1480 oleautomation::NamedArgument aNamedArgument
;
1481 aNamedArgument
.Name
= aParamName
;
1482 aNamedArgument
.Value
= aValAny
;
1483 pAnyArgs
[i
] <<= aNamedArgument
;
1487 pAnyArgs
[i
] = aValAny
;
1493 for( i
= 0 ; i
< nParamCount
; i
++ )
1495 pAnyArgs
[i
] = sbxToUnoValueImpl(pParams
->Get32(i
+ 1),
1496 bBlockConversionToSmallestType
);
1504 enum class INVOKETYPE
1512 static Any
invokeAutomationMethod( const OUString
& Name
, Sequence
< Any
> const & args
, SbxArray
* pParams
, sal_uInt32 nParamCount
, Reference
< XInvocation
> const & rxInvocation
, INVOKETYPE invokeType
)
1514 Sequence
< sal_Int16
> OutParamIndex
;
1515 Sequence
< Any
> OutParam
;
1518 switch( invokeType
)
1520 case INVOKETYPE::Func
:
1521 aRetAny
= rxInvocation
->invoke( Name
, args
, OutParamIndex
, OutParam
);
1523 case INVOKETYPE::GetProp
:
1525 Reference
< XAutomationInvocation
> xAutoInv( rxInvocation
, UNO_QUERY
);
1526 aRetAny
= xAutoInv
->invokeGetProperty( Name
, args
, OutParamIndex
, OutParam
);
1530 assert(false); break;
1533 const sal_Int16
* pIndices
= OutParamIndex
.getConstArray();
1534 sal_uInt32 nLen
= OutParamIndex
.getLength();
1537 const Any
* pNewValues
= OutParam
.getConstArray();
1538 for( sal_uInt32 j
= 0 ; j
< nLen
; j
++ )
1540 sal_Int16 iTarget
= pIndices
[ j
];
1541 if( iTarget
>= static_cast<sal_Int16
>(nParamCount
) )
1543 unoToSbxValue( pParams
->Get32(j
+ 1), pNewValues
[ j
] );
1549 // Debugging help method to readout the implemented interfaces of an object
1550 static OUString
Impl_GetInterfaceInfo( const Reference
< XInterface
>& x
, const Reference
< XIdlClass
>& xClass
, sal_uInt16 nRekLevel
)
1552 Type aIfaceType
= cppu::UnoType
<XInterface
>::get();
1553 static Reference
< XIdlClass
> xIfaceClass
= TypeToIdlClass( aIfaceType
);
1555 OUStringBuffer aRetStr
;
1556 for( sal_uInt16 i
= 0 ; i
< nRekLevel
; i
++ )
1557 aRetStr
.append( " " );
1558 aRetStr
.append( xClass
->getName() );
1559 OUString aClassName
= xClass
->getName();
1560 Type
aClassType( xClass
->getTypeClass(), aClassName
);
1562 // checking if the interface is really supported
1563 if( !x
->queryInterface( aClassType
).hasValue() )
1565 aRetStr
.append( " (ERROR: Not really supported!)\n" );
1567 // Are there super interfaces?
1570 aRetStr
.append( "\n" );
1572 // get the super interfaces
1573 Sequence
< Reference
< XIdlClass
> > aSuperClassSeq
= xClass
->getSuperclasses();
1574 const Reference
< XIdlClass
>* pClasses
= aSuperClassSeq
.getConstArray();
1575 sal_uInt32 nSuperIfaceCount
= aSuperClassSeq
.getLength();
1576 for( sal_uInt32 j
= 0 ; j
< nSuperIfaceCount
; j
++ )
1578 const Reference
< XIdlClass
>& rxIfaceClass
= pClasses
[j
];
1579 if( !rxIfaceClass
->equals( xIfaceClass
) )
1580 aRetStr
.append( Impl_GetInterfaceInfo( x
, rxIfaceClass
, nRekLevel
+ 1 ) );
1583 return aRetStr
.makeStringAndClear();
1586 static OUString
getDbgObjectNameImpl(SbUnoObject
& rUnoObj
)
1588 OUString aName
= rUnoObj
.GetClassName();
1589 if( aName
.isEmpty() )
1591 Any aToInspectObj
= rUnoObj
.getUnoAny();
1592 Reference
< XInterface
> xObj(aToInspectObj
, css::uno::UNO_QUERY
);
1595 Reference
< XServiceInfo
> xServiceInfo( xObj
, UNO_QUERY
);
1596 if( xServiceInfo
.is() )
1597 aName
= xServiceInfo
->getImplementationName();
1603 static OUString
getDbgObjectName(SbUnoObject
& rUnoObj
)
1605 OUString aName
= getDbgObjectNameImpl(rUnoObj
);
1606 if( aName
.isEmpty() )
1609 OUStringBuffer aRet
;
1610 if( aName
.getLength() > 20 )
1612 aRet
.append( "\n" );
1614 aRet
.append( "\"" );
1615 aRet
.append( aName
);
1616 aRet
.append( "\":" );
1617 return aRet
.makeStringAndClear();
1620 OUString
getBasicObjectTypeName( SbxObject
* pObj
)
1624 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
1626 return getDbgObjectNameImpl(*pUnoObj
);
1628 else if (SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>(pObj
))
1630 return pUnoStructObj
->GetClassName();
1638 bool matchesBasicTypeName(
1639 css::uno::Reference
<css::reflection::XIdlClass
> const & unoType
, OUString
const & basicTypeName
)
1641 if (unoType
->getName().endsWithIgnoreAsciiCase(basicTypeName
)) {
1644 auto const sups
= unoType
->getSuperclasses();
1646 sups
.begin(), sups
.end(),
1647 [&basicTypeName
](auto const & t
) { return matchesBasicTypeName(t
, basicTypeName
); });
1652 bool checkUnoObjectType(SbUnoObject
& rUnoObj
, const OUString
& rClass
)
1654 Any aToInspectObj
= rUnoObj
.getUnoAny();
1656 // Return true for XInvocation based objects as interface type names don't count then
1657 Reference
< XInvocation
> xInvocation( aToInspectObj
, UNO_QUERY
);
1658 if( xInvocation
.is() )
1662 bool bResult
= false;
1663 Reference
< XTypeProvider
> xTypeProvider( aToInspectObj
, UNO_QUERY
);
1664 if( xTypeProvider
.is() )
1666 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1667 have a leading 'X', in Basic we want to be able to do something
1668 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1669 add a leading 'X' to the class name and a leading dot to the entire
1670 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1671 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1672 'ooo.vba.msforms.XLabel'.
1674 OUString aClassName
;
1675 if ( SbiRuntime::isVBAEnabled() )
1678 sal_Int32 nClassNameDot
= rClass
.lastIndexOf( '.' );
1679 if( nClassNameDot
>= 0 )
1681 aClassName
+= OUString::Concat(rClass
.subView( 0, nClassNameDot
+ 1 )) + "X" + rClass
.subView( nClassNameDot
+ 1 );
1685 aClassName
+= "X" + rClass
;
1688 else // assume extended type declaration support for basic ( can't get here
1690 aClassName
= rClass
;
1692 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1693 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1694 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1695 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1697 const Type
& rType
= pTypeArray
[j
];
1699 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1702 OSL_FAIL("failed to get XIdlClass for type");
1705 OUString aInterfaceName
= xClass
->getName();
1706 if ( aInterfaceName
== "com.sun.star.bridge.oleautomation.XAutomationObject" )
1708 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1710 Reference
< XInvocation
> xInv( aToInspectObj
, UNO_QUERY
);
1714 xInv
->getValue( "$GetTypeName" ) >>= sTypeName
;
1715 if ( sTypeName
.isEmpty() || sTypeName
== "IDispatch" )
1717 // can't check type, leave it pass
1722 bResult
= sTypeName
== rClass
;
1725 break; // finished checking automation object
1728 if ( matchesBasicTypeName(xClass
, aClassName
) )
1738 // Debugging help method to readout the implemented interfaces of an object
1739 static OUString
Impl_GetSupportedInterfaces(SbUnoObject
& rUnoObj
)
1741 Any aToInspectObj
= rUnoObj
.getUnoAny();
1743 // allow only TypeClass interface
1744 OUStringBuffer aRet
;
1745 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aToInspectObj
);
1748 aRet
.append( ID_DBG_SUPPORTEDINTERFACES
);
1749 aRet
.append( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1753 Reference
< XTypeProvider
> xTypeProvider( *x
, UNO_QUERY
);
1755 aRet
.append( "Supported interfaces by object " );
1756 aRet
.append(getDbgObjectName(rUnoObj
));
1757 aRet
.append( "\n" );
1758 if( xTypeProvider
.is() )
1760 // get the interfaces of the implementation
1761 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1762 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1763 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1764 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1766 const Type
& rType
= pTypeArray
[j
];
1768 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1771 aRet
.append( Impl_GetInterfaceInfo( *x
, xClass
, 1 ) );
1775 typelib_TypeDescription
* pTD
= nullptr;
1776 rType
.getDescription( &pTD
);
1778 aRet
.append( "*** ERROR: No IdlClass for type \"" );
1779 aRet
.append( pTD
->pTypeName
);
1780 aRet
.append( "\"\n*** Please check type library\n" );
1785 return aRet
.makeStringAndClear();
1789 // Debugging help method SbxDataType -> String
1790 static OUString
Dbg_SbxDataType2String( SbxDataType eType
)
1792 OUStringBuffer aRet
;
1795 case SbxEMPTY
: aRet
.append("SbxEMPTY"); break;
1796 case SbxNULL
: aRet
.append("SbxNULL"); break;
1797 case SbxINTEGER
: aRet
.append("SbxINTEGER"); break;
1798 case SbxLONG
: aRet
.append("SbxLONG"); break;
1799 case SbxSINGLE
: aRet
.append("SbxSINGLE"); break;
1800 case SbxDOUBLE
: aRet
.append("SbxDOUBLE"); break;
1801 case SbxCURRENCY
: aRet
.append("SbxCURRENCY"); break;
1802 case SbxDECIMAL
: aRet
.append("SbxDECIMAL"); break;
1803 case SbxDATE
: aRet
.append("SbxDATE"); break;
1804 case SbxSTRING
: aRet
.append("SbxSTRING"); break;
1805 case SbxOBJECT
: aRet
.append("SbxOBJECT"); break;
1806 case SbxERROR
: aRet
.append("SbxERROR"); break;
1807 case SbxBOOL
: aRet
.append("SbxBOOL"); break;
1808 case SbxVARIANT
: aRet
.append("SbxVARIANT"); break;
1809 case SbxDATAOBJECT
: aRet
.append("SbxDATAOBJECT"); break;
1810 case SbxCHAR
: aRet
.append("SbxCHAR"); break;
1811 case SbxBYTE
: aRet
.append("SbxBYTE"); break;
1812 case SbxUSHORT
: aRet
.append("SbxUSHORT"); break;
1813 case SbxULONG
: aRet
.append("SbxULONG"); break;
1814 case SbxSALINT64
: aRet
.append("SbxINT64"); break;
1815 case SbxSALUINT64
: aRet
.append("SbxUINT64"); break;
1816 case SbxINT
: aRet
.append("SbxINT"); break;
1817 case SbxUINT
: aRet
.append("SbxUINT"); break;
1818 case SbxVOID
: aRet
.append("SbxVOID"); break;
1819 case SbxHRESULT
: aRet
.append("SbxHRESULT"); break;
1820 case SbxPOINTER
: aRet
.append("SbxPOINTER"); break;
1821 case SbxDIMARRAY
: aRet
.append("SbxDIMARRAY"); break;
1822 case SbxCARRAY
: aRet
.append("SbxCARRAY"); break;
1823 case SbxUSERDEF
: aRet
.append("SbxUSERDEF"); break;
1824 case SbxLPSTR
: aRet
.append("SbxLPSTR"); break;
1825 case SbxLPWSTR
: aRet
.append("SbxLPWSTR"); break;
1826 case SbxCoreSTRING
: aRet
.append("SbxCoreSTRING"); break;
1827 case SbxOBJECT
| SbxARRAY
: aRet
.append("SbxARRAY"); break;
1828 default: aRet
.append("Unknown Sbx-Type!");break;
1830 return aRet
.makeStringAndClear();
1833 // Debugging help method to display the properties of a SbUnoObjects
1834 static OUString
Impl_DumpProperties(SbUnoObject
& rUnoObj
)
1836 OUStringBuffer aRet
;
1837 aRet
.append("Properties of object ");
1838 aRet
.append(getDbgObjectName(rUnoObj
));
1840 // analyse the Uno-Infos to recognise the arrays
1841 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1844 Reference
< XInvocation
> xInvok
= rUnoObj
.getInvocation();
1846 xAccess
= xInvok
->getIntrospection();
1850 aRet
.append( "\nUnknown, no introspection available\n" );
1851 return aRet
.makeStringAndClear();
1854 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
1855 sal_uInt32 nUnoPropCount
= props
.getLength();
1856 const Property
* pUnoProps
= props
.getConstArray();
1858 SbxArray
* pProps
= rUnoObj
.GetProperties();
1859 sal_uInt32 nPropCount
= pProps
->Count32();
1860 sal_uInt32 nPropsPerLine
= 1 + nPropCount
/ 30;
1861 for( sal_uInt32 i
= 0; i
< nPropCount
; i
++ )
1863 SbxVariable
* pVar
= pProps
->Get32( i
);
1866 OUStringBuffer aPropStr
;
1867 if( (i
% nPropsPerLine
) == 0 )
1868 aPropStr
.append( "\n" );
1870 // output the type and name
1871 // Is it in Uno a sequence?
1872 SbxDataType eType
= pVar
->GetFullType();
1874 bool bMaybeVoid
= false;
1875 if( i
< nUnoPropCount
)
1877 const Property
& rProp
= pUnoProps
[ i
];
1879 // For MAYBEVOID freshly convert the type from Uno,
1880 // so not just SbxEMPTY is returned.
1881 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
1883 eType
= unoToSbxType( rProp
.Type
.getTypeClass() );
1886 if( eType
== SbxOBJECT
)
1888 Type aType
= rProp
.Type
;
1889 if( aType
.getTypeClass() == TypeClass_SEQUENCE
)
1890 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1893 aPropStr
.append( Dbg_SbxDataType2String( eType
) );
1895 aPropStr
.append( "/void" );
1896 aPropStr
.append( " " );
1897 aPropStr
.append( pVar
->GetName() );
1899 if( i
== nPropCount
- 1 )
1900 aPropStr
.append( "\n" );
1902 aPropStr
.append( "; " );
1904 aRet
.append( aPropStr
.makeStringAndClear() );
1907 return aRet
.makeStringAndClear();
1910 // Debugging help method to display the methods of an SbUnoObjects
1911 static OUString
Impl_DumpMethods(SbUnoObject
& rUnoObj
)
1913 OUStringBuffer aRet
;
1914 aRet
.append("Methods of object ");
1915 aRet
.append(getDbgObjectName(rUnoObj
));
1917 // XIntrospectionAccess, so that the types of the parameter could be outputted
1918 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1921 Reference
< XInvocation
> xInvok
= rUnoObj
.getInvocation();
1923 xAccess
= xInvok
->getIntrospection();
1927 aRet
.append( "\nUnknown, no introspection available\n" );
1928 return aRet
.makeStringAndClear();
1930 Sequence
< Reference
< XIdlMethod
> > methods
= xAccess
->getMethods
1931 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
1932 const Reference
< XIdlMethod
>* pUnoMethods
= methods
.getConstArray();
1934 SbxArray
* pMethods
= rUnoObj
.GetMethods();
1935 sal_uInt32 nMethodCount
= pMethods
->Count32();
1938 aRet
.append( "\nNo methods found\n" );
1939 return aRet
.makeStringAndClear();
1941 sal_uInt32 nPropsPerLine
= 1 + nMethodCount
/ 30;
1942 for( sal_uInt32 i
= 0; i
< nMethodCount
; i
++ )
1944 SbxVariable
* pVar
= pMethods
->Get32( i
);
1947 if( (i
% nPropsPerLine
) == 0 )
1948 aRet
.append( "\n" );
1950 // address the method
1951 const Reference
< XIdlMethod
>& rxMethod
= pUnoMethods
[i
];
1953 // Is it in Uno a sequence?
1954 SbxDataType eType
= pVar
->GetFullType();
1955 if( eType
== SbxOBJECT
)
1957 Reference
< XIdlClass
> xClass
= rxMethod
->getReturnType();
1958 if( xClass
.is() && xClass
->getTypeClass() == TypeClass_SEQUENCE
)
1959 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1961 // output the name and the type
1962 aRet
.append( Dbg_SbxDataType2String( eType
) );
1964 aRet
.append ( pVar
->GetName() );
1965 aRet
.append( " ( " );
1967 // the get-method mustn't have a parameter
1968 Sequence
< Reference
< XIdlClass
> > aParamsSeq
= rxMethod
->getParameterTypes();
1969 sal_uInt32 nParamCount
= aParamsSeq
.getLength();
1970 const Reference
< XIdlClass
>* pParams
= aParamsSeq
.getConstArray();
1972 if( nParamCount
> 0 )
1974 for( sal_uInt32 j
= 0; j
< nParamCount
; j
++ )
1976 aRet
.append ( Dbg_SbxDataType2String( unoToSbxType( pParams
[ j
] ) ) );
1977 if( j
< nParamCount
- 1 )
1978 aRet
.append( ", " );
1982 aRet
.append( "void" );
1984 aRet
.append( " ) " );
1986 if( i
== nMethodCount
- 1 )
1987 aRet
.append( "\n" );
1989 aRet
.append( "; " );
1992 return aRet
.makeStringAndClear();
1996 // Implementation SbUnoObject
1997 void SbUnoObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1999 if( bNeedIntrospection
)
2002 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
2006 SbxVariable
* pVar
= pHint
->GetVar();
2007 SbxArray
* pParams
= pVar
->GetParameters();
2008 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
2009 SbUnoMethod
* pMeth
= dynamic_cast<SbUnoMethod
*>( pVar
);
2012 bool bInvocation
= pProp
->isInvocationBased();
2013 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
2016 sal_Int32 nId
= pProp
->nId
;
2019 // Id == -1: Display implemented interfaces according the ClassProvider
2020 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2022 OUString aRetStr
= Impl_GetSupportedInterfaces(*this);
2023 pVar
->PutString( aRetStr
);
2025 // Id == -2: output properties
2026 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
2028 // now all properties must be created
2030 OUString aRetStr
= Impl_DumpProperties(*this);
2031 pVar
->PutString( aRetStr
);
2033 // Id == -3: output the methods
2034 else if( nId
== -3 ) // Property ID_DBG_METHODS
2036 // now all properties must be created
2038 OUString aRetStr
= Impl_DumpMethods(*this);
2039 pVar
->PutString( aRetStr
);
2044 if( !bInvocation
&& mxUnoAccess
.is() )
2050 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2051 if ( aMember
.isEmpty() )
2053 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2057 if ( pProp
->isUnoStruct() )
2059 SbUnoStructRefObject
* pSbUnoObject
= new SbUnoStructRefObject( pProp
->GetName(), aMember
);
2060 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
2061 pVar
->PutObject( xWrapper
.get() );
2065 Any aRetAny
= aMember
.getValue();
2066 // take over the value from Uno to Sbx
2067 unoToSbxValue( pVar
, aRetAny
);
2073 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2074 Any aRetAny
= xPropSet
->getPropertyValue( pProp
->GetName() );
2075 // The use of getPropertyValue (instead of using the index) is
2076 // suboptimal, but the refactoring to XInvocation is already pending
2077 // Otherwise it is possible to use FastPropertySet
2079 // take over the value from Uno to Sbx
2080 unoToSbxValue( pVar
, aRetAny
);
2082 catch( const Exception
& )
2084 implHandleAnyException( ::cppu::getCaughtException() );
2087 else if( bInvocation
&& mxInvocation
.is() )
2091 sal_uInt32 nParamCount
= pParams
? (pParams
->Count32() - 1) : 0;
2092 bool bCanBeConsideredAMethod
= mxInvocation
->hasMethod( pProp
->GetName() );
2094 if ( bCanBeConsideredAMethod
&& nParamCount
)
2096 // Automation properties have methods, so... we need to invoke this through
2099 processAutomationParams( pParams
, args
, nParamCount
);
2100 aRetAny
= invokeAutomationMethod( pProp
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::GetProp
);
2103 aRetAny
= mxInvocation
->getValue( pProp
->GetName() );
2104 // take over the value from Uno to Sbx
2105 unoToSbxValue( pVar
, aRetAny
);
2106 if( pParams
&& bCanBeConsideredAMethod
)
2107 pVar
->SetParameters( nullptr );
2110 catch( const Exception
& )
2112 implHandleAnyException( ::cppu::getCaughtException() );
2116 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
2118 if( !bInvocation
&& mxUnoAccess
.is() )
2120 if( pProp
->aUnoProp
.Attributes
& PropertyAttribute::READONLY
)
2122 StarBASIC::Error( ERRCODE_BASIC_PROP_READONLY
);
2127 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2128 if ( aMember
.isEmpty() )
2130 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2134 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2135 aMember
.setValue( aAnyValue
);
2139 // take over the value from Uno to Sbx
2140 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2144 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2145 xPropSet
->setPropertyValue( pProp
->GetName(), aAnyValue
);
2146 // The use of getPropertyValue (instead of using the index) is
2147 // suboptimal, but the refactoring to XInvocation is already pending
2148 // Otherwise it is possible to use FastPropertySet
2150 catch( const Exception
& )
2152 implHandleAnyException( ::cppu::getCaughtException() );
2155 else if( bInvocation
&& mxInvocation
.is() )
2157 // take over the value from Uno to Sbx
2158 Any aAnyValue
= sbxToUnoValueImpl( pVar
);
2162 mxInvocation
->setValue( pProp
->GetName(), aAnyValue
);
2164 catch( const Exception
& )
2166 implHandleAnyException( ::cppu::getCaughtException() );
2173 bool bInvocation
= pMeth
->isInvocationBased();
2174 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
2176 // number of Parameter -1 because of Param0 == this
2177 sal_uInt32 nParamCount
= pParams
? (pParams
->Count32() - 1) : 0;
2179 bool bOutParams
= false;
2181 if( !bInvocation
&& mxUnoAccess
.is() )
2184 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2185 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2186 sal_uInt32 nUnoParamCount
= rInfoSeq
.getLength();
2187 sal_uInt32 nAllocParamCount
= nParamCount
;
2189 // ignore surplus parameter; alternative: throw an error
2190 if( nParamCount
> nUnoParamCount
)
2192 nParamCount
= nUnoParamCount
;
2193 nAllocParamCount
= nParamCount
;
2195 else if( nParamCount
< nUnoParamCount
)
2197 SbiInstance
* pInst
= GetSbData()->pInst
;
2198 if( pInst
&& pInst
->IsCompatibility() )
2201 bool bError
= false;
2202 for( sal_uInt32 i
= nParamCount
; i
< nUnoParamCount
; i
++ )
2204 const ParamInfo
& rInfo
= pParamInfos
[i
];
2205 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2206 if( rxClass
->getTypeClass() != TypeClass_ANY
)
2209 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
2213 nAllocParamCount
= nUnoParamCount
;
2217 if( nAllocParamCount
> 0 )
2219 args
.realloc( nAllocParamCount
);
2220 Any
* pAnyArgs
= args
.getArray();
2221 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2223 const ParamInfo
& rInfo
= pParamInfos
[i
];
2224 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2226 css::uno::Type
aType( rxClass
->getTypeClass(), rxClass
->getName() );
2228 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2229 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get32(i
+ 1), aType
);
2231 // If it is not certain check whether the out-parameter are available.
2234 ParamMode aParamMode
= rInfo
.aMode
;
2235 if( aParamMode
!= ParamMode_IN
)
2241 else if( bInvocation
&& pParams
&& mxInvocation
.is() )
2243 processAutomationParams( pParams
, args
, nParamCount
);
2247 GetSbData()->bBlockCompilerError
= true; // #106433 Block compiler errors for API calls
2250 if( !bInvocation
&& mxUnoAccess
.is() )
2252 Any aRetAny
= pMeth
->m_xUnoMethod
->invoke( getUnoAny(), args
);
2254 // take over the value from Uno to Sbx
2255 unoToSbxValue( pVar
, aRetAny
);
2257 // Did we to copy back the Out-Parameter?
2260 const Any
* pAnyArgs
= args
.getConstArray();
2263 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2264 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2267 for( j
= 0 ; j
< nParamCount
; j
++ )
2269 const ParamInfo
& rInfo
= pParamInfos
[j
];
2270 ParamMode aParamMode
= rInfo
.aMode
;
2271 if( aParamMode
!= ParamMode_IN
)
2272 unoToSbxValue( pParams
->Get32(j
+ 1), pAnyArgs
[ j
] );
2276 else if( bInvocation
&& mxInvocation
.is() )
2278 Any aRetAny
= invokeAutomationMethod( pMeth
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::Func
);
2279 unoToSbxValue( pVar
, aRetAny
);
2282 // remove parameter here, because this was not done anymore in unoToSbxValue()
2285 pVar
->SetParameters( nullptr );
2287 catch( const Exception
& )
2289 implHandleAnyException( ::cppu::getCaughtException() );
2291 GetSbData()->bBlockCompilerError
= false; // #106433 Unblock compiler errors
2295 SbxObject::Notify( rBC
, rHint
);
2299 SbUnoObject::SbUnoObject( const OUString
& aName_
, const Any
& aUnoObj_
)
2300 : SbxObject( aName_
)
2301 , bNeedIntrospection( true )
2302 , bNativeCOMObject( false )
2304 // beat out again the default properties of Sbx
2305 Remove( "Name", SbxClassType::DontCare
);
2306 Remove( "Parent", SbxClassType::DontCare
);
2308 // check the type of the objects
2309 TypeClass eType
= aUnoObj_
.getValueType().getTypeClass();
2310 Reference
< XInterface
> x
;
2311 if( eType
== TypeClass_INTERFACE
)
2313 // get the interface from the Any
2319 Reference
< XTypeProvider
> xTypeProvider
;
2320 // Did the object have an invocation itself?
2321 mxInvocation
.set( x
, UNO_QUERY
);
2323 xTypeProvider
.set( x
, UNO_QUERY
);
2325 if( mxInvocation
.is() )
2328 // get the ExactName
2329 mxExactNameInvocation
.set( mxInvocation
, UNO_QUERY
);
2331 // The remainder refers only to the introspection
2332 if( !xTypeProvider
.is() )
2334 bNeedIntrospection
= false;
2338 // Ignore introspection based members for COM objects to avoid
2339 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2340 Reference
< oleautomation::XAutomationObject
> xAutomationObject( aUnoObj_
, UNO_QUERY
);
2341 if( xAutomationObject
.is() )
2342 bNativeCOMObject
= true;
2345 maTmpUnoObj
= aUnoObj_
;
2348 //*** Define the name ***
2349 bool bFatalError
= true;
2351 // Is it an interface or a struct?
2352 bool bSetClassName
= false;
2353 OUString aClassName_
;
2354 if( eType
== TypeClass_STRUCT
|| eType
== TypeClass_EXCEPTION
)
2357 bFatalError
= false;
2359 // insert the real name of the class
2360 if( aName_
.isEmpty() )
2362 aClassName_
= aUnoObj_
.getValueType().getTypeName();
2363 bSetClassName
= true;
2365 StructRefInfo
aThisStruct( maTmpUnoObj
, maTmpUnoObj
.getValueType(), 0 );
2366 maStructInfo
= std::make_shared
<SbUnoStructRefObject
>( GetName(), aThisStruct
);
2368 else if( eType
== TypeClass_INTERFACE
)
2370 // Interface works always through the type in the Any
2371 bFatalError
= false;
2374 SetClassName( aClassName_
);
2376 // Neither interface nor Struct -> FatalError
2379 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION
);
2383 // pass the introspection primal on demand
2386 SbUnoObject::~SbUnoObject()
2391 // pass the introspection on Demand
2392 void SbUnoObject::doIntrospection()
2394 if( !bNeedIntrospection
)
2397 Reference
<XComponentContext
> xContext
= comphelper::getProcessComponentContext();
2403 // get the introspection service
2404 Reference
<XIntrospection
> xIntrospection
;
2408 xIntrospection
= theIntrospection::get(xContext
);
2410 catch ( const css::uno::DeploymentException
& )
2414 if (!xIntrospection
.is())
2417 bNeedIntrospection
= false;
2419 // pass the introspection
2422 mxUnoAccess
= xIntrospection
->inspect( maTmpUnoObj
);
2424 catch( const RuntimeException
& e
)
2426 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2429 if( !mxUnoAccess
.is() )
2431 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2435 // get MaterialHolder from access
2436 mxMaterialHolder
.set( mxUnoAccess
, UNO_QUERY
);
2438 // get ExactName from access
2439 mxExactName
.set( mxUnoAccess
, UNO_QUERY
);
2443 // Start of a list of all SbUnoMethod-Instances
2444 static SbUnoMethod
* pFirst
= nullptr;
2446 void clearUnoMethodsForBasic( StarBASIC
const * pBasic
)
2448 SbUnoMethod
* pMeth
= pFirst
;
2451 SbxObject
* pObject
= pMeth
->GetParent();
2454 StarBASIC
* pModBasic
= dynamic_cast< StarBASIC
* >( pObject
->GetParent() );
2455 if ( pModBasic
== pBasic
)
2457 // for now the solution is to remove the method from the list and to clear it,
2458 // but in case the element should be correctly transferred to another StarBASIC,
2459 // we should either set module parent to NULL without clearing it, or even
2460 // set the new StarBASIC as the parent of the module
2461 // pObject->SetParent( NULL );
2463 if( pMeth
== pFirst
)
2464 pFirst
= pMeth
->pNext
;
2465 else if( pMeth
->pPrev
)
2466 pMeth
->pPrev
->pNext
= pMeth
->pNext
;
2468 pMeth
->pNext
->pPrev
= pMeth
->pPrev
;
2470 pMeth
->pPrev
= nullptr;
2471 pMeth
->pNext
= nullptr;
2473 pMeth
->SbxValue::Clear();
2474 pObject
->SbxValue::Clear();
2476 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2480 pMeth
= pMeth
->pNext
;
2483 pMeth
= pMeth
->pNext
;
2487 void clearUnoMethods()
2489 SbUnoMethod
* pMeth
= pFirst
;
2492 pMeth
->SbxValue::Clear();
2493 pMeth
= pMeth
->pNext
;
2498 SbUnoMethod::SbUnoMethod
2500 const OUString
& aName_
,
2501 SbxDataType eSbxType
,
2502 Reference
< XIdlMethod
> const & xUnoMethod_
,
2505 : SbxMethod( aName_
, eSbxType
)
2506 , mbInvocation( bInvocation
)
2508 m_xUnoMethod
= xUnoMethod_
;
2509 pParamInfoSeq
= nullptr;
2511 // enregister the method in a list
2516 pNext
->pPrev
= this;
2519 SbUnoMethod::~SbUnoMethod()
2521 pParamInfoSeq
.reset();
2523 if( this == pFirst
)
2526 pPrev
->pNext
= pNext
;
2528 pNext
->pPrev
= pPrev
;
2531 SbxInfo
* SbUnoMethod::GetInfo()
2533 if( !pInfo
.is() && m_xUnoMethod
.is() )
2535 SbiInstance
* pInst
= GetSbData()->pInst
;
2536 if( pInst
&& pInst
->IsCompatibility() )
2538 pInfo
= new SbxInfo();
2540 const Sequence
<ParamInfo
>& rInfoSeq
= getParamInfos();
2541 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2542 sal_uInt32 nParamCount
= rInfoSeq
.getLength();
2544 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2546 const ParamInfo
& rInfo
= pParamInfos
[i
];
2547 OUString aParamName
= rInfo
.aName
;
2549 pInfo
->AddParam( aParamName
, SbxVARIANT
, SbxFlagBits::Read
);
2556 const Sequence
<ParamInfo
>& SbUnoMethod::getParamInfos()
2560 Sequence
<ParamInfo
> aTmp
;
2561 if (m_xUnoMethod
.is())
2562 aTmp
= m_xUnoMethod
->getParameterInfos();
2563 pParamInfoSeq
.reset( new Sequence
<ParamInfo
>(aTmp
) );
2565 return *pParamInfoSeq
;
2568 SbUnoProperty::SbUnoProperty
2570 const OUString
& aName_
,
2571 SbxDataType eSbxType
,
2572 SbxDataType eRealSbxType
,
2573 const Property
& aUnoProp_
,
2578 : SbxProperty( aName_
, eSbxType
)
2579 , aUnoProp( aUnoProp_
)
2581 , mbInvocation( bInvocation
)
2582 , mRealType( eRealSbxType
)
2583 , mbUnoStruct( bUnoStruct
)
2585 // as needed establish a dummy array so that SbiRuntime::CheckArray() works
2586 static SbxArrayRef xDummyArray
= new SbxArray( SbxVARIANT
);
2587 if( eSbxType
& SbxARRAY
)
2588 PutObject( xDummyArray
.get() );
2591 SbUnoProperty::~SbUnoProperty()
2595 SbxVariable
* SbUnoObject::Find( const OUString
& rName
, SbxClassType t
)
2597 static Reference
< XIdlMethod
> xDummyMethod
;
2598 static Property aDummyProp
;
2600 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
2602 if( bNeedIntrospection
)
2605 // New 1999-03-04: Create properties on demand. Therefore search now via
2606 // IntrospectionAccess if a property or a method of the required name exist
2609 OUString
aUName( rName
);
2610 if( mxUnoAccess
.is() && !bNativeCOMObject
)
2612 if( mxExactName
.is() )
2614 OUString aUExactName
= mxExactName
->getExactName( aUName
);
2615 if( !aUExactName
.isEmpty() )
2617 aUName
= aUExactName
;
2620 if( mxUnoAccess
->hasProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
) )
2622 const Property
& rProp
= mxUnoAccess
->
2623 getProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2625 // If the property could be void the type had to be set to Variant
2626 SbxDataType eSbxType
;
2627 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2628 eSbxType
= SbxVARIANT
;
2630 eSbxType
= unoToSbxType( rProp
.Type
.getTypeClass() );
2632 SbxDataType eRealSbxType
= ( ( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( rProp
.Type
.getTypeClass() ) : eSbxType
);
2633 // create the property and superimpose it
2634 auto pProp
= tools::make_ref
<SbUnoProperty
>( rProp
.Name
, eSbxType
, eRealSbxType
, rProp
, 0, false, ( rProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2635 QuickInsert( pProp
.get() );
2638 else if( mxUnoAccess
->hasMethod( aUName
,
2639 MethodConcept::ALL
- MethodConcept::DANGEROUS
) )
2641 // address the method
2642 const Reference
< XIdlMethod
>& rxMethod
= mxUnoAccess
->
2643 getMethod( aUName
, MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2645 // create SbUnoMethod and superimpose it
2646 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( rxMethod
->getName(),
2647 unoToSbxType( rxMethod
->getReturnType() ), rxMethod
, false );
2648 QuickInsert( xMethRef
.get() );
2649 pRes
= xMethRef
.get();
2652 // If nothing was found check via XNameAccess
2657 Reference
< XNameAccess
> xNameAccess( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2659 if( xNameAccess
.is() && xNameAccess
->hasByName( rName
) )
2661 Any aAny
= xNameAccess
->getByName( rName
);
2663 // ATTENTION: Because of XNameAccess, the variable generated here
2664 // may not be included as a fixed property in the object and therefore
2665 // won't be stored anywhere.
2666 // If this leads to problems, it has to be created
2667 // synthetically or a class SbUnoNameAccessProperty,
2668 // which checks the existence on access and which
2669 // is disposed if the name is not found anymore.
2670 pRes
= new SbxVariable( SbxVARIANT
);
2671 unoToSbxValue( pRes
, aAny
);
2674 catch( const NoSuchElementException
& e
)
2676 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2678 catch( const Exception
& )
2680 // Establish so that the exception error will not be overwritten
2682 pRes
= new SbxVariable( SbxVARIANT
);
2684 implHandleAnyException( ::cppu::getCaughtException() );
2688 if( !pRes
&& mxInvocation
.is() )
2690 if( mxExactNameInvocation
.is() )
2692 OUString aUExactName
= mxExactNameInvocation
->getExactName( aUName
);
2693 if( !aUExactName
.isEmpty() )
2695 aUName
= aUExactName
;
2701 if( mxInvocation
->hasProperty( aUName
) )
2703 // create a property and superimpose it
2704 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( aUName
, SbxVARIANT
, SbxVARIANT
, aDummyProp
, 0, true, false );
2705 QuickInsert( xVarRef
.get() );
2706 pRes
= xVarRef
.get();
2708 else if( mxInvocation
->hasMethod( aUName
) )
2710 // create SbUnoMethode and superimpose it
2711 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2712 QuickInsert( xMethRef
.get() );
2713 pRes
= xMethRef
.get();
2717 Reference
< XDirectInvocation
> xDirectInvoke( mxInvocation
, UNO_QUERY
);
2718 if ( xDirectInvoke
.is() && xDirectInvoke
->hasMember( aUName
) )
2720 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2721 QuickInsert( xMethRef
.get() );
2722 pRes
= xMethRef
.get();
2727 catch( const RuntimeException
& e
)
2729 // Establish so that the exception error will not be overwritten
2731 pRes
= new SbxVariable( SbxVARIANT
);
2733 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2738 // At the very end checking if the Dbg_-Properties are meant
2742 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
2743 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
2744 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
2747 implCreateDbgProperties();
2749 // Now they have to be found regular
2750 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
2757 // help method to create the dbg_-Properties
2758 void SbUnoObject::implCreateDbgProperties()
2762 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2763 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_SUPPORTEDINTERFACES
), SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
2764 QuickInsert( xVarRef
.get() );
2766 // Id == -2: output the properties
2767 xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_PROPERTIES
), SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
2768 QuickInsert( xVarRef
.get() );
2770 // Id == -3: output the Methods
2771 xVarRef
= tools::make_ref
<SbUnoProperty
>( OUString(ID_DBG_METHODS
), SbxSTRING
, SbxSTRING
, aProp
, -3, false, false );
2772 QuickInsert( xVarRef
.get() );
2775 void SbUnoObject::implCreateAll()
2777 // throw away all existing methods and properties
2778 pMethods
= tools::make_ref
<SbxArray
>();
2779 pProps
= tools::make_ref
<SbxArray
>();
2781 if( bNeedIntrospection
) doIntrospection();
2783 // get introspection
2784 Reference
< XIntrospectionAccess
> xAccess
= mxUnoAccess
;
2785 if( !xAccess
.is() || bNativeCOMObject
)
2787 if( mxInvocation
.is() )
2788 xAccess
= mxInvocation
->getIntrospection();
2789 else if( bNativeCOMObject
)
2795 // Establish properties
2796 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2797 sal_uInt32 nPropCount
= props
.getLength();
2798 const Property
* pProps_
= props
.getConstArray();
2801 for( i
= 0 ; i
< nPropCount
; i
++ )
2803 const Property
& rProp
= pProps_
[ i
];
2805 // If the property could be void the type had to be set to Variant
2806 SbxDataType eSbxType
;
2807 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2808 eSbxType
= SbxVARIANT
;
2810 eSbxType
= unoToSbxType( rProp
.Type
.getTypeClass() );
2812 SbxDataType eRealSbxType
= ( ( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( rProp
.Type
.getTypeClass() ) : eSbxType
);
2813 // Create property and superimpose it
2814 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( rProp
.Name
, eSbxType
, eRealSbxType
, rProp
, i
, false, ( rProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2815 QuickInsert( xVarRef
.get() );
2818 // Create Dbg_-Properties
2819 implCreateDbgProperties();
2822 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods
2823 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2824 sal_uInt32 nMethCount
= aMethodSeq
.getLength();
2825 const Reference
< XIdlMethod
>* pMethods_
= aMethodSeq
.getConstArray();
2826 for( i
= 0 ; i
< nMethCount
; i
++ )
2829 const Reference
< XIdlMethod
>& rxMethod
= pMethods_
[i
];
2831 // Create SbUnoMethod and superimpose it
2832 auto xMethRef
= tools::make_ref
<SbUnoMethod
>
2833 ( rxMethod
->getName(), unoToSbxType( rxMethod
->getReturnType() ), rxMethod
, false );
2834 QuickInsert( xMethRef
.get() );
2840 Any
SbUnoObject::getUnoAny()
2843 if( bNeedIntrospection
) doIntrospection();
2845 aRetAny
= maTmpUnoObj
;
2846 else if( mxMaterialHolder
.is() )
2847 aRetAny
= mxMaterialHolder
->getMaterial();
2848 else if( mxInvocation
.is() )
2849 aRetAny
<<= mxInvocation
;
2853 // help method to create a Uno-Struct per CoreReflection
2854 static SbUnoObject
* Impl_CreateUnoStruct( const OUString
& aClassName
)
2856 // get CoreReflection
2857 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
2858 if( !xCoreReflection
.is() )
2861 // search for the class
2862 Reference
< XIdlClass
> xClass
;
2863 const Reference
< XHierarchicalNameAccess
>& xHarryName
=
2864 getCoreReflection_HierarchicalNameAccess_Impl();
2865 if( xHarryName
.is() && xHarryName
->hasByHierarchicalName( aClassName
) )
2866 xClass
= xCoreReflection
->forName( aClassName
);
2870 // Is it really a struct?
2871 TypeClass eType
= xClass
->getTypeClass();
2872 if ( ( eType
!= TypeClass_STRUCT
) && ( eType
!= TypeClass_EXCEPTION
) )
2875 // create an instance
2877 xClass
->createObject( aNewAny
);
2878 // make a SbUnoObject out of it
2879 SbUnoObject
* pUnoObj
= new SbUnoObject( aClassName
, aNewAny
);
2884 // Factory-Class to create Uno-Structs per DIM AS NEW
2885 SbxBase
* SbUnoFactory::Create( sal_uInt16
, sal_uInt32
)
2887 // Via SbxId nothing works in Uno
2891 SbxObject
* SbUnoFactory::CreateObject( const OUString
& rClassName
)
2893 return Impl_CreateUnoStruct( rClassName
);
2897 // Provisional interface for the UNO-Connection
2898 // Deliver a SbxObject, that wrap a Uno-Interface
2899 SbxObjectRef
GetSbUnoObject( const OUString
& aName
, const Any
& aUnoObj_
)
2901 return new SbUnoObject( aName
, aUnoObj_
);
2904 // Force creation of all properties for debugging
2905 void createAllObjectProperties( SbxObject
* pObj
)
2910 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
2911 SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>( pObj
);
2914 pUnoObj
->createAllProperties();
2916 else if ( pUnoStructObj
)
2918 pUnoStructObj
->createAllProperties();
2923 void RTL_Impl_CreateUnoStruct( SbxArray
& rPar
)
2925 // We need 1 parameter minimum
2926 if ( rPar
.Count32() < 2 )
2928 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2932 // get the name of the class of the struct
2933 OUString aClassName
= rPar
.Get32(1)->GetOUString();
2935 // try to create Struct with the same name
2936 SbUnoObjectRef xUnoObj
= Impl_CreateUnoStruct( aClassName
);
2941 // return the object
2942 SbxVariableRef refVar
= rPar
.Get32(0);
2943 refVar
->PutObject( xUnoObj
.get() );
2946 void RTL_Impl_CreateUnoService( SbxArray
& rPar
)
2948 // We need 1 Parameter minimum
2949 if ( rPar
.Count32() < 2 )
2951 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2955 // get the name of the class of the struct
2956 OUString aServiceName
= rPar
.Get32(1)->GetOUString();
2958 // search for the service and instantiate it
2959 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
2960 Reference
< XInterface
> xInterface
;
2963 xInterface
= xFactory
->createInstance( aServiceName
);
2965 catch( const Exception
& )
2967 implHandleAnyException( ::cppu::getCaughtException() );
2970 SbxVariableRef refVar
= rPar
.Get32(0);
2971 if( xInterface
.is() )
2973 // Create a SbUnoObject out of it and return it
2974 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
2975 if( xUnoObj
->getUnoAny().hasValue() )
2977 // return the object
2978 refVar
->PutObject( xUnoObj
.get() );
2982 refVar
->PutObject( nullptr );
2987 refVar
->PutObject( nullptr );
2991 void RTL_Impl_CreateUnoServiceWithArguments( SbxArray
& rPar
)
2993 // We need 2 parameter minimum
2994 if ( rPar
.Count32() < 3 )
2996 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3000 // get the name of the class of the struct
3001 OUString aServiceName
= rPar
.Get32(1)->GetOUString();
3002 Any aArgAsAny
= sbxToUnoValue( rPar
.Get32(2),
3003 cppu::UnoType
<Sequence
<Any
>>::get() );
3004 Sequence
< Any
> aArgs
;
3005 aArgAsAny
>>= aArgs
;
3007 // search for the service and instantiate it
3008 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
3009 Reference
< XInterface
> xInterface
;
3012 xInterface
= xFactory
->createInstanceWithArguments( aServiceName
, aArgs
);
3014 catch( const Exception
& )
3016 implHandleAnyException( ::cppu::getCaughtException() );
3019 SbxVariableRef refVar
= rPar
.Get32(0);
3020 if( xInterface
.is() )
3022 // Create a SbUnoObject out of it and return it
3023 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
3024 if( xUnoObj
->getUnoAny().hasValue() )
3026 // return the object
3027 refVar
->PutObject( xUnoObj
.get() );
3031 refVar
->PutObject( nullptr );
3036 refVar
->PutObject( nullptr );
3040 void RTL_Impl_GetProcessServiceManager( SbxArray
& rPar
)
3042 SbxVariableRef refVar
= rPar
.Get32(0);
3044 // get the global service manager
3045 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
3047 // Create a SbUnoObject out of it and return it
3048 SbUnoObjectRef xUnoObj
= new SbUnoObject( "ProcessServiceManager", Any(xFactory
) );
3049 refVar
->PutObject( xUnoObj
.get() );
3052 void RTL_Impl_HasInterfaces( SbxArray
& rPar
)
3054 // We need 2 parameter minimum
3055 sal_uInt32 nParCount
= rPar
.Count32();
3058 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3062 // variable for the return value
3063 SbxVariableRef refVar
= rPar
.Get32(0);
3064 refVar
->PutBool( false );
3066 // get the Uno-Object
3067 SbxBaseRef pObj
= rPar
.Get32( 1 )->GetObject();
3068 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3069 if( obj
== nullptr )
3073 Any aAny
= obj
->getUnoAny();
3074 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aAny
);
3080 // get CoreReflection
3081 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3082 if( !xCoreReflection
.is() )
3086 for( sal_uInt32 i
= 2 ; i
< nParCount
; i
++ )
3088 // get the name of the interface of the struct
3089 OUString aIfaceName
= rPar
.Get32( i
)->GetOUString();
3091 // search for the class
3092 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aIfaceName
);
3097 // check if the interface will be supported
3098 OUString aClassName
= xClass
->getName();
3099 Type
aClassType( xClass
->getTypeClass(), aClassName
);
3100 if( !(*x
)->queryInterface( aClassType
).hasValue() )
3106 // Everything works; then return TRUE
3107 refVar
->PutBool( true );
3110 void RTL_Impl_IsUnoStruct( SbxArray
& rPar
)
3112 // We need 1 parameter minimum
3113 if ( rPar
.Count32() < 2 )
3115 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3119 // variable for the return value
3120 SbxVariableRef refVar
= rPar
.Get32(0);
3121 refVar
->PutBool( false );
3123 // get the Uno-Object
3124 SbxVariableRef xParam
= rPar
.Get32( 1 );
3125 if( !xParam
->IsObject() )
3129 SbxBaseRef pObj
= xParam
->GetObject();
3130 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3131 if( obj
== nullptr )
3135 Any aAny
= obj
->getUnoAny();
3136 TypeClass eType
= aAny
.getValueType().getTypeClass();
3137 if( eType
== TypeClass_STRUCT
)
3139 refVar
->PutBool( true );
3144 void RTL_Impl_EqualUnoObjects( SbxArray
& rPar
)
3146 if ( rPar
.Count32() < 3 )
3148 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3152 // variable for the return value
3153 SbxVariableRef refVar
= rPar
.Get32(0);
3154 refVar
->PutBool( false );
3156 // get the Uno-Objects
3157 SbxVariableRef xParam1
= rPar
.Get32( 1 );
3158 if( !xParam1
->IsObject() )
3162 SbxBaseRef pObj1
= xParam1
->GetObject();
3163 auto obj1
= dynamic_cast<SbUnoObject
*>( pObj1
.get() );
3164 if( obj1
== nullptr )
3168 Any aAny1
= obj1
->getUnoAny();
3169 TypeClass eType1
= aAny1
.getValueType().getTypeClass();
3170 if( eType1
!= TypeClass_INTERFACE
)
3174 Reference
< XInterface
> x1
;
3177 SbxVariableRef xParam2
= rPar
.Get32( 2 );
3178 if( !xParam2
->IsObject() )
3182 SbxBaseRef pObj2
= xParam2
->GetObject();
3183 auto obj2
= dynamic_cast<SbUnoObject
*>( pObj2
.get() );
3184 if( obj2
== nullptr )
3188 Any aAny2
= obj2
->getUnoAny();
3189 TypeClass eType2
= aAny2
.getValueType().getTypeClass();
3190 if( eType2
!= TypeClass_INTERFACE
)
3194 Reference
< XInterface
> x2
;
3199 refVar
->PutBool( true );
3204 // helper wrapper function to interact with TypeProvider and
3205 // XTypeDescriptionEnumerationAccess.
3206 // if it fails for whatever reason
3207 // returned Reference<> be null e.g. .is() will be false
3209 static Reference
< XTypeDescriptionEnumeration
> getTypeDescriptorEnumeration( const OUString
& sSearchRoot
,
3210 const Sequence
< TypeClass
>& types
,
3211 TypeDescriptionSearchDepth depth
)
3213 Reference
< XTypeDescriptionEnumeration
> xEnum
;
3214 Reference
< XTypeDescriptionEnumerationAccess
> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY
);
3215 if ( xTypeEnumAccess
.is() )
3219 xEnum
= xTypeEnumAccess
->createTypeDescriptionEnumeration(
3220 sSearchRoot
, types
, depth
);
3222 catch(const NoSuchTypeNameException
& /*nstne*/ ) {}
3223 catch(const InvalidTypeNameException
& /*nstne*/ ) {}
3229 VBAConstantHelper::instance()
3231 static VBAConstantHelper aHelper
;
3235 void VBAConstantHelper::init()
3240 Reference
< XTypeDescriptionEnumeration
> xEnum
= getTypeDescriptorEnumeration( "ooo.vba", {TypeClass_CONSTANTS
}, TypeDescriptionSearchDepth_INFINITE
);
3246 while ( xEnum
->hasMoreElements() )
3248 Reference
< XConstantsTypeDescription
> xConstants( xEnum
->nextElement(), UNO_QUERY
);
3249 if ( xConstants
.is() )
3251 // store constant group name
3252 OUString sFullName
= xConstants
->getName();
3253 sal_Int32 indexLastDot
= sFullName
.lastIndexOf('.');
3254 OUString
sLeafName( sFullName
);
3255 if ( indexLastDot
> -1 )
3257 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3259 aConstCache
.push_back( sLeafName
); // assume constant group names are unique
3260 const Sequence
< Reference
< XConstantTypeDescription
> > aConsts
= xConstants
->getConstants();
3261 for (const auto& ctd
: aConsts
)
3263 // store constant member name
3264 sFullName
= ctd
->getName();
3265 indexLastDot
= sFullName
.lastIndexOf('.');
3266 sLeafName
= sFullName
;
3267 if ( indexLastDot
> -1 )
3269 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3271 aConstHash
[ sLeafName
.toAsciiLowerCase() ] = ctd
->getConstantValue();
3279 VBAConstantHelper::isVBAConstantType( const OUString
& rName
)
3282 bool bConstant
= false;
3284 for (auto const& elem
: aConstCache
)
3286 if( rName
.equalsIgnoreAsciiCase(elem
) )
3296 VBAConstantHelper::getVBAConstant( const OUString
& rName
)
3298 SbxVariable
* pConst
= nullptr;
3301 auto it
= aConstHash
.find( rName
.toAsciiLowerCase() );
3303 if ( it
!= aConstHash
.end() )
3305 pConst
= new SbxVariable( SbxVARIANT
);
3306 pConst
->SetName( rName
);
3307 unoToSbxValue( pConst
, it
->second
);
3313 // Function to search for a global identifier in the
3314 // UnoScope and to wrap it for Sbx
3315 SbUnoClass
* findUnoClass( const OUString
& rName
)
3317 // #105550 Check if module exists
3318 SbUnoClass
* pUnoClass
= nullptr;
3320 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3321 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3323 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3324 Reference
< XTypeDescription
> xTypeDesc
;
3327 if( xTypeDesc
.is() )
3329 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3330 if( eTypeClass
== TypeClass_MODULE
|| eTypeClass
== TypeClass_CONSTANTS
)
3332 pUnoClass
= new SbUnoClass( rName
);
3339 SbxVariable
* SbUnoClass::Find( const OUString
& rName
, SbxClassType
)
3341 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Variable
);
3343 // If nothing were located the submodule isn't known yet
3346 // If it is already a class, ask for the field
3350 Reference
< XIdlField
> xField
= m_xClass
->getField( rName
);
3355 Any aAny
= xField
->get( {} ); //TODO: does this make sense?
3358 pRes
= new SbxVariable( SbxVARIANT
);
3359 pRes
->SetName( rName
);
3360 unoToSbxValue( pRes
, aAny
);
3362 catch( const Exception
& )
3364 implHandleAnyException( ::cppu::getCaughtException() );
3370 // expand fully qualified name
3371 OUString aNewName
= GetName()
3375 // get CoreReflection
3376 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3377 if( xCoreReflection
.is() )
3379 // Is it a constant?
3380 Reference
< XHierarchicalNameAccess
> xHarryName( xCoreReflection
, UNO_QUERY
);
3381 if( xHarryName
.is() )
3385 Any aValue
= xHarryName
->getByHierarchicalName( aNewName
);
3386 TypeClass eType
= aValue
.getValueType().getTypeClass();
3388 // Interface located? Then it is a class
3389 if( eType
== TypeClass_INTERFACE
)
3391 Reference
< XIdlClass
> xClass( aValue
, UNO_QUERY
);
3394 pRes
= new SbxVariable( SbxVARIANT
);
3395 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(new SbUnoClass( aNewName
, xClass
));
3396 pRes
->PutObject( xWrapper
.get() );
3401 pRes
= new SbxVariable( SbxVARIANT
);
3402 unoToSbxValue( pRes
, aValue
);
3405 catch( const NoSuchElementException
& )
3410 // Otherwise take it again as class
3413 SbUnoClass
* pNewClass
= findUnoClass( aNewName
);
3416 pRes
= new SbxVariable( SbxVARIANT
);
3417 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pNewClass
);
3418 pRes
->PutObject( xWrapper
.get() );
3425 SbUnoService
* pUnoService
= findUnoService( aNewName
);
3428 pRes
= new SbxVariable( SbxVARIANT
);
3429 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoService
);
3430 pRes
->PutObject( xWrapper
.get() );
3437 SbUnoSingleton
* pUnoSingleton
= findUnoSingleton( aNewName
);
3440 pRes
= new SbxVariable( SbxVARIANT
);
3441 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoSingleton
);
3442 pRes
->PutObject( xWrapper
.get() );
3450 pRes
->SetName( rName
);
3452 // Insert variable, so that it could be found later
3453 QuickInsert( pRes
);
3455 // Take us out as listener at once,
3456 // the values are all constant
3457 if( pRes
->IsBroadcaster() )
3458 EndListening( pRes
->GetBroadcaster(), true );
3465 SbUnoService
* findUnoService( const OUString
& rName
)
3467 SbUnoService
* pSbUnoService
= nullptr;
3469 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3470 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3472 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3473 Reference
< XTypeDescription
> xTypeDesc
;
3476 if( xTypeDesc
.is() )
3478 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3479 if( eTypeClass
== TypeClass_SERVICE
)
3481 Reference
< XServiceTypeDescription2
> xServiceTypeDesc( xTypeDesc
, UNO_QUERY
);
3482 if( xServiceTypeDesc
.is() )
3483 pSbUnoService
= new SbUnoService( rName
, xServiceTypeDesc
);
3487 return pSbUnoService
;
3490 SbxVariable
* SbUnoService::Find( const OUString
& rName
, SbxClassType
)
3492 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3496 // If it is already a class ask for a field
3497 if( m_bNeedsInit
&& m_xServiceTypeDesc
.is() )
3499 m_bNeedsInit
= false;
3501 Sequence
< Reference
< XServiceConstructorDescription
> > aSCDSeq
= m_xServiceTypeDesc
->getConstructors();
3502 const Reference
< XServiceConstructorDescription
>* pCtorSeq
= aSCDSeq
.getConstArray();
3503 int nCtorCount
= aSCDSeq
.getLength();
3504 for( int i
= 0 ; i
< nCtorCount
; ++i
)
3506 Reference
< XServiceConstructorDescription
> xCtor
= pCtorSeq
[i
];
3508 OUString
aName( xCtor
->getName() );
3509 if( aName
.isEmpty() )
3511 if( xCtor
->isDefaultConstructor() )
3517 if( !aName
.isEmpty() )
3519 // Create and insert SbUnoServiceCtor
3520 SbxVariableRef xSbCtorRef
= new SbUnoServiceCtor( aName
, xCtor
);
3521 QuickInsert( xSbCtorRef
.get() );
3524 pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3531 void SbUnoService::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3533 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3537 SbxVariable
* pVar
= pHint
->GetVar();
3538 SbxArray
* pParams
= pVar
->GetParameters();
3539 SbUnoServiceCtor
* pUnoCtor
= dynamic_cast<SbUnoServiceCtor
*>( pVar
);
3540 if( pUnoCtor
&& pHint
->GetId() == SfxHintId::BasicDataWanted
)
3542 // Parameter count -1 because of Param0 == this
3543 sal_uInt32 nParamCount
= pParams
? (pParams
->Count32() - 1) : 0;
3546 Reference
< XServiceConstructorDescription
> xCtor
= pUnoCtor
->getServiceCtorDesc();
3547 Sequence
< Reference
< XParameter
> > aParameterSeq
= xCtor
->getParameters();
3548 const Reference
< XParameter
>* pParameterSeq
= aParameterSeq
.getConstArray();
3549 sal_uInt32 nUnoParamCount
= aParameterSeq
.getLength();
3551 // Default: Ignore not needed parameters
3552 bool bParameterError
= false;
3554 // Is the last parameter a rest parameter?
3555 bool bRestParameterMode
= false;
3556 if( nUnoParamCount
> 0 )
3558 Reference
< XParameter
> xLastParam
= pParameterSeq
[ nUnoParamCount
- 1 ];
3559 if( xLastParam
.is() )
3561 if( xLastParam
->isRestParameter() )
3562 bRestParameterMode
= true;
3566 // Too many parameters with context as first parameter?
3567 sal_uInt32 nSbxParameterOffset
= 1;
3568 sal_uInt32 nParameterOffsetByContext
= 0;
3569 Reference
< XComponentContext
> xFirstParamContext
;
3570 if( nParamCount
> nUnoParamCount
)
3572 // Check if first parameter is a context and use it
3573 // then in createInstanceWithArgumentsAndContext
3574 Any aArg0
= sbxToUnoValue( pParams
->Get32( nSbxParameterOffset
) );
3575 if( (aArg0
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3576 nParameterOffsetByContext
= 1;
3579 sal_uInt32 nEffectiveParamCount
= nParamCount
- nParameterOffsetByContext
;
3580 sal_uInt32 nAllocParamCount
= nEffectiveParamCount
;
3581 if( nEffectiveParamCount
> nUnoParamCount
)
3583 if( !bRestParameterMode
)
3585 nEffectiveParamCount
= nUnoParamCount
;
3586 nAllocParamCount
= nUnoParamCount
;
3589 // Not enough parameters?
3590 else if( nUnoParamCount
> nEffectiveParamCount
)
3592 // RestParameterMode only helps if one (the last) parameter is missing
3593 int nDiff
= nUnoParamCount
- nEffectiveParamCount
;
3594 if( !bRestParameterMode
|| nDiff
> 1 )
3596 bParameterError
= true;
3597 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
3601 if( !bParameterError
)
3603 bool bOutParams
= false;
3604 if( nAllocParamCount
> 0 )
3606 args
.realloc( nAllocParamCount
);
3607 Any
* pAnyArgs
= args
.getArray();
3608 for( sal_uInt32 i
= 0 ; i
< nEffectiveParamCount
; i
++ )
3610 sal_uInt32 iSbx
= i
+ nSbxParameterOffset
+ nParameterOffsetByContext
;
3612 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3613 Reference
< XParameter
> xParam
;
3614 if( i
< nUnoParamCount
)
3616 xParam
= pParameterSeq
[i
];
3620 Reference
< XTypeDescription
> xParamTypeDesc
= xParam
->getType();
3621 if( !xParamTypeDesc
.is() )
3623 css::uno::Type
aType( xParamTypeDesc
->getTypeClass(), xParamTypeDesc
->getName() );
3625 // sbx parameter needs offset 1
3626 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get32( iSbx
), aType
);
3628 // Check for out parameter if not already done
3629 if( !bOutParams
&& xParam
->isOut() )
3634 pAnyArgs
[i
] = sbxToUnoValue( pParams
->Get32( iSbx
) );
3639 // "Call" ctor using createInstanceWithArgumentsAndContext
3640 Reference
< XComponentContext
> xContext(
3641 xFirstParamContext
.is()
3642 ? xFirstParamContext
3643 : comphelper::getProcessComponentContext() );
3644 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
3647 OUString aServiceName
= GetName();
3648 Reference
< XInterface
> xRet
;
3651 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext( aServiceName
, args
, xContext
);
3653 catch( const Exception
& )
3655 implHandleAnyException( ::cppu::getCaughtException() );
3658 unoToSbxValue( pVar
, aRetAny
);
3660 // Copy back out parameters?
3663 const Any
* pAnyArgs
= args
.getConstArray();
3665 for( sal_uInt32 j
= 0 ; j
< nUnoParamCount
; j
++ )
3667 Reference
< XParameter
> xParam
= pParameterSeq
[j
];
3671 if( xParam
->isOut() )
3672 unoToSbxValue( pParams
->Get32(j
+ 1), pAnyArgs
[ j
] );
3678 SbxObject::Notify( rBC
, rHint
);
3682 SbUnoServiceCtor::SbUnoServiceCtor( const OUString
& aName_
, Reference
< XServiceConstructorDescription
> const & xServiceCtorDesc
)
3683 : SbxMethod( aName_
, SbxOBJECT
)
3684 , m_xServiceCtorDesc( xServiceCtorDesc
)
3688 SbUnoServiceCtor::~SbUnoServiceCtor()
3692 SbxInfo
* SbUnoServiceCtor::GetInfo()
3698 SbUnoSingleton
* findUnoSingleton( const OUString
& rName
)
3700 SbUnoSingleton
* pSbUnoSingleton
= nullptr;
3702 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3703 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3705 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3706 Reference
< XTypeDescription
> xTypeDesc
;
3709 if( xTypeDesc
.is() )
3711 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3712 if( eTypeClass
== TypeClass_SINGLETON
)
3714 Reference
< XSingletonTypeDescription
> xSingletonTypeDesc( xTypeDesc
, UNO_QUERY
);
3715 if( xSingletonTypeDesc
.is() )
3716 pSbUnoSingleton
= new SbUnoSingleton( rName
);
3720 return pSbUnoSingleton
;
3723 SbUnoSingleton::SbUnoSingleton( const OUString
& aName_
)
3724 : SbxObject( aName_
)
3726 SbxVariableRef xGetMethodRef
= new SbxMethod( "get", SbxOBJECT
);
3727 QuickInsert( xGetMethodRef
.get() );
3730 void SbUnoSingleton::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3732 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3735 SbxVariable
* pVar
= pHint
->GetVar();
3736 SbxArray
* pParams
= pVar
->GetParameters();
3737 sal_uInt32 nParamCount
= pParams
? (pParams
->Count32() - 1) : 0;
3738 sal_uInt32 nAllowedParamCount
= 1;
3740 Reference
< XComponentContext
> xContextToUse
;
3741 if( nParamCount
> 0 )
3743 // Check if first parameter is a context and use it then
3744 Reference
< XComponentContext
> xFirstParamContext
;
3745 Any aArg1
= sbxToUnoValue( pParams
->Get32( 1 ) );
3746 if( (aArg1
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3747 xContextToUse
= xFirstParamContext
;
3750 if( !xContextToUse
.is() )
3752 xContextToUse
= comphelper::getProcessComponentContext();
3753 --nAllowedParamCount
;
3756 if( nParamCount
> nAllowedParamCount
)
3758 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3763 if( xContextToUse
.is() )
3765 OUString aSingletonName
= "/singletons/"
3767 Reference
< XInterface
> xRet
;
3768 xContextToUse
->getValueByName( aSingletonName
) >>= xRet
;
3771 unoToSbxValue( pVar
, aRetAny
);
3775 SbxObject::Notify( rBC
, rHint
);
3781 // Implementation of an EventAttacher-drawn AllListener, which
3782 // solely transmits several events to a general AllListener
3783 class BasicAllListener_Impl
: public WeakImplHelper
< XAllListener
>
3785 void firing_impl(const AllEventObject
& Event
, Any
* pRet
);
3788 SbxObjectRef xSbxObj
;
3789 OUString aPrefixName
;
3791 explicit BasicAllListener_Impl( const OUString
& aPrefixName
);
3793 // Methods of XAllListener
3794 virtual void SAL_CALL
firing(const AllEventObject
& Event
) override
;
3795 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) override
;
3797 // Methods of XEventListener
3798 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
3803 BasicAllListener_Impl::BasicAllListener_Impl(const OUString
& aPrefixName_
)
3804 : aPrefixName( aPrefixName_
)
3808 void BasicAllListener_Impl::firing_impl( const AllEventObject
& Event
, Any
* pRet
)
3810 SolarMutexGuard guard
;
3815 OUString aMethodName
= aPrefixName
+ Event
.MethodName
;
3817 SbxVariable
* pP
= xSbxObj
.get();
3818 while( pP
->GetParent() )
3820 pP
= pP
->GetParent();
3821 StarBASIC
* pLib
= dynamic_cast<StarBASIC
*>( pP
);
3824 // Create in a Basic Array
3825 SbxArrayRef xSbxArray
= new SbxArray( SbxVARIANT
);
3826 const Any
* pArgs
= Event
.Arguments
.getConstArray();
3827 sal_Int32 nCount
= Event
.Arguments
.getLength();
3828 for( sal_Int32 i
= 0; i
< nCount
; i
++ )
3831 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
3832 unoToSbxValue( xVar
.get(), pArgs
[i
] );
3833 xSbxArray
->Put32( xVar
.get(), i
+ 1 );
3836 pLib
->Call( aMethodName
, xSbxArray
.get() );
3838 // get the return value from the Param-Array, if requested
3841 SbxVariable
* pVar
= xSbxArray
->Get32( 0 );
3844 // #95792 Avoid a second call
3845 SbxFlagBits nFlags
= pVar
->GetFlags();
3846 pVar
->SetFlag( SbxFlagBits::NoBroadcast
);
3847 *pRet
= sbxToUnoValueImpl( pVar
);
3848 pVar
->SetFlags( nFlags
);
3857 // Methods of Listener
3858 void BasicAllListener_Impl::firing( const AllEventObject
& Event
)
3860 firing_impl( Event
, nullptr );
3863 Any
BasicAllListener_Impl::approveFiring( const AllEventObject
& Event
)
3866 firing_impl( Event
, &aRetAny
);
3871 // Methods of XEventListener
3872 void BasicAllListener_Impl ::disposing(const EventObject
& )
3874 SolarMutexGuard guard
;
3880 // class InvocationToAllListenerMapper
3881 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
3885 class InvocationToAllListenerMapper
: public WeakImplHelper
< XInvocation
>
3888 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
3889 const Reference
< XAllListener
>& AllListener
, const Any
& Helper
);
3892 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
3893 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
) override
;
3894 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
) override
;
3895 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) override
;
3896 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) override
;
3897 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) override
;
3900 Reference
< XAllListener
> m_xAllListener
;
3901 Reference
< XIdlClass
> m_xListenerType
;
3907 // Function to replace AllListenerAdapterService::createAllListerAdapter
3908 static Reference
< XInterface
> createAllListenerAdapter
3910 const Reference
< XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
3911 const Reference
< XIdlClass
>& xListenerType
,
3912 const Reference
< XAllListener
>& xListener
,
3916 Reference
< XInterface
> xAdapter
;
3917 if( xInvocationAdapterFactory
.is() && xListenerType
.is() && xListener
.is() )
3919 Reference
< XInvocation
> xInvocationToAllListenerMapper
=
3920 new InvocationToAllListenerMapper(xListenerType
, xListener
, Helper
);
3921 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName() );
3922 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, {aListenerType
} );
3928 // InvocationToAllListenerMapper
3929 InvocationToAllListenerMapper::InvocationToAllListenerMapper
3930 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, const Any
& Helper
)
3931 : m_xAllListener( AllListener
)
3932 , m_xListenerType( ListenerType
)
3933 , m_Helper( Helper
)
3938 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection()
3940 return Reference
< XIntrospectionAccess
>();
3944 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
3945 Sequence
< sal_Int16
>&, Sequence
< Any
>&)
3949 // Check if to firing or approveFiring has to be called
3950 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
3951 bool bApproveFiring
= false;
3954 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
3955 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
3956 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
3957 aExceptionSeq
.hasElements() )
3959 bApproveFiring
= true;
3963 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
3964 sal_uInt32 nParamCount
= aParamSeq
.getLength();
3965 if( nParamCount
> 1 )
3967 const ParamInfo
* pInfo
= aParamSeq
.getConstArray();
3968 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
3970 if( pInfo
[ i
].aMode
!= ParamMode_IN
)
3972 bApproveFiring
= true;
3979 AllEventObject aAllEvent
;
3980 aAllEvent
.Source
= static_cast<OWeakObject
*>(this);
3981 aAllEvent
.Helper
= m_Helper
;
3982 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName() );
3983 aAllEvent
.MethodName
= FunctionName
;
3984 aAllEvent
.Arguments
= Params
;
3985 if( bApproveFiring
)
3986 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
3988 m_xAllListener
->firing( aAllEvent
);
3993 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
&, const Any
&)
3997 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
&)
4003 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
4005 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
4006 return xMethod
.is();
4010 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
4012 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
4017 // create Uno-Service
4018 // 1. Parameter == Prefix-Name of the macro
4019 // 2. Parameter == fully qualified name of the listener
4020 void SbRtl_CreateUnoListener(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
4022 // We need 2 parameters
4023 if ( rPar
.Count32() != 3 )
4025 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4029 // get the name of the class of the struct
4030 OUString aPrefixName
= rPar
.Get32(1)->GetOUString();
4031 OUString aListenerClassName
= rPar
.Get32(2)->GetOUString();
4033 // get the CoreReflection
4034 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
4035 if( !xCoreReflection
.is() )
4038 // get the AllListenerAdapterService
4039 Reference
< XComponentContext
> xContext( comphelper::getProcessComponentContext() );
4042 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aListenerClassName
);
4046 // From 1999-11-30: get the InvocationAdapterFactory
4047 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
=
4048 InvocationAdapterFactory::create( xContext
);
4050 BasicAllListener_Impl
* p
;
4051 Reference
< XAllListener
> xAllLst
= p
= new BasicAllListener_Impl( aPrefixName
);
4053 Reference
< XInterface
> xLst
= createAllListenerAdapter( xInvocationAdapterFactory
, xClass
, xAllLst
, aTmp
);
4057 OUString aClassName
= xClass
->getName();
4058 Type
aClassType( xClass
->getTypeClass(), aClassName
);
4059 aTmp
= xLst
->queryInterface( aClassType
);
4060 if( !aTmp
.hasValue() )
4063 SbUnoObject
* pUnoObj
= new SbUnoObject( aListenerClassName
, aTmp
);
4064 p
->xSbxObj
= pUnoObj
;
4065 p
->xSbxObj
->SetParent( pBasic
);
4067 // #100326 Register listener object to set Parent NULL in Dtor
4068 SbxArrayRef xBasicUnoListeners
= pBasic
->getUnoListeners();
4069 xBasicUnoListeners
->Insert32( pUnoObj
, xBasicUnoListeners
->Count32() );
4071 // return the object
4072 SbxVariableRef refVar
= rPar
.Get32(0);
4073 refVar
->PutObject( p
->xSbxObj
.get() );
4077 // Represents the DefaultContext property of the ProcessServiceManager
4078 // in the Basic runtime system.
4079 void RTL_Impl_GetDefaultContext( SbxArray
& rPar
)
4081 SbxVariableRef refVar
= rPar
.Get32(0);
4083 Any
aContextAny( comphelper::getProcessComponentContext() );
4085 SbUnoObjectRef xUnoObj
= new SbUnoObject( "DefaultContext", aContextAny
);
4086 refVar
->PutObject( xUnoObj
.get() );
4090 // Creates a Basic wrapper object for a strongly typed Uno value
4091 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4092 void RTL_Impl_CreateUnoValue( SbxArray
& rPar
)
4094 // 2 parameters needed
4095 if ( rPar
.Count32() != 3 )
4097 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4101 // get the name of the class of the struct
4102 OUString aTypeName
= rPar
.Get32(1)->GetOUString();
4103 SbxVariable
* pVal
= rPar
.Get32(2);
4105 if( aTypeName
== "type" )
4107 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
4108 OUString aValTypeName
;
4109 if( eBaseType
== SbxSTRING
)
4111 aValTypeName
= pVal
->GetOUString();
4113 else if( eBaseType
== SbxOBJECT
)
4116 Reference
< XIdlClass
> xIdlClass
;
4118 SbxBaseRef pObj
= pVal
->GetObject();
4119 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
4121 Any aUnoAny
= obj
->getUnoAny();
4122 aUnoAny
>>= xIdlClass
;
4125 if( xIdlClass
.is() )
4127 aValTypeName
= xIdlClass
->getName();
4131 bool bSuccess
= implGetTypeByName( aValTypeName
, aType
);
4134 Any
aTypeAny( aType
);
4135 SbxVariableRef refVar
= rPar
.Get32(0);
4136 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject( aTypeAny
);
4137 refVar
->PutObject( xUnoAnyObject
.get() );
4143 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
4147 aRet
= xTypeAccess
->getByHierarchicalName( aTypeName
);
4149 catch( const NoSuchElementException
& e1
)
4151 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
4152 implGetExceptionMsg( e1
, "com.sun.star.container.NoSuchElementException" ) );
4155 Reference
< XTypeDescription
> xTypeDesc
;
4157 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
4158 Type
aDestType( eTypeClass
, aTypeName
);
4162 Any aVal
= sbxToUnoValueImpl( pVal
);
4163 Any aConvertedVal
= convertAny( aVal
, aDestType
);
4165 SbxVariableRef refVar
= rPar
.Get32(0);
4166 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject( aConvertedVal
);
4167 refVar
->PutObject( xUnoAnyObject
.get() );
4172 class ModuleInvocationProxy
: public WeakImplHelper
< XInvocation
, XComponent
>
4174 ::osl::Mutex m_aMutex
;
4176 SbxObjectRef m_xScopeObj
;
4177 bool m_bProxyIsClassModuleObject
;
4179 ::comphelper::OInterfaceContainerHelper2 m_aListeners
;
4182 ModuleInvocationProxy( OUString
const & aPrefix
, SbxObjectRef
const & xScopeObj
);
4185 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
4186 virtual void SAL_CALL
setValue( const OUString
& rProperty
, const Any
& rValue
) override
;
4187 virtual Any SAL_CALL
getValue( const OUString
& rProperty
) override
;
4188 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& rName
) override
;
4189 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& rProp
) override
;
4191 virtual Any SAL_CALL
invoke( const OUString
& rFunction
,
4192 const Sequence
< Any
>& rParams
,
4193 Sequence
< sal_Int16
>& rOutParamIndex
,
4194 Sequence
< Any
>& rOutParam
) override
;
4197 virtual void SAL_CALL
dispose() override
;
4198 virtual void SAL_CALL
addEventListener( const Reference
< XEventListener
>& xListener
) override
;
4199 virtual void SAL_CALL
removeEventListener( const Reference
< XEventListener
>& aListener
) override
;
4204 ModuleInvocationProxy::ModuleInvocationProxy( OUString
const & aPrefix
, SbxObjectRef
const & xScopeObj
)
4206 , m_aPrefix( aPrefix
+ "_" )
4207 , m_xScopeObj( xScopeObj
)
4208 , m_aListeners( m_aMutex
)
4210 m_bProxyIsClassModuleObject
= xScopeObj
.is() && dynamic_cast<const SbClassModuleObject
*>( xScopeObj
.get() ) != nullptr;
4213 Reference
< XIntrospectionAccess
> SAL_CALL
ModuleInvocationProxy::getIntrospection()
4215 return Reference
< XIntrospectionAccess
>();
4218 void SAL_CALL
ModuleInvocationProxy::setValue(const OUString
& rProperty
, const Any
& rValue
)
4220 if( !m_bProxyIsClassModuleObject
)
4221 throw UnknownPropertyException();
4223 SolarMutexGuard guard
;
4225 OUString aPropertyFunctionName
= "Property Set "
4229 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4230 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4231 if( pMeth
== nullptr )
4233 // TODO: Check vba behavior concerning missing function
4234 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4235 throw UnknownPropertyException(aPropertyFunctionName
);
4239 SbxArrayRef xArray
= new SbxArray
;
4240 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4241 unoToSbxValue( xVar
.get(), rValue
);
4242 xArray
->Put32( xVar
.get(), 1 );
4244 // Call property method
4245 SbxVariableRef xValue
= new SbxVariable
;
4246 pMeth
->SetParameters( xArray
.get() );
4247 pMeth
->Call( xValue
.get() );
4248 pMeth
->SetParameters( nullptr );
4250 // TODO: OutParameter?
4255 Any SAL_CALL
ModuleInvocationProxy::getValue(const OUString
& rProperty
)
4257 if( !m_bProxyIsClassModuleObject
)
4259 throw UnknownPropertyException();
4261 SolarMutexGuard guard
;
4263 OUString aPropertyFunctionName
= "Property Get "
4267 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4268 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4269 if( pMeth
== nullptr )
4271 // TODO: Check vba behavior concerning missing function
4272 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4273 throw UnknownPropertyException(aPropertyFunctionName
);
4277 SbxVariableRef xValue
= new SbxVariable
;
4278 pMeth
->Call( xValue
.get() );
4279 Any aRet
= sbxToUnoValue( xValue
.get() );
4283 sal_Bool SAL_CALL
ModuleInvocationProxy::hasMethod( const OUString
& )
4288 sal_Bool SAL_CALL
ModuleInvocationProxy::hasProperty( const OUString
& )
4293 Any SAL_CALL
ModuleInvocationProxy::invoke( const OUString
& rFunction
,
4294 const Sequence
< Any
>& rParams
,
4295 Sequence
< sal_Int16
>&,
4298 SolarMutexGuard guard
;
4301 SbxObjectRef xScopeObj
= m_xScopeObj
;
4302 if( !xScopeObj
.is() )
4306 OUString aFunctionName
= m_aPrefix
4309 bool bSetRescheduleBack
= false;
4310 bool bOldReschedule
= true;
4311 SbiInstance
* pInst
= GetSbData()->pInst
;
4312 if( pInst
&& pInst
->IsCompatibility() )
4314 bOldReschedule
= pInst
->IsReschedule();
4315 if ( bOldReschedule
)
4317 pInst
->EnableReschedule( false );
4318 bSetRescheduleBack
= true;
4322 SbxVariable
* p
= xScopeObj
->Find( aFunctionName
, SbxClassType::Method
);
4323 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4324 if( pMeth
== nullptr )
4326 // TODO: Check vba behavior concerning missing function
4327 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4333 sal_Int32 nParamCount
= rParams
.getLength();
4336 xArray
= new SbxArray
;
4337 const Any
*pArgs
= rParams
.getConstArray();
4338 for( sal_Int32 i
= 0 ; i
< nParamCount
; i
++ )
4340 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4341 unoToSbxValue( xVar
.get(), pArgs
[i
] );
4342 xArray
->Put32( xVar
.get(), sal::static_int_cast
< sal_uInt16
>(i
+1) );
4347 SbxVariableRef xValue
= new SbxVariable
;
4349 pMeth
->SetParameters( xArray
.get() );
4350 pMeth
->Call( xValue
.get() );
4351 aRet
= sbxToUnoValue( xValue
.get() );
4352 pMeth
->SetParameters( nullptr );
4354 if( bSetRescheduleBack
)
4355 pInst
->EnableReschedule( bOldReschedule
);
4357 // TODO: OutParameter?
4362 void SAL_CALL
ModuleInvocationProxy::dispose()
4364 ::osl::MutexGuard
aGuard( m_aMutex
);
4366 EventObject
aEvent( static_cast<XComponent
*>(this) );
4367 m_aListeners
.disposeAndClear( aEvent
);
4369 m_xScopeObj
= nullptr;
4372 void SAL_CALL
ModuleInvocationProxy::addEventListener( const Reference
< XEventListener
>& xListener
)
4374 m_aListeners
.addInterface( xListener
);
4377 void SAL_CALL
ModuleInvocationProxy::removeEventListener( const Reference
< XEventListener
>& xListener
)
4379 m_aListeners
.removeInterface( xListener
);
4383 Reference
< XInterface
> createComListener( const Any
& aControlAny
, const OUString
& aVBAType
,
4384 const OUString
& aPrefix
, const SbxObjectRef
& xScopeObj
)
4386 Reference
< XInterface
> xRet
;
4388 Reference
< XComponentContext
> xContext(
4389 comphelper::getProcessComponentContext() );
4390 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4392 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPrefix
, xScopeObj
);
4394 Sequence
<Any
> args( 3 );
4395 args
[0] = aControlAny
;
4396 args
[1] <<= aVBAType
;
4401 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext(
4402 "com.sun.star.custom.UnoComListener",
4405 catch( const Exception
& )
4407 implHandleAnyException( ::cppu::getCaughtException() );
4413 typedef std::vector
< WeakReference
< XComponent
> > ComponentRefVector
;
4417 struct StarBasicDisposeItem
4419 StarBASIC
* m_pBasic
;
4420 SbxArrayRef m_pRegisteredVariables
;
4421 ComponentRefVector m_vComImplementsObjects
;
4423 explicit StarBasicDisposeItem( StarBASIC
* pBasic
)
4424 : m_pBasic( pBasic
)
4425 , m_pRegisteredVariables(new SbxArray())
4432 typedef std::vector
< StarBasicDisposeItem
* > DisposeItemVector
;
4434 static DisposeItemVector GaDisposeItemVector
;
4436 static DisposeItemVector::iterator
lcl_findItemForBasic( StarBASIC
const * pBasic
)
4438 return std::find_if(GaDisposeItemVector
.begin(), GaDisposeItemVector
.end(),
4439 [&pBasic
](StarBasicDisposeItem
* pItem
) { return pItem
->m_pBasic
== pBasic
; });
4442 static StarBasicDisposeItem
* lcl_getOrCreateItemForBasic( StarBASIC
* pBasic
)
4444 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4445 StarBasicDisposeItem
* pItem
= (it
!= GaDisposeItemVector
.end()) ? *it
: nullptr;
4446 if( pItem
== nullptr )
4448 pItem
= new StarBasicDisposeItem( pBasic
);
4449 GaDisposeItemVector
.push_back( pItem
);
4454 void registerComponentToBeDisposedForBasic
4455 ( const Reference
< XComponent
>& xComponent
, StarBASIC
* pBasic
)
4457 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4458 pItem
->m_vComImplementsObjects
.emplace_back(xComponent
);
4461 void registerComListenerVariableForBasic( SbxVariable
* pVar
, StarBASIC
* pBasic
)
4463 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4464 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4465 pArray
->Put32( pVar
, pArray
->Count32() );
4468 void disposeComVariablesForBasic( StarBASIC
const * pBasic
)
4470 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4471 if( it
== GaDisposeItemVector
.end() )
4474 StarBasicDisposeItem
* pItem
= *it
;
4476 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4477 sal_uInt32 nCount
= pArray
->Count32();
4478 for( sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
4480 SbxVariable
* pVar
= pArray
->Get32( i
);
4481 pVar
->ClearComListener();
4484 ComponentRefVector
& rv
= pItem
->m_vComImplementsObjects
;
4485 for (auto const& elem
: rv
)
4487 Reference
< XComponent
> xComponent( elem
.get(), UNO_QUERY
);
4488 if (xComponent
.is())
4489 xComponent
->dispose();
4493 GaDisposeItemVector
.erase( it
);
4497 // Handle module implements mechanism for OLE types
4498 bool SbModule::createCOMWrapperForIface( Any
& o_rRetAny
, SbClassModuleObject
* pProxyClassModuleObject
)
4500 // For now: Take first interface that allows to instantiate COM wrapper
4501 // TODO: Check if support for multiple interfaces is needed
4503 Reference
< XComponentContext
> xContext(
4504 comphelper::getProcessComponentContext() );
4505 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4506 Reference
< XSingleServiceFactory
> xComImplementsFactory
4508 xServiceMgr
->createInstanceWithContext( "com.sun.star.custom.ComImplementsFactory", xContext
),
4511 if( !xComImplementsFactory
.is() )
4514 bool bSuccess
= false;
4516 SbxArray
* pModIfaces
= pClassData
->mxIfaces
.get();
4517 sal_uInt32 nCount
= pModIfaces
->Count32();
4518 for( sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
4520 SbxVariable
* pVar
= pModIfaces
->Get32( i
);
4521 const OUString
& aIfaceName
= pVar
->GetName();
4523 if( !aIfaceName
.isEmpty() )
4525 OUString aPureIfaceName
= aIfaceName
;
4526 sal_Int32 indexLastDot
= aIfaceName
.lastIndexOf('.');
4527 if ( indexLastDot
> -1 )
4529 aPureIfaceName
= aIfaceName
.copy( indexLastDot
+ 1 );
4531 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPureIfaceName
, pProxyClassModuleObject
);
4533 Sequence
<Any
> args( 2 );
4534 args
[0] <<= aIfaceName
;
4537 Reference
< XInterface
> xRet
;
4540 xRet
= xComImplementsFactory
->createInstanceWithArguments( args
);
4543 catch( const Exception
& )
4545 implHandleAnyException( ::cppu::getCaughtException() );
4550 Reference
< XComponent
> xComponent( xProxy
, UNO_QUERY
);
4551 if( xComponent
.is() )
4553 StarBASIC
* pParentBasic
= nullptr;
4554 SbxObject
* pCurObject
= this;
4557 SbxObject
* pObjParent
= pCurObject
->GetParent();
4558 pParentBasic
= dynamic_cast<StarBASIC
*>( pObjParent
);
4559 pCurObject
= pObjParent
;
4561 while( pParentBasic
== nullptr && pCurObject
!= nullptr );
4563 assert( pParentBasic
!= nullptr );
4564 registerComponentToBeDisposedForBasic( xComponent
, pParentBasic
);
4577 // Due to an incorrect behavior IE returns an object instead of a string
4578 // in some scenarios. Calling toString at the object may correct this.
4579 // Helper function used in sbxvalue.cxx
4580 bool handleToStringForCOMObjects( SbxObject
* pObj
, SbxValue
* pVal
)
4582 bool bSuccess
= false;
4584 if( auto pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
) )
4586 // Only for native COM objects
4587 if( pUnoObj
->isNativeCOMObject() )
4589 SbxVariableRef pMeth
= pObj
->Find( "toString", SbxClassType::Method
);
4602 Any
StructRefInfo::getValue()
4606 &aRet
, reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4607 typelib_TypeDescription
* pTD
= nullptr;
4608 maType
.getDescription(&pTD
);
4610 &aRet
, getInst(), pTD
,
4611 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
) );
4612 typelib_typedescription_release(pTD
);
4616 void StructRefInfo::setValue( const Any
& rValue
)
4618 bool bSuccess
= uno_type_assignData( getInst(),
4619 maType
.getTypeLibType(),
4620 const_cast<void*>(rValue
.getValue()),
4621 rValue
.getValueTypeRef(),
4622 reinterpret_cast< uno_QueryInterfaceFunc
>(cpp_queryInterface
),
4623 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
),
4624 reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4625 OSL_ENSURE(bSuccess
,
4626 "StructRefInfo::setValue: ooops... the value could not be assigned!");
4629 OUString
StructRefInfo::getTypeName() const
4631 return maType
.getTypeName();
4634 void* StructRefInfo::getInst()
4636 return const_cast<char *>(static_cast<char const *>(maAny
.getValue()) + mnPos
);
4639 TypeClass
StructRefInfo::getTypeClass() const
4641 return maType
.getTypeClass();
4644 SbUnoStructRefObject::SbUnoStructRefObject( const OUString
& aName_
, const StructRefInfo
& rMemberInfo
) : SbxObject( aName_
), maMemberInfo( rMemberInfo
), mbMemberCacheInit( false )
4646 SetClassName( maMemberInfo
.getTypeName() );
4649 SbUnoStructRefObject::~SbUnoStructRefObject()
4653 void SbUnoStructRefObject::initMemberCache()
4655 if ( mbMemberCacheInit
)
4657 typelib_TypeDescription
* pTD
= nullptr;
4658 maMemberInfo
.getType().getDescription(&pTD
);
4659 for ( typelib_CompoundTypeDescription
* pCompTypeDescr
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTD
);
4661 pCompTypeDescr
= pCompTypeDescr
->pBaseTypeDescription
)
4663 typelib_TypeDescriptionReference
** ppTypeRefs
= pCompTypeDescr
->ppTypeRefs
;
4664 rtl_uString
** ppNames
= pCompTypeDescr
->ppMemberNames
;
4665 sal_Int32
* pMemberOffsets
= pCompTypeDescr
->pMemberOffsets
;
4666 for ( sal_Int32 nPos
= pCompTypeDescr
->nMembers
; nPos
--; )
4668 OUString
aName( ppNames
[nPos
] );
4669 maFields
[ aName
] = std::make_unique
<StructRefInfo
>( maMemberInfo
.getRootAnyRef(), ppTypeRefs
[nPos
], maMemberInfo
.getPos() + pMemberOffsets
[nPos
] );
4672 typelib_typedescription_release(pTD
);
4673 mbMemberCacheInit
= true;
4676 SbxVariable
* SbUnoStructRefObject::Find( const OUString
& rName
, SbxClassType t
)
4678 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
4681 if ( !mbMemberCacheInit
)
4683 StructFieldInfo::iterator it
= maFields
.find( rName
);
4684 if ( it
!= maFields
.end() )
4686 SbxDataType eSbxType
;
4687 eSbxType
= unoToSbxType( it
->second
->getTypeClass() );
4688 SbxDataType eRealSbxType
= eSbxType
;
4691 aProp
.Type
= css::uno::Type( it
->second
->getTypeClass(), it
->second
->getTypeName() );
4692 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, aProp
, 0, false, ( aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
4693 SbxVariableRef xVarRef
= pProp
;
4694 QuickInsert( xVarRef
.get() );
4695 pRes
= xVarRef
.get();
4701 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
4702 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
4703 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
4706 implCreateDbgProperties();
4708 // Now they have to be found regular
4709 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
4716 // help method to create the dbg_-Properties
4717 void SbUnoStructRefObject::implCreateDbgProperties()
4721 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4722 SbxVariableRef xVarRef
= new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES
, SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
4723 QuickInsert( xVarRef
.get() );
4725 // Id == -2: output the properties
4726 xVarRef
= new SbUnoProperty( ID_DBG_PROPERTIES
, SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
4727 QuickInsert( xVarRef
.get() );
4729 // Id == -3: output the Methods
4730 xVarRef
= new SbUnoProperty( ID_DBG_METHODS
, SbxSTRING
, SbxSTRING
, aProp
, -3, false, false );
4731 QuickInsert( xVarRef
.get() );
4734 void SbUnoStructRefObject::implCreateAll()
4736 // throw away all existing methods and properties
4737 pMethods
= new SbxArray
;
4738 pProps
= new SbxArray
;
4740 if (!mbMemberCacheInit
)
4743 for (auto const& field
: maFields
)
4745 const OUString
& rName
= field
.first
;
4746 SbxDataType eSbxType
;
4747 eSbxType
= unoToSbxType( field
.second
->getTypeClass() );
4748 SbxDataType eRealSbxType
= eSbxType
;
4751 aProp
.Type
= css::uno::Type( field
.second
->getTypeClass(), field
.second
->getTypeName() );
4752 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, aProp
, 0, false, ( aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
4753 SbxVariableRef xVarRef
= pProp
;
4754 QuickInsert( xVarRef
.get() );
4757 // Create Dbg_-Properties
4758 implCreateDbgProperties();
4762 Any
SbUnoStructRefObject::getUnoAny()
4764 return maMemberInfo
.getValue();
4767 OUString
SbUnoStructRefObject::Impl_DumpProperties()
4769 OUStringBuffer aRet
;
4770 aRet
.append("Properties of object ");
4771 aRet
.append( getDbgObjectName() );
4773 sal_uInt32 nPropCount
= pProps
->Count32();
4774 sal_uInt32 nPropsPerLine
= 1 + nPropCount
/ 30;
4775 for( sal_uInt32 i
= 0; i
< nPropCount
; i
++ )
4777 SbxVariable
* pVar
= pProps
->Get32( i
);
4780 OUStringBuffer aPropStr
;
4781 if( (i
% nPropsPerLine
) == 0 )
4783 aPropStr
.append( "\n" );
4785 // output the type and name
4786 // Is it in Uno a sequence?
4787 SbxDataType eType
= pVar
->GetFullType();
4789 const OUString
& aName( pVar
->GetName() );
4790 StructFieldInfo::iterator it
= maFields
.find( aName
);
4792 if ( it
!= maFields
.end() )
4794 const StructRefInfo
& rPropInfo
= *it
->second
;
4796 if( eType
== SbxOBJECT
)
4798 if( rPropInfo
.getTypeClass() == TypeClass_SEQUENCE
)
4800 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
4804 aPropStr
.append( Dbg_SbxDataType2String( eType
) );
4806 aPropStr
.append( " " );
4807 aPropStr
.append( pVar
->GetName() );
4809 if( i
== nPropCount
- 1 )
4811 aPropStr
.append( "\n" );
4815 aPropStr
.append( "; " );
4817 aRet
.append( aPropStr
.makeStringAndClear() );
4820 return aRet
.makeStringAndClear();
4823 void SbUnoStructRefObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
4825 if ( !mbMemberCacheInit
)
4827 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
4831 SbxVariable
* pVar
= pHint
->GetVar();
4832 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
4835 StructFieldInfo::iterator it
= maFields
.find( pProp
->GetName() );
4836 // handle get/set of members of struct
4837 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
4840 sal_Int32 nId
= pProp
->nId
;
4843 // Id == -1: Display implemented interfaces according the ClassProvider
4844 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
4846 OUString aRet
= OUStringLiteral( ID_DBG_SUPPORTEDINTERFACES
)
4847 + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n";
4849 pVar
->PutString( aRet
);
4851 // Id == -2: output properties
4852 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
4854 // by now all properties must be established
4856 OUString aRetStr
= Impl_DumpProperties();
4857 pVar
->PutString( aRetStr
);
4859 // Id == -3: output the methods
4860 else if( nId
== -3 ) // Property ID_DBG_METHODS
4862 // by now all properties must be established
4864 OUString aRet
= "Methods of object "
4865 + getDbgObjectName()
4866 + "\nNo methods found\n";
4867 pVar
->PutString( aRet
);
4872 if ( it
!= maFields
.end() )
4874 Any aRetAny
= it
->second
->getValue();
4875 unoToSbxValue( pVar
, aRetAny
);
4878 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4880 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
4882 if ( it
!= maFields
.end() )
4884 // take over the value from Uno to Sbx
4885 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
4886 it
->second
->setValue( aAnyValue
);
4889 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4893 SbxObject::Notify( rBC
, rHint
);
4896 StructRefInfo
SbUnoStructRefObject::getStructMember( const OUString
& rMemberName
)
4898 if (!mbMemberCacheInit
)
4902 StructFieldInfo::iterator it
= maFields
.find( rMemberName
);
4904 css::uno::Type aFoundType
;
4905 sal_Int32 nFoundPos
= -1;
4907 if ( it
!= maFields
.end() )
4909 aFoundType
= it
->second
->getType();
4910 nFoundPos
= it
->second
->getPos();
4912 StructRefInfo
aRet( maMemberInfo
.getRootAnyRef(), aFoundType
, nFoundPos
);
4916 OUString
SbUnoStructRefObject::getDbgObjectName() const
4918 OUString aName
= GetClassName();
4919 if( aName
.isEmpty() )
4923 OUStringBuffer aRet
;
4924 if( aName
.getLength() > 20 )
4926 aRet
.append( "\n" );
4928 aRet
.append( "\"" );
4929 aRet
.append( aName
);
4930 aRet
.append( "\":" );
4931 return aRet
.makeStringAndClear();
4934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */