fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / basic / source / classes / sbunoobj.cxx
blobfbc0f58a09f82780983555cbdb5e9969cc64267f
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/Introspection.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/bridge/oleautomation/NamedArgument.hpp>
65 #include <com/sun/star/bridge/oleautomation/Date.hpp>
66 #include <com/sun/star/bridge/oleautomation/Decimal.hpp>
67 #include <com/sun/star/bridge/oleautomation/Currency.hpp>
68 #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp>
69 #include <com/sun/star/script/XAutomationInvocation.hpp>
71 using com::sun::star::uno::Reference;
72 using namespace com::sun::star::uno;
73 using namespace com::sun::star::lang;
74 using namespace com::sun::star::reflection;
75 using namespace com::sun::star::beans;
76 using namespace com::sun::star::script;
77 using namespace com::sun::star::container;
78 using namespace com::sun::star::bridge;
79 using namespace cppu;
82 #include<basic/sbstar.hxx>
83 #include<basic/sbuno.hxx>
84 #include<basic/sberrors.hxx>
85 #include<sbunoobj.hxx>
86 #include"sbjsmod.hxx"
87 #include<basic/basmgr.hxx>
88 #include<sbintern.hxx>
89 #include<runtime.hxx>
91 #include<math.h>
92 #include <boost/unordered_map.hpp>
93 #include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
94 #include <com/sun/star/reflection/XConstantsTypeDescription.hpp>
96 TYPEINIT1(SbUnoMethod,SbxMethod)
97 TYPEINIT1(SbUnoProperty,SbxProperty)
98 TYPEINIT1(SbUnoObject,SbxObject)
99 TYPEINIT1(SbUnoStructRefObject,SbxObject)
100 TYPEINIT1(SbUnoClass,SbxObject)
101 TYPEINIT1(SbUnoService,SbxObject)
102 TYPEINIT1(SbUnoServiceCtor,SbxMethod)
103 TYPEINIT1(SbUnoSingleton,SbxObject)
105 typedef WeakImplHelper1< XAllListener > BasicAllListenerHelper;
107 // Identifiers for creating the strings for dbg_Properties
108 static char const ID_DBG_SUPPORTEDINTERFACES[] = "Dbg_SupportedInterfaces";
109 static char const ID_DBG_PROPERTIES[] = "Dbg_Properties";
110 static char const ID_DBG_METHODS[] = "Dbg_Methods";
112 static char const aSeqLevelStr[] = "[]";
113 static char const defaultNameSpace[] = "ooo.vba";
115 // Gets the default property for an uno object. Note: There is some
116 // redirection built in. The property name specifies the name
117 // of the default property.
119 bool SbUnoObject::getDefaultPropName( SbUnoObject* pUnoObj, OUString& sDfltProp )
121 bool result = false;
122 Reference< XDefaultProperty> xDefaultProp( pUnoObj->maTmpUnoObj, UNO_QUERY );
123 if ( xDefaultProp.is() )
125 sDfltProp = xDefaultProp->getDefaultPropertyName();
126 if ( !sDfltProp.isEmpty() )
127 result = true;
129 return result;
132 SbxVariable* getDefaultProp( SbxVariable* pRef )
134 SbxVariable* pDefaultProp = NULL;
135 if ( pRef->GetType() == SbxOBJECT )
137 SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pRef);
138 if ( !pObj )
140 SbxBase* pObjVarObj = pRef->GetObject();
141 pObj = PTR_CAST(SbxObject,pObjVarObj);
143 if ( pObj && pObj->ISA(SbUnoObject) )
145 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj);
146 pDefaultProp = pUnoObj->GetDfltProperty();
149 return pDefaultProp;
152 void SetSbUnoObjectDfltPropName( SbxObject* pObj )
154 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*) pObj);
155 if ( pUnoObj )
157 OUString sDfltPropName;
159 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
161 OSL_TRACE("SetSbUnoObjectDfltPropName setting dflt prop for %s", OUStringToOString( pObj->GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
162 pUnoObj->SetDfltProperty( sDfltPropName );
167 // save CoreReflection statically
168 Reference< XIdlReflection > getCoreReflection_Impl( void )
170 static Reference< XIdlReflection > xCoreReflection;
172 // Do we have already CoreReflection; if not obtain it
173 if( !xCoreReflection.is() )
175 Reference< XComponentContext > xContext(
176 comphelper::getProcessComponentContext() );
177 if( xContext.is() )
179 xContext->getValueByName(
180 OUString( "/singletons/com.sun.star.reflection.theCoreReflection" ) )
181 >>= xCoreReflection;
182 OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessible!?" );
184 if( !xCoreReflection.is() )
186 throw DeploymentException(
187 OUString( "/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible" ),
188 Reference< XInterface >() );
191 return xCoreReflection;
194 // save CoreReflection statically
195 Reference< XHierarchicalNameAccess > getCoreReflection_HierarchicalNameAccess_Impl( void )
197 static Reference< XHierarchicalNameAccess > xCoreReflection_HierarchicalNameAccess;
199 if( !xCoreReflection_HierarchicalNameAccess.is() )
201 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
202 if( xCoreReflection.is() )
204 xCoreReflection_HierarchicalNameAccess =
205 Reference< XHierarchicalNameAccess >( xCoreReflection, UNO_QUERY );
208 return xCoreReflection_HierarchicalNameAccess;
211 // Hold TypeProvider statically
212 Reference< XHierarchicalNameAccess > getTypeProvider_Impl( void )
214 static Reference< XHierarchicalNameAccess > xAccess;
216 // Do we have already CoreReflection; if not obtain it
217 if( !xAccess.is() )
219 Reference< XComponentContext > xContext(
220 comphelper::getProcessComponentContext() );
221 if( xContext.is() )
223 xContext->getValueByName(
224 OUString( "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) )
225 >>= xAccess;
226 OSL_ENSURE( xAccess.is(), "### TypeDescriptionManager singleton not accessible!?" );
228 if( !xAccess.is() )
230 throw DeploymentException(
231 OUString("/singletons/com.sun.star.reflection.theTypeDescriptionManager singleton not accessible"),
232 Reference< XInterface >() );
235 return xAccess;
238 // Hold TypeConverter statically
239 Reference< XTypeConverter > getTypeConverter_Impl( void )
241 static Reference< XTypeConverter > xTypeConverter;
243 // Do we have already CoreReflection; if not obtain it
244 if( !xTypeConverter.is() )
246 Reference< XComponentContext > xContext(
247 comphelper::getProcessComponentContext() );
248 if( xContext.is() )
250 xTypeConverter = Converter::create(xContext);
252 if( !xTypeConverter.is() )
254 throw DeploymentException(
255 OUString("com.sun.star.script.Converter service not accessible"),
256 Reference< XInterface >() );
259 return xTypeConverter;
263 // #111851 factory function to create an OLE object
264 SbUnoObject* createOLEObject_Impl( const OUString& aType )
266 static Reference< XMultiServiceFactory > xOLEFactory;
267 static bool bNeedsInit = true;
269 if( bNeedsInit )
271 bNeedsInit = false;
273 Reference< XComponentContext > xContext(
274 comphelper::getProcessComponentContext() );
275 if( xContext.is() )
277 Reference<XMultiComponentFactory> xSMgr = xContext->getServiceManager();
278 xOLEFactory = Reference<XMultiServiceFactory>(
279 xSMgr->createInstanceWithContext(
280 OUString( "com.sun.star.bridge.OleObjectFactory"),
281 xContext ), UNO_QUERY );
285 SbUnoObject* pUnoObj = NULL;
286 if( xOLEFactory.is() )
288 // some type names available in VBA can not be directly used in COM
289 OUString aOLEType = aType;
290 if ( aOLEType == "SAXXMLReader30" )
292 aOLEType = "Msxml2.SAXXMLReader.3.0";
294 Reference< XInterface > xOLEObject = xOLEFactory->createInstance( aOLEType );
295 if( xOLEObject.is() )
297 Any aAny;
298 aAny <<= xOLEObject;
299 pUnoObj = new SbUnoObject( aType, aAny );
300 OUString sDfltPropName;
302 if ( SbUnoObject::getDefaultPropName( pUnoObj, sDfltPropName ) )
303 pUnoObj->SetDfltProperty( sDfltPropName );
306 return pUnoObj;
310 namespace
312 void lcl_indent( OUStringBuffer& _inout_rBuffer, sal_Int32 _nLevel )
314 while ( _nLevel-- > 0 )
316 _inout_rBuffer.appendAscii( " " );
321 void implAppendExceptionMsg( OUStringBuffer& _inout_rBuffer, const Exception& _e, const OUString& _rExceptionType, sal_Int32 _nLevel )
323 _inout_rBuffer.appendAscii( "\n" );
324 lcl_indent( _inout_rBuffer, _nLevel );
325 _inout_rBuffer.appendAscii( "Type: " );
327 if ( _rExceptionType.isEmpty() )
328 _inout_rBuffer.appendAscii( "Unknown" );
329 else
330 _inout_rBuffer.append( _rExceptionType );
332 _inout_rBuffer.appendAscii( "\n" );
333 lcl_indent( _inout_rBuffer, _nLevel );
334 _inout_rBuffer.appendAscii( "Message: " );
335 _inout_rBuffer.append( _e.Message );
339 // construct an error message for the exception
340 OUString implGetExceptionMsg( const Exception& e, const OUString& aExceptionType_ )
342 OUStringBuffer aMessageBuf;
343 implAppendExceptionMsg( aMessageBuf, e, aExceptionType_, 0 );
344 return aMessageBuf.makeStringAndClear();
347 OUString implGetExceptionMsg( const Any& _rCaughtException )
349 OSL_PRECOND( _rCaughtException.getValueTypeClass() == TypeClass_EXCEPTION, "implGetExceptionMsg: illegal argument!" );
350 if ( _rCaughtException.getValueTypeClass() != TypeClass_EXCEPTION )
352 return OUString();
354 return implGetExceptionMsg( *static_cast< const Exception* >( _rCaughtException.getValue() ), _rCaughtException.getValueTypeName() );
357 Any convertAny( const Any& rVal, const Type& aDestType )
359 Any aConvertedVal;
360 Reference< XTypeConverter > xConverter = getTypeConverter_Impl();
363 aConvertedVal = xConverter->convertTo( rVal, aDestType );
365 catch( const IllegalArgumentException& )
367 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
368 implGetExceptionMsg( ::cppu::getCaughtException() ) );
369 return aConvertedVal;
371 catch( const CannotConvertException& e2 )
373 OUString aCannotConvertExceptionName( "com.sun.star.lang.IllegalArgumentException");
374 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
375 implGetExceptionMsg( e2, aCannotConvertExceptionName ) );
376 return aConvertedVal;
378 return aConvertedVal;
382 // #105565 Special Object to wrap a strongly typed Uno Any
383 TYPEINIT1(SbUnoAnyObject,SbxObject)
386 // TODO: source out later
387 Reference<XIdlClass> TypeToIdlClass( const Type& rType )
389 // register void as default class
390 Reference<XIdlClass> xRetClass;
391 typelib_TypeDescription * pTD = 0;
392 rType.getDescription( &pTD );
394 if( pTD )
396 OUString sOWName( pTD->pTypeName );
397 Reference< XIdlReflection > xRefl = getCoreReflection_Impl();
398 xRetClass = xRefl->forName( sOWName );
400 return xRetClass;
403 // Exception type unknown
404 template< class EXCEPTION >
405 OUString implGetExceptionMsg( const EXCEPTION& e )
407 return implGetExceptionMsg( e, ::getCppuType( &e ).getTypeName() );
410 void implHandleBasicErrorException( BasicErrorException& e )
412 SbError nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)e.ErrorCode );
413 StarBASIC::Error( nError, e.ErrorMessageArgument );
416 void implHandleWrappedTargetException( const Any& _rWrappedTargetException )
418 Any aExamine( _rWrappedTargetException );
420 // completely strip the first InvocationTargetException, its error message isn't of any
421 // interest to the user, it just says something like "invoking the UNO method went wrong.".
422 InvocationTargetException aInvocationError;
423 if ( aExamine >>= aInvocationError )
424 aExamine = aInvocationError.TargetException;
426 BasicErrorException aBasicError;
428 SbError nError( ERRCODE_BASIC_EXCEPTION );
429 OUStringBuffer aMessageBuf;
431 // strip any other WrappedTargetException instances, but this time preserve the error messages.
432 WrappedTargetException aWrapped;
433 sal_Int32 nLevel = 0;
434 while ( aExamine >>= aWrapped )
436 // special handling for BasicErrorException errors
437 if ( aWrapped.TargetException >>= aBasicError )
439 nError = StarBASIC::GetSfxFromVBError( (sal_uInt16)aBasicError.ErrorCode );
440 aMessageBuf.append( aBasicError.ErrorMessageArgument );
441 aExamine.clear();
442 break;
445 // append this round's message
446 implAppendExceptionMsg( aMessageBuf, aWrapped, aExamine.getValueTypeName(), nLevel );
447 if ( aWrapped.TargetException.getValueTypeClass() == TypeClass_EXCEPTION )
448 // there is a next chain element
449 aMessageBuf.appendAscii( "\nTargetException:" );
451 // next round
452 aExamine = aWrapped.TargetException;
453 ++nLevel;
456 if ( aExamine.getValueTypeClass() == TypeClass_EXCEPTION )
458 // the last element in the chain is still an exception, but no WrappedTargetException
459 implAppendExceptionMsg( aMessageBuf, *static_cast< const Exception* >( aExamine.getValue() ), aExamine.getValueTypeName(), nLevel );
462 StarBASIC::Error( nError, aMessageBuf.makeStringAndClear() );
465 static void implHandleAnyException( const Any& _rCaughtException )
467 BasicErrorException aBasicError;
468 WrappedTargetException aWrappedError;
470 if ( _rCaughtException >>= aBasicError )
472 implHandleBasicErrorException( aBasicError );
474 else if ( _rCaughtException >>= aWrappedError )
476 implHandleWrappedTargetException( _rCaughtException );
478 else
480 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( _rCaughtException ) );
484 // NativeObjectWrapper handling
485 struct ObjectItem
487 SbxObjectRef m_xNativeObj;
489 ObjectItem( void )
491 ObjectItem( SbxObject* pNativeObj )
492 : m_xNativeObj( pNativeObj )
496 typedef std::vector< ObjectItem > NativeObjectWrapperVector;
497 class GaNativeObjectWrapperVector : public rtl::Static<NativeObjectWrapperVector, GaNativeObjectWrapperVector> {};
499 void clearNativeObjectWrapperVector( void )
501 GaNativeObjectWrapperVector::get().clear();
504 static sal_uInt32 lcl_registerNativeObjectWrapper( SbxObject* pNativeObj )
506 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
507 sal_uInt32 nIndex = rNativeObjectWrapperVector.size();
508 rNativeObjectWrapperVector.push_back( ObjectItem( pNativeObj ) );
509 return nIndex;
512 static SbxObject* lcl_getNativeObject( sal_uInt32 nIndex )
514 SbxObjectRef xRetObj;
515 NativeObjectWrapperVector &rNativeObjectWrapperVector = GaNativeObjectWrapperVector::get();
516 if( nIndex < rNativeObjectWrapperVector.size() )
518 ObjectItem& rItem = rNativeObjectWrapperVector[ nIndex ];
519 xRetObj = rItem.m_xNativeObj;
521 return xRetObj;
524 // convert from Uno to Sbx
525 SbxDataType unoToSbxType( TypeClass eType )
527 SbxDataType eRetType = SbxVOID;
529 switch( eType )
531 case TypeClass_INTERFACE:
532 case TypeClass_TYPE:
533 case TypeClass_STRUCT:
534 case TypeClass_EXCEPTION: eRetType = SbxOBJECT; break;
536 case TypeClass_ENUM: eRetType = SbxLONG; break;
537 case TypeClass_SEQUENCE:
538 eRetType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
539 break;
542 case TypeClass_ANY: eRetType = SbxVARIANT; break;
543 case TypeClass_BOOLEAN: eRetType = SbxBOOL; break;
544 case TypeClass_CHAR: eRetType = SbxCHAR; break;
545 case TypeClass_STRING: eRetType = SbxSTRING; break;
546 case TypeClass_FLOAT: eRetType = SbxSINGLE; break;
547 case TypeClass_DOUBLE: eRetType = SbxDOUBLE; break;
548 case TypeClass_BYTE: eRetType = SbxINTEGER; break;
549 case TypeClass_SHORT: eRetType = SbxINTEGER; break;
550 case TypeClass_LONG: eRetType = SbxLONG; break;
551 case TypeClass_HYPER: eRetType = SbxSALINT64; break;
552 case TypeClass_UNSIGNED_SHORT: eRetType = SbxUSHORT; break;
553 case TypeClass_UNSIGNED_LONG: eRetType = SbxULONG; break;
554 case TypeClass_UNSIGNED_HYPER: eRetType = SbxSALUINT64;break;
555 default: break;
557 return eRetType;
560 SbxDataType unoToSbxType( const Reference< XIdlClass >& xIdlClass )
562 SbxDataType eRetType = SbxVOID;
563 if( xIdlClass.is() )
565 TypeClass eType = xIdlClass->getTypeClass();
566 eRetType = unoToSbxType( eType );
568 return eRetType;
571 static void implSequenceToMultiDimArray( SbxDimArray*& pArray, Sequence< sal_Int32 >& indices, Sequence< sal_Int32 >& sizes, const Any& aValue, sal_Int32& dimension, sal_Bool bIsZeroIndex, Type* pType = NULL )
573 Type aType = aValue.getValueType();
574 TypeClass eTypeClass = aType.getTypeClass();
576 sal_Int32 dimCopy = dimension;
578 if ( eTypeClass == TypeClass_SEQUENCE )
580 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
581 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
582 typelib_TypeDescription * pTD = 0;
583 aType.getDescription( &pTD );
584 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
585 ::typelib_typedescription_release( pTD );
587 sal_Int32 nLen = xIdlArray->getLen( aValue );
588 for ( sal_Int32 index = 0; index < nLen; ++index )
590 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)index );
591 // This detects the dimension were currently processing
592 if ( dimCopy == dimension )
594 ++dimCopy;
595 if ( sizes.getLength() < dimCopy )
597 sizes.realloc( sizes.getLength() + 1 );
598 sizes[ sizes.getLength() - 1 ] = nLen;
599 indices.realloc( indices.getLength() + 1 );
603 if ( bIsZeroIndex )
604 indices[ dimCopy - 1 ] = index;
605 else
606 indices[ dimCopy - 1] = index + 1;
608 implSequenceToMultiDimArray( pArray, indices, sizes, aElementAny, dimCopy, bIsZeroIndex, &aElementType );
612 else
614 if ( indices.getLength() < 1 )
616 // Should never ever get here ( indices.getLength()
617 // should equal number of dimensions in the array )
618 // And that should at least be 1 !
619 // #QUESTION is there a better error?
620 StarBASIC::Error( SbERR_INVALID_OBJECT );
621 return;
624 SbxDataType eSbxElementType = unoToSbxType( pType ? pType->getTypeClass() : aValue.getValueTypeClass() );
625 if ( !pArray )
627 pArray = new SbxDimArray( eSbxElementType );
628 sal_Int32 nIndexLen = indices.getLength();
630 // Dimension the array
631 for ( sal_Int32 index = 0; index < nIndexLen; ++index )
633 if ( bIsZeroIndex )
634 pArray->unoAddDim32( 0, sizes[ index ] - 1);
635 else
636 pArray->unoAddDim32( 1, sizes[ index ] );
641 if ( pArray )
643 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
644 unoToSbxValue( (SbxVariable*)xVar, aValue );
646 sal_Int32* pIndices = indices.getArray();
647 pArray->Put32( (SbxVariable*)xVar, pIndices );
653 void unoToSbxValue( SbxVariable* pVar, const Any& aValue )
655 Type aType = aValue.getValueType();
656 TypeClass eTypeClass = aType.getTypeClass();
657 switch( eTypeClass )
659 case TypeClass_TYPE:
661 // Map Type to IdlClass
662 Type aType_;
663 aValue >>= aType_;
664 Reference<XIdlClass> xClass = TypeToIdlClass( aType_ );
665 Any aClassAny;
666 aClassAny <<= xClass;
668 // instantiate SbUnoObject
669 OUString aName;
670 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aClassAny );
671 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
673 // If the object is invalid deliver zero
674 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
676 pVar->PutObject( NULL );
678 else
680 pVar->PutObject( xWrapper );
683 break;
684 // Interfaces and Structs must be wrapped in a SbUnoObject
685 case TypeClass_INTERFACE:
686 case TypeClass_STRUCT:
687 case TypeClass_EXCEPTION:
689 if( eTypeClass == TypeClass_STRUCT )
691 ArrayWrapper aWrap;
692 NativeObjectWrapper aNativeObjectWrapper;
693 if ( (aValue >>= aWrap) )
695 SbxDimArray* pArray = NULL;
696 Sequence< sal_Int32 > indices;
697 Sequence< sal_Int32 > sizes;
698 sal_Int32 dimension = 0;
699 implSequenceToMultiDimArray( pArray, indices, sizes, aWrap.Array, dimension, aWrap.IsZeroIndex );
700 if ( pArray )
702 SbxDimArrayRef xArray = pArray;
703 sal_uInt16 nFlags = pVar->GetFlags();
704 pVar->ResetFlag( SBX_FIXED );
705 pVar->PutObject( (SbxDimArray*)xArray );
706 pVar->SetFlags( nFlags );
708 else
709 pVar->PutEmpty();
710 break;
712 else if ( (aValue >>= aNativeObjectWrapper) )
714 sal_uInt32 nIndex = 0;
715 if( (aNativeObjectWrapper.ObjectId >>= nIndex) )
717 SbxObject* pObj = lcl_getNativeObject( nIndex );
718 pVar->PutObject( pObj );
720 else
721 pVar->PutEmpty();
722 break;
724 else
726 SbiInstance* pInst = GetSbData()->pInst;
727 if( pInst && pInst->IsCompatibility() )
729 oleautomation::Date aDate;
730 if( (aValue >>= aDate) )
732 pVar->PutDate( aDate.Value );
733 break;
735 else
737 oleautomation::Decimal aDecimal;
738 if( (aValue >>= aDecimal) )
740 pVar->PutDecimal( aDecimal );
741 break;
743 else
745 oleautomation::Currency aCurrency;
746 if( (aValue >>= aCurrency) )
748 pVar->PutCurrency( aCurrency.Value );
749 break;
756 // instantiate a SbUnoObject
757 OUString aName;
758 SbUnoObject* pSbUnoObject = new SbUnoObject( aName, aValue );
759 //If this is called externally e.g. from the scripting
760 //framework then there is no 'active' runtime the default property will not be set up
761 //only a vba object will have XDefaultProp set anyway so... this
762 //test seems a bit of overkill
763 //if ( SbiRuntime::isVBAEnabled() )
765 OUString sDfltPropName;
767 if ( SbUnoObject::getDefaultPropName( pSbUnoObject, sDfltPropName ) )
769 pSbUnoObject->SetDfltProperty( sDfltPropName );
772 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
774 // If the object is invalid deliver zero
775 if( pSbUnoObject->getUnoAny().getValueType().getTypeClass() == TypeClass_VOID )
777 pVar->PutObject( NULL );
779 else
781 pVar->PutObject( xWrapper );
784 break;
787 case TypeClass_ENUM:
789 sal_Int32 nEnum = 0;
790 enum2int( nEnum, aValue );
791 pVar->PutLong( nEnum );
793 break;
795 case TypeClass_SEQUENCE:
797 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aType );
798 Reference< XIdlArray > xIdlArray = xIdlTargetClass->getArray();
799 sal_Int32 i, nLen = xIdlArray->getLen( aValue );
801 typelib_TypeDescription * pTD = 0;
802 aType.getDescription( &pTD );
803 OSL_ASSERT( pTD && pTD->eTypeClass == typelib_TypeClass_SEQUENCE );
804 Type aElementType( ((typelib_IndirectTypeDescription *)pTD)->pType );
805 ::typelib_typedescription_release( pTD );
807 // build an Array in Basic
808 SbxDimArrayRef xArray;
809 SbxDataType eSbxElementType = unoToSbxType( aElementType.getTypeClass() );
810 xArray = new SbxDimArray( eSbxElementType );
811 if( nLen > 0 )
813 xArray->unoAddDim32( 0, nLen - 1 );
815 // register the elements as variables
816 for( i = 0 ; i < nLen ; i++ )
818 // convert elements
819 Any aElementAny = xIdlArray->get( aValue, (sal_uInt32)i );
820 SbxVariableRef xVar = new SbxVariable( eSbxElementType );
821 unoToSbxValue( (SbxVariable*)xVar, aElementAny );
823 // put into the Array
824 xArray->Put32( (SbxVariable*)xVar, &i );
827 else
829 xArray->unoAddDim( 0, -1 );
832 // return the Array
833 sal_uInt16 nFlags = pVar->GetFlags();
834 pVar->ResetFlag( SBX_FIXED );
835 pVar->PutObject( (SbxDimArray*)xArray );
836 pVar->SetFlags( nFlags );
839 break;
842 case TypeClass_BOOLEAN: pVar->PutBool( *(sal_Bool*)aValue.getValue() ); break;
843 case TypeClass_CHAR:
845 pVar->PutChar( *(sal_Unicode*)aValue.getValue() );
846 break;
848 case TypeClass_STRING: { OUString val; aValue >>= val; pVar->PutString( val ); } break;
849 case TypeClass_FLOAT: { float val = 0; aValue >>= val; pVar->PutSingle( val ); } break;
850 case TypeClass_DOUBLE: { double val = 0; aValue >>= val; pVar->PutDouble( val ); } break;
851 case TypeClass_BYTE: { sal_Int8 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
852 case TypeClass_SHORT: { sal_Int16 val = 0; aValue >>= val; pVar->PutInteger( val ); } break;
853 case TypeClass_LONG: { sal_Int32 val = 0; aValue >>= val; pVar->PutLong( val ); } break;
854 case TypeClass_HYPER: { sal_Int64 val = 0; aValue >>= val; pVar->PutInt64( val ); } break;
855 case TypeClass_UNSIGNED_SHORT: { sal_uInt16 val = 0; aValue >>= val; pVar->PutUShort( val ); } break;
856 case TypeClass_UNSIGNED_LONG: { sal_uInt32 val = 0; aValue >>= val; pVar->PutULong( val ); } break;
857 case TypeClass_UNSIGNED_HYPER: { sal_uInt64 val = 0; aValue >>= val; pVar->PutUInt64( val ); } break;
858 default: pVar->PutEmpty(); break;
862 // Deliver the reflection for Sbx types
863 Type getUnoTypeForSbxBaseType( SbxDataType eType )
865 Type aRetType = getCppuVoidType();
866 switch( eType )
868 case SbxNULL: aRetType = ::getCppuType( (const Reference< XInterface > *)0 ); break;
869 case SbxINTEGER: aRetType = ::getCppuType( (sal_Int16*)0 ); break;
870 case SbxLONG: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
871 case SbxSINGLE: aRetType = ::getCppuType( (float*)0 ); break;
872 case SbxDOUBLE: aRetType = ::getCppuType( (double*)0 ); break;
873 case SbxCURRENCY: aRetType = ::getCppuType( (oleautomation::Currency*)0 ); break;
874 case SbxDECIMAL: aRetType = ::getCppuType( (oleautomation::Decimal*)0 ); break;
875 case SbxDATE: {
876 SbiInstance* pInst = GetSbData()->pInst;
877 if( pInst && pInst->IsCompatibility() )
878 aRetType = ::getCppuType( (double*)0 );
879 else
880 aRetType = ::getCppuType( (oleautomation::Date*)0 );
882 break;
883 case SbxSTRING: aRetType = ::getCppuType( (OUString*)0 ); break;
884 case SbxBOOL: aRetType = ::getCppuType( (sal_Bool*)0 ); break;
885 case SbxVARIANT: aRetType = ::getCppuType( (Any*)0 ); break;
886 case SbxCHAR: aRetType = ::getCppuType( (sal_Unicode*)0 ); break;
887 case SbxBYTE: aRetType = ::getCppuType( (sal_Int8*)0 ); break;
888 case SbxUSHORT: aRetType = ::getCppuType( (sal_uInt16*)0 ); break;
889 case SbxULONG: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
890 // map machine-dependent ones on hyper for secureness
891 case SbxINT: aRetType = ::getCppuType( (sal_Int32*)0 ); break;
892 case SbxUINT: aRetType = ::getCppuType( (sal_uInt32*)0 ); break;
893 default: break;
895 return aRetType;
898 // Converting of Sbx to Uno without a know target class for TypeClass_ANY
899 Type getUnoTypeForSbxValue( const SbxValue* pVal )
901 Type aRetType = getCppuVoidType();
902 if( !pVal )
903 return aRetType;
905 // convert SbxType to Uno
906 SbxDataType eBaseType = pVal->SbxValue::GetType();
907 if( eBaseType == SbxOBJECT )
909 SbxBaseRef xObj = (SbxBase*)pVal->GetObject();
910 if( !xObj )
912 aRetType = getCppuType( static_cast<Reference<XInterface> *>(0) );
913 return aRetType;
916 if( xObj->ISA(SbxDimArray) )
918 SbxBase* pObj = (SbxBase*)xObj;
919 SbxDimArray* pArray = (SbxDimArray*)pObj;
921 short nDims = pArray->GetDims();
922 Type aElementType = getUnoTypeForSbxBaseType( (SbxDataType)(pArray->GetType() & 0xfff) );
923 TypeClass eElementTypeClass = aElementType.getTypeClass();
925 // Normal case: One dimensional array
926 sal_Int32 nLower, nUpper;
927 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
929 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
931 // If all elements of the arrays are from the same type, take
932 // this one - otherwise the whole will be considered as Any-Sequence
933 bool bNeedsInit = true;
935 sal_Int32 nSize = nUpper - nLower + 1;
936 sal_Int32 nIdx = nLower;
937 for( sal_Int32 i = 0 ; i < nSize ; i++,nIdx++ )
939 SbxVariableRef xVar = pArray->Get32( &nIdx );
940 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
941 if( bNeedsInit )
943 if( aType.getTypeClass() == TypeClass_VOID )
945 // if only first element is void: different types -> []any
946 // if all elements are void: []void is not allowed -> []any
947 aElementType = getCppuType( (Any*)0 );
948 break;
950 aElementType = aType;
951 bNeedsInit = false;
953 else if( aElementType != aType )
955 // different types -> AnySequence
956 aElementType = getCppuType( (Any*)0 );
957 break;
962 OUString aSeqTypeName = aSeqLevelStr + aElementType.getTypeName();
963 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName );
965 // #i33795 Map also multi dimensional arrays to corresponding sequences
966 else if( nDims > 1 )
968 if( eElementTypeClass == TypeClass_VOID || eElementTypeClass == TypeClass_ANY )
970 // For this check the array's dim structure does not matter
971 sal_uInt32 nFlatArraySize = pArray->Count32();
973 bool bNeedsInit = true;
974 for( sal_uInt32 i = 0 ; i < nFlatArraySize ; i++ )
976 SbxVariableRef xVar = pArray->SbxArray::Get32( i );
977 Type aType = getUnoTypeForSbxValue( (SbxVariable*)xVar );
978 if( bNeedsInit )
980 if( aType.getTypeClass() == TypeClass_VOID )
982 // if only first element is void: different types -> []any
983 // if all elements are void: []void is not allowed -> []any
984 aElementType = getCppuType( (Any*)0 );
985 break;
987 aElementType = aType;
988 bNeedsInit = false;
990 else if( aElementType != aType )
992 // different types -> AnySequence
993 aElementType = getCppuType( (Any*)0 );
994 break;
999 OUStringBuffer aSeqTypeName;
1000 for( short iDim = 0 ; iDim < nDims ; iDim++ )
1002 aSeqTypeName.appendAscii(aSeqLevelStr);
1004 aSeqTypeName.append(aElementType.getTypeName());
1005 aRetType = Type( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
1008 // No array, but ...
1009 else if( xObj->ISA(SbUnoObject) )
1011 aRetType = ((SbUnoObject*)(SbxBase*)xObj)->getUnoAny().getValueType();
1013 // SbUnoAnyObject?
1014 else if( xObj->ISA(SbUnoAnyObject) )
1016 aRetType = ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue().getValueType();
1018 // Otherwise it is a No-Uno-Basic-Object -> default==deliver void
1020 // No object, convert basic type
1021 else
1023 aRetType = getUnoTypeForSbxBaseType( eBaseType );
1025 return aRetType;
1028 // converting of Sbx to Uno without known target class for TypeClass_ANY
1029 Any sbxToUnoValueImpl( const SbxValue* pVar, bool bBlockConversionToSmallestType = false )
1031 SbxDataType eBaseType = pVar->SbxValue::GetType();
1032 if( eBaseType == SbxOBJECT )
1034 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1035 if( xObj.Is() )
1037 if( xObj->ISA(SbUnoAnyObject) )
1038 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1039 if( xObj->ISA(SbClassModuleObject) )
1041 Any aRetAny;
1042 SbClassModuleObject* pClassModuleObj = (SbClassModuleObject*)(SbxBase*)xObj;
1043 SbModule* pClassModule = pClassModuleObj->getClassModule();
1044 if( pClassModule->createCOMWrapperForIface( aRetAny, pClassModuleObj ) )
1045 return aRetAny;
1047 if( !xObj->ISA(SbUnoObject) )
1049 // Create NativeObjectWrapper to identify object in case of callbacks
1050 SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject());
1051 if( pObj != NULL )
1053 NativeObjectWrapper aNativeObjectWrapper;
1054 sal_uInt32 nIndex = lcl_registerNativeObjectWrapper( pObj );
1055 aNativeObjectWrapper.ObjectId <<= nIndex;
1056 Any aRetAny;
1057 aRetAny <<= aNativeObjectWrapper;
1058 return aRetAny;
1064 Type aType = getUnoTypeForSbxValue( pVar );
1065 TypeClass eType = aType.getTypeClass();
1067 if( !bBlockConversionToSmallestType )
1069 // #79615 Choose "smallest" represention for int values
1070 // because up cast is allowed, downcast not
1071 switch( eType )
1073 case TypeClass_FLOAT:
1074 case TypeClass_DOUBLE:
1076 double d = pVar->GetDouble();
1077 if( d == floor( d ) )
1079 if( d >= -128 && d <= 127 )
1080 aType = ::getCppuType( (sal_Int8*)0 );
1081 else if( d >= SbxMININT && d <= SbxMAXINT )
1082 aType = ::getCppuType( (sal_Int16*)0 );
1083 else if( d >= -SbxMAXLNG && d <= SbxMAXLNG )
1084 aType = ::getCppuType( (sal_Int32*)0 );
1086 break;
1088 case TypeClass_SHORT:
1090 sal_Int16 n = pVar->GetInteger();
1091 if( n >= -128 && n <= 127 )
1092 aType = ::getCppuType( (sal_Int8*)0 );
1093 break;
1095 case TypeClass_LONG:
1097 sal_Int32 n = pVar->GetLong();
1098 if( n >= -128 && n <= 127 )
1099 aType = ::getCppuType( (sal_Int8*)0 );
1100 else if( n >= SbxMININT && n <= SbxMAXINT )
1101 aType = ::getCppuType( (sal_Int16*)0 );
1102 break;
1104 case TypeClass_UNSIGNED_SHORT:
1106 sal_uInt16 n = pVar->GetUShort();
1107 if( n <= 255 )
1108 aType = ::getCppuType( (sal_uInt8*)0 );
1109 break;
1111 case TypeClass_UNSIGNED_LONG:
1113 sal_uInt32 n = pVar->GetLong();
1114 if( n <= 255 )
1115 aType = ::getCppuType( (sal_uInt8*)0 );
1116 else if( n <= SbxMAXUINT )
1117 aType = ::getCppuType( (sal_uInt16*)0 );
1118 break;
1120 // TODO: need to add hyper types ?
1121 default: break;
1125 return sbxToUnoValue( pVar, aType );
1130 // Helper function for StepREDIMP
1131 static Any implRekMultiDimArrayToSequence( SbxDimArray* pArray,
1132 const Type& aElemType, short nMaxDimIndex, short nActualDim,
1133 sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
1135 sal_Int32 nSeqLevel = nMaxDimIndex - nActualDim + 1;
1136 OUStringBuffer aSeqTypeName;
1137 sal_Int32 i;
1138 for( i = 0 ; i < nSeqLevel ; i++ )
1140 aSeqTypeName.appendAscii(aSeqLevelStr);
1142 aSeqTypeName.append(aElemType.getTypeName());
1143 Type aSeqType( TypeClass_SEQUENCE, aSeqTypeName.makeStringAndClear() );
1145 // Create Sequence instance
1146 Any aRetVal;
1147 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( aSeqType );
1148 xIdlTargetClass->createObject( aRetVal );
1150 // Alloc sequence according to array bounds
1151 sal_Int32 nUpper = pUpperBounds[nActualDim];
1152 sal_Int32 nLower = pLowerBounds[nActualDim];
1153 sal_Int32 nSeqSize = nUpper - nLower + 1;
1154 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1155 xArray->realloc( aRetVal, nSeqSize );
1157 sal_Int32& ri = pActualIndices[nActualDim];
1159 for( ri = nLower,i = 0 ; ri <= nUpper ; ri++,i++ )
1161 Any aElementVal;
1163 if( nActualDim < nMaxDimIndex )
1165 aElementVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1166 nMaxDimIndex, nActualDim + 1, pActualIndices, pLowerBounds, pUpperBounds );
1168 else
1170 SbxVariable* pSource = pArray->Get32( pActualIndices );
1171 aElementVal = sbxToUnoValue( pSource, aElemType );
1176 // transfer to the sequence
1177 xArray->set( aRetVal, i, aElementVal );
1179 catch( const IllegalArgumentException& )
1181 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1182 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1184 catch (const IndexOutOfBoundsException&)
1186 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1189 return aRetVal;
1192 // Map old interface
1193 Any sbxToUnoValue( const SbxValue* pVar )
1195 return sbxToUnoValueImpl( pVar );
1198 // function to find a global identifier in
1199 // the UnoScope and to wrap it for Sbx
1200 static bool implGetTypeByName( const OUString& rName, Type& rRetType )
1202 bool bSuccess = false;
1204 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
1205 if( xTypeAccess->hasByHierarchicalName( rName ) )
1207 Any aRet = xTypeAccess->getByHierarchicalName( rName );
1208 Reference< XTypeDescription > xTypeDesc;
1209 aRet >>= xTypeDesc;
1211 if( xTypeDesc.is() )
1213 rRetType = Type( xTypeDesc->getTypeClass(), xTypeDesc->getName() );
1214 bSuccess = true;
1217 return bSuccess;
1221 // converting of Sbx to Uno with known target class
1222 Any sbxToUnoValue( const SbxValue* pVar, const Type& rType, Property* pUnoProperty )
1224 Any aRetVal;
1226 // #94560 No conversion of empty/void for MAYBE_VOID properties
1227 if( pUnoProperty && pUnoProperty->Attributes & PropertyAttribute::MAYBEVOID )
1229 if( pVar->IsEmpty() )
1230 return aRetVal;
1233 SbxDataType eBaseType = pVar->SbxValue::GetType();
1234 if( eBaseType == SbxOBJECT )
1236 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1237 if( xObj.Is() && xObj->ISA(SbUnoAnyObject) )
1239 return ((SbUnoAnyObject*)(SbxBase*)xObj)->getValue();
1243 TypeClass eType = rType.getTypeClass();
1244 switch( eType )
1246 case TypeClass_INTERFACE:
1247 case TypeClass_STRUCT:
1248 case TypeClass_EXCEPTION:
1250 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1252 // zero referenz?
1253 if( pVar->IsNull() && eType == TypeClass_INTERFACE )
1255 Reference< XInterface > xRef;
1256 OUString aClassName = xIdlTargetClass->getName();
1257 Type aClassType( xIdlTargetClass->getTypeClass(), aClassName.getStr() );
1258 aRetVal.setValue( &xRef, aClassType );
1260 else
1262 // #112368 Special conversion for Decimal, Currency and Date
1263 if( eType == TypeClass_STRUCT )
1265 SbiInstance* pInst = GetSbData()->pInst;
1266 if( pInst && pInst->IsCompatibility() )
1268 if( rType == ::getCppuType( (oleautomation::Decimal*)0 ) )
1270 oleautomation::Decimal aDecimal;
1271 pVar->fillAutomationDecimal( aDecimal );
1272 aRetVal <<= aDecimal;
1273 break;
1275 else if( rType == ::getCppuType( (oleautomation::Currency*)0 ) )
1277 // assumes per previous code that ole Currency is Int64
1278 aRetVal <<= (sal_Int64)( pVar->GetInt64() );
1279 break;
1281 else if( rType == ::getCppuType( (oleautomation::Date*)0 ) )
1283 oleautomation::Date aDate;
1284 aDate.Value = pVar->GetDate();
1285 aRetVal <<= aDate;
1286 break;
1291 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1292 if( pObj && pObj->ISA(SbUnoObject) )
1294 aRetVal = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1296 else if( pObj && pObj->ISA(SbUnoStructRefObject) )
1298 aRetVal = ((SbUnoStructRefObject*)(SbxBase*)pObj)->getUnoAny();
1300 else
1302 // zero object -> zero XInterface
1303 Reference<XInterface> xInt;
1304 aRetVal <<= xInt;
1308 break;
1310 case TypeClass_TYPE:
1312 if( eBaseType == SbxOBJECT )
1314 // XIdlClass?
1315 Reference< XIdlClass > xIdlClass;
1317 SbxBaseRef pObj = (SbxBase*)pVar->GetObject();
1318 if( pObj && pObj->ISA(SbUnoObject) )
1320 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
1321 aUnoAny >>= xIdlClass;
1324 if( xIdlClass.is() )
1326 OUString aClassName = xIdlClass->getName();
1327 Type aType( xIdlClass->getTypeClass(), aClassName.getStr() );
1328 aRetVal <<= aType;
1331 else if( eBaseType == SbxSTRING )
1333 OUString aTypeName = pVar->GetOUString();
1334 Type aType;
1335 bool bSuccess = implGetTypeByName( aTypeName, aType );
1336 if( bSuccess )
1338 aRetVal <<= aType;
1342 break;
1345 case TypeClass_ENUM:
1347 aRetVal = int2enum( pVar->GetLong(), rType );
1349 break;
1351 case TypeClass_SEQUENCE:
1353 SbxBaseRef xObj = (SbxBase*)pVar->GetObject();
1354 if( xObj && xObj->ISA(SbxDimArray) )
1356 SbxBase* pObj = (SbxBase*)xObj;
1357 SbxDimArray* pArray = (SbxDimArray*)pObj;
1359 short nDims = pArray->GetDims();
1361 // Normal case: One dimensional array
1362 sal_Int32 nLower, nUpper;
1363 if( nDims == 1 && pArray->GetDim32( 1, nLower, nUpper ) )
1365 sal_Int32 nSeqSize = nUpper - nLower + 1;
1367 // create the instanz of the required sequence
1368 Reference< XIdlClass > xIdlTargetClass = TypeToIdlClass( rType );
1369 xIdlTargetClass->createObject( aRetVal );
1370 Reference< XIdlArray > xArray = xIdlTargetClass->getArray();
1371 xArray->realloc( aRetVal, nSeqSize );
1373 // Element-Type
1374 OUString aClassName = xIdlTargetClass->getName();
1375 typelib_TypeDescription * pSeqTD = 0;
1376 typelib_typedescription_getByName( &pSeqTD, aClassName.pData );
1377 OSL_ASSERT( pSeqTD );
1378 Type aElemType( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1380 // convert all array member and register them
1381 sal_Int32 nIdx = nLower;
1382 for( sal_Int32 i = 0 ; i < nSeqSize ; i++,nIdx++ )
1384 SbxVariableRef xVar = pArray->Get32( &nIdx );
1386 // Convert the value of Sbx to Uno
1387 Any aAnyValue = sbxToUnoValue( (SbxVariable*)xVar, aElemType );
1391 // take over to the sequence
1392 xArray->set( aRetVal, i, aAnyValue );
1394 catch( const IllegalArgumentException& )
1396 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
1397 implGetExceptionMsg( ::cppu::getCaughtException() ) );
1399 catch (const IndexOutOfBoundsException&)
1401 StarBASIC::Error( SbERR_OUT_OF_RANGE );
1405 // #i33795 Map also multi dimensional arrays to corresponding sequences
1406 else if( nDims > 1 )
1408 // Element-Type
1409 typelib_TypeDescription * pSeqTD = 0;
1410 Type aCurType( rType );
1411 sal_Int32 nSeqLevel = 0;
1412 Type aElemType;
1415 OUString aTypeName = aCurType.getTypeName();
1416 typelib_typedescription_getByName( &pSeqTD, aTypeName.pData );
1417 OSL_ASSERT( pSeqTD );
1418 if( pSeqTD->eTypeClass == typelib_TypeClass_SEQUENCE )
1420 aCurType = Type( ((typelib_IndirectTypeDescription *)pSeqTD)->pType );
1421 nSeqLevel++;
1423 else
1425 aElemType = aCurType;
1426 break;
1429 while( true );
1431 if( nSeqLevel == nDims )
1433 sal_Int32* pLowerBounds = new sal_Int32[nDims];
1434 sal_Int32* pUpperBounds = new sal_Int32[nDims];
1435 sal_Int32* pActualIndices = new sal_Int32[nDims];
1436 for( short i = 1 ; i <= nDims ; i++ )
1438 sal_Int32 lBound, uBound;
1439 pArray->GetDim32( i, lBound, uBound );
1441 short j = i - 1;
1442 pActualIndices[j] = pLowerBounds[j] = lBound;
1443 pUpperBounds[j] = uBound;
1446 aRetVal = implRekMultiDimArrayToSequence( pArray, aElemType,
1447 nDims - 1, 0, pActualIndices, pLowerBounds, pUpperBounds );
1449 delete[] pUpperBounds;
1450 delete[] pLowerBounds;
1451 delete[] pActualIndices;
1456 break;
1459 // Use for Any the class indipendent converting routine
1460 case TypeClass_ANY:
1462 aRetVal = sbxToUnoValueImpl( pVar );
1464 break;
1466 case TypeClass_BOOLEAN:
1468 sal_Bool b = pVar->GetBool();
1469 aRetVal.setValue( &b, getBooleanCppuType() );
1470 break;
1472 case TypeClass_CHAR:
1474 sal_Unicode c = pVar->GetChar();
1475 aRetVal.setValue( &c , getCharCppuType() );
1476 break;
1478 case TypeClass_STRING: aRetVal <<= pVar->GetOUString(); break;
1479 case TypeClass_FLOAT: aRetVal <<= pVar->GetSingle(); break;
1480 case TypeClass_DOUBLE: aRetVal <<= pVar->GetDouble(); break;
1482 case TypeClass_BYTE:
1484 sal_Int16 nVal = pVar->GetInteger();
1485 sal_Bool bOverflow = sal_False;
1486 if( nVal < -128 )
1488 bOverflow = sal_True;
1489 nVal = -128;
1491 else if( nVal > 127 )
1493 bOverflow = sal_True;
1494 nVal = 127;
1496 if( bOverflow )
1497 StarBASIC::Error( ERRCODE_BASIC_MATH_OVERFLOW );
1499 sal_Int8 nByteVal = (sal_Int8)nVal;
1500 aRetVal <<= nByteVal;
1501 break;
1503 case TypeClass_SHORT: aRetVal <<= (sal_Int16)( pVar->GetInteger() ); break;
1504 case TypeClass_LONG: aRetVal <<= (sal_Int32)( pVar->GetLong() ); break;
1505 case TypeClass_HYPER: aRetVal <<= (sal_Int64)( pVar->GetInt64() ); break;
1506 case TypeClass_UNSIGNED_SHORT: aRetVal <<= (sal_uInt16)( pVar->GetUShort() ); break;
1507 case TypeClass_UNSIGNED_LONG: aRetVal <<= (sal_uInt32)( pVar->GetULong() ); break;
1508 case TypeClass_UNSIGNED_HYPER: aRetVal <<= (sal_uInt64)( pVar->GetUInt64() ); break;
1509 default: break;
1512 return aRetVal;
1515 void processAutomationParams( SbxArray* pParams, Sequence< Any >& args, bool bOLEAutomation, sal_uInt32 nParamCount )
1517 AutomationNamedArgsSbxArray* pArgNamesArray = NULL;
1518 if( bOLEAutomation )
1519 pArgNamesArray = PTR_CAST(AutomationNamedArgsSbxArray,pParams);
1521 args.realloc( nParamCount );
1522 Any* pAnyArgs = args.getArray();
1523 bool bBlockConversionToSmallestType = GetSbData()->pInst->IsCompatibility();
1524 sal_uInt32 i = 0;
1525 if( pArgNamesArray )
1527 Sequence< OUString >& rNameSeq = pArgNamesArray->getNames();
1528 OUString* pNames = rNameSeq.getArray();
1529 Any aValAny;
1530 for( i = 0 ; i < nParamCount ; i++ )
1532 sal_uInt16 iSbx = (sal_uInt16)(i+1);
1534 aValAny = sbxToUnoValueImpl( pParams->Get( iSbx ),
1535 bBlockConversionToSmallestType );
1537 OUString aParamName = pNames[iSbx];
1538 if( !aParamName.isEmpty() )
1540 oleautomation::NamedArgument aNamedArgument;
1541 aNamedArgument.Name = aParamName;
1542 aNamedArgument.Value = aValAny;
1543 pAnyArgs[i] <<= aNamedArgument;
1545 else
1547 pAnyArgs[i] = aValAny;
1551 else
1553 for( i = 0 ; i < nParamCount ; i++ )
1555 pAnyArgs[i] = sbxToUnoValueImpl( pParams->Get( (sal_uInt16)(i+1) ),
1556 bBlockConversionToSmallestType );
1561 enum INVOKETYPE
1563 GetProp = 0,
1564 SetProp,
1565 Func
1567 Any invokeAutomationMethod( const OUString& Name, Sequence< Any >& args, SbxArray* pParams, sal_uInt32 nParamCount, Reference< XInvocation >& rxInvocation, INVOKETYPE invokeType = Func )
1569 Sequence< sal_Int16 > OutParamIndex;
1570 Sequence< Any > OutParam;
1572 Any aRetAny;
1573 switch( invokeType )
1575 case Func:
1576 aRetAny = rxInvocation->invoke( Name, args, OutParamIndex, OutParam );
1577 break;
1578 case GetProp:
1580 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY );
1581 aRetAny = xAutoInv->invokeGetProperty( Name, args, OutParamIndex, OutParam );
1582 break;
1584 case SetProp:
1586 Reference< XAutomationInvocation > xAutoInv( rxInvocation, UNO_QUERY_THROW );
1587 aRetAny = xAutoInv->invokePutProperty( Name, args, OutParamIndex, OutParam );
1588 break;
1590 default:
1591 break; // should introduce an error here
1594 const sal_Int16* pIndices = OutParamIndex.getConstArray();
1595 sal_uInt32 nLen = OutParamIndex.getLength();
1596 if( nLen )
1598 const Any* pNewValues = OutParam.getConstArray();
1599 for( sal_uInt32 j = 0 ; j < nLen ; j++ )
1601 sal_Int16 iTarget = pIndices[ j ];
1602 if( iTarget >= (sal_Int16)nParamCount )
1603 break;
1604 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pNewValues[ j ] );
1607 return aRetAny;
1610 // Debugging help method to readout the imlemented interfaces of an object
1611 OUString Impl_GetInterfaceInfo( const Reference< XInterface >& x, const Reference< XIdlClass >& xClass, sal_uInt16 nRekLevel )
1613 Type aIfaceType = ::getCppuType( (const Reference< XInterface > *)0 );
1614 static Reference< XIdlClass > xIfaceClass = TypeToIdlClass( aIfaceType );
1616 OUStringBuffer aRetStr;
1617 for( sal_uInt16 i = 0 ; i < nRekLevel ; i++ )
1618 aRetStr.appendAscii( " " );
1619 aRetStr.append( xClass->getName() );
1620 OUString aClassName = xClass->getName();
1621 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
1623 // checking if the interface is realy supported
1624 if( !x->queryInterface( aClassType ).hasValue() )
1626 aRetStr.appendAscii( " (ERROR: Not really supported!)\n" );
1628 // Are there super interfaces?
1629 else
1631 aRetStr.appendAscii( "\n" );
1633 // get the super interfaces
1634 Sequence< Reference< XIdlClass > > aSuperClassSeq = xClass->getSuperclasses();
1635 const Reference< XIdlClass >* pClasses = aSuperClassSeq.getConstArray();
1636 sal_uInt32 nSuperIfaceCount = aSuperClassSeq.getLength();
1637 for( sal_uInt32 j = 0 ; j < nSuperIfaceCount ; j++ )
1639 const Reference< XIdlClass >& rxIfaceClass = pClasses[j];
1640 if( !rxIfaceClass->equals( xIfaceClass ) )
1641 aRetStr.append( Impl_GetInterfaceInfo( x, rxIfaceClass, nRekLevel + 1 ) );
1644 return aRetStr.makeStringAndClear();
1647 OUString getDbgObjectNameImpl( SbUnoObject* pUnoObj )
1649 OUString aName;
1650 if( pUnoObj )
1652 aName = pUnoObj->GetClassName();
1653 if( aName.isEmpty() )
1655 Any aToInspectObj = pUnoObj->getUnoAny();
1656 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1657 Reference< XInterface > xObj;
1658 if( eType == TypeClass_INTERFACE )
1659 xObj = *(Reference< XInterface >*)aToInspectObj.getValue();
1660 if( xObj.is() )
1662 Reference< XServiceInfo > xServiceInfo( xObj, UNO_QUERY );
1663 if( xServiceInfo.is() )
1664 aName = xServiceInfo->getImplementationName();
1668 return aName;
1671 OUString getDbgObjectName( SbUnoObject* pUnoObj )
1673 OUString aName = getDbgObjectNameImpl( pUnoObj );
1674 if( aName.isEmpty() )
1675 aName += "Unknown";
1677 OUStringBuffer aRet;
1678 if( aName.getLength() > 20 )
1680 aRet.appendAscii( "\n" );
1682 aRet.appendAscii( "\"" );
1683 aRet.append( aName );
1684 aRet.appendAscii( "\":" );
1685 return aRet.makeStringAndClear();
1688 OUString getBasicObjectTypeName( SbxObject* pObj )
1690 OUString aName;
1691 if( pObj )
1693 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
1694 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
1695 if( pUnoObj )
1696 aName = getDbgObjectNameImpl( pUnoObj );
1697 else if ( pUnoStructObj )
1698 aName = pUnoStructObj->GetClassName();
1700 return aName;
1703 bool checkUnoObjectType( SbUnoObject* pUnoObj, const OUString& rClass )
1705 Any aToInspectObj = pUnoObj->getUnoAny();
1706 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1707 if( eType != TypeClass_INTERFACE )
1709 return false;
1711 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1713 // Return true for XInvocation based objects as interface type names don't count then
1714 Reference< XInvocation > xInvocation( x, UNO_QUERY );
1715 if( xInvocation.is() )
1717 return true;
1719 bool result = false;
1720 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1721 if( xTypeProvider.is() )
1723 /* Although interfaces in the ooo.vba namespace obey the IDL rules and
1724 have a leading 'X', in Basic we want to be able to do something
1725 like 'Dim wb As Workbooks' or 'Dim lb As MSForms.Label'. Here we
1726 add a leading 'X' to the class name and a leading dot to the entire
1727 type name. This results e.g. in '.XWorkbooks' or '.MSForms.XLabel'
1728 which matches the interface names 'ooo.vba.excel.XWorkbooks' or
1729 'ooo.vba.msforms.XLabel'.
1731 OUString aClassName( sal_Unicode( '.' ) );
1732 sal_Int32 nClassNameDot = rClass.lastIndexOf( '.' );
1733 if( nClassNameDot >= 0 )
1735 aClassName += rClass.copy( 0, nClassNameDot + 1 ) + OUString( sal_Unicode( 'X' ) ) + rClass.copy( nClassNameDot + 1 );
1737 else
1739 aClassName += OUString( sal_Unicode( 'X' ) ) + rClass;
1741 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1742 const Type* pTypeArray = aTypeSeq.getConstArray();
1743 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1744 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1746 const Type& rType = pTypeArray[j];
1748 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1749 if( !xClass.is() )
1751 OSL_FAIL("failed to get XIdlClass for type");
1752 break;
1754 OUString aInterfaceName = xClass->getName();
1755 if ( aInterfaceName == "com.sun.star.bridge.oleautomation.XAutomationObject" )
1757 // there is a hack in the extensions/source/ole/oleobj.cxx to return the typename of the automation object, lets check if it
1758 // matches
1759 Reference< XInvocation > xInv( aToInspectObj, UNO_QUERY );
1760 if ( xInv.is() )
1762 OUString sTypeName;
1763 xInv->getValue( OUString( "$GetTypeName" ) ) >>= sTypeName;
1764 if ( sTypeName.isEmpty() || sTypeName == "IDispatch" )
1766 // can't check type, leave it pass
1767 result = true;
1769 else
1771 result = sTypeName.equals( rClass );
1774 break; // finished checking automation object
1777 // match interface name with passed class name
1778 OSL_TRACE("Checking if object implements %s", OUStringToOString( aClassName, RTL_TEXTENCODING_UTF8 ).getStr() );
1779 if ( (aClassName.getLength() < aInterfaceName.getLength()) &&
1780 aInterfaceName.matchIgnoreAsciiCase( aClassName, aInterfaceName.getLength() - aClassName.getLength() ) )
1782 result = true;
1783 break;
1787 return result;
1790 // Debugging help method to readout the imlemented interfaces of an object
1791 OUString Impl_GetSupportedInterfaces( SbUnoObject* pUnoObj )
1793 Any aToInspectObj = pUnoObj->getUnoAny();
1795 // allow only TypeClass interface
1796 TypeClass eType = aToInspectObj.getValueType().getTypeClass();
1797 OUStringBuffer aRet;
1798 if( eType != TypeClass_INTERFACE )
1800 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
1801 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
1803 else
1805 // get the interface from the Any
1806 const Reference< XInterface > x = *(Reference< XInterface >*)aToInspectObj.getValue();
1808 Reference< XTypeProvider > xTypeProvider( x, UNO_QUERY );
1810 aRet.appendAscii( "Supported interfaces by object " );
1811 aRet.append( getDbgObjectName( pUnoObj ) );
1812 aRet.appendAscii( "\n" );
1813 if( xTypeProvider.is() )
1815 // get the interfaces of the implementation
1816 Sequence< Type > aTypeSeq = xTypeProvider->getTypes();
1817 const Type* pTypeArray = aTypeSeq.getConstArray();
1818 sal_uInt32 nIfaceCount = aTypeSeq.getLength();
1819 for( sal_uInt32 j = 0 ; j < nIfaceCount ; j++ )
1821 const Type& rType = pTypeArray[j];
1823 Reference<XIdlClass> xClass = TypeToIdlClass( rType );
1824 if( xClass.is() )
1826 aRet.append( Impl_GetInterfaceInfo( x, xClass, 1 ) );
1828 else
1830 typelib_TypeDescription * pTD = 0;
1831 rType.getDescription( &pTD );
1833 aRet.appendAscii( "*** ERROR: No IdlClass for type \"" );
1834 aRet.append( pTD->pTypeName );
1835 aRet.appendAscii( "\"\n*** Please check type library\n" );
1840 return aRet.makeStringAndClear();
1845 // Debugging help method SbxDataType -> String
1846 OUString Dbg_SbxDataType2String( SbxDataType eType )
1848 OUStringBuffer aRet;
1849 switch( +eType )
1851 case SbxEMPTY: aRet.appendAscii("SbxEMPTY"); break;
1852 case SbxNULL: aRet.appendAscii("SbxNULL"); break;
1853 case SbxINTEGER: aRet.appendAscii("SbxINTEGER"); break;
1854 case SbxLONG: aRet.appendAscii("SbxLONG"); break;
1855 case SbxSINGLE: aRet.appendAscii("SbxSINGLE"); break;
1856 case SbxDOUBLE: aRet.appendAscii("SbxDOUBLE"); break;
1857 case SbxCURRENCY: aRet.appendAscii("SbxCURRENCY"); break;
1858 case SbxDECIMAL: aRet.appendAscii("SbxDECIMAL"); break;
1859 case SbxDATE: aRet.appendAscii("SbxDATE"); break;
1860 case SbxSTRING: aRet.appendAscii("SbxSTRING"); break;
1861 case SbxOBJECT: aRet.appendAscii("SbxOBJECT"); break;
1862 case SbxERROR: aRet.appendAscii("SbxERROR"); break;
1863 case SbxBOOL: aRet.appendAscii("SbxBOOL"); break;
1864 case SbxVARIANT: aRet.appendAscii("SbxVARIANT"); break;
1865 case SbxDATAOBJECT: aRet.appendAscii("SbxDATAOBJECT"); break;
1866 case SbxCHAR: aRet.appendAscii("SbxCHAR"); break;
1867 case SbxBYTE: aRet.appendAscii("SbxBYTE"); break;
1868 case SbxUSHORT: aRet.appendAscii("SbxUSHORT"); break;
1869 case SbxULONG: aRet.appendAscii("SbxULONG"); break;
1870 case SbxSALINT64: aRet.appendAscii("SbxINT64"); break;
1871 case SbxSALUINT64: aRet.appendAscii("SbxUINT64"); break;
1872 case SbxINT: aRet.appendAscii("SbxINT"); break;
1873 case SbxUINT: aRet.appendAscii("SbxUINT"); break;
1874 case SbxVOID: aRet.appendAscii("SbxVOID"); break;
1875 case SbxHRESULT: aRet.appendAscii("SbxHRESULT"); break;
1876 case SbxPOINTER: aRet.appendAscii("SbxPOINTER"); break;
1877 case SbxDIMARRAY: aRet.appendAscii("SbxDIMARRAY"); break;
1878 case SbxCARRAY: aRet.appendAscii("SbxCARRAY"); break;
1879 case SbxUSERDEF: aRet.appendAscii("SbxUSERDEF"); break;
1880 case SbxLPSTR: aRet.appendAscii("SbxLPSTR"); break;
1881 case SbxLPWSTR: aRet.appendAscii("SbxLPWSTR"); break;
1882 case SbxCoreSTRING: aRet.appendAscii("SbxCoreSTRING"); break;
1883 case SbxOBJECT | SbxARRAY: aRet.appendAscii("SbxARRAY"); break;
1884 default: aRet.appendAscii("Unknown Sbx-Type!");break;
1886 return aRet.makeStringAndClear();
1889 // Debugging help method to display the properties of a SbUnoObjects
1890 OUString Impl_DumpProperties( SbUnoObject* pUnoObj )
1892 OUStringBuffer aRet;
1893 aRet.appendAscii("Properties of object ");
1894 aRet.append( getDbgObjectName( pUnoObj ) );
1896 // analyse the Uno-Infos to recognise the arrays
1897 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1898 if( !xAccess.is() )
1900 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1901 if( xInvok.is() )
1902 xAccess = xInvok->getIntrospection();
1904 if( !xAccess.is() )
1906 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1907 return aRet.makeStringAndClear();
1910 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
1911 sal_uInt32 nUnoPropCount = props.getLength();
1912 const Property* pUnoProps = props.getConstArray();
1914 SbxArray* pProps = pUnoObj->GetProperties();
1915 sal_uInt16 nPropCount = pProps->Count();
1916 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
1917 for( sal_uInt16 i = 0; i < nPropCount; i++ )
1919 SbxVariable* pVar = pProps->Get( i );
1920 if( pVar )
1922 OUStringBuffer aPropStr;
1923 if( (i % nPropsPerLine) == 0 )
1924 aPropStr.appendAscii( "\n" );
1926 // output the type and name
1927 // Is it in Uno a sequence?
1928 SbxDataType eType = pVar->GetFullType();
1930 sal_Bool bMaybeVoid = sal_False;
1931 if( i < nUnoPropCount )
1933 const Property& rProp = pUnoProps[ i ];
1935 // By MAYBEVOID convert the type out of Uno newly,
1936 // so that not only SbxEMPTY were outputed.
1937 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
1939 eType = unoToSbxType( rProp.Type.getTypeClass() );
1940 bMaybeVoid = sal_True;
1942 if( eType == SbxOBJECT )
1944 Type aType = rProp.Type;
1945 if( aType.getTypeClass() == TypeClass_SEQUENCE )
1946 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
1949 aPropStr.append( Dbg_SbxDataType2String( eType ) );
1950 if( bMaybeVoid )
1951 aPropStr.appendAscii( "/void" );
1952 aPropStr.appendAscii( " " );
1953 aPropStr.append( pVar->GetName() );
1955 if( i == nPropCount - 1 )
1956 aPropStr.appendAscii( "\n" );
1957 else
1958 aPropStr.appendAscii( "; " );
1960 aRet.append( aPropStr.makeStringAndClear() );
1963 return aRet.makeStringAndClear();
1966 // Debugging help method to display the methods of an SbUnoObjects
1967 OUString Impl_DumpMethods( SbUnoObject* pUnoObj )
1969 OUStringBuffer aRet;
1970 aRet.appendAscii("Methods of object ");
1971 aRet.append( getDbgObjectName( pUnoObj ) );
1973 // XIntrospectionAccess, so that the types of the parameter could be outputed
1974 Reference< XIntrospectionAccess > xAccess = pUnoObj->getIntrospectionAccess();
1975 if( !xAccess.is() )
1977 Reference< XInvocation > xInvok = pUnoObj->getInvocation();
1978 if( xInvok.is() )
1979 xAccess = xInvok->getIntrospection();
1981 if( !xAccess.is() )
1983 aRet.appendAscii( "\nUnknown, no introspection available\n" );
1984 return aRet.makeStringAndClear();
1986 Sequence< Reference< XIdlMethod > > methods = xAccess->getMethods
1987 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
1988 const Reference< XIdlMethod >* pUnoMethods = methods.getConstArray();
1990 SbxArray* pMethods = pUnoObj->GetMethods();
1991 sal_uInt16 nMethodCount = pMethods->Count();
1992 if( !nMethodCount )
1994 aRet.appendAscii( "\nNo methods found\n" );
1995 return aRet.makeStringAndClear();
1997 sal_uInt16 nPropsPerLine = 1 + nMethodCount / 30;
1998 for( sal_uInt16 i = 0; i < nMethodCount; i++ )
2000 SbxVariable* pVar = pMethods->Get( i );
2001 if( pVar )
2003 if( (i % nPropsPerLine) == 0 )
2004 aRet.appendAscii( "\n" );
2006 // address the method
2007 const Reference< XIdlMethod >& rxMethod = pUnoMethods[i];
2009 // Is it in Uno a sequence?
2010 SbxDataType eType = pVar->GetFullType();
2011 if( eType == SbxOBJECT )
2013 Reference< XIdlClass > xClass = rxMethod->getReturnType();
2014 if( xClass.is() && xClass->getTypeClass() == TypeClass_SEQUENCE )
2015 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
2017 // output the name and the type
2018 aRet.append( Dbg_SbxDataType2String( eType ) );
2019 aRet.appendAscii( " " );
2020 aRet.append ( pVar->GetName() );
2021 aRet.appendAscii( " ( " );
2023 // the get-method mustn't have a parameter
2024 Sequence< Reference< XIdlClass > > aParamsSeq = rxMethod->getParameterTypes();
2025 sal_uInt32 nParamCount = aParamsSeq.getLength();
2026 const Reference< XIdlClass >* pParams = aParamsSeq.getConstArray();
2028 if( nParamCount > 0 )
2030 for( sal_uInt16 j = 0; j < nParamCount; j++ )
2032 aRet.append ( Dbg_SbxDataType2String( unoToSbxType( pParams[ j ] ) ) );
2033 if( j < nParamCount - 1 )
2034 aRet.appendAscii( ", " );
2037 else
2038 aRet.appendAscii( "void" );
2040 aRet.appendAscii( " ) " );
2042 if( i == nMethodCount - 1 )
2043 aRet.appendAscii( "\n" );
2044 else
2045 aRet.appendAscii( "; " );
2048 return aRet.makeStringAndClear();
2051 TYPEINIT1(AutomationNamedArgsSbxArray,SbxArray)
2053 // Implementation SbUnoObject
2054 void SbUnoObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
2055 const SfxHint& rHint, const TypeId& rHintType )
2057 if( bNeedIntrospection )
2058 doIntrospection();
2060 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
2061 if( pHint )
2063 SbxVariable* pVar = pHint->GetVar();
2064 SbxArray* pParams = pVar->GetParameters();
2065 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
2066 SbUnoMethod* pMeth = PTR_CAST(SbUnoMethod,pVar);
2067 if( pProp )
2069 bool bInvocation = pProp->isInvocationBased();
2070 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2072 // Test-Properties
2073 sal_Int32 nId = pProp->nId;
2074 if( nId < 0 )
2076 // Id == -1: Display implemented interfaces according the ClassProvider
2077 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
2079 OUString aRetStr = Impl_GetSupportedInterfaces( this );
2080 pVar->PutString( aRetStr );
2082 // Id == -2: output properties
2083 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
2085 // by now all properties must be established
2086 implCreateAll();
2087 OUString aRetStr = Impl_DumpProperties( this );
2088 pVar->PutString( aRetStr );
2090 // Id == -3: output the methods
2091 else if( nId == -3 ) // Property ID_DBG_METHODS
2093 // y now all properties must be established
2094 implCreateAll();
2095 OUString aRetStr = Impl_DumpMethods( this );
2096 pVar->PutString( aRetStr );
2098 return;
2101 if( !bInvocation && mxUnoAccess.is() )
2105 if ( maStructInfo.get() )
2107 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2108 if ( aMember.isEmpty() )
2110 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2112 else
2114 if ( pProp->isUnoStruct() )
2116 SbUnoStructRefObject* pSbUnoObject = new SbUnoStructRefObject( pProp->GetName(), aMember );
2117 SbxObjectRef xWrapper = (SbxObject*)pSbUnoObject;
2118 pVar->PutObject( xWrapper );
2120 else
2122 Any aRetAny = aMember.getValue();
2123 // take over the value from Uno to Sbx
2124 unoToSbxValue( pVar, aRetAny );
2126 return;
2129 // get the value
2130 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2131 Any aRetAny = xPropSet->getPropertyValue( pProp->GetName() );
2132 // The use of getPropertyValue (instead of using the index) is
2133 // suboptimal, but the refactoring to XInvocation is already pending
2134 // Otherwise it is posible to use FastPropertySet
2136 // take over the value from Uno to Sbx
2137 unoToSbxValue( pVar, aRetAny );
2139 catch( const Exception& )
2141 implHandleAnyException( ::cppu::getCaughtException() );
2144 else if( bInvocation && mxInvocation.is() )
2148 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2149 sal_Bool bCanBeConsideredAMethod = mxInvocation->hasMethod( pProp->GetName() );
2150 Any aRetAny;
2151 if ( bCanBeConsideredAMethod && nParamCount )
2153 // Automation properties have methods, so.. we need to invoke this through
2154 // XInvocation
2155 Sequence<Any> args;
2156 processAutomationParams( pParams, args, true, nParamCount );
2157 aRetAny = invokeAutomationMethod( pProp->GetName(), args, pParams, nParamCount, mxInvocation, GetProp );
2159 else
2160 aRetAny = mxInvocation->getValue( pProp->GetName() );
2161 // take over the value from Uno to Sbx
2162 unoToSbxValue( pVar, aRetAny );
2163 if( pParams && bCanBeConsideredAMethod )
2164 pVar->SetParameters( NULL );
2167 catch( const Exception& )
2169 implHandleAnyException( ::cppu::getCaughtException() );
2173 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
2175 if( !bInvocation && mxUnoAccess.is() )
2177 if( pProp->aUnoProp.Attributes & PropertyAttribute::READONLY )
2179 StarBASIC::Error( SbERR_PROP_READONLY );
2180 return;
2182 if ( maStructInfo.get() )
2184 StructRefInfo aMember = maStructInfo->getStructMember( pProp->GetName() );
2185 if ( aMember.isEmpty() )
2187 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
2189 else
2191 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2192 aMember.setValue( aAnyValue );
2194 return;
2196 // take over the value from Uno to Sbx
2197 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
2200 // set the value
2201 Reference< XPropertySet > xPropSet( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2202 xPropSet->setPropertyValue( pProp->GetName(), aAnyValue );
2203 // The use of getPropertyValue (instead of using the index) is
2204 // suboptimal, but the refactoring to XInvocation is already pending
2205 // Otherwise it is posible to use FastPropertySet
2207 catch( const Exception& )
2209 implHandleAnyException( ::cppu::getCaughtException() );
2212 else if( bInvocation && mxInvocation.is() )
2214 // take over the value from Uno to Sbx
2215 Any aAnyValue = sbxToUnoValueImpl( pVar );
2218 // set the value
2219 mxInvocation->setValue( pProp->GetName(), aAnyValue );
2221 catch( const Exception& )
2223 implHandleAnyException( ::cppu::getCaughtException() );
2228 else if( pMeth )
2230 bool bInvocation = pMeth->isInvocationBased();
2231 if( pHint->GetId() == SBX_HINT_DATAWANTED )
2233 // number of Parameter -1 because of Param0 == this
2234 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
2235 Sequence<Any> args;
2236 sal_Bool bOutParams = sal_False;
2237 sal_uInt32 i;
2239 if( !bInvocation && mxUnoAccess.is() )
2241 // get info
2242 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2243 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2244 sal_uInt32 nUnoParamCount = rInfoSeq.getLength();
2245 sal_uInt32 nAllocParamCount = nParamCount;
2247 // ignore surplus parameter; alternative: throw an error
2248 if( nParamCount > nUnoParamCount )
2250 nParamCount = nUnoParamCount;
2251 nAllocParamCount = nParamCount;
2253 else if( nParamCount < nUnoParamCount )
2255 SbiInstance* pInst = GetSbData()->pInst;
2256 if( pInst && pInst->IsCompatibility() )
2258 // Check types
2259 bool bError = false;
2260 for( i = nParamCount ; i < nUnoParamCount ; i++ )
2262 const ParamInfo& rInfo = pParamInfos[i];
2263 const Reference< XIdlClass >& rxClass = rInfo.aType;
2264 if( rxClass->getTypeClass() != TypeClass_ANY )
2266 bError = true;
2267 StarBASIC::Error( SbERR_NOT_OPTIONAL );
2270 if( !bError )
2271 nAllocParamCount = nUnoParamCount;
2275 if( nAllocParamCount > 0 )
2277 args.realloc( nAllocParamCount );
2278 Any* pAnyArgs = args.getArray();
2279 for( i = 0 ; i < nParamCount ; i++ )
2281 const ParamInfo& rInfo = pParamInfos[i];
2282 const Reference< XIdlClass >& rxClass = rInfo.aType;
2284 com::sun::star::uno::Type aType( rxClass->getTypeClass(), rxClass->getName() );
2286 // ATTENTION: Don't forget for Sbx-Parameter the offset!
2287 pAnyArgs[i] = sbxToUnoValue( pParams->Get( (sal_uInt16)(i+1) ), aType );
2289 // If it is not certain check whether the out-parameter are available.
2290 if( !bOutParams )
2292 ParamMode aParamMode = rInfo.aMode;
2293 if( aParamMode != ParamMode_IN )
2294 bOutParams = sal_True;
2299 else if( bInvocation && pParams && mxInvocation.is() )
2301 bool bOLEAutomation = true;
2302 processAutomationParams( pParams, args, bOLEAutomation, nParamCount );
2305 // call the method
2306 GetSbData()->bBlockCompilerError = true; // #106433 Block compiler errors for API calls
2309 if( !bInvocation && mxUnoAccess.is() )
2311 Any aRetAny = pMeth->m_xUnoMethod->invoke( getUnoAny(), args );
2313 // take over the value from Uno to Sbx
2314 unoToSbxValue( pVar, aRetAny );
2316 // Did we to copy back the Out-Parameter?
2317 if( bOutParams )
2319 const Any* pAnyArgs = args.getConstArray();
2321 // get info
2322 const Sequence<ParamInfo>& rInfoSeq = pMeth->getParamInfos();
2323 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2325 sal_uInt32 j;
2326 for( j = 0 ; j < nParamCount ; j++ )
2328 const ParamInfo& rInfo = pParamInfos[j];
2329 ParamMode aParamMode = rInfo.aMode;
2330 if( aParamMode != ParamMode_IN )
2331 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
2335 else if( bInvocation && mxInvocation.is() )
2337 Any aRetAny = invokeAutomationMethod( pMeth->GetName(), args, pParams, nParamCount, mxInvocation );
2338 unoToSbxValue( pVar, aRetAny );
2341 // remove parameter here, because this was not done anymore in unoToSbxValue()
2342 // for arrays
2343 if( pParams )
2344 pVar->SetParameters( NULL );
2346 catch( const Exception& )
2348 implHandleAnyException( ::cppu::getCaughtException() );
2350 GetSbData()->bBlockCompilerError = false; // #106433 Unblock compiler errors
2353 else
2354 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
2359 SbUnoObject::SbUnoObject( const OUString& aName_, const Any& aUnoObj_ )
2360 : SbxObject( aName_ )
2361 , bNeedIntrospection( true )
2362 , bNativeCOMObject( false )
2364 static Reference< XIntrospection > xIntrospection;
2366 // beat out again the default properties of Sbx
2367 Remove( OUString("Name"), SbxCLASS_DONTCARE );
2368 Remove( OUString("Parent"), SbxCLASS_DONTCARE );
2370 // check the type of the ojekts
2371 TypeClass eType = aUnoObj_.getValueType().getTypeClass();
2372 Reference< XInterface > x;
2373 if( eType == TypeClass_INTERFACE )
2375 // get the interface from the Any
2376 x = *(Reference< XInterface >*)aUnoObj_.getValue();
2377 if( !x.is() )
2378 return;
2381 Reference< XTypeProvider > xTypeProvider;
2382 // Did the object have an invocation itself?
2383 mxInvocation = Reference< XInvocation >( x, UNO_QUERY );
2385 xTypeProvider = Reference< XTypeProvider >( x, UNO_QUERY );
2387 if( mxInvocation.is() )
2390 // get the ExactName
2391 mxExactNameInvocation = Reference< XExactName >::query( mxInvocation );
2393 // The remainder refers only to the introspection
2394 if( !xTypeProvider.is() )
2396 bNeedIntrospection = false;
2397 return;
2400 // Ignore introspection based members for COM objects to avoid
2401 // hiding of equally named COM symbols, e.g. XInvocation::getValue
2402 Reference< oleautomation::XAutomationObject > xAutomationObject( aUnoObj_, UNO_QUERY );
2403 if( xAutomationObject.is() )
2404 bNativeCOMObject = true;
2407 maTmpUnoObj = aUnoObj_;
2410 //*** Define the name ***
2411 sal_Bool bFatalError = sal_True;
2413 // Is it an interface or a struct?
2414 sal_Bool bSetClassName = sal_False;
2415 OUString aClassName_;
2416 if( eType == TypeClass_STRUCT || eType == TypeClass_EXCEPTION )
2418 // Struct is Ok
2419 bFatalError = sal_False;
2421 // insert the real name of the class
2422 if( aName_.isEmpty() )
2424 aClassName_ = aUnoObj_.getValueType().getTypeName();
2425 bSetClassName = sal_True;
2427 typelib_TypeDescription * pDeclTD = 0;
2428 typelib_typedescription_getByName( &pDeclTD, maTmpUnoObj.getValueTypeName().pData );
2429 StructRefInfo aThisStruct( maTmpUnoObj, pDeclTD, 0 );
2430 maStructInfo.reset( new SbUnoStructRefObject( GetName(), aThisStruct ) );
2432 else if( eType == TypeClass_INTERFACE )
2434 // Interface works always through the type in the Any
2435 bFatalError = sal_False;
2437 if( bSetClassName )
2438 SetClassName( aClassName_ );
2440 // Neither interface nor Struct -> FatalError
2441 if( bFatalError )
2443 StarBASIC::FatalError( ERRCODE_BASIC_EXCEPTION );
2444 return;
2447 // pass the introspection primal on demand
2450 SbUnoObject::~SbUnoObject()
2455 // pass the introspection on Demand
2456 void SbUnoObject::doIntrospection( void )
2458 static Reference< XIntrospection > xIntrospection;
2460 if( !bNeedIntrospection )
2461 return;
2462 bNeedIntrospection = false;
2464 if( !xIntrospection.is() )
2466 // get the introspection service
2467 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
2468 xIntrospection = Introspection::create( xContext );
2471 // pass the introspection
2474 mxUnoAccess = xIntrospection->inspect( maTmpUnoObj );
2476 catch( const RuntimeException& e )
2478 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2481 if( !mxUnoAccess.is() )
2483 // #51475 mark to indicate an invalid object (no mxMaterialHolder)
2484 return;
2487 // get MaterialHolder from access
2488 mxMaterialHolder = Reference< XMaterialHolder >::query( mxUnoAccess );
2490 // get ExactName from access
2491 mxExactName = Reference< XExactName >::query( mxUnoAccess );
2497 // Start of a list of all SbUnoMethod-Instances
2498 static SbUnoMethod* pFirst = NULL;
2500 void clearUnoMethodsForBasic( StarBASIC* pBasic )
2502 SbUnoMethod* pMeth = pFirst;
2503 while( pMeth )
2505 SbxObject* pObject = dynamic_cast< SbxObject* >( pMeth->GetParent() );
2506 if ( pObject )
2508 StarBASIC* pModBasic = dynamic_cast< StarBASIC* >( pObject->GetParent() );
2509 if ( pModBasic == pBasic )
2511 // for now the solution is to remove the method from the list and to clear it,
2512 // but in case the element should be correctly transferred to another StarBASIC,
2513 // we should either set module parent to NULL without clearing it, or even
2514 // set the new StarBASIC as the parent of the module
2515 // pObject->SetParent( NULL );
2517 if( pMeth == pFirst )
2518 pFirst = pMeth->pNext;
2519 else if( pMeth->pPrev )
2520 pMeth->pPrev->pNext = pMeth->pNext;
2521 if( pMeth->pNext )
2522 pMeth->pNext->pPrev = pMeth->pPrev;
2524 pMeth->pPrev = NULL;
2525 pMeth->pNext = NULL;
2527 pMeth->SbxValue::Clear();
2528 pObject->SbxValue::Clear();
2530 // start from the beginning after object clearing, the cycle will end since the method is removed each time
2531 pMeth = pFirst;
2533 else
2534 pMeth = pMeth->pNext;
2536 else
2537 pMeth = pMeth->pNext;
2541 void clearUnoMethods( void )
2543 SbUnoMethod* pMeth = pFirst;
2544 while( pMeth )
2546 pMeth->SbxValue::Clear();
2547 pMeth = pMeth->pNext;
2552 SbUnoMethod::SbUnoMethod
2554 const OUString& aName_,
2555 SbxDataType eSbxType,
2556 Reference< XIdlMethod > xUnoMethod_,
2557 bool bInvocation,
2558 bool bDirect
2560 : SbxMethod( aName_, eSbxType )
2561 , mbInvocation( bInvocation )
2562 , mbDirectInvocation( bDirect )
2564 m_xUnoMethod = xUnoMethod_;
2565 pParamInfoSeq = NULL;
2567 // enregister the method in a list
2568 pNext = pFirst;
2569 pPrev = NULL;
2570 pFirst = this;
2571 if( pNext )
2572 pNext->pPrev = this;
2575 SbUnoMethod::~SbUnoMethod()
2577 delete pParamInfoSeq;
2579 if( this == pFirst )
2580 pFirst = pNext;
2581 else if( pPrev )
2582 pPrev->pNext = pNext;
2583 if( pNext )
2584 pNext->pPrev = pPrev;
2587 SbxInfo* SbUnoMethod::GetInfo()
2589 if( !pInfo && m_xUnoMethod.is() )
2591 SbiInstance* pInst = GetSbData()->pInst;
2592 if( pInst && pInst->IsCompatibility() )
2594 pInfo = new SbxInfo();
2596 const Sequence<ParamInfo>& rInfoSeq = getParamInfos();
2597 const ParamInfo* pParamInfos = rInfoSeq.getConstArray();
2598 sal_uInt32 nParamCount = rInfoSeq.getLength();
2600 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
2602 const ParamInfo& rInfo = pParamInfos[i];
2603 OUString aParamName = rInfo.aName;
2605 SbxDataType t = SbxVARIANT;
2606 sal_uInt16 nFlags_ = SBX_READ;
2607 pInfo->AddParam( aParamName, t, nFlags_ );
2611 return pInfo;
2614 const Sequence<ParamInfo>& SbUnoMethod::getParamInfos( void )
2616 if( !pParamInfoSeq && m_xUnoMethod.is() )
2618 Sequence<ParamInfo> aTmp = m_xUnoMethod->getParameterInfos() ;
2619 pParamInfoSeq = new Sequence<ParamInfo>( aTmp );
2621 return *pParamInfoSeq;
2624 SbUnoProperty::SbUnoProperty
2626 const OUString& aName_,
2627 SbxDataType eSbxType,
2628 SbxDataType eRealSbxType,
2629 const Property& aUnoProp_,
2630 sal_Int32 nId_,
2631 bool bInvocation,
2632 bool bUnoStruct
2634 : SbxProperty( aName_, eSbxType )
2635 , aUnoProp( aUnoProp_ )
2636 , nId( nId_ )
2637 , mbInvocation( bInvocation )
2638 , mRealType( eRealSbxType )
2639 , mbUnoStruct( bUnoStruct )
2641 // as needed establish an dummy array so that SbiRuntime::CheckArray() works
2642 static SbxArrayRef xDummyArray = new SbxArray( SbxVARIANT );
2643 if( eSbxType & SbxARRAY )
2644 PutObject( xDummyArray );
2647 SbUnoProperty::~SbUnoProperty()
2651 SbxVariable* SbUnoObject::Find( const OUString& rName, SbxClassType t )
2653 static Reference< XIdlMethod > xDummyMethod;
2654 static Property aDummyProp;
2656 SbxVariable* pRes = SbxObject::Find( rName, t );
2658 if( bNeedIntrospection )
2659 doIntrospection();
2661 // New 1999-03-04: Create properties on demand. Therefore search now perIntrospectionAccess,
2662 // if a property or a method of the required name exist
2663 if( !pRes )
2665 OUString aUName( rName );
2666 if( mxUnoAccess.is() && !bNativeCOMObject )
2668 if( mxExactName.is() )
2670 OUString aUExactName = mxExactName->getExactName( aUName );
2671 if( !aUExactName.isEmpty() )
2673 aUName = aUExactName;
2676 if( mxUnoAccess->hasProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ) )
2678 const Property& rProp = mxUnoAccess->
2679 getProperty( aUName, PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2681 // If the property could be void the type had to be set to Variant
2682 SbxDataType eSbxType;
2683 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2684 eSbxType = SbxVARIANT;
2685 else
2686 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2688 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2689 // create the property and superimpose it
2690 SbUnoProperty* pProp = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, 0, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2691 SbxVariableRef xVarRef = pProp;
2692 QuickInsert( (SbxVariable*)xVarRef );
2693 pRes = xVarRef;
2695 else if( mxUnoAccess->hasMethod( aUName,
2696 MethodConcept::ALL - MethodConcept::DANGEROUS ) )
2698 // address the method
2699 const Reference< XIdlMethod >& rxMethod = mxUnoAccess->
2700 getMethod( aUName, MethodConcept::ALL - MethodConcept::DANGEROUS );
2702 // create SbUnoMethod and superimpose it
2703 SbxVariableRef xMethRef = new SbUnoMethod( rxMethod->getName(),
2704 unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2705 QuickInsert( (SbxVariable*)xMethRef );
2706 pRes = xMethRef;
2709 // Elsewise nothing would be found it had to be checked, if NameAccess is existent
2710 if( !pRes )
2714 Reference< XNameAccess > xNameAccess( mxUnoAccess->queryAdapter( ::getCppuType( (const Reference< XPropertySet > *)0 ) ), UNO_QUERY );
2715 OUString aUName2( rName );
2717 if( xNameAccess.is() && xNameAccess->hasByName( aUName2 ) )
2719 Any aAny = xNameAccess->getByName( aUName2 );
2721 // ATTENTION: Because of XNameAccess, the variable generated here
2722 // may not be included as a fixed property in the object and therefore
2723 // won't be stored anywhere.
2724 // If this leads to problems, it has to be created synthetically or
2725 // a class SbUnoNameAccessProperty, whose existence had to be checked
2726 // constantly and which were if necessary thrown away
2727 // if the name was not found anymore.
2728 pRes = new SbxVariable( SbxVARIANT );
2729 unoToSbxValue( pRes, aAny );
2732 catch( const NoSuchElementException& e )
2734 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2736 catch( const Exception& )
2738 // Establish so that the exeption error will not be overwriten
2739 if( !pRes )
2740 pRes = new SbxVariable( SbxVARIANT );
2742 implHandleAnyException( ::cppu::getCaughtException() );
2746 if( !pRes && mxInvocation.is() )
2748 if( mxExactNameInvocation.is() )
2750 OUString aUExactName = mxExactNameInvocation->getExactName( aUName );
2751 if( !aUExactName.isEmpty() )
2753 aUName = aUExactName;
2759 if( mxInvocation->hasProperty( aUName ) )
2761 // create a property and superimpose it
2762 SbxVariableRef xVarRef = new SbUnoProperty( aUName, SbxVARIANT, SbxVARIANT, aDummyProp, 0, true, false );
2763 QuickInsert( (SbxVariable*)xVarRef );
2764 pRes = xVarRef;
2766 else if( mxInvocation->hasMethod( aUName ) )
2768 // create SbUnoMethode and superimpose it
2769 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true );
2770 QuickInsert( (SbxVariable*)xMethRef );
2771 pRes = xMethRef;
2773 else
2775 Reference< XDirectInvocation > xDirectInvoke( mxInvocation, UNO_QUERY );
2776 if ( xDirectInvoke.is() && xDirectInvoke->hasMember( aUName ) )
2778 SbxVariableRef xMethRef = new SbUnoMethod( aUName, SbxVARIANT, xDummyMethod, true, true );
2779 QuickInsert( (SbxVariable*)xMethRef );
2780 pRes = xMethRef;
2785 catch( const RuntimeException& e )
2787 // Establish so that the exeption error will not be overwriten
2788 if( !pRes )
2789 pRes = new SbxVariable( SbxVARIANT );
2791 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION, implGetExceptionMsg( e ) );
2796 // At the very end checking if the Dbg_-Properties are meant
2798 if( !pRes )
2800 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
2801 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
2802 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
2804 // Create
2805 implCreateDbgProperties();
2807 // Now they have to be found regular
2808 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
2811 return pRes;
2815 // help method to create the dbg_-Properties
2816 void SbUnoObject::implCreateDbgProperties( void )
2818 Property aProp;
2820 // Id == -1: display the implemented interfaces corresponding the ClassProvider
2821 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
2822 QuickInsert( (SbxVariable*)xVarRef );
2824 // Id == -2: output the properties
2825 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
2826 QuickInsert( (SbxVariable*)xVarRef );
2828 // Id == -3: output the Methods
2829 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
2830 QuickInsert( (SbxVariable*)xVarRef );
2833 void SbUnoObject::implCreateAll( void )
2835 // throw away all existing methods and properties
2836 pMethods = new SbxArray;
2837 pProps = new SbxArray;
2839 if( bNeedIntrospection ) doIntrospection();
2841 // get instrospection
2842 Reference< XIntrospectionAccess > xAccess = mxUnoAccess;
2843 if( !xAccess.is() || bNativeCOMObject )
2845 if( mxInvocation.is() )
2846 xAccess = mxInvocation->getIntrospection();
2847 else if( bNativeCOMObject )
2848 return;
2850 if( !xAccess.is() )
2851 return;
2853 // Establish properties
2854 Sequence<Property> props = xAccess->getProperties( PropertyConcept::ALL - PropertyConcept::DANGEROUS );
2855 sal_uInt32 nPropCount = props.getLength();
2856 const Property* pProps_ = props.getConstArray();
2858 sal_uInt32 i;
2859 for( i = 0 ; i < nPropCount ; i++ )
2861 const Property& rProp = pProps_[ i ];
2863 // If the property could be void the type had to be set to Variant
2864 SbxDataType eSbxType;
2865 if( rProp.Attributes & PropertyAttribute::MAYBEVOID )
2866 eSbxType = SbxVARIANT;
2867 else
2868 eSbxType = unoToSbxType( rProp.Type.getTypeClass() );
2870 SbxDataType eRealSbxType = ( ( rProp.Attributes & PropertyAttribute::MAYBEVOID ) ? unoToSbxType( rProp.Type.getTypeClass() ) : eSbxType );
2871 // Create property and superimpose it
2872 SbxVariableRef xVarRef = new SbUnoProperty( rProp.Name, eSbxType, eRealSbxType, rProp, i, false, ( rProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT ) );
2873 QuickInsert( (SbxVariable*)xVarRef );
2876 // Create Dbg_-Properties
2877 implCreateDbgProperties();
2879 // Create methods
2880 Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods
2881 ( MethodConcept::ALL - MethodConcept::DANGEROUS );
2882 sal_uInt32 nMethCount = aMethodSeq.getLength();
2883 const Reference< XIdlMethod >* pMethods_ = aMethodSeq.getConstArray();
2884 for( i = 0 ; i < nMethCount ; i++ )
2886 // address method
2887 const Reference< XIdlMethod >& rxMethod = pMethods_[i];
2889 // Create SbUnoMethod and superimpose it
2890 SbxVariableRef xMethRef = new SbUnoMethod
2891 ( rxMethod->getName(), unoToSbxType( rxMethod->getReturnType() ), rxMethod, false );
2892 QuickInsert( (SbxVariable*)xMethRef );
2897 // output the value
2898 Any SbUnoObject::getUnoAny( void )
2900 Any aRetAny;
2901 if( bNeedIntrospection ) doIntrospection();
2902 if ( maStructInfo.get() )
2903 aRetAny = maTmpUnoObj;
2904 else if( mxMaterialHolder.is() )
2905 aRetAny = mxMaterialHolder->getMaterial();
2906 else if( mxInvocation.is() )
2907 aRetAny <<= mxInvocation;
2908 return aRetAny;
2911 // help method to create an Uno-Struct per CoreReflection
2912 SbUnoObject* Impl_CreateUnoStruct( const OUString& aClassName )
2914 // get CoreReflection
2915 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
2916 if( !xCoreReflection.is() )
2917 return NULL;
2919 // search for the class
2920 Reference< XIdlClass > xClass;
2921 Reference< XHierarchicalNameAccess > xHarryName =
2922 getCoreReflection_HierarchicalNameAccess_Impl();
2923 if( xHarryName.is() && xHarryName->hasByHierarchicalName( aClassName ) )
2924 xClass = xCoreReflection->forName( aClassName );
2925 if( !xClass.is() )
2926 return NULL;
2928 // Is it realy a struct?
2929 TypeClass eType = xClass->getTypeClass();
2930 if ( ( eType != TypeClass_STRUCT ) && ( eType != TypeClass_EXCEPTION ) )
2931 return NULL;
2933 // create an instance
2934 Any aNewAny;
2935 xClass->createObject( aNewAny );
2936 // make a SbUnoObject out of it
2937 SbUnoObject* pUnoObj = new SbUnoObject( aClassName, aNewAny );
2938 return pUnoObj;
2942 // Factory-Class to create Uno-Structs per DIM AS NEW
2943 SbxBase* SbUnoFactory::Create( sal_uInt16, sal_uInt32 )
2945 // Via SbxId nothing works in Uno
2946 return NULL;
2949 SbxObject* SbUnoFactory::CreateObject( const OUString& rClassName )
2951 return Impl_CreateUnoStruct( rClassName );
2955 // Provisional interface for the UNO-Connection
2956 // Deliver a SbxObject, that wrap an Uno-Interface
2957 SbxObjectRef GetSbUnoObject( const OUString& aName, const Any& aUnoObj_ )
2959 return new SbUnoObject( aName, aUnoObj_ );
2962 // Force creation of all properties for debugging
2963 void createAllObjectProperties( SbxObject* pObj )
2965 if( !pObj )
2966 return;
2968 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
2969 SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,pObj);
2970 if( pUnoObj )
2972 pUnoObj->createAllProperties();
2974 else if ( pUnoStructObj )
2976 pUnoStructObj->createAllProperties();
2978 else
2980 pObj->GetAll( SbxCLASS_DONTCARE );
2985 void RTL_Impl_CreateUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
2987 (void)pBasic;
2988 (void)bWrite;
2990 // We need 1 parameter minimum
2991 if ( rPar.Count() < 2 )
2993 StarBASIC::Error( SbERR_BAD_ARGUMENT );
2994 return;
2997 // get the name of the class of the struct
2998 OUString aClassName = rPar.Get(1)->GetOUString();
3000 // try to create Struct with the same name
3001 SbUnoObjectRef xUnoObj = Impl_CreateUnoStruct( aClassName );
3002 if( !xUnoObj )
3004 return;
3006 // return the object
3007 SbxVariableRef refVar = rPar.Get(0);
3008 refVar->PutObject( (SbUnoObject*)xUnoObj );
3011 void RTL_Impl_CreateUnoService( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3013 (void)pBasic;
3014 (void)bWrite;
3016 // We need 1 Parameter minimum
3017 if ( rPar.Count() < 2 )
3019 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3020 return;
3023 // get the name of the class of the struct
3024 OUString aServiceName = rPar.Get(1)->GetOUString();
3026 // search for the service and instatiate it
3027 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3028 Reference< XInterface > xInterface;
3031 xInterface = xFactory->createInstance( aServiceName );
3033 catch( const Exception& )
3035 implHandleAnyException( ::cppu::getCaughtException() );
3038 SbxVariableRef refVar = rPar.Get(0);
3039 if( xInterface.is() )
3041 Any aAny;
3042 aAny <<= xInterface;
3044 // Create a SbUnoObject out of it and return it
3045 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3046 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3048 // return the object
3049 refVar->PutObject( (SbUnoObject*)xUnoObj );
3051 else
3053 refVar->PutObject( NULL );
3056 else
3058 refVar->PutObject( NULL );
3062 void RTL_Impl_CreateUnoServiceWithArguments( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3064 (void)pBasic;
3065 (void)bWrite;
3067 // We need 2 parameter minimum
3068 if ( rPar.Count() < 3 )
3070 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3071 return;
3074 // get the name of the class of the struct
3075 OUString aServiceName = rPar.Get(1)->GetOUString();
3076 Any aArgAsAny = sbxToUnoValue( rPar.Get(2),
3077 getCppuType( (Sequence<Any>*)0 ) );
3078 Sequence< Any > aArgs;
3079 aArgAsAny >>= aArgs;
3081 // search for the service and instatiate it
3082 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3083 Reference< XInterface > xInterface;
3086 xInterface = xFactory->createInstanceWithArguments( aServiceName, aArgs );
3088 catch( const Exception& )
3090 implHandleAnyException( ::cppu::getCaughtException() );
3093 SbxVariableRef refVar = rPar.Get(0);
3094 if( xInterface.is() )
3096 Any aAny;
3097 aAny <<= xInterface;
3099 // Create a SbUnoObject out of it and return it
3100 SbUnoObjectRef xUnoObj = new SbUnoObject( aServiceName, aAny );
3101 if( xUnoObj->getUnoAny().getValueType().getTypeClass() != TypeClass_VOID )
3103 // return the object
3104 refVar->PutObject( (SbUnoObject*)xUnoObj );
3106 else
3108 refVar->PutObject( NULL );
3111 else
3113 refVar->PutObject( NULL );
3117 void RTL_Impl_GetProcessServiceManager( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3119 (void)pBasic;
3120 (void)bWrite;
3122 SbxVariableRef refVar = rPar.Get(0);
3124 // get the global service manager
3125 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
3126 Any aAny;
3127 aAny <<= xFactory;
3129 // Create a SbUnoObject out of it and return it
3130 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "ProcessServiceManager" ), aAny );
3131 refVar->PutObject( (SbUnoObject*)xUnoObj );
3134 void RTL_Impl_HasInterfaces( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3136 (void)pBasic;
3137 (void)bWrite;
3139 // We need 2 parameter minimum
3140 sal_uInt16 nParCount = rPar.Count();
3141 if( nParCount < 3 )
3143 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3144 return;
3147 // variable for the return value
3148 SbxVariableRef refVar = rPar.Get(0);
3149 refVar->PutBool( sal_False );
3151 // get the Uno-Object
3152 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3153 if( !(pObj && pObj->ISA(SbUnoObject)) )
3155 return;
3157 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3158 TypeClass eType = aAny.getValueType().getTypeClass();
3159 if( eType != TypeClass_INTERFACE )
3161 return;
3163 // get the interface out of the Any
3164 Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
3166 // get CoreReflection
3167 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3168 if( !xCoreReflection.is() )
3170 return;
3172 for( sal_uInt16 i = 2 ; i < nParCount ; i++ )
3174 // get the name of the interface of the struct
3175 OUString aIfaceName = rPar.Get( i )->GetOUString();
3177 // search for the class
3178 Reference< XIdlClass > xClass = xCoreReflection->forName( aIfaceName );
3179 if( !xClass.is() )
3181 return;
3183 // check if the interface will be supported
3184 OUString aClassName = xClass->getName();
3185 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
3186 if( !x->queryInterface( aClassType ).hasValue() )
3188 return;
3192 // Every thing works; then return TRUE
3193 refVar->PutBool( sal_True );
3196 void RTL_Impl_IsUnoStruct( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3198 (void)pBasic;
3199 (void)bWrite;
3201 // We need 1 parameter minimum
3202 if ( rPar.Count() < 2 )
3204 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3205 return;
3208 // variable for the return value
3209 SbxVariableRef refVar = rPar.Get(0);
3210 refVar->PutBool( sal_False );
3212 // get the Uno-Object
3213 SbxVariableRef xParam = rPar.Get( 1 );
3214 if( !xParam->IsObject() )
3216 return;
3218 SbxBaseRef pObj = (SbxBase*)rPar.Get( 1 )->GetObject();
3219 if( !(pObj && pObj->ISA(SbUnoObject)) )
3221 return;
3223 Any aAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
3224 TypeClass eType = aAny.getValueType().getTypeClass();
3225 if( eType == TypeClass_STRUCT )
3227 refVar->PutBool( sal_True );
3232 void RTL_Impl_EqualUnoObjects( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
3234 (void)pBasic;
3235 (void)bWrite;
3237 if ( rPar.Count() < 3 )
3239 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3240 return;
3243 // variable for the return value
3244 SbxVariableRef refVar = rPar.Get(0);
3245 refVar->PutBool( sal_False );
3247 // get the Uno-Objects
3248 SbxVariableRef xParam1 = rPar.Get( 1 );
3249 if( !xParam1->IsObject() )
3251 return;
3253 SbxBaseRef pObj1 = (SbxBase*)xParam1->GetObject();
3254 if( !(pObj1 && pObj1->ISA(SbUnoObject)) )
3256 return;
3258 Any aAny1 = ((SbUnoObject*)(SbxBase*)pObj1)->getUnoAny();
3259 TypeClass eType1 = aAny1.getValueType().getTypeClass();
3260 if( eType1 != TypeClass_INTERFACE )
3262 return;
3264 Reference< XInterface > x1;
3265 aAny1 >>= x1;
3267 SbxVariableRef xParam2 = rPar.Get( 2 );
3268 if( !xParam2->IsObject() )
3270 return;
3272 SbxBaseRef pObj2 = (SbxBase*)xParam2->GetObject();
3273 if( !(pObj2 && pObj2->ISA(SbUnoObject)) )
3275 return;
3277 Any aAny2 = ((SbUnoObject*)(SbxBase*)pObj2)->getUnoAny();
3278 TypeClass eType2 = aAny2.getValueType().getTypeClass();
3279 if( eType2 != TypeClass_INTERFACE )
3281 return;
3283 Reference< XInterface > x2;
3284 aAny2 >>= x2;
3286 if( x1 == x2 )
3288 refVar->PutBool( sal_True );
3293 // helper wrapper function to interact with TypeProvider and
3294 // XTypeDescriptionEnumerationAccess.
3295 // if it fails for whatever reason
3296 // returned Reference<> be null e.g. .is() will be false
3298 Reference< XTypeDescriptionEnumeration > getTypeDescriptorEnumeration( const OUString& sSearchRoot,
3299 const Sequence< TypeClass >& types,
3300 TypeDescriptionSearchDepth depth )
3302 Reference< XTypeDescriptionEnumeration > xEnum;
3303 Reference< XTypeDescriptionEnumerationAccess> xTypeEnumAccess( getTypeProvider_Impl(), UNO_QUERY );
3304 if ( xTypeEnumAccess.is() )
3308 xEnum = xTypeEnumAccess->createTypeDescriptionEnumeration(
3309 sSearchRoot, types, depth );
3311 catch(const NoSuchTypeNameException& /*nstne*/ ) {}
3312 catch(const InvalidTypeNameException& /*nstne*/ ) {}
3314 return xEnum;
3317 typedef boost::unordered_map< OUString, Any, OUStringHash, ::std::equal_to< OUString > > VBAConstantsHash;
3319 VBAConstantHelper&
3320 VBAConstantHelper::instance()
3322 static VBAConstantHelper aHelper;
3323 return aHelper;
3326 void VBAConstantHelper::init()
3328 if ( !isInited )
3330 Sequence< TypeClass > types(1);
3331 types[ 0 ] = TypeClass_CONSTANTS;
3332 Reference< XTypeDescriptionEnumeration > xEnum = getTypeDescriptorEnumeration( OUString(defaultNameSpace), types, TypeDescriptionSearchDepth_INFINITE );
3334 if ( !xEnum.is())
3336 return; //NULL;
3338 while ( xEnum->hasMoreElements() )
3340 Reference< XConstantsTypeDescription > xConstants( xEnum->nextElement(), UNO_QUERY );
3341 if ( xConstants.is() )
3343 // store constant group name
3344 OUString sFullName = xConstants->getName();
3345 sal_Int32 indexLastDot = sFullName.lastIndexOf('.');
3346 OUString sLeafName( sFullName );
3347 if ( indexLastDot > -1 )
3349 sLeafName = sFullName.copy( indexLastDot + 1);
3351 aConstCache.push_back( sLeafName ); // assume constant group names are unique
3352 Sequence< Reference< XConstantTypeDescription > > aConsts = xConstants->getConstants();
3353 Reference< XConstantTypeDescription >* pSrc = aConsts.getArray();
3354 sal_Int32 nLen = aConsts.getLength();
3355 for ( sal_Int32 index =0; index<nLen; ++pSrc, ++index )
3357 // store constant member name
3358 Reference< XConstantTypeDescription >& rXConst = *pSrc;
3359 sFullName = rXConst->getName();
3360 indexLastDot = sFullName.lastIndexOf('.');
3361 sLeafName = sFullName;
3362 if ( indexLastDot > -1 )
3364 sLeafName = sFullName.copy( indexLastDot + 1);
3366 aConstHash[ sLeafName.toAsciiLowerCase() ] = rXConst->getConstantValue();
3370 isInited = true;
3374 bool
3375 VBAConstantHelper::isVBAConstantType( const OUString& rName )
3377 init();
3378 bool bConstant = false;
3379 OUString sKey( rName );
3380 VBAConstantsVector::const_iterator it = aConstCache.begin();
3382 for( ; it != aConstCache.end(); ++it )
3384 if( sKey.equalsIgnoreAsciiCase( *it ) )
3386 bConstant = true;
3387 break;
3390 return bConstant;
3393 SbxVariable*
3394 VBAConstantHelper::getVBAConstant( const OUString& rName )
3396 SbxVariable* pConst = NULL;
3397 init();
3399 OUString sKey( rName );
3401 VBAConstantsHash::const_iterator it = aConstHash.find( sKey.toAsciiLowerCase() );
3403 if ( it != aConstHash.end() )
3405 pConst = new SbxVariable( SbxVARIANT );
3406 pConst->SetName( rName );
3407 unoToSbxValue( pConst, it->second );
3410 return pConst;
3413 // Function to search for a global identifier in the
3414 // UnoScope and to wrap it for Sbx
3415 SbUnoClass* findUnoClass( const OUString& rName )
3417 // #105550 Check if module exists
3418 SbUnoClass* pUnoClass = NULL;
3420 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3421 if( xTypeAccess->hasByHierarchicalName( rName ) )
3423 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3424 Reference< XTypeDescription > xTypeDesc;
3425 aRet >>= xTypeDesc;
3427 if( xTypeDesc.is() )
3429 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3430 if( eTypeClass == TypeClass_MODULE || eTypeClass == TypeClass_CONSTANTS )
3432 pUnoClass = new SbUnoClass( rName );
3436 return pUnoClass;
3439 SbxVariable* SbUnoClass::Find( const OUString& rName, SbxClassType )
3441 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_VARIABLE );
3443 // If nothing were located the submodule isn't known yet
3444 if( !pRes )
3446 // If it is already a class, ask for the field
3447 if( m_xClass.is() )
3449 // Is it a field(?)
3450 OUString aUStr( rName );
3451 Reference< XIdlField > xField = m_xClass->getField( aUStr );
3452 Reference< XIdlClass > xClass;
3453 if( xField.is() )
3457 Any aAny;
3458 aAny = xField->get( aAny );
3460 // Convert to Sbx
3461 pRes = new SbxVariable( SbxVARIANT );
3462 pRes->SetName( rName );
3463 unoToSbxValue( pRes, aAny );
3465 catch( const Exception& )
3467 implHandleAnyException( ::cppu::getCaughtException() );
3471 else
3473 // expand fully qualified name
3474 OUString aNewName = GetName();
3475 aNewName += ".";
3476 aNewName += rName;
3478 // get CoreReflection
3479 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
3480 if( xCoreReflection.is() )
3482 // Is it a constant?
3483 Reference< XHierarchicalNameAccess > xHarryName( xCoreReflection, UNO_QUERY );
3484 if( xHarryName.is() )
3488 Any aValue = xHarryName->getByHierarchicalName( aNewName );
3489 TypeClass eType = aValue.getValueType().getTypeClass();
3491 // Interface located? Then it is a class
3492 if( eType == TypeClass_INTERFACE )
3494 Reference< XInterface > xIface = *(Reference< XInterface >*)aValue.getValue();
3495 Reference< XIdlClass > xClass( xIface, UNO_QUERY );
3496 if( xClass.is() )
3498 pRes = new SbxVariable( SbxVARIANT );
3499 SbxObjectRef xWrapper = (SbxObject*)new SbUnoClass( aNewName, xClass );
3500 pRes->PutObject( xWrapper );
3503 else
3505 pRes = new SbxVariable( SbxVARIANT );
3506 unoToSbxValue( pRes, aValue );
3509 catch( const NoSuchElementException& )
3514 // Otherwise take it again as class
3515 if( !pRes )
3517 SbUnoClass* pNewClass = findUnoClass( aNewName );
3518 if( pNewClass )
3520 pRes = new SbxVariable( SbxVARIANT );
3521 SbxObjectRef xWrapper = (SbxObject*)pNewClass;
3522 pRes->PutObject( xWrapper );
3526 // An UNO service?
3527 if( !pRes )
3529 SbUnoService* pUnoService = findUnoService( aNewName );
3530 if( pUnoService )
3532 pRes = new SbxVariable( SbxVARIANT );
3533 SbxObjectRef xWrapper = (SbxObject*)pUnoService;
3534 pRes->PutObject( xWrapper );
3538 // An UNO singleton?
3539 if( !pRes )
3541 SbUnoSingleton* pUnoSingleton = findUnoSingleton( aNewName );
3542 if( pUnoSingleton )
3544 pRes = new SbxVariable( SbxVARIANT );
3545 SbxObjectRef xWrapper = (SbxObject*)pUnoSingleton;
3546 pRes->PutObject( xWrapper );
3552 if( pRes )
3554 pRes->SetName( rName );
3556 // Insert variable, so that it could be found later
3557 QuickInsert( pRes );
3559 // Take us out as listener at once,
3560 // the values are all constant
3561 if( pRes->IsBroadcaster() )
3562 EndListening( pRes->GetBroadcaster(), sal_True );
3565 return pRes;
3569 SbUnoService* findUnoService( const OUString& rName )
3571 SbUnoService* pSbUnoService = NULL;
3573 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3574 if( xTypeAccess->hasByHierarchicalName( rName ) )
3576 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3577 Reference< XTypeDescription > xTypeDesc;
3578 aRet >>= xTypeDesc;
3580 if( xTypeDesc.is() )
3582 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3583 if( eTypeClass == TypeClass_SERVICE )
3585 Reference< XServiceTypeDescription2 > xServiceTypeDesc( xTypeDesc, UNO_QUERY );
3586 if( xServiceTypeDesc.is() )
3587 pSbUnoService = new SbUnoService( rName, xServiceTypeDesc );
3591 return pSbUnoService;
3594 SbxVariable* SbUnoService::Find( const OUString& rName, SbxClassType )
3596 SbxVariable* pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3598 if( !pRes )
3600 // If it is already a class ask for a field
3601 if( m_bNeedsInit && m_xServiceTypeDesc.is() )
3603 m_bNeedsInit = false;
3605 Sequence< Reference< XServiceConstructorDescription > > aSCDSeq = m_xServiceTypeDesc->getConstructors();
3606 const Reference< XServiceConstructorDescription >* pCtorSeq = aSCDSeq.getConstArray();
3607 int nCtorCount = aSCDSeq.getLength();
3608 for( int i = 0 ; i < nCtorCount ; ++i )
3610 Reference< XServiceConstructorDescription > xCtor = pCtorSeq[i];
3612 OUString aName( xCtor->getName() );
3613 if( aName.isEmpty() )
3615 if( xCtor->isDefaultConstructor() )
3617 aName = OUString("create");
3621 if( !aName.isEmpty() )
3623 // Create and insert SbUnoServiceCtor
3624 SbxVariableRef xSbCtorRef = new SbUnoServiceCtor( aName, xCtor );
3625 QuickInsert( (SbxVariable*)xSbCtorRef );
3628 pRes = SbxObject::Find( rName, SbxCLASS_METHOD );
3632 return pRes;
3635 void SbUnoService::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3636 const SfxHint& rHint, const TypeId& rHintType )
3638 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3639 if( pHint )
3641 SbxVariable* pVar = pHint->GetVar();
3642 SbxArray* pParams = pVar->GetParameters();
3643 SbUnoServiceCtor* pUnoCtor = PTR_CAST(SbUnoServiceCtor,pVar);
3644 if( pUnoCtor && pHint->GetId() == SBX_HINT_DATAWANTED )
3646 // Parameter count -1 because of Param0 == this
3647 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3648 Sequence<Any> args;
3649 sal_Bool bOutParams = sal_False;
3651 Reference< XServiceConstructorDescription > xCtor = pUnoCtor->getServiceCtorDesc();
3652 Sequence< Reference< XParameter > > aParameterSeq = xCtor->getParameters();
3653 const Reference< XParameter >* pParameterSeq = aParameterSeq.getConstArray();
3654 sal_uInt32 nUnoParamCount = aParameterSeq.getLength();
3656 // Default: Ignore not needed parameters
3657 bool bParameterError = false;
3659 // Is the last parameter a rest parameter?
3660 bool bRestParameterMode = false;
3661 if( nUnoParamCount > 0 )
3663 Reference< XParameter > xLastParam = pParameterSeq[ nUnoParamCount - 1 ];
3664 if( xLastParam.is() )
3666 if( xLastParam->isRestParameter() )
3667 bRestParameterMode = true;
3671 // Too many parameters with context as first parameter?
3672 sal_uInt16 nSbxParameterOffset = 1;
3673 sal_uInt16 nParameterOffsetByContext = 0;
3674 Reference < XComponentContext > xFirstParamContext;
3675 if( nParamCount > nUnoParamCount )
3677 // Check if first parameter is a context and use it
3678 // then in createInstanceWithArgumentsAndContext
3679 Any aArg0 = sbxToUnoValue( pParams->Get( nSbxParameterOffset ) );
3680 if( (aArg0 >>= xFirstParamContext) && xFirstParamContext.is() )
3681 nParameterOffsetByContext = 1;
3684 sal_uInt32 nEffectiveParamCount = nParamCount - nParameterOffsetByContext;
3685 sal_uInt32 nAllocParamCount = nEffectiveParamCount;
3686 if( nEffectiveParamCount > nUnoParamCount )
3688 if( !bRestParameterMode )
3690 nEffectiveParamCount = nUnoParamCount;
3691 nAllocParamCount = nUnoParamCount;
3694 // Not enough parameters?
3695 else if( nUnoParamCount > nEffectiveParamCount )
3697 // RestParameterMode only helps if one (the last) parameter is missing
3698 int nDiff = nUnoParamCount - nEffectiveParamCount;
3699 if( !bRestParameterMode || nDiff > 1 )
3701 bParameterError = true;
3702 StarBASIC::Error( SbERR_NOT_OPTIONAL );
3706 if( !bParameterError )
3708 if( nAllocParamCount > 0 )
3710 args.realloc( nAllocParamCount );
3711 Any* pAnyArgs = args.getArray();
3712 for( sal_uInt32 i = 0 ; i < nEffectiveParamCount ; i++ )
3714 sal_uInt16 iSbx = (sal_uInt16)(i + nSbxParameterOffset + nParameterOffsetByContext);
3716 // bRestParameterMode allows nEffectiveParamCount > nUnoParamCount
3717 Reference< XParameter > xParam;
3718 if( i < nUnoParamCount )
3720 xParam = pParameterSeq[i];
3721 if( !xParam.is() )
3722 continue;
3724 Reference< XTypeDescription > xParamTypeDesc = xParam->getType();
3725 if( !xParamTypeDesc.is() )
3726 continue;
3727 com::sun::star::uno::Type aType( xParamTypeDesc->getTypeClass(), xParamTypeDesc->getName() );
3729 // sbx paramter needs offset 1
3730 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ), aType );
3732 // Check for out parameter if not already done
3733 if( !bOutParams )
3735 if( xParam->isOut() )
3736 bOutParams = sal_True;
3739 else
3741 pAnyArgs[i] = sbxToUnoValue( pParams->Get( iSbx ) );
3746 // "Call" ctor using createInstanceWithArgumentsAndContext
3747 Reference < XComponentContext > xContext(
3748 xFirstParamContext.is()
3749 ? xFirstParamContext
3750 : comphelper::getProcessComponentContext() );
3751 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
3753 Any aRetAny;
3754 OUString aServiceName = GetName();
3755 Reference < XInterface > xRet;
3758 xRet = xServiceMgr->createInstanceWithArgumentsAndContext( aServiceName, args, xContext );
3760 catch( const Exception& )
3762 implHandleAnyException( ::cppu::getCaughtException() );
3764 aRetAny <<= xRet;
3765 unoToSbxValue( pVar, aRetAny );
3767 // Copy back out parameters?
3768 if( bOutParams )
3770 const Any* pAnyArgs = args.getConstArray();
3772 for( sal_uInt32 j = 0 ; j < nUnoParamCount ; j++ )
3774 Reference< XParameter > xParam = pParameterSeq[j];
3775 if( !xParam.is() )
3776 continue;
3778 if( xParam->isOut() )
3779 unoToSbxValue( (SbxVariable*)pParams->Get( (sal_uInt16)(j+1) ), pAnyArgs[ j ] );
3784 else
3785 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3791 static SbUnoServiceCtor* pFirstCtor = NULL;
3793 void clearUnoServiceCtors( void )
3795 SbUnoServiceCtor* pCtor = pFirstCtor;
3796 while( pCtor )
3798 pCtor->SbxValue::Clear();
3799 pCtor = pCtor->pNext;
3803 SbUnoServiceCtor::SbUnoServiceCtor( const OUString& aName_, Reference< XServiceConstructorDescription > xServiceCtorDesc )
3804 : SbxMethod( aName_, SbxOBJECT )
3805 , m_xServiceCtorDesc( xServiceCtorDesc )
3809 SbUnoServiceCtor::~SbUnoServiceCtor()
3813 SbxInfo* SbUnoServiceCtor::GetInfo()
3815 SbxInfo* pRet = NULL;
3817 return pRet;
3821 SbUnoSingleton* findUnoSingleton( const OUString& rName )
3823 SbUnoSingleton* pSbUnoSingleton = NULL;
3825 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
3826 if( xTypeAccess->hasByHierarchicalName( rName ) )
3828 Any aRet = xTypeAccess->getByHierarchicalName( rName );
3829 Reference< XTypeDescription > xTypeDesc;
3830 aRet >>= xTypeDesc;
3832 if( xTypeDesc.is() )
3834 TypeClass eTypeClass = xTypeDesc->getTypeClass();
3835 if( eTypeClass == TypeClass_SINGLETON )
3837 Reference< XSingletonTypeDescription > xSingletonTypeDesc( xTypeDesc, UNO_QUERY );
3838 if( xSingletonTypeDesc.is() )
3839 pSbUnoSingleton = new SbUnoSingleton( rName, xSingletonTypeDesc );
3843 return pSbUnoSingleton;
3846 SbUnoSingleton::SbUnoSingleton( const OUString& aName_,
3847 const Reference< XSingletonTypeDescription >& xSingletonTypeDesc )
3848 : SbxObject( aName_ )
3849 , m_xSingletonTypeDesc( xSingletonTypeDesc )
3851 SbxVariableRef xGetMethodRef = new SbxMethod( OUString( "get" ), SbxOBJECT );
3852 QuickInsert( (SbxVariable*)xGetMethodRef );
3855 void SbUnoSingleton::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
3856 const SfxHint& rHint, const TypeId& rHintType )
3858 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
3859 if( pHint )
3861 SbxVariable* pVar = pHint->GetVar();
3862 SbxArray* pParams = pVar->GetParameters();
3863 sal_uInt32 nParamCount = pParams ? ((sal_uInt32)pParams->Count() - 1) : 0;
3864 sal_uInt32 nAllowedParamCount = 1;
3866 Reference < XComponentContext > xContextToUse;
3867 if( nParamCount > 0 )
3869 // Check if first parameter is a context and use it then
3870 Reference < XComponentContext > xFirstParamContext;
3871 Any aArg1 = sbxToUnoValue( pParams->Get( 1 ) );
3872 if( (aArg1 >>= xFirstParamContext) && xFirstParamContext.is() )
3873 xContextToUse = xFirstParamContext;
3876 if( !xContextToUse.is() )
3878 xContextToUse = comphelper::getProcessComponentContext();
3879 --nAllowedParamCount;
3882 if( nParamCount > nAllowedParamCount )
3884 StarBASIC::Error( SbERR_BAD_ARGUMENT );
3885 return;
3888 Any aRetAny;
3889 if( xContextToUse.is() )
3891 OUString aSingletonName( "/singletons/" );
3892 aSingletonName += GetName();
3893 Reference < XInterface > xRet;
3894 xContextToUse->getValueByName( aSingletonName ) >>= xRet;
3895 aRetAny <<= xRet;
3897 unoToSbxValue( pVar, aRetAny );
3899 else
3901 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
3906 //========================================================================
3908 // Implementation of an EventAttacher-drawn AllListener, which
3909 // solely transmits several events to an general AllListener
3910 class BasicAllListener_Impl : public BasicAllListenerHelper
3912 virtual void firing_impl(const AllEventObject& Event, Any* pRet);
3914 public:
3915 SbxObjectRef xSbxObj;
3916 OUString aPrefixName;
3918 BasicAllListener_Impl( const OUString& aPrefixName );
3919 ~BasicAllListener_Impl();
3921 // Methods of XAllListener
3922 virtual void SAL_CALL firing(const AllEventObject& Event) throw ( RuntimeException );
3923 virtual Any SAL_CALL approveFiring(const AllEventObject& Event) throw ( RuntimeException );
3925 // Methods of XEventListener
3926 virtual void SAL_CALL disposing(const EventObject& Source) throw ( RuntimeException );
3930 //========================================================================
3931 BasicAllListener_Impl::BasicAllListener_Impl(const OUString& aPrefixName_)
3932 : aPrefixName( aPrefixName_ )
3936 //========================================================================
3937 BasicAllListener_Impl::~BasicAllListener_Impl()
3941 //========================================================================
3943 void BasicAllListener_Impl::firing_impl( const AllEventObject& Event, Any* pRet )
3945 SolarMutexGuard guard;
3947 if( xSbxObj.Is() )
3949 OUString aMethodName = aPrefixName;
3950 aMethodName = aMethodName + Event.MethodName;
3952 SbxVariable * pP = xSbxObj;
3953 while( pP->GetParent() )
3955 pP = pP->GetParent();
3956 StarBASIC * pLib = PTR_CAST(StarBASIC,pP);
3957 if( pLib )
3959 // Create in a Basic Array
3960 SbxArrayRef xSbxArray = new SbxArray( SbxVARIANT );
3961 const Any * pArgs = Event.Arguments.getConstArray();
3962 sal_Int32 nCount = Event.Arguments.getLength();
3963 for( sal_Int32 i = 0; i < nCount; i++ )
3965 // Convert elements
3966 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
3967 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
3968 xSbxArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
3971 pLib->Call( aMethodName, xSbxArray );
3973 // get the return value from the Param-Array, if requestet
3974 if( pRet )
3976 SbxVariable* pVar = xSbxArray->Get( 0 );
3977 if( pVar )
3979 // #95792 Avoid a second call
3980 sal_uInt16 nFlags = pVar->GetFlags();
3981 pVar->SetFlag( SBX_NO_BROADCAST );
3982 *pRet = sbxToUnoValueImpl( pVar );
3983 pVar->SetFlags( nFlags );
3986 break;
3993 // Methods of Listener
3994 void BasicAllListener_Impl::firing( const AllEventObject& Event ) throw ( RuntimeException )
3996 firing_impl( Event, NULL );
3999 Any BasicAllListener_Impl::approveFiring( const AllEventObject& Event ) throw ( RuntimeException )
4001 Any aRetAny;
4002 firing_impl( Event, &aRetAny );
4003 return aRetAny;
4006 //========================================================================
4007 // Methods of XEventListener
4008 void BasicAllListener_Impl ::disposing(const EventObject& ) throw ( RuntimeException )
4010 SolarMutexGuard guard;
4012 xSbxObj.Clear();
4017 //*************************************************************************
4018 // class InvocationToAllListenerMapper
4019 // helper class to map XInvocation to XAllListener (also in project eventattacher!)
4020 //*************************************************************************
4021 class InvocationToAllListenerMapper : public WeakImplHelper1< XInvocation >
4023 public:
4024 InvocationToAllListenerMapper( const Reference< XIdlClass >& ListenerType,
4025 const Reference< XAllListener >& AllListener, const Any& Helper );
4027 // XInvocation
4028 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(void) throw( RuntimeException );
4029 virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4030 throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException );
4031 virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value)
4032 throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException );
4033 virtual Any SAL_CALL getValue(const OUString& PropertyName) throw( UnknownPropertyException, RuntimeException );
4034 virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException );
4035 virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException );
4037 private:
4038 Reference< XIdlReflection > m_xCoreReflection;
4039 Reference< XAllListener > m_xAllListener;
4040 Reference< XIdlClass > m_xListenerType;
4041 Any m_Helper;
4045 // Function to replace AllListenerAdapterService::createAllListerAdapter
4046 Reference< XInterface > createAllListenerAdapter
4048 const Reference< XInvocationAdapterFactory2 >& xInvocationAdapterFactory,
4049 const Reference< XIdlClass >& xListenerType,
4050 const Reference< XAllListener >& xListener,
4051 const Any& Helper
4054 Reference< XInterface > xAdapter;
4055 if( xInvocationAdapterFactory.is() && xListenerType.is() && xListener.is() )
4057 Reference< XInvocation > xInvocationToAllListenerMapper =
4058 (XInvocation*)new InvocationToAllListenerMapper( xListenerType, xListener, Helper );
4059 Type aListenerType( xListenerType->getTypeClass(), xListenerType->getName() );
4060 Sequence<Type> arg2(1);
4061 arg2[0] = aListenerType;
4062 xAdapter = xInvocationAdapterFactory->createAdapter( xInvocationToAllListenerMapper, arg2 );
4064 return xAdapter;
4068 //--------------------------------------------------------------------------------------------------
4069 // InvocationToAllListenerMapper
4070 InvocationToAllListenerMapper::InvocationToAllListenerMapper
4071 ( const Reference< XIdlClass >& ListenerType, const Reference< XAllListener >& AllListener, const Any& Helper )
4072 : m_xAllListener( AllListener )
4073 , m_xListenerType( ListenerType )
4074 , m_Helper( Helper )
4078 //*************************************************************************
4079 Reference< XIntrospectionAccess > SAL_CALL InvocationToAllListenerMapper::getIntrospection(void)
4080 throw( RuntimeException )
4082 return Reference< XIntrospectionAccess >();
4085 //*************************************************************************
4086 Any SAL_CALL InvocationToAllListenerMapper::invoke(const OUString& FunctionName, const Sequence< Any >& Params,
4087 Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam)
4088 throw( IllegalArgumentException, CannotConvertException,
4089 InvocationTargetException, RuntimeException )
4091 (void)OutParamIndex;
4092 (void)OutParam ;
4094 Any aRet;
4096 // Check if to firing or approveFiring has to be called
4097 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( FunctionName );
4098 sal_Bool bApproveFiring = sal_False;
4099 if( !xMethod.is() )
4100 return aRet;
4101 Reference< XIdlClass > xReturnType = xMethod->getReturnType();
4102 Sequence< Reference< XIdlClass > > aExceptionSeq = xMethod->getExceptionTypes();
4103 if( ( xReturnType.is() && xReturnType->getTypeClass() != TypeClass_VOID ) ||
4104 aExceptionSeq.getLength() > 0 )
4106 bApproveFiring = sal_True;
4108 else
4110 Sequence< ParamInfo > aParamSeq = xMethod->getParameterInfos();
4111 sal_uInt32 nParamCount = aParamSeq.getLength();
4112 if( nParamCount > 1 )
4114 const ParamInfo* pInfos = aParamSeq.getConstArray();
4115 for( sal_uInt32 i = 0 ; i < nParamCount ; i++ )
4117 if( pInfos[ i ].aMode != ParamMode_IN )
4119 bApproveFiring = sal_True;
4120 break;
4126 AllEventObject aAllEvent;
4127 aAllEvent.Source = (OWeakObject*) this;
4128 aAllEvent.Helper = m_Helper;
4129 aAllEvent.ListenerType = Type(m_xListenerType->getTypeClass(), m_xListenerType->getName() );
4130 aAllEvent.MethodName = FunctionName;
4131 aAllEvent.Arguments = Params;
4132 if( bApproveFiring )
4133 aRet = m_xAllListener->approveFiring( aAllEvent );
4134 else
4135 m_xAllListener->firing( aAllEvent );
4136 return aRet;
4139 //*************************************************************************
4140 void SAL_CALL InvocationToAllListenerMapper::setValue(const OUString& PropertyName, const Any& Value)
4141 throw( UnknownPropertyException, CannotConvertException,
4142 InvocationTargetException, RuntimeException )
4144 (void)PropertyName;
4145 (void)Value;
4148 //*************************************************************************
4149 Any SAL_CALL InvocationToAllListenerMapper::getValue(const OUString& PropertyName)
4150 throw( UnknownPropertyException, RuntimeException )
4152 (void)PropertyName;
4154 return Any();
4157 //*************************************************************************
4158 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasMethod(const OUString& Name)
4159 throw( RuntimeException )
4161 Reference< XIdlMethod > xMethod = m_xListenerType->getMethod( Name );
4162 return xMethod.is();
4165 //*************************************************************************
4166 sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Name)
4167 throw( RuntimeException )
4169 Reference< XIdlField > xField = m_xListenerType->getField( Name );
4170 return xField.is();
4173 //========================================================================
4174 // create Uno-Service
4175 // 1. Parameter == Prefix-Name of the macro
4176 // 2. Parameter == fully qualified name of the listener
4177 void SbRtl_CreateUnoListener( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4178 //RTLFUNC(CreateUnoListener)
4180 (void)bWrite;
4182 // We need 2 parameters
4183 if ( rPar.Count() != 3 )
4185 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4186 return;
4189 // get the name of the class of the struct
4190 OUString aPrefixName = rPar.Get(1)->GetOUString();
4191 OUString aListenerClassName = rPar.Get(2)->GetOUString();
4193 // get the CoreReflection
4194 Reference< XIdlReflection > xCoreReflection = getCoreReflection_Impl();
4195 if( !xCoreReflection.is() )
4196 return;
4198 // get the AllListenerAdapterService
4199 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
4201 // search the class
4202 Reference< XIdlClass > xClass = xCoreReflection->forName( aListenerClassName );
4203 if( !xClass.is() )
4204 return;
4206 // From 1999-11-30: get the InvocationAdapterFactory
4207 Reference< XInvocationAdapterFactory2 > xInvocationAdapterFactory =
4208 InvocationAdapterFactory::create( xContext );
4210 BasicAllListener_Impl * p;
4211 Reference< XAllListener > xAllLst = p = new BasicAllListener_Impl( aPrefixName );
4212 Any aTmp;
4213 Reference< XInterface > xLst = createAllListenerAdapter( xInvocationAdapterFactory, xClass, xAllLst, aTmp );
4214 if( !xLst.is() )
4215 return;
4217 OUString aClassName = xClass->getName();
4218 Type aClassType( xClass->getTypeClass(), aClassName.getStr() );
4219 aTmp = xLst->queryInterface( aClassType );
4220 if( !aTmp.hasValue() )
4221 return;
4223 SbUnoObject* pUnoObj = new SbUnoObject( aListenerClassName, aTmp );
4224 p->xSbxObj = pUnoObj;
4225 p->xSbxObj->SetParent( pBasic );
4227 // #100326 Register listener object to set Parent NULL in Dtor
4228 SbxArrayRef xBasicUnoListeners = pBasic->getUnoListeners();
4229 xBasicUnoListeners->Insert( pUnoObj, xBasicUnoListeners->Count() );
4231 // return the object
4232 SbxVariableRef refVar = rPar.Get(0);
4233 refVar->PutObject( p->xSbxObj );
4236 //========================================================================
4237 // Represents the DefaultContext property of the ProcessServiceManager
4238 // in the Basic runtime system.
4239 void RTL_Impl_GetDefaultContext( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4241 (void)pBasic;
4242 (void)bWrite;
4244 SbxVariableRef refVar = rPar.Get(0);
4246 Any aContextAny( comphelper::getProcessComponentContext() );
4248 SbUnoObjectRef xUnoObj = new SbUnoObject( OUString( "DefaultContext" ), aContextAny );
4249 refVar->PutObject( (SbUnoObject*)xUnoObj );
4252 //========================================================================
4253 // Creates a Basic wrapper object for a strongly typed Uno value
4254 // 1. parameter: Uno type as full qualified type name, e.g. "byte[]"
4255 void RTL_Impl_CreateUnoValue( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite )
4257 (void)pBasic;
4258 (void)bWrite;
4260 static OUString aTypeTypeString( "type" );
4262 // 2 parameters needed
4263 if ( rPar.Count() != 3 )
4265 StarBASIC::Error( SbERR_BAD_ARGUMENT );
4266 return;
4269 // get the name of the class of the struct
4270 OUString aTypeName = rPar.Get(1)->GetOUString();
4271 SbxVariable* pVal = rPar.Get(2);
4273 if( aTypeName == aTypeTypeString )
4275 SbxDataType eBaseType = pVal->SbxValue::GetType();
4276 OUString aValTypeName;
4277 if( eBaseType == SbxSTRING )
4279 aValTypeName = pVal->GetOUString();
4281 else if( eBaseType == SbxOBJECT )
4283 // XIdlClass?
4284 Reference< XIdlClass > xIdlClass;
4286 SbxBaseRef pObj = (SbxBase*)pVal->GetObject();
4287 if( pObj && pObj->ISA(SbUnoObject) )
4289 Any aUnoAny = ((SbUnoObject*)(SbxBase*)pObj)->getUnoAny();
4290 aUnoAny >>= xIdlClass;
4293 if( xIdlClass.is() )
4295 aValTypeName = xIdlClass->getName();
4298 Type aType;
4299 bool bSuccess = implGetTypeByName( aValTypeName, aType );
4300 if( bSuccess )
4302 Any aTypeAny( aType );
4303 SbxVariableRef refVar = rPar.Get(0);
4304 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aTypeAny );
4305 refVar->PutObject( xUnoAnyObject );
4307 return;
4310 // Check the type
4311 Reference< XHierarchicalNameAccess > xTypeAccess = getTypeProvider_Impl();
4312 Any aRet;
4315 aRet = xTypeAccess->getByHierarchicalName( aTypeName );
4317 catch( const NoSuchElementException& e1 )
4319 OUString aNoSuchElementExceptionName( "com.sun.star.container.NoSuchElementException" );
4320 StarBASIC::Error( ERRCODE_BASIC_EXCEPTION,
4321 implGetExceptionMsg( e1, aNoSuchElementExceptionName ) );
4322 return;
4324 Reference< XTypeDescription > xTypeDesc;
4325 aRet >>= xTypeDesc;
4326 TypeClass eTypeClass = xTypeDesc->getTypeClass();
4327 Type aDestType( eTypeClass, aTypeName );
4330 // Preconvert value
4331 Any aVal = sbxToUnoValueImpl( pVal );
4332 Any aConvertedVal = convertAny( aVal, aDestType );
4334 SbxVariableRef refVar = rPar.Get(0);
4335 SbxObjectRef xUnoAnyObject = new SbUnoAnyObject( aConvertedVal );
4336 refVar->PutObject( xUnoAnyObject );
4339 //==========================================================================
4341 namespace {
4342 class OMutexBasis
4344 protected:
4345 // this mutex is necessary for OInterfaceContainerHelper
4346 ::osl::Mutex m_aMutex;
4348 } // namespace
4350 typedef WeakImplHelper2< XInvocation, XComponent > ModuleInvocationProxyHelper;
4352 class ModuleInvocationProxy : public OMutexBasis,
4353 public ModuleInvocationProxyHelper
4355 OUString m_aPrefix;
4356 SbxObjectRef m_xScopeObj;
4357 bool m_bProxyIsClassModuleObject;
4359 ::cppu::OInterfaceContainerHelper m_aListeners;
4361 public:
4362 ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj );
4363 ~ModuleInvocationProxy()
4366 // XInvocation
4367 virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw();
4368 virtual void SAL_CALL setValue( const OUString& rProperty, const Any& rValue )
4369 throw( UnknownPropertyException );
4370 virtual Any SAL_CALL getValue( const OUString& rProperty )
4371 throw( UnknownPropertyException );
4372 virtual sal_Bool SAL_CALL hasMethod( const OUString& rName ) throw();
4373 virtual sal_Bool SAL_CALL hasProperty( const OUString& rProp ) throw();
4375 virtual Any SAL_CALL invoke( const OUString& rFunction,
4376 const Sequence< Any >& rParams,
4377 Sequence< sal_Int16 >& rOutParamIndex,
4378 Sequence< Any >& rOutParam )
4379 throw( CannotConvertException, InvocationTargetException );
4381 // XComponent
4382 virtual void SAL_CALL dispose() throw(RuntimeException);
4383 virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException);
4384 virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) throw (RuntimeException);
4387 ModuleInvocationProxy::ModuleInvocationProxy( const OUString& aPrefix, SbxObjectRef xScopeObj )
4388 : m_aPrefix( aPrefix + OUString( "_" ) )
4389 , m_xScopeObj( xScopeObj )
4390 , m_aListeners( m_aMutex )
4392 m_bProxyIsClassModuleObject = xScopeObj.Is() ? xScopeObj->ISA(SbClassModuleObject) : false;
4395 Reference< XIntrospectionAccess > SAL_CALL ModuleInvocationProxy::getIntrospection() throw()
4397 return Reference< XIntrospectionAccess >();
4400 void SAL_CALL ModuleInvocationProxy::setValue( const OUString& rProperty, const Any& rValue ) throw( UnknownPropertyException )
4402 if( !m_bProxyIsClassModuleObject )
4403 throw UnknownPropertyException();
4405 SolarMutexGuard guard;
4407 OUString aPropertyFunctionName( "Property Set " );
4408 aPropertyFunctionName += m_aPrefix;
4409 aPropertyFunctionName += rProperty;
4411 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4412 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4413 if( pMeth == NULL )
4415 // TODO: Check vba behavior concernig missing function
4416 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4417 throw UnknownPropertyException();
4420 // Setup parameter
4421 SbxArrayRef xArray = new SbxArray;
4422 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4423 unoToSbxValue( (SbxVariable*)xVar, rValue );
4424 xArray->Put( xVar, 1 );
4426 // Call property method
4427 SbxVariableRef xValue = new SbxVariable;
4428 pMeth->SetParameters( xArray );
4429 pMeth->Call( xValue );
4430 pMeth->SetParameters( NULL );
4432 // TODO: OutParameter?
4438 Any SAL_CALL ModuleInvocationProxy::getValue( const OUString& rProperty ) throw( UnknownPropertyException )
4440 if( !m_bProxyIsClassModuleObject )
4442 throw UnknownPropertyException();
4444 SolarMutexGuard guard;
4446 OUString aPropertyFunctionName( "Property Get " );
4447 aPropertyFunctionName += m_aPrefix;
4448 aPropertyFunctionName += rProperty;
4450 SbxVariable* p = m_xScopeObj->Find( aPropertyFunctionName, SbxCLASS_METHOD );
4451 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4452 if( pMeth == NULL )
4454 // TODO: Check vba behavior concernig missing function
4455 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4456 throw UnknownPropertyException();
4459 // Call method
4460 SbxVariableRef xValue = new SbxVariable;
4461 pMeth->Call( xValue );
4462 Any aRet = sbxToUnoValue( xValue );
4463 return aRet;
4466 sal_Bool SAL_CALL ModuleInvocationProxy::hasMethod( const OUString& ) throw()
4468 return sal_False;
4471 sal_Bool SAL_CALL ModuleInvocationProxy::hasProperty( const OUString& ) throw()
4473 return sal_False;
4476 Any SAL_CALL ModuleInvocationProxy::invoke( const OUString& rFunction,
4477 const Sequence< Any >& rParams,
4478 Sequence< sal_Int16 >&,
4479 Sequence< Any >& )
4480 throw( CannotConvertException, InvocationTargetException )
4482 SolarMutexGuard guard;
4484 Any aRet;
4485 SbxObjectRef xScopeObj = m_xScopeObj;
4486 if( !xScopeObj.Is() )
4488 return aRet;
4490 OUString aFunctionName = m_aPrefix;
4491 aFunctionName += rFunction;
4493 sal_Bool bSetRescheduleBack = sal_False;
4494 sal_Bool bOldReschedule = sal_True;
4495 SbiInstance* pInst = GetSbData()->pInst;
4496 if( pInst && pInst->IsCompatibility() )
4498 bOldReschedule = pInst->IsReschedule();
4499 if ( bOldReschedule )
4501 pInst->EnableReschedule( sal_False );
4502 bSetRescheduleBack = sal_True;
4506 SbxVariable* p = xScopeObj->Find( aFunctionName, SbxCLASS_METHOD );
4507 SbMethod* pMeth = p != NULL ? PTR_CAST(SbMethod,p) : NULL;
4508 if( pMeth == NULL )
4510 // TODO: Check vba behavior concernig missing function
4511 //StarBASIC::Error( SbERR_NO_METHOD, aFunctionName );
4512 return aRet;
4515 // Setup parameters
4516 SbxArrayRef xArray;
4517 sal_Int32 nParamCount = rParams.getLength();
4518 if( nParamCount )
4520 xArray = new SbxArray;
4521 const Any *pArgs = rParams.getConstArray();
4522 for( sal_Int32 i = 0 ; i < nParamCount ; i++ )
4524 SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
4525 unoToSbxValue( (SbxVariable*)xVar, pArgs[i] );
4526 xArray->Put( xVar, sal::static_int_cast< sal_uInt16 >(i+1) );
4530 // Call method
4531 SbxVariableRef xValue = new SbxVariable;
4532 if( xArray.Is() )
4533 pMeth->SetParameters( xArray );
4534 pMeth->Call( xValue );
4535 aRet = sbxToUnoValue( xValue );
4536 pMeth->SetParameters( NULL );
4538 if( bSetRescheduleBack )
4539 pInst->EnableReschedule( bOldReschedule );
4541 // TODO: OutParameter?
4543 return aRet;
4546 void SAL_CALL ModuleInvocationProxy::dispose()
4547 throw(RuntimeException)
4549 ::osl::MutexGuard aGuard( m_aMutex );
4551 EventObject aEvent( (XComponent*)this );
4552 m_aListeners.disposeAndClear( aEvent );
4554 m_xScopeObj = NULL;
4557 void SAL_CALL ModuleInvocationProxy::addEventListener( const Reference< XEventListener >& xListener )
4558 throw (RuntimeException)
4560 m_aListeners.addInterface( xListener );
4563 void SAL_CALL ModuleInvocationProxy::removeEventListener( const Reference< XEventListener >& xListener )
4564 throw (RuntimeException)
4566 m_aListeners.removeInterface( xListener );
4570 Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType,
4571 const OUString& aPrefix, SbxObjectRef xScopeObj )
4573 Reference< XInterface > xRet;
4575 Reference< XComponentContext > xContext(
4576 comphelper::getProcessComponentContext() );
4577 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4579 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPrefix, xScopeObj );
4581 Sequence<Any> args( 3 );
4582 args[0] <<= aControlAny;
4583 args[1] <<= aVBAType;
4584 args[2] <<= xProxy;
4588 xRet = xServiceMgr->createInstanceWithArgumentsAndContext(
4589 OUString( "com.sun.star.custom.UnoComListener"),
4590 args, xContext );
4592 catch( const Exception& )
4594 implHandleAnyException( ::cppu::getCaughtException() );
4597 return xRet;
4600 typedef std::vector< WeakReference< XComponent > > ComponentRefVector;
4602 struct StarBasicDisposeItem
4604 StarBASIC* m_pBasic;
4605 SbxArrayRef m_pRegisteredVariables;
4606 ComponentRefVector m_vComImplementsObjects;
4608 StarBasicDisposeItem( StarBASIC* pBasic )
4609 : m_pBasic( pBasic )
4611 m_pRegisteredVariables = new SbxArray();
4615 typedef std::vector< StarBasicDisposeItem* > DisposeItemVector;
4617 static DisposeItemVector GaDisposeItemVector;
4619 static DisposeItemVector::iterator lcl_findItemForBasic( StarBASIC* pBasic )
4621 DisposeItemVector::iterator it;
4622 for( it = GaDisposeItemVector.begin() ; it != GaDisposeItemVector.end() ; ++it )
4624 StarBasicDisposeItem* pItem = *it;
4625 if( pItem->m_pBasic == pBasic )
4626 return it;
4628 return GaDisposeItemVector.end();
4631 static StarBasicDisposeItem* lcl_getOrCreateItemForBasic( StarBASIC* pBasic )
4633 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4634 StarBasicDisposeItem* pItem = (it != GaDisposeItemVector.end()) ? *it : NULL;
4635 if( pItem == NULL )
4637 pItem = new StarBasicDisposeItem( pBasic );
4638 GaDisposeItemVector.push_back( pItem );
4640 return pItem;
4643 void registerComponentToBeDisposedForBasic
4644 ( Reference< XComponent > xComponent, StarBASIC* pBasic )
4646 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4647 pItem->m_vComImplementsObjects.push_back( xComponent );
4650 void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic )
4652 StarBasicDisposeItem* pItem = lcl_getOrCreateItemForBasic( pBasic );
4653 SbxArray* pArray = pItem->m_pRegisteredVariables;
4654 pArray->Put( pVar, pArray->Count() );
4657 void disposeComVariablesForBasic( StarBASIC* pBasic )
4659 DisposeItemVector::iterator it = lcl_findItemForBasic( pBasic );
4660 if( it != GaDisposeItemVector.end() )
4662 StarBasicDisposeItem* pItem = *it;
4664 SbxArray* pArray = pItem->m_pRegisteredVariables;
4665 sal_uInt16 nCount = pArray->Count();
4666 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4668 SbxVariable* pVar = pArray->Get( i );
4669 pVar->ClearComListener();
4672 ComponentRefVector& rv = pItem->m_vComImplementsObjects;
4673 ComponentRefVector::iterator itCRV;
4674 for( itCRV = rv.begin() ; itCRV != rv.end() ; ++itCRV )
4678 Reference< XComponent > xComponent( (*itCRV).get(), UNO_QUERY_THROW );
4679 xComponent->dispose();
4681 catch(const Exception& )
4685 delete pItem;
4686 GaDisposeItemVector.erase( it );
4691 // Handle module implements mechanism for OLE types
4692 bool SbModule::createCOMWrapperForIface( Any& o_rRetAny, SbClassModuleObject* pProxyClassModuleObject )
4694 // For now: Take first interface that allows to instantiate COM wrapper
4695 // TODO: Check if support for multiple interfaces is needed
4697 Reference< XComponentContext > xContext(
4698 comphelper::getProcessComponentContext() );
4699 Reference< XMultiComponentFactory > xServiceMgr( xContext->getServiceManager() );
4700 Reference< XSingleServiceFactory > xComImplementsFactory
4702 xServiceMgr->createInstanceWithContext(
4703 OUString( "com.sun.star.custom.ComImplementsFactory"), xContext ),
4704 UNO_QUERY
4706 if( !xComImplementsFactory.is() )
4707 return false;
4709 bool bSuccess = false;
4711 SbxArray* pModIfaces = pClassData->mxIfaces;
4712 sal_uInt16 nCount = pModIfaces->Count();
4713 for( sal_uInt16 i = 0 ; i < nCount ; ++i )
4715 SbxVariable* pVar = pModIfaces->Get( i );
4716 OUString aIfaceName = pVar->GetName();
4718 if( !aIfaceName.isEmpty() )
4720 OUString aPureIfaceName = aIfaceName;
4721 sal_Int32 indexLastDot = aIfaceName.lastIndexOf('.');
4722 if ( indexLastDot > -1 )
4724 aPureIfaceName = aIfaceName.copy( indexLastDot + 1 );
4726 Reference< XInvocation > xProxy = new ModuleInvocationProxy( aPureIfaceName, pProxyClassModuleObject );
4728 Sequence<Any> args( 2 );
4729 args[0] <<= aIfaceName;
4730 args[1] <<= xProxy;
4732 Reference< XInterface > xRet;
4733 bSuccess = false;
4736 xRet = xComImplementsFactory->createInstanceWithArguments( args );
4737 bSuccess = true;
4739 catch( const Exception& )
4741 implHandleAnyException( ::cppu::getCaughtException() );
4744 if( bSuccess )
4746 Reference< XComponent > xComponent( xProxy, UNO_QUERY );
4747 if( xComponent.is() )
4749 StarBASIC* pParentBasic = NULL;
4750 SbxObject* pCurObject = this;
4753 SbxObject* pObjParent = pCurObject->GetParent();
4754 pParentBasic = PTR_CAST( StarBASIC, pObjParent );
4755 pCurObject = pObjParent;
4757 while( pParentBasic == NULL && pCurObject != NULL );
4759 OSL_ASSERT( pParentBasic != NULL );
4760 registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
4763 o_rRetAny <<= xRet;
4764 break;
4769 return bSuccess;
4773 // Due to an incorrect behavior IE returns an object instead of a string
4774 // in some scenarios. Calling toString at the object may correct this.
4775 // Helper function used in sbxvalue.cxx
4776 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal )
4778 bool bSuccess = false;
4780 SbUnoObject* pUnoObj = NULL;
4781 if( pObj != NULL && (pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)pObj)) != NULL )
4783 // Only for native COM objects
4784 if( pUnoObj->isNativeCOMObject() )
4786 SbxVariableRef pMeth = pObj->Find( OUString( "toString" ), SbxCLASS_METHOD );
4787 if ( pMeth.Is() )
4789 SbxValues aRes;
4790 pMeth->Get( aRes );
4791 pVal->Put( aRes );
4792 bSuccess = true;
4796 return bSuccess;
4799 Any StructRefInfo::getValue()
4801 Any aRet;
4802 uno_any_destruct(
4803 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4804 uno_any_construct(
4805 &aRet, getInst(), mpTD,
4806 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
4807 return aRet;
4810 void StructRefInfo::setValue( const Any& rValue )
4812 uno_type_assignData( getInst(),
4813 mpTD->pWeakRef,
4814 (void*)rValue.getValue(),
4815 rValue.getValueTypeRef(),
4816 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
4817 reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
4818 reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
4821 OUString StructRefInfo::getTypeName() const
4823 OUString sTypeName;
4824 if ( mpTD )
4826 sTypeName = mpTD->pTypeName;
4828 return sTypeName;
4831 void* StructRefInfo::getInst()
4833 return ((char*)maAny.getValue() + mnPos );
4836 TypeClass StructRefInfo::getTypeClass() const
4838 TypeClass t = TypeClass_VOID;
4839 if ( mpTD )
4840 t = (TypeClass)mpTD->eTypeClass;
4841 return t;
4844 SbUnoStructRefObject::SbUnoStructRefObject( const OUString& aName_, const StructRefInfo& rMemberInfo ) : SbxObject( aName_ ), maMemberInfo( rMemberInfo ), mbMemberCacheInit( false )
4846 SetClassName( OUString( maMemberInfo.getTypeName() ) );
4849 SbUnoStructRefObject::~SbUnoStructRefObject()
4851 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4852 delete it->second;
4855 void SbUnoStructRefObject::initMemberCache()
4857 if ( mbMemberCacheInit )
4858 return;
4859 sal_Int32 nAll = 0;
4860 typelib_TypeDescription * pTD = maMemberInfo.getTD();
4861 typelib_CompoundTypeDescription * pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD;
4862 for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4863 nAll += pCompTypeDescr->nMembers;
4864 for ( pCompTypeDescr = (typelib_CompoundTypeDescription *)pTD; pCompTypeDescr;
4865 pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
4867 typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs;
4868 rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames;
4869 sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets;
4870 for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; )
4872 typelib_TypeDescription * pMemberTD = 0;
4873 TYPELIB_DANGER_GET( &pMemberTD, ppTypeRefs[nPos] );
4874 OSL_ENSURE( pMemberTD, "### cannot get field in struct!" );
4875 if (pMemberTD)
4877 OUString aName( ppNames[nPos] );
4878 TYPELIB_DANGER_RELEASE( pMemberTD );
4879 maFields[ aName ] = new StructRefInfo( maMemberInfo.getRootAnyRef(), pMemberTD, maMemberInfo.getPos() + pMemberOffsets[nPos] );
4883 mbMemberCacheInit = true;
4886 SbxVariable* SbUnoStructRefObject::Find( const OUString& rName, SbxClassType t )
4888 SbxVariable* pRes = SbxObject::Find( rName, t );
4889 if ( !pRes )
4891 if ( !mbMemberCacheInit )
4892 initMemberCache();
4893 StructFieldInfo::iterator it = maFields.find( OUString( rName ).toAsciiUpperCase() );
4894 if ( it != maFields.end() )
4896 SbxDataType eSbxType;
4897 eSbxType = unoToSbxType( it->second->getTypeClass() );
4898 SbxDataType eRealSbxType = eSbxType;
4899 Property aProp;
4900 aProp.Name = rName;
4901 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4902 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4903 SbxVariableRef xVarRef = pProp;
4904 QuickInsert( (SbxVariable*)xVarRef );
4905 pRes = xVarRef;
4909 if( !pRes )
4911 if( rName.equalsIgnoreAsciiCase(ID_DBG_SUPPORTEDINTERFACES) ||
4912 rName.equalsIgnoreAsciiCase(ID_DBG_PROPERTIES) ||
4913 rName.equalsIgnoreAsciiCase(ID_DBG_METHODS) )
4915 // Create
4916 implCreateDbgProperties();
4918 // Now they have to be found regular
4919 pRes = SbxObject::Find( rName, SbxCLASS_DONTCARE );
4923 return pRes;
4926 // help method to create the dbg_-Properties
4927 void SbUnoStructRefObject::implCreateDbgProperties( void )
4929 Property aProp;
4931 // Id == -1: display the implemented interfaces corresponding the ClassProvider
4932 SbxVariableRef xVarRef = new SbUnoProperty( OUString(ID_DBG_SUPPORTEDINTERFACES), SbxSTRING, SbxSTRING, aProp, -1, false, false );
4933 QuickInsert( (SbxVariable*)xVarRef );
4935 // Id == -2: output the properties
4936 xVarRef = new SbUnoProperty( OUString(ID_DBG_PROPERTIES), SbxSTRING, SbxSTRING, aProp, -2, false, false );
4937 QuickInsert( (SbxVariable*)xVarRef );
4939 // Id == -3: output the Methods
4940 xVarRef = new SbUnoProperty( OUString(ID_DBG_METHODS), SbxSTRING, SbxSTRING, aProp, -3, false, false );
4941 QuickInsert( (SbxVariable*)xVarRef );
4944 void SbUnoStructRefObject::implCreateAll()
4946 // throw away all existing methods and properties
4947 pMethods = new SbxArray;
4948 pProps = new SbxArray;
4950 if (!mbMemberCacheInit)
4951 initMemberCache();
4953 for ( StructFieldInfo::iterator it = maFields.begin(), it_end = maFields.end(); it != it_end; ++it )
4955 const OUString& rName = it->first;
4956 SbxDataType eSbxType;
4957 eSbxType = unoToSbxType( it->second->getTypeClass() );
4958 SbxDataType eRealSbxType = eSbxType;
4959 Property aProp;
4960 aProp.Name = rName;
4961 aProp.Type = com::sun::star::uno::Type( it->second->getTypeClass(), it->second->getTypeName() );
4962 SbUnoProperty* pProp = new SbUnoProperty( rName, eSbxType, eRealSbxType, aProp, 0, false, ( aProp.Type.getTypeClass() == com::sun::star::uno::TypeClass_STRUCT) );
4963 SbxVariableRef xVarRef = pProp;
4964 QuickInsert( (SbxVariable*)xVarRef );
4967 // Create Dbg_-Properties
4968 implCreateDbgProperties();
4971 // output the value
4972 Any SbUnoStructRefObject::getUnoAny( void )
4974 return maMemberInfo.getValue();
4977 OUString SbUnoStructRefObject::Impl_DumpProperties()
4979 OUStringBuffer aRet;
4980 aRet.appendAscii("Properties of object ");
4981 aRet.append( getDbgObjectName() );
4983 sal_uInt16 nPropCount = pProps->Count();
4984 sal_uInt16 nPropsPerLine = 1 + nPropCount / 30;
4985 for( sal_uInt16 i = 0; i < nPropCount; i++ )
4987 SbxVariable* pVar = pProps->Get( i );
4988 if( pVar )
4990 OUStringBuffer aPropStr;
4991 if( (i % nPropsPerLine) == 0 )
4993 aPropStr.appendAscii( "\n" );
4995 // output the type and name
4996 // Is it in Uno a sequence?
4997 SbxDataType eType = pVar->GetFullType();
4999 sal_Bool bMaybeVoid = sal_False;
5000 OUString aName( pVar->GetName() );
5001 StructFieldInfo::iterator it = maFields.find( aName );
5003 if ( it != maFields.end() )
5005 const StructRefInfo& rPropInfo = *it->second;
5007 if( eType == SbxOBJECT )
5009 if( rPropInfo.getTypeClass() == TypeClass_SEQUENCE )
5011 eType = (SbxDataType) ( SbxOBJECT | SbxARRAY );
5015 aPropStr.append( Dbg_SbxDataType2String( eType ) );
5016 if( bMaybeVoid )
5018 aPropStr.appendAscii( "/void" );
5020 aPropStr.appendAscii( " " );
5021 aPropStr.append( pVar->GetName() );
5023 if( i == nPropCount - 1 )
5025 aPropStr.appendAscii( "\n" );
5027 else
5029 aPropStr.appendAscii( "; " );
5031 aRet.append( aPropStr.makeStringAndClear() );
5034 return aRet.makeStringAndClear();
5037 void SbUnoStructRefObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
5038 const SfxHint& rHint, const TypeId& rHintType )
5040 if ( !mbMemberCacheInit )
5041 initMemberCache();
5042 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
5043 if( pHint )
5045 SbxVariable* pVar = pHint->GetVar();
5046 SbUnoProperty* pProp = PTR_CAST(SbUnoProperty,pVar);
5047 if( pProp )
5049 StructFieldInfo::iterator it = maFields.find( pProp->GetName() );
5050 // handle get/set of members of struct
5051 if( pHint->GetId() == SBX_HINT_DATAWANTED )
5053 // Test-Properties
5054 sal_Int32 nId = pProp->nId;
5055 if( nId < 0 )
5057 // Id == -1: Display implemented interfaces according the ClassProvider
5058 if( nId == -1 ) // Property ID_DBG_SUPPORTEDINTERFACES"
5060 OUStringBuffer aRet;
5061 aRet.appendAscii( ID_DBG_SUPPORTEDINTERFACES );
5062 aRet.appendAscii( " not available.\n(TypeClass is not TypeClass_INTERFACE)\n" );
5064 pVar->PutString( aRet.makeStringAndClear() );
5066 // Id == -2: output properties
5067 else if( nId == -2 ) // Property ID_DBG_PROPERTIES
5069 // by now all properties must be established
5070 implCreateAll();
5071 OUString aRetStr = Impl_DumpProperties();
5072 pVar->PutString( aRetStr );
5074 // Id == -3: output the methods
5075 else if( nId == -3 ) // Property ID_DBG_METHODS
5077 // by now all properties must be established
5078 implCreateAll();
5079 OUStringBuffer aRet;
5080 aRet.appendAscii("Methods of object ");
5081 aRet.append( getDbgObjectName() );
5082 aRet.appendAscii( "\nNo methods found\n" );
5083 pVar->PutString( aRet.makeStringAndClear() );
5085 return;
5088 if ( it != maFields.end() )
5090 Any aRetAny = it->second->getValue();
5091 unoToSbxValue( pVar, aRetAny );
5093 else
5094 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5096 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
5098 if ( it != maFields.end() )
5100 // take over the value from Uno to Sbx
5101 Any aAnyValue = sbxToUnoValue( pVar, pProp->aUnoProp.Type, &pProp->aUnoProp );
5102 it->second->setValue( aAnyValue );
5104 else
5105 StarBASIC::Error( SbERR_PROPERTY_NOT_FOUND );
5108 else
5109 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
5113 StructRefInfo SbUnoStructRefObject::getStructMember( const OUString& rMemberName )
5115 if (!mbMemberCacheInit)
5117 initMemberCache();
5119 StructFieldInfo::iterator it = maFields.find( rMemberName );
5121 typelib_TypeDescription * pFoundTD = NULL;
5122 sal_Int32 nFoundPos = -1;
5124 if ( it != maFields.end() )
5126 pFoundTD = it->second->getTD();
5127 nFoundPos = it->second->getPos();
5129 StructRefInfo aRet( maMemberInfo.getRootAnyRef(), pFoundTD, nFoundPos );
5130 return aRet;
5133 OUString SbUnoStructRefObject::getDbgObjectName()
5135 OUString aName = GetClassName();
5136 if( aName.isEmpty() )
5138 aName += "Unknown";
5140 OUStringBuffer aRet;
5141 if( aName.getLength() > 20 )
5143 aRet.appendAscii( "\n" );
5145 aRet.appendAscii( "\"" );
5146 aRet.append( aName );
5147 aRet.appendAscii( "\":" );
5148 return aRet.makeStringAndClear();
5151 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */