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 <osl/diagnose.h>
23 #include <o3tl/any.hxx>
24 #include <o3tl/safeint.hxx>
26 #include <vcl/svapp.hxx>
27 #include <comphelper/errcode.hxx>
28 #include <svl/hint.hxx>
30 #include <cppuhelper/implbase.hxx>
31 #include <cppuhelper/exc_hlp.hxx>
32 #include <comphelper/interfacecontainer4.hxx>
33 #include <comphelper/extract.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <cppuhelper/weakref.hxx>
37 #include <rtl/math.hxx>
38 #include <rtl/ustrbuf.hxx>
40 #include <com/sun/star/script/ArrayWrapper.hpp>
41 #include <com/sun/star/script/CannotConvertException.hpp>
42 #include <com/sun/star/script/NativeObjectWrapper.hpp>
43 #include <com/sun/star/sheet/XSheetCellCursor.hpp>
45 #include <com/sun/star/uno/XComponentContext.hpp>
46 #include <com/sun/star/uno/DeploymentException.hpp>
47 #include <com/sun/star/lang/XTypeProvider.hpp>
48 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/lang/XServiceInfo.hpp>
51 #include <com/sun/star/beans/PropertyAttribute.hpp>
52 #include <com/sun/star/beans/PropertyConcept.hpp>
53 #include <com/sun/star/beans/MethodConcept.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/beans/theIntrospection.hpp>
56 #include <com/sun/star/script/BasicErrorException.hpp>
57 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
58 #include <com/sun/star/script/XAllListener.hpp>
59 #include <com/sun/star/script/Converter.hpp>
60 #include <com/sun/star/script/XDefaultProperty.hpp>
61 #include <com/sun/star/script/XDirectInvocation.hpp>
62 #include <com/sun/star/container/XNameAccess.hpp>
63 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
64 #include <com/sun/star/reflection/XIdlArray.hpp>
65 #include <com/sun/star/reflection/XIdlReflection.hpp>
66 #include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
67 #include <com/sun/star/reflection/XSingletonTypeDescription.hpp>
68 #include <com/sun/star/reflection/theCoreReflection.hpp>
69 #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp>
70 #include <com/sun/star/bridge/oleautomation/Date.hpp>
71 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
72 #include <com/sun/star/bridge/oleautomation/Currency.hpp>
73 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
74 #include <com/sun/star/script/XAutomationInvocation.hpp>
76 #include <rtlproto.hxx>
78 #include <basic/sbstar.hxx>
79 #include <basic/sbuno.hxx>
80 #include <basic/sberrors.hxx>
81 #include <sbunoobj.hxx>
82 #include <sbintern.hxx>
83 #include <runtime.hxx>
88 #include <string_view>
89 #include <unordered_map>
90 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
91 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
93 using com::sun::star::uno::Reference
;
94 using namespace com::sun::star::uno
;
95 using namespace com::sun::star::lang
;
96 using namespace com::sun::star::reflection
;
97 using namespace com::sun::star::beans
;
98 using namespace com::sun::star::script
;
99 using namespace com::sun::star::container
;
100 using namespace com::sun::star::bridge
;
101 using namespace cppu
;
104 // Identifiers for creating the strings for dbg_Properties
105 constexpr OUString ID_DBG_SUPPORTEDINTERFACES
= u
"Dbg_SupportedInterfaces"_ustr
;
106 constexpr OUString ID_DBG_PROPERTIES
= u
"Dbg_Properties"_ustr
;
107 constexpr OUString ID_DBG_METHODS
= u
"Dbg_Methods"_ustr
;
109 char const aSeqLevelStr
[] = "[]";
111 // Gets the default property for a uno object. Note: There is some
112 // redirection built in. The property name specifies the name
113 // of the default property.
115 bool SbUnoObject::getDefaultPropName( SbUnoObject
const * pUnoObj
, OUString
& sDfltProp
)
117 bool bResult
= false;
118 Reference
< XDefaultProperty
> xDefaultProp( pUnoObj
->maTmpUnoObj
, UNO_QUERY
);
119 if ( xDefaultProp
.is() )
121 sDfltProp
= xDefaultProp
->getDefaultPropertyName();
122 if ( !sDfltProp
.isEmpty() )
128 SbxVariable
* getDefaultProp( SbxVariable
* pRef
)
130 SbxVariable
* pDefaultProp
= nullptr;
131 if ( pRef
->GetType() == SbxOBJECT
)
133 SbxObject
* pObj
= dynamic_cast<SbxObject
*>(pRef
);
136 SbxBase
* pObjVarObj
= pRef
->GetObject();
137 pObj
= dynamic_cast<SbxObject
*>( pObjVarObj
);
139 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
141 pDefaultProp
= pUnoObj
->GetDfltProperty();
147 void SetSbUnoObjectDfltPropName( SbxObject
* pObj
)
149 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
152 OUString sDfltPropName
;
154 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
156 pUnoObj
->SetDfltProperty( sDfltPropName
);
161 // save CoreReflection statically
162 static Reference
< XIdlReflection
> getCoreReflection_Impl()
164 return css::reflection::theCoreReflection::get(
165 comphelper::getProcessComponentContext());
168 // save CoreReflection statically
169 static Reference
< XHierarchicalNameAccess
> const & getCoreReflection_HierarchicalNameAccess_Impl()
171 static Reference
< XHierarchicalNameAccess
> xCoreReflection_HierarchicalNameAccess
;
173 if( !xCoreReflection_HierarchicalNameAccess
.is() )
175 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
176 if( xCoreReflection
.is() )
178 xCoreReflection_HierarchicalNameAccess
=
179 Reference
< XHierarchicalNameAccess
>( xCoreReflection
, UNO_QUERY
);
182 return xCoreReflection_HierarchicalNameAccess
;
185 // Hold TypeProvider statically
186 static Reference
< XHierarchicalNameAccess
> const & getTypeProvider_Impl()
188 static Reference
< XHierarchicalNameAccess
> xAccess
;
190 // Do we have already CoreReflection; if not obtain it
193 const Reference
< XComponentContext
>& xContext(
194 comphelper::getProcessComponentContext() );
197 xContext
->getValueByName(
198 u
"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr
)
200 OSL_ENSURE( xAccess
.is(), "### TypeDescriptionManager singleton not accessible!?" );
204 throw DeploymentException(
205 u
"/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible"_ustr
);
211 // Hold TypeConverter statically
212 static Reference
< XTypeConverter
> const & getTypeConverter_Impl()
214 static Reference
< XTypeConverter
> xTypeConverter
;
216 // Do we have already CoreReflection; if not obtain it
217 if( !xTypeConverter
.is() )
219 const Reference
< XComponentContext
>& xContext(
220 comphelper::getProcessComponentContext() );
223 xTypeConverter
= Converter::create(xContext
);
225 if( !xTypeConverter
.is() )
227 throw DeploymentException(
228 u
"com.sun.star.script.Converter service not accessible"_ustr
);
231 return xTypeConverter
;
235 // #111851 factory function to create an OLE object
236 SbUnoObject
* createOLEObject_Impl( const OUString
& aType
)
238 static const Reference
<XMultiServiceFactory
> xOLEFactory
= [] {
239 Reference
<XMultiServiceFactory
> xFactory
;
240 const Reference
< XComponentContext
>& xContext( comphelper::getProcessComponentContext() );
243 Reference
<XMultiComponentFactory
> xSMgr
= xContext
->getServiceManager();
245 xSMgr
->createInstanceWithContext( u
"com.sun.star.bridge.OleObjectFactory"_ustr
, xContext
),
251 SbUnoObject
* pUnoObj
= nullptr;
252 if( xOLEFactory
.is() )
254 // some type names available in VBA can not be directly used in COM
255 OUString aOLEType
= aType
;
256 if ( aOLEType
== "SAXXMLReader30" )
258 aOLEType
= "Msxml2.SAXXMLReader.3.0";
260 Reference
< XInterface
> xOLEObject
= xOLEFactory
->createInstance( aOLEType
);
261 if( xOLEObject
.is() )
263 pUnoObj
= new SbUnoObject( aType
, Any(xOLEObject
) );
264 OUString sDfltPropName
;
266 if ( SbUnoObject::getDefaultPropName( pUnoObj
, sDfltPropName
) )
267 pUnoObj
->SetDfltProperty( sDfltPropName
);
276 void lcl_indent( OUStringBuffer
& _inout_rBuffer
, sal_Int32 _nLevel
)
278 while ( _nLevel
-- > 0 )
280 _inout_rBuffer
.append( " " );
285 static void implAppendExceptionMsg( OUStringBuffer
& _inout_rBuffer
, const Exception
& _e
, std::u16string_view _rExceptionType
, sal_Int32 _nLevel
)
287 _inout_rBuffer
.append( "\n" );
288 lcl_indent( _inout_rBuffer
, _nLevel
);
289 _inout_rBuffer
.append( "Type: " );
291 if ( _rExceptionType
.empty() )
292 _inout_rBuffer
.append( "Unknown" );
294 _inout_rBuffer
.append( _rExceptionType
);
296 _inout_rBuffer
.append( "\n" );
297 lcl_indent( _inout_rBuffer
, _nLevel
);
298 _inout_rBuffer
.append( "Message: " );
299 _inout_rBuffer
.append( _e
.Message
);
303 // construct an error message for the exception
304 static OUString
implGetExceptionMsg( const Exception
& e
, std::u16string_view aExceptionType_
)
306 OUStringBuffer aMessageBuf
;
307 implAppendExceptionMsg( aMessageBuf
, e
, aExceptionType_
, 0 );
308 return aMessageBuf
.makeStringAndClear();
311 static OUString
implGetExceptionMsg( const Any
& _rCaughtException
)
313 auto e
= o3tl::tryAccess
<Exception
>(_rCaughtException
);
314 OSL_PRECOND( e
, "implGetExceptionMsg: illegal argument!" );
319 return implGetExceptionMsg( *e
, _rCaughtException
.getValueTypeName() );
322 static Any
convertAny( const Any
& rVal
, const Type
& aDestType
)
325 const Reference
< XTypeConverter
>& xConverter
= getTypeConverter_Impl();
328 aConvertedVal
= xConverter
->convertTo( rVal
, aDestType
);
330 catch( const IllegalArgumentException
& )
332 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
333 implGetExceptionMsg( ::cppu::getCaughtException() ) );
334 return aConvertedVal
;
336 catch( const CannotConvertException
& e2
)
338 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
339 implGetExceptionMsg( e2
, u
"com.sun.star.lang.IllegalArgumentException" ) );
340 return aConvertedVal
;
342 return aConvertedVal
;
346 // #105565 Special Object to wrap a strongly typed Uno Any
349 // TODO: source out later
350 static Reference
<XIdlClass
> TypeToIdlClass( const Type
& rType
)
352 return getCoreReflection_Impl()->forName(rType
.getTypeName());
355 // Exception type unknown
356 template< class EXCEPTION
>
357 static OUString
implGetExceptionMsg( const EXCEPTION
& e
)
359 return implGetExceptionMsg( e
, cppu::UnoType
<decltype(e
)>::get().getTypeName() );
362 static void implHandleBasicErrorException( BasicErrorException
const & e
)
364 ErrCode nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(e
.ErrorCode
) );
365 StarBASIC::Error( nError
, e
.ErrorMessageArgument
);
368 static void implHandleWrappedTargetException( const Any
& _rWrappedTargetException
)
370 Any
aExamine( _rWrappedTargetException
);
372 // completely strip the first InvocationTargetException, its error message isn't of any
373 // interest to the user, it just says something like "invoking the UNO method went wrong.".
374 InvocationTargetException aInvocationError
;
375 if ( aExamine
>>= aInvocationError
)
376 aExamine
= aInvocationError
.TargetException
;
378 BasicErrorException aBasicError
;
380 ErrCode
nError( ERRCODE_BASIC_EXCEPTION
);
381 OUStringBuffer aMessageBuf
;
383 // strip any other WrappedTargetException instances, but this time preserve the error messages.
384 WrappedTargetException aWrapped
;
385 sal_Int32 nLevel
= 0;
386 while ( aExamine
>>= aWrapped
)
388 // special handling for BasicErrorException errors
389 if ( aWrapped
.TargetException
>>= aBasicError
)
391 nError
= StarBASIC::GetSfxFromVBError( static_cast<sal_uInt16
>(aBasicError
.ErrorCode
) );
392 aMessageBuf
.append( aBasicError
.ErrorMessageArgument
);
397 // append this round's message
398 implAppendExceptionMsg( aMessageBuf
, aWrapped
, aExamine
.getValueTypeName(), nLevel
);
399 if ( aWrapped
.TargetException
.getValueTypeClass() == TypeClass_EXCEPTION
)
400 // there is a next chain element
401 aMessageBuf
.append( "\nTargetException:" );
404 aExamine
= aWrapped
.TargetException
;
408 if ( auto e
= o3tl::tryAccess
<Exception
>(aExamine
) )
410 // the last element in the chain is still an exception, but no WrappedTargetException
411 implAppendExceptionMsg( aMessageBuf
, *e
, aExamine
.getValueTypeName(), nLevel
);
414 StarBASIC::Error( nError
, aMessageBuf
.makeStringAndClear() );
417 static void implHandleAnyException( const Any
& _rCaughtException
)
419 BasicErrorException aBasicError
;
420 WrappedTargetException aWrappedError
;
422 if ( _rCaughtException
>>= aBasicError
)
424 implHandleBasicErrorException( aBasicError
);
426 else if ( _rCaughtException
>>= aWrappedError
)
428 implHandleWrappedTargetException( _rCaughtException
);
432 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( _rCaughtException
) );
438 // NativeObjectWrapper handling
441 SbxObjectRef m_xNativeObj
;
443 explicit ObjectItem( SbxObject
* pNativeObj
)
444 : m_xNativeObj( pNativeObj
)
450 typedef std::vector
< ObjectItem
> NativeObjectWrapperVector
;
454 NativeObjectWrapperVector gaNativeObjectWrapperVector
;
458 void clearNativeObjectWrapperVector()
460 gaNativeObjectWrapperVector
.clear();
463 static sal_uInt32
lcl_registerNativeObjectWrapper( SbxObject
* pNativeObj
)
465 sal_uInt32 nIndex
= gaNativeObjectWrapperVector
.size();
466 gaNativeObjectWrapperVector
.emplace_back( pNativeObj
);
470 static SbxObject
* lcl_getNativeObject( sal_uInt32 nIndex
)
472 SbxObjectRef xRetObj
;
473 if( nIndex
< gaNativeObjectWrapperVector
.size() )
475 ObjectItem
& rItem
= gaNativeObjectWrapperVector
[ nIndex
];
476 xRetObj
= rItem
.m_xNativeObj
;
478 return xRetObj
.get();
481 // convert from Uno to Sbx
482 static SbxDataType
unoToSbxType( TypeClass eType
)
484 SbxDataType eRetType
= SbxVOID
;
488 case TypeClass_INTERFACE
:
490 case TypeClass_STRUCT
:
491 case TypeClass_EXCEPTION
: eRetType
= SbxOBJECT
; break;
493 case TypeClass_ENUM
: eRetType
= SbxLONG
; break;
494 case TypeClass_SEQUENCE
:
495 eRetType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
499 case TypeClass_ANY
: eRetType
= SbxVARIANT
; break;
500 case TypeClass_BOOLEAN
: eRetType
= SbxBOOL
; break;
501 case TypeClass_CHAR
: eRetType
= SbxCHAR
; break;
502 case TypeClass_STRING
: eRetType
= SbxSTRING
; break;
503 case TypeClass_FLOAT
: eRetType
= SbxSINGLE
; break;
504 case TypeClass_DOUBLE
: eRetType
= SbxDOUBLE
; break;
505 case TypeClass_BYTE
: eRetType
= SbxINTEGER
; break;
506 case TypeClass_SHORT
: eRetType
= SbxINTEGER
; break;
507 case TypeClass_LONG
: eRetType
= SbxLONG
; break;
508 case TypeClass_HYPER
: eRetType
= SbxSALINT64
; break;
509 case TypeClass_UNSIGNED_SHORT
: eRetType
= SbxUSHORT
; break;
510 case TypeClass_UNSIGNED_LONG
: eRetType
= SbxULONG
; break;
511 case TypeClass_UNSIGNED_HYPER
: eRetType
= SbxSALUINT64
;break;
517 static SbxDataType
unoToSbxType( const Reference
< XIdlClass
>& xIdlClass
)
519 SbxDataType eRetType
= SbxVOID
;
522 TypeClass eType
= xIdlClass
->getTypeClass();
523 eRetType
= unoToSbxType( eType
);
528 static void implSequenceToMultiDimArray( SbxDimArray
*& pArray
, Sequence
< sal_Int32
>& indices
, Sequence
< sal_Int32
>& sizes
, const Any
& aValue
, sal_Int32 dimension
, bool bIsZeroIndex
, Type
const * pType
)
530 const Type
& aType
= aValue
.getValueType();
531 TypeClass eTypeClass
= aType
.getTypeClass();
533 sal_Int32 dimCopy
= dimension
;
535 if ( eTypeClass
== TypeClass_SEQUENCE
)
537 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
538 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
539 typelib_TypeDescription
* pTD
= nullptr;
540 aType
.getDescription( &pTD
);
541 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
542 ::typelib_typedescription_release( pTD
);
544 sal_Int32 nLen
= xIdlArray
->getLen( aValue
);
545 for ( sal_Int32 index
= 0; index
< nLen
; ++index
)
547 auto pindices
= indices
.getArray();
548 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(index
) );
549 // This detects the dimension were currently processing
550 if ( dimCopy
== dimension
)
553 if ( sizes
.getLength() < dimCopy
)
555 sizes
.realloc( sizes
.getLength() + 1 );
556 sizes
.getArray()[ sizes
.getLength() - 1 ] = nLen
;
557 indices
.realloc( indices
.getLength() + 1 );
558 pindices
= indices
.getArray();
563 pindices
[ dimCopy
- 1 ] = index
;
565 pindices
[ dimCopy
- 1] = index
+ 1;
567 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aElementAny
, dimCopy
, bIsZeroIndex
, &aElementType
);
573 if ( !indices
.hasElements() )
575 // Should never ever get here ( indices.getLength()
576 // should equal number of dimensions in the array )
577 // And that should at least be 1 !
578 // #QUESTION is there a better error?
579 StarBASIC::Error( ERRCODE_BASIC_INVALID_OBJECT
);
583 SbxDataType eSbxElementType
= unoToSbxType( pType
? pType
->getTypeClass() : aValue
.getValueTypeClass() );
586 pArray
= new SbxDimArray( eSbxElementType
);
587 sal_Int32 nIndexLen
= indices
.getLength();
589 // Dimension the array
590 for ( sal_Int32 index
= 0; index
< nIndexLen
; ++index
)
593 pArray
->unoAddDim(0, sizes
[index
] - 1);
595 pArray
->unoAddDim(1, sizes
[index
]);
602 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
603 unoToSbxValue( xVar
.get(), aValue
);
605 sal_Int32
* pIndices
= indices
.getArray();
606 pArray
->Put(xVar
.get(), pIndices
);
612 void unoToSbxValue( SbxVariable
* pVar
, const Any
& aValue
)
614 const Type
& aType
= aValue
.getValueType();
615 TypeClass eTypeClass
= aType
.getTypeClass();
620 // Map Type to IdlClass
623 Reference
<XIdlClass
> xClass
= TypeToIdlClass( aType_
);
625 aClassAny
<<= xClass
;
627 // instantiate SbUnoObject
628 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aClassAny
);
629 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
631 // If the object is invalid deliver null
632 if( !pSbUnoObject
->getUnoAny().hasValue() )
634 pVar
->PutObject( nullptr );
638 pVar
->PutObject( xWrapper
.get() );
642 // Interfaces and Structs must be wrapped in a SbUnoObject
643 case TypeClass_INTERFACE
:
644 case TypeClass_STRUCT
:
645 case TypeClass_EXCEPTION
:
647 if( eTypeClass
== TypeClass_STRUCT
)
650 NativeObjectWrapper aNativeObjectWrapper
;
651 if ( aValue
>>= aWrap
)
653 SbxDimArray
* pArray
= nullptr;
654 Sequence
< sal_Int32
> indices
;
655 Sequence
< sal_Int32
> sizes
;
656 implSequenceToMultiDimArray( pArray
, indices
, sizes
, aWrap
.Array
, /*dimension*/0, aWrap
.IsZeroIndex
, nullptr );
659 SbxDimArrayRef xArray
= pArray
;
660 SbxFlagBits nFlags
= pVar
->GetFlags();
661 pVar
->ResetFlag( SbxFlagBits::Fixed
);
662 pVar
->PutObject( xArray
.get() );
663 pVar
->SetFlags( nFlags
);
669 else if ( aValue
>>= aNativeObjectWrapper
)
671 sal_uInt32 nIndex
= 0;
672 if( aNativeObjectWrapper
.ObjectId
>>= nIndex
)
674 SbxObject
* pObj
= lcl_getNativeObject( nIndex
);
675 pVar
->PutObject( pObj
);
683 SbiInstance
* pInst
= GetSbData()->pInst
;
684 if( pInst
&& pInst
->IsCompatibility() )
686 oleautomation::Date aDate
;
687 if( aValue
>>= aDate
)
689 pVar
->PutDate( aDate
.Value
);
694 oleautomation::Decimal aDecimal
;
695 if( aValue
>>= aDecimal
)
697 pVar
->PutDecimal( aDecimal
);
702 oleautomation::Currency aCurrency
;
703 if( aValue
>>= aCurrency
)
705 pVar
->PutCurrency( aCurrency
.Value
);
713 // instantiate a SbUnoObject
714 SbUnoObject
* pSbUnoObject
= new SbUnoObject( OUString(), aValue
);
715 //If this is called externally e.g. from the scripting
716 //framework then there is no 'active' runtime the default property will not be set up
717 //only a vba object will have XDefaultProp set anyway so... this
718 //test seems a bit of overkill
719 //if ( SbiRuntime::isVBAEnabled() )
721 OUString sDfltPropName
;
723 if ( SbUnoObject::getDefaultPropName( pSbUnoObject
, sDfltPropName
) )
725 pSbUnoObject
->SetDfltProperty( sDfltPropName
);
728 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
730 // If the object is invalid deliver null
731 if( !pSbUnoObject
->getUnoAny().hasValue() )
733 pVar
->PutObject( nullptr );
737 pVar
->PutObject( xWrapper
.get() );
746 enum2int( nEnum
, aValue
);
747 pVar
->PutLong( nEnum
);
751 case TypeClass_SEQUENCE
:
753 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aType
);
754 Reference
< XIdlArray
> xIdlArray
= xIdlTargetClass
->getArray();
755 sal_Int32 i
, nLen
= xIdlArray
->getLen( aValue
);
757 typelib_TypeDescription
* pTD
= nullptr;
758 aType
.getDescription( &pTD
);
759 assert( pTD
&& pTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
);
760 Type
aElementType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pTD
)->pType
);
761 ::typelib_typedescription_release( pTD
);
763 // build an Array in Basic
764 SbxDimArrayRef xArray
;
765 SbxDataType eSbxElementType
= unoToSbxType( aElementType
.getTypeClass() );
766 xArray
= new SbxDimArray( eSbxElementType
);
769 xArray
->unoAddDim(0, nLen
- 1);
771 // register the elements as variables
772 for( i
= 0 ; i
< nLen
; i
++ )
775 Any aElementAny
= xIdlArray
->get( aValue
, static_cast<sal_uInt32
>(i
) );
776 auto xVar
= tools::make_ref
<SbxVariable
>( eSbxElementType
);
777 unoToSbxValue( xVar
.get(), aElementAny
);
779 // put into the Array
780 xArray
->Put(xVar
.get(), &i
);
785 xArray
->unoAddDim(0, -1);
789 SbxFlagBits nFlags
= pVar
->GetFlags();
790 pVar
->ResetFlag( SbxFlagBits::Fixed
);
791 pVar
->PutObject( xArray
.get() );
792 pVar
->SetFlags( nFlags
);
798 case TypeClass_BOOLEAN
: pVar
->PutBool( *o3tl::forceAccess
<bool>(aValue
) ); break;
801 pVar
->PutChar( *o3tl::forceAccess
<sal_Unicode
>(aValue
) );
804 case TypeClass_STRING
: { OUString val
; aValue
>>= val
; pVar
->PutString( val
); } break;
805 case TypeClass_FLOAT
: { float val
= 0; aValue
>>= val
; pVar
->PutSingle( val
); } break;
806 case TypeClass_DOUBLE
: { double val
= 0; aValue
>>= val
; pVar
->PutDouble( val
); } break;
807 case TypeClass_BYTE
: { sal_Int8 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
808 case TypeClass_SHORT
: { sal_Int16 val
= 0; aValue
>>= val
; pVar
->PutInteger( val
); } break;
809 case TypeClass_LONG
: { sal_Int32 val
= 0; aValue
>>= val
; pVar
->PutLong( val
); } break;
810 case TypeClass_HYPER
: { sal_Int64 val
= 0; aValue
>>= val
; pVar
->PutInt64( val
); } break;
811 case TypeClass_UNSIGNED_SHORT
: { sal_uInt16 val
= 0; aValue
>>= val
; pVar
->PutUShort( val
); } break;
812 case TypeClass_UNSIGNED_LONG
: { sal_uInt32 val
= 0; aValue
>>= val
; pVar
->PutULong( val
); } break;
813 case TypeClass_UNSIGNED_HYPER
: { sal_uInt64 val
= 0; aValue
>>= val
; pVar
->PutUInt64( val
); } break;
814 default: pVar
->PutEmpty(); break;
818 // Deliver the reflection for Sbx types
819 static Type
getUnoTypeForSbxBaseType( SbxDataType eType
)
821 Type aRetType
= cppu::UnoType
<void>::get();
824 case SbxNULL
: aRetType
= cppu::UnoType
<XInterface
>::get(); break;
825 case SbxINTEGER
: aRetType
= cppu::UnoType
<sal_Int16
>::get(); break;
826 case SbxLONG
: aRetType
= cppu::UnoType
<sal_Int32
>::get(); break;
827 case SbxSINGLE
: aRetType
= cppu::UnoType
<float>::get(); break;
828 case SbxDOUBLE
: aRetType
= cppu::UnoType
<double>::get(); break;
829 case SbxCURRENCY
: aRetType
= cppu::UnoType
<oleautomation::Currency
>::get(); break;
830 case SbxDECIMAL
: aRetType
= cppu::UnoType
<oleautomation::Decimal
>::get(); break;
832 SbiInstance
* pInst
= GetSbData()->pInst
;
833 if( pInst
&& pInst
->IsCompatibility() )
834 aRetType
= cppu::UnoType
<double>::get();
836 aRetType
= cppu::UnoType
<oleautomation::Date
>::get();
839 case SbxSTRING
: aRetType
= cppu::UnoType
<OUString
>::get(); break;
840 case SbxBOOL
: aRetType
= cppu::UnoType
<sal_Bool
>::get(); break;
841 case SbxVARIANT
: aRetType
= cppu::UnoType
<Any
>::get(); break;
842 case SbxCHAR
: aRetType
= cppu::UnoType
<cppu::UnoCharType
>::get(); break;
843 case SbxBYTE
: aRetType
= cppu::UnoType
<sal_Int8
>::get(); break;
844 case SbxUSHORT
: aRetType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get(); break;
845 case SbxULONG
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
846 // map machine-dependent ones to long for consistency
847 case SbxINT
: aRetType
= ::cppu::UnoType
<sal_Int32
>::get(); break;
848 case SbxUINT
: aRetType
= ::cppu::UnoType
<sal_uInt32
>::get(); break;
854 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
855 static Type
getUnoTypeForSbxValue( const SbxValue
* pVal
)
857 Type aRetType
= cppu::UnoType
<void>::get();
861 // convert SbxType to Uno
862 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
863 if( eBaseType
== SbxOBJECT
)
865 SbxBaseRef xObj
= pVal
->GetObject();
868 aRetType
= cppu::UnoType
<XInterface
>::get();
872 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
874 sal_Int32 nDims
= pArray
->GetDims();
875 Type aElementType
= getUnoTypeForSbxBaseType( static_cast<SbxDataType
>(pArray
->GetType() & 0xfff) );
876 TypeClass eElementTypeClass
= aElementType
.getTypeClass();
878 // Normal case: One dimensional array
879 sal_Int32 nLower
, nUpper
;
880 if (nDims
== 1 && pArray
->GetDim(1, nLower
, nUpper
))
882 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
884 // If all elements of the arrays are from the same type, take
885 // this one - otherwise the whole will be considered as Any-Sequence
886 bool bNeedsInit
= true;
888 for (sal_Int32 aIdx
[1] = { nLower
}; aIdx
[0] <= nUpper
; ++aIdx
[0])
890 SbxVariableRef xVar
= pArray
->Get(aIdx
);
891 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
894 if( aType
.getTypeClass() == TypeClass_VOID
)
896 // if only first element is void: different types -> []any
897 // if all elements are void: []void is not allowed -> []any
898 aElementType
= cppu::UnoType
<Any
>::get();
901 aElementType
= std::move(aType
);
904 else if( aElementType
!= aType
)
906 // different types -> AnySequence
907 aElementType
= cppu::UnoType
<Any
>::get();
913 OUString aSeqTypeName
= aSeqLevelStr
+ aElementType
.getTypeName();
914 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
);
916 // #i33795 Map also multi dimensional arrays to corresponding sequences
919 if( eElementTypeClass
== TypeClass_VOID
|| eElementTypeClass
== TypeClass_ANY
)
921 // For this check the array's dim structure does not matter
922 sal_uInt32 nFlatArraySize
= pArray
->Count();
924 bool bNeedsInit
= true;
925 for( sal_uInt32 i
= 0 ; i
< nFlatArraySize
; i
++ )
927 SbxVariableRef xVar
= pArray
->SbxArray::Get(i
);
928 Type aType
= getUnoTypeForSbxValue( xVar
.get() );
931 if( aType
.getTypeClass() == TypeClass_VOID
)
933 // if only first element is void: different types -> []any
934 // if all elements are void: []void is not allowed -> []any
935 aElementType
= cppu::UnoType
<Any
>::get();
938 aElementType
= std::move(aType
);
941 else if( aElementType
!= aType
)
943 // different types -> AnySequence
944 aElementType
= cppu::UnoType
<Any
>::get();
950 OUStringBuffer aSeqTypeName
;
951 for(sal_Int32 iDim
= 0 ; iDim
< nDims
; iDim
++ )
953 aSeqTypeName
.append(aSeqLevelStr
);
955 aSeqTypeName
.append(aElementType
.getTypeName());
956 aRetType
= Type( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
960 else if( auto obj
= dynamic_cast<SbUnoObject
*>( xObj
.get() ) )
962 aRetType
= obj
->getUnoAny().getValueType();
965 else if( auto any
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
967 aRetType
= any
->getValue().getValueType();
969 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
971 // No object, convert basic type
974 if (eBaseType
== SbxBYTE
&& pVal
->GetByte() > 127)
976 // Basic Byte type is unsigned; cppu::UnoType<sal_uInt8> corresponds to UNO boolean,
977 // so values 128-255 are only representable starting with UNO short types
978 eBaseType
= SbxUSHORT
;
980 aRetType
= getUnoTypeForSbxBaseType( eBaseType
);
985 // converting of Sbx to Uno without known target class for TypeClass_ANY
986 static Any
sbxToUnoValueImpl( const SbxValue
* pVar
, bool bBlockConversionToSmallestType
= false )
988 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
989 if( eBaseType
== SbxOBJECT
)
991 SbxBaseRef xObj
= pVar
->GetObject();
994 if( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
995 return obj
->getValue();
996 if( auto pClassModuleObj
= dynamic_cast<SbClassModuleObject
*>( xObj
.get() ) )
999 SbModule
& rClassModule
= pClassModuleObj
->getClassModule();
1000 if (rClassModule
.createCOMWrapperForIface(aRetAny
, pClassModuleObj
))
1003 if( dynamic_cast<const SbUnoObject
*>( xObj
.get() ) == nullptr )
1005 // Create NativeObjectWrapper to identify object in case of callbacks
1006 SbxObject
* pObj
= dynamic_cast<SbxObject
*>( pVar
->GetObject() );
1007 if( pObj
!= nullptr )
1009 NativeObjectWrapper aNativeObjectWrapper
;
1010 sal_uInt32 nIndex
= lcl_registerNativeObjectWrapper( pObj
);
1011 aNativeObjectWrapper
.ObjectId
<<= nIndex
;
1013 aRetAny
<<= aNativeObjectWrapper
;
1020 Type aType
= getUnoTypeForSbxValue( pVar
);
1021 TypeClass eType
= aType
.getTypeClass();
1023 if( !bBlockConversionToSmallestType
)
1025 // #79615 Choose "smallest" representation for int values
1026 // because up cast is allowed, downcast not
1029 case TypeClass_FLOAT
:
1030 case TypeClass_DOUBLE
:
1032 double d
= pVar
->GetDouble();
1033 if( rtl::math::approxEqual(d
, floor( d
)) )
1035 if( d
>= -128 && d
<= 127 )
1036 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1037 else if( d
>= SbxMININT
&& d
<= SbxMAXINT
)
1038 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1039 else if( d
>= -SbxMAXLNG
&& d
<= SbxMAXLNG
)
1040 aType
= ::cppu::UnoType
<sal_Int32
>::get();
1044 case TypeClass_SHORT
:
1046 sal_Int16 n
= pVar
->GetInteger();
1047 if( n
>= -128 && n
<= 127 )
1048 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1051 case TypeClass_LONG
:
1053 sal_Int32 n
= pVar
->GetLong();
1054 if( n
>= -128 && n
<= 127 )
1055 aType
= ::cppu::UnoType
<sal_Int8
>::get();
1056 else if( n
>= SbxMININT
&& n
<= SbxMAXINT
)
1057 aType
= ::cppu::UnoType
<sal_Int16
>::get();
1060 case TypeClass_UNSIGNED_LONG
:
1062 sal_uInt32 n
= pVar
->GetLong();
1063 if( n
<= SbxMAXUINT
)
1064 aType
= cppu::UnoType
<cppu::UnoUnsignedShortType
>::get();
1067 // TODO: need to add hyper types ?
1072 return sbxToUnoValue( pVar
, aType
);
1076 // Helper function for StepREDIMP
1077 static Any
implRekMultiDimArrayToSequence( SbxDimArray
* pArray
,
1078 const Type
& aElemType
, sal_Int32 nMaxDimIndex
, sal_Int32 nActualDim
,
1079 sal_Int32
* pActualIndices
, sal_Int32
* pLowerBounds
, sal_Int32
* pUpperBounds
)
1081 sal_Int32 nSeqLevel
= nMaxDimIndex
- nActualDim
+ 1;
1082 OUStringBuffer aSeqTypeName
;
1084 for( i
= 0 ; i
< nSeqLevel
; i
++ )
1086 aSeqTypeName
.append(aSeqLevelStr
);
1088 aSeqTypeName
.append(aElemType
.getTypeName());
1089 Type
aSeqType( TypeClass_SEQUENCE
, aSeqTypeName
.makeStringAndClear() );
1091 // Create Sequence instance
1093 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( aSeqType
);
1094 xIdlTargetClass
->createObject( aRetVal
);
1096 // Alloc sequence according to array bounds
1097 sal_Int32 nUpper
= pUpperBounds
[nActualDim
];
1098 sal_Int32 nLower
= pLowerBounds
[nActualDim
];
1099 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1100 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1101 xArray
->realloc( aRetVal
, nSeqSize
);
1103 sal_Int32
& ri
= pActualIndices
[nActualDim
];
1105 for( ri
= nLower
,i
= 0 ; ri
<= nUpper
; ri
++,i
++ )
1109 if( nActualDim
< nMaxDimIndex
)
1111 aElementVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1112 nMaxDimIndex
, nActualDim
+ 1, pActualIndices
, pLowerBounds
, pUpperBounds
);
1116 SbxVariable
* pSource
= pArray
->Get(pActualIndices
);
1117 aElementVal
= sbxToUnoValue( pSource
, aElemType
);
1122 // transfer to the sequence
1123 xArray
->set( aRetVal
, i
, aElementVal
);
1125 catch( const IllegalArgumentException
& )
1127 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1128 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1130 catch (const IndexOutOfBoundsException
&)
1132 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1138 // Map old interface
1139 Any
sbxToUnoValue( const SbxValue
* pVar
)
1141 return sbxToUnoValueImpl( pVar
);
1144 // function to find a global identifier in
1145 // the UnoScope and to wrap it for Sbx
1146 static bool implGetTypeByName( const OUString
& rName
, Type
& rRetType
)
1148 bool bSuccess
= false;
1150 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
1151 if( xTypeAccess
->hasByHierarchicalName( rName
) )
1153 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
1154 Reference
< XTypeDescription
> xTypeDesc
;
1157 if( xTypeDesc
.is() )
1159 rRetType
= Type( xTypeDesc
->getTypeClass(), xTypeDesc
->getName() );
1167 // converting of Sbx to Uno with known target class
1168 Any
sbxToUnoValue( const SbxValue
* pVar
, const Type
& rType
, Property
const * pUnoProperty
)
1172 // #94560 No conversion of empty/void for MAYBE_VOID properties
1173 if( pUnoProperty
&& pUnoProperty
->Attributes
& PropertyAttribute::MAYBEVOID
)
1175 if( pVar
->IsEmpty() )
1179 SbxDataType eBaseType
= pVar
->SbxValue::GetType();
1180 if( eBaseType
== SbxOBJECT
)
1182 SbxBaseRef xObj
= pVar
->GetObject();
1183 if ( auto obj
= dynamic_cast<SbUnoAnyObject
*>( xObj
.get() ) )
1185 return obj
->getValue();
1189 TypeClass eType
= rType
.getTypeClass();
1191 // tdf#162431 - check for missing parameters
1192 if (eType
!= TypeClass_ANY
&& eType
!= TypeClass_VOID
&& pVar
->GetType() == SbxERROR
)
1194 SbxVariable
* paSbxVariable
= dynamic_cast<SbxVariable
*>(const_cast<SbxValue
*>(pVar
));
1195 if (paSbxVariable
&& SbiRuntime::IsMissing(paSbxVariable
, 1))
1196 StarBASIC::Error(ERRCODE_BASIC_NOT_OPTIONAL
);
1201 case TypeClass_INTERFACE
:
1202 case TypeClass_STRUCT
:
1203 case TypeClass_EXCEPTION
:
1205 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1208 if( pVar
->IsNull() && eType
== TypeClass_INTERFACE
)
1210 Reference
< XInterface
> xRef
;
1211 OUString aClassName
= xIdlTargetClass
->getName();
1212 Type
aClassType( xIdlTargetClass
->getTypeClass(), aClassName
);
1213 aRetVal
.setValue( &xRef
, aClassType
);
1217 // #112368 Special conversion for Decimal, Currency and Date
1218 if( eType
== TypeClass_STRUCT
)
1220 SbiInstance
* pInst
= GetSbData()->pInst
;
1221 if( pInst
&& pInst
->IsCompatibility() )
1223 if( rType
== cppu::UnoType
<oleautomation::Decimal
>::get())
1225 oleautomation::Decimal aDecimal
;
1226 pVar
->fillAutomationDecimal( aDecimal
);
1227 aRetVal
<<= aDecimal
;
1230 else if( rType
== cppu::UnoType
<oleautomation::Currency
>::get())
1232 // assumes per previous code that ole Currency is Int64
1233 aRetVal
<<= pVar
->GetInt64();
1236 else if( rType
== cppu::UnoType
<oleautomation::Date
>::get())
1238 oleautomation::Date aDate
;
1239 aDate
.Value
= pVar
->GetDate();
1246 SbxBaseRef pObj
= pVar
->GetObject();
1247 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1249 aRetVal
= obj
->getUnoAny();
1251 else if( auto structRef
= dynamic_cast<SbUnoStructRefObject
*>( pObj
.get() ) )
1253 aRetVal
= structRef
->getUnoAny();
1257 // null object -> null XInterface
1258 Reference
<XInterface
> xInt
;
1265 case TypeClass_TYPE
:
1267 if( eBaseType
== SbxOBJECT
)
1270 Reference
< XIdlClass
> xIdlClass
;
1272 SbxBaseRef pObj
= pVar
->GetObject();
1273 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
1275 Any aUnoAny
= obj
->getUnoAny();
1276 aUnoAny
>>= xIdlClass
;
1279 if( xIdlClass
.is() )
1281 OUString aClassName
= xIdlClass
->getName();
1282 Type
aType( xIdlClass
->getTypeClass(), aClassName
);
1286 else if( eBaseType
== SbxSTRING
)
1288 OUString aTypeName
= pVar
->GetOUString();
1290 bool bSuccess
= implGetTypeByName( aTypeName
, aType
);
1300 case TypeClass_ENUM
:
1302 aRetVal
= int2enum( pVar
->GetLong(), rType
);
1306 case TypeClass_SEQUENCE
:
1308 SbxBaseRef xObj
= pVar
->GetObject();
1309 if( auto pArray
= dynamic_cast<SbxDimArray
*>( xObj
.get() ) )
1311 sal_Int32 nDims
= pArray
->GetDims();
1313 // Normal case: One dimensional array
1314 sal_Int32 nLower
, nUpper
;
1315 if (nDims
== 1 && pArray
->GetDim(1, nLower
, nUpper
))
1317 sal_Int32 nSeqSize
= nUpper
- nLower
+ 1;
1319 // create the instance of the required sequence
1320 Reference
< XIdlClass
> xIdlTargetClass
= TypeToIdlClass( rType
);
1321 xIdlTargetClass
->createObject( aRetVal
);
1322 Reference
< XIdlArray
> xArray
= xIdlTargetClass
->getArray();
1323 xArray
->realloc( aRetVal
, nSeqSize
);
1326 OUString aClassName
= xIdlTargetClass
->getName();
1327 typelib_TypeDescription
* pSeqTD
= nullptr;
1328 typelib_typedescription_getByName( &pSeqTD
, aClassName
.pData
);
1330 Type
aElemType( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1332 // convert all array member and register them
1335 for (sal_Int32 i
= 0 ; i
< nSeqSize
; ++i
, ++aIdx
[0])
1337 SbxVariableRef xVar
= pArray
->Get(aIdx
);
1339 // Convert the value of Sbx to Uno
1340 Any aAnyValue
= sbxToUnoValue( xVar
.get(), aElemType
);
1344 // insert in the sequence
1345 xArray
->set( aRetVal
, i
, aAnyValue
);
1347 catch( const IllegalArgumentException
& )
1349 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
1350 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1352 catch (const IndexOutOfBoundsException
&)
1354 StarBASIC::Error( ERRCODE_BASIC_OUT_OF_RANGE
);
1358 // #i33795 Map also multi dimensional arrays to corresponding sequences
1359 else if( nDims
> 1 )
1362 typelib_TypeDescription
* pSeqTD
= nullptr;
1363 Type
aCurType( rType
);
1364 sal_Int32 nSeqLevel
= 0;
1368 OUString aTypeName
= aCurType
.getTypeName();
1369 typelib_typedescription_getByName( &pSeqTD
, aTypeName
.pData
);
1371 if( pSeqTD
->eTypeClass
== typelib_TypeClass_SEQUENCE
)
1373 aCurType
= Type( reinterpret_cast<typelib_IndirectTypeDescription
*>(pSeqTD
)->pType
);
1378 aElemType
= aCurType
;
1384 if( nSeqLevel
== nDims
)
1386 std::unique_ptr
<sal_Int32
[]> pLowerBounds(new sal_Int32
[nDims
]);
1387 std::unique_ptr
<sal_Int32
[]> pUpperBounds(new sal_Int32
[nDims
]);
1388 std::unique_ptr
<sal_Int32
[]> pActualIndices(new sal_Int32
[nDims
]);
1389 for(sal_Int32 i
= 1 ; i
<= nDims
; i
++ )
1391 sal_Int32 lBound
, uBound
;
1392 pArray
->GetDim(i
, lBound
, uBound
);
1394 sal_Int32 j
= i
- 1;
1395 pActualIndices
[j
] = pLowerBounds
[j
] = lBound
;
1396 pUpperBounds
[j
] = uBound
;
1399 aRetVal
= implRekMultiDimArrayToSequence( pArray
, aElemType
,
1400 nDims
- 1, 0, pActualIndices
.get(), pLowerBounds
.get(), pUpperBounds
.get() );
1408 // for Any use the class independent converting routine
1411 aRetVal
= sbxToUnoValueImpl( pVar
);
1415 case TypeClass_BOOLEAN
:
1417 aRetVal
<<= pVar
->GetBool();
1420 case TypeClass_CHAR
:
1422 aRetVal
<<= pVar
->GetChar();
1425 case TypeClass_STRING
: aRetVal
<<= pVar
->GetOUString(); break;
1426 case TypeClass_FLOAT
: aRetVal
<<= pVar
->GetSingle(); break;
1427 case TypeClass_DOUBLE
: aRetVal
<<= pVar
->GetDouble(); break;
1429 case TypeClass_BYTE
:
1431 sal_Int16 nVal
= pVar
->GetInteger();
1432 bool bOverflow
= false;
1438 else if( nVal
> 255 ) // 128..255 map to -128..-1
1444 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW
);
1446 sal_Int8 nByteVal
= static_cast<sal_Int8
>(nVal
);
1447 aRetVal
<<= nByteVal
;
1450 case TypeClass_SHORT
: aRetVal
<<= pVar
->GetInteger(); break;
1451 case TypeClass_LONG
: aRetVal
<<= pVar
->GetLong(); break;
1452 case TypeClass_HYPER
: aRetVal
<<= pVar
->GetInt64(); break;
1453 case TypeClass_UNSIGNED_SHORT
: aRetVal
<<= pVar
->GetUShort(); break;
1454 case TypeClass_UNSIGNED_LONG
: aRetVal
<<= pVar
->GetULong(); break;
1455 case TypeClass_UNSIGNED_HYPER
: aRetVal
<<= pVar
->GetUInt64(); break;
1462 static void processAutomationParams( SbxArray
* pParams
, Sequence
< Any
>& args
, sal_uInt32 nParamCount
)
1464 AutomationNamedArgsSbxArray
* pArgNamesArray
= dynamic_cast<AutomationNamedArgsSbxArray
*>( pParams
);
1466 args
.realloc( nParamCount
);
1467 Any
* pAnyArgs
= args
.getArray();
1468 bool bBlockConversionToSmallestType
= GetSbData()->pInst
->IsCompatibility();
1470 if( pArgNamesArray
)
1472 Sequence
< OUString
>& rNameSeq
= pArgNamesArray
->getNames();
1473 OUString
* pNames
= rNameSeq
.getArray();
1475 for( i
= 0 ; i
< nParamCount
; i
++ )
1477 sal_uInt32 iSbx
= i
+ 1;
1479 aValAny
= sbxToUnoValueImpl(pParams
->Get(iSbx
),
1480 bBlockConversionToSmallestType
);
1482 OUString aParamName
= pNames
[iSbx
];
1483 if( !aParamName
.isEmpty() )
1485 oleautomation::NamedArgument aNamedArgument
;
1486 aNamedArgument
.Name
= aParamName
;
1487 aNamedArgument
.Value
= aValAny
;
1488 pAnyArgs
[i
] <<= aNamedArgument
;
1492 pAnyArgs
[i
] = aValAny
;
1498 for( i
= 0 ; i
< nParamCount
; i
++ )
1500 pAnyArgs
[i
] = sbxToUnoValueImpl(pParams
->Get(i
+ 1),
1501 bBlockConversionToSmallestType
);
1509 enum class INVOKETYPE
1517 static Any
invokeAutomationMethod( const OUString
& Name
, Sequence
< Any
> const & args
, SbxArray
* pParams
, sal_uInt32 nParamCount
, Reference
< XInvocation
> const & rxInvocation
, INVOKETYPE invokeType
)
1519 Sequence
< sal_Int16
> OutParamIndex
;
1520 Sequence
< Any
> OutParam
;
1523 switch( invokeType
)
1525 case INVOKETYPE::Func
:
1526 aRetAny
= rxInvocation
->invoke( Name
, args
, OutParamIndex
, OutParam
);
1528 case INVOKETYPE::GetProp
:
1530 Reference
< XAutomationInvocation
> xAutoInv( rxInvocation
, UNO_QUERY
);
1531 aRetAny
= xAutoInv
->invokeGetProperty( Name
, args
, OutParamIndex
, OutParam
);
1535 assert(false); break;
1538 const sal_Int16
* pIndices
= OutParamIndex
.getConstArray();
1539 sal_uInt32 nLen
= OutParamIndex
.getLength();
1542 const Any
* pNewValues
= OutParam
.getConstArray();
1543 for( sal_uInt32 j
= 0 ; j
< nLen
; j
++ )
1545 sal_Int16 iTarget
= pIndices
[ j
];
1546 if( o3tl::make_unsigned(iTarget
) >= nParamCount
)
1548 unoToSbxValue(pParams
->Get(j
+ 1), pNewValues
[j
]);
1554 // Debugging help method to readout the implemented interfaces of an object
1555 static OUString
Impl_GetInterfaceInfo( const Reference
< XInterface
>& x
, const Reference
< XIdlClass
>& xClass
, sal_uInt16 nRekLevel
)
1557 Type aIfaceType
= cppu::UnoType
<XInterface
>::get();
1558 static Reference
< XIdlClass
> xIfaceClass
= TypeToIdlClass( aIfaceType
);
1560 OUStringBuffer aRetStr
;
1561 for( sal_uInt16 i
= 0 ; i
< nRekLevel
; i
++ )
1562 aRetStr
.append( " " );
1563 aRetStr
.append( xClass
->getName() );
1564 OUString aClassName
= xClass
->getName();
1565 Type
aClassType( xClass
->getTypeClass(), aClassName
);
1567 // checking if the interface is really supported
1568 if( !x
->queryInterface( aClassType
).hasValue() )
1570 aRetStr
.append( " (ERROR: Not really supported!)\n" );
1572 // Are there super interfaces?
1575 aRetStr
.append( "\n" );
1577 // get the super interfaces
1578 Sequence
< Reference
< XIdlClass
> > aSuperClassSeq
= xClass
->getSuperclasses();
1579 const Reference
< XIdlClass
>* pClasses
= aSuperClassSeq
.getConstArray();
1580 sal_uInt32 nSuperIfaceCount
= aSuperClassSeq
.getLength();
1581 for( sal_uInt32 j
= 0 ; j
< nSuperIfaceCount
; j
++ )
1583 const Reference
< XIdlClass
>& rxIfaceClass
= pClasses
[j
];
1584 if( !rxIfaceClass
->equals( xIfaceClass
) )
1585 aRetStr
.append( Impl_GetInterfaceInfo( x
, rxIfaceClass
, nRekLevel
+ 1 ) );
1588 return aRetStr
.makeStringAndClear();
1591 static OUString
getDbgObjectNameImpl(SbUnoObject
& rUnoObj
)
1593 OUString aName
= rUnoObj
.GetClassName();
1594 if( aName
.isEmpty() )
1596 Any aToInspectObj
= rUnoObj
.getUnoAny();
1597 Reference
< XInterface
> xObj(aToInspectObj
, css::uno::UNO_QUERY
);
1600 Reference
< XServiceInfo
> xServiceInfo( xObj
, UNO_QUERY
);
1601 if( xServiceInfo
.is() )
1602 aName
= xServiceInfo
->getImplementationName();
1608 static OUString
getDbgObjectName(SbUnoObject
& rUnoObj
)
1610 OUString aName
= getDbgObjectNameImpl(rUnoObj
);
1611 if( aName
.isEmpty() )
1614 OUStringBuffer aRet
;
1615 if( aName
.getLength() > 20 )
1617 aRet
.append( "\n" );
1619 aRet
.append( "\"" + aName
+ "\":" );
1620 return aRet
.makeStringAndClear();
1623 OUString
getBasicObjectTypeName( SbxObject
* pObj
)
1627 if (SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>(pObj
))
1629 return getDbgObjectNameImpl(*pUnoObj
);
1631 else if (SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>(pObj
))
1633 return pUnoStructObj
->GetClassName();
1641 bool matchesBasicTypeName(
1642 css::uno::Reference
<css::reflection::XIdlClass
> const & unoType
, OUString
const & basicTypeName
)
1644 if (unoType
->getName().endsWithIgnoreAsciiCase(basicTypeName
)) {
1647 auto const sups
= unoType
->getSuperclasses();
1649 sups
.begin(), sups
.end(),
1650 [&basicTypeName
](auto const & t
) { return matchesBasicTypeName(t
, basicTypeName
); });
1655 bool checkUnoObjectType(SbUnoObject
& rUnoObj
, const OUString
& rClass
)
1657 Any aToInspectObj
= rUnoObj
.getUnoAny();
1659 // Return true for XInvocation based objects as interface type names don't count then
1660 Reference
< XInvocation
> xInvocation( aToInspectObj
, UNO_QUERY
);
1661 if( xInvocation
.is() )
1665 bool bResult
= false;
1666 Reference
< XTypeProvider
> xTypeProvider( aToInspectObj
, UNO_QUERY
);
1667 if( xTypeProvider
.is() )
1669 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1670 have a leading 'X', in Basic we want to be able to do something
1671 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1672 add a leading 'X' to the class name and a leading dot to the entire
1673 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1674 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1675 'ooo.vba.msforms.XLabel'.
1677 OUString aClassName
;
1678 if ( SbiRuntime::isVBAEnabled() )
1681 sal_Int32 nClassNameDot
= rClass
.lastIndexOf( '.' );
1682 if( nClassNameDot
>= 0 )
1684 aClassName
+= OUString::Concat(rClass
.subView( 0, nClassNameDot
+ 1 )) + "X" + rClass
.subView( nClassNameDot
+ 1 );
1688 aClassName
+= "X" + rClass
;
1691 else // assume extended type declaration support for basic ( can't get here
1693 aClassName
= rClass
;
1695 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1696 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1697 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1698 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1700 const Type
& rType
= pTypeArray
[j
];
1702 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1705 OSL_FAIL("failed to get XIdlClass for type");
1708 OUString aInterfaceName
= xClass
->getName();
1709 if ( aInterfaceName
== "com.sun.star.bridge.oleautomation.XAutomationObject" )
1711 // there is a hack in the extensions/source/ole/oleobj.cxx
1712 // to return the typename of the automation object, let's
1713 // check if it matches
1714 Reference
< XInvocation
> xInv( aToInspectObj
, UNO_QUERY
);
1718 xInv
->getValue( u
"$GetTypeName"_ustr
) >>= sTypeName
;
1719 if ( sTypeName
.isEmpty() || sTypeName
== "IDispatch" )
1721 // can't check type, leave it pass
1726 bResult
= sTypeName
== rClass
;
1729 break; // finished checking automation object
1732 if ( matchesBasicTypeName(xClass
, aClassName
) )
1742 // Debugging help method to readout the implemented interfaces of an object
1743 static OUString
Impl_GetSupportedInterfaces(SbUnoObject
& rUnoObj
)
1745 Any aToInspectObj
= rUnoObj
.getUnoAny();
1747 // allow only TypeClass interface
1748 OUStringBuffer aRet
;
1749 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aToInspectObj
);
1752 aRet
.append( ID_DBG_SUPPORTEDINTERFACES
1753 + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1757 Reference
< XTypeProvider
> xTypeProvider( *x
, UNO_QUERY
);
1759 aRet
.append( "Supported interfaces by object "
1760 + getDbgObjectName(rUnoObj
)
1762 if( xTypeProvider
.is() )
1764 // get the interfaces of the implementation
1765 Sequence
< Type
> aTypeSeq
= xTypeProvider
->getTypes();
1766 const Type
* pTypeArray
= aTypeSeq
.getConstArray();
1767 sal_uInt32 nIfaceCount
= aTypeSeq
.getLength();
1768 for( sal_uInt32 j
= 0 ; j
< nIfaceCount
; j
++ )
1770 const Type
& rType
= pTypeArray
[j
];
1772 Reference
<XIdlClass
> xClass
= TypeToIdlClass( rType
);
1775 aRet
.append( Impl_GetInterfaceInfo( *x
, xClass
, 1 ) );
1779 typelib_TypeDescription
* pTD
= nullptr;
1780 rType
.getDescription( &pTD
);
1782 aRet
.append( OUString::Concat("*** ERROR: No IdlClass for type \"")
1783 + OUString::unacquired(&pTD
->pTypeName
)
1784 + "\"\n*** Please check type library\n" );
1789 return aRet
.makeStringAndClear();
1793 // Debugging help method SbxDataType -> String
1794 static OUString
Dbg_SbxDataType2String( SbxDataType eType
)
1796 OUStringBuffer aRet
;
1799 case SbxEMPTY
: aRet
.append("SbxEMPTY"); break;
1800 case SbxNULL
: aRet
.append("SbxNULL"); break;
1801 case SbxINTEGER
: aRet
.append("SbxINTEGER"); break;
1802 case SbxLONG
: aRet
.append("SbxLONG"); break;
1803 case SbxSINGLE
: aRet
.append("SbxSINGLE"); break;
1804 case SbxDOUBLE
: aRet
.append("SbxDOUBLE"); break;
1805 case SbxCURRENCY
: aRet
.append("SbxCURRENCY"); break;
1806 case SbxDECIMAL
: aRet
.append("SbxDECIMAL"); break;
1807 case SbxDATE
: aRet
.append("SbxDATE"); break;
1808 case SbxSTRING
: aRet
.append("SbxSTRING"); break;
1809 case SbxOBJECT
: aRet
.append("SbxOBJECT"); break;
1810 case SbxERROR
: aRet
.append("SbxERROR"); break;
1811 case SbxBOOL
: aRet
.append("SbxBOOL"); break;
1812 case SbxVARIANT
: aRet
.append("SbxVARIANT"); break;
1813 case SbxDATAOBJECT
: aRet
.append("SbxDATAOBJECT"); break;
1814 case SbxCHAR
: aRet
.append("SbxCHAR"); break;
1815 case SbxBYTE
: aRet
.append("SbxBYTE"); break;
1816 case SbxUSHORT
: aRet
.append("SbxUSHORT"); break;
1817 case SbxULONG
: aRet
.append("SbxULONG"); break;
1818 case SbxSALINT64
: aRet
.append("SbxINT64"); break;
1819 case SbxSALUINT64
: aRet
.append("SbxUINT64"); break;
1820 case SbxINT
: aRet
.append("SbxINT"); break;
1821 case SbxUINT
: aRet
.append("SbxUINT"); break;
1822 case SbxVOID
: aRet
.append("SbxVOID"); break;
1823 case SbxHRESULT
: aRet
.append("SbxHRESULT"); break;
1824 case SbxPOINTER
: aRet
.append("SbxPOINTER"); break;
1825 case SbxDIMARRAY
: aRet
.append("SbxDIMARRAY"); break;
1826 case SbxCARRAY
: aRet
.append("SbxCARRAY"); break;
1827 case SbxUSERDEF
: aRet
.append("SbxUSERDEF"); break;
1828 case SbxLPSTR
: aRet
.append("SbxLPSTR"); break;
1829 case SbxLPWSTR
: aRet
.append("SbxLPWSTR"); break;
1830 case SbxCoreSTRING
: aRet
.append("SbxCoreSTRING"); break;
1831 case SbxOBJECT
| SbxARRAY
: aRet
.append("SbxARRAY"); break;
1832 default: aRet
.append("Unknown Sbx-Type!");break;
1834 return aRet
.makeStringAndClear();
1837 // Debugging help method to display the properties of a SbUnoObjects
1838 static OUString
Impl_DumpProperties(SbUnoObject
& rUnoObj
)
1840 OUStringBuffer
aRet("Properties of object " + getDbgObjectName(rUnoObj
));
1842 // analyse the Uno-Infos to recognise the arrays
1843 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1846 const Reference
< XInvocation
>& xInvok
= rUnoObj
.getInvocation();
1848 xAccess
= xInvok
->getIntrospection();
1852 aRet
.append( "\nUnknown, no introspection available\n" );
1853 return aRet
.makeStringAndClear();
1856 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
1857 sal_uInt32 nUnoPropCount
= props
.getLength();
1858 const Property
* pUnoProps
= props
.getConstArray();
1860 SbxArray
* pProps
= rUnoObj
.GetProperties();
1861 sal_uInt32 nPropCount
= pProps
->Count();
1862 sal_uInt32 nPropsPerLine
= 1 + nPropCount
/ 30;
1863 for( sal_uInt32 i
= 0; i
< nPropCount
; i
++ )
1865 SbxVariable
* pVar
= pProps
->Get(i
);
1868 OUStringBuffer aPropStr
;
1869 if( (i
% nPropsPerLine
) == 0 )
1870 aPropStr
.append( "\n" );
1872 // output the type and name
1873 // Is it in Uno a sequence?
1874 SbxDataType eType
= pVar
->GetFullType();
1876 bool bMaybeVoid
= false;
1877 if( i
< nUnoPropCount
)
1879 const Property
& rProp
= pUnoProps
[ i
];
1881 // For MAYBEVOID freshly convert the type from Uno,
1882 // so not just SbxEMPTY is returned.
1883 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
1885 eType
= unoToSbxType( rProp
.Type
.getTypeClass() );
1888 if( eType
== SbxOBJECT
)
1890 Type aType
= rProp
.Type
;
1891 if( aType
.getTypeClass() == TypeClass_SEQUENCE
)
1892 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1895 aPropStr
.append( Dbg_SbxDataType2String( eType
) );
1897 aPropStr
.append( "/void" );
1898 aPropStr
.append( " " + pVar
->GetName() );
1900 if( i
== nPropCount
- 1 )
1901 aPropStr
.append( "\n" );
1903 aPropStr
.append( "; " );
1905 aRet
.append( aPropStr
);
1908 return aRet
.makeStringAndClear();
1911 // Debugging help method to display the methods of an SbUnoObjects
1912 static OUString
Impl_DumpMethods(SbUnoObject
& rUnoObj
)
1914 OUStringBuffer
aRet("Methods of object " + getDbgObjectName(rUnoObj
));
1916 // XIntrospectionAccess, so that the types of the parameter could be outputted
1917 Reference
< XIntrospectionAccess
> xAccess
= rUnoObj
.getIntrospectionAccess();
1920 const Reference
< XInvocation
>& xInvok
= rUnoObj
.getInvocation();
1922 xAccess
= xInvok
->getIntrospection();
1926 aRet
.append( "\nUnknown, no introspection available\n" );
1927 return aRet
.makeStringAndClear();
1929 Sequence
< Reference
< XIdlMethod
> > methods
= xAccess
->getMethods
1930 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
1931 const Reference
< XIdlMethod
>* pUnoMethods
= methods
.getConstArray();
1933 SbxArray
* pMethods
= rUnoObj
.GetMethods();
1934 sal_uInt32 nMethodCount
= pMethods
->Count();
1937 aRet
.append( "\nNo methods found\n" );
1938 return aRet
.makeStringAndClear();
1940 sal_uInt32 nPropsPerLine
= 1 + nMethodCount
/ 30;
1941 for( sal_uInt32 i
= 0; i
< nMethodCount
; i
++ )
1943 SbxVariable
* pVar
= pMethods
->Get(i
);
1946 if( (i
% nPropsPerLine
) == 0 )
1947 aRet
.append( "\n" );
1949 // address the method
1950 const Reference
< XIdlMethod
>& rxMethod
= pUnoMethods
[i
];
1952 // Is it in Uno a sequence?
1953 SbxDataType eType
= pVar
->GetFullType();
1954 if( eType
== SbxOBJECT
)
1956 Reference
< XIdlClass
> xClass
= rxMethod
->getReturnType();
1957 if( xClass
.is() && xClass
->getTypeClass() == TypeClass_SEQUENCE
)
1958 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
1960 // output the name and the type
1961 aRet
.append( Dbg_SbxDataType2String( eType
)
1962 + " " + pVar
->GetName() + " ( " );
1964 // the get-method mustn't have a parameter
1965 Sequence
< Reference
< XIdlClass
> > aParamsSeq
= rxMethod
->getParameterTypes();
1966 sal_uInt32 nParamCount
= aParamsSeq
.getLength();
1967 const Reference
< XIdlClass
>* pParams
= aParamsSeq
.getConstArray();
1969 if( nParamCount
> 0 )
1971 for( sal_uInt32 j
= 0; j
< nParamCount
; j
++ )
1973 aRet
.append ( Dbg_SbxDataType2String( unoToSbxType( pParams
[ j
] ) ) );
1974 if( j
< nParamCount
- 1 )
1975 aRet
.append( ", " );
1979 aRet
.append( "void" );
1981 aRet
.append( " ) " );
1983 if( i
== nMethodCount
- 1 )
1984 aRet
.append( "\n" );
1986 aRet
.append( "; " );
1989 return aRet
.makeStringAndClear();
1993 // Implementation SbUnoObject
1994 void SbUnoObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
1996 if( bNeedIntrospection
)
1999 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
2003 SbxVariable
* pVar
= pHint
->GetVar();
2004 SbxArray
* pParams
= pVar
->GetParameters();
2005 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
2006 SbUnoMethod
* pMeth
= dynamic_cast<SbUnoMethod
*>( pVar
);
2009 bool bInvocation
= pProp
->isInvocationBased();
2010 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
2013 sal_Int32 nId
= pProp
->nId
;
2016 // Id == -1: Display implemented interfaces according the ClassProvider
2017 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2019 OUString aRetStr
= Impl_GetSupportedInterfaces(*this);
2020 pVar
->PutString( aRetStr
);
2022 // Id == -2: output properties
2023 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
2025 // now all properties must be created
2027 OUString aRetStr
= Impl_DumpProperties(*this);
2028 pVar
->PutString( aRetStr
);
2030 // Id == -3: output the methods
2031 else if( nId
== -3 ) // Property ID_DBG_METHODS
2033 // now all properties must be created
2035 OUString aRetStr
= Impl_DumpMethods(*this);
2036 pVar
->PutString( aRetStr
);
2041 if( !bInvocation
&& mxUnoAccess
.is() )
2047 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2048 if ( aMember
.isEmpty() )
2050 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2054 if ( pProp
->isUnoStruct() )
2056 SbUnoStructRefObject
* pSbUnoObject
= new SbUnoStructRefObject( pProp
->GetName(), std::move(aMember
) );
2057 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pSbUnoObject
);
2058 pVar
->PutObject( xWrapper
.get() );
2062 Any aRetAny
= aMember
.getValue();
2063 // take over the value from Uno to Sbx
2064 unoToSbxValue( pVar
, aRetAny
);
2070 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2071 Any aRetAny
= xPropSet
->getPropertyValue( pProp
->GetName() );
2072 // The use of getPropertyValue (instead of using the index) is
2073 // suboptimal, but the refactoring to XInvocation is already pending
2074 // Otherwise it is possible to use FastPropertySet
2076 // take over the value from Uno to Sbx
2077 unoToSbxValue( pVar
, aRetAny
);
2079 catch( const Exception
& )
2081 implHandleAnyException( ::cppu::getCaughtException() );
2084 else if( bInvocation
&& mxInvocation
.is() )
2088 sal_uInt32 nParamCount
= pParams
? (pParams
->Count() - 1) : 0;
2089 bool bCanBeConsideredAMethod
= mxInvocation
->hasMethod( pProp
->GetName() );
2091 if ( bCanBeConsideredAMethod
&& nParamCount
)
2093 // Automation properties have methods, so... we need to invoke this through
2096 processAutomationParams( pParams
, args
, nParamCount
);
2097 aRetAny
= invokeAutomationMethod( pProp
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::GetProp
);
2100 aRetAny
= mxInvocation
->getValue( pProp
->GetName() );
2101 // take over the value from Uno to Sbx
2102 unoToSbxValue( pVar
, aRetAny
);
2103 if( pParams
&& bCanBeConsideredAMethod
)
2104 pVar
->SetParameters( nullptr );
2107 catch( const Exception
& )
2109 implHandleAnyException( ::cppu::getCaughtException() );
2113 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
2115 if( !bInvocation
&& mxUnoAccess
.is() )
2117 if( pProp
->aUnoProp
.Attributes
& PropertyAttribute::READONLY
)
2119 StarBASIC::Error( ERRCODE_BASIC_PROP_READONLY
);
2124 StructRefInfo aMember
= maStructInfo
->getStructMember( pProp
->GetName() );
2125 if ( aMember
.isEmpty() )
2127 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
2131 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2132 aMember
.setValue( aAnyValue
);
2136 // take over the value from Uno to Sbx
2137 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
2141 Reference
< XPropertySet
> xPropSet( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2142 xPropSet
->setPropertyValue( pProp
->GetName(), aAnyValue
);
2143 // The use of getPropertyValue (instead of using the index) is
2144 // suboptimal, but the refactoring to XInvocation is already pending
2145 // Otherwise it is possible to use FastPropertySet
2147 catch( const Exception
& )
2149 implHandleAnyException( ::cppu::getCaughtException() );
2152 else if( bInvocation
&& mxInvocation
.is() )
2154 // take over the value from Uno to Sbx
2155 Any aAnyValue
= sbxToUnoValueImpl( pVar
);
2159 mxInvocation
->setValue( pProp
->GetName(), aAnyValue
);
2161 catch( const Exception
& )
2163 implHandleAnyException( ::cppu::getCaughtException() );
2170 bool bInvocation
= pMeth
->isInvocationBased();
2171 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
2173 // number of Parameter -1 because of Param0 == this
2174 sal_uInt32 nParamCount
= pParams
? (pParams
->Count() - 1) : 0;
2176 bool bOutParams
= false;
2178 if( !bInvocation
&& mxUnoAccess
.is() )
2181 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2182 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2183 sal_uInt32 nUnoParamCount
= rInfoSeq
.getLength();
2184 sal_uInt32 nAllocParamCount
= nParamCount
;
2186 // ignore surplus parameter; alternative: throw an error
2187 if( nParamCount
> nUnoParamCount
)
2189 nParamCount
= nUnoParamCount
;
2190 nAllocParamCount
= nParamCount
;
2192 else if( nParamCount
< nUnoParamCount
)
2194 SbiInstance
* pInst
= GetSbData()->pInst
;
2195 if( pInst
&& pInst
->IsCompatibility() )
2198 bool bError
= false;
2199 for( sal_uInt32 i
= nParamCount
; i
< nUnoParamCount
; i
++ )
2201 const ParamInfo
& rInfo
= pParamInfos
[i
];
2202 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2203 if( rxClass
->getTypeClass() != TypeClass_ANY
)
2206 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
2210 nAllocParamCount
= nUnoParamCount
;
2214 if( nAllocParamCount
> 0 )
2216 args
.realloc( nAllocParamCount
);
2217 Any
* pAnyArgs
= args
.getArray();
2218 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2220 const ParamInfo
& rInfo
= pParamInfos
[i
];
2221 const Reference
< XIdlClass
>& rxClass
= rInfo
.aType
;
2223 css::uno::Type
aType( rxClass
->getTypeClass(), rxClass
->getName() );
2225 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2226 pAnyArgs
[i
] = sbxToUnoValue(pParams
->Get(i
+ 1), aType
);
2228 // If it is not certain check whether the out-parameter are available.
2231 ParamMode aParamMode
= rInfo
.aMode
;
2232 if( aParamMode
!= ParamMode_IN
)
2238 else if( bInvocation
&& pParams
&& mxInvocation
.is() )
2240 processAutomationParams( pParams
, args
, nParamCount
);
2244 GetSbData()->bBlockCompilerError
= true; // #106433 Block compiler errors for API calls
2247 if( !bInvocation
&& mxUnoAccess
.is() )
2249 Any aRetAny
= pMeth
->m_xUnoMethod
->invoke( getUnoAny(), args
);
2251 // take over the value from Uno to Sbx
2252 unoToSbxValue( pVar
, aRetAny
);
2254 // Did we to copy back the Out-Parameter?
2257 const Any
* pAnyArgs
= args
.getConstArray();
2260 const Sequence
<ParamInfo
>& rInfoSeq
= pMeth
->getParamInfos();
2261 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2264 for( j
= 0 ; j
< nParamCount
; j
++ )
2266 const ParamInfo
& rInfo
= pParamInfos
[j
];
2267 ParamMode aParamMode
= rInfo
.aMode
;
2268 if( aParamMode
!= ParamMode_IN
)
2269 unoToSbxValue(pParams
->Get(j
+ 1), pAnyArgs
[j
]);
2273 else if( bInvocation
&& mxInvocation
.is() )
2275 Any aRetAny
= invokeAutomationMethod( pMeth
->GetName(), args
, pParams
, nParamCount
, mxInvocation
, INVOKETYPE::Func
);
2276 unoToSbxValue( pVar
, aRetAny
);
2279 // remove parameter here, because this was not done anymore in unoToSbxValue()
2282 pVar
->SetParameters( nullptr );
2284 catch( const Exception
& )
2286 implHandleAnyException( ::cppu::getCaughtException() );
2288 GetSbData()->bBlockCompilerError
= false; // #106433 Unblock compiler errors
2292 SbxObject::Notify( rBC
, rHint
);
2296 SbUnoObject::SbUnoObject( const OUString
& aName_
, const Any
& aUnoObj_
)
2297 : SbxObject( aName_
)
2298 , bNeedIntrospection( true )
2299 , bNativeCOMObject( false )
2301 // beat out again the default properties of Sbx
2302 Remove( u
"Name"_ustr
, SbxClassType::DontCare
);
2303 Remove( u
"Parent"_ustr
, SbxClassType::DontCare
);
2305 // check the type of the objects
2306 TypeClass eType
= aUnoObj_
.getValueTypeClass();
2307 Reference
< XInterface
> x
;
2308 if( eType
== TypeClass_INTERFACE
)
2310 // get the interface from the Any
2316 // Did the object have an invocation itself?
2317 mxInvocation
.set( x
, UNO_QUERY
);
2319 if( mxInvocation
.is() )
2322 // get the ExactName
2323 mxExactNameInvocation
.set( mxInvocation
, UNO_QUERY
);
2325 // The remainder refers only to the introspection
2326 Reference
< XTypeProvider
> xTypeProvider( x
, UNO_QUERY
);
2327 if( !xTypeProvider
.is() )
2329 bNeedIntrospection
= false;
2333 // Ignore introspection based members for COM objects to avoid
2334 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2335 Reference
< oleautomation::XAutomationObject
> xAutomationObject( aUnoObj_
, UNO_QUERY
);
2336 if( xAutomationObject
.is() )
2337 bNativeCOMObject
= true;
2340 maTmpUnoObj
= aUnoObj_
;
2343 //*** Define the name ***
2344 bool bFatalError
= true;
2346 // Is it an interface or a struct?
2347 bool bSetClassName
= false;
2348 OUString aClassName_
;
2349 if( eType
== TypeClass_STRUCT
|| eType
== TypeClass_EXCEPTION
)
2352 bFatalError
= false;
2354 // insert the real name of the class
2355 if( aName_
.isEmpty() )
2357 aClassName_
= aUnoObj_
.getValueTypeName();
2358 bSetClassName
= true;
2360 StructRefInfo
aThisStruct( maTmpUnoObj
, maTmpUnoObj
.getValueType(), 0 );
2361 maStructInfo
= std::make_shared
<SbUnoStructRefObject
>( GetName(), aThisStruct
);
2363 else if( eType
== TypeClass_INTERFACE
)
2365 // Interface works always through the type in the Any
2366 bFatalError
= false;
2369 SetClassName( aClassName_
);
2371 // Neither interface nor Struct -> FatalError
2374 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION
);
2378 // pass the introspection primal on demand
2381 SbUnoObject::~SbUnoObject()
2386 // pass the introspection on Demand
2387 void SbUnoObject::doIntrospection()
2389 if( !bNeedIntrospection
)
2392 const Reference
<XComponentContext
>& xContext
= comphelper::getProcessComponentContext();
2398 // get the introspection service
2399 Reference
<XIntrospection
> xIntrospection
;
2403 xIntrospection
= theIntrospection::get(xContext
);
2405 catch ( const css::uno::DeploymentException
& )
2409 if (!xIntrospection
.is())
2412 bNeedIntrospection
= false;
2414 // pass the introspection
2417 mxUnoAccess
= xIntrospection
->inspect( maTmpUnoObj
);
2419 catch( const RuntimeException
& e
)
2421 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2424 if( !mxUnoAccess
.is() )
2426 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2430 // get MaterialHolder from access
2431 mxMaterialHolder
.set( mxUnoAccess
, UNO_QUERY
);
2433 // get ExactName from access
2434 mxExactName
.set( mxUnoAccess
, UNO_QUERY
);
2438 // Start of a list of all SbUnoMethod-Instances
2439 static SbUnoMethod
* s_pFirst
= nullptr;
2441 void clearUnoMethodsForBasic( StarBASIC
const * pBasic
)
2443 SbUnoMethod
* pMeth
= s_pFirst
;
2446 SbxObject
* pObject
= pMeth
->GetParent();
2449 StarBASIC
* pModBasic
= dynamic_cast< StarBASIC
* >( pObject
->GetParent() );
2450 if ( pModBasic
== pBasic
)
2452 // for now the solution is to remove the method from the list and to clear it,
2453 // but in case the element should be correctly transferred to another StarBASIC,
2454 // we should either set module parent to NULL without clearing it, or even
2455 // set the new StarBASIC as the parent of the module
2456 // pObject->SetParent( NULL );
2458 if( pMeth
== s_pFirst
)
2459 s_pFirst
= pMeth
->pNext
;
2460 else if( pMeth
->pPrev
)
2461 pMeth
->pPrev
->pNext
= pMeth
->pNext
;
2463 pMeth
->pNext
->pPrev
= pMeth
->pPrev
;
2465 pMeth
->pPrev
= nullptr;
2466 pMeth
->pNext
= nullptr;
2468 pMeth
->SbxValue::Clear();
2469 pObject
->SbxValue::Clear();
2471 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2475 pMeth
= pMeth
->pNext
;
2478 pMeth
= pMeth
->pNext
;
2482 void clearUnoMethods()
2484 SbUnoMethod
* pMeth
= s_pFirst
;
2487 pMeth
->SbxValue::Clear();
2488 pMeth
= pMeth
->pNext
;
2493 SbUnoMethod::SbUnoMethod
2495 const OUString
& aName_
,
2496 SbxDataType eSbxType
,
2497 Reference
< XIdlMethod
> const & xUnoMethod_
,
2500 : SbxMethod( aName_
, eSbxType
)
2501 , mbInvocation( bInvocation
)
2503 m_xUnoMethod
= xUnoMethod_
;
2504 pParamInfoSeq
= nullptr;
2506 // enregister the method in a list
2511 pNext
->pPrev
= this;
2514 SbUnoMethod::~SbUnoMethod()
2516 pParamInfoSeq
.reset();
2518 if( this == s_pFirst
)
2521 pPrev
->pNext
= pNext
;
2523 pNext
->pPrev
= pPrev
;
2526 SbxInfo
* SbUnoMethod::GetInfo()
2528 if( !pInfo
.is() && m_xUnoMethod
.is() )
2530 SbiInstance
* pInst
= GetSbData()->pInst
;
2531 if( pInst
&& pInst
->IsCompatibility() )
2533 pInfo
= new SbxInfo();
2535 const Sequence
<ParamInfo
>& rInfoSeq
= getParamInfos();
2536 const ParamInfo
* pParamInfos
= rInfoSeq
.getConstArray();
2537 sal_uInt32 nParamCount
= rInfoSeq
.getLength();
2539 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
2541 const ParamInfo
& rInfo
= pParamInfos
[i
];
2542 OUString aParamName
= rInfo
.aName
;
2544 pInfo
->AddParam( aParamName
, SbxVARIANT
, SbxFlagBits::Read
);
2551 const Sequence
<ParamInfo
>& SbUnoMethod::getParamInfos()
2555 Sequence
<ParamInfo
> aTmp
;
2556 if (m_xUnoMethod
.is())
2557 aTmp
= m_xUnoMethod
->getParameterInfos();
2558 pParamInfoSeq
.reset( new Sequence
<ParamInfo
>(aTmp
) );
2560 return *pParamInfoSeq
;
2563 SbUnoProperty::SbUnoProperty
2565 const OUString
& aName_
,
2566 SbxDataType eSbxType
,
2567 SbxDataType eRealSbxType
,
2573 : SbxProperty( aName_
, eSbxType
)
2574 , aUnoProp(std::move( aUnoProp_
))
2576 , mbInvocation( bInvocation
)
2577 , mRealType( eRealSbxType
)
2578 , mbUnoStruct( bUnoStruct
)
2580 // as needed establish a dummy array so that SbiRuntime::CheckArray() works
2581 static SbxArrayRef xDummyArray
= new SbxArray( SbxVARIANT
);
2582 if( eSbxType
& SbxARRAY
)
2583 PutObject( xDummyArray
.get() );
2586 SbUnoProperty::~SbUnoProperty()
2589 bool isVeryLargeUnoProperty(SbxVariable
const * pVar
)
2591 auto pUnoVar
= dynamic_cast<const SbUnoProperty
*>(pVar
);
2594 // The ScCellRangeObj methods will attempt to generate massive strings,
2595 // which will use up massive amounts of RAM and also lock of the program
2597 const OUString
& aUnoName
= pUnoVar
->getUnoName();
2598 if (aUnoName
== "DataArray" || aUnoName
== "FormulaArray")
2600 auto pParent
= dynamic_cast<const SbUnoObject
*>(pUnoVar
->GetParent());
2603 css::uno::Any aAny
= const_cast<SbUnoObject
*>(pParent
)->getUnoAny();
2604 css::uno::Reference
<css::sheet::XSheetCellCursor
> xCursor
= aAny
.query
<css::sheet::XSheetCellCursor
>();
2611 SbxVariable
* SbUnoObject::Find( const OUString
& rName
, SbxClassType t
)
2613 static Reference
< XIdlMethod
> xDummyMethod
;
2614 static Property aDummyProp
;
2616 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
2618 if( bNeedIntrospection
)
2621 // New 1999-03-04: Create properties on demand. Therefore search now via
2622 // IntrospectionAccess if a property or a method of the required name exist
2625 OUString
aUName( rName
);
2626 if( mxUnoAccess
.is() && !bNativeCOMObject
)
2628 if( mxExactName
.is() )
2630 OUString aUExactName
= mxExactName
->getExactName( aUName
);
2631 if( !aUExactName
.isEmpty() )
2633 aUName
= aUExactName
;
2636 if( mxUnoAccess
->hasProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
) )
2638 const Property aProp
= mxUnoAccess
->
2639 getProperty( aUName
, PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2641 // If the property could be void the type had to be set to Variant
2642 SbxDataType eSbxType
;
2643 if( aProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2644 eSbxType
= SbxVARIANT
;
2646 eSbxType
= unoToSbxType( aProp
.Type
.getTypeClass() );
2648 SbxDataType eRealSbxType
= ( ( aProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( aProp
.Type
.getTypeClass() ) : eSbxType
);
2649 // create the property and superimpose it
2650 auto pProp
= tools::make_ref
<SbUnoProperty
>( aProp
.Name
, eSbxType
, eRealSbxType
, aProp
, 0, false, ( aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2651 QuickInsert( pProp
.get() );
2654 else if( mxUnoAccess
->hasMethod( aUName
,
2655 MethodConcept::ALL
- MethodConcept::DANGEROUS
) )
2657 // address the method
2658 const Reference
< XIdlMethod
> xMethod
= mxUnoAccess
->
2659 getMethod( aUName
, MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2661 // create SbUnoMethod and superimpose it
2662 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( xMethod
->getName(),
2663 unoToSbxType( xMethod
->getReturnType() ), xMethod
, false );
2664 QuickInsert( xMethRef
.get() );
2665 pRes
= xMethRef
.get();
2668 // If nothing was found check via XNameAccess
2673 Reference
< XNameAccess
> xNameAccess( mxUnoAccess
->queryAdapter( cppu::UnoType
<XPropertySet
>::get()), UNO_QUERY
);
2675 if( xNameAccess
.is() && xNameAccess
->hasByName( rName
) )
2677 Any aAny
= xNameAccess
->getByName( rName
);
2679 // ATTENTION: Because of XNameAccess, the variable generated here
2680 // may not be included as a fixed property in the object and therefore
2681 // won't be stored anywhere.
2682 // If this leads to problems, it has to be created
2683 // synthetically or a class SbUnoNameAccessProperty,
2684 // which checks the existence on access and which
2685 // is disposed if the name is not found anymore.
2686 pRes
= new SbxVariable( SbxVARIANT
);
2687 unoToSbxValue( pRes
, aAny
);
2690 catch( const NoSuchElementException
& e
)
2692 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2694 catch( const Exception
& )
2696 // Establish so that the exception error will not be overwritten
2698 pRes
= new SbxVariable( SbxVARIANT
);
2700 implHandleAnyException( ::cppu::getCaughtException() );
2704 if( !pRes
&& mxInvocation
.is() )
2706 if( mxExactNameInvocation
.is() )
2708 OUString aUExactName
= mxExactNameInvocation
->getExactName( aUName
);
2709 if( !aUExactName
.isEmpty() )
2711 aUName
= aUExactName
;
2717 if( mxInvocation
->hasProperty( aUName
) )
2719 // create a property and superimpose it
2720 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( aUName
, SbxVARIANT
, SbxVARIANT
, aDummyProp
, 0, true, false );
2721 QuickInsert( xVarRef
.get() );
2722 pRes
= xVarRef
.get();
2724 else if( mxInvocation
->hasMethod( aUName
) )
2726 // create SbUnoMethode and superimpose it
2727 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2728 QuickInsert( xMethRef
.get() );
2729 pRes
= xMethRef
.get();
2733 Reference
< XDirectInvocation
> xDirectInvoke( mxInvocation
, UNO_QUERY
);
2734 if ( xDirectInvoke
.is() && xDirectInvoke
->hasMember( aUName
) )
2736 auto xMethRef
= tools::make_ref
<SbUnoMethod
>( aUName
, SbxVARIANT
, xDummyMethod
, true );
2737 QuickInsert( xMethRef
.get() );
2738 pRes
= xMethRef
.get();
2743 catch( const RuntimeException
& e
)
2745 // Establish so that the exception error will not be overwritten
2747 pRes
= new SbxVariable( SbxVARIANT
);
2749 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
, implGetExceptionMsg( e
) );
2754 // At the very end checking if the Dbg_-Properties are meant
2758 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
2759 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
2760 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
2763 implCreateDbgProperties();
2765 // Now they have to be found regular
2766 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
2773 // help method to create the dbg_-Properties
2774 void SbUnoObject::implCreateDbgProperties()
2778 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2779 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( ID_DBG_SUPPORTEDINTERFACES
, SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
2780 QuickInsert( xVarRef
.get() );
2782 // Id == -2: output the properties
2783 xVarRef
= tools::make_ref
<SbUnoProperty
>( ID_DBG_PROPERTIES
, SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
2784 QuickInsert( xVarRef
.get() );
2786 // Id == -3: output the Methods
2787 xVarRef
= tools::make_ref
<SbUnoProperty
>( ID_DBG_METHODS
, SbxSTRING
, SbxSTRING
, aProp
, -3, false, false );
2788 QuickInsert( xVarRef
.get() );
2791 void SbUnoObject::implCreateAll()
2793 // throw away all existing methods and properties
2794 pMethods
= tools::make_ref
<SbxArray
>();
2795 pProps
= tools::make_ref
<SbxArray
>();
2797 if( bNeedIntrospection
) doIntrospection();
2799 // get introspection
2800 Reference
< XIntrospectionAccess
> xAccess
= mxUnoAccess
;
2801 if( !xAccess
.is() || bNativeCOMObject
)
2803 if( mxInvocation
.is() )
2804 xAccess
= mxInvocation
->getIntrospection();
2805 else if( bNativeCOMObject
)
2811 // Establish properties
2812 Sequence
<Property
> props
= xAccess
->getProperties( PropertyConcept::ALL
- PropertyConcept::DANGEROUS
);
2813 sal_uInt32 nPropCount
= props
.getLength();
2814 const Property
* pProps_
= props
.getConstArray();
2817 for( i
= 0 ; i
< nPropCount
; i
++ )
2819 const Property
& rProp
= pProps_
[ i
];
2821 // If the property could be void the type had to be set to Variant
2822 SbxDataType eSbxType
;
2823 if( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
)
2824 eSbxType
= SbxVARIANT
;
2826 eSbxType
= unoToSbxType( rProp
.Type
.getTypeClass() );
2828 SbxDataType eRealSbxType
= ( ( rProp
.Attributes
& PropertyAttribute::MAYBEVOID
) ? unoToSbxType( rProp
.Type
.getTypeClass() ) : eSbxType
);
2829 // Create property and superimpose it
2830 auto xVarRef
= tools::make_ref
<SbUnoProperty
>( rProp
.Name
, eSbxType
, eRealSbxType
, rProp
, i
, false, ( rProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
) );
2831 QuickInsert( xVarRef
.get() );
2834 // Create Dbg_-Properties
2835 implCreateDbgProperties();
2838 Sequence
< Reference
< XIdlMethod
> > aMethodSeq
= xAccess
->getMethods
2839 ( MethodConcept::ALL
- MethodConcept::DANGEROUS
);
2840 sal_uInt32 nMethCount
= aMethodSeq
.getLength();
2841 const Reference
< XIdlMethod
>* pMethods_
= aMethodSeq
.getConstArray();
2842 for( i
= 0 ; i
< nMethCount
; i
++ )
2845 const Reference
< XIdlMethod
>& rxMethod
= pMethods_
[i
];
2847 // Create SbUnoMethod and superimpose it
2848 auto xMethRef
= tools::make_ref
<SbUnoMethod
>
2849 ( rxMethod
->getName(), unoToSbxType( rxMethod
->getReturnType() ), rxMethod
, false );
2850 QuickInsert( xMethRef
.get() );
2856 Any
SbUnoObject::getUnoAny()
2859 if( bNeedIntrospection
) doIntrospection();
2861 aRetAny
= maTmpUnoObj
;
2862 else if( mxMaterialHolder
.is() )
2863 aRetAny
= mxMaterialHolder
->getMaterial();
2864 else if( mxInvocation
.is() )
2865 aRetAny
<<= mxInvocation
;
2869 // help method to create a Uno-Struct per CoreReflection
2870 static SbUnoObjectRef
Impl_CreateUnoStruct( const OUString
& aClassName
)
2872 // get CoreReflection
2873 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
2874 if( !xCoreReflection
.is() )
2877 // search for the class
2878 Reference
< XIdlClass
> xClass
;
2879 const Reference
< XHierarchicalNameAccess
>& xHarryName
=
2880 getCoreReflection_HierarchicalNameAccess_Impl();
2881 if( xHarryName
.is() && xHarryName
->hasByHierarchicalName( aClassName
) )
2882 xClass
= xCoreReflection
->forName( aClassName
);
2886 // Is it really a struct?
2887 TypeClass eType
= xClass
->getTypeClass();
2888 if ( ( eType
!= TypeClass_STRUCT
) && ( eType
!= TypeClass_EXCEPTION
) )
2891 // create an instance
2893 xClass
->createObject( aNewAny
);
2894 // make a SbUnoObject out of it
2895 SbUnoObjectRef pUnoObj
= new SbUnoObject( aClassName
, aNewAny
);
2900 // Factory-Class to create Uno-Structs per DIM AS NEW
2901 SbxBaseRef
SbUnoFactory::Create( sal_uInt16
, sal_uInt32
)
2903 // Via SbxId nothing works in Uno
2907 SbxObjectRef
SbUnoFactory::CreateObject( const OUString
& rClassName
)
2909 return Impl_CreateUnoStruct( rClassName
).get();
2913 // Provisional interface for the UNO-Connection
2914 // Deliver a SbxObject, that wrap a Uno-Interface
2915 SbxObjectRef
GetSbUnoObject( const OUString
& aName
, const Any
& aUnoObj_
)
2917 return new SbUnoObject( aName
, aUnoObj_
);
2920 // Force creation of all properties for debugging
2921 void createAllObjectProperties( SbxObject
* pObj
)
2926 SbUnoObject
* pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
);
2927 SbUnoStructRefObject
* pUnoStructObj
= dynamic_cast<SbUnoStructRefObject
*>( pObj
);
2930 pUnoObj
->createAllProperties();
2932 else if ( pUnoStructObj
)
2934 pUnoStructObj
->createAllProperties();
2939 void RTL_Impl_CreateUnoStruct( SbxArray
& rPar
)
2941 // We need 1 parameter minimum
2942 if (rPar
.Count() < 2)
2944 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2948 // get the name of the class of the struct
2949 OUString aClassName
= rPar
.Get(1)->GetOUString();
2951 // try to create Struct with the same name
2952 SbUnoObjectRef xUnoObj
= Impl_CreateUnoStruct( aClassName
);
2957 // return the object
2958 SbxVariableRef refVar
= rPar
.Get(0);
2959 refVar
->PutObject( xUnoObj
.get() );
2962 void RTL_Impl_CreateUnoService( SbxArray
& rPar
)
2964 // We need 1 Parameter minimum
2965 if (rPar
.Count() < 2)
2967 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
2971 // get the name of the class of the struct
2972 OUString aServiceName
= rPar
.Get(1)->GetOUString();
2974 // search for the service and instantiate it
2975 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
2976 Reference
< XInterface
> xInterface
;
2979 xInterface
= xFactory
->createInstance( aServiceName
);
2981 catch( const Exception
& )
2983 implHandleAnyException( ::cppu::getCaughtException() );
2986 SbxVariableRef refVar
= rPar
.Get(0);
2987 if( xInterface
.is() )
2989 // Create a SbUnoObject out of it and return it
2990 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
2991 if( xUnoObj
->getUnoAny().hasValue() )
2993 // return the object
2994 refVar
->PutObject( xUnoObj
.get() );
2998 refVar
->PutObject( nullptr );
3003 refVar
->PutObject( nullptr );
3007 void RTL_Impl_CreateUnoServiceWithArguments( SbxArray
& rPar
)
3009 // We need 2 parameter minimum
3010 if (rPar
.Count() < 3)
3012 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3016 // get the name of the class of the struct
3017 OUString aServiceName
= rPar
.Get(1)->GetOUString();
3018 Any aArgAsAny
= sbxToUnoValue(rPar
.Get(2),
3019 cppu::UnoType
<Sequence
<Any
>>::get() );
3020 Sequence
< Any
> aArgs
;
3021 aArgAsAny
>>= aArgs
;
3023 // search for the service and instantiate it
3024 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
3025 Reference
< XInterface
> xInterface
;
3028 xInterface
= xFactory
->createInstanceWithArguments( aServiceName
, aArgs
);
3030 catch( const Exception
& )
3032 implHandleAnyException( ::cppu::getCaughtException() );
3035 SbxVariableRef refVar
= rPar
.Get(0);
3036 if( xInterface
.is() )
3038 // Create a SbUnoObject out of it and return it
3039 SbUnoObjectRef xUnoObj
= new SbUnoObject( aServiceName
, Any(xInterface
) );
3040 if( xUnoObj
->getUnoAny().hasValue() )
3042 // return the object
3043 refVar
->PutObject( xUnoObj
.get() );
3047 refVar
->PutObject( nullptr );
3052 refVar
->PutObject( nullptr );
3056 void RTL_Impl_GetProcessServiceManager( SbxArray
& rPar
)
3058 SbxVariableRef refVar
= rPar
.Get(0);
3060 // get the global service manager
3061 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
3063 // Create a SbUnoObject out of it and return it
3064 SbUnoObjectRef xUnoObj
= new SbUnoObject( u
"ProcessServiceManager"_ustr
, Any(xFactory
) );
3065 refVar
->PutObject( xUnoObj
.get() );
3068 void RTL_Impl_HasInterfaces( SbxArray
& rPar
)
3070 // We need 2 parameter minimum
3071 sal_uInt32 nParCount
= rPar
.Count();
3074 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3078 // variable for the return value
3079 SbxVariableRef refVar
= rPar
.Get(0);
3080 refVar
->PutBool( false );
3082 // get the Uno-Object
3083 SbxBaseRef pObj
= rPar
.Get(1)->GetObject();
3084 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3085 if( obj
== nullptr )
3089 Any aAny
= obj
->getUnoAny();
3090 auto x
= o3tl::tryAccess
<Reference
<XInterface
>>(aAny
);
3096 // get CoreReflection
3097 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3098 if( !xCoreReflection
.is() )
3102 for( sal_uInt32 i
= 2 ; i
< nParCount
; i
++ )
3104 // get the name of the interface of the struct
3105 OUString aIfaceName
= rPar
.Get(i
)->GetOUString();
3107 // search for the class
3108 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aIfaceName
);
3113 // check if the interface will be supported
3114 OUString aClassName
= xClass
->getName();
3115 Type
aClassType( xClass
->getTypeClass(), aClassName
);
3116 if( !(*x
)->queryInterface( aClassType
).hasValue() )
3122 // Everything works; then return TRUE
3123 refVar
->PutBool( true );
3126 void RTL_Impl_IsUnoStruct( SbxArray
& rPar
)
3128 // We need 1 parameter minimum
3129 if (rPar
.Count() < 2)
3131 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3135 // variable for the return value
3136 SbxVariableRef refVar
= rPar
.Get(0);
3137 refVar
->PutBool( false );
3139 // get the Uno-Object
3140 SbxVariableRef xParam
= rPar
.Get(1);
3141 if( !xParam
->IsObject() )
3145 SbxBaseRef pObj
= xParam
->GetObject();
3146 auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() );
3147 if( obj
== nullptr )
3151 Any aAny
= obj
->getUnoAny();
3152 TypeClass eType
= aAny
.getValueTypeClass();
3153 if( eType
== TypeClass_STRUCT
)
3155 refVar
->PutBool( true );
3160 void RTL_Impl_EqualUnoObjects( SbxArray
& rPar
)
3162 if (rPar
.Count() < 3)
3164 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3168 // variable for the return value
3169 SbxVariableRef refVar
= rPar
.Get(0);
3170 refVar
->PutBool( false );
3172 // get the Uno-Objects
3173 SbxVariableRef xParam1
= rPar
.Get(1);
3174 if( !xParam1
->IsObject() )
3178 SbxBaseRef pObj1
= xParam1
->GetObject();
3179 auto obj1
= dynamic_cast<SbUnoObject
*>( pObj1
.get() );
3180 if( obj1
== nullptr )
3184 Any aAny1
= obj1
->getUnoAny();
3185 TypeClass eType1
= aAny1
.getValueTypeClass();
3186 if( eType1
!= TypeClass_INTERFACE
)
3190 Reference
< XInterface
> x1
;
3193 SbxVariableRef xParam2
= rPar
.Get(2);
3194 if( !xParam2
->IsObject() )
3198 SbxBaseRef pObj2
= xParam2
->GetObject();
3199 auto obj2
= dynamic_cast<SbUnoObject
*>( pObj2
.get() );
3200 if( obj2
== nullptr )
3204 Any aAny2
= obj2
->getUnoAny();
3205 TypeClass eType2
= aAny2
.getValueTypeClass();
3206 if( eType2
!= TypeClass_INTERFACE
)
3210 Reference
< XInterface
> x2
;
3215 refVar
->PutBool( true );
3220 // helper wrapper function to interact with TypeProvider and
3221 // XTypeDescriptionEnumerationAccess.
3222 // if it fails for whatever reason
3223 // returned Reference<> be null e.g. .is() will be false
3225 static Reference
< XTypeDescriptionEnumeration
> getTypeDescriptorEnumeration( const OUString
& sSearchRoot
,
3226 const Sequence
< TypeClass
>& types
,
3227 TypeDescriptionSearchDepth depth
)
3229 Reference
< XTypeDescriptionEnumeration
> xEnum
;
3230 Reference
< XTypeDescriptionEnumerationAccess
> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY
);
3231 if ( xTypeEnumAccess
.is() )
3235 xEnum
= xTypeEnumAccess
->createTypeDescriptionEnumeration(
3236 sSearchRoot
, types
, depth
);
3238 catch(const NoSuchTypeNameException
& /*nstne*/ ) {}
3239 catch(const InvalidTypeNameException
& /*nstne*/ ) {}
3245 VBAConstantHelper::instance()
3247 static VBAConstantHelper aHelper
;
3251 void VBAConstantHelper::init()
3256 Reference
< XTypeDescriptionEnumeration
> xEnum
= getTypeDescriptorEnumeration( u
"ooo.vba"_ustr
, {TypeClass_CONSTANTS
}, TypeDescriptionSearchDepth_INFINITE
);
3262 while ( xEnum
->hasMoreElements() )
3264 Reference
< XConstantsTypeDescription
> xConstants( xEnum
->nextElement(), UNO_QUERY
);
3265 if ( xConstants
.is() )
3267 // store constant group name
3268 OUString sFullName
= xConstants
->getName();
3269 sal_Int32 indexLastDot
= sFullName
.lastIndexOf('.');
3270 OUString
sLeafName( sFullName
);
3271 if ( indexLastDot
> -1 )
3273 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3275 aConstCache
.push_back( sLeafName
); // assume constant group names are unique
3276 const Sequence
< Reference
< XConstantTypeDescription
> > aConsts
= xConstants
->getConstants();
3277 for (const auto& ctd
: aConsts
)
3279 // store constant member name
3280 sFullName
= ctd
->getName();
3281 indexLastDot
= sFullName
.lastIndexOf('.');
3282 sLeafName
= sFullName
;
3283 if ( indexLastDot
> -1 )
3285 sLeafName
= sFullName
.copy( indexLastDot
+ 1);
3287 aConstHash
[ sLeafName
.toAsciiLowerCase() ] = ctd
->getConstantValue();
3295 VBAConstantHelper::isVBAConstantType( std::u16string_view rName
)
3298 bool bConstant
= false;
3300 for (auto const& elem
: aConstCache
)
3302 if( o3tl::equalsIgnoreAsciiCase(rName
, elem
) )
3312 VBAConstantHelper::getVBAConstant( const OUString
& rName
)
3314 SbxVariable
* pConst
= nullptr;
3317 auto it
= aConstHash
.find( rName
.toAsciiLowerCase() );
3319 if ( it
!= aConstHash
.end() )
3321 pConst
= new SbxVariable( SbxVARIANT
);
3322 pConst
->SetName( rName
);
3323 unoToSbxValue( pConst
, it
->second
);
3329 // Function to search for a global identifier in the
3330 // UnoScope and to wrap it for Sbx
3331 SbUnoClass
* findUnoClass( const OUString
& rName
)
3333 // #105550 Check if module exists
3334 SbUnoClass
* pUnoClass
= nullptr;
3336 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3337 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3339 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3340 Reference
< XTypeDescription
> xTypeDesc
;
3343 if( xTypeDesc
.is() )
3345 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3346 if( eTypeClass
== TypeClass_MODULE
|| eTypeClass
== TypeClass_CONSTANTS
)
3348 pUnoClass
= new SbUnoClass( rName
);
3355 SbxVariable
* SbUnoClass::Find( const OUString
& rName
, SbxClassType
)
3357 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Variable
);
3359 // If nothing were located the submodule isn't known yet
3362 // If it is already a class, ask for the field
3366 Reference
< XIdlField
> xField
= m_xClass
->getField( rName
);
3371 Any aAny
= xField
->get( {} ); //TODO: does this make sense?
3374 pRes
= new SbxVariable( SbxVARIANT
);
3375 pRes
->SetName( rName
);
3376 unoToSbxValue( pRes
, aAny
);
3378 catch( const Exception
& )
3380 implHandleAnyException( ::cppu::getCaughtException() );
3386 // expand fully qualified name
3387 OUString aNewName
= GetName()
3391 // get CoreReflection
3392 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
3393 if( xCoreReflection
.is() )
3395 // Is it a constant?
3396 Reference
< XHierarchicalNameAccess
> xHarryName( xCoreReflection
, UNO_QUERY
);
3397 if( xHarryName
.is() )
3401 Any aValue
= xHarryName
->getByHierarchicalName( aNewName
);
3402 TypeClass eType
= aValue
.getValueTypeClass();
3404 // Interface located? Then it is a class
3405 if( eType
== TypeClass_INTERFACE
)
3407 Reference
< XIdlClass
> xClass( aValue
, UNO_QUERY
);
3410 pRes
= new SbxVariable( SbxVARIANT
);
3411 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(new SbUnoClass( aNewName
, xClass
));
3412 pRes
->PutObject( xWrapper
.get() );
3417 pRes
= new SbxVariable( SbxVARIANT
);
3418 unoToSbxValue( pRes
, aValue
);
3421 catch( const NoSuchElementException
& )
3426 // Otherwise take it again as class
3429 SbUnoClass
* pNewClass
= findUnoClass( aNewName
);
3432 pRes
= new SbxVariable( SbxVARIANT
);
3433 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pNewClass
);
3434 pRes
->PutObject( xWrapper
.get() );
3441 SbUnoService
* pUnoService
= findUnoService( aNewName
);
3444 pRes
= new SbxVariable( SbxVARIANT
);
3445 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoService
);
3446 pRes
->PutObject( xWrapper
.get() );
3453 SbUnoSingleton
* pUnoSingleton
= findUnoSingleton( aNewName
);
3456 pRes
= new SbxVariable( SbxVARIANT
);
3457 SbxObjectRef xWrapper
= static_cast<SbxObject
*>(pUnoSingleton
);
3458 pRes
->PutObject( xWrapper
.get() );
3466 pRes
->SetName( rName
);
3468 // Insert variable, so that it could be found later
3469 QuickInsert( pRes
);
3471 // Take us out as listener at once,
3472 // the values are all constant
3473 if( pRes
->IsBroadcaster() )
3474 EndListening( pRes
->GetBroadcaster(), true );
3481 SbUnoService
* findUnoService( const OUString
& rName
)
3483 SbUnoService
* pSbUnoService
= nullptr;
3485 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3486 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3488 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3489 Reference
< XTypeDescription
> xTypeDesc
;
3492 if( xTypeDesc
.is() )
3494 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3495 if( eTypeClass
== TypeClass_SERVICE
)
3497 Reference
< XServiceTypeDescription2
> xServiceTypeDesc( xTypeDesc
, UNO_QUERY
);
3498 if( xServiceTypeDesc
.is() )
3499 pSbUnoService
= new SbUnoService( rName
, xServiceTypeDesc
);
3503 return pSbUnoService
;
3506 SbxVariable
* SbUnoService::Find( const OUString
& rName
, SbxClassType
)
3508 SbxVariable
* pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3512 // If it is already a class ask for a field
3513 if( m_bNeedsInit
&& m_xServiceTypeDesc
.is() )
3515 m_bNeedsInit
= false;
3517 Sequence
< Reference
< XServiceConstructorDescription
> > aSCDSeq
= m_xServiceTypeDesc
->getConstructors();
3518 const Reference
< XServiceConstructorDescription
>* pCtorSeq
= aSCDSeq
.getConstArray();
3519 int nCtorCount
= aSCDSeq
.getLength();
3520 for( int i
= 0 ; i
< nCtorCount
; ++i
)
3522 Reference
< XServiceConstructorDescription
> xCtor
= pCtorSeq
[i
];
3524 OUString
aName( xCtor
->getName() );
3525 if( aName
.isEmpty() )
3527 if( xCtor
->isDefaultConstructor() )
3533 if( !aName
.isEmpty() )
3535 // Create and insert SbUnoServiceCtor
3536 SbxVariableRef xSbCtorRef
= new SbUnoServiceCtor( aName
, xCtor
);
3537 QuickInsert( xSbCtorRef
.get() );
3540 pRes
= SbxObject::Find( rName
, SbxClassType::Method
);
3547 void SbUnoService::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3549 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3553 SbxVariable
* pVar
= pHint
->GetVar();
3554 SbxArray
* pParams
= pVar
->GetParameters();
3555 SbUnoServiceCtor
* pUnoCtor
= dynamic_cast<SbUnoServiceCtor
*>( pVar
);
3556 if( pUnoCtor
&& pHint
->GetId() == SfxHintId::BasicDataWanted
)
3558 // Parameter count -1 because of Param0 == this
3559 sal_uInt32 nParamCount
= pParams
? (pParams
->Count() - 1) : 0;
3562 Reference
< XServiceConstructorDescription
> xCtor
= pUnoCtor
->getServiceCtorDesc();
3563 Sequence
< Reference
< XParameter
> > aParameterSeq
= xCtor
->getParameters();
3564 const Reference
< XParameter
>* pParameterSeq
= aParameterSeq
.getConstArray();
3565 sal_uInt32 nUnoParamCount
= aParameterSeq
.getLength();
3567 // Default: Ignore not needed parameters
3568 bool bParameterError
= false;
3570 // Is the last parameter a rest parameter?
3571 bool bRestParameterMode
= false;
3572 if( nUnoParamCount
> 0 )
3574 Reference
< XParameter
> xLastParam
= pParameterSeq
[ nUnoParamCount
- 1 ];
3575 if( xLastParam
.is() )
3577 if( xLastParam
->isRestParameter() )
3578 bRestParameterMode
= true;
3582 // Too many parameters with context as first parameter?
3583 sal_uInt32 nSbxParameterOffset
= 1;
3584 sal_uInt32 nParameterOffsetByContext
= 0;
3585 Reference
< XComponentContext
> xFirstParamContext
;
3586 if( nParamCount
> nUnoParamCount
)
3588 // Check if first parameter is a context and use it
3589 // then in createInstanceWithArgumentsAndContext
3590 Any aArg0
= sbxToUnoValue(pParams
->Get(nSbxParameterOffset
));
3591 if( (aArg0
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3592 nParameterOffsetByContext
= 1;
3595 sal_uInt32 nEffectiveParamCount
= nParamCount
- nParameterOffsetByContext
;
3596 sal_uInt32 nAllocParamCount
= nEffectiveParamCount
;
3597 if( nEffectiveParamCount
> nUnoParamCount
)
3599 if( !bRestParameterMode
)
3601 nEffectiveParamCount
= nUnoParamCount
;
3602 nAllocParamCount
= nUnoParamCount
;
3605 // Not enough parameters?
3606 else if( nUnoParamCount
> nEffectiveParamCount
)
3608 // RestParameterMode only helps if one (the last) parameter is missing
3609 int nDiff
= nUnoParamCount
- nEffectiveParamCount
;
3610 if( !bRestParameterMode
|| nDiff
> 1 )
3612 bParameterError
= true;
3613 StarBASIC::Error( ERRCODE_BASIC_NOT_OPTIONAL
);
3617 if( !bParameterError
)
3619 bool bOutParams
= false;
3620 if( nAllocParamCount
> 0 )
3622 args
.realloc( nAllocParamCount
);
3623 Any
* pAnyArgs
= args
.getArray();
3624 for( sal_uInt32 i
= 0 ; i
< nEffectiveParamCount
; i
++ )
3626 sal_uInt32 iSbx
= i
+ nSbxParameterOffset
+ nParameterOffsetByContext
;
3628 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3629 Reference
< XParameter
> xParam
;
3630 if( i
< nUnoParamCount
)
3632 xParam
= pParameterSeq
[i
];
3636 Reference
< XTypeDescription
> xParamTypeDesc
= xParam
->getType();
3637 if( !xParamTypeDesc
.is() )
3639 css::uno::Type
aType( xParamTypeDesc
->getTypeClass(), xParamTypeDesc
->getName() );
3641 // sbx parameter needs offset 1
3642 pAnyArgs
[i
] = sbxToUnoValue(pParams
->Get(iSbx
), aType
);
3644 // Check for out parameter if not already done
3645 if( !bOutParams
&& xParam
->isOut() )
3650 pAnyArgs
[i
] = sbxToUnoValue(pParams
->Get(iSbx
));
3655 // "Call" ctor using createInstanceWithArgumentsAndContext
3656 Reference
< XComponentContext
> xContext(
3657 xFirstParamContext
.is()
3658 ? xFirstParamContext
3659 : comphelper::getProcessComponentContext() );
3660 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
3663 OUString aServiceName
= GetName();
3664 Reference
< XInterface
> xRet
;
3667 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext( aServiceName
, args
, xContext
);
3669 catch( const Exception
& )
3671 implHandleAnyException( ::cppu::getCaughtException() );
3674 unoToSbxValue( pVar
, aRetAny
);
3676 // Copy back out parameters?
3679 const Any
* pAnyArgs
= args
.getConstArray();
3681 for( sal_uInt32 j
= 0 ; j
< nUnoParamCount
; j
++ )
3683 Reference
< XParameter
> xParam
= pParameterSeq
[j
];
3687 if( xParam
->isOut() )
3688 unoToSbxValue(pParams
->Get(j
+ 1), pAnyArgs
[j
]);
3694 SbxObject::Notify( rBC
, rHint
);
3698 SbUnoServiceCtor::SbUnoServiceCtor( const OUString
& aName_
, Reference
< XServiceConstructorDescription
> const & xServiceCtorDesc
)
3699 : SbxMethod( aName_
, SbxOBJECT
)
3700 , m_xServiceCtorDesc( xServiceCtorDesc
)
3704 SbUnoServiceCtor::~SbUnoServiceCtor()
3708 SbxInfo
* SbUnoServiceCtor::GetInfo()
3714 SbUnoSingleton
* findUnoSingleton( const OUString
& rName
)
3716 SbUnoSingleton
* pSbUnoSingleton
= nullptr;
3718 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
3719 if( xTypeAccess
->hasByHierarchicalName( rName
) )
3721 Any aRet
= xTypeAccess
->getByHierarchicalName( rName
);
3722 Reference
< XTypeDescription
> xTypeDesc
;
3725 if( xTypeDesc
.is() )
3727 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
3728 if( eTypeClass
== TypeClass_SINGLETON
)
3730 Reference
< XSingletonTypeDescription
> xSingletonTypeDesc( xTypeDesc
, UNO_QUERY
);
3731 if( xSingletonTypeDesc
.is() )
3732 pSbUnoSingleton
= new SbUnoSingleton( rName
);
3736 return pSbUnoSingleton
;
3739 SbUnoSingleton::SbUnoSingleton( const OUString
& aName_
)
3740 : SbxObject( aName_
)
3742 SbxVariableRef xGetMethodRef
= new SbxMethod( u
"get"_ustr
, SbxOBJECT
);
3743 QuickInsert( xGetMethodRef
.get() );
3746 void SbUnoSingleton::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
3748 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
3751 SbxVariable
* pVar
= pHint
->GetVar();
3752 SbxArray
* pParams
= pVar
->GetParameters();
3753 sal_uInt32 nParamCount
= pParams
? (pParams
->Count() - 1) : 0;
3754 sal_uInt32 nAllowedParamCount
= 1;
3756 Reference
< XComponentContext
> xContextToUse
;
3757 if( nParamCount
> 0 )
3759 // Check if first parameter is a context and use it then
3760 Reference
< XComponentContext
> xFirstParamContext
;
3761 Any aArg1
= sbxToUnoValue(pParams
->Get(1));
3762 if( (aArg1
>>= xFirstParamContext
) && xFirstParamContext
.is() )
3763 xContextToUse
= std::move(xFirstParamContext
);
3766 if( !xContextToUse
.is() )
3768 xContextToUse
= comphelper::getProcessComponentContext();
3769 --nAllowedParamCount
;
3772 if( nParamCount
> nAllowedParamCount
)
3774 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
3779 if( xContextToUse
.is() )
3781 OUString aSingletonName
= "/singletons/"
3783 Reference
< XInterface
> xRet
;
3784 xContextToUse
->getValueByName( aSingletonName
) >>= xRet
;
3787 unoToSbxValue( pVar
, aRetAny
);
3791 SbxObject::Notify( rBC
, rHint
);
3797 // Implementation of an EventAttacher-drawn AllListener, which
3798 // solely transmits several events to a general AllListener
3799 class BasicAllListener_Impl
: public WeakImplHelper
< XAllListener
>
3801 void firing_impl(const AllEventObject
& Event
, Any
* pRet
);
3804 SbxObjectRef xSbxObj
;
3805 OUString aPrefixName
;
3807 explicit BasicAllListener_Impl( OUString aPrefixName
);
3809 // Methods of XAllListener
3810 virtual void SAL_CALL
firing(const AllEventObject
& Event
) override
;
3811 virtual Any SAL_CALL
approveFiring(const AllEventObject
& Event
) override
;
3813 // Methods of XEventListener
3814 virtual void SAL_CALL
disposing(const EventObject
& Source
) override
;
3819 BasicAllListener_Impl::BasicAllListener_Impl(OUString aPrefixName_
)
3820 : aPrefixName(std::move( aPrefixName_
))
3824 void BasicAllListener_Impl::firing_impl( const AllEventObject
& Event
, Any
* pRet
)
3826 SolarMutexGuard guard
;
3831 OUString aMethodName
= aPrefixName
+ Event
.MethodName
;
3833 SbxVariable
* pP
= xSbxObj
.get();
3834 while( pP
->GetParent() )
3836 pP
= pP
->GetParent();
3837 StarBASIC
* pLib
= dynamic_cast<StarBASIC
*>( pP
);
3840 // Create in a Basic Array
3841 SbxArrayRef xSbxArray
= new SbxArray( SbxVARIANT
);
3842 const Any
* pArgs
= Event
.Arguments
.getConstArray();
3843 sal_Int32 nCount
= Event
.Arguments
.getLength();
3844 for( sal_Int32 i
= 0; i
< nCount
; i
++ )
3847 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
3848 unoToSbxValue( xVar
.get(), pArgs
[i
] );
3849 xSbxArray
->Put(xVar
.get(), i
+ 1);
3852 pLib
->Call( aMethodName
, xSbxArray
.get() );
3854 // get the return value from the Param-Array, if requested
3857 SbxVariable
* pVar
= xSbxArray
->Get(0);
3860 // #95792 Avoid a second call
3861 SbxFlagBits nFlags
= pVar
->GetFlags();
3862 pVar
->SetFlag( SbxFlagBits::NoBroadcast
);
3863 *pRet
= sbxToUnoValueImpl( pVar
);
3864 pVar
->SetFlags( nFlags
);
3873 // Methods of Listener
3874 void BasicAllListener_Impl::firing( const AllEventObject
& Event
)
3876 firing_impl( Event
, nullptr );
3879 Any
BasicAllListener_Impl::approveFiring( const AllEventObject
& Event
)
3882 firing_impl( Event
, &aRetAny
);
3887 // Methods of XEventListener
3888 void BasicAllListener_Impl ::disposing(const EventObject
& )
3890 SolarMutexGuard guard
;
3896 // class InvocationToAllListenerMapper
3897 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
3901 class InvocationToAllListenerMapper
: public WeakImplHelper
< XInvocation
>
3904 InvocationToAllListenerMapper( const Reference
< XIdlClass
>& ListenerType
,
3905 const Reference
< XAllListener
>& AllListener
, Any Helper
);
3908 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
3909 virtual Any SAL_CALL
invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
, Sequence
< sal_Int16
>& OutParamIndex
, Sequence
< Any
>& OutParam
) override
;
3910 virtual void SAL_CALL
setValue(const OUString
& PropertyName
, const Any
& Value
) override
;
3911 virtual Any SAL_CALL
getValue(const OUString
& PropertyName
) override
;
3912 virtual sal_Bool SAL_CALL
hasMethod(const OUString
& Name
) override
;
3913 virtual sal_Bool SAL_CALL
hasProperty(const OUString
& Name
) override
;
3916 Reference
< XAllListener
> m_xAllListener
;
3917 Reference
< XIdlClass
> m_xListenerType
;
3923 // Function to replace AllListenerAdapterService::createAllListerAdapter
3924 static Reference
< XInterface
> createAllListenerAdapter
3926 const Reference
< XInvocationAdapterFactory2
>& xInvocationAdapterFactory
,
3927 const Reference
< XIdlClass
>& xListenerType
,
3928 const Reference
< XAllListener
>& xListener
,
3932 Reference
< XInterface
> xAdapter
;
3933 if( xInvocationAdapterFactory
.is() && xListenerType
.is() && xListener
.is() )
3935 Reference
< XInvocation
> xInvocationToAllListenerMapper
=
3936 new InvocationToAllListenerMapper(xListenerType
, xListener
, Helper
);
3937 Type
aListenerType( xListenerType
->getTypeClass(), xListenerType
->getName() );
3938 xAdapter
= xInvocationAdapterFactory
->createAdapter( xInvocationToAllListenerMapper
, {aListenerType
} );
3944 // InvocationToAllListenerMapper
3945 InvocationToAllListenerMapper::InvocationToAllListenerMapper
3946 ( const Reference
< XIdlClass
>& ListenerType
, const Reference
< XAllListener
>& AllListener
, Any Helper
)
3947 : m_xAllListener( AllListener
)
3948 , m_xListenerType( ListenerType
)
3949 , m_Helper(std::move( Helper
))
3954 Reference
< XIntrospectionAccess
> SAL_CALL
InvocationToAllListenerMapper::getIntrospection()
3956 return Reference
< XIntrospectionAccess
>();
3960 Any SAL_CALL
InvocationToAllListenerMapper::invoke(const OUString
& FunctionName
, const Sequence
< Any
>& Params
,
3961 Sequence
< sal_Int16
>&, Sequence
< Any
>&)
3965 // Check if to firing or approveFiring has to be called
3966 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( FunctionName
);
3967 bool bApproveFiring
= false;
3970 Reference
< XIdlClass
> xReturnType
= xMethod
->getReturnType();
3971 Sequence
< Reference
< XIdlClass
> > aExceptionSeq
= xMethod
->getExceptionTypes();
3972 if( ( xReturnType
.is() && xReturnType
->getTypeClass() != TypeClass_VOID
) ||
3973 aExceptionSeq
.hasElements() )
3975 bApproveFiring
= true;
3979 Sequence
< ParamInfo
> aParamSeq
= xMethod
->getParameterInfos();
3980 sal_uInt32 nParamCount
= aParamSeq
.getLength();
3981 if( nParamCount
> 1 )
3983 const ParamInfo
* pInfo
= aParamSeq
.getConstArray();
3984 for( sal_uInt32 i
= 0 ; i
< nParamCount
; i
++ )
3986 if( pInfo
[ i
].aMode
!= ParamMode_IN
)
3988 bApproveFiring
= true;
3995 AllEventObject aAllEvent
;
3996 aAllEvent
.Source
= getXWeak();
3997 aAllEvent
.Helper
= m_Helper
;
3998 aAllEvent
.ListenerType
= Type(m_xListenerType
->getTypeClass(), m_xListenerType
->getName() );
3999 aAllEvent
.MethodName
= FunctionName
;
4000 aAllEvent
.Arguments
= Params
;
4001 if( bApproveFiring
)
4002 aRet
= m_xAllListener
->approveFiring( aAllEvent
);
4004 m_xAllListener
->firing( aAllEvent
);
4009 void SAL_CALL
InvocationToAllListenerMapper::setValue(const OUString
&, const Any
&)
4013 Any SAL_CALL
InvocationToAllListenerMapper::getValue(const OUString
&)
4019 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasMethod(const OUString
& Name
)
4021 Reference
< XIdlMethod
> xMethod
= m_xListenerType
->getMethod( Name
);
4022 return xMethod
.is();
4026 sal_Bool SAL_CALL
InvocationToAllListenerMapper::hasProperty(const OUString
& Name
)
4028 Reference
< XIdlField
> xField
= m_xListenerType
->getField( Name
);
4033 // create Uno-Service
4034 // 1. Parameter == Prefix-Name of the macro
4035 // 2. Parameter == fully qualified name of the listener
4036 void SbRtl_CreateUnoListener(StarBASIC
* pBasic
, SbxArray
& rPar
, bool)
4038 // We need 2 parameters
4039 if (rPar
.Count() != 3)
4041 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4045 // get the name of the class of the struct
4046 OUString aPrefixName
= rPar
.Get(1)->GetOUString();
4047 OUString aListenerClassName
= rPar
.Get(2)->GetOUString();
4049 // get the CoreReflection
4050 Reference
< XIdlReflection
> xCoreReflection
= getCoreReflection_Impl();
4051 if( !xCoreReflection
.is() )
4054 // get the AllListenerAdapterService
4055 const Reference
< XComponentContext
>& xContext( comphelper::getProcessComponentContext() );
4058 Reference
< XIdlClass
> xClass
= xCoreReflection
->forName( aListenerClassName
);
4062 // From 1999-11-30: get the InvocationAdapterFactory
4063 Reference
< XInvocationAdapterFactory2
> xInvocationAdapterFactory
=
4064 InvocationAdapterFactory::create( xContext
);
4066 rtl::Reference
<BasicAllListener_Impl
> xAllLst
= new BasicAllListener_Impl( aPrefixName
);
4068 Reference
< XInterface
> xLst
= createAllListenerAdapter( xInvocationAdapterFactory
, xClass
, xAllLst
, aTmp
);
4072 OUString aClassName
= xClass
->getName();
4073 Type
aClassType( xClass
->getTypeClass(), aClassName
);
4074 aTmp
= xLst
->queryInterface( aClassType
);
4075 if( !aTmp
.hasValue() )
4078 SbUnoObject
* pUnoObj
= new SbUnoObject( aListenerClassName
, aTmp
);
4079 xAllLst
->xSbxObj
= pUnoObj
;
4080 xAllLst
->xSbxObj
->SetParent( pBasic
);
4082 // #100326 Register listener object to set Parent NULL in Dtor
4083 SbxArrayRef xBasicUnoListeners
= pBasic
->getUnoListeners();
4084 xBasicUnoListeners
->Insert(pUnoObj
, xBasicUnoListeners
->Count());
4086 // return the object
4087 SbxVariableRef refVar
= rPar
.Get(0);
4088 refVar
->PutObject( xAllLst
->xSbxObj
.get() );
4092 // Represents the DefaultContext property of the ProcessServiceManager
4093 // in the Basic runtime system.
4094 void RTL_Impl_GetDefaultContext( SbxArray
& rPar
)
4096 SbxVariableRef refVar
= rPar
.Get(0);
4098 Any
aContextAny( comphelper::getProcessComponentContext() );
4100 SbUnoObjectRef xUnoObj
= new SbUnoObject( u
"DefaultContext"_ustr
, aContextAny
);
4101 refVar
->PutObject( xUnoObj
.get() );
4105 // Creates a Basic wrapper object for a strongly typed Uno value
4106 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4107 void RTL_Impl_CreateUnoValue( SbxArray
& rPar
)
4109 // 2 parameters needed
4110 if (rPar
.Count() != 3)
4112 StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT
);
4116 // get the name of the class of the struct
4117 OUString aTypeName
= rPar
.Get(1)->GetOUString();
4118 SbxVariable
* pVal
= rPar
.Get(2);
4120 if( aTypeName
== "type" )
4122 SbxDataType eBaseType
= pVal
->SbxValue::GetType();
4123 OUString aValTypeName
;
4124 if( eBaseType
== SbxSTRING
)
4126 aValTypeName
= pVal
->GetOUString();
4128 else if( eBaseType
== SbxOBJECT
)
4131 Reference
< XIdlClass
> xIdlClass
;
4133 SbxBaseRef pObj
= pVal
->GetObject();
4134 if( auto obj
= dynamic_cast<SbUnoObject
*>( pObj
.get() ) )
4136 Any aUnoAny
= obj
->getUnoAny();
4137 aUnoAny
>>= xIdlClass
;
4140 if( xIdlClass
.is() )
4142 aValTypeName
= xIdlClass
->getName();
4146 bool bSuccess
= implGetTypeByName( aValTypeName
, aType
);
4149 SbxVariableRef refVar
= rPar
.Get(0);
4150 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject(Any(aType
));
4151 refVar
->PutObject( xUnoAnyObject
.get() );
4157 const Reference
< XHierarchicalNameAccess
>& xTypeAccess
= getTypeProvider_Impl();
4161 aRet
= xTypeAccess
->getByHierarchicalName( aTypeName
);
4163 catch( const NoSuchElementException
& e1
)
4165 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION
,
4166 implGetExceptionMsg( e1
, u
"com.sun.star.container.NoSuchElementException" ) );
4169 Reference
< XTypeDescription
> xTypeDesc
;
4171 TypeClass eTypeClass
= xTypeDesc
->getTypeClass();
4172 Type
aDestType( eTypeClass
, aTypeName
);
4176 Any aVal
= sbxToUnoValueImpl( pVal
);
4177 Any aConvertedVal
= convertAny( aVal
, aDestType
);
4179 SbxVariableRef refVar
= rPar
.Get(0);
4180 SbxObjectRef xUnoAnyObject
= new SbUnoAnyObject( aConvertedVal
);
4181 refVar
->PutObject( xUnoAnyObject
.get() );
4186 class ModuleInvocationProxy
: public WeakImplHelper
< XInvocation
, XComponent
>
4188 std::mutex m_aMutex
;
4190 SbxObjectRef m_xScopeObj
;
4191 bool m_bProxyIsClassModuleObject
;
4193 ::comphelper::OInterfaceContainerHelper4
<XEventListener
> m_aListeners
;
4196 ModuleInvocationProxy( std::u16string_view aPrefix
, SbxObjectRef
const & xScopeObj
);
4199 virtual Reference
< XIntrospectionAccess
> SAL_CALL
getIntrospection() override
;
4200 virtual void SAL_CALL
setValue( const OUString
& rProperty
, const Any
& rValue
) override
;
4201 virtual Any SAL_CALL
getValue( const OUString
& rProperty
) override
;
4202 virtual sal_Bool SAL_CALL
hasMethod( const OUString
& rName
) override
;
4203 virtual sal_Bool SAL_CALL
hasProperty( const OUString
& rProp
) override
;
4205 virtual Any SAL_CALL
invoke( const OUString
& rFunction
,
4206 const Sequence
< Any
>& rParams
,
4207 Sequence
< sal_Int16
>& rOutParamIndex
,
4208 Sequence
< Any
>& rOutParam
) override
;
4211 virtual void SAL_CALL
dispose() override
;
4212 virtual void SAL_CALL
addEventListener( const Reference
< XEventListener
>& xListener
) override
;
4213 virtual void SAL_CALL
removeEventListener( const Reference
< XEventListener
>& aListener
) override
;
4218 ModuleInvocationProxy::ModuleInvocationProxy( std::u16string_view aPrefix
, SbxObjectRef
const & xScopeObj
)
4219 : m_aPrefix( OUString::Concat(aPrefix
) + "_" )
4220 , m_xScopeObj( xScopeObj
)
4222 m_bProxyIsClassModuleObject
= xScopeObj
.is() && dynamic_cast<const SbClassModuleObject
*>( xScopeObj
.get() ) != nullptr;
4225 Reference
< XIntrospectionAccess
> SAL_CALL
ModuleInvocationProxy::getIntrospection()
4227 return Reference
< XIntrospectionAccess
>();
4230 void SAL_CALL
ModuleInvocationProxy::setValue(const OUString
& rProperty
, const Any
& rValue
)
4232 if( !m_bProxyIsClassModuleObject
)
4233 throw UnknownPropertyException();
4235 SolarMutexGuard guard
;
4237 OUString aPropertyFunctionName
= "Property Set "
4241 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4242 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4243 if( pMeth
== nullptr )
4245 // TODO: Check vba behavior concerning missing function
4246 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4247 throw UnknownPropertyException(aPropertyFunctionName
);
4251 SbxArrayRef xArray
= new SbxArray
;
4252 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4253 unoToSbxValue( xVar
.get(), rValue
);
4254 xArray
->Put(xVar
.get(), 1);
4256 // Call property method
4257 SbxVariableRef xValue
= new SbxVariable
;
4258 pMeth
->SetParameters( xArray
.get() );
4259 pMeth
->Call( xValue
.get() );
4260 pMeth
->SetParameters( nullptr );
4262 // TODO: OutParameter?
4267 Any SAL_CALL
ModuleInvocationProxy::getValue(const OUString
& rProperty
)
4269 if( !m_bProxyIsClassModuleObject
)
4271 throw UnknownPropertyException();
4273 SolarMutexGuard guard
;
4275 OUString aPropertyFunctionName
= "Property Get "
4279 SbxVariable
* p
= m_xScopeObj
->Find( aPropertyFunctionName
, SbxClassType::Method
);
4280 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4281 if( pMeth
== nullptr )
4283 // TODO: Check vba behavior concerning missing function
4284 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4285 throw UnknownPropertyException(aPropertyFunctionName
);
4289 SbxVariableRef xValue
= new SbxVariable
;
4290 pMeth
->Call( xValue
.get() );
4291 Any aRet
= sbxToUnoValue( xValue
.get() );
4295 sal_Bool SAL_CALL
ModuleInvocationProxy::hasMethod( const OUString
& )
4300 sal_Bool SAL_CALL
ModuleInvocationProxy::hasProperty( const OUString
& )
4305 Any SAL_CALL
ModuleInvocationProxy::invoke( const OUString
& rFunction
,
4306 const Sequence
< Any
>& rParams
,
4307 Sequence
< sal_Int16
>&,
4310 SolarMutexGuard guard
;
4313 SbxObjectRef xScopeObj
= m_xScopeObj
;
4314 if( !xScopeObj
.is() )
4318 OUString aFunctionName
= m_aPrefix
4321 bool bOldReschedule
= false;
4322 SbiInstance
* pInst
= GetSbData()->pInst
;
4323 if( pInst
&& pInst
->IsCompatibility() )
4325 bOldReschedule
= pInst
->IsReschedule();
4326 if ( bOldReschedule
)
4327 pInst
->EnableReschedule( false );
4330 SbxVariable
* p
= xScopeObj
->Find( aFunctionName
, SbxClassType::Method
);
4331 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( p
);
4332 if( pMeth
== nullptr )
4334 // TODO: Check vba behavior concerning missing function
4335 //StarBASIC::Error( ERRCODE_BASIC_NO_METHOD, aFunctionName );
4341 sal_Int32 nParamCount
= rParams
.getLength();
4344 xArray
= new SbxArray
;
4345 const Any
*pArgs
= rParams
.getConstArray();
4346 for( sal_Int32 i
= 0 ; i
< nParamCount
; i
++ )
4348 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
4349 unoToSbxValue( xVar
.get(), pArgs
[i
] );
4350 xArray
->Put(xVar
.get(), sal::static_int_cast
<sal_uInt16
>(i
+ 1));
4355 SbxVariableRef xValue
= new SbxVariable
;
4357 pMeth
->SetParameters( xArray
.get() );
4358 pMeth
->Call( xValue
.get() );
4359 aRet
= sbxToUnoValue( xValue
.get() );
4360 pMeth
->SetParameters( nullptr );
4363 pInst
->EnableReschedule( bOldReschedule
);
4365 // TODO: OutParameter?
4370 void SAL_CALL
ModuleInvocationProxy::dispose()
4372 std::unique_lock
aGuard( m_aMutex
);
4374 EventObject
aEvent( static_cast<XComponent
*>(this) );
4375 m_aListeners
.disposeAndClear( aGuard
, aEvent
);
4377 m_xScopeObj
= nullptr;
4380 void SAL_CALL
ModuleInvocationProxy::addEventListener( const Reference
< XEventListener
>& xListener
)
4382 std::unique_lock
aGuard( m_aMutex
);
4383 m_aListeners
.addInterface( aGuard
, xListener
);
4386 void SAL_CALL
ModuleInvocationProxy::removeEventListener( const Reference
< XEventListener
>& xListener
)
4388 std::unique_lock
aGuard( m_aMutex
);
4389 m_aListeners
.removeInterface( aGuard
, xListener
);
4393 Reference
< XInterface
> createComListener( const Any
& aControlAny
, const OUString
& aVBAType
,
4394 std::u16string_view aPrefix
,
4395 const SbxObjectRef
& xScopeObj
)
4397 Reference
< XInterface
> xRet
;
4399 const Reference
< XComponentContext
>& xContext(
4400 comphelper::getProcessComponentContext() );
4401 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4403 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPrefix
, xScopeObj
);
4405 Sequence
<Any
> args
{ aControlAny
, Any(aVBAType
), Any(xProxy
) };
4409 xRet
= xServiceMgr
->createInstanceWithArgumentsAndContext(
4410 u
"com.sun.star.custom.UnoComListener"_ustr
,
4413 catch( const Exception
& )
4415 implHandleAnyException( ::cppu::getCaughtException() );
4421 typedef std::vector
< WeakReference
< XComponent
> > ComponentRefVector
;
4425 struct StarBasicDisposeItem
4427 StarBASIC
* m_pBasic
;
4428 SbxArrayRef m_pRegisteredVariables
;
4429 ComponentRefVector m_vComImplementsObjects
;
4431 explicit StarBasicDisposeItem( StarBASIC
* pBasic
)
4432 : m_pBasic( pBasic
)
4433 , m_pRegisteredVariables(new SbxArray())
4440 typedef std::vector
< StarBasicDisposeItem
* > DisposeItemVector
;
4442 static DisposeItemVector GaDisposeItemVector
;
4444 static DisposeItemVector::iterator
lcl_findItemForBasic( StarBASIC
const * pBasic
)
4446 return std::find_if(GaDisposeItemVector
.begin(), GaDisposeItemVector
.end(),
4447 [&pBasic
](StarBasicDisposeItem
* pItem
) { return pItem
->m_pBasic
== pBasic
; });
4450 static StarBasicDisposeItem
* lcl_getOrCreateItemForBasic( StarBASIC
* pBasic
)
4452 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4453 StarBasicDisposeItem
* pItem
= (it
!= GaDisposeItemVector
.end()) ? *it
: nullptr;
4454 if( pItem
== nullptr )
4456 pItem
= new StarBasicDisposeItem( pBasic
);
4457 GaDisposeItemVector
.push_back( pItem
);
4462 void registerComponentToBeDisposedForBasic
4463 ( const Reference
< XComponent
>& xComponent
, StarBASIC
* pBasic
)
4465 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4466 pItem
->m_vComImplementsObjects
.emplace_back(xComponent
);
4469 void registerComListenerVariableForBasic( SbxVariable
* pVar
, StarBASIC
* pBasic
)
4471 StarBasicDisposeItem
* pItem
= lcl_getOrCreateItemForBasic( pBasic
);
4472 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4473 pArray
->Put(pVar
, pArray
->Count());
4476 void disposeComVariablesForBasic( StarBASIC
const * pBasic
)
4478 DisposeItemVector::iterator it
= lcl_findItemForBasic( pBasic
);
4479 if( it
== GaDisposeItemVector
.end() )
4482 StarBasicDisposeItem
* pItem
= *it
;
4484 SbxArray
* pArray
= pItem
->m_pRegisteredVariables
.get();
4485 sal_uInt32 nCount
= pArray
->Count();
4486 for( sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
4488 SbxVariable
* pVar
= pArray
->Get(i
);
4489 pVar
->ClearComListener();
4492 ComponentRefVector
& rv
= pItem
->m_vComImplementsObjects
;
4493 for (auto const& elem
: rv
)
4495 Reference
< XComponent
> xComponent( elem
);
4496 if (xComponent
.is())
4497 xComponent
->dispose();
4501 GaDisposeItemVector
.erase( it
);
4505 // Handle module implements mechanism for OLE types
4506 bool SbModule::createCOMWrapperForIface( Any
& o_rRetAny
, SbClassModuleObject
* pProxyClassModuleObject
)
4508 // For now: Take first interface that allows to instantiate COM wrapper
4509 // TODO: Check if support for multiple interfaces is needed
4511 const Reference
< XComponentContext
>& xContext(
4512 comphelper::getProcessComponentContext() );
4513 Reference
< XMultiComponentFactory
> xServiceMgr( xContext
->getServiceManager() );
4514 Reference
< XSingleServiceFactory
> xComImplementsFactory
4516 xServiceMgr
->createInstanceWithContext( u
"com.sun.star.custom.ComImplementsFactory"_ustr
, xContext
),
4519 if( !xComImplementsFactory
.is() )
4522 bool bSuccess
= false;
4524 SbxArray
* pModIfaces
= pClassData
->mxIfaces
.get();
4525 sal_uInt32 nCount
= pModIfaces
->Count();
4526 for( sal_uInt32 i
= 0 ; i
< nCount
; ++i
)
4528 SbxVariable
* pVar
= pModIfaces
->Get(i
);
4529 const OUString
& aIfaceName
= pVar
->GetName();
4531 if( !aIfaceName
.isEmpty() )
4533 OUString aPureIfaceName
= aIfaceName
;
4534 sal_Int32 indexLastDot
= aIfaceName
.lastIndexOf('.');
4535 if ( indexLastDot
> -1 )
4537 aPureIfaceName
= aIfaceName
.copy( indexLastDot
+ 1 );
4539 Reference
< XInvocation
> xProxy
= new ModuleInvocationProxy( aPureIfaceName
, pProxyClassModuleObject
);
4541 Sequence
<Any
> args
{ Any(aIfaceName
), Any(xProxy
) };
4543 Reference
< XInterface
> xRet
;
4546 xRet
= xComImplementsFactory
->createInstanceWithArguments( args
);
4549 catch( const Exception
& )
4551 implHandleAnyException( ::cppu::getCaughtException() );
4556 Reference
< XComponent
> xComponent( xProxy
, UNO_QUERY
);
4557 if( xComponent
.is() )
4559 StarBASIC
* pParentBasic
= nullptr;
4560 SbxObject
* pCurObject
= this;
4563 SbxObject
* pObjParent
= pCurObject
->GetParent();
4564 pParentBasic
= dynamic_cast<StarBASIC
*>( pObjParent
);
4565 pCurObject
= pObjParent
;
4567 while( pParentBasic
== nullptr && pCurObject
!= nullptr );
4569 assert( pParentBasic
!= nullptr );
4570 registerComponentToBeDisposedForBasic( xComponent
, pParentBasic
);
4583 // Due to an incorrect behavior IE returns an object instead of a string
4584 // in some scenarios. Calling toString at the object may correct this.
4585 // Helper function used in sbxvalue.cxx
4586 bool handleToStringForCOMObjects( SbxObject
* pObj
, SbxValue
* pVal
)
4588 bool bSuccess
= false;
4590 if( auto pUnoObj
= dynamic_cast<SbUnoObject
*>( pObj
) )
4592 // Only for native COM objects
4593 if( pUnoObj
->isNativeCOMObject() )
4595 SbxVariableRef pMeth
= pObj
->Find( u
"toString"_ustr
, SbxClassType::Method
);
4608 Any
StructRefInfo::getValue()
4612 &aRet
, reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4613 typelib_TypeDescription
* pTD
= nullptr;
4614 maType
.getDescription(&pTD
);
4616 &aRet
, getInst(), pTD
,
4617 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
) );
4618 typelib_typedescription_release(pTD
);
4622 void StructRefInfo::setValue( const Any
& rValue
)
4624 bool bSuccess
= uno_type_assignData( getInst(),
4625 maType
.getTypeLibType(),
4626 const_cast<void*>(rValue
.getValue()),
4627 rValue
.getValueTypeRef(),
4628 reinterpret_cast< uno_QueryInterfaceFunc
>(cpp_queryInterface
),
4629 reinterpret_cast< uno_AcquireFunc
>(cpp_acquire
),
4630 reinterpret_cast< uno_ReleaseFunc
>(cpp_release
) );
4631 OSL_ENSURE(bSuccess
,
4632 "StructRefInfo::setValue: ooops... the value could not be assigned!");
4635 OUString
StructRefInfo::getTypeName() const
4637 return maType
.getTypeName();
4640 void* StructRefInfo::getInst()
4642 return const_cast<char *>(static_cast<char const *>(maAny
.getValue()) + mnPos
);
4645 TypeClass
StructRefInfo::getTypeClass() const
4647 return maType
.getTypeClass();
4650 SbUnoStructRefObject::SbUnoStructRefObject( const OUString
& aName_
, StructRefInfo aMemberInfo
) : SbxObject( aName_
), maMemberInfo(std::move( aMemberInfo
)), mbMemberCacheInit( false )
4652 SetClassName( maMemberInfo
.getTypeName() );
4655 SbUnoStructRefObject::~SbUnoStructRefObject()
4659 void SbUnoStructRefObject::initMemberCache()
4661 if ( mbMemberCacheInit
)
4663 typelib_TypeDescription
* pTD
= nullptr;
4664 maMemberInfo
.getType().getDescription(&pTD
);
4665 for ( typelib_CompoundTypeDescription
* pCompTypeDescr
= reinterpret_cast<typelib_CompoundTypeDescription
*>(pTD
);
4667 pCompTypeDescr
= pCompTypeDescr
->pBaseTypeDescription
)
4669 typelib_TypeDescriptionReference
** ppTypeRefs
= pCompTypeDescr
->ppTypeRefs
;
4670 rtl_uString
** ppNames
= pCompTypeDescr
->ppMemberNames
;
4671 sal_Int32
* pMemberOffsets
= pCompTypeDescr
->pMemberOffsets
;
4672 for ( sal_Int32 nPos
= pCompTypeDescr
->nMembers
; nPos
--; )
4674 OUString
aName( ppNames
[nPos
] );
4675 maFields
[ aName
] = std::make_unique
<StructRefInfo
>( maMemberInfo
.getRootAnyRef(), ppTypeRefs
[nPos
], maMemberInfo
.getPos() + pMemberOffsets
[nPos
] );
4678 typelib_typedescription_release(pTD
);
4679 mbMemberCacheInit
= true;
4682 SbxVariable
* SbUnoStructRefObject::Find( const OUString
& rName
, SbxClassType t
)
4684 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
4687 if ( !mbMemberCacheInit
)
4689 StructFieldInfo::iterator it
= maFields
.find( rName
);
4690 if ( it
!= maFields
.end() )
4692 SbxDataType eSbxType
;
4693 eSbxType
= unoToSbxType( it
->second
->getTypeClass() );
4694 SbxDataType eRealSbxType
= eSbxType
;
4697 aProp
.Type
= css::uno::Type( it
->second
->getTypeClass(), it
->second
->getTypeName() );
4698 const bool bIsStruct
= aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
;
4699 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, std::move(aProp
), 0, false, bIsStruct
);
4700 SbxVariableRef xVarRef
= pProp
;
4701 QuickInsert( xVarRef
.get() );
4702 pRes
= xVarRef
.get();
4708 if( rName
.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES
) ||
4709 rName
.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES
) ||
4710 rName
.equalsIgnoreAsciiCase(ID_DBG_METHODS
) )
4713 implCreateDbgProperties();
4715 // Now they have to be found regular
4716 pRes
= SbxObject::Find( rName
, SbxClassType::DontCare
);
4723 // help method to create the dbg_-Properties
4724 void SbUnoStructRefObject::implCreateDbgProperties()
4728 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4729 SbxVariableRef xVarRef
= new SbUnoProperty( ID_DBG_SUPPORTEDINTERFACES
, SbxSTRING
, SbxSTRING
, aProp
, -1, false, false );
4730 QuickInsert( xVarRef
.get() );
4732 // Id == -2: output the properties
4733 xVarRef
= new SbUnoProperty( ID_DBG_PROPERTIES
, SbxSTRING
, SbxSTRING
, aProp
, -2, false, false );
4734 QuickInsert( xVarRef
.get() );
4736 // Id == -3: output the Methods
4737 xVarRef
= new SbUnoProperty( ID_DBG_METHODS
, SbxSTRING
, SbxSTRING
, std::move(aProp
), -3, false, false );
4738 QuickInsert( xVarRef
.get() );
4741 void SbUnoStructRefObject::implCreateAll()
4743 // throw away all existing methods and properties
4744 pMethods
= new SbxArray
;
4745 pProps
= new SbxArray
;
4747 if (!mbMemberCacheInit
)
4750 for (auto const& field
: maFields
)
4752 const OUString
& rName
= field
.first
;
4753 SbxDataType eSbxType
;
4754 eSbxType
= unoToSbxType( field
.second
->getTypeClass() );
4755 SbxDataType eRealSbxType
= eSbxType
;
4758 aProp
.Type
= css::uno::Type( field
.second
->getTypeClass(), field
.second
->getTypeName() );
4759 const bool bIsStruct
= aProp
.Type
.getTypeClass() == css::uno::TypeClass_STRUCT
;
4760 SbUnoProperty
* pProp
= new SbUnoProperty( rName
, eSbxType
, eRealSbxType
, std::move(aProp
), 0, false, bIsStruct
);
4761 SbxVariableRef xVarRef
= pProp
;
4762 QuickInsert( xVarRef
.get() );
4765 // Create Dbg_-Properties
4766 implCreateDbgProperties();
4770 Any
SbUnoStructRefObject::getUnoAny()
4772 return maMemberInfo
.getValue();
4775 OUString
SbUnoStructRefObject::Impl_DumpProperties()
4777 OUStringBuffer
aRet("Properties of object " + getDbgObjectName() );
4779 sal_uInt32 nPropCount
= pProps
->Count();
4780 sal_uInt32 nPropsPerLine
= 1 + nPropCount
/ 30;
4781 for( sal_uInt32 i
= 0; i
< nPropCount
; i
++ )
4783 SbxVariable
* pVar
= pProps
->Get(i
);
4786 OUStringBuffer aPropStr
;
4787 if( (i
% nPropsPerLine
) == 0 )
4789 aPropStr
.append( "\n" );
4791 // output the type and name
4792 // Is it in Uno a sequence?
4793 SbxDataType eType
= pVar
->GetFullType();
4795 const OUString
& aName( pVar
->GetName() );
4796 StructFieldInfo::iterator it
= maFields
.find( aName
);
4798 if ( it
!= maFields
.end() )
4800 const StructRefInfo
& rPropInfo
= *it
->second
;
4802 if( eType
== SbxOBJECT
)
4804 if( rPropInfo
.getTypeClass() == TypeClass_SEQUENCE
)
4806 eType
= SbxDataType( SbxOBJECT
| SbxARRAY
);
4810 aPropStr
.append( Dbg_SbxDataType2String( eType
)
4811 + " " + pVar
->GetName() );
4813 if( i
== nPropCount
- 1 )
4815 aPropStr
.append( "\n" );
4819 aPropStr
.append( "; " );
4821 aRet
.append( aPropStr
);
4824 return aRet
.makeStringAndClear();
4827 void SbUnoStructRefObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
4829 if ( !mbMemberCacheInit
)
4831 const SbxHint
* pHint
= dynamic_cast<const SbxHint
*>(&rHint
);
4835 SbxVariable
* pVar
= pHint
->GetVar();
4836 SbUnoProperty
* pProp
= dynamic_cast<SbUnoProperty
*>( pVar
);
4839 StructFieldInfo::iterator it
= maFields
.find( pProp
->GetName() );
4840 // handle get/set of members of struct
4841 if( pHint
->GetId() == SfxHintId::BasicDataWanted
)
4844 sal_Int32 nId
= pProp
->nId
;
4847 // Id == -1: Display implemented interfaces according the ClassProvider
4848 if( nId
== -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
4850 OUString aRet
= OUString::Concat( ID_DBG_SUPPORTEDINTERFACES
)
4851 + " not available.\n(TypeClass is not TypeClass_INTERFACE)\n";
4853 pVar
->PutString( aRet
);
4855 // Id == -2: output properties
4856 else if( nId
== -2 ) // Property ID_DBG_PROPERTIES
4858 // by now all properties must be established
4860 OUString aRetStr
= Impl_DumpProperties();
4861 pVar
->PutString( aRetStr
);
4863 // Id == -3: output the methods
4864 else if( nId
== -3 ) // Property ID_DBG_METHODS
4866 // by now all properties must be established
4868 OUString aRet
= "Methods of object "
4869 + getDbgObjectName()
4870 + "\nNo methods found\n";
4871 pVar
->PutString( aRet
);
4876 if ( it
!= maFields
.end() )
4878 Any aRetAny
= it
->second
->getValue();
4879 unoToSbxValue( pVar
, aRetAny
);
4882 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4884 else if( pHint
->GetId() == SfxHintId::BasicDataChanged
)
4886 if ( it
!= maFields
.end() )
4888 // take over the value from Uno to Sbx
4889 Any aAnyValue
= sbxToUnoValue( pVar
, pProp
->aUnoProp
.Type
, &pProp
->aUnoProp
);
4890 it
->second
->setValue( aAnyValue
);
4893 StarBASIC::Error( ERRCODE_BASIC_PROPERTY_NOT_FOUND
);
4897 SbxObject::Notify( rBC
, rHint
);
4900 StructRefInfo
SbUnoStructRefObject::getStructMember( const OUString
& rMemberName
)
4902 if (!mbMemberCacheInit
)
4906 StructFieldInfo::iterator it
= maFields
.find( rMemberName
);
4908 css::uno::Type aFoundType
;
4909 sal_Int32 nFoundPos
= -1;
4911 if ( it
!= maFields
.end() )
4913 aFoundType
= it
->second
->getType();
4914 nFoundPos
= it
->second
->getPos();
4916 StructRefInfo
aRet( maMemberInfo
.getRootAnyRef(), aFoundType
, nFoundPos
);
4920 OUString
SbUnoStructRefObject::getDbgObjectName() const
4922 OUString aName
= GetClassName();
4923 if( aName
.isEmpty() )
4927 OUStringBuffer aRet
;
4928 if( aName
.getLength() > 20 )
4930 aRet
.append( "\n" );
4932 aRet
.append( "\"" + aName
+ "\":" );
4933 return aRet
.makeStringAndClear();
4936 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */