Bump version to 5.0-43
[LibreOffice.git] / basic / source / classes / sbunoobj.cxx
blob8e9a3d4d94f889e14b0c0b10feff18c4eee52253
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <osl/mutex.hxx>
21 #include <vcl/svapp.hxx>
22 #include <tools/errcode.hxx>
23 #include <svl/hint.hxx>
25 #include <cppuhelper/implbase1.hxx>
26 #include <cppuhelper/implbase2.hxx>
27 #include <cppuhelper/exc_hlp.hxx>
28 #include <cppuhelper/typeprovider.hxx>
29 #include <cppuhelper/interfacecontainer.hxx>
30 #include <comphelper/extract.hxx>
31 #include <comphelper/processfactory.hxx>
33 #include <rtl/instance.hxx>
34 #include <rtl/strbuf.hxx>
35 #include <rtl/ustrbuf.hxx>
37 #include <com/sun/star/script/ArrayWrapper.hpp>
38 #include <com/sun/star/script/NativeObjectWrapper.hpp>
40 #include <com/sun/star/uno/XComponentContext.hpp>
41 #include <com/sun/star/uno/DeploymentException.hpp>
42 #include <com/sun/star/lang/XTypeProvider.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/lang/XServiceInfo.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/PropertyConcept.hpp>
48 #include <com/sun/star/beans/MethodConcept.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/beans/theIntrospection.hpp>
51 #include <com/sun/star/script/BasicErrorException.hpp>
52 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
53 #include <com/sun/star/script/XAllListener.hpp>
54 #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
55 #include <com/sun/star/script/Converter.hpp>
56 #include <com/sun/star/script/XDefaultProperty.hpp>
57 #include <com/sun/star/script/XDefaultMethod.hpp>
58 #include <com/sun/star/script/XDirectInvocation.hpp>
59 #include <com/sun/star/container/XNameAccess.hpp>
60 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
61 #include <com/sun/star/reflection/XIdlArray.hpp>
62 #include <com/sun/star/reflection/XIdlReflection.hpp>
63 #include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
64 #include <com/sun/star/reflection/theCoreReflection.hpp>
65 #include <com/sun/star/bridge/oleautomation/NamedArgument.hpp>
66 #include <com/sun/star/bridge/oleautomation/Date.hpp>
67 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
68 #include <com/sun/star/bridge/oleautomation/Currency.hpp>
69 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
70 #include <com/sun/star/script/XAutomationInvocation.hpp>
71 #include <basic/codecompletecache.hxx>
73 #include <rtlproto.hxx>
75 #include <basic/sbstar.hxx>
76 #include <basic/sbuno.hxx>
77 #include <basic/sberrors.hxx>
78 #include <sbunoobj.hxx>
79 #include "sbjsmod.hxx"
80 #include <basic/basmgr.hxx>
81 #include <sbintern.hxx>
82 #include <runtime.hxx>
84 #include <math.h>
85 #include <boost/scoped_array.hpp>
86 #include <unordered_map>
87 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
88 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
90 using com::sun::star::uno::Reference;
91 using namespace com::sun::star::uno;
92 using namespace com::sun::star::lang;
93 using namespace com::sun::star::reflection;
94 using namespace com::sun::star::beans;
95 using namespace com::sun::star::script;
96 using namespace com::sun::star::container;
97 using namespace com::sun::star::bridge;
98 using namespace cppu;
100 TYPEINIT1(SbUnoMethod,SbxMethod)
101 TYPEINIT1(SbUnoProperty,SbxProperty)
102 TYPEINIT1(SbUnoObject,SbxObject)
103 TYPEINIT1(SbUnoStructRefObject,SbxObject)
104 TYPEINIT1(SbUnoClass,SbxObject)
105 TYPEINIT1(SbUnoService,SbxObject)
106 TYPEINIT1(SbUnoServiceCtor,SbxMethod)
107 TYPEINIT1(SbUnoSingleton,SbxObject)
109 typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper;
111 // Identifiers for creating the strings for dbg_Properties
112 static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces";
113 static char const ID_DBG_PROPERTIES[] = "Dbg_Properties";
114 static char const ID_DBG_METHODS[] = "Dbg_Methods";
116 static char const aSeqLevelStr[] = "[]";
117 static char const defaultNameSpace[] = "ooo.vba";
119 // Gets the default property for an uno object. Note: There is some
120 // redirection built in. The property name specifies the name
121 // of the default property.
123 bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, OUString& sDfltProp )
125 bool result = false;
126 Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY );
127 if ( xDefaultProp.is() )
129 sDfltProp = xDefaultProp->getDefaultPropertyName();
130 if ( !sDfltProp.isEmpty() )
131 result = true;
133 return result;
136 SbxVariable* getDefaultProp( SbxVariable* pRef )
138 SbxVariable* pDefaultProp = NULL;
139 if ( pRef->GetType() == SbxOBJECT )
141 SbxObject* pObj = PTR_CAST(SbxObject, pRef);
142 if ( !pObj )
144 SbxBase* pObjVarObj = pRef->GetObject();
145 pObj = PTR_CAST(SbxObject,pObjVarObj);
147 if ( pObj && pObj->ISA(SbUnoObject) )
149 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
150 pDefaultProp = pUnoObj->GetDfltProperty();
153 return pDefaultProp;
156 void SetSbUnoObjectDfltPropName( SbxObject* pObj )
158 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject, pObj);
159 if ( pUnoObj )
161 OUString sDfltPropName;
163 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
165 OSL_TRACE("SetSbUnoObjectDfltPropName setting default prop for %s", OUStringToOString( pObj->GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
166 pUnoObj->SetDfltProperty( sDfltPropName );
171 // save CoreReflection statically
172 Reference< XIdlReflection > getCoreReflection_Impl()
174 return css::reflection::theCoreReflection::get(
175 comphelper::getProcessComponentContext());
178 // save CoreReflection statically
179 Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl()
181 static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess;
183 if( !xCoreReflection_HierarchicalNameAccess.is() )
185 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
186 if( xCoreReflection.is() )
188 xCoreReflection_HierarchicalNameAccess =
189 Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY );
192 return xCoreReflection_HierarchicalNameAccess;
195 // Hold TypeProvider statically
196 Reference< XHierarchicalNameAccess > getTypeProvider_Impl()
198 static Reference< XHierarchicalNameAccess > xAccess;
200 // Do we have already CoreReflection; if not obtain it
201 if( !xAccess.is() )
203 Reference< XComponentContext > xContext(
204 comphelper::getProcessComponentContext() );
205 if( xContext.is() )
207 xContext->getValueByName(
208 OUString( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) )
209 >>= xAccess;
210 OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" );
212 if( !xAccess.is() )
214 throw DeploymentException(
215 "/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible" );
218 return xAccess;
221 // Hold TypeConverter statically
222 Reference< XTypeConverter > getTypeConverter_Impl()
224 static Reference< XTypeConverter > xTypeConverter;
226 // Do we have already CoreReflection; if not obtain it
227 if( !xTypeConverter.is() )
229 Reference< XComponentContext > xContext(
230 comphelper::getProcessComponentContext() );
231 if( xContext.is() )
233 xTypeConverter = Converter::create(xContext);
235 if( !xTypeConverter.is() )
237 throw DeploymentException(
238 "com.sun.star.script.Converter service not accessible" );
241 return xTypeConverter;
245 // #111851 factory function to create an OLE object
246 SbUnoObject* createOLEObject_Impl( const OUString& aType )
248 static Reference< XMultiServiceFactory > xOLEFactory;
249 static bool bNeedsInit = true;
251 if( bNeedsInit )
253 bNeedsInit = false;
255 Reference< XComponentContext > xContext(
256 comphelper::getProcessComponentContext() );
257 if( xContext.is() )
259 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
260 xOLEFactory = Reference<XMultiServiceFactory>(
261 xSMgr->createInstanceWithContext(
262 OUString( "com.sun.star.bridge.OleObjectFactory"),
263 xContext ), UNO_QUERY );
267 SbUnoObject* pUnoObj = NULL;
268 if( xOLEFactory.is() )
270 // some type names available in VBA can not be directly used in COM
271 OUString aOLEType = aType;
272 if ( aOLEType == "SAXXMLReader30" )
274 aOLEType = "Msxml2.SAXXMLReader.3.0";
276 Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType );
277 if( xOLEObject.is() )
279 Any aAny;
280 aAny <<= xOLEObject;
281 pUnoObj = new SbUnoObject( aType, aAny );
282 OUString sDfltPropName;
284 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
285 pUnoObj->SetDfltProperty( sDfltPropName );
288 return pUnoObj;
292 namespace
294 void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel )
296 while ( _nLevel-- > 0 )
298 _inout_rBuffer.appendAscii( " " );
303 void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, const OUString& _rExceptionType, sal_Int32 _nLevel )
305 _inout_rBuffer.appendAscii( "\n" );
306 lcl_indent( _inout_rBuffer, _nLevel );
307 _inout_rBuffer.appendAscii( "Type: " );
309 if ( _rExceptionType.isEmpty() )
310 _inout_rBuffer.appendAscii( "Unknown" );
311 else
312 _inout_rBuffer.append( _rExceptionType );
314 _inout_rBuffer.appendAscii( "\n" );
315 lcl_indent( _inout_rBuffer, _nLevel );
316 _inout_rBuffer.appendAscii( "Message: " );
317 _inout_rBuffer.append( _e.Message );
321 // construct an error message for the exception
322 OUString implGetExceptionMsg( const Exception& e, const OUString& aExceptionType_ )
324 OUStringBuffer aMessageBuf;
325 implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 );
326 return aMessageBuf.makeStringAndClear();
329 OUString implGetExceptionMsg( const Any& _rCaughtException )
331 OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" );
332 if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION )
334 return OUString();
336 return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() );
339 Any convertAny( const Any& rVal, const Type& aDestType )
341 Any aConvertedVal;
342 Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
345 aConvertedVal = xConverter->convertTo( rVal, aDestType );
347 catch( const IllegalArgumentException& )
349 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
350 implGetExceptionMsg( ::cppu::getCaughtException() ) );
351 return aConvertedVal;
353 catch( const CannotConvertException& e2 )
355 OUString aCannotConvertExceptionName( "com.sun.star.lang.IllegalArgumentException");
356 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
357 implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
358 return aConvertedVal;
360 return aConvertedVal;
364 // #105565 Special Object to wrap a strongly typed Uno Any
365 TYPEINIT1(SbUnoAnyObject,SbxObject)
368 // TODO: source out later
369 Reference<XIdlClass> TypeToIdlClass( const Type& rType )
371 return getCoreReflection_Impl()->forName(rType.getTypeName());
374 // Exception type unknown
375 template< class EXCEPTION >
376 OUString implGetExceptionMsg( const EXCEPTION& e )
378 return implGetExceptionMsg( e, cppu::UnoType<decltype(e)>::get().getTypeName() );
381 void implHandleBasicErrorException( BasicErrorException& e )
383 SbError nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)e.ErrorCode );
384 StarBASIC::Error( nError, e.ErrorMessageArgument );
387 void implHandleWrappedTargetException( const Any& _rWrappedTargetException )
389 Any aExamine( _rWrappedTargetException );
391 // completely strip the first InvocationTargetException, its error message isn't of any
392 // interest to the user, it just says something like "invoking the UNO method went wrong.".
393 InvocationTargetException aInvocationError;
394 if ( aExamine >>= aInvocationError )
395 aExamine = aInvocationError.TargetException;
397 BasicErrorException aBasicError;
399 SbError nError( ERRCODE_BASIC_EXCEPTION );
400 OUStringBuffer aMessageBuf;
402 // strip any other WrappedTargetException instances, but this time preserve the error messages.
403 WrappedTargetException aWrapped;
404 sal_Int32 nLevel = 0;
405 while ( aExamine >>= aWrapped )
407 // special handling for BasicErrorException errors
408 if ( aWrapped.TargetException >>= aBasicError )
410 nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)aBasicError.ErrorCode );
411 aMessageBuf.append( aBasicError.ErrorMessageArgument );
412 aExamine.clear();
413 break;
416 // append this round's message
417 implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel );
418 if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION )
419 // there is a next chain element
420 aMessageBuf.appendAscii( "\nTargetException:" );
422 // next round
423 aExamine = aWrapped.TargetException;
424 ++nLevel;
427 if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION )
429 // the last element in the chain is still an exception, but no WrappedTargetException
430 implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), aExamine.getValueTypeName(), nLevel );
433 StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() );
436 static void implHandleAnyException( const Any& _rCaughtException )
438 BasicErrorException aBasicError;
439 WrappedTargetException aWrappedError;
441 if ( _rCaughtException >>= aBasicError )
443 implHandleBasicErrorException( aBasicError );
445 else if ( _rCaughtException >>= aWrappedError )
447 implHandleWrappedTargetException( _rCaughtException );
449 else
451 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) );
455 // NativeObjectWrapper handling
456 struct ObjectItem
458 SbxObjectRef m_xNativeObj;
460 ObjectItem( SbxObject* pNativeObj )
461 : m_xNativeObj( pNativeObj )
465 typedef std::vector< ObjectItem > NativeObjectWrapperVector;
466 class GaNativeObjectWrapperVector : public rtl::Static<NativeObjectWrapperVector, GaNativeObjectWrapperVector> {};
468 void clearNativeObjectWrapperVector()
470 GaNativeObjectWrapperVector::get().clear();
473 static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj )
475 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
476 sal_uInt32 nIndex = rNativeObjectWrapperVector.size();
477 rNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) );
478 return nIndex;
481 static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex )
483 SbxObjectRef xRetObj;
484 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
485 if( nIndex < rNativeObjectWrapperVector.size() )
487 ObjectItem& rItem = rNativeObjectWrapperVector[ nIndex ];
488 xRetObj = rItem.m_xNativeObj;
490 return xRetObj;
493 // convert from Uno to Sbx
494 SbxDataType unoToSbxType( TypeClass eType )
496 SbxDataType eRetType = SbxVOID;
498 switch( eType )
500 case TypeClass_INTERFACE:
501 case TypeClass_TYPE:
502 case TypeClass_STRUCT:
503 case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break;
505 case TypeClass_ENUM: eRetType = SbxLONG; break;
506 case TypeClass_SEQUENCE:
507 eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
508 break;
511 case TypeClass_ANY: eRetType = SbxVARIANT; break;
512 case TypeClass_BOOLEAN: eRetType = SbxBOOL; break;
513 case TypeClass_CHAR: eRetType = SbxCHAR; break;
514 case TypeClass_STRING: eRetType = SbxSTRING; break;
515 case TypeClass_FLOAT: eRetType = SbxSINGLE; break;
516 case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break;
517 case TypeClass_BYTE: eRetType = SbxINTEGER; break;
518 case TypeClass_SHORT: eRetType = SbxINTEGER; break;
519 case TypeClass_LONG: eRetType = SbxLONG; break;
520 case TypeClass_HYPER: eRetType = SbxSALINT64; break;
521 case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break;
522 case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break;
523 case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break;
524 default: break;
526 return eRetType;
529 SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass )
531 SbxDataType eRetType = SbxVOID;
532 if( xIdlClass.is() )
534 TypeClass eType = xIdlClass->getTypeClass();
535 eRetType = unoToSbxType( eType );
537 return eRetType;
540 static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32& dimension, bool bIsZeroIndex, Type* pType = NULL )
542 Type aType = aValue.getValueType();
543 TypeClass eTypeClass = aType.getTypeClass();
545 sal_Int32 dimCopy = dimension;
547 if ( eTypeClass == TypeClass_SEQUENCE )
549 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
550 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
551 typelib_TypeDescription * pTD = 0;
552 aType.getDescription( &pTD );
553 Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType );
554 ::typelib_typedescription_release( pTD );
556 sal_Int32 nLen = xIdlArray->getLen( aValue );
557 for ( sal_Int32 index = 0; index < nLen; ++index )
559 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)index );
560 // This detects the dimension were currently processing
561 if ( dimCopy == dimension )
563 ++dimCopy;
564 if ( sizes.getLength() < dimCopy )
566 sizes.realloc( sizes.getLength() + 1 );
567 sizes[ sizes.getLength() - 1 ] = nLen;
568 indices.realloc( indices.getLength() + 1 );
572 if ( bIsZeroIndex )
573 indices[ dimCopy - 1 ] = index;
574 else
575 indices[ dimCopy - 1] = index + 1;
577 implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType );
581 else
583 if ( indices.getLength() < 1 )
585 // Should never ever get here ( indices.getLength()
586 // should equal number of dimensions in the array )
587 // And that should at least be 1 !
588 // #QUESTION is there a better error?
589 StarBASIC::Error( SbERR_INVALID_OBJECT );
590 return;
593 SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() );
594 if ( !pArray )
596 pArray = new SbxDimArray( eSbxElementType );
597 sal_Int32 nIndexLen = indices.getLength();
599 // Dimension the array
600 for ( sal_Int32 index = 0; index < nIndexLen; ++index )
602 if ( bIsZeroIndex )
603 pArray->unoAddDim32( 0, sizes[ index ] - 1);
604 else
605 pArray->unoAddDim32( 1, sizes[ index ] );
610 if ( pArray )
612 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
613 unoToSbxValue( (SbxVariable*)xVar, aValue );
615 sal_Int32* pIndices = indices.getArray();
616 pArray->Put32( (SbxVariable*)xVar, pIndices );
622 void unoToSbxValue( SbxVariable* pVar, const Any& aValue )
624 Type aType = aValue.getValueType();
625 TypeClass eTypeClass = aType.getTypeClass();
626 switch( eTypeClass )
628 case TypeClass_TYPE:
630 // Map Type to IdlClass
631 Type aType_;
632 aValue >>= aType_;
633 Reference<XIdlClass> xClass = TypeToIdlClass( aType_ );
634 Any aClassAny;
635 aClassAny <<= xClass;
637 // instantiate SbUnoObject
638 OUString aName;
639 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny );
640 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
642 // If the object is invalid deliver null
643 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
645 pVar->PutObject( NULL );
647 else
649 pVar->PutObject( xWrapper );
652 break;
653 // Interfaces and Structs must be wrapped in a SbUnoObject
654 case TypeClass_INTERFACE:
655 case TypeClass_STRUCT:
656 case TypeClass_EXCEPTION:
658 if( eTypeClass == TypeClass_STRUCT )
660 ArrayWrapper aWrap;
661 NativeObjectWrapper aNativeObjectWrapper;
662 if ( (aValue >>= aWrap) )
664 SbxDimArray* pArray = NULL;
665 Sequence< sal_Int32 > indices;
666 Sequence< sal_Int32 > sizes;
667 sal_Int32 dimension = 0;
668 implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex );
669 if ( pArray )
671 SbxDimArrayRef xArray = pArray;
672 SbxFlagBits nFlags = pVar->GetFlags();
673 pVar->ResetFlag( SBX_FIXED );
674 pVar->PutObject( (SbxDimArray*)xArray );
675 pVar->SetFlags( nFlags );
677 else
678 pVar->PutEmpty();
679 break;
681 else if ( (aValue >>= aNativeObjectWrapper) )
683 sal_uInt32 nIndex = 0;
684 if( (aNativeObjectWrapper.ObjectId >>= nIndex) )
686 SbxObject* pObj = lcl_getNativeObject( nIndex );
687 pVar->PutObject( pObj );
689 else
690 pVar->PutEmpty();
691 break;
693 else
695 SbiInstance* pInst = GetSbData()->pInst;
696 if( pInst && pInst->IsCompatibility() )
698 oleautomation::Date aDate;
699 if( (aValue >>= aDate) )
701 pVar->PutDate( aDate.Value );
702 break;
704 else
706 oleautomation::Decimal aDecimal;
707 if( (aValue >>= aDecimal) )
709 pVar->PutDecimal( aDecimal );
710 break;
712 else
714 oleautomation::Currency aCurrency;
715 if( (aValue >>= aCurrency) )
717 pVar->PutCurrency( aCurrency.Value );
718 break;
725 // instantiate a SbUnoObject
726 OUString aName;
727 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue );
728 //If this is called externally e.g. from the scripting
729 //framework then there is no 'active' runtime the default property will not be set up
730 //only a vba object will have XDefaultProp set anyway so... this
731 //test seems a bit of overkill
732 //if ( SbiRuntime::isVBAEnabled() )
734 OUString sDfltPropName;
736 if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) )
738 pSbUnoObject->SetDfltProperty( sDfltPropName );
741 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
743 // If the object is invalid deliver null
744 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
746 pVar->PutObject( NULL );
748 else
750 pVar->PutObject( xWrapper );
753 break;
756 case TypeClass_ENUM:
758 sal_Int32 nEnum = 0;
759 enum2int( nEnum, aValue );
760 pVar->PutLong( nEnum );
762 break;
764 case TypeClass_SEQUENCE:
766 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
767 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
768 sal_Int32 i, nLen = xIdlArray->getLen( aValue );
770 typelib_TypeDescription * pTD = 0;
771 aType.getDescription( &pTD );
772 OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE );
773 Type aElementType( reinterpret_cast<typelib_IndirectTypeDescription *>(pTD)->pType );
774 ::typelib_typedescription_release( pTD );
776 // build an Array in Basic
777 SbxDimArrayRef xArray;
778 SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() );
779 xArray = new SbxDimArray( eSbxElementType );
780 if( nLen > 0 )
782 xArray->unoAddDim32( 0, nLen - 1 );
784 // register the elements as variables
785 for( i = 0 ; i < nLen ; i++ )
787 // convert elements
788 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)i );
789 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
790 unoToSbxValue( (SbxVariable*)xVar, aElementAny );
792 // put into the Array
793 xArray->Put32( (SbxVariable*)xVar, &i );
796 else
798 xArray->unoAddDim( 0, -1 );
801 // return the Array
802 SbxFlagBits nFlags = pVar->GetFlags();
803 pVar->ResetFlag( SBX_FIXED );
804 pVar->PutObject( (SbxDimArray*)xArray );
805 pVar->SetFlags( nFlags );
808 break;
811 case TypeClass_BOOLEAN: pVar->PutBool( *static_cast<sal_Bool const *>(aValue.getValue()) ); break;
812 case TypeClass_CHAR:
814 pVar->PutChar( *static_cast<sal_Unicode const *>(aValue.getValue()) );
815 break;
817 case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( val ); } break;
818 case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break;
819 case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break;
820 case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
821 case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
822 case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break;
823 case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break;
824 case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break;
825 case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break;
826 case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break;
827 default: pVar->PutEmpty(); break;
831 // Deliver the reflection for Sbx types
832 Type getUnoTypeForSbxBaseType( SbxDataType eType )
834 Type aRetType = cppu::UnoType<void>::get();
835 switch( eType )
837 case SbxNULL: aRetType = cppu::UnoType<XInterface>::get(); break;
838 case SbxINTEGER: aRetType = cppu::UnoType<sal_Int16>::get(); break;
839 case SbxLONG: aRetType = cppu::UnoType<sal_Int32>::get(); break;
840 case SbxSINGLE: aRetType = cppu::UnoType<float>::get(); break;
841 case SbxDOUBLE: aRetType = cppu::UnoType<double>::get(); break;
842 case SbxCURRENCY: aRetType = cppu::UnoType<oleautomation::Currency>::get(); break;
843 case SbxDECIMAL: aRetType = cppu::UnoType<oleautomation::Decimal>::get(); break;
844 case SbxDATE: {
845 SbiInstance* pInst = GetSbData()->pInst;
846 if( pInst && pInst->IsCompatibility() )
847 aRetType = cppu::UnoType<double>::get();
848 else
849 aRetType = cppu::UnoType<oleautomation::Date>::get();
851 break;
852 case SbxSTRING: aRetType = cppu::UnoType<OUString>::get(); break;
853 case SbxBOOL: aRetType = cppu::UnoType<sal_Bool>::get(); break;
854 case SbxVARIANT: aRetType = cppu::UnoType<Any>::get(); break;
855 case SbxCHAR: aRetType = cppu::UnoType<cppu::UnoCharType>::get(); break;
856 case SbxBYTE: aRetType = cppu::UnoType<sal_Int8>::get(); break;
857 case SbxUSHORT: aRetType = cppu::UnoType<cppu::UnoUnsignedShortType>::get(); break;
858 case SbxULONG: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break;
859 // map machine-dependent ones to long for consistency
860 case SbxINT: aRetType = ::cppu::UnoType<sal_Int32>::get(); break;
861 case SbxUINT: aRetType = ::cppu::UnoType<sal_uInt32>::get(); break;
862 default: break;
864 return aRetType;
867 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
868 Type getUnoTypeForSbxValue( const SbxValue* pVal )
870 Type aRetType = cppu::UnoType<void>::get();
871 if( !pVal )
872 return aRetType;
874 // convert SbxType to Uno
875 SbxDataType eBaseType = pVal->SbxValue::GetType();
876 if( eBaseType == SbxOBJECT )
878 SbxBaseRef xObj = pVal->GetObject();
879 if( !xObj )
881 aRetType = cppu::UnoType<XInterface>::get();
882 return aRetType;
885 if( xObj->ISA(SbxDimArray) )
887 SbxBase* pObj = static_cast<SbxBase*>(xObj);
888 SbxDimArray* pArray = static_cast<SbxDimArray*>(pObj);
890 short nDims = pArray->GetDims();
891 Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) );
892 TypeClass eElementTypeClass = aElementType.getTypeClass();
894 // Normal case: One dimensional array
895 sal_Int32 nLower, nUpper;
896 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
898 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
900 // If all elements of the arrays are from the same type, take
901 // this one - otherwise the whole will be considered as Any-Sequence
902 bool bNeedsInit = true;
904 sal_Int32 nSize = nUpper - nLower + 1;
905 sal_Int32 nIdx = nLower;
906 for( sal_Int32 i = 0 ; i < nSize ; i++,nIdx++ )
908 // coverity[callee_ptr_arith]
909 SbxVariableRef xVar = pArray->Get32( &nIdx );
910 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
911 if( bNeedsInit )
913 if( aType.getTypeClass() == TypeClass_VOID )
915 // if only first element is void: different types -> []any
916 // if all elements are void: []void is not allowed -> []any
917 aElementType = cppu::UnoType<Any>::get();
918 break;
920 aElementType = aType;
921 bNeedsInit = false;
923 else if( aElementType != aType )
925 // different types -> AnySequence
926 aElementType = cppu::UnoType<Any>::get();
927 break;
932 OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName();
933 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
935 // #i33795 Map also multi dimensional arrays to corresponding sequences
936 else if( nDims > 1 )
938 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
940 // For this check the array's dim structure does not matter
941 sal_uInt32 nFlatArraySize = pArray->Count32();
943 bool bNeedsInit = true;
944 for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ )
946 SbxVariableRef xVar = pArray->SbxArray::Get32( i );
947 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
948 if( bNeedsInit )
950 if( aType.getTypeClass() == TypeClass_VOID )
952 // if only first element is void: different types -> []any
953 // if all elements are void: []void is not allowed -> []any
954 aElementType = cppu::UnoType<Any>::get();
955 break;
957 aElementType = aType;
958 bNeedsInit = false;
960 else if( aElementType != aType )
962 // different types -> AnySequence
963 aElementType = cppu::UnoType<Any>::get();
964 break;
969 OUStringBuffer aSeqTypeName;
970 for( short iDim = 0 ; iDim < nDims ; iDim++ )
972 aSeqTypeName.appendAscii(aSeqLevelStr);
974 aSeqTypeName.append(aElementType.getTypeName());
975 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
978 // No array, but ...
979 else if( xObj->ISA(SbUnoObject) )
981 aRetType = static_cast<SbUnoObject*>((SbxBase*)xObj)->getUnoAny().getValueType();
983 // SbUnoAnyObject?
984 else if( xObj->ISA(SbUnoAnyObject) )
986 aRetType = static_cast<SbUnoAnyObject*>((SbxBase*)xObj)->getValue().getValueType();
988 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
990 // No object, convert basic type
991 else
993 aRetType = getUnoTypeForSbxBaseType( eBaseType );
995 return aRetType;
998 // converting of Sbx to Uno without known target class for TypeClass_ANY
999 Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType = false )
1001 SbxDataType eBaseType = pVar->SbxValue::GetType();
1002 if( eBaseType == SbxOBJECT )
1004 SbxBaseRef xObj = pVar->GetObject();
1005 if( xObj.Is() )
1007 if( xObj->ISA(SbUnoAnyObject) )
1008 return static_cast<SbUnoAnyObject*>((SbxBase*)xObj)->getValue();
1009 if( xObj->ISA(SbClassModuleObject) )
1011 Any aRetAny;
1012 SbClassModuleObject* pClassModuleObj = static_cast<SbClassModuleObject*>((SbxBase*)xObj);
1013 SbModule* pClassModule = pClassModuleObj->getClassModule();
1014 if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) )
1015 return aRetAny;
1017 if( !xObj->ISA(SbUnoObject) )
1019 // Create NativeObjectWrapper to identify object in case of callbacks
1020 SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject());
1021 if( pObj != NULL )
1023 NativeObjectWrapper aNativeObjectWrapper;
1024 sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj );
1025 aNativeObjectWrapper.ObjectId <<= nIndex;
1026 Any aRetAny;
1027 aRetAny <<= aNativeObjectWrapper;
1028 return aRetAny;
1034 Type aType = getUnoTypeForSbxValue( pVar );
1035 TypeClass eType = aType.getTypeClass();
1037 if( !bBlockConversionToSmallestType )
1039 // #79615 Choose "smallest" represention for int values
1040 // because up cast is allowed, downcast not
1041 switch( eType )
1043 case TypeClass_FLOAT:
1044 case TypeClass_DOUBLE:
1046 double d = pVar->GetDouble();
1047 if( d == floor( d ) )
1049 if( d >= -128 && d <= 127 )
1050 aType = ::cppu::UnoType<sal_Int8>::get();
1051 else if( d >= SbxMININT && d <= SbxMAXINT )
1052 aType = ::cppu::UnoType<sal_Int16>::get();
1053 else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
1054 aType = ::cppu::UnoType<sal_Int32>::get();
1056 break;
1058 case TypeClass_SHORT:
1060 sal_Int16 n = pVar->GetInteger();
1061 if( n >= -128 && n <= 127 )
1062 aType = ::cppu::UnoType<sal_Int8>::get();
1063 break;
1065 case TypeClass_LONG:
1067 sal_Int32 n = pVar->GetLong();
1068 if( n >= -128 && n <= 127 )
1069 aType = ::cppu::UnoType<sal_Int8>::get();
1070 else if( n >= SbxMININT && n <= SbxMAXINT )
1071 aType = ::cppu::UnoType<sal_Int16>::get();
1072 break;
1074 case TypeClass_UNSIGNED_SHORT:
1076 sal_uInt16 n = pVar->GetUShort();
1077 if( n <= 255 )
1078 aType = cppu::UnoType<sal_uInt8>::get();
1079 break;
1081 case TypeClass_UNSIGNED_LONG:
1083 sal_uInt32 n = pVar->GetLong();
1084 if( n <= 255 )
1085 aType = cppu::UnoType<sal_uInt8>::get();
1086 else if( n <= SbxMAXUINT )
1087 aType = cppu::UnoType<cppu::UnoUnsignedShortType>::get();
1088 break;
1090 // TODO: need to add hyper types ?
1091 default: break;
1095 return sbxToUnoValue( pVar, aType );
1100 // Helper function for StepREDIMP
1101 static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray,
1102 const Type& aElemType, short nMaxDimIndex, short nActualDim,
1103 sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
1105 sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1;
1106 OUStringBuffer aSeqTypeName;
1107 sal_Int32 i;
1108 for( i = 0 ; i < nSeqLevel ; i++ )
1110 aSeqTypeName.appendAscii(aSeqLevelStr);
1112 aSeqTypeName.append(aElemType.getTypeName());
1113 Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
1115 // Create Sequence instance
1116 Any aRetVal;
1117 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType );
1118 xIdlTargetClass->createObject( aRetVal );
1120 // Alloc sequence according to array bounds
1121 sal_Int32 nUpper = pUpperBounds[nActualDim];
1122 sal_Int32 nLower = pLowerBounds[nActualDim];
1123 sal_Int32 nSeqSize = nUpper - nLower + 1;
1124 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1125 xArray->realloc( aRetVal, nSeqSize );
1127 sal_Int32& ri = pActualIndices[nActualDim];
1129 for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ )
1131 Any aElementVal;
1133 if( nActualDim < nMaxDimIndex )
1135 aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1136 nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds );
1138 else
1140 SbxVariable* pSource = pArray->Get32( pActualIndices );
1141 aElementVal = sbxToUnoValue( pSource, aElemType );
1146 // transfer to the sequence
1147 xArray->set( aRetVal, i, aElementVal );
1149 catch( const IllegalArgumentException& )
1151 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1152 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1154 catch (const IndexOutOfBoundsException&)
1156 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1159 return aRetVal;
1162 // Map old interface
1163 Any sbxToUnoValue( const SbxValue* pVar )
1165 return sbxToUnoValueImpl( pVar );
1168 // function to find a global identifier in
1169 // the UnoScope and to wrap it for Sbx
1170 static bool implGetTypeByName( const OUString& rName, Type& rRetType )
1172 bool bSuccess = false;
1174 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
1175 if( xTypeAccess->hasByHierarchicalName( rName ) )
1177 Any aRet = xTypeAccess->getByHierarchicalName( rName );
1178 Reference< XTypeDescription > xTypeDesc;
1179 aRet >>= xTypeDesc;
1181 if( xTypeDesc.is() )
1183 rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() );
1184 bSuccess = true;
1187 return bSuccess;
1191 // converting of Sbx to Uno with known target class
1192 Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property* pUnoProperty )
1194 Any aRetVal;
1196 // #94560 No conversion of empty/void for MAYBE_VOID properties
1197 if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID )
1199 if( pVar->IsEmpty() )
1200 return aRetVal;
1203 SbxDataType eBaseType = pVar->SbxValue::GetType();
1204 if( eBaseType == SbxOBJECT )
1206 SbxBaseRef xObj = pVar->GetObject();
1207 if( xObj.Is() && xObj->ISA(SbUnoAnyObject) )
1209 return static_cast<SbUnoAnyObject*>((SbxBase*)xObj)->getValue();
1213 TypeClass eType = rType.getTypeClass();
1214 switch( eType )
1216 case TypeClass_INTERFACE:
1217 case TypeClass_STRUCT:
1218 case TypeClass_EXCEPTION:
1220 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1222 // null reference?
1223 if( pVar->IsNull() && eType == TypeClass_INTERFACE )
1225 Reference< XInterface > xRef;
1226 OUString aClassName = xIdlTargetClass->getName();
1227 Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() );
1228 aRetVal.setValue( &xRef, aClassType );
1230 else
1232 // #112368 Special conversion for Decimal, Currency and Date
1233 if( eType == TypeClass_STRUCT )
1235 SbiInstance* pInst = GetSbData()->pInst;
1236 if( pInst && pInst->IsCompatibility() )
1238 if( rType == cppu::UnoType<oleautomation::Decimal>::get())
1240 oleautomation::Decimal aDecimal;
1241 pVar->fillAutomationDecimal( aDecimal );
1242 aRetVal <<= aDecimal;
1243 break;
1245 else if( rType == cppu::UnoType<oleautomation::Currency>::get())
1247 // assumes per previous code that ole Currency is Int64
1248 aRetVal <<= (sal_Int64)( pVar->GetInt64() );
1249 break;
1251 else if( rType == cppu::UnoType<oleautomation::Date>::get())
1253 oleautomation::Date aDate;
1254 aDate.Value = pVar->GetDate();
1255 aRetVal <<= aDate;
1256 break;
1261 SbxBaseRef pObj = pVar->GetObject();
1262 if( pObj && pObj->ISA(SbUnoObject) )
1264 aRetVal = static_cast<SbUnoObject*>((SbxBase*)pObj)->getUnoAny();
1266 else if( pObj && pObj->ISA(SbUnoStructRefObject) )
1268 aRetVal = static_cast<SbUnoStructRefObject*>((SbxBase*)pObj)->getUnoAny();
1270 else
1272 // null object -> null XInterface
1273 Reference<XInterface> xInt;
1274 aRetVal <<= xInt;
1278 break;
1280 case TypeClass_TYPE:
1282 if( eBaseType == SbxOBJECT )
1284 // XIdlClass?
1285 Reference< XIdlClass > xIdlClass;
1287 SbxBaseRef pObj = pVar->GetObject();
1288 if( pObj && pObj->ISA(SbUnoObject) )
1290 Any aUnoAny = static_cast<SbUnoObject*>((SbxBase*)pObj)->getUnoAny();
1291 aUnoAny >>= xIdlClass;
1294 if( xIdlClass.is() )
1296 OUString aClassName = xIdlClass->getName();
1297 Type aType( xIdlClass->getTypeClass(), aClassName.getStr() );
1298 aRetVal <<= aType;
1301 else if( eBaseType == SbxSTRING )
1303 OUString aTypeName = pVar->GetOUString();
1304 Type aType;
1305 bool bSuccess = implGetTypeByName( aTypeName, aType );
1306 if( bSuccess )
1308 aRetVal <<= aType;
1312 break;
1315 case TypeClass_ENUM:
1317 aRetVal = int2enum( pVar->GetLong(), rType );
1319 break;
1321 case TypeClass_SEQUENCE:
1323 SbxBaseRef xObj = pVar->GetObject();
1324 if( xObj && xObj->ISA(SbxDimArray) )
1326 SbxBase* pObj = static_cast<SbxBase*>(xObj);
1327 SbxDimArray* pArray = static_cast<SbxDimArray*>(pObj);
1329 short nDims = pArray->GetDims();
1331 // Normal case: One dimensional array
1332 sal_Int32 nLower, nUpper;
1333 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
1335 sal_Int32 nSeqSize = nUpper - nLower + 1;
1337 // create the instance of the required sequence
1338 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1339 xIdlTargetClass->createObject( aRetVal );
1340 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1341 xArray->realloc( aRetVal, nSeqSize );
1343 // Element-Type
1344 OUString aClassName = xIdlTargetClass->getName();
1345 typelib_TypeDescription * pSeqTD = 0;
1346 typelib_typedescription_getByName( &pSeqTD, aClassName.pData );
1347 OSL_ASSERT( pSeqTD );
1348 Type aElemType( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType );
1350 // convert all array member and register them
1351 sal_Int32 nIdx = nLower;
1352 for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ )
1354 // coverity[callee_ptr_arith]
1355 SbxVariableRef xVar = pArray->Get32( &nIdx );
1357 // Convert the value of Sbx to Uno
1358 Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType );
1362 // insert in the sequence
1363 xArray->set( aRetVal, i, aAnyValue );
1365 catch( const IllegalArgumentException& )
1367 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1368 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1370 catch (const IndexOutOfBoundsException&)
1372 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1376 // #i33795 Map also multi dimensional arrays to corresponding sequences
1377 else if( nDims > 1 )
1379 // Element-Type
1380 typelib_TypeDescription * pSeqTD = 0;
1381 Type aCurType( rType );
1382 sal_Int32 nSeqLevel = 0;
1383 Type aElemType;
1386 OUString aTypeName = aCurType.getTypeName();
1387 typelib_typedescription_getByName( &pSeqTD, aTypeName.pData );
1388 OSL_ASSERT( pSeqTD );
1389 if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE )
1391 aCurType = Type( reinterpret_cast<typelib_IndirectTypeDescription *>(pSeqTD)->pType );
1392 nSeqLevel++;
1394 else
1396 aElemType = aCurType;
1397 break;
1400 while( true );
1402 if( nSeqLevel == nDims )
1404 boost::scoped_array<sal_Int32> pLowerBounds(new sal_Int32[nDims]);
1405 boost::scoped_array<sal_Int32> pUpperBounds(new sal_Int32[nDims]);
1406 boost::scoped_array<sal_Int32> pActualIndices(new sal_Int32[nDims]);
1407 for( short i = 1 ; i <= nDims ; i++ )
1409 sal_Int32 lBound, uBound;
1410 pArray->GetDim32( i, lBound, uBound );
1412 short j = i - 1;
1413 pActualIndices[j] = pLowerBounds[j] = lBound;
1414 pUpperBounds[j] = uBound;
1417 aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1418 nDims - 1, 0, pActualIndices.get(), pLowerBounds.get(), pUpperBounds.get() );
1423 break;
1426 // for Any use the class independent converting routine
1427 case TypeClass_ANY:
1429 aRetVal = sbxToUnoValueImpl( pVar );
1431 break;
1433 case TypeClass_BOOLEAN:
1435 sal_Bool b = pVar->GetBool();
1436 aRetVal.setValue( &b, cppu::UnoType<bool>::get() );
1437 break;
1439 case TypeClass_CHAR:
1441 sal_Unicode c = pVar->GetChar();
1442 aRetVal.setValue( &c , cppu::UnoType<cppu::UnoCharType>::get() );
1443 break;
1445 case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break;
1446 case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break;
1447 case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break;
1449 case TypeClass_BYTE:
1451 sal_Int16 nVal = pVar->GetInteger();
1452 bool bOverflow = false;
1453 if( nVal < -128 )
1455 bOverflow = true;
1456 nVal = -128;
1458 else if( nVal > 127 )
1460 bOverflow = true;
1461 nVal = 127;
1463 if( bOverflow )
1464 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
1466 sal_Int8 nByteVal = (sal_Int8)nVal;
1467 aRetVal <<= nByteVal;
1468 break;
1470 case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break;
1471 case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break;
1472 case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break;
1473 case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break;
1474 case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break;
1475 case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break;
1476 default: break;
1479 return aRetVal;
1482 void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, bool bOLEAutomation, sal_uInt32 nParamCount )
1484 AutomationNamedArgsSbxArray* pArgNamesArray = NULL;
1485 if( bOLEAutomation )
1486 pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams);
1488 args.realloc( nParamCount );
1489 Any* pAnyArgs = args.getArray();
1490 bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility();
1491 sal_uInt32 i = 0;
1492 if( pArgNamesArray )
1494 Sequence< OUString >& rNameSeq = pArgNamesArray->getNames();
1495 OUString* pNames = rNameSeq.getArray();
1496 Any aValAny;
1497 for( i = 0 ; i < nParamCount ; i++ )
1499 sal_uInt16 iSbx = (sal_uInt16)(i+1);
1501 aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ),
1502 bBlockConversionToSmallestType );
1504 OUString aParamName = pNames[iSbx];
1505 if( !aParamName.isEmpty() )
1507 oleautomation::NamedArgument aNamedArgument;
1508 aNamedArgument.Name = aParamName;
1509 aNamedArgument.Value = aValAny;
1510 pAnyArgs[i] <<= aNamedArgument;
1512 else
1514 pAnyArgs[i] = aValAny;
1518 else
1520 for( i = 0 ; i < nParamCount ; i++ )
1522 pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (sal_uInt16)(i+1) ),
1523 bBlockConversionToSmallestType );
1528 enum INVOKETYPE
1530 GetProp = 0,
1531 SetProp,
1532 Func
1534 Any invokeAutomationMethod( const OUString& Name, Sequence< Any >& args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation >& rxInvocation, INVOKETYPE invokeType = Func )
1536 Sequence< sal_Int16 > OutParamIndex;
1537 Sequence< Any > OutParam;
1539 Any aRetAny;
1540 switch( invokeType )
1542 case Func:
1543 aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam );
1544 break;
1545 case GetProp:
1547 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY );
1548 aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam );
1549 break;
1551 case SetProp:
1553 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY_THROW );
1554 aRetAny = xAutoInv->invokePutProperty( Name, args, OutParamIndex, OutParam );
1555 break;
1557 default:
1558 break; // should introduce an error here
1561 const sal_Int16* pIndices = OutParamIndex.getConstArray();
1562 sal_uInt32 nLen = OutParamIndex.getLength();
1563 if( nLen )
1565 const Any* pNewValues = OutParam.getConstArray();
1566 for( sal_uInt32 j = 0 ; j < nLen ; j++ )
1568 sal_Int16 iTarget = pIndices[ j ];
1569 if( iTarget >= (sal_Int16)nParamCount )
1570 break;
1571 unoToSbxValue( pParams->Get( (sal_uInt16)(j+1) ), pNewValues[ j ] );
1574 return aRetAny;
1577 // Debugging help method to readout the imlemented interfaces of an object
1578 OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel )
1580 Type aIfaceType = cppu::UnoType<XInterface>::get();
1581 static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType );
1583 OUStringBuffer aRetStr;
1584 for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ )
1585 aRetStr.appendAscii( " " );
1586 aRetStr.append( xClass->getName() );
1587 OUString aClassName = xClass->getName();
1588 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
1590 // checking if the interface is really supported
1591 if( !x->queryInterface( aClassType ).hasValue() )
1593 aRetStr.appendAscii( " (ERROR: Not really supported!)\n" );
1595 // Are there super interfaces?
1596 else
1598 aRetStr.appendAscii( "\n" );
1600 // get the super interfaces
1601 Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses();
1602 const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray();
1603 sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength();
1604 for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ )
1606 const Reference< XIdlClass >& rxIfaceClass = pClasses[j];
1607 if( !rxIfaceClass->equals( xIfaceClass ) )
1608 aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) );
1611 return aRetStr.makeStringAndClear();
1614 OUString getDbgObjectNameImpl( SbUnoObject* pUnoObj )
1616 OUString aName;
1617 if( pUnoObj )
1619 aName = pUnoObj->GetClassName();
1620 if( aName.isEmpty() )
1622 Any aToInspectObj = pUnoObj->getUnoAny();
1623 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1624 Reference< XInterface > xObj;
1625 if( eType == TypeClass_INTERFACE )
1626 xObj = *static_cast<Reference< XInterface > const *>(aToInspectObj.getValue());
1627 if( xObj.is() )
1629 Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY );
1630 if( xServiceInfo.is() )
1631 aName = xServiceInfo->getImplementationName();
1635 return aName;
1638 OUString getDbgObjectName( SbUnoObject* pUnoObj )
1640 OUString aName = getDbgObjectNameImpl( pUnoObj );
1641 if( aName.isEmpty() )
1642 aName += "Unknown";
1644 OUStringBuffer aRet;
1645 if( aName.getLength() > 20 )
1647 aRet.appendAscii( "\n" );
1649 aRet.appendAscii( "\"" );
1650 aRet.append( aName );
1651 aRet.appendAscii( "\":" );
1652 return aRet.makeStringAndClear();
1655 OUString getBasicObjectTypeName( SbxObject* pObj )
1657 OUString aName;
1658 if( pObj )
1660 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
1661 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
1662 if( pUnoObj )
1663 aName = getDbgObjectNameImpl( pUnoObj );
1664 else if ( pUnoStructObj )
1665 aName = pUnoStructObj->GetClassName();
1667 return aName;
1670 bool checkUnoObjectType( SbUnoObject* pUnoObj, const OUString& rClass )
1672 Any aToInspectObj = pUnoObj->getUnoAny();
1673 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1674 if( eType != TypeClass_INTERFACE )
1676 return false;
1678 const Reference< XInterface > x = *static_cast<Reference< XInterface > const *>(aToInspectObj.getValue());
1680 // Return true for XInvocation based objects as interface type names don't count then
1681 Reference< XInvocation > xInvocation( x, UNO_QUERY );
1682 if( xInvocation.is() )
1684 return true;
1686 bool result = false;
1687 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1688 if( xTypeProvider.is() )
1690 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1691 have a leading 'X', in Basic we want to be able to do something
1692 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1693 add a leading 'X' to the class name and a leading dot to the entire
1694 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1695 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1696 'ooo.vba.msforms.XLabel'.
1698 OUString aClassName;
1699 if ( SbiRuntime::isVBAEnabled() )
1701 aClassName = ".";
1702 sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' );
1703 if( nClassNameDot >= 0 )
1705 aClassName += rClass.copy( 0, nClassNameDot + 1 ) + "X" + rClass.copy( nClassNameDot + 1 );
1707 else
1709 aClassName += "X" + rClass;
1712 else // assume extended type declaration support for basic ( can't get here
1713 // otherwise.
1714 aClassName = rClass;
1716 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1717 const Type* pTypeArray = aTypeSeq.getConstArray();
1718 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1719 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1721 const Type& rType = pTypeArray[j];
1723 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1724 if( !xClass.is() )
1726 OSL_FAIL("failed to get XIdlClass for type");
1727 break;
1729 OUString aInterfaceName = xClass->getName();
1730 if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" )
1732 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1733 // matches
1734 Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY );
1735 if ( xInv.is() )
1737 OUString sTypeName;
1738 xInv->getValue( OUString( "$GetTypeName" ) ) >>= sTypeName;
1739 if ( sTypeName.isEmpty() || sTypeName == "IDispatch" )
1741 // can't check type, leave it pass
1742 result = true;
1744 else
1746 result = sTypeName.equals( rClass );
1749 break; // finished checking automation object
1752 // match interface name with passed class name
1753 OSL_TRACE("Checking if object implements %s", OUStringToOString( aClassName, RTL_TEXTENCODING_UTF8 ).getStr() );
1754 if ( (aClassName.getLength() <= aInterfaceName.getLength()) &&
1755 aInterfaceName.endsWithIgnoreAsciiCase( aClassName ) )
1757 result = true;
1758 break;
1762 return result;
1765 // Debugging help method to readout the imlemented interfaces of an object
1766 OUString Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj )
1768 Any aToInspectObj = pUnoObj->getUnoAny();
1770 // allow only TypeClass interface
1771 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1772 OUStringBuffer aRet;
1773 if( eType != TypeClass_INTERFACE )
1775 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
1776 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1778 else
1780 // get the interface from the Any
1781 const Reference< XInterface > x = *static_cast<Reference< XInterface > const *>(aToInspectObj.getValue());
1783 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1785 aRet.appendAscii( "Supported interfaces by object " );
1786 aRet.append( getDbgObjectName( pUnoObj ) );
1787 aRet.appendAscii( "\n" );
1788 if( xTypeProvider.is() )
1790 // get the interfaces of the implementation
1791 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1792 const Type* pTypeArray = aTypeSeq.getConstArray();
1793 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1794 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1796 const Type& rType = pTypeArray[j];
1798 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1799 if( xClass.is() )
1801 aRet.append( Impl_GetInterfaceInfo( x, xClass, 1 ) );
1803 else
1805 typelib_TypeDescription * pTD = 0;
1806 rType.getDescription( &pTD );
1808 aRet.appendAscii( "*** ERROR: No IdlClass for type \"" );
1809 aRet.append( pTD->pTypeName );
1810 aRet.appendAscii( "\"\n*** Please check type library\n" );
1815 return aRet.makeStringAndClear();
1820 // Debugging help method SbxDataType -> String
1821 OUString Dbg_SbxDataType2String( SbxDataType eType )
1823 OUStringBuffer aRet;
1824 switch( +eType )
1826 case SbxEMPTY: aRet.appendAscii("SbxEMPTY"); break;
1827 case SbxNULL: aRet.appendAscii("SbxNULL"); break;
1828 case SbxINTEGER: aRet.appendAscii("SbxINTEGER"); break;
1829 case SbxLONG: aRet.appendAscii("SbxLONG"); break;
1830 case SbxSINGLE: aRet.appendAscii("SbxSINGLE"); break;
1831 case SbxDOUBLE: aRet.appendAscii("SbxDOUBLE"); break;
1832 case SbxCURRENCY: aRet.appendAscii("SbxCURRENCY"); break;
1833 case SbxDECIMAL: aRet.appendAscii("SbxDECIMAL"); break;
1834 case SbxDATE: aRet.appendAscii("SbxDATE"); break;
1835 case SbxSTRING: aRet.appendAscii("SbxSTRING"); break;
1836 case SbxOBJECT: aRet.appendAscii("SbxOBJECT"); break;
1837 case SbxERROR: aRet.appendAscii("SbxERROR"); break;
1838 case SbxBOOL: aRet.appendAscii("SbxBOOL"); break;
1839 case SbxVARIANT: aRet.appendAscii("SbxVARIANT"); break;
1840 case SbxDATAOBJECT: aRet.appendAscii("SbxDATAOBJECT"); break;
1841 case SbxCHAR: aRet.appendAscii("SbxCHAR"); break;
1842 case SbxBYTE: aRet.appendAscii("SbxBYTE"); break;
1843 case SbxUSHORT: aRet.appendAscii("SbxUSHORT"); break;
1844 case SbxULONG: aRet.appendAscii("SbxULONG"); break;
1845 case SbxSALINT64: aRet.appendAscii("SbxINT64"); break;
1846 case SbxSALUINT64: aRet.appendAscii("SbxUINT64"); break;
1847 case SbxINT: aRet.appendAscii("SbxINT"); break;
1848 case SbxUINT: aRet.appendAscii("SbxUINT"); break;
1849 case SbxVOID: aRet.appendAscii("SbxVOID"); break;
1850 case SbxHRESULT: aRet.appendAscii("SbxHRESULT"); break;
1851 case SbxPOINTER: aRet.appendAscii("SbxPOINTER"); break;
1852 case SbxDIMARRAY: aRet.appendAscii("SbxDIMARRAY"); break;
1853 case SbxCARRAY: aRet.appendAscii("SbxCARRAY"); break;
1854 case SbxUSERDEF: aRet.appendAscii("SbxUSERDEF"); break;
1855 case SbxLPSTR: aRet.appendAscii("SbxLPSTR"); break;
1856 case SbxLPWSTR: aRet.appendAscii("SbxLPWSTR"); break;
1857 case SbxCoreSTRING: aRet.appendAscii("SbxCoreSTRING"); break;
1858 case SbxOBJECT | SbxARRAY: aRet.appendAscii("SbxARRAY"); break;
1859 default: aRet.appendAscii("Unknown Sbx-Type!");break;
1861 return aRet.makeStringAndClear();
1864 // Debugging help method to display the properties of a SbUnoObjects
1865 OUString Impl_DumpProperties( SbUnoObject* pUnoObj )
1867 OUStringBuffer aRet;
1868 aRet.appendAscii("Properties of object ");
1869 aRet.append( getDbgObjectName( pUnoObj ) );
1871 // analyse the Uno-Infos to recognise the arrays
1872 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1873 if( !xAccess.is() )
1875 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1876 if( xInvok.is() )
1877 xAccess = xInvok->getIntrospection();
1879 if( !xAccess.is() )
1881 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1882 return aRet.makeStringAndClear();
1885 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
1886 sal_uInt32 nUnoPropCount = props.getLength();
1887 const Property* pUnoProps = props.getConstArray();
1889 SbxArray* pProps = pUnoObj->GetProperties();
1890 sal_uInt16 nPropCount = pProps->Count();
1891 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
1892 for( sal_uInt16 i = 0; i < nPropCount; i++ )
1894 SbxVariable* pVar = pProps->Get( i );
1895 if( pVar )
1897 OUStringBuffer aPropStr;
1898 if( (i % nPropsPerLine) == 0 )
1899 aPropStr.appendAscii( "\n" );
1901 // output the type and name
1902 // Is it in Uno a sequence?
1903 SbxDataType eType = pVar->GetFullType();
1905 bool bMaybeVoid = false;
1906 if( i < nUnoPropCount )
1908 const Property& rProp = pUnoProps[ i ];
1910 // For MAYBEVOID freshly convert the type from Uno,
1911 // so not just SbxEMPTY is returned.
1912 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
1914 eType = unoToSbxType( rProp.Type.getTypeClass() );
1915 bMaybeVoid = true;
1917 if( eType == SbxOBJECT )
1919 Type aType = rProp.Type;
1920 if( aType.getTypeClass() == TypeClass_SEQUENCE )
1921 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
1924 aPropStr.append( Dbg_SbxDataType2String( eType ) );
1925 if( bMaybeVoid )
1926 aPropStr.appendAscii( "/void" );
1927 aPropStr.appendAscii( " " );
1928 aPropStr.append( pVar->GetName() );
1930 if( i == nPropCount - 1 )
1931 aPropStr.appendAscii( "\n" );
1932 else
1933 aPropStr.appendAscii( "; " );
1935 aRet.append( aPropStr.makeStringAndClear() );
1938 return aRet.makeStringAndClear();
1941 // Debugging help method to display the methods of an SbUnoObjects
1942 OUString Impl_DumpMethods( SbUnoObject* pUnoObj )
1944 OUStringBuffer aRet;
1945 aRet.appendAscii("Methods of object ");
1946 aRet.append( getDbgObjectName( pUnoObj ) );
1948 // XIntrospectionAccess, so that the types of the parameter could be outputed
1949 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1950 if( !xAccess.is() )
1952 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1953 if( xInvok.is() )
1954 xAccess = xInvok->getIntrospection();
1956 if( !xAccess.is() )
1958 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1959 return aRet.makeStringAndClear();
1961 Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods
1962 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
1963 const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray();
1965 SbxArray* pMethods = pUnoObj->GetMethods();
1966 sal_uInt16 nMethodCount = pMethods->Count();
1967 if( !nMethodCount )
1969 aRet.appendAscii( "\nNo methods found\n" );
1970 return aRet.makeStringAndClear();
1972 sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30;
1973 for( sal_uInt16 i = 0; i < nMethodCount; i++ )
1975 SbxVariable* pVar = pMethods->Get( i );
1976 if( pVar )
1978 if( (i % nPropsPerLine) == 0 )
1979 aRet.appendAscii( "\n" );
1981 // address the method
1982 const Reference< XIdlMethod >& rxMethod = pUnoMethods[i];
1984 // Is it in Uno a sequence?
1985 SbxDataType eType = pVar->GetFullType();
1986 if( eType == SbxOBJECT )
1988 Reference< XIdlClass > xClass = rxMethod->getReturnType();
1989 if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE )
1990 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
1992 // output the name and the type
1993 aRet.append( Dbg_SbxDataType2String( eType ) );
1994 aRet.appendAscii( " " );
1995 aRet.append ( pVar->GetName() );
1996 aRet.appendAscii( " ( " );
1998 // the get-method mustn't have a parameter
1999 Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes();
2000 sal_uInt32 nParamCount = aParamsSeq.getLength();
2001 const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray();
2003 if( nParamCount > 0 )
2005 for( sal_uInt16 j = 0; j < nParamCount; j++ )
2007 aRet.append ( Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ) );
2008 if( j < nParamCount - 1 )
2009 aRet.appendAscii( ", " );
2012 else
2013 aRet.appendAscii( "void" );
2015 aRet.appendAscii( " ) " );
2017 if( i == nMethodCount - 1 )
2018 aRet.appendAscii( "\n" );
2019 else
2020 aRet.appendAscii( "; " );
2023 return aRet.makeStringAndClear();
2026 TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray)
2028 // Implementation SbUnoObject
2029 void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
2030 const SfxHint& rHint, const TypeId& rHintType )
2032 if( bNeedIntrospection )
2033 doIntrospection();
2035 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint);
2036 if( pHint )
2038 SbxVariable* pVar = pHint->GetVar();
2039 SbxArray* pParams = pVar->GetParameters();
2040 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
2041 SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar);
2042 if( pProp )
2044 bool bInvocation = pProp->isInvocationBased();
2045 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2047 // Test-Properties
2048 sal_Int32 nId = pProp->nId;
2049 if( nId < 0 )
2051 // Id == -1: Display implemented interfaces according the ClassProvider
2052 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2054 OUString aRetStr = Impl_GetSupportedInterfaces( this );
2055 pVar->PutString( aRetStr );
2057 // Id == -2: output properties
2058 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
2060 // now all properties must be created
2061 implCreateAll();
2062 OUString aRetStr = Impl_DumpProperties( this );
2063 pVar->PutString( aRetStr );
2065 // Id == -3: output the methods
2066 else if( nId == -3 ) // Property ID_DBG_METHODS
2068 // now all properties must be created
2069 implCreateAll();
2070 OUString aRetStr = Impl_DumpMethods( this );
2071 pVar->PutString( aRetStr );
2073 return;
2076 if( !bInvocation && mxUnoAccess.is() )
2080 if ( maStructInfo.get() )
2082 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2083 if ( aMember.isEmpty() )
2085 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2087 else
2089 if ( pProp->isUnoStruct() )
2091 SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMember );
2092 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
2093 pVar->PutObject( xWrapper );
2095 else
2097 Any aRetAny = aMember.getValue();
2098 // take over the value from Uno to Sbx
2099 unoToSbxValue( pVar, aRetAny );
2101 return;
2104 // get the value
2105 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY );
2106 Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() );
2107 // The use of getPropertyValue (instead of using the index) is
2108 // suboptimal, but the refactoring to XInvocation is already pending
2109 // Otherwise it is possible to use FastPropertySet
2111 // take over the value from Uno to Sbx
2112 unoToSbxValue( pVar, aRetAny );
2114 catch( const Exception& )
2116 implHandleAnyException( ::cppu::getCaughtException() );
2119 else if( bInvocation && mxInvocation.is() )
2123 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2124 bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() );
2125 Any aRetAny;
2126 if ( bCanBeConsideredAMethod && nParamCount )
2128 // Automation properties have methods, so.. we need to invoke this through
2129 // XInvocation
2130 Sequence<Any> args;
2131 processAutomationParams( pParams, args, true, nParamCount );
2132 aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, GetProp );
2134 else
2135 aRetAny = mxInvocation->getValue( pProp->GetName() );
2136 // take over the value from Uno to Sbx
2137 unoToSbxValue( pVar, aRetAny );
2138 if( pParams && bCanBeConsideredAMethod )
2139 pVar->SetParameters( NULL );
2142 catch( const Exception& )
2144 implHandleAnyException( ::cppu::getCaughtException() );
2148 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
2150 if( !bInvocation && mxUnoAccess.is() )
2152 if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY )
2154 StarBASIC::Error( SbERR_PROP_READONLY );
2155 return;
2157 if ( maStructInfo.get() )
2159 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2160 if ( aMember.isEmpty() )
2162 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2164 else
2166 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2167 aMember.setValue( aAnyValue );
2169 return;
2171 // take over the value from Uno to Sbx
2172 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2175 // set the value
2176 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY );
2177 xPropSet->setPropertyValue( pProp->GetName(), aAnyValue );
2178 // The use of getPropertyValue (instead of using the index) is
2179 // suboptimal, but the refactoring to XInvocation is already pending
2180 // Otherwise it is possible to use FastPropertySet
2182 catch( const Exception& )
2184 implHandleAnyException( ::cppu::getCaughtException() );
2187 else if( bInvocation && mxInvocation.is() )
2189 // take over the value from Uno to Sbx
2190 Any aAnyValue = sbxToUnoValueImpl( pVar );
2193 // set the value
2194 mxInvocation->setValue( pProp->GetName(), aAnyValue );
2196 catch( const Exception& )
2198 implHandleAnyException( ::cppu::getCaughtException() );
2203 else if( pMeth )
2205 bool bInvocation = pMeth->isInvocationBased();
2206 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2208 // number of Parameter -1 because of Param0 == this
2209 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2210 Sequence<Any> args;
2211 bool bOutParams = false;
2212 sal_uInt32 i;
2214 if( !bInvocation && mxUnoAccess.is() )
2216 // get info
2217 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2218 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2219 sal_uInt32 nUnoParamCount = rInfoSeq.getLength();
2220 sal_uInt32 nAllocParamCount = nParamCount;
2222 // ignore surplus parameter; alternative: throw an error
2223 if( nParamCount > nUnoParamCount )
2225 nParamCount = nUnoParamCount;
2226 nAllocParamCount = nParamCount;
2228 else if( nParamCount < nUnoParamCount )
2230 SbiInstance* pInst = GetSbData()->pInst;
2231 if( pInst && pInst->IsCompatibility() )
2233 // Check types
2234 bool bError = false;
2235 for( i = nParamCount ; i < nUnoParamCount ; i++ )
2237 const ParamInfo& rInfo = pParamInfos[i];
2238 const Reference< XIdlClass >& rxClass = rInfo.aType;
2239 if( rxClass->getTypeClass() != TypeClass_ANY )
2241 bError = true;
2242 StarBASIC::Error( SbERR_NOT_OPTIONAL );
2245 if( !bError )
2246 nAllocParamCount = nUnoParamCount;
2250 if( nAllocParamCount > 0 )
2252 args.realloc( nAllocParamCount );
2253 Any* pAnyArgs = args.getArray();
2254 for( i = 0 ; i < nParamCount ; i++ )
2256 const ParamInfo& rInfo = pParamInfos[i];
2257 const Reference< XIdlClass >& rxClass = rInfo.aType;
2259 com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() );
2261 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2262 pAnyArgs[i] = sbxToUnoValue( pParams->Get( (sal_uInt16)(i+1) ), aType );
2264 // If it is not certain check whether the out-parameter are available.
2265 if( !bOutParams )
2267 ParamMode aParamMode = rInfo.aMode;
2268 if( aParamMode != ParamMode_IN )
2269 bOutParams = true;
2274 else if( bInvocation && pParams && mxInvocation.is() )
2276 bool bOLEAutomation = true;
2277 processAutomationParams( pParams, args, bOLEAutomation, nParamCount );
2280 // call the method
2281 GetSbData()->bBlockCompilerError = true; // #106433 Block compiler errors for API calls
2284 if( !bInvocation && mxUnoAccess.is() )
2286 Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args );
2288 // take over the value from Uno to Sbx
2289 unoToSbxValue( pVar, aRetAny );
2291 // Did we to copy back the Out-Parameter?
2292 if( bOutParams )
2294 const Any* pAnyArgs = args.getConstArray();
2296 // get info
2297 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2298 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2300 sal_uInt32 j;
2301 for( j = 0 ; j < nParamCount ; j++ )
2303 const ParamInfo& rInfo = pParamInfos[j];
2304 ParamMode aParamMode = rInfo.aMode;
2305 if( aParamMode != ParamMode_IN )
2306 unoToSbxValue( pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
2310 else if( bInvocation && mxInvocation.is() )
2312 Any aRetAny = invokeAutomationMethod( pMeth->GetName(), args, pParams, nParamCount, mxInvocation );
2313 unoToSbxValue( pVar, aRetAny );
2316 // remove parameter here, because this was not done anymore in unoToSbxValue()
2317 // for arrays
2318 if( pParams )
2319 pVar->SetParameters( NULL );
2321 catch( const Exception& )
2323 implHandleAnyException( ::cppu::getCaughtException() );
2325 GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors
2328 else
2329 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
2334 SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ )
2335 : SbxObject( aName_ )
2336 , bNeedIntrospection( true )
2337 , bNativeCOMObject( false )
2339 static Reference< XIntrospection > xIntrospection;
2341 // beat out again the default properties of Sbx
2342 Remove( OUString("Name"), SbxCLASS_DONTCARE );
2343 Remove( OUString("Parent"), SbxCLASS_DONTCARE );
2345 // check the type of the ojekts
2346 TypeClass eType = aUnoObj_.getValueType().getTypeClass();
2347 Reference< XInterface > x;
2348 if( eType == TypeClass_INTERFACE )
2350 // get the interface from the Any
2351 x = *static_cast<Reference< XInterface > const *>(aUnoObj_.getValue());
2352 if( !x.is() )
2353 return;
2356 Reference< XTypeProvider > xTypeProvider;
2357 // Did the object have an invocation itself?
2358 mxInvocation = Reference< XInvocation >( x, UNO_QUERY );
2360 xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY );
2362 if( mxInvocation.is() )
2365 // get the ExactName
2366 mxExactNameInvocation = Reference< XExactName >::query( mxInvocation );
2368 // The remainder refers only to the introspection
2369 if( !xTypeProvider.is() )
2371 bNeedIntrospection = false;
2372 return;
2375 // Ignore introspection based members for COM objects to avoid
2376 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2377 Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY );
2378 if( xAutomationObject.is() )
2379 bNativeCOMObject = true;
2382 maTmpUnoObj = aUnoObj_;
2385 //*** Define the name ***
2386 bool bFatalError = true;
2388 // Is it an interface or a struct?
2389 bool bSetClassName = false;
2390 OUString aClassName_;
2391 if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
2393 // Struct is Ok
2394 bFatalError = false;
2396 // insert the real name of the class
2397 if( aName_.isEmpty() )
2399 aClassName_ = aUnoObj_.getValueType().getTypeName();
2400 bSetClassName = true;
2402 StructRefInfo aThisStruct( maTmpUnoObj, maTmpUnoObj.getValueType(), 0 );
2403 maStructInfo.reset( new SbUnoStructRefObject( GetName(), aThisStruct ) );
2405 else if( eType == TypeClass_INTERFACE )
2407 // Interface works always through the type in the Any
2408 bFatalError = false;
2410 if( bSetClassName )
2411 SetClassName( aClassName_ );
2413 // Neither interface nor Struct -> FatalError
2414 if( bFatalError )
2416 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2417 return;
2420 // pass the introspection primal on demand
2423 SbUnoObject::~SbUnoObject()
2428 // pass the introspection on Demand
2429 void SbUnoObject::doIntrospection()
2431 if( !bNeedIntrospection )
2432 return;
2434 Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
2436 if (!xContext.is())
2437 return;
2440 // get the introspection service
2441 Reference<XIntrospection> xIntrospection;
2445 xIntrospection = theIntrospection::get(xContext);
2447 catch ( const css::uno::DeploymentException& )
2451 if (!xIntrospection.is())
2452 return;
2454 bNeedIntrospection = false;
2456 // pass the introspection
2459 mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
2461 catch( const RuntimeException& e )
2463 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2466 if( !mxUnoAccess.is() )
2468 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2469 return;
2472 // get MaterialHolder from access
2473 mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess );
2475 // get ExactName from access
2476 mxExactName = Reference< XExactName >::query( mxUnoAccess );
2482 // Start of a list of all SbUnoMethod-Instances
2483 static SbUnoMethod* pFirst = NULL;
2485 void clearUnoMethodsForBasic( StarBASIC* pBasic )
2487 SbUnoMethod* pMeth = pFirst;
2488 while( pMeth )
2490 SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() );
2491 if ( pObject )
2493 StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() );
2494 if ( pModBasic == pBasic )
2496 // for now the solution is to remove the method from the list and to clear it,
2497 // but in case the element should be correctly transferred to another StarBASIC,
2498 // we should either set module parent to NULL without clearing it, or even
2499 // set the new StarBASIC as the parent of the module
2500 // pObject->SetParent( NULL );
2502 if( pMeth == pFirst )
2503 pFirst = pMeth->pNext;
2504 else if( pMeth->pPrev )
2505 pMeth->pPrev->pNext = pMeth->pNext;
2506 if( pMeth->pNext )
2507 pMeth->pNext->pPrev = pMeth->pPrev;
2509 pMeth->pPrev = NULL;
2510 pMeth->pNext = NULL;
2512 pMeth->SbxValue::Clear();
2513 pObject->SbxValue::Clear();
2515 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2516 pMeth = pFirst;
2518 else
2519 pMeth = pMeth->pNext;
2521 else
2522 pMeth = pMeth->pNext;
2526 void clearUnoMethods()
2528 SbUnoMethod* pMeth = pFirst;
2529 while( pMeth )
2531 pMeth->SbxValue::Clear();
2532 pMeth = pMeth->pNext;
2537 SbUnoMethod::SbUnoMethod
2539 const OUString& aName_,
2540 SbxDataType eSbxType,
2541 Reference< XIdlMethod > xUnoMethod_,
2542 bool bInvocation,
2543 bool bDirect
2545 : SbxMethod( aName_, eSbxType )
2546 , mbInvocation( bInvocation )
2547 , mbDirectInvocation( bDirect )
2549 m_xUnoMethod = xUnoMethod_;
2550 pParamInfoSeq = NULL;
2552 // enregister the method in a list
2553 pNext = pFirst;
2554 pPrev = NULL;
2555 pFirst = this;
2556 if( pNext )
2557 pNext->pPrev = this;
2560 SbUnoMethod::~SbUnoMethod()
2562 delete pParamInfoSeq;
2564 if( this == pFirst )
2565 pFirst = pNext;
2566 else if( pPrev )
2567 pPrev->pNext = pNext;
2568 if( pNext )
2569 pNext->pPrev = pPrev;
2572 SbxInfo* SbUnoMethod::GetInfo()
2574 if( !pInfo && m_xUnoMethod.is() )
2576 SbiInstance* pInst = GetSbData()->pInst;
2577 if( pInst && pInst->IsCompatibility() )
2579 pInfo = new SbxInfo();
2581 const Sequence<ParamInfo>& rInfoSeq = getParamInfos();
2582 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2583 sal_uInt32 nParamCount = rInfoSeq.getLength();
2585 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
2587 const ParamInfo& rInfo = pParamInfos[i];
2588 OUString aParamName = rInfo.aName;
2590 SbxDataType t = SbxVARIANT;
2591 SbxFlagBits nFlags_ = SBX_READ;
2592 pInfo->AddParam( aParamName, t, nFlags_ );
2596 return pInfo;
2599 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos()
2601 if (!pParamInfoSeq)
2603 Sequence<ParamInfo> aTmp;
2604 if (m_xUnoMethod.is())
2605 aTmp = m_xUnoMethod->getParameterInfos();
2606 pParamInfoSeq = new Sequence<ParamInfo>(aTmp);
2608 return *pParamInfoSeq;
2611 SbUnoProperty::SbUnoProperty
2613 const OUString& aName_,
2614 SbxDataType eSbxType,
2615 SbxDataType eRealSbxType,
2616 const Property& aUnoProp_,
2617 sal_Int32 nId_,
2618 bool bInvocation,
2619 bool bUnoStruct
2621 : SbxProperty( aName_, eSbxType )
2622 , aUnoProp( aUnoProp_ )
2623 , nId( nId_ )
2624 , mbInvocation( bInvocation )
2625 , mRealType( eRealSbxType )
2626 , mbUnoStruct( bUnoStruct )
2628 // as needed establish an dummy array so that SbiRuntime::CheckArray() works
2629 static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT );
2630 if( eSbxType & SbxARRAY )
2631 PutObject( xDummyArray );
2634 SbUnoProperty::~SbUnoProperty()
2638 SbxVariable* SbUnoObject::Find( const OUString& rName, SbxClassType t )
2640 static Reference< XIdlMethod > xDummyMethod;
2641 static Property aDummyProp;
2643 SbxVariable* pRes = SbxObject::Find( rName, t );
2645 if( bNeedIntrospection )
2646 doIntrospection();
2648 // New 1999-03-04: Create properties on demand. Therefore search now via
2649 // IntrospectionAccess if a property or a method of the required name exist
2650 if( !pRes )
2652 OUString aUName( rName );
2653 if( mxUnoAccess.is() && !bNativeCOMObject )
2655 if( mxExactName.is() )
2657 OUString aUExactName = mxExactName->getExactName( aUName );
2658 if( !aUExactName.isEmpty() )
2660 aUName = aUExactName;
2663 if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
2665 const Property& rProp = mxUnoAccess->
2666 getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2668 // If the property could be void the type had to be set to Variant
2669 SbxDataType eSbxType;
2670 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2671 eSbxType = SbxVARIANT;
2672 else
2673 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2675 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2676 // create the property and superimpose it
2677 SbUnoProperty* pProp = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2678 SbxVariableRef xVarRef = pProp;
2679 QuickInsert( (SbxVariable*)xVarRef );
2680 pRes = xVarRef;
2682 else if( mxUnoAccess->hasMethod( aUName,
2683 MethodConcept::ALL - MethodConcept::DANGEROUS ) )
2685 // address the method
2686 const Reference< XIdlMethod >& rxMethod = mxUnoAccess->
2687 getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS );
2689 // create SbUnoMethod and superimpose it
2690 SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(),
2691 unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2692 QuickInsert( (SbxVariable*)xMethRef );
2693 pRes = xMethRef;
2696 // If nothing was found check via XNameAccess
2697 if( !pRes )
2701 Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( cppu::UnoType<XPropertySet>::get()), UNO_QUERY );
2702 OUString aUName2( rName );
2704 if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) )
2706 Any aAny = xNameAccess->getByName( aUName2 );
2708 // ATTENTION: Because of XNameAccess, the variable generated here
2709 // may not be included as a fixed property in the object and therefore
2710 // won't be stored anywhere.
2711 // If this leads to problems, it has to be created
2712 // synthetically or a class SbUnoNameAccessProperty,
2713 // witch checks the existence on access and which
2714 // is disposed if the name is not found anymore.
2715 pRes = new SbxVariable( SbxVARIANT );
2716 unoToSbxValue( pRes, aAny );
2719 catch( const NoSuchElementException& e )
2721 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2723 catch( const Exception& )
2725 // Establish so that the exception error will not be overwritten
2726 if( !pRes )
2727 pRes = new SbxVariable( SbxVARIANT );
2729 implHandleAnyException( ::cppu::getCaughtException() );
2733 if( !pRes && mxInvocation.is() )
2735 if( mxExactNameInvocation.is() )
2737 OUString aUExactName = mxExactNameInvocation->getExactName( aUName );
2738 if( !aUExactName.isEmpty() )
2740 aUName = aUExactName;
2746 if( mxInvocation->hasProperty( aUName ) )
2748 // create a property and superimpose it
2749 SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false );
2750 QuickInsert( (SbxVariable*)xVarRef );
2751 pRes = xVarRef;
2753 else if( mxInvocation->hasMethod( aUName ) )
2755 // create SbUnoMethode and superimpose it
2756 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true );
2757 QuickInsert( (SbxVariable*)xMethRef );
2758 pRes = xMethRef;
2760 else
2762 Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY );
2763 if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) )
2765 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true );
2766 QuickInsert( (SbxVariable*)xMethRef );
2767 pRes = xMethRef;
2772 catch( const RuntimeException& e )
2774 // Establish so that the exception error will not be overwritten
2775 if( !pRes )
2776 pRes = new SbxVariable( SbxVARIANT );
2778 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2783 // At the very end checking if the Dbg_-Properties are meant
2785 if( !pRes )
2787 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
2788 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
2789 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
2791 // Create
2792 implCreateDbgProperties();
2794 // Now they have to be found regular
2795 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
2798 return pRes;
2802 // help method to create the dbg_-Properties
2803 void SbUnoObject::implCreateDbgProperties()
2805 Property aProp;
2807 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2808 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
2809 QuickInsert( (SbxVariable*)xVarRef );
2811 // Id == -2: output the properties
2812 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
2813 QuickInsert( (SbxVariable*)xVarRef );
2815 // Id == -3: output the Methods
2816 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
2817 QuickInsert( (SbxVariable*)xVarRef );
2820 void SbUnoObject::implCreateAll()
2822 // throw away all existing methods and properties
2823 pMethods = new SbxArray;
2824 pProps = new SbxArray;
2826 if( bNeedIntrospection ) doIntrospection();
2828 // get introspection
2829 Reference< XIntrospectionAccess > xAccess = mxUnoAccess;
2830 if( !xAccess.is() || bNativeCOMObject )
2832 if( mxInvocation.is() )
2833 xAccess = mxInvocation->getIntrospection();
2834 else if( bNativeCOMObject )
2835 return;
2837 if( !xAccess.is() )
2838 return;
2840 // Establish properties
2841 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2842 sal_uInt32 nPropCount = props.getLength();
2843 const Property* pProps_ = props.getConstArray();
2845 sal_uInt32 i;
2846 for( i = 0 ; i < nPropCount ; i++ )
2848 const Property& rProp = pProps_[ i ];
2850 // If the property could be void the type had to be set to Variant
2851 SbxDataType eSbxType;
2852 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2853 eSbxType = SbxVARIANT;
2854 else
2855 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2857 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2858 // Create property and superimpose it
2859 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2860 QuickInsert( (SbxVariable*)xVarRef );
2863 // Create Dbg_-Properties
2864 implCreateDbgProperties();
2866 // Create methods
2867 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods
2868 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2869 sal_uInt32 nMethCount = aMethodSeq.getLength();
2870 const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray();
2871 for( i = 0 ; i < nMethCount ; i++ )
2873 // address method
2874 const Reference< XIdlMethod >& rxMethod = pMethods_[i];
2876 // Create SbUnoMethod and superimpose it
2877 SbxVariableRef xMethRef = new SbUnoMethod
2878 ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2879 QuickInsert( (SbxVariable*)xMethRef );
2884 // output the value
2885 Any SbUnoObject::getUnoAny()
2887 Any aRetAny;
2888 if( bNeedIntrospection ) doIntrospection();
2889 if ( maStructInfo.get() )
2890 aRetAny = maTmpUnoObj;
2891 else if( mxMaterialHolder.is() )
2892 aRetAny = mxMaterialHolder->getMaterial();
2893 else if( mxInvocation.is() )
2894 aRetAny <<= mxInvocation;
2895 return aRetAny;
2898 // help method to create an Uno-Struct per CoreReflection
2899 SbUnoObject* Impl_CreateUnoStruct( const OUString& aClassName )
2901 // get CoreReflection
2902 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
2903 if( !xCoreReflection.is() )
2904 return NULL;
2906 // search for the class
2907 Reference< XIdlClass > xClass;
2908 Reference< XHierarchicalNameAccess > xHarryName =
2909 getCoreReflection_HierarchicalNameAccess_Impl();
2910 if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) )
2911 xClass = xCoreReflection->forName( aClassName );
2912 if( !xClass.is() )
2913 return NULL;
2915 // Is it really a struct?
2916 TypeClass eType = xClass->getTypeClass();
2917 if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) )
2918 return NULL;
2920 // create an instance
2921 Any aNewAny;
2922 xClass->createObject( aNewAny );
2923 // make a SbUnoObject out of it
2924 SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny );
2925 return pUnoObj;
2929 // Factory-Class to create Uno-Structs per DIM AS NEW
2930 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
2932 // Via SbxId nothing works in Uno
2933 return NULL;
2936 SbxObject* SbUnoFactory::CreateObject( const OUString& rClassName )
2938 return Impl_CreateUnoStruct( rClassName );
2942 // Provisional interface for the UNO-Connection
2943 // Deliver a SbxObject, that wrap an Uno-Interface
2944 SbxObjectRef GetSbUnoObject( const OUString& aName, const Any& aUnoObj_ )
2946 return new SbUnoObject( aName, aUnoObj_ );
2949 // Force creation of all properties for debugging
2950 void createAllObjectProperties( SbxObject* pObj )
2952 if( !pObj )
2953 return;
2955 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
2956 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
2957 if( pUnoObj )
2959 pUnoObj->createAllProperties();
2961 else if ( pUnoStructObj )
2963 pUnoStructObj->createAllProperties();
2968 void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
2970 (void)pBasic;
2971 (void)bWrite;
2973 // We need 1 parameter minimum
2974 if ( rPar.Count() < 2 )
2976 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2977 return;
2980 // get the name of the class of the struct
2981 OUString aClassName = rPar.Get(1)->GetOUString();
2983 // try to create Struct with the same name
2984 SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName );
2985 if( !xUnoObj )
2987 return;
2989 // return the object
2990 SbxVariableRef refVar = rPar.Get(0);
2991 refVar->PutObject( (SbUnoObject*)xUnoObj );
2994 void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
2996 (void)pBasic;
2997 (void)bWrite;
2999 // We need 1 Parameter minimum
3000 if ( rPar.Count() < 2 )
3002 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3003 return;
3006 // get the name of the class of the struct
3007 OUString aServiceName = rPar.Get(1)->GetOUString();
3009 // search for the service and instatiate it
3010 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3011 Reference< XInterface > xInterface;
3014 xInterface = xFactory->createInstance( aServiceName );
3016 catch( const Exception& )
3018 implHandleAnyException( ::cppu::getCaughtException() );
3021 SbxVariableRef refVar = rPar.Get(0);
3022 if( xInterface.is() )
3024 Any aAny;
3025 aAny <<= xInterface;
3027 // Create a SbUnoObject out of it and return it
3028 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3029 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3031 // return the object
3032 refVar->PutObject( (SbUnoObject*)xUnoObj );
3034 else
3036 refVar->PutObject( NULL );
3039 else
3041 refVar->PutObject( NULL );
3045 void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
3047 (void)pBasic;
3048 (void)bWrite;
3050 // We need 2 parameter minimum
3051 if ( rPar.Count() < 3 )
3053 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3054 return;
3057 // get the name of the class of the struct
3058 OUString aServiceName = rPar.Get(1)->GetOUString();
3059 Any aArgAsAny = sbxToUnoValue( rPar.Get(2),
3060 cppu::UnoType<Sequence<Any>>::get() );
3061 Sequence< Any > aArgs;
3062 aArgAsAny >>= aArgs;
3064 // search for the service and instatiate it
3065 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3066 Reference< XInterface > xInterface;
3069 xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
3071 catch( const Exception& )
3073 implHandleAnyException( ::cppu::getCaughtException() );
3076 SbxVariableRef refVar = rPar.Get(0);
3077 if( xInterface.is() )
3079 Any aAny;
3080 aAny <<= xInterface;
3082 // Create a SbUnoObject out of it and return it
3083 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3084 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3086 // return the object
3087 refVar->PutObject( (SbUnoObject*)xUnoObj );
3089 else
3091 refVar->PutObject( NULL );
3094 else
3096 refVar->PutObject( NULL );
3100 void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
3102 (void)pBasic;
3103 (void)bWrite;
3105 SbxVariableRef refVar = rPar.Get(0);
3107 // get the global service manager
3108 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3109 Any aAny;
3110 aAny <<= xFactory;
3112 // Create a SbUnoObject out of it and return it
3113 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "ProcessServiceManager" ), aAny );
3114 refVar->PutObject( (SbUnoObject*)xUnoObj );
3117 void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
3119 (void)pBasic;
3120 (void)bWrite;
3122 // We need 2 parameter minimum
3123 sal_uInt16 nParCount = rPar.Count();
3124 if( nParCount < 3 )
3126 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3127 return;
3130 // variable for the return value
3131 SbxVariableRef refVar = rPar.Get(0);
3132 refVar->PutBool( false );
3134 // get the Uno-Object
3135 SbxBaseRef pObj = rPar.Get( 1 )->GetObject();
3136 if( !(pObj && pObj->ISA(SbUnoObject)) )
3138 return;
3140 Any aAny = static_cast<SbUnoObject*>((SbxBase*)pObj)->getUnoAny();
3141 TypeClass eType = aAny.getValueType().getTypeClass();
3142 if( eType != TypeClass_INTERFACE )
3144 return;
3146 // get the interface out of the Any
3147 Reference< XInterface > x = *static_cast<Reference< XInterface > const *>(aAny.getValue());
3149 // get CoreReflection
3150 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3151 if( !xCoreReflection.is() )
3153 return;
3155 for( sal_uInt16 i = 2 ; i < nParCount ; i++ )
3157 // get the name of the interface of the struct
3158 OUString aIfaceName = rPar.Get( i )->GetOUString();
3160 // search for the class
3161 Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName );
3162 if( !xClass.is() )
3164 return;
3166 // check if the interface will be supported
3167 OUString aClassName = xClass->getName();
3168 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
3169 if( !x->queryInterface( aClassType ).hasValue() )
3171 return;
3175 // Every thing works; then return TRUE
3176 refVar->PutBool( true );
3179 void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
3181 (void)pBasic;
3182 (void)bWrite;
3184 // We need 1 parameter minimum
3185 if ( rPar.Count() < 2 )
3187 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3188 return;
3191 // variable for the return value
3192 SbxVariableRef refVar = rPar.Get(0);
3193 refVar->PutBool( false );
3195 // get the Uno-Object
3196 SbxVariableRef xParam = rPar.Get( 1 );
3197 if( !xParam->IsObject() )
3199 return;
3201 SbxBaseRef pObj = rPar.Get( 1 )->GetObject();
3202 if( !(pObj && pObj->ISA(SbUnoObject)) )
3204 return;
3206 Any aAny = static_cast<SbUnoObject*>((SbxBase*)pObj)->getUnoAny();
3207 TypeClass eType = aAny.getValueType().getTypeClass();
3208 if( eType == TypeClass_STRUCT )
3210 refVar->PutBool( true );
3215 void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
3217 (void)pBasic;
3218 (void)bWrite;
3220 if ( rPar.Count() < 3 )
3222 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3223 return;
3226 // variable for the return value
3227 SbxVariableRef refVar = rPar.Get(0);
3228 refVar->PutBool( false );
3230 // get the Uno-Objects
3231 SbxVariableRef xParam1 = rPar.Get( 1 );
3232 if( !xParam1->IsObject() )
3234 return;
3236 SbxBaseRef pObj1 = xParam1->GetObject();
3237 if( !(pObj1 && pObj1->ISA(SbUnoObject)) )
3239 return;
3241 Any aAny1 = static_cast<SbUnoObject*>((SbxBase*)pObj1)->getUnoAny();
3242 TypeClass eType1 = aAny1.getValueType().getTypeClass();
3243 if( eType1 != TypeClass_INTERFACE )
3245 return;
3247 Reference< XInterface > x1;
3248 aAny1 >>= x1;
3250 SbxVariableRef xParam2 = rPar.Get( 2 );
3251 if( !xParam2->IsObject() )
3253 return;
3255 SbxBaseRef pObj2 = xParam2->GetObject();
3256 if( !(pObj2 && pObj2->ISA(SbUnoObject)) )
3258 return;
3260 Any aAny2 = static_cast<SbUnoObject*>((SbxBase*)pObj2)->getUnoAny();
3261 TypeClass eType2 = aAny2.getValueType().getTypeClass();
3262 if( eType2 != TypeClass_INTERFACE )
3264 return;
3266 Reference< XInterface > x2;
3267 aAny2 >>= x2;
3269 if( x1 == x2 )
3271 refVar->PutBool( true );
3276 // helper wrapper function to interact with TypeProvider and
3277 // XTypeDescriptionEnumerationAccess.
3278 // if it fails for whatever reason
3279 // returned Reference<> be null e.g. .is() will be false
3281 Reference< XTypeDescriptionEnumeration > getTypeDescriptorEnumeration( const OUString& sSearchRoot,
3282 const Sequence< TypeClass >& types,
3283 TypeDescriptionSearchDepth depth )
3285 Reference< XTypeDescriptionEnumeration > xEnum;
3286 Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY );
3287 if ( xTypeEnumAccess.is() )
3291 xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration(
3292 sSearchRoot, types, depth );
3294 catch(const NoSuchTypeNameException& /*nstne*/ ) {}
3295 catch(const InvalidTypeNameException& /*nstne*/ ) {}
3297 return xEnum;
3300 typedef std::unordered_map< OUString, Any, OUStringHash, ::std::equal_to< OUString > > VBAConstantsHash;
3302 VBAConstantHelper&
3303 VBAConstantHelper::instance()
3305 static VBAConstantHelper aHelper;
3306 return aHelper;
3309 void VBAConstantHelper::init()
3311 if ( !isInited )
3313 Sequence< TypeClass > types(1);
3314 types[ 0 ] = TypeClass_CONSTANTS;
3315 Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( OUString(defaultNameSpace), types, TypeDescriptionSearchDepth_INFINITE );
3317 if ( !xEnum.is())
3319 return; //NULL;
3321 while ( xEnum->hasMoreElements() )
3323 Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY );
3324 if ( xConstants.is() )
3326 // store constant group name
3327 OUString sFullName = xConstants->getName();
3328 sal_Int32 indexLastDot = sFullName.lastIndexOf('.');
3329 OUString sLeafName( sFullName );
3330 if ( indexLastDot > -1 )
3332 sLeafName = sFullName.copy( indexLastDot + 1);
3334 aConstCache.push_back( sLeafName ); // assume constant group names are unique
3335 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants();
3336 for (sal_Int32 i = 0; i != aConsts.getLength(); ++i)
3338 // store constant member name
3339 sFullName = aConsts[i]->getName();
3340 indexLastDot = sFullName.lastIndexOf('.');
3341 sLeafName = sFullName;
3342 if ( indexLastDot > -1 )
3344 sLeafName = sFullName.copy( indexLastDot + 1);
3346 aConstHash[ sLeafName.toAsciiLowerCase() ] = aConsts[i]->getConstantValue();
3350 isInited = true;
3354 bool
3355 VBAConstantHelper::isVBAConstantType( const OUString& rName )
3357 init();
3358 bool bConstant = false;
3359 OUString sKey( rName );
3360 VBAConstantsVector::const_iterator it = aConstCache.begin();
3362 for( ; it != aConstCache.end(); ++it )
3364 if( sKey.equalsIgnoreAsciiCase( *it ) )
3366 bConstant = true;
3367 break;
3370 return bConstant;
3373 SbxVariable*
3374 VBAConstantHelper::getVBAConstant( const OUString& rName )
3376 SbxVariable* pConst = NULL;
3377 init();
3379 OUString sKey( rName );
3381 VBAConstantsHash::const_iterator it = aConstHash.find( sKey.toAsciiLowerCase() );
3383 if ( it != aConstHash.end() )
3385 pConst = new SbxVariable( SbxVARIANT );
3386 pConst->SetName( rName );
3387 unoToSbxValue( pConst, it->second );
3390 return pConst;
3393 // Function to search for a global identifier in the
3394 // UnoScope and to wrap it for Sbx
3395 SbUnoClass* findUnoClass( const OUString& rName )
3397 // #105550 Check if module exists
3398 SbUnoClass* pUnoClass = NULL;
3400 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3401 if( xTypeAccess->hasByHierarchicalName( rName ) )
3403 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3404 Reference< XTypeDescription > xTypeDesc;
3405 aRet >>= xTypeDesc;
3407 if( xTypeDesc.is() )
3409 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3410 if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS )
3412 pUnoClass = new SbUnoClass( rName );
3416 return pUnoClass;
3419 SbxVariable* SbUnoClass::Find( const OUString& rName, SbxClassType )
3421 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE );
3423 // If nothing were located the submodule isn't known yet
3424 if( !pRes )
3426 // If it is already a class, ask for the field
3427 if( m_xClass.is() )
3429 // Is it a field(?)
3430 OUString aUStr( rName );
3431 Reference< XIdlField > xField = m_xClass->getField( aUStr );
3432 Reference< XIdlClass > xClass;
3433 if( xField.is() )
3437 Any aAny;
3438 aAny = xField->get( aAny );
3440 // Convert to Sbx
3441 pRes = new SbxVariable( SbxVARIANT );
3442 pRes->SetName( rName );
3443 unoToSbxValue( pRes, aAny );
3445 catch( const Exception& )
3447 implHandleAnyException( ::cppu::getCaughtException() );
3451 else
3453 // expand fully qualified name
3454 OUString aNewName = GetName();
3455 aNewName += ".";
3456 aNewName += rName;
3458 // get CoreReflection
3459 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3460 if( xCoreReflection.is() )
3462 // Is it a constant?
3463 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY );
3464 if( xHarryName.is() )
3468 Any aValue = xHarryName->getByHierarchicalName( aNewName );
3469 TypeClass eType = aValue.getValueType().getTypeClass();
3471 // Interface located? Then it is a class
3472 if( eType == TypeClass_INTERFACE )
3474 Reference< XInterface > xIface = *static_cast<Reference< XInterface > const *>(aValue.getValue());
3475 Reference< XIdlClass > xClass( xIface, UNO_QUERY );
3476 if( xClass.is() )
3478 pRes = new SbxVariable( SbxVARIANT );
3479 SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass );
3480 pRes->PutObject( xWrapper );
3483 else
3485 pRes = new SbxVariable( SbxVARIANT );
3486 unoToSbxValue( pRes, aValue );
3489 catch( const NoSuchElementException& )
3494 // Otherwise take it again as class
3495 if( !pRes )
3497 SbUnoClass* pNewClass = findUnoClass( aNewName );
3498 if( pNewClass )
3500 pRes = new SbxVariable( SbxVARIANT );
3501 SbxObjectRef xWrapper = (SbxObject*)pNewClass;
3502 pRes->PutObject( xWrapper );
3506 // An UNO service?
3507 if( !pRes )
3509 SbUnoService* pUnoService = findUnoService( aNewName );
3510 if( pUnoService )
3512 pRes = new SbxVariable( SbxVARIANT );
3513 SbxObjectRef xWrapper = (SbxObject*)pUnoService;
3514 pRes->PutObject( xWrapper );
3518 // An UNO singleton?
3519 if( !pRes )
3521 SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName );
3522 if( pUnoSingleton )
3524 pRes = new SbxVariable( SbxVARIANT );
3525 SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton;
3526 pRes->PutObject( xWrapper );
3532 if( pRes )
3534 pRes->SetName( rName );
3536 // Insert variable, so that it could be found later
3537 QuickInsert( pRes );
3539 // Take us out as listener at once,
3540 // the values are all constant
3541 if( pRes->IsBroadcaster() )
3542 EndListening( pRes->GetBroadcaster(), true );
3545 return pRes;
3549 SbUnoService* findUnoService( const OUString& rName )
3551 SbUnoService* pSbUnoService = NULL;
3553 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3554 if( xTypeAccess->hasByHierarchicalName( rName ) )
3556 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3557 Reference< XTypeDescription > xTypeDesc;
3558 aRet >>= xTypeDesc;
3560 if( xTypeDesc.is() )
3562 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3563 if( eTypeClass == TypeClass_SERVICE )
3565 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY );
3566 if( xServiceTypeDesc.is() )
3567 pSbUnoService = new SbUnoService( rName, xServiceTypeDesc );
3571 return pSbUnoService;
3574 SbxVariable* SbUnoService::Find( const OUString& rName, SbxClassType )
3576 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3578 if( !pRes )
3580 // If it is already a class ask for a field
3581 if( m_bNeedsInit && m_xServiceTypeDesc.is() )
3583 m_bNeedsInit = false;
3585 Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors();
3586 const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray();
3587 int nCtorCount = aSCDSeq.getLength();
3588 for( int i = 0 ; i < nCtorCount ; ++i )
3590 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i];
3592 OUString aName( xCtor->getName() );
3593 if( aName.isEmpty() )
3595 if( xCtor->isDefaultConstructor() )
3597 aName = "create";
3601 if( !aName.isEmpty() )
3603 // Create and insert SbUnoServiceCtor
3604 SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor );
3605 QuickInsert( (SbxVariable*)xSbCtorRef );
3608 pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3612 return pRes;
3615 void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3616 const SfxHint& rHint, const TypeId& rHintType )
3618 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint);
3619 if( pHint )
3621 SbxVariable* pVar = pHint->GetVar();
3622 SbxArray* pParams = pVar->GetParameters();
3623 SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar);
3624 if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED )
3626 // Parameter count -1 because of Param0 == this
3627 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3628 Sequence<Any> args;
3630 Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc();
3631 Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters();
3632 const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray();
3633 sal_uInt32 nUnoParamCount = aParameterSeq.getLength();
3635 // Default: Ignore not needed parameters
3636 bool bParameterError = false;
3638 // Is the last parameter a rest parameter?
3639 bool bRestParameterMode = false;
3640 if( nUnoParamCount > 0 )
3642 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ];
3643 if( xLastParam.is() )
3645 if( xLastParam->isRestParameter() )
3646 bRestParameterMode = true;
3650 // Too many parameters with context as first parameter?
3651 sal_uInt16 nSbxParameterOffset = 1;
3652 sal_uInt16 nParameterOffsetByContext = 0;
3653 Reference < XComponentContext > xFirstParamContext;
3654 if( nParamCount > nUnoParamCount )
3656 // Check if first parameter is a context and use it
3657 // then in createInstanceWithArgumentsAndContext
3658 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) );
3659 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
3660 nParameterOffsetByContext = 1;
3663 sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext;
3664 sal_uInt32 nAllocParamCount = nEffectiveParamCount;
3665 if( nEffectiveParamCount > nUnoParamCount )
3667 if( !bRestParameterMode )
3669 nEffectiveParamCount = nUnoParamCount;
3670 nAllocParamCount = nUnoParamCount;
3673 // Not enough parameters?
3674 else if( nUnoParamCount > nEffectiveParamCount )
3676 // RestParameterMode only helps if one (the last) parameter is missing
3677 int nDiff = nUnoParamCount - nEffectiveParamCount;
3678 if( !bRestParameterMode || nDiff > 1 )
3680 bParameterError = true;
3681 StarBASIC::Error( SbERR_NOT_OPTIONAL );
3685 if( !bParameterError )
3687 bool bOutParams = false;
3688 if( nAllocParamCount > 0 )
3690 args.realloc( nAllocParamCount );
3691 Any* pAnyArgs = args.getArray();
3692 for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ )
3694 sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext);
3696 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3697 Reference< XParameter > xParam;
3698 if( i < nUnoParamCount )
3700 xParam = pParameterSeq[i];
3701 if( !xParam.is() )
3702 continue;
3704 Reference< XTypeDescription > xParamTypeDesc = xParam->getType();
3705 if( !xParamTypeDesc.is() )
3706 continue;
3707 com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() );
3709 // sbx parameter needs offset 1
3710 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType );
3712 // Check for out parameter if not already done
3713 if( !bOutParams )
3715 if( xParam->isOut() )
3716 bOutParams = true;
3719 else
3721 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) );
3726 // "Call" ctor using createInstanceWithArgumentsAndContext
3727 Reference < XComponentContext > xContext(
3728 xFirstParamContext.is()
3729 ? xFirstParamContext
3730 : comphelper::getProcessComponentContext() );
3731 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
3733 Any aRetAny;
3734 OUString aServiceName = GetName();
3735 Reference < XInterface > xRet;
3738 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext );
3740 catch( const Exception& )
3742 implHandleAnyException( ::cppu::getCaughtException() );
3744 aRetAny <<= xRet;
3745 unoToSbxValue( pVar, aRetAny );
3747 // Copy back out parameters?
3748 if( bOutParams )
3750 const Any* pAnyArgs = args.getConstArray();
3752 for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ )
3754 Reference< XParameter > xParam = pParameterSeq[j];
3755 if( !xParam.is() )
3756 continue;
3758 if( xParam->isOut() )
3759 unoToSbxValue( pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
3764 else
3765 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3771 static SbUnoServiceCtor* pFirstCtor = NULL;
3773 void clearUnoServiceCtors()
3775 SbUnoServiceCtor* pCtor = pFirstCtor;
3776 while( pCtor )
3778 pCtor->SbxValue::Clear();
3779 pCtor = pCtor->pNext;
3783 SbUnoServiceCtor::SbUnoServiceCtor( const OUString& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc )
3784 : SbxMethod( aName_, SbxOBJECT )
3785 , m_xServiceCtorDesc( xServiceCtorDesc )
3786 , pNext(0)
3790 SbUnoServiceCtor::~SbUnoServiceCtor()
3794 SbxInfo* SbUnoServiceCtor::GetInfo()
3796 SbxInfo* pRet = NULL;
3798 return pRet;
3802 SbUnoSingleton* findUnoSingleton( const OUString& rName )
3804 SbUnoSingleton* pSbUnoSingleton = NULL;
3806 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3807 if( xTypeAccess->hasByHierarchicalName( rName ) )
3809 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3810 Reference< XTypeDescription > xTypeDesc;
3811 aRet >>= xTypeDesc;
3813 if( xTypeDesc.is() )
3815 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3816 if( eTypeClass == TypeClass_SINGLETON )
3818 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY );
3819 if( xSingletonTypeDesc.is() )
3820 pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc );
3824 return pSbUnoSingleton;
3827 SbUnoSingleton::SbUnoSingleton( const OUString& aName_,
3828 const Reference< XSingletonTypeDescription >& xSingletonTypeDesc )
3829 : SbxObject( aName_ )
3830 , m_xSingletonTypeDesc( xSingletonTypeDesc )
3832 SbxVariableRef xGetMethodRef = new SbxMethod( OUString( "get" ), SbxOBJECT );
3833 QuickInsert( (SbxVariable*)xGetMethodRef );
3836 void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3837 const SfxHint& rHint, const TypeId& rHintType )
3839 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint);
3840 if( pHint )
3842 SbxVariable* pVar = pHint->GetVar();
3843 SbxArray* pParams = pVar->GetParameters();
3844 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3845 sal_uInt32 nAllowedParamCount = 1;
3847 Reference < XComponentContext > xContextToUse;
3848 if( nParamCount > 0 )
3850 // Check if first parameter is a context and use it then
3851 Reference < XComponentContext > xFirstParamContext;
3852 Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) );
3853 if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
3854 xContextToUse = xFirstParamContext;
3857 if( !xContextToUse.is() )
3859 xContextToUse = comphelper::getProcessComponentContext();
3860 --nAllowedParamCount;
3863 if( nParamCount > nAllowedParamCount )
3865 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3866 return;
3869 Any aRetAny;
3870 if( xContextToUse.is() )
3872 OUString aSingletonName( "/singletons/" );
3873 aSingletonName += GetName();
3874 Reference < XInterface > xRet;
3875 xContextToUse->getValueByName( aSingletonName ) >>= xRet;
3876 aRetAny <<= xRet;
3878 unoToSbxValue( pVar, aRetAny );
3880 else
3882 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3889 // Implementation of an EventAttacher-drawn AllListener, which
3890 // solely transmits several events to an general AllListener
3891 class BasicAllListener_Impl : public BasicAllListenerHelper
3893 void firing_impl(const AllEventObject& Event, Any* pRet);
3895 public:
3896 SbxObjectRef xSbxObj;
3897 OUString aPrefixName;
3899 BasicAllListener_Impl( const OUString& aPrefixName );
3900 virtual ~BasicAllListener_Impl();
3902 // Methods of XAllListener
3903 virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException, std::exception ) SAL_OVERRIDE;
3904 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException, std::exception ) SAL_OVERRIDE;
3906 // Methods of XEventListener
3907 virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException, std::exception ) SAL_OVERRIDE;
3912 BasicAllListener_Impl::BasicAllListener_Impl(const OUString& aPrefixName_)
3913 : aPrefixName( aPrefixName_ )
3918 BasicAllListener_Impl::~BasicAllListener_Impl()
3924 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet )
3926 SolarMutexGuard guard;
3928 if( xSbxObj.Is() )
3930 OUString aMethodName = aPrefixName;
3931 aMethodName = aMethodName + Event.MethodName;
3933 SbxVariable * pP = xSbxObj;
3934 while( pP->GetParent() )
3936 pP = pP->GetParent();
3937 StarBASIC * pLib = PTR_CAST(StarBASIC,pP);
3938 if( pLib )
3940 // Create in a Basic Array
3941 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT );
3942 const Any * pArgs = Event.Arguments.getConstArray();
3943 sal_Int32 nCount = Event.Arguments.getLength();
3944 for( sal_Int32 i = 0; i < nCount; i++ )
3946 // Convert elements
3947 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
3948 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
3949 xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
3952 pLib->Call( aMethodName, xSbxArray );
3954 // get the return value from the Param-Array, if requested
3955 if( pRet )
3957 SbxVariable* pVar = xSbxArray->Get( 0 );
3958 if( pVar )
3960 // #95792 Avoid a second call
3961 SbxFlagBits nFlags = pVar->GetFlags();
3962 pVar->SetFlag( SBX_NO_BROADCAST );
3963 *pRet = sbxToUnoValueImpl( pVar );
3964 pVar->SetFlags( nFlags );
3967 break;
3974 // Methods of Listener
3975 void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException, std::exception )
3977 firing_impl( Event, NULL );
3980 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException, std::exception )
3982 Any aRetAny;
3983 firing_impl( Event, &aRetAny );
3984 return aRetAny;
3988 // Methods of XEventListener
3989 void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException, std::exception )
3991 SolarMutexGuard guard;
3993 xSbxObj.Clear();
3999 // class InvocationToAllListenerMapper
4000 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
4002 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
4004 public:
4005 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
4006 const Reference< XAllListener >& AllListener, const Any& Helper );
4008 // XInvocation
4009 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
4010 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4011 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
4012 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
4013 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
4014 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException, std::exception ) SAL_OVERRIDE;
4015 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
4016 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
4018 private:
4019 Reference< XIdlReflection > m_xCoreReflection;
4020 Reference< XAllListener > m_xAllListener;
4021 Reference< XIdlClass > m_xListenerType;
4022 Any m_Helper;
4026 // Function to replace AllListenerAdapterService::createAllListerAdapter
4027 Reference< XInterface > createAllListenerAdapter
4029 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
4030 const Reference< XIdlClass >& xListenerType,
4031 const Reference< XAllListener >& xListener,
4032 const Any& Helper
4035 Reference< XInterface > xAdapter;
4036 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
4038 Reference< XInvocation > xInvocationToAllListenerMapper =
4039 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
4040 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() );
4041 Sequence<Type> arg2(1);
4042 arg2[0] = aListenerType;
4043 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
4045 return xAdapter;
4050 // InvocationToAllListenerMapper
4051 InvocationToAllListenerMapper::InvocationToAllListenerMapper
4052 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
4053 : m_xAllListener( AllListener )
4054 , m_xListenerType( ListenerType )
4055 , m_Helper( Helper )
4060 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection()
4061 throw( RuntimeException, std::exception )
4063 return Reference< XIntrospectionAccess >();
4067 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
4068 Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4069 throw( IllegalArgumentException, CannotConvertException,
4070 InvocationTargetException, RuntimeException, std::exception )
4072 (void)OutParamIndex;
4073 (void)OutParam ;
4075 Any aRet;
4077 // Check if to firing or approveFiring has to be called
4078 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
4079 bool bApproveFiring = false;
4080 if( !xMethod.is() )
4081 return aRet;
4082 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
4083 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
4084 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
4085 aExceptionSeq.getLength() > 0 )
4087 bApproveFiring = true;
4089 else
4091 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
4092 sal_uInt32 nParamCount = aParamSeq.getLength();
4093 if( nParamCount > 1 )
4095 const ParamInfo* pInfos = aParamSeq.getConstArray();
4096 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
4098 if( pInfos[ i ].aMode != ParamMode_IN )
4100 bApproveFiring = true;
4101 break;
4107 AllEventObject aAllEvent;
4108 aAllEvent.Source = (OWeakObject*) this;
4109 aAllEvent.Helper = m_Helper;
4110 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() );
4111 aAllEvent.MethodName = FunctionName;
4112 aAllEvent.Arguments = Params;
4113 if( bApproveFiring )
4114 aRet = m_xAllListener->approveFiring( aAllEvent );
4115 else
4116 m_xAllListener->firing( aAllEvent );
4117 return aRet;
4121 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& PropertyName, const Any& Value)
4122 throw( UnknownPropertyException, CannotConvertException,
4123 InvocationTargetException, RuntimeException, std::exception )
4125 (void)PropertyName;
4126 (void)Value;
4130 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& PropertyName)
4131 throw( UnknownPropertyException, RuntimeException, std::exception )
4133 (void)PropertyName;
4135 return Any();
4139 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
4140 throw( RuntimeException, std::exception )
4142 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
4143 return xMethod.is();
4147 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
4148 throw( RuntimeException, std::exception )
4150 Reference< XIdlField > xField = m_xListenerType->getField( Name );
4151 return xField.is();
4155 // create Uno-Service
4156 // 1. Parameter == Prefix-Name of the macro
4157 // 2. Parameter == fully qualified name of the listener
4158 void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
4159 //RTLFUNC(CreateUnoListener)
4161 (void)bWrite;
4163 // We need 2 parameters
4164 if ( rPar.Count() != 3 )
4166 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4167 return;
4170 // get the name of the class of the struct
4171 OUString aPrefixName = rPar.Get(1)->GetOUString();
4172 OUString aListenerClassName = rPar.Get(2)->GetOUString();
4174 // get the CoreReflection
4175 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
4176 if( !xCoreReflection.is() )
4177 return;
4179 // get the AllListenerAdapterService
4180 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
4182 // search the class
4183 Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName );
4184 if( !xClass.is() )
4185 return;
4187 // From 1999-11-30: get the InvocationAdapterFactory
4188 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory =
4189 InvocationAdapterFactory::create( xContext );
4191 BasicAllListener_Impl * p;
4192 Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName );
4193 Any aTmp;
4194 Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp );
4195 if( !xLst.is() )
4196 return;
4198 OUString aClassName = xClass->getName();
4199 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
4200 aTmp = xLst->queryInterface( aClassType );
4201 if( !aTmp.hasValue() )
4202 return;
4204 SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp );
4205 p->xSbxObj = pUnoObj;
4206 p->xSbxObj->SetParent( pBasic );
4208 // #100326 Register listener object to set Parent NULL in Dtor
4209 SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners();
4210 xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() );
4212 // return the object
4213 SbxVariableRef refVar = rPar.Get(0);
4214 refVar->PutObject( p->xSbxObj );
4218 // Represents the DefaultContext property of the ProcessServiceManager
4219 // in the Basic runtime system.
4220 void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
4222 (void)pBasic;
4223 (void)bWrite;
4225 SbxVariableRef refVar = rPar.Get(0);
4227 Any aContextAny( comphelper::getProcessComponentContext() );
4229 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "DefaultContext" ), aContextAny );
4230 refVar->PutObject( (SbUnoObject*)xUnoObj );
4234 // Creates a Basic wrapper object for a strongly typed Uno value
4235 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4236 void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, bool bWrite )
4238 (void)pBasic;
4239 (void)bWrite;
4241 static const char aTypeTypeString[] = "type";
4243 // 2 parameters needed
4244 if ( rPar.Count() != 3 )
4246 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4247 return;
4250 // get the name of the class of the struct
4251 OUString aTypeName = rPar.Get(1)->GetOUString();
4252 SbxVariable* pVal = rPar.Get(2);
4254 if( aTypeName == aTypeTypeString )
4256 SbxDataType eBaseType = pVal->SbxValue::GetType();
4257 OUString aValTypeName;
4258 if( eBaseType == SbxSTRING )
4260 aValTypeName = pVal->GetOUString();
4262 else if( eBaseType == SbxOBJECT )
4264 // XIdlClass?
4265 Reference< XIdlClass > xIdlClass;
4267 SbxBaseRef pObj = pVal->GetObject();
4268 if( pObj && pObj->ISA(SbUnoObject) )
4270 Any aUnoAny = static_cast<SbUnoObject*>((SbxBase*)pObj)->getUnoAny();
4271 aUnoAny >>= xIdlClass;
4274 if( xIdlClass.is() )
4276 aValTypeName = xIdlClass->getName();
4279 Type aType;
4280 bool bSuccess = implGetTypeByName( aValTypeName, aType );
4281 if( bSuccess )
4283 Any aTypeAny( aType );
4284 SbxVariableRef refVar = rPar.Get(0);
4285 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny );
4286 refVar->PutObject( xUnoAnyObject );
4288 return;
4291 // Check the type
4292 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
4293 Any aRet;
4296 aRet = xTypeAccess->getByHierarchicalName( aTypeName );
4298 catch( const NoSuchElementException& e1 )
4300 OUString aNoSuchElementExceptionName( "com.sun.star.container.NoSuchElementException" );
4301 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4302 implGetExceptionMsg( e1, aNoSuchElementExceptionName ) );
4303 return;
4305 Reference< XTypeDescription > xTypeDesc;
4306 aRet >>= xTypeDesc;
4307 TypeClass eTypeClass = xTypeDesc->getTypeClass();
4308 Type aDestType( eTypeClass, aTypeName );
4311 // Preconvert value
4312 Any aVal = sbxToUnoValueImpl( pVal );
4313 Any aConvertedVal = convertAny( aVal, aDestType );
4315 SbxVariableRef refVar = rPar.Get(0);
4316 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal );
4317 refVar->PutObject( xUnoAnyObject );
4322 namespace {
4323 class OMutexBasis
4325 protected:
4326 // this mutex is necessary for OInterfaceContainerHelper
4327 ::osl::Mutex m_aMutex;
4329 } // namespace
4331 typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper;
4333 class ModuleInvocationProxy : public OMutexBasis,
4334 public ModuleInvocationProxyHelper
4336 OUString m_aPrefix;
4337 SbxObjectRef m_xScopeObj;
4338 bool m_bProxyIsClassModuleObject;
4340 ::cppu::OInterfaceContainerHelper m_aListeners;
4342 public:
4343 ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj );
4344 virtual ~ModuleInvocationProxy()
4347 // XInvocation
4348 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw(std::exception) SAL_OVERRIDE;
4349 virtual void SAL_CALL setValue( const OUString& rProperty, const Any& rValue )
4350 throw (UnknownPropertyException, RuntimeException, std::exception) SAL_OVERRIDE;
4351 virtual Any SAL_CALL getValue( const OUString& rProperty )
4352 throw (UnknownPropertyException, RuntimeException, std::exception) SAL_OVERRIDE;
4353 virtual sal_Bool SAL_CALL hasMethod( const OUString& rName ) throw(std::exception) SAL_OVERRIDE;
4354 virtual sal_Bool SAL_CALL hasProperty( const OUString& rProp ) throw(std::exception) SAL_OVERRIDE;
4356 virtual Any SAL_CALL invoke( const OUString& rFunction,
4357 const Sequence< Any >& rParams,
4358 Sequence< sal_Int16 >& rOutParamIndex,
4359 Sequence< Any >& rOutParam )
4360 throw (CannotConvertException, InvocationTargetException,
4361 RuntimeException, std::exception ) SAL_OVERRIDE;
4363 // XComponent
4364 virtual void SAL_CALL dispose() throw(RuntimeException, std::exception) SAL_OVERRIDE;
4365 virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
4366 virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
4369 ModuleInvocationProxy::ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj )
4370 : m_aPrefix( aPrefix + "_" )
4371 , m_xScopeObj( xScopeObj )
4372 , m_aListeners( m_aMutex )
4374 m_bProxyIsClassModuleObject = xScopeObj.Is() && xScopeObj->ISA(SbClassModuleObject);
4377 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw(std::exception)
4379 return Reference< XIntrospectionAccess >();
4382 void SAL_CALL ModuleInvocationProxy::setValue(const OUString& rProperty, const Any& rValue)
4383 throw (UnknownPropertyException, RuntimeException, std::exception)
4385 if( !m_bProxyIsClassModuleObject )
4386 throw UnknownPropertyException();
4388 SolarMutexGuard guard;
4390 OUString aPropertyFunctionName( "Property Set " );
4391 aPropertyFunctionName += m_aPrefix;
4392 aPropertyFunctionName += rProperty;
4394 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4395 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4396 if( pMeth == NULL )
4398 // TODO: Check vba behavior concernig missing function
4399 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4400 throw UnknownPropertyException();
4403 // Setup parameter
4404 SbxArrayRef xArray = new SbxArray;
4405 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4406 unoToSbxValue( (SbxVariable*)xVar, rValue );
4407 xArray->Put( xVar, 1 );
4409 // Call property method
4410 SbxVariableRef xValue = new SbxVariable;
4411 pMeth->SetParameters( xArray );
4412 pMeth->Call( xValue );
4413 pMeth->SetParameters( NULL );
4415 // TODO: OutParameter?
4421 Any SAL_CALL ModuleInvocationProxy::getValue(const OUString& rProperty)
4422 throw (UnknownPropertyException, RuntimeException, std::exception)
4424 if( !m_bProxyIsClassModuleObject )
4426 throw UnknownPropertyException();
4428 SolarMutexGuard guard;
4430 OUString aPropertyFunctionName( "Property Get " );
4431 aPropertyFunctionName += m_aPrefix;
4432 aPropertyFunctionName += rProperty;
4434 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4435 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4436 if( pMeth == NULL )
4438 // TODO: Check vba behavior concernig missing function
4439 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4440 throw UnknownPropertyException();
4443 // Call method
4444 SbxVariableRef xValue = new SbxVariable;
4445 pMeth->Call( xValue );
4446 Any aRet = sbxToUnoValue( xValue );
4447 return aRet;
4450 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const OUString& ) throw(std::exception)
4452 return sal_False;
4455 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const OUString& ) throw(std::exception)
4457 return sal_False;
4460 Any SAL_CALL ModuleInvocationProxy::invoke( const OUString& rFunction,
4461 const Sequence< Any >& rParams,
4462 Sequence< sal_Int16 >&,
4463 Sequence< Any >& )
4464 throw (CannotConvertException, InvocationTargetException,
4465 RuntimeException, std::exception)
4467 SolarMutexGuard guard;
4469 Any aRet;
4470 SbxObjectRef xScopeObj = m_xScopeObj;
4471 if( !xScopeObj.Is() )
4473 return aRet;
4475 OUString aFunctionName = m_aPrefix;
4476 aFunctionName += rFunction;
4478 bool bSetRescheduleBack = false;
4479 bool bOldReschedule = true;
4480 SbiInstance* pInst = GetSbData()->pInst;
4481 if( pInst && pInst->IsCompatibility() )
4483 bOldReschedule = pInst->IsReschedule();
4484 if ( bOldReschedule )
4486 pInst->EnableReschedule( false );
4487 bSetRescheduleBack = true;
4491 SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD );
4492 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4493 if( pMeth == NULL )
4495 // TODO: Check vba behavior concernig missing function
4496 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4497 return aRet;
4500 // Setup parameters
4501 SbxArrayRef xArray;
4502 sal_Int32 nParamCount = rParams.getLength();
4503 if( nParamCount )
4505 xArray = new SbxArray;
4506 const Any *pArgs = rParams.getConstArray();
4507 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
4509 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4510 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
4511 xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
4515 // Call method
4516 SbxVariableRef xValue = new SbxVariable;
4517 if( xArray.Is() )
4518 pMeth->SetParameters( xArray );
4519 pMeth->Call( xValue );
4520 aRet = sbxToUnoValue( xValue );
4521 pMeth->SetParameters( NULL );
4523 if( bSetRescheduleBack )
4524 pInst->EnableReschedule( bOldReschedule );
4526 // TODO: OutParameter?
4528 return aRet;
4531 void SAL_CALL ModuleInvocationProxy::dispose()
4532 throw(RuntimeException, std::exception)
4534 ::osl::MutexGuard aGuard( m_aMutex );
4536 EventObject aEvent( (XComponent*)this );
4537 m_aListeners.disposeAndClear( aEvent );
4539 m_xScopeObj = NULL;
4542 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener )
4543 throw (RuntimeException, std::exception)
4545 m_aListeners.addInterface( xListener );
4548 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener )
4549 throw (RuntimeException, std::exception)
4551 m_aListeners.removeInterface( xListener );
4555 Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType,
4556 const OUString& aPrefix, SbxObjectRef xScopeObj )
4558 Reference< XInterface > xRet;
4560 Reference< XComponentContext > xContext(
4561 comphelper::getProcessComponentContext() );
4562 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4564 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj );
4566 Sequence<Any> args( 3 );
4567 args[0] <<= aControlAny;
4568 args[1] <<= aVBAType;
4569 args[2] <<= xProxy;
4573 xRet = xServiceMgr->createInstanceWithArgumentsAndContext(
4574 OUString( "com.sun.star.custom.UnoComListener"),
4575 args, xContext );
4577 catch( const Exception& )
4579 implHandleAnyException( ::cppu::getCaughtException() );
4582 return xRet;
4585 typedef std::vector< WeakReference< XComponent > > ComponentRefVector;
4587 struct StarBasicDisposeItem
4589 StarBASIC* m_pBasic;
4590 SbxArrayRef m_pRegisteredVariables;
4591 ComponentRefVector m_vComImplementsObjects;
4593 StarBasicDisposeItem( StarBASIC* pBasic )
4594 : m_pBasic( pBasic )
4596 m_pRegisteredVariables = new SbxArray();
4600 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector;
4602 static DisposeItemVector GaDisposeItemVector;
4604 static DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic )
4606 DisposeItemVector::iterator it;
4607 for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it )
4609 StarBasicDisposeItem* pItem = *it;
4610 if( pItem->m_pBasic == pBasic )
4611 return it;
4613 return GaDisposeItemVector.end();
4616 static StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic )
4618 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4619 StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL;
4620 if( pItem == NULL )
4622 pItem = new StarBasicDisposeItem( pBasic );
4623 GaDisposeItemVector.push_back( pItem );
4625 return pItem;
4628 void registerComponentToBeDisposedForBasic
4629 ( Reference< XComponent > xComponent, StarBASIC* pBasic )
4631 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4632 pItem->m_vComImplementsObjects.push_back( xComponent );
4635 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic )
4637 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4638 SbxArray* pArray = pItem->m_pRegisteredVariables;
4639 pArray->Put( pVar, pArray->Count() );
4642 void disposeComVariablesForBasic( StarBASIC* pBasic )
4644 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4645 if( it != GaDisposeItemVector.end() )
4647 StarBasicDisposeItem* pItem = *it;
4649 SbxArray* pArray = pItem->m_pRegisteredVariables;
4650 sal_uInt16 nCount = pArray->Count();
4651 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4653 SbxVariable* pVar = pArray->Get( i );
4654 pVar->ClearComListener();
4657 ComponentRefVector& rv = pItem->m_vComImplementsObjects;
4658 ComponentRefVector::iterator itCRV;
4659 for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV )
4663 Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW );
4664 xComponent->dispose();
4666 catch(const Exception& )
4670 delete pItem;
4671 GaDisposeItemVector.erase( it );
4676 // Handle module implements mechanism for OLE types
4677 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
4679 // For now: Take first interface that allows to instantiate COM wrapper
4680 // TODO: Check if support for multiple interfaces is needed
4682 Reference< XComponentContext > xContext(
4683 comphelper::getProcessComponentContext() );
4684 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4685 Reference< XSingleServiceFactory > xComImplementsFactory
4687 xServiceMgr->createInstanceWithContext(
4688 OUString( "com.sun.star.custom.ComImplementsFactory"), xContext ),
4689 UNO_QUERY
4691 if( !xComImplementsFactory.is() )
4692 return false;
4694 bool bSuccess = false;
4696 SbxArray* pModIfaces = pClassData->mxIfaces;
4697 sal_uInt16 nCount = pModIfaces->Count();
4698 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4700 SbxVariable* pVar = pModIfaces->Get( i );
4701 OUString aIfaceName = pVar->GetName();
4703 if( !aIfaceName.isEmpty() )
4705 OUString aPureIfaceName = aIfaceName;
4706 sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.');
4707 if ( indexLastDot > -1 )
4709 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 );
4711 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject );
4713 Sequence<Any> args( 2 );
4714 args[0] <<= aIfaceName;
4715 args[1] <<= xProxy;
4717 Reference< XInterface > xRet;
4718 bSuccess = false;
4721 xRet = xComImplementsFactory->createInstanceWithArguments( args );
4722 bSuccess = true;
4724 catch( const Exception& )
4726 implHandleAnyException( ::cppu::getCaughtException() );
4729 if( bSuccess )
4731 Reference< XComponent > xComponent( xProxy, UNO_QUERY );
4732 if( xComponent.is() )
4734 StarBASIC* pParentBasic = NULL;
4735 SbxObject* pCurObject = this;
4738 SbxObject* pObjParent = pCurObject->GetParent();
4739 pParentBasic = PTR_CAST( StarBASIC, pObjParent );
4740 pCurObject = pObjParent;
4742 while( pParentBasic == NULL && pCurObject != NULL );
4744 OSL_ASSERT( pParentBasic != NULL );
4745 registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
4748 o_rRetAny <<= xRet;
4749 break;
4754 return bSuccess;
4758 // Due to an incorrect behavior IE returns an object instead of a string
4759 // in some scenarios. Calling toString at the object may correct this.
4760 // Helper function used in sbxvalue.cxx
4761 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
4763 bool bSuccess = false;
4765 SbUnoObject* pUnoObj = NULL;
4766 if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,pObj)) != NULL )
4768 // Only for native COM objects
4769 if( pUnoObj->isNativeCOMObject() )
4771 SbxVariableRef pMeth = pObj->Find( OUString( "toString" ), SbxCLASS_METHOD );
4772 if ( pMeth.Is() )
4774 SbxValues aRes;
4775 pMeth->Get( aRes );
4776 pVal->Put( aRes );
4777 bSuccess = true;
4781 return bSuccess;
4784 Any StructRefInfo::getValue()
4786 Any aRet;
4787 uno_any_destruct(
4788 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4789 typelib_TypeDescription * pTD = 0;
4790 maType.getDescription(&pTD);
4791 uno_any_construct(
4792 &aRet, getInst(), pTD,
4793 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
4794 typelib_typedescription_release(pTD);
4795 return aRet;
4798 bool StructRefInfo::setValue( const Any& rValue )
4800 return uno_type_assignData( getInst(),
4801 maType.getTypeLibType(),
4802 const_cast<void*>(rValue.getValue()),
4803 rValue.getValueTypeRef(),
4804 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
4805 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
4806 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4809 OUString StructRefInfo::getTypeName() const
4811 return maType.getTypeName();
4814 void* StructRefInfo::getInst()
4816 return const_cast<char *>(static_cast<char const *>(maAny.getValue()) + mnPos);
4819 TypeClass StructRefInfo::getTypeClass() const
4821 return maType.getTypeClass();
4824 SbUnoStructRefObject::SbUnoStructRefObject( const OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false )
4826 SetClassName( OUString( maMemberInfo.getTypeName() ) );
4829 SbUnoStructRefObject::~SbUnoStructRefObject()
4831 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4832 delete it->second;
4835 void SbUnoStructRefObject::initMemberCache()
4837 if ( mbMemberCacheInit )
4838 return;
4839 sal_Int32 nAll = 0;
4840 typelib_TypeDescription * pTD = 0;
4841 maMemberInfo.getType().getDescription(&pTD);
4842 typelib_CompoundTypeDescription * pCompTypeDescr = reinterpret_cast<typelib_CompoundTypeDescription *>(pTD);
4843 for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4844 nAll += pCompTypeDescr->nMembers;
4845 for ( pCompTypeDescr = reinterpret_cast<typelib_CompoundTypeDescription *>(pTD); pCompTypeDescr;
4846 pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4848 typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs;
4849 rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames;
4850 sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets;
4851 for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; )
4853 OUString aName( ppNames[nPos] );
4854 maFields[ aName ] = new StructRefInfo( maMemberInfo.getRootAnyRef(), ppTypeRefs[nPos], maMemberInfo.getPos() + pMemberOffsets[nPos] );
4857 typelib_typedescription_release(pTD);
4858 mbMemberCacheInit = true;
4861 SbxVariable* SbUnoStructRefObject::Find( const OUString& rName, SbxClassType t )
4863 SbxVariable* pRes = SbxObject::Find( rName, t );
4864 if ( !pRes )
4866 if ( !mbMemberCacheInit )
4867 initMemberCache();
4868 StructFieldInfo::iterator it = maFields.find( OUString( rName ).toAsciiUpperCase() );
4869 if ( it != maFields.end() )
4871 SbxDataType eSbxType;
4872 eSbxType = unoToSbxType( it->second->getTypeClass() );
4873 SbxDataType eRealSbxType = eSbxType;
4874 Property aProp;
4875 aProp.Name = rName;
4876 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4877 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4878 SbxVariableRef xVarRef = pProp;
4879 QuickInsert( (SbxVariable*)xVarRef );
4880 pRes = xVarRef;
4884 if( !pRes )
4886 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
4887 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
4888 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
4890 // Create
4891 implCreateDbgProperties();
4893 // Now they have to be found regular
4894 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
4898 return pRes;
4901 // help method to create the dbg_-Properties
4902 void SbUnoStructRefObject::implCreateDbgProperties()
4904 Property aProp;
4906 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4907 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
4908 QuickInsert( (SbxVariable*)xVarRef );
4910 // Id == -2: output the properties
4911 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
4912 QuickInsert( (SbxVariable*)xVarRef );
4914 // Id == -3: output the Methods
4915 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
4916 QuickInsert( (SbxVariable*)xVarRef );
4919 void SbUnoStructRefObject::implCreateAll()
4921 // throw away all existing methods and properties
4922 pMethods = new SbxArray;
4923 pProps = new SbxArray;
4925 if (!mbMemberCacheInit)
4926 initMemberCache();
4928 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4930 const OUString& rName = it->first;
4931 SbxDataType eSbxType;
4932 eSbxType = unoToSbxType( it->second->getTypeClass() );
4933 SbxDataType eRealSbxType = eSbxType;
4934 Property aProp;
4935 aProp.Name = rName;
4936 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4937 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4938 SbxVariableRef xVarRef = pProp;
4939 QuickInsert( (SbxVariable*)xVarRef );
4942 // Create Dbg_-Properties
4943 implCreateDbgProperties();
4946 // output the value
4947 Any SbUnoStructRefObject::getUnoAny()
4949 return maMemberInfo.getValue();
4952 OUString SbUnoStructRefObject::Impl_DumpProperties()
4954 OUStringBuffer aRet;
4955 aRet.appendAscii("Properties of object ");
4956 aRet.append( getDbgObjectName() );
4958 sal_uInt16 nPropCount = pProps->Count();
4959 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
4960 for( sal_uInt16 i = 0; i < nPropCount; i++ )
4962 SbxVariable* pVar = pProps->Get( i );
4963 if( pVar )
4965 OUStringBuffer aPropStr;
4966 if( (i % nPropsPerLine) == 0 )
4968 aPropStr.appendAscii( "\n" );
4970 // output the type and name
4971 // Is it in Uno a sequence?
4972 SbxDataType eType = pVar->GetFullType();
4974 OUString aName( pVar->GetName() );
4975 StructFieldInfo::iterator it = maFields.find( aName );
4977 if ( it != maFields.end() )
4979 const StructRefInfo& rPropInfo = *it->second;
4981 if( eType == SbxOBJECT )
4983 if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE )
4985 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
4989 aPropStr.append( Dbg_SbxDataType2String( eType ) );
4991 aPropStr.appendAscii( " " );
4992 aPropStr.append( pVar->GetName() );
4994 if( i == nPropCount - 1 )
4996 aPropStr.appendAscii( "\n" );
4998 else
5000 aPropStr.appendAscii( "; " );
5002 aRet.append( aPropStr.makeStringAndClear() );
5005 return aRet.makeStringAndClear();
5008 void SbUnoStructRefObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
5009 const SfxHint& rHint, const TypeId& rHintType )
5011 if ( !mbMemberCacheInit )
5012 initMemberCache();
5013 const SbxHint* pHint = dynamic_cast<const SbxHint*>(&rHint);
5014 if( pHint )
5016 SbxVariable* pVar = pHint->GetVar();
5017 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
5018 if( pProp )
5020 StructFieldInfo::iterator it = maFields.find( pProp->GetName() );
5021 // handle get/set of members of struct
5022 if( pHint->GetId() == SBX_HINT_DATAWANTED )
5024 // Test-Properties
5025 sal_Int32 nId = pProp->nId;
5026 if( nId < 0 )
5028 // Id == -1: Display implemented interfaces according the ClassProvider
5029 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
5031 OUStringBuffer aRet;
5032 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
5033 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
5035 pVar->PutString( aRet.makeStringAndClear() );
5037 // Id == -2: output properties
5038 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
5040 // by now all properties must be established
5041 implCreateAll();
5042 OUString aRetStr = Impl_DumpProperties();
5043 pVar->PutString( aRetStr );
5045 // Id == -3: output the methods
5046 else if( nId == -3 ) // Property ID_DBG_METHODS
5048 // by now all properties must be established
5049 implCreateAll();
5050 OUStringBuffer aRet;
5051 aRet.appendAscii("Methods of object ");
5052 aRet.append( getDbgObjectName() );
5053 aRet.appendAscii( "\nNo methods found\n" );
5054 pVar->PutString( aRet.makeStringAndClear() );
5056 return;
5059 if ( it != maFields.end() )
5061 Any aRetAny = it->second->getValue();
5062 unoToSbxValue( pVar, aRetAny );
5064 else
5065 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5067 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
5069 if ( it != maFields.end() )
5071 // take over the value from Uno to Sbx
5072 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
5073 it->second->setValue( aAnyValue );
5075 else
5076 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5079 else
5080 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
5084 StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName )
5086 if (!mbMemberCacheInit)
5088 initMemberCache();
5090 StructFieldInfo::iterator it = maFields.find( rMemberName );
5092 css::uno::Type aFoundType;
5093 sal_Int32 nFoundPos = -1;
5095 if ( it != maFields.end() )
5097 aFoundType = it->second->getType();
5098 nFoundPos = it->second->getPos();
5100 StructRefInfo aRet( maMemberInfo.getRootAnyRef(), aFoundType, nFoundPos );
5101 return aRet;
5104 OUString SbUnoStructRefObject::getDbgObjectName()
5106 OUString aName = GetClassName();
5107 if( aName.isEmpty() )
5109 aName += "Unknown";
5111 OUStringBuffer aRet;
5112 if( aName.getLength() > 20 )
5114 aRet.appendAscii( "\n" );
5116 aRet.appendAscii( "\"" );
5117 aRet.append( aName );
5118 aRet.appendAscii( "\":" );
5119 return aRet.makeStringAndClear();
5122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */